[FFmpeg-devel] [PATCH 1/2] Add programs to ffprobe
Stefano Sabatini
stefasab at gmail.com
Wed Jul 24 16:56:37 CEST 2013
On date Tuesday 2013-07-23 11:05:40 +0200, Florent Tribouilloy encoded:
> Option -show_programs for ffprobe will sort the output by programs
>
> Signed-off-by: Florent Tribouilloy <florent.tribouilloy at smartjog.com>
> ---
> doc/ffprobe.texi | 14 ++++++--
> doc/ffprobe.xsd | 26 ++++++++++++++
> ffprobe.c | 76 +++++++++++++++++++++++++++++++++++-----
> 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 +-
> 10 files changed, 112 insertions(+), 14 deletions(-)
>
> diff --git a/doc/ffprobe.texi b/doc/ffprobe.texi
> index 38517a8..02cffbb 100644
> --- a/doc/ffprobe.texi
> +++ b/doc/ffprobe.texi
> @@ -44,7 +44,8 @@ name (which may be shared by other sections), and an unique
> name. See the output of @option{sections}.
>
> Metadata tags stored in the container or in the streams are recognized
> -and printed in the corresponding "FORMAT" or "STREAM" section.
> +and printed in the corresponding "FORMAT", "STREAM" or "PROGRAM_STREAM"
> +section.
>
> @c man end
>
> @@ -209,6 +210,13 @@ multimedia stream.
> Each media stream information is printed within a dedicated section
> with name "STREAM".
>
> + at item -show_programs
> +Show information about programs and their streams contained in the input
> +multimedia stream.
> +
> +Each media stream information is printed within a dedicated section
> +with name "PROGRAM_STREAM".
> +
> @item -show_chapters
> Show information about chapters stored in the format.
>
> @@ -279,8 +287,8 @@ keyN=valN
> [/SECTION]
> @end example
>
> -Metadata tags are printed as a line in the corresponding FORMAT or
> -STREAM section, and are prefixed by the string "TAG:".
> +Metadata tags are printed as a line in the corresponding FORMAT, STREAM or
> +PROGRAM_STREAM section, and are prefixed by the string "TAG:".
>
> A description of the accepted options follows.
>
> diff --git a/doc/ffprobe.xsd b/doc/ffprobe.xsd
> index bd890b1..5716c7f 100644
> --- a/doc/ffprobe.xsd
> +++ b/doc/ffprobe.xsd
> @@ -11,6 +11,7 @@
> <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="streams" type="ffprobe:streamsType" minOccurs="0" maxOccurs="1" />
> + <xsd:element name="programs" type="ffprobe:programsType" minOccurs="0" maxOccurs="1" />
> <xsd:element name="chapters" type="ffprobe:chaptersType" minOccurs="0" maxOccurs="1" />
> <xsd:element name="format" type="ffprobe:formatType" minOccurs="0" maxOccurs="1" />
> <xsd:element name="error" type="ffprobe:errorType" minOccurs="0" maxOccurs="1" />
> @@ -87,6 +88,12 @@
> </xsd:sequence>
> </xsd:complexType>
>
> + <xsd:complexType name="programsType">
> + <xsd:sequence>
> + <xsd:element name="programs" type="ffprobe:programType" minOccurs="0" maxOccurs="unbounded"/>
> + </xsd:sequence>
> + </xsd:complexType>
> +
> <xsd:complexType name="streamDispositionType">
> <xsd:attribute name="default" type="xsd:int" use="required" />
> <xsd:attribute name="dub" type="xsd:int" use="required" />
> @@ -147,6 +154,25 @@
> <xsd:attribute name="nb_read_packets" type="xsd:int"/>
> </xsd:complexType>
>
> + <xsd:complexType name="programType">
> + <xsd:sequence>
> + <xsd:element name="tag" type="ffprobe:tagType" minOccurs="0" maxOccurs="unbounded"/>
> + </xsd:sequence>
> +
> + <xsd:attribute name="program_id" type="xsd:int" use="required"/>
> + <xsd:attribute name="program_num" type="xsd:int" use="required"/>
> + <xsd:attribute name="nb_stream" type="xsd:int" use="required"/>
> + <xsd:attribute name="start_time" type="xsd:int" use="required"/>
> + <xsd:attribute name="end_time" type="xsd:int" use="required"/>
start/end_pts?
I use xmllint to test compliance.
> + <xsd:attribute name="pmt_pid" type="xsd:int" use="required"/>
> + <xsd:attribute name="pcr_pid" type="xsd:int" use="required"/>
> + <xsd:attribute name="pts_wrap_reference" type="xsd:int" use="required"/>
> + <xsd:attribute name="pts_wrap_behavior" type="xsd:int" use="required"/>
Need to be removed?
> + <xsd:sequence>
> + <xsd:element name="program_stream" type="ffprobe:streamType" minOccurs="0" maxOccurs="unbounded"/>
> + </xsd:sequence>
> + </xsd:complexType>
> +
> <xsd:complexType name="formatType">
> <xsd:sequence>
> <xsd:element name="tag" type="ffprobe:tagType" minOccurs="0" maxOccurs="unbounded"/>
> diff --git a/ffprobe.c b/ffprobe.c
> index d4adde0..907869e 100644
> --- a/ffprobe.c
> +++ b/ffprobe.c
> @@ -57,6 +57,7 @@ static int do_show_error = 0;
> 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_streams = 0;
> static int do_show_stream_disposition = 0;
> static int do_show_data = 0;
> @@ -108,7 +109,13 @@ typedef enum {
> SECTION_ID_PACKET,
> SECTION_ID_PACKETS,
> SECTION_ID_PACKETS_AND_FRAMES,
> + SECTION_ID_PROGRAM_STREAM_DISPOSITION,
> + SECTION_ID_PROGRAM_STREAM_TAGS,
> + SECTION_ID_PROGRAM,
> + SECTION_ID_PROGRAM_STREAM,
> + SECTION_ID_PROGRAM_TAGS,
> SECTION_ID_PROGRAM_VERSION,
> + SECTION_ID_PROGRAMS,
> SECTION_ID_ROOT,
> SECTION_ID_STREAM,
> SECTION_ID_STREAM_DISPOSITION,
> @@ -131,10 +138,16 @@ 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_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_STREAM, -1 } },
> + [SECTION_ID_PROGRAM_STREAM] = { SECTION_ID_PROGRAM_STREAM, "program_stream", 0, { SECTION_ID_PROGRAM_STREAM_DISPOSITION, SECTION_ID_PROGRAM_STREAM_TAGS, -1 } },
> + [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_ROOT] = { SECTION_ID_ROOT, "root", SECTION_FLAG_IS_WRAPPER,
> - { SECTION_ID_CHAPTERS, SECTION_ID_FORMAT, SECTION_ID_FRAMES, SECTION_ID_STREAMS, SECTION_ID_PACKETS,
> - SECTION_ID_ERROR, SECTION_ID_PROGRAM_VERSION, SECTION_ID_LIBRARY_VERSIONS, -1} },
> + { 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_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" },
> @@ -1598,7 +1611,7 @@ static void read_packets(WriterContext *w, AVFormatContext *fmt_ctx)
> }
> }
>
> -static void show_stream(WriterContext *w, AVFormatContext *fmt_ctx, int stream_idx)
> +static void show_stream(WriterContext *w, AVFormatContext *fmt_ctx, int stream_idx, int in_program)
> {
> AVStream *stream = fmt_ctx->streams[stream_idx];
> AVCodecContext *dec_ctx;
> @@ -1610,7 +1623,7 @@ static void show_stream(WriterContext *w, AVFormatContext *fmt_ctx, int stream_i
>
> av_bprint_init(&pbuf, 1, AV_BPRINT_SIZE_UNLIMITED);
>
> - writer_print_section_header(w, SECTION_ID_STREAM);
> + writer_print_section_header(w, in_program ? SECTION_ID_PROGRAM_STREAM : SECTION_ID_STREAM);
>
> print_int("index", stream->index);
>
> @@ -1726,7 +1739,7 @@ static void show_stream(WriterContext *w, AVFormatContext *fmt_ctx, int stream_i
> } while (0)
>
> if (do_show_stream_disposition) {
> - writer_print_section_header(w, SECTION_ID_STREAM_DISPOSITION);
> + writer_print_section_header(w, in_program ? SECTION_ID_PROGRAM_STREAM_DISPOSITION : SECTION_ID_STREAM_DISPOSITION);
> PRINT_DISPOSITION(DEFAULT, "default");
> PRINT_DISPOSITION(DUB, "dub");
> PRINT_DISPOSITION(ORIGINAL, "original");
> @@ -1741,7 +1754,7 @@ static void show_stream(WriterContext *w, AVFormatContext *fmt_ctx, int stream_i
> writer_print_section_footer(w);
> }
>
> - show_tags(w, stream->metadata, SECTION_ID_STREAM_TAGS);
> + show_tags(w, stream->metadata, in_program ? SECTION_ID_PROGRAM_STREAM_TAGS : SECTION_ID_STREAM_TAGS);
>
> writer_print_section_footer(w);
> av_bprint_finalize(&pbuf, NULL);
> @@ -1754,7 +1767,47 @@ static void show_streams(WriterContext *w, AVFormatContext *fmt_ctx)
> writer_print_section_header(w, SECTION_ID_STREAMS);
> for (i = 0; i < fmt_ctx->nb_streams; i++)
> if (selected_streams[i])
> - show_stream(w, fmt_ctx, i);
> + show_stream(w, fmt_ctx, i, 0);
> + writer_print_section_footer(w);
> +}
> +
> +static void show_program(WriterContext *w, AVFormatContext *fmt_ctx, AVProgram *program)
> +{
> + int i;
> +
> + writer_print_section_header(w, SECTION_ID_PROGRAM);
> + print_int("program_id", program->id);
> + print_int("program_num", program->program_num);
> + print_int("nb_streams", program->nb_stream_indexes);
> + print_int("pmt_pid", program->pmt_pid);
> + print_int("pcr_pid", program->pcr_pid);
> + if (program->start_time != INT64_MIN) {
> + print_ts("start_pts", program->start_time);
> + print_time("start_time", program->start_time, &AV_TIME_BASE_Q);
> + }
> + if (program->end_time != INT64_MIN) {
> + print_ts("end_pts", program->end_time);
> + print_time("end_time", program->end_time, &AV_TIME_BASE_Q);
> + }
usually times/PTSs are printed in case their value is !=
AV_NOPTS_VALUE. Any reason to check on INT64_MIN instead?
[...]
--
FFmpeg = Fantastic and Furious Merciful Purposeless Erroneous Gangster
More information about the ffmpeg-devel
mailing list