Commit 4da54022 authored by Stefano Sabatini's avatar Stefano Sabatini

ffprobe: show chapter and chapter metadata information

Address trac ticket #2636.
parent 21d0f75f
...@@ -64,6 +64,7 @@ version <next>: ...@@ -64,6 +64,7 @@ version <next>:
- Go2Webinar decoder - Go2Webinar decoder
- mcdeint filter ported from libmpcodecs - mcdeint filter ported from libmpcodecs
- sab filter ported from libmpcodecs - sab filter ported from libmpcodecs
- ffprobe -show_chapters option
version 1.2: version 1.2:
......
...@@ -209,6 +209,11 @@ multimedia stream. ...@@ -209,6 +209,11 @@ multimedia stream.
Each media stream information is printed within a dedicated section Each media stream information is printed within a dedicated section
with name "STREAM". with name "STREAM".
@item -show_chapters
Show information about chapters stored in the format.
Each chapter is printed within a dedicated section with name "CHAPTER".
@item -count_frames @item -count_frames
Count the number of frames per stream and report it in the Count the number of frames per stream and report it in the
corresponding stream section. corresponding stream section.
......
...@@ -11,6 +11,7 @@ ...@@ -11,6 +11,7 @@
<xsd:element name="packets" type="ffprobe:packetsType" 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="frames" type="ffprobe:framesType" minOccurs="0" maxOccurs="1" />
<xsd:element name="streams" type="ffprobe:streamsType" minOccurs="0" maxOccurs="1" /> <xsd:element name="streams" type="ffprobe:streamsType" 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="format" type="ffprobe:formatType" minOccurs="0" maxOccurs="1" />
<xsd:element name="error" type="ffprobe:errorType" minOccurs="0" maxOccurs="1" /> <xsd:element name="error" type="ffprobe:errorType" minOccurs="0" maxOccurs="1" />
<xsd:element name="program_version" type="ffprobe:programVersionType" minOccurs="0" maxOccurs="1" /> <xsd:element name="program_version" type="ffprobe:programVersionType" minOccurs="0" maxOccurs="1" />
...@@ -181,6 +182,25 @@ ...@@ -181,6 +182,25 @@
<xsd:attribute name="configuration" type="xsd:string" use="required"/> <xsd:attribute name="configuration" type="xsd:string" use="required"/>
</xsd:complexType> </xsd:complexType>
<xsd:complexType name="chaptersType">
<xsd:sequence>
<xsd:element name="chapter" type="ffprobe:chapterType" minOccurs="0" maxOccurs="unbounded"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="chapterType">
<xsd:sequence>
<xsd:element name="tag" type="ffprobe:tagType" minOccurs="0" maxOccurs="unbounded"/>
</xsd:sequence>
<xsd:attribute name="id" type="xsd:int" use="required"/>
<xsd:attribute name="time_base" type="xsd:string" use="required"/>
<xsd:attribute name="start" type="xsd:int" use="required"/>
<xsd:attribute name="start_time" type="xsd:float"/>
<xsd:attribute name="end" type="xsd:int" use="required"/>
<xsd:attribute name="end_time" type="xsd:float" use="required"/>
</xsd:complexType>
<xsd:complexType name="libraryVersionType"> <xsd:complexType name="libraryVersionType">
<xsd:attribute name="name" type="xsd:string" use="required"/> <xsd:attribute name="name" type="xsd:string" use="required"/>
<xsd:attribute name="major" type="xsd:int" use="required"/> <xsd:attribute name="major" type="xsd:int" use="required"/>
......
...@@ -52,6 +52,7 @@ static int do_count_frames = 0; ...@@ -52,6 +52,7 @@ static int do_count_frames = 0;
static int do_count_packets = 0; static int do_count_packets = 0;
static int do_read_frames = 0; static int do_read_frames = 0;
static int do_read_packets = 0; static int do_read_packets = 0;
static int do_show_chapters = 0;
static int do_show_error = 0; static int do_show_error = 0;
static int do_show_format = 0; static int do_show_format = 0;
static int do_show_frames = 0; static int do_show_frames = 0;
...@@ -93,6 +94,9 @@ struct section { ...@@ -93,6 +94,9 @@ struct section {
typedef enum { typedef enum {
SECTION_ID_NONE = -1, SECTION_ID_NONE = -1,
SECTION_ID_CHAPTER,
SECTION_ID_CHAPTER_TAGS,
SECTION_ID_CHAPTERS,
SECTION_ID_ERROR, SECTION_ID_ERROR,
SECTION_ID_FORMAT, SECTION_ID_FORMAT,
SECTION_ID_FORMAT_TAGS, SECTION_ID_FORMAT_TAGS,
...@@ -113,6 +117,9 @@ typedef enum { ...@@ -113,6 +117,9 @@ typedef enum {
} SectionID; } SectionID;
static struct section sections[] = { 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 } },
[SECTION_ID_CHAPTER_TAGS] = { SECTION_ID_CHAPTER_TAGS, "tags", SECTION_FLAG_HAS_VARIABLE_FIELDS, { -1 }, .element_name = "tag", .unique_name = "chapter_tags" },
[SECTION_ID_ERROR] = { SECTION_ID_ERROR, "error", 0, { -1 } }, [SECTION_ID_ERROR] = { SECTION_ID_ERROR, "error", 0, { -1 } },
[SECTION_ID_FORMAT] = { SECTION_ID_FORMAT, "format", 0, { SECTION_ID_FORMAT_TAGS, -1 } }, [SECTION_ID_FORMAT] = { SECTION_ID_FORMAT, "format", 0, { SECTION_ID_FORMAT_TAGS, -1 } },
[SECTION_ID_FORMAT_TAGS] = { SECTION_ID_FORMAT_TAGS, "tags", SECTION_FLAG_HAS_VARIABLE_FIELDS, { -1 }, .element_name = "tag", .unique_name = "format_tags" }, [SECTION_ID_FORMAT_TAGS] = { SECTION_ID_FORMAT_TAGS, "tags", SECTION_FLAG_HAS_VARIABLE_FIELDS, { -1 }, .element_name = "tag", .unique_name = "format_tags" },
...@@ -126,7 +133,7 @@ static struct section sections[] = { ...@@ -126,7 +133,7 @@ static struct section sections[] = {
[SECTION_ID_PACKET] = { SECTION_ID_PACKET, "packet", 0, { -1 } }, [SECTION_ID_PACKET] = { SECTION_ID_PACKET, "packet", 0, { -1 } },
[SECTION_ID_PROGRAM_VERSION] = { SECTION_ID_PROGRAM_VERSION, "program_version", 0, { -1 } }, [SECTION_ID_PROGRAM_VERSION] = { SECTION_ID_PROGRAM_VERSION, "program_version", 0, { -1 } },
[SECTION_ID_ROOT] = { SECTION_ID_ROOT, "root", SECTION_FLAG_IS_WRAPPER, [SECTION_ID_ROOT] = { SECTION_ID_ROOT, "root", SECTION_FLAG_IS_WRAPPER,
{ SECTION_ID_FORMAT, SECTION_ID_FRAMES, SECTION_ID_STREAMS, SECTION_ID_PACKETS, { 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_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_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] = { SECTION_ID_STREAM, "stream", 0, { SECTION_ID_STREAM_DISPOSITION, SECTION_ID_STREAM_TAGS, -1 } },
...@@ -1751,6 +1758,27 @@ static void show_streams(WriterContext *w, AVFormatContext *fmt_ctx) ...@@ -1751,6 +1758,27 @@ static void show_streams(WriterContext *w, AVFormatContext *fmt_ctx)
writer_print_section_footer(w); writer_print_section_footer(w);
} }
static void show_chapters(WriterContext *w, AVFormatContext *fmt_ctx)
{
int i;
writer_print_section_header(w, SECTION_ID_CHAPTERS);
for (i = 0; i < fmt_ctx->nb_chapters; i++) {
AVChapter *chapter = fmt_ctx->chapters[i];
writer_print_section_header(w, SECTION_ID_CHAPTER);
print_int("id", chapter->id);
print_q ("time_base", chapter->time_base, '/');
print_int("start", chapter->start);
print_time("start_time", chapter->start, &chapter->time_base);
print_int("end", chapter->end);
print_time("end_time", chapter->end, &chapter->time_base);
show_tags(w, chapter->metadata, SECTION_ID_CHAPTER_TAGS);
writer_print_section_footer(w);
}
writer_print_section_footer(w);
}
static void show_format(WriterContext *w, AVFormatContext *fmt_ctx) static void show_format(WriterContext *w, AVFormatContext *fmt_ctx)
{ {
char val_str[128]; char val_str[128];
...@@ -1911,6 +1939,8 @@ static int probe_file(WriterContext *wctx, const char *filename) ...@@ -1911,6 +1939,8 @@ static int probe_file(WriterContext *wctx, const char *filename)
} }
if (do_show_streams) if (do_show_streams)
show_streams(wctx, fmt_ctx); show_streams(wctx, fmt_ctx);
if (do_show_chapters)
show_chapters(wctx, fmt_ctx);
if (do_show_format) if (do_show_format)
show_format(wctx, fmt_ctx); show_format(wctx, fmt_ctx);
...@@ -2165,6 +2195,7 @@ static int opt_show_versions(const char *opt, const char *arg) ...@@ -2165,6 +2195,7 @@ static int opt_show_versions(const char *opt, const char *arg)
return 0; \ return 0; \
} }
DEFINE_OPT_SHOW_SECTION(chapters, CHAPTERS);
DEFINE_OPT_SHOW_SECTION(error, ERROR); DEFINE_OPT_SHOW_SECTION(error, ERROR);
DEFINE_OPT_SHOW_SECTION(format, FORMAT); DEFINE_OPT_SHOW_SECTION(format, FORMAT);
DEFINE_OPT_SHOW_SECTION(frames, FRAMES); DEFINE_OPT_SHOW_SECTION(frames, FRAMES);
...@@ -2199,6 +2230,7 @@ static const OptionDef real_options[] = { ...@@ -2199,6 +2230,7 @@ static const OptionDef real_options[] = {
"show a set of specified entries", "entry_list" }, "show a set of specified entries", "entry_list" },
{ "show_packets", 0, {(void*)&opt_show_packets}, "show packets info" }, { "show_packets", 0, {(void*)&opt_show_packets}, "show packets info" },
{ "show_streams", 0, {(void*)&opt_show_streams}, "show streams info" }, { "show_streams", 0, {(void*)&opt_show_streams}, "show streams info" },
{ "show_chapters", 0, {(void*)&opt_show_chapters}, "show chapters info" },
{ "count_frames", OPT_BOOL, {(void*)&do_count_frames}, "count the number of frames per stream" }, { "count_frames", OPT_BOOL, {(void*)&do_count_frames}, "count the number of frames per stream" },
{ "count_packets", OPT_BOOL, {(void*)&do_count_packets}, "count the number of packets per stream" }, { "count_packets", OPT_BOOL, {(void*)&do_count_packets}, "count the number of packets per stream" },
{ "show_program_version", 0, {(void*)&opt_show_program_version}, "show ffprobe version" }, { "show_program_version", 0, {(void*)&opt_show_program_version}, "show ffprobe version" },
...@@ -2253,6 +2285,7 @@ int main(int argc, char **argv) ...@@ -2253,6 +2285,7 @@ int main(int argc, char **argv)
parse_options(NULL, argc, argv, options, opt_input_file); parse_options(NULL, argc, argv, options, opt_input_file);
/* mark things to show, based on -show_entries */ /* mark things to show, based on -show_entries */
SET_DO_SHOW(CHAPTERS, chapters);
SET_DO_SHOW(ERROR, error); SET_DO_SHOW(ERROR, error);
SET_DO_SHOW(FORMAT, format); SET_DO_SHOW(FORMAT, format);
SET_DO_SHOW(FRAMES, frames); SET_DO_SHOW(FRAMES, frames);
...@@ -2298,7 +2331,7 @@ int main(int argc, char **argv) ...@@ -2298,7 +2331,7 @@ int main(int argc, char **argv)
ffprobe_show_library_versions(wctx); ffprobe_show_library_versions(wctx);
if (!input_filename && if (!input_filename &&
((do_show_format || do_show_streams || do_show_packets || do_show_error) || ((do_show_format || do_show_streams || do_show_chapters || do_show_packets || do_show_error) ||
(!do_show_program_version && !do_show_library_versions))) { (!do_show_program_version && !do_show_library_versions))) {
show_usage(); show_usage();
av_log(NULL, AV_LOG_ERROR, "You have to specify one input file.\n"); av_log(NULL, AV_LOG_ERROR, "You have to specify one input file.\n");
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment