FFmpeg
Loading...
Searching...
No Matches
avtextformat.c
Go to the documentation of this file.
1/*
2 * Copyright (c) The FFmpeg developers
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#include <inttypes.h>
22#include <limits.h>
23#include <math.h>
24#include <stdarg.h>
25#include <stdio.h>
26#include <string.h>
27
28#include "libavutil/mem.h"
29#include "libavutil/avassert.h"
30#include "libavutil/avutil.h"
31#include "libavutil/base64.h"
32#include "libavutil/bprint.h"
33#include "libavutil/common.h"
34#include "libavutil/error.h"
35#include "libavutil/hash.h"
36#include "libavutil/macros.h"
37#include "libavutil/opt.h"
38#include "avtextformat.h"
39
40#define SECTION_ID_NONE (-1)
41
42#define SHOW_OPTIONAL_FIELDS_AUTO (-1)
43#define SHOW_OPTIONAL_FIELDS_NEVER 0
44#define SHOW_OPTIONAL_FIELDS_ALWAYS 1
45
46static const struct {
47 double bin_val;
48 double dec_val;
49 char bin_str[4];
50 char dec_str[4];
51} si_prefixes[] = {
52 { 1.0, 1.0, "", "" },
53 { 1.024e3, 1e3, "Ki", "K" },
54 { 1.048576e6, 1e6, "Mi", "M" },
55 { 1.073741824e9, 1e9, "Gi", "G" },
56 { 1.099511627776e12, 1e12, "Ti", "T" },
57 { 1.125899906842624e15, 1e15, "Pi", "P" },
58};
59
60static const char *textcontext_get_formatter_name(void *p)
61{
62 AVTextFormatContext *tctx = p;
63 return tctx->formatter->name;
64}
65
66#define OFFSET(x) offsetof(AVTextFormatContext, x)
67
68static const AVOption textcontext_options[] = {
69 { "string_validation", "set string validation mode",
70 OFFSET(string_validation), AV_OPT_TYPE_INT, { .i64 = AV_TEXTFORMAT_STRING_VALIDATION_REPLACE }, 0, AV_TEXTFORMAT_STRING_VALIDATION_NB - 1, .unit = "sv" },
71 { "sv", "set string validation mode",
72 OFFSET(string_validation), AV_OPT_TYPE_INT, { .i64 = AV_TEXTFORMAT_STRING_VALIDATION_REPLACE }, 0, AV_TEXTFORMAT_STRING_VALIDATION_NB - 1, .unit = "sv" },
73 { "ignore", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_TEXTFORMAT_STRING_VALIDATION_IGNORE }, .unit = "sv" },
74 { "replace", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_TEXTFORMAT_STRING_VALIDATION_REPLACE }, .unit = "sv" },
75 { "fail", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = AV_TEXTFORMAT_STRING_VALIDATION_FAIL }, .unit = "sv" },
76 { "string_validation_replacement", "set string validation replacement string", OFFSET(string_validation_replacement), AV_OPT_TYPE_STRING, { .str = "" } },
77 { "svr", "set string validation replacement string", OFFSET(string_validation_replacement), AV_OPT_TYPE_STRING, { .str = "\xEF\xBF\xBD" } },
78 { NULL }
79};
80
81static void *textcontext_child_next(void *obj, void *prev)
82{
84 if (!prev && ctx->formatter && ctx->formatter->priv_class && ctx->priv)
85 return ctx->priv;
86 return NULL;
87}
88
89static const AVClass textcontext_class = {
90 .class_name = "AVTextContext",
92 .option = textcontext_options,
93 .version = LIBAVUTIL_VERSION_INT,
94 .child_next = textcontext_child_next,
95};
96
97static void bprint_bytes(AVBPrint *bp, const uint8_t *ubuf, size_t ubuf_size)
98{
99 av_bprintf(bp, "0X");
100 for (unsigned i = 0; i < ubuf_size; i++)
101 av_bprintf(bp, "%02X", ubuf[i]);
102}
103
105{
106 AVTextFormatContext *tctx = *ptctx;
107 int ret = 0;
108
109 if (!tctx)
110 return AVERROR(EINVAL);
111
112 av_hash_freep(&tctx->hash);
113
114 if (tctx->formatter) {
115 if (tctx->formatter->uninit)
116 ret = tctx->formatter->uninit(tctx);
117 if (tctx->formatter->priv_class)
118 av_opt_free(tctx->priv);
119 }
120 for (int i = 0; i < SECTION_MAX_NB_LEVELS; i++)
122 av_freep(&tctx->priv);
123 av_opt_free(tctx);
124 av_freep(ptctx);
125 return ret;
126}
127
128
129int avtext_context_open(AVTextFormatContext **ptctx, const AVTextFormatter *formatter, AVTextWriterContext *writer_context, const char *args,
131{
133 int ret = 0;
134
135 av_assert0(ptctx && formatter);
136
137 if (!(tctx = av_mallocz(sizeof(AVTextFormatContext)))) {
138 ret = AVERROR(ENOMEM);
139 goto fail;
140 }
141
142 for (int i = 0; i < SECTION_MAX_NB_LEVELS; i++)
144
145 tctx->class = &textcontext_class;
147
148 if (!(tctx->priv = av_mallocz(formatter->priv_size))) {
149 ret = AVERROR(ENOMEM);
150 goto fail;
151 }
152
153 tctx->opts = options;
154
155 if (nb_sections > SECTION_MAX_NB_SECTIONS) {
156 av_log(tctx, AV_LOG_ERROR, "The number of section definitions (%d) is larger than the maximum allowed (%d)\n", nb_sections, SECTION_MAX_NB_SECTIONS);
157 ret = AVERROR(EINVAL);
158 goto fail;
159 }
160
161 tctx->formatter = formatter;
162 tctx->level = -1;
163 tctx->sections = sections;
164 tctx->nb_sections = nb_sections;
165 tctx->writer = writer_context;
166
167 if (formatter->priv_class) {
168 void *priv_ctx = tctx->priv;
169 *(const AVClass **)priv_ctx = formatter->priv_class;
170 av_opt_set_defaults(priv_ctx);
171 }
172
173 /* convert options to dictionary */
174 if (args) {
176 const AVDictionaryEntry *opt = NULL;
177
178 if ((ret = av_dict_parse_string(&opts, args, "=", ":", 0)) < 0) {
179 av_log(tctx, AV_LOG_ERROR, "Failed to parse option string '%s' provided to textformat context\n", args);
181 goto fail;
182 }
183
184 while ((opt = av_dict_iterate(opts, opt))) {
185 if ((ret = av_opt_set(tctx, opt->key, opt->value, AV_OPT_SEARCH_CHILDREN)) < 0) {
186 av_log(tctx, AV_LOG_ERROR, "Failed to set option '%s' with value '%s' provided to textformat context\n",
187 opt->key, opt->value);
189 goto fail;
190 }
191 }
192
194 }
195
196 if (show_data_hash) {
197 if ((ret = av_hash_alloc(&tctx->hash, show_data_hash)) < 0) {
198 if (ret == AVERROR(EINVAL)) {
199 const char *n;
200 av_log(NULL, AV_LOG_ERROR, "Unknown hash algorithm '%s'\nKnown algorithms:", show_data_hash);
201 for (unsigned i = 0; (n = av_hash_names(i)); i++)
202 av_log(NULL, AV_LOG_ERROR, " %s", n);
203 av_log(NULL, AV_LOG_ERROR, "\n");
204 }
205 goto fail;
206 }
207 }
208
209 /* validate replace string */
210 {
211 const uint8_t *p = (uint8_t *)tctx->string_validation_replacement;
212 const uint8_t *endp = p + strlen((const char *)p);
213 while (*p) {
214 const uint8_t *p0 = p;
216 ret = av_utf8_decode(&code, &p, endp, tctx->string_validation_utf8_flags);
217 if (ret < 0) {
218 AVBPrint bp;
220 bprint_bytes(&bp, p0, p - p0);
221 av_log(tctx, AV_LOG_ERROR,
222 "Invalid UTF8 sequence %s found in string validation replace '%s'\n",
223 bp.str, tctx->string_validation_replacement);
224 goto fail;
225 }
226 }
227 }
228
229 if (tctx->formatter->init)
230 ret = tctx->formatter->init(tctx);
231 if (ret < 0)
232 goto fail;
233
234 *ptctx = tctx;
235
236 return 0;
237
238fail:
240 return ret;
241}
242
243static const char unit_second_str[] = "s";
244
245void avtext_print_section_header(AVTextFormatContext *tctx, const void *data, int section_id)
246{
247 if (section_id < 0 || section_id >= tctx->nb_sections) {
248 av_log(tctx, AV_LOG_ERROR, "Invalid section_id for section_header: %d\n", section_id);
249 return;
250 }
251
252 tctx->level++;
254
255 tctx->nb_item[tctx->level] = 0;
256 memset(tctx->nb_item_type[tctx->level], 0, sizeof(tctx->nb_item_type[tctx->level]));
257 tctx->section[tctx->level] = &tctx->sections[section_id];
258
260 tctx->formatter->print_section_header(tctx, data);
261}
262
264{
265 if (tctx->level < 0 || tctx->level >= SECTION_MAX_NB_LEVELS) {
266 av_log(tctx, AV_LOG_ERROR, "Invalid level for section_footer: %d\n", tctx->level);
267 return;
268 }
269
270 int section_id = tctx->section[tctx->level]->id;
271 int parent_section_id = tctx->level ?
272 tctx->section[tctx->level - 1]->id : SECTION_ID_NONE;
273
274 if (parent_section_id != SECTION_ID_NONE) {
275 tctx->nb_item[tctx->level - 1]++;
276 tctx->nb_item_type[tctx->level - 1][section_id]++;
277 }
278
280 tctx->formatter->print_section_footer(tctx);
281 tctx->level--;
282}
283
285{
286 av_assert0(tctx);
287
289 return;
290
294 return;
295
296 av_assert0(key && tctx->level >= 0 && tctx->level < SECTION_MAX_NB_LEVELS);
297
298 if (!tctx->opts.is_key_selected || tctx->opts.is_key_selected(tctx, key)) {
299 tctx->formatter->print_integer(tctx, key, val);
300 tctx->nb_item[tctx->level]++;
301 }
302}
303
304static inline int validate_string(AVTextFormatContext *tctx, char **dstp, const char *src)
305{
306 const uint8_t *p, *endp, *srcp = (const uint8_t *)src;
307 AVBPrint dstbuf;
308 AVBPrint invalid_seq;
309 int invalid_chars_nb = 0, ret = 0;
310
311 *dstp = NULL;
314
315 endp = srcp + strlen(src);
316 for (p = srcp; *p;) {
318 int invalid = 0;
319 const uint8_t *p0 = p;
320
321 if (av_utf8_decode(&code, &p, endp, tctx->string_validation_utf8_flags) < 0) {
322
323 av_bprint_clear(&invalid_seq);
324
325 bprint_bytes(&invalid_seq, p0, p - p0);
326
327 av_log(tctx, AV_LOG_DEBUG, "Invalid UTF-8 sequence '%s' found in string '%s'\n", invalid_seq.str, src);
328 invalid = 1;
329 }
330
331 if (invalid) {
332 invalid_chars_nb++;
333
334 switch (tctx->string_validation) {
336 av_log(tctx, AV_LOG_ERROR, "Invalid UTF-8 sequence found in string '%s'\n", src);
338 goto end;
339
341 av_bprintf(&dstbuf, "%s", tctx->string_validation_replacement);
342 break;
343 }
344 }
345
347 av_bprint_append_data(&dstbuf, p0, p-p0);
348 }
349
350 if (invalid_chars_nb && tctx->string_validation == AV_TEXTFORMAT_STRING_VALIDATION_REPLACE)
352 "%d invalid UTF-8 sequence(s) found in string '%s', replaced with '%s'\n",
353 invalid_chars_nb, src, tctx->string_validation_replacement);
354
355end:
356 av_bprint_finalize(&dstbuf, dstp);
357 av_bprint_finalize(&invalid_seq, NULL);
358 return ret;
359}
360
362 union {
363 double d;
366
368 const char *unit;
369};
370
371static const char float_fmt_full[] = "%f";
372static const char float_fmt_singledigit[] = "%.1f";
373static char *value_string(const AVTextFormatContext *tctx, char *buf, int buf_size, struct unit_value uv)
374{
375 double vald;
376 int64_t vali = 0;
377 const char *float_fmt = 0;
378
380 vald = 20 * log10(uv.val.d);
381 float_fmt = float_fmt_singledigit;
382 } else if (uv.fmt >= AV_TEXTFORMAT_VALUE_FMT_DOUBLE) {
383 vald = uv.val.d;
384 float_fmt = float_fmt_full;
385 } else {
386 vald = (double)uv.val.i;
387 vali = uv.val.i;
388 }
389
391 double secs;
392 int hours, mins;
393 secs = vald;
394 mins = (int)secs / 60;
395 secs = secs - mins * 60;
396 hours = mins / 60;
397 mins %= 60;
398 snprintf(buf, buf_size, "%d:%02d:%09.6f", hours, mins, secs);
399 } else {
400 const char *prefix_string = "";
401
402 if (tctx->opts.use_value_prefix && vald > 1) {
404
406 index = (int64_t)(log2(vald) / 10);
408 vald /= si_prefixes[index].bin_val;
409 prefix_string = si_prefixes[index].bin_str;
410 } else {
411 index = (int64_t)(log10(vald) / 3);
413 vald /= si_prefixes[index].dec_val;
414 prefix_string = si_prefixes[index].dec_str;
415 }
416 vali = (int64_t)vald;
417 }
418
419 if (float_fmt || (tctx->opts.use_value_prefix && vald != (int64_t)vald))
420 snprintf(buf, buf_size, float_fmt ? float_fmt : "%f", vald);
421 else
422 snprintf(buf, buf_size, "%"PRId64, vali);
423
424 av_strlcatf(buf, buf_size, "%s%s%s", *prefix_string || tctx->opts.show_value_unit && uv.unit && *uv.unit ? " " : "",
425 prefix_string, tctx->opts.show_value_unit && uv.unit ? uv.unit : "");
426 }
427
428 return buf;
429}
430
431
433{
434 char val_str[128];
435 struct unit_value uv;
436
438
439 uv.val.i = val;
440 uv.fmt = fmt;
441 uv.unit = unit;
442 avtext_print_string(tctx, key, value_string(tctx, val_str, sizeof(val_str), uv), 0);
443}
444
445
447{
448 char val_str[128];
449 struct unit_value uv;
450
452
453 uv.val.d = val;
454 uv.fmt = fmt;
455 uv.unit = unit;
456 avtext_print_string(tctx, key, value_string(tctx, val_str, sizeof(val_str), uv), 0);
457}
458
459int avtext_print_string(AVTextFormatContext *tctx, const char *key, const char *val, int flags)
460{
461 const AVTextFormatSection *section;
462 int ret = 0;
463
464 av_assert0(key && val && tctx->level >= 0 && tctx->level < SECTION_MAX_NB_LEVELS);
465
466 section = tctx->section[tctx->level];
467
469 return 0;
470
474 return 0;
475
476 if (!tctx->opts.is_key_selected || tctx->opts.is_key_selected(tctx, key)) {
478 char *key1 = NULL, *val1 = NULL;
479 ret = validate_string(tctx, &key1, key);
480 if (ret < 0) goto end;
481 ret = validate_string(tctx, &val1, val);
482 if (ret < 0) goto end;
483 tctx->formatter->print_string(tctx, key1, val1);
484 end:
485 if (ret < 0)
486 av_log(tctx, AV_LOG_ERROR,
487 "Invalid key=value string combination %s=%s in section %s\n",
488 key, val, section->unique_name);
489 av_free(key1);
490 av_free(val1);
491 } else {
492 tctx->formatter->print_string(tctx, key, val);
493 }
494
495 tctx->nb_item[tctx->level]++;
496 }
497
498 return ret;
499}
500
501void avtext_print_rational(AVTextFormatContext *tctx, const char *key, AVRational q, char sep)
502{
503 char buf[44];
504 snprintf(buf, sizeof(buf), "%d%c%d", q.num, sep, q.den);
505 avtext_print_string(tctx, key, buf, 0);
506}
507
509 int64_t ts, const AVRational *time_base, int is_duration)
510{
511 if ((!is_duration && ts == AV_NOPTS_VALUE) || (is_duration && ts == 0)) {
513 } else {
514 char buf[128];
515 double d = av_q2d(*time_base) * ts;
516 struct unit_value uv;
517 uv.val.d = d;
520 value_string(tctx, buf, sizeof(buf), uv);
521 avtext_print_string(tctx, key, buf, 0);
522 }
523}
524
525void avtext_print_ts(AVTextFormatContext *tctx, const char *key, int64_t ts, int is_duration)
526{
527 if ((!is_duration && ts == AV_NOPTS_VALUE) || (is_duration && ts == 0))
529 else
530 avtext_print_integer(tctx, key, ts, 0);
531}
532
533static void print_data_xxd(AVBPrint *bp, const uint8_t *data, int size)
534{
535 unsigned offset = 0;
536 int i;
537
538 av_bprintf(bp, "\n");
539 while (size) {
540 av_bprintf(bp, "%08x: ", offset);
541 int l = FFMIN(size, 16);
542 for (i = 0; i < l; i++) {
543 av_bprintf(bp, "%02x", data[i]);
544 if (i & 1)
545 av_bprintf(bp, " ");
546 }
547 av_bprint_chars(bp, ' ', 41 - 2 * i - i / 2);
548 for (i = 0; i < l; i++)
549 av_bprint_chars(bp, data[i] - 32U < 95 ? data[i] : '.', 1);
550 av_bprintf(bp, "\n");
551 offset += l;
552 data += l;
553 size -= l;
554 }
555}
556
557static void print_data_base64(AVBPrint *bp, const uint8_t *data, int size)
558{
559 char buf[AV_BASE64_SIZE(60)];
560
561 av_bprintf(bp, "\n");
562 while (size) {
563 int l = FFMIN(size, 60);
564 av_base64_encode(buf, sizeof(buf), data, l);
565 av_bprintf(bp, "%s\n", buf);
566 data += l;
567 size -= l;
568 }
569}
571 const uint8_t *data, int size)
572{
573 AVBPrint bp;
575 switch (tctx->opts.data_dump_format) {
577 print_data_xxd(&bp, data, size);
578 break;
581 break;
582 default:
583 av_unreachable("Invalid data dump type");
584 }
585 avtext_print_string(tctx, key, bp.str, 0);
587}
588
590 const uint8_t *data, int size)
591{
592 char buf[AV_HASH_MAX_SIZE * 2 + 64] = { 0 };
593 int len;
594
595 if (!tctx->hash)
596 return;
597
598 av_hash_init(tctx->hash);
599 av_hash_update(tctx->hash, data, size);
600 len = snprintf(buf, sizeof(buf), "%s:", av_hash_get_name(tctx->hash));
601 av_hash_final_hex(tctx->hash, (uint8_t *)&buf[len], (int)sizeof(buf) - len);
602 avtext_print_string(tctx, key, buf, 0);
603}
604
605static const char *writercontext_get_writer_name(void *p)
606{
607 AVTextWriterContext *wctx = p;
608 return wctx->writer->name;
609}
610
611static void *writercontext_child_next(void *obj, void *prev)
612{
614 if (!prev && ctx->formatter && ctx->formatter->priv_class && ctx->priv)
615 return ctx->priv;
616 return NULL;
617}
618
619static const AVClass textwriter_class = {
620 .class_name = "AVTextWriterContext",
622 .version = LIBAVUTIL_VERSION_INT,
623 .child_next = writercontext_child_next,
624};
625
626
628{
629 AVTextWriterContext *wctx = *pwctx;
630 int ret = 0;
631
632 if (!wctx)
633 return AVERROR(EINVAL);
634
635 if (wctx->writer) {
636 if (wctx->writer->uninit)
637 ret = wctx->writer->uninit(wctx);
638 if (wctx->writer->priv_class)
639 av_opt_free(wctx->priv);
640 }
641 av_freep(&wctx->priv);
642 av_freep(pwctx);
643 return ret;
644}
645
646
648{
650 int ret = 0;
651
652 if (!pwctx || !writer)
653 return AVERROR(EINVAL);
654
655 if (!((wctx = av_mallocz(sizeof(AVTextWriterContext))))) {
656 ret = AVERROR(ENOMEM);
657 goto fail;
658 }
659
660 if (writer->priv_size && !((wctx->priv = av_mallocz(writer->priv_size)))) {
661 ret = AVERROR(ENOMEM);
662 goto fail;
663 }
664
665 if (writer->priv_class) {
666 void *priv_ctx = wctx->priv;
667 *(const AVClass **)priv_ctx = writer->priv_class;
668 av_opt_set_defaults(priv_ctx);
669 }
670
671 wctx->class = &textwriter_class;
672 wctx->writer = writer;
673
675
676
677 if (wctx->writer->init)
678 ret = wctx->writer->init(wctx);
679 if (ret < 0)
680 goto fail;
681
682 *pwctx = wctx;
683
684 return 0;
685
686fail:
688 return ret;
689}
690
704
706{
707 for (int i = 0; registered_formatters[i]; i++) {
708 const char *end;
710 (*end == '\0' || *end == '='))
711 return registered_formatters[i];
712 }
713
714 return NULL;
715}
static double val(void *priv, double ch)
Definition aeval.c:77
int32_t
simple assert() macros that are a bit more flexible than ISO C assert().
#define av_unreachable(msg)
Asserts that are used as compiler optimization hints depending upon ASSERT_LEVEL and NBDEBUG.
Definition avassert.h:109
#define av_assert0(cond)
assert() equivalent, that is always enabled.
Definition avassert.h:42
size_t av_strlcatf(char *dst, size_t size, const char *fmt,...)
Definition avstring.c:103
static const AVClass textwriter_class
void avtext_print_integer(AVTextFormatContext *tctx, const char *key, int64_t val, int flags)
static void bprint_bytes(AVBPrint *bp, const uint8_t *ubuf, size_t ubuf_size)
char dec_str[4]
static const char unit_second_str[]
static char * value_string(const AVTextFormatContext *tctx, char *buf, int buf_size, struct unit_value uv)
void avtext_print_unit_integer(AVTextFormatContext *tctx, const char *key, int64_t val, AVTextFormatValueFormat fmt, const char *unit)
static const struct @105000147377261105311001355164026305374075040210 si_prefixes[]
static void * writercontext_child_next(void *obj, void *prev)
char bin_str[4]
double dec_val
static const char * writercontext_get_writer_name(void *p)
int avtextwriter_context_open(AVTextWriterContext **pwctx, const AVTextWriter *writer)
void avtext_print_unit_double(AVTextFormatContext *tctx, const char *key, double val, AVTextFormatValueFormat fmt, const char *unit)
int avtext_context_open(AVTextFormatContext **ptctx, const AVTextFormatter *formatter, AVTextWriterContext *writer_context, const char *args, const AVTextFormatSection *sections, int nb_sections, AVTextFormatOptions options, char *show_data_hash)
void avtext_print_data(AVTextFormatContext *tctx, const char *key, const uint8_t *data, int size)
int avtext_print_string(AVTextFormatContext *tctx, const char *key, const char *val, int flags)
static const AVClass textcontext_class
static void * textcontext_child_next(void *obj, void *prev)
static void print_data_xxd(AVBPrint *bp, const uint8_t *data, int size)
static const char * textcontext_get_formatter_name(void *p)
int avtext_context_close(AVTextFormatContext **ptctx)
static const AVOption textcontext_options[]
static void print_data_base64(AVBPrint *bp, const uint8_t *data, int size)
void avtext_print_time(AVTextFormatContext *tctx, const char *key, int64_t ts, const AVRational *time_base, int is_duration)
void avtext_print_ts(AVTextFormatContext *tctx, const char *key, int64_t ts, int is_duration)
double bin_val
void avtext_print_data_hash(AVTextFormatContext *tctx, const char *key, const uint8_t *data, int size)
static const AVTextFormatter *const registered_formatters[]
void avtext_print_rational(AVTextFormatContext *tctx, const char *key, AVRational q, char sep)
static const char float_fmt_singledigit[]
void avtext_print_section_header(AVTextFormatContext *tctx, const void *data, int section_id)
#define OFFSET(x)
void avtext_print_section_footer(AVTextFormatContext *tctx)
const AVTextFormatter * avtext_get_formatter_by_name(const char *name)
static const char float_fmt_full[]
static int validate_string(AVTextFormatContext *tctx, char **dstp, const char *src)
int avtextwriter_context_close(AVTextWriterContext **pwctx)
#define SECTION_ID_NONE
const AVTextFormatter avtextformatter_compact
Definition tf_compact.c:239
@ AV_TEXTFORMAT_DATADUMP_BASE64
@ AV_TEXTFORMAT_DATADUMP_XXD
#define AV_TEXTFORMAT_PRINT_STRING_OPTIONAL
#define SECTION_MAX_NB_LEVELS
const AVTextFormatter avtextformatter_ini
Definition tf_ini.c:140
#define AV_TEXTFORMAT_FLAG_SUPPORTS_OPTIONAL_FIELDS
const AVTextFormatter avtextformatter_csv
Definition tf_compact.c:270
#define SECTION_MAX_NB_SECTIONS
AVTextFormatValueFormat
@ AV_TEXTFORMAT_VALUE_FMT_DOUBLE
@ AV_TEXTFORMAT_VALUE_FMT_DECIBEL
@ AV_TEXTFORMAT_VALUE_FMT_SECOND
@ AV_TEXTFORMAT_VALUE_FMT_BYTE
const AVTextFormatter avtextformatter_default
Definition tf_default.c:128
@ AV_TEXTFORMAT_STRING_VALIDATION_NB
@ AV_TEXTFORMAT_STRING_VALIDATION_FAIL
@ AV_TEXTFORMAT_STRING_VALIDATION_IGNORE
@ AV_TEXTFORMAT_STRING_VALIDATION_REPLACE
#define AV_TEXTFORMAT_PRINT_STRING_VALIDATE
const AVTextFormatter avtextformatter_mermaid
Definition tf_mermaid.c:650
const AVTextFormatter avtextformatter_json
Definition tf_json.c:202
const AVTextFormatter avtextformatter_flat
Definition tf_flat.c:150
const AVTextFormatter avtextformatter_mermaidhtml
Definition tf_mermaid.c:664
const AVTextFormatter avtextformatter_xml
Definition tf_xml.c:202
Convenience header that includes libavutil's core.
void av_bprintf(AVBPrint *buf, const char *fmt,...)
Definition bprint.c:122
void av_bprint_init(AVBPrint *buf, unsigned size_init, unsigned size_max)
Definition bprint.c:69
AVBPrint public header.
#define AV_BPRINT_SIZE_UNLIMITED
#define AV_BPRINT_SIZE_AUTOMATIC
#define flags(name, subs,...)
Definition cbs_h264.c:74
#define i(width, name, range_min, range_max)
Definition cbs_h264.c:63
common internal and external API header
#define av_clip64
Definition common.h:103
#define NULL
Definition coverity.c:32
long long int64_t
Definition coverity.c:34
error code definitions
const char * key
static char * show_data_hash
Definition ffprobe.c:147
#define SHOW_OPTIONAL_FIELDS_AUTO
Definition ffprobe.c:140
static const AVTextFormatSection sections[]
Definition ffprobe.c:259
#define SHOW_OPTIONAL_FIELDS_NEVER
Definition ffprobe.c:141
#define fail
Definition test.h:479
@ AV_OPT_TYPE_CONST
Special option type for declaring named constants.
Definition opt.h:298
@ AV_OPT_TYPE_INT
Underlying C type is int.
Definition opt.h:258
@ AV_OPT_TYPE_STRING
Underlying C type is a uint8_t* that is either NULL or points to a C string allocated with the av_mal...
Definition opt.h:275
int av_bprint_finalize(AVBPrint *buf, char **ret_str)
Finalize a print buffer.
Definition bprint.c:235
void av_bprint_append_data(AVBPrint *buf, const char *data, unsigned size)
Append data to a print buffer.
Definition bprint.c:148
void av_bprint_chars(AVBPrint *buf, char c, unsigned n)
Append char c n times to a print buffer.
Definition bprint.c:130
void av_bprint_clear(AVBPrint *buf)
Reset the string to "" but keep internal allocated data.
Definition bprint.c:227
char * av_base64_encode(char *out, int out_size, const uint8_t *in, int in_size)
Encode data to base64 and null-terminate.
Definition base64.c:147
#define AV_BASE64_SIZE(x)
Calculate the output size needed to base64-encode x bytes to a null-terminated string.
Definition base64.h:66
void av_dict_free(AVDictionary **pm)
Free all the memory allocated for an AVDictionary struct and all keys and values.
Definition dict.c:233
const AVDictionaryEntry * av_dict_iterate(const AVDictionary *m, const AVDictionaryEntry *prev)
Iterate over a dictionary.
Definition dict.c:42
int av_dict_parse_string(AVDictionary **pm, const char *str, const char *key_val_sep, const char *pairs_sep, int flags)
Parse the key/value pairs list and add the parsed entries to a dictionary.
Definition dict.c:210
#define AVERROR_INVALIDDATA
Invalid data found when processing input.
Definition error.h:61
#define AVERROR(e)
Definition error.h:45
void av_hash_freep(AVHashContext **ctx)
Free hash context and set hash context pointer to NULL.
Definition hash.c:248
void av_hash_final_hex(struct AVHashContext *ctx, uint8_t *dst, int size)
Finalize a hash context and store the hexadecimal representation of the actual hash value as a string...
Definition hash.c:225
void av_hash_init(AVHashContext *ctx)
Initialize or reset a hash context.
Definition hash.c:151
void av_hash_update(AVHashContext *ctx, const uint8_t *src, size_t len)
Update a hash context with additional data.
Definition hash.c:172
int av_hash_alloc(AVHashContext **ctx, const char *name)
Allocate a hash context for the algorithm specified by name.
Definition hash.c:114
const char * av_hash_names(int i)
Get the names of available hash algorithms.
Definition hash.c:98
#define AV_HASH_MAX_SIZE
Maximum value that av_hash_get_size() will currently return.
Definition hash.h:156
#define AV_LOG_DEBUG
Stuff which is only useful for libav* developers.
Definition log.h:231
#define AV_LOG_WARNING
Something somehow does not look correct.
Definition log.h:216
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition log.h:210
static double av_q2d(AVRational a)
Convert an AVRational to a double.
Definition rational.h:104
int av_strstart(const char *str, const char *pfx, const char **ptr)
Return non-zero if pfx is a prefix of str.
Definition avstring.c:36
int av_utf8_decode(int32_t *codep, const uint8_t **bufp, const uint8_t *buf_end, unsigned int flags)
Read and decode a single UTF-8 code point (character) from the buffer in *buf, and update *buf to poi...
Definition avstring.c:364
#define AV_NOPTS_VALUE
Undefined timestamp value.
Definition avutil.h:247
#define LIBAVUTIL_VERSION_INT
Definition version.h:85
#define AV_OPT_SEARCH_CHILDREN
Search in possible children of the given object first.
Definition opt.h:604
void av_opt_free(void *obj)
Free all allocated objects in obj.
Definition opt.c:2025
void av_opt_set_defaults(void *s)
Set the values of all AVOption fields to their default values.
Definition opt.c:1754
int av_opt_set(void *obj, const char *name, const char *val, int search_flags)
Definition opt.c:887
int index
Definition gxfenc.c:90
const char * av_hash_get_name(const AVHashContext *ctx)
Definition hash.c:104
Generic hashing API.
unsigned offset
Definition libaomenc.c:763
#define log2(x)
Definition libm.h:406
Utility Preprocessor macros.
#define FFMIN(a, b)
Definition macros.h:49
Memory handling functions.
const char data[16]
Definition mxf.c:149
AVOptions.
const char * name
Definition qsvenc.c:142
#define FF_ARRAY_ELEMS(a)
#define snprintf
Definition snprintf.h:34
const uint8_t * code
Definition spdifenc.c:433
Describe the class of an AVClass context structure.
Definition log.h:76
char * key
Definition dict.h:91
char * value
Definition dict.h:92
AVOption.
Definition opt.h:428
Rational number (pair of numerator and denominator).
Definition rational.h:58
int num
Numerator.
Definition rational.h:59
int den
Denominator.
Definition rational.h:60
unsigned int nb_item_type[SECTION_MAX_NB_LEVELS][SECTION_MAX_NB_SECTIONS]
struct AVHashContext * hash
void * priv
private data for use by the filter
const AVClass * class
class of the formatter
const AVTextFormatSection * section[SECTION_MAX_NB_LEVELS]
section per each level
AVTextFormatOptions opts
char * string_validation_replacement
int level
current level, starting from 0
unsigned int nb_item[SECTION_MAX_NB_LEVELS]
number of the item printed in the given section, starting from 0
unsigned int string_validation_utf8_flags
AVTextWriterContext * writer
the AVTextWriterContext
AVBPrint section_pbuf[SECTION_MAX_NB_LEVELS]
generic print buffer dedicated to each section, used by various formatters
const AVTextFormatSection * sections
array containing all sections
const AVTextFormatter * formatter
the AVTextFormatter of which this is an instance
int nb_sections
number of sections
int(* is_key_selected)(struct AVTextFormatContext *tctx, const char *key)
Callback to discard certain elements based upon the key used.
AVTextFormatDataDump data_dump_format
const char * unique_name
unique section name, in case the name is ambiguous
int id
unique id identifying a section
int(* uninit)(AVTextFormatContext *tctx)
int priv_size
private size for the formatter context
int flags
a combination or AV_TEXTFORMAT__FLAG_*
void(* print_string)(AVTextFormatContext *tctx, const char *, const char *)
void(* print_section_header)(AVTextFormatContext *tctx, const void *data)
const AVClass * priv_class
private class of the formatter, if any
const char * name
void(* print_integer)(AVTextFormatContext *tctx, const char *, int64_t)
void(* print_section_footer)(AVTextFormatContext *tctx)
int(* init)(AVTextFormatContext *tctx)
void * priv
private data for use by the writer
const AVTextWriter * writer
const AVClass * class
class of the writer
const char * name
int priv_size
private size for the writer private class
int(* uninit)(AVTextWriterContext *wctx)
int(* init)(AVTextWriterContext *wctx)
const AVClass * priv_class
private class of the writer, if any
const char * unit
union unit_value::@153353126176234320255222000327105263006301132050 val
AVTextFormatValueFormat fmt
#define av_free(p)
#define av_mallocz(s)
#define av_freep(p)
#define av_log(a,...)
#define src
Definition vp8dsp.c:248
static AVFormatContext * ctx
Definition movenc.c:49
static AVDictionary * opts
Definition movenc.c:51
int size
int len