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/avstring.h"
27 #include "libavutil/opt.h"
28 #include "libavutil/pixdesc.h"
29 #include "libavutil/dict.h"
30 #include "libavutil/libm.h"
31 #include "libavdevice/avdevice.h"
34 const char program_name
[] = "avprobe";
35 const int program_birth_year
= 2007;
37 static int do_show_format
= 0;
38 static AVDictionary
*fmt_entries_to_show
= NULL
;
39 static int nb_fmt_entries_to_show
;
40 static int do_show_packets
= 0;
41 static int do_show_streams
= 0;
43 static int show_value_unit
= 0;
44 static int use_value_prefix
= 0;
45 static int use_byte_value_binary_prefix
= 0;
46 static int use_value_sexagesimal_format
= 0;
49 static const OptionDef
*options
;
52 static const char *input_filename
;
53 static AVInputFormat
*iformat
= NULL
;
55 static const char *const binary_unit_prefixes
[] = { "", "Ki", "Mi", "Gi", "Ti", "Pi" };
56 static const char *const decimal_unit_prefixes
[] = { "", "K" , "M" , "G" , "T" , "P" };
58 static const char unit_second_str
[] = "s" ;
59 static const char unit_hertz_str
[] = "Hz" ;
60 static const char unit_byte_str
[] = "byte" ;
61 static const char unit_bit_per_second_str
[] = "bit/s";
63 static void exit_program(void)
65 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
, *sar
= NULL
;
588 const AVPixFmtDescriptor
*desc
;
590 probe_object_header("stream");
592 probe_int("index", stream
->index
);
594 if ((dec_ctx
= stream
->codec
)) {
595 if ((dec
= dec_ctx
->codec
)) {
596 probe_str("codec_name", dec
->name
);
597 probe_str("codec_long_name", dec
->long_name
);
599 probe_str("codec_name", "unknown");
602 probe_str("codec_type", media_type_string(dec_ctx
->codec_type
));
603 probe_str("codec_time_base",
604 rational_string(val_str
, sizeof(val_str
),
605 "/", &dec_ctx
->time_base
));
607 /* print AVI/FourCC tag */
608 av_get_codec_tag_string(val_str
, sizeof(val_str
), dec_ctx
->codec_tag
);
609 probe_str("codec_tag_string", val_str
);
610 probe_str("codec_tag", tag_string(val_str
, sizeof(val_str
),
611 dec_ctx
->codec_tag
));
613 /* print profile, if there is one */
614 if (dec
&& (profile
= av_get_profile_name(dec
, dec_ctx
->profile
)))
615 probe_str("profile", profile
);
617 switch (dec_ctx
->codec_type
) {
618 case AVMEDIA_TYPE_VIDEO
:
619 probe_int("width", dec_ctx
->width
);
620 probe_int("height", dec_ctx
->height
);
621 probe_int("has_b_frames", dec_ctx
->has_b_frames
);
622 if (dec_ctx
->sample_aspect_ratio
.num
)
623 sar
= &dec_ctx
->sample_aspect_ratio
;
624 else if (stream
->sample_aspect_ratio
.num
)
625 sar
= &stream
->sample_aspect_ratio
;
628 probe_str("sample_aspect_ratio",
629 rational_string(val_str
, sizeof(val_str
), ":", sar
));
630 av_reduce(&display_aspect_ratio
.num
, &display_aspect_ratio
.den
,
631 dec_ctx
->width
* sar
->num
, dec_ctx
->height
* sar
->den
,
633 probe_str("display_aspect_ratio",
634 rational_string(val_str
, sizeof(val_str
), ":",
635 &display_aspect_ratio
));
637 desc
= av_pix_fmt_desc_get(dec_ctx
->pix_fmt
);
638 probe_str("pix_fmt", desc
? desc
->name
: "unknown");
639 probe_int("level", dec_ctx
->level
);
642 case AVMEDIA_TYPE_AUDIO
:
643 probe_str("sample_rate",
644 value_string(val_str
, sizeof(val_str
),
645 dec_ctx
->sample_rate
,
647 probe_int("channels", dec_ctx
->channels
);
648 probe_int("bits_per_sample",
649 av_get_bits_per_sample(dec_ctx
->codec_id
));
653 probe_str("codec_type", "unknown");
656 if (fmt_ctx
->iformat
->flags
& AVFMT_SHOW_IDS
)
657 probe_int("id", stream
->id
);
658 probe_str("avg_frame_rate",
659 rational_string(val_str
, sizeof(val_str
), "/",
660 &stream
->avg_frame_rate
));
661 if (dec_ctx
->bit_rate
)
662 probe_str("bit_rate",
663 value_string(val_str
, sizeof(val_str
),
664 dec_ctx
->bit_rate
, unit_bit_per_second_str
));
665 probe_str("time_base",
666 rational_string(val_str
, sizeof(val_str
), "/",
667 &stream
->time_base
));
668 probe_str("start_time",
669 time_value_string(val_str
, sizeof(val_str
),
670 stream
->start_time
, &stream
->time_base
));
671 probe_str("duration",
672 time_value_string(val_str
, sizeof(val_str
),
673 stream
->duration
, &stream
->time_base
));
674 if (stream
->nb_frames
)
675 probe_int("nb_frames", stream
->nb_frames
);
677 probe_dict(stream
->metadata
, "tags");
679 probe_object_footer("stream");
682 static void show_format(AVFormatContext
*fmt_ctx
)
685 int64_t size
= fmt_ctx
->pb
? avio_size(fmt_ctx
->pb
) : -1;
687 probe_object_header("format");
688 probe_str("filename", fmt_ctx
->filename
);
689 probe_int("nb_streams", fmt_ctx
->nb_streams
);
690 probe_str("format_name", fmt_ctx
->iformat
->name
);
691 probe_str("format_long_name", fmt_ctx
->iformat
->long_name
);
692 probe_str("start_time",
693 time_value_string(val_str
, sizeof(val_str
),
694 fmt_ctx
->start_time
, &AV_TIME_BASE_Q
));
695 probe_str("duration",
696 time_value_string(val_str
, sizeof(val_str
),
697 fmt_ctx
->duration
, &AV_TIME_BASE_Q
));
699 size
>= 0 ? value_string(val_str
, sizeof(val_str
),
702 probe_str("bit_rate",
703 value_string(val_str
, sizeof(val_str
),
704 fmt_ctx
->bit_rate
, unit_bit_per_second_str
));
706 probe_dict(fmt_ctx
->metadata
, "tags");
708 probe_object_footer("format");
711 static int open_input_file(AVFormatContext
**fmt_ctx_ptr
, const char *filename
)
714 AVFormatContext
*fmt_ctx
= NULL
;
715 AVDictionaryEntry
*t
;
717 if ((err
= avformat_open_input(&fmt_ctx
, filename
,
718 iformat
, &format_opts
)) < 0) {
719 print_error(filename
, err
);
722 if ((t
= av_dict_get(format_opts
, "", NULL
, AV_DICT_IGNORE_SUFFIX
))) {
723 av_log(NULL
, AV_LOG_ERROR
, "Option %s not found.\n", t
->key
);
724 return AVERROR_OPTION_NOT_FOUND
;
728 /* fill the streams in the format context */
729 if ((err
= avformat_find_stream_info(fmt_ctx
, NULL
)) < 0) {
730 print_error(filename
, err
);
734 av_dump_format(fmt_ctx
, 0, filename
, 0);
736 /* bind a decoder to each input stream */
737 for (i
= 0; i
< fmt_ctx
->nb_streams
; i
++) {
738 AVStream
*stream
= fmt_ctx
->streams
[i
];
741 if (stream
->codec
->codec_id
== AV_CODEC_ID_PROBE
) {
742 fprintf(stderr
, "Failed to probe codec for input stream %d\n",
744 } else if (!(codec
= avcodec_find_decoder(stream
->codec
->codec_id
))) {
746 "Unsupported codec with id %d for input stream %d\n",
747 stream
->codec
->codec_id
, stream
->index
);
748 } else if (avcodec_open2(stream
->codec
, codec
, NULL
) < 0) {
749 fprintf(stderr
, "Error while opening codec for input stream %d\n",
754 *fmt_ctx_ptr
= fmt_ctx
;
758 static void close_input_file(AVFormatContext
**ctx_ptr
)
761 AVFormatContext
*fmt_ctx
= *ctx_ptr
;
763 /* close decoder for each stream */
764 for (i
= 0; i
< fmt_ctx
->nb_streams
; i
++) {
765 AVStream
*stream
= fmt_ctx
->streams
[i
];
767 avcodec_close(stream
->codec
);
769 avformat_close_input(ctx_ptr
);
772 static int probe_file(const char *filename
)
774 AVFormatContext
*fmt_ctx
;
777 if ((ret
= open_input_file(&fmt_ctx
, filename
)))
781 show_format(fmt_ctx
);
783 if (do_show_streams
) {
784 probe_array_header("streams");
785 for (i
= 0; i
< fmt_ctx
->nb_streams
; i
++)
786 show_stream(fmt_ctx
, i
);
787 probe_array_footer("streams");
791 show_packets(fmt_ctx
);
793 close_input_file(&fmt_ctx
);
797 static void show_usage(void)
799 printf("Simple multimedia streams analyzer\n");
800 printf("usage: %s [OPTIONS] [INPUT_FILE]\n", program_name
);
804 static int opt_format(void *optctx
, const char *opt
, const char *arg
)
806 iformat
= av_find_input_format(arg
);
808 fprintf(stderr
, "Unknown input format: %s\n", arg
);
809 return AVERROR(EINVAL
);
814 static int opt_output_format(void *optctx
, const char *opt
, const char *arg
)
817 if (!strcmp(arg
, "json")) {
818 octx
.print_header
= json_print_header
;
819 octx
.print_footer
= json_print_footer
;
820 octx
.print_array_header
= json_print_array_header
;
821 octx
.print_array_footer
= json_print_array_footer
;
822 octx
.print_object_header
= json_print_object_header
;
823 octx
.print_object_footer
= json_print_object_footer
;
825 octx
.print_integer
= json_print_integer
;
826 octx
.print_string
= json_print_string
;
827 } else if (!strcmp(arg
, "ini")) {
828 octx
.print_header
= ini_print_header
;
829 octx
.print_footer
= ini_print_footer
;
830 octx
.print_array_header
= ini_print_array_header
;
831 octx
.print_object_header
= ini_print_object_header
;
833 octx
.print_integer
= ini_print_integer
;
834 octx
.print_string
= ini_print_string
;
835 } else if (!strcmp(arg
, "old")) {
836 octx
.print_header
= NULL
;
837 octx
.print_object_header
= old_print_object_header
;
838 octx
.print_object_footer
= old_print_object_footer
;
840 octx
.print_string
= old_print_string
;
842 av_log(NULL
, AV_LOG_ERROR
, "Unsupported formatter %s\n", arg
);
843 return AVERROR(EINVAL
);
848 static int opt_show_format_entry(void *optctx
, const char *opt
, const char *arg
)
851 nb_fmt_entries_to_show
++;
852 octx
.print_header
= NULL
;
853 octx
.print_footer
= NULL
;
854 octx
.print_array_header
= NULL
;
855 octx
.print_array_footer
= NULL
;
856 octx
.print_object_header
= NULL
;
857 octx
.print_object_footer
= NULL
;
859 octx
.print_integer
= show_format_entry_integer
;
860 octx
.print_string
= show_format_entry_string
;
861 av_dict_set(&fmt_entries_to_show
, arg
, "", 0);
865 static void opt_input_file(void *optctx
, const char *arg
)
867 if (input_filename
) {
869 "Argument '%s' provided as input filename, but '%s' was already specified.\n",
870 arg
, input_filename
);
873 if (!strcmp(arg
, "-"))
875 input_filename
= arg
;
878 void show_help_default(const char *opt
, const char *arg
)
880 av_log_set_callback(log_callback_help
);
882 show_help_options(options
, "Main options:", 0, 0, 0);
884 show_help_children(avformat_get_class(), AV_OPT_FLAG_DECODING_PARAM
);
887 static int opt_pretty(void *optctx
, const char *opt
, const char *arg
)
890 use_value_prefix
= 1;
891 use_byte_value_binary_prefix
= 1;
892 use_value_sexagesimal_format
= 1;
896 static const OptionDef real_options
[] = {
897 #include "cmdutils_common_opts.h"
898 { "f", HAS_ARG
, {.func_arg
= opt_format
}, "force format", "format" },
899 { "of", HAS_ARG
, {.func_arg
= opt_output_format
}, "output the document either as ini or json", "output_format" },
900 { "unit", OPT_BOOL
, {&show_value_unit
},
901 "show unit of the displayed values" },
902 { "prefix", OPT_BOOL
, {&use_value_prefix
},
903 "use SI prefixes for the displayed values" },
904 { "byte_binary_prefix", OPT_BOOL
, {&use_byte_value_binary_prefix
},
905 "use binary prefixes for byte units" },
906 { "sexagesimal", OPT_BOOL
, {&use_value_sexagesimal_format
},
907 "use sexagesimal format HOURS:MM:SS.MICROSECONDS for time units" },
908 { "pretty", 0, {.func_arg
= opt_pretty
},
909 "prettify the format of displayed values, make it more human readable" },
910 { "show_format", OPT_BOOL
, {&do_show_format
} , "show format/container info" },
911 { "show_format_entry", HAS_ARG
, {.func_arg
= opt_show_format_entry
},
912 "show a particular entry from the format/container info", "entry" },
913 { "show_packets", OPT_BOOL
, {&do_show_packets
}, "show packets info" },
914 { "show_streams", OPT_BOOL
, {&do_show_streams
}, "show streams info" },
915 { "default", HAS_ARG
| OPT_AUDIO
| OPT_VIDEO
| OPT_EXPERT
, {.func_arg
= opt_default
},
916 "generic catch all option", "" },
920 static int probe_buf_write(void *opaque
, uint8_t *buf
, int buf_size
)
922 printf("%.*s", buf_size
, buf
);
926 #define AVP_BUFFSIZE 4096
928 int main(int argc
, char **argv
)
931 uint8_t *buffer
= av_malloc(AVP_BUFFSIZE
);
936 atexit(exit_program
);
938 options
= real_options
;
939 parse_loglevel(argc
, argv
, options
);
941 avformat_network_init();
944 avdevice_register_all();
949 octx
.print_header
= ini_print_header
;
950 octx
.print_footer
= ini_print_footer
;
952 octx
.print_array_header
= ini_print_array_header
;
953 octx
.print_object_header
= ini_print_object_header
;
955 octx
.print_integer
= ini_print_integer
;
956 octx
.print_string
= ini_print_string
;
958 parse_options(NULL
, argc
, argv
, options
, opt_input_file
);
960 if (!input_filename
) {
962 fprintf(stderr
, "You have to specify one input file.\n");
964 "Use -h to get full help or, even better, run 'man %s'.\n",
969 probe_out
= avio_alloc_context(buffer
, AVP_BUFFSIZE
, 1, NULL
, NULL
,
970 probe_buf_write
, NULL
);
975 ret
= probe_file(input_filename
);
977 avio_flush(probe_out
);
978 avio_close(probe_out
);
980 avformat_network_deinit();