Git Inbox Mirror of the ffmpeg-devel mailing list - see https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
 help / color / mirror / Atom feed
From: James Almer <jamrial@gmail.com>
To: ffmpeg-devel@ffmpeg.org
Subject: Re: [FFmpeg-devel] [PATCH 3/9 v3] fftools/ffprobe: add support for Stream Groups
Date: Tue, 5 Mar 2024 12:09:45 -0300
Message-ID: <63de1cdf-95c3-49d6-9e12-25961e35d294@gmail.com> (raw)
In-Reply-To: <Zec0/RFt0a2oST93@mariano>

On 3/5/2024 12:06 PM, Stefano Sabatini wrote:
> On date Monday 2024-03-04 21:00:23 -0300, James Almer wrote:
>> Signed-off-by: James Almer <jamrial@gmail.com>
>> ---
>>   Changelog                                     |   1 +
>>   doc/ffprobe.xsd                               |   1 +
>>   fftools/ffprobe.c                             | 147 ++++++++++++++++--
>>   tests/ref/fate/cavs-demux                     |   2 +-
>>   tests/ref/fate/ffprobe_compact                |   2 +-
>>   tests/ref/fate/ffprobe_csv                    |   2 +-
>>   tests/ref/fate/ffprobe_default                |   1 +
>>   tests/ref/fate/ffprobe_flat                   |   1 +
>>   tests/ref/fate/ffprobe_ini                    |   1 +
>>   tests/ref/fate/ffprobe_json                   |   1 +
>>   tests/ref/fate/ffprobe_xml                    |   2 +-
>>   tests/ref/fate/ffprobe_xsd                    |   2 +-
>>   tests/ref/fate/flv-demux                      |   2 +-
>>   tests/ref/fate/gapless-mp3-side-data          |   2 +-
>>   .../ref/fate/mov-mp4-disposition-mpegts-remux |   3 +
>>   tests/ref/fate/mov-mp4-ttml-dfxp              |   3 +
>>   tests/ref/fate/mov-mp4-ttml-stpp              |   3 +
>>   tests/ref/fate/oggopus-demux                  |   2 +-
>>   tests/ref/fate/ts-demux                       |   2 +-
>>   tests/ref/fate/ts-opus-demux                  |   2 +-
>>   tests/ref/fate/ts-small-demux                 |   2 +-
>>   tests/ref/fate/ts-timed-id3-demux             |   2 +-
> 
> still missing doc/ffprobe.texi updates

Ok.

> 
>>   22 files changed, 163 insertions(+), 23 deletions(-)
>>
>> diff --git a/Changelog b/Changelog
>> index f388d41b02..0ba3a77c08 100644
>> --- a/Changelog
>> +++ b/Changelog
>> @@ -30,6 +30,7 @@ version <next>:
>>   - Change the default bitrate control method from VBR to CQP for QSV encoders.
>>   - removed deprecated ffmpeg CLI options -psnr and -map_channel
>>   - DVD-Video demuxer, powered by libdvdnav and libdvdread
>> +- ffprobe -show_stream_groups option
>>   
>>   
>>   version 6.1:
>> diff --git a/doc/ffprobe.xsd b/doc/ffprobe.xsd
>> index 9490a20ce8..dc04ce7142 100644
>> --- a/doc/ffprobe.xsd
>> +++ b/doc/ffprobe.xsd
>> @@ -337,6 +337,7 @@
>>       <xsd:attribute name="filename"         type="xsd:string" use="required"/>
>>       <xsd:attribute name="nb_streams"       type="xsd:int"    use="required"/>
>>       <xsd:attribute name="nb_programs"      type="xsd:int"    use="required"/>
>> +    <xsd:attribute name="nb_stream_groups" type="xsd:int"    use="required"/>
>>       <xsd:attribute name="format_name"      type="xsd:string" use="required"/>
>>       <xsd:attribute name="format_long_name" type="xsd:string"/>
>>       <xsd:attribute name="start_time"       type="xsd:float"/>
>> diff --git a/fftools/ffprobe.c b/fftools/ffprobe.c
>> index 8390377159..ff05c4c1db 100644
>> --- a/fftools/ffprobe.c
>> +++ b/fftools/ffprobe.c
>> @@ -112,8 +112,10 @@ static int do_show_format  = 0;
>>   static int do_show_frames  = 0;
>>   static int do_show_packets = 0;
>>   static int do_show_programs = 0;
>> +static int do_show_stream_groups = 0;
>>   static int do_show_streams = 0;
>>   static int do_show_stream_disposition = 0;
>> +static int do_show_stream_group_disposition = 0;
>>   static int do_show_data    = 0;
>>   static int do_show_program_version  = 0;
>>   static int do_show_library_versions = 0;
>> @@ -126,6 +128,7 @@ static int do_show_chapter_tags = 0;
>>   static int do_show_format_tags = 0;
>>   static int do_show_frame_tags = 0;
>>   static int do_show_program_tags = 0;
>> +static int do_show_stream_group_tags = 0;
>>   static int do_show_stream_tags = 0;
>>   static int do_show_packet_tags = 0;
>>   
>> @@ -159,7 +162,7 @@ static int find_stream_info  = 1;
>>   
>>   /* section structure definition */
>>   
>> -#define SECTION_MAX_NB_CHILDREN 10
>> +#define SECTION_MAX_NB_CHILDREN 11
>>   
>>   typedef enum {
>>       SECTION_ID_NONE = -1,
>> @@ -203,6 +206,14 @@ typedef enum {
>>       SECTION_ID_PROGRAM_TAGS,
>>       SECTION_ID_PROGRAM_VERSION,
>>       SECTION_ID_PROGRAMS,
>> +    SECTION_ID_STREAM_GROUP_STREAM_DISPOSITION,
>> +    SECTION_ID_STREAM_GROUP_STREAM_TAGS,
>> +    SECTION_ID_STREAM_GROUP,
>> +    SECTION_ID_STREAM_GROUP_STREAMS,
>> +    SECTION_ID_STREAM_GROUP_STREAM,
>> +    SECTION_ID_STREAM_GROUP_DISPOSITION,
>> +    SECTION_ID_STREAM_GROUP_TAGS,
>> +    SECTION_ID_STREAM_GROUPS,
>>       SECTION_ID_ROOT,
>>       SECTION_ID_STREAM,
>>       SECTION_ID_STREAM_DISPOSITION,
>> @@ -249,6 +260,12 @@ static const char *get_raw_string_type(const void *data)
>>       return data;
>>   }
>>   
>> +static const char *get_stream_group_type(const void *data)
>> +{
>> +    const AVStreamGroup *stg = (const AVStreamGroup *)data;
>> +    return av_x_if_null(avformat_stream_group_name(stg->type), "unknown");
>> +}
>> +
>>   static struct section sections[] = {
>>       [SECTION_ID_CHAPTERS] =           { SECTION_ID_CHAPTERS, "chapters", SECTION_FLAG_IS_ARRAY, { SECTION_ID_CHAPTER, -1 } },
>>       [SECTION_ID_CHAPTER] =            { SECTION_ID_CHAPTER, "chapter", 0, { SECTION_ID_CHAPTER_TAGS, -1 } },
>> @@ -290,8 +307,16 @@ static struct section sections[] = {
>>       [SECTION_ID_PROGRAM_TAGS] =               { SECTION_ID_PROGRAM_TAGS, "tags", SECTION_FLAG_HAS_VARIABLE_FIELDS, { -1 }, .element_name = "tag", .unique_name = "program_tags" },
>>       [SECTION_ID_PROGRAM_VERSION] =    { SECTION_ID_PROGRAM_VERSION, "program_version", 0, { -1 } },
>>       [SECTION_ID_PROGRAMS] =                   { SECTION_ID_PROGRAMS, "programs", SECTION_FLAG_IS_ARRAY, { SECTION_ID_PROGRAM, -1 } },
>> +    [SECTION_ID_STREAM_GROUP_STREAM_DISPOSITION] = { SECTION_ID_STREAM_GROUP_STREAM_DISPOSITION, "disposition", 0, { -1 }, .unique_name = "stream_group_stream_disposition" },
>> +    [SECTION_ID_STREAM_GROUP_STREAM_TAGS] =        { SECTION_ID_STREAM_GROUP_STREAM_TAGS, "tags", SECTION_FLAG_HAS_VARIABLE_FIELDS, { -1 }, .element_name = "tag", .unique_name = "stream_group_stream_tags" },
>> +    [SECTION_ID_STREAM_GROUP] =                    { SECTION_ID_STREAM_GROUP, "stream_group", SECTION_FLAG_HAS_TYPE, { SECTION_ID_STREAM_GROUP_TAGS, SECTION_ID_STREAM_GROUP_DISPOSITION, SECTION_ID_STREAM_GROUP_STREAMS, -1 }, .get_type = get_stream_group_type },
>> +    [SECTION_ID_STREAM_GROUP_STREAMS] =            { SECTION_ID_STREAM_GROUP_STREAMS, "streams", SECTION_FLAG_IS_ARRAY, { SECTION_ID_STREAM_GROUP_STREAM, -1 }, .unique_name = "stream_group_streams" },
>> +    [SECTION_ID_STREAM_GROUP_STREAM] =             { SECTION_ID_STREAM_GROUP_STREAM, "stream", 0, { SECTION_ID_STREAM_GROUP_STREAM_DISPOSITION, SECTION_ID_STREAM_GROUP_STREAM_TAGS, -1 }, .unique_name = "stream_group_stream" },
>> +    [SECTION_ID_STREAM_GROUP_DISPOSITION] =        { SECTION_ID_STREAM_GROUP_DISPOSITION, "disposition", 0, { -1 }, .unique_name = "stream_group_disposition" },
>> +    [SECTION_ID_STREAM_GROUP_TAGS] =               { SECTION_ID_STREAM_GROUP_TAGS, "tags", SECTION_FLAG_HAS_VARIABLE_FIELDS, { -1 }, .element_name = "tag", .unique_name = "stream_group_tags" },
>> +    [SECTION_ID_STREAM_GROUPS] =                   { SECTION_ID_STREAM_GROUPS, "stream_groups", SECTION_FLAG_IS_ARRAY, { SECTION_ID_STREAM_GROUP, -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_CHAPTERS, SECTION_ID_FORMAT, SECTION_ID_FRAMES, SECTION_ID_PROGRAMS, SECTION_ID_STREAM_GROUPS, SECTION_ID_STREAMS,
>>                                             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 } },
>> @@ -3071,7 +3096,10 @@ static void print_dispositions(WriterContext *w, uint32_t disposition, SectionID
>>       writer_print_section_footer(w);
>>   }
>>   
>> -static int show_stream(WriterContext *w, AVFormatContext *fmt_ctx, int stream_idx, InputStream *ist, int in_program)
>> +#define IN_PROGRAM 1
>> +#define IN_STREAM_GROUP 2
>> +
>> +static int show_stream(WriterContext *w, AVFormatContext *fmt_ctx, int stream_idx, InputStream *ist, int container)
>>   {
>>       AVStream *stream = ist->st;
>>       AVCodecParameters *par;
>> @@ -3081,12 +3109,29 @@ static int show_stream(WriterContext *w, AVFormatContext *fmt_ctx, int stream_id
>>       AVRational sar, dar;
>>       AVBPrint pbuf;
>>       const AVCodecDescriptor *cd;
>> +    const SectionID section_header[] = {
>> +        SECTION_ID_STREAM,
>> +        SECTION_ID_PROGRAM_STREAM,
>> +        SECTION_ID_STREAM_GROUP_STREAM,
>> +    };
>> +    const SectionID section_disposition[] = {
>> +        SECTION_ID_STREAM_DISPOSITION,
>> +        SECTION_ID_PROGRAM_STREAM_DISPOSITION,
>> +        SECTION_ID_STREAM_GROUP_STREAM_DISPOSITION,
>> +    };
>> +    const SectionID section_tags[] = {
>> +        SECTION_ID_STREAM_TAGS,
>> +        SECTION_ID_PROGRAM_STREAM_TAGS,
>> +        SECTION_ID_STREAM_GROUP_STREAM_TAGS,
>> +    };
>>       int ret = 0;
>>       const char *profile = NULL;
>>   
>> +    av_assert0(container < FF_ARRAY_ELEMS(section_header));
>> +
>>       av_bprint_init(&pbuf, 1, AV_BPRINT_SIZE_UNLIMITED);
>>   
>> -    writer_print_section_header(w, NULL, in_program ? SECTION_ID_PROGRAM_STREAM : SECTION_ID_STREAM);
>> +    writer_print_section_header(w, NULL, section_header[container]);
>>   
>>       print_int("index", stream->index);
>>   
>> @@ -3248,13 +3293,14 @@ static int show_stream(WriterContext *w, AVFormatContext *fmt_ctx, int stream_id
>>   
>>       /* Print disposition information */
>>       if (do_show_stream_disposition) {
>> -        print_dispositions(w, stream->disposition,
>> -                           in_program ? SECTION_ID_PROGRAM_STREAM_DISPOSITION
>> -                                      : SECTION_ID_STREAM_DISPOSITION);
>> +        av_assert0(container < FF_ARRAY_ELEMS(section_disposition));
>> +        print_dispositions(w, stream->disposition, section_disposition[container]);
>>       }
>>   
>> -    if (do_show_stream_tags)
>> -        ret = show_tags(w, stream->metadata, in_program ? SECTION_ID_PROGRAM_STREAM_TAGS : SECTION_ID_STREAM_TAGS);
>> +    if (do_show_stream_tags) {
>> +        av_assert0(container < FF_ARRAY_ELEMS(section_tags));
>> +        ret = show_tags(w, stream->metadata, section_tags[container]);
>> +    }
>>   
>>       if (stream->codecpar->nb_coded_side_data) {
>>           writer_print_section_header(w, NULL, SECTION_ID_STREAM_SIDE_DATA_LIST);
>> @@ -3309,7 +3355,7 @@ static int show_program(WriterContext *w, InputFile *ifile, AVProgram *program)
>>       writer_print_section_header(w, NULL, SECTION_ID_PROGRAM_STREAMS);
>>       for (i = 0; i < program->nb_stream_indexes; i++) {
>>           if (selected_streams[program->stream_index[i]]) {
>> -            ret = show_stream(w, fmt_ctx, program->stream_index[i], &ifile->streams[program->stream_index[i]], 1);
>> +            ret = show_stream(w, fmt_ctx, program->stream_index[i], &ifile->streams[program->stream_index[i]], IN_PROGRAM);
>>               if (ret < 0)
>>                   break;
>>           }
>> @@ -3339,6 +3385,72 @@ static int show_programs(WriterContext *w, InputFile *ifile)
>>       return ret;
>>   }
>>   
>> +static void print_stream_group_params(WriterContext *w, AVStreamGroup *stg)
>> +{
>> +    const char *unknown = "unknown";
>> +    if (stg->type != AV_STREAM_GROUP_PARAMS_NONE)
>> +        print_str("type", av_x_if_null(avformat_stream_group_name(stg->type), unknown));
>> +    else
>> +        print_str_opt("type", unknown);
>> +}
>> +
>> +static int show_stream_group(WriterContext *w, InputFile *ifile, AVStreamGroup *stg)
>> +{
>> +    AVFormatContext *fmt_ctx = ifile->fmt_ctx;
>> +    AVBPrint pbuf;
>> +    int i, ret = 0;
>> +
>> +    av_bprint_init(&pbuf, 1, AV_BPRINT_SIZE_UNLIMITED);
>> +    writer_print_section_header(w, stg, SECTION_ID_STREAM_GROUP);
>> +    print_int("index", stg->index);
>> +    if (fmt_ctx->iformat->flags & AVFMT_SHOW_IDS) print_fmt    ("id", "0x%"PRIx64, stg->id);
>> +    else                                          print_str_opt("id", "N/A");
>> +    print_int("nb_streams", stg->nb_streams);
>> +    print_stream_group_params(w, stg);
>> +
>> +    /* Print disposition information */
>> +    if (do_show_stream_group_disposition)
>> +        print_dispositions(w, stg->disposition, SECTION_ID_STREAM_GROUP_DISPOSITION);
>> +
>> +    if (do_show_stream_group_tags)
>> +        ret = show_tags(w, stg->metadata, SECTION_ID_STREAM_GROUP_TAGS);
>> +    if (ret < 0)
>> +        goto end;
>> +
>> +    writer_print_section_header(w, NULL, SECTION_ID_STREAM_GROUP_STREAMS);
>> +    for (i = 0; i < stg->nb_streams; i++) {
>> +        if (selected_streams[stg->streams[i]->index]) {
>> +            ret = show_stream(w, fmt_ctx, stg->streams[i]->index, &ifile->streams[stg->streams[i]->index], IN_STREAM_GROUP);
>> +            if (ret < 0)
>> +                break;
>> +        }
>> +    }
>> +    writer_print_section_footer(w);
>> +
>> +end:
>> +    av_bprint_finalize(&pbuf, NULL);
>> +    writer_print_section_footer(w);
>> +    return ret;
>> +}
>> +
>> +static int show_stream_groups(WriterContext *w, InputFile *ifile)
>> +{
>> +    AVFormatContext *fmt_ctx = ifile->fmt_ctx;
>> +    int i, ret = 0;
>> +
>> +    writer_print_section_header(w, NULL, SECTION_ID_STREAM_GROUPS);
> 
>> +    for (i = 0; i < fmt_ctx->nb_stream_groups; i++) {
>> +        AVStreamGroup *stg = fmt_ctx->stream_groups[i];
> 
>> +        if (!stg)
>> +            continue;
> 
> why can this be NULL? (this sounds a bit unexpected to me)

Not really, i just copied the check from show_programs(). Can remove it.

> 
> [...]
> 
> LGTM otherwise, thanks.
> _______________________________________________
> ffmpeg-devel mailing list
> ffmpeg-devel@ffmpeg.org
> https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
> 
> To unsubscribe, visit link above, or email
> ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel

To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".

  reply	other threads:[~2024-03-05 15:09 UTC|newest]

Thread overview: 22+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-03-05  0:00 [FFmpeg-devel] [PATCH 1/9 v2] fftools/ffprobe: fix printing side data components and pieces James Almer
2024-03-05  0:00 ` [FFmpeg-devel] [PATCH 2/9] avformat/avformat: add a function to return the name of stream groups James Almer
2024-03-05 14:50   ` Stefano Sabatini
2024-03-05 14:52     ` Stefano Sabatini
2024-03-05 14:56       ` James Almer
2024-03-05  0:00 ` [FFmpeg-devel] [PATCH 3/9 v3] fftools/ffprobe: add support for Stream Groups James Almer
2024-03-05 15:06   ` Stefano Sabatini
2024-03-05 15:09     ` James Almer [this message]
2024-03-05  0:00 ` [FFmpeg-devel] [PATCH 4/9 v2] fate/iamf: print stream group information James Almer
2024-03-05 15:10   ` Stefano Sabatini
2024-03-05  0:00 ` [FFmpeg-devel] [PATCH 5/9 v2] fate/mov: print stream group information for iamf tests James Almer
2024-03-05 15:14   ` Stefano Sabatini
2024-03-05  0:00 ` [FFmpeg-devel] [PATCH 6/9] fftools/ffprobe: export Tile Grid Stream Group parameters James Almer
2024-03-05 15:14   ` James Almer
2024-03-05 15:24     ` Stefano Sabatini
2024-03-05 15:50       ` James Almer
2024-03-06 13:39         ` Stefano Sabatini
2024-03-05 15:21   ` Stefano Sabatini
2024-03-05  0:00 ` [FFmpeg-devel] [PATCH 7/9 v3] fate/mov: print stream group information for avif/heic tests James Almer
2024-03-05  0:00 ` [FFmpeg-devel] [PATCH 8/9 v2] fate/mov: use framecrc for the remaining " James Almer
2024-03-05  0:00 ` [FFmpeg-devel] [PATCH 9/9] fate/mov: add a heic test with a derived image using a single item twice James Almer
2024-03-05 14:46 ` [FFmpeg-devel] [PATCH 1/9 v2] fftools/ffprobe: fix printing side data components and pieces Stefano Sabatini

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=63de1cdf-95c3-49d6-9e12-25961e35d294@gmail.com \
    --to=jamrial@gmail.com \
    --cc=ffmpeg-devel@ffmpeg.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link

Git Inbox Mirror of the ffmpeg-devel mailing list - see https://ffmpeg.org/mailman/listinfo/ffmpeg-devel

This inbox may be cloned and mirrored by anyone:

	git clone --mirror https://master.gitmailbox.com/ffmpegdev/0 ffmpegdev/git/0.git

	# If you have public-inbox 1.1+ installed, you may
	# initialize and index your mirror using the following commands:
	public-inbox-init -V2 ffmpegdev ffmpegdev/ https://master.gitmailbox.com/ffmpegdev \
		ffmpegdev@gitmailbox.com
	public-inbox-index ffmpegdev

Example config snippet for mirrors.


AGPL code for this site: git clone https://public-inbox.org/public-inbox.git