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 void exit_program(int ret
)
64 av_dict_free(&fmt_entries_to_show
);
69 * The output is structured in array and objects that might contain items
70 * Array could require the objects within to not be named.
71 * Object could require the items within to be named.
73 * For flat representation the name of each section is saved on prefix so it
74 * can be rendered in order to represent nested structures (e.g. array of
75 * objects for the packets list).
77 * Within an array each element can need an unique identifier or an index.
79 * Nesting level is accounted separately.
89 ProbeElementType type
;
97 void (*print_header
)(void);
98 void (*print_footer
)(void);
100 void (*print_array_header
) (const char *name
);
101 void (*print_array_footer
) (const char *name
);
102 void (*print_object_header
)(const char *name
);
103 void (*print_object_footer
)(const char *name
);
105 void (*print_integer
) (const char *key
, int64_t value
);
106 void (*print_string
) (const char *key
, const char *value
);
109 static AVIOContext
*probe_out
= NULL
;
110 static OutputContext octx
;
111 #define AVP_INDENT() avio_printf(probe_out, "%*c", octx.level * 2, ' ')
114 * Default format, INI
116 * - all key and values are utf8
117 * - '.' is the subgroup separator
118 * - newlines and the following characters are escaped
119 * - '\' is the escape character
120 * - '#' is the comment
121 * - '=' is the key/value separators
122 * - ':' is not used but usually parsed as key/value separator
125 static void ini_print_header(void)
127 avio_printf(probe_out
, "# avprobe output\n\n");
129 static void ini_print_footer(void)
131 avio_w8(probe_out
, '\n');
134 static void ini_escape_print(const char *s
)
141 case '\r': avio_printf(probe_out
, "%s", "\\r"); break;
142 case '\n': avio_printf(probe_out
, "%s", "\\n"); break;
143 case '\f': avio_printf(probe_out
, "%s", "\\f"); break;
144 case '\b': avio_printf(probe_out
, "%s", "\\b"); break;
145 case '\t': avio_printf(probe_out
, "%s", "\\t"); break;
149 case ':' : avio_w8(probe_out
, '\\');
151 if ((unsigned char)c
< 32)
152 avio_printf(probe_out
, "\\x00%02x", c
& 0xff);
154 avio_w8(probe_out
, c
);
160 static void ini_print_array_header(const char *name
)
162 if (octx
.prefix
[octx
.level
-1].nb_elems
)
163 avio_printf(probe_out
, "\n");
166 static void ini_print_object_header(const char *name
)
169 ProbeElement
*el
= octx
.prefix
+ octx
.level
-1;
172 avio_printf(probe_out
, "\n");
174 avio_printf(probe_out
, "[");
176 for (i
= 1; i
< octx
.level
; i
++) {
177 el
= octx
.prefix
+ i
;
178 avio_printf(probe_out
, "%s.", el
->name
);
180 avio_printf(probe_out
, "%"PRId64
".", el
->index
);
183 avio_printf(probe_out
, "%s", name
);
184 if (el
&& el
->type
== ARRAY
)
185 avio_printf(probe_out
, ".%"PRId64
"", el
->nb_elems
);
186 avio_printf(probe_out
, "]\n");
189 static void ini_print_integer(const char *key
, int64_t value
)
191 ini_escape_print(key
);
192 avio_printf(probe_out
, "=%"PRId64
"\n", value
);
196 static void ini_print_string(const char *key
, const char *value
)
198 ini_escape_print(key
);
199 avio_printf(probe_out
, "=");
200 ini_escape_print(value
);
201 avio_w8(probe_out
, '\n');
205 * Alternate format, JSON
208 static void json_print_header(void)
210 avio_printf(probe_out
, "{");
212 static void json_print_footer(void)
214 avio_printf(probe_out
, "}\n");
217 static void json_print_array_header(const char *name
)
219 if (octx
.prefix
[octx
.level
-1].nb_elems
)
220 avio_printf(probe_out
, ",\n");
222 avio_printf(probe_out
, "\"%s\" : ", name
);
223 avio_printf(probe_out
, "[\n");
226 static void json_print_array_footer(const char *name
)
228 avio_printf(probe_out
, "\n");
230 avio_printf(probe_out
, "]");
233 static void json_print_object_header(const char *name
)
235 if (octx
.prefix
[octx
.level
-1].nb_elems
)
236 avio_printf(probe_out
, ",\n");
238 if (octx
.prefix
[octx
.level
-1].type
== OBJECT
)
239 avio_printf(probe_out
, "\"%s\" : ", name
);
240 avio_printf(probe_out
, "{\n");
243 static void json_print_object_footer(const char *name
)
245 avio_printf(probe_out
, "\n");
247 avio_printf(probe_out
, "}");
250 static void json_print_integer(const char *key
, int64_t value
)
252 if (octx
.prefix
[octx
.level
-1].nb_elems
)
253 avio_printf(probe_out
, ",\n");
255 avio_printf(probe_out
, "\"%s\" : %"PRId64
"", key
, value
);
258 static void json_escape_print(const char *s
)
265 case '\r': avio_printf(probe_out
, "%s", "\\r"); break;
266 case '\n': avio_printf(probe_out
, "%s", "\\n"); break;
267 case '\f': avio_printf(probe_out
, "%s", "\\f"); break;
268 case '\b': avio_printf(probe_out
, "%s", "\\b"); break;
269 case '\t': avio_printf(probe_out
, "%s", "\\t"); break;
271 case '"' : avio_w8(probe_out
, '\\');
273 if ((unsigned char)c
< 32)
274 avio_printf(probe_out
, "\\u00%02x", c
& 0xff);
276 avio_w8(probe_out
, c
);
282 static void json_print_string(const char *key
, const char *value
)
284 if (octx
.prefix
[octx
.level
-1].nb_elems
)
285 avio_printf(probe_out
, ",\n");
287 avio_w8(probe_out
, '\"');
288 json_escape_print(key
);
289 avio_printf(probe_out
, "\" : \"");
290 json_escape_print(value
);
291 avio_w8(probe_out
, '\"');
295 * old-style pseudo-INI
297 static void old_print_object_header(const char *name
)
301 if (!strcmp(name
, "tags"))
304 str
= p
= av_strdup(name
);
310 avio_printf(probe_out
, "[%s]\n", str
);
314 static void old_print_object_footer(const char *name
)
318 if (!strcmp(name
, "tags"))
321 str
= p
= av_strdup(name
);
327 avio_printf(probe_out
, "[/%s]\n", str
);
331 static void old_print_string(const char *key
, const char *value
)
333 if (!strcmp(octx
.prefix
[octx
.level
- 1].name
, "tags"))
334 avio_printf(probe_out
, "TAG:");
335 ini_print_string(key
, value
);
339 * Simple Formatter for single entries.
342 static void show_format_entry_integer(const char *key
, int64_t value
)
344 if (key
&& av_dict_get(fmt_entries_to_show
, key
, NULL
, 0)) {
345 if (nb_fmt_entries_to_show
> 1)
346 avio_printf(probe_out
, "%s=", key
);
347 avio_printf(probe_out
, "%"PRId64
"\n", value
);
351 static void show_format_entry_string(const char *key
, const char *value
)
353 if (key
&& av_dict_get(fmt_entries_to_show
, key
, NULL
, 0)) {
354 if (nb_fmt_entries_to_show
> 1)
355 avio_printf(probe_out
, "%s=", key
);
356 avio_printf(probe_out
, "%s\n", value
);
360 static void probe_group_enter(const char *name
, int type
)
365 av_realloc(octx
.prefix
, sizeof(ProbeElement
) * (octx
.level
+ 1));
367 if (!octx
.prefix
|| !name
) {
368 fprintf(stderr
, "Out of memory\n");
373 ProbeElement
*parent
= octx
.prefix
+ octx
.level
-1;
374 if (parent
->type
== ARRAY
)
375 count
= parent
->nb_elems
;
379 octx
.prefix
[octx
.level
++] = (ProbeElement
){name
, type
, count
, 0};
382 static void probe_group_leave(void)
387 static void probe_header(void)
389 if (octx
.print_header
)
391 probe_group_enter("root", OBJECT
);
394 static void probe_footer(void)
396 if (octx
.print_footer
)
402 static void probe_array_header(const char *name
)
404 if (octx
.print_array_header
)
405 octx
.print_array_header(name
);
407 probe_group_enter(name
, ARRAY
);
410 static void probe_array_footer(const char *name
)
413 if (octx
.print_array_footer
)
414 octx
.print_array_footer(name
);
417 static void probe_object_header(const char *name
)
419 if (octx
.print_object_header
)
420 octx
.print_object_header(name
);
422 probe_group_enter(name
, OBJECT
);
425 static void probe_object_footer(const char *name
)
428 if (octx
.print_object_footer
)
429 octx
.print_object_footer(name
);
432 static void probe_int(const char *key
, int64_t value
)
434 octx
.print_integer(key
, value
);
435 octx
.prefix
[octx
.level
-1].nb_elems
++;
438 static void probe_str(const char *key
, const char *value
)
440 octx
.print_string(key
, value
);
441 octx
.prefix
[octx
.level
-1].nb_elems
++;
444 static void probe_dict(AVDictionary
*dict
, const char *name
)
446 AVDictionaryEntry
*entry
= NULL
;
449 probe_object_header(name
);
450 while ((entry
= av_dict_get(dict
, "", entry
, AV_DICT_IGNORE_SUFFIX
))) {
451 probe_str(entry
->key
, entry
->value
);
453 probe_object_footer(name
);
456 static char *value_string(char *buf
, int buf_size
, double val
, const char *unit
)
458 if (unit
== unit_second_str
&& use_value_sexagesimal_format
) {
462 mins
= (int)secs
/ 60;
463 secs
= secs
- mins
* 60;
466 snprintf(buf
, buf_size
, "%d:%02d:%09.6f", hours
, mins
, secs
);
467 } else if (use_value_prefix
) {
468 const char *prefix_string
;
471 if (unit
== unit_byte_str
&& use_byte_value_binary_prefix
) {
472 index
= (int) log2(val
) / 10;
473 index
= av_clip(index
, 0, FF_ARRAY_ELEMS(binary_unit_prefixes
) - 1);
474 val
/= pow(2, index
* 10);
475 prefix_string
= binary_unit_prefixes
[index
];
477 index
= (int) (log10(val
)) / 3;
478 index
= av_clip(index
, 0, FF_ARRAY_ELEMS(decimal_unit_prefixes
) - 1);
479 val
/= pow(10, index
* 3);
480 prefix_string
= decimal_unit_prefixes
[index
];
482 snprintf(buf
, buf_size
, "%.*f%s%s",
485 show_value_unit ? unit
: "");
487 snprintf(buf
, buf_size
, "%f%s", val
, show_value_unit ? unit
: "");
493 static char *time_value_string(char *buf
, int buf_size
, int64_t val
,
494 const AVRational
*time_base
)
496 if (val
== AV_NOPTS_VALUE
) {
497 snprintf(buf
, buf_size
, "N/A");
499 value_string(buf
, buf_size
, val
* av_q2d(*time_base
), unit_second_str
);
505 static char *ts_value_string(char *buf
, int buf_size
, int64_t ts
)
507 if (ts
== AV_NOPTS_VALUE
) {
508 snprintf(buf
, buf_size
, "N/A");
510 snprintf(buf
, buf_size
, "%"PRId64
, ts
);
516 static char *rational_string(char *buf
, int buf_size
, const char *sep
,
517 const AVRational
*rat
)
519 snprintf(buf
, buf_size
, "%d%s%d", rat
->num
, sep
, rat
->den
);
523 static char *tag_string(char *buf
, int buf_size
, int tag
)
525 snprintf(buf
, buf_size
, "0x%04x", tag
);
531 static const char *media_type_string(enum AVMediaType media_type
)
533 switch (media_type
) {
534 case AVMEDIA_TYPE_VIDEO
: return "video";
535 case AVMEDIA_TYPE_AUDIO
: return "audio";
536 case AVMEDIA_TYPE_DATA
: return "data";
537 case AVMEDIA_TYPE_SUBTITLE
: return "subtitle";
538 case AVMEDIA_TYPE_ATTACHMENT
: return "attachment";
539 default: return "unknown";
543 static void show_packet(AVFormatContext
*fmt_ctx
, AVPacket
*pkt
)
546 AVStream
*st
= fmt_ctx
->streams
[pkt
->stream_index
];
548 probe_object_header("packet");
549 probe_str("codec_type", media_type_string(st
->codec
->codec_type
));
550 probe_int("stream_index", pkt
->stream_index
);
551 probe_str("pts", ts_value_string(val_str
, sizeof(val_str
), pkt
->pts
));
552 probe_str("pts_time", time_value_string(val_str
, sizeof(val_str
),
553 pkt
->pts
, &st
->time_base
));
554 probe_str("dts", ts_value_string(val_str
, sizeof(val_str
), pkt
->dts
));
555 probe_str("dts_time", time_value_string(val_str
, sizeof(val_str
),
556 pkt
->dts
, &st
->time_base
));
557 probe_str("duration", ts_value_string(val_str
, sizeof(val_str
),
559 probe_str("duration_time", time_value_string(val_str
, sizeof(val_str
),
562 probe_str("size", value_string(val_str
, sizeof(val_str
),
563 pkt
->size
, unit_byte_str
));
564 probe_int("pos", pkt
->pos
);
565 probe_str("flags", pkt
->flags
& AV_PKT_FLAG_KEY ?
"K" : "_");
566 probe_object_footer("packet");
569 static void show_packets(AVFormatContext
*fmt_ctx
)
573 av_init_packet(&pkt
);
574 probe_array_header("packets");
575 while (!av_read_frame(fmt_ctx
, &pkt
))
576 show_packet(fmt_ctx
, &pkt
);
577 probe_array_footer("packets");
580 static void show_stream(AVFormatContext
*fmt_ctx
, int stream_idx
)
582 AVStream
*stream
= fmt_ctx
->streams
[stream_idx
];
583 AVCodecContext
*dec_ctx
;
587 AVRational display_aspect_ratio
;
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
));
634 dec_ctx
->pix_fmt
!= PIX_FMT_NONE ? av_pix_fmt_descriptors
[dec_ctx
->pix_fmt
].name
636 probe_int("level", dec_ctx
->level
);
639 case AVMEDIA_TYPE_AUDIO
:
640 probe_str("sample_rate",
641 value_string(val_str
, sizeof(val_str
),
642 dec_ctx
->sample_rate
,
644 probe_int("channels", dec_ctx
->channels
);
645 probe_int("bits_per_sample",
646 av_get_bits_per_sample(dec_ctx
->codec_id
));
650 probe_str("codec_type", "unknown");
653 if (fmt_ctx
->iformat
->flags
& AVFMT_SHOW_IDS
)
654 probe_int("id", stream
->id
);
655 probe_str("avg_frame_rate",
656 rational_string(val_str
, sizeof(val_str
), "/",
657 &stream
->avg_frame_rate
));
658 probe_str("time_base",
659 rational_string(val_str
, sizeof(val_str
), "/",
660 &stream
->time_base
));
661 probe_str("start_time",
662 time_value_string(val_str
, sizeof(val_str
),
663 stream
->start_time
, &stream
->time_base
));
664 probe_str("duration",
665 time_value_string(val_str
, sizeof(val_str
),
666 stream
->duration
, &stream
->time_base
));
667 if (stream
->nb_frames
)
668 probe_int("nb_frames", stream
->nb_frames
);
670 probe_dict(stream
->metadata
, "tags");
672 probe_object_footer("stream");
675 static void show_format(AVFormatContext
*fmt_ctx
)
678 int64_t size
= fmt_ctx
->pb ?
avio_size(fmt_ctx
->pb
) : -1;
680 probe_object_header("format");
681 probe_str("filename", fmt_ctx
->filename
);
682 probe_int("nb_streams", fmt_ctx
->nb_streams
);
683 probe_str("format_name", fmt_ctx
->iformat
->name
);
684 probe_str("format_long_name", fmt_ctx
->iformat
->long_name
);
685 probe_str("start_time",
686 time_value_string(val_str
, sizeof(val_str
),
687 fmt_ctx
->start_time
, &AV_TIME_BASE_Q
));
688 probe_str("duration",
689 time_value_string(val_str
, sizeof(val_str
),
690 fmt_ctx
->duration
, &AV_TIME_BASE_Q
));
692 size
>= 0 ?
value_string(val_str
, sizeof(val_str
),
695 probe_str("bit_rate",
696 value_string(val_str
, sizeof(val_str
),
697 fmt_ctx
->bit_rate
, unit_bit_per_second_str
));
699 probe_dict(fmt_ctx
->metadata
, "tags");
701 probe_object_footer("format");
704 static int open_input_file(AVFormatContext
**fmt_ctx_ptr
, const char *filename
)
707 AVFormatContext
*fmt_ctx
= NULL
;
708 AVDictionaryEntry
*t
;
710 if ((err
= avformat_open_input(&fmt_ctx
, filename
,
711 iformat
, &format_opts
)) < 0) {
712 print_error(filename
, err
);
715 if ((t
= av_dict_get(format_opts
, "", NULL
, AV_DICT_IGNORE_SUFFIX
))) {
716 av_log(NULL
, AV_LOG_ERROR
, "Option %s not found.\n", t
->key
);
717 return AVERROR_OPTION_NOT_FOUND
;
721 /* fill the streams in the format context */
722 if ((err
= avformat_find_stream_info(fmt_ctx
, NULL
)) < 0) {
723 print_error(filename
, err
);
727 av_dump_format(fmt_ctx
, 0, filename
, 0);
729 /* bind a decoder to each input stream */
730 for (i
= 0; i
< fmt_ctx
->nb_streams
; i
++) {
731 AVStream
*stream
= fmt_ctx
->streams
[i
];
734 if (stream
->codec
->codec_id
== AV_CODEC_ID_PROBE
) {
735 fprintf(stderr
, "Failed to probe codec for input stream %d\n",
737 } else if (!(codec
= avcodec_find_decoder(stream
->codec
->codec_id
))) {
739 "Unsupported codec with id %d for input stream %d\n",
740 stream
->codec
->codec_id
, stream
->index
);
741 } else if (avcodec_open2(stream
->codec
, codec
, NULL
) < 0) {
742 fprintf(stderr
, "Error while opening codec for input stream %d\n",
747 *fmt_ctx_ptr
= fmt_ctx
;
751 static void close_input_file(AVFormatContext
**ctx_ptr
)
754 AVFormatContext
*fmt_ctx
= *ctx_ptr
;
756 /* close decoder for each stream */
757 for (i
= 0; i
< fmt_ctx
->nb_streams
; i
++) {
758 AVStream
*stream
= fmt_ctx
->streams
[i
];
760 avcodec_close(stream
->codec
);
762 avformat_close_input(ctx_ptr
);
765 static int probe_file(const char *filename
)
767 AVFormatContext
*fmt_ctx
;
770 if ((ret
= open_input_file(&fmt_ctx
, filename
)))
774 show_format(fmt_ctx
);
776 if (do_show_streams
) {
777 probe_array_header("streams");
778 for (i
= 0; i
< fmt_ctx
->nb_streams
; i
++)
779 show_stream(fmt_ctx
, i
);
780 probe_array_footer("streams");
784 show_packets(fmt_ctx
);
786 close_input_file(&fmt_ctx
);
790 static void show_usage(void)
792 printf("Simple multimedia streams analyzer\n");
793 printf("usage: %s [OPTIONS] [INPUT_FILE]\n", program_name
);
797 static int opt_format(const char *opt
, const char *arg
)
799 iformat
= av_find_input_format(arg
);
801 fprintf(stderr
, "Unknown input format: %s\n", arg
);
802 return AVERROR(EINVAL
);
807 static int opt_output_format(const char *opt
, const char *arg
)
810 if (!strcmp(arg
, "json")) {
811 octx
.print_header
= json_print_header
;
812 octx
.print_footer
= json_print_footer
;
813 octx
.print_array_header
= json_print_array_header
;
814 octx
.print_array_footer
= json_print_array_footer
;
815 octx
.print_object_header
= json_print_object_header
;
816 octx
.print_object_footer
= json_print_object_footer
;
818 octx
.print_integer
= json_print_integer
;
819 octx
.print_string
= json_print_string
;
820 } else if (!strcmp(arg
, "ini")) {
821 octx
.print_header
= ini_print_header
;
822 octx
.print_footer
= ini_print_footer
;
823 octx
.print_array_header
= ini_print_array_header
;
824 octx
.print_object_header
= ini_print_object_header
;
826 octx
.print_integer
= ini_print_integer
;
827 octx
.print_string
= ini_print_string
;
828 } else if (!strcmp(arg
, "old")) {
829 octx
.print_header
= NULL
;
830 octx
.print_object_header
= old_print_object_header
;
831 octx
.print_object_footer
= old_print_object_footer
;
833 octx
.print_string
= old_print_string
;
835 av_log(NULL
, AV_LOG_ERROR
, "Unsupported formatter %s\n", arg
);
836 return AVERROR(EINVAL
);
841 static int opt_show_format_entry(const char *opt
, const char *arg
)
844 nb_fmt_entries_to_show
++;
845 octx
.print_header
= NULL
;
846 octx
.print_footer
= NULL
;
847 octx
.print_array_header
= NULL
;
848 octx
.print_array_footer
= NULL
;
849 octx
.print_object_header
= NULL
;
850 octx
.print_object_footer
= NULL
;
852 octx
.print_integer
= show_format_entry_integer
;
853 octx
.print_string
= show_format_entry_string
;
854 av_dict_set(&fmt_entries_to_show
, arg
, "", 0);
858 static void opt_input_file(void *optctx
, const char *arg
)
860 if (input_filename
) {
862 "Argument '%s' provided as input filename, but '%s' was already specified.\n",
863 arg
, input_filename
);
866 if (!strcmp(arg
, "-"))
868 input_filename
= arg
;
871 void show_help_default(const char *opt
, const char *arg
)
873 av_log_set_callback(log_callback_help
);
875 show_help_options(options
, "Main options:", 0, 0, 0);
877 show_help_children(avformat_get_class(), AV_OPT_FLAG_DECODING_PARAM
);
880 static void opt_pretty(void)
883 use_value_prefix
= 1;
884 use_byte_value_binary_prefix
= 1;
885 use_value_sexagesimal_format
= 1;
888 static const OptionDef real_options
[] = {
889 #include "cmdutils_common_opts.h"
890 { "f", HAS_ARG
, {(void*)opt_format
}, "force format", "format" },
891 { "of", HAS_ARG
, {(void*)&opt_output_format
}, "output the document either as ini or json", "output_format" },
892 { "unit", OPT_BOOL
, {(void*)&show_value_unit
},
893 "show unit of the displayed values" },
894 { "prefix", OPT_BOOL
, {(void*)&use_value_prefix
},
895 "use SI prefixes for the displayed values" },
896 { "byte_binary_prefix", OPT_BOOL
, {(void*)&use_byte_value_binary_prefix
},
897 "use binary prefixes for byte units" },
898 { "sexagesimal", OPT_BOOL
, {(void*)&use_value_sexagesimal_format
},
899 "use sexagesimal format HOURS:MM:SS.MICROSECONDS for time units" },
900 { "pretty", 0, {(void*)&opt_pretty
},
901 "prettify the format of displayed values, make it more human readable" },
902 { "show_format", OPT_BOOL
, {(void*)&do_show_format
} , "show format/container info" },
903 { "show_format_entry", HAS_ARG
, {(void*)opt_show_format_entry
},
904 "show a particular entry from the format/container info", "entry" },
905 { "show_packets", OPT_BOOL
, {(void*)&do_show_packets
}, "show packets info" },
906 { "show_streams", OPT_BOOL
, {(void*)&do_show_streams
}, "show streams info" },
907 { "default", HAS_ARG
| OPT_AUDIO
| OPT_VIDEO
| OPT_EXPERT
, {(void*)opt_default
},
908 "generic catch all option", "" },
912 static int probe_buf_write(void *opaque
, uint8_t *buf
, int buf_size
)
914 printf("%.*s", buf_size
, buf
);
918 #define AVP_BUFFSIZE 4096
920 int main(int argc
, char **argv
)
923 uint8_t *buffer
= av_malloc(AVP_BUFFSIZE
);
928 options
= real_options
;
929 parse_loglevel(argc
, argv
, options
);
931 avformat_network_init();
934 avdevice_register_all();
939 octx
.print_header
= ini_print_header
;
940 octx
.print_footer
= ini_print_footer
;
942 octx
.print_array_header
= ini_print_array_header
;
943 octx
.print_object_header
= ini_print_object_header
;
945 octx
.print_integer
= ini_print_integer
;
946 octx
.print_string
= ini_print_string
;
948 parse_options(NULL
, argc
, argv
, options
, opt_input_file
);
950 if (!input_filename
) {
952 fprintf(stderr
, "You have to specify one input file.\n");
954 "Use -h to get full help or, even better, run 'man %s'.\n",
959 probe_out
= avio_alloc_context(buffer
, AVP_BUFFSIZE
, 1, NULL
, NULL
,
960 probe_buf_write
, NULL
);
965 ret
= probe_file(input_filename
);
967 avio_flush(probe_out
);
968 avio_close(probe_out
);
970 avformat_network_deinit();