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/display.h"
28 #include "libavutil/opt.h"
29 #include "libavutil/pixdesc.h"
30 #include "libavutil/spherical.h"
31 #include "libavutil/stereo3d.h"
32 #include "libavutil/dict.h"
33 #include "libavutil/libm.h"
34 #include "libavdevice/avdevice.h"
37 typedef struct InputStream
{
40 AVCodecContext
*dec_ctx
;
43 typedef struct InputFile
{
44 AVFormatContext
*fmt_ctx
;
50 const char program_name
[] = "avprobe";
51 const int program_birth_year
= 2007;
53 static int do_show_format
= 0;
54 static AVDictionary
*fmt_entries_to_show
= NULL
;
55 static int nb_fmt_entries_to_show
;
56 static int do_show_packets
= 0;
57 static int do_show_streams
= 0;
58 static AVDictionary
*stream_entries_to_show
= NULL
;
59 static int nb_stream_entries_to_show
;
61 /* key used to print when probe_{int,str}(NULL, ..) is invoked */
62 static const char *header_key
;
64 static int show_value_unit
= 0;
65 static int use_value_prefix
= 0;
66 static int use_byte_value_binary_prefix
= 0;
67 static int use_value_sexagesimal_format
= 0;
70 static const OptionDef
*options
;
73 static const char *input_filename
;
74 static AVInputFormat
*iformat
= NULL
;
76 static const char *const binary_unit_prefixes
[] = { "", "Ki", "Mi", "Gi", "Ti", "Pi" };
77 static const char *const decimal_unit_prefixes
[] = { "", "K" , "M" , "G" , "T" , "P" };
79 static const char unit_second_str
[] = "s" ;
80 static const char unit_hertz_str
[] = "Hz" ;
81 static const char unit_byte_str
[] = "byte" ;
82 static const char unit_bit_per_second_str
[] = "bit/s";
84 static void avprobe_cleanup(int ret
)
86 av_dict_free(&fmt_entries_to_show
);
87 av_dict_free(&stream_entries_to_show
);
91 * The output is structured in array and objects that might contain items
92 * Array could require the objects within to not be named.
93 * Object could require the items within to be named.
95 * For flat representation the name of each section is saved on prefix so it
96 * can be rendered in order to represent nested structures (e.g. array of
97 * objects for the packets list).
99 * Within an array each element can need an unique identifier or an index.
101 * Nesting level is accounted separately.
109 typedef struct PrintElement
{
111 PrintElementType type
;
116 typedef struct PrintContext
{
117 PrintElement
*prefix
;
119 void (*print_header
)(void);
120 void (*print_footer
)(void);
122 void (*print_array_header
) (const char *name
, int plain_values
);
123 void (*print_array_footer
) (const char *name
, int plain_values
);
124 void (*print_object_header
)(const char *name
);
125 void (*print_object_footer
)(const char *name
);
127 void (*print_integer
) (const char *key
, int64_t value
);
128 void (*print_string
) (const char *key
, const char *value
);
131 static AVIOContext
*probe_out
= NULL
;
132 static PrintContext octx
;
133 #define AVP_INDENT() avio_printf(probe_out, "%*c", octx.level * 2, ' ')
134 #define CONV_FP(x,fp) ((double) (x)) / (1 << fp)
137 * Default format, INI
139 * - all key and values are utf8
140 * - '.' is the subgroup separator
141 * - newlines and the following characters are escaped
142 * - '\' is the escape character
143 * - '#' is the comment
144 * - '=' is the key/value separators
145 * - ':' is not used but usually parsed as key/value separator
148 static void ini_print_header(void)
150 avio_printf(probe_out
, "# avprobe output\n\n");
152 static void ini_print_footer(void)
154 avio_w8(probe_out
, '\n');
157 static void ini_escape_print(const char *s
)
164 case '\r': avio_printf(probe_out
, "%s", "\\r"); break;
165 case '\n': avio_printf(probe_out
, "%s", "\\n"); break;
166 case '\f': avio_printf(probe_out
, "%s", "\\f"); break;
167 case '\b': avio_printf(probe_out
, "%s", "\\b"); break;
168 case '\t': avio_printf(probe_out
, "%s", "\\t"); break;
172 case ':' : avio_w8(probe_out
, '\\');
174 if ((unsigned char)c
< 32)
175 avio_printf(probe_out
, "\\x00%02x", c
& 0xff);
177 avio_w8(probe_out
, c
);
183 static void ini_print_array_header(const char *name
, int plain_values
)
186 /* Add a new line if we create a new full group */
187 if (octx
.prefix
[octx
.level
-1].nb_elems
)
188 avio_printf(probe_out
, "\n");
190 ini_escape_print(name
);
191 avio_w8(probe_out
, '=');
195 static void ini_print_array_footer(const char *name
, int plain_values
)
198 avio_printf(probe_out
, "\n");
201 static void ini_print_object_header(const char *name
)
204 PrintElement
*el
= octx
.prefix
+ octx
.level
-1;
207 avio_printf(probe_out
, "\n");
209 avio_printf(probe_out
, "[");
211 for (i
= 1; i
< octx
.level
; i
++) {
212 el
= octx
.prefix
+ i
;
213 avio_printf(probe_out
, "%s.", el
->name
);
215 avio_printf(probe_out
, "%"PRId64
".", el
->index
);
218 avio_printf(probe_out
, "%s", name
);
219 if (el
->type
== ARRAY
)
220 avio_printf(probe_out
, ".%"PRId64
"", el
->nb_elems
);
221 avio_printf(probe_out
, "]\n");
224 static void ini_print_integer(const char *key
, int64_t value
)
227 ini_escape_print(key
);
228 avio_printf(probe_out
, "=%"PRId64
"\n", value
);
230 if (octx
.prefix
[octx
.level
-1].nb_elems
)
231 avio_printf(probe_out
, ",");
232 avio_printf(probe_out
, "%"PRId64
, value
);
237 static void ini_print_string(const char *key
, const char *value
)
240 ini_escape_print(key
);
241 avio_printf(probe_out
, "=%s\n", value
);
243 if (octx
.prefix
[octx
.level
-1].nb_elems
)
244 avio_printf(probe_out
, ",");
245 avio_printf(probe_out
, "%s", value
);
250 * Alternate format, JSON
253 static void json_print_header(void)
255 avio_printf(probe_out
, "{");
257 static void json_print_footer(void)
259 avio_printf(probe_out
, "}\n");
262 static void json_print_array_header(const char *name
, int plain_values
)
264 if (octx
.prefix
[octx
.level
-1].nb_elems
)
265 avio_printf(probe_out
, ",\n");
267 avio_printf(probe_out
, "\"%s\" : ", name
);
268 avio_printf(probe_out
, "[\n");
271 static void json_print_array_footer(const char *name
, int plain_values
)
273 avio_printf(probe_out
, "\n");
275 avio_printf(probe_out
, "]");
278 static void json_print_object_header(const char *name
)
280 if (octx
.prefix
[octx
.level
-1].nb_elems
)
281 avio_printf(probe_out
, ",\n");
283 if (octx
.prefix
[octx
.level
-1].type
== OBJECT
)
284 avio_printf(probe_out
, "\"%s\" : ", name
);
285 avio_printf(probe_out
, "{\n");
288 static void json_print_object_footer(const char *name
)
290 avio_printf(probe_out
, "\n");
292 avio_printf(probe_out
, "}");
295 static void json_print_integer(const char *key
, int64_t value
)
298 if (octx
.prefix
[octx
.level
-1].nb_elems
)
299 avio_printf(probe_out
, ",\n");
301 avio_printf(probe_out
, "\"%s\" : ", key
);
303 if (octx
.prefix
[octx
.level
-1].nb_elems
)
304 avio_printf(probe_out
, ", ");
308 avio_printf(probe_out
, "%"PRId64
, value
);
311 static void json_escape_print(const char *s
)
318 case '\r': avio_printf(probe_out
, "%s", "\\r"); break;
319 case '\n': avio_printf(probe_out
, "%s", "\\n"); break;
320 case '\f': avio_printf(probe_out
, "%s", "\\f"); break;
321 case '\b': avio_printf(probe_out
, "%s", "\\b"); break;
322 case '\t': avio_printf(probe_out
, "%s", "\\t"); break;
324 case '"' : avio_w8(probe_out
, '\\');
326 if ((unsigned char)c
< 32)
327 avio_printf(probe_out
, "\\u00%02x", c
& 0xff);
329 avio_w8(probe_out
, c
);
335 static void json_print_string(const char *key
, const char *value
)
338 if (octx
.prefix
[octx
.level
-1].nb_elems
)
339 avio_printf(probe_out
, ",\n");
341 avio_w8(probe_out
, '\"');
342 json_escape_print(key
);
343 avio_printf(probe_out
, "\" : \"");
344 json_escape_print(value
);
345 avio_w8(probe_out
, '\"');
347 if (octx
.prefix
[octx
.level
-1].nb_elems
)
348 avio_printf(probe_out
, ", ");
351 avio_w8(probe_out
, '\"');
352 json_escape_print(value
);
353 avio_w8(probe_out
, '\"');
358 * old-style pseudo-INI
360 static void old_print_object_header(const char *name
)
364 if (!strcmp(name
, "tags"))
367 str
= p
= av_strdup(name
);
375 avio_printf(probe_out
, "[%s]\n", str
);
379 static void old_print_object_footer(const char *name
)
383 if (!strcmp(name
, "tags"))
386 str
= p
= av_strdup(name
);
394 avio_printf(probe_out
, "[/%s]\n", str
);
398 static void old_print_string(const char *key
, const char *value
)
400 if (!strcmp(octx
.prefix
[octx
.level
- 1].name
, "tags"))
401 avio_printf(probe_out
, "TAG:");
402 ini_print_string(key
, value
);
406 * Simple Formatter for single entries.
409 static void show_format_entry_integer(const char *key
, int64_t value
)
411 if (key
&& av_dict_get(fmt_entries_to_show
, key
, NULL
, 0)) {
412 if (nb_fmt_entries_to_show
> 1)
413 avio_printf(probe_out
, "%s=", key
);
414 avio_printf(probe_out
, "%"PRId64
"\n", value
);
418 static void show_format_entry_string(const char *key
, const char *value
)
420 if (key
&& av_dict_get(fmt_entries_to_show
, key
, NULL
, 0)) {
421 if (nb_fmt_entries_to_show
> 1)
422 avio_printf(probe_out
, "%s=", key
);
423 avio_printf(probe_out
, "%s\n", value
);
427 static void show_stream_entry_header(const char *key
, int value
)
432 static void show_stream_entry_footer(const char *key
, int value
)
437 static void show_stream_entry_integer(const char *key
, int64_t value
)
442 if (key
&& av_dict_get(stream_entries_to_show
, key
, NULL
, 0)) {
443 if (nb_stream_entries_to_show
> 1)
444 avio_printf(probe_out
, "%s=", key
);
445 avio_printf(probe_out
, "%"PRId64
"\n", value
);
449 static void show_stream_entry_string(const char *key
, const char *value
)
451 if (key
&& av_dict_get(stream_entries_to_show
, key
, NULL
, 0)) {
452 if (nb_stream_entries_to_show
> 1)
453 avio_printf(probe_out
, "%s=", key
);
454 avio_printf(probe_out
, "%s\n", value
);
458 static void probe_group_enter(const char *name
, int type
)
463 av_realloc(octx
.prefix
, sizeof(PrintElement
) * (octx
.level
+ 1));
465 if (!octx
.prefix
|| !name
) {
466 fprintf(stderr
, "Out of memory\n");
471 PrintElement
*parent
= octx
.prefix
+ octx
.level
-1;
472 if (parent
->type
== ARRAY
)
473 count
= parent
->nb_elems
;
477 octx
.prefix
[octx
.level
++] = (PrintElement
){name
, type
, count
, 0};
480 static void probe_group_leave(void)
485 static void probe_header(void)
487 if (octx
.print_header
)
489 probe_group_enter("root", OBJECT
);
492 static void probe_footer(void)
494 if (octx
.print_footer
)
500 static void probe_array_header(const char *name
, int plain_values
)
502 if (octx
.print_array_header
)
503 octx
.print_array_header(name
, plain_values
);
505 probe_group_enter(name
, ARRAY
);
508 static void probe_array_footer(const char *name
, int plain_values
)
511 if (octx
.print_array_footer
)
512 octx
.print_array_footer(name
, plain_values
);
515 static void probe_object_header(const char *name
)
517 if (octx
.print_object_header
)
518 octx
.print_object_header(name
);
520 probe_group_enter(name
, OBJECT
);
523 static void probe_object_footer(const char *name
)
526 if (octx
.print_object_footer
)
527 octx
.print_object_footer(name
);
530 static void probe_int(const char *key
, int64_t value
)
532 octx
.print_integer(key
, value
);
533 octx
.prefix
[octx
.level
-1].nb_elems
++;
536 static void probe_str(const char *key
, const char *value
)
538 octx
.print_string(key
, value
);
539 octx
.prefix
[octx
.level
-1].nb_elems
++;
542 static void probe_dict(AVDictionary
*dict
, const char *name
)
544 AVDictionaryEntry
*entry
= NULL
;
547 probe_object_header(name
);
548 while ((entry
= av_dict_get(dict
, "", entry
, AV_DICT_IGNORE_SUFFIX
))) {
549 probe_str(entry
->key
, entry
->value
);
551 probe_object_footer(name
);
554 static char *value_string(char *buf
, int buf_size
, double val
, const char *unit
)
556 if (unit
== unit_second_str
&& use_value_sexagesimal_format
) {
560 mins
= (int)secs
/ 60;
561 secs
= secs
- mins
* 60;
564 snprintf(buf
, buf_size
, "%d:%02d:%09.6f", hours
, mins
, secs
);
565 } else if (use_value_prefix
) {
566 const char *prefix_string
;
569 if (unit
== unit_byte_str
&& use_byte_value_binary_prefix
) {
570 index
= (int) log2(val
) / 10;
571 index
= av_clip(index
, 0, FF_ARRAY_ELEMS(binary_unit_prefixes
) - 1);
572 val
/= pow(2, index
* 10);
573 prefix_string
= binary_unit_prefixes
[index
];
575 index
= (int) (log10(val
)) / 3;
576 index
= av_clip(index
, 0, FF_ARRAY_ELEMS(decimal_unit_prefixes
) - 1);
577 val
/= pow(10, index
* 3);
578 prefix_string
= decimal_unit_prefixes
[index
];
580 snprintf(buf
, buf_size
, "%.*f%s%s",
583 show_value_unit
? unit
: "");
585 snprintf(buf
, buf_size
, "%f%s", val
, show_value_unit
? unit
: "");
591 static char *time_value_string(char *buf
, int buf_size
, int64_t val
,
592 const AVRational
*time_base
)
594 if (val
== AV_NOPTS_VALUE
) {
595 snprintf(buf
, buf_size
, "N/A");
597 value_string(buf
, buf_size
, val
* av_q2d(*time_base
), unit_second_str
);
603 static char *ts_value_string(char *buf
, int buf_size
, int64_t ts
)
605 if (ts
== AV_NOPTS_VALUE
) {
606 snprintf(buf
, buf_size
, "N/A");
608 snprintf(buf
, buf_size
, "%"PRId64
, ts
);
614 static char *rational_string(char *buf
, int buf_size
, const char *sep
,
615 const AVRational
*rat
)
617 snprintf(buf
, buf_size
, "%d%s%d", rat
->num
, sep
, rat
->den
);
621 static char *tag_string(char *buf
, int buf_size
, int tag
)
623 snprintf(buf
, buf_size
, "0x%04x", tag
);
627 static char *unknown_string(char *buf
, int buf_size
, int val
)
629 snprintf(buf
, buf_size
, "Unknown (%d)", val
);
633 static void show_packet(AVFormatContext
*fmt_ctx
, AVPacket
*pkt
)
636 AVStream
*st
= fmt_ctx
->streams
[pkt
->stream_index
];
638 probe_object_header("packet");
639 probe_str("codec_type", media_type_string(st
->codecpar
->codec_type
));
640 probe_int("stream_index", pkt
->stream_index
);
641 probe_str("pts", ts_value_string(val_str
, sizeof(val_str
), pkt
->pts
));
642 probe_str("pts_time", time_value_string(val_str
, sizeof(val_str
),
643 pkt
->pts
, &st
->time_base
));
644 probe_str("dts", ts_value_string(val_str
, sizeof(val_str
), pkt
->dts
));
645 probe_str("dts_time", time_value_string(val_str
, sizeof(val_str
),
646 pkt
->dts
, &st
->time_base
));
647 probe_str("duration", ts_value_string(val_str
, sizeof(val_str
),
649 probe_str("duration_time", time_value_string(val_str
, sizeof(val_str
),
652 probe_str("size", value_string(val_str
, sizeof(val_str
),
653 pkt
->size
, unit_byte_str
));
654 probe_int("pos", pkt
->pos
);
655 probe_str("flags", pkt
->flags
& AV_PKT_FLAG_KEY
? "K" : "_");
656 probe_object_footer("packet");
659 static void show_packets(InputFile
*ifile
)
661 AVFormatContext
*fmt_ctx
= ifile
->fmt_ctx
;
664 av_init_packet(&pkt
);
665 probe_array_header("packets", 0);
666 while (!av_read_frame(fmt_ctx
, &pkt
)) {
667 show_packet(fmt_ctx
, &pkt
);
668 av_packet_unref(&pkt
);
670 probe_array_footer("packets", 0);
673 static void show_stream(InputFile
*ifile
, InputStream
*ist
)
675 AVFormatContext
*fmt_ctx
= ifile
->fmt_ctx
;
676 AVStream
*stream
= ist
->st
;
677 AVCodecParameters
*par
;
678 AVCodecContext
*dec_ctx
;
679 const AVCodecDescriptor
*codec_desc
;
682 AVRational display_aspect_ratio
, *sar
= NULL
;
683 const AVPixFmtDescriptor
*desc
;
686 probe_object_header("stream");
688 probe_int("index", stream
->index
);
690 par
= stream
->codecpar
;
691 dec_ctx
= ist
->dec_ctx
;
692 codec_desc
= avcodec_descriptor_get(par
->codec_id
);
694 probe_str("codec_name", codec_desc
->name
);
695 probe_str("codec_long_name", codec_desc
->long_name
);
697 probe_str("codec_name", "unknown");
700 probe_str("codec_type", media_type_string(par
->codec_type
));
702 /* print AVI/FourCC tag */
703 av_get_codec_tag_string(val_str
, sizeof(val_str
), par
->codec_tag
);
704 probe_str("codec_tag_string", val_str
);
705 probe_str("codec_tag", tag_string(val_str
, sizeof(val_str
),
708 /* print profile, if there is one */
709 profile
= avcodec_profile_name(par
->codec_id
, par
->profile
);
711 probe_str("profile", profile
);
713 switch (par
->codec_type
) {
714 case AVMEDIA_TYPE_VIDEO
:
715 probe_int("width", par
->width
);
716 probe_int("height", par
->height
);
718 probe_int("coded_width", dec_ctx
->coded_width
);
719 probe_int("coded_height", dec_ctx
->coded_height
);
720 probe_int("has_b_frames", dec_ctx
->has_b_frames
);
722 if (dec_ctx
&& dec_ctx
->sample_aspect_ratio
.num
)
723 sar
= &dec_ctx
->sample_aspect_ratio
;
724 else if (par
->sample_aspect_ratio
.num
)
725 sar
= &par
->sample_aspect_ratio
;
726 else if (stream
->sample_aspect_ratio
.num
)
727 sar
= &stream
->sample_aspect_ratio
;
730 probe_str("sample_aspect_ratio",
731 rational_string(val_str
, sizeof(val_str
), ":", sar
));
732 av_reduce(&display_aspect_ratio
.num
, &display_aspect_ratio
.den
,
733 par
->width
* sar
->num
, par
->height
* sar
->den
,
735 probe_str("display_aspect_ratio",
736 rational_string(val_str
, sizeof(val_str
), ":",
737 &display_aspect_ratio
));
739 desc
= av_pix_fmt_desc_get(par
->format
);
740 probe_str("pix_fmt", desc
? desc
->name
: "unknown");
741 probe_int("level", par
->level
);
743 val
= av_color_range_name(par
->color_range
);
745 val
= unknown_string(val_str
, sizeof(val_str
), par
->color_range
);
746 probe_str("color_range", val
);
748 val
= av_color_space_name(par
->color_space
);
750 val
= unknown_string(val_str
, sizeof(val_str
), par
->color_space
);
751 probe_str("color_space", val
);
753 val
= av_color_transfer_name(par
->color_trc
);
755 val
= unknown_string(val_str
, sizeof(val_str
), par
->color_trc
);
756 probe_str("color_trc", val
);
758 val
= av_color_primaries_name(par
->color_primaries
);
760 val
= unknown_string(val_str
, sizeof(val_str
), par
->color_primaries
);
761 probe_str("color_pri", val
);
763 val
= av_chroma_location_name(par
->chroma_location
);
765 val
= unknown_string(val_str
, sizeof(val_str
), par
->chroma_location
);
766 probe_str("chroma_loc", val
);
769 case AVMEDIA_TYPE_AUDIO
:
770 probe_str("sample_rate",
771 value_string(val_str
, sizeof(val_str
),
774 probe_int("channels", par
->channels
);
775 probe_int("bits_per_sample",
776 av_get_bits_per_sample(par
->codec_id
));
780 if (fmt_ctx
->iformat
->flags
& AVFMT_SHOW_IDS
)
781 probe_int("id", stream
->id
);
782 probe_str("avg_frame_rate",
783 rational_string(val_str
, sizeof(val_str
), "/",
784 &stream
->avg_frame_rate
));
787 probe_str("bit_rate",
788 value_string(val_str
, sizeof(val_str
),
789 par
->bit_rate
, unit_bit_per_second_str
));
790 probe_str("time_base",
791 rational_string(val_str
, sizeof(val_str
), "/",
792 &stream
->time_base
));
793 probe_str("start_time",
794 time_value_string(val_str
, sizeof(val_str
),
795 stream
->start_time
, &stream
->time_base
));
796 probe_str("duration",
797 time_value_string(val_str
, sizeof(val_str
),
798 stream
->duration
, &stream
->time_base
));
799 if (stream
->nb_frames
)
800 probe_int("nb_frames", stream
->nb_frames
);
802 probe_dict(stream
->metadata
, "tags");
804 if (stream
->nb_side_data
) {
807 probe_object_header("sidedata");
808 for (i
= 0; i
< stream
->nb_side_data
; i
++) {
809 const AVPacketSideData
* sd
= &stream
->side_data
[i
];
811 AVSphericalMapping
*spherical
;
814 case AV_PKT_DATA_DISPLAYMATRIX
:
815 probe_object_header("displaymatrix");
816 probe_array_header("matrix", 1);
817 for (j
= 0; j
< 9; j
++)
818 probe_int(NULL
, ((int32_t *)sd
->data
)[j
]);
819 probe_array_footer("matrix", 1);
820 probe_array_header("matrix_str", 1);
821 for (j
= 0; j
< 9; j
++) {
823 int fp
= (j
== 2 || j
== 5 || j
== 8) ? 30 : 16;
824 int32_t val
= ((int32_t *)sd
->data
)[j
];
825 value_string(buf
, sizeof(buf
), CONV_FP(val
, fp
), "");
826 probe_str(NULL
, buf
);
828 probe_array_footer("matrix_str", 1);
829 probe_int("rotation",
830 av_display_rotation_get((int32_t *)sd
->data
));
831 probe_object_footer("displaymatrix");
833 case AV_PKT_DATA_STEREO3D
:
834 stereo
= (AVStereo3D
*)sd
->data
;
835 probe_object_header("stereo3d");
836 probe_str("type", av_stereo3d_type_name(stereo
->type
));
837 probe_int("inverted",
838 !!(stereo
->flags
& AV_STEREO3D_FLAG_INVERT
));
839 probe_object_footer("stereo3d");
841 case AV_PKT_DATA_SPHERICAL
:
842 spherical
= (AVSphericalMapping
*)sd
->data
;
843 probe_object_header("spherical");
844 probe_str("projection", av_spherical_projection_name(spherical
->projection
));
846 if (spherical
->projection
== AV_SPHERICAL_CUBEMAP
) {
847 probe_int("padding", spherical
->padding
);
848 } else if (spherical
->projection
== AV_SPHERICAL_EQUIRECTANGULAR_TILE
) {
850 av_spherical_tile_bounds(spherical
, par
->width
, par
->height
,
852 probe_object_header("bounding");
853 probe_int("left", l
);
855 probe_int("right", r
);
856 probe_int("bottom", b
);
857 probe_object_footer("bounding");
860 probe_object_header("orientation");
861 probe_int("yaw", (double) spherical
->yaw
/ (1 << 16));
862 probe_int("pitch", (double) spherical
->pitch
/ (1 << 16));
863 probe_int("roll", (double) spherical
->roll
/ (1 << 16));
864 probe_object_footer("orientation");
866 probe_object_footer("spherical");
870 probe_object_footer("sidedata");
873 probe_object_footer("stream");
876 static void show_format(InputFile
*ifile
)
878 AVFormatContext
*fmt_ctx
= ifile
->fmt_ctx
;
880 int64_t size
= fmt_ctx
->pb
? avio_size(fmt_ctx
->pb
) : -1;
882 probe_object_header("format");
883 probe_str("filename", fmt_ctx
->filename
);
884 probe_int("nb_streams", fmt_ctx
->nb_streams
);
885 probe_str("format_name", fmt_ctx
->iformat
->name
);
886 probe_str("format_long_name", fmt_ctx
->iformat
->long_name
);
887 probe_str("start_time",
888 time_value_string(val_str
, sizeof(val_str
),
889 fmt_ctx
->start_time
, &AV_TIME_BASE_Q
));
890 probe_str("duration",
891 time_value_string(val_str
, sizeof(val_str
),
892 fmt_ctx
->duration
, &AV_TIME_BASE_Q
));
894 size
>= 0 ? value_string(val_str
, sizeof(val_str
),
897 probe_str("bit_rate",
898 value_string(val_str
, sizeof(val_str
),
899 fmt_ctx
->bit_rate
, unit_bit_per_second_str
));
901 probe_dict(fmt_ctx
->metadata
, "tags");
903 probe_object_footer("format");
906 static int open_input_file(InputFile
*ifile
, const char *filename
)
909 AVFormatContext
*fmt_ctx
= NULL
;
910 AVDictionaryEntry
*t
;
912 if ((err
= avformat_open_input(&fmt_ctx
, filename
,
913 iformat
, &format_opts
)) < 0) {
914 print_error(filename
, err
);
917 if ((t
= av_dict_get(format_opts
, "", NULL
, AV_DICT_IGNORE_SUFFIX
))) {
918 av_log(NULL
, AV_LOG_ERROR
, "Option %s not found.\n", t
->key
);
919 return AVERROR_OPTION_NOT_FOUND
;
923 /* fill the streams in the format context */
924 if ((err
= avformat_find_stream_info(fmt_ctx
, NULL
)) < 0) {
925 print_error(filename
, err
);
929 av_dump_format(fmt_ctx
, 0, filename
, 0);
931 ifile
->streams
= av_mallocz_array(fmt_ctx
->nb_streams
,
932 sizeof(*ifile
->streams
));
935 ifile
->nb_streams
= fmt_ctx
->nb_streams
;
937 /* bind a decoder to each input stream */
938 for (i
= 0; i
< fmt_ctx
->nb_streams
; i
++) {
939 InputStream
*ist
= &ifile
->streams
[i
];
940 AVStream
*stream
= fmt_ctx
->streams
[i
];
945 if (stream
->codecpar
->codec_id
== AV_CODEC_ID_PROBE
) {
946 fprintf(stderr
, "Failed to probe codec for input stream %d\n",
951 codec
= avcodec_find_decoder(stream
->codecpar
->codec_id
);
954 "Unsupported codec with id %d for input stream %d\n",
955 stream
->codecpar
->codec_id
, stream
->index
);
959 ist
->dec_ctx
= avcodec_alloc_context3(codec
);
963 err
= avcodec_parameters_to_context(ist
->dec_ctx
, stream
->codecpar
);
967 err
= avcodec_open2(ist
->dec_ctx
, NULL
, NULL
);
969 fprintf(stderr
, "Error while opening codec for input stream %d\n",
976 ifile
->fmt_ctx
= fmt_ctx
;
980 static void close_input_file(InputFile
*ifile
)
984 /* close decoder for each stream */
985 for (i
= 0; i
< ifile
->nb_streams
; i
++) {
986 InputStream
*ist
= &ifile
->streams
[i
];
988 avcodec_free_context(&ist
->dec_ctx
);
991 av_freep(&ifile
->streams
);
992 ifile
->nb_streams
= 0;
994 avformat_close_input(&ifile
->fmt_ctx
);
997 static int probe_file(const char *filename
)
1002 ret
= open_input_file(&ifile
, filename
);
1007 show_format(&ifile
);
1009 if (do_show_streams
) {
1010 probe_array_header("streams", 0);
1011 for (i
= 0; i
< ifile
.nb_streams
; i
++)
1012 show_stream(&ifile
, &ifile
.streams
[i
]);
1013 probe_array_footer("streams", 0);
1016 if (do_show_packets
)
1017 show_packets(&ifile
);
1019 close_input_file(&ifile
);
1023 static void show_usage(void)
1025 printf("Simple multimedia streams analyzer\n");
1026 printf("usage: %s [OPTIONS] [INPUT_FILE]\n", program_name
);
1030 static int opt_format(void *optctx
, const char *opt
, const char *arg
)
1032 iformat
= av_find_input_format(arg
);
1034 fprintf(stderr
, "Unknown input format: %s\n", arg
);
1035 return AVERROR(EINVAL
);
1040 static int opt_output_format(void *optctx
, const char *opt
, const char *arg
)
1043 if (!strcmp(arg
, "json")) {
1044 octx
.print_header
= json_print_header
;
1045 octx
.print_footer
= json_print_footer
;
1046 octx
.print_array_header
= json_print_array_header
;
1047 octx
.print_array_footer
= json_print_array_footer
;
1048 octx
.print_object_header
= json_print_object_header
;
1049 octx
.print_object_footer
= json_print_object_footer
;
1051 octx
.print_integer
= json_print_integer
;
1052 octx
.print_string
= json_print_string
;
1053 } else if (!strcmp(arg
, "ini")) {
1054 octx
.print_header
= ini_print_header
;
1055 octx
.print_footer
= ini_print_footer
;
1056 octx
.print_array_header
= ini_print_array_header
;
1057 octx
.print_array_footer
= ini_print_array_footer
;
1058 octx
.print_object_header
= ini_print_object_header
;
1060 octx
.print_integer
= ini_print_integer
;
1061 octx
.print_string
= ini_print_string
;
1062 } else if (!strcmp(arg
, "old")) {
1063 octx
.print_header
= NULL
;
1064 octx
.print_object_header
= old_print_object_header
;
1065 octx
.print_object_footer
= old_print_object_footer
;
1067 octx
.print_string
= old_print_string
;
1069 av_log(NULL
, AV_LOG_ERROR
, "Unsupported formatter %s\n", arg
);
1070 return AVERROR(EINVAL
);
1075 static int opt_show_format_entry(void *optctx
, const char *opt
, const char *arg
)
1078 nb_fmt_entries_to_show
++;
1079 octx
.print_header
= NULL
;
1080 octx
.print_footer
= NULL
;
1081 octx
.print_array_header
= NULL
;
1082 octx
.print_array_footer
= NULL
;
1083 octx
.print_object_header
= NULL
;
1084 octx
.print_object_footer
= NULL
;
1086 octx
.print_integer
= show_format_entry_integer
;
1087 octx
.print_string
= show_format_entry_string
;
1088 av_dict_set(&fmt_entries_to_show
, arg
, "", 0);
1092 static int opt_show_stream_entry(void *optctx
, const char *opt
, const char *arg
)
1094 const char *p
= arg
;
1096 do_show_streams
= 1;
1097 nb_stream_entries_to_show
++;
1098 octx
.print_header
= NULL
;
1099 octx
.print_footer
= NULL
;
1100 octx
.print_array_header
= show_stream_entry_header
;
1101 octx
.print_array_footer
= show_stream_entry_footer
;
1102 octx
.print_object_header
= NULL
;
1103 octx
.print_object_footer
= NULL
;
1105 octx
.print_integer
= show_stream_entry_integer
;
1106 octx
.print_string
= show_stream_entry_string
;
1109 char *val
= av_get_token(&p
, ",");
1111 return AVERROR(ENOMEM
);
1113 av_dict_set(&stream_entries_to_show
, val
, "", 0);
1123 static void opt_input_file(void *optctx
, const char *arg
)
1125 if (input_filename
) {
1127 "Argument '%s' provided as input filename, but '%s' was already specified.\n",
1128 arg
, input_filename
);
1131 if (!strcmp(arg
, "-"))
1133 input_filename
= arg
;
1136 void show_help_default(const char *opt
, const char *arg
)
1138 av_log_set_callback(log_callback_help
);
1140 show_help_options(options
, "Main options:", 0, 0, 0);
1142 show_help_children(avformat_get_class(), AV_OPT_FLAG_DECODING_PARAM
);
1145 static int opt_pretty(void *optctx
, const char *opt
, const char *arg
)
1147 show_value_unit
= 1;
1148 use_value_prefix
= 1;
1149 use_byte_value_binary_prefix
= 1;
1150 use_value_sexagesimal_format
= 1;
1154 static const OptionDef real_options
[] = {
1155 CMDUTILS_COMMON_OPTIONS
1156 { "f", HAS_ARG
, {.func_arg
= opt_format
}, "force format", "format" },
1157 { "of", HAS_ARG
, {.func_arg
= opt_output_format
}, "output the document either as ini or json", "output_format" },
1158 { "unit", OPT_BOOL
, {&show_value_unit
},
1159 "show unit of the displayed values" },
1160 { "prefix", OPT_BOOL
, {&use_value_prefix
},
1161 "use SI prefixes for the displayed values" },
1162 { "byte_binary_prefix", OPT_BOOL
, {&use_byte_value_binary_prefix
},
1163 "use binary prefixes for byte units" },
1164 { "sexagesimal", OPT_BOOL
, {&use_value_sexagesimal_format
},
1165 "use sexagesimal format HOURS:MM:SS.MICROSECONDS for time units" },
1166 { "pretty", 0, {.func_arg
= opt_pretty
},
1167 "prettify the format of displayed values, make it more human readable" },
1168 { "show_format", OPT_BOOL
, {&do_show_format
} , "show format/container info" },
1169 { "show_format_entry", HAS_ARG
, {.func_arg
= opt_show_format_entry
},
1170 "show a particular entry from the format/container info", "entry" },
1171 { "show_packets", OPT_BOOL
, {&do_show_packets
}, "show packets info" },
1172 { "show_streams", OPT_BOOL
, {&do_show_streams
}, "show streams info" },
1173 { "show_stream_entry", HAS_ARG
, {.func_arg
= opt_show_stream_entry
},
1174 "show a particular entry from all streams (comma separated)", "entry" },
1175 { "default", HAS_ARG
| OPT_AUDIO
| OPT_VIDEO
| OPT_EXPERT
, {.func_arg
= opt_default
},
1176 "generic catch all option", "" },
1180 static int probe_buf_write(void *opaque
, uint8_t *buf
, int buf_size
)
1182 printf("%.*s", buf_size
, buf
);
1186 #define AVP_BUFFSIZE 4096
1188 int main(int argc
, char **argv
)
1191 uint8_t *buffer
= av_malloc(AVP_BUFFSIZE
);
1196 register_exit(avprobe_cleanup
);
1198 options
= real_options
;
1199 parse_loglevel(argc
, argv
, options
);
1201 avformat_network_init();
1204 avdevice_register_all();
1209 octx
.print_header
= ini_print_header
;
1210 octx
.print_footer
= ini_print_footer
;
1212 octx
.print_array_header
= ini_print_array_header
;
1213 octx
.print_array_footer
= ini_print_array_footer
;
1214 octx
.print_object_header
= ini_print_object_header
;
1216 octx
.print_integer
= ini_print_integer
;
1217 octx
.print_string
= ini_print_string
;
1219 parse_options(NULL
, argc
, argv
, options
, opt_input_file
);
1221 if (!input_filename
) {
1223 fprintf(stderr
, "You have to specify one input file.\n");
1225 "Use -h to get full help or, even better, run 'man %s'.\n",
1230 probe_out
= avio_alloc_context(buffer
, AVP_BUFFSIZE
, 1, NULL
, NULL
,
1231 probe_buf_write
, NULL
);
1236 ret
= probe_file(input_filename
);
1238 avio_flush(probe_out
);
1239 avio_context_free(&probe_out
);
1242 avformat_network_deinit();