]> git.sesse.net Git - ffmpeg/blob - avprobe.c
configure: Support msan as toolchain
[ffmpeg] / avprobe.c
1 /*
2  * avprobe : Simple Media Prober based on the Libav libraries
3  * Copyright (c) 2007-2010 Stefano Sabatini
4  *
5  * This file is part of Libav.
6  *
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.
11  *
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.
16  *
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
20  */
21
22 #include "config.h"
23
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/dict.h"
31 #include "libavutil/libm.h"
32 #include "libavdevice/avdevice.h"
33 #include "cmdutils.h"
34
35 typedef struct InputStream {
36     AVStream *st;
37
38     AVCodecContext *dec_ctx;
39 } InputStream;
40
41 typedef struct InputFile {
42     AVFormatContext *fmt_ctx;
43
44     InputStream *streams;
45     int       nb_streams;
46 } InputFile;
47
48 const char program_name[] = "avprobe";
49 const int program_birth_year = 2007;
50
51 static int do_show_format  = 0;
52 static AVDictionary *fmt_entries_to_show = NULL;
53 static int nb_fmt_entries_to_show;
54 static int do_show_packets = 0;
55 static int do_show_streams = 0;
56
57 static int show_value_unit              = 0;
58 static int use_value_prefix             = 0;
59 static int use_byte_value_binary_prefix = 0;
60 static int use_value_sexagesimal_format = 0;
61
62 /* globals */
63 static const OptionDef *options;
64
65 /* AVprobe context */
66 static const char *input_filename;
67 static AVInputFormat *iformat = NULL;
68
69 static const char *const binary_unit_prefixes [] = { "", "Ki", "Mi", "Gi", "Ti", "Pi" };
70 static const char *const decimal_unit_prefixes[] = { "", "K" , "M" , "G" , "T" , "P"  };
71
72 static const char unit_second_str[]         = "s"    ;
73 static const char unit_hertz_str[]          = "Hz"   ;
74 static const char unit_byte_str[]           = "byte" ;
75 static const char unit_bit_per_second_str[] = "bit/s";
76
77 static void avprobe_cleanup(int ret)
78 {
79     av_dict_free(&fmt_entries_to_show);
80 }
81
82 /*
83  * The output is structured in array and objects that might contain items
84  * Array could require the objects within to not be named.
85  * Object could require the items within to be named.
86  *
87  * For flat representation the name of each section is saved on prefix so it
88  * can be rendered in order to represent nested structures (e.g. array of
89  * objects for the packets list).
90  *
91  * Within an array each element can need an unique identifier or an index.
92  *
93  * Nesting level is accounted separately.
94  */
95
96 typedef enum {
97     ARRAY,
98     OBJECT
99 } PrintElementType;
100
101 typedef struct PrintElement {
102     const char *name;
103     PrintElementType type;
104     int64_t index;
105     int64_t nb_elems;
106 } PrintElement;
107
108 typedef struct PrintContext {
109     PrintElement *prefix;
110     int level;
111     void (*print_header)(void);
112     void (*print_footer)(void);
113
114     void (*print_array_header) (const char *name, int plain_values);
115     void (*print_array_footer) (const char *name, int plain_values);
116     void (*print_object_header)(const char *name);
117     void (*print_object_footer)(const char *name);
118
119     void (*print_integer) (const char *key, int64_t value);
120     void (*print_string)  (const char *key, const char *value);
121 } PrintContext;
122
123 static AVIOContext *probe_out = NULL;
124 static PrintContext octx;
125 #define AVP_INDENT() avio_printf(probe_out, "%*c", octx.level * 2, ' ')
126
127 /*
128  * Default format, INI
129  *
130  * - all key and values are utf8
131  * - '.' is the subgroup separator
132  * - newlines and the following characters are escaped
133  * - '\' is the escape character
134  * - '#' is the comment
135  * - '=' is the key/value separators
136  * - ':' is not used but usually parsed as key/value separator
137  */
138
139 static void ini_print_header(void)
140 {
141     avio_printf(probe_out, "# avprobe output\n\n");
142 }
143 static void ini_print_footer(void)
144 {
145     avio_w8(probe_out, '\n');
146 }
147
148 static void ini_escape_print(const char *s)
149 {
150     int i = 0;
151     char c = 0;
152
153     while (c = s[i++]) {
154         switch (c) {
155         case '\r': avio_printf(probe_out, "%s", "\\r"); break;
156         case '\n': avio_printf(probe_out, "%s", "\\n"); break;
157         case '\f': avio_printf(probe_out, "%s", "\\f"); break;
158         case '\b': avio_printf(probe_out, "%s", "\\b"); break;
159         case '\t': avio_printf(probe_out, "%s", "\\t"); break;
160         case '\\':
161         case '#' :
162         case '=' :
163         case ':' : avio_w8(probe_out, '\\');
164         default:
165             if ((unsigned char)c < 32)
166                 avio_printf(probe_out, "\\x00%02x", c & 0xff);
167             else
168                 avio_w8(probe_out, c);
169         break;
170         }
171     }
172 }
173
174 static void ini_print_array_header(const char *name, int plain_values)
175 {
176     if (!plain_values) {
177         /* Add a new line if we create a new full group */
178         if (octx.prefix[octx.level -1].nb_elems)
179             avio_printf(probe_out, "\n");
180     } else {
181         ini_escape_print(name);
182         avio_w8(probe_out, '=');
183     }
184 }
185
186 static void ini_print_array_footer(const char *name, int plain_values)
187 {
188     if (plain_values)
189         avio_printf(probe_out, "\n");
190 }
191
192 static void ini_print_object_header(const char *name)
193 {
194     int i;
195     PrintElement *el = octx.prefix + octx.level -1;
196
197     if (el->nb_elems)
198         avio_printf(probe_out, "\n");
199
200     avio_printf(probe_out, "[");
201
202     for (i = 1; i < octx.level; i++) {
203         el = octx.prefix + i;
204         avio_printf(probe_out, "%s.", el->name);
205         if (el->index >= 0)
206             avio_printf(probe_out, "%"PRId64".", el->index);
207     }
208
209     avio_printf(probe_out, "%s", name);
210     if (el->type == ARRAY)
211         avio_printf(probe_out, ".%"PRId64"", el->nb_elems);
212     avio_printf(probe_out, "]\n");
213 }
214
215 static void ini_print_integer(const char *key, int64_t value)
216 {
217     if (key) {
218         ini_escape_print(key);
219         avio_printf(probe_out, "=%"PRId64"\n", value);
220     } else {
221         if (octx.prefix[octx.level -1].nb_elems)
222             avio_printf(probe_out, ",");
223         avio_printf(probe_out, "%"PRId64, value);
224     }
225 }
226
227
228 static void ini_print_string(const char *key, const char *value)
229 {
230     ini_escape_print(key);
231     avio_printf(probe_out, "=");
232     ini_escape_print(value);
233     avio_w8(probe_out, '\n');
234 }
235
236 /*
237  * Alternate format, JSON
238  */
239
240 static void json_print_header(void)
241 {
242     avio_printf(probe_out, "{");
243 }
244 static void json_print_footer(void)
245 {
246     avio_printf(probe_out, "}\n");
247 }
248
249 static void json_print_array_header(const char *name, int plain_values)
250 {
251     if (octx.prefix[octx.level -1].nb_elems)
252         avio_printf(probe_out, ",\n");
253     AVP_INDENT();
254     avio_printf(probe_out, "\"%s\" : ", name);
255     avio_printf(probe_out, "[\n");
256 }
257
258 static void json_print_array_footer(const char *name, int plain_values)
259 {
260     avio_printf(probe_out, "\n");
261     AVP_INDENT();
262     avio_printf(probe_out, "]");
263 }
264
265 static void json_print_object_header(const char *name)
266 {
267     if (octx.prefix[octx.level -1].nb_elems)
268         avio_printf(probe_out, ",\n");
269     AVP_INDENT();
270     if (octx.prefix[octx.level -1].type == OBJECT)
271         avio_printf(probe_out, "\"%s\" : ", name);
272     avio_printf(probe_out, "{\n");
273 }
274
275 static void json_print_object_footer(const char *name)
276 {
277     avio_printf(probe_out, "\n");
278     AVP_INDENT();
279     avio_printf(probe_out, "}");
280 }
281
282 static void json_print_integer(const char *key, int64_t value)
283 {
284     if (key) {
285         if (octx.prefix[octx.level -1].nb_elems)
286             avio_printf(probe_out, ",\n");
287         AVP_INDENT();
288         avio_printf(probe_out, "\"%s\" : ", key);
289     } else {
290         if (octx.prefix[octx.level -1].nb_elems)
291             avio_printf(probe_out, ", ");
292         else
293             AVP_INDENT();
294     }
295     avio_printf(probe_out, "%"PRId64, value);
296 }
297
298 static void json_escape_print(const char *s)
299 {
300     int i = 0;
301     char c = 0;
302
303     while (c = s[i++]) {
304         switch (c) {
305         case '\r': avio_printf(probe_out, "%s", "\\r"); break;
306         case '\n': avio_printf(probe_out, "%s", "\\n"); break;
307         case '\f': avio_printf(probe_out, "%s", "\\f"); break;
308         case '\b': avio_printf(probe_out, "%s", "\\b"); break;
309         case '\t': avio_printf(probe_out, "%s", "\\t"); break;
310         case '\\':
311         case '"' : avio_w8(probe_out, '\\');
312         default:
313             if ((unsigned char)c < 32)
314                 avio_printf(probe_out, "\\u00%02x", c & 0xff);
315             else
316                 avio_w8(probe_out, c);
317         break;
318         }
319     }
320 }
321
322 static void json_print_string(const char *key, const char *value)
323 {
324     if (octx.prefix[octx.level -1].nb_elems)
325         avio_printf(probe_out, ",\n");
326     AVP_INDENT();
327     avio_w8(probe_out, '\"');
328     json_escape_print(key);
329     avio_printf(probe_out, "\" : \"");
330     json_escape_print(value);
331     avio_w8(probe_out, '\"');
332 }
333
334 /*
335  * old-style pseudo-INI
336  */
337 static void old_print_object_header(const char *name)
338 {
339     char *str, *p;
340
341     if (!strcmp(name, "tags"))
342         return;
343
344     str = p = av_strdup(name);
345     if (!str)
346         return;
347     while (*p) {
348         *p = av_toupper(*p);
349         p++;
350     }
351
352     avio_printf(probe_out, "[%s]\n", str);
353     av_freep(&str);
354 }
355
356 static void old_print_object_footer(const char *name)
357 {
358     char *str, *p;
359
360     if (!strcmp(name, "tags"))
361         return;
362
363     str = p = av_strdup(name);
364     if (!str)
365         return;
366     while (*p) {
367         *p = av_toupper(*p);
368         p++;
369     }
370
371     avio_printf(probe_out, "[/%s]\n", str);
372     av_freep(&str);
373 }
374
375 static void old_print_string(const char *key, const char *value)
376 {
377     if (!strcmp(octx.prefix[octx.level - 1].name, "tags"))
378         avio_printf(probe_out, "TAG:");
379     ini_print_string(key, value);
380 }
381
382 /*
383  * Simple Formatter for single entries.
384  */
385
386 static void show_format_entry_integer(const char *key, int64_t value)
387 {
388     if (key && av_dict_get(fmt_entries_to_show, key, NULL, 0)) {
389         if (nb_fmt_entries_to_show > 1)
390             avio_printf(probe_out, "%s=", key);
391         avio_printf(probe_out, "%"PRId64"\n", value);
392     }
393 }
394
395 static void show_format_entry_string(const char *key, const char *value)
396 {
397     if (key && av_dict_get(fmt_entries_to_show, key, NULL, 0)) {
398         if (nb_fmt_entries_to_show > 1)
399             avio_printf(probe_out, "%s=", key);
400         avio_printf(probe_out, "%s\n", value);
401     }
402 }
403
404 static void probe_group_enter(const char *name, int type)
405 {
406     int64_t count = -1;
407
408     octx.prefix =
409         av_realloc(octx.prefix, sizeof(PrintElement) * (octx.level + 1));
410
411     if (!octx.prefix || !name) {
412         fprintf(stderr, "Out of memory\n");
413         exit_program(1);
414     }
415
416     if (octx.level) {
417         PrintElement *parent = octx.prefix + octx.level -1;
418         if (parent->type == ARRAY)
419             count = parent->nb_elems;
420         parent->nb_elems++;
421     }
422
423     octx.prefix[octx.level++] = (PrintElement){name, type, count, 0};
424 }
425
426 static void probe_group_leave(void)
427 {
428     --octx.level;
429 }
430
431 static void probe_header(void)
432 {
433     if (octx.print_header)
434         octx.print_header();
435     probe_group_enter("root", OBJECT);
436 }
437
438 static void probe_footer(void)
439 {
440     if (octx.print_footer)
441         octx.print_footer();
442     probe_group_leave();
443 }
444
445
446 static void probe_array_header(const char *name, int plain_values)
447 {
448     if (octx.print_array_header)
449         octx.print_array_header(name, plain_values);
450
451     probe_group_enter(name, ARRAY);
452 }
453
454 static void probe_array_footer(const char *name, int plain_values)
455 {
456     probe_group_leave();
457     if (octx.print_array_footer)
458         octx.print_array_footer(name, plain_values);
459 }
460
461 static void probe_object_header(const char *name)
462 {
463     if (octx.print_object_header)
464         octx.print_object_header(name);
465
466     probe_group_enter(name, OBJECT);
467 }
468
469 static void probe_object_footer(const char *name)
470 {
471     probe_group_leave();
472     if (octx.print_object_footer)
473         octx.print_object_footer(name);
474 }
475
476 static void probe_int(const char *key, int64_t value)
477 {
478     octx.print_integer(key, value);
479     octx.prefix[octx.level -1].nb_elems++;
480 }
481
482 static void probe_str(const char *key, const char *value)
483 {
484     octx.print_string(key, value);
485     octx.prefix[octx.level -1].nb_elems++;
486 }
487
488 static void probe_dict(AVDictionary *dict, const char *name)
489 {
490     AVDictionaryEntry *entry = NULL;
491     if (!dict)
492         return;
493     probe_object_header(name);
494     while ((entry = av_dict_get(dict, "", entry, AV_DICT_IGNORE_SUFFIX))) {
495         probe_str(entry->key, entry->value);
496     }
497     probe_object_footer(name);
498 }
499
500 static char *value_string(char *buf, int buf_size, double val, const char *unit)
501 {
502     if (unit == unit_second_str && use_value_sexagesimal_format) {
503         double secs;
504         int hours, mins;
505         secs  = val;
506         mins  = (int)secs / 60;
507         secs  = secs - mins * 60;
508         hours = mins / 60;
509         mins %= 60;
510         snprintf(buf, buf_size, "%d:%02d:%09.6f", hours, mins, secs);
511     } else if (use_value_prefix) {
512         const char *prefix_string;
513         int index;
514
515         if (unit == unit_byte_str && use_byte_value_binary_prefix) {
516             index = (int) log2(val) / 10;
517             index = av_clip(index, 0, FF_ARRAY_ELEMS(binary_unit_prefixes) - 1);
518             val  /= pow(2, index * 10);
519             prefix_string = binary_unit_prefixes[index];
520         } else {
521             index = (int) (log10(val)) / 3;
522             index = av_clip(index, 0, FF_ARRAY_ELEMS(decimal_unit_prefixes) - 1);
523             val  /= pow(10, index * 3);
524             prefix_string = decimal_unit_prefixes[index];
525         }
526         snprintf(buf, buf_size, "%.*f%s%s",
527                  index ? 3 : 0, val,
528                  prefix_string,
529                  show_value_unit ? unit : "");
530     } else {
531         snprintf(buf, buf_size, "%f%s", val, show_value_unit ? unit : "");
532     }
533
534     return buf;
535 }
536
537 static char *time_value_string(char *buf, int buf_size, int64_t val,
538                                const AVRational *time_base)
539 {
540     if (val == AV_NOPTS_VALUE) {
541         snprintf(buf, buf_size, "N/A");
542     } else {
543         value_string(buf, buf_size, val * av_q2d(*time_base), unit_second_str);
544     }
545
546     return buf;
547 }
548
549 static char *ts_value_string(char *buf, int buf_size, int64_t ts)
550 {
551     if (ts == AV_NOPTS_VALUE) {
552         snprintf(buf, buf_size, "N/A");
553     } else {
554         snprintf(buf, buf_size, "%"PRId64, ts);
555     }
556
557     return buf;
558 }
559
560 static char *rational_string(char *buf, int buf_size, const char *sep,
561                              const AVRational *rat)
562 {
563     snprintf(buf, buf_size, "%d%s%d", rat->num, sep, rat->den);
564     return buf;
565 }
566
567 static char *tag_string(char *buf, int buf_size, int tag)
568 {
569     snprintf(buf, buf_size, "0x%04x", tag);
570     return buf;
571 }
572
573 static void show_packet(AVFormatContext *fmt_ctx, AVPacket *pkt)
574 {
575     char val_str[128];
576     AVStream *st = fmt_ctx->streams[pkt->stream_index];
577
578     probe_object_header("packet");
579     probe_str("codec_type", media_type_string(st->codecpar->codec_type));
580     probe_int("stream_index", pkt->stream_index);
581     probe_str("pts", ts_value_string(val_str, sizeof(val_str), pkt->pts));
582     probe_str("pts_time", time_value_string(val_str, sizeof(val_str),
583                                                pkt->pts, &st->time_base));
584     probe_str("dts", ts_value_string(val_str, sizeof(val_str), pkt->dts));
585     probe_str("dts_time", time_value_string(val_str, sizeof(val_str),
586                                                pkt->dts, &st->time_base));
587     probe_str("duration", ts_value_string(val_str, sizeof(val_str),
588                                              pkt->duration));
589     probe_str("duration_time", time_value_string(val_str, sizeof(val_str),
590                                                     pkt->duration,
591                                                     &st->time_base));
592     probe_str("size", value_string(val_str, sizeof(val_str),
593                                       pkt->size, unit_byte_str));
594     probe_int("pos", pkt->pos);
595     probe_str("flags", pkt->flags & AV_PKT_FLAG_KEY ? "K" : "_");
596     probe_object_footer("packet");
597 }
598
599 static void show_packets(InputFile *ifile)
600 {
601     AVFormatContext *fmt_ctx = ifile->fmt_ctx;
602     AVPacket pkt;
603
604     av_init_packet(&pkt);
605     probe_array_header("packets", 0);
606     while (!av_read_frame(fmt_ctx, &pkt)) {
607         show_packet(fmt_ctx, &pkt);
608         av_packet_unref(&pkt);
609     }
610     probe_array_footer("packets", 0);
611 }
612
613 static void show_stream(InputFile *ifile, InputStream *ist)
614 {
615     AVFormatContext *fmt_ctx = ifile->fmt_ctx;
616     AVStream *stream = ist->st;
617     AVCodecParameters *par;
618     AVCodecContext *dec_ctx;
619     const AVCodecDescriptor *codec_desc;
620     const char *profile;
621     char val_str[128];
622     AVRational display_aspect_ratio, *sar = NULL;
623     const AVPixFmtDescriptor *desc;
624
625     probe_object_header("stream");
626
627     probe_int("index", stream->index);
628
629     par     = stream->codecpar;
630     dec_ctx = ist->dec_ctx;
631     codec_desc = avcodec_descriptor_get(par->codec_id);
632     if (codec_desc) {
633         probe_str("codec_name", codec_desc->name);
634         probe_str("codec_long_name", codec_desc->long_name);
635     } else {
636         probe_str("codec_name", "unknown");
637     }
638
639     probe_str("codec_type", media_type_string(par->codec_type));
640
641     /* print AVI/FourCC tag */
642     av_get_codec_tag_string(val_str, sizeof(val_str), par->codec_tag);
643     probe_str("codec_tag_string", val_str);
644     probe_str("codec_tag", tag_string(val_str, sizeof(val_str),
645                                       par->codec_tag));
646
647     /* print profile, if there is one */
648     profile = avcodec_profile_name(par->codec_id, par->profile);
649     if (profile)
650         probe_str("profile", profile);
651
652     switch (par->codec_type) {
653     case AVMEDIA_TYPE_VIDEO:
654         probe_int("width",  par->width);
655         probe_int("height", par->height);
656         if (dec_ctx) {
657             probe_int("coded_width",  dec_ctx->coded_width);
658             probe_int("coded_height", dec_ctx->coded_height);
659             probe_int("has_b_frames", dec_ctx->has_b_frames);
660         }
661         if (dec_ctx && dec_ctx->sample_aspect_ratio.num)
662             sar = &dec_ctx->sample_aspect_ratio;
663         else if (par->sample_aspect_ratio.num)
664             sar = &par->sample_aspect_ratio;
665         else if (stream->sample_aspect_ratio.num)
666             sar = &stream->sample_aspect_ratio;
667
668         if (sar) {
669             probe_str("sample_aspect_ratio",
670                       rational_string(val_str, sizeof(val_str), ":", sar));
671             av_reduce(&display_aspect_ratio.num, &display_aspect_ratio.den,
672                       par->width  * sar->num, par->height * sar->den,
673                       1024*1024);
674             probe_str("display_aspect_ratio",
675                       rational_string(val_str, sizeof(val_str), ":",
676                       &display_aspect_ratio));
677         }
678         desc = av_pix_fmt_desc_get(par->format);
679         probe_str("pix_fmt", desc ? desc->name : "unknown");
680         probe_int("level", par->level);
681
682         probe_str("color_range", av_color_range_name    (par->color_range));
683         probe_str("color_space", av_color_space_name    (par->color_space));
684         probe_str("color_trc",   av_color_transfer_name (par->color_trc));
685         probe_str("color_pri",   av_color_primaries_name(par->color_primaries));
686         probe_str("chroma_loc", av_chroma_location_name (par->chroma_location));
687         break;
688
689     case AVMEDIA_TYPE_AUDIO:
690         probe_str("sample_rate",
691                   value_string(val_str, sizeof(val_str),
692                                par->sample_rate,
693                                unit_hertz_str));
694         probe_int("channels", par->channels);
695         probe_int("bits_per_sample",
696                   av_get_bits_per_sample(par->codec_id));
697         break;
698     }
699
700     if (fmt_ctx->iformat->flags & AVFMT_SHOW_IDS)
701         probe_int("id", stream->id);
702     probe_str("avg_frame_rate",
703               rational_string(val_str, sizeof(val_str), "/",
704               &stream->avg_frame_rate));
705
706     if (par->bit_rate)
707         probe_str("bit_rate",
708                   value_string(val_str, sizeof(val_str),
709                                par->bit_rate, unit_bit_per_second_str));
710     probe_str("time_base",
711               rational_string(val_str, sizeof(val_str), "/",
712               &stream->time_base));
713     probe_str("start_time",
714               time_value_string(val_str, sizeof(val_str),
715                                 stream->start_time, &stream->time_base));
716     probe_str("duration",
717               time_value_string(val_str, sizeof(val_str),
718                                 stream->duration, &stream->time_base));
719     if (stream->nb_frames)
720         probe_int("nb_frames", stream->nb_frames);
721
722     probe_dict(stream->metadata, "tags");
723
724     if (stream->nb_side_data) {
725         int i, j;
726         probe_object_header("sidedata");
727         for (i = 0; i < stream->nb_side_data; i++) {
728             const AVPacketSideData* sd = &stream->side_data[i];
729             switch (sd->type) {
730             case AV_PKT_DATA_DISPLAYMATRIX:
731                 probe_object_header("displaymatrix");
732                 probe_array_header("matrix", 1);
733                 for (j = 0; j < 9; j++)
734                     probe_int(NULL, ((int32_t *)sd->data)[j]);
735                 probe_array_footer("matrix", 1);
736                 probe_int("rotation",
737                           av_display_rotation_get((int32_t *)sd->data));
738                 probe_object_footer("displaymatrix");
739                 break;
740             }
741         }
742         probe_object_footer("sidedata");
743     }
744
745     probe_object_footer("stream");
746 }
747
748 static void show_format(InputFile *ifile)
749 {
750     AVFormatContext *fmt_ctx = ifile->fmt_ctx;
751     char val_str[128];
752     int64_t size = fmt_ctx->pb ? avio_size(fmt_ctx->pb) : -1;
753
754     probe_object_header("format");
755     probe_str("filename",         fmt_ctx->filename);
756     probe_int("nb_streams",       fmt_ctx->nb_streams);
757     probe_str("format_name",      fmt_ctx->iformat->name);
758     probe_str("format_long_name", fmt_ctx->iformat->long_name);
759     probe_str("start_time",
760                        time_value_string(val_str, sizeof(val_str),
761                                          fmt_ctx->start_time, &AV_TIME_BASE_Q));
762     probe_str("duration",
763                        time_value_string(val_str, sizeof(val_str),
764                                          fmt_ctx->duration, &AV_TIME_BASE_Q));
765     probe_str("size",
766                        size >= 0 ? value_string(val_str, sizeof(val_str),
767                                                 size, unit_byte_str)
768                                   : "unknown");
769     probe_str("bit_rate",
770                        value_string(val_str, sizeof(val_str),
771                                     fmt_ctx->bit_rate, unit_bit_per_second_str));
772
773     probe_dict(fmt_ctx->metadata, "tags");
774
775     probe_object_footer("format");
776 }
777
778 static int open_input_file(InputFile *ifile, const char *filename)
779 {
780     int err, i;
781     AVFormatContext *fmt_ctx = NULL;
782     AVDictionaryEntry *t;
783
784     if ((err = avformat_open_input(&fmt_ctx, filename,
785                                    iformat, &format_opts)) < 0) {
786         print_error(filename, err);
787         return err;
788     }
789     if ((t = av_dict_get(format_opts, "", NULL, AV_DICT_IGNORE_SUFFIX))) {
790         av_log(NULL, AV_LOG_ERROR, "Option %s not found.\n", t->key);
791         return AVERROR_OPTION_NOT_FOUND;
792     }
793
794
795     /* fill the streams in the format context */
796     if ((err = avformat_find_stream_info(fmt_ctx, NULL)) < 0) {
797         print_error(filename, err);
798         return err;
799     }
800
801     av_dump_format(fmt_ctx, 0, filename, 0);
802
803     ifile->streams = av_mallocz_array(fmt_ctx->nb_streams,
804                                       sizeof(*ifile->streams));
805     if (!ifile->streams)
806         exit(1);
807     ifile->nb_streams = fmt_ctx->nb_streams;
808
809     /* bind a decoder to each input stream */
810     for (i = 0; i < fmt_ctx->nb_streams; i++) {
811         InputStream *ist = &ifile->streams[i];
812         AVStream *stream = fmt_ctx->streams[i];
813         AVCodec *codec;
814
815         ist->st = stream;
816
817         if (stream->codecpar->codec_id == AV_CODEC_ID_PROBE) {
818             fprintf(stderr, "Failed to probe codec for input stream %d\n",
819                     stream->index);
820             continue;
821         }
822
823         codec = avcodec_find_decoder(stream->codecpar->codec_id);
824         if (!codec) {
825             fprintf(stderr,
826                     "Unsupported codec with id %d for input stream %d\n",
827                     stream->codecpar->codec_id, stream->index);
828             continue;
829         }
830
831         ist->dec_ctx = avcodec_alloc_context3(codec);
832         if (!ist->dec_ctx)
833             exit(1);
834
835         err = avcodec_parameters_to_context(ist->dec_ctx, stream->codecpar);
836         if (err < 0)
837             exit(1);
838
839         err = avcodec_open2(ist->dec_ctx, NULL, NULL);
840         if (err < 0) {
841             fprintf(stderr, "Error while opening codec for input stream %d\n",
842                     stream->index);
843             exit(1);
844
845         }
846     }
847
848     ifile->fmt_ctx = fmt_ctx;
849     return 0;
850 }
851
852 static void close_input_file(InputFile *ifile)
853 {
854     int i;
855
856     /* close decoder for each stream */
857     for (i = 0; i < ifile->nb_streams; i++) {
858         InputStream *ist = &ifile->streams[i];
859
860         avcodec_free_context(&ist->dec_ctx);
861     }
862
863     av_freep(&ifile->streams);
864     ifile->nb_streams = 0;
865
866     avformat_close_input(&ifile->fmt_ctx);
867 }
868
869 static int probe_file(const char *filename)
870 {
871     InputFile ifile;
872     int ret, i;
873
874     ret = open_input_file(&ifile, filename);
875     if (ret < 0)
876         return ret;
877
878     if (do_show_format)
879         show_format(&ifile);
880
881     if (do_show_streams) {
882         probe_array_header("streams", 0);
883         for (i = 0; i < ifile.nb_streams; i++)
884             show_stream(&ifile, &ifile.streams[i]);
885         probe_array_footer("streams", 0);
886     }
887
888     if (do_show_packets)
889         show_packets(&ifile);
890
891     close_input_file(&ifile);
892     return 0;
893 }
894
895 static void show_usage(void)
896 {
897     printf("Simple multimedia streams analyzer\n");
898     printf("usage: %s [OPTIONS] [INPUT_FILE]\n", program_name);
899     printf("\n");
900 }
901
902 static int opt_format(void *optctx, const char *opt, const char *arg)
903 {
904     iformat = av_find_input_format(arg);
905     if (!iformat) {
906         fprintf(stderr, "Unknown input format: %s\n", arg);
907         return AVERROR(EINVAL);
908     }
909     return 0;
910 }
911
912 static int opt_output_format(void *optctx, const char *opt, const char *arg)
913 {
914
915     if (!strcmp(arg, "json")) {
916         octx.print_header        = json_print_header;
917         octx.print_footer        = json_print_footer;
918         octx.print_array_header  = json_print_array_header;
919         octx.print_array_footer  = json_print_array_footer;
920         octx.print_object_header = json_print_object_header;
921         octx.print_object_footer = json_print_object_footer;
922
923         octx.print_integer = json_print_integer;
924         octx.print_string  = json_print_string;
925     } else if (!strcmp(arg, "ini")) {
926         octx.print_header        = ini_print_header;
927         octx.print_footer        = ini_print_footer;
928         octx.print_array_header  = ini_print_array_header;
929         octx.print_array_footer  = ini_print_array_footer;
930         octx.print_object_header = ini_print_object_header;
931
932         octx.print_integer = ini_print_integer;
933         octx.print_string  = ini_print_string;
934     } else if (!strcmp(arg, "old")) {
935         octx.print_header        = NULL;
936         octx.print_object_header = old_print_object_header;
937         octx.print_object_footer = old_print_object_footer;
938
939         octx.print_string        = old_print_string;
940     } else {
941         av_log(NULL, AV_LOG_ERROR, "Unsupported formatter %s\n", arg);
942         return AVERROR(EINVAL);
943     }
944     return 0;
945 }
946
947 static int opt_show_format_entry(void *optctx, const char *opt, const char *arg)
948 {
949     do_show_format = 1;
950     nb_fmt_entries_to_show++;
951     octx.print_header        = NULL;
952     octx.print_footer        = NULL;
953     octx.print_array_header  = NULL;
954     octx.print_array_footer  = NULL;
955     octx.print_object_header = NULL;
956     octx.print_object_footer = NULL;
957
958     octx.print_integer = show_format_entry_integer;
959     octx.print_string  = show_format_entry_string;
960     av_dict_set(&fmt_entries_to_show, arg, "", 0);
961     return 0;
962 }
963
964 static void opt_input_file(void *optctx, const char *arg)
965 {
966     if (input_filename) {
967         fprintf(stderr,
968                 "Argument '%s' provided as input filename, but '%s' was already specified.\n",
969                 arg, input_filename);
970         exit_program(1);
971     }
972     if (!strcmp(arg, "-"))
973         arg = "pipe:";
974     input_filename = arg;
975 }
976
977 void show_help_default(const char *opt, const char *arg)
978 {
979     av_log_set_callback(log_callback_help);
980     show_usage();
981     show_help_options(options, "Main options:", 0, 0, 0);
982     printf("\n");
983     show_help_children(avformat_get_class(), AV_OPT_FLAG_DECODING_PARAM);
984 }
985
986 static int opt_pretty(void *optctx, const char *opt, const char *arg)
987 {
988     show_value_unit              = 1;
989     use_value_prefix             = 1;
990     use_byte_value_binary_prefix = 1;
991     use_value_sexagesimal_format = 1;
992     return 0;
993 }
994
995 static const OptionDef real_options[] = {
996 #include "cmdutils_common_opts.h"
997     { "f", HAS_ARG, {.func_arg = opt_format}, "force format", "format" },
998     { "of", HAS_ARG, {.func_arg = opt_output_format}, "output the document either as ini or json", "output_format" },
999     { "unit", OPT_BOOL, {&show_value_unit},
1000       "show unit of the displayed values" },
1001     { "prefix", OPT_BOOL, {&use_value_prefix},
1002       "use SI prefixes for the displayed values" },
1003     { "byte_binary_prefix", OPT_BOOL, {&use_byte_value_binary_prefix},
1004       "use binary prefixes for byte units" },
1005     { "sexagesimal", OPT_BOOL,  {&use_value_sexagesimal_format},
1006       "use sexagesimal format HOURS:MM:SS.MICROSECONDS for time units" },
1007     { "pretty", 0, {.func_arg = opt_pretty},
1008       "prettify the format of displayed values, make it more human readable" },
1009     { "show_format",  OPT_BOOL, {&do_show_format} , "show format/container info" },
1010     { "show_format_entry", HAS_ARG, {.func_arg = opt_show_format_entry},
1011       "show a particular entry from the format/container info", "entry" },
1012     { "show_packets", OPT_BOOL, {&do_show_packets}, "show packets info" },
1013     { "show_streams", OPT_BOOL, {&do_show_streams}, "show streams info" },
1014     { "default", HAS_ARG | OPT_AUDIO | OPT_VIDEO | OPT_EXPERT, {.func_arg = opt_default},
1015       "generic catch all option", "" },
1016     { NULL, },
1017 };
1018
1019 static int probe_buf_write(void *opaque, uint8_t *buf, int buf_size)
1020 {
1021     printf("%.*s", buf_size, buf);
1022     return 0;
1023 }
1024
1025 #define AVP_BUFFSIZE 4096
1026
1027 int main(int argc, char **argv)
1028 {
1029     int ret;
1030     uint8_t *buffer = av_malloc(AVP_BUFFSIZE);
1031
1032     if (!buffer)
1033         exit(1);
1034
1035     register_exit(avprobe_cleanup);
1036
1037     options = real_options;
1038     parse_loglevel(argc, argv, options);
1039     av_register_all();
1040     avformat_network_init();
1041     init_opts();
1042 #if CONFIG_AVDEVICE
1043     avdevice_register_all();
1044 #endif
1045
1046     show_banner();
1047
1048     octx.print_header = ini_print_header;
1049     octx.print_footer = ini_print_footer;
1050
1051     octx.print_array_header = ini_print_array_header;
1052     octx.print_array_footer = ini_print_array_footer;
1053     octx.print_object_header = ini_print_object_header;
1054
1055     octx.print_integer = ini_print_integer;
1056     octx.print_string = ini_print_string;
1057
1058     parse_options(NULL, argc, argv, options, opt_input_file);
1059
1060     if (!input_filename) {
1061         show_usage();
1062         fprintf(stderr, "You have to specify one input file.\n");
1063         fprintf(stderr,
1064                 "Use -h to get full help or, even better, run 'man %s'.\n",
1065                 program_name);
1066         exit_program(1);
1067     }
1068
1069     probe_out = avio_alloc_context(buffer, AVP_BUFFSIZE, 1, NULL, NULL,
1070                                  probe_buf_write, NULL);
1071     if (!probe_out)
1072         exit_program(1);
1073
1074     probe_header();
1075     ret = probe_file(input_filename);
1076     probe_footer();
1077     avio_flush(probe_out);
1078     av_freep(&probe_out);
1079     av_freep(&buffer);
1080
1081     avformat_network_deinit();
1082
1083     return ret;
1084 }