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
, *sar
= NULL
;
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 sar
= &dec_ctx
->sample_aspect_ratio
;
623 else if (stream
->sample_aspect_ratio
.num
)
624 sar
= &stream
->sample_aspect_ratio
;
627 probe_str("sample_aspect_ratio",
628 rational_string(val_str
, sizeof(val_str
), ":", sar
));
629 av_reduce(&display_aspect_ratio
.num
, &display_aspect_ratio
.den
,
630 dec_ctx
->width
* sar
->num
, dec_ctx
->height
* sar
->den
,
632 probe_str("display_aspect_ratio",
633 rational_string(val_str
, sizeof(val_str
), ":",
634 &display_aspect_ratio
));
636 desc
= av_pix_fmt_desc_get(dec_ctx
->pix_fmt
);
637 probe_str("pix_fmt", desc
? desc
->name
: "unknown");
638 probe_int("level", dec_ctx
->level
);
641 case AVMEDIA_TYPE_AUDIO
:
642 probe_str("sample_rate",
643 value_string(val_str
, sizeof(val_str
),
644 dec_ctx
->sample_rate
,
646 probe_int("channels", dec_ctx
->channels
);
647 probe_int("bits_per_sample",
648 av_get_bits_per_sample(dec_ctx
->codec_id
));
652 probe_str("codec_type", "unknown");
655 if (fmt_ctx
->iformat
->flags
& AVFMT_SHOW_IDS
)
656 probe_int("id", stream
->id
);
657 probe_str("avg_frame_rate",
658 rational_string(val_str
, sizeof(val_str
), "/",
659 &stream
->avg_frame_rate
));
660 if (dec_ctx
->bit_rate
)
661 probe_str("bit_rate",
662 value_string(val_str
, sizeof(val_str
),
663 dec_ctx
->bit_rate
, unit_bit_per_second_str
));
664 probe_str("time_base",
665 rational_string(val_str
, sizeof(val_str
), "/",
666 &stream
->time_base
));
667 probe_str("start_time",
668 time_value_string(val_str
, sizeof(val_str
),
669 stream
->start_time
, &stream
->time_base
));
670 probe_str("duration",
671 time_value_string(val_str
, sizeof(val_str
),
672 stream
->duration
, &stream
->time_base
));
673 if (stream
->nb_frames
)
674 probe_int("nb_frames", stream
->nb_frames
);
676 probe_dict(stream
->metadata
, "tags");
678 probe_object_footer("stream");
681 static void show_format(AVFormatContext
*fmt_ctx
)
684 int64_t size
= fmt_ctx
->pb
? avio_size(fmt_ctx
->pb
) : -1;
686 probe_object_header("format");
687 probe_str("filename", fmt_ctx
->filename
);
688 probe_int("nb_streams", fmt_ctx
->nb_streams
);
689 probe_str("format_name", fmt_ctx
->iformat
->name
);
690 probe_str("format_long_name", fmt_ctx
->iformat
->long_name
);
691 probe_str("start_time",
692 time_value_string(val_str
, sizeof(val_str
),
693 fmt_ctx
->start_time
, &AV_TIME_BASE_Q
));
694 probe_str("duration",
695 time_value_string(val_str
, sizeof(val_str
),
696 fmt_ctx
->duration
, &AV_TIME_BASE_Q
));
698 size
>= 0 ? value_string(val_str
, sizeof(val_str
),
701 probe_str("bit_rate",
702 value_string(val_str
, sizeof(val_str
),
703 fmt_ctx
->bit_rate
, unit_bit_per_second_str
));
705 probe_dict(fmt_ctx
->metadata
, "tags");
707 probe_object_footer("format");
710 static int open_input_file(AVFormatContext
**fmt_ctx_ptr
, const char *filename
)
713 AVFormatContext
*fmt_ctx
= NULL
;
714 AVDictionaryEntry
*t
;
716 if ((err
= avformat_open_input(&fmt_ctx
, filename
,
717 iformat
, &format_opts
)) < 0) {
718 print_error(filename
, err
);
721 if ((t
= av_dict_get(format_opts
, "", NULL
, AV_DICT_IGNORE_SUFFIX
))) {
722 av_log(NULL
, AV_LOG_ERROR
, "Option %s not found.\n", t
->key
);
723 return AVERROR_OPTION_NOT_FOUND
;
727 /* fill the streams in the format context */
728 if ((err
= avformat_find_stream_info(fmt_ctx
, NULL
)) < 0) {
729 print_error(filename
, err
);
733 av_dump_format(fmt_ctx
, 0, filename
, 0);
735 /* bind a decoder to each input stream */
736 for (i
= 0; i
< fmt_ctx
->nb_streams
; i
++) {
737 AVStream
*stream
= fmt_ctx
->streams
[i
];
740 if (stream
->codec
->codec_id
== AV_CODEC_ID_PROBE
) {
741 fprintf(stderr
, "Failed to probe codec for input stream %d\n",
743 } else if (!(codec
= avcodec_find_decoder(stream
->codec
->codec_id
))) {
745 "Unsupported codec with id %d for input stream %d\n",
746 stream
->codec
->codec_id
, stream
->index
);
747 } else if (avcodec_open2(stream
->codec
, codec
, NULL
) < 0) {
748 fprintf(stderr
, "Error while opening codec for input stream %d\n",
753 *fmt_ctx_ptr
= fmt_ctx
;
757 static void close_input_file(AVFormatContext
**ctx_ptr
)
760 AVFormatContext
*fmt_ctx
= *ctx_ptr
;
762 /* close decoder for each stream */
763 for (i
= 0; i
< fmt_ctx
->nb_streams
; i
++) {
764 AVStream
*stream
= fmt_ctx
->streams
[i
];
766 avcodec_close(stream
->codec
);
768 avformat_close_input(ctx_ptr
);
771 static int probe_file(const char *filename
)
773 AVFormatContext
*fmt_ctx
;
776 if ((ret
= open_input_file(&fmt_ctx
, filename
)))
780 show_format(fmt_ctx
);
782 if (do_show_streams
) {
783 probe_array_header("streams");
784 for (i
= 0; i
< fmt_ctx
->nb_streams
; i
++)
785 show_stream(fmt_ctx
, i
);
786 probe_array_footer("streams");
790 show_packets(fmt_ctx
);
792 close_input_file(&fmt_ctx
);
796 static void show_usage(void)
798 printf("Simple multimedia streams analyzer\n");
799 printf("usage: %s [OPTIONS] [INPUT_FILE]\n", program_name
);
803 static int opt_format(void *optctx
, const char *opt
, const char *arg
)
805 iformat
= av_find_input_format(arg
);
807 fprintf(stderr
, "Unknown input format: %s\n", arg
);
808 return AVERROR(EINVAL
);
813 static int opt_output_format(void *optctx
, const char *opt
, const char *arg
)
816 if (!strcmp(arg
, "json")) {
817 octx
.print_header
= json_print_header
;
818 octx
.print_footer
= json_print_footer
;
819 octx
.print_array_header
= json_print_array_header
;
820 octx
.print_array_footer
= json_print_array_footer
;
821 octx
.print_object_header
= json_print_object_header
;
822 octx
.print_object_footer
= json_print_object_footer
;
824 octx
.print_integer
= json_print_integer
;
825 octx
.print_string
= json_print_string
;
826 } else if (!strcmp(arg
, "ini")) {
827 octx
.print_header
= ini_print_header
;
828 octx
.print_footer
= ini_print_footer
;
829 octx
.print_array_header
= ini_print_array_header
;
830 octx
.print_object_header
= ini_print_object_header
;
832 octx
.print_integer
= ini_print_integer
;
833 octx
.print_string
= ini_print_string
;
834 } else if (!strcmp(arg
, "old")) {
835 octx
.print_header
= NULL
;
836 octx
.print_object_header
= old_print_object_header
;
837 octx
.print_object_footer
= old_print_object_footer
;
839 octx
.print_string
= old_print_string
;
841 av_log(NULL
, AV_LOG_ERROR
, "Unsupported formatter %s\n", arg
);
842 return AVERROR(EINVAL
);
847 static int opt_show_format_entry(void *optctx
, const char *opt
, const char *arg
)
850 nb_fmt_entries_to_show
++;
851 octx
.print_header
= NULL
;
852 octx
.print_footer
= NULL
;
853 octx
.print_array_header
= NULL
;
854 octx
.print_array_footer
= NULL
;
855 octx
.print_object_header
= NULL
;
856 octx
.print_object_footer
= NULL
;
858 octx
.print_integer
= show_format_entry_integer
;
859 octx
.print_string
= show_format_entry_string
;
860 av_dict_set(&fmt_entries_to_show
, arg
, "", 0);
864 static void opt_input_file(void *optctx
, const char *arg
)
866 if (input_filename
) {
868 "Argument '%s' provided as input filename, but '%s' was already specified.\n",
869 arg
, input_filename
);
872 if (!strcmp(arg
, "-"))
874 input_filename
= arg
;
877 void show_help_default(const char *opt
, const char *arg
)
879 av_log_set_callback(log_callback_help
);
881 show_help_options(options
, "Main options:", 0, 0, 0);
883 show_help_children(avformat_get_class(), AV_OPT_FLAG_DECODING_PARAM
);
886 static int opt_pretty(void *optctx
, const char *opt
, const char *arg
)
889 use_value_prefix
= 1;
890 use_byte_value_binary_prefix
= 1;
891 use_value_sexagesimal_format
= 1;
895 static const OptionDef real_options
[] = {
896 #include "cmdutils_common_opts.h"
897 { "f", HAS_ARG
, {.func_arg
= opt_format
}, "force format", "format" },
898 { "of", HAS_ARG
, {.func_arg
= opt_output_format
}, "output the document either as ini or json", "output_format" },
899 { "unit", OPT_BOOL
, {&show_value_unit
},
900 "show unit of the displayed values" },
901 { "prefix", OPT_BOOL
, {&use_value_prefix
},
902 "use SI prefixes for the displayed values" },
903 { "byte_binary_prefix", OPT_BOOL
, {&use_byte_value_binary_prefix
},
904 "use binary prefixes for byte units" },
905 { "sexagesimal", OPT_BOOL
, {&use_value_sexagesimal_format
},
906 "use sexagesimal format HOURS:MM:SS.MICROSECONDS for time units" },
907 { "pretty", 0, {.func_arg
= opt_pretty
},
908 "prettify the format of displayed values, make it more human readable" },
909 { "show_format", OPT_BOOL
, {&do_show_format
} , "show format/container info" },
910 { "show_format_entry", HAS_ARG
, {.func_arg
= opt_show_format_entry
},
911 "show a particular entry from the format/container info", "entry" },
912 { "show_packets", OPT_BOOL
, {&do_show_packets
}, "show packets info" },
913 { "show_streams", OPT_BOOL
, {&do_show_streams
}, "show streams info" },
914 { "default", HAS_ARG
| OPT_AUDIO
| OPT_VIDEO
| OPT_EXPERT
, {.func_arg
= opt_default
},
915 "generic catch all option", "" },
919 static int probe_buf_write(void *opaque
, uint8_t *buf
, int buf_size
)
921 printf("%.*s", buf_size
, buf
);
925 #define AVP_BUFFSIZE 4096
927 int main(int argc
, char **argv
)
930 uint8_t *buffer
= av_malloc(AVP_BUFFSIZE
);
935 atexit(exit_program
);
937 options
= real_options
;
938 parse_loglevel(argc
, argv
, options
);
940 avformat_network_init();
943 avdevice_register_all();
948 octx
.print_header
= ini_print_header
;
949 octx
.print_footer
= ini_print_footer
;
951 octx
.print_array_header
= ini_print_array_header
;
952 octx
.print_object_header
= ini_print_object_header
;
954 octx
.print_integer
= ini_print_integer
;
955 octx
.print_string
= ini_print_string
;
957 parse_options(NULL
, argc
, argv
, options
, opt_input_file
);
959 if (!input_filename
) {
961 fprintf(stderr
, "You have to specify one input file.\n");
963 "Use -h to get full help or, even better, run 'man %s'.\n",
968 probe_out
= avio_alloc_context(buffer
, AVP_BUFFSIZE
, 1, NULL
, NULL
,
969 probe_buf_write
, NULL
);
974 ret
= probe_file(input_filename
);
976 avio_flush(probe_out
);
977 avio_close(probe_out
);
979 avformat_network_deinit();