2 * avprobe : Simple Media Prober based on the Libav libraries
3 * Copyright (c) 2007-2010 Stefano Sabatini
5 * This file is part of Libav.
7 * Libav is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * Libav is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with Libav; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
24 #include "libavformat/avformat.h"
25 #include "libavcodec/avcodec.h"
26 #include "libavutil/opt.h"
27 #include "libavutil/pixdesc.h"
28 #include "libavutil/dict.h"
29 #include "libavutil/libm.h"
30 #include "libavdevice/avdevice.h"
33 const char program_name
[] = "avprobe";
34 const int program_birth_year
= 2007;
36 static int do_show_format
= 0;
37 static AVDictionary
*fmt_entries_to_show
= NULL
;
38 static int nb_fmt_entries_to_show
;
39 static int do_show_packets
= 0;
40 static int do_show_streams
= 0;
42 static int show_value_unit
= 0;
43 static int use_value_prefix
= 0;
44 static int use_byte_value_binary_prefix
= 0;
45 static int use_value_sexagesimal_format
= 0;
48 static const OptionDef
*options
;
51 static const char *input_filename
;
52 static AVInputFormat
*iformat
= NULL
;
54 static const char *const binary_unit_prefixes
[] = { "", "Ki", "Mi", "Gi", "Ti", "Pi" };
55 static const char *const decimal_unit_prefixes
[] = { "", "K" , "M" , "G" , "T" , "P" };
57 static const char unit_second_str
[] = "s" ;
58 static const char unit_hertz_str
[] = "Hz" ;
59 static const char unit_byte_str
[] = "byte" ;
60 static const char unit_bit_per_second_str
[] = "bit/s";
62 static void exit_program(void)
64 av_dict_free(&fmt_entries_to_show
);
68 * The output is structured in array and objects that might contain items
69 * Array could require the objects within to not be named.
70 * Object could require the items within to be named.
72 * For flat representation the name of each section is saved on prefix so it
73 * can be rendered in order to represent nested structures (e.g. array of
74 * objects for the packets list).
76 * Within an array each element can need an unique identifier or an index.
78 * Nesting level is accounted separately.
88 ProbeElementType type
;
96 void (*print_header
)(void);
97 void (*print_footer
)(void);
99 void (*print_array_header
) (const char *name
);
100 void (*print_array_footer
) (const char *name
);
101 void (*print_object_header
)(const char *name
);
102 void (*print_object_footer
)(const char *name
);
104 void (*print_integer
) (const char *key
, int64_t value
);
105 void (*print_string
) (const char *key
, const char *value
);
108 static AVIOContext
*probe_out
= NULL
;
109 static OutputContext octx
;
110 #define AVP_INDENT() avio_printf(probe_out, "%*c", octx.level * 2, ' ')
113 * Default format, INI
115 * - all key and values are utf8
116 * - '.' is the subgroup separator
117 * - newlines and the following characters are escaped
118 * - '\' is the escape character
119 * - '#' is the comment
120 * - '=' is the key/value separators
121 * - ':' is not used but usually parsed as key/value separator
124 static void ini_print_header(void)
126 avio_printf(probe_out
, "# avprobe output\n\n");
128 static void ini_print_footer(void)
130 avio_w8(probe_out
, '\n');
133 static void ini_escape_print(const char *s
)
140 case '\r': avio_printf(probe_out
, "%s", "\\r"); break;
141 case '\n': avio_printf(probe_out
, "%s", "\\n"); break;
142 case '\f': avio_printf(probe_out
, "%s", "\\f"); break;
143 case '\b': avio_printf(probe_out
, "%s", "\\b"); break;
144 case '\t': avio_printf(probe_out
, "%s", "\\t"); break;
148 case ':' : avio_w8(probe_out
, '\\');
150 if ((unsigned char)c
< 32)
151 avio_printf(probe_out
, "\\x00%02x", c
& 0xff);
153 avio_w8(probe_out
, c
);
159 static void ini_print_array_header(const char *name
)
161 if (octx
.prefix
[octx
.level
-1].nb_elems
)
162 avio_printf(probe_out
, "\n");
165 static void ini_print_object_header(const char *name
)
168 ProbeElement
*el
= octx
.prefix
+ octx
.level
-1;
171 avio_printf(probe_out
, "\n");
173 avio_printf(probe_out
, "[");
175 for (i
= 1; i
< octx
.level
; i
++) {
176 el
= octx
.prefix
+ i
;
177 avio_printf(probe_out
, "%s.", el
->name
);
179 avio_printf(probe_out
, "%"PRId64
".", el
->index
);
182 avio_printf(probe_out
, "%s", name
);
183 if (el
&& el
->type
== ARRAY
)
184 avio_printf(probe_out
, ".%"PRId64
"", el
->nb_elems
);
185 avio_printf(probe_out
, "]\n");
188 static void ini_print_integer(const char *key
, int64_t value
)
190 ini_escape_print(key
);
191 avio_printf(probe_out
, "=%"PRId64
"\n", value
);
195 static void ini_print_string(const char *key
, const char *value
)
197 ini_escape_print(key
);
198 avio_printf(probe_out
, "=");
199 ini_escape_print(value
);
200 avio_w8(probe_out
, '\n');
204 * Alternate format, JSON
207 static void json_print_header(void)
209 avio_printf(probe_out
, "{");
211 static void json_print_footer(void)
213 avio_printf(probe_out
, "}\n");
216 static void json_print_array_header(const char *name
)
218 if (octx
.prefix
[octx
.level
-1].nb_elems
)
219 avio_printf(probe_out
, ",\n");
221 avio_printf(probe_out
, "\"%s\" : ", name
);
222 avio_printf(probe_out
, "[\n");
225 static void json_print_array_footer(const char *name
)
227 avio_printf(probe_out
, "\n");
229 avio_printf(probe_out
, "]");
232 static void json_print_object_header(const char *name
)
234 if (octx
.prefix
[octx
.level
-1].nb_elems
)
235 avio_printf(probe_out
, ",\n");
237 if (octx
.prefix
[octx
.level
-1].type
== OBJECT
)
238 avio_printf(probe_out
, "\"%s\" : ", name
);
239 avio_printf(probe_out
, "{\n");
242 static void json_print_object_footer(const char *name
)
244 avio_printf(probe_out
, "\n");
246 avio_printf(probe_out
, "}");
249 static void json_print_integer(const char *key
, int64_t value
)
251 if (octx
.prefix
[octx
.level
-1].nb_elems
)
252 avio_printf(probe_out
, ",\n");
254 avio_printf(probe_out
, "\"%s\" : %"PRId64
"", key
, value
);
257 static void json_escape_print(const char *s
)
264 case '\r': avio_printf(probe_out
, "%s", "\\r"); break;
265 case '\n': avio_printf(probe_out
, "%s", "\\n"); break;
266 case '\f': avio_printf(probe_out
, "%s", "\\f"); break;
267 case '\b': avio_printf(probe_out
, "%s", "\\b"); break;
268 case '\t': avio_printf(probe_out
, "%s", "\\t"); break;
270 case '"' : avio_w8(probe_out
, '\\');
272 if ((unsigned char)c
< 32)
273 avio_printf(probe_out
, "\\u00%02x", c
& 0xff);
275 avio_w8(probe_out
, c
);
281 static void json_print_string(const char *key
, const char *value
)
283 if (octx
.prefix
[octx
.level
-1].nb_elems
)
284 avio_printf(probe_out
, ",\n");
286 avio_w8(probe_out
, '\"');
287 json_escape_print(key
);
288 avio_printf(probe_out
, "\" : \"");
289 json_escape_print(value
);
290 avio_w8(probe_out
, '\"');
294 * old-style pseudo-INI
296 static void old_print_object_header(const char *name
)
300 if (!strcmp(name
, "tags"))
303 str
= p
= av_strdup(name
);
309 avio_printf(probe_out
, "[%s]\n", str
);
313 static void old_print_object_footer(const char *name
)
317 if (!strcmp(name
, "tags"))
320 str
= p
= av_strdup(name
);
326 avio_printf(probe_out
, "[/%s]\n", str
);
330 static void old_print_string(const char *key
, const char *value
)
332 if (!strcmp(octx
.prefix
[octx
.level
- 1].name
, "tags"))
333 avio_printf(probe_out
, "TAG:");
334 ini_print_string(key
, value
);
338 * Simple Formatter for single entries.
341 static void show_format_entry_integer(const char *key
, int64_t value
)
343 if (key
&& av_dict_get(fmt_entries_to_show
, key
, NULL
, 0)) {
344 if (nb_fmt_entries_to_show
> 1)
345 avio_printf(probe_out
, "%s=", key
);
346 avio_printf(probe_out
, "%"PRId64
"\n", value
);
350 static void show_format_entry_string(const char *key
, const char *value
)
352 if (key
&& av_dict_get(fmt_entries_to_show
, key
, NULL
, 0)) {
353 if (nb_fmt_entries_to_show
> 1)
354 avio_printf(probe_out
, "%s=", key
);
355 avio_printf(probe_out
, "%s\n", value
);
359 static void probe_group_enter(const char *name
, int type
)
364 av_realloc(octx
.prefix
, sizeof(ProbeElement
) * (octx
.level
+ 1));
366 if (!octx
.prefix
|| !name
) {
367 fprintf(stderr
, "Out of memory\n");
372 ProbeElement
*parent
= octx
.prefix
+ octx
.level
-1;
373 if (parent
->type
== ARRAY
)
374 count
= parent
->nb_elems
;
378 octx
.prefix
[octx
.level
++] = (ProbeElement
){name
, type
, count
, 0};
381 static void probe_group_leave(void)
386 static void probe_header(void)
388 if (octx
.print_header
)
390 probe_group_enter("root", OBJECT
);
393 static void probe_footer(void)
395 if (octx
.print_footer
)
401 static void probe_array_header(const char *name
)
403 if (octx
.print_array_header
)
404 octx
.print_array_header(name
);
406 probe_group_enter(name
, ARRAY
);
409 static void probe_array_footer(const char *name
)
412 if (octx
.print_array_footer
)
413 octx
.print_array_footer(name
);
416 static void probe_object_header(const char *name
)
418 if (octx
.print_object_header
)
419 octx
.print_object_header(name
);
421 probe_group_enter(name
, OBJECT
);
424 static void probe_object_footer(const char *name
)
427 if (octx
.print_object_footer
)
428 octx
.print_object_footer(name
);
431 static void probe_int(const char *key
, int64_t value
)
433 octx
.print_integer(key
, value
);
434 octx
.prefix
[octx
.level
-1].nb_elems
++;
437 static void probe_str(const char *key
, const char *value
)
439 octx
.print_string(key
, value
);
440 octx
.prefix
[octx
.level
-1].nb_elems
++;
443 static void probe_dict(AVDictionary
*dict
, const char *name
)
445 AVDictionaryEntry
*entry
= NULL
;
448 probe_object_header(name
);
449 while ((entry
= av_dict_get(dict
, "", entry
, AV_DICT_IGNORE_SUFFIX
))) {
450 probe_str(entry
->key
, entry
->value
);
452 probe_object_footer(name
);
455 static char *value_string(char *buf
, int buf_size
, double val
, const char *unit
)
457 if (unit
== unit_second_str
&& use_value_sexagesimal_format
) {
461 mins
= (int)secs
/ 60;
462 secs
= secs
- mins
* 60;
465 snprintf(buf
, buf_size
, "%d:%02d:%09.6f", hours
, mins
, secs
);
466 } else if (use_value_prefix
) {
467 const char *prefix_string
;
470 if (unit
== unit_byte_str
&& use_byte_value_binary_prefix
) {
471 index
= (int) log2(val
) / 10;
472 index
= av_clip(index
, 0, FF_ARRAY_ELEMS(binary_unit_prefixes
) - 1);
473 val
/= pow(2, index
* 10);
474 prefix_string
= binary_unit_prefixes
[index
];
476 index
= (int) (log10(val
)) / 3;
477 index
= av_clip(index
, 0, FF_ARRAY_ELEMS(decimal_unit_prefixes
) - 1);
478 val
/= pow(10, index
* 3);
479 prefix_string
= decimal_unit_prefixes
[index
];
481 snprintf(buf
, buf_size
, "%.*f%s%s",
484 show_value_unit
? unit
: "");
486 snprintf(buf
, buf_size
, "%f%s", val
, show_value_unit
? unit
: "");
492 static char *time_value_string(char *buf
, int buf_size
, int64_t val
,
493 const AVRational
*time_base
)
495 if (val
== AV_NOPTS_VALUE
) {
496 snprintf(buf
, buf_size
, "N/A");
498 value_string(buf
, buf_size
, val
* av_q2d(*time_base
), unit_second_str
);
504 static char *ts_value_string(char *buf
, int buf_size
, int64_t ts
)
506 if (ts
== AV_NOPTS_VALUE
) {
507 snprintf(buf
, buf_size
, "N/A");
509 snprintf(buf
, buf_size
, "%"PRId64
, ts
);
515 static char *rational_string(char *buf
, int buf_size
, const char *sep
,
516 const AVRational
*rat
)
518 snprintf(buf
, buf_size
, "%d%s%d", rat
->num
, sep
, rat
->den
);
522 static char *tag_string(char *buf
, int buf_size
, int tag
)
524 snprintf(buf
, buf_size
, "0x%04x", tag
);
530 static const char *media_type_string(enum AVMediaType media_type
)
532 switch (media_type
) {
533 case AVMEDIA_TYPE_VIDEO
: return "video";
534 case AVMEDIA_TYPE_AUDIO
: return "audio";
535 case AVMEDIA_TYPE_DATA
: return "data";
536 case AVMEDIA_TYPE_SUBTITLE
: return "subtitle";
537 case AVMEDIA_TYPE_ATTACHMENT
: return "attachment";
538 default: return "unknown";
542 static void show_packet(AVFormatContext
*fmt_ctx
, AVPacket
*pkt
)
545 AVStream
*st
= fmt_ctx
->streams
[pkt
->stream_index
];
547 probe_object_header("packet");
548 probe_str("codec_type", media_type_string(st
->codec
->codec_type
));
549 probe_int("stream_index", pkt
->stream_index
);
550 probe_str("pts", ts_value_string(val_str
, sizeof(val_str
), pkt
->pts
));
551 probe_str("pts_time", time_value_string(val_str
, sizeof(val_str
),
552 pkt
->pts
, &st
->time_base
));
553 probe_str("dts", ts_value_string(val_str
, sizeof(val_str
), pkt
->dts
));
554 probe_str("dts_time", time_value_string(val_str
, sizeof(val_str
),
555 pkt
->dts
, &st
->time_base
));
556 probe_str("duration", ts_value_string(val_str
, sizeof(val_str
),
558 probe_str("duration_time", time_value_string(val_str
, sizeof(val_str
),
561 probe_str("size", value_string(val_str
, sizeof(val_str
),
562 pkt
->size
, unit_byte_str
));
563 probe_int("pos", pkt
->pos
);
564 probe_str("flags", pkt
->flags
& AV_PKT_FLAG_KEY
? "K" : "_");
565 probe_object_footer("packet");
568 static void show_packets(AVFormatContext
*fmt_ctx
)
572 av_init_packet(&pkt
);
573 probe_array_header("packets");
574 while (!av_read_frame(fmt_ctx
, &pkt
))
575 show_packet(fmt_ctx
, &pkt
);
576 probe_array_footer("packets");
579 static void show_stream(AVFormatContext
*fmt_ctx
, int stream_idx
)
581 AVStream
*stream
= fmt_ctx
->streams
[stream_idx
];
582 AVCodecContext
*dec_ctx
;
586 AVRational display_aspect_ratio
;
587 const AVPixFmtDescriptor
*desc
;
589 probe_object_header("stream");
591 probe_int("index", stream
->index
);
593 if ((dec_ctx
= stream
->codec
)) {
594 if ((dec
= dec_ctx
->codec
)) {
595 probe_str("codec_name", dec
->name
);
596 probe_str("codec_long_name", dec
->long_name
);
598 probe_str("codec_name", "unknown");
601 probe_str("codec_type", media_type_string(dec_ctx
->codec_type
));
602 probe_str("codec_time_base",
603 rational_string(val_str
, sizeof(val_str
),
604 "/", &dec_ctx
->time_base
));
606 /* print AVI/FourCC tag */
607 av_get_codec_tag_string(val_str
, sizeof(val_str
), dec_ctx
->codec_tag
);
608 probe_str("codec_tag_string", val_str
);
609 probe_str("codec_tag", tag_string(val_str
, sizeof(val_str
),
610 dec_ctx
->codec_tag
));
612 /* print profile, if there is one */
613 if (dec
&& (profile
= av_get_profile_name(dec
, dec_ctx
->profile
)))
614 probe_str("profile", profile
);
616 switch (dec_ctx
->codec_type
) {
617 case AVMEDIA_TYPE_VIDEO
:
618 probe_int("width", dec_ctx
->width
);
619 probe_int("height", dec_ctx
->height
);
620 probe_int("has_b_frames", dec_ctx
->has_b_frames
);
621 if (dec_ctx
->sample_aspect_ratio
.num
) {
622 probe_str("sample_aspect_ratio",
623 rational_string(val_str
, sizeof(val_str
), ":",
624 &dec_ctx
->sample_aspect_ratio
));
625 av_reduce(&display_aspect_ratio
.num
, &display_aspect_ratio
.den
,
626 dec_ctx
->width
* dec_ctx
->sample_aspect_ratio
.num
,
627 dec_ctx
->height
* dec_ctx
->sample_aspect_ratio
.den
,
629 probe_str("display_aspect_ratio",
630 rational_string(val_str
, sizeof(val_str
), ":",
631 &display_aspect_ratio
));
633 desc
= av_pix_fmt_desc_get(dec_ctx
->pix_fmt
);
634 probe_str("pix_fmt", desc
? desc
->name
: "unknown");
635 probe_int("level", dec_ctx
->level
);
638 case AVMEDIA_TYPE_AUDIO
:
639 probe_str("sample_rate",
640 value_string(val_str
, sizeof(val_str
),
641 dec_ctx
->sample_rate
,
643 probe_int("channels", dec_ctx
->channels
);
644 probe_int("bits_per_sample",
645 av_get_bits_per_sample(dec_ctx
->codec_id
));
649 probe_str("codec_type", "unknown");
652 if (fmt_ctx
->iformat
->flags
& AVFMT_SHOW_IDS
)
653 probe_int("id", stream
->id
);
654 probe_str("avg_frame_rate",
655 rational_string(val_str
, sizeof(val_str
), "/",
656 &stream
->avg_frame_rate
));
657 if (dec_ctx
->bit_rate
)
658 probe_str("bit_rate",
659 value_string(val_str
, sizeof(val_str
),
660 dec_ctx
->bit_rate
, unit_bit_per_second_str
));
661 probe_str("time_base",
662 rational_string(val_str
, sizeof(val_str
), "/",
663 &stream
->time_base
));
664 probe_str("start_time",
665 time_value_string(val_str
, sizeof(val_str
),
666 stream
->start_time
, &stream
->time_base
));
667 probe_str("duration",
668 time_value_string(val_str
, sizeof(val_str
),
669 stream
->duration
, &stream
->time_base
));
670 if (stream
->nb_frames
)
671 probe_int("nb_frames", stream
->nb_frames
);
673 probe_dict(stream
->metadata
, "tags");
675 probe_object_footer("stream");
678 static void show_format(AVFormatContext
*fmt_ctx
)
681 int64_t size
= fmt_ctx
->pb
? avio_size(fmt_ctx
->pb
) : -1;
683 probe_object_header("format");
684 probe_str("filename", fmt_ctx
->filename
);
685 probe_int("nb_streams", fmt_ctx
->nb_streams
);
686 probe_str("format_name", fmt_ctx
->iformat
->name
);
687 probe_str("format_long_name", fmt_ctx
->iformat
->long_name
);
688 probe_str("start_time",
689 time_value_string(val_str
, sizeof(val_str
),
690 fmt_ctx
->start_time
, &AV_TIME_BASE_Q
));
691 probe_str("duration",
692 time_value_string(val_str
, sizeof(val_str
),
693 fmt_ctx
->duration
, &AV_TIME_BASE_Q
));
695 size
>= 0 ? value_string(val_str
, sizeof(val_str
),
698 probe_str("bit_rate",
699 value_string(val_str
, sizeof(val_str
),
700 fmt_ctx
->bit_rate
, unit_bit_per_second_str
));
702 probe_dict(fmt_ctx
->metadata
, "tags");
704 probe_object_footer("format");
707 static int open_input_file(AVFormatContext
**fmt_ctx_ptr
, const char *filename
)
710 AVFormatContext
*fmt_ctx
= NULL
;
711 AVDictionaryEntry
*t
;
713 if ((err
= avformat_open_input(&fmt_ctx
, filename
,
714 iformat
, &format_opts
)) < 0) {
715 print_error(filename
, err
);
718 if ((t
= av_dict_get(format_opts
, "", NULL
, AV_DICT_IGNORE_SUFFIX
))) {
719 av_log(NULL
, AV_LOG_ERROR
, "Option %s not found.\n", t
->key
);
720 return AVERROR_OPTION_NOT_FOUND
;
724 /* fill the streams in the format context */
725 if ((err
= avformat_find_stream_info(fmt_ctx
, NULL
)) < 0) {
726 print_error(filename
, err
);
730 av_dump_format(fmt_ctx
, 0, filename
, 0);
732 /* bind a decoder to each input stream */
733 for (i
= 0; i
< fmt_ctx
->nb_streams
; i
++) {
734 AVStream
*stream
= fmt_ctx
->streams
[i
];
737 if (stream
->codec
->codec_id
== AV_CODEC_ID_PROBE
) {
738 fprintf(stderr
, "Failed to probe codec for input stream %d\n",
740 } else if (!(codec
= avcodec_find_decoder(stream
->codec
->codec_id
))) {
742 "Unsupported codec with id %d for input stream %d\n",
743 stream
->codec
->codec_id
, stream
->index
);
744 } else if (avcodec_open2(stream
->codec
, codec
, NULL
) < 0) {
745 fprintf(stderr
, "Error while opening codec for input stream %d\n",
750 *fmt_ctx_ptr
= fmt_ctx
;
754 static void close_input_file(AVFormatContext
**ctx_ptr
)
757 AVFormatContext
*fmt_ctx
= *ctx_ptr
;
759 /* close decoder for each stream */
760 for (i
= 0; i
< fmt_ctx
->nb_streams
; i
++) {
761 AVStream
*stream
= fmt_ctx
->streams
[i
];
763 avcodec_close(stream
->codec
);
765 avformat_close_input(ctx_ptr
);
768 static int probe_file(const char *filename
)
770 AVFormatContext
*fmt_ctx
;
773 if ((ret
= open_input_file(&fmt_ctx
, filename
)))
777 show_format(fmt_ctx
);
779 if (do_show_streams
) {
780 probe_array_header("streams");
781 for (i
= 0; i
< fmt_ctx
->nb_streams
; i
++)
782 show_stream(fmt_ctx
, i
);
783 probe_array_footer("streams");
787 show_packets(fmt_ctx
);
789 close_input_file(&fmt_ctx
);
793 static void show_usage(void)
795 printf("Simple multimedia streams analyzer\n");
796 printf("usage: %s [OPTIONS] [INPUT_FILE]\n", program_name
);
800 static int opt_format(void *optctx
, const char *opt
, const char *arg
)
802 iformat
= av_find_input_format(arg
);
804 fprintf(stderr
, "Unknown input format: %s\n", arg
);
805 return AVERROR(EINVAL
);
810 static int opt_output_format(void *optctx
, const char *opt
, const char *arg
)
813 if (!strcmp(arg
, "json")) {
814 octx
.print_header
= json_print_header
;
815 octx
.print_footer
= json_print_footer
;
816 octx
.print_array_header
= json_print_array_header
;
817 octx
.print_array_footer
= json_print_array_footer
;
818 octx
.print_object_header
= json_print_object_header
;
819 octx
.print_object_footer
= json_print_object_footer
;
821 octx
.print_integer
= json_print_integer
;
822 octx
.print_string
= json_print_string
;
823 } else if (!strcmp(arg
, "ini")) {
824 octx
.print_header
= ini_print_header
;
825 octx
.print_footer
= ini_print_footer
;
826 octx
.print_array_header
= ini_print_array_header
;
827 octx
.print_object_header
= ini_print_object_header
;
829 octx
.print_integer
= ini_print_integer
;
830 octx
.print_string
= ini_print_string
;
831 } else if (!strcmp(arg
, "old")) {
832 octx
.print_header
= NULL
;
833 octx
.print_object_header
= old_print_object_header
;
834 octx
.print_object_footer
= old_print_object_footer
;
836 octx
.print_string
= old_print_string
;
838 av_log(NULL
, AV_LOG_ERROR
, "Unsupported formatter %s\n", arg
);
839 return AVERROR(EINVAL
);
844 static int opt_show_format_entry(void *optctx
, const char *opt
, const char *arg
)
847 nb_fmt_entries_to_show
++;
848 octx
.print_header
= NULL
;
849 octx
.print_footer
= NULL
;
850 octx
.print_array_header
= NULL
;
851 octx
.print_array_footer
= NULL
;
852 octx
.print_object_header
= NULL
;
853 octx
.print_object_footer
= NULL
;
855 octx
.print_integer
= show_format_entry_integer
;
856 octx
.print_string
= show_format_entry_string
;
857 av_dict_set(&fmt_entries_to_show
, arg
, "", 0);
861 static void opt_input_file(void *optctx
, const char *arg
)
863 if (input_filename
) {
865 "Argument '%s' provided as input filename, but '%s' was already specified.\n",
866 arg
, input_filename
);
869 if (!strcmp(arg
, "-"))
871 input_filename
= arg
;
874 void show_help_default(const char *opt
, const char *arg
)
876 av_log_set_callback(log_callback_help
);
878 show_help_options(options
, "Main options:", 0, 0, 0);
880 show_help_children(avformat_get_class(), AV_OPT_FLAG_DECODING_PARAM
);
883 static int opt_pretty(void *optctx
, const char *opt
, const char *arg
)
886 use_value_prefix
= 1;
887 use_byte_value_binary_prefix
= 1;
888 use_value_sexagesimal_format
= 1;
892 static const OptionDef real_options
[] = {
893 #include "cmdutils_common_opts.h"
894 { "f", HAS_ARG
, {.func_arg
= opt_format
}, "force format", "format" },
895 { "of", HAS_ARG
, {.func_arg
= opt_output_format
}, "output the document either as ini or json", "output_format" },
896 { "unit", OPT_BOOL
, {&show_value_unit
},
897 "show unit of the displayed values" },
898 { "prefix", OPT_BOOL
, {&use_value_prefix
},
899 "use SI prefixes for the displayed values" },
900 { "byte_binary_prefix", OPT_BOOL
, {&use_byte_value_binary_prefix
},
901 "use binary prefixes for byte units" },
902 { "sexagesimal", OPT_BOOL
, {&use_value_sexagesimal_format
},
903 "use sexagesimal format HOURS:MM:SS.MICROSECONDS for time units" },
904 { "pretty", 0, {.func_arg
= opt_pretty
},
905 "prettify the format of displayed values, make it more human readable" },
906 { "show_format", OPT_BOOL
, {&do_show_format
} , "show format/container info" },
907 { "show_format_entry", HAS_ARG
, {.func_arg
= opt_show_format_entry
},
908 "show a particular entry from the format/container info", "entry" },
909 { "show_packets", OPT_BOOL
, {&do_show_packets
}, "show packets info" },
910 { "show_streams", OPT_BOOL
, {&do_show_streams
}, "show streams info" },
911 { "default", HAS_ARG
| OPT_AUDIO
| OPT_VIDEO
| OPT_EXPERT
, {.func_arg
= opt_default
},
912 "generic catch all option", "" },
916 static int probe_buf_write(void *opaque
, uint8_t *buf
, int buf_size
)
918 printf("%.*s", buf_size
, buf
);
922 #define AVP_BUFFSIZE 4096
924 int main(int argc
, char **argv
)
927 uint8_t *buffer
= av_malloc(AVP_BUFFSIZE
);
932 atexit(exit_program
);
934 options
= real_options
;
935 parse_loglevel(argc
, argv
, options
);
937 avformat_network_init();
940 avdevice_register_all();
945 octx
.print_header
= ini_print_header
;
946 octx
.print_footer
= ini_print_footer
;
948 octx
.print_array_header
= ini_print_array_header
;
949 octx
.print_object_header
= ini_print_object_header
;
951 octx
.print_integer
= ini_print_integer
;
952 octx
.print_string
= ini_print_string
;
954 parse_options(NULL
, argc
, argv
, options
, opt_input_file
);
956 if (!input_filename
) {
958 fprintf(stderr
, "You have to specify one input file.\n");
960 "Use -h to get full help or, even better, run 'man %s'.\n",
965 probe_out
= avio_alloc_context(buffer
, AVP_BUFFSIZE
, 1, NULL
, NULL
,
966 probe_buf_write
, NULL
);
971 ret
= probe_file(input_filename
);
973 avio_flush(probe_out
);
974 avio_close(probe_out
);
976 avformat_network_deinit();