FFmpeg
ffprobe.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2007-2010 Stefano Sabatini
3  *
4  * This file is part of FFmpeg.
5  *
6  * FFmpeg is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * FFmpeg is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with FFmpeg; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19  */
20 
21 /**
22  * @file
23  * simple media prober based on the FFmpeg libraries
24  */
25 
26 #include "config.h"
27 #include "libavutil/ffversion.h"
28 
29 #include <string.h>
30 
31 #include "libavformat/avformat.h"
32 #include "libavcodec/avcodec.h"
33 #include "libavutil/avassert.h"
34 #include "libavutil/avstring.h"
35 #include "libavutil/bprint.h"
36 #include "libavutil/display.h"
37 #include "libavutil/hash.h"
40 #include "libavutil/dovi_meta.h"
41 #include "libavutil/opt.h"
42 #include "libavutil/pixdesc.h"
43 #include "libavutil/spherical.h"
44 #include "libavutil/stereo3d.h"
45 #include "libavutil/dict.h"
46 #include "libavutil/intreadwrite.h"
47 #include "libavutil/libm.h"
48 #include "libavutil/parseutils.h"
49 #include "libavutil/timecode.h"
50 #include "libavutil/timestamp.h"
51 #include "libavdevice/avdevice.h"
52 #include "libswscale/swscale.h"
55 #include "cmdutils.h"
56 
57 #include "libavutil/thread.h"
58 
59 #if !HAVE_THREADS
60 # ifdef pthread_mutex_lock
61 # undef pthread_mutex_lock
62 # endif
63 # define pthread_mutex_lock(a) do{}while(0)
64 # ifdef pthread_mutex_unlock
65 # undef pthread_mutex_unlock
66 # endif
67 # define pthread_mutex_unlock(a) do{}while(0)
68 #endif
69 
70 typedef struct InputStream {
71  AVStream *st;
72 
74 } InputStream;
75 
76 typedef struct InputFile {
78 
80  int nb_streams;
81 } InputFile;
82 
83 const char program_name[] = "ffprobe";
84 const int program_birth_year = 2007;
85 
86 static int do_bitexact = 0;
87 static int do_count_frames = 0;
88 static int do_count_packets = 0;
89 static int do_read_frames = 0;
90 static int do_read_packets = 0;
91 static int do_show_chapters = 0;
92 static int do_show_error = 0;
93 static int do_show_format = 0;
94 static int do_show_frames = 0;
95 static int do_show_packets = 0;
96 static int do_show_programs = 0;
97 static int do_show_streams = 0;
99 static int do_show_data = 0;
100 static int do_show_program_version = 0;
102 static int do_show_pixel_formats = 0;
105 static int do_show_log = 0;
106 
107 static int do_show_chapter_tags = 0;
108 static int do_show_format_tags = 0;
109 static int do_show_frame_tags = 0;
110 static int do_show_program_tags = 0;
111 static int do_show_stream_tags = 0;
112 static int do_show_packet_tags = 0;
113 
114 static int show_value_unit = 0;
115 static int use_value_prefix = 0;
118 static int show_private_data = 1;
119 
120 #define SHOW_OPTIONAL_FIELDS_AUTO -1
121 #define SHOW_OPTIONAL_FIELDS_NEVER 0
122 #define SHOW_OPTIONAL_FIELDS_ALWAYS 1
124 
125 static char *print_format;
126 static char *stream_specifier;
127 static char *show_data_hash;
128 
129 typedef struct ReadInterval {
130  int id; ///< identifier
131  int64_t start, end; ///< start, end in second/AV_TIME_BASE units
135 } ReadInterval;
136 
138 static int read_intervals_nb = 0;
139 
140 static int find_stream_info = 1;
141 
142 /* section structure definition */
143 
144 #define SECTION_MAX_NB_CHILDREN 10
145 
146 struct section {
147  int id; ///< unique id identifying a section
148  const char *name;
149 
150 #define SECTION_FLAG_IS_WRAPPER 1 ///< the section only contains other sections, but has no data at its own level
151 #define SECTION_FLAG_IS_ARRAY 2 ///< the section contains an array of elements of the same type
152 #define SECTION_FLAG_HAS_VARIABLE_FIELDS 4 ///< the section may contain a variable number of fields with variable keys.
153  /// For these sections the element_name field is mandatory.
154  int flags;
155  int children_ids[SECTION_MAX_NB_CHILDREN+1]; ///< list of children section IDS, terminated by -1
156  const char *element_name; ///< name of the contained element, if provided
157  const char *unique_name; ///< unique section name, in case the name is ambiguous
160 };
161 
162 typedef enum {
208 } SectionID;
209 
210 static struct section sections[] = {
212  [SECTION_ID_CHAPTER] = { SECTION_ID_CHAPTER, "chapter", 0, { SECTION_ID_CHAPTER_TAGS, -1 } },
213  [SECTION_ID_CHAPTER_TAGS] = { SECTION_ID_CHAPTER_TAGS, "tags", SECTION_FLAG_HAS_VARIABLE_FIELDS, { -1 }, .element_name = "tag", .unique_name = "chapter_tags" },
214  [SECTION_ID_ERROR] = { SECTION_ID_ERROR, "error", 0, { -1 } },
215  [SECTION_ID_FORMAT] = { SECTION_ID_FORMAT, "format", 0, { SECTION_ID_FORMAT_TAGS, -1 } },
216  [SECTION_ID_FORMAT_TAGS] = { SECTION_ID_FORMAT_TAGS, "tags", SECTION_FLAG_HAS_VARIABLE_FIELDS, { -1 }, .element_name = "tag", .unique_name = "format_tags" },
219  [SECTION_ID_FRAME_TAGS] = { SECTION_ID_FRAME_TAGS, "tags", SECTION_FLAG_HAS_VARIABLE_FIELDS, { -1 }, .element_name = "tag", .unique_name = "frame_tags" },
220  [SECTION_ID_FRAME_SIDE_DATA_LIST] ={ SECTION_ID_FRAME_SIDE_DATA_LIST, "side_data_list", SECTION_FLAG_IS_ARRAY, { SECTION_ID_FRAME_SIDE_DATA, -1 }, .element_name = "side_data", .unique_name = "frame_side_data_list" },
225  [SECTION_ID_FRAME_LOG] = { SECTION_ID_FRAME_LOG, "log", 0, { -1 }, },
227  [SECTION_ID_LIBRARY_VERSION] = { SECTION_ID_LIBRARY_VERSION, "library_version", 0, { -1 } },
231  [SECTION_ID_PACKET_TAGS] = { SECTION_ID_PACKET_TAGS, "tags", SECTION_FLAG_HAS_VARIABLE_FIELDS, { -1 }, .element_name = "tag", .unique_name = "packet_tags" },
232  [SECTION_ID_PACKET_SIDE_DATA_LIST] ={ SECTION_ID_PACKET_SIDE_DATA_LIST, "side_data_list", SECTION_FLAG_IS_ARRAY, { SECTION_ID_PACKET_SIDE_DATA, -1 }, .element_name = "side_data", .unique_name = "packet_side_data_list" },
233  [SECTION_ID_PACKET_SIDE_DATA] = { SECTION_ID_PACKET_SIDE_DATA, "side_data", 0, { -1 } },
236  [SECTION_ID_PIXEL_FORMAT_FLAGS] = { SECTION_ID_PIXEL_FORMAT_FLAGS, "flags", 0, { -1 }, .unique_name = "pixel_format_flags" },
237  [SECTION_ID_PIXEL_FORMAT_COMPONENTS] = { SECTION_ID_PIXEL_FORMAT_COMPONENTS, "components", SECTION_FLAG_IS_ARRAY, {SECTION_ID_PIXEL_FORMAT_COMPONENT, -1 }, .unique_name = "pixel_format_components" },
239  [SECTION_ID_PROGRAM_STREAM_DISPOSITION] = { SECTION_ID_PROGRAM_STREAM_DISPOSITION, "disposition", 0, { -1 }, .unique_name = "program_stream_disposition" },
240  [SECTION_ID_PROGRAM_STREAM_TAGS] = { SECTION_ID_PROGRAM_STREAM_TAGS, "tags", SECTION_FLAG_HAS_VARIABLE_FIELDS, { -1 }, .element_name = "tag", .unique_name = "program_stream_tags" },
242  [SECTION_ID_PROGRAM_STREAMS] = { SECTION_ID_PROGRAM_STREAMS, "streams", SECTION_FLAG_IS_ARRAY, { SECTION_ID_PROGRAM_STREAM, -1 }, .unique_name = "program_streams" },
244  [SECTION_ID_PROGRAM_TAGS] = { SECTION_ID_PROGRAM_TAGS, "tags", SECTION_FLAG_HAS_VARIABLE_FIELDS, { -1 }, .element_name = "tag", .unique_name = "program_tags" },
245  [SECTION_ID_PROGRAM_VERSION] = { SECTION_ID_PROGRAM_VERSION, "program_version", 0, { -1 } },
253  [SECTION_ID_STREAM_DISPOSITION] = { SECTION_ID_STREAM_DISPOSITION, "disposition", 0, { -1 }, .unique_name = "stream_disposition" },
254  [SECTION_ID_STREAM_TAGS] = { SECTION_ID_STREAM_TAGS, "tags", SECTION_FLAG_HAS_VARIABLE_FIELDS, { -1 }, .element_name = "tag", .unique_name = "stream_tags" },
255  [SECTION_ID_STREAM_SIDE_DATA_LIST] ={ SECTION_ID_STREAM_SIDE_DATA_LIST, "side_data_list", SECTION_FLAG_IS_ARRAY, { SECTION_ID_STREAM_SIDE_DATA, -1 }, .element_name = "side_data", .unique_name = "stream_side_data_list" },
256  [SECTION_ID_STREAM_SIDE_DATA] = { SECTION_ID_STREAM_SIDE_DATA, "side_data", 0, { -1 } },
257  [SECTION_ID_SUBTITLE] = { SECTION_ID_SUBTITLE, "subtitle", 0, { -1 } },
258 };
259 
260 static const OptionDef *options;
261 
262 /* FFprobe context */
263 static const char *input_filename;
264 static const char *print_input_filename;
265 static const AVInputFormat *iformat = NULL;
266 
267 static struct AVHashContext *hash;
268 
269 static const struct {
270  double bin_val;
271  double dec_val;
272  const char *bin_str;
273  const char *dec_str;
274 } si_prefixes[] = {
275  { 1.0, 1.0, "", "" },
276  { 1.024e3, 1e3, "Ki", "K" },
277  { 1.048576e6, 1e6, "Mi", "M" },
278  { 1.073741824e9, 1e9, "Gi", "G" },
279  { 1.099511627776e12, 1e12, "Ti", "T" },
280  { 1.125899906842624e15, 1e15, "Pi", "P" },
281 };
282 
283 static const char unit_second_str[] = "s" ;
284 static const char unit_hertz_str[] = "Hz" ;
285 static const char unit_byte_str[] = "byte" ;
286 static const char unit_bit_per_second_str[] = "bit/s";
287 
288 static int nb_streams;
289 static uint64_t *nb_streams_packets;
290 static uint64_t *nb_streams_frames;
291 static int *selected_streams;
292 
293 #if HAVE_THREADS
294 pthread_mutex_t log_mutex;
295 #endif
296 typedef struct LogBuffer {
299  char *log_message;
301  char *parent_name;
303 }LogBuffer;
304 
306 static int log_buffer_size;
307 
308 static void log_callback(void *ptr, int level, const char *fmt, va_list vl)
309 {
310  AVClass* avc = ptr ? *(AVClass **) ptr : NULL;
311  va_list vl2;
312  char line[1024];
313  static int print_prefix = 1;
314  void *new_log_buffer;
315 
316  va_copy(vl2, vl);
317  av_log_default_callback(ptr, level, fmt, vl);
318  av_log_format_line(ptr, level, fmt, vl2, line, sizeof(line), &print_prefix);
319  va_end(vl2);
320 
321 #if HAVE_THREADS
322  pthread_mutex_lock(&log_mutex);
323 
324  new_log_buffer = av_realloc_array(log_buffer, log_buffer_size + 1, sizeof(*log_buffer));
325  if (new_log_buffer) {
326  char *msg;
327  int i;
328 
329  log_buffer = new_log_buffer;
330  memset(&log_buffer[log_buffer_size], 0, sizeof(log_buffer[log_buffer_size]));
332  if (avc) {
335  }
338  for (i=strlen(msg) - 1; i>=0 && msg[i] == '\n'; i--) {
339  msg[i] = 0;
340  }
341  if (avc && avc->parent_log_context_offset) {
342  AVClass** parent = *(AVClass ***) (((uint8_t *) ptr) +
344  if (parent && *parent) {
345  log_buffer[log_buffer_size].parent_name = av_strdup((*parent)->item_name(parent));
347  (*parent)->get_category ? (*parent)->get_category(parent) :(*parent)->category;
348  }
349  }
350  log_buffer_size ++;
351  }
352 
353  pthread_mutex_unlock(&log_mutex);
354 #endif
355 }
356 
357 static void ffprobe_cleanup(int ret)
358 {
359  int i;
360  for (i = 0; i < FF_ARRAY_ELEMS(sections); i++)
361  av_dict_free(&(sections[i].entries_to_show));
362 
363 #if HAVE_THREADS
364  pthread_mutex_destroy(&log_mutex);
365 #endif
366 }
367 
368 struct unit_value {
369  union { double d; long long int i; } val;
370  const char *unit;
371 };
372 
373 static char *value_string(char *buf, int buf_size, struct unit_value uv)
374 {
375  double vald;
376  long long int vali;
377  int show_float = 0;
378 
379  if (uv.unit == unit_second_str) {
380  vald = uv.val.d;
381  show_float = 1;
382  } else {
383  vald = vali = uv.val.i;
384  }
385 
387  double secs;
388  int hours, mins;
389  secs = vald;
390  mins = (int)secs / 60;
391  secs = secs - mins * 60;
392  hours = mins / 60;
393  mins %= 60;
394  snprintf(buf, buf_size, "%d:%02d:%09.6f", hours, mins, secs);
395  } else {
396  const char *prefix_string = "";
397 
398  if (use_value_prefix && vald > 1) {
399  long long int index;
400 
402  index = (long long int) (log2(vald)) / 10;
404  vald /= si_prefixes[index].bin_val;
405  prefix_string = si_prefixes[index].bin_str;
406  } else {
407  index = (long long int) (log10(vald)) / 3;
409  vald /= si_prefixes[index].dec_val;
410  prefix_string = si_prefixes[index].dec_str;
411  }
412  vali = vald;
413  }
414 
415  if (show_float || (use_value_prefix && vald != (long long int)vald))
416  snprintf(buf, buf_size, "%f", vald);
417  else
418  snprintf(buf, buf_size, "%lld", vali);
419  av_strlcatf(buf, buf_size, "%s%s%s", *prefix_string || show_value_unit ? " " : "",
420  prefix_string, show_value_unit ? uv.unit : "");
421  }
422 
423  return buf;
424 }
425 
426 /* WRITERS API */
427 
428 typedef struct WriterContext WriterContext;
429 
430 #define WRITER_FLAG_DISPLAY_OPTIONAL_FIELDS 1
431 #define WRITER_FLAG_PUT_PACKETS_AND_FRAMES_IN_SAME_CHAPTER 2
432 
433 typedef enum {
439 
440 typedef struct Writer {
441  const AVClass *priv_class; ///< private class of the writer, if any
442  int priv_size; ///< private size for the writer context
443  const char *name;
444 
445  int (*init) (WriterContext *wctx);
446  void (*uninit)(WriterContext *wctx);
447 
450  void (*print_integer) (WriterContext *wctx, const char *, long long int);
451  void (*print_rational) (WriterContext *wctx, AVRational *q, char *sep);
452  void (*print_string) (WriterContext *wctx, const char *, const char *);
453  int flags; ///< a combination or WRITER_FLAG_*
454 } Writer;
455 
456 #define SECTION_MAX_NB_LEVELS 10
457 
459  const AVClass *class; ///< class of the writer
460  const Writer *writer; ///< the Writer of which this is an instance
461  char *name; ///< name of this writer instance
462  void *priv; ///< private data for use by the filter
463 
464  const struct section *sections; ///< array containing all sections
465  int nb_sections; ///< number of sections
466 
467  int level; ///< current level, starting from 0
468 
469  /** number of the item printed in the given section, starting from 0 */
471 
472  /** section per each level */
474  AVBPrint section_pbuf[SECTION_MAX_NB_LEVELS]; ///< generic print buffer dedicated to each section,
475  /// used by various writers
476 
477  unsigned int nb_section_packet; ///< number of the packet section in case we are in "packets_and_frames" section
478  unsigned int nb_section_frame; ///< number of the frame section in case we are in "packets_and_frames" section
479  unsigned int nb_section_packet_frame; ///< nb_section_packet or nb_section_frame according if is_packets_and_frames
480 
484 };
485 
486 static const char *writer_get_name(void *p)
487 {
488  WriterContext *wctx = p;
489  return wctx->writer->name;
490 }
491 
492 #define OFFSET(x) offsetof(WriterContext, x)
493 
494 static const AVOption writer_options[] = {
495  { "string_validation", "set string validation mode",
496  OFFSET(string_validation), AV_OPT_TYPE_INT, {.i64=WRITER_STRING_VALIDATION_REPLACE}, 0, WRITER_STRING_VALIDATION_NB-1, .unit = "sv" },
497  { "sv", "set string validation mode",
498  OFFSET(string_validation), AV_OPT_TYPE_INT, {.i64=WRITER_STRING_VALIDATION_REPLACE}, 0, WRITER_STRING_VALIDATION_NB-1, .unit = "sv" },
499  { "ignore", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = WRITER_STRING_VALIDATION_IGNORE}, .unit = "sv" },
500  { "replace", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = WRITER_STRING_VALIDATION_REPLACE}, .unit = "sv" },
501  { "fail", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = WRITER_STRING_VALIDATION_FAIL}, .unit = "sv" },
502  { "string_validation_replacement", "set string validation replacement string", OFFSET(string_validation_replacement), AV_OPT_TYPE_STRING, {.str=""}},
503  { "svr", "set string validation replacement string", OFFSET(string_validation_replacement), AV_OPT_TYPE_STRING, {.str="\xEF\xBF\xBD"}},
504  { NULL }
505 };
506 
507 static void *writer_child_next(void *obj, void *prev)
508 {
509  WriterContext *ctx = obj;
510  if (!prev && ctx->writer && ctx->writer->priv_class && ctx->priv)
511  return ctx->priv;
512  return NULL;
513 }
514 
515 static const AVClass writer_class = {
516  .class_name = "Writer",
517  .item_name = writer_get_name,
518  .option = writer_options,
519  .version = LIBAVUTIL_VERSION_INT,
520  .child_next = writer_child_next,
521 };
522 
523 static void writer_close(WriterContext **wctx)
524 {
525  int i;
526 
527  if (!*wctx)
528  return;
529 
530  if ((*wctx)->writer->uninit)
531  (*wctx)->writer->uninit(*wctx);
532  for (i = 0; i < SECTION_MAX_NB_LEVELS; i++)
533  av_bprint_finalize(&(*wctx)->section_pbuf[i], NULL);
534  if ((*wctx)->writer->priv_class)
535  av_opt_free((*wctx)->priv);
536  av_freep(&((*wctx)->priv));
537  av_opt_free(*wctx);
538  av_freep(wctx);
539 }
540 
541 static void bprint_bytes(AVBPrint *bp, const uint8_t *ubuf, size_t ubuf_size)
542 {
543  int i;
544  av_bprintf(bp, "0X");
545  for (i = 0; i < ubuf_size; i++)
546  av_bprintf(bp, "%02X", ubuf[i]);
547 }
548 
549 
550 static int writer_open(WriterContext **wctx, const Writer *writer, const char *args,
551  const struct section *sections, int nb_sections)
552 {
553  int i, ret = 0;
554 
555  if (!(*wctx = av_mallocz(sizeof(WriterContext)))) {
556  ret = AVERROR(ENOMEM);
557  goto fail;
558  }
559 
560  if (!((*wctx)->priv = av_mallocz(writer->priv_size))) {
561  ret = AVERROR(ENOMEM);
562  goto fail;
563  }
564 
565  (*wctx)->class = &writer_class;
566  (*wctx)->writer = writer;
567  (*wctx)->level = -1;
568  (*wctx)->sections = sections;
569  (*wctx)->nb_sections = nb_sections;
570 
571  av_opt_set_defaults(*wctx);
572 
573  if (writer->priv_class) {
574  void *priv_ctx = (*wctx)->priv;
575  *((const AVClass **)priv_ctx) = writer->priv_class;
576  av_opt_set_defaults(priv_ctx);
577  }
578 
579  /* convert options to dictionary */
580  if (args) {
582  AVDictionaryEntry *opt = NULL;
583 
584  if ((ret = av_dict_parse_string(&opts, args, "=", ":", 0)) < 0) {
585  av_log(*wctx, AV_LOG_ERROR, "Failed to parse option string '%s' provided to writer context\n", args);
586  av_dict_free(&opts);
587  goto fail;
588  }
589 
590  while ((opt = av_dict_get(opts, "", opt, AV_DICT_IGNORE_SUFFIX))) {
591  if ((ret = av_opt_set(*wctx, opt->key, opt->value, AV_OPT_SEARCH_CHILDREN)) < 0) {
592  av_log(*wctx, AV_LOG_ERROR, "Failed to set option '%s' with value '%s' provided to writer context\n",
593  opt->key, opt->value);
594  av_dict_free(&opts);
595  goto fail;
596  }
597  }
598 
599  av_dict_free(&opts);
600  }
601 
602  /* validate replace string */
603  {
604  const uint8_t *p = (*wctx)->string_validation_replacement;
605  const uint8_t *endp = p + strlen(p);
606  while (*p) {
607  const uint8_t *p0 = p;
608  int32_t code;
609  ret = av_utf8_decode(&code, &p, endp, (*wctx)->string_validation_utf8_flags);
610  if (ret < 0) {
611  AVBPrint bp;
613  bprint_bytes(&bp, p0, p-p0),
614  av_log(wctx, AV_LOG_ERROR,
615  "Invalid UTF8 sequence %s found in string validation replace '%s'\n",
616  bp.str, (*wctx)->string_validation_replacement);
617  return ret;
618  }
619  }
620  }
621 
622  for (i = 0; i < SECTION_MAX_NB_LEVELS; i++)
623  av_bprint_init(&(*wctx)->section_pbuf[i], 1, AV_BPRINT_SIZE_UNLIMITED);
624 
625  if ((*wctx)->writer->init)
626  ret = (*wctx)->writer->init(*wctx);
627  if (ret < 0)
628  goto fail;
629 
630  return 0;
631 
632 fail:
633  writer_close(wctx);
634  return ret;
635 }
636 
638  int section_id)
639 {
640  int parent_section_id;
641  wctx->level++;
643  parent_section_id = wctx->level ?
644  (wctx->section[wctx->level-1])->id : SECTION_ID_NONE;
645 
646  wctx->nb_item[wctx->level] = 0;
647  wctx->section[wctx->level] = &wctx->sections[section_id];
648 
649  if (section_id == SECTION_ID_PACKETS_AND_FRAMES) {
650  wctx->nb_section_packet = wctx->nb_section_frame =
651  wctx->nb_section_packet_frame = 0;
652  } else if (parent_section_id == SECTION_ID_PACKETS_AND_FRAMES) {
653  wctx->nb_section_packet_frame = section_id == SECTION_ID_PACKET ?
654  wctx->nb_section_packet : wctx->nb_section_frame;
655  }
656 
657  if (wctx->writer->print_section_header)
658  wctx->writer->print_section_header(wctx);
659 }
660 
662 {
663  int section_id = wctx->section[wctx->level]->id;
664  int parent_section_id = wctx->level ?
665  wctx->section[wctx->level-1]->id : SECTION_ID_NONE;
666 
667  if (parent_section_id != SECTION_ID_NONE)
668  wctx->nb_item[wctx->level-1]++;
669  if (parent_section_id == SECTION_ID_PACKETS_AND_FRAMES) {
670  if (section_id == SECTION_ID_PACKET) wctx->nb_section_packet++;
671  else wctx->nb_section_frame++;
672  }
673  if (wctx->writer->print_section_footer)
674  wctx->writer->print_section_footer(wctx);
675  wctx->level--;
676 }
677 
678 static inline void writer_print_integer(WriterContext *wctx,
679  const char *key, long long int val)
680 {
681  const struct section *section = wctx->section[wctx->level];
682 
684  wctx->writer->print_integer(wctx, key, val);
685  wctx->nb_item[wctx->level]++;
686  }
687 }
688 
689 static inline int validate_string(WriterContext *wctx, char **dstp, const char *src)
690 {
691  const uint8_t *p, *endp;
692  AVBPrint dstbuf;
693  int invalid_chars_nb = 0, ret = 0;
694 
696 
697  endp = src + strlen(src);
698  for (p = (uint8_t *)src; *p;) {
699  uint32_t code;
700  int invalid = 0;
701  const uint8_t *p0 = p;
702 
703  if (av_utf8_decode(&code, &p, endp, wctx->string_validation_utf8_flags) < 0) {
704  AVBPrint bp;
706  bprint_bytes(&bp, p0, p-p0);
707  av_log(wctx, AV_LOG_DEBUG,
708  "Invalid UTF-8 sequence %s found in string '%s'\n", bp.str, src);
709  invalid = 1;
710  }
711 
712  if (invalid) {
713  invalid_chars_nb++;
714 
715  switch (wctx->string_validation) {
717  av_log(wctx, AV_LOG_ERROR,
718  "Invalid UTF-8 sequence found in string '%s'\n", src);
720  goto end;
721  break;
722 
724  av_bprintf(&dstbuf, "%s", wctx->string_validation_replacement);
725  break;
726  }
727  }
728 
729  if (!invalid || wctx->string_validation == WRITER_STRING_VALIDATION_IGNORE)
730  av_bprint_append_data(&dstbuf, p0, p-p0);
731  }
732 
733  if (invalid_chars_nb && wctx->string_validation == WRITER_STRING_VALIDATION_REPLACE) {
734  av_log(wctx, AV_LOG_WARNING,
735  "%d invalid UTF-8 sequence(s) found in string '%s', replaced with '%s'\n",
736  invalid_chars_nb, src, wctx->string_validation_replacement);
737  }
738 
739 end:
740  av_bprint_finalize(&dstbuf, dstp);
741  return ret;
742 }
743 
744 #define PRINT_STRING_OPT 1
745 #define PRINT_STRING_VALIDATE 2
746 
747 static inline int writer_print_string(WriterContext *wctx,
748  const char *key, const char *val, int flags)
749 {
750  const struct section *section = wctx->section[wctx->level];
751  int ret = 0;
752 
755  && (flags & PRINT_STRING_OPT)
757  return 0;
758 
761  char *key1 = NULL, *val1 = NULL;
762  ret = validate_string(wctx, &key1, key);
763  if (ret < 0) goto end;
764  ret = validate_string(wctx, &val1, val);
765  if (ret < 0) goto end;
766  wctx->writer->print_string(wctx, key1, val1);
767  end:
768  if (ret < 0) {
769  av_log(wctx, AV_LOG_ERROR,
770  "Invalid key=value string combination %s=%s in section %s\n",
772  }
773  av_free(key1);
774  av_free(val1);
775  } else {
776  wctx->writer->print_string(wctx, key, val);
777  }
778 
779  wctx->nb_item[wctx->level]++;
780  }
781 
782  return ret;
783 }
784 
785 static inline void writer_print_rational(WriterContext *wctx,
786  const char *key, AVRational q, char sep)
787 {
788  AVBPrint buf;
790  av_bprintf(&buf, "%d%c%d", q.num, sep, q.den);
791  writer_print_string(wctx, key, buf.str, 0);
792 }
793 
794 static void writer_print_time(WriterContext *wctx, const char *key,
795  int64_t ts, const AVRational *time_base, int is_duration)
796 {
797  char buf[128];
798 
799  if ((!is_duration && ts == AV_NOPTS_VALUE) || (is_duration && ts == 0)) {
801  } else {
802  double d = ts * av_q2d(*time_base);
803  struct unit_value uv;
804  uv.val.d = d;
805  uv.unit = unit_second_str;
806  value_string(buf, sizeof(buf), uv);
807  writer_print_string(wctx, key, buf, 0);
808  }
809 }
810 
811 static void writer_print_ts(WriterContext *wctx, const char *key, int64_t ts, int is_duration)
812 {
813  if ((!is_duration && ts == AV_NOPTS_VALUE) || (is_duration && ts == 0)) {
815  } else {
816  writer_print_integer(wctx, key, ts);
817  }
818 }
819 
820 static void writer_print_data(WriterContext *wctx, const char *name,
821  uint8_t *data, int size)
822 {
823  AVBPrint bp;
824  int offset = 0, l, i;
825 
827  av_bprintf(&bp, "\n");
828  while (size) {
829  av_bprintf(&bp, "%08x: ", offset);
830  l = FFMIN(size, 16);
831  for (i = 0; i < l; i++) {
832  av_bprintf(&bp, "%02x", data[i]);
833  if (i & 1)
834  av_bprintf(&bp, " ");
835  }
836  av_bprint_chars(&bp, ' ', 41 - 2 * i - i / 2);
837  for (i = 0; i < l; i++)
838  av_bprint_chars(&bp, data[i] - 32U < 95 ? data[i] : '.', 1);
839  av_bprintf(&bp, "\n");
840  offset += l;
841  data += l;
842  size -= l;
843  }
844  writer_print_string(wctx, name, bp.str, 0);
845  av_bprint_finalize(&bp, NULL);
846 }
847 
848 static void writer_print_data_hash(WriterContext *wctx, const char *name,
849  uint8_t *data, int size)
850 {
851  char *p, buf[AV_HASH_MAX_SIZE * 2 + 64] = { 0 };
852 
853  if (!hash)
854  return;
857  snprintf(buf, sizeof(buf), "%s:", av_hash_get_name(hash));
858  p = buf + strlen(buf);
859  av_hash_final_hex(hash, p, buf + sizeof(buf) - p);
860  writer_print_string(wctx, name, buf, 0);
861 }
862 
863 static void writer_print_integers(WriterContext *wctx, const char *name,
864  uint8_t *data, int size, const char *format,
865  int columns, int bytes, int offset_add)
866 {
867  AVBPrint bp;
868  int offset = 0, l, i;
869 
871  av_bprintf(&bp, "\n");
872  while (size) {
873  av_bprintf(&bp, "%08x: ", offset);
874  l = FFMIN(size, columns);
875  for (i = 0; i < l; i++) {
876  if (bytes == 1) av_bprintf(&bp, format, *data);
877  else if (bytes == 2) av_bprintf(&bp, format, AV_RN16(data));
878  else if (bytes == 4) av_bprintf(&bp, format, AV_RN32(data));
879  data += bytes;
880  size --;
881  }
882  av_bprintf(&bp, "\n");
883  offset += offset_add;
884  }
885  writer_print_string(wctx, name, bp.str, 0);
886  av_bprint_finalize(&bp, NULL);
887 }
888 
889 #define MAX_REGISTERED_WRITERS_NB 64
890 
892 
893 static int writer_register(const Writer *writer)
894 {
895  static int next_registered_writer_idx = 0;
896 
897  if (next_registered_writer_idx == MAX_REGISTERED_WRITERS_NB)
898  return AVERROR(ENOMEM);
899 
900  registered_writers[next_registered_writer_idx++] = writer;
901  return 0;
902 }
903 
904 static const Writer *writer_get_by_name(const char *name)
905 {
906  int i;
907 
908  for (i = 0; registered_writers[i]; i++)
909  if (!strcmp(registered_writers[i]->name, name))
910  return registered_writers[i];
911 
912  return NULL;
913 }
914 
915 
916 /* WRITERS */
917 
918 #define DEFINE_WRITER_CLASS(name) \
919 static const char *name##_get_name(void *ctx) \
920 { \
921  return #name ; \
922 } \
923 static const AVClass name##_class = { \
924  .class_name = #name, \
925  .item_name = name##_get_name, \
926  .option = name##_options \
927 }
928 
929 /* Default output */
930 
931 typedef struct DefaultContext {
932  const AVClass *class;
933  int nokey;
937 
938 #undef OFFSET
939 #define OFFSET(x) offsetof(DefaultContext, x)
940 
941 static const AVOption default_options[] = {
942  { "noprint_wrappers", "do not print headers and footers", OFFSET(noprint_wrappers), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1 },
943  { "nw", "do not print headers and footers", OFFSET(noprint_wrappers), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1 },
944  { "nokey", "force no key printing", OFFSET(nokey), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1 },
945  { "nk", "force no key printing", OFFSET(nokey), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1 },
946  {NULL},
947 };
948 
949 DEFINE_WRITER_CLASS(default);
950 
951 /* lame uppercasing routine, assumes the string is lower case ASCII */
952 static inline char *upcase_string(char *dst, size_t dst_size, const char *src)
953 {
954  int i;
955  for (i = 0; src[i] && i < dst_size-1; i++)
956  dst[i] = av_toupper(src[i]);
957  dst[i] = 0;
958  return dst;
959 }
960 
962 {
963  DefaultContext *def = wctx->priv;
964  char buf[32];
965  const struct section *section = wctx->section[wctx->level];
966  const struct section *parent_section = wctx->level ?
967  wctx->section[wctx->level-1] : NULL;
968 
969  av_bprint_clear(&wctx->section_pbuf[wctx->level]);
970  if (parent_section &&
971  !(parent_section->flags & (SECTION_FLAG_IS_WRAPPER|SECTION_FLAG_IS_ARRAY))) {
972  def->nested_section[wctx->level] = 1;
973  av_bprintf(&wctx->section_pbuf[wctx->level], "%s%s:",
974  wctx->section_pbuf[wctx->level-1].str,
975  upcase_string(buf, sizeof(buf),
977  }
978 
979  if (def->noprint_wrappers || def->nested_section[wctx->level])
980  return;
981 
983  printf("[%s]\n", upcase_string(buf, sizeof(buf), section->name));
984 }
985 
987 {
988  DefaultContext *def = wctx->priv;
989  const struct section *section = wctx->section[wctx->level];
990  char buf[32];
991 
992  if (def->noprint_wrappers || def->nested_section[wctx->level])
993  return;
994 
996  printf("[/%s]\n", upcase_string(buf, sizeof(buf), section->name));
997 }
998 
999 static void default_print_str(WriterContext *wctx, const char *key, const char *value)
1000 {
1001  DefaultContext *def = wctx->priv;
1002 
1003  if (!def->nokey)
1004  printf("%s%s=", wctx->section_pbuf[wctx->level].str, key);
1005  printf("%s\n", value);
1006 }
1007 
1008 static void default_print_int(WriterContext *wctx, const char *key, long long int value)
1009 {
1010  DefaultContext *def = wctx->priv;
1011 
1012  if (!def->nokey)
1013  printf("%s%s=", wctx->section_pbuf[wctx->level].str, key);
1014  printf("%lld\n", value);
1015 }
1016 
1017 static const Writer default_writer = {
1018  .name = "default",
1019  .priv_size = sizeof(DefaultContext),
1022  .print_integer = default_print_int,
1023  .print_string = default_print_str,
1025  .priv_class = &default_class,
1026 };
1027 
1028 /* Compact output */
1029 
1030 /**
1031  * Apply C-language-like string escaping.
1032  */
1033 static const char *c_escape_str(AVBPrint *dst, const char *src, const char sep, void *log_ctx)
1034 {
1035  const char *p;
1036 
1037  for (p = src; *p; p++) {
1038  switch (*p) {
1039  case '\b': av_bprintf(dst, "%s", "\\b"); break;
1040  case '\f': av_bprintf(dst, "%s", "\\f"); break;
1041  case '\n': av_bprintf(dst, "%s", "\\n"); break;
1042  case '\r': av_bprintf(dst, "%s", "\\r"); break;
1043  case '\\': av_bprintf(dst, "%s", "\\\\"); break;
1044  default:
1045  if (*p == sep)
1046  av_bprint_chars(dst, '\\', 1);
1047  av_bprint_chars(dst, *p, 1);
1048  }
1049  }
1050  return dst->str;
1051 }
1052 
1053 /**
1054  * Quote fields containing special characters, check RFC4180.
1055  */
1056 static const char *csv_escape_str(AVBPrint *dst, const char *src, const char sep, void *log_ctx)
1057 {
1058  char meta_chars[] = { sep, '"', '\n', '\r', '\0' };
1059  int needs_quoting = !!src[strcspn(src, meta_chars)];
1060 
1061  if (needs_quoting)
1062  av_bprint_chars(dst, '"', 1);
1063 
1064  for (; *src; src++) {
1065  if (*src == '"')
1066  av_bprint_chars(dst, '"', 1);
1067  av_bprint_chars(dst, *src, 1);
1068  }
1069  if (needs_quoting)
1070  av_bprint_chars(dst, '"', 1);
1071  return dst->str;
1072 }
1073 
1074 static const char *none_escape_str(AVBPrint *dst, const char *src, const char sep, void *log_ctx)
1075 {
1076  return src;
1077 }
1078 
1079 typedef struct CompactContext {
1080  const AVClass *class;
1082  char item_sep;
1083  int nokey;
1086  const char * (*escape_str)(AVBPrint *dst, const char *src, const char sep, void *log_ctx);
1090 } CompactContext;
1091 
1092 #undef OFFSET
1093 #define OFFSET(x) offsetof(CompactContext, x)
1094 
1095 static const AVOption compact_options[]= {
1096  {"item_sep", "set item separator", OFFSET(item_sep_str), AV_OPT_TYPE_STRING, {.str="|"}, 0, 0 },
1097  {"s", "set item separator", OFFSET(item_sep_str), AV_OPT_TYPE_STRING, {.str="|"}, 0, 0 },
1098  {"nokey", "force no key printing", OFFSET(nokey), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1 },
1099  {"nk", "force no key printing", OFFSET(nokey), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1 },
1100  {"escape", "set escape mode", OFFSET(escape_mode_str), AV_OPT_TYPE_STRING, {.str="c"}, 0, 0 },
1101  {"e", "set escape mode", OFFSET(escape_mode_str), AV_OPT_TYPE_STRING, {.str="c"}, 0, 0 },
1102  {"print_section", "print section name", OFFSET(print_section), AV_OPT_TYPE_BOOL, {.i64=1}, 0, 1 },
1103  {"p", "print section name", OFFSET(print_section), AV_OPT_TYPE_BOOL, {.i64=1}, 0, 1 },
1104  {NULL},
1105 };
1106 
1107 DEFINE_WRITER_CLASS(compact);
1108 
1110 {
1111  CompactContext *compact = wctx->priv;
1112 
1113  if (strlen(compact->item_sep_str) != 1) {
1114  av_log(wctx, AV_LOG_ERROR, "Item separator '%s' specified, but must contain a single character\n",
1115  compact->item_sep_str);
1116  return AVERROR(EINVAL);
1117  }
1118  compact->item_sep = compact->item_sep_str[0];
1119 
1120  if (!strcmp(compact->escape_mode_str, "none")) compact->escape_str = none_escape_str;
1121  else if (!strcmp(compact->escape_mode_str, "c" )) compact->escape_str = c_escape_str;
1122  else if (!strcmp(compact->escape_mode_str, "csv" )) compact->escape_str = csv_escape_str;
1123  else {
1124  av_log(wctx, AV_LOG_ERROR, "Unknown escape mode '%s'\n", compact->escape_mode_str);
1125  return AVERROR(EINVAL);
1126  }
1127 
1128  return 0;
1129 }
1130 
1132 {
1133  CompactContext *compact = wctx->priv;
1134  const struct section *section = wctx->section[wctx->level];
1135  const struct section *parent_section = wctx->level ?
1136  wctx->section[wctx->level-1] : NULL;
1137  compact->terminate_line[wctx->level] = 1;
1138  compact->has_nested_elems[wctx->level] = 0;
1139 
1140  av_bprint_clear(&wctx->section_pbuf[wctx->level]);
1141  if (!(section->flags & SECTION_FLAG_IS_ARRAY) && parent_section &&
1142  !(parent_section->flags & (SECTION_FLAG_IS_WRAPPER|SECTION_FLAG_IS_ARRAY))) {
1143  compact->nested_section[wctx->level] = 1;
1144  compact->has_nested_elems[wctx->level-1] = 1;
1145  av_bprintf(&wctx->section_pbuf[wctx->level], "%s%s:",
1146  wctx->section_pbuf[wctx->level-1].str,
1148  wctx->nb_item[wctx->level] = wctx->nb_item[wctx->level-1];
1149  } else {
1150  if (parent_section && compact->has_nested_elems[wctx->level-1] &&
1152  compact->terminate_line[wctx->level-1] = 0;
1153  printf("\n");
1154  }
1155  if (compact->print_section &&
1157  printf("%s%c", section->name, compact->item_sep);
1158  }
1159 }
1160 
1162 {
1163  CompactContext *compact = wctx->priv;
1164 
1165  if (!compact->nested_section[wctx->level] &&
1166  compact->terminate_line[wctx->level] &&
1168  printf("\n");
1169 }
1170 
1171 static void compact_print_str(WriterContext *wctx, const char *key, const char *value)
1172 {
1173  CompactContext *compact = wctx->priv;
1174  AVBPrint buf;
1175 
1176  if (wctx->nb_item[wctx->level]) printf("%c", compact->item_sep);
1177  if (!compact->nokey)
1178  printf("%s%s=", wctx->section_pbuf[wctx->level].str, key);
1180  printf("%s", compact->escape_str(&buf, value, compact->item_sep, wctx));
1181  av_bprint_finalize(&buf, NULL);
1182 }
1183 
1184 static void compact_print_int(WriterContext *wctx, const char *key, long long int value)
1185 {
1186  CompactContext *compact = wctx->priv;
1187 
1188  if (wctx->nb_item[wctx->level]) printf("%c", compact->item_sep);
1189  if (!compact->nokey)
1190  printf("%s%s=", wctx->section_pbuf[wctx->level].str, key);
1191  printf("%lld", value);
1192 }
1193 
1194 static const Writer compact_writer = {
1195  .name = "compact",
1196  .priv_size = sizeof(CompactContext),
1197  .init = compact_init,
1200  .print_integer = compact_print_int,
1201  .print_string = compact_print_str,
1203  .priv_class = &compact_class,
1204 };
1205 
1206 /* CSV output */
1207 
1208 #undef OFFSET
1209 #define OFFSET(x) offsetof(CompactContext, x)
1210 
1211 static const AVOption csv_options[] = {
1212  {"item_sep", "set item separator", OFFSET(item_sep_str), AV_OPT_TYPE_STRING, {.str=","}, 0, 0 },
1213  {"s", "set item separator", OFFSET(item_sep_str), AV_OPT_TYPE_STRING, {.str=","}, 0, 0 },
1214  {"nokey", "force no key printing", OFFSET(nokey), AV_OPT_TYPE_BOOL, {.i64=1}, 0, 1 },
1215  {"nk", "force no key printing", OFFSET(nokey), AV_OPT_TYPE_BOOL, {.i64=1}, 0, 1 },
1216  {"escape", "set escape mode", OFFSET(escape_mode_str), AV_OPT_TYPE_STRING, {.str="csv"}, 0, 0 },
1217  {"e", "set escape mode", OFFSET(escape_mode_str), AV_OPT_TYPE_STRING, {.str="csv"}, 0, 0 },
1218  {"print_section", "print section name", OFFSET(print_section), AV_OPT_TYPE_BOOL, {.i64=1}, 0, 1 },
1219  {"p", "print section name", OFFSET(print_section), AV_OPT_TYPE_BOOL, {.i64=1}, 0, 1 },
1220  {NULL},
1221 };
1222 
1223 DEFINE_WRITER_CLASS(csv);
1224 
1225 static const Writer csv_writer = {
1226  .name = "csv",
1227  .priv_size = sizeof(CompactContext),
1228  .init = compact_init,
1231  .print_integer = compact_print_int,
1232  .print_string = compact_print_str,
1234  .priv_class = &csv_class,
1235 };
1236 
1237 /* Flat output */
1238 
1239 typedef struct FlatContext {
1240  const AVClass *class;
1241  const char *sep_str;
1242  char sep;
1244 } FlatContext;
1245 
1246 #undef OFFSET
1247 #define OFFSET(x) offsetof(FlatContext, x)
1248 
1249 static const AVOption flat_options[]= {
1250  {"sep_char", "set separator", OFFSET(sep_str), AV_OPT_TYPE_STRING, {.str="."}, 0, 0 },
1251  {"s", "set separator", OFFSET(sep_str), AV_OPT_TYPE_STRING, {.str="."}, 0, 0 },
1252  {"hierarchical", "specify if the section specification should be hierarchical", OFFSET(hierarchical), AV_OPT_TYPE_BOOL, {.i64=1}, 0, 1 },
1253  {"h", "specify if the section specification should be hierarchical", OFFSET(hierarchical), AV_OPT_TYPE_BOOL, {.i64=1}, 0, 1 },
1254  {NULL},
1255 };
1256 
1258 
1260 {
1261  FlatContext *flat = wctx->priv;
1262 
1263  if (strlen(flat->sep_str) != 1) {
1264  av_log(wctx, AV_LOG_ERROR, "Item separator '%s' specified, but must contain a single character\n",
1265  flat->sep_str);
1266  return AVERROR(EINVAL);
1267  }
1268  flat->sep = flat->sep_str[0];
1269 
1270  return 0;
1271 }
1272 
1273 static const char *flat_escape_key_str(AVBPrint *dst, const char *src, const char sep)
1274 {
1275  const char *p;
1276 
1277  for (p = src; *p; p++) {
1278  if (!((*p >= '0' && *p <= '9') ||
1279  (*p >= 'a' && *p <= 'z') ||
1280  (*p >= 'A' && *p <= 'Z')))
1281  av_bprint_chars(dst, '_', 1);
1282  else
1283  av_bprint_chars(dst, *p, 1);
1284  }
1285  return dst->str;
1286 }
1287 
1288 static const char *flat_escape_value_str(AVBPrint *dst, const char *src)
1289 {
1290  const char *p;
1291 
1292  for (p = src; *p; p++) {
1293  switch (*p) {
1294  case '\n': av_bprintf(dst, "%s", "\\n"); break;
1295  case '\r': av_bprintf(dst, "%s", "\\r"); break;
1296  case '\\': av_bprintf(dst, "%s", "\\\\"); break;
1297  case '"': av_bprintf(dst, "%s", "\\\""); break;
1298  case '`': av_bprintf(dst, "%s", "\\`"); break;
1299  case '$': av_bprintf(dst, "%s", "\\$"); break;
1300  default: av_bprint_chars(dst, *p, 1); break;
1301  }
1302  }
1303  return dst->str;
1304 }
1305 
1307 {
1308  FlatContext *flat = wctx->priv;
1309  AVBPrint *buf = &wctx->section_pbuf[wctx->level];
1310  const struct section *section = wctx->section[wctx->level];
1311  const struct section *parent_section = wctx->level ?
1312  wctx->section[wctx->level-1] : NULL;
1313 
1314  /* build section header */
1315  av_bprint_clear(buf);
1316  if (!parent_section)
1317  return;
1318  av_bprintf(buf, "%s", wctx->section_pbuf[wctx->level-1].str);
1319 
1320  if (flat->hierarchical ||
1322  av_bprintf(buf, "%s%s", wctx->section[wctx->level]->name, flat->sep_str);
1323 
1324  if (parent_section->flags & SECTION_FLAG_IS_ARRAY) {
1325  int n = parent_section->id == SECTION_ID_PACKETS_AND_FRAMES ?
1326  wctx->nb_section_packet_frame : wctx->nb_item[wctx->level-1];
1327  av_bprintf(buf, "%d%s", n, flat->sep_str);
1328  }
1329  }
1330 }
1331 
1332 static void flat_print_int(WriterContext *wctx, const char *key, long long int value)
1333 {
1334  printf("%s%s=%lld\n", wctx->section_pbuf[wctx->level].str, key, value);
1335 }
1336 
1337 static void flat_print_str(WriterContext *wctx, const char *key, const char *value)
1338 {
1339  FlatContext *flat = wctx->priv;
1340  AVBPrint buf;
1341 
1342  printf("%s", wctx->section_pbuf[wctx->level].str);
1344  printf("%s=", flat_escape_key_str(&buf, key, flat->sep));
1345  av_bprint_clear(&buf);
1346  printf("\"%s\"\n", flat_escape_value_str(&buf, value));
1347  av_bprint_finalize(&buf, NULL);
1348 }
1349 
1350 static const Writer flat_writer = {
1351  .name = "flat",
1352  .priv_size = sizeof(FlatContext),
1353  .init = flat_init,
1355  .print_integer = flat_print_int,
1356  .print_string = flat_print_str,
1358  .priv_class = &flat_class,
1359 };
1360 
1361 /* INI format output */
1362 
1363 typedef struct INIContext {
1364  const AVClass *class;
1366 } INIContext;
1367 
1368 #undef OFFSET
1369 #define OFFSET(x) offsetof(INIContext, x)
1370 
1371 static const AVOption ini_options[] = {
1372  {"hierarchical", "specify if the section specification should be hierarchical", OFFSET(hierarchical), AV_OPT_TYPE_BOOL, {.i64=1}, 0, 1 },
1373  {"h", "specify if the section specification should be hierarchical", OFFSET(hierarchical), AV_OPT_TYPE_BOOL, {.i64=1}, 0, 1 },
1374  {NULL},
1375 };
1376 
1377 DEFINE_WRITER_CLASS(ini);
1378 
1379 static char *ini_escape_str(AVBPrint *dst, const char *src)
1380 {
1381  int i = 0;
1382  char c = 0;
1383 
1384  while (c = src[i++]) {
1385  switch (c) {
1386  case '\b': av_bprintf(dst, "%s", "\\b"); break;
1387  case '\f': av_bprintf(dst, "%s", "\\f"); break;
1388  case '\n': av_bprintf(dst, "%s", "\\n"); break;
1389  case '\r': av_bprintf(dst, "%s", "\\r"); break;
1390  case '\t': av_bprintf(dst, "%s", "\\t"); break;
1391  case '\\':
1392  case '#' :
1393  case '=' :
1394  case ':' : av_bprint_chars(dst, '\\', 1);
1395  default:
1396  if ((unsigned char)c < 32)
1397  av_bprintf(dst, "\\x00%02x", c & 0xff);
1398  else
1399  av_bprint_chars(dst, c, 1);
1400  break;
1401  }
1402  }
1403  return dst->str;
1404 }
1405 
1407 {
1408  INIContext *ini = wctx->priv;
1409  AVBPrint *buf = &wctx->section_pbuf[wctx->level];
1410  const struct section *section = wctx->section[wctx->level];
1411  const struct section *parent_section = wctx->level ?
1412  wctx->section[wctx->level-1] : NULL;
1413 
1414  av_bprint_clear(buf);
1415  if (!parent_section) {
1416  printf("# ffprobe output\n\n");
1417  return;
1418  }
1419 
1420  if (wctx->nb_item[wctx->level-1])
1421  printf("\n");
1422 
1423  av_bprintf(buf, "%s", wctx->section_pbuf[wctx->level-1].str);
1424  if (ini->hierarchical ||
1426  av_bprintf(buf, "%s%s", buf->str[0] ? "." : "", wctx->section[wctx->level]->name);
1427 
1428  if (parent_section->flags & SECTION_FLAG_IS_ARRAY) {
1429  int n = parent_section->id == SECTION_ID_PACKETS_AND_FRAMES ?
1430  wctx->nb_section_packet_frame : wctx->nb_item[wctx->level-1];
1431  av_bprintf(buf, ".%d", n);
1432  }
1433  }
1434 
1436  printf("[%s]\n", buf->str);
1437 }
1438 
1439 static void ini_print_str(WriterContext *wctx, const char *key, const char *value)
1440 {
1441  AVBPrint buf;
1442 
1444  printf("%s=", ini_escape_str(&buf, key));
1445  av_bprint_clear(&buf);
1446  printf("%s\n", ini_escape_str(&buf, value));
1447  av_bprint_finalize(&buf, NULL);
1448 }
1449 
1450 static void ini_print_int(WriterContext *wctx, const char *key, long long int value)
1451 {
1452  printf("%s=%lld\n", key, value);
1453 }
1454 
1455 static const Writer ini_writer = {
1456  .name = "ini",
1457  .priv_size = sizeof(INIContext),
1459  .print_integer = ini_print_int,
1460  .print_string = ini_print_str,
1462  .priv_class = &ini_class,
1463 };
1464 
1465 /* JSON output */
1466 
1467 typedef struct JSONContext {
1468  const AVClass *class;
1470  int compact;
1471  const char *item_sep, *item_start_end;
1472 } JSONContext;
1473 
1474 #undef OFFSET
1475 #define OFFSET(x) offsetof(JSONContext, x)
1476 
1477 static const AVOption json_options[]= {
1478  { "compact", "enable compact output", OFFSET(compact), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1 },
1479  { "c", "enable compact output", OFFSET(compact), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1 },
1480  { NULL }
1481 };
1482 
1483 DEFINE_WRITER_CLASS(json);
1484 
1486 {
1487  JSONContext *json = wctx->priv;
1488 
1489  json->item_sep = json->compact ? ", " : ",\n";
1490  json->item_start_end = json->compact ? " " : "\n";
1491 
1492  return 0;
1493 }
1494 
1495 static const char *json_escape_str(AVBPrint *dst, const char *src, void *log_ctx)
1496 {
1497  static const char json_escape[] = {'"', '\\', '\b', '\f', '\n', '\r', '\t', 0};
1498  static const char json_subst[] = {'"', '\\', 'b', 'f', 'n', 'r', 't', 0};
1499  const char *p;
1500 
1501  for (p = src; *p; p++) {
1502  char *s = strchr(json_escape, *p);
1503  if (s) {
1504  av_bprint_chars(dst, '\\', 1);
1505  av_bprint_chars(dst, json_subst[s - json_escape], 1);
1506  } else if ((unsigned char)*p < 32) {
1507  av_bprintf(dst, "\\u00%02x", *p & 0xff);
1508  } else {
1509  av_bprint_chars(dst, *p, 1);
1510  }
1511  }
1512  return dst->str;
1513 }
1514 
1515 #define JSON_INDENT() printf("%*c", json->indent_level * 4, ' ')
1516 
1518 {
1519  JSONContext *json = wctx->priv;
1520  AVBPrint buf;
1521  const struct section *section = wctx->section[wctx->level];
1522  const struct section *parent_section = wctx->level ?
1523  wctx->section[wctx->level-1] : NULL;
1524 
1525  if (wctx->level && wctx->nb_item[wctx->level-1])
1526  printf(",\n");
1527 
1529  printf("{\n");
1530  json->indent_level++;
1531  } else {
1533  json_escape_str(&buf, section->name, wctx);
1534  JSON_INDENT();
1535 
1536  json->indent_level++;
1538  printf("\"%s\": [\n", buf.str);
1539  } else if (parent_section && !(parent_section->flags & SECTION_FLAG_IS_ARRAY)) {
1540  printf("\"%s\": {%s", buf.str, json->item_start_end);
1541  } else {
1542  printf("{%s", json->item_start_end);
1543 
1544  /* this is required so the parser can distinguish between packets and frames */
1545  if (parent_section && parent_section->id == SECTION_ID_PACKETS_AND_FRAMES) {
1546  if (!json->compact)
1547  JSON_INDENT();
1548  printf("\"type\": \"%s\"", section->name);
1549  }
1550  }
1551  av_bprint_finalize(&buf, NULL);
1552  }
1553 }
1554 
1556 {
1557  JSONContext *json = wctx->priv;
1558  const struct section *section = wctx->section[wctx->level];
1559 
1560  if (wctx->level == 0) {
1561  json->indent_level--;
1562  printf("\n}\n");
1563  } else if (section->flags & SECTION_FLAG_IS_ARRAY) {
1564  printf("\n");
1565  json->indent_level--;
1566  JSON_INDENT();
1567  printf("]");
1568  } else {
1569  printf("%s", json->item_start_end);
1570  json->indent_level--;
1571  if (!json->compact)
1572  JSON_INDENT();
1573  printf("}");
1574  }
1575 }
1576 
1577 static inline void json_print_item_str(WriterContext *wctx,
1578  const char *key, const char *value)
1579 {
1580  AVBPrint buf;
1581 
1583  printf("\"%s\":", json_escape_str(&buf, key, wctx));
1584  av_bprint_clear(&buf);
1585  printf(" \"%s\"", json_escape_str(&buf, value, wctx));
1586  av_bprint_finalize(&buf, NULL);
1587 }
1588 
1589 static void json_print_str(WriterContext *wctx, const char *key, const char *value)
1590 {
1591  JSONContext *json = wctx->priv;
1592  const struct section *parent_section = wctx->level ?
1593  wctx->section[wctx->level-1] : NULL;
1594 
1595  if (wctx->nb_item[wctx->level] || (parent_section && parent_section->id == SECTION_ID_PACKETS_AND_FRAMES))
1596  printf("%s", json->item_sep);
1597  if (!json->compact)
1598  JSON_INDENT();
1599  json_print_item_str(wctx, key, value);
1600 }
1601 
1602 static void json_print_int(WriterContext *wctx, const char *key, long long int value)
1603 {
1604  JSONContext *json = wctx->priv;
1605  const struct section *parent_section = wctx->level ?
1606  wctx->section[wctx->level-1] : NULL;
1607  AVBPrint buf;
1608 
1609  if (wctx->nb_item[wctx->level] || (parent_section && parent_section->id == SECTION_ID_PACKETS_AND_FRAMES))
1610  printf("%s", json->item_sep);
1611  if (!json->compact)
1612  JSON_INDENT();
1613 
1615  printf("\"%s\": %lld", json_escape_str(&buf, key, wctx), value);
1616  av_bprint_finalize(&buf, NULL);
1617 }
1618 
1619 static const Writer json_writer = {
1620  .name = "json",
1621  .priv_size = sizeof(JSONContext),
1622  .init = json_init,
1625  .print_integer = json_print_int,
1626  .print_string = json_print_str,
1628  .priv_class = &json_class,
1629 };
1630 
1631 /* XML output */
1632 
1633 typedef struct XMLContext {
1634  const AVClass *class;
1639 } XMLContext;
1640 
1641 #undef OFFSET
1642 #define OFFSET(x) offsetof(XMLContext, x)
1643 
1644 static const AVOption xml_options[] = {
1645  {"fully_qualified", "specify if the output should be fully qualified", OFFSET(fully_qualified), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1 },
1646  {"q", "specify if the output should be fully qualified", OFFSET(fully_qualified), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1 },
1647  {"xsd_strict", "ensure that the output is XSD compliant", OFFSET(xsd_strict), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1 },
1648  {"x", "ensure that the output is XSD compliant", OFFSET(xsd_strict), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1 },
1649  {NULL},
1650 };
1651 
1652 DEFINE_WRITER_CLASS(xml);
1653 
1654 static av_cold int xml_init(WriterContext *wctx)
1655 {
1656  XMLContext *xml = wctx->priv;
1657 
1658  if (xml->xsd_strict) {
1659  xml->fully_qualified = 1;
1660 #define CHECK_COMPLIANCE(opt, opt_name) \
1661  if (opt) { \
1662  av_log(wctx, AV_LOG_ERROR, \
1663  "XSD-compliant output selected but option '%s' was selected, XML output may be non-compliant.\n" \
1664  "You need to disable such option with '-no%s'\n", opt_name, opt_name); \
1665  return AVERROR(EINVAL); \
1666  }
1667  CHECK_COMPLIANCE(show_private_data, "private");
1670  }
1671 
1672  return 0;
1673 }
1674 
1675 #define XML_INDENT() printf("%*c", xml->indent_level * 4, ' ')
1676 
1678 {
1679  XMLContext *xml = wctx->priv;
1680  const struct section *section = wctx->section[wctx->level];
1681  const struct section *parent_section = wctx->level ?
1682  wctx->section[wctx->level-1] : NULL;
1683 
1684  if (wctx->level == 0) {
1685  const char *qual = " xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' "
1686  "xmlns:ffprobe='http://www.ffmpeg.org/schema/ffprobe' "
1687  "xsi:schemaLocation='http://www.ffmpeg.org/schema/ffprobe ffprobe.xsd'";
1688 
1689  printf("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
1690  printf("<%sffprobe%s>\n",
1691  xml->fully_qualified ? "ffprobe:" : "",
1692  xml->fully_qualified ? qual : "");
1693  return;
1694  }
1695 
1696  if (xml->within_tag) {
1697  xml->within_tag = 0;
1698  printf(">\n");
1699  }
1701  xml->indent_level++;
1702  } else {
1703  if (parent_section && (parent_section->flags & SECTION_FLAG_IS_WRAPPER) &&
1704  wctx->level && wctx->nb_item[wctx->level-1])
1705  printf("\n");
1706  xml->indent_level++;
1707 
1709  XML_INDENT(); printf("<%s>\n", section->name);
1710  } else {
1711  XML_INDENT(); printf("<%s ", section->name);
1712  xml->within_tag = 1;
1713  }
1714  }
1715 }
1716 
1718 {
1719  XMLContext *xml = wctx->priv;
1720  const struct section *section = wctx->section[wctx->level];
1721 
1722  if (wctx->level == 0) {
1723  printf("</%sffprobe>\n", xml->fully_qualified ? "ffprobe:" : "");
1724  } else if (xml->within_tag) {
1725  xml->within_tag = 0;
1726  printf("/>\n");
1727  xml->indent_level--;
1729  xml->indent_level--;
1730  } else {
1731  XML_INDENT(); printf("</%s>\n", section->name);
1732  xml->indent_level--;
1733  }
1734 }
1735 
1736 static void xml_print_str(WriterContext *wctx, const char *key, const char *value)
1737 {
1738  AVBPrint buf;
1739  XMLContext *xml = wctx->priv;
1740  const struct section *section = wctx->section[wctx->level];
1741 
1743 
1745  XML_INDENT();
1746  av_bprint_escape(&buf, key, NULL,
1748  printf("<%s key=\"%s\"",
1749  section->element_name, buf.str);
1750  av_bprint_clear(&buf);
1751 
1752  av_bprint_escape(&buf, value, NULL,
1754  printf(" value=\"%s\"/>\n", buf.str);
1755  } else {
1756  if (wctx->nb_item[wctx->level])
1757  printf(" ");
1758 
1759  av_bprint_escape(&buf, value, NULL,
1761  printf("%s=\"%s\"", key, buf.str);
1762  }
1763 
1764  av_bprint_finalize(&buf, NULL);
1765 }
1766 
1767 static void xml_print_int(WriterContext *wctx, const char *key, long long int value)
1768 {
1769  if (wctx->nb_item[wctx->level])
1770  printf(" ");
1771  printf("%s=\"%lld\"", key, value);
1772 }
1773 
1774 static Writer xml_writer = {
1775  .name = "xml",
1776  .priv_size = sizeof(XMLContext),
1777  .init = xml_init,
1780  .print_integer = xml_print_int,
1781  .print_string = xml_print_str,
1783  .priv_class = &xml_class,
1784 };
1785 
1786 static void writer_register_all(void)
1787 {
1788  static int initialized;
1789 
1790  if (initialized)
1791  return;
1792  initialized = 1;
1793 
1801 }
1802 
1803 #define print_fmt(k, f, ...) do { \
1804  av_bprint_clear(&pbuf); \
1805  av_bprintf(&pbuf, f, __VA_ARGS__); \
1806  writer_print_string(w, k, pbuf.str, 0); \
1807 } while (0)
1808 
1809 #define print_int(k, v) writer_print_integer(w, k, v)
1810 #define print_q(k, v, s) writer_print_rational(w, k, v, s)
1811 #define print_str(k, v) writer_print_string(w, k, v, 0)
1812 #define print_str_opt(k, v) writer_print_string(w, k, v, PRINT_STRING_OPT)
1813 #define print_str_validate(k, v) writer_print_string(w, k, v, PRINT_STRING_VALIDATE)
1814 #define print_time(k, v, tb) writer_print_time(w, k, v, tb, 0)
1815 #define print_ts(k, v) writer_print_ts(w, k, v, 0)
1816 #define print_duration_time(k, v, tb) writer_print_time(w, k, v, tb, 1)
1817 #define print_duration_ts(k, v) writer_print_ts(w, k, v, 1)
1818 #define print_val(k, v, u) do { \
1819  struct unit_value uv; \
1820  uv.val.i = v; \
1821  uv.unit = u; \
1822  writer_print_string(w, k, value_string(val_str, sizeof(val_str), uv), 0); \
1823 } while (0)
1824 
1825 #define print_section_header(s) writer_print_section_header(w, s)
1826 #define print_section_footer(s) writer_print_section_footer(w, s)
1827 
1828 #define REALLOCZ_ARRAY_STREAM(ptr, cur_n, new_n) \
1829 { \
1830  ret = av_reallocp_array(&(ptr), (new_n), sizeof(*(ptr))); \
1831  if (ret < 0) \
1832  goto end; \
1833  memset( (ptr) + (cur_n), 0, ((new_n) - (cur_n)) * sizeof(*(ptr)) ); \
1834 }
1835 
1836 static inline int show_tags(WriterContext *w, AVDictionary *tags, int section_id)
1837 {
1839  int ret = 0;
1840 
1841  if (!tags)
1842  return 0;
1843  writer_print_section_header(w, section_id);
1844 
1845  while ((tag = av_dict_get(tags, "", tag, AV_DICT_IGNORE_SUFFIX))) {
1846  if ((ret = print_str_validate(tag->key, tag->value)) < 0)
1847  break;
1848  }
1850 
1851  return ret;
1852 }
1853 
1855 {
1856  if (!metadata)
1857  return;
1858  print_int("application version", metadata->application_version);
1859  print_int("num_windows", metadata->num_windows);
1860  for (int n = 1; n < metadata->num_windows; n++) {
1861  const AVHDRPlusColorTransformParams *params = &metadata->params[n];
1862  print_q("window_upper_left_corner_x",
1863  params->window_upper_left_corner_x,'/');
1864  print_q("window_upper_left_corner_y",
1865  params->window_upper_left_corner_y,'/');
1866  print_q("window_lower_right_corner_x",
1867  params->window_lower_right_corner_x,'/');
1868  print_q("window_lower_right_corner_y",
1869  params->window_lower_right_corner_y,'/');
1870  print_q("window_upper_left_corner_x",
1871  params->window_upper_left_corner_x,'/');
1872  print_q("window_upper_left_corner_y",
1873  params->window_upper_left_corner_y,'/');
1874  print_int("center_of_ellipse_x",
1875  params->center_of_ellipse_x ) ;
1876  print_int("center_of_ellipse_y",
1877  params->center_of_ellipse_y );
1878  print_int("rotation_angle",
1879  params->rotation_angle);
1880  print_int("semimajor_axis_internal_ellipse",
1882  print_int("semimajor_axis_external_ellipse",
1884  print_int("semiminor_axis_external_ellipse",
1886  print_int("overlap_process_option",
1887  params->overlap_process_option);
1888  }
1889  print_q("targeted_system_display_maximum_luminance",
1892  print_int("num_rows_targeted_system_display_actual_peak_luminance",
1894  print_int("num_cols_targeted_system_display_actual_peak_luminance",
1896  for (int i = 0; i < metadata->num_rows_targeted_system_display_actual_peak_luminance; i++) {
1897  for (int j = 0; j < metadata->num_cols_targeted_system_display_actual_peak_luminance; j++) {
1898  print_q("targeted_system_display_actual_peak_luminance",
1900  }
1901  }
1902  }
1903  for (int n = 0; n < metadata->num_windows; n++) {
1904  const AVHDRPlusColorTransformParams *params = &metadata->params[n];
1905  for (int i = 0; i < 3; i++) {
1906  print_q("maxscl",params->maxscl[i],'/');
1907  }
1908  print_q("average_maxrgb",
1909  params->average_maxrgb,'/');
1910  print_int("num_distribution_maxrgb_percentiles",
1912  for (int i = 0; i < params->num_distribution_maxrgb_percentiles; i++) {
1913  print_int("distribution_maxrgb_percentage",
1914  params->distribution_maxrgb[i].percentage);
1915  print_q("distribution_maxrgb_percentile",
1916  params->distribution_maxrgb[i].percentile,'/');
1917  }
1918  print_q("fraction_bright_pixels",
1919  params->fraction_bright_pixels,'/');
1920  }
1922  print_int("num_rows_mastering_display_actual_peak_luminance",
1924  print_int("num_cols_mastering_display_actual_peak_luminance",
1926  for (int i = 0; i < metadata->num_rows_mastering_display_actual_peak_luminance; i++) {
1927  for (int j = 0; j < metadata->num_cols_mastering_display_actual_peak_luminance; j++) {
1928  print_q("mastering_display_actual_peak_luminance",
1929  metadata->mastering_display_actual_peak_luminance[i][j],'/');
1930  }
1931  }
1932  }
1933 
1934  for (int n = 0; n < metadata->num_windows; n++) {
1935  const AVHDRPlusColorTransformParams *params = &metadata->params[n];
1936  if (params->tone_mapping_flag) {
1937  print_q("knee_point_x", params->knee_point_x,'/');
1938  print_q("knee_point_y", params->knee_point_y,'/');
1939  print_int("num_bezier_curve_anchors",
1940  params->num_bezier_curve_anchors );
1941  for (int i = 0; i < params->num_bezier_curve_anchors; i++) {
1942  print_q("bezier_curve_anchors",
1943  params->bezier_curve_anchors[i],'/');
1944  }
1945  }
1946  if (params->color_saturation_mapping_flag) {
1947  print_q("color_saturation_weight",
1948  params->color_saturation_weight,'/');
1949  }
1950  }
1951 }
1952 
1954  AVCodecParameters *par,
1955  const AVPacketSideData *side_data,
1956  int nb_side_data,
1957  SectionID id_data_list,
1958  SectionID id_data)
1959 {
1960  int i;
1961 
1962  writer_print_section_header(w, id_data_list);
1963  for (i = 0; i < nb_side_data; i++) {
1964  const AVPacketSideData *sd = &side_data[i];
1965  const char *name = av_packet_side_data_name(sd->type);
1966 
1967  writer_print_section_header(w, id_data);
1968  print_str("side_data_type", name ? name : "unknown");
1969  if (sd->type == AV_PKT_DATA_DISPLAYMATRIX && sd->size >= 9*4) {
1970  writer_print_integers(w, "displaymatrix", sd->data, 9, " %11d", 3, 4, 1);
1971  print_int("rotation", av_display_rotation_get((int32_t *)sd->data));
1972  } else if (sd->type == AV_PKT_DATA_STEREO3D) {
1973  const AVStereo3D *stereo = (AVStereo3D *)sd->data;
1974  print_str("type", av_stereo3d_type_name(stereo->type));
1975  print_int("inverted", !!(stereo->flags & AV_STEREO3D_FLAG_INVERT));
1976  } else if (sd->type == AV_PKT_DATA_SPHERICAL) {
1977  const AVSphericalMapping *spherical = (AVSphericalMapping *)sd->data;
1978  print_str("projection", av_spherical_projection_name(spherical->projection));
1979  if (spherical->projection == AV_SPHERICAL_CUBEMAP) {
1980  print_int("padding", spherical->padding);
1981  } else if (spherical->projection == AV_SPHERICAL_EQUIRECTANGULAR_TILE) {
1982  size_t l, t, r, b;
1983  av_spherical_tile_bounds(spherical, par->width, par->height,
1984  &l, &t, &r, &b);
1985  print_int("bound_left", l);
1986  print_int("bound_top", t);
1987  print_int("bound_right", r);
1988  print_int("bound_bottom", b);
1989  }
1990 
1991  print_int("yaw", (double) spherical->yaw / (1 << 16));
1992  print_int("pitch", (double) spherical->pitch / (1 << 16));
1993  print_int("roll", (double) spherical->roll / (1 << 16));
1994  } else if (sd->type == AV_PKT_DATA_SKIP_SAMPLES && sd->size == 10) {
1995  print_int("skip_samples", AV_RL32(sd->data));
1996  print_int("discard_padding", AV_RL32(sd->data + 4));
1997  print_int("skip_reason", AV_RL8(sd->data + 8));
1998  print_int("discard_reason", AV_RL8(sd->data + 9));
1999  } else if (sd->type == AV_PKT_DATA_MASTERING_DISPLAY_METADATA) {
2001 
2002  if (metadata->has_primaries) {
2003  print_q("red_x", metadata->display_primaries[0][0], '/');
2004  print_q("red_y", metadata->display_primaries[0][1], '/');
2005  print_q("green_x", metadata->display_primaries[1][0], '/');
2006  print_q("green_y", metadata->display_primaries[1][1], '/');
2007  print_q("blue_x", metadata->display_primaries[2][0], '/');
2008  print_q("blue_y", metadata->display_primaries[2][1], '/');
2009 
2010  print_q("white_point_x", metadata->white_point[0], '/');
2011  print_q("white_point_y", metadata->white_point[1], '/');
2012  }
2013 
2014  if (metadata->has_luminance) {
2015  print_q("min_luminance", metadata->min_luminance, '/');
2016  print_q("max_luminance", metadata->max_luminance, '/');
2017  }
2018  } else if (sd->type == AV_PKT_DATA_CONTENT_LIGHT_LEVEL) {
2020  print_int("max_content", metadata->MaxCLL);
2021  print_int("max_average", metadata->MaxFALL);
2022  } else if (sd->type == AV_PKT_DATA_DOVI_CONF) {
2024  print_int("dv_version_major", dovi->dv_version_major);
2025  print_int("dv_version_minor", dovi->dv_version_minor);
2026  print_int("dv_profile", dovi->dv_profile);
2027  print_int("dv_level", dovi->dv_level);
2028  print_int("rpu_present_flag", dovi->rpu_present_flag);
2029  print_int("el_present_flag", dovi->el_present_flag);
2030  print_int("bl_present_flag", dovi->bl_present_flag);
2031  print_int("dv_bl_signal_compatibility_id", dovi->dv_bl_signal_compatibility_id);
2032  } else if (sd->type == AV_PKT_DATA_AUDIO_SERVICE_TYPE) {
2033  enum AVAudioServiceType *t = (enum AVAudioServiceType *)sd->data;
2034  print_int("type", *t);
2035  } else if (sd->type == AV_PKT_DATA_MPEGTS_STREAM_ID) {
2036  print_int("id", *sd->data);
2037  } else if (sd->type == AV_PKT_DATA_CPB_PROPERTIES) {
2038  const AVCPBProperties *prop = (AVCPBProperties *)sd->data;
2039  print_int("max_bitrate", prop->max_bitrate);
2040  print_int("min_bitrate", prop->min_bitrate);
2041  print_int("avg_bitrate", prop->avg_bitrate);
2042  print_int("buffer_size", prop->buffer_size);
2043  print_int("vbv_delay", prop->vbv_delay);
2044  } else if (sd->type == AV_PKT_DATA_WEBVTT_IDENTIFIER ||
2046  if (do_show_data)
2047  writer_print_data(w, "data", sd->data, sd->size);
2048  writer_print_data_hash(w, "data_hash", sd->data, sd->size);
2049  }
2051  }
2053 }
2054 
2056 {
2057  const char *val = av_color_range_name(color_range);
2059  print_str_opt("color_range", "unknown");
2060  } else {
2061  print_str("color_range", val);
2062  }
2063 }
2064 
2065 static void print_color_space(WriterContext *w, enum AVColorSpace color_space)
2066 {
2067  const char *val = av_color_space_name(color_space);
2068  if (!val || color_space == AVCOL_SPC_UNSPECIFIED) {
2069  print_str_opt("color_space", "unknown");
2070  } else {
2071  print_str("color_space", val);
2072  }
2073 }
2074 
2076 {
2079  print_str_opt("color_primaries", "unknown");
2080  } else {
2081  print_str("color_primaries", val);
2082  }
2083 }
2084 
2086 {
2087  const char *val = av_color_transfer_name(color_trc);
2088  if (!val || color_trc == AVCOL_TRC_UNSPECIFIED) {
2089  print_str_opt("color_transfer", "unknown");
2090  } else {
2091  print_str("color_transfer", val);
2092  }
2093 }
2094 
2095 static void print_chroma_location(WriterContext *w, enum AVChromaLocation chroma_location)
2096 {
2097  const char *val = av_chroma_location_name(chroma_location);
2098  if (!val || chroma_location == AVCHROMA_LOC_UNSPECIFIED) {
2099  print_str_opt("chroma_location", "unspecified");
2100  } else {
2101  print_str("chroma_location", val);
2102  }
2103 }
2104 
2105 
2106 static void clear_log(int need_lock)
2107 {
2108  int i;
2109 
2110  if (need_lock)
2111  pthread_mutex_lock(&log_mutex);
2112  for (i=0; i<log_buffer_size; i++) {
2113  av_freep(&log_buffer[i].context_name);
2114  av_freep(&log_buffer[i].parent_name);
2115  av_freep(&log_buffer[i].log_message);
2116  }
2117  log_buffer_size = 0;
2118  if(need_lock)
2119  pthread_mutex_unlock(&log_mutex);
2120 }
2121 
2122 static int show_log(WriterContext *w, int section_ids, int section_id, int log_level)
2123 {
2124  int i;
2125  pthread_mutex_lock(&log_mutex);
2126  if (!log_buffer_size) {
2127  pthread_mutex_unlock(&log_mutex);
2128  return 0;
2129  }
2130  writer_print_section_header(w, section_ids);
2131 
2132  for (i=0; i<log_buffer_size; i++) {
2133  if (log_buffer[i].log_level <= log_level) {
2134  writer_print_section_header(w, section_id);
2135  print_str("context", log_buffer[i].context_name);
2136  print_int("level", log_buffer[i].log_level);
2137  print_int("category", log_buffer[i].category);
2138  if (log_buffer[i].parent_name) {
2139  print_str("parent_context", log_buffer[i].parent_name);
2140  print_int("parent_category", log_buffer[i].parent_category);
2141  } else {
2142  print_str_opt("parent_context", "N/A");
2143  print_str_opt("parent_category", "N/A");
2144  }
2145  print_str("message", log_buffer[i].log_message);
2147  }
2148  }
2149  clear_log(0);
2150  pthread_mutex_unlock(&log_mutex);
2151 
2153 
2154  return 0;
2155 }
2156 
2157 static void show_packet(WriterContext *w, InputFile *ifile, AVPacket *pkt, int packet_idx)
2158 {
2159  char val_str[128];
2160  AVStream *st = ifile->streams[pkt->stream_index].st;
2161  AVBPrint pbuf;
2162  const char *s;
2163 
2165 
2167 
2169  if (s) print_str ("codec_type", s);
2170  else print_str_opt("codec_type", "unknown");
2171  print_int("stream_index", pkt->stream_index);
2172  print_ts ("pts", pkt->pts);
2173  print_time("pts_time", pkt->pts, &st->time_base);
2174  print_ts ("dts", pkt->dts);
2175  print_time("dts_time", pkt->dts, &st->time_base);
2176  print_duration_ts("duration", pkt->duration);
2177  print_duration_time("duration_time", pkt->duration, &st->time_base);
2178  print_val("size", pkt->size, unit_byte_str);
2179  if (pkt->pos != -1) print_fmt ("pos", "%"PRId64, pkt->pos);
2180  else print_str_opt("pos", "N/A");
2181  print_fmt("flags", "%c%c", pkt->flags & AV_PKT_FLAG_KEY ? 'K' : '_',
2182  pkt->flags & AV_PKT_FLAG_DISCARD ? 'D' : '_');
2183 
2184  if (pkt->side_data_elems) {
2185  size_t size;
2186  const uint8_t *side_metadata;
2187 
2189  if (side_metadata && size && do_show_packet_tags) {
2190  AVDictionary *dict = NULL;
2191  if (av_packet_unpack_dictionary(side_metadata, size, &dict) >= 0)
2193  av_dict_free(&dict);
2194  }
2195 
2199  }
2200 
2201  if (do_show_data)
2202  writer_print_data(w, "data", pkt->data, pkt->size);
2203  writer_print_data_hash(w, "data_hash", pkt->data, pkt->size);
2205 
2206  av_bprint_finalize(&pbuf, NULL);
2207  fflush(stdout);
2208 }
2209 
2212 {
2213  AVBPrint pbuf;
2214 
2216 
2218 
2219  print_str ("media_type", "subtitle");
2220  print_ts ("pts", sub->pts);
2221  print_time("pts_time", sub->pts, &AV_TIME_BASE_Q);
2222  print_int ("format", sub->format);
2223  print_int ("start_display_time", sub->start_display_time);
2224  print_int ("end_display_time", sub->end_display_time);
2225  print_int ("num_rects", sub->num_rects);
2226 
2228 
2229  av_bprint_finalize(&pbuf, NULL);
2230  fflush(stdout);
2231 }
2232 
2235 {
2236  AVBPrint pbuf;
2237  char val_str[128];
2238  const char *s;
2239  int i;
2240 
2242 
2244 
2246  if (s) print_str ("media_type", s);
2247  else print_str_opt("media_type", "unknown");
2248  print_int("stream_index", stream->index);
2249  print_int("key_frame", frame->key_frame);
2250  print_ts ("pkt_pts", frame->pts);
2251  print_time("pkt_pts_time", frame->pts, &stream->time_base);
2252  print_ts ("pkt_dts", frame->pkt_dts);
2253  print_time("pkt_dts_time", frame->pkt_dts, &stream->time_base);
2254  print_ts ("best_effort_timestamp", frame->best_effort_timestamp);
2255  print_time("best_effort_timestamp_time", frame->best_effort_timestamp, &stream->time_base);
2256  print_duration_ts ("pkt_duration", frame->pkt_duration);
2257  print_duration_time("pkt_duration_time", frame->pkt_duration, &stream->time_base);
2258  if (frame->pkt_pos != -1) print_fmt ("pkt_pos", "%"PRId64, frame->pkt_pos);
2259  else print_str_opt("pkt_pos", "N/A");
2260  if (frame->pkt_size != -1) print_val ("pkt_size", frame->pkt_size, unit_byte_str);
2261  else print_str_opt("pkt_size", "N/A");
2262 
2263  switch (stream->codecpar->codec_type) {
2264  AVRational sar;
2265 
2266  case AVMEDIA_TYPE_VIDEO:
2267  print_int("width", frame->width);
2268  print_int("height", frame->height);
2269  s = av_get_pix_fmt_name(frame->format);
2270  if (s) print_str ("pix_fmt", s);
2271  else print_str_opt("pix_fmt", "unknown");
2272  sar = av_guess_sample_aspect_ratio(fmt_ctx, stream, frame);
2273  if (sar.num) {
2274  print_q("sample_aspect_ratio", sar, ':');
2275  } else {
2276  print_str_opt("sample_aspect_ratio", "N/A");
2277  }
2278  print_fmt("pict_type", "%c", av_get_picture_type_char(frame->pict_type));
2279  print_int("coded_picture_number", frame->coded_picture_number);
2280  print_int("display_picture_number", frame->display_picture_number);
2281  print_int("interlaced_frame", frame->interlaced_frame);
2282  print_int("top_field_first", frame->top_field_first);
2283  print_int("repeat_pict", frame->repeat_pict);
2284 
2285  print_color_range(w, frame->color_range);
2286  print_color_space(w, frame->colorspace);
2287  print_primaries(w, frame->color_primaries);
2288  print_color_trc(w, frame->color_trc);
2289  print_chroma_location(w, frame->chroma_location);
2290  break;
2291 
2292  case AVMEDIA_TYPE_AUDIO:
2293  s = av_get_sample_fmt_name(frame->format);
2294  if (s) print_str ("sample_fmt", s);
2295  else print_str_opt("sample_fmt", "unknown");
2296  print_int("nb_samples", frame->nb_samples);
2297  print_int("channels", frame->channels);
2298  if (frame->channel_layout) {
2299  av_bprint_clear(&pbuf);
2300  av_bprint_channel_layout(&pbuf, frame->channels,
2301  frame->channel_layout);
2302  print_str ("channel_layout", pbuf.str);
2303  } else
2304  print_str_opt("channel_layout", "unknown");
2305  break;
2306  }
2307  if (do_show_frame_tags)
2308  show_tags(w, frame->metadata, SECTION_ID_FRAME_TAGS);
2309  if (do_show_log)
2311  if (frame->nb_side_data) {
2313  for (i = 0; i < frame->nb_side_data; i++) {
2314  AVFrameSideData *sd = frame->side_data[i];
2315  const char *name;
2316 
2319  print_str("side_data_type", name ? name : "unknown");
2320  if (sd->type == AV_FRAME_DATA_DISPLAYMATRIX && sd->size >= 9*4) {
2321  writer_print_integers(w, "displaymatrix", sd->data, 9, " %11d", 3, 4, 1);
2322  print_int("rotation", av_display_rotation_get((int32_t *)sd->data));
2323  } else if (sd->type == AV_FRAME_DATA_GOP_TIMECODE && sd->size >= 8) {
2324  char tcbuf[AV_TIMECODE_STR_SIZE];
2325  av_timecode_make_mpeg_tc_string(tcbuf, *(int64_t *)(sd->data));
2326  print_str("timecode", tcbuf);
2327  } else if (sd->type == AV_FRAME_DATA_S12M_TIMECODE && sd->size == 16) {
2328  uint32_t *tc = (uint32_t*)sd->data;
2329  int m = FFMIN(tc[0],3);
2331  for (int j = 1; j <= m ; j++) {
2332  char tcbuf[AV_TIMECODE_STR_SIZE];
2333  av_timecode_make_smpte_tc_string2(tcbuf, stream->avg_frame_rate, tc[j], 0, 0);
2335  print_str("value", tcbuf);
2337  }
2339  } else if (sd->type == AV_FRAME_DATA_MASTERING_DISPLAY_METADATA) {
2341 
2342  if (metadata->has_primaries) {
2343  print_q("red_x", metadata->display_primaries[0][0], '/');
2344  print_q("red_y", metadata->display_primaries[0][1], '/');
2345  print_q("green_x", metadata->display_primaries[1][0], '/');
2346  print_q("green_y", metadata->display_primaries[1][1], '/');
2347  print_q("blue_x", metadata->display_primaries[2][0], '/');
2348  print_q("blue_y", metadata->display_primaries[2][1], '/');
2349 
2350  print_q("white_point_x", metadata->white_point[0], '/');
2351  print_q("white_point_y", metadata->white_point[1], '/');
2352  }
2353 
2354  if (metadata->has_luminance) {
2355  print_q("min_luminance", metadata->min_luminance, '/');
2356  print_q("max_luminance", metadata->max_luminance, '/');
2357  }
2358  } else if (sd->type == AV_FRAME_DATA_DYNAMIC_HDR_PLUS) {
2359  AVDynamicHDRPlus *metadata = (AVDynamicHDRPlus *)sd->data;
2360  print_dynamic_hdr10_plus(w, metadata);
2361  } else if (sd->type == AV_FRAME_DATA_CONTENT_LIGHT_LEVEL) {
2363  print_int("max_content", metadata->MaxCLL);
2364  print_int("max_average", metadata->MaxFALL);
2365  } else if (sd->type == AV_FRAME_DATA_ICC_PROFILE) {
2367  if (tag)
2368  print_str(tag->key, tag->value);
2369  print_int("size", sd->size);
2370  }
2372  }
2374  }
2375 
2377 
2378  av_bprint_finalize(&pbuf, NULL);
2379  fflush(stdout);
2380 }
2381 
2383  InputFile *ifile,
2385  int *packet_new)
2386 {
2387  AVFormatContext *fmt_ctx = ifile->fmt_ctx;
2388  AVCodecContext *dec_ctx = ifile->streams[pkt->stream_index].dec_ctx;
2389  AVCodecParameters *par = ifile->streams[pkt->stream_index].st->codecpar;
2390  AVSubtitle sub;
2391  int ret = 0, got_frame = 0;
2392 
2393  clear_log(1);
2394  if (dec_ctx && dec_ctx->codec) {
2395  switch (par->codec_type) {
2396  case AVMEDIA_TYPE_VIDEO:
2397  case AVMEDIA_TYPE_AUDIO:
2398  if (*packet_new) {
2400  if (ret == AVERROR(EAGAIN)) {
2401  ret = 0;
2402  } else if (ret >= 0 || ret == AVERROR_EOF) {
2403  ret = 0;
2404  *packet_new = 0;
2405  }
2406  }
2407  if (ret >= 0) {
2409  if (ret >= 0) {
2410  got_frame = 1;
2411  } else if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) {
2412  ret = 0;
2413  }
2414  }
2415  break;
2416 
2417  case AVMEDIA_TYPE_SUBTITLE:
2418  if (*packet_new)
2419  ret = avcodec_decode_subtitle2(dec_ctx, &sub, &got_frame, pkt);
2420  *packet_new = 0;
2421  break;
2422  default:
2423  *packet_new = 0;
2424  }
2425  } else {
2426  *packet_new = 0;
2427  }
2428 
2429  if (ret < 0)
2430  return ret;
2431  if (got_frame) {
2432  int is_sub = (par->codec_type == AVMEDIA_TYPE_SUBTITLE);
2434  if (do_show_frames)
2435  if (is_sub)
2436  show_subtitle(w, &sub, ifile->streams[pkt->stream_index].st, fmt_ctx);
2437  else
2438  show_frame(w, frame, ifile->streams[pkt->stream_index].st, fmt_ctx);
2439  if (is_sub)
2440  avsubtitle_free(&sub);
2441  }
2442  return got_frame || *packet_new;
2443 }
2444 
2445 static void log_read_interval(const ReadInterval *interval, void *log_ctx, int log_level)
2446 {
2447  av_log(log_ctx, log_level, "id:%d", interval->id);
2448 
2449  if (interval->has_start) {
2450  av_log(log_ctx, log_level, " start:%s%s", interval->start_is_offset ? "+" : "",
2451  av_ts2timestr(interval->start, &AV_TIME_BASE_Q));
2452  } else {
2453  av_log(log_ctx, log_level, " start:N/A");
2454  }
2455 
2456  if (interval->has_end) {
2457  av_log(log_ctx, log_level, " end:%s", interval->end_is_offset ? "+" : "");
2458  if (interval->duration_frames)
2459  av_log(log_ctx, log_level, "#%"PRId64, interval->end);
2460  else
2461  av_log(log_ctx, log_level, "%s", av_ts2timestr(interval->end, &AV_TIME_BASE_Q));
2462  } else {
2463  av_log(log_ctx, log_level, " end:N/A");
2464  }
2465 
2466  av_log(log_ctx, log_level, "\n");
2467 }
2468 
2470  const ReadInterval *interval, int64_t *cur_ts)
2471 {
2472  AVFormatContext *fmt_ctx = ifile->fmt_ctx;
2473  AVPacket *pkt = NULL;
2474  AVFrame *frame = NULL;
2475  int ret = 0, i = 0, frame_count = 0;
2476  int64_t start = -INT64_MAX, end = interval->end;
2477  int has_start = 0, has_end = interval->has_end && !interval->end_is_offset;
2478 
2479  av_log(NULL, AV_LOG_VERBOSE, "Processing read interval ");
2481 
2482  if (interval->has_start) {
2483  int64_t target;
2484  if (interval->start_is_offset) {
2485  if (*cur_ts == AV_NOPTS_VALUE) {
2487  "Could not seek to relative position since current "
2488  "timestamp is not defined\n");
2489  ret = AVERROR(EINVAL);
2490  goto end;
2491  }
2492  target = *cur_ts + interval->start;
2493  } else {
2494  target = interval->start;
2495  }
2496 
2497  av_log(NULL, AV_LOG_VERBOSE, "Seeking to read interval start point %s\n",
2498  av_ts2timestr(target, &AV_TIME_BASE_Q));
2499  if ((ret = avformat_seek_file(fmt_ctx, -1, -INT64_MAX, target, INT64_MAX, 0)) < 0) {
2500  av_log(NULL, AV_LOG_ERROR, "Could not seek to position %"PRId64": %s\n",
2501  interval->start, av_err2str(ret));
2502  goto end;
2503  }
2504  }
2505 
2506  frame = av_frame_alloc();
2507  if (!frame) {
2508  ret = AVERROR(ENOMEM);
2509  goto end;
2510  }
2511  pkt = av_packet_alloc();
2512  if (!pkt) {
2513  ret = AVERROR(ENOMEM);
2514  goto end;
2515  }
2516  while (!av_read_frame(fmt_ctx, pkt)) {
2517  if (fmt_ctx->nb_streams > nb_streams) {
2522  }
2524  AVRational tb = ifile->streams[pkt->stream_index].st->time_base;
2525 
2526  if (pkt->pts != AV_NOPTS_VALUE)
2527  *cur_ts = av_rescale_q(pkt->pts, tb, AV_TIME_BASE_Q);
2528 
2529  if (!has_start && *cur_ts != AV_NOPTS_VALUE) {
2530  start = *cur_ts;
2531  has_start = 1;
2532  }
2533 
2534  if (has_start && !has_end && interval->end_is_offset) {
2535  end = start + interval->end;
2536  has_end = 1;
2537  }
2538 
2539  if (interval->end_is_offset && interval->duration_frames) {
2540  if (frame_count >= interval->end)
2541  break;
2542  } else if (has_end && *cur_ts != AV_NOPTS_VALUE && *cur_ts >= end) {
2543  break;
2544  }
2545 
2546  frame_count++;
2547  if (do_read_packets) {
2548  if (do_show_packets)
2549  show_packet(w, ifile, pkt, i++);
2551  }
2552  if (do_read_frames) {
2553  int packet_new = 1;
2554  while (process_frame(w, ifile, frame, pkt, &packet_new) > 0);
2555  }
2556  }
2558  }
2560  //Flush remaining frames that are cached in the decoder
2561  for (i = 0; i < fmt_ctx->nb_streams; i++) {
2562  pkt->stream_index = i;
2563  if (do_read_frames)
2564  while (process_frame(w, ifile, frame, pkt, &(int){1}) > 0);
2565  }
2566 
2567 end:
2568  av_frame_free(&frame);
2569  av_packet_free(&pkt);
2570  if (ret < 0) {
2571  av_log(NULL, AV_LOG_ERROR, "Could not read packets in interval ");
2572  log_read_interval(interval, NULL, AV_LOG_ERROR);
2573  }
2574  return ret;
2575 }
2576 
2578 {
2579  AVFormatContext *fmt_ctx = ifile->fmt_ctx;
2580  int i, ret = 0;
2581  int64_t cur_ts = fmt_ctx->start_time;
2582 
2583  if (read_intervals_nb == 0) {
2584  ReadInterval interval = (ReadInterval) { .has_start = 0, .has_end = 0 };
2585  ret = read_interval_packets(w, ifile, &interval, &cur_ts);
2586  } else {
2587  for (i = 0; i < read_intervals_nb; i++) {
2588  ret = read_interval_packets(w, ifile, &read_intervals[i], &cur_ts);
2589  if (ret < 0)
2590  break;
2591  }
2592  }
2593 
2594  return ret;
2595 }
2596 
2597 static int show_stream(WriterContext *w, AVFormatContext *fmt_ctx, int stream_idx, InputStream *ist, int in_program)
2598 {
2599  AVStream *stream = ist->st;
2600  AVCodecParameters *par;
2602  char val_str[128];
2603  const char *s;
2604  AVRational sar, dar;
2605  AVBPrint pbuf;
2606  const AVCodecDescriptor *cd;
2607  int ret = 0;
2608  const char *profile = NULL;
2609 
2611 
2613 
2614  print_int("index", stream->index);
2615 
2616  par = stream->codecpar;
2617  dec_ctx = ist->dec_ctx;
2618  if (cd = avcodec_descriptor_get(par->codec_id)) {
2619  print_str("codec_name", cd->name);
2620  if (!do_bitexact) {
2621  print_str("codec_long_name",
2622  cd->long_name ? cd->long_name : "unknown");
2623  }
2624  } else {
2625  print_str_opt("codec_name", "unknown");
2626  if (!do_bitexact) {
2627  print_str_opt("codec_long_name", "unknown");
2628  }
2629  }
2630 
2631  if (!do_bitexact && (profile = avcodec_profile_name(par->codec_id, par->profile)))
2632  print_str("profile", profile);
2633  else {
2634  if (par->profile != FF_PROFILE_UNKNOWN) {
2635  char profile_num[12];
2636  snprintf(profile_num, sizeof(profile_num), "%d", par->profile);
2637  print_str("profile", profile_num);
2638  } else
2639  print_str_opt("profile", "unknown");
2640  }
2641 
2643  if (s) print_str ("codec_type", s);
2644  else print_str_opt("codec_type", "unknown");
2645 
2646  /* print AVI/FourCC tag */
2647  print_str("codec_tag_string", av_fourcc2str(par->codec_tag));
2648  print_fmt("codec_tag", "0x%04"PRIx32, par->codec_tag);
2649 
2650  switch (par->codec_type) {
2651  case AVMEDIA_TYPE_VIDEO:
2652  print_int("width", par->width);
2653  print_int("height", par->height);
2654  if (dec_ctx) {
2655  print_int("coded_width", dec_ctx->coded_width);
2656  print_int("coded_height", dec_ctx->coded_height);
2658  }
2659  print_int("has_b_frames", par->video_delay);
2660  sar = av_guess_sample_aspect_ratio(fmt_ctx, stream, NULL);
2661  if (sar.num) {
2662  print_q("sample_aspect_ratio", sar, ':');
2663  av_reduce(&dar.num, &dar.den,
2664  par->width * sar.num,
2665  par->height * sar.den,
2666  1024*1024);
2667  print_q("display_aspect_ratio", dar, ':');
2668  } else {
2669  print_str_opt("sample_aspect_ratio", "N/A");
2670  print_str_opt("display_aspect_ratio", "N/A");
2671  }
2672  s = av_get_pix_fmt_name(par->format);
2673  if (s) print_str ("pix_fmt", s);
2674  else print_str_opt("pix_fmt", "unknown");
2675  print_int("level", par->level);
2676 
2679  print_color_trc(w, par->color_trc);
2682 
2683  if (par->field_order == AV_FIELD_PROGRESSIVE)
2684  print_str("field_order", "progressive");
2685  else if (par->field_order == AV_FIELD_TT)
2686  print_str("field_order", "tt");
2687  else if (par->field_order == AV_FIELD_BB)
2688  print_str("field_order", "bb");
2689  else if (par->field_order == AV_FIELD_TB)
2690  print_str("field_order", "tb");
2691  else if (par->field_order == AV_FIELD_BT)
2692  print_str("field_order", "bt");
2693  else
2694  print_str_opt("field_order", "unknown");
2695 
2696  if (dec_ctx)
2697  print_int("refs", dec_ctx->refs);
2698  break;
2699 
2700  case AVMEDIA_TYPE_AUDIO:
2702  if (s) print_str ("sample_fmt", s);
2703  else print_str_opt("sample_fmt", "unknown");
2704  print_val("sample_rate", par->sample_rate, unit_hertz_str);
2705  print_int("channels", par->channels);
2706 
2707  if (par->channel_layout) {
2708  av_bprint_clear(&pbuf);
2710  print_str ("channel_layout", pbuf.str);
2711  } else {
2712  print_str_opt("channel_layout", "unknown");
2713  }
2714 
2715  print_int("bits_per_sample", av_get_bits_per_sample(par->codec_id));
2716  break;
2717 
2718  case AVMEDIA_TYPE_SUBTITLE:
2719  if (par->width)
2720  print_int("width", par->width);
2721  else
2722  print_str_opt("width", "N/A");
2723  if (par->height)
2724  print_int("height", par->height);
2725  else
2726  print_str_opt("height", "N/A");
2727  break;
2728  }
2729 
2731  const AVOption *opt = NULL;
2732  while (opt = av_opt_next(dec_ctx->priv_data,opt)) {
2733  uint8_t *str;
2734  if (!(opt->flags & AV_OPT_FLAG_EXPORT)) continue;
2735  if (av_opt_get(dec_ctx->priv_data, opt->name, 0, &str) >= 0) {
2736  print_str(opt->name, str);
2737  av_free(str);
2738  }
2739  }
2740  }
2741 
2742  if (fmt_ctx->iformat->flags & AVFMT_SHOW_IDS) print_fmt ("id", "0x%x", stream->id);
2743  else print_str_opt("id", "N/A");
2744  print_q("r_frame_rate", stream->r_frame_rate, '/');
2745  print_q("avg_frame_rate", stream->avg_frame_rate, '/');
2746  print_q("time_base", stream->time_base, '/');
2747  print_ts ("start_pts", stream->start_time);
2748  print_time("start_time", stream->start_time, &stream->time_base);
2749  print_ts ("duration_ts", stream->duration);
2750  print_time("duration", stream->duration, &stream->time_base);
2751  if (par->bit_rate > 0) print_val ("bit_rate", par->bit_rate, unit_bit_per_second_str);
2752  else print_str_opt("bit_rate", "N/A");
2753  if (dec_ctx && dec_ctx->rc_max_rate > 0)
2755  else
2756  print_str_opt("max_bit_rate", "N/A");
2757  if (dec_ctx && dec_ctx->bits_per_raw_sample > 0) print_fmt("bits_per_raw_sample", "%d", dec_ctx->bits_per_raw_sample);
2758  else print_str_opt("bits_per_raw_sample", "N/A");
2759  if (stream->nb_frames) print_fmt ("nb_frames", "%"PRId64, stream->nb_frames);
2760  else print_str_opt("nb_frames", "N/A");
2761  if (nb_streams_frames[stream_idx]) print_fmt ("nb_read_frames", "%"PRIu64, nb_streams_frames[stream_idx]);
2762  else print_str_opt("nb_read_frames", "N/A");
2763  if (nb_streams_packets[stream_idx]) print_fmt ("nb_read_packets", "%"PRIu64, nb_streams_packets[stream_idx]);
2764  else print_str_opt("nb_read_packets", "N/A");
2765  if (do_show_data)
2766  writer_print_data(w, "extradata", par->extradata,
2767  par->extradata_size);
2768 
2769  if (par->extradata_size > 0) {
2770  writer_print_data_hash(w, "extradata_hash", par->extradata,
2771  par->extradata_size);
2772  }
2773 
2774  /* Print disposition information */
2775 #define PRINT_DISPOSITION(flagname, name) do { \
2776  print_int(name, !!(stream->disposition & AV_DISPOSITION_##flagname)); \
2777  } while (0)
2778 
2781  PRINT_DISPOSITION(DEFAULT, "default");
2782  PRINT_DISPOSITION(DUB, "dub");
2783  PRINT_DISPOSITION(ORIGINAL, "original");
2784  PRINT_DISPOSITION(COMMENT, "comment");
2785  PRINT_DISPOSITION(LYRICS, "lyrics");
2786  PRINT_DISPOSITION(KARAOKE, "karaoke");
2787  PRINT_DISPOSITION(FORCED, "forced");
2788  PRINT_DISPOSITION(HEARING_IMPAIRED, "hearing_impaired");
2789  PRINT_DISPOSITION(VISUAL_IMPAIRED, "visual_impaired");
2790  PRINT_DISPOSITION(CLEAN_EFFECTS, "clean_effects");
2791  PRINT_DISPOSITION(ATTACHED_PIC, "attached_pic");
2792  PRINT_DISPOSITION(TIMED_THUMBNAILS, "timed_thumbnails");
2793  PRINT_DISPOSITION(CAPTIONS, "captions");
2794  PRINT_DISPOSITION(DESCRIPTIONS, "descriptions");
2795  PRINT_DISPOSITION(METADATA, "metadata");
2796  PRINT_DISPOSITION(DEPENDENT, "dependent");
2797  PRINT_DISPOSITION(STILL_IMAGE, "still_image");
2799  }
2800 
2801  if (do_show_stream_tags)
2803 
2804  if (stream->nb_side_data) {
2805  print_pkt_side_data(w, stream->codecpar, stream->side_data, stream->nb_side_data,
2808  }
2809 
2811  av_bprint_finalize(&pbuf, NULL);
2812  fflush(stdout);
2813 
2814  return ret;
2815 }
2816 
2818 {
2819  AVFormatContext *fmt_ctx = ifile->fmt_ctx;
2820  int i, ret = 0;
2821 
2823  for (i = 0; i < ifile->nb_streams; i++)
2824  if (selected_streams[i]) {
2825  ret = show_stream(w, fmt_ctx, i, &ifile->streams[i], 0);
2826  if (ret < 0)
2827  break;
2828  }
2830 
2831  return ret;
2832 }
2833 
2835 {
2836  AVFormatContext *fmt_ctx = ifile->fmt_ctx;
2837  int i, ret = 0;
2838 
2840  print_int("program_id", program->id);
2841  print_int("program_num", program->program_num);
2842  print_int("nb_streams", program->nb_stream_indexes);
2843  print_int("pmt_pid", program->pmt_pid);
2844  print_int("pcr_pid", program->pcr_pid);
2845  print_ts("start_pts", program->start_time);
2846  print_time("start_time", program->start_time, &AV_TIME_BASE_Q);
2847  print_ts("end_pts", program->end_time);
2848  print_time("end_time", program->end_time, &AV_TIME_BASE_Q);
2851  if (ret < 0)
2852  goto end;
2853 
2855  for (i = 0; i < program->nb_stream_indexes; i++) {
2856  if (selected_streams[program->stream_index[i]]) {
2857  ret = show_stream(w, fmt_ctx, program->stream_index[i], &ifile->streams[program->stream_index[i]], 1);
2858  if (ret < 0)
2859  break;
2860  }
2861  }
2863 
2864 end:
2866  return ret;
2867 }
2868 
2870 {
2871  AVFormatContext *fmt_ctx = ifile->fmt_ctx;
2872  int i, ret = 0;
2873 
2875  for (i = 0; i < fmt_ctx->nb_programs; i++) {
2877  if (!program)
2878  continue;
2880  if (ret < 0)
2881  break;
2882  }
2884  return ret;
2885 }
2886 
2888 {
2889  AVFormatContext *fmt_ctx = ifile->fmt_ctx;
2890  int i, ret = 0;
2891 
2893  for (i = 0; i < fmt_ctx->nb_chapters; i++) {
2894  AVChapter *chapter = fmt_ctx->chapters[i];
2895 
2897  print_int("id", chapter->id);
2898  print_q ("time_base", chapter->time_base, '/');
2899  print_int("start", chapter->start);
2900  print_time("start_time", chapter->start, &chapter->time_base);
2901  print_int("end", chapter->end);
2902  print_time("end_time", chapter->end, &chapter->time_base);
2906  }
2908 
2909  return ret;
2910 }
2911 
2913 {
2914  AVFormatContext *fmt_ctx = ifile->fmt_ctx;
2915  char val_str[128];
2916  int64_t size = fmt_ctx->pb ? avio_size(fmt_ctx->pb) : -1;
2917  int ret = 0;
2918 
2920  print_str_validate("filename", fmt_ctx->url);
2921  print_int("nb_streams", fmt_ctx->nb_streams);
2922  print_int("nb_programs", fmt_ctx->nb_programs);
2923  print_str("format_name", fmt_ctx->iformat->name);
2924  if (!do_bitexact) {
2925  if (fmt_ctx->iformat->long_name) print_str ("format_long_name", fmt_ctx->iformat->long_name);
2926  else print_str_opt("format_long_name", "unknown");
2927  }
2928  print_time("start_time", fmt_ctx->start_time, &AV_TIME_BASE_Q);
2929  print_time("duration", fmt_ctx->duration, &AV_TIME_BASE_Q);
2930  if (size >= 0) print_val ("size", size, unit_byte_str);
2931  else print_str_opt("size", "N/A");
2933  else print_str_opt("bit_rate", "N/A");
2934  print_int("probe_score", fmt_ctx->probe_score);
2935  if (do_show_format_tags)
2937 
2939  fflush(stdout);
2940  return ret;
2941 }
2942 
2943 static void show_error(WriterContext *w, int err)
2944 {
2945  char errbuf[128];
2946  const char *errbuf_ptr = errbuf;
2947 
2948  if (av_strerror(err, errbuf, sizeof(errbuf)) < 0)
2949  errbuf_ptr = strerror(AVUNERROR(err));
2950 
2952  print_int("code", err);
2953  print_str("string", errbuf_ptr);
2955 }
2956 
2957 static int open_input_file(InputFile *ifile, const char *filename,
2958  const char *print_filename)
2959 {
2960  int err, i;
2962  AVDictionaryEntry *t = NULL;
2963  int scan_all_pmts_set = 0;
2964 
2966  if (!fmt_ctx) {
2967  print_error(filename, AVERROR(ENOMEM));
2968  exit_program(1);
2969  }
2970 
2971  if (!av_dict_get(format_opts, "scan_all_pmts", NULL, AV_DICT_MATCH_CASE)) {
2972  av_dict_set(&format_opts, "scan_all_pmts", "1", AV_DICT_DONT_OVERWRITE);
2973  scan_all_pmts_set = 1;
2974  }
2975  if ((err = avformat_open_input(&fmt_ctx, filename,
2976  iformat, &format_opts)) < 0) {
2977  print_error(filename, err);
2978  return err;
2979  }
2980  if (print_filename) {
2981  av_freep(&fmt_ctx->url);
2982  fmt_ctx->url = av_strdup(print_filename);
2983  }
2984  ifile->fmt_ctx = fmt_ctx;
2985  if (scan_all_pmts_set)
2986  av_dict_set(&format_opts, "scan_all_pmts", NULL, AV_DICT_MATCH_CASE);
2987  while ((t = av_dict_get(format_opts, "", t, AV_DICT_IGNORE_SUFFIX)))
2988  av_log(NULL, AV_LOG_WARNING, "Option %s skipped - not known to demuxer.\n", t->key);
2989 
2990  if (find_stream_info) {
2992  int orig_nb_streams = fmt_ctx->nb_streams;
2993 
2995 
2996  for (i = 0; i < orig_nb_streams; i++)
2997  av_dict_free(&opts[i]);
2998  av_freep(&opts);
2999 
3000  if (err < 0) {
3001  print_error(filename, err);
3002  return err;
3003  }
3004  }
3005 
3006  av_dump_format(fmt_ctx, 0, filename, 0);
3007 
3009  sizeof(*ifile->streams));
3010  if (!ifile->streams)
3011  exit(1);
3012  ifile->nb_streams = fmt_ctx->nb_streams;
3013 
3014  /* bind a decoder to each input stream */
3015  for (i = 0; i < fmt_ctx->nb_streams; i++) {
3016  InputStream *ist = &ifile->streams[i];
3017  AVStream *stream = fmt_ctx->streams[i];
3018  const AVCodec *codec;
3019 
3020  ist->st = stream;
3021 
3022  if (stream->codecpar->codec_id == AV_CODEC_ID_PROBE) {
3024  "Failed to probe codec for input stream %d\n",
3025  stream->index);
3026  continue;
3027  }
3028 
3029  codec = avcodec_find_decoder(stream->codecpar->codec_id);
3030  if (!codec) {
3032  "Unsupported codec with id %d for input stream %d\n",
3033  stream->codecpar->codec_id, stream->index);
3034  continue;
3035  }
3036  {
3038  fmt_ctx, stream, codec);
3039 
3040  ist->dec_ctx = avcodec_alloc_context3(codec);
3041  if (!ist->dec_ctx)
3042  exit(1);
3043 
3044  err = avcodec_parameters_to_context(ist->dec_ctx, stream->codecpar);
3045  if (err < 0)
3046  exit(1);
3047 
3048  if (do_show_log) {
3049  // For loging it is needed to disable at least frame threads as otherwise
3050  // the log information would need to be reordered and matches up to contexts and frames
3051  // That is in fact possible but not trivial
3052  av_dict_set(&codec_opts, "threads", "1", 0);
3053  }
3054 
3055  ist->dec_ctx->pkt_timebase = stream->time_base;
3056 
3057  if (avcodec_open2(ist->dec_ctx, codec, &opts) < 0) {
3058  av_log(NULL, AV_LOG_WARNING, "Could not open codec for input stream %d\n",
3059  stream->index);
3060  exit(1);
3061  }
3062 
3063  if ((t = av_dict_get(opts, "", NULL, AV_DICT_IGNORE_SUFFIX))) {
3064  av_log(NULL, AV_LOG_ERROR, "Option %s for input stream %d not found\n",
3065  t->key, stream->index);
3066  return AVERROR_OPTION_NOT_FOUND;
3067  }
3068  }
3069  }
3070 
3071  ifile->fmt_ctx = fmt_ctx;
3072  return 0;
3073 }
3074 
3076 {
3077  int i;
3078 
3079  /* close decoder for each stream */
3080  for (i = 0; i < ifile->nb_streams; i++)
3081  avcodec_free_context(&ifile->streams[i].dec_ctx);
3082 
3083  av_freep(&ifile->streams);
3084  ifile->nb_streams = 0;
3085 
3086  avformat_close_input(&ifile->fmt_ctx);
3087 }
3088 
3089 static int probe_file(WriterContext *wctx, const char *filename,
3090  const char *print_filename)
3091 {
3092  InputFile ifile = { 0 };
3093  int ret, i;
3094  int section_id;
3095 
3098 
3099  ret = open_input_file(&ifile, filename, print_filename);
3100  if (ret < 0)
3101  goto end;
3102 
3103 #define CHECK_END if (ret < 0) goto end
3104 
3105  nb_streams = ifile.fmt_ctx->nb_streams;
3106  REALLOCZ_ARRAY_STREAM(nb_streams_frames,0,ifile.fmt_ctx->nb_streams);
3107  REALLOCZ_ARRAY_STREAM(nb_streams_packets,0,ifile.fmt_ctx->nb_streams);
3108  REALLOCZ_ARRAY_STREAM(selected_streams,0,ifile.fmt_ctx->nb_streams);
3109 
3110  for (i = 0; i < ifile.fmt_ctx->nb_streams; i++) {
3111  if (stream_specifier) {
3113  ifile.fmt_ctx->streams[i],
3115  CHECK_END;
3116  else
3117  selected_streams[i] = ret;
3118  ret = 0;
3119  } else {
3120  selected_streams[i] = 1;
3121  }
3122  if (!selected_streams[i])
3123  ifile.fmt_ctx->streams[i]->discard = AVDISCARD_ALL;
3124  }
3125 
3129  section_id = SECTION_ID_PACKETS_AND_FRAMES;
3130  else if (do_show_packets && !do_show_frames)
3131  section_id = SECTION_ID_PACKETS;
3132  else // (!do_show_packets && do_show_frames)
3133  section_id = SECTION_ID_FRAMES;
3135  writer_print_section_header(wctx, section_id);
3136  ret = read_packets(wctx, &ifile);
3139  CHECK_END;
3140  }
3141 
3142  if (do_show_programs) {
3143  ret = show_programs(wctx, &ifile);
3144  CHECK_END;
3145  }
3146 
3147  if (do_show_streams) {
3148  ret = show_streams(wctx, &ifile);
3149  CHECK_END;
3150  }
3151  if (do_show_chapters) {
3152  ret = show_chapters(wctx, &ifile);
3153  CHECK_END;
3154  }
3155  if (do_show_format) {
3156  ret = show_format(wctx, &ifile);
3157  CHECK_END;
3158  }
3159 
3160 end:
3161  if (ifile.fmt_ctx)
3166 
3167  return ret;
3168 }
3169 
3170 static void show_usage(void)
3171 {
3172  av_log(NULL, AV_LOG_INFO, "Simple multimedia streams analyzer\n");
3173  av_log(NULL, AV_LOG_INFO, "usage: %s [OPTIONS] [INPUT_FILE]\n", program_name);
3174  av_log(NULL, AV_LOG_INFO, "\n");
3175 }
3176 
3178 {
3179  AVBPrint pbuf;
3181 
3183  print_str("version", FFMPEG_VERSION);
3184  print_fmt("copyright", "Copyright (c) %d-%d the FFmpeg developers",
3185  program_birth_year, CONFIG_THIS_YEAR);
3186  print_str("compiler_ident", CC_IDENT);
3187  print_str("configuration", FFMPEG_CONFIGURATION);
3189 
3190  av_bprint_finalize(&pbuf, NULL);
3191 }
3192 
3193 #define SHOW_LIB_VERSION(libname, LIBNAME) \
3194  do { \
3195  if (CONFIG_##LIBNAME) { \
3196  unsigned int version = libname##_version(); \
3197  writer_print_section_header(w, SECTION_ID_LIBRARY_VERSION); \
3198  print_str("name", "lib" #libname); \
3199  print_int("major", LIB##LIBNAME##_VERSION_MAJOR); \
3200  print_int("minor", LIB##LIBNAME##_VERSION_MINOR); \
3201  print_int("micro", LIB##LIBNAME##_VERSION_MICRO); \
3202  print_int("version", version); \
3203  print_str("ident", LIB##LIBNAME##_IDENT); \
3204  writer_print_section_footer(w); \
3205  } \
3206  } while (0)
3207 
3209 {
3211  SHOW_LIB_VERSION(avutil, AVUTIL);
3212  SHOW_LIB_VERSION(avcodec, AVCODEC);
3213  SHOW_LIB_VERSION(avformat, AVFORMAT);
3214  SHOW_LIB_VERSION(avdevice, AVDEVICE);
3215  SHOW_LIB_VERSION(avfilter, AVFILTER);
3216  SHOW_LIB_VERSION(swscale, SWSCALE);
3217  SHOW_LIB_VERSION(swresample, SWRESAMPLE);
3218  SHOW_LIB_VERSION(postproc, POSTPROC);
3220 }
3221 
3222 #define PRINT_PIX_FMT_FLAG(flagname, name) \
3223  do { \
3224  print_int(name, !!(pixdesc->flags & AV_PIX_FMT_FLAG_##flagname)); \
3225  } while (0)
3226 
3228 {
3229  const AVPixFmtDescriptor *pixdesc = NULL;
3230  int i, n;
3231 
3233  while (pixdesc = av_pix_fmt_desc_next(pixdesc)) {
3235  print_str("name", pixdesc->name);
3236  print_int("nb_components", pixdesc->nb_components);
3237  if ((pixdesc->nb_components >= 3) && !(pixdesc->flags & AV_PIX_FMT_FLAG_RGB)) {
3238  print_int ("log2_chroma_w", pixdesc->log2_chroma_w);
3239  print_int ("log2_chroma_h", pixdesc->log2_chroma_h);
3240  } else {
3241  print_str_opt("log2_chroma_w", "N/A");
3242  print_str_opt("log2_chroma_h", "N/A");
3243  }
3244  n = av_get_bits_per_pixel(pixdesc);
3245  if (n) print_int ("bits_per_pixel", n);
3246  else print_str_opt("bits_per_pixel", "N/A");
3249  PRINT_PIX_FMT_FLAG(BE, "big_endian");
3250  PRINT_PIX_FMT_FLAG(PAL, "palette");
3251  PRINT_PIX_FMT_FLAG(BITSTREAM, "bitstream");
3252  PRINT_PIX_FMT_FLAG(HWACCEL, "hwaccel");
3253  PRINT_PIX_FMT_FLAG(PLANAR, "planar");
3254  PRINT_PIX_FMT_FLAG(RGB, "rgb");
3255  PRINT_PIX_FMT_FLAG(ALPHA, "alpha");
3257  }
3258  if (do_show_pixel_format_components && (pixdesc->nb_components > 0)) {
3260  for (i = 0; i < pixdesc->nb_components; i++) {
3262  print_int("index", i + 1);
3263  print_int("bit_depth", pixdesc->comp[i].depth);
3265  }
3267  }
3269  }
3271 }
3272 
3273 static int opt_show_optional_fields(void *optctx, const char *opt, const char *arg)
3274 {
3278 
3281  return 0;
3282 }
3283 
3284 static int opt_format(void *optctx, const char *opt, const char *arg)
3285 {
3287  if (!iformat) {
3288  av_log(NULL, AV_LOG_ERROR, "Unknown input format: %s\n", arg);
3289  return AVERROR(EINVAL);
3290  }
3291  return 0;
3292 }
3293 
3294 static inline void mark_section_show_entries(SectionID section_id,
3295  int show_all_entries, AVDictionary *entries)
3296 {
3297  struct section *section = &sections[section_id];
3298 
3300  if (show_all_entries) {
3301  SectionID *id;
3302  for (id = section->children_ids; *id != -1; id++)
3304  } else {
3305  av_dict_copy(&section->entries_to_show, entries, 0);
3306  }
3307 }
3308 
3309 static int match_section(const char *section_name,
3310  int show_all_entries, AVDictionary *entries)
3311 {
3312  int i, ret = 0;
3313 
3314  for (i = 0; i < FF_ARRAY_ELEMS(sections); i++) {
3315  const struct section *section = &sections[i];
3316  if (!strcmp(section_name, section->name) ||
3317  (section->unique_name && !strcmp(section_name, section->unique_name))) {
3319  "'%s' matches section with unique name '%s'\n", section_name,
3321  ret++;
3323  }
3324  }
3325  return ret;
3326 }
3327 
3328 static int opt_show_entries(void *optctx, const char *opt, const char *arg)
3329 {
3330  const char *p = arg;
3331  int ret = 0;
3332 
3333  while (*p) {
3334  AVDictionary *entries = NULL;
3335  char *section_name = av_get_token(&p, "=:");
3336  int show_all_entries = 0;
3337 
3338  if (!section_name) {
3340  "Missing section name for option '%s'\n", opt);
3341  return AVERROR(EINVAL);
3342  }
3343 
3344  if (*p == '=') {
3345  p++;
3346  while (*p && *p != ':') {
3347  char *entry = av_get_token(&p, ",:");
3348  if (!entry)
3349  break;
3351  "Adding '%s' to the entries to show in section '%s'\n",
3352  entry, section_name);
3353  av_dict_set(&entries, entry, "", AV_DICT_DONT_STRDUP_KEY);
3354  if (*p == ',')
3355  p++;
3356  }
3357  } else {
3358  show_all_entries = 1;
3359  }
3360 
3361  ret = match_section(section_name, show_all_entries, entries);
3362  if (ret == 0) {
3363  av_log(NULL, AV_LOG_ERROR, "No match for section '%s'\n", section_name);
3364  ret = AVERROR(EINVAL);
3365  }
3366  av_dict_free(&entries);
3367  av_free(section_name);
3368 
3369  if (ret <= 0)
3370  break;
3371  if (*p)
3372  p++;
3373  }
3374 
3375  return ret;
3376 }
3377 
3378 static int opt_show_format_entry(void *optctx, const char *opt, const char *arg)
3379 {
3380  char *buf = av_asprintf("format=%s", arg);
3381  int ret;
3382 
3383  if (!buf)
3384  return AVERROR(ENOMEM);
3385 
3387  "Option '%s' is deprecated, use '-show_entries format=%s' instead\n",
3388  opt, arg);
3389  ret = opt_show_entries(optctx, opt, buf);
3390  av_free(buf);
3391  return ret;
3392 }
3393 
3394 static void opt_input_file(void *optctx, const char *arg)
3395 {
3396  if (input_filename) {
3398  "Argument '%s' provided as input filename, but '%s' was already specified.\n",
3399  arg, input_filename);
3400  exit_program(1);
3401  }
3402  if (!strcmp(arg, "-"))
3403  arg = "pipe:";
3404  input_filename = arg;
3405 }
3406 
3407 static int opt_input_file_i(void *optctx, const char *opt, const char *arg)
3408 {
3409  opt_input_file(optctx, arg);
3410  return 0;
3411 }
3412 
3413 static int opt_print_filename(void *optctx, const char *opt, const char *arg)
3414 {
3416  return 0;
3417 }
3418 
3419 void show_help_default(const char *opt, const char *arg)
3420 {
3422  show_usage();
3423  show_help_options(options, "Main options:", 0, 0, 0);
3424  printf("\n");
3425 
3428 }
3429 
3430 /**
3431  * Parse interval specification, according to the format:
3432  * INTERVAL ::= [START|+START_OFFSET][%[END|+END_OFFSET]]
3433  * INTERVALS ::= INTERVAL[,INTERVALS]
3434 */
3435 static int parse_read_interval(const char *interval_spec,
3436  ReadInterval *interval)
3437 {
3438  int ret = 0;
3439  char *next, *p, *spec = av_strdup(interval_spec);
3440  if (!spec)
3441  return AVERROR(ENOMEM);
3442 
3443  if (!*spec) {
3444  av_log(NULL, AV_LOG_ERROR, "Invalid empty interval specification\n");
3445  ret = AVERROR(EINVAL);
3446  goto end;
3447  }
3448 
3449  p = spec;
3450  next = strchr(spec, '%');
3451  if (next)
3452  *next++ = 0;
3453 
3454  /* parse first part */
3455  if (*p) {
3456  interval->has_start = 1;
3457 
3458  if (*p == '+') {
3459  interval->start_is_offset = 1;
3460  p++;
3461  } else {
3462  interval->start_is_offset = 0;
3463  }
3464 
3465  ret = av_parse_time(&interval->start, p, 1);
3466  if (ret < 0) {
3467  av_log(NULL, AV_LOG_ERROR, "Invalid interval start specification '%s'\n", p);
3468  goto end;
3469  }
3470  } else {
3471  interval->has_start = 0;
3472  }
3473 
3474  /* parse second part */
3475  p = next;
3476  if (p && *p) {
3477  int64_t us;
3478  interval->has_end = 1;
3479 
3480  if (*p == '+') {
3481  interval->end_is_offset = 1;
3482  p++;
3483  } else {
3484  interval->end_is_offset = 0;
3485  }
3486 
3487  if (interval->end_is_offset && *p == '#') {
3488  long long int lli;
3489  char *tail;
3490  interval->duration_frames = 1;
3491  p++;
3492  lli = strtoll(p, &tail, 10);
3493  if (*tail || lli < 0) {
3495  "Invalid or negative value '%s' for duration number of frames\n", p);
3496  goto end;
3497  }
3498  interval->end = lli;
3499  } else {
3500  interval->duration_frames = 0;
3501  ret = av_parse_time(&us, p, 1);
3502  if (ret < 0) {
3503  av_log(NULL, AV_LOG_ERROR, "Invalid interval end/duration specification '%s'\n", p);
3504  goto end;
3505  }
3506  interval->end = us;
3507  }
3508  } else {
3509  interval->has_end = 0;
3510  }
3511 
3512 end:
3513  av_free(spec);
3514  return ret;
3515 }
3516 
3517 static int parse_read_intervals(const char *intervals_spec)
3518 {
3519  int ret, n, i;
3520  char *p, *spec = av_strdup(intervals_spec);
3521  if (!spec)
3522  return AVERROR(ENOMEM);
3523 
3524  /* preparse specification, get number of intervals */
3525  for (n = 0, p = spec; *p; p++)
3526  if (*p == ',')
3527  n++;
3528  n++;
3529 
3531  if (!read_intervals) {
3532  ret = AVERROR(ENOMEM);
3533  goto end;
3534  }
3535  read_intervals_nb = n;
3536 
3537  /* parse intervals */
3538  p = spec;
3539  for (i = 0; p; i++) {
3540  char *next;
3541 
3543  next = strchr(p, ',');
3544  if (next)
3545  *next++ = 0;
3546 
3547  read_intervals[i].id = i;
3549  if (ret < 0) {
3550  av_log(NULL, AV_LOG_ERROR, "Error parsing read interval #%d '%s'\n",
3551  i, p);
3552  goto end;
3553  }
3554  av_log(NULL, AV_LOG_VERBOSE, "Parsed log interval ");
3556  p = next;
3557  }
3559 
3560 end:
3561  av_free(spec);
3562  return ret;
3563 }
3564 
3565 static int opt_read_intervals(void *optctx, const char *opt, const char *arg)
3566 {
3567  return parse_read_intervals(arg);
3568 }
3569 
3570 static int opt_pretty(void *optctx, const char *opt, const char *arg)
3571 {
3572  show_value_unit = 1;
3573  use_value_prefix = 1;
3576  return 0;
3577 }
3578 
3579 static void print_section(SectionID id, int level)
3580 {
3581  const SectionID *pid;
3582  const struct section *section = &sections[id];
3583  printf("%c%c%c",
3584  section->flags & SECTION_FLAG_IS_WRAPPER ? 'W' : '.',
3585  section->flags & SECTION_FLAG_IS_ARRAY ? 'A' : '.',
3587  printf("%*c %s", level * 4, ' ', section->name);
3588  if (section->unique_name)
3589  printf("/%s", section->unique_name);
3590  printf("\n");
3591 
3592  for (pid = section->children_ids; *pid != -1; pid++)
3593  print_section(*pid, level+1);
3594 }
3595 
3596 static int opt_sections(void *optctx, const char *opt, const char *arg)
3597 {
3598  printf("Sections:\n"
3599  "W.. = Section is a wrapper (contains other sections, no local entries)\n"
3600  ".A. = Section contains an array of elements of the same type\n"
3601  "..V = Section may contain a variable number of fields with variable keys\n"
3602  "FLAGS NAME/UNIQUE_NAME\n"
3603  "---\n");
3605  return 0;
3606 }
3607 
3608 static int opt_show_versions(void *optctx, const char *opt, const char *arg)
3609 {
3612  return 0;
3613 }
3614 
3615 #define DEFINE_OPT_SHOW_SECTION(section, target_section_id) \
3616  static int opt_show_##section(void *optctx, const char *opt, const char *arg) \
3617  { \
3618  mark_section_show_entries(SECTION_ID_##target_section_id, 1, NULL); \
3619  return 0; \
3620  }
3621 
3622 DEFINE_OPT_SHOW_SECTION(chapters, CHAPTERS)
3626 DEFINE_OPT_SHOW_SECTION(library_versions, LIBRARY_VERSIONS)
3627 DEFINE_OPT_SHOW_SECTION(packets, PACKETS)
3628 DEFINE_OPT_SHOW_SECTION(pixel_formats, PIXEL_FORMATS)
3629 DEFINE_OPT_SHOW_SECTION(program_version, PROGRAM_VERSION)
3630 DEFINE_OPT_SHOW_SECTION(streams, STREAMS)
3631 DEFINE_OPT_SHOW_SECTION(programs, PROGRAMS)
3632 
3633 static const OptionDef real_options[] = {
3635  { "f", HAS_ARG, {.func_arg = opt_format}, "force format", "format" },
3636  { "unit", OPT_BOOL, {&show_value_unit}, "show unit of the displayed values" },
3637  { "prefix", OPT_BOOL, {&use_value_prefix}, "use SI prefixes for the displayed values" },
3638  { "byte_binary_prefix", OPT_BOOL, {&use_byte_value_binary_prefix},
3639  "use binary prefixes for byte units" },
3640  { "sexagesimal", OPT_BOOL, {&use_value_sexagesimal_format},
3641  "use sexagesimal format HOURS:MM:SS.MICROSECONDS for time units" },
3642  { "pretty", 0, {.func_arg = opt_pretty},
3643  "prettify the format of displayed values, make it more human readable" },
3644  { "print_format", OPT_STRING | HAS_ARG, { &print_format },
3645  "set the output printing format (available formats are: default, compact, csv, flat, ini, json, xml)", "format" },
3646  { "of", OPT_STRING | HAS_ARG, { &print_format }, "alias for -print_format", "format" },
3647  { "select_streams", OPT_STRING | HAS_ARG, { &stream_specifier }, "select the specified streams", "stream_specifier" },
3648  { "sections", OPT_EXIT, {.func_arg = opt_sections}, "print sections structure and section information, and exit" },
3649  { "show_data", OPT_BOOL, { &do_show_data }, "show packets data" },
3650  { "show_data_hash", OPT_STRING | HAS_ARG, { &show_data_hash }, "show packets data hash" },
3651  { "show_error", 0, { .func_arg = &opt_show_error }, "show probing error" },
3652  { "show_format", 0, { .func_arg = &opt_show_format }, "show format/container info" },
3653  { "show_frames", 0, { .func_arg = &opt_show_frames }, "show frames info" },
3654  { "show_format_entry", HAS_ARG, {.func_arg = opt_show_format_entry},
3655  "show a particular entry from the format/container info", "entry" },
3656  { "show_entries", HAS_ARG, {.func_arg = opt_show_entries},
3657  "show a set of specified entries", "entry_list" },
3658 #if HAVE_THREADS
3659  { "show_log", OPT_INT|HAS_ARG, { &do_show_log }, "show log" },
3660 #endif
3661  { "show_packets", 0, { .func_arg = &opt_show_packets }, "show packets info" },
3662  { "show_programs", 0, { .func_arg = &opt_show_programs }, "show programs info" },
3663  { "show_streams", 0, { .func_arg = &opt_show_streams }, "show streams info" },
3664  { "show_chapters", 0, { .func_arg = &opt_show_chapters }, "show chapters info" },
3665  { "count_frames", OPT_BOOL, { &do_count_frames }, "count the number of frames per stream" },
3666  { "count_packets", OPT_BOOL, { &do_count_packets }, "count the number of packets per stream" },
3667  { "show_program_version", 0, { .func_arg = &opt_show_program_version }, "show ffprobe version" },
3668  { "show_library_versions", 0, { .func_arg = &opt_show_library_versions }, "show library versions" },
3669  { "show_versions", 0, { .func_arg = &opt_show_versions }, "show program and library versions" },
3670  { "show_pixel_formats", 0, { .func_arg = &opt_show_pixel_formats }, "show pixel format descriptions" },
3671  { "show_optional_fields", HAS_ARG, { .func_arg = &opt_show_optional_fields }, "show optional fields" },
3672  { "show_private_data", OPT_BOOL, { &show_private_data }, "show private data" },
3673  { "private", OPT_BOOL, { &show_private_data }, "same as show_private_data" },
3674  { "bitexact", OPT_BOOL, {&do_bitexact}, "force bitexact output" },
3675  { "read_intervals", HAS_ARG, {.func_arg = opt_read_intervals}, "set read intervals", "read_intervals" },
3676  { "default", HAS_ARG | OPT_AUDIO | OPT_VIDEO | OPT_EXPERT, {.func_arg = opt_default}, "generic catch all option", "" },
3677  { "i", HAS_ARG, {.func_arg = opt_input_file_i}, "read specified file", "input_file"},
3678  { "print_filename", HAS_ARG, {.func_arg = opt_print_filename}, "override the printed input filename", "print_file"},
3679  { "find_stream_info", OPT_BOOL | OPT_INPUT | OPT_EXPERT, { &find_stream_info },
3680  "read and decode the streams to fill missing information with heuristics" },
3681  { NULL, },
3682 };
3683 
3684 static inline int check_section_show_entries(int section_id)
3685 {
3686  int *id;
3687  struct section *section = &sections[section_id];
3688  if (sections[section_id].show_all_entries || sections[section_id].entries_to_show)
3689  return 1;
3690  for (id = section->children_ids; *id != -1; id++)
3691  if (check_section_show_entries(*id))
3692  return 1;
3693  return 0;
3694 }
3695 
3696 #define SET_DO_SHOW(id, varname) do { \
3697  if (check_section_show_entries(SECTION_ID_##id)) \
3698  do_show_##varname = 1; \
3699  } while (0)
3700 
3701 int main(int argc, char **argv)
3702 {
3703  const Writer *w;
3704  WriterContext *wctx;
3705  char *buf;
3706  char *w_name = NULL, *w_args = NULL;
3707  int ret, i;
3708 
3709  init_dynload();
3710 
3711 #if HAVE_THREADS
3712  ret = pthread_mutex_init(&log_mutex, NULL);
3713  if (ret != 0) {
3714  goto end;
3715  }
3716 #endif
3719 
3721  parse_loglevel(argc, argv, options);
3723  init_opts();
3724 #if CONFIG_AVDEVICE
3726 #endif
3727 
3728  show_banner(argc, argv, options);
3729  parse_options(NULL, argc, argv, options, opt_input_file);
3730 
3731  if (do_show_log)
3733 
3734  /* mark things to show, based on -show_entries */
3735  SET_DO_SHOW(CHAPTERS, chapters);
3737  SET_DO_SHOW(FORMAT, format);
3738  SET_DO_SHOW(FRAMES, frames);
3739  SET_DO_SHOW(LIBRARY_VERSIONS, library_versions);
3740  SET_DO_SHOW(PACKETS, packets);
3741  SET_DO_SHOW(PIXEL_FORMATS, pixel_formats);
3742  SET_DO_SHOW(PIXEL_FORMAT_FLAGS, pixel_format_flags);
3743  SET_DO_SHOW(PIXEL_FORMAT_COMPONENTS, pixel_format_components);
3744  SET_DO_SHOW(PROGRAM_VERSION, program_version);
3745  SET_DO_SHOW(PROGRAMS, programs);
3746  SET_DO_SHOW(STREAMS, streams);
3747  SET_DO_SHOW(STREAM_DISPOSITION, stream_disposition);
3748  SET_DO_SHOW(PROGRAM_STREAM_DISPOSITION, stream_disposition);
3749 
3750  SET_DO_SHOW(CHAPTER_TAGS, chapter_tags);
3751  SET_DO_SHOW(FORMAT_TAGS, format_tags);
3752  SET_DO_SHOW(FRAME_TAGS, frame_tags);
3753  SET_DO_SHOW(PROGRAM_TAGS, program_tags);
3754  SET_DO_SHOW(STREAM_TAGS, stream_tags);
3755  SET_DO_SHOW(PROGRAM_STREAM_TAGS, stream_tags);
3756  SET_DO_SHOW(PACKET_TAGS, packet_tags);
3757 
3760  "-bitexact and -show_program_version or -show_library_versions "
3761  "options are incompatible\n");
3762  ret = AVERROR(EINVAL);
3763  goto end;
3764  }
3765 
3767 
3768  if (!print_format)
3769  print_format = av_strdup("default");
3770  if (!print_format) {
3771  ret = AVERROR(ENOMEM);
3772  goto end;
3773  }
3774  w_name = av_strtok(print_format, "=", &buf);
3775  if (!w_name) {
3777  "No name specified for the output format\n");
3778  ret = AVERROR(EINVAL);
3779  goto end;
3780  }
3781  w_args = buf;
3782 
3783  if (show_data_hash) {
3784  if ((ret = av_hash_alloc(&hash, show_data_hash)) < 0) {
3785  if (ret == AVERROR(EINVAL)) {
3786  const char *n;
3788  "Unknown hash algorithm '%s'\nKnown algorithms:",
3789  show_data_hash);
3790  for (i = 0; (n = av_hash_names(i)); i++)
3791  av_log(NULL, AV_LOG_ERROR, " %s", n);
3792  av_log(NULL, AV_LOG_ERROR, "\n");
3793  }
3794  goto end;
3795  }
3796  }
3797 
3798  w = writer_get_by_name(w_name);
3799  if (!w) {
3800  av_log(NULL, AV_LOG_ERROR, "Unknown output format with name '%s'\n", w_name);
3801  ret = AVERROR(EINVAL);
3802  goto end;
3803  }
3804 
3805  if ((ret = writer_open(&wctx, w, w_args,
3806  sections, FF_ARRAY_ELEMS(sections))) >= 0) {
3807  if (w == &xml_writer)
3809 
3811 
3818 
3819  if (!input_filename &&
3822  show_usage();
3823  av_log(NULL, AV_LOG_ERROR, "You have to specify one input file.\n");
3824  av_log(NULL, AV_LOG_ERROR, "Use -h to get full help or, even better, run 'man %s'.\n", program_name);
3825  ret = AVERROR(EINVAL);
3826  } else if (input_filename) {
3828  if (ret < 0 && do_show_error)
3829  show_error(wctx, ret);
3830  }
3831 
3833  writer_close(&wctx);
3834  }
3835 
3836 end:
3839  av_hash_freep(&hash);
3840 
3841  uninit_opts();
3842  for (i = 0; i < FF_ARRAY_ELEMS(sections); i++)
3844 
3846 
3847  return ret < 0;
3848 }
error
static void error(const char *err)
Definition: target_bsf_fuzzer.c:30
flat_escape_key_str
static const char * flat_escape_key_str(AVBPrint *dst, const char *src, const char sep)
Definition: ffprobe.c:1273
main
int main(int argc, char **argv)
Definition: ffprobe.c:3701
AVSubtitle
Definition: avcodec.h:2276
SECTION_ID_STREAM_SIDE_DATA_LIST
@ SECTION_ID_STREAM_SIDE_DATA_LIST
Definition: ffprobe.c:205
opt_format
static int opt_format(void *optctx, const char *opt, const char *arg)
Definition: ffprobe.c:3284
pthread_mutex_t
_fmutex pthread_mutex_t
Definition: os2threads.h:53
clear_log
static void clear_log(int need_lock)
Definition: ffprobe.c:2106
AVMasteringDisplayMetadata::has_primaries
int has_primaries
Flag indicating whether the display primaries (and white point) are set.
Definition: mastering_display_metadata.h:62
AVHDRPlusColorTransformParams::average_maxrgb
AVRational average_maxrgb
The average of linearized maxRGB values in the processing window in the scene.
Definition: hdr_dynamic_metadata.h:164
mark_section_show_entries
static void mark_section_show_entries(SectionID section_id, int show_all_entries, AVDictionary *entries)
Definition: ffprobe.c:3294
av_packet_unref
void av_packet_unref(AVPacket *pkt)
Wipe the packet.
Definition: avpacket.c:403
OPT_EXIT
#define OPT_EXIT
Definition: cmdutils.h:171
AVCodec
AVCodec.
Definition: codec.h:197
writer_get_by_name
static const Writer * writer_get_by_name(const char *name)
Definition: ffprobe.c:904
av_utf8_decode
int av_utf8_decode(int32_t *codep, const uint8_t **bufp, const uint8_t *buf_end, unsigned int flags)
Read and decode a single UTF-8 code point (character) from the buffer in *buf, and update *buf to poi...
Definition: avstring.c:376
AVDynamicHDRPlus::params
AVHDRPlusColorTransformParams params[3]
The color transform parameters for every processing window.
Definition: hdr_dynamic_metadata.h:264
AVMEDIA_TYPE_SUBTITLE
@ AVMEDIA_TYPE_SUBTITLE
Definition: avutil.h:204
flat_options
static const AVOption flat_options[]
Definition: ffprobe.c:1249
WriterContext::section_pbuf
AVBPrint section_pbuf[SECTION_MAX_NB_LEVELS]
generic print buffer dedicated to each section, used by various writers
Definition: ffprobe.c:474
AV_LOG_WARNING
#define AV_LOG_WARNING
Something somehow does not look correct.
Definition: log.h:187
AV_BPRINT_SIZE_UNLIMITED
#define AV_BPRINT_SIZE_UNLIMITED
AV_TIMECODE_STR_SIZE
#define AV_TIMECODE_STR_SIZE
Definition: timecode.h:33
use_byte_value_binary_prefix
static int use_byte_value_binary_prefix
Definition: ffprobe.c:116
WriterContext::level
int level
current level, starting from 0
Definition: ffprobe.c:467
WriterContext::string_validation
int string_validation
Definition: ffprobe.c:481
AVMasteringDisplayMetadata::max_luminance
AVRational max_luminance
Max luminance of mastering display (cd/m^2).
Definition: mastering_display_metadata.h:57
AVCodecParameters::extradata
uint8_t * extradata
Extra binary data needed for initializing the decoder, codec-dependent.
Definition: codec_par.h:74
MAX_REGISTERED_WRITERS_NB
#define MAX_REGISTERED_WRITERS_NB
Definition: ffprobe.c:889
name
it s the only field you need to keep assuming you have a context There is some magic you don t need to care about around this just let it vf default minimum maximum flags name is the option name
Definition: writing_filters.txt:88
level
uint8_t level
Definition: svq3.c:204
do_show_log
static int do_show_log
Definition: ffprobe.c:105
program
Undefined Behavior In the C some operations are like signed integer dereferencing freed accessing outside allocated Undefined Behavior must not occur in a C program
Definition: undefined.txt:6
av_clip
#define av_clip
Definition: common.h:122
InputFile::fmt_ctx
AVFormatContext * fmt_ctx
Definition: ffprobe.c:77
SECTION_MAX_NB_LEVELS
#define SECTION_MAX_NB_LEVELS
Definition: ffprobe.c:456
writer_close
static void writer_close(WriterContext **wctx)
Definition: ffprobe.c:523
SECTION_ID_STREAM_SIDE_DATA
@ SECTION_ID_STREAM_SIDE_DATA
Definition: ffprobe.c:206
init
static av_cold int init(AVCodecContext *avctx)
Definition: avrndec.c:31
do_show_frame_tags
static int do_show_frame_tags
Definition: ffprobe.c:109
PLANAR
#define PLANAR
Definition: flacdsp.c:43
AVChapter::metadata
AVDictionary * metadata
Definition: avformat.h:1058
r
const char * r
Definition: vf_curves.c:116
AVERROR
Filter the word “frame” indicates either a video frame or a group of audio as stored in an AVFrame structure Format for each input and each output the list of supported formats For video that means pixel format For audio that means channel sample they are references to shared objects When the negotiation mechanism computes the intersection of the formats supported at each end of a all references to both lists are replaced with a reference to the intersection And when a single format is eventually chosen for a link amongst the remaining all references to the list are updated That means that if a filter requires that its input and output have the same format amongst a supported all it has to do is use a reference to the same list of formats query_formats can leave some formats unset and return AVERROR(EAGAIN) to cause the negotiation mechanism toagain later. That can be used by filters with complex requirements to use the format negotiated on one link to set the formats supported on another. Frame references ownership and permissions
opt_show_optional_fields
static int opt_show_optional_fields(void *optctx, const char *opt, const char *arg)
Definition: ffprobe.c:3273
SECTION_ID_NONE
@ SECTION_ID_NONE
Definition: ffprobe.c:163
opt.h
read_intervals_nb
static int read_intervals_nb
Definition: ffprobe.c:138
AVCodecParameters::codec_type
enum AVMediaType codec_type
General type of the encoded data.
Definition: codec_par.h:56
AVFMT_SHOW_IDS
#define AVFMT_SHOW_IDS
Show format stream IDs numbers.
Definition: avformat.h:465
AVSphericalMapping::projection
enum AVSphericalProjection projection
Projection type.
Definition: spherical.h:86
av_opt_set_defaults
void av_opt_set_defaults(void *s)
Set the values of all AVOption fields to their default values.
Definition: opt.c:1358
ReadInterval::end_is_offset
int end_is_offset
Definition: ffprobe.c:133
LogBuffer::log_message
char * log_message
Definition: ffprobe.c:299
AVColorTransferCharacteristic
AVColorTransferCharacteristic
Color Transfer Characteristic.
Definition: pixfmt.h:473
libm.h
av_bprint_finalize
int av_bprint_finalize(AVBPrint *buf, char **ret_str)
Finalize a print buffer.
Definition: bprint.c:235
show_streams
static int show_streams(WriterContext *w, InputFile *ifile)
Definition: ffprobe.c:2817
AV_PKT_DATA_MPEGTS_STREAM_ID
@ AV_PKT_DATA_MPEGTS_STREAM_ID
MPEGTS stream ID as uint8_t, this is required to pass the stream ID information from the demuxer to t...
Definition: packet.h:215
Writer::name
const char * name
Definition: ffprobe.c:443
print_str
#define print_str(k, v)
Definition: ffprobe.c:1811
LogBuffer::context_name
char * context_name
Definition: ffprobe.c:297
writer_print_section_header
static void writer_print_section_header(WriterContext *wctx, int section_id)
Definition: ffprobe.c:637
av_bprint_init
void av_bprint_init(AVBPrint *buf, unsigned size_init, unsigned size_max)
Definition: bprint.c:69
av_get_token
char * av_get_token(const char **buf, const char *term)
Unescape the given string until a non escaped terminating char, and return the token corresponding to...
Definition: avstring.c:151
AV_HASH_MAX_SIZE
#define AV_HASH_MAX_SIZE
Maximum value that av_hash_get_size() will currently return.
Definition: hash.h:158
AVHDRPlusColorTransformParams::rotation_angle
uint8_t rotation_angle
The clockwise rotation angle in degree of arc with respect to the positive direction of the x-axis of...
Definition: hdr_dynamic_metadata.h:118
print_val
#define print_val(k, v, u)
Definition: ffprobe.c:1818
compact_print_section_footer
static void compact_print_section_footer(WriterContext *wctx)
Definition: ffprobe.c:1161
SECTION_ID_PACKET_SIDE_DATA_LIST
@ SECTION_ID_PACKET_SIDE_DATA_LIST
Definition: ffprobe.c:185
AVFormatContext::nb_chapters
unsigned int nb_chapters
Number of chapters in AVChapter array.
Definition: avformat.h:1315
AVCodecParameters
This struct describes the properties of an encoded stream.
Definition: codec_par.h:52
AVHDRPlusPercentile::percentile
AVRational percentile
The linearized maxRGB value at a specific percentile in the processing window in the scene.
Definition: hdr_dynamic_metadata.h:52
AVCodec::priv_class
const AVClass * priv_class
AVClass for the private context.
Definition: codec.h:223
show_stream
static int show_stream(WriterContext *w, AVFormatContext *fmt_ctx, int stream_idx, InputStream *ist, int in_program)
Definition: ffprobe.c:2597
sub
static float sub(float src0, float src1)
Definition: dnn_backend_native_layer_mathbinary.c:32
AVCodecParameters::color_space
enum AVColorSpace color_space
Definition: codec_par.h:149
Writer::init
int(* init)(WriterContext *wctx)
Definition: ffprobe.c:445
thread.h
value_string
static char * value_string(char *buf, int buf_size, struct unit_value uv)
Definition: ffprobe.c:373
AVERROR_EOF
#define AVERROR_EOF
End of file.
Definition: error.h:55
read_packets
static int read_packets(WriterContext *w, InputFile *ifile)
Definition: ffprobe.c:2577
pthread_mutex_init
static av_always_inline int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *attr)
Definition: os2threads.h:104
AVCodecDescriptor::long_name
const char * long_name
A more descriptive name for this codec.
Definition: codec_desc.h:50
AVMasteringDisplayMetadata::display_primaries
AVRational display_primaries[3][2]
CIE 1931 xy chromaticity coords of color primaries (r, g, b order).
Definition: mastering_display_metadata.h:42
show_packet
static void show_packet(WriterContext *w, InputFile *ifile, AVPacket *pkt, int packet_idx)
Definition: ffprobe.c:2157
AV_PKT_FLAG_DISCARD
#define AV_PKT_FLAG_DISCARD
Flag is used to discard packets which are required to maintain valid decoder state but are not requir...
Definition: packet.h:403
CompactContext::print_section
int print_section
Definition: ffprobe.c:1084
AVMasteringDisplayMetadata::has_luminance
int has_luminance
Flag indicating whether the luminance (min_ and max_) have been set.
Definition: mastering_display_metadata.h:67
InputStream::dec_ctx
AVCodecContext * dec_ctx
Definition: ffmpeg.h:309
AV_TIME_BASE_Q
#define AV_TIME_BASE_Q
Internal time base represented as fractional value.
Definition: avutil.h:260
Writer::print_section_footer
void(* print_section_footer)(WriterContext *wctx)
Definition: ffprobe.c:449
AVCodecDescriptor::name
const char * name
Name of the codec described by this descriptor.
Definition: codec_desc.h:46
writer_open
static int writer_open(WriterContext **wctx, const Writer *writer, const char *args, const struct section *sections, int nb_sections)
Definition: ffprobe.c:550
selected_streams
static int * selected_streams
Definition: ffprobe.c:291
SECTION_ID_PROGRAM_TAGS
@ SECTION_ID_PROGRAM_TAGS
Definition: ffprobe.c:197
av_asprintf
char * av_asprintf(const char *fmt,...)
Definition: avstring.c:113
av_strcasecmp
int av_strcasecmp(const char *a, const char *b)
Locale-independent case-insensitive compare.
Definition: avstring.c:215
AVHDRPlusColorTransformParams::semimajor_axis_external_ellipse
uint16_t semimajor_axis_external_ellipse
The semi-major axis value of the external ellipse of the elliptical pixel selector in amount of pixel...
Definition: hdr_dynamic_metadata.h:134
avformat_get_class
const AVClass * avformat_get_class(void)
Get the AVClass for AVFormatContext.
Definition: options.c:201
AV_FRAME_DATA_S12M_TIMECODE
@ AV_FRAME_DATA_S12M_TIMECODE
Timecode which conforms to SMPTE ST 12-1.
Definition: frame.h:151
DefaultContext
Definition: ffprobe.c:931
Writer::priv_class
const AVClass * priv_class
private class of the writer, if any
Definition: ffprobe.c:441
AVHDRPlusColorTransformParams
Color transform parameters at a processing window in a dynamic metadata for SMPTE 2094-40.
Definition: hdr_dynamic_metadata.h:59
AV_RN16
#define AV_RN16(p)
Definition: intreadwrite.h:360
av_frame_free
void av_frame_free(AVFrame **frame)
Free the frame and any dynamically allocated objects in it, e.g.
Definition: frame.c:111
AVContentLightMetadata::MaxCLL
unsigned MaxCLL
Max content light level (cd/m^2).
Definition: mastering_display_metadata.h:102
profile
mfxU16 profile
Definition: qsvenc.c:45
WriterContext::section
const struct section * section[SECTION_MAX_NB_LEVELS]
section per each level
Definition: ffprobe.c:473
json_escape_str
static const char * json_escape_str(AVBPrint *dst, const char *src, void *log_ctx)
Definition: ffprobe.c:1495
print_ts
#define print_ts(k, v)
Definition: ffprobe.c:1815
opt_input_file_i
static int opt_input_file_i(void *optctx, const char *opt, const char *arg)
Definition: ffprobe.c:3407
WriterContext::nb_section_packet_frame
unsigned int nb_section_packet_frame
nb_section_packet or nb_section_frame according if is_packets_and_frames
Definition: ffprobe.c:479
AVFrame
This structure describes decoded (raw) audio or video data.
Definition: frame.h:303
pixdesc.h
AVFormatContext::streams
AVStream ** streams
A list of all streams in the file.
Definition: avformat.h:1165
index
fg index
Definition: ffmpeg_filter.c:168
AVPacketSideData
Definition: packet.h:306
w
uint8_t w
Definition: llviddspenc.c:39
validate_string
static int validate_string(WriterContext *wctx, char **dstp, const char *src)
Definition: ffprobe.c:689
OPT_INPUT
#define OPT_INPUT
Definition: cmdutils.h:178
opt_show_format_entry
static int opt_show_format_entry(void *optctx, const char *opt, const char *arg)
Definition: ffprobe.c:3378
avcodec_decode_subtitle2
int avcodec_decode_subtitle2(AVCodecContext *avctx, AVSubtitle *sub, int *got_sub_ptr, AVPacket *avpkt)
Decode a subtitle message.
Definition: decode.c:800
SECTION_ID_PIXEL_FORMAT_COMPONENTS
@ SECTION_ID_PIXEL_FORMAT_COMPONENTS
Definition: ffprobe.c:190
AVDynamicHDRPlus::num_cols_targeted_system_display_actual_peak_luminance
uint8_t num_cols_targeted_system_display_actual_peak_luminance
The number of columns in the targeted_system_display_actual_peak_luminance array.
Definition: hdr_dynamic_metadata.h:290
AVPacket::data
uint8_t * data
Definition: packet.h:365
ReadInterval::duration_frames
int duration_frames
Definition: ffprobe.c:134
AVComponentDescriptor::depth
int depth
Number of bits in the component.
Definition: pixdesc.h:58
av_spherical_tile_bounds
void av_spherical_tile_bounds(const AVSphericalMapping *map, size_t width, size_t height, size_t *left, size_t *top, size_t *right, size_t *bottom)
Convert the bounding fields from an AVSphericalVideo from 0.32 fixed point to pixels.
Definition: spherical.c:37
AVPixFmtDescriptor::name
const char * name
Definition: pixdesc.h:71
AVOption
AVOption.
Definition: opt.h:248
HAS_ARG
#define HAS_ARG
Definition: cmdutils.h:161
b
#define b
Definition: input.c:41
AVCOL_TRC_UNSPECIFIED
@ AVCOL_TRC_UNSPECIFIED
Definition: pixfmt.h:476
SECTION_ID_STREAM
@ SECTION_ID_STREAM
Definition: ffprobe.c:201
section::element_name
const char * element_name</