static int show_private_data = 1;
static char *print_format;
+static char *stream_specifier;
/* section structure definition */
#define SECTION_FLAG_IS_WRAPPER 1 ///< the section only contains other sections, but has no data at its own level
#define SECTION_FLAG_IS_ARRAY 2 ///< the section contains an array of elements of the same type
+#define SECTION_FLAG_HAS_VARIABLE_FIELDS 4 ///< the section may contain a variable number of fields with variable keys.
+ /// For these sections the element_name field is mandatory.
int flags;
const char *element_name; ///< name of the contained element, if provided
};
SECTION_ID_PROGRAM_VERSION,
SECTION_ID_ROOT,
SECTION_ID_STREAM,
+ SECTION_ID_STREAM_DISPOSITION,
SECTION_ID_STREAMS,
SECTION_ID_STREAM_TAGS
} SectionID;
static const struct section sections[] = {
[SECTION_ID_ERROR] = { SECTION_ID_ERROR, "error" },
[SECTION_ID_FORMAT] = { SECTION_ID_FORMAT, "format" },
- [SECTION_ID_FORMAT_TAGS] = { SECTION_ID_FORMAT_TAGS, "tags", .element_name = "tag" },
+ [SECTION_ID_FORMAT_TAGS] = { SECTION_ID_FORMAT_TAGS, "tags", SECTION_FLAG_HAS_VARIABLE_FIELDS, .element_name = "tag" },
[SECTION_ID_FRAME] = { SECTION_ID_FRAME, "frame" },
[SECTION_ID_FRAMES] = { SECTION_ID_FRAMES, "frames", SECTION_FLAG_IS_ARRAY },
- [SECTION_ID_FRAME_TAGS] = { SECTION_ID_FRAME_TAGS, "tags", .element_name = "tag" },
+ [SECTION_ID_FRAME_TAGS] = { SECTION_ID_FRAME_TAGS, "tags", SECTION_FLAG_HAS_VARIABLE_FIELDS, .element_name = "tag" },
[SECTION_ID_LIBRARY_VERSION] = { SECTION_ID_LIBRARY_VERSION, "library_version" },
[SECTION_ID_LIBRARY_VERSIONS] = { SECTION_ID_LIBRARY_VERSIONS, "library_versions", SECTION_FLAG_IS_ARRAY },
[SECTION_ID_PACKET] = { SECTION_ID_PACKET, "packet" },
[SECTION_ID_PROGRAM_VERSION] = { SECTION_ID_PROGRAM_VERSION, "program_version" },
[SECTION_ID_ROOT] = { SECTION_ID_ROOT, "root", SECTION_FLAG_IS_WRAPPER },
[SECTION_ID_STREAM] = { SECTION_ID_STREAM, "stream" },
+ [SECTION_ID_STREAM_DISPOSITION] = { SECTION_ID_STREAM_DISPOSITION, "disposition" },
[SECTION_ID_STREAMS] = { SECTION_ID_STREAMS, "streams", SECTION_FLAG_IS_ARRAY },
- [SECTION_ID_STREAM_TAGS] = { SECTION_ID_STREAM_TAGS, "tags", .element_name = "tag" },
+ [SECTION_ID_STREAM_TAGS] = { SECTION_ID_STREAM_TAGS, "tags", SECTION_FLAG_HAS_VARIABLE_FIELDS, .element_name = "tag" },
};
static const OptionDef *options;
static const char unit_hertz_str[] = "Hz" ;
static const char unit_byte_str[] = "byte" ;
static const char unit_bit_per_second_str[] = "bit/s";
+
static uint64_t *nb_streams_packets;
static uint64_t *nb_streams_frames;
+static int *selected_streams;
-void av_noreturn exit_program(int ret)
+static void exit_program(void)
{
av_dict_free(&fmt_entries_to_show);
- exit(ret);
}
struct unit_value {
xml->within_tag = 0;
printf(">\n");
}
- if (!strcmp(section->name, "tags")) {
+ if (section->flags & SECTION_FLAG_HAS_VARIABLE_FIELDS) {
xml->indent_level++;
} else {
- if (!(parent_section->flags & SECTION_FLAG_IS_ARRAY) &&
- (wctx->level && wctx->nb_item[wctx->level-1]))
- printf("\n");
-
+ if (parent_section && (parent_section->flags & SECTION_FLAG_IS_WRAPPER) &&
+ wctx->level && wctx->nb_item[wctx->level-1])
+ printf("\n");
xml->indent_level++;
if (section->flags & SECTION_FLAG_IS_ARRAY) {
xml->within_tag = 0;
printf("/>\n");
xml->indent_level--;
- } else if (!strcmp(section->name, "tags")) {
+ } else if (section->flags & SECTION_FLAG_HAS_VARIABLE_FIELDS) {
xml->indent_level--;
} else {
XML_INDENT(); printf("</%s>\n", section->name);
av_bprint_init(&buf, 1, AV_BPRINT_SIZE_UNLIMITED);
- if (!strcmp(section->name, "tags")) {
+ if (section->flags & SECTION_FLAG_HAS_VARIABLE_FIELDS) {
XML_INDENT();
- printf("<tag key=\"%s\"", xml_escape_str(&buf, key, wctx));
+ printf("<%s key=\"%s\"",
+ section->element_name, xml_escape_str(&buf, key, wctx));
av_bprint_clear(&buf);
printf(" value=\"%s\"/>\n", xml_escape_str(&buf, value, wctx));
} else {
av_init_packet(&pkt);
while (!av_read_frame(fmt_ctx, &pkt)) {
- if (do_read_packets) {
- if (do_show_packets)
- show_packet(w, fmt_ctx, &pkt, i++);
- nb_streams_packets[pkt.stream_index]++;
- }
- if (do_read_frames) {
- pkt1 = pkt;
- while (pkt1.size && process_frame(w, fmt_ctx, &frame, &pkt1) > 0);
+ if (selected_streams[pkt.stream_index]) {
+ if (do_read_packets) {
+ if (do_show_packets)
+ show_packet(w, fmt_ctx, &pkt, i++);
+ nb_streams_packets[pkt.stream_index]++;
+ }
+ if (do_read_frames) {
+ pkt1 = pkt;
+ while (pkt1.size && process_frame(w, fmt_ctx, &frame, &pkt1) > 0);
+ }
}
av_free_packet(&pkt);
}
print_str("codec_tag_string", val_str);
print_fmt("codec_tag", "0x%04x", dec_ctx->codec_tag);
- /* Print useful disposition */
- print_int("default", !!(stream->disposition & AV_DISPOSITION_DEFAULT));
- print_int("forced", !!(stream->disposition & AV_DISPOSITION_FORCED));
-
switch (dec_ctx->codec_type) {
case AVMEDIA_TYPE_VIDEO:
print_int("width", dec_ctx->width);
} else {
print_str_opt("timecode", "N/A");
}
- print_int("attached_pic",
- !!(stream->disposition & AV_DISPOSITION_ATTACHED_PIC));
break;
case AVMEDIA_TYPE_AUDIO:
if (do_show_data)
writer_print_data(w, "extradata", dec_ctx->extradata,
dec_ctx->extradata_size);
+
+ /* Print disposition information */
+#define PRINT_DISPOSITION(flagname, name) do { \
+ print_int(name, !!(stream->disposition & AV_DISPOSITION_##flagname)); \
+ } while (0)
+
+ writer_print_section_header(w, SECTION_ID_STREAM_DISPOSITION);
+ PRINT_DISPOSITION(DEFAULT, "default");
+ PRINT_DISPOSITION(DUB, "dub");
+ PRINT_DISPOSITION(ORIGINAL, "original");
+ PRINT_DISPOSITION(COMMENT, "comment");
+ PRINT_DISPOSITION(LYRICS, "lyrics");
+ PRINT_DISPOSITION(KARAOKE, "karaoke");
+ PRINT_DISPOSITION(FORCED, "forced");
+ PRINT_DISPOSITION(HEARING_IMPAIRED, "hearing_impaired");
+ PRINT_DISPOSITION(VISUAL_IMPAIRED, "visual_impaired");
+ PRINT_DISPOSITION(CLEAN_EFFECTS, "clean_effects");
+ PRINT_DISPOSITION(ATTACHED_PIC, "attached_pic");
+ writer_print_section_footer(w);
+
show_tags(w, stream->metadata, SECTION_ID_STREAM_TAGS);
writer_print_section_footer(w);
int i;
writer_print_section_header(w, SECTION_ID_STREAMS);
for (i = 0; i < fmt_ctx->nb_streams; i++)
- show_stream(w, fmt_ctx, i);
+ if (selected_streams[i])
+ show_stream(w, fmt_ctx, i);
writer_print_section_footer(w);
}
static int probe_file(WriterContext *wctx, const char *filename)
{
AVFormatContext *fmt_ctx;
- int ret;
+ int ret, i;
int section_id;
do_read_frames = do_show_frames || do_count_frames;
if (ret >= 0) {
nb_streams_frames = av_calloc(fmt_ctx->nb_streams, sizeof(*nb_streams_frames));
nb_streams_packets = av_calloc(fmt_ctx->nb_streams, sizeof(*nb_streams_packets));
+ selected_streams = av_calloc(fmt_ctx->nb_streams, sizeof(*selected_streams));
+
+ for (i = 0; i < fmt_ctx->nb_streams; i++) {
+ if (stream_specifier) {
+ ret = avformat_match_stream_specifier(fmt_ctx,
+ fmt_ctx->streams[i],
+ stream_specifier);
+ if (ret < 0)
+ goto end;
+ else
+ selected_streams[i] = ret;
+ } else {
+ selected_streams[i] = 1;
+ }
+ }
+
if (do_read_frames || do_read_packets) {
if (do_show_frames && do_show_packets &&
wctx->writer->flags & WRITER_FLAG_PUT_PACKETS_AND_FRAMES_IN_SAME_CHAPTER)
if (do_show_format)
show_format(wctx, fmt_ctx);
+ end:
close_input_file(&fmt_ctx);
av_freep(&nb_streams_frames);
av_freep(&nb_streams_packets);
+ av_freep(&selected_streams);
}
return ret;
}
{ "print_format", OPT_STRING | HAS_ARG, {(void*)&print_format},
"set the output printing format (available formats are: default, compact, csv, flat, ini, json, xml)", "format" },
{ "of", OPT_STRING | HAS_ARG, {(void*)&print_format}, "alias for -print_format", "format" },
+ { "select_streams", OPT_STRING | HAS_ARG, {(void*)&stream_specifier}, "select the specified streams", "stream_specifier" },
{ "show_data", OPT_BOOL, {(void*)&do_show_data}, "show packets data" },
{ "show_error", OPT_BOOL, {(void*)&do_show_error} , "show probing error" },
{ "show_format", OPT_BOOL, {&do_show_format} , "show format/container info" },
int ret;
av_log_set_flags(AV_LOG_SKIP_REPEATED);
+ atexit(exit_program);
+
options = real_options;
parse_loglevel(argc, argv, options);
av_register_all();
if (!print_format)
print_format = av_strdup("default");
+ if (!print_format) {
+ ret = AVERROR(ENOMEM);
+ goto end;
+ }
w_name = av_strtok(print_format, "=", &buf);
w_args = buf;