FFmpeg coverage


Directory: ../../../ffmpeg/
File: src/fftools/ffprobe.c
Date: 2022-07-06 18:02:43
Exec Total Coverage
Lines: 1623 2157 75.2%
Branches: 881 1317 66.9%

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