FFmpeg coverage


Directory: ../../../ffmpeg/
File: src/fftools/ffprobe.c
Date: 2022-01-18 10:05:52
Exec Total Coverage
Lines: 1559 2071 75.3%
Branches: 864 1287 67.1%

Line Branch Exec Source
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/channel_layout.h"
37 #include "libavutil/display.h"
38 #include "libavutil/hash.h"
39 #include "libavutil/hdr_dynamic_metadata.h"
40 #include "libavutil/mastering_display_metadata.h"
41 #include "libavutil/dovi_meta.h"
42 #include "libavutil/opt.h"
43 #include "libavutil/pixdesc.h"
44 #include "libavutil/spherical.h"
45 #include "libavutil/stereo3d.h"
46 #include "libavutil/dict.h"
47 #include "libavutil/intreadwrite.h"
48 #include "libavutil/libm.h"
49 #include "libavutil/parseutils.h"
50 #include "libavutil/timecode.h"
51 #include "libavutil/timestamp.h"
52 #include "libavdevice/avdevice.h"
53 #include "libswscale/swscale.h"
54 #include "libswresample/swresample.h"
55 #include "libpostproc/postprocess.h"
56 #include "cmdutils.h"
57
58 #include "libavutil/thread.h"
59
60 #if !HAVE_THREADS
61 # ifdef pthread_mutex_lock
62 # undef pthread_mutex_lock
63 # endif
64 # define pthread_mutex_lock(a) do{}while(0)
65 # ifdef pthread_mutex_unlock
66 # undef pthread_mutex_unlock
67 # endif
68 # define pthread_mutex_unlock(a) do{}while(0)
69 #endif
70
71 typedef struct InputStream {
72 AVStream *st;
73
74 AVCodecContext *dec_ctx;
75 } InputStream;
76
77 typedef struct InputFile {
78 AVFormatContext *fmt_ctx;
79
80 InputStream *streams;
81 int nb_streams;
82 } InputFile;
83
84 const char program_name[] = "ffprobe";
85 const int program_birth_year = 2007;
86
87 static int do_bitexact = 0;
88 static int do_count_frames = 0;
89 static int do_count_packets = 0;
90 static int do_read_frames = 0;
91 static int do_read_packets = 0;
92 static int do_show_chapters = 0;
93 static int do_show_error = 0;
94 static int do_show_format = 0;
95 static int do_show_frames = 0;
96 static int do_show_packets = 0;
97 static int do_show_programs = 0;
98 static int do_show_streams = 0;
99 static int do_show_stream_disposition = 0;
100 static int do_show_data = 0;
101 static int do_show_program_version = 0;
102 static int do_show_library_versions = 0;
103 static int do_show_pixel_formats = 0;
104 static int do_show_pixel_format_flags = 0;
105 static int do_show_pixel_format_components = 0;
106 static int do_show_log = 0;
107
108 static int do_show_chapter_tags = 0;
109 static int do_show_format_tags = 0;
110 static int do_show_frame_tags = 0;
111 static int do_show_program_tags = 0;
112 static int do_show_stream_tags = 0;
113 static int do_show_packet_tags = 0;
114
115 static int show_value_unit = 0;
116 static int use_value_prefix = 0;
117 static int use_byte_value_binary_prefix = 0;
118 static int use_value_sexagesimal_format = 0;
119 static int show_private_data = 1;
120
121 #define SHOW_OPTIONAL_FIELDS_AUTO -1
122 #define SHOW_OPTIONAL_FIELDS_NEVER 0
123 #define SHOW_OPTIONAL_FIELDS_ALWAYS 1
124 static int show_optional_fields = SHOW_OPTIONAL_FIELDS_AUTO;
125
126 static char *print_format;
127 static char *stream_specifier;
128 static char *show_data_hash;
129
130 typedef struct ReadInterval {
131 int id; ///< identifier
132 int64_t start, end; ///< start, end in second/AV_TIME_BASE units
133 int has_start, has_end;
134 int start_is_offset, end_is_offset;
135 int duration_frames;
136 } ReadInterval;
137
138 static ReadInterval *read_intervals;
139 static int read_intervals_nb = 0;
140
141 static int find_stream_info = 1;
142
143 /* section structure definition */
144
145 #define SECTION_MAX_NB_CHILDREN 10
146
147 struct section {
148 int id; ///< unique id identifying a section
149 const char *name;
150
151 #define SECTION_FLAG_IS_WRAPPER 1 ///< the section only contains other sections, but has no data at its own level
152 #define SECTION_FLAG_IS_ARRAY 2 ///< the section contains an array of elements of the same type
153 #define SECTION_FLAG_HAS_VARIABLE_FIELDS 4 ///< the section may contain a variable number of fields with variable keys.
154 /// For these sections the element_name field is mandatory.
155 int flags;
156 int children_ids[SECTION_MAX_NB_CHILDREN+1]; ///< list of children section IDS, terminated by -1
157 const char *element_name; ///< name of the contained element, if provided
158 const char *unique_name; ///< unique section name, in case the name is ambiguous
159 AVDictionary *entries_to_show;
160 int show_all_entries;
161 };
162
163 typedef enum {
164 SECTION_ID_NONE = -1,
165 SECTION_ID_CHAPTER,
166 SECTION_ID_CHAPTER_TAGS,
167 SECTION_ID_CHAPTERS,
168 SECTION_ID_ERROR,
169 SECTION_ID_FORMAT,
170 SECTION_ID_FORMAT_TAGS,
171 SECTION_ID_FRAME,
172 SECTION_ID_FRAMES,
173 SECTION_ID_FRAME_TAGS,
174 SECTION_ID_FRAME_SIDE_DATA_LIST,
175 SECTION_ID_FRAME_SIDE_DATA,
176 SECTION_ID_FRAME_SIDE_DATA_TIMECODE_LIST,
177 SECTION_ID_FRAME_SIDE_DATA_TIMECODE,
178 SECTION_ID_FRAME_SIDE_DATA_COMPONENT_LIST,
179 SECTION_ID_FRAME_SIDE_DATA_COMPONENT,
180 SECTION_ID_FRAME_SIDE_DATA_PIECE_LIST,
181 SECTION_ID_FRAME_SIDE_DATA_PIECE,
182 SECTION_ID_FRAME_LOG,
183 SECTION_ID_FRAME_LOGS,
184 SECTION_ID_LIBRARY_VERSION,
185 SECTION_ID_LIBRARY_VERSIONS,
186 SECTION_ID_PACKET,
187 SECTION_ID_PACKET_TAGS,
188 SECTION_ID_PACKETS,
189 SECTION_ID_PACKETS_AND_FRAMES,
190 SECTION_ID_PACKET_SIDE_DATA_LIST,
191 SECTION_ID_PACKET_SIDE_DATA,
192 SECTION_ID_PIXEL_FORMAT,
193 SECTION_ID_PIXEL_FORMAT_FLAGS,
194 SECTION_ID_PIXEL_FORMAT_COMPONENT,
195 SECTION_ID_PIXEL_FORMAT_COMPONENTS,
196 SECTION_ID_PIXEL_FORMATS,
197 SECTION_ID_PROGRAM_STREAM_DISPOSITION,
198 SECTION_ID_PROGRAM_STREAM_TAGS,
199 SECTION_ID_PROGRAM,
200 SECTION_ID_PROGRAM_STREAMS,
201 SECTION_ID_PROGRAM_STREAM,
202 SECTION_ID_PROGRAM_TAGS,
203 SECTION_ID_PROGRAM_VERSION,
204 SECTION_ID_PROGRAMS,
205 SECTION_ID_ROOT,
206 SECTION_ID_STREAM,
207 SECTION_ID_STREAM_DISPOSITION,
208 SECTION_ID_STREAMS,
209 SECTION_ID_STREAM_TAGS,
210 SECTION_ID_STREAM_SIDE_DATA_LIST,
211 SECTION_ID_STREAM_SIDE_DATA,
212 SECTION_ID_SUBTITLE,
213 } SectionID;
214
215 static struct section sections[] = {
216 [SECTION_ID_CHAPTERS] = { SECTION_ID_CHAPTERS, "chapters", SECTION_FLAG_IS_ARRAY, { SECTION_ID_CHAPTER, -1 } },
217 [SECTION_ID_CHAPTER] = { SECTION_ID_CHAPTER, "chapter", 0, { SECTION_ID_CHAPTER_TAGS, -1 } },
218 [SECTION_ID_CHAPTER_TAGS] = { SECTION_ID_CHAPTER_TAGS, "tags", SECTION_FLAG_HAS_VARIABLE_FIELDS, { -1 }, .element_name = "tag", .unique_name = "chapter_tags" },
219 [SECTION_ID_ERROR] = { SECTION_ID_ERROR, "error", 0, { -1 } },
220 [SECTION_ID_FORMAT] = { SECTION_ID_FORMAT, "format", 0, { SECTION_ID_FORMAT_TAGS, -1 } },
221 [SECTION_ID_FORMAT_TAGS] = { SECTION_ID_FORMAT_TAGS, "tags", SECTION_FLAG_HAS_VARIABLE_FIELDS, { -1 }, .element_name = "tag", .unique_name = "format_tags" },
222 [SECTION_ID_FRAMES] = { SECTION_ID_FRAMES, "frames", SECTION_FLAG_IS_ARRAY, { SECTION_ID_FRAME, SECTION_ID_SUBTITLE, -1 } },
223 [SECTION_ID_FRAME] = { SECTION_ID_FRAME, "frame", 0, { SECTION_ID_FRAME_TAGS, SECTION_ID_FRAME_SIDE_DATA_LIST, SECTION_ID_FRAME_LOGS, -1 } },
224 [SECTION_ID_FRAME_TAGS] = { SECTION_ID_FRAME_TAGS, "tags", SECTION_FLAG_HAS_VARIABLE_FIELDS, { -1 }, .element_name = "tag", .unique_name = "frame_tags" },
225 [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" },
226 [SECTION_ID_FRAME_SIDE_DATA] = { SECTION_ID_FRAME_SIDE_DATA, "side_data", 0, { SECTION_ID_FRAME_SIDE_DATA_TIMECODE_LIST, SECTION_ID_FRAME_SIDE_DATA_COMPONENT_LIST, -1 } },
227 [SECTION_ID_FRAME_SIDE_DATA_TIMECODE_LIST] = { SECTION_ID_FRAME_SIDE_DATA_TIMECODE_LIST, "timecodes", SECTION_FLAG_IS_ARRAY, { SECTION_ID_FRAME_SIDE_DATA_TIMECODE, -1 } },
228 [SECTION_ID_FRAME_SIDE_DATA_TIMECODE] = { SECTION_ID_FRAME_SIDE_DATA_TIMECODE, "timecode", 0, { -1 } },
229 [SECTION_ID_FRAME_SIDE_DATA_COMPONENT_LIST] = { SECTION_ID_FRAME_SIDE_DATA_COMPONENT_LIST, "components", SECTION_FLAG_IS_ARRAY, { SECTION_ID_FRAME_SIDE_DATA_COMPONENT, -1 } },
230 [SECTION_ID_FRAME_SIDE_DATA_COMPONENT] = { SECTION_ID_FRAME_SIDE_DATA_COMPONENT, "component", 0, { SECTION_ID_FRAME_SIDE_DATA_PIECE_LIST, -1 } },
231 [SECTION_ID_FRAME_SIDE_DATA_PIECE_LIST] = { SECTION_ID_FRAME_SIDE_DATA_PIECE_LIST, "pieces", SECTION_FLAG_IS_ARRAY, { SECTION_ID_FRAME_SIDE_DATA_PIECE, -1 } },
232 [SECTION_ID_FRAME_SIDE_DATA_PIECE] = { SECTION_ID_FRAME_SIDE_DATA_PIECE, "section", 0, { -1 } },
233 [SECTION_ID_FRAME_LOGS] = { SECTION_ID_FRAME_LOGS, "logs", SECTION_FLAG_IS_ARRAY, { SECTION_ID_FRAME_LOG, -1 } },
234 [SECTION_ID_FRAME_LOG] = { SECTION_ID_FRAME_LOG, "log", 0, { -1 }, },
235 [SECTION_ID_LIBRARY_VERSIONS] = { SECTION_ID_LIBRARY_VERSIONS, "library_versions", SECTION_FLAG_IS_ARRAY, { SECTION_ID_LIBRARY_VERSION, -1 } },
236 [SECTION_ID_LIBRARY_VERSION] = { SECTION_ID_LIBRARY_VERSION, "library_version", 0, { -1 } },
237 [SECTION_ID_PACKETS] = { SECTION_ID_PACKETS, "packets", SECTION_FLAG_IS_ARRAY, { SECTION_ID_PACKET, -1} },
238 [SECTION_ID_PACKETS_AND_FRAMES] = { SECTION_ID_PACKETS_AND_FRAMES, "packets_and_frames", SECTION_FLAG_IS_ARRAY, { SECTION_ID_PACKET, -1} },
239 [SECTION_ID_PACKET] = { SECTION_ID_PACKET, "packet", 0, { SECTION_ID_PACKET_TAGS, SECTION_ID_PACKET_SIDE_DATA_LIST, -1 } },
240 [SECTION_ID_PACKET_TAGS] = { SECTION_ID_PACKET_TAGS, "tags", SECTION_FLAG_HAS_VARIABLE_FIELDS, { -1 }, .element_name = "tag", .unique_name = "packet_tags" },
241 [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" },
242 [SECTION_ID_PACKET_SIDE_DATA] = { SECTION_ID_PACKET_SIDE_DATA, "side_data", 0, { -1 } },
243 [SECTION_ID_PIXEL_FORMATS] = { SECTION_ID_PIXEL_FORMATS, "pixel_formats", SECTION_FLAG_IS_ARRAY, { SECTION_ID_PIXEL_FORMAT, -1 } },
244 [SECTION_ID_PIXEL_FORMAT] = { SECTION_ID_PIXEL_FORMAT, "pixel_format", 0, { SECTION_ID_PIXEL_FORMAT_FLAGS, SECTION_ID_PIXEL_FORMAT_COMPONENTS, -1 } },
245 [SECTION_ID_PIXEL_FORMAT_FLAGS] = { SECTION_ID_PIXEL_FORMAT_FLAGS, "flags", 0, { -1 }, .unique_name = "pixel_format_flags" },
246 [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" },
247 [SECTION_ID_PIXEL_FORMAT_COMPONENT] = { SECTION_ID_PIXEL_FORMAT_COMPONENT, "component", 0, { -1 } },
248 [SECTION_ID_PROGRAM_STREAM_DISPOSITION] = { SECTION_ID_PROGRAM_STREAM_DISPOSITION, "disposition", 0, { -1 }, .unique_name = "program_stream_disposition" },
249 [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" },
250 [SECTION_ID_PROGRAM] = { SECTION_ID_PROGRAM, "program", 0, { SECTION_ID_PROGRAM_TAGS, SECTION_ID_PROGRAM_STREAMS, -1 } },
251 [SECTION_ID_PROGRAM_STREAMS] = { SECTION_ID_PROGRAM_STREAMS, "streams", SECTION_FLAG_IS_ARRAY, { SECTION_ID_PROGRAM_STREAM, -1 }, .unique_name = "program_streams" },
252 [SECTION_ID_PROGRAM_STREAM] = { SECTION_ID_PROGRAM_STREAM, "stream", 0, { SECTION_ID_PROGRAM_STREAM_DISPOSITION, SECTION_ID_PROGRAM_STREAM_TAGS, -1 }, .unique_name = "program_stream" },
253 [SECTION_ID_PROGRAM_TAGS] = { SECTION_ID_PROGRAM_TAGS, "tags", SECTION_FLAG_HAS_VARIABLE_FIELDS, { -1 }, .element_name = "tag", .unique_name = "program_tags" },
254 [SECTION_ID_PROGRAM_VERSION] = { SECTION_ID_PROGRAM_VERSION, "program_version", 0, { -1 } },
255 [SECTION_ID_PROGRAMS] = { SECTION_ID_PROGRAMS, "programs", SECTION_FLAG_IS_ARRAY, { SECTION_ID_PROGRAM, -1 } },
256 [SECTION_ID_ROOT] = { SECTION_ID_ROOT, "root", SECTION_FLAG_IS_WRAPPER,
257 { SECTION_ID_CHAPTERS, SECTION_ID_FORMAT, SECTION_ID_FRAMES, SECTION_ID_PROGRAMS, SECTION_ID_STREAMS,
258 SECTION_ID_PACKETS, SECTION_ID_ERROR, SECTION_ID_PROGRAM_VERSION, SECTION_ID_LIBRARY_VERSIONS,
259 SECTION_ID_PIXEL_FORMATS, -1} },
260 [SECTION_ID_STREAMS] = { SECTION_ID_STREAMS, "streams", SECTION_FLAG_IS_ARRAY, { SECTION_ID_STREAM, -1 } },
261 [SECTION_ID_STREAM] = { SECTION_ID_STREAM, "stream", 0, { SECTION_ID_STREAM_DISPOSITION, SECTION_ID_STREAM_TAGS, SECTION_ID_STREAM_SIDE_DATA_LIST, -1 } },
262 [SECTION_ID_STREAM_DISPOSITION] = { SECTION_ID_STREAM_DISPOSITION, "disposition", 0, { -1 }, .unique_name = "stream_disposition" },
263 [SECTION_ID_STREAM_TAGS] = { SECTION_ID_STREAM_TAGS, "tags", SECTION_FLAG_HAS_VARIABLE_FIELDS, { -1 }, .element_name = "tag", .unique_name = "stream_tags" },
264 [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" },
265 [SECTION_ID_STREAM_SIDE_DATA] = { SECTION_ID_STREAM_SIDE_DATA, "side_data", 0, { -1 } },
266 [SECTION_ID_SUBTITLE] = { SECTION_ID_SUBTITLE, "subtitle", 0, { -1 } },
267 };
268
269 static const OptionDef *options;
270
271 /* FFprobe context */
272 static const char *input_filename;
273 static const char *print_input_filename;
274 static const AVInputFormat *iformat = NULL;
275
276 static struct AVHashContext *hash;
277
278 static const struct {
279 double bin_val;
280 double dec_val;
281 const char *bin_str;
282 const char *dec_str;
283 } si_prefixes[] = {
284 { 1.0, 1.0, "", "" },
285 { 1.024e3, 1e3, "Ki", "K" },
286 { 1.048576e6, 1e6, "Mi", "M" },
287 { 1.073741824e9, 1e9, "Gi", "G" },
288 { 1.099511627776e12, 1e12, "Ti", "T" },
289 { 1.125899906842624e15, 1e15, "Pi", "P" },
290 };
291
292 static const char unit_second_str[] = "s" ;
293 static const char unit_hertz_str[] = "Hz" ;
294 static const char unit_byte_str[] = "byte" ;
295 static const char unit_bit_per_second_str[] = "bit/s";
296
297 static int nb_streams;
298 static uint64_t *nb_streams_packets;
299 static uint64_t *nb_streams_frames;
300 static int *selected_streams;
301
302 #if HAVE_THREADS
303 pthread_mutex_t log_mutex;
304 #endif
305 typedef struct LogBuffer {
306 char *context_name;
307 int log_level;
308 char *log_message;
309 AVClassCategory category;
310 char *parent_name;
311 AVClassCategory parent_category;
312 }LogBuffer;
313
314 static LogBuffer *log_buffer;
315 static int log_buffer_size;
316
317 static void log_callback(void *ptr, int level, const char *fmt, va_list vl)
318 {
319 AVClass* avc = ptr ? *(AVClass **) ptr : NULL;
320 va_list vl2;
321 char line[1024];
322 static int print_prefix = 1;
323 void *new_log_buffer;
324
325 va_copy(vl2, vl);
326 av_log_default_callback(ptr, level, fmt, vl);
327 av_log_format_line(ptr, level, fmt, vl2, line, sizeof(line), &print_prefix);
328 va_end(vl2);
329
330 #if HAVE_THREADS
331 pthread_mutex_lock(&log_mutex);
332
333 new_log_buffer = av_realloc_array(log_buffer, log_buffer_size + 1, sizeof(*log_buffer));
334 if (new_log_buffer) {
335 char *msg;
336 int i;
337
338 log_buffer = new_log_buffer;
339 memset(&log_buffer[log_buffer_size], 0, sizeof(log_buffer[log_buffer_size]));
340 log_buffer[log_buffer_size].context_name= avc ? av_strdup(avc->item_name(ptr)) : NULL;
341 if (avc) {
342 if (avc->get_category) log_buffer[log_buffer_size].category = avc->get_category(ptr);
343 else log_buffer[log_buffer_size].category = avc->category;
344 }
345 log_buffer[log_buffer_size].log_level = level;
346 msg = log_buffer[log_buffer_size].log_message = av_strdup(line);
347 for (i=strlen(msg) - 1; i>=0 && msg[i] == '\n'; i--) {
348 msg[i] = 0;
349 }
350 if (avc && avc->parent_log_context_offset) {
351 AVClass** parent = *(AVClass ***) (((uint8_t *) ptr) +
352 avc->parent_log_context_offset);
353 if (parent && *parent) {
354 log_buffer[log_buffer_size].parent_name = av_strdup((*parent)->item_name(parent));
355 log_buffer[log_buffer_size].parent_category =
356 (*parent)->get_category ? (*parent)->get_category(parent) :(*parent)->category;
357 }
358 }
359 log_buffer_size ++;
360 }
361
362 pthread_mutex_unlock(&log_mutex);
363 #endif
364 }
365
366 static void ffprobe_cleanup(int ret)
367 {
368 int i;
369 for (i = 0; i < FF_ARRAY_ELEMS(sections); i++)
370 av_dict_free(&(sections[i].entries_to_show));
371
372 #if HAVE_THREADS
373 pthread_mutex_destroy(&log_mutex);
374 #endif
375 }
376
377 struct unit_value {
378 union { double d; long long int i; } val;
379 const char *unit;
380 };
381
382 37256 static char *value_string(char *buf, int buf_size, struct unit_value uv)
383 {
384 double vald;
385 long long int vali;
386 37256 int show_float = 0;
387
388
2/2
✓ Branch 0 taken 28504 times.
✓ Branch 1 taken 8752 times.
37256 if (uv.unit == unit_second_str) {
389 28504 vald = uv.val.d;
390 28504 show_float = 1;
391 } else {
392 8752 vald = vali = uv.val.i;
393 }
394
395
3/4
✓ Branch 0 taken 28504 times.
✓ Branch 1 taken 8752 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 28504 times.
37256 if (uv.unit == unit_second_str && use_value_sexagesimal_format) {
396 double secs;
397 int hours, mins;
398 secs = vald;
399 mins = (int)secs / 60;
400 secs = secs - mins * 60;
401 hours = mins / 60;
402 mins %= 60;
403 snprintf(buf, buf_size, "%d:%02d:%09.6f", hours, mins, secs);
404 } else {
405 37256 const char *prefix_string = "";
406
407
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 37256 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
37256 if (use_value_prefix && vald > 1) {
408 long long int index;
409
410 if (uv.unit == unit_byte_str && use_byte_value_binary_prefix) {
411 index = (long long int) (log2(vald)) / 10;
412 index = av_clip(index, 0, FF_ARRAY_ELEMS(si_prefixes) - 1);
413 vald /= si_prefixes[index].bin_val;
414 prefix_string = si_prefixes[index].bin_str;
415 } else {
416 index = (long long int) (log10(vald)) / 3;
417 index = av_clip(index, 0, FF_ARRAY_ELEMS(si_prefixes) - 1);
418 vald /= si_prefixes[index].dec_val;
419 prefix_string = si_prefixes[index].dec_str;
420 }
421 vali = vald;
422 }
423
424
3/6
✓ Branch 0 taken 8752 times.
✓ Branch 1 taken 28504 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 8752 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
37256 if (show_float || (use_value_prefix && vald != (long long int)vald))
425 28504 snprintf(buf, buf_size, "%f", vald);
426 else
427 8752 snprintf(buf, buf_size, "%lld", vali);
428
2/4
✓ Branch 0 taken 37256 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 37256 times.
37256 av_strlcatf(buf, buf_size, "%s%s%s", *prefix_string || show_value_unit ? " " : "",
429
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 37256 times.
37256 prefix_string, show_value_unit ? uv.unit : "");
430 }
431
432 37256 return buf;
433 }
434
435 /* WRITERS API */
436
437 typedef struct WriterContext WriterContext;
438
439 #define WRITER_FLAG_DISPLAY_OPTIONAL_FIELDS 1
440 #define WRITER_FLAG_PUT_PACKETS_AND_FRAMES_IN_SAME_CHAPTER 2
441
442 typedef enum {
443 WRITER_STRING_VALIDATION_FAIL,
444 WRITER_STRING_VALIDATION_REPLACE,
445 WRITER_STRING_VALIDATION_IGNORE,
446 WRITER_STRING_VALIDATION_NB
447 } StringValidation;
448
449 typedef struct Writer {
450 const AVClass *priv_class; ///< private class of the writer, if any
451 int priv_size; ///< private size for the writer context
452 const char *name;
453
454 int (*init) (WriterContext *wctx);
455 void (*uninit)(WriterContext *wctx);
456
457 void (*print_section_header)(WriterContext *wctx);
458 void (*print_section_footer)(WriterContext *wctx);
459 void (*print_integer) (WriterContext *wctx, const char *, long long int);
460 void (*print_rational) (WriterContext *wctx, AVRational *q, char *sep);
461 void (*print_string) (WriterContext *wctx, const char *, const char *);
462 int flags; ///< a combination or WRITER_FLAG_*
463 } Writer;
464
465 #define SECTION_MAX_NB_LEVELS 10
466
467 struct WriterContext {
468 const AVClass *class; ///< class of the writer
469 const Writer *writer; ///< the Writer of which this is an instance
470 char *name; ///< name of this writer instance
471 void *priv; ///< private data for use by the filter
472
473 const struct section *sections; ///< array containing all sections
474 int nb_sections; ///< number of sections
475
476 int level; ///< current level, starting from 0
477
478 /** number of the item printed in the given section, starting from 0 */
479 unsigned int nb_item[SECTION_MAX_NB_LEVELS];
480
481 /** section per each level */
482 const struct section *section[SECTION_MAX_NB_LEVELS];
483 AVBPrint section_pbuf[SECTION_MAX_NB_LEVELS]; ///< generic print buffer dedicated to each section,
484 /// used by various writers
485
486 unsigned int nb_section_packet; ///< number of the packet section in case we are in "packets_and_frames" section
487 unsigned int nb_section_frame; ///< number of the frame section in case we are in "packets_and_frames" section
488 unsigned int nb_section_packet_frame; ///< nb_section_packet or nb_section_frame according if is_packets_and_frames
489
490 int string_validation;
491 char *string_validation_replacement;
492 unsigned int string_validation_utf8_flags;
493 };
494
495 static const char *writer_get_name(void *p)
496 {
497 WriterContext *wctx = p;
498 return wctx->writer->name;
499 }
500
501 #define OFFSET(x) offsetof(WriterContext, x)
502
503 static const AVOption writer_options[] = {
504 { "string_validation", "set string validation mode",
505 OFFSET(string_validation), AV_OPT_TYPE_INT, {.i64=WRITER_STRING_VALIDATION_REPLACE}, 0, WRITER_STRING_VALIDATION_NB-1, .unit = "sv" },
506 { "sv", "set string validation mode",
507 OFFSET(string_validation), AV_OPT_TYPE_INT, {.i64=WRITER_STRING_VALIDATION_REPLACE}, 0, WRITER_STRING_VALIDATION_NB-1, .unit = "sv" },
508 { "ignore", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = WRITER_STRING_VALIDATION_IGNORE}, .unit = "sv" },
509 { "replace", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = WRITER_STRING_VALIDATION_REPLACE}, .unit = "sv" },
510 { "fail", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = WRITER_STRING_VALIDATION_FAIL}, .unit = "sv" },
511 { "string_validation_replacement", "set string validation replacement string", OFFSET(string_validation_replacement), AV_OPT_TYPE_STRING, {.str=""}},
512 { "svr", "set string validation replacement string", OFFSET(string_validation_replacement), AV_OPT_TYPE_STRING, {.str="\xEF\xBF\xBD"}},
513 { NULL }
514 };
515
516 28 static void *writer_child_next(void *obj, void *prev)
517 {
518 28 WriterContext *ctx = obj;
519
4/8
✓ Branch 0 taken 28 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 28 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 28 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 28 times.
✗ Branch 7 not taken.
28 if (!prev && ctx->writer && ctx->writer->priv_class && ctx->priv)
520 28 return ctx->priv;
521 return NULL;
522 }
523
524 static const AVClass writer_class = {
525 .class_name = "Writer",
526 .item_name = writer_get_name,
527 .option = writer_options,
528 .version = LIBAVUTIL_VERSION_INT,
529 .child_next = writer_child_next,
530 };
531
532 107 static void writer_close(WriterContext **wctx)
533 {
534 int i;
535
536
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 107 times.
107 if (!*wctx)
537 return;
538
539
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 107 times.
107 if ((*wctx)->writer->uninit)
540 (*wctx)->writer->uninit(*wctx);
541
2/2
✓ Branch 0 taken 1070 times.
✓ Branch 1 taken 107 times.
1177 for (i = 0; i < SECTION_MAX_NB_LEVELS; i++)
542 1070 av_bprint_finalize(&(*wctx)->section_pbuf[i], NULL);
543
1/2
✓ Branch 0 taken 107 times.
✗ Branch 1 not taken.
107 if ((*wctx)->writer->priv_class)
544 107 av_opt_free((*wctx)->priv);
545 107 av_freep(&((*wctx)->priv));
546 107 av_opt_free(*wctx);
547 107 av_freep(wctx);
548 }
549
550 static void bprint_bytes(AVBPrint *bp, const uint8_t *ubuf, size_t ubuf_size)
551 {
552 int i;
553 av_bprintf(bp, "0X");
554 for (i = 0; i < ubuf_size; i++)
555 av_bprintf(bp, "%02X", ubuf[i]);
556 }
557
558
559 107 static int writer_open(WriterContext **wctx, const Writer *writer, const char *args,
560 const struct section *sections, int nb_sections)
561 {
562 107 int i, ret = 0;
563
564
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 107 times.
107 if (!(*wctx = av_mallocz(sizeof(WriterContext)))) {
565 ret = AVERROR(ENOMEM);
566 goto fail;
567 }
568
569
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 107 times.
107 if (!((*wctx)->priv = av_mallocz(writer->priv_size))) {
570 ret = AVERROR(ENOMEM);
571 goto fail;
572 }
573
574 107 (*wctx)->class = &writer_class;
575 107 (*wctx)->writer = writer;
576 107 (*wctx)->level = -1;
577 107 (*wctx)->sections = sections;
578 107 (*wctx)->nb_sections = nb_sections;
579
580 107 av_opt_set_defaults(*wctx);
581
582
1/2
✓ Branch 0 taken 107 times.
✗ Branch 1 not taken.
107 if (writer->priv_class) {
583 107 void *priv_ctx = (*wctx)->priv;
584 107 *((const AVClass **)priv_ctx) = writer->priv_class;
585 107 av_opt_set_defaults(priv_ctx);
586 }
587
588 /* convert options to dictionary */
589
2/2
✓ Branch 0 taken 20 times.
✓ Branch 1 taken 87 times.
107 if (args) {
590 20 AVDictionary *opts = NULL;
591 20 const AVDictionaryEntry *opt = NULL;
592
593
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 20 times.
20 if ((ret = av_dict_parse_string(&opts, args, "=", ":", 0)) < 0) {
594 av_log(*wctx, AV_LOG_ERROR, "Failed to parse option string '%s' provided to writer context\n", args);
595 av_dict_free(&opts);
596 goto fail;
597 }
598
599
2/2
✓ Branch 1 taken 28 times.
✓ Branch 2 taken 20 times.
48 while ((opt = av_dict_get(opts, "", opt, AV_DICT_IGNORE_SUFFIX))) {
600
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 28 times.
28 if ((ret = av_opt_set(*wctx, opt->key, opt->value, AV_OPT_SEARCH_CHILDREN)) < 0) {
601 av_log(*wctx, AV_LOG_ERROR, "Failed to set option '%s' with value '%s' provided to writer context\n",
602 opt->key, opt->value);
603 av_dict_free(&opts);
604 goto fail;
605 }
606 }
607
608 20 av_dict_free(&opts);
609 }
610
611 /* validate replace string */
612 {
613 107 const uint8_t *p = (*wctx)->string_validation_replacement;
614 107 const uint8_t *endp = p + strlen(p);
615
2/2
✓ Branch 0 taken 107 times.
✓ Branch 1 taken 107 times.
214 while (*p) {
616 107 const uint8_t *p0 = p;
617 int32_t code;
618 107 ret = av_utf8_decode(&code, &p, endp, (*wctx)->string_validation_utf8_flags);
619
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 107 times.
107 if (ret < 0) {
620 AVBPrint bp;
621 av_bprint_init(&bp, 0, AV_BPRINT_SIZE_AUTOMATIC);
622 bprint_bytes(&bp, p0, p-p0),
623 av_log(wctx, AV_LOG_ERROR,
624 "Invalid UTF8 sequence %s found in string validation replace '%s'\n",
625 bp.str, (*wctx)->string_validation_replacement);
626 return ret;
627 }
628 }
629 }
630
631
2/2
✓ Branch 0 taken 1070 times.
✓ Branch 1 taken 107 times.
1177 for (i = 0; i < SECTION_MAX_NB_LEVELS; i++)
632 1070 av_bprint_init(&(*wctx)->section_pbuf[i], 1, AV_BPRINT_SIZE_UNLIMITED);
633
634
2/2
✓ Branch 0 taken 43 times.
✓ Branch 1 taken 64 times.
107 if ((*wctx)->writer->init)
635 43 ret = (*wctx)->writer->init(*wctx);
636
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 107 times.
107 if (ret < 0)
637 goto fail;
638
639 107 return 0;
640
641 fail:
642 writer_close(wctx);
643 return ret;
644 }
645
646 11677 static inline void writer_print_section_header(WriterContext *wctx,
647 int section_id)
648 {
649 int parent_section_id;
650 11677 wctx->level++;
651
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11677 times.
11677 av_assert0(wctx->level < SECTION_MAX_NB_LEVELS);
652 23354 parent_section_id = wctx->level ?
653
2/2
✓ Branch 0 taken 11570 times.
✓ Branch 1 taken 107 times.
11677 (wctx->section[wctx->level-1])->id : SECTION_ID_NONE;
654
655 11677 wctx->nb_item[wctx->level] = 0;
656 11677 wctx->section[wctx->level] = &wctx->sections[section_id];
657
658
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 11672 times.
11677 if (section_id == SECTION_ID_PACKETS_AND_FRAMES) {
659 5 wctx->nb_section_packet = wctx->nb_section_frame =
660 5 wctx->nb_section_packet_frame = 0;
661
2/2
✓ Branch 0 taken 140 times.
✓ Branch 1 taken 11532 times.
11672 } else if (parent_section_id == SECTION_ID_PACKETS_AND_FRAMES) {
662 140 wctx->nb_section_packet_frame = section_id == SECTION_ID_PACKET ?
663
2/2
✓ Branch 0 taken 70 times.
✓ Branch 1 taken 70 times.
140 wctx->nb_section_packet : wctx->nb_section_frame;
664 }
665
666
1/2
✓ Branch 0 taken 11677 times.
✗ Branch 1 not taken.
11677 if (wctx->writer->print_section_header)
667 11677 wctx->writer->print_section_header(wctx);
668 11677 }
669
670 11677 static inline void writer_print_section_footer(WriterContext *wctx)
671 {
672 11677 int section_id = wctx->section[wctx->level]->id;
673 23354 int parent_section_id = wctx->level ?
674
2/2
✓ Branch 0 taken 11570 times.
✓ Branch 1 taken 107 times.
11677 wctx->section[wctx->level-1]->id : SECTION_ID_NONE;
675
676
2/2
✓ Branch 0 taken 11570 times.
✓ Branch 1 taken 107 times.
11677 if (parent_section_id != SECTION_ID_NONE)
677 11570 wctx->nb_item[wctx->level-1]++;
678
2/2
✓ Branch 0 taken 140 times.
✓ Branch 1 taken 11537 times.
11677 if (parent_section_id == SECTION_ID_PACKETS_AND_FRAMES) {
679
2/2
✓ Branch 0 taken 70 times.
✓ Branch 1 taken 70 times.
140 if (section_id == SECTION_ID_PACKET) wctx->nb_section_packet++;
680 70 else wctx->nb_section_frame++;
681 }
682
2/2
✓ Branch 0 taken 11593 times.
✓ Branch 1 taken 84 times.
11677 if (wctx->writer->print_section_footer)
683 11593 wctx->writer->print_section_footer(wctx);
684 11677 wctx->level--;
685 11677 }
686
687 51902 static inline void writer_print_integer(WriterContext *wctx,
688 const char *key, long long int val)
689 {
690 51902 const struct section *section = wctx->section[wctx->level];
691
692
4/4
✓ Branch 0 taken 32143 times.
✓ Branch 1 taken 19759 times.
✓ Branch 3 taken 16741 times.
✓ Branch 4 taken 15402 times.
51902 if (section->show_all_entries || av_dict_get(section->entries_to_show, key, NULL, 0)) {
693 36500 wctx->writer->print_integer(wctx, key, val);
694 36500 wctx->nb_item[wctx->level]++;
695 }
696 51902 }
697
698 5282 static inline int validate_string(WriterContext *wctx, char **dstp, const char *src)
699 {
700 const uint8_t *p, *endp;
701 AVBPrint dstbuf;
702 5282 int invalid_chars_nb = 0, ret = 0;
703
704 5282 av_bprint_init(&dstbuf, 0, AV_BPRINT_SIZE_UNLIMITED);
705
706 5282 endp = src + strlen(src);
707
2/2
✓ Branch 0 taken 82460 times.
✓ Branch 1 taken 5282 times.
87742 for (p = (uint8_t *)src; *p;) {
708 uint32_t code;
709 82460 int invalid = 0;
710 82460 const uint8_t *p0 = p;
711
712
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 82460 times.
82460 if (av_utf8_decode(&code, &p, endp, wctx->string_validation_utf8_flags) < 0) {
713 AVBPrint bp;
714 av_bprint_init(&bp, 0, AV_BPRINT_SIZE_AUTOMATIC);
715 bprint_bytes(&bp, p0, p-p0);
716 av_log(wctx, AV_LOG_DEBUG,
717 "Invalid UTF-8 sequence %s found in string '%s'\n", bp.str, src);
718 invalid = 1;
719 }
720
721
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 82460 times.
82460 if (invalid) {
722 invalid_chars_nb++;
723
724 switch (wctx->string_validation) {
725 case WRITER_STRING_VALIDATION_FAIL:
726 av_log(wctx, AV_LOG_ERROR,
727 "Invalid UTF-8 sequence found in string '%s'\n", src);
728 ret = AVERROR_INVALIDDATA;
729 goto end;
730 break;
731
732 case WRITER_STRING_VALIDATION_REPLACE:
733 av_bprintf(&dstbuf, "%s", wctx->string_validation_replacement);
734 break;
735 }
736 }
737
738
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 82460 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
82460 if (!invalid || wctx->string_validation == WRITER_STRING_VALIDATION_IGNORE)
739 82460 av_bprint_append_data(&dstbuf, p0, p-p0);
740 }
741
742
1/4
✓ Branch 0 taken 5282 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
5282 if (invalid_chars_nb && wctx->string_validation == WRITER_STRING_VALIDATION_REPLACE) {
743 av_log(wctx, AV_LOG_WARNING,
744 "%d invalid UTF-8 sequence(s) found in string '%s', replaced with '%s'\n",
745 invalid_chars_nb, src, wctx->string_validation_replacement);
746 }
747
748 5282 end:
749 5282 av_bprint_finalize(&dstbuf, dstp);
750 5282 return ret;
751 }
752
753 #define PRINT_STRING_OPT 1
754 #define PRINT_STRING_VALIDATE 2
755
756 78543 static inline int writer_print_string(WriterContext *wctx,
757 const char *key, const char *val, int flags)
758 {
759 78543 const struct section *section = wctx->section[wctx->level];
760 78543 int ret = 0;
761
762
1/2
✓ Branch 0 taken 78543 times.
✗ Branch 1 not taken.
78543 if (show_optional_fields == SHOW_OPTIONAL_FIELDS_NEVER ||
763
1/2
✓ Branch 0 taken 78543 times.
✗ Branch 1 not taken.
78543 (show_optional_fields == SHOW_OPTIONAL_FIELDS_AUTO
764
2/2
✓ Branch 0 taken 4882 times.
✓ Branch 1 taken 73661 times.
78543 && (flags & PRINT_STRING_OPT)
765
2/2
✓ Branch 0 taken 268 times.
✓ Branch 1 taken 4614 times.
4882 && !(wctx->writer->flags & WRITER_FLAG_DISPLAY_OPTIONAL_FIELDS)))
766 268 return 0;
767
768
4/4
✓ Branch 0 taken 42380 times.
✓ Branch 1 taken 35895 times.
✓ Branch 3 taken 2108 times.
✓ Branch 4 taken 40272 times.
78275 if (section->show_all_entries || av_dict_get(section->entries_to_show, key, NULL, 0)) {
769
2/2
✓ Branch 0 taken 2641 times.
✓ Branch 1 taken 35362 times.
38003 if (flags & PRINT_STRING_VALIDATE) {
770 2641 char *key1 = NULL, *val1 = NULL;
771 2641 ret = validate_string(wctx, &key1, key);
772
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2641 times.
2641 if (ret < 0) goto end;
773 2641 ret = validate_string(wctx, &val1, val);
774
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2641 times.
2641 if (ret < 0) goto end;
775 2641 wctx->writer->print_string(wctx, key1, val1);
776 2641 end:
777
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2641 times.
2641 if (ret < 0) {
778 av_log(wctx, AV_LOG_ERROR,
779 "Invalid key=value string combination %s=%s in section %s\n",
780 key, val, section->unique_name);
781 }
782 2641 av_free(key1);
783 2641 av_free(val1);
784 } else {
785 35362 wctx->writer->print_string(wctx, key, val);
786 }
787
788 38003 wctx->nb_item[wctx->level]++;
789 }
790
791 78275 return ret;
792 }
793
794 1085 static inline void writer_print_rational(WriterContext *wctx,
795 const char *key, AVRational q, char sep)
796 {
797 AVBPrint buf;
798 1085 av_bprint_init(&buf, 0, AV_BPRINT_SIZE_AUTOMATIC);
799 1085 av_bprintf(&buf, "%d%c%d", q.num, sep, q.den);
800 1085 writer_print_string(wctx, key, buf.str, 0);
801 1085 }
802
803 29093 static void writer_print_time(WriterContext *wctx, const char *key,
804 int64_t ts, const AVRational *time_base, int is_duration)
805 {
806 char buf[128];
807
808
8/8
✓ Branch 0 taken 20537 times.
✓ Branch 1 taken 8556 times.
✓ Branch 2 taken 19971 times.
✓ Branch 3 taken 566 times.
✓ Branch 4 taken 8556 times.
✓ Branch 5 taken 19971 times.
✓ Branch 6 taken 23 times.
✓ Branch 7 taken 8533 times.
29093 if ((!is_duration && ts == AV_NOPTS_VALUE) || (is_duration && ts == 0)) {
809 589 writer_print_string(wctx, key, "N/A", PRINT_STRING_OPT);
810 } else {
811 28504 double d = ts * av_q2d(*time_base);
812 struct unit_value uv;
813 28504 uv.val.d = d;
814 28504 uv.unit = unit_second_str;
815 28504 value_string(buf, sizeof(buf), uv);
816 28504 writer_print_string(wctx, key, buf, 0);
817 }
818 29093 }
819
820 28989 static void writer_print_ts(WriterContext *wctx, const char *key, int64_t ts, int is_duration)
821 {
822
8/8
✓ Branch 0 taken 20433 times.
✓ Branch 1 taken 8556 times.
✓ Branch 2 taken 19868 times.
✓ Branch 3 taken 565 times.
✓ Branch 4 taken 8556 times.
✓ Branch 5 taken 19868 times.
✓ Branch 6 taken 23 times.
✓ Branch 7 taken 8533 times.
28989 if ((!is_duration && ts == AV_NOPTS_VALUE) || (is_duration && ts == 0)) {
823 588 writer_print_string(wctx, key, "N/A", PRINT_STRING_OPT);
824 } else {
825 28401 writer_print_integer(wctx, key, ts);
826 }
827 28989 }
828
829 static void writer_print_data(WriterContext *wctx, const char *name,
830 uint8_t *data, int size)
831 {
832 AVBPrint bp;
833 int offset = 0, l, i;
834
835 av_bprint_init(&bp, 0, AV_BPRINT_SIZE_UNLIMITED);
836 av_bprintf(&bp, "\n");
837 while (size) {
838 av_bprintf(&bp, "%08x: ", offset);
839 l = FFMIN(size, 16);
840 for (i = 0; i < l; i++) {
841 av_bprintf(&bp, "%02x", data[i]);
842 if (i & 1)
843 av_bprintf(&bp, " ");
844 }
845 av_bprint_chars(&bp, ' ', 41 - 2 * i - i / 2);
846 for (i = 0; i < l; i++)
847 av_bprint_chars(&bp, data[i] - 32U < 95 ? data[i] : '.', 1);
848 av_bprintf(&bp, "\n");
849 offset += l;
850 data += l;
851 size -= l;
852 }
853 writer_print_string(wctx, name, bp.str, 0);
854 av_bprint_finalize(&bp, NULL);
855 }
856
857 5589 static void writer_print_data_hash(WriterContext *wctx, const char *name,
858 uint8_t *data, int size)
859 {
860 5589 char *p, buf[AV_HASH_MAX_SIZE * 2 + 64] = { 0 };
861
862
2/2
✓ Branch 0 taken 3647 times.
✓ Branch 1 taken 1942 times.
5589 if (!hash)
863 3647 return;
864 1942 av_hash_init(hash);
865 1942 av_hash_update(hash, data, size);
866 1942 snprintf(buf, sizeof(buf), "%s:", av_hash_get_name(hash));
867 1942 p = buf + strlen(buf);
868 1942 av_hash_final_hex(hash, p, buf + sizeof(buf) - p);
869 1942 writer_print_string(wctx, name, buf, 0);
870 }
871
872 2 static void writer_print_integers(WriterContext *wctx, const char *name,
873 uint8_t *data, int size, const char *format,
874 int columns, int bytes, int offset_add)
875 {
876 AVBPrint bp;
877 2 int offset = 0, l, i;
878
879 2 av_bprint_init(&bp, 0, AV_BPRINT_SIZE_UNLIMITED);
880 2 av_bprintf(&bp, "\n");
881
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 2 times.
8 while (size) {
882 6 av_bprintf(&bp, "%08x: ", offset);
883 6 l = FFMIN(size, columns);
884
2/2
✓ Branch 0 taken 18 times.
✓ Branch 1 taken 6 times.
24 for (i = 0; i < l; i++) {
885
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
18 if (bytes == 1) av_bprintf(&bp, format, *data);
886
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
18 else if (bytes == 2) av_bprintf(&bp, format, AV_RN16(data));
887
1/2
✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
18 else if (bytes == 4) av_bprintf(&bp, format, AV_RN32(data));
888 18 data += bytes;
889 18 size --;
890 }
891 6 av_bprintf(&bp, "\n");
892 6 offset += offset_add;
893 }
894 2 writer_print_string(wctx, name, bp.str, 0);
895 2 av_bprint_finalize(&bp, NULL);
896 2 }
897
898 #define MAX_REGISTERED_WRITERS_NB 64
899
900 static const Writer *registered_writers[MAX_REGISTERED_WRITERS_NB + 1];
901
902 749 static int writer_register(const Writer *writer)
903 {
904 static int next_registered_writer_idx = 0;
905
906
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 749 times.
749 if (next_registered_writer_idx == MAX_REGISTERED_WRITERS_NB)
907 return AVERROR(ENOMEM);
908
909 749 registered_writers[next_registered_writer_idx++] = writer;
910 749 return 0;
911 }
912
913 107 static const Writer *writer_get_by_name(const char *name)
914 {
915 int i;
916
917
1/2
✓ Branch 0 taken 183 times.
✗ Branch 1 not taken.
183 for (i = 0; registered_writers[i]; i++)
918
2/2
✓ Branch 0 taken 107 times.
✓ Branch 1 taken 76 times.
183 if (!strcmp(registered_writers[i]->name, name))
919 107 return registered_writers[i];
920
921 return NULL;
922 }
923
924
925 /* WRITERS */
926
927 #define DEFINE_WRITER_CLASS(name) \
928 static const char *name##_get_name(void *ctx) \
929 { \
930 return #name ; \
931 } \
932 static const AVClass name##_class = { \
933 .class_name = #name, \
934 .item_name = name##_get_name, \
935 .option = name##_options \
936 }
937
938 /* Default output */
939
940 typedef struct DefaultContext {
941 const AVClass *class;
942 int nokey;
943 int noprint_wrappers;
944 int nested_section[SECTION_MAX_NB_LEVELS];
945 } DefaultContext;
946
947 #undef OFFSET
948 #define OFFSET(x) offsetof(DefaultContext, x)
949
950 static const AVOption default_options[] = {
951 { "noprint_wrappers", "do not print headers and footers", OFFSET(noprint_wrappers), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1 },
952 { "nw", "do not print headers and footers", OFFSET(noprint_wrappers), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1 },
953 { "nokey", "force no key printing", OFFSET(nokey), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1 },
954 { "nk", "force no key printing", OFFSET(nokey), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1 },
955 {NULL},
956 };
957
958 DEFINE_WRITER_CLASS(default);
959
960 /* lame uppercasing routine, assumes the string is lower case ASCII */
961 2790 static inline char *upcase_string(char *dst, size_t dst_size, const char *src)
962 {
963 int i;
964
3/4
✓ Branch 0 taken 17852 times.
✓ Branch 1 taken 2790 times.
✓ Branch 2 taken 17852 times.
✗ Branch 3 not taken.
20642 for (i = 0; src[i] && i < dst_size-1; i++)
965 17852 dst[i] = av_toupper(src[i]);
966 2790 dst[i] = 0;
967 2790 return dst;
968 }
969
970 1743 static void default_print_section_header(WriterContext *wctx)
971 {
972 1743 DefaultContext *def = wctx->priv;
973 char buf[32];
974 1743 const struct section *section = wctx->section[wctx->level];
975 3486 const struct section *parent_section = wctx->level ?
976
2/2
✓ Branch 0 taken 1680 times.
✓ Branch 1 taken 63 times.
1743 wctx->section[wctx->level-1] : NULL;
977
978 1743 av_bprint_clear(&wctx->section_pbuf[wctx->level]);
979
2/2
✓ Branch 0 taken 1680 times.
✓ Branch 1 taken 63 times.
1743 if (parent_section &&
980
2/2
✓ Branch 0 taken 380 times.
✓ Branch 1 taken 1300 times.
1680 !(parent_section->flags & (SECTION_FLAG_IS_WRAPPER|SECTION_FLAG_IS_ARRAY))) {
981 380 def->nested_section[wctx->level] = 1;
982 380 av_bprintf(&wctx->section_pbuf[wctx->level], "%s%s:",
983 380 wctx->section_pbuf[wctx->level-1].str,
984 upcase_string(buf, sizeof(buf),
985 380 av_x_if_null(section->element_name, section->name)));
986 }
987
988
4/4
✓ Branch 0 taken 1735 times.
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 380 times.
✓ Branch 3 taken 1355 times.
1743 if (def->noprint_wrappers || def->nested_section[wctx->level])
989 388 return;
990
991
2/2
✓ Branch 0 taken 1205 times.
✓ Branch 1 taken 150 times.
1355 if (!(section->flags & (SECTION_FLAG_IS_WRAPPER|SECTION_FLAG_IS_ARRAY)))
992 1205 printf("[%s]\n", upcase_string(buf, sizeof(buf), section->name));
993 }
994
995 1743 static void default_print_section_footer(WriterContext *wctx)
996 {
997 1743 DefaultContext *def = wctx->priv;
998 1743 const struct section *section = wctx->section[wctx->level];
999 char buf[32];
1000
1001
4/4
✓ Branch 0 taken 1735 times.
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 380 times.
✓ Branch 3 taken 1355 times.
1743 if (def->noprint_wrappers || def->nested_section[wctx->level])
1002 388 return;
1003
1004
2/2
✓ Branch 0 taken 1205 times.
✓ Branch 1 taken 150 times.
1355 if (!(section->flags & (SECTION_FLAG_IS_WRAPPER|SECTION_FLAG_IS_ARRAY)))
1005 1205 printf("[/%s]\n", upcase_string(buf, sizeof(buf), section->name));
1006 }
1007
1008 7306 static void default_print_str(WriterContext *wctx, const char *key, const char *value)
1009 {
1010 7306 DefaultContext *def = wctx->priv;
1011
1012
2/2
✓ Branch 0 taken 7302 times.
✓ Branch 1 taken 4 times.
7306 if (!def->nokey)
1013 7302 printf("%s%s=", wctx->section_pbuf[wctx->level].str, key);
1014 7306 printf("%s\n", value);
1015 7306 }
1016
1017 4645 static void default_print_int(WriterContext *wctx, const char *key, long long int value)
1018 {
1019 4645 DefaultContext *def = wctx->priv;
1020
1021
1/2
✓ Branch 0 taken 4645 times.
✗ Branch 1 not taken.
4645 if (!def->nokey)
1022 4645 printf("%s%s=", wctx->section_pbuf[wctx->level].str, key);
1023 4645 printf("%lld\n", value);
1024 4645 }
1025
1026 static const Writer default_writer = {
1027 .name = "default",
1028 .priv_size = sizeof(DefaultContext),
1029 .print_section_header = default_print_section_header,
1030 .print_section_footer = default_print_section_footer,
1031 .print_integer = default_print_int,
1032 .print_string = default_print_str,
1033 .flags = WRITER_FLAG_DISPLAY_OPTIONAL_FIELDS,
1034 .priv_class = &default_class,
1035 };
1036
1037 /* Compact output */
1038
1039 /**
1040 * Apply C-language-like string escaping.
1041 */
1042 28737 static const char *c_escape_str(AVBPrint *dst, const char *src, const char sep, void *log_ctx)
1043 {
1044 const char *p;
1045
1046
2/2
✓ Branch 0 taken 180468 times.
✓ Branch 1 taken 28737 times.
209205 for (p = src; *p; p++) {
1047
2/6
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 180464 times.
180468 switch (*p) {
1048 case '\b': av_bprintf(dst, "%s", "\\b"); break;
1049 case '\f': av_bprintf(dst, "%s", "\\f"); break;
1050 4 case '\n': av_bprintf(dst, "%s", "\\n"); break;
1051 case '\r': av_bprintf(dst, "%s", "\\r"); break;
1052 case '\\': av_bprintf(dst, "%s", "\\\\"); break;
1053 180464 default:
1054
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 180464 times.
180464 if (*p == sep)
1055 av_bprint_chars(dst, '\\', 1);
1056 180464 av_bprint_chars(dst, *p, 1);
1057 }
1058 }
1059 28737 return dst->str;
1060 }
1061
1062 /**
1063 * Quote fields containing special characters, check RFC4180.
1064 */
1065 362 static const char *csv_escape_str(AVBPrint *dst, const char *src, const char sep, void *log_ctx)
1066 {
1067 362 char meta_chars[] = { sep, '"', '\n', '\r', '\0' };
1068 362 int needs_quoting = !!src[strcspn(src, meta_chars)];
1069
1070
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 361 times.
362 if (needs_quoting)
1071 1 av_bprint_chars(dst, '"', 1);
1072
1073
2/2
✓ Branch 0 taken 2312 times.
✓ Branch 1 taken 362 times.
2674 for (; *src; src++) {
1074
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2310 times.
2312 if (*src == '"')
1075 2 av_bprint_chars(dst, '"', 1);
1076 2312 av_bprint_chars(dst, *src, 1);
1077 }
1078
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 361 times.
362 if (needs_quoting)
1079 1 av_bprint_chars(dst, '"', 1);
1080 362 return dst->str;
1081 }
1082
1083 static const char *none_escape_str(AVBPrint *dst, const char *src, const char sep, void *log_ctx)
1084 {
1085 return src;
1086 }
1087
1088 typedef struct CompactContext {
1089 const AVClass *class;
1090 char *item_sep_str;
1091 char item_sep;
1092 int nokey;
1093 int print_section;
1094 char *escape_mode_str;
1095 const char * (*escape_str)(AVBPrint *dst, const char *src, const char sep, void *log_ctx);
1096 int nested_section[SECTION_MAX_NB_LEVELS];
1097 int has_nested_elems[SECTION_MAX_NB_LEVELS];
1098 int terminate_line[SECTION_MAX_NB_LEVELS];
1099 } CompactContext;
1100
1101 #undef OFFSET
1102 #define OFFSET(x) offsetof(CompactContext, x)
1103
1104 static const AVOption compact_options[]= {
1105 {"item_sep", "set item separator", OFFSET(item_sep_str), AV_OPT_TYPE_STRING, {.str="|"}, 0, 0 },
1106 {"s", "set item separator", OFFSET(item_sep_str), AV_OPT_TYPE_STRING, {.str="|"}, 0, 0 },
1107 {"nokey", "force no key printing", OFFSET(nokey), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1 },
1108 {"nk", "force no key printing", OFFSET(nokey), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1 },
1109 {"escape", "set escape mode", OFFSET(escape_mode_str), AV_OPT_TYPE_STRING, {.str="c"}, 0, 0 },
1110 {"e", "set escape mode", OFFSET(escape_mode_str), AV_OPT_TYPE_STRING, {.str="c"}, 0, 0 },
1111 {"print_section", "print section name", OFFSET(print_section), AV_OPT_TYPE_BOOL, {.i64=1}, 0, 1 },
1112 {"p", "print section name", OFFSET(print_section), AV_OPT_TYPE_BOOL, {.i64=1}, 0, 1 },
1113 {NULL},
1114 };
1115
1116 DEFINE_WRITER_CLASS(compact);
1117
1118 36 static av_cold int compact_init(WriterContext *wctx)
1119 {
1120 36 CompactContext *compact = wctx->priv;
1121
1122
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 36 times.
36 if (strlen(compact->item_sep_str) != 1) {
1123 av_log(wctx, AV_LOG_ERROR, "Item separator '%s' specified, but must contain a single character\n",
1124 compact->item_sep_str);
1125 return AVERROR(EINVAL);
1126 }
1127 36 compact->item_sep = compact->item_sep_str[0];
1128
1129
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 36 times.
36 if (!strcmp(compact->escape_mode_str, "none")) compact->escape_str = none_escape_str;
1130
2/2
✓ Branch 0 taken 35 times.
✓ Branch 1 taken 1 times.
36 else if (!strcmp(compact->escape_mode_str, "c" )) compact->escape_str = c_escape_str;
1131
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 else if (!strcmp(compact->escape_mode_str, "csv" )) compact->escape_str = csv_escape_str;
1132 else {
1133 av_log(wctx, AV_LOG_ERROR, "Unknown escape mode '%s'\n", compact->escape_mode_str);
1134 return AVERROR(EINVAL);
1135 }
1136
1137 36 return 0;
1138 }
1139
1140 9699 static void compact_print_section_header(WriterContext *wctx)
1141 {
1142 9699 CompactContext *compact = wctx->priv;
1143 9699 const struct section *section = wctx->section[wctx->level];
1144 19398 const struct section *parent_section = wctx->level ?
1145
2/2
✓ Branch 0 taken 9663 times.
✓ Branch 1 taken 36 times.
9699 wctx->section[wctx->level-1] : NULL;
1146 9699 compact->terminate_line[wctx->level] = 1;
1147 9699 compact->has_nested_elems[wctx->level] = 0;
1148
1149 9699 av_bprint_clear(&wctx->section_pbuf[wctx->level]);
1150
4/4
✓ Branch 0 taken 8855 times.
✓ Branch 1 taken 844 times.
✓ Branch 2 taken 8819 times.
✓ Branch 3 taken 36 times.
9699 if (!(section->flags & SECTION_FLAG_IS_ARRAY) && parent_section &&
1151
2/2
✓ Branch 0 taken 479 times.
✓ Branch 1 taken 8340 times.
8819 !(parent_section->flags & (SECTION_FLAG_IS_WRAPPER|SECTION_FLAG_IS_ARRAY))) {
1152 479 compact->nested_section[wctx->level] = 1;
1153 479 compact->has_nested_elems[wctx->level-1] = 1;
1154 479 av_bprintf(&wctx->section_pbuf[wctx->level], "%s%s:",
1155 479 wctx->section_pbuf[wctx->level-1].str,
1156 479 (char *)av_x_if_null(section->element_name, section->name));
1157 479 wctx->nb_item[wctx->level] = wctx->nb_item[wctx->level-1];
1158 } else {
1159
4/4
✓ Branch 0 taken 9184 times.
✓ Branch 1 taken 36 times.
✓ Branch 2 taken 36 times.
✓ Branch 3 taken 9148 times.
9220 if (parent_section && compact->has_nested_elems[wctx->level-1] &&
1160
1/2
✓ Branch 0 taken 36 times.
✗ Branch 1 not taken.
36 (section->flags & SECTION_FLAG_IS_ARRAY)) {
1161 36 compact->terminate_line[wctx->level-1] = 0;
1162 }
1163
4/4
✓ Branch 0 taken 9184 times.
✓ Branch 1 taken 36 times.
✓ Branch 2 taken 780 times.
✓ Branch 3 taken 8404 times.
9220 if (parent_section && !(parent_section->flags & (SECTION_FLAG_IS_WRAPPER|SECTION_FLAG_IS_ARRAY)) &&
1164
2/4
✓ Branch 0 taken 780 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 780 times.
✗ Branch 3 not taken.
780 wctx->level && wctx->nb_item[wctx->level-1])
1165 780 printf("%c", compact->item_sep);
1166
2/2
✓ Branch 0 taken 7998 times.
✓ Branch 1 taken 1222 times.
9220 if (compact->print_section &&
1167
2/2
✓ Branch 0 taken 7249 times.
✓ Branch 1 taken 749 times.
7998 !(section->flags & (SECTION_FLAG_IS_WRAPPER|SECTION_FLAG_IS_ARRAY)))
1168 7249 printf("%s%c", section->name, compact->item_sep);
1169 }
1170 9699 }
1171
1172 9699 static void compact_print_section_footer(WriterContext *wctx)
1173 {
1174 9699 CompactContext *compact = wctx->priv;
1175
1176
2/2
✓ Branch 0 taken 9184 times.
✓ Branch 1 taken 515 times.
9699 if (!compact->nested_section[wctx->level] &&
1177
2/2
✓ Branch 0 taken 9148 times.
✓ Branch 1 taken 36 times.
9184 compact->terminate_line[wctx->level] &&
1178
2/2
✓ Branch 0 taken 8304 times.
✓ Branch 1 taken 844 times.
9148 !(wctx->section[wctx->level]->flags & (SECTION_FLAG_IS_WRAPPER|SECTION_FLAG_IS_ARRAY)))
1179 8304 printf("\n");
1180 9699 }
1181
1182 29099 static void compact_print_str(WriterContext *wctx, const char *key, const char *value)
1183 {
1184 29099 CompactContext *compact = wctx->priv;
1185 AVBPrint buf;
1186
1187
2/2
✓ Branch 0 taken 25420 times.
✓ Branch 1 taken 3679 times.
29099 if (wctx->nb_item[wctx->level]) printf("%c", compact->item_sep);
1188
2/2
✓ Branch 0 taken 26216 times.
✓ Branch 1 taken 2883 times.
29099 if (!compact->nokey)
1189 26216 printf("%s%s=", wctx->section_pbuf[wctx->level].str, key);
1190 29099 av_bprint_init(&buf, 1, AV_BPRINT_SIZE_UNLIMITED);
1191 29099 printf("%s", compact->escape_str(&buf, value, compact->item_sep, wctx));
1192 29099 av_bprint_finalize(&buf, NULL);
1193 29099 }
1194
1195 30367 static void compact_print_int(WriterContext *wctx, const char *key, long long int value)
1196 {
1197 30367 CompactContext *compact = wctx->priv;
1198
1199
2/2
✓ Branch 0 taken 25710 times.
✓ Branch 1 taken 4657 times.
30367 if (wctx->nb_item[wctx->level]) printf("%c", compact->item_sep);
1200
2/2
✓ Branch 0 taken 28572 times.
✓ Branch 1 taken 1795 times.
30367 if (!compact->nokey)
1201 28572 printf("%s%s=", wctx->section_pbuf[wctx->level].str, key);
1202 30367 printf("%lld", value);
1203 30367 }
1204
1205 static const Writer compact_writer = {
1206 .name = "compact",
1207 .priv_size = sizeof(CompactContext),
1208 .init = compact_init,
1209 .print_section_header = compact_print_section_header,
1210 .print_section_footer = compact_print_section_footer,
1211 .print_integer = compact_print_int,
1212 .print_string = compact_print_str,
1213 .flags = WRITER_FLAG_DISPLAY_OPTIONAL_FIELDS,
1214 .priv_class = &compact_class,
1215 };
1216
1217 /* CSV output */
1218
1219 #undef OFFSET
1220 #define OFFSET(x) offsetof(CompactContext, x)
1221
1222 static const AVOption csv_options[] = {
1223 {"item_sep", "set item separator", OFFSET(item_sep_str), AV_OPT_TYPE_STRING, {.str=","}, 0, 0 },
1224 {"s", "set item separator", OFFSET(item_sep_str), AV_OPT_TYPE_STRING, {.str=","}, 0, 0 },
1225 {"nokey", "force no key printing", OFFSET(nokey), AV_OPT_TYPE_BOOL, {.i64=1}, 0, 1 },
1226 {"nk", "force no key printing", OFFSET(nokey), AV_OPT_TYPE_BOOL, {.i64=1}, 0, 1 },
1227 {"escape", "set escape mode", OFFSET(escape_mode_str), AV_OPT_TYPE_STRING, {.str="csv"}, 0, 0 },
1228 {"e", "set escape mode", OFFSET(escape_mode_str), AV_OPT_TYPE_STRING, {.str="csv"}, 0, 0 },
1229 {"print_section", "print section name", OFFSET(print_section), AV_OPT_TYPE_BOOL, {.i64=1}, 0, 1 },
1230 {"p", "print section name", OFFSET(print_section), AV_OPT_TYPE_BOOL, {.i64=1}, 0, 1 },
1231 {NULL},
1232 };
1233
1234 DEFINE_WRITER_CLASS(csv);
1235
1236 static const Writer csv_writer = {
1237 .name = "csv",
1238 .priv_size = sizeof(CompactContext),
1239 .init = compact_init,
1240 .print_section_header = compact_print_section_header,
1241 .print_section_footer = compact_print_section_footer,
1242 .print_integer = compact_print_int,
1243 .print_string = compact_print_str,
1244 .flags = WRITER_FLAG_DISPLAY_OPTIONAL_FIELDS,
1245 .priv_class = &csv_class,
1246 };
1247
1248 /* Flat output */
1249
1250 typedef struct FlatContext {
1251 const AVClass *class;
1252 const char *sep_str;
1253 char sep;
1254 int hierarchical;
1255 } FlatContext;
1256
1257 #undef OFFSET
1258 #define OFFSET(x) offsetof(FlatContext, x)
1259
1260 static const AVOption flat_options[]= {
1261 {"sep_char", "set separator", OFFSET(sep_str), AV_OPT_TYPE_STRING, {.str="."}, 0, 0 },
1262 {"s", "set separator", OFFSET(sep_str), AV_OPT_TYPE_STRING, {.str="."}, 0, 0 },
1263 {"hierarchical", "specify if the section specification should be hierarchical", OFFSET(hierarchical), AV_OPT_TYPE_BOOL, {.i64=1}, 0, 1 },
1264 {"h", "specify if the section specification should be hierarchical", OFFSET(hierarchical), AV_OPT_TYPE_BOOL, {.i64=1}, 0, 1 },
1265 {NULL},
1266 };
1267
1268 DEFINE_WRITER_CLASS(flat);
1269
1270 1 static av_cold int flat_init(WriterContext *wctx)
1271 {
1272 1 FlatContext *flat = wctx->priv;
1273
1274
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (strlen(flat->sep_str) != 1) {
1275 av_log(wctx, AV_LOG_ERROR, "Item separator '%s' specified, but must contain a single character\n",
1276 flat->sep_str);
1277 return AVERROR(EINVAL);
1278 }
1279 1 flat->sep = flat->sep_str[0];
1280
1281 1 return 0;
1282 }
1283
1284 362 static const char *flat_escape_key_str(AVBPrint *dst, const char *src, const char sep)
1285 {
1286 const char *p;
1287
1288
2/2
✓ Branch 0 taken 3871 times.
✓ Branch 1 taken 362 times.
4233 for (p = src; *p; p++) {
1289
3/4
✓ Branch 0 taken 3871 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3870 times.
✓ Branch 3 taken 1 times.
3871 if (!((*p >= '0' && *p <= '9') ||
1290
3/4
✓ Branch 0 taken 3477 times.
✓ Branch 1 taken 393 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 3477 times.
3870 (*p >= 'a' && *p <= 'z') ||
1291
3/4
✓ Branch 0 taken 393 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 392 times.
✓ Branch 3 taken 1 times.
393 (*p >= 'A' && *p <= 'Z')))
1292 392 av_bprint_chars(dst, '_', 1);
1293 else
1294 3479 av_bprint_chars(dst, *p, 1);
1295 }
1296 362 return dst->str;
1297 }
1298
1299 362 static const char *flat_escape_value_str(AVBPrint *dst, const char *src)
1300 {
1301 const char *p;
1302
1303
2/2
✓ Branch 0 taken 2312 times.
✓ Branch 1 taken 362 times.
2674 for (p = src; *p; p++) {
1304
2/7
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✓ Branch 6 taken 2310 times.
2312 switch (*p) {
1305 case '\n': av_bprintf(dst, "%s", "\\n"); break;
1306 case '\r': av_bprintf(dst, "%s", "\\r"); break;
1307 case '\\': av_bprintf(dst, "%s", "\\\\"); break;
1308 2 case '"': av_bprintf(dst, "%s", "\\\""); break;
1309 case '`': av_bprintf(dst, "%s", "\\`"); break;
1310 case '$': av_bprintf(dst, "%s", "\\$"); break;
1311 2310 default: av_bprint_chars(dst, *p, 1); break;
1312 }
1313 }
1314 362 return dst->str;
1315 }
1316
1317 42 static void flat_print_section_header(WriterContext *wctx)
1318 {
1319 42 FlatContext *flat = wctx->priv;
1320 42 AVBPrint *buf = &wctx->section_pbuf[wctx->level];
1321 42 const struct section *section = wctx->section[wctx->level];
1322 84 const struct section *parent_section = wctx->level ?
1323
2/2
✓ Branch 0 taken 41 times.
✓ Branch 1 taken 1 times.
42 wctx->section[wctx->level-1] : NULL;
1324
1325 /* build section header */
1326 42 av_bprint_clear(buf);
1327
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 41 times.
42 if (!parent_section)
1328 1 return;
1329 41 av_bprintf(buf, "%s", wctx->section_pbuf[wctx->level-1].str);
1330
1331
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 41 times.
41 if (flat->hierarchical ||
1332 !(section->flags & (SECTION_FLAG_IS_ARRAY|SECTION_FLAG_IS_WRAPPER))) {
1333 41 av_bprintf(buf, "%s%s", wctx->section[wctx->level]->name, flat->sep_str);
1334
1335
2/2
✓ Branch 0 taken 31 times.
✓ Branch 1 taken 10 times.
41 if (parent_section->flags & SECTION_FLAG_IS_ARRAY) {
1336 62 int n = parent_section->id == SECTION_ID_PACKETS_AND_FRAMES ?
1337
2/2
✓ Branch 0 taken 28 times.
✓ Branch 1 taken 3 times.
31 wctx->nb_section_packet_frame : wctx->nb_item[wctx->level-1];
1338 31 av_bprintf(buf, "%d%s", n, flat->sep_str);
1339 }
1340 }
1341 }
1342
1343 288 static void flat_print_int(WriterContext *wctx, const char *key, long long int value)
1344 {
1345 288 printf("%s%s=%lld\n", wctx->section_pbuf[wctx->level].str, key, value);
1346 288 }
1347
1348 362 static void flat_print_str(WriterContext *wctx, const char *key, const char *value)
1349 {
1350 362 FlatContext *flat = wctx->priv;
1351 AVBPrint buf;
1352
1353 362 printf("%s", wctx->section_pbuf[wctx->level].str);
1354 362 av_bprint_init(&buf, 1, AV_BPRINT_SIZE_UNLIMITED);
1355 362 printf("%s=", flat_escape_key_str(&buf, key, flat->sep));
1356 362 av_bprint_clear(&buf);
1357 362 printf("\"%s\"\n", flat_escape_value_str(&buf, value));
1358 362 av_bprint_finalize(&buf, NULL);
1359 362 }
1360
1361 static const Writer flat_writer = {
1362 .name = "flat",
1363 .priv_size = sizeof(FlatContext),
1364 .init = flat_init,
1365 .print_section_header = flat_print_section_header,
1366 .print_integer = flat_print_int,
1367 .print_string = flat_print_str,
1368 .flags = WRITER_FLAG_DISPLAY_OPTIONAL_FIELDS|WRITER_FLAG_PUT_PACKETS_AND_FRAMES_IN_SAME_CHAPTER,
1369 .priv_class = &flat_class,
1370 };
1371
1372 /* INI format output */
1373
1374 typedef struct INIContext {
1375 const AVClass *class;
1376 int hierarchical;
1377 } INIContext;
1378
1379 #undef OFFSET
1380 #define OFFSET(x) offsetof(INIContext, x)
1381
1382 static const AVOption ini_options[] = {
1383 {"hierarchical", "specify if the section specification should be hierarchical", OFFSET(hierarchical), AV_OPT_TYPE_BOOL, {.i64=1}, 0, 1 },
1384 {"h", "specify if the section specification should be hierarchical", OFFSET(hierarchical), AV_OPT_TYPE_BOOL, {.i64=1}, 0, 1 },
1385 {NULL},
1386 };
1387
1388 DEFINE_WRITER_CLASS(ini);
1389
1390 724 static char *ini_escape_str(AVBPrint *dst, const char *src)
1391 {
1392 724 int i = 0;
1393 724 char c = 0;
1394
1395
2/2
✓ Branch 0 taken 6183 times.
✓ Branch 1 taken 724 times.
6907 while (c = src[i++]) {
1396
2/7
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 14 times.
✓ Branch 6 taken 6169 times.
6183 switch (c) {
1397 case '\b': av_bprintf(dst, "%s", "\\b"); break;
1398 case '\f': av_bprintf(dst, "%s", "\\f"); break;
1399 case '\n': av_bprintf(dst, "%s", "\\n"); break;
1400 case '\r': av_bprintf(dst, "%s", "\\r"); break;
1401 case '\t': av_bprintf(dst, "%s", "\\t"); break;
1402 14 case '\\':
1403 case '#' :
1404 case '=' :
1405 14 case ':' : av_bprint_chars(dst, '\\', 1);
1406 6183 default:
1407
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6183 times.
6183 if ((unsigned char)c < 32)
1408 av_bprintf(dst, "\\x00%02x", c & 0xff);
1409 else
1410 6183 av_bprint_chars(dst, c, 1);
1411 6183 break;
1412 }
1413 }
1414 724 return dst->str;
1415 }
1416
1417 42 static void ini_print_section_header(WriterContext *wctx)
1418 {
1419 42 INIContext *ini = wctx->priv;
1420 42 AVBPrint *buf = &wctx->section_pbuf[wctx->level];
1421 42 const struct section *section = wctx->section[wctx->level];
1422 84 const struct section *parent_section = wctx->level ?
1423
2/2
✓ Branch 0 taken 41 times.
✓ Branch 1 taken 1 times.
42 wctx->section[wctx->level-1] : NULL;
1424
1425 42 av_bprint_clear(buf);
1426
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 41 times.
42 if (!parent_section) {
1427 1 printf("# ffprobe output\n\n");
1428 1 return;
1429 }
1430
1431
2/2
✓ Branch 0 taken 38 times.
✓ Branch 1 taken 3 times.
41 if (wctx->nb_item[wctx->level-1])
1432 38 printf("\n");
1433
1434 41 av_bprintf(buf, "%s", wctx->section_pbuf[wctx->level-1].str);
1435
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 41 times.
41 if (ini->hierarchical ||
1436 !(section->flags & (SECTION_FLAG_IS_ARRAY|SECTION_FLAG_IS_WRAPPER))) {
1437
2/2
✓ Branch 0 taken 38 times.
✓ Branch 1 taken 3 times.
41 av_bprintf(buf, "%s%s", buf->str[0] ? "." : "", wctx->section[wctx->level]->name);
1438
1439
2/2
✓ Branch 0 taken 31 times.
✓ Branch 1 taken 10 times.
41 if (parent_section->flags & SECTION_FLAG_IS_ARRAY) {
1440 62 int n = parent_section->id == SECTION_ID_PACKETS_AND_FRAMES ?
1441
2/2
✓ Branch 0 taken 28 times.
✓ Branch 1 taken 3 times.
31 wctx->nb_section_packet_frame : wctx->nb_item[wctx->level-1];
1442 31 av_bprintf(buf, ".%d", n);
1443 }
1444 }
1445
1446
2/2
✓ Branch 0 taken 39 times.
✓ Branch 1 taken 2 times.
41 if (!(section->flags & (SECTION_FLAG_IS_ARRAY|SECTION_FLAG_IS_WRAPPER)))
1447 39 printf("[%s]\n", buf->str);
1448 }
1449
1450 362 static void ini_print_str(WriterContext *wctx, const char *key, const char *value)
1451 {
1452 AVBPrint buf;
1453
1454 362 av_bprint_init(&buf, 1, AV_BPRINT_SIZE_UNLIMITED);
1455 362 printf("%s=", ini_escape_str(&buf, key));
1456 362 av_bprint_clear(&buf);
1457 362 printf("%s\n", ini_escape_str(&buf, value));
1458 362 av_bprint_finalize(&buf, NULL);
1459 362 }
1460
1461 288 static void ini_print_int(WriterContext *wctx, const char *key, long long int value)
1462 {
1463 288 printf("%s=%lld\n", key, value);
1464 288 }
1465
1466 static const Writer ini_writer = {
1467 .name = "ini",
1468 .priv_size = sizeof(INIContext),
1469 .print_section_header = ini_print_section_header,
1470 .print_integer = ini_print_int,
1471 .print_string = ini_print_str,
1472 .flags = WRITER_FLAG_DISPLAY_OPTIONAL_FIELDS|WRITER_FLAG_PUT_PACKETS_AND_FRAMES_IN_SAME_CHAPTER,
1473 .priv_class = &ini_class,
1474 };
1475
1476 /* JSON output */
1477
1478 typedef struct JSONContext {
1479 const AVClass *class;
1480 int indent_level;
1481 int compact;
1482 const char *item_sep, *item_start_end;
1483 } JSONContext;
1484
1485 #undef OFFSET
1486 #define OFFSET(x) offsetof(JSONContext, x)
1487
1488 static const AVOption json_options[]= {
1489 { "compact", "enable compact output", OFFSET(compact), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1 },
1490 { "c", "enable compact output", OFFSET(compact), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1 },
1491 { NULL }
1492 };
1493
1494 DEFINE_WRITER_CLASS(json);
1495
1496 4 static av_cold int json_init(WriterContext *wctx)
1497 {
1498 4 JSONContext *json = wctx->priv;
1499
1500
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 json->item_sep = json->compact ? ", " : ",\n";
1501
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 json->item_start_end = json->compact ? " " : "\n";
1502
1503 4 return 0;
1504 }
1505
1506 1027 static const char *json_escape_str(AVBPrint *dst, const char *src, void *log_ctx)
1507 {
1508 static const char json_escape[] = {'"', '\\', '\b', '\f', '\n', '\r', '\t', 0};
1509 static const char json_subst[] = {'"', '\\', 'b', 'f', 'n', 'r', 't', 0};
1510 const char *p;
1511
1512
2/2
✓ Branch 0 taken 8881 times.
✓ Branch 1 taken 1027 times.
9908 for (p = src; *p; p++) {
1513 8881 char *s = strchr(json_escape, *p);
1514
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 8879 times.
8881 if (s) {
1515 2 av_bprint_chars(dst, '\\', 1);
1516 2 av_bprint_chars(dst, json_subst[s - json_escape], 1);
1517
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8879 times.
8879 } else if ((unsigned char)*p < 32) {
1518 av_bprintf(dst, "\\u00%02x", *p & 0xff);
1519 } else {
1520 8879 av_bprint_chars(dst, *p, 1);
1521 }
1522 }
1523 1027 return dst->str;
1524 }
1525
1526 #define JSON_INDENT() printf("%*c", json->indent_level * 4, ' ')
1527
1528 67 static void json_print_section_header(WriterContext *wctx)
1529 {
1530 67 JSONContext *json = wctx->priv;
1531 AVBPrint buf;
1532 67 const struct section *section = wctx->section[wctx->level];
1533 134 const struct section *parent_section = wctx->level ?
1534
2/2
✓ Branch 0 taken 63 times.
✓ Branch 1 taken 4 times.
67 wctx->section[wctx->level-1] : NULL;
1535
1536
4/4
✓ Branch 0 taken 63 times.
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 50 times.
✓ Branch 3 taken 13 times.
67 if (wctx->level && wctx->nb_item[wctx->level-1])
1537 50 printf(",\n");
1538
1539
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 63 times.
67 if (section->flags & SECTION_FLAG_IS_WRAPPER) {
1540 4 printf("{\n");
1541 4 json->indent_level++;
1542 } else {
1543 63 av_bprint_init(&buf, 1, AV_BPRINT_SIZE_UNLIMITED);
1544 63 json_escape_str(&buf, section->name, wctx);
1545 63 JSON_INDENT();
1546
1547 63 json->indent_level++;
1548
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 51 times.
63 if (section->flags & SECTION_FLAG_IS_ARRAY) {
1549 12 printf("\"%s\": [\n", buf.str);
1550
3/4
✓ Branch 0 taken 51 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 12 times.
✓ Branch 3 taken 39 times.
51 } else if (parent_section && !(parent_section->flags & SECTION_FLAG_IS_ARRAY)) {
1551 12 printf("\"%s\": {%s", buf.str, json->item_start_end);
1552 } else {
1553 39 printf("{%s", json->item_start_end);
1554
1555 /* this is required so the parser can distinguish between packets and frames */
1556
3/4
✓ Branch 0 taken 39 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 28 times.
✓ Branch 3 taken 11 times.
39 if (parent_section && parent_section->id == SECTION_ID_PACKETS_AND_FRAMES) {
1557
1/2
✓ Branch 0 taken 28 times.
✗ Branch 1 not taken.
28 if (!json->compact)
1558 28 JSON_INDENT();
1559 28 printf("\"type\": \"%s\"", section->name);
1560 }
1561 }
1562 63 av_bprint_finalize(&buf, NULL);
1563 }
1564 67 }
1565
1566 67 static void json_print_section_footer(WriterContext *wctx)
1567 {
1568 67 JSONContext *json = wctx->priv;
1569 67 const struct section *section = wctx->section[wctx->level];
1570
1571
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 63 times.
67 if (wctx->level == 0) {
1572 4 json->indent_level--;
1573 4 printf("\n}\n");
1574
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 51 times.
63 } else if (section->flags & SECTION_FLAG_IS_ARRAY) {
1575 12 printf("\n");
1576 12 json->indent_level--;
1577 12 JSON_INDENT();
1578 12 printf("]");
1579 } else {
1580 51 printf("%s", json->item_start_end);
1581 51 json->indent_level--;
1582
1/2
✓ Branch 0 taken 51 times.
✗ Branch 1 not taken.
51 if (!json->compact)
1583 51 JSON_INDENT();
1584 51 printf("}");
1585 }
1586 67 }
1587
1588 314 static inline void json_print_item_str(WriterContext *wctx,
1589 const char *key, const char *value)
1590 {
1591 AVBPrint buf;
1592
1593 314 av_bprint_init(&buf, 1, AV_BPRINT_SIZE_UNLIMITED);
1594 314 printf("\"%s\":", json_escape_str(&buf, key, wctx));
1595 314 av_bprint_clear(&buf);
1596 314 printf(" \"%s\"", json_escape_str(&buf, value, wctx));
1597 314 av_bprint_finalize(&buf, NULL);
1598 314 }
1599
1600 314 static void json_print_str(WriterContext *wctx, const char *key, const char *value)
1601 {
1602 314 JSONContext *json = wctx->priv;
1603 628 const struct section *parent_section = wctx->level ?
1604
1/2
✓ Branch 0 taken 314 times.
✗ Branch 1 not taken.
314 wctx->section[wctx->level-1] : NULL;
1605
1606
5/6
✓ Branch 0 taken 37 times.
✓ Branch 1 taken 277 times.
✓ Branch 2 taken 37 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 28 times.
✓ Branch 5 taken 9 times.
314 if (wctx->nb_item[wctx->level] || (parent_section && parent_section->id == SECTION_ID_PACKETS_AND_FRAMES))
1607 305 printf("%s", json->item_sep);
1608
1/2
✓ Branch 0 taken 314 times.
✗ Branch 1 not taken.
314 if (!json->compact)
1609 314 JSON_INDENT();
1610 314 json_print_item_str(wctx, key, value);
1611 314 }
1612
1613 336 static void json_print_int(WriterContext *wctx, const char *key, long long int value)
1614 {
1615 336 JSONContext *json = wctx->priv;
1616 672 const struct section *parent_section = wctx->level ?
1617
1/2
✓ Branch 0 taken 336 times.
✗ Branch 1 not taken.
336 wctx->section[wctx->level-1] : NULL;
1618 AVBPrint buf;
1619
1620
4/6
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 324 times.
✓ Branch 2 taken 12 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 12 times.
336 if (wctx->nb_item[wctx->level] || (parent_section && parent_section->id == SECTION_ID_PACKETS_AND_FRAMES))
1621 324 printf("%s", json->item_sep);
1622
1/2
✓ Branch 0 taken 336 times.
✗ Branch 1 not taken.
336 if (!json->compact)
1623 336 JSON_INDENT();
1624
1625 336 av_bprint_init(&buf, 1, AV_BPRINT_SIZE_UNLIMITED);
1626 336 printf("\"%s\": %lld", json_escape_str(&buf, key, wctx), value);
1627 336 av_bprint_finalize(&buf, NULL);
1628 336 }
1629
1630 static const Writer json_writer = {
1631 .name = "json",
1632 .priv_size = sizeof(JSONContext),
1633 .init = json_init,
1634 .print_section_header = json_print_section_header,
1635 .print_section_footer = json_print_section_footer,
1636 .print_integer = json_print_int,
1637 .print_string = json_print_str,
1638 .flags = WRITER_FLAG_PUT_PACKETS_AND_FRAMES_IN_SAME_CHAPTER,
1639 .priv_class = &json_class,
1640 };
1641
1642 /* XML output */
1643
1644 typedef struct XMLContext {
1645 const AVClass *class;
1646 int within_tag;
1647 int indent_level;
1648 int fully_qualified;
1649 int xsd_strict;
1650 } XMLContext;
1651
1652 #undef OFFSET
1653 #define OFFSET(x) offsetof(XMLContext, x)
1654
1655 static const AVOption xml_options[] = {
1656 {"fully_qualified", "specify if the output should be fully qualified", OFFSET(fully_qualified), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1 },
1657 {"q", "specify if the output should be fully qualified", OFFSET(fully_qualified), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1 },
1658 {"xsd_strict", "ensure that the output is XSD compliant", OFFSET(xsd_strict), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1 },
1659 {"x", "ensure that the output is XSD compliant", OFFSET(xsd_strict), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1 },
1660 {NULL},
1661 };
1662
1663 DEFINE_WRITER_CLASS(xml);
1664
1665 2 static av_cold int xml_init(WriterContext *wctx)
1666 {
1667 2 XMLContext *xml = wctx->priv;
1668
1669
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
2 if (xml->xsd_strict) {
1670 1 xml->fully_qualified = 1;
1671 #define CHECK_COMPLIANCE(opt, opt_name) \
1672 if (opt) { \
1673 av_log(wctx, AV_LOG_ERROR, \
1674 "XSD-compliant output selected but option '%s' was selected, XML output may be non-compliant.\n" \
1675 "You need to disable such option with '-no%s'\n", opt_name, opt_name); \
1676 return AVERROR(EINVAL); \
1677 }
1678
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 CHECK_COMPLIANCE(show_private_data, "private");
1679
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 CHECK_COMPLIANCE(show_value_unit, "unit");
1680
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 CHECK_COMPLIANCE(use_value_prefix, "prefix");
1681 }
1682
1683 2 return 0;
1684 }
1685
1686 #define XML_INDENT() printf("%*c", xml->indent_level * 4, ' ')
1687
1688 84 static void xml_print_section_header(WriterContext *wctx)
1689 {
1690 84 XMLContext *xml = wctx->priv;
1691 84 const struct section *section = wctx->section[wctx->level];
1692 168 const struct section *parent_section = wctx->level ?
1693
2/2
✓ Branch 0 taken 82 times.
✓ Branch 1 taken 2 times.
84 wctx->section[wctx->level-1] : NULL;
1694
1695
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 82 times.
84 if (wctx->level == 0) {
1696 2 const char *qual = " xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" "
1697 "xmlns:ffprobe=\"http://www.ffmpeg.org/schema/ffprobe\" "
1698 "xsi:schemaLocation=\"http://www.ffmpeg.org/schema/ffprobe ffprobe.xsd\"";
1699
1700 2 printf("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
1701 4 printf("<%sffprobe%s>\n",
1702
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
2 xml->fully_qualified ? "ffprobe:" : "",
1703
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
2 xml->fully_qualified ? qual : "");
1704 2 return;
1705 }
1706
1707
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 74 times.
82 if (xml->within_tag) {
1708 8 xml->within_tag = 0;
1709 8 printf(">\n");
1710 }
1711
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 74 times.
82 if (section->flags & SECTION_FLAG_HAS_VARIABLE_FIELDS) {
1712 8 xml->indent_level++;
1713 } else {
1714
3/4
✓ Branch 0 taken 74 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
✓ Branch 3 taken 68 times.
74 if (parent_section && (parent_section->flags & SECTION_FLAG_IS_WRAPPER) &&
1715
3/4
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 2 times.
6 wctx->level && wctx->nb_item[wctx->level-1])
1716 4 printf("\n");
1717 74 xml->indent_level++;
1718
1719
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 70 times.
74 if (section->flags & SECTION_FLAG_IS_ARRAY) {
1720 4 XML_INDENT(); printf("<%s>\n", section->name);
1721 } else {
1722 70 XML_INDENT(); printf("<%s ", section->name);
1723 70 xml->within_tag = 1;
1724 }
1725 }
1726 }
1727
1728 84 static void xml_print_section_footer(WriterContext *wctx)
1729 {
1730 84 XMLContext *xml = wctx->priv;
1731 84 const struct section *section = wctx->section[wctx->level];
1732
1733
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 82 times.
84 if (wctx->level == 0) {
1734
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
2 printf("</%sffprobe>\n", xml->fully_qualified ? "ffprobe:" : "");
1735
2/2
✓ Branch 0 taken 62 times.
✓ Branch 1 taken 20 times.
82 } else if (xml->within_tag) {
1736 62 xml->within_tag = 0;
1737 62 printf("/>\n");
1738 62 xml->indent_level--;
1739
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 12 times.
20 } else if (section->flags & SECTION_FLAG_HAS_VARIABLE_FIELDS) {
1740 8 xml->indent_level--;
1741 } else {
1742 12 XML_INDENT(); printf("</%s>\n", section->name);
1743 12 xml->indent_level--;
1744 }
1745 84 }
1746
1747 560 static void xml_print_str(WriterContext *wctx, const char *key, const char *value)
1748 {
1749 AVBPrint buf;
1750 560 XMLContext *xml = wctx->priv;
1751 560 const struct section *section = wctx->section[wctx->level];
1752
1753 560 av_bprint_init(&buf, 1, AV_BPRINT_SIZE_UNLIMITED);
1754
1755
2/2
✓ Branch 0 taken 18 times.
✓ Branch 1 taken 542 times.
560 if (section->flags & SECTION_FLAG_HAS_VARIABLE_FIELDS) {
1756 18 XML_INDENT();
1757 18 av_bprint_escape(&buf, key, NULL,
1758 AV_ESCAPE_MODE_XML, AV_ESCAPE_FLAG_XML_DOUBLE_QUOTES);
1759 18 printf("<%s key=\"%s\"",
1760 18 section->element_name, buf.str);
1761 18 av_bprint_clear(&buf);
1762
1763 18 av_bprint_escape(&buf, value, NULL,
1764 AV_ESCAPE_MODE_XML, AV_ESCAPE_FLAG_XML_DOUBLE_QUOTES);
1765 18 printf(" value=\"%s\"/>\n", buf.str);
1766 } else {
1767
2/2
✓ Branch 0 taken 484 times.
✓ Branch 1 taken 58 times.
542 if (wctx->nb_item[wctx->level])
1768 484 printf(" ");
1769
1770 542 av_bprint_escape(&buf, value, NULL,
1771 AV_ESCAPE_MODE_XML, AV_ESCAPE_FLAG_XML_DOUBLE_QUOTES);
1772 542 printf("%s=\"%s\"", key, buf.str);
1773 }
1774
1775 560 av_bprint_finalize(&buf, NULL);
1776 560 }
1777
1778 576 static void xml_print_int(WriterContext *wctx, const char *key, long long int value)
1779 {
1780
2/2
✓ Branch 0 taken 564 times.
✓ Branch 1 taken 12 times.
576 if (wctx->nb_item[wctx->level])
1781 564 printf(" ");
1782 576 printf("%s=\"%lld\"", key, value);
1783 576 }
1784
1785 static Writer xml_writer = {
1786 .name = "xml",
1787 .priv_size = sizeof(XMLContext),
1788 .init = xml_init,
1789 .print_section_header = xml_print_section_header,
1790 .print_section_footer = xml_print_section_footer,
1791 .print_integer = xml_print_int,
1792 .print_string = xml_print_str,
1793 .flags = WRITER_FLAG_PUT_PACKETS_AND_FRAMES_IN_SAME_CHAPTER,
1794 .priv_class = &xml_class,
1795 };
1796
1797 107 static void writer_register_all(void)
1798 {
1799 static int initialized;
1800
1801
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 107 times.
107 if (initialized)
1802 return;
1803 107 initialized = 1;
1804
1805 107 writer_register(&default_writer);
1806 107 writer_register(&compact_writer);
1807 107 writer_register(&csv_writer);
1808 107 writer_register(&flat_writer);
1809 107 writer_register(&ini_writer);
1810 107 writer_register(&json_writer);
1811 107 writer_register(&xml_writer);
1812 }
1813
1814 #define print_fmt(k, f, ...) do { \
1815 av_bprint_clear(&pbuf); \
1816 av_bprintf(&pbuf, f, __VA_ARGS__); \
1817 writer_print_string(w, k, pbuf.str, 0); \
1818 } while (0)
1819
1820 #define print_list_fmt(k, f, n, ...) do { \
1821 av_bprint_clear(&pbuf); \
1822 for (int idx = 0; idx < n; idx++) { \
1823 if (idx > 0) \
1824 av_bprint_chars(&pbuf, ' ', 1); \
1825 av_bprintf(&pbuf, f, __VA_ARGS__); \
1826 } \
1827 writer_print_string(w, k, pbuf.str, 0); \
1828 } while (0)
1829
1830 #define print_int(k, v) writer_print_integer(w, k, v)
1831 #define print_q(k, v, s) writer_print_rational(w, k, v, s)
1832 #define print_str(k, v) writer_print_string(w, k, v, 0)
1833 #define print_str_opt(k, v) writer_print_string(w, k, v, PRINT_STRING_OPT)
1834 #define print_str_validate(k, v) writer_print_string(w, k, v, PRINT_STRING_VALIDATE)
1835 #define print_time(k, v, tb) writer_print_time(w, k, v, tb, 0)
1836 #define print_ts(k, v) writer_print_ts(w, k, v, 0)
1837 #define print_duration_time(k, v, tb) writer_print_time(w, k, v, tb, 1)
1838 #define print_duration_ts(k, v) writer_print_ts(w, k, v, 1)
1839 #define print_val(k, v, u) do { \
1840 struct unit_value uv; \
1841 uv.val.i = v; \
1842 uv.unit = u; \
1843 writer_print_string(w, k, value_string(val_str, sizeof(val_str), uv), 0); \
1844 } while (0)
1845
1846 #define print_section_header(s) writer_print_section_header(w, s)
1847 #define print_section_footer(s) writer_print_section_footer(w, s)
1848
1849 #define REALLOCZ_ARRAY_STREAM(ptr, cur_n, new_n) \
1850 { \
1851 ret = av_reallocp_array(&(ptr), (new_n), sizeof(*(ptr))); \
1852 if (ret < 0) \
1853 goto end; \
1854 memset( (ptr) + (cur_n), 0, ((new_n) - (cur_n)) * sizeof(*(ptr)) ); \
1855 }
1856
1857 1315 static inline int show_tags(WriterContext *w, AVDictionary *tags, int section_id)
1858 {
1859 1315 const AVDictionaryEntry *tag = NULL;
1860 1315 int ret = 0;
1861
1862
2/2
✓ Branch 0 taken 660 times.
✓ Branch 1 taken 655 times.
1315 if (!tags)
1863 660 return 0;
1864 655 writer_print_section_header(w, section_id);
1865
1866
2/2
✓ Branch 1 taken 2635 times.
✓ Branch 2 taken 655 times.
3290 while ((tag = av_dict_get(tags, "", tag, AV_DICT_IGNORE_SUFFIX))) {
1867
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2635 times.
2635 if ((ret = print_str_validate(tag->key, tag->value)) < 0)
1868 break;
1869 }
1870 655 writer_print_section_footer(w);
1871
1872 655 return ret;
1873 }
1874
1875 2 static void print_dovi_metadata(WriterContext *w, const AVDOVIMetadata *dovi)
1876 {
1877
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (!dovi)
1878 return;
1879
1880 {
1881 2 const AVDOVIRpuDataHeader *hdr = av_dovi_get_header(dovi);
1882 2 const AVDOVIDataMapping *mapping = av_dovi_get_mapping(dovi);
1883 2 const AVDOVIColorMetadata *color = av_dovi_get_color(dovi);
1884 AVBPrint pbuf;
1885
1886 2 av_bprint_init(&pbuf, 1, AV_BPRINT_SIZE_UNLIMITED);
1887
1888 // header
1889 2 print_int("rpu_type", hdr->rpu_type);
1890 2 print_int("rpu_format", hdr->rpu_format);
1891 2 print_int("vdr_rpu_profile", hdr->vdr_rpu_profile);
1892 2 print_int("vdr_rpu_level", hdr->vdr_rpu_level);
1893 2 print_int("chroma_resampling_explicit_filter_flag",
1894 hdr->chroma_resampling_explicit_filter_flag);
1895 2 print_int("coef_data_type", hdr->coef_data_type);
1896 2 print_int("coef_log2_denom", hdr->coef_log2_denom);
1897 2 print_int("vdr_rpu_normalized_idc", hdr->vdr_rpu_normalized_idc);
1898 2 print_int("bl_video_full_range_flag", hdr->bl_video_full_range_flag);
1899 2 print_int("bl_bit_depth", hdr->bl_bit_depth);
1900 2 print_int("el_bit_depth", hdr->el_bit_depth);
1901 2 print_int("vdr_bit_depth", hdr->vdr_bit_depth);
1902 2 print_int("spatial_resampling_filter_flag",
1903 hdr->spatial_resampling_filter_flag);
1904 2 print_int("el_spatial_resampling_filter_flag",
1905 hdr->el_spatial_resampling_filter_flag);
1906 2 print_int("disable_residual_flag", hdr->disable_residual_flag);
1907
1908 // data mapping values
1909 2 print_int("vdr_rpu_id", mapping->vdr_rpu_id);
1910 2 print_int("mapping_color_space", mapping->mapping_color_space);
1911 2 print_int("mapping_chroma_format_idc",
1912 mapping->mapping_chroma_format_idc);
1913
1914 2 print_int("nlq_method_idc", mapping->nlq_method_idc);
1915
1/3
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
2 switch (mapping->nlq_method_idc) {
1916 2 case AV_DOVI_NLQ_NONE:
1917 2 print_str("nlq_method_idc_name", "none");
1918 2 break;
1919 case AV_DOVI_NLQ_LINEAR_DZ:
1920 print_str("nlq_method_idc_name", "linear_dz");
1921 break;
1922 default:
1923 print_str("nlq_method_idc_name", "unknown");
1924 break;
1925 }
1926
1927 2 print_int("num_x_partitions", mapping->num_x_partitions);
1928 2 print_int("num_y_partitions", mapping->num_y_partitions);
1929
1930 2 writer_print_section_header(w, SECTION_ID_FRAME_SIDE_DATA_COMPONENT_LIST);
1931
1932
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 2 times.
8 for (int c = 0; c < 3; c++) {
1933 6 const AVDOVIReshapingCurve *curve = &mapping->curves[c];
1934 6 writer_print_section_header(w, SECTION_ID_FRAME_SIDE_DATA_COMPONENT);
1935
1936
4/4
✓ Branch 1 taken 20 times.
✓ Branch 2 taken 6 times.
✓ Branch 5 taken 26 times.
✓ Branch 6 taken 6 times.
32 print_list_fmt("pivots", "%"PRIu16, curve->num_pivots, curve->pivots[idx]);
1937
1938 6 writer_print_section_header(w, SECTION_ID_FRAME_SIDE_DATA_PIECE_LIST);
1939
2/2
✓ Branch 0 taken 20 times.
✓ Branch 1 taken 6 times.
26 for (int i = 0; i < curve->num_pivots - 1; i++) {
1940
1941 20 writer_print_section_header(w, SECTION_ID_FRAME_SIDE_DATA_PIECE);
1942 20 print_int("mapping_idc", curve->mapping_idc[i]);
1943
2/3
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
20 switch (curve->mapping_idc[i]) {
1944 16 case AV_DOVI_MAPPING_POLYNOMIAL:
1945 16 print_str("mapping_idc_name", "polynomial");
1946 16 print_int("poly_order", curve->poly_order[i]);
1947
4/4
✓ Branch 1 taken 32 times.
✓ Branch 2 taken 16 times.
✓ Branch 5 taken 48 times.
✓ Branch 6 taken 16 times.
64 print_list_fmt("poly_coef", "%"PRIi64,
1948 curve->poly_order[i] + 1,
1949 curve->poly_coef[i][idx]);
1950 16 break;
1951 4 case AV_DOVI_MAPPING_MMR:
1952 4 print_str("mapping_idc_name", "mmr");
1953 4 print_int("mmr_order", curve->mmr_order[i]);
1954 4 print_int("mmr_constant", curve->mmr_constant[i]);
1955
4/4
✓ Branch 1 taken 80 times.
✓ Branch 2 taken 4 times.
✓ Branch 5 taken 84 times.
✓ Branch 6 taken 4 times.
88 print_list_fmt("mmr_coef", "%"PRIi64,
1956 curve->mmr_order[i] * 7,
1957 curve->mmr_coef[i][0][idx]);
1958 4 break;
1959 default:
1960 print_str("mapping_idc_name", "unknown");
1961 break;
1962 }
1963
1964 // SECTION_ID_FRAME_SIDE_DATA_PIECE
1965 20 writer_print_section_footer(w);
1966 }
1967
1968 // SECTION_ID_FRAME_SIDE_DATA_PIECE_LIST
1969 6 writer_print_section_footer(w);
1970
1971
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (mapping->nlq_method_idc != AV_DOVI_NLQ_NONE) {
1972 const AVDOVINLQParams *nlq = &mapping->nlq[c];
1973 print_int("nlq_offset", nlq->nlq_offset);
1974 print_int("vdr_in_max", nlq->vdr_in_max);
1975
1976 switch (mapping->nlq_method_idc) {
1977 case AV_DOVI_NLQ_LINEAR_DZ:
1978 print_int("linear_deadzone_slope", nlq->linear_deadzone_slope);
1979 print_int("linear_deadzone_threshold", nlq->linear_deadzone_threshold);
1980 break;
1981 }
1982 }
1983
1984 // SECTION_ID_FRAME_SIDE_DATA_COMPONENT
1985 6 writer_print_section_footer(w);
1986 }
1987
1988 // SECTION_ID_FRAME_SIDE_DATA_COMPONENT_LIST
1989 2 writer_print_section_footer(w);
1990
1991 // color metadata
1992 2 print_int("dm_metadata_id", color->dm_metadata_id);
1993 2 print_int("scene_refresh_flag", color->scene_refresh_flag);
1994
4/4
✓ Branch 1 taken 16 times.
✓ Branch 2 taken 2 times.
✓ Branch 5 taken 18 times.
✓ Branch 6 taken 2 times.
20 print_list_fmt("ycc_to_rgb_matrix", "%d/%d",
1995 FF_ARRAY_ELEMS(color->ycc_to_rgb_matrix),
1996 color->ycc_to_rgb_matrix[idx].num,
1997 color->ycc_to_rgb_matrix[idx].den);
1998
4/4
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 2 times.
✓ Branch 5 taken 6 times.
✓ Branch 6 taken 2 times.
8 print_list_fmt("ycc_to_rgb_offset", "%d/%d",
1999 FF_ARRAY_ELEMS(color->ycc_to_rgb_offset),
2000 color->ycc_to_rgb_offset[idx].num,
2001 color->ycc_to_rgb_offset[idx].den);
2002
4/4
✓ Branch 1 taken 16 times.
✓ Branch 2 taken 2 times.
✓ Branch 5 taken 18 times.
✓ Branch 6 taken 2 times.
20 print_list_fmt("rgb_to_lms_matrix", "%d/%d",
2003 FF_ARRAY_ELEMS(color->rgb_to_lms_matrix),
2004 color->rgb_to_lms_matrix[idx].num,
2005 color->rgb_to_lms_matrix[idx].den);
2006 2 print_int("signal_eotf", color->signal_eotf);
2007 2 print_int("signal_eotf_param0", color->signal_eotf_param0);
2008 2 print_int("signal_eotf_param1", color->signal_eotf_param1);
2009 2 print_int("signal_eotf_param2", color->signal_eotf_param2);
2010 2 print_int("signal_bit_depth", color->signal_bit_depth);
2011 2 print_int("signal_color_space", color->signal_color_space);
2012 2 print_int("signal_chroma_format", color->signal_chroma_format);
2013 2 print_int("signal_full_range_flag", color->signal_full_range_flag);
2014 2 print_int("source_min_pq", color->source_min_pq);
2015 2 print_int("source_max_pq", color->source_max_pq);
2016 2 print_int("source_diagonal", color->source_diagonal);
2017
2018 2 av_bprint_finalize(&pbuf, NULL);
2019 }
2020 }
2021
2022 1 static void print_dynamic_hdr10_plus(WriterContext *w, const AVDynamicHDRPlus *metadata)
2023 {
2024
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (!metadata)
2025 return;
2026 1 print_int("application version", metadata->application_version);
2027 1 print_int("num_windows", metadata->num_windows);
2028
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 for (int n = 1; n < metadata->num_windows; n++) {
2029 const AVHDRPlusColorTransformParams *params = &metadata->params[n];
2030 print_q("window_upper_left_corner_x",
2031 params->window_upper_left_corner_x,'/');
2032 print_q("window_upper_left_corner_y",
2033 params->window_upper_left_corner_y,'/');
2034 print_q("window_lower_right_corner_x",
2035 params->window_lower_right_corner_x,'/');
2036 print_q("window_lower_right_corner_y",
2037 params->window_lower_right_corner_y,'/');
2038 print_q("window_upper_left_corner_x",
2039 params->window_upper_left_corner_x,'/');
2040 print_q("window_upper_left_corner_y",
2041 params->window_upper_left_corner_y,'/');
2042 print_int("center_of_ellipse_x",
2043 params->center_of_ellipse_x ) ;
2044 print_int("center_of_ellipse_y",
2045 params->center_of_ellipse_y );
2046 print_int("rotation_angle",
2047 params->rotation_angle);
2048 print_int("semimajor_axis_internal_ellipse",
2049 params->semimajor_axis_internal_ellipse);
2050 print_int("semimajor_axis_external_ellipse",
2051 params->semimajor_axis_external_ellipse);
2052 print_int("semiminor_axis_external_ellipse",
2053 params->semiminor_axis_external_ellipse);
2054 print_int("overlap_process_option",
2055 params->overlap_process_option);
2056 }
2057 1 print_q("targeted_system_display_maximum_luminance",
2058 metadata->targeted_system_display_maximum_luminance,'/');
2059
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (metadata->targeted_system_display_actual_peak_luminance_flag) {
2060 print_int("num_rows_targeted_system_display_actual_peak_luminance",
2061 metadata->num_rows_targeted_system_display_actual_peak_luminance);
2062 print_int("num_cols_targeted_system_display_actual_peak_luminance",
2063 metadata->num_cols_targeted_system_display_actual_peak_luminance);
2064 for (int i = 0; i < metadata->num_rows_targeted_system_display_actual_peak_luminance; i++) {
2065 for (int j = 0; j < metadata->num_cols_targeted_system_display_actual_peak_luminance; j++) {
2066 print_q("targeted_system_display_actual_peak_luminance",
2067 metadata->targeted_system_display_actual_peak_luminance[i][j],'/');
2068 }
2069 }
2070 }
2071
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
2 for (int n = 0; n < metadata->num_windows; n++) {
2072 1 const AVHDRPlusColorTransformParams *params = &metadata->params[n];
2073
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 1 times.
4 for (int i = 0; i < 3; i++) {
2074 3 print_q("maxscl",params->maxscl[i],'/');
2075 }
2076 1 print_q("average_maxrgb",
2077 params->average_maxrgb,'/');
2078 1 print_int("num_distribution_maxrgb_percentiles",
2079 params->num_distribution_maxrgb_percentiles);
2080
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 1 times.
10 for (int i = 0; i < params->num_distribution_maxrgb_percentiles; i++) {
2081 9 print_int("distribution_maxrgb_percentage",
2082 params->distribution_maxrgb[i].percentage);
2083 9 print_q("distribution_maxrgb_percentile",
2084 params->distribution_maxrgb[i].percentile,'/');
2085 }
2086 1 print_q("fraction_bright_pixels",
2087 params->fraction_bright_pixels,'/');
2088 }
2089
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (metadata->mastering_display_actual_peak_luminance_flag) {
2090 print_int("num_rows_mastering_display_actual_peak_luminance",
2091 metadata->num_rows_mastering_display_actual_peak_luminance);
2092 print_int("num_cols_mastering_display_actual_peak_luminance",
2093 metadata->num_cols_mastering_display_actual_peak_luminance);
2094 for (int i = 0; i < metadata->num_rows_mastering_display_actual_peak_luminance; i++) {
2095 for (int j = 0; j < metadata->num_cols_mastering_display_actual_peak_luminance; j++) {
2096 print_q("mastering_display_actual_peak_luminance",
2097 metadata->mastering_display_actual_peak_luminance[i][j],'/');
2098 }
2099 }
2100 }
2101
2102
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
2 for (int n = 0; n < metadata->num_windows; n++) {
2103 1 const AVHDRPlusColorTransformParams *params = &metadata->params[n];
2104
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (params->tone_mapping_flag) {
2105 1 print_q("knee_point_x", params->knee_point_x,'/');
2106 1 print_q("knee_point_y", params->knee_point_y,'/');
2107 1 print_int("num_bezier_curve_anchors",
2108 params->num_bezier_curve_anchors );
2109
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 1 times.
10 for (int i = 0; i < params->num_bezier_curve_anchors; i++) {
2110 9 print_q("bezier_curve_anchors",
2111 params->bezier_curve_anchors[i],'/');
2112 }
2113 }
2114
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (params->color_saturation_mapping_flag) {
2115 print_q("color_saturation_weight",
2116 params->color_saturation_weight,'/');
2117 }
2118 }
2119 }
2120
2121 855 static void print_pkt_side_data(WriterContext *w,
2122 AVCodecParameters *par,
2123 const AVPacketSideData *side_data,
2124 int nb_side_data,
2125 SectionID id_data_list,
2126 SectionID id_data)
2127 {
2128 int i;
2129
2130 855 writer_print_section_header(w, id_data_list);
2131
2/2
✓ Branch 0 taken 862 times.
✓ Branch 1 taken 855 times.
1717 for (i = 0; i < nb_side_data; i++) {
2132 862 const AVPacketSideData *sd = &side_data[i];
2133 862 const char *name = av_packet_side_data_name(sd->type);
2134
2135 862 writer_print_section_header(w, id_data);
2136
1/2
✓ Branch 0 taken 862 times.
✗ Branch 1 not taken.
862 print_str("side_data_type", name ? name : "unknown");
2137
3/4
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 860 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
862 if (sd->type == AV_PKT_DATA_DISPLAYMATRIX && sd->size >= 9*4) {
2138 2 writer_print_integers(w, "displaymatrix", sd->data, 9, " %11d", 3, 4, 1);
2139 2 print_int("rotation", av_display_rotation_get((int32_t *)sd->data));
2140
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 855 times.
860 } else if (sd->type == AV_PKT_DATA_STEREO3D) {
2141 5 const AVStereo3D *stereo = (AVStereo3D *)sd->data;
2142 5 print_str("type", av_stereo3d_type_name(stereo->type));
2143 5 print_int("inverted", !!(stereo->flags & AV_STEREO3D_FLAG_INVERT));
2144
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 851 times.
855 } else if (sd->type == AV_PKT_DATA_SPHERICAL) {
2145 4 const AVSphericalMapping *spherical = (AVSphericalMapping *)sd->data;
2146 4 print_str("projection", av_spherical_projection_name(spherical->projection));
2147
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (spherical->projection == AV_SPHERICAL_CUBEMAP) {
2148 print_int("padding", spherical->padding);
2149
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 } else if (spherical->projection == AV_SPHERICAL_EQUIRECTANGULAR_TILE) {
2150 size_t l, t, r, b;
2151 4 av_spherical_tile_bounds(spherical, par->width, par->height,
2152 &l, &t, &r, &b);
2153 4 print_int("bound_left", l);
2154 4 print_int("bound_top", t);
2155 4 print_int("bound_right", r);
2156 4 print_int("bound_bottom", b);
2157 }
2158
2159 4 print_int("yaw", (double) spherical->yaw / (1 << 16));
2160 4 print_int("pitch", (double) spherical->pitch / (1 << 16));
2161 4 print_int("roll", (double) spherical->roll / (1 << 16));
2162
3/4
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 841 times.
✓ Branch 2 taken 10 times.
✗ Branch 3 not taken.
851 } else if (sd->type == AV_PKT_DATA_SKIP_SAMPLES && sd->size == 10) {
2163 10 print_int("skip_samples", AV_RL32(sd->data));
2164 10 print_int("discard_padding", AV_RL32(sd->data + 4));
2165 10 print_int("skip_reason", AV_RL8(sd->data + 8));
2166 10 print_int("discard_reason", AV_RL8(sd->data + 9));
2167
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 838 times.
841 } else if (sd->type == AV_PKT_DATA_MASTERING_DISPLAY_METADATA) {
2168 3 AVMasteringDisplayMetadata *metadata = (AVMasteringDisplayMetadata *)sd->data;
2169
2170
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 if (metadata->has_primaries) {
2171 3 print_q("red_x", metadata->display_primaries[0][0], '/');
2172 3 print_q("red_y", metadata->display_primaries[0][1], '/');
2173 3 print_q("green_x", metadata->display_primaries[1][0], '/');
2174 3 print_q("green_y", metadata->display_primaries[1][1], '/');
2175 3 print_q("blue_x", metadata->display_primaries[2][0], '/');
2176 3 print_q("blue_y", metadata->display_primaries[2][1], '/');
2177
2178 3 print_q("white_point_x", metadata->white_point[0], '/');
2179 3 print_q("white_point_y", metadata->white_point[1], '/');
2180 }
2181
2182
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 if (metadata->has_luminance) {
2183 3 print_q("min_luminance", metadata->min_luminance, '/');
2184 3 print_q("max_luminance", metadata->max_luminance, '/');
2185 }
2186
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 835 times.
838 } else if (sd->type == AV_PKT_DATA_CONTENT_LIGHT_LEVEL) {
2187 3 AVContentLightMetadata *metadata = (AVContentLightMetadata *)sd->data;
2188 3 print_int("max_content", metadata->MaxCLL);
2189 3 print_int("max_average", metadata->MaxFALL);
2190
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 834 times.
835 } else if (sd->type == AV_PKT_DATA_DOVI_CONF) {
2191 1 AVDOVIDecoderConfigurationRecord *dovi = (AVDOVIDecoderConfigurationRecord *)sd->data;
2192 1 print_int("dv_version_major", dovi->dv_version_major);
2193 1 print_int("dv_version_minor", dovi->dv_version_minor);
2194 1 print_int("dv_profile", dovi->dv_profile);
2195 1 print_int("dv_level", dovi->dv_level);
2196 1 print_int("rpu_present_flag", dovi->rpu_present_flag);
2197 1 print_int("el_present_flag", dovi->el_present_flag);
2198 1 print_int("bl_present_flag", dovi->bl_present_flag);
2199 1 print_int("dv_bl_signal_compatibility_id", dovi->dv_bl_signal_compatibility_id);
2200
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 831 times.
834 } else if (sd->type == AV_PKT_DATA_AUDIO_SERVICE_TYPE) {
2201 3 enum AVAudioServiceType *t = (enum AVAudioServiceType *)sd->data;
2202 3 print_int("service_type", *t);
2203
2/2
✓ Branch 0 taken 667 times.
✓ Branch 1 taken 164 times.
831 } else if (sd->type == AV_PKT_DATA_MPEGTS_STREAM_ID) {
2204 667 print_int("id", *sd->data);
2205
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 157 times.
164 } else if (sd->type == AV_PKT_DATA_CPB_PROPERTIES) {
2206 7 const AVCPBProperties *prop = (AVCPBProperties *)sd->data;
2207 7 print_int("max_bitrate", prop->max_bitrate);
2208 7 print_int("min_bitrate", prop->min_bitrate);
2209 7 print_int("avg_bitrate", prop->avg_bitrate);
2210 7 print_int("buffer_size", prop->buffer_size);
2211 7 print_int("vbv_delay", prop->vbv_delay);
2212
2/2
✓ Branch 0 taken 149 times.
✓ Branch 1 taken 8 times.
157 } else if (sd->type == AV_PKT_DATA_WEBVTT_IDENTIFIER ||
2213
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 133 times.
149 sd->type == AV_PKT_DATA_WEBVTT_SETTINGS) {
2214
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 24 times.
24 if (do_show_data)
2215 writer_print_data(w, "data", sd->data, sd->size);
2216 24 writer_print_data_hash(w, "data_hash", sd->data, sd->size);
2217 }
2218 862 writer_print_section_footer(w);
2219 }
2220 855 writer_print_section_footer(w);
2221 855 }
2222
2223 534 static void print_color_range(WriterContext *w, enum AVColorRange color_range)
2224 {
2225 534 const char *val = av_color_range_name(color_range);
2226
3/4
✓ Branch 0 taken 534 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 418 times.
✓ Branch 3 taken 116 times.
534 if (!val || color_range == AVCOL_RANGE_UNSPECIFIED) {
2227 418 print_str_opt("color_range", "unknown");
2228 } else {
2229 116 print_str("color_range", val);
2230 }
2231 534 }
2232
2233 534 static void print_color_space(WriterContext *w, enum AVColorSpace color_space)
2234 {
2235 534 const char *val = av_color_space_name(color_space);
2236
3/4
✓ Branch 0 taken 534 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 441 times.
✓ Branch 3 taken 93 times.
534 if (!val || color_space == AVCOL_SPC_UNSPECIFIED) {
2237 441 print_str_opt("color_space", "unknown");
2238 } else {
2239 93 print_str("color_space", val);
2240 }
2241 534 }
2242
2243 534 static void print_primaries(WriterContext *w, enum AVColorPrimaries color_primaries)
2244 {
2245 534 const char *val = av_color_primaries_name(color_primaries);
2246
3/4
✓ Branch 0 taken 534 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 450 times.
✓ Branch 3 taken 84 times.
534 if (!val || color_primaries == AVCOL_PRI_UNSPECIFIED) {
2247 450 print_str_opt("color_primaries", "unknown");
2248 } else {
2249 84 print_str("color_primaries", val);
2250 }
2251 534 }
2252
2253 534 static void print_color_trc(WriterContext *w, enum AVColorTransferCharacteristic color_trc)
2254 {
2255 534 const char *val = av_color_transfer_name(color_trc);
2256
3/4
✓ Branch 0 taken 534 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 449 times.
✓ Branch 3 taken 85 times.
534 if (!val || color_trc == AVCOL_TRC_UNSPECIFIED) {
2257 449 print_str_opt("color_transfer", "unknown");
2258 } else {
2259 85 print_str("color_transfer", val);
2260 }
2261 534 }
2262
2263 534 static void print_chroma_location(WriterContext *w, enum AVChromaLocation chroma_location)
2264 {
2265 534 const char *val = av_chroma_location_name(chroma_location);
2266
3/4
✓ Branch 0 taken 534 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 425 times.
✓ Branch 3 taken 109 times.
534 if (!val || chroma_location == AVCHROMA_LOC_UNSPECIFIED) {
2267 425 print_str_opt("chroma_location", "unspecified");
2268 } else {
2269 109 print_str("chroma_location", val);
2270 }
2271 534 }
2272
2273
2274 5998 static void clear_log(int need_lock)
2275 {
2276 int i;
2277
2278
1/2
✓ Branch 0 taken 5998 times.
✗ Branch 1 not taken.
5998 if (need_lock)
2279 5998 pthread_mutex_lock(&log_mutex);
2280
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5998 times.
5998 for (i=0; i<log_buffer_size; i++) {
2281 av_freep(&log_buffer[i].context_name);
2282 av_freep(&log_buffer[i].parent_name);
2283 av_freep(&log_buffer[i].log_message);
2284 }
2285 5998 log_buffer_size = 0;
2286
1/2
✓ Branch 0 taken 5998 times.
✗ Branch 1 not taken.
5998 if(need_lock)
2287 5998 pthread_mutex_unlock(&log_mutex);
2288 5998 }
2289
2290 static int show_log(WriterContext *w, int section_ids, int section_id, int log_level)
2291 {
2292 int i;
2293 pthread_mutex_lock(&log_mutex);
2294 if (!log_buffer_size) {
2295 pthread_mutex_unlock(&log_mutex);
2296 return 0;
2297 }
2298 writer_print_section_header(w, section_ids);
2299
2300 for (i=0; i<log_buffer_size; i++) {
2301 if (log_buffer[i].log_level <= log_level) {
2302 writer_print_section_header(w, section_id);
2303 print_str("context", log_buffer[i].context_name);
2304 print_int("level", log_buffer[i].log_level);
2305 print_int("category", log_buffer[i].category);
2306 if (log_buffer[i].parent_name) {
2307 print_str("parent_context", log_buffer[i].parent_name);
2308 print_int("parent_category", log_buffer[i].parent_category);
2309 } else {
2310 print_str_opt("parent_context", "N/A");
2311 print_str_opt("parent_category", "N/A");
2312 }
2313 print_str("message", log_buffer[i].log_message);
2314 writer_print_section_footer(w);
2315 }
2316 }
2317 clear_log(0);
2318 pthread_mutex_unlock(&log_mutex);
2319
2320 writer_print_section_footer(w);
2321
2322 return 0;
2323 }
2324
2325 5515 static void show_packet(WriterContext *w, InputFile *ifile, AVPacket *pkt, int packet_idx)
2326 {
2327 char val_str[128];
2328 5515 AVStream *st = ifile->streams[pkt->stream_index].st;
2329 AVBPrint pbuf;
2330 const char *s;
2331
2332 5515 av_bprint_init(&pbuf, 1, AV_BPRINT_SIZE_UNLIMITED);
2333
2334 5515 writer_print_section_header(w, SECTION_ID_PACKET);
2335
2336 5515 s = av_get_media_type_string(st->codecpar->codec_type);
2337
1/2
✓ Branch 0 taken 5515 times.
✗ Branch 1 not taken.
5515 if (s) print_str ("codec_type", s);
2338 else print_str_opt("codec_type", "unknown");
2339 5515 print_int("stream_index", pkt->stream_index);
2340 5515 print_ts ("pts", pkt->pts);
2341 5515 print_time("pts_time", pkt->pts, &st->time_base);
2342 5515 print_ts ("dts", pkt->dts);
2343 5515 print_time("dts_time", pkt->dts, &st->time_base);
2344 5515 print_duration_ts("duration", pkt->duration);
2345 5515 print_duration_time("duration_time", pkt->duration, &st->time_base);
2346 5515 print_val("size", pkt->size, unit_byte_str);
2347
2/2
✓ Branch 0 taken 5427 times.
✓ Branch 1 taken 88 times.
5515 if (pkt->pos != -1) print_fmt ("pos", "%"PRId64, pkt->pos);
2348 88 else print_str_opt("pos", "N/A");
2349
4/4
✓ Branch 1 taken 6 times.
✓ Branch 2 taken 5509 times.
✓ Branch 3 taken 4555 times.
✓ Branch 4 taken 960 times.
5515 print_fmt("flags", "%c%c", pkt->flags & AV_PKT_FLAG_KEY ? 'K' : '_',
2350 pkt->flags & AV_PKT_FLAG_DISCARD ? 'D' : '_');
2351
2352
2/2
✓ Branch 0 taken 834 times.
✓ Branch 1 taken 4681 times.
5515 if (pkt->side_data_elems) {
2353 size_t size;
2354 const uint8_t *side_metadata;
2355
2356 834 side_metadata = av_packet_get_side_data(pkt, AV_PKT_DATA_STRINGS_METADATA, &size);
2357
4/6
✓ Branch 0 taken 131 times.
✓ Branch 1 taken 703 times.
✓ Branch 2 taken 131 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 131 times.
✗ Branch 5 not taken.
834 if (side_metadata && size && do_show_packet_tags) {
2358 131 AVDictionary *dict = NULL;
2359
1/2
✓ Branch 1 taken 131 times.
✗ Branch 2 not taken.
131 if (av_packet_unpack_dictionary(side_metadata, size, &dict) >= 0)
2360 131 show_tags(w, dict, SECTION_ID_PACKET_TAGS);
2361 131 av_dict_free(&dict);
2362 }
2363
2364 834 print_pkt_side_data(w, st->codecpar, pkt->side_data, pkt->side_data_elems,
2365 SECTION_ID_PACKET_SIDE_DATA_LIST,
2366 SECTION_ID_PACKET_SIDE_DATA);
2367 }
2368
2369
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5515 times.
5515 if (do_show_data)
2370 writer_print_data(w, "data", pkt->data, pkt->size);
2371 5515 writer_print_data_hash(w, "data_hash", pkt->data, pkt->size);
2372 5515 writer_print_section_footer(w);
2373
2374 5515 av_bprint_finalize(&pbuf, NULL);
2375 5515 fflush(stdout);
2376 5515 }
2377
2378 static void show_subtitle(WriterContext *w, AVSubtitle *sub, AVStream *stream,
2379 AVFormatContext *fmt_ctx)
2380 {
2381 AVBPrint pbuf;
2382
2383 av_bprint_init(&pbuf, 1, AV_BPRINT_SIZE_UNLIMITED);
2384
2385 writer_print_section_header(w, SECTION_ID_SUBTITLE);
2386
2387 print_str ("media_type", "subtitle");
2388 print_ts ("pts", sub->pts);
2389 print_time("pts_time", sub->pts, &AV_TIME_BASE_Q);
2390 print_int ("format", sub->format);
2391 print_int ("start_display_time", sub->start_display_time);
2392 print_int ("end_display_time", sub->end_display_time);
2393 print_int ("num_rects", sub->num_rects);
2394
2395 writer_print_section_footer(w);
2396
2397 av_bprint_finalize(&pbuf, NULL);
2398 fflush(stdout);
2399 }
2400
2401 3041 static void show_frame(WriterContext *w, AVFrame *frame, AVStream *stream,
2402 AVFormatContext *fmt_ctx)
2403 {
2404 AVBPrint pbuf;
2405 char val_str[128];
2406 const char *s;
2407 int i;
2408
2409 3041 av_bprint_init(&pbuf, 1, AV_BPRINT_SIZE_UNLIMITED);
2410
2411 3041 writer_print_section_header(w, SECTION_ID_FRAME);
2412
2413 3041 s = av_get_media_type_string(stream->codecpar->codec_type);
2414
1/2
✓ Branch 0 taken 3041 times.
✗ Branch 1 not taken.
3041 if (s) print_str ("media_type", s);
2415 else print_str_opt("media_type", "unknown");
2416 3041 print_int("stream_index", stream->index);
2417 3041 print_int("key_frame", frame->key_frame);
2418 3041 print_ts ("pts", frame->pts);
2419 3041 print_time("pts_time", frame->pts, &stream->time_base);
2420 3041 print_ts ("pkt_dts", frame->pkt_dts);
2421 3041 print_time("pkt_dts_time", frame->pkt_dts, &stream->time_base);
2422 3041 print_ts ("best_effort_timestamp", frame->best_effort_timestamp);
2423 3041 print_time("best_effort_timestamp_time", frame->best_effort_timestamp, &stream->time_base);
2424 3041 print_duration_ts ("pkt_duration", frame->pkt_duration);
2425 3041 print_duration_time("pkt_duration_time", frame->pkt_duration, &stream->time_base);
2426
2/2
✓ Branch 0 taken 2738 times.
✓ Branch 1 taken 303 times.
3041 if (frame->pkt_pos != -1) print_fmt ("pkt_pos", "%"PRId64, frame->pkt_pos);
2427 303 else print_str_opt("pkt_pos", "N/A");
2428
1/2
✓ Branch 0 taken 3041 times.
✗ Branch 1 not taken.
3041 if (frame->pkt_size != -1) print_val ("pkt_size", frame->pkt_size, unit_byte_str);
2429 else print_str_opt("pkt_size", "N/A");
2430
2431
2/3
✓ Branch 0 taken 466 times.
✓ Branch 1 taken 2575 times.
✗ Branch 2 not taken.
3041 switch (stream->codecpar->codec_type) {
2432 AVRational sar;
2433
2434 466 case AVMEDIA_TYPE_VIDEO:
2435 466 print_int("width", frame->width);
2436 466 print_int("height", frame->height);
2437 466 s = av_get_pix_fmt_name(frame->format);
2438
1/2
✓ Branch 0 taken 466 times.
✗ Branch 1 not taken.
466 if (s) print_str ("pix_fmt", s);
2439 else print_str_opt("pix_fmt", "unknown");
2440 466 sar = av_guess_sample_aspect_ratio(fmt_ctx, stream, frame);
2441
2/2
✓ Branch 0 taken 461 times.
✓ Branch 1 taken 5 times.
466 if (sar.num) {
2442 461 print_q("sample_aspect_ratio", sar, ':');
2443 } else {
2444 5 print_str_opt("sample_aspect_ratio", "N/A");
2445 }
2446 466 print_fmt("pict_type", "%c", av_get_picture_type_char(frame->pict_type));
2447 466 print_int("coded_picture_number", frame->coded_picture_number);
2448 466 print_int("display_picture_number", frame->display_picture_number);
2449 466 print_int("interlaced_frame", frame->interlaced_frame);
2450 466 print_int("top_field_first", frame->top_field_first);
2451 466 print_int("repeat_pict", frame->repeat_pict);
2452
2453 466 print_color_range(w, frame->color_range);
2454 466 print_color_space(w, frame->colorspace);
2455 466 print_primaries(w, frame->color_primaries);
2456 466 print_color_trc(w, frame->color_trc);
2457 466 print_chroma_location(w, frame->chroma_location);
2458 466 break;
2459
2460 2575 case AVMEDIA_TYPE_AUDIO:
2461 2575 s = av_get_sample_fmt_name(frame->format);
2462
1/2
✓ Branch 0 taken 2575 times.
✗ Branch 1 not taken.
2575 if (s) print_str ("sample_fmt", s);
2463 else print_str_opt("sample_fmt", "unknown");
2464 2575 print_int("nb_samples", frame->nb_samples);
2465 2575 print_int("channels", frame->channels);
2466
2/2
✓ Branch 0 taken 2352 times.
✓ Branch 1 taken 223 times.
2575 if (frame->channel_layout) {
2467 2352 av_bprint_clear(&pbuf);
2468 2352 av_bprint_channel_layout(&pbuf, frame->channels,
2469 frame->channel_layout);
2470 2352 print_str ("channel_layout", pbuf.str);
2471 } else
2472 223 print_str_opt("channel_layout", "unknown");
2473 2575 break;
2474 }
2475
2/2
✓ Branch 0 taken 1060 times.
✓ Branch 1 taken 1981 times.
3041 if (do_show_frame_tags)
2476 1060 show_tags(w, frame->metadata, SECTION_ID_FRAME_TAGS);
2477
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3041 times.
3041 if (do_show_log)
2478 show_log(w, SECTION_ID_FRAME_LOGS, SECTION_ID_FRAME_LOG, do_show_log);
2479
2/2
✓ Branch 0 taken 71 times.
✓ Branch 1 taken 2970 times.
3041 if (frame->nb_side_data) {
2480 71 writer_print_section_header(w, SECTION_ID_FRAME_SIDE_DATA_LIST);
2481
2/2
✓ Branch 0 taken 77 times.
✓ Branch 1 taken 71 times.
148 for (i = 0; i < frame->nb_side_data; i++) {
2482 77 AVFrameSideData *sd = frame->side_data[i];
2483 const char *name;
2484
2485 77 writer_print_section_header(w, SECTION_ID_FRAME_SIDE_DATA);
2486 77 name = av_frame_side_data_name(sd->type);
2487
1/2
✓ Branch 0 taken 77 times.
✗ Branch 1 not taken.
77 print_str("side_data_type", name ? name : "unknown");
2488
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 77 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
77 if (sd->type == AV_FRAME_DATA_DISPLAYMATRIX && sd->size >= 9*4) {
2489 writer_print_integers(w, "displaymatrix", sd->data, 9, " %11d", 3, 4, 1);
2490 print_int("rotation", av_display_rotation_get((int32_t *)sd->data));
2491
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 77 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
77 } else if (sd->type == AV_FRAME_DATA_GOP_TIMECODE && sd->size >= 8) {
2492 char tcbuf[AV_TIMECODE_STR_SIZE];
2493 av_timecode_make_mpeg_tc_string(tcbuf, *(int64_t *)(sd->data));
2494 print_str("timecode", tcbuf);
2495
3/4
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 76 times.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
78 } else if (sd->type == AV_FRAME_DATA_S12M_TIMECODE && sd->size == 16) {
2496 1 uint32_t *tc = (uint32_t*)sd->data;
2497 1 int m = FFMIN(tc[0],3);
2498 1 writer_print_section_header(w, SECTION_ID_FRAME_SIDE_DATA_TIMECODE_LIST);
2499
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
2 for (int j = 1; j <= m ; j++) {
2500 char tcbuf[AV_TIMECODE_STR_SIZE];
2501 1 av_timecode_make_smpte_tc_string2(tcbuf, stream->avg_frame_rate, tc[j], 0, 0);
2502 1 writer_print_section_header(w, SECTION_ID_FRAME_SIDE_DATA_TIMECODE);
2503 1 print_str("value", tcbuf);
2504 1 writer_print_section_footer(w);
2505 }
2506 1 writer_print_section_footer(w);
2507
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 74 times.
76 } else if (sd->type == AV_FRAME_DATA_MASTERING_DISPLAY_METADATA) {
2508 2 AVMasteringDisplayMetadata *metadata = (AVMasteringDisplayMetadata *)sd->data;
2509
2510
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (metadata->has_primaries) {
2511 2 print_q("red_x", metadata->display_primaries[0][0], '/');
2512 2 print_q("red_y", metadata->display_primaries[0][1], '/');
2513 2 print_q("green_x", metadata->display_primaries[1][0], '/');
2514 2 print_q("green_y", metadata->display_primaries[1][1], '/');
2515 2 print_q("blue_x", metadata->display_primaries[2][0], '/');
2516 2 print_q("blue_y", metadata->display_primaries[2][1], '/');
2517
2518 2 print_q("white_point_x", metadata->white_point[0], '/');
2519 2 print_q("white_point_y", metadata->white_point[1], '/');
2520 }
2521
2522
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
2 if (metadata->has_luminance) {
2523 1 print_q("min_luminance", metadata->min_luminance, '/');
2524 1 print_q("max_luminance", metadata->max_luminance, '/');
2525 }
2526
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 73 times.
74 } else if (sd->type == AV_FRAME_DATA_DYNAMIC_HDR_PLUS) {
2527 1 AVDynamicHDRPlus *metadata = (AVDynamicHDRPlus *)sd->data;
2528 1 print_dynamic_hdr10_plus(w, metadata);
2529
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 72 times.
73 } else if (sd->type == AV_FRAME_DATA_CONTENT_LIGHT_LEVEL) {
2530 1 AVContentLightMetadata *metadata = (AVContentLightMetadata *)sd->data;
2531 1 print_int("max_content", metadata->MaxCLL);
2532 1 print_int("max_average", metadata->MaxFALL);
2533
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 71 times.
72 } else if (sd->type == AV_FRAME_DATA_ICC_PROFILE) {
2534 1 const AVDictionaryEntry *tag = av_dict_get(sd->metadata, "name", NULL, AV_DICT_MATCH_CASE);
2535
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (tag)
2536 1 print_str(tag->key, tag->value);
2537 1 print_int("size", sd->size);
2538
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 69 times.
71 } else if (sd->type == AV_FRAME_DATA_DOVI_METADATA) {
2539 2 print_dovi_metadata(w, (const AVDOVIMetadata *)sd->data);
2540 }
2541 77 writer_print_section_footer(w);
2542 }
2543 71 writer_print_section_footer(w);
2544 }
2545
2546 3041 writer_print_section_footer(w);
2547
2548 3041 av_bprint_finalize(&pbuf, NULL);
2549 3041 fflush(stdout);
2550 3041 }
2551
2552 5998 static av_always_inline int process_frame(WriterContext *w,
2553 InputFile *ifile,
2554 AVFrame *frame, AVPacket *pkt,
2555 int *packet_new)
2556 {
2557 5998 AVFormatContext *fmt_ctx = ifile->fmt_ctx;
2558 5998 AVCodecContext *dec_ctx = ifile->streams[pkt->stream_index].dec_ctx;
2559 5998 AVCodecParameters *par = ifile->streams[pkt->stream_index].st->codecpar;
2560 AVSubtitle sub;
2561 5998 int ret = 0, got_frame = 0;
2562
2563 5998 clear_log(1);
2564
3/4
✓ Branch 0 taken 5995 times.
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 5995 times.
✗ Branch 3 not taken.
5998 if (dec_ctx && dec_ctx->codec) {
2565
1/3
✓ Branch 0 taken 5995 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
5995 switch (par->codec_type) {
2566 5995 case AVMEDIA_TYPE_VIDEO:
2567 case AVMEDIA_TYPE_AUDIO:
2568
2/2
✓ Branch 0 taken 2963 times.
✓ Branch 1 taken 3032 times.
5995 if (*packet_new) {
2569 2963 ret = avcodec_send_packet(dec_ctx, pkt);
2570
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2963 times.
2963 if (ret == AVERROR(EAGAIN)) {
2571 ret = 0;
2572
4/4
✓ Branch 0 taken 11 times.
✓ Branch 1 taken 2952 times.
✓ Branch 2 taken 9 times.
✓ Branch 3 taken 2 times.
2963 } else if (ret >= 0 || ret == AVERROR_EOF) {
2573 2961 ret = 0;
2574 2961 *packet_new = 0;
2575 }
2576 }
2577
2/2
✓ Branch 0 taken 5993 times.
✓ Branch 1 taken 2 times.
5995 if (ret >= 0) {
2578 5993 ret = avcodec_receive_frame(dec_ctx, frame);
2579
2/2
✓ Branch 0 taken 3041 times.
✓ Branch 1 taken 2952 times.
5993 if (ret >= 0) {
2580 3041 got_frame = 1;
2581
3/4
✓ Branch 0 taken 58 times.
✓ Branch 1 taken 2894 times.
✓ Branch 2 taken 58 times.
✗ Branch 3 not taken.
2952 } else if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) {
2582 2952 ret = 0;
2583 }
2584 }
2585 5995 break;
2586
2587 case AVMEDIA_TYPE_SUBTITLE:
2588 if (*packet_new)
2589 ret = avcodec_decode_subtitle2(dec_ctx, &sub, &got_frame, pkt);
2590 *packet_new = 0;
2591 break;
2592 default:
2593 *packet_new = 0;
2594 }
2595 } else {
2596 3 *packet_new = 0;
2597 }
2598
2599
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 5996 times.
5998 if (ret < 0)
2600 2 return ret;
2601
2/2
✓ Branch 0 taken 3041 times.
✓ Branch 1 taken 2955 times.
5996 if (got_frame) {
2602 3041 int is_sub = (par->codec_type == AVMEDIA_TYPE_SUBTITLE);
2603 3041 nb_streams_frames[pkt->stream_index]++;
2604
1/2
✓ Branch 0 taken 3041 times.
✗ Branch 1 not taken.
3041 if (do_show_frames)
2605
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3041 times.
3041 if (is_sub)
2606 show_subtitle(w, &sub, ifile->streams[pkt->stream_index].st, fmt_ctx);
2607 else
2608 3041 show_frame(w, frame, ifile->streams[pkt->stream_index].st, fmt_ctx);
2609
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3041 times.
3041 if (is_sub)
2610 avsubtitle_free(&sub);
2611 }
2612
3/4
✓ Branch 0 taken 2955 times.
✓ Branch 1 taken 3041 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 2955 times.
5996 return got_frame || *packet_new;
2613 }
2614
2615 63 static void log_read_interval(const ReadInterval *interval, void *log_ctx, int log_level)
2616 {
2617 63 av_log(log_ctx, log_level, "id:%d", interval->id);
2618
2619
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 63 times.
63 if (interval->has_start) {
2620 av_log(log_ctx, log_level, " start:%s%s", interval->start_is_offset ? "+" : "",
2621 av_ts2timestr(interval->start, &AV_TIME_BASE_Q));
2622 } else {
2623 63 av_log(log_ctx, log_level, " start:N/A");
2624 }
2625
2626
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 61 times.
63 if (interval->has_end) {
2627
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 av_log(log_ctx, log_level, " end:%s", interval->end_is_offset ? "+" : "");
2628
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (interval->duration_frames)
2629 2 av_log(log_ctx, log_level, "#%"PRId64, interval->end);
2630 else
2631 av_log(log_ctx, log_level, "%s", av_ts2timestr(interval->end, &AV_TIME_BASE_Q));
2632 } else {
2633 61 av_log(log_ctx, log_level, " end:N/A");
2634 }
2635
2636 63 av_log(log_ctx, log_level, "\n");
2637 63 }
2638
2639 62 static int read_interval_packets(WriterContext *w, InputFile *ifile,
2640 const ReadInterval *interval, int64_t *cur_ts)
2641 {
2642 62 AVFormatContext *fmt_ctx = ifile->fmt_ctx;
2643 62 AVPacket *pkt = NULL;
2644 62 AVFrame *frame = NULL;
2645 62 int ret = 0, i = 0, frame_count = 0;
2646 62 int64_t start = -INT64_MAX, end = interval->end;
2647
3/4
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 61 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
62 int has_start = 0, has_end = interval->has_end && !interval->end_is_offset;
2648
2649 62 av_log(NULL, AV_LOG_VERBOSE, "Processing read interval ");
2650 62 log_read_interval(interval, NULL, AV_LOG_VERBOSE);
2651
2652
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 62 times.
62 if (interval->has_start) {
2653 int64_t target;
2654 if (interval->start_is_offset) {
2655 if (*cur_ts == AV_NOPTS_VALUE) {
2656 av_log(NULL, AV_LOG_ERROR,
2657 "Could not seek to relative position since current "
2658 "timestamp is not defined\n");
2659 ret = AVERROR(EINVAL);
2660 goto end;
2661 }
2662 target = *cur_ts + interval->start;
2663 } else {
2664 target = interval->start;
2665 }
2666
2667 av_log(NULL, AV_LOG_VERBOSE, "Seeking to read interval start point %s\n",
2668 av_ts2timestr(target, &AV_TIME_BASE_Q));
2669 if ((ret = avformat_seek_file(fmt_ctx, -1, -INT64_MAX, target, INT64_MAX, 0)) < 0) {
2670 av_log(NULL, AV_LOG_ERROR, "Could not seek to position %"PRId64": %s\n",
2671 interval->start, av_err2str(ret));
2672 goto end;
2673 }
2674 }
2675
2676 62 frame = av_frame_alloc();
2677
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 62 times.
62 if (!frame) {
2678 ret = AVERROR(ENOMEM);
2679 goto end;
2680 }
2681 62 pkt = av_packet_alloc();
2682
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 62 times.
62 if (!pkt) {
2683 ret = AVERROR(ENOMEM);
2684 goto end;
2685 }
2686
2/2
✓ Branch 1 taken 8261 times.
✓ Branch 2 taken 61 times.
8322 while (!av_read_frame(fmt_ctx, pkt)) {
2687
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8261 times.
8261 if (fmt_ctx->nb_streams > nb_streams) {
2688 REALLOCZ_ARRAY_STREAM(nb_streams_frames, nb_streams, fmt_ctx->nb_streams);
2689 REALLOCZ_ARRAY_STREAM(nb_streams_packets, nb_streams, fmt_ctx->nb_streams);
2690 REALLOCZ_ARRAY_STREAM(selected_streams, nb_streams, fmt_ctx->nb_streams);
2691 nb_streams = fmt_ctx->nb_streams;
2692 }
2693
2/2
✓ Branch 0 taken 8217 times.
✓ Branch 1 taken 44 times.
8261 if (selected_streams[pkt->stream_index]) {
2694 8217 AVRational tb = ifile->streams[pkt->stream_index].st->time_base;
2695
2696
2/2
✓ Branch 0 taken 8204 times.
✓ Branch 1 taken 13 times.
8217 if (pkt->pts != AV_NOPTS_VALUE)
2697 8204 *cur_ts = av_rescale_q(pkt->pts, tb, AV_TIME_BASE_Q);
2698
2699
4/4
✓ Branch 0 taken 70 times.
✓ Branch 1 taken 8147 times.
✓ Branch 2 taken 58 times.
✓ Branch 3 taken 12 times.
8217 if (!has_start && *cur_ts != AV_NOPTS_VALUE) {
2700 58 start = *cur_ts;
2701 58 has_start = 1;
2702 }
2703
2704
6/6
✓ Branch 0 taken 8205 times.
✓ Branch 1 taken 12 times.
✓ Branch 2 taken 8203 times.
✓ Branch 3 taken 2 times.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 8202 times.
8217 if (has_start && !has_end && interval->end_is_offset) {
2705 1 end = start + interval->end;
2706 1 has_end = 1;
2707 }
2708
2709
3/4
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 8214 times.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
8217 if (interval->end_is_offset && interval->duration_frames) {
2710
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 2 times.
3 if (frame_count >= interval->end)
2711 1 break;
2712
1/6
✗ Branch 0 not taken.
✓ Branch 1 taken 8214 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
8214 } else if (has_end && *cur_ts != AV_NOPTS_VALUE && *cur_ts >= end) {
2713 break;
2714 }
2715
2716 8216 frame_count++;
2717
2/2
✓ Branch 0 taken 5515 times.
✓ Branch 1 taken 2701 times.
8216 if (do_read_packets) {
2718
1/2
✓ Branch 0 taken 5515 times.
✗ Branch 1 not taken.
5515 if (do_show_packets)
2719 5515 show_packet(w, ifile, pkt, i++);
2720 5515 nb_streams_packets[pkt->stream_index]++;
2721 }
2722
2/2
✓ Branch 0 taken 2896 times.
✓ Branch 1 taken 5320 times.
8216 if (do_read_frames) {
2723 2896 int packet_new = 1;
2724
2/2
✓ Branch 1 taken 3032 times.
✓ Branch 2 taken 2896 times.
5928 while (process_frame(w, ifile, frame, pkt, &packet_new) > 0);
2725 }
2726 }
2727 8260 av_packet_unref(pkt);
2728 }
2729 62 av_packet_unref(pkt);
2730 //Flush remaining frames that are cached in the decoder
2731
2/2
✓ Branch 0 taken 97 times.
✓ Branch 1 taken 62 times.
159 for (i = 0; i < fmt_ctx->nb_streams; i++) {
2732 97 pkt->stream_index = i;
2733
2/2
✓ Branch 0 taken 61 times.
✓ Branch 1 taken 36 times.
97 if (do_read_frames)
2734
2/2
✓ Branch 1 taken 9 times.
✓ Branch 2 taken 61 times.
70 while (process_frame(w, ifile, frame, pkt, &(int){1}) > 0);
2735 }
2736
2737 62 end:
2738 62 av_frame_free(&frame);
2739 62 av_packet_free(&pkt);
2740
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 62 times.
62 if (ret < 0) {
2741 av_log(NULL, AV_LOG_ERROR, "Could not read packets in interval ");
2742 log_read_interval(interval, NULL, AV_LOG_ERROR);
2743 }
2744 62 return ret;
2745 }
2746
2747 62 static int read_packets(WriterContext *w, InputFile *ifile)
2748 {
2749 62 AVFormatContext *fmt_ctx = ifile->fmt_ctx;
2750 62 int i, ret = 0;
2751 62 int64_t cur_ts = fmt_ctx->start_time;
2752
2753
2/2
✓ Branch 0 taken 61 times.
✓ Branch 1 taken 1 times.
62 if (read_intervals_nb == 0) {
2754 61 ReadInterval interval = (ReadInterval) { .has_start = 0, .has_end = 0 };
2755 61 ret = read_interval_packets(w, ifile, &interval, &cur_ts);
2756 } else {
2757
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
2 for (i = 0; i < read_intervals_nb; i++) {
2758 1 ret = read_interval_packets(w, ifile, &read_intervals[i], &cur_ts);
2759
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (ret < 0)
2760 break;
2761 }
2762 }
2763
2764 62 return ret;
2765 }
2766
2767 140 static int show_stream(WriterContext *w, AVFormatContext *fmt_ctx, int stream_idx, InputStream *ist, int in_program)
2768 {
2769 140 AVStream *stream = ist->st;
2770 AVCodecParameters *par;
2771 AVCodecContext *dec_ctx;
2772 char val_str[128];
2773 const char *s;
2774 AVRational sar, dar;
2775 AVBPrint pbuf;
2776 const AVCodecDescriptor *cd;
2777 140 int ret = 0;
2778 140 const char *profile = NULL;
2779
2780 140 av_bprint_init(&pbuf, 1, AV_BPRINT_SIZE_UNLIMITED);
2781
2782
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 132 times.
140 writer_print_section_header(w, in_program ? SECTION_ID_PROGRAM_STREAM : SECTION_ID_STREAM);
2783
2784 140 print_int("index", stream->index);
2785
2786 140 par = stream->codecpar;
2787 140 dec_ctx = ist->dec_ctx;
2788
2/2
✓ Branch 1 taken 135 times.
✓ Branch 2 taken 5 times.
140 if (cd = avcodec_descriptor_get(par->codec_id)) {
2789 135 print_str("codec_name", cd->name);
2790
2/2
✓ Branch 0 taken 49 times.
✓ Branch 1 taken 86 times.
135 if (!do_bitexact) {
2791
1/2
✓ Branch 0 taken 49 times.
✗ Branch 1 not taken.
49 print_str("codec_long_name",
2792 cd->long_name ? cd->long_name : "unknown");
2793 }
2794 } else {
2795 5 print_str_opt("codec_name", "unknown");
2796
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 3 times.
5 if (!do_bitexact) {
2797 2 print_str_opt("codec_long_name", "unknown");
2798 }
2799 }
2800
2801
4/4
✓ Branch 0 taken 51 times.
✓ Branch 1 taken 89 times.
✓ Branch 3 taken 21 times.
✓ Branch 4 taken 30 times.
140 if (!do_bitexact && (profile = avcodec_profile_name(par->codec_id, par->profile)))
2802 21 print_str("profile", profile);
2803 else {
2804
2/2
✓ Branch 0 taken 33 times.
✓ Branch 1 taken 86 times.
119 if (par->profile != FF_PROFILE_UNKNOWN) {
2805 char profile_num[12];
2806 33 snprintf(profile_num, sizeof(profile_num), "%d", par->profile);
2807 33 print_str("profile", profile_num);
2808 } else
2809 86 print_str_opt("profile", "unknown");
2810 }
2811
2812 140 s = av_get_media_type_string(par->codec_type);
2813
1/2
✓ Branch 0 taken 140 times.
✗ Branch 1 not taken.
140 if (s) print_str ("codec_type", s);
2814 else print_str_opt("codec_type", "unknown");
2815
2816 /* print AVI/FourCC tag */
2817 140 print_str("codec_tag_string", av_fourcc2str(par->codec_tag));
2818 140 print_fmt("codec_tag", "0x%04"PRIx32, par->codec_tag);
2819
2820
4/4
✓ Branch 0 taken 68 times.
✓ Branch 1 taken 59 times.
✓ Branch 2 taken 5 times.
✓ Branch 3 taken 8 times.
140 switch (par->codec_type) {
2821 68 case AVMEDIA_TYPE_VIDEO:
2822 68 print_int("width", par->width);
2823 68 print_int("height", par->height);
2824
1/2
✓ Branch 0 taken 68 times.
✗ Branch 1 not taken.
68 if (dec_ctx) {
2825 68 print_int("coded_width", dec_ctx->coded_width);
2826 68 print_int("coded_height", dec_ctx->coded_height);
2827 68 print_int("closed_captions", !!(dec_ctx->properties & FF_CODEC_PROPERTY_CLOSED_CAPTIONS));
2828 68 print_int("film_grain", !!(dec_ctx->properties & FF_CODEC_PROPERTY_FILM_GRAIN));
2829 }
2830 68 print_int("has_b_frames", par->video_delay);
2831 68 sar = av_guess_sample_aspect_ratio(fmt_ctx, stream, NULL);
2832
2/2
✓ Branch 0 taken 56 times.
✓ Branch 1 taken 12 times.
68 if (sar.num) {
2833 56 print_q("sample_aspect_ratio", sar, ':');
2834 56 av_reduce(&dar.num, &dar.den,
2835 56 par->width * sar.num,
2836 56 par->height * sar.den,
2837 1024*1024);
2838 56 print_q("display_aspect_ratio", dar, ':');
2839 } else {
2840 12 print_str_opt("sample_aspect_ratio", "N/A");
2841 12 print_str_opt("display_aspect_ratio", "N/A");
2842 }
2843 68 s = av_get_pix_fmt_name(par->format);
2844
2/2
✓ Branch 0 taken 66 times.
✓ Branch 1 taken 2 times.
68 if (s) print_str ("pix_fmt", s);
2845 2 else print_str_opt("pix_fmt", "unknown");
2846 68 print_int("level", par->level);
2847
2848 68 print_color_range(w, par->color_range);
2849 68 print_color_space(w, par->color_space);
2850 68 print_color_trc(w, par->color_trc);
2851 68 print_primaries(w, par->color_primaries);
2852 68 print_chroma_location(w, par->chroma_location);
2853
2854
2/2
✓ Branch 0 taken 21 times.
✓ Branch 1 taken 47 times.
68 if (par->field_order == AV_FIELD_PROGRESSIVE)
2855 21 print_str("field_order", "progressive");
2856
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 42 times.
47 else if (par->field_order == AV_FIELD_TT)
2857 5 print_str("field_order", "tt");
2858
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 41 times.
42 else if (par->field_order == AV_FIELD_BB)
2859 1 print_str("field_order", "bb");
2860
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 39 times.
41 else if (par->field_order == AV_FIELD_TB)
2861 2 print_str("field_order", "tb");
2862
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 39 times.
39 else if (par->field_order == AV_FIELD_BT)
2863 print_str("field_order", "bt");
2864 else
2865 39 print_str_opt("field_order", "unknown");
2866
2867
1/2
✓ Branch 0 taken 68 times.
✗ Branch 1 not taken.
68 if (dec_ctx)
2868 68 print_int("refs", dec_ctx->refs);
2869 68 break;
2870
2871 59 case AVMEDIA_TYPE_AUDIO:
2872 59 s = av_get_sample_fmt_name(par->format);
2873
1/2
✓ Branch 0 taken 59 times.
✗ Branch 1 not taken.
59 if (s) print_str ("sample_fmt", s);
2874 else print_str_opt("sample_fmt", "unknown");
2875 59 print_val("sample_rate", par->sample_rate, unit_hertz_str);
2876 59 print_int("channels", par->channels);
2877
2878
2/2
✓ Branch 0 taken 36 times.
✓ Branch 1 taken 23 times.
59 if (par->channel_layout) {
2879 36 av_bprint_clear(&pbuf);
2880 36 av_bprint_channel_layout(&pbuf, par->channels, par->channel_layout);
2881 36 print_str ("channel_layout", pbuf.str);
2882 } else {
2883 23 print_str_opt("channel_layout", "unknown");
2884 }
2885
2886 59 print_int("bits_per_sample", av_get_bits_per_sample(par->codec_id));
2887 59 break;
2888
2889 5 case AVMEDIA_TYPE_SUBTITLE:
2890
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (par->width)
2891 print_int("width", par->width);
2892 else
2893 5 print_str_opt("width", "N/A");
2894
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (par->height)
2895 print_int("height", par->height);
2896 else
2897 5 print_str_opt("height", "N/A");
2898 5 break;
2899 }
2900
2901
7/8
✓ Branch 0 taken 132 times.
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 132 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 73 times.
✓ Branch 5 taken 59 times.
✓ Branch 6 taken 71 times.
✓ Branch 7 taken 2 times.
140 if (dec_ctx && dec_ctx->codec && dec_ctx->codec->priv_class && show_private_data) {
2902 71 const AVOption *opt = NULL;
2903
2/2
✓ Branch 1 taken 280 times.
✓ Branch 2 taken 71 times.
351 while (opt = av_opt_next(dec_ctx->priv_data,opt)) {
2904 uint8_t *str;
2905
2/2
✓ Branch 0 taken 252 times.
✓ Branch 1 taken 28 times.
280 if (!(opt->flags & AV_OPT_FLAG_EXPORT)) continue;
2906
1/2
✓ Branch 1 taken 28 times.
✗ Branch 2 not taken.
28 if (av_opt_get(dec_ctx->priv_data, opt->name, 0, &str) >= 0) {
2907 28 print_str(opt->name, str);
2908 28 av_free(str);
2909 }
2910 }
2911 }
2912
2913
2/2
✓ Branch 0 taken 53 times.
✓ Branch 1 taken 87 times.
140 if (fmt_ctx->iformat->flags & AVFMT_SHOW_IDS) print_fmt ("id", "0x%x", stream->id);
2914 87 else print_str_opt("id", "N/A");
2915 140 print_q("r_frame_rate", stream->r_frame_rate, '/');
2916 140 print_q("avg_frame_rate", stream->avg_frame_rate, '/');
2917 140 print_q("time_base", stream->time_base, '/');
2918 140 print_ts ("start_pts", stream->start_time);
2919 140 print_time("start_time", stream->start_time, &stream->time_base);
2920 140 print_ts ("duration_ts", stream->duration);
2921 140 print_time("duration", stream->duration, &stream->time_base);
2922
2/2
✓ Branch 0 taken 69 times.
✓ Branch 1 taken 71 times.
140 if (par->bit_rate > 0) print_val ("bit_rate", par->bit_rate, unit_bit_per_second_str);
2923 71 else print_str_opt("bit_rate", "N/A");
2924
3/4
✓ Branch 0 taken 132 times.
✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 132 times.
140 if (dec_ctx && dec_ctx->rc_max_rate > 0)
2925 print_val ("max_bit_rate", dec_ctx->rc_max_rate, unit_bit_per_second_str);
2926 else
2927 140 print_str_opt("max_bit_rate", "N/A");
2928
4/4
✓ Branch 0 taken 132 times.
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 31 times.
✓ Branch 3 taken 101 times.
140 if (dec_ctx && dec_ctx->bits_per_raw_sample > 0) print_fmt("bits_per_raw_sample", "%d", dec_ctx->bits_per_raw_sample);
2929 109 else print_str_opt("bits_per_raw_sample", "N/A");
2930
2/2
✓ Branch 0 taken 29 times.
✓ Branch 1 taken 111 times.
140 if (stream->nb_frames) print_fmt ("nb_frames", "%"PRId64, stream->nb_frames);
2931 111 else print_str_opt("nb_frames", "N/A");
2932
2/2
✓ Branch 0 taken 30 times.
✓ Branch 1 taken 110 times.
140 if (nb_streams_frames[stream_idx]) print_fmt ("nb_read_frames", "%"PRIu64, nb_streams_frames[stream_idx]);
2933 110 else print_str_opt("nb_read_frames", "N/A");
2934
2/2
✓ Branch 0 taken 56 times.
✓ Branch 1 taken 84 times.
140 if (nb_streams_packets[stream_idx]) print_fmt ("nb_read_packets", "%"PRIu64, nb_streams_packets[stream_idx]);
2935 84 else print_str_opt("nb_read_packets", "N/A");
2936
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 140 times.
140 if (do_show_data)
2937 writer_print_data(w, "extradata", par->extradata,
2938 par->extradata_size);
2939
2940
2/2
✓ Branch 0 taken 50 times.
✓ Branch 1 taken 90 times.
140 if (par->extradata_size > 0) {
2941 50 print_int("extradata_size", par->extradata_size);
2942 50 writer_print_data_hash(w, "extradata_hash", par->extradata,
2943 par->extradata_size);
2944 }
2945
2946 /* Print disposition information */
2947 #define PRINT_DISPOSITION(flagname, name) do { \
2948 print_int(name, !!(stream->disposition & AV_DISPOSITION_##flagname)); \
2949 } while (0)
2950
2951
2/2
✓ Branch 0 taken 87 times.
✓ Branch 1 taken 53 times.
140 if (do_show_stream_disposition) {
2952
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 87 times.
87 writer_print_section_header(w, in_program ? SECTION_ID_PROGRAM_STREAM_DISPOSITION : SECTION_ID_STREAM_DISPOSITION);
2953 87 PRINT_DISPOSITION(DEFAULT, "default");
2954 87 PRINT_DISPOSITION(DUB, "dub");
2955 87 PRINT_DISPOSITION(ORIGINAL, "original");
2956 87 PRINT_DISPOSITION(COMMENT, "comment");
2957 87 PRINT_DISPOSITION(LYRICS, "lyrics");
2958 87 PRINT_DISPOSITION(KARAOKE, "karaoke");
2959 87 PRINT_DISPOSITION(FORCED, "forced");
2960 87 PRINT_DISPOSITION(HEARING_IMPAIRED, "hearing_impaired");
2961 87 PRINT_DISPOSITION(VISUAL_IMPAIRED, "visual_impaired");
2962 87 PRINT_DISPOSITION(CLEAN_EFFECTS, "clean_effects");
2963 87 PRINT_DISPOSITION(ATTACHED_PIC, "attached_pic");
2964 87 PRINT_DISPOSITION(TIMED_THUMBNAILS, "timed_thumbnails");
2965 87 PRINT_DISPOSITION(CAPTIONS, "captions");
2966 87 PRINT_DISPOSITION(DESCRIPTIONS, "descriptions");
2967 87 PRINT_DISPOSITION(METADATA, "metadata");
2968 87 PRINT_DISPOSITION(DEPENDENT, "dependent");
2969 87 PRINT_DISPOSITION(STILL_IMAGE, "still_image");
2970 87 writer_print_section_footer(w);
2971 }
2972
2973
2/2
✓ Branch 0 taken 80 times.
✓ Branch 1 taken 60 times.
140 if (do_show_stream_tags)
2974
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 80 times.
80 ret = show_tags(w, stream->metadata, in_program ? SECTION_ID_PROGRAM_STREAM_TAGS : SECTION_ID_STREAM_TAGS);
2975
2976
2/2
✓ Branch 0 taken 21 times.
✓ Branch 1 taken 119 times.
140 if (stream->nb_side_data) {
2977 21 print_pkt_side_data(w, stream->codecpar, stream->side_data, stream->nb_side_data,
2978 SECTION_ID_STREAM_SIDE_DATA_LIST,
2979 SECTION_ID_STREAM_SIDE_DATA);
2980 }
2981
2982 140 writer_print_section_footer(w);
2983 140 av_bprint_finalize(&pbuf, NULL);
2984 140 fflush(stdout);
2985
2986 140 return ret;
2987 }
2988
2989 67 static int show_streams(WriterContext *w, InputFile *ifile)
2990 {
2991 67 AVFormatContext *fmt_ctx = ifile->fmt_ctx;
2992 67 int i, ret = 0;
2993
2994 67 writer_print_section_header(w, SECTION_ID_STREAMS);
2995
2/2
✓ Branch 0 taken 139 times.
✓ Branch 1 taken 67 times.
206 for (i = 0; i < ifile->nb_streams; i++)
2996
2/2
✓ Branch 0 taken 132 times.
✓ Branch 1 taken 7 times.
139 if (selected_streams[i]) {
2997 132 ret = show_stream(w, fmt_ctx, i, &ifile->streams[i], 0);
2998
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 132 times.
132 if (ret < 0)
2999 break;
3000 }
3001 67 writer_print_section_footer(w);
3002
3003 67 return ret;
3004 }
3005
3006 3 static int show_program(WriterContext *w, InputFile *ifile, AVProgram *program)
3007 {
3008 3 AVFormatContext *fmt_ctx = ifile->fmt_ctx;
3009 3 int i, ret = 0;
3010
3011 3 writer_print_section_header(w, SECTION_ID_PROGRAM);
3012 3 print_int("program_id", program->id);
3013 3 print_int("program_num", program->program_num);
3014 3 print_int("nb_streams", program->nb_stream_indexes);
3015 3 print_int("pmt_pid", program->pmt_pid);
3016 3 print_int("pcr_pid", program->pcr_pid);
3017
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (do_show_program_tags)
3018 ret = show_tags(w, program->metadata, SECTION_ID_PROGRAM_TAGS);
3019
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (ret < 0)
3020 goto end;
3021
3022 3 writer_print_section_header(w, SECTION_ID_PROGRAM_STREAMS);
3023
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 3 times.
12 for (i = 0; i < program->nb_stream_indexes; i++) {
3024
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 1 times.
9 if (selected_streams[program->stream_index[i]]) {
3025 8 ret = show_stream(w, fmt_ctx, program->stream_index[i], &ifile->streams[program->stream_index[i]], 1);
3026
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 if (ret < 0)
3027 break;
3028 }
3029 }
3030 3 writer_print_section_footer(w);
3031
3032 3 end:
3033 3 writer_print_section_footer(w);
3034 3 return ret;
3035 }
3036
3037 40 static int show_programs(WriterContext *w, InputFile *ifile)
3038 {
3039 40 AVFormatContext *fmt_ctx = ifile->fmt_ctx;
3040 40 int i, ret = 0;
3041
3042 40 writer_print_section_header(w, SECTION_ID_PROGRAMS);
3043
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 40 times.
43 for (i = 0; i < fmt_ctx->nb_programs; i++) {
3044 3 AVProgram *program = fmt_ctx->programs[i];
3045
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (!program)
3046 continue;
3047 3 ret = show_program(w, ifile, program);
3048
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (ret < 0)
3049 break;
3050 }
3051 40 writer_print_section_footer(w);
3052 40 return ret;
3053 }
3054
3055 4 static int show_chapters(WriterContext *w, InputFile *ifile)
3056 {
3057 4 AVFormatContext *fmt_ctx = ifile->fmt_ctx;
3058 4 int i, ret = 0;
3059
3060 4 writer_print_section_header(w, SECTION_ID_CHAPTERS);
3061
2/2
✓ Branch 0 taken 18 times.
✓ Branch 1 taken 4 times.
22 for (i = 0; i < fmt_ctx->nb_chapters; i++) {
3062 18 AVChapter *chapter = fmt_ctx->chapters[i];
3063
3064 18 writer_print_section_header(w, SECTION_ID_CHAPTER);
3065 18 print_int("id", chapter->id);
3066 18 print_q ("time_base", chapter->time_base, '/');
3067 18 print_int("start", chapter->start);
3068 18 print_time("start_time", chapter->start, &chapter->time_base);
3069 18 print_int("end", chapter->end);
3070 18 print_time("end_time", chapter->end, &chapter->time_base);
3071
1/2
✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
18 if (do_show_chapter_tags)
3072 18 ret = show_tags(w, chapter->metadata, SECTION_ID_CHAPTER_TAGS);
3073 18 writer_print_section_footer(w);
3074 }
3075 4 writer_print_section_footer(w);
3076
3077 4 return ret;
3078 }
3079
3080 34 static int show_format(WriterContext *w, InputFile *ifile)
3081 {
3082 34 AVFormatContext *fmt_ctx = ifile->fmt_ctx;
3083 char val_str[128];
3084
1/2
✓ Branch 0 taken 34 times.
✗ Branch 1 not taken.
34 int64_t size = fmt_ctx->pb ? avio_size(fmt_ctx->pb) : -1;
3085 34 int ret = 0;
3086
3087 34 writer_print_section_header(w, SECTION_ID_FORMAT);
3088 34 print_str_validate("filename", fmt_ctx->url);
3089 34 print_int("nb_streams", fmt_ctx->nb_streams);
3090 34 print_int("nb_programs", fmt_ctx->nb_programs);
3091 34 print_str("format_name", fmt_ctx->iformat->name);
3092
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 22 times.
34 if (!do_bitexact) {
3093
1/2
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
12 if (fmt_ctx->iformat->long_name) print_str ("format_long_name", fmt_ctx->iformat->long_name);
3094 else print_str_opt("format_long_name", "unknown");
3095 }
3096 34 print_time("start_time", fmt_ctx->start_time, &AV_TIME_BASE_Q);
3097 34 print_time("duration", fmt_ctx->duration, &AV_TIME_BASE_Q);
3098
1/2
✓ Branch 0 taken 34 times.
✗ Branch 1 not taken.
34 if (size >= 0) print_val ("size", size, unit_byte_str);
3099 else print_str_opt("size", "N/A");
3100
1/2
✓ Branch 0 taken 34 times.
✗ Branch 1 not taken.
34 if (fmt_ctx->bit_rate > 0) print_val ("bit_rate", fmt_ctx->bit_rate, unit_bit_per_second_str);
3101 else print_str_opt("bit_rate", "N/A");
3102 34 print_int("probe_score", fmt_ctx->probe_score);
3103
2/2
✓ Branch 0 taken 26 times.
✓ Branch 1 taken 8 times.
34 if (do_show_format_tags)
3104 26 ret = show_tags(w, fmt_ctx->metadata, SECTION_ID_FORMAT_TAGS);
3105
3106 34 writer_print_section_footer(w);
3107 34 fflush(stdout);
3108 34 return ret;
3109 }
3110
3111 static void show_error(WriterContext *w, int err)
3112 {
3113 char errbuf[128];
3114 const char *errbuf_ptr = errbuf;
3115
3116 if (av_strerror(err, errbuf, sizeof(errbuf)) < 0)
3117 errbuf_ptr = strerror(AVUNERROR(err));
3118
3119 writer_print_section_header(w, SECTION_ID_ERROR);
3120 print_int("code", err);
3121 print_str("string", errbuf_ptr);
3122 writer_print_section_footer(w);
3123 }
3124
3125 107 static int open_input_file(InputFile *ifile, const char *filename,
3126 const char *print_filename)
3127 {
3128 int err, i;
3129 107 AVFormatContext *fmt_ctx = NULL;
3130 107 const AVDictionaryEntry *t = NULL;
3131 107 int scan_all_pmts_set = 0;
3132
3133 107 fmt_ctx = avformat_alloc_context();
3134
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 107 times.
107 if (!fmt_ctx) {
3135 print_error(filename, AVERROR(ENOMEM));
3136 exit_program(1);
3137 }
3138
3139
1/2
✓ Branch 1 taken 107 times.
✗ Branch 2 not taken.
107 if (!av_dict_get(format_opts, "scan_all_pmts", NULL, AV_DICT_MATCH_CASE)) {
3140 107 av_dict_set(&format_opts, "scan_all_pmts", "1", AV_DICT_DONT_OVERWRITE);
3141 107 scan_all_pmts_set = 1;
3142 }
3143
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 107 times.
107 if ((err = avformat_open_input(&fmt_ctx, filename,
3144 iformat, &format_opts)) < 0) {
3145 print_error(filename, err);
3146 return err;
3147 }
3148
2/2
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 93 times.
107 if (print_filename) {
3149 14 av_freep(&fmt_ctx->url);
3150 14 fmt_ctx->url = av_strdup(print_filename);
3151 }
3152 107 ifile->fmt_ctx = fmt_ctx;
3153
1/2
✓ Branch 0 taken 107 times.
✗ Branch 1 not taken.
107 if (scan_all_pmts_set)
3154 107 av_dict_set(&format_opts, "scan_all_pmts", NULL, AV_DICT_MATCH_CASE);
3155
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 107 times.
107 while ((t = av_dict_get(format_opts, "", t, AV_DICT_IGNORE_SUFFIX)))
3156 av_log(NULL, AV_LOG_WARNING, "Option %s skipped - not known to demuxer.\n", t->key);
3157
3158
1/2
✓ Branch 0 taken 107 times.
✗ Branch 1 not taken.
107 if (find_stream_info) {
3159 107 AVDictionary **opts = setup_find_stream_info_opts(fmt_ctx, codec_opts);
3160 107 int orig_nb_streams = fmt_ctx->nb_streams;
3161
3162 107 err = avformat_find_stream_info(fmt_ctx, opts);
3163
3164
2/2
✓ Branch 0 taken 179 times.
✓ Branch 1 taken 107 times.
286 for (i = 0; i < orig_nb_streams; i++)
3165 179 av_dict_free(&opts[i]);
3166 107 av_freep(&opts);
3167
3168
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 107 times.
107 if (err < 0) {
3169 print_error(filename, err);
3170 return err;
3171 }
3172 }
3173
3174 107 av_dump_format(fmt_ctx, 0, filename, 0);
3175
3176 107 ifile->streams = av_calloc(fmt_ctx->nb_streams, sizeof(*ifile->streams));
3177
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 107 times.
107 if (!ifile->streams)
3178 exit(1);
3179 107 ifile->nb_streams = fmt_ctx->nb_streams;
3180
3181 /* bind a decoder to each input stream */
3182
2/2
✓ Branch 0 taken 188 times.
✓ Branch 1 taken 107 times.
295 for (i = 0; i < fmt_ctx->nb_streams; i++) {
3183 188 InputStream *ist = &ifile->streams[i];
3184 188 AVStream *stream = fmt_ctx->streams[i];
3185 const AVCodec *codec;
3186
3187 188 ist->st = stream;
3188
3189
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 188 times.
188 if (stream->codecpar->codec_id == AV_CODEC_ID_PROBE) {
3190 av_log(NULL, AV_LOG_WARNING,
3191 "Failed to probe codec for input stream %d\n",
3192 stream->index);
3193 continue;
3194 }
3195
3196 188 codec = avcodec_find_decoder(stream->codecpar->codec_id);
3197
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 176 times.
188 if (!codec) {
3198 12 av_log(NULL, AV_LOG_WARNING,
3199 "Unsupported codec with id %d for input stream %d\n",
3200 12 stream->codecpar->codec_id, stream->index);
3201 12 continue;
3202 }
3203 {
3204 176 AVDictionary *opts = filter_codec_opts(codec_opts, stream->codecpar->codec_id,
3205 fmt_ctx, stream, codec);
3206
3207 176 ist->dec_ctx = avcodec_alloc_context3(codec);
3208
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 176 times.
176 if (!ist->dec_ctx)
3209 exit(1);
3210
3211 176 err = avcodec_parameters_to_context(ist->dec_ctx, stream->codecpar);
3212
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 176 times.
176 if (err < 0)
3213 exit(1);
3214
3215
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 176 times.
176 if (do_show_log) {
3216 // For loging it is needed to disable at least frame threads as otherwise
3217 // the log information would need to be reordered and matches up to contexts and frames
3218 // That is in fact possible but not trivial
3219 av_dict_set(&codec_opts, "threads", "1", 0);
3220 }
3221
3222 176 ist->dec_ctx->pkt_timebase = stream->time_base;
3223
3224
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 176 times.
176 if (avcodec_open2(ist->dec_ctx, codec, &opts) < 0) {
3225 av_log(NULL, AV_LOG_WARNING, "Could not open codec for input stream %d\n",
3226 stream->index);
3227 exit(1);
3228 }
3229
3230
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 176 times.
176 if ((t = av_dict_get(opts, "", NULL, AV_DICT_IGNORE_SUFFIX))) {
3231 av_log(NULL, AV_LOG_ERROR, "Option %s for input stream %d not found\n",
3232 t->key, stream->index);
3233 return AVERROR_OPTION_NOT_FOUND;
3234 }
3235 }
3236 }
3237
3238 107 ifile->fmt_ctx = fmt_ctx;
3239 107 return 0;
3240 }
3241
3242 107 static void close_input_file(InputFile *ifile)
3243 {
3244 int i;
3245
3246 /* close decoder for each stream */
3247
2/2
✓ Branch 0 taken 188 times.
✓ Branch 1 taken 107 times.
295 for (i = 0; i < ifile->nb_streams; i++)
3248 188 avcodec_free_context(&ifile->streams[i].dec_ctx);
3249
3250 107 av_freep(&ifile->streams);
3251 107 ifile->nb_streams = 0;
3252
3253 107 avformat_close_input(&ifile->fmt_ctx);
3254 107 }
3255
3256 107 static int probe_file(WriterContext *wctx, const char *filename,
3257 const char *print_filename)
3258 {
3259 107 InputFile ifile = { 0 };
3260 int ret, i;
3261 int section_id;
3262
3263
3/4
✓ Branch 0 taken 68 times.
✓ Branch 1 taken 39 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 68 times.
107 do_read_frames = do_show_frames || do_count_frames;
3264
3/4
✓ Branch 0 taken 73 times.
✓ Branch 1 taken 34 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 73 times.
107 do_read_packets = do_show_packets || do_count_packets;
3265
3266 107 ret = open_input_file(&ifile, filename, print_filename);
3267
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 107 times.
107 if (ret < 0)
3268 goto end;
3269
3270 #define CHECK_END if (ret < 0) goto end
3271
3272 107 nb_streams = ifile.fmt_ctx->nb_streams;
3273
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 107 times.
107 REALLOCZ_ARRAY_STREAM(nb_streams_frames,0,ifile.fmt_ctx->nb_streams);
3274
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 107 times.
107 REALLOCZ_ARRAY_STREAM(nb_streams_packets,0,ifile.fmt_ctx->nb_streams);
3275
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 107 times.
107 REALLOCZ_ARRAY_STREAM(selected_streams,0,ifile.fmt_ctx->nb_streams);
3276
3277
2/2
✓ Branch 0 taken 188 times.
✓ Branch 1 taken 107 times.
295 for (i = 0; i < ifile.fmt_ctx->nb_streams; i++) {
3278
2/2
✓ Branch 0 taken 37 times.
✓ Branch 1 taken 151 times.
188 if (stream_specifier) {
3279 37 ret = avformat_match_stream_specifier(ifile.fmt_ctx,
3280 37 ifile.fmt_ctx->streams[i],
3281 stream_specifier);
3282
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 37 times.
37 CHECK_END;
3283 else
3284 37 selected_streams[i] = ret;
3285 37 ret = 0;
3286 } else {
3287 151 selected_streams[i] = 1;
3288 }
3289
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 176 times.
188 if (!selected_streams[i])
3290 12 ifile.fmt_ctx->streams[i]->discard = AVDISCARD_ALL;
3291 }
3292
3293
4/4
✓ Branch 0 taken 68 times.
✓ Branch 1 taken 39 times.
✓ Branch 2 taken 23 times.
✓ Branch 3 taken 45 times.
107 if (do_read_frames || do_read_packets) {
3294
4/4
✓ Branch 0 taken 39 times.
✓ Branch 1 taken 23 times.
✓ Branch 2 taken 11 times.
✓ Branch 3 taken 28 times.
62 if (do_show_frames && do_show_packets &&
3295
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 6 times.
11 wctx->writer->flags & WRITER_FLAG_PUT_PACKETS_AND_FRAMES_IN_SAME_CHAPTER)
3296 5 section_id = SECTION_ID_PACKETS_AND_FRAMES;
3297
4/4
✓ Branch 0 taken 29 times.
✓ Branch 1 taken 28 times.
✓ Branch 2 taken 23 times.
✓ Branch 3 taken 6 times.
57 else if (do_show_packets && !do_show_frames)
3298 23 section_id = SECTION_ID_PACKETS;
3299 else // (!do_show_packets && do_show_frames)
3300 34 section_id = SECTION_ID_FRAMES;
3301
3/4
✓ Branch 0 taken 23 times.
✓ Branch 1 taken 39 times.
✓ Branch 2 taken 23 times.
✗ Branch 3 not taken.
62 if (do_show_frames || do_show_packets)
3302 62 writer_print_section_header(wctx, section_id);
3303 62 ret = read_packets(wctx, &ifile);
3304
3/4
✓ Branch 0 taken 23 times.
✓ Branch 1 taken 39 times.
✓ Branch 2 taken 23 times.
✗ Branch 3 not taken.
62 if (do_show_frames || do_show_packets)
3305 62 writer_print_section_footer(wctx);
3306
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 62 times.
62 CHECK_END;
3307 }
3308
3309
2/2
✓ Branch 0 taken 40 times.
✓ Branch 1 taken 67 times.
107 if (do_show_programs) {
3310 40 ret = show_programs(wctx, &ifile);
3311
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 40 times.
40 CHECK_END;
3312 }
3313
3314
2/2
✓ Branch 0 taken 67 times.
✓ Branch 1 taken 40 times.
107 if (do_show_streams) {
3315 67 ret = show_streams(wctx, &ifile);
3316
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 67 times.
67 CHECK_END;
3317 }
3318
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 103 times.
107 if (do_show_chapters) {
3319 4 ret = show_chapters(wctx, &ifile);
3320
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 CHECK_END;
3321 }
3322
2/2
✓ Branch 0 taken 73 times.
✓ Branch 1 taken 34 times.
107 if (do_show_format) {
3323 34 ret = show_format(wctx, &ifile);
3324
1/2
✓ Branch 0 taken 34 times.
✗ Branch 1 not taken.
34 CHECK_END;
3325 }
3326
3327 107 end:
3328
1/2
✓ Branch 0 taken 107 times.
✗ Branch 1 not taken.
107 if (ifile.fmt_ctx)
3329 107 close_input_file(&ifile);
3330 107 av_freep(&nb_streams_frames);
3331 107 av_freep(&nb_streams_packets);
3332 107 av_freep(&selected_streams);
3333
3334 107 return ret;
3335 }
3336
3337 static void show_usage(void)
3338 {
3339 av_log(NULL, AV_LOG_INFO, "Simple multimedia streams analyzer\n");
3340 av_log(NULL, AV_LOG_INFO, "usage: %s [OPTIONS] [INPUT_FILE]\n", program_name);
3341 av_log(NULL, AV_LOG_INFO, "\n");
3342 }
3343
3344 static void ffprobe_show_program_version(WriterContext *w)
3345 {
3346 AVBPrint pbuf;
3347 av_bprint_init(&pbuf, 1, AV_BPRINT_SIZE_UNLIMITED);
3348
3349 writer_print_section_header(w, SECTION_ID_PROGRAM_VERSION);
3350 print_str("version", FFMPEG_VERSION);
3351 print_fmt("copyright", "Copyright (c) %d-%d the FFmpeg developers",
3352 program_birth_year, CONFIG_THIS_YEAR);
3353 print_str("compiler_ident", CC_IDENT);
3354 print_str("configuration", FFMPEG_CONFIGURATION);
3355 writer_print_section_footer(w);
3356
3357 av_bprint_finalize(&pbuf, NULL);
3358 }
3359
3360 #define SHOW_LIB_VERSION(libname, LIBNAME) \
3361 do { \
3362 if (CONFIG_##LIBNAME) { \
3363 unsigned int version = libname##_version(); \
3364 writer_print_section_header(w, SECTION_ID_LIBRARY_VERSION); \
3365 print_str("name", "lib" #libname); \
3366 print_int("major", LIB##LIBNAME##_VERSION_MAJOR); \
3367 print_int("minor", LIB##LIBNAME##_VERSION_MINOR); \
3368 print_int("micro", LIB##LIBNAME##_VERSION_MICRO); \
3369 print_int("version", version); \
3370 print_str("ident", LIB##LIBNAME##_IDENT); \
3371 writer_print_section_footer(w); \
3372 } \
3373 } while (0)
3374
3375 static void ffprobe_show_library_versions(WriterContext *w)
3376 {
3377 writer_print_section_header(w, SECTION_ID_LIBRARY_VERSIONS);
3378 SHOW_LIB_VERSION(avutil, AVUTIL);
3379 SHOW_LIB_VERSION(avcodec, AVCODEC);
3380 SHOW_LIB_VERSION(avformat, AVFORMAT);
3381 SHOW_LIB_VERSION(avdevice, AVDEVICE);
3382 SHOW_LIB_VERSION(avfilter, AVFILTER);
3383 SHOW_LIB_VERSION(swscale, SWSCALE);
3384 SHOW_LIB_VERSION(swresample, SWRESAMPLE);
3385 SHOW_LIB_VERSION(postproc, POSTPROC);
3386 writer_print_section_footer(w);
3387 }
3388
3389 #define PRINT_PIX_FMT_FLAG(flagname, name) \
3390 do { \
3391 print_int(name, !!(pixdesc->flags & AV_PIX_FMT_FLAG_##flagname)); \
3392 } while (0)
3393
3394 static void ffprobe_show_pixel_formats(WriterContext *w)
3395 {
3396 const AVPixFmtDescriptor *pixdesc = NULL;
3397 int i, n;
3398
3399 writer_print_section_header(w, SECTION_ID_PIXEL_FORMATS);
3400