From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org [79.124.17.100]) by master.gitmailbox.com (Postfix) with ESMTP id 220B949C4B for ; Tue, 5 Mar 2024 15:09:44 +0000 (UTC) Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 6D97A68D060; Tue, 5 Mar 2024 17:09:42 +0200 (EET) Received: from mail-pf1-f174.google.com (mail-pf1-f174.google.com [209.85.210.174]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id 37D8068D03D for ; Tue, 5 Mar 2024 17:09:36 +0200 (EET) Received: by mail-pf1-f174.google.com with SMTP id d2e1a72fcca58-6e5eaf5bb3eso762653b3a.3 for ; Tue, 05 Mar 2024 07:09:36 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1709651374; x=1710256174; darn=ffmpeg.org; h=content-transfer-encoding:in-reply-to:from:references:to :content-language:subject:user-agent:mime-version:date:message-id :from:to:cc:subject:date:message-id:reply-to; bh=0SjRYbmEIJepUIY1+gtXn6HoHXkVR1byCuijWGKP/1o=; b=ee1aR3OehqIwVTlmGuNVJ14Wh0MeZay+vUXDFHiE8pdw3zvnTF9HupATVD9kymDRdD mlaU1LwC9WOAmWo6HNuV/tyRyJ0lIPMmCWnW5WhNK4pfn+IwKTuSCE1MIe+1mNW49BJg OCNYJwqQ8ONbYN22QaSqWS5XxCdHnu1AIrQfuKA8Q2WL2w/++k4EyPPWdsuDAzylLPJt fUdWcfXDby1RcYnsiXoTRWib/ScsP+FjdOuztbLwU87LoIiW/0UTAyZ4Pz6b8koHd7GU CbAO1T8ojpgiLg4Tk6/HngwisJD9JSQkUNRoqtDU3MaHr95pybDogaAbSQC5IEw/3y3R xYIw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1709651374; x=1710256174; h=content-transfer-encoding:in-reply-to:from:references:to :content-language:subject:user-agent:mime-version:date:message-id :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=0SjRYbmEIJepUIY1+gtXn6HoHXkVR1byCuijWGKP/1o=; b=NHLeCYIhxJr9IS5Vh/vP8kiWESm+zRXLiunL8ZBnTiydwzZBKuYk9tvTxITWXQhCMs GA1Ka6pZMG8G+ng4XcZgZ6Af936yGiXIfhSMnDK+vg24YMiuLlLb018xwBOh1kLWbNXW mOdwgq2DYrJqBP9rj8gkRN5lYg/v4KhRrmpniBXRos7z1XpzDmWFJe7fUtRdhfPHnekz Av57EyIYT0FuRSVgCZ/hoVNwqYbPcdxuKeT6NwGgb6doitIthi6rIrYRVn/mBWMwr9SU R3HX5t4w4DpnpMEXJ1C4xBLMthSIFOBTwzPEPiiQCVg42193yS/gV1zcV4CNs3hatleu nusg== X-Gm-Message-State: AOJu0YxSz0q5skZ+6nHdWbSU3MebE6X81pGp9kcALd9KfOxTgINIPoKm BsUneEmF47RmyRsiLAXF/Z+0IfTfTCCdAV4vmmD7zfEF/JZlREX6PBfO5iU4 X-Google-Smtp-Source: AGHT+IGpN0qYLs7y3KSrozZnRCgQXi8R7e9bGAWOInHa/HNEefOfMI76D2JUYQD6u4uKTVqoC07e+Q== X-Received: by 2002:aa7:88d4:0:b0:6e4:f753:1e12 with SMTP id k20-20020aa788d4000000b006e4f7531e12mr13757895pff.28.1709651373712; Tue, 05 Mar 2024 07:09:33 -0800 (PST) Received: from [192.168.0.14] ([190.194.169.124]) by smtp.gmail.com with ESMTPSA id j2-20020a056a00234200b006e56e5abc0bsm8970037pfj.51.2024.03.05.07.09.32 for (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Tue, 05 Mar 2024 07:09:33 -0800 (PST) Message-ID: <63de1cdf-95c3-49d6-9e12-25961e35d294@gmail.com> Date: Tue, 5 Mar 2024 12:09:45 -0300 MIME-Version: 1.0 User-Agent: Mozilla Thunderbird Content-Language: en-US To: ffmpeg-devel@ffmpeg.org References: <20240305000033.10379-1-jamrial@gmail.com> <20240305000033.10379-3-jamrial@gmail.com> From: James Almer In-Reply-To: Subject: Re: [FFmpeg-devel] [PATCH 3/9 v3] fftools/ffprobe: add support for Stream Groups X-BeenThere: ffmpeg-devel@ffmpeg.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: FFmpeg development discussions and patches List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-To: FFmpeg development discussions and patches Content-Transfer-Encoding: 7bit Content-Type: text/plain; charset="us-ascii"; Format="flowed" Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" Archived-At: List-Archive: List-Post: 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 >> --- >> 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 : >> - 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 @@ >> >> >> >> + >> >> >> >> 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".