[FFmpeg-devel] [PATCH] ffprobe: add "-show sections" option.

Stefano Sabatini stefasab at gmail.com
Sun Jan 12 10:59:19 CET 2014


On date Saturday 2014-01-11 12:50:58 +0100, Nicolas George encoded:
> This syntax is more concise than the various -show_* options
> and furthermore allows to control the order of the sections.
> 
> Signed-off-by: Nicolas George <george at nsup.org>
> ---
>  doc/ffprobe.texi |  23 +++++++++
>  ffprobe.c        | 154 ++++++++++++++++++++++++++++++++++++++++++-------------
>  2 files changed, 141 insertions(+), 36 deletions(-)
> 
> 
> I have to reasons for proposing this patch:
> 
> * There is a project I have that that needs the format and streams sections
>   before the packets, and -show format,streams,packets instead of -show
>   packets,streams,format seems like a convenient enough way of allowing it.
> 

> * As a user, I have found the interaction between the various -show_*
>   options and the -show_entries option rather confusing. Merging everything
>   into a single option with a short name and a logical syntax looks like a
>   good idea. But this is nit yet done.

-show_entries enables to specify which branches to show, or which
entries to show in a given section. -show_XXX is the equivalent of
-enable_entries=XXX, but can only be used for first level sections.

In short, -enable_entries could be used instead of -show_XXX but was
retained for backward compatibility and convenience.

> diff --git a/doc/ffprobe.texi b/doc/ffprobe.texi
> index 8de8956..7cdec46 100644
> --- a/doc/ffprobe.texi
> +++ b/doc/ffprobe.texi
> @@ -124,6 +124,29 @@ Show information about the error found when trying to probe the input.
>  
>  The error information is printed within a section with name "ERROR".
>  

> + at item -show @var{sections}
> +Enable showing various informational sections about the file;
> + at var{sections} is a comma-separated list of section names chosen in the
> +following list:
> + at code{format},
> + at code{programs},
> + at code{streams},
> + at code{chapters},
> + at code{packets},
> + at code{frames},
> + at code{packets_and_frames}.
> +Section names can be abbreviated provided the prefix is unambiguous; since
> +new sections can be added later, the prefixes are not guaranteed to stay
> +unambiguous.
> +
> +The sections are printed in the given order. It can make a difference for
> +files with streams reconfiguration: printing the format and streams sections
> +before reading the packets or frame will show information about the
> +beginning of the file while printing them after will show information about
> +the end of the file. Sections can be printed several times, but will not
> +cause the file to be re-read, so printing frames or packets twice will
> +result mostly in empty output.

How is that different from -show_entries format:programs:frames? Did
you consider to extend the -show_entries option? This would avoid two
different options with slightly different semantics.

> +
>  @item -show_format
>  Show information about the container format of the input multimedia
>  stream.
> diff --git a/ffprobe.c b/ffprobe.c
> index ef3bcc6..193c411 100644
> --- a/ffprobe.c
> +++ b/ffprobe.c
> @@ -78,6 +78,8 @@ static int use_byte_value_binary_prefix = 0;
>  static int use_value_sexagesimal_format = 0;
>  static int show_private_data            = 1;
>  
> +static char *opt_show;
> +
>  static char *print_format;
>  static char *stream_specifier;
>  
> @@ -195,6 +197,9 @@ static uint64_t *nb_streams_packets;
>  static uint64_t *nb_streams_frames;
>  static int *selected_streams;
>  
> +static SectionID do_show[SECTION_MAX_NB_CHILDREN * 5];
> +static unsigned do_show_nb = 0;
> +
>  static void ffprobe_cleanup(int ret)
>  {
>      int i;
> @@ -2351,14 +2356,34 @@ static void close_input_file(AVFormatContext **ctx_ptr)
>      avformat_close_input(ctx_ptr);
>  }
>  
> +static inline int check_section_show_entries(int section_id);
> +static inline void mark_section_show_entries(SectionID section_id,
> +                                             int show_all_entries, AVDictionary *entries);
> +
> +static int show_packets_and_frames(WriterContext *wctx, AVFormatContext *fmt_ctx,
> +                                   SectionID section_id)
> +{
> +    int ret;
> +
> +    do_show_packets = section_id == SECTION_ID_PACKETS_AND_FRAMES || section_id == SECTION_ID_PACKETS;
> +    do_show_frames  = section_id == SECTION_ID_PACKETS_AND_FRAMES || section_id == SECTION_ID_FRAMES;
> +    do_read_frames  = do_show_frames  || do_count_frames;
> +    do_read_packets = do_show_packets || do_count_packets;
> +
> +    if (do_show_frames || do_show_packets)
> +        writer_print_section_header(wctx, section_id);
> +    ret = read_packets(wctx, fmt_ctx);
> +    if (do_show_frames || do_show_packets)
> +        writer_print_section_footer(wctx);
> +    return ret;
> +}
> +
>  static int probe_file(WriterContext *wctx, const char *filename)
>  {
>      AVFormatContext *fmt_ctx;
>      int ret, i;
>      int section_id;
> -
> -    do_read_frames = do_show_frames || do_count_frames;
> -    do_read_packets = do_show_packets || do_count_packets;
> +    struct section *sec;
>  
>      ret = open_input_file(&fmt_ctx, filename);
>      if (ret < 0)
> @@ -2384,38 +2409,38 @@ static int probe_file(WriterContext *wctx, const char *filename)
>          }
>      }
>  
> -    if (do_read_frames || do_read_packets) {
> -        if (do_show_frames && do_show_packets &&
> -            wctx->writer->flags & WRITER_FLAG_PUT_PACKETS_AND_FRAMES_IN_SAME_CHAPTER)
> -            section_id = SECTION_ID_PACKETS_AND_FRAMES;
> -        else if (do_show_packets && !do_show_frames)
> -            section_id = SECTION_ID_PACKETS;
> -        else // (!do_show_packets && do_show_frames)
> -            section_id = SECTION_ID_FRAMES;
> -        if (do_show_frames || do_show_packets)
> -            writer_print_section_header(wctx, section_id);
> -        ret = read_packets(wctx, fmt_ctx);
> -        if (do_show_frames || do_show_packets)
> -            writer_print_section_footer(wctx);
> -        CHECK_END;
> -    }
> -
> -    if (do_show_programs) {
> -        ret = show_programs(wctx, fmt_ctx);
> -        CHECK_END;
> -    }
> -
> -    if (do_show_streams) {
> -        ret = show_streams(wctx, fmt_ctx);
> -        CHECK_END;
> -    }
> -    if (do_show_chapters) {
> -        ret = show_chapters(wctx, fmt_ctx);
> -        CHECK_END;
> -    }
> -    if (do_show_format) {
> -        ret = show_format(wctx, fmt_ctx);
> -        CHECK_END;

> +    for (i = 0; i < do_show_nb; i++) {
> +        section_id = do_show[i];
> +        sec = &sections[section_id];
> +        if (!check_section_show_entries(section_id))
> +            mark_section_show_entries(section_id, 1, NULL);
> +        switch (section_id) {
> +        case SECTION_ID_FORMAT:
> +            ret = show_format(wctx, fmt_ctx);
> +            break;
> +        case SECTION_ID_PROGRAMS:
> +            ret = show_programs(wctx, fmt_ctx);
> +            break;
> +        case SECTION_ID_STREAMS:
> +            ret = show_streams(wctx, fmt_ctx);
> +            break;
> +        case SECTION_ID_CHAPTERS:
> +            ret = show_chapters(wctx, fmt_ctx);
> +            break;
> +        case SECTION_ID_PACKETS:
> +        case SECTION_ID_FRAMES:
> +        case SECTION_ID_PACKETS_AND_FRAMES:
> +        case -SECTION_ID_PACKETS_AND_FRAMES:
> +            ret = show_packets_and_frames(wctx, fmt_ctx, section_id);
> +            break;
> +        default:
> +            av_log(NULL, AV_LOG_ERROR, "Unknown section to show: %s\n",
> +                   sec->name);
> +            ret = AVERROR(EINVAL);
> +            break;
> +        }

Possibly more general: we set the function with signature
int show_section(wctx, fmt_ctx, section_id) in the section definition,
and call the function if it is defined. This will work only for first
level sections.

[...]
-- 
FFmpeg = Fostering and Freak Majestic Peaceful EniGma


More information about the ffmpeg-devel mailing list