ffprobe.c 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692
  1. /*
  2. * ffprobe : Simple Media Prober based on the FFmpeg libraries
  3. * Copyright (c) 2007-2010 Stefano Sabatini
  4. *
  5. * This file is part of FFmpeg.
  6. *
  7. * FFmpeg 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. * FFmpeg 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 FFmpeg; if not, write to the Free Software
  19. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  20. */
  21. #include "config.h"
  22. #include "libavformat/avformat.h"
  23. #include "libavcodec/avcodec.h"
  24. #include "libavutil/opt.h"
  25. #include "libavutil/pixdesc.h"
  26. #include "libavutil/dict.h"
  27. #include "libavdevice/avdevice.h"
  28. #include "cmdutils.h"
  29. const char program_name[] = "ffprobe";
  30. const int program_birth_year = 2007;
  31. static int do_show_format = 0;
  32. static int do_show_packets = 0;
  33. static int do_show_streams = 0;
  34. static int show_value_unit = 0;
  35. static int use_value_prefix = 0;
  36. static int use_byte_value_binary_prefix = 0;
  37. static int use_value_sexagesimal_format = 0;
  38. static char *print_format;
  39. static const OptionDef options[];
  40. /* FFprobe context */
  41. static const char *input_filename;
  42. static AVInputFormat *iformat = NULL;
  43. static const char *binary_unit_prefixes [] = { "", "Ki", "Mi", "Gi", "Ti", "Pi" };
  44. static const char *decimal_unit_prefixes[] = { "", "K" , "M" , "G" , "T" , "P" };
  45. static const char *unit_second_str = "s" ;
  46. static const char *unit_hertz_str = "Hz" ;
  47. static const char *unit_byte_str = "byte" ;
  48. static const char *unit_bit_per_second_str = "bit/s";
  49. void exit_program(int ret)
  50. {
  51. exit(ret);
  52. }
  53. static char *value_string(char *buf, int buf_size, double val, const char *unit)
  54. {
  55. if (unit == unit_second_str && use_value_sexagesimal_format) {
  56. double secs;
  57. int hours, mins;
  58. secs = val;
  59. mins = (int)secs / 60;
  60. secs = secs - mins * 60;
  61. hours = mins / 60;
  62. mins %= 60;
  63. snprintf(buf, buf_size, "%d:%02d:%09.6f", hours, mins, secs);
  64. } else if (use_value_prefix) {
  65. const char *prefix_string;
  66. int index;
  67. if (unit == unit_byte_str && use_byte_value_binary_prefix) {
  68. index = (int) (log(val)/log(2)) / 10;
  69. index = av_clip(index, 0, FF_ARRAY_ELEMS(binary_unit_prefixes) -1);
  70. val /= pow(2, index*10);
  71. prefix_string = binary_unit_prefixes[index];
  72. } else {
  73. index = (int) (log10(val)) / 3;
  74. index = av_clip(index, 0, FF_ARRAY_ELEMS(decimal_unit_prefixes) -1);
  75. val /= pow(10, index*3);
  76. prefix_string = decimal_unit_prefixes[index];
  77. }
  78. snprintf(buf, buf_size, "%.3f%s%s%s", val, prefix_string || show_value_unit ? " " : "",
  79. prefix_string, show_value_unit ? unit : "");
  80. } else {
  81. snprintf(buf, buf_size, "%f%s%s", val, show_value_unit ? " " : "",
  82. show_value_unit ? unit : "");
  83. }
  84. return buf;
  85. }
  86. static char *time_value_string(char *buf, int buf_size, int64_t val, const AVRational *time_base)
  87. {
  88. if (val == AV_NOPTS_VALUE) {
  89. snprintf(buf, buf_size, "N/A");
  90. } else {
  91. value_string(buf, buf_size, val * av_q2d(*time_base), unit_second_str);
  92. }
  93. return buf;
  94. }
  95. static char *ts_value_string (char *buf, int buf_size, int64_t ts)
  96. {
  97. if (ts == AV_NOPTS_VALUE) {
  98. snprintf(buf, buf_size, "N/A");
  99. } else {
  100. snprintf(buf, buf_size, "%"PRId64, ts);
  101. }
  102. return buf;
  103. }
  104. struct writer {
  105. const char *name;
  106. const char *item_sep; ///< separator between key/value couples
  107. const char *items_sep; ///< separator between sets of key/value couples
  108. const char *section_sep; ///< separator between sections (streams, packets, ...)
  109. const char *header, *footer;
  110. void (*print_section_start)(const char *, int);
  111. void (*print_section_end) (const char *, int);
  112. void (*print_header)(const char *);
  113. void (*print_footer)(const char *);
  114. void (*print_integer)(const char *, int);
  115. void (*print_string)(const char *, const char *);
  116. void (*show_tags)(struct writer *w, AVDictionary *dict);
  117. };
  118. /* JSON output */
  119. static void json_print_header(const char *section)
  120. {
  121. printf("{\n");
  122. }
  123. static char *json_escape_str(const char *s)
  124. {
  125. static const char json_escape[] = {'"', '\\', '\b', '\f', '\n', '\r', '\t', 0};
  126. static const char json_subst[] = {'"', '\\', 'b', 'f', 'n', 'r', 't', 0};
  127. char *ret, *p;
  128. int i, len = 0;
  129. // compute the length of the escaped string
  130. for (i = 0; s[i]; i++) {
  131. if (strchr(json_escape, s[i])) len += 2; // simple escape
  132. else if ((unsigned char)s[i] < 32) len += 6; // handle non-printable chars
  133. else len += 1; // char copy
  134. }
  135. p = ret = av_malloc(len + 1);
  136. if (!p)
  137. return NULL;
  138. for (i = 0; s[i]; i++) {
  139. char *q = strchr(json_escape, s[i]);
  140. if (q) {
  141. *p++ = '\\';
  142. *p++ = json_subst[q - json_escape];
  143. } else if ((unsigned char)s[i] < 32) {
  144. snprintf(p, 7, "\\u00%02x", s[i] & 0xff);
  145. p += 6;
  146. } else {
  147. *p++ = s[i];
  148. }
  149. }
  150. *p = 0;
  151. return ret;
  152. }
  153. static void json_print_str(const char *key, const char *value)
  154. {
  155. char *key_esc = json_escape_str(key);
  156. char *value_esc = json_escape_str(value);
  157. printf(" \"%s\": \"%s\"",
  158. key_esc ? key_esc : "",
  159. value_esc ? value_esc : "");
  160. av_free(key_esc);
  161. av_free(value_esc);
  162. }
  163. static void json_print_int(const char *key, int value)
  164. {
  165. char *key_esc = json_escape_str(key);
  166. printf(" \"%s\": %d", key_esc ? key_esc : "", value);
  167. av_free(key_esc);
  168. }
  169. static void json_print_footer(const char *section)
  170. {
  171. printf("\n }");
  172. }
  173. static void json_print_section_start(const char *section, int multiple_entries)
  174. {
  175. char *section_esc = json_escape_str(section);
  176. printf("\n \"%s\":%s", section_esc ? section_esc : "",
  177. multiple_entries ? " [" : " ");
  178. av_free(section_esc);
  179. }
  180. static void json_print_section_end(const char *section, int multiple_entries)
  181. {
  182. if (multiple_entries)
  183. printf("]");
  184. }
  185. /* Default output */
  186. static void default_print_header(const char *section)
  187. {
  188. printf("[%s]\n", section);
  189. }
  190. static void default_print_str(const char *key, const char *value)
  191. {
  192. printf("%s=%s", key, value);
  193. }
  194. static void default_print_int(const char *key, int value)
  195. {
  196. printf("%s=%d", key, value);
  197. }
  198. static void default_print_footer(const char *section)
  199. {
  200. printf("\n[/%s]", section);
  201. }
  202. /* Print helpers */
  203. struct print_buf {
  204. char *s;
  205. int len;
  206. };
  207. static char *fast_asprintf(struct print_buf *pbuf, const char *fmt, ...)
  208. {
  209. va_list va;
  210. int len;
  211. va_start(va, fmt);
  212. len = vsnprintf(NULL, 0, fmt, va);
  213. va_end(va);
  214. if (len < 0)
  215. goto fail;
  216. if (pbuf->len < len) {
  217. char *p = av_realloc(pbuf->s, len + 1);
  218. if (!p)
  219. goto fail;
  220. pbuf->s = p;
  221. pbuf->len = len;
  222. }
  223. va_start(va, fmt);
  224. len = vsnprintf(pbuf->s, len + 1, fmt, va);
  225. va_end(va);
  226. if (len < 0)
  227. goto fail;
  228. return pbuf->s;
  229. fail:
  230. av_freep(&pbuf->s);
  231. pbuf->len = 0;
  232. return NULL;
  233. }
  234. #define print_fmt0(k, f, ...) do { \
  235. if (fast_asprintf(&pbuf, f, __VA_ARGS__)) \
  236. w->print_string(k, pbuf.s); \
  237. } while (0)
  238. #define print_fmt( k, f, ...) do { \
  239. if (w->item_sep) \
  240. printf("%s", w->item_sep); \
  241. print_fmt0(k, f, __VA_ARGS__); \
  242. } while (0)
  243. #define print_int0(k, v) w->print_integer(k, v)
  244. #define print_int( k, v) do { \
  245. if (w->item_sep) \
  246. printf("%s", w->item_sep); \
  247. print_int0(k, v); \
  248. } while (0)
  249. #define print_str0(k, v) print_fmt0(k, "%s", v)
  250. #define print_str( k, v) print_fmt (k, "%s", v)
  251. static void show_packet(struct writer *w, AVFormatContext *fmt_ctx, AVPacket *pkt, int packet_idx)
  252. {
  253. char val_str[128];
  254. AVStream *st = fmt_ctx->streams[pkt->stream_index];
  255. struct print_buf pbuf = {.s = NULL};
  256. if (packet_idx)
  257. printf("%s", w->items_sep);
  258. w->print_header("PACKET");
  259. print_str0("codec_type", av_x_if_null(av_get_media_type_string(st->codec->codec_type), "unknown"));
  260. print_int("stream_index", pkt->stream_index);
  261. print_str("pts", ts_value_string (val_str, sizeof(val_str), pkt->pts));
  262. print_str("pts_time", time_value_string(val_str, sizeof(val_str), pkt->pts, &st->time_base));
  263. print_str("dts", ts_value_string (val_str, sizeof(val_str), pkt->dts));
  264. print_str("dts_time", time_value_string(val_str, sizeof(val_str), pkt->dts, &st->time_base));
  265. print_str("duration", ts_value_string (val_str, sizeof(val_str), pkt->duration));
  266. print_str("duration_time", time_value_string(val_str, sizeof(val_str), pkt->duration, &st->time_base));
  267. print_str("size", value_string (val_str, sizeof(val_str), pkt->size, unit_byte_str));
  268. print_fmt("pos", "%"PRId64, pkt->pos);
  269. print_fmt("flags", "%c", pkt->flags & AV_PKT_FLAG_KEY ? 'K' : '_');
  270. w->print_footer("PACKET");
  271. av_free(pbuf.s);
  272. fflush(stdout);
  273. }
  274. static void show_packets(struct writer *w, AVFormatContext *fmt_ctx)
  275. {
  276. AVPacket pkt;
  277. int i = 0;
  278. av_init_packet(&pkt);
  279. while (!av_read_frame(fmt_ctx, &pkt))
  280. show_packet(w, fmt_ctx, &pkt, i++);
  281. }
  282. static void json_show_tags(struct writer *w, AVDictionary *dict)
  283. {
  284. AVDictionaryEntry *tag = NULL;
  285. struct print_buf pbuf = {.s = NULL};
  286. int first = 1;
  287. if (!dict)
  288. return;
  289. printf(",\n \"tags\": {\n");
  290. while ((tag = av_dict_get(dict, "", tag, AV_DICT_IGNORE_SUFFIX))) {
  291. if (first) {
  292. print_str0(tag->key, tag->value);
  293. first = 0;
  294. } else {
  295. print_str(tag->key, tag->value);
  296. }
  297. }
  298. printf("\n }");
  299. av_free(pbuf.s);
  300. }
  301. static void default_show_tags(struct writer *w, AVDictionary *dict)
  302. {
  303. AVDictionaryEntry *tag = NULL;
  304. struct print_buf pbuf = {.s = NULL};
  305. while ((tag = av_dict_get(dict, "", tag, AV_DICT_IGNORE_SUFFIX))) {
  306. printf("\nTAG:");
  307. print_str0(tag->key, tag->value);
  308. }
  309. av_free(pbuf.s);
  310. }
  311. static void show_stream(struct writer *w, AVFormatContext *fmt_ctx, int stream_idx)
  312. {
  313. AVStream *stream = fmt_ctx->streams[stream_idx];
  314. AVCodecContext *dec_ctx;
  315. AVCodec *dec;
  316. char val_str[128];
  317. AVRational display_aspect_ratio;
  318. struct print_buf pbuf = {.s = NULL};
  319. if (stream_idx)
  320. printf("%s", w->items_sep);
  321. w->print_header("STREAM");
  322. print_int0("index", stream->index);
  323. if ((dec_ctx = stream->codec)) {
  324. if ((dec = dec_ctx->codec)) {
  325. print_str("codec_name", dec->name);
  326. print_str("codec_long_name", dec->long_name);
  327. } else {
  328. print_str("codec_name", "unknown");
  329. }
  330. print_str("codec_type", av_x_if_null(av_get_media_type_string(dec_ctx->codec_type), "unknown"));
  331. print_fmt("codec_time_base", "%d/%d", dec_ctx->time_base.num, dec_ctx->time_base.den);
  332. /* print AVI/FourCC tag */
  333. av_get_codec_tag_string(val_str, sizeof(val_str), dec_ctx->codec_tag);
  334. print_str("codec_tag_string", val_str);
  335. print_fmt("codec_tag", "0x%04x", dec_ctx->codec_tag);
  336. switch (dec_ctx->codec_type) {
  337. case AVMEDIA_TYPE_VIDEO:
  338. print_int("width", dec_ctx->width);
  339. print_int("height", dec_ctx->height);
  340. print_int("has_b_frames", dec_ctx->has_b_frames);
  341. if (dec_ctx->sample_aspect_ratio.num) {
  342. print_fmt("sample_aspect_ratio", "%d:%d",
  343. dec_ctx->sample_aspect_ratio.num,
  344. dec_ctx->sample_aspect_ratio.den);
  345. av_reduce(&display_aspect_ratio.num, &display_aspect_ratio.den,
  346. dec_ctx->width * dec_ctx->sample_aspect_ratio.num,
  347. dec_ctx->height * dec_ctx->sample_aspect_ratio.den,
  348. 1024*1024);
  349. print_fmt("display_aspect_ratio", "%d:%d",
  350. display_aspect_ratio.num,
  351. display_aspect_ratio.den);
  352. }
  353. print_str("pix_fmt", av_x_if_null(av_get_pix_fmt_name(dec_ctx->pix_fmt), "unknown"));
  354. print_int("level", dec_ctx->level);
  355. break;
  356. case AVMEDIA_TYPE_AUDIO:
  357. print_str("sample_rate", value_string(val_str, sizeof(val_str), dec_ctx->sample_rate, unit_hertz_str));
  358. print_int("channels", dec_ctx->channels);
  359. print_int("bits_per_sample", av_get_bits_per_sample(dec_ctx->codec_id));
  360. break;
  361. }
  362. } else {
  363. print_str("codec_type", "unknown");
  364. }
  365. if (fmt_ctx->iformat->flags & AVFMT_SHOW_IDS)
  366. print_fmt("id", "0x%x", stream->id);
  367. print_fmt("r_frame_rate", "%d/%d", stream->r_frame_rate.num, stream->r_frame_rate.den);
  368. print_fmt("avg_frame_rate", "%d/%d", stream->avg_frame_rate.num, stream->avg_frame_rate.den);
  369. print_fmt("time_base", "%d/%d", stream->time_base.num, stream->time_base.den);
  370. print_str("start_time", time_value_string(val_str, sizeof(val_str), stream->start_time, &stream->time_base));
  371. print_str("duration", time_value_string(val_str, sizeof(val_str), stream->duration, &stream->time_base));
  372. if (stream->nb_frames)
  373. print_fmt("nb_frames", "%"PRId64, stream->nb_frames);
  374. w->show_tags(w, stream->metadata);
  375. w->print_footer("STREAM");
  376. av_free(pbuf.s);
  377. fflush(stdout);
  378. }
  379. static void show_streams(struct writer *w, AVFormatContext *fmt_ctx)
  380. {
  381. int i;
  382. for (i = 0; i < fmt_ctx->nb_streams; i++)
  383. show_stream(w, fmt_ctx, i);
  384. }
  385. static void show_format(struct writer *w, AVFormatContext *fmt_ctx)
  386. {
  387. char val_str[128];
  388. struct print_buf pbuf = {.s = NULL};
  389. w->print_header("FORMAT");
  390. print_str0("filename", fmt_ctx->filename);
  391. print_int("nb_streams", fmt_ctx->nb_streams);
  392. print_str("format_name", fmt_ctx->iformat->name);
  393. print_str("format_long_name", fmt_ctx->iformat->long_name);
  394. print_str("start_time", time_value_string(val_str, sizeof(val_str), fmt_ctx->start_time, &AV_TIME_BASE_Q));
  395. print_str("duration", time_value_string(val_str, sizeof(val_str), fmt_ctx->duration, &AV_TIME_BASE_Q));
  396. print_str("size", value_string(val_str, sizeof(val_str), fmt_ctx->file_size, unit_byte_str));
  397. print_str("bit_rate", value_string(val_str, sizeof(val_str), fmt_ctx->bit_rate, unit_bit_per_second_str));
  398. w->show_tags(w, fmt_ctx->metadata);
  399. w->print_footer("FORMAT");
  400. av_free(pbuf.s);
  401. fflush(stdout);
  402. }
  403. static int open_input_file(AVFormatContext **fmt_ctx_ptr, const char *filename)
  404. {
  405. int err, i;
  406. AVFormatContext *fmt_ctx = NULL;
  407. AVDictionaryEntry *t;
  408. if ((err = avformat_open_input(&fmt_ctx, filename, iformat, &format_opts)) < 0) {
  409. print_error(filename, err);
  410. return err;
  411. }
  412. if ((t = av_dict_get(format_opts, "", NULL, AV_DICT_IGNORE_SUFFIX))) {
  413. av_log(NULL, AV_LOG_ERROR, "Option %s not found.\n", t->key);
  414. return AVERROR_OPTION_NOT_FOUND;
  415. }
  416. /* fill the streams in the format context */
  417. if ((err = avformat_find_stream_info(fmt_ctx, NULL)) < 0) {
  418. print_error(filename, err);
  419. return err;
  420. }
  421. av_dump_format(fmt_ctx, 0, filename, 0);
  422. /* bind a decoder to each input stream */
  423. for (i = 0; i < fmt_ctx->nb_streams; i++) {
  424. AVStream *stream = fmt_ctx->streams[i];
  425. AVCodec *codec;
  426. if (!(codec = avcodec_find_decoder(stream->codec->codec_id))) {
  427. fprintf(stderr, "Unsupported codec with id %d for input stream %d\n",
  428. stream->codec->codec_id, stream->index);
  429. } else if (avcodec_open2(stream->codec, codec, NULL) < 0) {
  430. fprintf(stderr, "Error while opening codec for input stream %d\n",
  431. stream->index);
  432. }
  433. }
  434. *fmt_ctx_ptr = fmt_ctx;
  435. return 0;
  436. }
  437. #define WRITER_FUNC(func) \
  438. .print_header = func ## _print_header, \
  439. .print_footer = func ## _print_footer, \
  440. .print_integer = func ## _print_int, \
  441. .print_string = func ## _print_str, \
  442. .show_tags = func ## _show_tags
  443. static struct writer writers[] = {{
  444. .name = "default",
  445. .item_sep = "\n",
  446. .items_sep = "\n",
  447. .section_sep = "\n",
  448. .footer = "\n",
  449. WRITER_FUNC(default),
  450. },{
  451. .name = "json",
  452. .header = "{",
  453. .item_sep = ",\n",
  454. .items_sep = ",",
  455. .section_sep = ",",
  456. .footer = "\n}\n",
  457. .print_section_start = json_print_section_start,
  458. .print_section_end = json_print_section_end,
  459. WRITER_FUNC(json),
  460. }
  461. };
  462. static int get_writer(const char *name)
  463. {
  464. int i;
  465. if (!name)
  466. return 0;
  467. for (i = 0; i < FF_ARRAY_ELEMS(writers); i++)
  468. if (!strcmp(writers[i].name, name))
  469. return i;
  470. return -1;
  471. }
  472. #define SECTION_PRINT(name, multiple_entries, left) do { \
  473. if (do_show_ ## name) { \
  474. if (w->print_section_start) \
  475. w->print_section_start(#name, multiple_entries); \
  476. show_ ## name (w, fmt_ctx); \
  477. if (w->print_section_end) \
  478. w->print_section_end(#name, multiple_entries); \
  479. if (left) \
  480. printf("%s", w->section_sep); \
  481. } \
  482. } while (0)
  483. static int probe_file(const char *filename)
  484. {
  485. AVFormatContext *fmt_ctx;
  486. int ret, writer_id;
  487. struct writer *w;
  488. writer_id = get_writer(print_format);
  489. if (writer_id < 0) {
  490. fprintf(stderr, "Invalid output format '%s'\n", print_format);
  491. return AVERROR(EINVAL);
  492. }
  493. w = &writers[writer_id];
  494. if ((ret = open_input_file(&fmt_ctx, filename)))
  495. return ret;
  496. if (w->header)
  497. printf("%s", w->header);
  498. SECTION_PRINT(packets, 1, do_show_streams || do_show_format);
  499. SECTION_PRINT(streams, 1, do_show_format);
  500. SECTION_PRINT(format, 0, 0);
  501. if (w->footer)
  502. printf("%s", w->footer);
  503. av_close_input_file(fmt_ctx);
  504. return 0;
  505. }
  506. static void show_usage(void)
  507. {
  508. printf("Simple multimedia streams analyzer\n");
  509. printf("usage: %s [OPTIONS] [INPUT_FILE]\n", program_name);
  510. printf("\n");
  511. }
  512. static int opt_format(const char *opt, const char *arg)
  513. {
  514. iformat = av_find_input_format(arg);
  515. if (!iformat) {
  516. fprintf(stderr, "Unknown input format: %s\n", arg);
  517. return AVERROR(EINVAL);
  518. }
  519. return 0;
  520. }
  521. static void opt_input_file(void *optctx, const char *arg)
  522. {
  523. if (input_filename) {
  524. fprintf(stderr, "Argument '%s' provided as input filename, but '%s' was already specified.\n",
  525. arg, input_filename);
  526. exit(1);
  527. }
  528. if (!strcmp(arg, "-"))
  529. arg = "pipe:";
  530. input_filename = arg;
  531. }
  532. static int opt_help(const char *opt, const char *arg)
  533. {
  534. const AVClass *class = avformat_get_class();
  535. av_log_set_callback(log_callback_help);
  536. show_usage();
  537. show_help_options(options, "Main options:\n", 0, 0);
  538. printf("\n");
  539. av_opt_show2(&class, NULL,
  540. AV_OPT_FLAG_DECODING_PARAM, 0);
  541. return 0;
  542. }
  543. static int opt_pretty(const char *opt, const char *arg)
  544. {
  545. show_value_unit = 1;
  546. use_value_prefix = 1;
  547. use_byte_value_binary_prefix = 1;
  548. use_value_sexagesimal_format = 1;
  549. return 0;
  550. }
  551. static const OptionDef options[] = {
  552. #include "cmdutils_common_opts.h"
  553. { "f", HAS_ARG, {(void*)opt_format}, "force format", "format" },
  554. { "unit", OPT_BOOL, {(void*)&show_value_unit}, "show unit of the displayed values" },
  555. { "prefix", OPT_BOOL, {(void*)&use_value_prefix}, "use SI prefixes for the displayed values" },
  556. { "byte_binary_prefix", OPT_BOOL, {(void*)&use_byte_value_binary_prefix},
  557. "use binary prefixes for byte units" },
  558. { "sexagesimal", OPT_BOOL, {(void*)&use_value_sexagesimal_format},
  559. "use sexagesimal format HOURS:MM:SS.MICROSECONDS for time units" },
  560. { "pretty", 0, {(void*)&opt_pretty},
  561. "prettify the format of displayed values, make it more human readable" },
  562. { "print_format", OPT_STRING | HAS_ARG, {(void*)&print_format}, "set the output printing format (available formats are: default, json)", "format" },
  563. { "show_format", OPT_BOOL, {(void*)&do_show_format} , "show format/container info" },
  564. { "show_packets", OPT_BOOL, {(void*)&do_show_packets}, "show packets info" },
  565. { "show_streams", OPT_BOOL, {(void*)&do_show_streams}, "show streams info" },
  566. { "default", HAS_ARG | OPT_AUDIO | OPT_VIDEO | OPT_EXPERT, {(void*)opt_default}, "generic catch all option", "" },
  567. { "i", HAS_ARG, {(void *)opt_input_file}, "read specified file", "input_file"},
  568. { NULL, },
  569. };
  570. int main(int argc, char **argv)
  571. {
  572. int ret;
  573. parse_loglevel(argc, argv, options);
  574. av_register_all();
  575. init_opts();
  576. #if CONFIG_AVDEVICE
  577. avdevice_register_all();
  578. #endif
  579. show_banner();
  580. parse_options(NULL, argc, argv, options, opt_input_file);
  581. if (!input_filename) {
  582. show_usage();
  583. fprintf(stderr, "You have to specify one input file.\n");
  584. fprintf(stderr, "Use -h to get full help or, even better, run 'man %s'.\n", program_name);
  585. exit(1);
  586. }
  587. ret = probe_file(input_filename);
  588. return ret;
  589. }