[FFmpeg-devel] [RFC] Add plotframes script
Nicolas George
nicolas.george at normalesup.org
Thu Jan 10 12:41:08 CET 2013
Le primidi 21 nivôse, an CCXXI, Stefano Sabatini a écrit :
> The script is ported from ffprobe/SourceForge and updated to the current
> ffprobe version.
> ---
> tools/plotframes | 134 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
> 1 file changed, 134 insertions(+)
> create mode 100755 tools/plotframes
>
> diff --git a/tools/plotframes b/tools/plotframes
> new file mode 100755
> index 0000000..e24fa75
> --- /dev/null
> +++ b/tools/plotframes
> @@ -0,0 +1,134 @@
> +#!/usr/bin/env perl
> +
> +use warnings;
> +use strict;
> +
> +use File::Temp;
> +use JSON -support_by_pp;
> +use Getopt::Long;
> +use Pod::Usage;
> +
> +my $input = $ARGV[0];
> +my $stream_specifier = "v";
> +my $gnuplot_terminal = "x11";
> +my $gnuplot_output;
> +
> +GetOptions (
> + 'input|i=s' => \$input,
> + 'help|usage|?|h' => sub { pod2usage ( { -verbose => 1, -exitval => 0 }) },
> + 'manpage|m' => sub { pod2usage ( { -verbose => 2, -exitval => 0 }) },
> + 'stream|s=s' => \$stream_specifier,
> + 'terminal|t=s' => \$gnuplot_terminal,
> + 'output|o=s' => \$gnuplot_output,
> + ) or pod2usage( { -message=> "Parsing error", -verbose => 1, -exitval => 1 });
> +
> +die "You must define an input file\n" unless $input;
"define"?
> +
> +$gnuplot_output = "plotframes.$$.$gnuplot_terminal" if not $gnuplot_output;
Urgh.
> +
> +# fetch data
> +my $cmd = "ffprobe -show_entries frame -select_streams $stream_specifier -of json \"$input\"";
Use a list:
my @cmd = (qw{ffprobe -show_entries frame -select_streams",
$stream_specifier, "-of", "json", $input);
That will avoid quoting problems with $input.
> +print STDERR "Executing command: $cmd\n";
> +my $json_struct;
> +{
> + open(FH, "$cmd|") or die "ffprobe command '$cmd' failed: $!\n";
open my $fh, "-|", @cmd or die ...
> + local $/;
> + my $json_text = <FH>;
A format that allows progressive parsing would be nice to give progress
information.
(I can work on -of perl if people think it useful.)
> + eval { $json_struct = decode_json($json_text); };
> + die "JSON parsing error: $@\n" if $@;
> +}
> +
> +# collect and print frame statistics per pict_type
> +my %stats;
> +my $frames = $json_struct->{frames};
> +foreach my $frame (@{$frames}) {
> + my $type = $frame->{pict_type};
> + if (not $stats{$type}) {
> + $stats{$type}->{tmpfile} = File::Temp->new(SUFFIX => '.dat');
> + my $fn = $stats{$type}->{tmpfile}->filename;
> + open ($stats{$type}->{fh}, ">$fn") or die "Can't open $fn";
open ..., ">", $fn
> + }
> +
> + print { $stats{$type}->{fh} }
> + "$frame->{pkt_pts_time} ", $frame->{pkt_size} * 8 /1000, "\n";
> +}
> +foreach (keys %stats) { close $stats{$_}->{fh}; }
> +
> +# write gnuplot script
> +my $gnuplot_script_tmpfile = File::Temp->new(SUFFIX => '.gnuplot');
Could be piped to gnuplot.
> +{
> + my $fn = $gnuplot_script_tmpfile->filename;
> + open (FH, ">$fn") or die "Couldn't open $fn: $!";
open my $fh, ">", $fn;
> + print FH << "EOF";
> +set title "video frame sizes - $input"
Problem if $input has special characters.
> +set xlabel "frame time"
> +set ylabel "frame size (Kbits)"
> +set grid
> +set terminal "$gnuplot_terminal"
> +set output "$gnuplot_output"
> +EOF
> +
> + print FH "plot";
> + my $sep = "";
> + foreach my $type (keys %stats) {
> + my $fn = $stats{$type}->{tmpfile}->filename;
> + print FH "$sep\"$fn\" title \"$type frames\" with impulses";
> + $sep = ", ";
> + }
> +}
> +close FH;
> +
> +# load the script in an interactive gnuplot session
> +system ("gnuplot", "--persist", $gnuplot_script_tmpfile->filename);
> +
> +=head1 NAME
> +
> +plotframes - Plot video frames size using ffprobe and gnuplot
> +
> +=head1 SYNOPSIS
> +
> +plotframes [<options>] <input>
> +
> +=head1 DESCRIPTION
> +
> +B<plotframes> reads a multimedia files with ffprobe, and plots the
> +collected video sizes with gnuplot.
> +
> +=head1 OPTIONS
> +
> +=over 4
> +
> +=item B<--input|-i> INFILE
> +
> +Specify multimedia file to read.
> +
> +=item B<--help|--usage|-h|-?>
> +
> +Print a brief help message and exit.
> +
> +=item B<--manpage|-m>
> +
> +Print the man page.
> +
> +=item B<--output|-o> OUTFILE
> +
> +Set the name of the output used by gnuplot. By default it is
> +gnuplot.PID.TERMINAL, where PID is the process ID of the script, and
> +TERMINAL is the value set by the --terminal option.
> +
> +=item B<--stream|--s> STREAM_SPECIFIER
> +
> +Specify stream. The value must be a string containing a stream
> +specifier. Default value is "v".
> +
> +=item B<--term|-t> TERMINAL
> +
> +Set the name of the terminal used by gnuplot. By default it is "x11".
> +
> +=back
> +
> +=cut
> +
> +=head1 SEEALSO
> +
> +ffprobe(1), gnuplot(1)
Regards,
--
Nicolas George
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 198 bytes
Desc: Digital signature
URL: <http://ffmpeg.org/pipermail/ffmpeg-devel/attachments/20130110/ea1a9e6c/attachment.asc>
More information about the ffmpeg-devel
mailing list