[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