[FFmpeg-devel] [PATCH] ffprobe: add -show_pixel_formats option (was: add -show_pixel_descriptions option)

Stefano Sabatini stefasab at gmail.com
Thu Sep 11 12:12:07 CEST 2014


On date Thursday 2014-09-11 09:54:42 +0200, Tobias Rapp encoded:
> Have now added documentation and cleaned up some unused variables
> with the new patch. Also on a second thought the option names
> "show_pixel_format_descriptions" or "show_pixel_formats" seem less
> confusing to me than "show_pixel_descriptions" so I did choose the
> shorter "show_pixel_formats".
> 
> What I would like to add in a follow-up patch is a way to output the
> flags. I see different options:
> 
> a) Output a character per flag (R=RGB, A=ALPHA, B=BITSTREAM, ...)
> but this needs extra documentation and might be confusing due to
> collisions (P=PALETTE or P=PLANAR? B=BIG-ENDIAN or B=BITSTREAM?)
> 
> Example: flag="RAP"
>
> b) Output a list of flag names separated by comma or space. This
> would fit mostly with JSON (comma) or XML (space) output format
> style, I guess.
> 
> Example 1: flag="rgb,alpha,palette"
> Example 2: flag="rgb alpha palette"
> 
> c) Output each flag as a boolean value. This increases amount of
> output but fits better to output formats like CSV or INI.
> 
> Example: is_rgb="1" has_alpha="1" is_bitstream="0" has_palette="1"
> 
> What do you think?

Flags are a collection, so probably it makes sense to print it as an
array. See how it is done with PRINT_DISPOSITION. That's not very
elegant though, but IMO the best solution for easing the following
parsing (no need to further serialize the flags value).

> 
> Tobias

> From 5938c171472469e91bb2b7445100ab6509929ba7 Mon Sep 17 00:00:00 2001
> From: Tobias Rapp <t.rapp at noa-audio.com>
> Date: Thu, 11 Sep 2014 09:16:52 +0200
> Subject: [PATCH] ffprobe: add -show_pixel_formats option
> 
> Adds option -show_pixel_formats to ffprobe which lists all
> available pixel formats with some details.
> ---
>  doc/ffprobe.texi |  6 +++++
>  doc/ffprobe.xsd  | 15 +++++++++++
>  ffprobe.c        | 78 ++++++++++++++++++++++++++++++++++++++++++++++++++++++--
>  3 files changed, 97 insertions(+), 2 deletions(-)
> 
> diff --git a/doc/ffprobe.texi b/doc/ffprobe.texi
> index 0a39ed4..5c90470 100644
> --- a/doc/ffprobe.texi
> +++ b/doc/ffprobe.texi
> @@ -321,6 +321,12 @@ Show information related to program and library versions. This is the
>  equivalent of setting both @option{-show_program_version} and
>  @option{-show_library_versions} options.
>  
> + at item -show_pixel_formats
> +Show information about all pixel formats supported by FFmpeg.
> +
> +Pixel format information for each format is printed within a section
> +with name "PIXEL_FORMAT".
> +
>  @item -bitexact
>  Force bitexact output, useful to produce output which is not dependent
>  on the specific build.
> diff --git a/doc/ffprobe.xsd b/doc/ffprobe.xsd
> index 5dfbb47..33c4f20 100644
> --- a/doc/ffprobe.xsd
> +++ b/doc/ffprobe.xsd
> @@ -10,6 +10,7 @@
>          <xsd:sequence>
>              <xsd:element name="program_version"  type="ffprobe:programVersionType"  minOccurs="0" maxOccurs="1" />
>              <xsd:element name="library_versions" type="ffprobe:libraryVersionsType" minOccurs="0" maxOccurs="1" />
> +            <xsd:element name="pixel_formats"    type="ffprobe:pixelFormatsType"    minOccurs="0" maxOccurs="1" />
>              <xsd:element name="packets"  type="ffprobe:packetsType" minOccurs="0" maxOccurs="1" />
>              <xsd:element name="frames"   type="ffprobe:framesType"  minOccurs="0" maxOccurs="1" />
>              <xsd:element name="programs" type="ffprobe:programsType" minOccurs="0" maxOccurs="1" />
> @@ -277,4 +278,18 @@
>            <xsd:element name="library_version" type="ffprobe:libraryVersionType" minOccurs="0" maxOccurs="unbounded"/>
>          </xsd:sequence>
>      </xsd:complexType>
> +
> +    <xsd:complexType name="pixelFormatType">
> +      <xsd:attribute name="name"                type="xsd:string" use="required"/>
> +      <xsd:attribute name="nb_components"       type="xsd:int"    use="required"/>
> +      <xsd:attribute name="bits_per_pixel"      type="xsd:int"/>
> +      <xsd:attribute name="bits_per_component"  type="xsd:int"/>
> +      <xsd:attribute name="chroma_sub_sampling" type="xsd:string"/>
> +    </xsd:complexType>
> +
> +    <xsd:complexType name="pixelFormatsType">
> +      <xsd:sequence>
> +        <xsd:element name="pixel_format" type="ffprobe:pixelFormatType" minOccurs="0" maxOccurs="unbounded"/>
> +      </xsd:sequence>
> +    </xsd:complexType>
>  </xsd:schema>
> diff --git a/ffprobe.c b/ffprobe.c
> index 9bb0f0f..621df04 100644
> --- a/ffprobe.c
> +++ b/ffprobe.c
> @@ -66,6 +66,7 @@ static int do_show_stream_disposition = 0;
>  static int do_show_data    = 0;
>  static int do_show_program_version  = 0;
>  static int do_show_library_versions = 0;
> +static int do_show_pixel_formats = 0;
>  
>  static int do_show_chapter_tags = 0;
>  static int do_show_format_tags = 0;
> @@ -132,6 +133,8 @@ typedef enum {
>      SECTION_ID_PACKET,
>      SECTION_ID_PACKETS,
>      SECTION_ID_PACKETS_AND_FRAMES,
> +    SECTION_ID_PIXEL_FORMAT,
> +    SECTION_ID_PIXEL_FORMATS,
>      SECTION_ID_PROGRAM_STREAM_DISPOSITION,
>      SECTION_ID_PROGRAM_STREAM_TAGS,
>      SECTION_ID_PROGRAM,
> @@ -165,6 +168,8 @@ static struct section sections[] = {
>      [SECTION_ID_PACKETS] =            { SECTION_ID_PACKETS, "packets", SECTION_FLAG_IS_ARRAY, { SECTION_ID_PACKET, -1} },
>      [SECTION_ID_PACKETS_AND_FRAMES] = { SECTION_ID_PACKETS_AND_FRAMES, "packets_and_frames", SECTION_FLAG_IS_ARRAY, { SECTION_ID_PACKET, -1} },
>      [SECTION_ID_PACKET] =             { SECTION_ID_PACKET, "packet", 0, { -1 } },
> +    [SECTION_ID_PIXEL_FORMATS] =      { SECTION_ID_PIXEL_FORMATS, "pixel_formats", SECTION_FLAG_IS_ARRAY, { SECTION_ID_PIXEL_FORMAT, -1 } },
> +    [SECTION_ID_PIXEL_FORMAT] =       { SECTION_ID_PIXEL_FORMAT, "pixel_format", 0, { -1 } },
>      [SECTION_ID_PROGRAM_STREAM_DISPOSITION] = { SECTION_ID_PROGRAM_STREAM_DISPOSITION, "disposition", 0, { -1 }, .unique_name = "program_stream_disposition" },
>      [SECTION_ID_PROGRAM_STREAM_TAGS] =        { SECTION_ID_PROGRAM_STREAM_TAGS, "tags", SECTION_FLAG_HAS_VARIABLE_FIELDS, { -1 }, .element_name = "tag", .unique_name = "program_stream_tags" },
>      [SECTION_ID_PROGRAM] =                    { SECTION_ID_PROGRAM, "program", 0, { SECTION_ID_PROGRAM_TAGS, SECTION_ID_PROGRAM_STREAMS, -1 } },
> @@ -175,7 +180,8 @@ static struct section sections[] = {
>      [SECTION_ID_PROGRAMS] =                   { SECTION_ID_PROGRAMS, "programs", SECTION_FLAG_IS_ARRAY, { SECTION_ID_PROGRAM, -1 } },
>      [SECTION_ID_ROOT] =               { SECTION_ID_ROOT, "root", SECTION_FLAG_IS_WRAPPER,
>                                          { SECTION_ID_CHAPTERS, SECTION_ID_FORMAT, SECTION_ID_FRAMES, SECTION_ID_PROGRAMS, SECTION_ID_STREAMS,
> -                                          SECTION_ID_PACKETS, SECTION_ID_ERROR, SECTION_ID_PROGRAM_VERSION, SECTION_ID_LIBRARY_VERSIONS, -1} },
> +                                          SECTION_ID_PACKETS, SECTION_ID_ERROR, SECTION_ID_PROGRAM_VERSION, SECTION_ID_LIBRARY_VERSIONS,
> +                                          SECTION_ID_PIXEL_FORMATS, -1} },
>      [SECTION_ID_STREAMS] =            { SECTION_ID_STREAMS, "streams", SECTION_FLAG_IS_ARRAY, { SECTION_ID_STREAM, -1 } },
>      [SECTION_ID_STREAM] =             { SECTION_ID_STREAM, "stream", 0, { SECTION_ID_STREAM_DISPOSITION, SECTION_ID_STREAM_TAGS, -1 } },
>      [SECTION_ID_STREAM_DISPOSITION] = { SECTION_ID_STREAM_DISPOSITION, "disposition", 0, { -1 }, .unique_name = "stream_disposition" },
> @@ -2557,6 +2563,69 @@ static void ffprobe_show_library_versions(WriterContext *w)
>      writer_print_section_footer(w);
>  }
>  

> +static int get_bits_per_component(const AVPixFmtDescriptor *pixdesc)
> +{
> +    int c, bits, first_bits = 0;
> +
> +    for (c = 0; c < pixdesc->nb_components; c++) {
> +        bits = pixdesc->comp[c].depth_minus1 + 1;
> +        if (c == 0)
> +            first_bits = bits;
> +        else if (bits != first_bits)
> +            return 0;
> +    }
> +
> +    return first_bits;
> +}

What if you compute this in the script? Since the bits_per_component
semantics is ambiguous it is probably better let the user compute it
herself.

> +
> +static const char *get_chroma_sub_sample_string(const AVPixFmtDescriptor *pixdesc)
> +{
> +    if (!pixdesc)
> +        return NULL;
> +    if ((pixdesc->flags & AV_PIX_FMT_FLAG_RGB) || pixdesc->nb_components < 3)
> +        return NULL;
> +
> +    if ((pixdesc->log2_chroma_w == 0) && (pixdesc->log2_chroma_h == 0))
> +        return "4:4:4";
> +    else if ((pixdesc->log2_chroma_w == 0) && (pixdesc->log2_chroma_h == 1))
> +        return "4:4:0";
> +    else if ((pixdesc->log2_chroma_w == 1) && (pixdesc->log2_chroma_h == 0))
> +        return "4:2:2";
> +    else if ((pixdesc->log2_chroma_w == 1) && (pixdesc->log2_chroma_h == 1))
> +        return "4:2:0";
> +    else if ((pixdesc->log2_chroma_w == 2) && (pixdesc->log2_chroma_h == 0))
> +        return "4:1:1";
> +    else if ((pixdesc->log2_chroma_w == 2) && (pixdesc->log2_chroma_h == 2))
> +        return "4:1:0";
> +    else
> +        return "unknown";
> +}

Why don't you just write the log2_chroma_w/h values?

[...]
-- 
FFmpeg = Fundamentalist & Fierce Mind-dumbing Purposeless Ecletic Gnome


More information about the ffmpeg-devel mailing list