* [FFmpeg-devel] [PATCH v6 1/8] fftools/textformat: Extract and generalize textformat api from ffprobe.c
2025-03-08 20:16 ` [FFmpeg-devel] [PATCH v6 0/8] print_graphs: Complete Filtergraph Printing ffmpegagent
@ 2025-03-08 20:16 ` softworkz
2025-03-08 20:16 ` [FFmpeg-devel] [PATCH v6 2/8] fftools/ffprobe: Change to use textformat api softworkz
` (8 subsequent siblings)
9 siblings, 0 replies; 108+ messages in thread
From: softworkz @ 2025-03-08 20:16 UTC (permalink / raw)
To: ffmpeg-devel; +Cc: softworkz
From: softworkz <softworkz@hotmail.com>
Signed-off-by: softworkz <softworkz@hotmail.com>
---
fftools/textformat/avtextformat.c | 672 +++++++++++++++++++++++++++++
fftools/textformat/avtextformat.h | 171 ++++++++
fftools/textformat/avtextwriters.h | 68 +++
fftools/textformat/tf_compact.c | 282 ++++++++++++
fftools/textformat/tf_default.c | 145 +++++++
fftools/textformat/tf_flat.c | 174 ++++++++
fftools/textformat/tf_ini.c | 160 +++++++
fftools/textformat/tf_json.c | 215 +++++++++
fftools/textformat/tf_xml.c | 221 ++++++++++
fftools/textformat/tw_avio.c | 129 ++++++
fftools/textformat/tw_buffer.c | 92 ++++
fftools/textformat/tw_stdout.c | 82 ++++
12 files changed, 2411 insertions(+)
create mode 100644 fftools/textformat/avtextformat.c
create mode 100644 fftools/textformat/avtextformat.h
create mode 100644 fftools/textformat/avtextwriters.h
create mode 100644 fftools/textformat/tf_compact.c
create mode 100644 fftools/textformat/tf_default.c
create mode 100644 fftools/textformat/tf_flat.c
create mode 100644 fftools/textformat/tf_ini.c
create mode 100644 fftools/textformat/tf_json.c
create mode 100644 fftools/textformat/tf_xml.c
create mode 100644 fftools/textformat/tw_avio.c
create mode 100644 fftools/textformat/tw_buffer.c
create mode 100644 fftools/textformat/tw_stdout.c
diff --git a/fftools/textformat/avtextformat.c b/fftools/textformat/avtextformat.c
new file mode 100644
index 0000000000..6c09f9d2cd
--- /dev/null
+++ b/fftools/textformat/avtextformat.c
@@ -0,0 +1,672 @@
+/*
+ * Copyright (c) The FFmpeg developers
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <limits.h>
+#include <stdarg.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "libavutil/mem.h"
+#include "libavutil/avassert.h"
+#include "libavutil/bprint.h"
+#include "libavutil/error.h"
+#include "libavutil/hash.h"
+#include "libavutil/intreadwrite.h"
+#include "libavutil/macros.h"
+#include "libavutil/opt.h"
+#include "avtextformat.h"
+
+#define SECTION_ID_NONE -1
+
+#define SHOW_OPTIONAL_FIELDS_AUTO -1
+#define SHOW_OPTIONAL_FIELDS_NEVER 0
+#define SHOW_OPTIONAL_FIELDS_ALWAYS 1
+
+static const struct {
+ double bin_val;
+ double dec_val;
+ const char *bin_str;
+ const char *dec_str;
+} si_prefixes[] = {
+ { 1.0, 1.0, "", "" },
+ { 1.024e3, 1e3, "Ki", "K" },
+ { 1.048576e6, 1e6, "Mi", "M" },
+ { 1.073741824e9, 1e9, "Gi", "G" },
+ { 1.099511627776e12, 1e12, "Ti", "T" },
+ { 1.125899906842624e15, 1e15, "Pi", "P" },
+};
+
+static const char *textcontext_get_formatter_name(void *p)
+{
+ AVTextFormatContext *tctx = p;
+ return tctx->formatter->name;
+}
+
+#define OFFSET(x) offsetof(AVTextFormatContext, x)
+
+static const AVOption textcontext_options[] = {
+ { "string_validation", "set string validation mode",
+ OFFSET(string_validation), AV_OPT_TYPE_INT, {.i64=AV_TEXTFORMAT_STRING_VALIDATION_REPLACE}, 0, AV_TEXTFORMAT_STRING_VALIDATION_NB-1, .unit = "sv" },
+ { "sv", "set string validation mode",
+ OFFSET(string_validation), AV_OPT_TYPE_INT, {.i64=AV_TEXTFORMAT_STRING_VALIDATION_REPLACE}, 0, AV_TEXTFORMAT_STRING_VALIDATION_NB-1, .unit = "sv" },
+ { "ignore", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = AV_TEXTFORMAT_STRING_VALIDATION_IGNORE}, .unit = "sv" },
+ { "replace", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = AV_TEXTFORMAT_STRING_VALIDATION_REPLACE}, .unit = "sv" },
+ { "fail", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = AV_TEXTFORMAT_STRING_VALIDATION_FAIL}, .unit = "sv" },
+ { "string_validation_replacement", "set string validation replacement string", OFFSET(string_validation_replacement), AV_OPT_TYPE_STRING, {.str=""}},
+ { "svr", "set string validation replacement string", OFFSET(string_validation_replacement), AV_OPT_TYPE_STRING, {.str="\xEF\xBF\xBD"}},
+ { NULL }
+};
+
+static void *textcontext_child_next(void *obj, void *prev)
+{
+ AVTextFormatContext *ctx = obj;
+ if (!prev && ctx->formatter && ctx->formatter->priv_class && ctx->priv)
+ return ctx->priv;
+ return NULL;
+}
+
+static const AVClass textcontext_class = {
+ .class_name = "AVTextContext",
+ .item_name = textcontext_get_formatter_name,
+ .option = textcontext_options,
+ .version = LIBAVUTIL_VERSION_INT,
+ .child_next = textcontext_child_next,
+};
+
+static void bprint_bytes(AVBPrint *bp, const uint8_t *ubuf, size_t ubuf_size)
+{
+ int i;
+ av_bprintf(bp, "0X");
+ for (i = 0; i < ubuf_size; i++)
+ av_bprintf(bp, "%02X", ubuf[i]);
+}
+
+int avtext_context_close(AVTextFormatContext **ptctx)
+{
+ AVTextFormatContext *tctx = *ptctx;
+ int i;
+ int ret = 0;
+
+ if (!tctx)
+ return EINVAL;
+
+ av_hash_freep(&tctx->hash);
+
+ av_hash_freep(&tctx->hash);
+
+ if (tctx->formatter->uninit)
+ tctx->formatter->uninit(tctx);
+ for (i = 0; i < SECTION_MAX_NB_LEVELS; i++)
+ av_bprint_finalize(&tctx->section_pbuf[i], NULL);
+ if (tctx->formatter->priv_class)
+ av_opt_free(tctx->priv);
+ av_freep(&tctx->priv);
+ av_opt_free(tctx);
+ av_freep(ptctx);
+ return ret;
+}
+
+
+int avtext_context_open(AVTextFormatContext **ptctx, const AVTextFormatter *formatter, AVTextWriterContext *writer_context, const char *args,
+ const struct AVTextFormatSection *sections, int nb_sections,
+ int show_value_unit,
+ int use_value_prefix,
+ int use_byte_value_binary_prefix,
+ int use_value_sexagesimal_format,
+ int show_optional_fields,
+ char *show_data_hash)
+{
+ AVTextFormatContext *tctx;
+ int i, ret = 0;
+
+ if (!(tctx = av_mallocz(sizeof(AVTextFormatContext)))) {
+ ret = AVERROR(ENOMEM);
+ goto fail;
+ }
+
+ if (!(tctx->priv = av_mallocz(formatter->priv_size))) {
+ ret = AVERROR(ENOMEM);
+ goto fail;
+ }
+
+ tctx->show_value_unit = show_value_unit;
+ tctx->use_value_prefix = use_value_prefix;
+ tctx->use_byte_value_binary_prefix = use_byte_value_binary_prefix;
+ tctx->use_value_sexagesimal_format = use_value_sexagesimal_format;
+ tctx->show_optional_fields = show_optional_fields;
+
+ if (nb_sections > SECTION_MAX_NB_SECTIONS) {
+ 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);
+ ret = AVERROR(EINVAL);
+ goto fail;
+ }
+
+ tctx->class = &textcontext_class;
+ tctx->formatter = formatter;
+ tctx->level = -1;
+ tctx->sections = sections;
+ tctx->nb_sections = nb_sections;
+ tctx->writer = writer_context;
+
+ av_opt_set_defaults(tctx);
+
+ if (formatter->priv_class) {
+ void *priv_ctx = tctx->priv;
+ *(const AVClass **)priv_ctx = formatter->priv_class;
+ av_opt_set_defaults(priv_ctx);
+ }
+
+ /* convert options to dictionary */
+ if (args) {
+ AVDictionary *opts = NULL;
+ const AVDictionaryEntry *opt = NULL;
+
+ if ((ret = av_dict_parse_string(&opts, args, "=", ":", 0)) < 0) {
+ av_log(tctx, AV_LOG_ERROR, "Failed to parse option string '%s' provided to textformat context\n", args);
+ av_dict_free(&opts);
+ goto fail;
+ }
+
+ while ((opt = av_dict_iterate(opts, opt))) {
+ if ((ret = av_opt_set(tctx, opt->key, opt->value, AV_OPT_SEARCH_CHILDREN)) < 0) {
+ av_log(tctx, AV_LOG_ERROR, "Failed to set option '%s' with value '%s' provided to textformat context\n",
+ opt->key, opt->value);
+ av_dict_free(&opts);
+ goto fail;
+ }
+ }
+
+ av_dict_free(&opts);
+ }
+
+ if (show_data_hash) {
+ if ((ret = av_hash_alloc(&tctx->hash, show_data_hash)) < 0) {
+ if (ret == AVERROR(EINVAL)) {
+ const char *n;
+ av_log(NULL, AV_LOG_ERROR, "Unknown hash algorithm '%s'\nKnown algorithms:", show_data_hash);
+ for (i = 0; (n = av_hash_names(i)); i++)
+ av_log(NULL, AV_LOG_ERROR, " %s", n);
+ av_log(NULL, AV_LOG_ERROR, "\n");
+ }
+ return ret;
+ }
+ }
+
+ /* validate replace string */
+ {
+ const uint8_t *p = tctx->string_validation_replacement;
+ const uint8_t *endp = p + strlen(p);
+ while (*p) {
+ const uint8_t *p0 = p;
+ int32_t code;
+ ret = av_utf8_decode(&code, &p, endp, tctx->string_validation_utf8_flags);
+ if (ret < 0) {
+ AVBPrint bp;
+ av_bprint_init(&bp, 0, AV_BPRINT_SIZE_AUTOMATIC);
+ bprint_bytes(&bp, p0, p-p0),
+ av_log(tctx, AV_LOG_ERROR,
+ "Invalid UTF8 sequence %s found in string validation replace '%s'\n",
+ bp.str, tctx->string_validation_replacement);
+ return ret;
+ }
+ }
+ }
+
+ for (i = 0; i < SECTION_MAX_NB_LEVELS; i++)
+ av_bprint_init(&tctx->section_pbuf[i], 1, AV_BPRINT_SIZE_UNLIMITED);
+
+ if (tctx->formatter->init)
+ ret = tctx->formatter->init(tctx);
+ if (ret < 0)
+ goto fail;
+
+ *ptctx = tctx;
+
+ return 0;
+
+fail:
+ avtext_context_close(&tctx);
+ return ret;
+}
+
+/* Temporary definitions during refactoring */
+static const char unit_second_str[] = "s" ;
+static const char unit_hertz_str[] = "Hz" ;
+static const char unit_byte_str[] = "byte" ;
+static const char unit_bit_per_second_str[] = "bit/s";
+
+
+void avtext_print_section_header(AVTextFormatContext *tctx,
+ const void *data,
+ int section_id)
+{
+ tctx->level++;
+ av_assert0(tctx->level < SECTION_MAX_NB_LEVELS);
+
+ tctx->nb_item[tctx->level] = 0;
+ memset(tctx->nb_item_type[tctx->level], 0, sizeof(tctx->nb_item_type[tctx->level]));
+ tctx->section[tctx->level] = &tctx->sections[section_id];
+
+ if (tctx->formatter->print_section_header)
+ tctx->formatter->print_section_header(tctx, data);
+}
+
+void avtext_print_section_footer(AVTextFormatContext *tctx)
+{
+ int section_id = tctx->section[tctx->level]->id;
+ int parent_section_id = tctx->level ?
+ tctx->section[tctx->level-1]->id : SECTION_ID_NONE;
+
+ if (parent_section_id != SECTION_ID_NONE) {
+ tctx->nb_item[tctx->level - 1]++;
+ tctx->nb_item_type[tctx->level - 1][section_id]++;
+ }
+
+ if (tctx->formatter->print_section_footer)
+ tctx->formatter->print_section_footer(tctx);
+ tctx->level--;
+}
+
+void avtext_print_integer(AVTextFormatContext *tctx,
+ const char *key, int64_t val)
+{
+ const struct AVTextFormatSection *section = tctx->section[tctx->level];
+
+ if (section->show_all_entries || av_dict_get(section->entries_to_show, key, NULL, 0)) {
+ tctx->formatter->print_integer(tctx, key, val);
+ tctx->nb_item[tctx->level]++;
+ }
+}
+
+static inline int validate_string(AVTextFormatContext *tctx, char **dstp, const char *src)
+{
+ const uint8_t *p, *endp;
+ AVBPrint dstbuf;
+ int invalid_chars_nb = 0, ret = 0;
+
+ av_bprint_init(&dstbuf, 0, AV_BPRINT_SIZE_UNLIMITED);
+
+ endp = src + strlen(src);
+ for (p = src; *p;) {
+ uint32_t code;
+ int invalid = 0;
+ const uint8_t *p0 = p;
+
+ if (av_utf8_decode(&code, &p, endp, tctx->string_validation_utf8_flags) < 0) {
+ AVBPrint bp;
+ av_bprint_init(&bp, 0, AV_BPRINT_SIZE_AUTOMATIC);
+ bprint_bytes(&bp, p0, p-p0);
+ av_log(tctx, AV_LOG_DEBUG,
+ "Invalid UTF-8 sequence %s found in string '%s'\n", bp.str, src);
+ invalid = 1;
+ }
+
+ if (invalid) {
+ invalid_chars_nb++;
+
+ switch (tctx->string_validation) {
+ case AV_TEXTFORMAT_STRING_VALIDATION_FAIL:
+ av_log(tctx, AV_LOG_ERROR,
+ "Invalid UTF-8 sequence found in string '%s'\n", src);
+ ret = AVERROR_INVALIDDATA;
+ goto end;
+ break;
+
+ case AV_TEXTFORMAT_STRING_VALIDATION_REPLACE:
+ av_bprintf(&dstbuf, "%s", tctx->string_validation_replacement);
+ break;
+ }
+ }
+
+ if (!invalid || tctx->string_validation == AV_TEXTFORMAT_STRING_VALIDATION_IGNORE)
+ av_bprint_append_data(&dstbuf, p0, p-p0);
+ }
+
+ if (invalid_chars_nb && tctx->string_validation == AV_TEXTFORMAT_STRING_VALIDATION_REPLACE) {
+ av_log(tctx, AV_LOG_WARNING,
+ "%d invalid UTF-8 sequence(s) found in string '%s', replaced with '%s'\n",
+ invalid_chars_nb, src, tctx->string_validation_replacement);
+ }
+
+end:
+ av_bprint_finalize(&dstbuf, dstp);
+ return ret;
+}
+
+struct unit_value {
+ union { double d; int64_t i; } val;
+ const char *unit;
+};
+
+static char *value_string(AVTextFormatContext *tctx, char *buf, int buf_size, struct unit_value uv)
+{
+ double vald;
+ int64_t vali;
+ int show_float = 0;
+
+ if (uv.unit == unit_second_str) {
+ vald = uv.val.d;
+ show_float = 1;
+ } else {
+ vald = vali = uv.val.i;
+ }
+
+ if (uv.unit == unit_second_str && tctx->use_value_sexagesimal_format) {
+ double secs;
+ int hours, mins;
+ secs = vald;
+ mins = (int)secs / 60;
+ secs = secs - mins * 60;
+ hours = mins / 60;
+ mins %= 60;
+ snprintf(buf, buf_size, "%d:%02d:%09.6f", hours, mins, secs);
+ } else {
+ const char *prefix_string = "";
+
+ if (tctx->use_value_prefix && vald > 1) {
+ int64_t index;
+
+ if (uv.unit == unit_byte_str && tctx->use_byte_value_binary_prefix) {
+ index = (int64_t) (log2(vald)) / 10;
+ index = av_clip(index, 0, FF_ARRAY_ELEMS(si_prefixes) - 1);
+ vald /= si_prefixes[index].bin_val;
+ prefix_string = si_prefixes[index].bin_str;
+ } else {
+ index = (int64_t) (log10(vald)) / 3;
+ index = av_clip(index, 0, FF_ARRAY_ELEMS(si_prefixes) - 1);
+ vald /= si_prefixes[index].dec_val;
+ prefix_string = si_prefixes[index].dec_str;
+ }
+ vali = vald;
+ }
+
+ if (show_float || (tctx->use_value_prefix && vald != (int64_t)vald))
+ snprintf(buf, buf_size, "%f", vald);
+ else
+ snprintf(buf, buf_size, "%"PRId64, vali);
+ av_strlcatf(buf, buf_size, "%s%s%s", *prefix_string || tctx->show_value_unit ? " " : "",
+ prefix_string, tctx->show_value_unit ? uv.unit : "");
+ }
+
+ return buf;
+}
+
+
+void avtext_print_unit_int(AVTextFormatContext *tctx, const char *key, int value, const char *unit)
+{
+ char val_str[128];
+ struct unit_value uv;
+ uv.val.i = value;
+ uv.unit = unit;
+ avtext_print_string(tctx, key, value_string(tctx, val_str, sizeof(val_str), uv), 0);
+}
+
+
+int avtext_print_string(AVTextFormatContext *tctx, const char *key, const char *val, int flags)
+{
+ const struct AVTextFormatSection *section = tctx->section[tctx->level];
+ int ret = 0;
+
+ if (tctx->show_optional_fields == SHOW_OPTIONAL_FIELDS_NEVER ||
+ (tctx->show_optional_fields == SHOW_OPTIONAL_FIELDS_AUTO
+ && (flags & AV_TEXTFORMAT_PRINT_STRING_OPTIONAL)
+ && !(tctx->formatter->flags & AV_TEXTFORMAT_FLAG_SUPPORTS_OPTIONAL_FIELDS)))
+ return 0;
+
+ if (section->show_all_entries || av_dict_get(section->entries_to_show, key, NULL, 0)) {
+ if (flags & AV_TEXTFORMAT_PRINT_STRING_VALIDATE) {
+ char *key1 = NULL, *val1 = NULL;
+ ret = validate_string(tctx, &key1, key);
+ if (ret < 0) goto end;
+ ret = validate_string(tctx, &val1, val);
+ if (ret < 0) goto end;
+ tctx->formatter->print_string(tctx, key1, val1);
+ end:
+ if (ret < 0) {
+ av_log(tctx, AV_LOG_ERROR,
+ "Invalid key=value string combination %s=%s in section %s\n",
+ key, val, section->unique_name);
+ }
+ av_free(key1);
+ av_free(val1);
+ } else {
+ tctx->formatter->print_string(tctx, key, val);
+ }
+
+ tctx->nb_item[tctx->level]++;
+ }
+
+ return ret;
+}
+
+void avtext_print_rational(AVTextFormatContext *tctx,
+ const char *key, AVRational q, char sep)
+{
+ AVBPrint buf;
+ av_bprint_init(&buf, 0, AV_BPRINT_SIZE_AUTOMATIC);
+ av_bprintf(&buf, "%d%c%d", q.num, sep, q.den);
+ avtext_print_string(tctx, key, buf.str, 0);
+}
+
+void avtext_print_time(AVTextFormatContext *tctx, const char *key,
+ int64_t ts, const AVRational *time_base, int is_duration)
+{
+ char buf[128];
+
+ if ((!is_duration && ts == AV_NOPTS_VALUE) || (is_duration && ts == 0)) {
+ avtext_print_string(tctx, key, "N/A", AV_TEXTFORMAT_PRINT_STRING_OPTIONAL);
+ } else {
+ double d = ts * av_q2d(*time_base);
+ struct unit_value uv;
+ uv.val.d = d;
+ uv.unit = unit_second_str;
+ value_string(tctx, buf, sizeof(buf), uv);
+ avtext_print_string(tctx, key, buf, 0);
+ }
+}
+
+void avtext_print_ts(AVTextFormatContext *tctx, const char *key, int64_t ts, int is_duration)
+{
+ if ((!is_duration && ts == AV_NOPTS_VALUE) || (is_duration && ts == 0)) {
+ avtext_print_string(tctx, key, "N/A", AV_TEXTFORMAT_PRINT_STRING_OPTIONAL);
+ } else {
+ avtext_print_integer(tctx, key, ts);
+ }
+}
+
+void avtext_print_data(AVTextFormatContext *tctx, const char *name,
+ const uint8_t *data, int size)
+{
+ AVBPrint bp;
+ int offset = 0, l, i;
+
+ av_bprint_init(&bp, 0, AV_BPRINT_SIZE_UNLIMITED);
+ av_bprintf(&bp, "\n");
+ while (size) {
+ av_bprintf(&bp, "%08x: ", offset);
+ l = FFMIN(size, 16);
+ for (i = 0; i < l; i++) {
+ av_bprintf(&bp, "%02x", data[i]);
+ if (i & 1)
+ av_bprintf(&bp, " ");
+ }
+ av_bprint_chars(&bp, ' ', 41 - 2 * i - i / 2);
+ for (i = 0; i < l; i++)
+ av_bprint_chars(&bp, data[i] - 32U < 95 ? data[i] : '.', 1);
+ av_bprintf(&bp, "\n");
+ offset += l;
+ data += l;
+ size -= l;
+ }
+ avtext_print_string(tctx, name, bp.str, 0);
+ av_bprint_finalize(&bp, NULL);
+}
+
+void avtext_print_data_hash(AVTextFormatContext *tctx, const char *name,
+ const uint8_t *data, int size)
+{
+ char *p, buf[AV_HASH_MAX_SIZE * 2 + 64] = { 0 };
+
+ if (!tctx->hash)
+ return;
+ av_hash_init(tctx->hash);
+ av_hash_update(tctx->hash, data, size);
+ snprintf(buf, sizeof(buf), "%s:", av_hash_get_name(tctx->hash));
+ p = buf + strlen(buf);
+ av_hash_final_hex(tctx->hash, p, buf + sizeof(buf) - p);
+ avtext_print_string(tctx, name, buf, 0);
+}
+
+void avtext_print_integers(AVTextFormatContext *tctx, const char *name,
+ uint8_t *data, int size, const char *format,
+ int columns, int bytes, int offset_add)
+{
+ AVBPrint bp;
+ int offset = 0, l, i;
+
+ av_bprint_init(&bp, 0, AV_BPRINT_SIZE_UNLIMITED);
+ av_bprintf(&bp, "\n");
+ while (size) {
+ av_bprintf(&bp, "%08x: ", offset);
+ l = FFMIN(size, columns);
+ for (i = 0; i < l; i++) {
+ if (bytes == 1) av_bprintf(&bp, format, *data);
+ else if (bytes == 2) av_bprintf(&bp, format, AV_RN16(data));
+ else if (bytes == 4) av_bprintf(&bp, format, AV_RN32(data));
+ data += bytes;
+ size --;
+ }
+ av_bprintf(&bp, "\n");
+ offset += offset_add;
+ }
+ avtext_print_string(tctx, name, bp.str, 0);
+ av_bprint_finalize(&bp, NULL);
+}
+
+static const char *writercontext_get_writer_name(void *p)
+{
+ AVTextWriterContext *wctx = p;
+ return wctx->writer->name;
+}
+
+static void *writercontext_child_next(void *obj, void *prev)
+{
+ AVTextFormatContext *ctx = obj;
+ if (!prev && ctx->formatter && ctx->formatter->priv_class && ctx->priv)
+ return ctx->priv;
+ return NULL;
+}
+
+static const AVClass textwriter_class = {
+ .class_name = "AVTextWriterContext",
+ .item_name = writercontext_get_writer_name,
+ .version = LIBAVUTIL_VERSION_INT,
+ .child_next = writercontext_child_next,
+};
+
+
+int avtextwriter_context_close(AVTextWriterContext **pwctx)
+{
+ AVTextWriterContext *wctx = *pwctx;
+ int ret = 0;
+
+ if (!wctx)
+ return EINVAL;
+
+ if (wctx->writer->uninit)
+ wctx->writer->uninit(wctx);
+ if (wctx->writer->priv_class)
+ av_opt_free(wctx->priv);
+ av_freep(&wctx->priv);
+ av_freep(pwctx);
+ return ret;
+}
+
+
+int avtextwriter_context_open(AVTextWriterContext **pwctx, const AVTextWriter *writer)
+{
+ AVTextWriterContext *wctx;
+ int ret = 0;
+
+ if (!(wctx = av_mallocz(sizeof(AVTextWriterContext)))) {
+ ret = AVERROR(ENOMEM);
+ goto fail;
+ }
+
+ if (!(wctx->priv = av_mallocz(writer->priv_size))) {
+ ret = AVERROR(ENOMEM);
+ goto fail;
+ }
+
+ if (writer->priv_class) {
+ void *priv_ctx = wctx->priv;
+ *(const AVClass **)priv_ctx = writer->priv_class;
+ av_opt_set_defaults(priv_ctx);
+ }
+
+ wctx->class = &textwriter_class;
+ wctx->writer = writer;
+
+ av_opt_set_defaults(wctx);
+
+
+ if (wctx->writer->init)
+ ret = wctx->writer->init(wctx);
+ if (ret < 0)
+ goto fail;
+
+ *pwctx = wctx;
+
+ return 0;
+
+fail:
+ avtextwriter_context_close(&wctx);
+ return ret;
+}
+
+static const AVTextFormatter *registered_formatters[7+1];
+static void formatters_register_all(void)
+{
+ static int initialized;
+
+ if (initialized)
+ return;
+ initialized = 1;
+
+ registered_formatters[0] = &avtextformatter_default;
+ registered_formatters[1] = &avtextformatter_compact;
+ registered_formatters[2] = &avtextformatter_csv;
+ registered_formatters[3] = &avtextformatter_flat;
+ registered_formatters[4] = &avtextformatter_ini;
+ registered_formatters[5] = &avtextformatter_json;
+ registered_formatters[6] = &avtextformatter_xml;
+}
+
+const AVTextFormatter *avtext_get_formatter_by_name(const char *name)
+{
+ formatters_register_all();
+
+ for (int i = 0; registered_formatters[i]; i++)
+ if (!strcmp(registered_formatters[i]->name, name))
+ return registered_formatters[i];
+
+ return NULL;
+}
diff --git a/fftools/textformat/avtextformat.h b/fftools/textformat/avtextformat.h
new file mode 100644
index 0000000000..4689499246
--- /dev/null
+++ b/fftools/textformat/avtextformat.h
@@ -0,0 +1,171 @@
+/*
+ * Copyright (c) The FFmpeg developers
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef FFTOOLS_TEXTFORMAT_AVTEXTFORMAT_H
+#define FFTOOLS_TEXTFORMAT_AVTEXTFORMAT_H
+
+#include <stddef.h>
+#include <stdint.h>
+#include "libavutil/attributes.h"
+#include "libavutil/dict.h"
+#include "libavformat/avio.h"
+#include "libavutil/bprint.h"
+#include "libavutil/rational.h"
+#include "libavutil/hash.h"
+#include "avtextwriters.h"
+
+#define SECTION_MAX_NB_CHILDREN 11
+
+
+struct AVTextFormatSection {
+ int id; ///< unique id identifying a section
+ const char *name;
+
+#define AV_TEXTFORMAT_SECTION_FLAG_IS_WRAPPER 1 ///< the section only contains other sections, but has no data at its own level
+#define AV_TEXTFORMAT_SECTION_FLAG_IS_ARRAY 2 ///< the section contains an array of elements of the same type
+#define AV_TEXTFORMAT_SECTION_FLAG_HAS_VARIABLE_FIELDS 4 ///< the section may contain a variable number of fields with variable keys.
+ /// For these sections the element_name field is mandatory.
+#define AV_TEXTFORMAT_SECTION_FLAG_HAS_TYPE 8 ///< the section contains a type to distinguish multiple nested elements
+#define AV_TEXTFORMAT_SECTION_FLAG_NUMBERING_BY_TYPE 16 ///< the items in this array section should be numbered individually by type
+
+ int flags;
+ const int children_ids[SECTION_MAX_NB_CHILDREN+1]; ///< list of children section IDS, terminated by -1
+ const char *element_name; ///< name of the contained element, if provided
+ const char *unique_name; ///< unique section name, in case the name is ambiguous
+ AVDictionary *entries_to_show;
+ const char *(* get_type)(const void *data); ///< function returning a type if defined, must be defined when SECTION_FLAG_HAS_TYPE is defined
+ int show_all_entries;
+} AVTextFormatSection;
+
+typedef struct AVTextFormatContext AVTextFormatContext;
+
+#define AV_TEXTFORMAT_FLAG_SUPPORTS_OPTIONAL_FIELDS 1
+#define AV_TEXTFORMAT_FLAG_SUPPORTS_MIXED_ARRAY_CONTENT 2
+
+typedef enum {
+ AV_TEXTFORMAT_STRING_VALIDATION_FAIL,
+ AV_TEXTFORMAT_STRING_VALIDATION_REPLACE,
+ AV_TEXTFORMAT_STRING_VALIDATION_IGNORE,
+ AV_TEXTFORMAT_STRING_VALIDATION_NB
+} StringValidation;
+
+typedef struct AVTextFormatter {
+ const AVClass *priv_class; ///< private class of the formatter, if any
+ int priv_size; ///< private size for the formatter context
+ const char *name;
+
+ int (*init) (AVTextFormatContext *tctx);
+ void (*uninit)(AVTextFormatContext *tctx);
+
+ void (*print_section_header)(AVTextFormatContext *tctx, const void *data);
+ void (*print_section_footer)(AVTextFormatContext *tctx);
+ void (*print_integer) (AVTextFormatContext *tctx, const char *, int64_t);
+ void (*print_rational) (AVTextFormatContext *tctx, AVRational *q, char *sep);
+ void (*print_string) (AVTextFormatContext *tctx, const char *, const char *);
+ int flags; ///< a combination or AV_TEXTFORMAT__FLAG_*
+} AVTextFormatter;
+
+#define SECTION_MAX_NB_LEVELS 12
+#define SECTION_MAX_NB_SECTIONS 100
+
+struct AVTextFormatContext {
+ const AVClass *class; ///< class of the formatter
+ const AVTextFormatter *formatter; ///< the AVTextFormatter of which this is an instance
+ AVTextWriterContext *writer; ///< the AVTextWriterContext
+
+ char *name; ///< name of this formatter instance
+ void *priv; ///< private data for use by the filter
+
+ const struct AVTextFormatSection *sections; ///< array containing all sections
+ int nb_sections; ///< number of sections
+
+ int level; ///< current level, starting from 0
+
+ /** number of the item printed in the given section, starting from 0 */
+ unsigned int nb_item[SECTION_MAX_NB_LEVELS];
+ unsigned int nb_item_type[SECTION_MAX_NB_LEVELS][SECTION_MAX_NB_SECTIONS];
+
+ /** section per each level */
+ const struct AVTextFormatSection *section[SECTION_MAX_NB_LEVELS];
+ AVBPrint section_pbuf[SECTION_MAX_NB_LEVELS]; ///< generic print buffer dedicated to each section,
+ /// used by various formatters
+
+ int show_optional_fields;
+ int show_value_unit;
+ int use_value_prefix;
+ int use_byte_value_binary_prefix;
+ int use_value_sexagesimal_format;
+
+ struct AVHashContext *hash;
+
+ int string_validation;
+ char *string_validation_replacement;
+ unsigned int string_validation_utf8_flags;
+};
+
+#define AV_TEXTFORMAT_PRINT_STRING_OPTIONAL 1
+#define AV_TEXTFORMAT_PRINT_STRING_VALIDATE 2
+
+int avtext_context_open(AVTextFormatContext **ptctx, const AVTextFormatter *formatter, AVTextWriterContext *writer_context, const char *args,
+ const struct AVTextFormatSection *sections, int nb_sections,
+ int show_value_unit,
+ int use_value_prefix,
+ int use_byte_value_binary_prefix,
+ int use_value_sexagesimal_format,
+ int show_optional_fields,
+ char *show_data_hash);
+
+int avtext_context_close(AVTextFormatContext **tctx);
+
+
+void avtext_print_section_header(AVTextFormatContext *tctx, const void *data, int section_id);
+
+void avtext_print_section_footer(AVTextFormatContext *tctx);
+
+void avtext_print_integer(AVTextFormatContext *tctx, const char *key, int64_t val);
+
+int avtext_print_string(AVTextFormatContext *tctx, const char *key, const char *val, int flags);
+
+void avtext_print_unit_int(AVTextFormatContext *tctx, const char *key, int value, const char *unit);
+
+void avtext_print_rational(AVTextFormatContext *tctx, const char *key, AVRational q, char sep);
+
+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);
+
+void avtext_print_data(AVTextFormatContext *tctx, const char *name, const uint8_t *data, int size);
+
+void avtext_print_data_hash(AVTextFormatContext *tctx, const char *name, const uint8_t *data, int size);
+
+void avtext_print_integers(AVTextFormatContext *tctx, const char *name, uint8_t *data, int size,
+ const char *format, int columns, int bytes, int offset_add);
+
+const AVTextFormatter *avtext_get_formatter_by_name(const char *name);
+
+extern const AVTextFormatter avtextformatter_default;
+extern const AVTextFormatter avtextformatter_compact;
+extern const AVTextFormatter avtextformatter_csv;
+extern const AVTextFormatter avtextformatter_flat;
+extern const AVTextFormatter avtextformatter_ini;
+extern const AVTextFormatter avtextformatter_json;
+extern const AVTextFormatter avtextformatter_xml;
+
+#endif /* FFTOOLS_TEXTFORMAT_AVTEXTFORMAT_H */
diff --git a/fftools/textformat/avtextwriters.h b/fftools/textformat/avtextwriters.h
new file mode 100644
index 0000000000..a62f2c8906
--- /dev/null
+++ b/fftools/textformat/avtextwriters.h
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) The FFmpeg developers
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef FFTOOLS_TEXTFORMAT_AVTEXTWRITERS_H
+#define FFTOOLS_TEXTFORMAT_AVTEXTWRITERS_H
+
+#include <stddef.h>
+#include <stdint.h>
+#include "libavutil/attributes.h"
+#include "libavutil/dict.h"
+#include "libavformat/avio.h"
+#include "libavutil/bprint.h"
+#include "libavutil/rational.h"
+#include "libavutil/hash.h"
+
+typedef struct AVTextWriterContext AVTextWriterContext;
+
+typedef struct AVTextWriter {
+ const AVClass *priv_class; ///< private class of the writer, if any
+ int priv_size; ///< private size for the writer private class
+ const char *name;
+
+ int (* init)(AVTextWriterContext *wctx);
+ void (* uninit)(AVTextWriterContext *wctx);
+ void (* writer_w8)(AVTextWriterContext *wctx, int b);
+ void (* writer_put_str)(AVTextWriterContext *wctx, const char *str);
+ void (* writer_printf)(AVTextWriterContext *wctx, const char *fmt, ...);
+} AVTextWriter;
+
+typedef struct AVTextWriterContext {
+ const AVClass *class; ///< class of the writer
+ const AVTextWriter *writer;
+ const char *name;
+ void *priv; ///< private data for use by the writer
+
+} AVTextWriterContext;
+
+
+int avtextwriter_context_open(AVTextWriterContext **pwctx, const AVTextWriter *writer);
+
+int avtextwriter_context_close(AVTextWriterContext **pwctx);
+
+int avtextwriter_create_stdout(AVTextWriterContext **pwctx);
+
+int avtextwriter_create_avio(AVTextWriterContext **pwctx, AVIOContext *avio_ctx, int close_on_uninit);
+
+int avtextwriter_create_file(AVTextWriterContext **pwctx, const char *output_filename, int close_on_uninit);
+
+int avtextwriter_create_buffer(AVTextWriterContext **pwctx, AVBPrint *buffer);
+
+#endif /* FFTOOLS_TEXTFORMAT_AVTEXTWRITERS_H */
diff --git a/fftools/textformat/tf_compact.c b/fftools/textformat/tf_compact.c
new file mode 100644
index 0000000000..825b67bc6e
--- /dev/null
+++ b/fftools/textformat/tf_compact.c
@@ -0,0 +1,282 @@
+/*
+ * Copyright (c) The FFmpeg developers
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <limits.h>
+#include <stdarg.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "avtextformat.h"
+#include <libavutil/mem.h>
+#include <libavutil/avassert.h>
+#include <libavutil/bprint.h>
+#include <libavutil/error.h>
+#include <libavutil/macros.h>
+#include <libavutil/opt.h>
+
+
+#define writer_w8(wctx_, b_) (wctx_)->writer->writer->writer_w8((wctx_)->writer, b_)
+#define writer_put_str(wctx_, str_) (wctx_)->writer->writer->writer_put_str((wctx_)->writer, str_)
+#define writer_printf(wctx_, fmt_, ...) (wctx_)->writer->writer->writer_printf((wctx_)->writer, fmt_, __VA_ARGS__)
+
+
+#define DEFINE_FORMATTER_CLASS(name) \
+static const char *name##_get_name(void *ctx) \
+{ \
+ return #name ; \
+} \
+static const AVClass name##_class = { \
+ .class_name = #name, \
+ .item_name = name##_get_name, \
+ .option = name##_options \
+}
+
+
+/* Compact output */
+
+/**
+ * Apply C-language-like string escaping.
+ */
+static const char *c_escape_str(AVBPrint *dst, const char *src, const char sep, void *log_ctx)
+{
+ const char *p;
+
+ for (p = src; *p; p++) {
+ switch (*p) {
+ case '\b': av_bprintf(dst, "%s", "\\b"); break;
+ case '\f': av_bprintf(dst, "%s", "\\f"); break;
+ case '\n': av_bprintf(dst, "%s", "\\n"); break;
+ case '\r': av_bprintf(dst, "%s", "\\r"); break;
+ case '\\': av_bprintf(dst, "%s", "\\\\"); break;
+ default:
+ if (*p == sep)
+ av_bprint_chars(dst, '\\', 1);
+ av_bprint_chars(dst, *p, 1);
+ }
+ }
+ return dst->str;
+}
+
+/**
+ * Quote fields containing special characters, check RFC4180.
+ */
+static const char *csv_escape_str(AVBPrint *dst, const char *src, const char sep, void *log_ctx)
+{
+ char meta_chars[] = { sep, '"', '\n', '\r', '\0' };
+ int needs_quoting = !!src[strcspn(src, meta_chars)];
+
+ if (needs_quoting)
+ av_bprint_chars(dst, '"', 1);
+
+ for (; *src; src++) {
+ if (*src == '"')
+ av_bprint_chars(dst, '"', 1);
+ av_bprint_chars(dst, *src, 1);
+ }
+ if (needs_quoting)
+ av_bprint_chars(dst, '"', 1);
+ return dst->str;
+}
+
+static const char *none_escape_str(AVBPrint *dst, const char *src, const char sep, void *log_ctx)
+{
+ return src;
+}
+
+typedef struct CompactContext {
+ const AVClass *class;
+ char *item_sep_str;
+ char item_sep;
+ int nokey;
+ int print_section;
+ char *escape_mode_str;
+ const char * (*escape_str)(AVBPrint *dst, const char *src, const char sep, void *log_ctx);
+ int nested_section[SECTION_MAX_NB_LEVELS];
+ int has_nested_elems[SECTION_MAX_NB_LEVELS];
+ int terminate_line[SECTION_MAX_NB_LEVELS];
+} CompactContext;
+
+#undef OFFSET
+#define OFFSET(x) offsetof(CompactContext, x)
+
+static const AVOption compact_options[]= {
+ {"item_sep", "set item separator", OFFSET(item_sep_str), AV_OPT_TYPE_STRING, {.str="|"}, 0, 0 },
+ {"s", "set item separator", OFFSET(item_sep_str), AV_OPT_TYPE_STRING, {.str="|"}, 0, 0 },
+ {"nokey", "force no key printing", OFFSET(nokey), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1 },
+ {"nk", "force no key printing", OFFSET(nokey), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1 },
+ {"escape", "set escape mode", OFFSET(escape_mode_str), AV_OPT_TYPE_STRING, {.str="c"}, 0, 0 },
+ {"e", "set escape mode", OFFSET(escape_mode_str), AV_OPT_TYPE_STRING, {.str="c"}, 0, 0 },
+ {"print_section", "print section name", OFFSET(print_section), AV_OPT_TYPE_BOOL, {.i64=1}, 0, 1 },
+ {"p", "print section name", OFFSET(print_section), AV_OPT_TYPE_BOOL, {.i64=1}, 0, 1 },
+ {NULL},
+};
+
+DEFINE_FORMATTER_CLASS(compact);
+
+static av_cold int compact_init(AVTextFormatContext *wctx)
+{
+ CompactContext *compact = wctx->priv;
+
+ if (strlen(compact->item_sep_str) != 1) {
+ av_log(wctx, AV_LOG_ERROR, "Item separator '%s' specified, but must contain a single character\n",
+ compact->item_sep_str);
+ return AVERROR(EINVAL);
+ }
+ compact->item_sep = compact->item_sep_str[0];
+
+ if (!strcmp(compact->escape_mode_str, "none")) compact->escape_str = none_escape_str;
+ else if (!strcmp(compact->escape_mode_str, "c" )) compact->escape_str = c_escape_str;
+ else if (!strcmp(compact->escape_mode_str, "csv" )) compact->escape_str = csv_escape_str;
+ else {
+ av_log(wctx, AV_LOG_ERROR, "Unknown escape mode '%s'\n", compact->escape_mode_str);
+ return AVERROR(EINVAL);
+ }
+
+ return 0;
+}
+
+static void compact_print_section_header(AVTextFormatContext *wctx, const void *data)
+{
+ CompactContext *compact = wctx->priv;
+ const struct AVTextFormatSection *section = wctx->section[wctx->level];
+ const struct AVTextFormatSection *parent_section = wctx->level ?
+ wctx->section[wctx->level-1] : NULL;
+ compact->terminate_line[wctx->level] = 1;
+ compact->has_nested_elems[wctx->level] = 0;
+
+ av_bprint_clear(&wctx->section_pbuf[wctx->level]);
+ if (parent_section &&
+ (section->flags & AV_TEXTFORMAT_SECTION_FLAG_HAS_TYPE ||
+ (!(section->flags & AV_TEXTFORMAT_SECTION_FLAG_IS_ARRAY) &&
+ !(parent_section->flags & (AV_TEXTFORMAT_SECTION_FLAG_IS_WRAPPER|AV_TEXTFORMAT_SECTION_FLAG_IS_ARRAY))))) {
+
+ /* define a prefix for elements not contained in an array or
+ in a wrapper, or for array elements with a type */
+ const char *element_name = (char *)av_x_if_null(section->element_name, section->name);
+ AVBPrint *section_pbuf = &wctx->section_pbuf[wctx->level];
+
+ compact->nested_section[wctx->level] = 1;
+ compact->has_nested_elems[wctx->level-1] = 1;
+
+ av_bprintf(section_pbuf, "%s%s",
+ wctx->section_pbuf[wctx->level-1].str, element_name);
+
+ if (section->flags & AV_TEXTFORMAT_SECTION_FLAG_HAS_TYPE) {
+ // add /TYPE to prefix
+ av_bprint_chars(section_pbuf, '/', 1);
+
+ // normalize section type, replace special characters and lower case
+ for (const char *p = section->get_type(data); *p; p++) {
+ char c =
+ (*p >= '0' && *p <= '9') ||
+ (*p >= 'a' && *p <= 'z') ||
+ (*p >= 'A' && *p <= 'Z') ? av_tolower(*p) : '_';
+ av_bprint_chars(section_pbuf, c, 1);
+ }
+ }
+ av_bprint_chars(section_pbuf, ':', 1);
+
+ wctx->nb_item[wctx->level] = wctx->nb_item[wctx->level-1];
+ } else {
+ if (parent_section && !(parent_section->flags & (AV_TEXTFORMAT_SECTION_FLAG_IS_WRAPPER|AV_TEXTFORMAT_SECTION_FLAG_IS_ARRAY)) &&
+ wctx->level && wctx->nb_item[wctx->level-1])
+ writer_w8(wctx, compact->item_sep);
+ if (compact->print_section &&
+ !(section->flags & (AV_TEXTFORMAT_SECTION_FLAG_IS_WRAPPER|AV_TEXTFORMAT_SECTION_FLAG_IS_ARRAY)))
+ writer_printf(wctx, "%s%c", section->name, compact->item_sep);
+ }
+}
+
+static void compact_print_section_footer(AVTextFormatContext *wctx)
+{
+ CompactContext *compact = wctx->priv;
+
+ if (!compact->nested_section[wctx->level] &&
+ compact->terminate_line[wctx->level] &&
+ !(wctx->section[wctx->level]->flags & (AV_TEXTFORMAT_SECTION_FLAG_IS_WRAPPER|AV_TEXTFORMAT_SECTION_FLAG_IS_ARRAY)))
+ writer_w8(wctx, '\n');
+}
+
+static void compact_print_str(AVTextFormatContext *wctx, const char *key, const char *value)
+{
+ CompactContext *compact = wctx->priv;
+ AVBPrint buf;
+
+ if (wctx->nb_item[wctx->level]) writer_w8(wctx, compact->item_sep);
+ if (!compact->nokey)
+ writer_printf(wctx, "%s%s=", wctx->section_pbuf[wctx->level].str, key);
+ av_bprint_init(&buf, 1, AV_BPRINT_SIZE_UNLIMITED);
+ writer_put_str(wctx, compact->escape_str(&buf, value, compact->item_sep, wctx));
+ av_bprint_finalize(&buf, NULL);
+}
+
+static void compact_print_int(AVTextFormatContext *wctx, const char *key, int64_t value)
+{
+ CompactContext *compact = wctx->priv;
+
+ if (wctx->nb_item[wctx->level]) writer_w8(wctx, compact->item_sep);
+ if (!compact->nokey)
+ writer_printf(wctx, "%s%s=", wctx->section_pbuf[wctx->level].str, key);
+ writer_printf(wctx, "%"PRId64, value);
+}
+
+const AVTextFormatter avtextformatter_compact = {
+ .name = "compact",
+ .priv_size = sizeof(CompactContext),
+ .init = compact_init,
+ .print_section_header = compact_print_section_header,
+ .print_section_footer = compact_print_section_footer,
+ .print_integer = compact_print_int,
+ .print_string = compact_print_str,
+ .flags = AV_TEXTFORMAT_FLAG_SUPPORTS_OPTIONAL_FIELDS,
+ .priv_class = &compact_class,
+};
+
+/* CSV output */
+
+#undef OFFSET
+#define OFFSET(x) offsetof(CompactContext, x)
+
+static const AVOption csv_options[] = {
+ {"item_sep", "set item separator", OFFSET(item_sep_str), AV_OPT_TYPE_STRING, {.str=","}, 0, 0 },
+ {"s", "set item separator", OFFSET(item_sep_str), AV_OPT_TYPE_STRING, {.str=","}, 0, 0 },
+ {"nokey", "force no key printing", OFFSET(nokey), AV_OPT_TYPE_BOOL, {.i64=1}, 0, 1 },
+ {"nk", "force no key printing", OFFSET(nokey), AV_OPT_TYPE_BOOL, {.i64=1}, 0, 1 },
+ {"escape", "set escape mode", OFFSET(escape_mode_str), AV_OPT_TYPE_STRING, {.str="csv"}, 0, 0 },
+ {"e", "set escape mode", OFFSET(escape_mode_str), AV_OPT_TYPE_STRING, {.str="csv"}, 0, 0 },
+ {"print_section", "print section name", OFFSET(print_section), AV_OPT_TYPE_BOOL, {.i64=1}, 0, 1 },
+ {"p", "print section name", OFFSET(print_section), AV_OPT_TYPE_BOOL, {.i64=1}, 0, 1 },
+ {NULL},
+};
+
+DEFINE_FORMATTER_CLASS(csv);
+
+const AVTextFormatter avtextformatter_csv = {
+ .name = "csv",
+ .priv_size = sizeof(CompactContext),
+ .init = compact_init,
+ .print_section_header = compact_print_section_header,
+ .print_section_footer = compact_print_section_footer,
+ .print_integer = compact_print_int,
+ .print_string = compact_print_str,
+ .flags = AV_TEXTFORMAT_FLAG_SUPPORTS_OPTIONAL_FIELDS,
+ .priv_class = &csv_class,
+};
diff --git a/fftools/textformat/tf_default.c b/fftools/textformat/tf_default.c
new file mode 100644
index 0000000000..7369992f01
--- /dev/null
+++ b/fftools/textformat/tf_default.c
@@ -0,0 +1,145 @@
+/*
+ * Copyright (c) The FFmpeg developers
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <limits.h>
+#include <stdarg.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "avtextformat.h"
+#include <libavutil/mem.h>
+#include <libavutil/avassert.h>
+#include <libavutil/bprint.h>
+#include <libavutil/opt.h>
+
+#define writer_w8(wctx_, b_) (wctx_)->writer->writer->writer_w8((wctx_)->writer, b_)
+#define writer_put_str(wctx_, str_) (wctx_)->writer->writer->writer_put_str((wctx_)->writer, str_)
+#define writer_printf(wctx_, fmt_, ...) (wctx_)->writer->writer->writer_printf((wctx_)->writer, fmt_, __VA_ARGS__)
+
+#define DEFINE_FORMATTER_CLASS(name) \
+static const char *name##_get_name(void *ctx) \
+{ \
+ return #name ; \
+} \
+static const AVClass name##_class = { \
+ .class_name = #name, \
+ .item_name = name##_get_name, \
+ .option = name##_options \
+}
+
+/* Default output */
+
+typedef struct DefaultContext {
+ const AVClass *class;
+ int nokey;
+ int noprint_wrappers;
+ int nested_section[SECTION_MAX_NB_LEVELS];
+} DefaultContext;
+
+#undef OFFSET
+#define OFFSET(x) offsetof(DefaultContext, x)
+
+static const AVOption default_options[] = {
+ { "noprint_wrappers", "do not print headers and footers", OFFSET(noprint_wrappers), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1 },
+ { "nw", "do not print headers and footers", OFFSET(noprint_wrappers), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1 },
+ { "nokey", "force no key printing", OFFSET(nokey), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1 },
+ { "nk", "force no key printing", OFFSET(nokey), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1 },
+ {NULL},
+};
+
+DEFINE_FORMATTER_CLASS(default);
+
+/* lame uppercasing routine, assumes the string is lower case ASCII */
+static inline char *upcase_string(char *dst, size_t dst_size, const char *src)
+{
+ int i;
+ for (i = 0; src[i] && i < dst_size-1; i++)
+ dst[i] = av_toupper(src[i]);
+ dst[i] = 0;
+ return dst;
+}
+
+static void default_print_section_header(AVTextFormatContext *wctx, const void *data)
+{
+ DefaultContext *def = wctx->priv;
+ char buf[32];
+ const struct AVTextFormatSection *section = wctx->section[wctx->level];
+ const struct AVTextFormatSection *parent_section = wctx->level ?
+ wctx->section[wctx->level-1] : NULL;
+
+ av_bprint_clear(&wctx->section_pbuf[wctx->level]);
+ if (parent_section &&
+ !(parent_section->flags & (AV_TEXTFORMAT_SECTION_FLAG_IS_WRAPPER|AV_TEXTFORMAT_SECTION_FLAG_IS_ARRAY))) {
+ def->nested_section[wctx->level] = 1;
+ av_bprintf(&wctx->section_pbuf[wctx->level], "%s%s:",
+ wctx->section_pbuf[wctx->level-1].str,
+ upcase_string(buf, sizeof(buf),
+ av_x_if_null(section->element_name, section->name)));
+ }
+
+ if (def->noprint_wrappers || def->nested_section[wctx->level])
+ return;
+
+ if (!(section->flags & (AV_TEXTFORMAT_SECTION_FLAG_IS_WRAPPER|AV_TEXTFORMAT_SECTION_FLAG_IS_ARRAY)))
+ writer_printf(wctx, "[%s]\n", upcase_string(buf, sizeof(buf), section->name));
+}
+
+static void default_print_section_footer(AVTextFormatContext *wctx)
+{
+ DefaultContext *def = wctx->priv;
+ const struct AVTextFormatSection *section = wctx->section[wctx->level];
+ char buf[32];
+
+ if (def->noprint_wrappers || def->nested_section[wctx->level])
+ return;
+
+ if (!(section->flags & (AV_TEXTFORMAT_SECTION_FLAG_IS_WRAPPER|AV_TEXTFORMAT_SECTION_FLAG_IS_ARRAY)))
+ writer_printf(wctx, "[/%s]\n", upcase_string(buf, sizeof(buf), section->name));
+}
+
+static void default_print_str(AVTextFormatContext *wctx, const char *key, const char *value)
+{
+ DefaultContext *def = wctx->priv;
+
+ if (!def->nokey)
+ writer_printf(wctx, "%s%s=", wctx->section_pbuf[wctx->level].str, key);
+ writer_printf(wctx, "%s\n", value);
+}
+
+static void default_print_int(AVTextFormatContext *wctx, const char *key, int64_t value)
+{
+ DefaultContext *def = wctx->priv;
+
+ if (!def->nokey)
+ writer_printf(wctx, "%s%s=", wctx->section_pbuf[wctx->level].str, key);
+ writer_printf(wctx, "%"PRId64"\n", value);
+}
+
+const AVTextFormatter avtextformatter_default = {
+ .name = "default",
+ .priv_size = sizeof(DefaultContext),
+ .print_section_header = default_print_section_header,
+ .print_section_footer = default_print_section_footer,
+ .print_integer = default_print_int,
+ .print_string = default_print_str,
+ .flags = AV_TEXTFORMAT_FLAG_SUPPORTS_OPTIONAL_FIELDS,
+ .priv_class = &default_class,
+};
\ No newline at end of file
diff --git a/fftools/textformat/tf_flat.c b/fftools/textformat/tf_flat.c
new file mode 100644
index 0000000000..6971593c77
--- /dev/null
+++ b/fftools/textformat/tf_flat.c
@@ -0,0 +1,174 @@
+/*
+ * Copyright (c) The FFmpeg developers
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <limits.h>
+#include <stdarg.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "avtextformat.h"
+#include <libavutil/mem.h>
+#include <libavutil/avassert.h>
+#include <libavutil/bprint.h>
+#include <libavutil/error.h>
+#include <libavutil/macros.h>
+#include <libavutil/opt.h>
+
+#define writer_w8(wctx_, b_) (wctx_)->writer->writer->writer_w8((wctx_)->writer, b_)
+#define writer_put_str(wctx_, str_) (wctx_)->writer->writer->writer_put_str((wctx_)->writer, str_)
+#define writer_printf(wctx_, fmt_, ...) (wctx_)->writer->writer->writer_printf((wctx_)->writer, fmt_, __VA_ARGS__)
+
+#define DEFINE_FORMATTER_CLASS(name) \
+static const char *name##_get_name(void *ctx) \
+{ \
+ return #name ; \
+} \
+static const AVClass name##_class = { \
+ .class_name = #name, \
+ .item_name = name##_get_name, \
+ .option = name##_options \
+}
+
+
+/* Flat output */
+
+typedef struct FlatContext {
+ const AVClass *class;
+ const char *sep_str;
+ char sep;
+ int hierarchical;
+} FlatContext;
+
+#undef OFFSET
+#define OFFSET(x) offsetof(FlatContext, x)
+
+static const AVOption flat_options[]= {
+ {"sep_char", "set separator", OFFSET(sep_str), AV_OPT_TYPE_STRING, {.str="."}, 0, 0 },
+ {"s", "set separator", OFFSET(sep_str), AV_OPT_TYPE_STRING, {.str="."}, 0, 0 },
+ {"hierarchical", "specify if the section specification should be hierarchical", OFFSET(hierarchical), AV_OPT_TYPE_BOOL, {.i64=1}, 0, 1 },
+ {"h", "specify if the section specification should be hierarchical", OFFSET(hierarchical), AV_OPT_TYPE_BOOL, {.i64=1}, 0, 1 },
+ {NULL},
+};
+
+DEFINE_FORMATTER_CLASS(flat);
+
+static av_cold int flat_init(AVTextFormatContext *wctx)
+{
+ FlatContext *flat = wctx->priv;
+
+ if (strlen(flat->sep_str) != 1) {
+ av_log(wctx, AV_LOG_ERROR, "Item separator '%s' specified, but must contain a single character\n",
+ flat->sep_str);
+ return AVERROR(EINVAL);
+ }
+ flat->sep = flat->sep_str[0];
+
+ return 0;
+}
+
+static const char *flat_escape_key_str(AVBPrint *dst, const char *src, const char sep)
+{
+ const char *p;
+
+ for (p = src; *p; p++) {
+ if (!((*p >= '0' && *p <= '9') ||
+ (*p >= 'a' && *p <= 'z') ||
+ (*p >= 'A' && *p <= 'Z')))
+ av_bprint_chars(dst, '_', 1);
+ else
+ av_bprint_chars(dst, *p, 1);
+ }
+ return dst->str;
+}
+
+static const char *flat_escape_value_str(AVBPrint *dst, const char *src)
+{
+ const char *p;
+
+ for (p = src; *p; p++) {
+ switch (*p) {
+ case '\n': av_bprintf(dst, "%s", "\\n"); break;
+ case '\r': av_bprintf(dst, "%s", "\\r"); break;
+ case '\\': av_bprintf(dst, "%s", "\\\\"); break;
+ case '"': av_bprintf(dst, "%s", "\\\""); break;
+ case '`': av_bprintf(dst, "%s", "\\`"); break;
+ case '$': av_bprintf(dst, "%s", "\\$"); break;
+ default: av_bprint_chars(dst, *p, 1); break;
+ }
+ }
+ return dst->str;
+}
+
+static void flat_print_section_header(AVTextFormatContext *wctx, const void *data)
+{
+ FlatContext *flat = wctx->priv;
+ AVBPrint *buf = &wctx->section_pbuf[wctx->level];
+ const struct AVTextFormatSection *section = wctx->section[wctx->level];
+ const struct AVTextFormatSection *parent_section = wctx->level ?
+ wctx->section[wctx->level-1] : NULL;
+
+ /* build section header */
+ av_bprint_clear(buf);
+ if (!parent_section)
+ return;
+ av_bprintf(buf, "%s", wctx->section_pbuf[wctx->level-1].str);
+
+ if (flat->hierarchical ||
+ !(section->flags & (AV_TEXTFORMAT_SECTION_FLAG_IS_ARRAY|AV_TEXTFORMAT_SECTION_FLAG_IS_WRAPPER))) {
+ av_bprintf(buf, "%s%s", wctx->section[wctx->level]->name, flat->sep_str);
+
+ if (parent_section->flags & AV_TEXTFORMAT_SECTION_FLAG_IS_ARRAY) {
+ int n = parent_section->flags & AV_TEXTFORMAT_SECTION_FLAG_NUMBERING_BY_TYPE ?
+ wctx->nb_item_type[wctx->level-1][section->id] :
+ wctx->nb_item[wctx->level-1];
+ av_bprintf(buf, "%d%s", n, flat->sep_str);
+ }
+ }
+}
+
+static void flat_print_int(AVTextFormatContext *wctx, const char *key, int64_t value)
+{
+ writer_printf(wctx, "%s%s=%"PRId64"\n", wctx->section_pbuf[wctx->level].str, key, value);
+}
+
+static void flat_print_str(AVTextFormatContext *wctx, const char *key, const char *value)
+{
+ FlatContext *flat = wctx->priv;
+ AVBPrint buf;
+
+ writer_put_str(wctx, wctx->section_pbuf[wctx->level].str);
+ av_bprint_init(&buf, 1, AV_BPRINT_SIZE_UNLIMITED);
+ writer_printf(wctx, "%s=", flat_escape_key_str(&buf, key, flat->sep));
+ av_bprint_clear(&buf);
+ writer_printf(wctx, "\"%s\"\n", flat_escape_value_str(&buf, value));
+ av_bprint_finalize(&buf, NULL);
+}
+
+const AVTextFormatter avtextformatter_flat = {
+ .name = "flat",
+ .priv_size = sizeof(FlatContext),
+ .init = flat_init,
+ .print_section_header = flat_print_section_header,
+ .print_integer = flat_print_int,
+ .print_string = flat_print_str,
+ .flags = AV_TEXTFORMAT_FLAG_SUPPORTS_OPTIONAL_FIELDS|AV_TEXTFORMAT_FLAG_SUPPORTS_MIXED_ARRAY_CONTENT,
+ .priv_class = &flat_class,
+};
diff --git a/fftools/textformat/tf_ini.c b/fftools/textformat/tf_ini.c
new file mode 100644
index 0000000000..1f4216069f
--- /dev/null
+++ b/fftools/textformat/tf_ini.c
@@ -0,0 +1,160 @@
+/*
+ * Copyright (c) The FFmpeg developers
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <limits.h>
+#include <stdarg.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "avtextformat.h"
+#include <libavutil/mem.h>
+#include <libavutil/avassert.h>
+#include <libavutil/bprint.h>
+#include <libavutil/opt.h>
+
+#define writer_w8(wctx_, b_) (wctx_)->writer->writer->writer_w8((wctx_)->writer, b_)
+#define writer_put_str(wctx_, str_) (wctx_)->writer->writer->writer_put_str((wctx_)->writer, str_)
+#define writer_printf(wctx_, fmt_, ...) (wctx_)->writer->writer->writer_printf((wctx_)->writer, fmt_, __VA_ARGS__)
+
+#define DEFINE_FORMATTER_CLASS(name) \
+static const char *name##_get_name(void *ctx) \
+{ \
+ return #name ; \
+} \
+static const AVClass name##_class = { \
+ .class_name = #name, \
+ .item_name = name##_get_name, \
+ .option = name##_options \
+}
+
+/* Default output */
+
+typedef struct DefaultContext {
+ const AVClass *class;
+ int nokey;
+ int noprint_wrappers;
+ int nested_section[SECTION_MAX_NB_LEVELS];
+} DefaultContext;
+
+/* INI format output */
+
+typedef struct INIContext {
+ const AVClass *class;
+ int hierarchical;
+} INIContext;
+
+#undef OFFSET
+#define OFFSET(x) offsetof(INIContext, x)
+
+static const AVOption ini_options[] = {
+ {"hierarchical", "specify if the section specification should be hierarchical", OFFSET(hierarchical), AV_OPT_TYPE_BOOL, {.i64=1}, 0, 1 },
+ {"h", "specify if the section specification should be hierarchical", OFFSET(hierarchical), AV_OPT_TYPE_BOOL, {.i64=1}, 0, 1 },
+ {NULL},
+};
+
+DEFINE_FORMATTER_CLASS(ini);
+
+static char *ini_escape_str(AVBPrint *dst, const char *src)
+{
+ int i = 0;
+ char c = 0;
+
+ while (c = src[i++]) {
+ switch (c) {
+ case '\b': av_bprintf(dst, "%s", "\\b"); break;
+ case '\f': av_bprintf(dst, "%s", "\\f"); break;
+ case '\n': av_bprintf(dst, "%s", "\\n"); break;
+ case '\r': av_bprintf(dst, "%s", "\\r"); break;
+ case '\t': av_bprintf(dst, "%s", "\\t"); break;
+ case '\\':
+ case '#' :
+ case '=' :
+ case ':' : av_bprint_chars(dst, '\\', 1);
+ default:
+ if ((unsigned char)c < 32)
+ av_bprintf(dst, "\\x00%02x", c & 0xff);
+ else
+ av_bprint_chars(dst, c, 1);
+ break;
+ }
+ }
+ return dst->str;
+}
+
+static void ini_print_section_header(AVTextFormatContext *wctx, const void *data)
+{
+ INIContext *ini = wctx->priv;
+ AVBPrint *buf = &wctx->section_pbuf[wctx->level];
+ const struct AVTextFormatSection *section = wctx->section[wctx->level];
+ const struct AVTextFormatSection *parent_section = wctx->level ?
+ wctx->section[wctx->level-1] : NULL;
+
+ av_bprint_clear(buf);
+ if (!parent_section) {
+ writer_put_str(wctx, "# ffprobe output\n\n");
+ return;
+ }
+
+ if (wctx->nb_item[wctx->level-1])
+ writer_w8(wctx, '\n');
+
+ av_bprintf(buf, "%s", wctx->section_pbuf[wctx->level-1].str);
+ if (ini->hierarchical ||
+ !(section->flags & (AV_TEXTFORMAT_SECTION_FLAG_IS_ARRAY|AV_TEXTFORMAT_SECTION_FLAG_IS_WRAPPER))) {
+ av_bprintf(buf, "%s%s", buf->str[0] ? "." : "", wctx->section[wctx->level]->name);
+
+ if (parent_section->flags & AV_TEXTFORMAT_SECTION_FLAG_IS_ARRAY) {
+ int n = parent_section->flags & AV_TEXTFORMAT_SECTION_FLAG_NUMBERING_BY_TYPE ?
+ wctx->nb_item_type[wctx->level-1][section->id] :
+ wctx->nb_item[wctx->level-1];
+ av_bprintf(buf, ".%d", n);
+ }
+ }
+
+ if (!(section->flags & (AV_TEXTFORMAT_SECTION_FLAG_IS_ARRAY|AV_TEXTFORMAT_SECTION_FLAG_IS_WRAPPER)))
+ writer_printf(wctx, "[%s]\n", buf->str);
+}
+
+static void ini_print_str(AVTextFormatContext *wctx, const char *key, const char *value)
+{
+ AVBPrint buf;
+
+ av_bprint_init(&buf, 1, AV_BPRINT_SIZE_UNLIMITED);
+ writer_printf(wctx, "%s=", ini_escape_str(&buf, key));
+ av_bprint_clear(&buf);
+ writer_printf(wctx, "%s\n", ini_escape_str(&buf, value));
+ av_bprint_finalize(&buf, NULL);
+}
+
+static void ini_print_int(AVTextFormatContext *wctx, const char *key, int64_t value)
+{
+ writer_printf(wctx, "%s=%"PRId64"\n", key, value);
+}
+
+const AVTextFormatter avtextformatter_ini = {
+ .name = "ini",
+ .priv_size = sizeof(INIContext),
+ .print_section_header = ini_print_section_header,
+ .print_integer = ini_print_int,
+ .print_string = ini_print_str,
+ .flags = AV_TEXTFORMAT_FLAG_SUPPORTS_OPTIONAL_FIELDS|AV_TEXTFORMAT_FLAG_SUPPORTS_MIXED_ARRAY_CONTENT,
+ .priv_class = &ini_class,
+};
diff --git a/fftools/textformat/tf_json.c b/fftools/textformat/tf_json.c
new file mode 100644
index 0000000000..de27a36e7e
--- /dev/null
+++ b/fftools/textformat/tf_json.c
@@ -0,0 +1,215 @@
+/*
+ * Copyright (c) The FFmpeg developers
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <limits.h>
+#include <stdarg.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "avtextformat.h"
+#include <libavutil/mem.h>
+#include <libavutil/avassert.h>
+#include <libavutil/bprint.h>
+#include <libavutil/opt.h>
+
+#define writer_w8(wctx_, b_) (wctx_)->writer->writer->writer_w8((wctx_)->writer, b_)
+#define writer_put_str(wctx_, str_) (wctx_)->writer->writer->writer_put_str((wctx_)->writer, str_)
+#define writer_printf(wctx_, fmt_, ...) (wctx_)->writer->writer->writer_printf((wctx_)->writer, fmt_, __VA_ARGS__)
+
+#define DEFINE_FORMATTER_CLASS(name) \
+static const char *name##_get_name(void *ctx) \
+{ \
+ return #name ; \
+} \
+static const AVClass name##_class = { \
+ .class_name = #name, \
+ .item_name = name##_get_name, \
+ .option = name##_options \
+}
+
+
+/* JSON output */
+
+typedef struct JSONContext {
+ const AVClass *class;
+ int indent_level;
+ int compact;
+ const char *item_sep, *item_start_end;
+} JSONContext;
+
+#undef OFFSET
+#define OFFSET(x) offsetof(JSONContext, x)
+
+static const AVOption json_options[]= {
+ { "compact", "enable compact output", OFFSET(compact), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1 },
+ { "c", "enable compact output", OFFSET(compact), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1 },
+ { NULL }
+};
+
+DEFINE_FORMATTER_CLASS(json);
+
+static av_cold int json_init(AVTextFormatContext *wctx)
+{
+ JSONContext *json = wctx->priv;
+
+ json->item_sep = json->compact ? ", " : ",\n";
+ json->item_start_end = json->compact ? " " : "\n";
+
+ return 0;
+}
+
+static const char *json_escape_str(AVBPrint *dst, const char *src, void *log_ctx)
+{
+ static const char json_escape[] = {'"', '\\', '\b', '\f', '\n', '\r', '\t', 0};
+ static const char json_subst[] = {'"', '\\', 'b', 'f', 'n', 'r', 't', 0};
+ const char *p;
+
+ for (p = src; *p; p++) {
+ char *s = strchr(json_escape, *p);
+ if (s) {
+ av_bprint_chars(dst, '\\', 1);
+ av_bprint_chars(dst, json_subst[s - json_escape], 1);
+ } else if ((unsigned char)*p < 32) {
+ av_bprintf(dst, "\\u00%02x", *p & 0xff);
+ } else {
+ av_bprint_chars(dst, *p, 1);
+ }
+ }
+ return dst->str;
+}
+
+#define JSON_INDENT() writer_printf(wctx, "%*c", json->indent_level * 4, ' ')
+
+static void json_print_section_header(AVTextFormatContext *wctx, const void *data)
+{
+ JSONContext *json = wctx->priv;
+ AVBPrint buf;
+ const struct AVTextFormatSection *section = wctx->section[wctx->level];
+ const struct AVTextFormatSection *parent_section = wctx->level ?
+ wctx->section[wctx->level-1] : NULL;
+
+ if (wctx->level && wctx->nb_item[wctx->level-1])
+ writer_put_str(wctx, ",\n");
+
+ if (section->flags & AV_TEXTFORMAT_SECTION_FLAG_IS_WRAPPER) {
+ writer_put_str(wctx, "{\n");
+ json->indent_level++;
+ } else {
+ av_bprint_init(&buf, 1, AV_BPRINT_SIZE_UNLIMITED);
+ json_escape_str(&buf, section->name, wctx);
+ JSON_INDENT();
+
+ json->indent_level++;
+ if (section->flags & AV_TEXTFORMAT_SECTION_FLAG_IS_ARRAY) {
+ writer_printf(wctx, "\"%s\": [\n", buf.str);
+ } else if (parent_section && !(parent_section->flags & AV_TEXTFORMAT_SECTION_FLAG_IS_ARRAY)) {
+ writer_printf(wctx, "\"%s\": {%s", buf.str, json->item_start_end);
+ } else {
+ writer_printf(wctx, "{%s", json->item_start_end);
+
+ /* this is required so the parser can distinguish between packets and frames */
+ if (parent_section && parent_section->flags & AV_TEXTFORMAT_SECTION_FLAG_NUMBERING_BY_TYPE) {
+ if (!json->compact)
+ JSON_INDENT();
+ writer_printf(wctx, "\"type\": \"%s\"", section->name);
+ wctx->nb_item[wctx->level]++;
+ }
+ }
+ av_bprint_finalize(&buf, NULL);
+ }
+}
+
+static void json_print_section_footer(AVTextFormatContext *wctx)
+{
+ JSONContext *json = wctx->priv;
+ const struct AVTextFormatSection *section = wctx->section[wctx->level];
+
+ if (wctx->level == 0) {
+ json->indent_level--;
+ writer_put_str(wctx, "\n}\n");
+ } else if (section->flags & AV_TEXTFORMAT_SECTION_FLAG_IS_ARRAY) {
+ writer_w8(wctx, '\n');
+ json->indent_level--;
+ JSON_INDENT();
+ writer_w8(wctx, ']');
+ } else {
+ writer_put_str(wctx, json->item_start_end);
+ json->indent_level--;
+ if (!json->compact)
+ JSON_INDENT();
+ writer_w8(wctx, '}');
+ }
+}
+
+static inline void json_print_item_str(AVTextFormatContext *wctx,
+ const char *key, const char *value)
+{
+ AVBPrint buf;
+
+ av_bprint_init(&buf, 1, AV_BPRINT_SIZE_UNLIMITED);
+ writer_printf(wctx, "\"%s\":", json_escape_str(&buf, key, wctx));
+ av_bprint_clear(&buf);
+ writer_printf(wctx, " \"%s\"", json_escape_str(&buf, value, wctx));
+ av_bprint_finalize(&buf, NULL);
+}
+
+static void json_print_str(AVTextFormatContext *wctx, const char *key, const char *value)
+{
+ JSONContext *json = wctx->priv;
+ const struct AVTextFormatSection *parent_section = wctx->level ?
+ wctx->section[wctx->level-1] : NULL;
+
+ if (wctx->nb_item[wctx->level] || (parent_section && parent_section->flags & AV_TEXTFORMAT_SECTION_FLAG_NUMBERING_BY_TYPE))
+ writer_put_str(wctx, json->item_sep);
+ if (!json->compact)
+ JSON_INDENT();
+ json_print_item_str(wctx, key, value);
+}
+
+static void json_print_int(AVTextFormatContext *wctx, const char *key, int64_t value)
+{
+ JSONContext *json = wctx->priv;
+ const struct AVTextFormatSection *parent_section = wctx->level ?
+ wctx->section[wctx->level-1] : NULL;
+ AVBPrint buf;
+
+ if (wctx->nb_item[wctx->level] || (parent_section && parent_section->flags & AV_TEXTFORMAT_SECTION_FLAG_NUMBERING_BY_TYPE))
+ writer_put_str(wctx, json->item_sep);
+ if (!json->compact)
+ JSON_INDENT();
+
+ av_bprint_init(&buf, 1, AV_BPRINT_SIZE_UNLIMITED);
+ writer_printf(wctx, "\"%s\": %"PRId64, json_escape_str(&buf, key, wctx), value);
+ av_bprint_finalize(&buf, NULL);
+}
+
+const AVTextFormatter avtextformatter_json = {
+ .name = "json",
+ .priv_size = sizeof(JSONContext),
+ .init = json_init,
+ .print_section_header = json_print_section_header,
+ .print_section_footer = json_print_section_footer,
+ .print_integer = json_print_int,
+ .print_string = json_print_str,
+ .flags = AV_TEXTFORMAT_FLAG_SUPPORTS_MIXED_ARRAY_CONTENT,
+ .priv_class = &json_class,
+};
+
diff --git a/fftools/textformat/tf_xml.c b/fftools/textformat/tf_xml.c
new file mode 100644
index 0000000000..57171c4cb3
--- /dev/null
+++ b/fftools/textformat/tf_xml.c
@@ -0,0 +1,221 @@
+/*
+ * Copyright (c) The FFmpeg developers
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <limits.h>
+#include <stdarg.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "avtextformat.h"
+#include <libavutil/mem.h>
+#include <libavutil/avassert.h>
+#include <libavutil/bprint.h>
+#include <libavutil/error.h>
+#include <libavutil/macros.h>
+#include <libavutil/opt.h>
+
+#define writer_w8(wctx_, b_) (wctx_)->writer->writer->writer_w8((wctx_)->writer, b_)
+#define writer_put_str(wctx_, str_) (wctx_)->writer->writer->writer_put_str((wctx_)->writer, str_)
+#define writer_printf(wctx_, fmt_, ...) (wctx_)->writer->writer->writer_printf((wctx_)->writer, fmt_, __VA_ARGS__)
+
+#define DEFINE_FORMATTER_CLASS(name) \
+static const char *name##_get_name(void *ctx) \
+{ \
+ return #name ; \
+} \
+static const AVClass name##_class = { \
+ .class_name = #name, \
+ .item_name = name##_get_name, \
+ .option = name##_options \
+}
+
+/* XML output */
+
+typedef struct XMLContext {
+ const AVClass *class;
+ int within_tag;
+ int indent_level;
+ int fully_qualified;
+ int xsd_strict;
+} XMLContext;
+
+#undef OFFSET
+#define OFFSET(x) offsetof(XMLContext, x)
+
+static const AVOption xml_options[] = {
+ {"fully_qualified", "specify if the output should be fully qualified", OFFSET(fully_qualified), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1 },
+ {"q", "specify if the output should be fully qualified", OFFSET(fully_qualified), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1 },
+ {"xsd_strict", "ensure that the output is XSD compliant", OFFSET(xsd_strict), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1 },
+ {"x", "ensure that the output is XSD compliant", OFFSET(xsd_strict), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1 },
+ {NULL},
+};
+
+DEFINE_FORMATTER_CLASS(xml);
+
+static av_cold int xml_init(AVTextFormatContext *wctx)
+{
+ XMLContext *xml = wctx->priv;
+
+ if (xml->xsd_strict) {
+ xml->fully_qualified = 1;
+#define CHECK_COMPLIANCE(opt, opt_name) \
+ if (opt) { \
+ av_log(wctx, AV_LOG_ERROR, \
+ "XSD-compliant output selected but option '%s' was selected, XML output may be non-compliant.\n" \
+ "You need to disable such option with '-no%s'\n", opt_name, opt_name); \
+ return AVERROR(EINVAL); \
+ }
+ ////CHECK_COMPLIANCE(show_private_data, "private");
+ CHECK_COMPLIANCE(wctx->show_value_unit, "unit");
+ CHECK_COMPLIANCE(wctx->use_value_prefix, "prefix");
+ }
+
+ return 0;
+}
+
+#define XML_INDENT() writer_printf(wctx, "%*c", xml->indent_level * 4, ' ')
+
+static void xml_print_section_header(AVTextFormatContext *wctx, const void *data)
+{
+ XMLContext *xml = wctx->priv;
+ const struct AVTextFormatSection *section = wctx->section[wctx->level];
+ const struct AVTextFormatSection *parent_section = wctx->level ?
+ wctx->section[wctx->level-1] : NULL;
+
+ if (wctx->level == 0) {
+ const char *qual = " xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" "
+ "xmlns:ffprobe=\"http://www.ffmpeg.org/schema/ffprobe\" "
+ "xsi:schemaLocation=\"http://www.ffmpeg.org/schema/ffprobe ffprobe.xsd\"";
+
+ writer_put_str(wctx, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
+ writer_printf(wctx, "<%sffprobe%s>\n",
+ xml->fully_qualified ? "ffprobe:" : "",
+ xml->fully_qualified ? qual : "");
+ return;
+ }
+
+ if (xml->within_tag) {
+ xml->within_tag = 0;
+ writer_put_str(wctx, ">\n");
+ }
+
+ if (parent_section && (parent_section->flags & AV_TEXTFORMAT_SECTION_FLAG_IS_WRAPPER) &&
+ wctx->level && wctx->nb_item[wctx->level-1])
+ writer_w8(wctx, '\n');
+ xml->indent_level++;
+
+ if (section->flags & (AV_TEXTFORMAT_SECTION_FLAG_IS_ARRAY|AV_TEXTFORMAT_SECTION_FLAG_HAS_VARIABLE_FIELDS)) {
+ XML_INDENT(); writer_printf(wctx, "<%s", section->name);
+
+ if (section->flags & AV_TEXTFORMAT_SECTION_FLAG_HAS_TYPE) {
+ AVBPrint buf;
+ av_bprint_init(&buf, 1, AV_BPRINT_SIZE_UNLIMITED);
+ av_bprint_escape(&buf, section->get_type(data), NULL,
+ AV_ESCAPE_MODE_XML, AV_ESCAPE_FLAG_XML_DOUBLE_QUOTES);
+ writer_printf(wctx, " type=\"%s\"", buf.str);
+ }
+ writer_printf(wctx, ">\n", section->name);
+ } else {
+ XML_INDENT(); writer_printf(wctx, "<%s ", section->name);
+ xml->within_tag = 1;
+ }
+}
+
+static void xml_print_section_footer(AVTextFormatContext *wctx)
+{
+ XMLContext *xml = wctx->priv;
+ const struct AVTextFormatSection *section = wctx->section[wctx->level];
+
+ if (wctx->level == 0) {
+ writer_printf(wctx, "</%sffprobe>\n", xml->fully_qualified ? "ffprobe:" : "");
+ } else if (xml->within_tag) {
+ xml->within_tag = 0;
+ writer_put_str(wctx, "/>\n");
+ xml->indent_level--;
+ } else {
+ XML_INDENT(); writer_printf(wctx, "</%s>\n", section->name);
+ xml->indent_level--;
+ }
+}
+
+static void xml_print_value(AVTextFormatContext *wctx, const char *key,
+ const char *str, int64_t num, const int is_int)
+{
+ AVBPrint buf;
+ XMLContext *xml = wctx->priv;
+ const struct AVTextFormatSection *section = wctx->section[wctx->level];
+
+ av_bprint_init(&buf, 1, AV_BPRINT_SIZE_UNLIMITED);
+
+ if (section->flags & AV_TEXTFORMAT_SECTION_FLAG_HAS_VARIABLE_FIELDS) {
+ xml->indent_level++;
+ XML_INDENT();
+ av_bprint_escape(&buf, key, NULL,
+ AV_ESCAPE_MODE_XML, AV_ESCAPE_FLAG_XML_DOUBLE_QUOTES);
+ writer_printf(wctx, "<%s key=\"%s\"",
+ section->element_name, buf.str);
+ av_bprint_clear(&buf);
+
+ if (is_int) {
+ writer_printf(wctx, " value=\"%"PRId64"\"/>\n", num);
+ } else {
+ av_bprint_escape(&buf, str, NULL,
+ AV_ESCAPE_MODE_XML, AV_ESCAPE_FLAG_XML_DOUBLE_QUOTES);
+ writer_printf(wctx, " value=\"%s\"/>\n", buf.str);
+ }
+ xml->indent_level--;
+ } else {
+ if (wctx->nb_item[wctx->level])
+ writer_w8(wctx, ' ');
+
+ if (is_int) {
+ writer_printf(wctx, "%s=\"%"PRId64"\"", key, num);
+ } else {
+ av_bprint_escape(&buf, str, NULL,
+ AV_ESCAPE_MODE_XML, AV_ESCAPE_FLAG_XML_DOUBLE_QUOTES);
+ writer_printf(wctx, "%s=\"%s\"", key, buf.str);
+ }
+ }
+
+ av_bprint_finalize(&buf, NULL);
+}
+
+static inline void xml_print_str(AVTextFormatContext *wctx, const char *key, const char *value) {
+ xml_print_value(wctx, key, value, 0, 0);
+}
+
+static void xml_print_int(AVTextFormatContext *wctx, const char *key, int64_t value)
+{
+ xml_print_value(wctx, key, NULL, value, 1);
+}
+
+const AVTextFormatter avtextformatter_xml = {
+ .name = "xml",
+ .priv_size = sizeof(XMLContext),
+ .init = xml_init,
+ .print_section_header = xml_print_section_header,
+ .print_section_footer = xml_print_section_footer,
+ .print_integer = xml_print_int,
+ .print_string = xml_print_str,
+ .flags = AV_TEXTFORMAT_FLAG_SUPPORTS_MIXED_ARRAY_CONTENT,
+ .priv_class = &xml_class,
+};
+
diff --git a/fftools/textformat/tw_avio.c b/fftools/textformat/tw_avio.c
new file mode 100644
index 0000000000..d335d35a56
--- /dev/null
+++ b/fftools/textformat/tw_avio.c
@@ -0,0 +1,129 @@
+/*
+ * Copyright (c) The FFmpeg developers
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <limits.h>
+#include <stdarg.h>
+
+#include "avtextwriters.h"
+#include "libavutil/opt.h"
+
+/* AVIO Writer */
+
+# define WRITER_NAME "aviowriter"
+
+typedef struct IOWriterContext {
+ const AVClass *class;
+ AVIOContext *avio_context;
+ int close_on_uninit;
+} IOWriterContext;
+
+static const char *iowriter_get_name(void *ctx)
+{
+ return WRITER_NAME;
+}
+
+static const AVClass iowriter_class = {
+ .class_name = WRITER_NAME,
+ .item_name = iowriter_get_name,
+};
+
+static av_cold void iowriter_uninit(AVTextWriterContext *wctx)
+{
+ IOWriterContext *ctx = wctx->priv;
+
+ if (ctx->close_on_uninit && ctx->avio_context) {
+ avio_flush(ctx->avio_context);
+ avio_close(ctx->avio_context);
+ }
+}
+
+static void io_w8(AVTextWriterContext *wctx, int b)
+{
+ IOWriterContext *ctx = wctx->priv;
+ avio_w8(ctx->avio_context, b);
+}
+
+static void io_put_str(AVTextWriterContext *wctx, const char *str)
+{
+ IOWriterContext *ctx = wctx->priv;
+ avio_write(ctx->avio_context, str, strlen(str));
+}
+
+static void io_printf(AVTextWriterContext *wctx, const char *fmt, ...)
+{
+ IOWriterContext *ctx = wctx->priv;
+ va_list ap;
+
+ va_start(ap, fmt);
+ avio_vprintf(ctx->avio_context, fmt, ap);
+ va_end(ap);
+}
+
+
+const AVTextWriter avtextwriter_avio = {
+ .name = WRITER_NAME,
+ .priv_size = sizeof(IOWriterContext),
+ .uninit = iowriter_uninit,
+ .priv_class = &iowriter_class,
+ .writer_put_str = io_put_str,
+ .writer_printf = io_printf,
+ .writer_w8 = io_w8
+};
+
+int avtextwriter_create_file(AVTextWriterContext **pwctx, const char *output_filename, int close_on_uninit)
+{
+ IOWriterContext *ctx;
+ int ret;
+
+
+ ret = avtextwriter_context_open(pwctx, &avtextwriter_avio);
+ if (ret < 0)
+ return ret;
+
+ ctx = (*pwctx)->priv;
+
+ if ((ret = avio_open(&ctx->avio_context, output_filename, AVIO_FLAG_WRITE)) < 0) {
+ av_log(ctx, AV_LOG_ERROR,
+ "Failed to open output '%s' with error: %s\n", output_filename, av_err2str(ret));
+ avtextwriter_context_close(pwctx);
+ return ret;
+ }
+
+ ctx->close_on_uninit = close_on_uninit;
+
+ return ret;
+}
+
+
+int avtextwriter_create_avio(AVTextWriterContext **pwctx, AVIOContext *avio_ctx, int close_on_uninit)
+{
+ IOWriterContext *ctx;
+ int ret;
+
+ ret = avtextwriter_context_open(pwctx, &avtextwriter_avio);
+ if (ret < 0)
+ return ret;
+
+ ctx = (*pwctx)->priv;
+ ctx->avio_context = avio_ctx;
+ ctx->close_on_uninit = close_on_uninit;
+
+ return ret;
+}
diff --git a/fftools/textformat/tw_buffer.c b/fftools/textformat/tw_buffer.c
new file mode 100644
index 0000000000..f8b38414a6
--- /dev/null
+++ b/fftools/textformat/tw_buffer.c
@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) The FFmpeg developers
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <limits.h>
+#include <stdarg.h>
+
+#include "avtextwriters.h"
+#include "libavutil/opt.h"
+#include "libavutil/bprint.h"
+
+/* Buffer Writer */
+
+# define WRITER_NAME "bufferwriter"
+
+typedef struct BufferWriterContext {
+ const AVClass *class;
+ AVBPrint *buffer;
+} BufferWriterContext;
+
+static const char *bufferwriter_get_name(void *ctx)
+{
+ return WRITER_NAME;
+}
+
+static const AVClass bufferwriter_class = {
+ .class_name = WRITER_NAME,
+ .item_name = bufferwriter_get_name,
+};
+
+static void buffer_w8(AVTextWriterContext *wctx, int b)
+{
+ BufferWriterContext *ctx = wctx->priv;
+ av_bprintf(ctx->buffer, "%c", b);
+}
+
+static void buffer_put_str(AVTextWriterContext *wctx, const char *str)
+{
+ BufferWriterContext *ctx = wctx->priv;
+ av_bprintf(ctx->buffer, "%s", str);
+}
+
+static void buffer_printf(AVTextWriterContext *wctx, const char *fmt, ...)
+{
+ BufferWriterContext *ctx = wctx->priv;
+
+ va_list vargs;
+ va_start(vargs, fmt);
+ av_vbprintf(ctx->buffer, fmt, vargs);
+ va_end(vargs);
+}
+
+
+const AVTextWriter avtextwriter_buffer = {
+ .name = WRITER_NAME,
+ .priv_size = sizeof(BufferWriterContext),
+ .priv_class = &bufferwriter_class,
+ .writer_put_str = buffer_put_str,
+ .writer_printf = buffer_printf,
+ .writer_w8 = buffer_w8
+};
+
+int avtextwriter_create_buffer(AVTextWriterContext **pwctx, AVBPrint *buffer)
+{
+ BufferWriterContext *ctx;
+ int ret;
+
+ ret = avtextwriter_context_open(pwctx, &avtextwriter_buffer);
+ if (ret < 0)
+ return ret;
+
+ ctx = (*pwctx)->priv;
+ ctx->buffer = buffer;
+
+ return ret;
+}
diff --git a/fftools/textformat/tw_stdout.c b/fftools/textformat/tw_stdout.c
new file mode 100644
index 0000000000..23de6f671f
--- /dev/null
+++ b/fftools/textformat/tw_stdout.c
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) The FFmpeg developers
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <stdarg.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "avtextwriters.h"
+#include "libavutil/opt.h"
+
+/* STDOUT Writer */
+
+# define WRITER_NAME "stdoutwriter"
+
+typedef struct StdOutWriterContext {
+ const AVClass *class;
+} StdOutWriterContext;
+
+static const char *stdoutwriter_get_name(void *ctx)
+{
+ return WRITER_NAME;
+}
+
+static const AVClass stdoutwriter_class = {
+ .class_name = WRITER_NAME,
+ .item_name = stdoutwriter_get_name,
+};
+
+static inline void stdout_w8(AVTextWriterContext *wctx, int b)
+{
+ printf("%c", b);
+}
+
+static inline void stdout_put_str(AVTextWriterContext *wctx, const char *str)
+{
+ printf("%s", str);
+}
+
+static inline void stdout_printf(AVTextWriterContext *wctx, const char *fmt, ...)
+{
+ va_list ap;
+
+ va_start(ap, fmt);
+ vprintf(fmt, ap);
+ va_end(ap);
+}
+
+
+static const AVTextWriter avtextwriter_stdout = {
+ .name = WRITER_NAME,
+ .priv_size = sizeof(StdOutWriterContext),
+ .priv_class = &stdoutwriter_class,
+ .writer_put_str = stdout_put_str,
+ .writer_printf = stdout_printf,
+ .writer_w8 = stdout_w8
+};
+
+int avtextwriter_create_stdout(AVTextWriterContext **pwctx)
+{
+ int ret;
+
+ ret = avtextwriter_context_open(pwctx, &avtextwriter_stdout);
+
+ return ret;
+}
--
ffmpeg-codebot
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 108+ messages in thread
* [FFmpeg-devel] [PATCH v6 2/8] fftools/ffprobe: Change to use textformat api
2025-03-08 20:16 ` [FFmpeg-devel] [PATCH v6 0/8] print_graphs: Complete Filtergraph Printing ffmpegagent
2025-03-08 20:16 ` [FFmpeg-devel] [PATCH v6 1/8] fftools/textformat: Extract and generalize textformat api from ffprobe.c softworkz
@ 2025-03-08 20:16 ` softworkz
2025-03-08 20:16 ` [FFmpeg-devel] [PATCH v6 3/8] fftools/ffprobe: Rename writer_print_section_* and WriterContext softworkz
` (7 subsequent siblings)
9 siblings, 0 replies; 108+ messages in thread
From: softworkz @ 2025-03-08 20:16 UTC (permalink / raw)
To: ffmpeg-devel; +Cc: softworkz
From: softworkz <softworkz@hotmail.com>
Signed-off-by: softworkz <softworkz@hotmail.com>
---
fftools/Makefile | 12 +
fftools/ffprobe.c | 1849 ++++-----------------------------------------
2 files changed, 142 insertions(+), 1719 deletions(-)
diff --git a/fftools/Makefile b/fftools/Makefile
index 4499799818..664b73b161 100644
--- a/fftools/Makefile
+++ b/fftools/Makefile
@@ -22,6 +22,18 @@ OBJS-ffmpeg += \
fftools/sync_queue.o \
fftools/thread_queue.o \
+OBJS-ffprobe += \
+ fftools/textformat/avtextformat.o \
+ fftools/textformat/tf_compact.o \
+ fftools/textformat/tf_default.o \
+ fftools/textformat/tf_flat.o \
+ fftools/textformat/tf_ini.o \
+ fftools/textformat/tf_json.o \
+ fftools/textformat/tf_xml.o \
+ fftools/textformat/tw_avio.o \
+ fftools/textformat/tw_buffer.o \
+ fftools/textformat/tw_stdout.o \
+
OBJS-ffplay += fftools/ffplay_renderer.o
define DOFFTOOL
diff --git a/fftools/ffprobe.c b/fftools/ffprobe.c
index 7341731d2f..f398057df7 100644
--- a/fftools/ffprobe.c
+++ b/fftools/ffprobe.c
@@ -40,7 +40,6 @@
#include "libavutil/channel_layout.h"
#include "libavutil/display.h"
#include "libavutil/film_grain_params.h"
-#include "libavutil/hash.h"
#include "libavutil/hdr_dynamic_metadata.h"
#include "libavutil/iamf.h"
#include "libavutil/mastering_display_metadata.h"
@@ -66,11 +65,17 @@
#include "libpostproc/postprocess.h"
#include "libpostproc/version.h"
#include "libavfilter/version.h"
+#include "textformat/avtextformat.h"
#include "cmdutils.h"
#include "opt_common.h"
#include "libavutil/thread.h"
+// TEMPORARY DEFINES
+#define writer_print_section_header(w, d, s) avtext_print_section_header(w, d, s)
+#define writer_print_section_footer(w) avtext_print_section_footer(w)
+#define WriterContext AVTextFormatContext
+
// attached as opaque_ref to packets/frames
typedef struct FrameData {
int64_t pkt_pos;
@@ -156,10 +161,7 @@ static int find_stream_info = 1;
/* section structure definition */
-#define SECTION_MAX_NB_CHILDREN 11
-
typedef enum {
- SECTION_ID_NONE = -1,
SECTION_ID_CHAPTER,
SECTION_ID_CHAPTER_TAGS,
SECTION_ID_CHAPTERS,
@@ -228,25 +230,6 @@ typedef enum {
SECTION_ID_SUBTITLE,
} SectionID;
-struct section {
- int id; ///< unique id identifying a section
- const char *name;
-
-#define SECTION_FLAG_IS_WRAPPER 1 ///< the section only contains other sections, but has no data at its own level
-#define SECTION_FLAG_IS_ARRAY 2 ///< the section contains an array of elements of the same type
-#define SECTION_FLAG_HAS_VARIABLE_FIELDS 4 ///< the section may contain a variable number of fields with variable keys.
- /// For these sections the element_name field is mandatory.
-#define SECTION_FLAG_HAS_TYPE 8 ///< the section contains a type to distinguish multiple nested elements
-
- int flags;
- const SectionID children_ids[SECTION_MAX_NB_CHILDREN+1]; ///< list of children section IDS, terminated by -1
- const char *element_name; ///< name of the contained element, if provided
- const char *unique_name; ///< unique section name, in case the name is ambiguous
- AVDictionary *entries_to_show;
- const char *(* get_type)(const void *data); ///< function returning a type if defined, must be defined when SECTION_FLAG_HAS_TYPE is defined
- int show_all_entries;
-};
-
static const char *get_packet_side_data_type(const void *data)
{
const AVPacketSideData *sd = (const AVPacketSideData *)data;
@@ -270,75 +253,75 @@ static const char *get_stream_group_type(const void *data)
return av_x_if_null(avformat_stream_group_name(stg->type), "unknown");
}
-static struct section sections[] = {
- [SECTION_ID_CHAPTERS] = { SECTION_ID_CHAPTERS, "chapters", SECTION_FLAG_IS_ARRAY, { SECTION_ID_CHAPTER, -1 } },
+static struct AVTextFormatSection sections[] = {
+ [SECTION_ID_CHAPTERS] = { SECTION_ID_CHAPTERS, "chapters", AV_TEXTFORMAT_SECTION_FLAG_IS_ARRAY, { SECTION_ID_CHAPTER, -1 } },
[SECTION_ID_CHAPTER] = { SECTION_ID_CHAPTER, "chapter", 0, { SECTION_ID_CHAPTER_TAGS, -1 } },
- [SECTION_ID_CHAPTER_TAGS] = { SECTION_ID_CHAPTER_TAGS, "tags", SECTION_FLAG_HAS_VARIABLE_FIELDS, { -1 }, .element_name = "tag", .unique_name = "chapter_tags" },
+ [SECTION_ID_CHAPTER_TAGS] = { SECTION_ID_CHAPTER_TAGS, "tags", AV_TEXTFORMAT_SECTION_FLAG_HAS_VARIABLE_FIELDS, { -1 }, .element_name = "tag", .unique_name = "chapter_tags" },
[SECTION_ID_ERROR] = { SECTION_ID_ERROR, "error", 0, { -1 } },
[SECTION_ID_FORMAT] = { SECTION_ID_FORMAT, "format", 0, { SECTION_ID_FORMAT_TAGS, -1 } },
- [SECTION_ID_FORMAT_TAGS] = { SECTION_ID_FORMAT_TAGS, "tags", SECTION_FLAG_HAS_VARIABLE_FIELDS, { -1 }, .element_name = "tag", .unique_name = "format_tags" },
- [SECTION_ID_FRAMES] = { SECTION_ID_FRAMES, "frames", SECTION_FLAG_IS_ARRAY, { SECTION_ID_FRAME, SECTION_ID_SUBTITLE, -1 } },
+ [SECTION_ID_FORMAT_TAGS] = { SECTION_ID_FORMAT_TAGS, "tags", AV_TEXTFORMAT_SECTION_FLAG_HAS_VARIABLE_FIELDS, { -1 }, .element_name = "tag", .unique_name = "format_tags" },
+ [SECTION_ID_FRAMES] = { SECTION_ID_FRAMES, "frames", AV_TEXTFORMAT_SECTION_FLAG_IS_ARRAY, { SECTION_ID_FRAME, SECTION_ID_SUBTITLE, -1 } },
[SECTION_ID_FRAME] = { SECTION_ID_FRAME, "frame", 0, { SECTION_ID_FRAME_TAGS, SECTION_ID_FRAME_SIDE_DATA_LIST, SECTION_ID_FRAME_LOGS, -1 } },
- [SECTION_ID_FRAME_TAGS] = { SECTION_ID_FRAME_TAGS, "tags", SECTION_FLAG_HAS_VARIABLE_FIELDS, { -1 }, .element_name = "tag", .unique_name = "frame_tags" },
- [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" },
- [SECTION_ID_FRAME_SIDE_DATA] = { SECTION_ID_FRAME_SIDE_DATA, "side_data", SECTION_FLAG_HAS_VARIABLE_FIELDS|SECTION_FLAG_HAS_TYPE, { SECTION_ID_FRAME_SIDE_DATA_TIMECODE_LIST, SECTION_ID_FRAME_SIDE_DATA_COMPONENT_LIST, -1 }, .unique_name = "frame_side_data", .element_name = "side_datum", .get_type = get_frame_side_data_type },
- [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 } },
+ [SECTION_ID_FRAME_TAGS] = { SECTION_ID_FRAME_TAGS, "tags", AV_TEXTFORMAT_SECTION_FLAG_HAS_VARIABLE_FIELDS, { -1 }, .element_name = "tag", .unique_name = "frame_tags" },
+ [SECTION_ID_FRAME_SIDE_DATA_LIST] ={ SECTION_ID_FRAME_SIDE_DATA_LIST, "side_data_list", AV_TEXTFORMAT_SECTION_FLAG_IS_ARRAY, { SECTION_ID_FRAME_SIDE_DATA, -1 }, .element_name = "side_data", .unique_name = "frame_side_data_list" },
+ [SECTION_ID_FRAME_SIDE_DATA] = { SECTION_ID_FRAME_SIDE_DATA, "side_data", AV_TEXTFORMAT_SECTION_FLAG_HAS_VARIABLE_FIELDS|AV_TEXTFORMAT_SECTION_FLAG_HAS_TYPE, { SECTION_ID_FRAME_SIDE_DATA_TIMECODE_LIST, SECTION_ID_FRAME_SIDE_DATA_COMPONENT_LIST, -1 }, .unique_name = "frame_side_data", .element_name = "side_datum", .get_type = get_frame_side_data_type },
+ [SECTION_ID_FRAME_SIDE_DATA_TIMECODE_LIST] = { SECTION_ID_FRAME_SIDE_DATA_TIMECODE_LIST, "timecodes", AV_TEXTFORMAT_SECTION_FLAG_IS_ARRAY, { SECTION_ID_FRAME_SIDE_DATA_TIMECODE, -1 } },
[SECTION_ID_FRAME_SIDE_DATA_TIMECODE] = { SECTION_ID_FRAME_SIDE_DATA_TIMECODE, "timecode", 0, { -1 } },
- [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 }, .element_name = "component", .unique_name = "frame_side_data_components" },
- [SECTION_ID_FRAME_SIDE_DATA_COMPONENT] = { SECTION_ID_FRAME_SIDE_DATA_COMPONENT, "component", SECTION_FLAG_HAS_VARIABLE_FIELDS|SECTION_FLAG_HAS_TYPE, { SECTION_ID_FRAME_SIDE_DATA_PIECE_LIST, -1 }, .unique_name = "frame_side_data_component", .element_name = "component_entry", .get_type = get_raw_string_type },
- [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 }, .element_name = "piece", .unique_name = "frame_side_data_pieces" },
- [SECTION_ID_FRAME_SIDE_DATA_PIECE] = { SECTION_ID_FRAME_SIDE_DATA_PIECE, "piece", SECTION_FLAG_HAS_VARIABLE_FIELDS|SECTION_FLAG_HAS_TYPE, { -1 }, .element_name = "piece_entry", .unique_name = "frame_side_data_piece", .get_type = get_raw_string_type },
- [SECTION_ID_FRAME_LOGS] = { SECTION_ID_FRAME_LOGS, "logs", SECTION_FLAG_IS_ARRAY, { SECTION_ID_FRAME_LOG, -1 } },
+ [SECTION_ID_FRAME_SIDE_DATA_COMPONENT_LIST] = { SECTION_ID_FRAME_SIDE_DATA_COMPONENT_LIST, "components", AV_TEXTFORMAT_SECTION_FLAG_IS_ARRAY, { SECTION_ID_FRAME_SIDE_DATA_COMPONENT, -1 }, .element_name = "component", .unique_name = "frame_side_data_components" },
+ [SECTION_ID_FRAME_SIDE_DATA_COMPONENT] = { SECTION_ID_FRAME_SIDE_DATA_COMPONENT, "component", AV_TEXTFORMAT_SECTION_FLAG_HAS_VARIABLE_FIELDS|AV_TEXTFORMAT_SECTION_FLAG_HAS_TYPE, { SECTION_ID_FRAME_SIDE_DATA_PIECE_LIST, -1 }, .unique_name = "frame_side_data_component", .element_name = "component_entry", .get_type = get_raw_string_type },
+ [SECTION_ID_FRAME_SIDE_DATA_PIECE_LIST] = { SECTION_ID_FRAME_SIDE_DATA_PIECE_LIST, "pieces", AV_TEXTFORMAT_SECTION_FLAG_IS_ARRAY, { SECTION_ID_FRAME_SIDE_DATA_PIECE, -1 }, .element_name = "piece", .unique_name = "frame_side_data_pieces" },
+ [SECTION_ID_FRAME_SIDE_DATA_PIECE] = { SECTION_ID_FRAME_SIDE_DATA_PIECE, "piece", AV_TEXTFORMAT_SECTION_FLAG_HAS_VARIABLE_FIELDS|AV_TEXTFORMAT_SECTION_FLAG_HAS_TYPE, { -1 }, .element_name = "piece_entry", .unique_name = "frame_side_data_piece", .get_type = get_raw_string_type },
+ [SECTION_ID_FRAME_LOGS] = { SECTION_ID_FRAME_LOGS, "logs", AV_TEXTFORMAT_SECTION_FLAG_IS_ARRAY, { SECTION_ID_FRAME_LOG, -1 } },
[SECTION_ID_FRAME_LOG] = { SECTION_ID_FRAME_LOG, "log", 0, { -1 }, },
- [SECTION_ID_LIBRARY_VERSIONS] = { SECTION_ID_LIBRARY_VERSIONS, "library_versions", SECTION_FLAG_IS_ARRAY, { SECTION_ID_LIBRARY_VERSION, -1 } },
+ [SECTION_ID_LIBRARY_VERSIONS] = { SECTION_ID_LIBRARY_VERSIONS, "library_versions", AV_TEXTFORMAT_SECTION_FLAG_IS_ARRAY, { SECTION_ID_LIBRARY_VERSION, -1 } },
[SECTION_ID_LIBRARY_VERSION] = { SECTION_ID_LIBRARY_VERSION, "library_version", 0, { -1 } },
- [SECTION_ID_PACKETS] = { SECTION_ID_PACKETS, "packets", SECTION_FLAG_IS_ARRAY, { SECTION_ID_PACKET, -1} },
- [SECTION_ID_PACKETS_AND_FRAMES] = { SECTION_ID_PACKETS_AND_FRAMES, "packets_and_frames", SECTION_FLAG_IS_ARRAY, { SECTION_ID_PACKET, -1} },
+ [SECTION_ID_PACKETS] = { SECTION_ID_PACKETS, "packets", AV_TEXTFORMAT_SECTION_FLAG_IS_ARRAY, { SECTION_ID_PACKET, -1} },
+ [SECTION_ID_PACKETS_AND_FRAMES] = { SECTION_ID_PACKETS_AND_FRAMES, "packets_and_frames", AV_TEXTFORMAT_SECTION_FLAG_IS_ARRAY | AV_TEXTFORMAT_SECTION_FLAG_NUMBERING_BY_TYPE, { SECTION_ID_PACKET, -1} },
[SECTION_ID_PACKET] = { SECTION_ID_PACKET, "packet", 0, { SECTION_ID_PACKET_TAGS, SECTION_ID_PACKET_SIDE_DATA_LIST, -1 } },
- [SECTION_ID_PACKET_TAGS] = { SECTION_ID_PACKET_TAGS, "tags", SECTION_FLAG_HAS_VARIABLE_FIELDS, { -1 }, .element_name = "tag", .unique_name = "packet_tags" },
- [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" },
- [SECTION_ID_PACKET_SIDE_DATA] = { SECTION_ID_PACKET_SIDE_DATA, "side_data", SECTION_FLAG_HAS_VARIABLE_FIELDS|SECTION_FLAG_HAS_TYPE, { -1 }, .unique_name = "packet_side_data", .element_name = "side_datum", .get_type = get_packet_side_data_type },
- [SECTION_ID_PIXEL_FORMATS] = { SECTION_ID_PIXEL_FORMATS, "pixel_formats", SECTION_FLAG_IS_ARRAY, { SECTION_ID_PIXEL_FORMAT, -1 } },
+ [SECTION_ID_PACKET_TAGS] = { SECTION_ID_PACKET_TAGS, "tags", AV_TEXTFORMAT_SECTION_FLAG_HAS_VARIABLE_FIELDS, { -1 }, .element_name = "tag", .unique_name = "packet_tags" },
+ [SECTION_ID_PACKET_SIDE_DATA_LIST] ={ SECTION_ID_PACKET_SIDE_DATA_LIST, "side_data_list", AV_TEXTFORMAT_SECTION_FLAG_IS_ARRAY, { SECTION_ID_PACKET_SIDE_DATA, -1 }, .element_name = "side_data", .unique_name = "packet_side_data_list" },
+ [SECTION_ID_PACKET_SIDE_DATA] = { SECTION_ID_PACKET_SIDE_DATA, "side_data", AV_TEXTFORMAT_SECTION_FLAG_HAS_VARIABLE_FIELDS|AV_TEXTFORMAT_SECTION_FLAG_HAS_TYPE, { -1 }, .unique_name = "packet_side_data", .element_name = "side_datum", .get_type = get_packet_side_data_type },
+ [SECTION_ID_PIXEL_FORMATS] = { SECTION_ID_PIXEL_FORMATS, "pixel_formats", AV_TEXTFORMAT_SECTION_FLAG_IS_ARRAY, { SECTION_ID_PIXEL_FORMAT, -1 } },
[SECTION_ID_PIXEL_FORMAT] = { SECTION_ID_PIXEL_FORMAT, "pixel_format", 0, { SECTION_ID_PIXEL_FORMAT_FLAGS, SECTION_ID_PIXEL_FORMAT_COMPONENTS, -1 } },
[SECTION_ID_PIXEL_FORMAT_FLAGS] = { SECTION_ID_PIXEL_FORMAT_FLAGS, "flags", 0, { -1 }, .unique_name = "pixel_format_flags" },
- [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" },
+ [SECTION_ID_PIXEL_FORMAT_COMPONENTS] = { SECTION_ID_PIXEL_FORMAT_COMPONENTS, "components", AV_TEXTFORMAT_SECTION_FLAG_IS_ARRAY, {SECTION_ID_PIXEL_FORMAT_COMPONENT, -1 }, .unique_name = "pixel_format_components" },
[SECTION_ID_PIXEL_FORMAT_COMPONENT] = { SECTION_ID_PIXEL_FORMAT_COMPONENT, "component", 0, { -1 } },
[SECTION_ID_PROGRAM_STREAM_DISPOSITION] = { SECTION_ID_PROGRAM_STREAM_DISPOSITION, "disposition", 0, { -1 }, .unique_name = "program_stream_disposition" },
- [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" },
+ [SECTION_ID_PROGRAM_STREAM_TAGS] = { SECTION_ID_PROGRAM_STREAM_TAGS, "tags", AV_TEXTFORMAT_SECTION_FLAG_HAS_VARIABLE_FIELDS, { -1 }, .element_name = "tag", .unique_name = "program_stream_tags" },
[SECTION_ID_PROGRAM] = { SECTION_ID_PROGRAM, "program", 0, { SECTION_ID_PROGRAM_TAGS, SECTION_ID_PROGRAM_STREAMS, -1 } },
- [SECTION_ID_PROGRAM_STREAMS] = { SECTION_ID_PROGRAM_STREAMS, "streams", SECTION_FLAG_IS_ARRAY, { SECTION_ID_PROGRAM_STREAM, -1 }, .unique_name = "program_streams" },
+ [SECTION_ID_PROGRAM_STREAMS] = { SECTION_ID_PROGRAM_STREAMS, "streams", AV_TEXTFORMAT_SECTION_FLAG_IS_ARRAY, { SECTION_ID_PROGRAM_STREAM, -1 }, .unique_name = "program_streams" },
[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" },
- [SECTION_ID_PROGRAM_TAGS] = { SECTION_ID_PROGRAM_TAGS, "tags", SECTION_FLAG_HAS_VARIABLE_FIELDS, { -1 }, .element_name = "tag", .unique_name = "program_tags" },
+ [SECTION_ID_PROGRAM_TAGS] = { SECTION_ID_PROGRAM_TAGS, "tags", AV_TEXTFORMAT_SECTION_FLAG_HAS_VARIABLE_FIELDS, { -1 }, .element_name = "tag", .unique_name = "program_tags" },
[SECTION_ID_PROGRAM_VERSION] = { SECTION_ID_PROGRAM_VERSION, "program_version", 0, { -1 } },
- [SECTION_ID_PROGRAMS] = { SECTION_ID_PROGRAMS, "programs", SECTION_FLAG_IS_ARRAY, { SECTION_ID_PROGRAM, -1 } },
+ [SECTION_ID_PROGRAMS] = { SECTION_ID_PROGRAMS, "programs", AV_TEXTFORMAT_SECTION_FLAG_IS_ARRAY, { SECTION_ID_PROGRAM, -1 } },
[SECTION_ID_STREAM_GROUP_STREAM_DISPOSITION] = { SECTION_ID_STREAM_GROUP_STREAM_DISPOSITION, "disposition", 0, { -1 }, .unique_name = "stream_group_stream_disposition" },
- [SECTION_ID_STREAM_GROUP_STREAM_TAGS] = { SECTION_ID_STREAM_GROUP_STREAM_TAGS, "tags", SECTION_FLAG_HAS_VARIABLE_FIELDS, { -1 }, .element_name = "tag", .unique_name = "stream_group_stream_tags" },
+ [SECTION_ID_STREAM_GROUP_STREAM_TAGS] = { SECTION_ID_STREAM_GROUP_STREAM_TAGS, "tags", AV_TEXTFORMAT_SECTION_FLAG_HAS_VARIABLE_FIELDS, { -1 }, .element_name = "tag", .unique_name = "stream_group_stream_tags" },
[SECTION_ID_STREAM_GROUP] = { SECTION_ID_STREAM_GROUP, "stream_group", 0, { SECTION_ID_STREAM_GROUP_TAGS, SECTION_ID_STREAM_GROUP_DISPOSITION, SECTION_ID_STREAM_GROUP_COMPONENTS, SECTION_ID_STREAM_GROUP_STREAMS, -1 } },
- [SECTION_ID_STREAM_GROUP_COMPONENTS] = { SECTION_ID_STREAM_GROUP_COMPONENTS, "components", SECTION_FLAG_IS_ARRAY, { SECTION_ID_STREAM_GROUP_COMPONENT, -1 }, .element_name = "component", .unique_name = "stream_group_components" },
- [SECTION_ID_STREAM_GROUP_COMPONENT] = { SECTION_ID_STREAM_GROUP_COMPONENT, "component", SECTION_FLAG_HAS_VARIABLE_FIELDS|SECTION_FLAG_HAS_TYPE, { SECTION_ID_STREAM_GROUP_SUBCOMPONENTS, -1 }, .unique_name = "stream_group_component", .element_name = "component_entry", .get_type = get_stream_group_type },
- [SECTION_ID_STREAM_GROUP_SUBCOMPONENTS] = { SECTION_ID_STREAM_GROUP_SUBCOMPONENTS, "subcomponents", SECTION_FLAG_IS_ARRAY, { SECTION_ID_STREAM_GROUP_SUBCOMPONENT, -1 }, .element_name = "component" },
- [SECTION_ID_STREAM_GROUP_SUBCOMPONENT] = { SECTION_ID_STREAM_GROUP_SUBCOMPONENT, "subcomponent", SECTION_FLAG_HAS_VARIABLE_FIELDS|SECTION_FLAG_HAS_TYPE, { SECTION_ID_STREAM_GROUP_PIECES, -1 }, .element_name = "subcomponent_entry", .get_type = get_raw_string_type },
- [SECTION_ID_STREAM_GROUP_PIECES] = { SECTION_ID_STREAM_GROUP_PIECES, "pieces", SECTION_FLAG_IS_ARRAY, { SECTION_ID_STREAM_GROUP_PIECE, -1 }, .element_name = "piece", .unique_name = "stream_group_pieces" },
- [SECTION_ID_STREAM_GROUP_PIECE] = { SECTION_ID_STREAM_GROUP_PIECE, "piece", SECTION_FLAG_HAS_VARIABLE_FIELDS|SECTION_FLAG_HAS_TYPE, { SECTION_ID_STREAM_GROUP_SUBPIECES, -1 }, .unique_name = "stream_group_piece", .element_name = "piece_entry", .get_type = get_raw_string_type },
- [SECTION_ID_STREAM_GROUP_SUBPIECES] = { SECTION_ID_STREAM_GROUP_SUBPIECES, "subpieces", SECTION_FLAG_IS_ARRAY, { SECTION_ID_STREAM_GROUP_SUBPIECE, -1 }, .element_name = "subpiece" },
- [SECTION_ID_STREAM_GROUP_SUBPIECE] = { SECTION_ID_STREAM_GROUP_SUBPIECE, "subpiece", SECTION_FLAG_HAS_VARIABLE_FIELDS|SECTION_FLAG_HAS_TYPE, { SECTION_ID_STREAM_GROUP_BLOCKS, -1 }, .element_name = "subpiece_entry", .get_type = get_raw_string_type },
- [SECTION_ID_STREAM_GROUP_BLOCKS] = { SECTION_ID_STREAM_GROUP_BLOCKS, "blocks", SECTION_FLAG_IS_ARRAY, { SECTION_ID_STREAM_GROUP_BLOCK, -1 }, .element_name = "block" },
- [SECTION_ID_STREAM_GROUP_BLOCK] = { SECTION_ID_STREAM_GROUP_BLOCK, "block", SECTION_FLAG_HAS_VARIABLE_FIELDS|SECTION_FLAG_HAS_TYPE, { -1 }, .element_name = "block_entry", .get_type = get_raw_string_type },
- [SECTION_ID_STREAM_GROUP_STREAMS] = { SECTION_ID_STREAM_GROUP_STREAMS, "streams", SECTION_FLAG_IS_ARRAY, { SECTION_ID_STREAM_GROUP_STREAM, -1 }, .unique_name = "stream_group_streams" },
+ [SECTION_ID_STREAM_GROUP_COMPONENTS] = { SECTION_ID_STREAM_GROUP_COMPONENTS, "components", AV_TEXTFORMAT_SECTION_FLAG_IS_ARRAY, { SECTION_ID_STREAM_GROUP_COMPONENT, -1 }, .element_name = "component", .unique_name = "stream_group_components" },
+ [SECTION_ID_STREAM_GROUP_COMPONENT] = { SECTION_ID_STREAM_GROUP_COMPONENT, "component", AV_TEXTFORMAT_SECTION_FLAG_HAS_VARIABLE_FIELDS|AV_TEXTFORMAT_SECTION_FLAG_HAS_TYPE, { SECTION_ID_STREAM_GROUP_SUBCOMPONENTS, -1 }, .unique_name = "stream_group_component", .element_name = "component_entry", .get_type = get_stream_group_type },
+ [SECTION_ID_STREAM_GROUP_SUBCOMPONENTS] = { SECTION_ID_STREAM_GROUP_SUBCOMPONENTS, "subcomponents", AV_TEXTFORMAT_SECTION_FLAG_IS_ARRAY, { SECTION_ID_STREAM_GROUP_SUBCOMPONENT, -1 }, .element_name = "component" },
+ [SECTION_ID_STREAM_GROUP_SUBCOMPONENT] = { SECTION_ID_STREAM_GROUP_SUBCOMPONENT, "subcomponent", AV_TEXTFORMAT_SECTION_FLAG_HAS_VARIABLE_FIELDS|AV_TEXTFORMAT_SECTION_FLAG_HAS_TYPE, { SECTION_ID_STREAM_GROUP_PIECES, -1 }, .element_name = "subcomponent_entry", .get_type = get_raw_string_type },
+ [SECTION_ID_STREAM_GROUP_PIECES] = { SECTION_ID_STREAM_GROUP_PIECES, "pieces", AV_TEXTFORMAT_SECTION_FLAG_IS_ARRAY, { SECTION_ID_STREAM_GROUP_PIECE, -1 }, .element_name = "piece", .unique_name = "stream_group_pieces" },
+ [SECTION_ID_STREAM_GROUP_PIECE] = { SECTION_ID_STREAM_GROUP_PIECE, "piece", AV_TEXTFORMAT_SECTION_FLAG_HAS_VARIABLE_FIELDS|AV_TEXTFORMAT_SECTION_FLAG_HAS_TYPE, { SECTION_ID_STREAM_GROUP_SUBPIECES, -1 }, .unique_name = "stream_group_piece", .element_name = "piece_entry", .get_type = get_raw_string_type },
+ [SECTION_ID_STREAM_GROUP_SUBPIECES] = { SECTION_ID_STREAM_GROUP_SUBPIECES, "subpieces", AV_TEXTFORMAT_SECTION_FLAG_IS_ARRAY, { SECTION_ID_STREAM_GROUP_SUBPIECE, -1 }, .element_name = "subpiece" },
+ [SECTION_ID_STREAM_GROUP_SUBPIECE] = { SECTION_ID_STREAM_GROUP_SUBPIECE, "subpiece", AV_TEXTFORMAT_SECTION_FLAG_HAS_VARIABLE_FIELDS|AV_TEXTFORMAT_SECTION_FLAG_HAS_TYPE, { SECTION_ID_STREAM_GROUP_BLOCKS, -1 }, .element_name = "subpiece_entry", .get_type = get_raw_string_type },
+ [SECTION_ID_STREAM_GROUP_BLOCKS] = { SECTION_ID_STREAM_GROUP_BLOCKS, "blocks", AV_TEXTFORMAT_SECTION_FLAG_IS_ARRAY, { SECTION_ID_STREAM_GROUP_BLOCK, -1 }, .element_name = "block" },
+ [SECTION_ID_STREAM_GROUP_BLOCK] = { SECTION_ID_STREAM_GROUP_BLOCK, "block", AV_TEXTFORMAT_SECTION_FLAG_HAS_VARIABLE_FIELDS|AV_TEXTFORMAT_SECTION_FLAG_HAS_TYPE, { -1 }, .element_name = "block_entry", .get_type = get_raw_string_type },
+ [SECTION_ID_STREAM_GROUP_STREAMS] = { SECTION_ID_STREAM_GROUP_STREAMS, "streams", AV_TEXTFORMAT_SECTION_FLAG_IS_ARRAY, { SECTION_ID_STREAM_GROUP_STREAM, -1 }, .unique_name = "stream_group_streams" },
[SECTION_ID_STREAM_GROUP_STREAM] = { SECTION_ID_STREAM_GROUP_STREAM, "stream", 0, { SECTION_ID_STREAM_GROUP_STREAM_DISPOSITION, SECTION_ID_STREAM_GROUP_STREAM_TAGS, -1 }, .unique_name = "stream_group_stream" },
[SECTION_ID_STREAM_GROUP_DISPOSITION] = { SECTION_ID_STREAM_GROUP_DISPOSITION, "disposition", 0, { -1 }, .unique_name = "stream_group_disposition" },
- [SECTION_ID_STREAM_GROUP_TAGS] = { SECTION_ID_STREAM_GROUP_TAGS, "tags", SECTION_FLAG_HAS_VARIABLE_FIELDS, { -1 }, .element_name = "tag", .unique_name = "stream_group_tags" },
- [SECTION_ID_STREAM_GROUPS] = { SECTION_ID_STREAM_GROUPS, "stream_groups", SECTION_FLAG_IS_ARRAY, { SECTION_ID_STREAM_GROUP, -1 } },
- [SECTION_ID_ROOT] = { SECTION_ID_ROOT, "root", SECTION_FLAG_IS_WRAPPER,
+ [SECTION_ID_STREAM_GROUP_TAGS] = { SECTION_ID_STREAM_GROUP_TAGS, "tags", AV_TEXTFORMAT_SECTION_FLAG_HAS_VARIABLE_FIELDS, { -1 }, .element_name = "tag", .unique_name = "stream_group_tags" },
+ [SECTION_ID_STREAM_GROUPS] = { SECTION_ID_STREAM_GROUPS, "stream_groups", AV_TEXTFORMAT_SECTION_FLAG_IS_ARRAY, { SECTION_ID_STREAM_GROUP, -1 } },
+ [SECTION_ID_ROOT] = { SECTION_ID_ROOT, "root", AV_TEXTFORMAT_SECTION_FLAG_IS_WRAPPER,
{ SECTION_ID_CHAPTERS, SECTION_ID_FORMAT, SECTION_ID_FRAMES, SECTION_ID_PROGRAMS, SECTION_ID_STREAM_GROUPS, SECTION_ID_STREAMS,
SECTION_ID_PACKETS, SECTION_ID_ERROR, SECTION_ID_PROGRAM_VERSION, SECTION_ID_LIBRARY_VERSIONS,
SECTION_ID_PIXEL_FORMATS, -1} },
- [SECTION_ID_STREAMS] = { SECTION_ID_STREAMS, "streams", SECTION_FLAG_IS_ARRAY, { SECTION_ID_STREAM, -1 } },
+ [SECTION_ID_STREAMS] = { SECTION_ID_STREAMS, "streams", AV_TEXTFORMAT_SECTION_FLAG_IS_ARRAY, { SECTION_ID_STREAM, -1 } },
[SECTION_ID_STREAM] = { SECTION_ID_STREAM, "stream", 0, { SECTION_ID_STREAM_DISPOSITION, SECTION_ID_STREAM_TAGS, SECTION_ID_STREAM_SIDE_DATA_LIST, -1 } },
[SECTION_ID_STREAM_DISPOSITION] = { SECTION_ID_STREAM_DISPOSITION, "disposition", 0, { -1 }, .unique_name = "stream_disposition" },
- [SECTION_ID_STREAM_TAGS] = { SECTION_ID_STREAM_TAGS, "tags", SECTION_FLAG_HAS_VARIABLE_FIELDS, { -1 }, .element_name = "tag", .unique_name = "stream_tags" },
- [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" },
- [SECTION_ID_STREAM_SIDE_DATA] = { SECTION_ID_STREAM_SIDE_DATA, "side_data", SECTION_FLAG_HAS_TYPE|SECTION_FLAG_HAS_VARIABLE_FIELDS, { -1 }, .unique_name = "stream_side_data", .element_name = "side_datum", .get_type = get_packet_side_data_type },
+ [SECTION_ID_STREAM_TAGS] = { SECTION_ID_STREAM_TAGS, "tags", AV_TEXTFORMAT_SECTION_FLAG_HAS_VARIABLE_FIELDS, { -1 }, .element_name = "tag", .unique_name = "stream_tags" },
+ [SECTION_ID_STREAM_SIDE_DATA_LIST] ={ SECTION_ID_STREAM_SIDE_DATA_LIST, "side_data_list", AV_TEXTFORMAT_SECTION_FLAG_IS_ARRAY, { SECTION_ID_STREAM_SIDE_DATA, -1 }, .element_name = "side_data", .unique_name = "stream_side_data_list" },
+ [SECTION_ID_STREAM_SIDE_DATA] = { SECTION_ID_STREAM_SIDE_DATA, "side_data", AV_TEXTFORMAT_SECTION_FLAG_HAS_TYPE|AV_TEXTFORMAT_SECTION_FLAG_HAS_VARIABLE_FIELDS, { -1 }, .unique_name = "stream_side_data", .element_name = "side_datum", .get_type = get_packet_side_data_type },
[SECTION_ID_SUBTITLE] = { SECTION_ID_SUBTITLE, "subtitle", 0, { -1 } },
};
@@ -350,22 +333,6 @@ static const char *print_input_filename;
static const AVInputFormat *iformat = NULL;
static const char *output_filename = NULL;
-static struct AVHashContext *hash;
-
-static const struct {
- double bin_val;
- double dec_val;
- const char *bin_str;
- const char *dec_str;
-} si_prefixes[] = {
- { 1.0, 1.0, "", "" },
- { 1.024e3, 1e3, "Ki", "K" },
- { 1.048576e6, 1e6, "Mi", "M" },
- { 1.073741824e9, 1e9, "Gi", "G" },
- { 1.099511627776e12, 1e12, "Ti", "T" },
- { 1.125899906842624e15, 1e15, "Pi", "P" },
-};
-
static const char unit_second_str[] = "s" ;
static const char unit_hertz_str[] = "Hz" ;
static const char unit_byte_str[] = "byte" ;
@@ -441,1554 +408,11 @@ static void log_callback(void *ptr, int level, const char *fmt, va_list vl)
#endif
}
-struct unit_value {
- union { double d; int64_t i; } val;
- const char *unit;
-};
-
-static char *value_string(char *buf, int buf_size, struct unit_value uv)
-{
- double vald;
- int64_t vali;
- int show_float = 0;
-
- if (uv.unit == unit_second_str) {
- vald = uv.val.d;
- show_float = 1;
- } else {
- vald = vali = uv.val.i;
- }
-
- if (uv.unit == unit_second_str && use_value_sexagesimal_format) {
- double secs;
- int hours, mins;
- secs = vald;
- mins = (int)secs / 60;
- secs = secs - mins * 60;
- hours = mins / 60;
- mins %= 60;
- snprintf(buf, buf_size, "%d:%02d:%09.6f", hours, mins, secs);
- } else {
- const char *prefix_string = "";
-
- if (use_value_prefix && vald > 1) {
- int64_t index;
-
- if (uv.unit == unit_byte_str && use_byte_value_binary_prefix) {
- index = (int64_t) (log2(vald)) / 10;
- index = av_clip(index, 0, FF_ARRAY_ELEMS(si_prefixes) - 1);
- vald /= si_prefixes[index].bin_val;
- prefix_string = si_prefixes[index].bin_str;
- } else {
- index = (int64_t) (log10(vald)) / 3;
- index = av_clip(index, 0, FF_ARRAY_ELEMS(si_prefixes) - 1);
- vald /= si_prefixes[index].dec_val;
- prefix_string = si_prefixes[index].dec_str;
- }
- vali = vald;
- }
-
- if (show_float || (use_value_prefix && vald != (int64_t)vald))
- snprintf(buf, buf_size, "%f", vald);
- else
- snprintf(buf, buf_size, "%"PRId64, vali);
- av_strlcatf(buf, buf_size, "%s%s%s", *prefix_string || show_value_unit ? " " : "",
- prefix_string, show_value_unit ? uv.unit : "");
- }
-
- return buf;
-}
-
-/* WRITERS API */
-
-typedef struct WriterContext WriterContext;
-
-#define WRITER_FLAG_DISPLAY_OPTIONAL_FIELDS 1
-#define WRITER_FLAG_PUT_PACKETS_AND_FRAMES_IN_SAME_CHAPTER 2
-
-typedef enum {
- WRITER_STRING_VALIDATION_FAIL,
- WRITER_STRING_VALIDATION_REPLACE,
- WRITER_STRING_VALIDATION_IGNORE,
- WRITER_STRING_VALIDATION_NB
-} StringValidation;
-
-typedef struct Writer {
- const AVClass *priv_class; ///< private class of the writer, if any
- int priv_size; ///< private size for the writer context
- const char *name;
-
- int (*init) (WriterContext *wctx);
- void (*uninit)(WriterContext *wctx);
-
- void (*print_section_header)(WriterContext *wctx, const void *data);
- void (*print_section_footer)(WriterContext *wctx);
- void (*print_integer) (WriterContext *wctx, const char *, int64_t);
- void (*print_rational) (WriterContext *wctx, AVRational *q, char *sep);
- void (*print_string) (WriterContext *wctx, const char *, const char *);
- int flags; ///< a combination or WRITER_FLAG_*
-} Writer;
-
-#define SECTION_MAX_NB_LEVELS 12
-
-struct WriterContext {
- const AVClass *class; ///< class of the writer
- const Writer *writer; ///< the Writer of which this is an instance
- AVIOContext *avio; ///< the I/O context used to write
-
- void (* writer_w8)(WriterContext *wctx, int b);
- void (* writer_put_str)(WriterContext *wctx, const char *str);
- void (* writer_printf)(WriterContext *wctx, const char *fmt, ...);
-
- char *name; ///< name of this writer instance
- void *priv; ///< private data for use by the filter
-
- const struct section *sections; ///< array containing all sections
- int nb_sections; ///< number of sections
-
- int level; ///< current level, starting from 0
-
- /** number of the item printed in the given section, starting from 0 */
- unsigned int nb_item[SECTION_MAX_NB_LEVELS];
-
- /** section per each level */
- const struct section *section[SECTION_MAX_NB_LEVELS];
- AVBPrint section_pbuf[SECTION_MAX_NB_LEVELS]; ///< generic print buffer dedicated to each section,
- /// used by various writers
-
- unsigned int nb_section_packet; ///< number of the packet section in case we are in "packets_and_frames" section
- unsigned int nb_section_frame; ///< number of the frame section in case we are in "packets_and_frames" section
- unsigned int nb_section_packet_frame; ///< nb_section_packet or nb_section_frame according if is_packets_and_frames
-
- int string_validation;
- char *string_validation_replacement;
- unsigned int string_validation_utf8_flags;
-};
-
-static const char *writer_get_name(void *p)
-{
- WriterContext *wctx = p;
- return wctx->writer->name;
-}
-
-#define OFFSET(x) offsetof(WriterContext, x)
-
-static const AVOption writer_options[] = {
- { "string_validation", "set string validation mode",
- OFFSET(string_validation), AV_OPT_TYPE_INT, {.i64=WRITER_STRING_VALIDATION_REPLACE}, 0, WRITER_STRING_VALIDATION_NB-1, .unit = "sv" },
- { "sv", "set string validation mode",
- OFFSET(string_validation), AV_OPT_TYPE_INT, {.i64=WRITER_STRING_VALIDATION_REPLACE}, 0, WRITER_STRING_VALIDATION_NB-1, .unit = "sv" },
- { "ignore", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = WRITER_STRING_VALIDATION_IGNORE}, .unit = "sv" },
- { "replace", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = WRITER_STRING_VALIDATION_REPLACE}, .unit = "sv" },
- { "fail", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = WRITER_STRING_VALIDATION_FAIL}, .unit = "sv" },
- { "string_validation_replacement", "set string validation replacement string", OFFSET(string_validation_replacement), AV_OPT_TYPE_STRING, {.str=""}},
- { "svr", "set string validation replacement string", OFFSET(string_validation_replacement), AV_OPT_TYPE_STRING, {.str="\xEF\xBF\xBD"}},
- { NULL }
-};
-
-static void *writer_child_next(void *obj, void *prev)
-{
- WriterContext *ctx = obj;
- if (!prev && ctx->writer && ctx->writer->priv_class && ctx->priv)
- return ctx->priv;
- return NULL;
-}
-
-static const AVClass writer_class = {
- .class_name = "Writer",
- .item_name = writer_get_name,
- .option = writer_options,
- .version = LIBAVUTIL_VERSION_INT,
- .child_next = writer_child_next,
-};
-
-static int writer_close(WriterContext **wctx)
-{
- int i;
- int ret = 0;
-
- if (!*wctx)
- return -1;
-
- if ((*wctx)->writer->uninit)
- (*wctx)->writer->uninit(*wctx);
- for (i = 0; i < SECTION_MAX_NB_LEVELS; i++)
- av_bprint_finalize(&(*wctx)->section_pbuf[i], NULL);
- if ((*wctx)->writer->priv_class)
- av_opt_free((*wctx)->priv);
- av_freep(&((*wctx)->priv));
- av_opt_free(*wctx);
- if ((*wctx)->avio) {
- avio_flush((*wctx)->avio);
- ret = avio_close((*wctx)->avio);
- }
- av_freep(wctx);
- return ret;
-}
-
-static void bprint_bytes(AVBPrint *bp, const uint8_t *ubuf, size_t ubuf_size)
-{
- int i;
- av_bprintf(bp, "0X");
- for (i = 0; i < ubuf_size; i++)
- av_bprintf(bp, "%02X", ubuf[i]);
-}
-
-static inline void writer_w8_avio(WriterContext *wctx, int b)
-{
- avio_w8(wctx->avio, b);
-}
-
-static inline void writer_put_str_avio(WriterContext *wctx, const char *str)
-{
- avio_write(wctx->avio, str, strlen(str));
-}
-
-static inline void writer_printf_avio(WriterContext *wctx, const char *fmt, ...)
-{
- va_list ap;
-
- va_start(ap, fmt);
- avio_vprintf(wctx->avio, fmt, ap);
- va_end(ap);
-}
-
-static inline void writer_w8_printf(WriterContext *wctx, int b)
-{
- printf("%c", b);
-}
-
-static inline void writer_put_str_printf(WriterContext *wctx, const char *str)
-{
- printf("%s", str);
-}
-
-static inline void writer_printf_printf(WriterContext *wctx, const char *fmt, ...)
-{
- va_list ap;
-
- va_start(ap, fmt);
- vprintf(fmt, ap);
- va_end(ap);
-}
-
-static int writer_open(WriterContext **wctx, const Writer *writer, const char *args,
- const struct section *sections, int nb_sections, const char *output)
-{
- int i, ret = 0;
-
- if (!(*wctx = av_mallocz(sizeof(WriterContext)))) {
- ret = AVERROR(ENOMEM);
- goto fail;
- }
-
- if (!((*wctx)->priv = av_mallocz(writer->priv_size))) {
- ret = AVERROR(ENOMEM);
- goto fail;
- }
-
- (*wctx)->class = &writer_class;
- (*wctx)->writer = writer;
- (*wctx)->level = -1;
- (*wctx)->sections = sections;
- (*wctx)->nb_sections = nb_sections;
-
- av_opt_set_defaults(*wctx);
-
- if (writer->priv_class) {
- void *priv_ctx = (*wctx)->priv;
- *((const AVClass **)priv_ctx) = writer->priv_class;
- av_opt_set_defaults(priv_ctx);
- }
-
- /* convert options to dictionary */
- if (args) {
- AVDictionary *opts = NULL;
- const AVDictionaryEntry *opt = NULL;
-
- if ((ret = av_dict_parse_string(&opts, args, "=", ":", 0)) < 0) {
- av_log(*wctx, AV_LOG_ERROR, "Failed to parse option string '%s' provided to writer context\n", args);
- av_dict_free(&opts);
- goto fail;
- }
-
- while ((opt = av_dict_iterate(opts, opt))) {
- if ((ret = av_opt_set(*wctx, opt->key, opt->value, AV_OPT_SEARCH_CHILDREN)) < 0) {
- av_log(*wctx, AV_LOG_ERROR, "Failed to set option '%s' with value '%s' provided to writer context\n",
- opt->key, opt->value);
- av_dict_free(&opts);
- goto fail;
- }
- }
-
- av_dict_free(&opts);
- }
-
- /* validate replace string */
- {
- const uint8_t *p = (*wctx)->string_validation_replacement;
- const uint8_t *endp = p + strlen(p);
- while (*p) {
- const uint8_t *p0 = p;
- int32_t code;
- ret = av_utf8_decode(&code, &p, endp, (*wctx)->string_validation_utf8_flags);
- if (ret < 0) {
- AVBPrint bp;
- av_bprint_init(&bp, 0, AV_BPRINT_SIZE_AUTOMATIC);
- bprint_bytes(&bp, p0, p-p0),
- av_log(wctx, AV_LOG_ERROR,
- "Invalid UTF8 sequence %s found in string validation replace '%s'\n",
- bp.str, (*wctx)->string_validation_replacement);
- return ret;
- }
- }
- }
-
- if (!output_filename) {
- (*wctx)->writer_w8 = writer_w8_printf;
- (*wctx)->writer_put_str = writer_put_str_printf;
- (*wctx)->writer_printf = writer_printf_printf;
- } else {
- if ((ret = avio_open(&(*wctx)->avio, output, AVIO_FLAG_WRITE)) < 0) {
- av_log(*wctx, AV_LOG_ERROR,
- "Failed to open output '%s' with error: %s\n", output, av_err2str(ret));
- goto fail;
- }
- (*wctx)->writer_w8 = writer_w8_avio;
- (*wctx)->writer_put_str = writer_put_str_avio;
- (*wctx)->writer_printf = writer_printf_avio;
- }
-
- for (i = 0; i < SECTION_MAX_NB_LEVELS; i++)
- av_bprint_init(&(*wctx)->section_pbuf[i], 1, AV_BPRINT_SIZE_UNLIMITED);
-
- if ((*wctx)->writer->init)
- ret = (*wctx)->writer->init(*wctx);
- if (ret < 0)
- goto fail;
-
- return 0;
-
-fail:
- writer_close(wctx);
- return ret;
-}
-
-static inline void writer_print_section_header(WriterContext *wctx,
- const void *data,
- int section_id)
-{
- int parent_section_id;
- wctx->level++;
- av_assert0(wctx->level < SECTION_MAX_NB_LEVELS);
- parent_section_id = wctx->level ?
- (wctx->section[wctx->level-1])->id : SECTION_ID_NONE;
-
- wctx->nb_item[wctx->level] = 0;
- wctx->section[wctx->level] = &wctx->sections[section_id];
-
- if (section_id == SECTION_ID_PACKETS_AND_FRAMES) {
- wctx->nb_section_packet = wctx->nb_section_frame =
- wctx->nb_section_packet_frame = 0;
- } else if (parent_section_id == SECTION_ID_PACKETS_AND_FRAMES) {
- wctx->nb_section_packet_frame = section_id == SECTION_ID_PACKET ?
- wctx->nb_section_packet : wctx->nb_section_frame;
- }
-
- if (wctx->writer->print_section_header)
- wctx->writer->print_section_header(wctx, data);
-}
-
-static inline void writer_print_section_footer(WriterContext *wctx)
-{
- int section_id = wctx->section[wctx->level]->id;
- int parent_section_id = wctx->level ?
- wctx->section[wctx->level-1]->id : SECTION_ID_NONE;
-
- if (parent_section_id != SECTION_ID_NONE)
- wctx->nb_item[wctx->level-1]++;
- if (parent_section_id == SECTION_ID_PACKETS_AND_FRAMES) {
- if (section_id == SECTION_ID_PACKET) wctx->nb_section_packet++;
- else wctx->nb_section_frame++;
- }
- if (wctx->writer->print_section_footer)
- wctx->writer->print_section_footer(wctx);
- wctx->level--;
-}
-
-static inline void writer_print_integer(WriterContext *wctx,
- const char *key, int64_t val)
-{
- const struct section *section = wctx->section[wctx->level];
-
- if (section->show_all_entries || av_dict_get(section->entries_to_show, key, NULL, 0)) {
- wctx->writer->print_integer(wctx, key, val);
- wctx->nb_item[wctx->level]++;
- }
-}
-
-static inline int validate_string(WriterContext *wctx, char **dstp, const char *src)
-{
- const uint8_t *p, *endp;
- AVBPrint dstbuf;
- int invalid_chars_nb = 0, ret = 0;
-
- av_bprint_init(&dstbuf, 0, AV_BPRINT_SIZE_UNLIMITED);
-
- endp = src + strlen(src);
- for (p = src; *p;) {
- uint32_t code;
- int invalid = 0;
- const uint8_t *p0 = p;
-
- if (av_utf8_decode(&code, &p, endp, wctx->string_validation_utf8_flags) < 0) {
- AVBPrint bp;
- av_bprint_init(&bp, 0, AV_BPRINT_SIZE_AUTOMATIC);
- bprint_bytes(&bp, p0, p-p0);
- av_log(wctx, AV_LOG_DEBUG,
- "Invalid UTF-8 sequence %s found in string '%s'\n", bp.str, src);
- invalid = 1;
- }
-
- if (invalid) {
- invalid_chars_nb++;
-
- switch (wctx->string_validation) {
- case WRITER_STRING_VALIDATION_FAIL:
- av_log(wctx, AV_LOG_ERROR,
- "Invalid UTF-8 sequence found in string '%s'\n", src);
- ret = AVERROR_INVALIDDATA;
- goto end;
- break;
-
- case WRITER_STRING_VALIDATION_REPLACE:
- av_bprintf(&dstbuf, "%s", wctx->string_validation_replacement);
- break;
- }
- }
-
- if (!invalid || wctx->string_validation == WRITER_STRING_VALIDATION_IGNORE)
- av_bprint_append_data(&dstbuf, p0, p-p0);
- }
-
- if (invalid_chars_nb && wctx->string_validation == WRITER_STRING_VALIDATION_REPLACE) {
- av_log(wctx, AV_LOG_WARNING,
- "%d invalid UTF-8 sequence(s) found in string '%s', replaced with '%s'\n",
- invalid_chars_nb, src, wctx->string_validation_replacement);
- }
-
-end:
- av_bprint_finalize(&dstbuf, dstp);
- return ret;
-}
-
-#define PRINT_STRING_OPT 1
-#define PRINT_STRING_VALIDATE 2
-
-static inline int writer_print_string(WriterContext *wctx,
- const char *key, const char *val, int flags)
-{
- const struct section *section = wctx->section[wctx->level];
- int ret = 0;
-
- if (show_optional_fields == SHOW_OPTIONAL_FIELDS_NEVER ||
- (show_optional_fields == SHOW_OPTIONAL_FIELDS_AUTO
- && (flags & PRINT_STRING_OPT)
- && !(wctx->writer->flags & WRITER_FLAG_DISPLAY_OPTIONAL_FIELDS)))
- return 0;
-
- if (section->show_all_entries || av_dict_get(section->entries_to_show, key, NULL, 0)) {
- if (flags & PRINT_STRING_VALIDATE) {
- char *key1 = NULL, *val1 = NULL;
- ret = validate_string(wctx, &key1, key);
- if (ret < 0) goto end;
- ret = validate_string(wctx, &val1, val);
- if (ret < 0) goto end;
- wctx->writer->print_string(wctx, key1, val1);
- end:
- if (ret < 0) {
- av_log(wctx, AV_LOG_ERROR,
- "Invalid key=value string combination %s=%s in section %s\n",
- key, val, section->unique_name);
- }
- av_free(key1);
- av_free(val1);
- } else {
- wctx->writer->print_string(wctx, key, val);
- }
-
- wctx->nb_item[wctx->level]++;
- }
-
- return ret;
-}
-
-static inline void writer_print_rational(WriterContext *wctx,
- const char *key, AVRational q, char sep)
-{
- AVBPrint buf;
- av_bprint_init(&buf, 0, AV_BPRINT_SIZE_AUTOMATIC);
- av_bprintf(&buf, "%d%c%d", q.num, sep, q.den);
- writer_print_string(wctx, key, buf.str, 0);
-}
-
-static void writer_print_time(WriterContext *wctx, const char *key,
- int64_t ts, const AVRational *time_base, int is_duration)
-{
- char buf[128];
-
- if ((!is_duration && ts == AV_NOPTS_VALUE) || (is_duration && ts == 0)) {
- writer_print_string(wctx, key, "N/A", PRINT_STRING_OPT);
- } else {
- double d = ts * av_q2d(*time_base);
- struct unit_value uv;
- uv.val.d = d;
- uv.unit = unit_second_str;
- value_string(buf, sizeof(buf), uv);
- writer_print_string(wctx, key, buf, 0);
- }
-}
-
-static void writer_print_ts(WriterContext *wctx, const char *key, int64_t ts, int is_duration)
-{
- if ((!is_duration && ts == AV_NOPTS_VALUE) || (is_duration && ts == 0)) {
- writer_print_string(wctx, key, "N/A", PRINT_STRING_OPT);
- } else {
- writer_print_integer(wctx, key, ts);
- }
-}
-
-static void writer_print_data(WriterContext *wctx, const char *name,
- const uint8_t *data, int size)
-{
- AVBPrint bp;
- int offset = 0, l, i;
-
- av_bprint_init(&bp, 0, AV_BPRINT_SIZE_UNLIMITED);
- av_bprintf(&bp, "\n");
- while (size) {
- av_bprintf(&bp, "%08x: ", offset);
- l = FFMIN(size, 16);
- for (i = 0; i < l; i++) {
- av_bprintf(&bp, "%02x", data[i]);
- if (i & 1)
- av_bprintf(&bp, " ");
- }
- av_bprint_chars(&bp, ' ', 41 - 2 * i - i / 2);
- for (i = 0; i < l; i++)
- av_bprint_chars(&bp, data[i] - 32U < 95 ? data[i] : '.', 1);
- av_bprintf(&bp, "\n");
- offset += l;
- data += l;
- size -= l;
- }
- writer_print_string(wctx, name, bp.str, 0);
- av_bprint_finalize(&bp, NULL);
-}
-
-static void writer_print_data_hash(WriterContext *wctx, const char *name,
- const uint8_t *data, int size)
-{
- char *p, buf[AV_HASH_MAX_SIZE * 2 + 64] = { 0 };
-
- if (!hash)
- return;
- av_hash_init(hash);
- av_hash_update(hash, data, size);
- snprintf(buf, sizeof(buf), "%s:", av_hash_get_name(hash));
- p = buf + strlen(buf);
- av_hash_final_hex(hash, p, buf + sizeof(buf) - p);
- writer_print_string(wctx, name, buf, 0);
-}
-
-static void writer_print_integers(WriterContext *wctx, const char *name,
- uint8_t *data, int size, const char *format,
- int columns, int bytes, int offset_add)
-{
- AVBPrint bp;
- int offset = 0, l, i;
-
- av_bprint_init(&bp, 0, AV_BPRINT_SIZE_UNLIMITED);
- av_bprintf(&bp, "\n");
- while (size) {
- av_bprintf(&bp, "%08x: ", offset);
- l = FFMIN(size, columns);
- for (i = 0; i < l; i++) {
- if (bytes == 1) av_bprintf(&bp, format, *data);
- else if (bytes == 2) av_bprintf(&bp, format, AV_RN16(data));
- else if (bytes == 4) av_bprintf(&bp, format, AV_RN32(data));
- data += bytes;
- size --;
- }
- av_bprintf(&bp, "\n");
- offset += offset_add;
- }
- writer_print_string(wctx, name, bp.str, 0);
- av_bprint_finalize(&bp, NULL);
-}
-
-#define writer_w8(wctx_, b_) (wctx_)->writer_w8(wctx_, b_)
-#define writer_put_str(wctx_, str_) (wctx_)->writer_put_str(wctx_, str_)
-#define writer_printf(wctx_, fmt_, ...) (wctx_)->writer_printf(wctx_, fmt_, __VA_ARGS__)
-
-#define MAX_REGISTERED_WRITERS_NB 64
-
-static const Writer *registered_writers[MAX_REGISTERED_WRITERS_NB + 1];
-
-static int writer_register(const Writer *writer)
-{
- static int next_registered_writer_idx = 0;
-
- if (next_registered_writer_idx == MAX_REGISTERED_WRITERS_NB)
- return AVERROR(ENOMEM);
-
- registered_writers[next_registered_writer_idx++] = writer;
- return 0;
-}
-
-static const Writer *writer_get_by_name(const char *name)
-{
- int i;
-
- for (i = 0; registered_writers[i]; i++)
- if (!strcmp(registered_writers[i]->name, name))
- return registered_writers[i];
-
- return NULL;
-}
-
-
-/* WRITERS */
-
-#define DEFINE_WRITER_CLASS(name) \
-static const char *name##_get_name(void *ctx) \
-{ \
- return #name ; \
-} \
-static const AVClass name##_class = { \
- .class_name = #name, \
- .item_name = name##_get_name, \
- .option = name##_options \
-}
-
-/* Default output */
-
-typedef struct DefaultContext {
- const AVClass *class;
- int nokey;
- int noprint_wrappers;
- int nested_section[SECTION_MAX_NB_LEVELS];
-} DefaultContext;
-
-#undef OFFSET
-#define OFFSET(x) offsetof(DefaultContext, x)
-
-static const AVOption default_options[] = {
- { "noprint_wrappers", "do not print headers and footers", OFFSET(noprint_wrappers), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1 },
- { "nw", "do not print headers and footers", OFFSET(noprint_wrappers), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1 },
- { "nokey", "force no key printing", OFFSET(nokey), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1 },
- { "nk", "force no key printing", OFFSET(nokey), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1 },
- {NULL},
-};
-
-DEFINE_WRITER_CLASS(default);
-
-/* lame uppercasing routine, assumes the string is lower case ASCII */
-static inline char *upcase_string(char *dst, size_t dst_size, const char *src)
-{
- int i;
- for (i = 0; src[i] && i < dst_size-1; i++)
- dst[i] = av_toupper(src[i]);
- dst[i] = 0;
- return dst;
-}
-
-static void default_print_section_header(WriterContext *wctx, const void *data)
-{
- DefaultContext *def = wctx->priv;
- char buf[32];
- const struct section *section = wctx->section[wctx->level];
- const struct section *parent_section = wctx->level ?
- wctx->section[wctx->level-1] : NULL;
-
- av_bprint_clear(&wctx->section_pbuf[wctx->level]);
- if (parent_section &&
- !(parent_section->flags & (SECTION_FLAG_IS_WRAPPER|SECTION_FLAG_IS_ARRAY))) {
- def->nested_section[wctx->level] = 1;
- av_bprintf(&wctx->section_pbuf[wctx->level], "%s%s:",
- wctx->section_pbuf[wctx->level-1].str,
- upcase_string(buf, sizeof(buf),
- av_x_if_null(section->element_name, section->name)));
- }
-
- if (def->noprint_wrappers || def->nested_section[wctx->level])
- return;
-
- if (!(section->flags & (SECTION_FLAG_IS_WRAPPER|SECTION_FLAG_IS_ARRAY)))
- writer_printf(wctx, "[%s]\n", upcase_string(buf, sizeof(buf), section->name));
-}
-
-static void default_print_section_footer(WriterContext *wctx)
-{
- DefaultContext *def = wctx->priv;
- const struct section *section = wctx->section[wctx->level];
- char buf[32];
-
- if (def->noprint_wrappers || def->nested_section[wctx->level])
- return;
-
- if (!(section->flags & (SECTION_FLAG_IS_WRAPPER|SECTION_FLAG_IS_ARRAY)))
- writer_printf(wctx, "[/%s]\n", upcase_string(buf, sizeof(buf), section->name));
-}
-
-static void default_print_str(WriterContext *wctx, const char *key, const char *value)
-{
- DefaultContext *def = wctx->priv;
-
- if (!def->nokey)
- writer_printf(wctx, "%s%s=", wctx->section_pbuf[wctx->level].str, key);
- writer_printf(wctx, "%s\n", value);
-}
-
-static void default_print_int(WriterContext *wctx, const char *key, int64_t value)
-{
- DefaultContext *def = wctx->priv;
-
- if (!def->nokey)
- writer_printf(wctx, "%s%s=", wctx->section_pbuf[wctx->level].str, key);
- writer_printf(wctx, "%"PRId64"\n", value);
-}
-
-static const Writer default_writer = {
- .name = "default",
- .priv_size = sizeof(DefaultContext),
- .print_section_header = default_print_section_header,
- .print_section_footer = default_print_section_footer,
- .print_integer = default_print_int,
- .print_string = default_print_str,
- .flags = WRITER_FLAG_DISPLAY_OPTIONAL_FIELDS,
- .priv_class = &default_class,
-};
-
-/* Compact output */
-
-/**
- * Apply C-language-like string escaping.
- */
-static const char *c_escape_str(AVBPrint *dst, const char *src, const char sep, void *log_ctx)
-{
- const char *p;
-
- for (p = src; *p; p++) {
- switch (*p) {
- case '\b': av_bprintf(dst, "%s", "\\b"); break;
- case '\f': av_bprintf(dst, "%s", "\\f"); break;
- case '\n': av_bprintf(dst, "%s", "\\n"); break;
- case '\r': av_bprintf(dst, "%s", "\\r"); break;
- case '\\': av_bprintf(dst, "%s", "\\\\"); break;
- default:
- if (*p == sep)
- av_bprint_chars(dst, '\\', 1);
- av_bprint_chars(dst, *p, 1);
- }
- }
- return dst->str;
-}
-
-/**
- * Quote fields containing special characters, check RFC4180.
- */
-static const char *csv_escape_str(AVBPrint *dst, const char *src, const char sep, void *log_ctx)
-{
- char meta_chars[] = { sep, '"', '\n', '\r', '\0' };
- int needs_quoting = !!src[strcspn(src, meta_chars)];
-
- if (needs_quoting)
- av_bprint_chars(dst, '"', 1);
-
- for (; *src; src++) {
- if (*src == '"')
- av_bprint_chars(dst, '"', 1);
- av_bprint_chars(dst, *src, 1);
- }
- if (needs_quoting)
- av_bprint_chars(dst, '"', 1);
- return dst->str;
-}
-
-static const char *none_escape_str(AVBPrint *dst, const char *src, const char sep, void *log_ctx)
-{
- return src;
-}
-
-typedef struct CompactContext {
- const AVClass *class;
- char *item_sep_str;
- char item_sep;
- int nokey;
- int print_section;
- char *escape_mode_str;
- const char * (*escape_str)(AVBPrint *dst, const char *src, const char sep, void *log_ctx);
- int nested_section[SECTION_MAX_NB_LEVELS];
- int has_nested_elems[SECTION_MAX_NB_LEVELS];
- int terminate_line[SECTION_MAX_NB_LEVELS];
-} CompactContext;
-
-#undef OFFSET
-#define OFFSET(x) offsetof(CompactContext, x)
-
-static const AVOption compact_options[]= {
- {"item_sep", "set item separator", OFFSET(item_sep_str), AV_OPT_TYPE_STRING, {.str="|"}, 0, 0 },
- {"s", "set item separator", OFFSET(item_sep_str), AV_OPT_TYPE_STRING, {.str="|"}, 0, 0 },
- {"nokey", "force no key printing", OFFSET(nokey), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1 },
- {"nk", "force no key printing", OFFSET(nokey), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1 },
- {"escape", "set escape mode", OFFSET(escape_mode_str), AV_OPT_TYPE_STRING, {.str="c"}, 0, 0 },
- {"e", "set escape mode", OFFSET(escape_mode_str), AV_OPT_TYPE_STRING, {.str="c"}, 0, 0 },
- {"print_section", "print section name", OFFSET(print_section), AV_OPT_TYPE_BOOL, {.i64=1}, 0, 1 },
- {"p", "print section name", OFFSET(print_section), AV_OPT_TYPE_BOOL, {.i64=1}, 0, 1 },
- {NULL},
-};
-
-DEFINE_WRITER_CLASS(compact);
-
-static av_cold int compact_init(WriterContext *wctx)
-{
- CompactContext *compact = wctx->priv;
-
- if (strlen(compact->item_sep_str) != 1) {
- av_log(wctx, AV_LOG_ERROR, "Item separator '%s' specified, but must contain a single character\n",
- compact->item_sep_str);
- return AVERROR(EINVAL);
- }
- compact->item_sep = compact->item_sep_str[0];
-
- if (!strcmp(compact->escape_mode_str, "none")) compact->escape_str = none_escape_str;
- else if (!strcmp(compact->escape_mode_str, "c" )) compact->escape_str = c_escape_str;
- else if (!strcmp(compact->escape_mode_str, "csv" )) compact->escape_str = csv_escape_str;
- else {
- av_log(wctx, AV_LOG_ERROR, "Unknown escape mode '%s'\n", compact->escape_mode_str);
- return AVERROR(EINVAL);
- }
-
- return 0;
-}
-
-static void compact_print_section_header(WriterContext *wctx, const void *data)
-{
- CompactContext *compact = wctx->priv;
- const struct section *section = wctx->section[wctx->level];
- const struct section *parent_section = wctx->level ?
- wctx->section[wctx->level-1] : NULL;
- compact->terminate_line[wctx->level] = 1;
- compact->has_nested_elems[wctx->level] = 0;
-
- av_bprint_clear(&wctx->section_pbuf[wctx->level]);
- if (parent_section &&
- (section->flags & SECTION_FLAG_HAS_TYPE ||
- (!(section->flags & SECTION_FLAG_IS_ARRAY) &&
- !(parent_section->flags & (SECTION_FLAG_IS_WRAPPER|SECTION_FLAG_IS_ARRAY))))) {
-
- /* define a prefix for elements not contained in an array or
- in a wrapper, or for array elements with a type */
- const char *element_name = (char *)av_x_if_null(section->element_name, section->name);
- AVBPrint *section_pbuf = &wctx->section_pbuf[wctx->level];
-
- compact->nested_section[wctx->level] = 1;
- compact->has_nested_elems[wctx->level-1] = 1;
-
- av_bprintf(section_pbuf, "%s%s",
- wctx->section_pbuf[wctx->level-1].str, element_name);
-
- if (section->flags & SECTION_FLAG_HAS_TYPE) {
- // add /TYPE to prefix
- av_bprint_chars(section_pbuf, '/', 1);
-
- // normalize section type, replace special characters and lower case
- for (const char *p = section->get_type(data); *p; p++) {
- char c =
- (*p >= '0' && *p <= '9') ||
- (*p >= 'a' && *p <= 'z') ||
- (*p >= 'A' && *p <= 'Z') ? av_tolower(*p) : '_';
- av_bprint_chars(section_pbuf, c, 1);
- }
- }
- av_bprint_chars(section_pbuf, ':', 1);
-
- wctx->nb_item[wctx->level] = wctx->nb_item[wctx->level-1];
- } else {
- if (parent_section && !(parent_section->flags & (SECTION_FLAG_IS_WRAPPER|SECTION_FLAG_IS_ARRAY)) &&
- wctx->level && wctx->nb_item[wctx->level-1])
- writer_w8(wctx, compact->item_sep);
- if (compact->print_section &&
- !(section->flags & (SECTION_FLAG_IS_WRAPPER|SECTION_FLAG_IS_ARRAY)))
- writer_printf(wctx, "%s%c", section->name, compact->item_sep);
- }
-}
-
-static void compact_print_section_footer(WriterContext *wctx)
-{
- CompactContext *compact = wctx->priv;
-
- if (!compact->nested_section[wctx->level] &&
- compact->terminate_line[wctx->level] &&
- !(wctx->section[wctx->level]->flags & (SECTION_FLAG_IS_WRAPPER|SECTION_FLAG_IS_ARRAY)))
- writer_w8(wctx, '\n');
-}
-
-static void compact_print_str(WriterContext *wctx, const char *key, const char *value)
-{
- CompactContext *compact = wctx->priv;
- AVBPrint buf;
-
- if (wctx->nb_item[wctx->level]) writer_w8(wctx, compact->item_sep);
- if (!compact->nokey)
- writer_printf(wctx, "%s%s=", wctx->section_pbuf[wctx->level].str, key);
- av_bprint_init(&buf, 1, AV_BPRINT_SIZE_UNLIMITED);
- writer_put_str(wctx, compact->escape_str(&buf, value, compact->item_sep, wctx));
- av_bprint_finalize(&buf, NULL);
-}
-
-static void compact_print_int(WriterContext *wctx, const char *key, int64_t value)
-{
- CompactContext *compact = wctx->priv;
-
- if (wctx->nb_item[wctx->level]) writer_w8(wctx, compact->item_sep);
- if (!compact->nokey)
- writer_printf(wctx, "%s%s=", wctx->section_pbuf[wctx->level].str, key);
- writer_printf(wctx, "%"PRId64, value);
-}
-
-static const Writer compact_writer = {
- .name = "compact",
- .priv_size = sizeof(CompactContext),
- .init = compact_init,
- .print_section_header = compact_print_section_header,
- .print_section_footer = compact_print_section_footer,
- .print_integer = compact_print_int,
- .print_string = compact_print_str,
- .flags = WRITER_FLAG_DISPLAY_OPTIONAL_FIELDS,
- .priv_class = &compact_class,
-};
-
-/* CSV output */
-
-#undef OFFSET
-#define OFFSET(x) offsetof(CompactContext, x)
-
-static const AVOption csv_options[] = {
- {"item_sep", "set item separator", OFFSET(item_sep_str), AV_OPT_TYPE_STRING, {.str=","}, 0, 0 },
- {"s", "set item separator", OFFSET(item_sep_str), AV_OPT_TYPE_STRING, {.str=","}, 0, 0 },
- {"nokey", "force no key printing", OFFSET(nokey), AV_OPT_TYPE_BOOL, {.i64=1}, 0, 1 },
- {"nk", "force no key printing", OFFSET(nokey), AV_OPT_TYPE_BOOL, {.i64=1}, 0, 1 },
- {"escape", "set escape mode", OFFSET(escape_mode_str), AV_OPT_TYPE_STRING, {.str="csv"}, 0, 0 },
- {"e", "set escape mode", OFFSET(escape_mode_str), AV_OPT_TYPE_STRING, {.str="csv"}, 0, 0 },
- {"print_section", "print section name", OFFSET(print_section), AV_OPT_TYPE_BOOL, {.i64=1}, 0, 1 },
- {"p", "print section name", OFFSET(print_section), AV_OPT_TYPE_BOOL, {.i64=1}, 0, 1 },
- {NULL},
-};
-
-DEFINE_WRITER_CLASS(csv);
-
-static const Writer csv_writer = {
- .name = "csv",
- .priv_size = sizeof(CompactContext),
- .init = compact_init,
- .print_section_header = compact_print_section_header,
- .print_section_footer = compact_print_section_footer,
- .print_integer = compact_print_int,
- .print_string = compact_print_str,
- .flags = WRITER_FLAG_DISPLAY_OPTIONAL_FIELDS,
- .priv_class = &csv_class,
-};
-
-/* Flat output */
-
-typedef struct FlatContext {
- const AVClass *class;
- const char *sep_str;
- char sep;
- int hierarchical;
-} FlatContext;
-
-#undef OFFSET
-#define OFFSET(x) offsetof(FlatContext, x)
-
-static const AVOption flat_options[]= {
- {"sep_char", "set separator", OFFSET(sep_str), AV_OPT_TYPE_STRING, {.str="."}, 0, 0 },
- {"s", "set separator", OFFSET(sep_str), AV_OPT_TYPE_STRING, {.str="."}, 0, 0 },
- {"hierarchical", "specify if the section specification should be hierarchical", OFFSET(hierarchical), AV_OPT_TYPE_BOOL, {.i64=1}, 0, 1 },
- {"h", "specify if the section specification should be hierarchical", OFFSET(hierarchical), AV_OPT_TYPE_BOOL, {.i64=1}, 0, 1 },
- {NULL},
-};
-
-DEFINE_WRITER_CLASS(flat);
-
-static av_cold int flat_init(WriterContext *wctx)
-{
- FlatContext *flat = wctx->priv;
-
- if (strlen(flat->sep_str) != 1) {
- av_log(wctx, AV_LOG_ERROR, "Item separator '%s' specified, but must contain a single character\n",
- flat->sep_str);
- return AVERROR(EINVAL);
- }
- flat->sep = flat->sep_str[0];
-
- return 0;
-}
-
-static const char *flat_escape_key_str(AVBPrint *dst, const char *src, const char sep)
-{
- const char *p;
-
- for (p = src; *p; p++) {
- if (!((*p >= '0' && *p <= '9') ||
- (*p >= 'a' && *p <= 'z') ||
- (*p >= 'A' && *p <= 'Z')))
- av_bprint_chars(dst, '_', 1);
- else
- av_bprint_chars(dst, *p, 1);
- }
- return dst->str;
-}
-
-static const char *flat_escape_value_str(AVBPrint *dst, const char *src)
-{
- const char *p;
-
- for (p = src; *p; p++) {
- switch (*p) {
- case '\n': av_bprintf(dst, "%s", "\\n"); break;
- case '\r': av_bprintf(dst, "%s", "\\r"); break;
- case '\\': av_bprintf(dst, "%s", "\\\\"); break;
- case '"': av_bprintf(dst, "%s", "\\\""); break;
- case '`': av_bprintf(dst, "%s", "\\`"); break;
- case '$': av_bprintf(dst, "%s", "\\$"); break;
- default: av_bprint_chars(dst, *p, 1); break;
- }
- }
- return dst->str;
-}
-
-static void flat_print_section_header(WriterContext *wctx, const void *data)
-{
- FlatContext *flat = wctx->priv;
- AVBPrint *buf = &wctx->section_pbuf[wctx->level];
- const struct section *section = wctx->section[wctx->level];
- const struct section *parent_section = wctx->level ?
- wctx->section[wctx->level-1] : NULL;
-
- /* build section header */
- av_bprint_clear(buf);
- if (!parent_section)
- return;
- av_bprintf(buf, "%s", wctx->section_pbuf[wctx->level-1].str);
-
- if (flat->hierarchical ||
- !(section->flags & (SECTION_FLAG_IS_ARRAY|SECTION_FLAG_IS_WRAPPER))) {
- av_bprintf(buf, "%s%s", wctx->section[wctx->level]->name, flat->sep_str);
-
- if (parent_section->flags & SECTION_FLAG_IS_ARRAY) {
- int n = parent_section->id == SECTION_ID_PACKETS_AND_FRAMES ?
- wctx->nb_section_packet_frame : wctx->nb_item[wctx->level-1];
- av_bprintf(buf, "%d%s", n, flat->sep_str);
- }
- }
-}
-
-static void flat_print_int(WriterContext *wctx, const char *key, int64_t value)
-{
- writer_printf(wctx, "%s%s=%"PRId64"\n", wctx->section_pbuf[wctx->level].str, key, value);
-}
-
-static void flat_print_str(WriterContext *wctx, const char *key, const char *value)
-{
- FlatContext *flat = wctx->priv;
- AVBPrint buf;
-
- writer_put_str(wctx, wctx->section_pbuf[wctx->level].str);
- av_bprint_init(&buf, 1, AV_BPRINT_SIZE_UNLIMITED);
- writer_printf(wctx, "%s=", flat_escape_key_str(&buf, key, flat->sep));
- av_bprint_clear(&buf);
- writer_printf(wctx, "\"%s\"\n", flat_escape_value_str(&buf, value));
- av_bprint_finalize(&buf, NULL);
-}
-
-static const Writer flat_writer = {
- .name = "flat",
- .priv_size = sizeof(FlatContext),
- .init = flat_init,
- .print_section_header = flat_print_section_header,
- .print_integer = flat_print_int,
- .print_string = flat_print_str,
- .flags = WRITER_FLAG_DISPLAY_OPTIONAL_FIELDS|WRITER_FLAG_PUT_PACKETS_AND_FRAMES_IN_SAME_CHAPTER,
- .priv_class = &flat_class,
-};
-
-/* INI format output */
-
-typedef struct INIContext {
- const AVClass *class;
- int hierarchical;
-} INIContext;
-
-#undef OFFSET
-#define OFFSET(x) offsetof(INIContext, x)
-
-static const AVOption ini_options[] = {
- {"hierarchical", "specify if the section specification should be hierarchical", OFFSET(hierarchical), AV_OPT_TYPE_BOOL, {.i64=1}, 0, 1 },
- {"h", "specify if the section specification should be hierarchical", OFFSET(hierarchical), AV_OPT_TYPE_BOOL, {.i64=1}, 0, 1 },
- {NULL},
-};
-
-DEFINE_WRITER_CLASS(ini);
-
-static char *ini_escape_str(AVBPrint *dst, const char *src)
-{
- int i = 0;
- char c = 0;
-
- while (c = src[i++]) {
- switch (c) {
- case '\b': av_bprintf(dst, "%s", "\\b"); break;
- case '\f': av_bprintf(dst, "%s", "\\f"); break;
- case '\n': av_bprintf(dst, "%s", "\\n"); break;
- case '\r': av_bprintf(dst, "%s", "\\r"); break;
- case '\t': av_bprintf(dst, "%s", "\\t"); break;
- case '\\':
- case '#' :
- case '=' :
- case ':' : av_bprint_chars(dst, '\\', 1);
- default:
- if ((unsigned char)c < 32)
- av_bprintf(dst, "\\x00%02x", c & 0xff);
- else
- av_bprint_chars(dst, c, 1);
- break;
- }
- }
- return dst->str;
-}
-
-static void ini_print_section_header(WriterContext *wctx, const void *data)
-{
- INIContext *ini = wctx->priv;
- AVBPrint *buf = &wctx->section_pbuf[wctx->level];
- const struct section *section = wctx->section[wctx->level];
- const struct section *parent_section = wctx->level ?
- wctx->section[wctx->level-1] : NULL;
-
- av_bprint_clear(buf);
- if (!parent_section) {
- writer_put_str(wctx, "# ffprobe output\n\n");
- return;
- }
-
- if (wctx->nb_item[wctx->level-1])
- writer_w8(wctx, '\n');
-
- av_bprintf(buf, "%s", wctx->section_pbuf[wctx->level-1].str);
- if (ini->hierarchical ||
- !(section->flags & (SECTION_FLAG_IS_ARRAY|SECTION_FLAG_IS_WRAPPER))) {
- av_bprintf(buf, "%s%s", buf->str[0] ? "." : "", wctx->section[wctx->level]->name);
-
- if (parent_section->flags & SECTION_FLAG_IS_ARRAY) {
- int n = parent_section->id == SECTION_ID_PACKETS_AND_FRAMES ?
- wctx->nb_section_packet_frame : wctx->nb_item[wctx->level-1];
- av_bprintf(buf, ".%d", n);
- }
- }
-
- if (!(section->flags & (SECTION_FLAG_IS_ARRAY|SECTION_FLAG_IS_WRAPPER)))
- writer_printf(wctx, "[%s]\n", buf->str);
-}
-
-static void ini_print_str(WriterContext *wctx, const char *key, const char *value)
-{
- AVBPrint buf;
-
- av_bprint_init(&buf, 1, AV_BPRINT_SIZE_UNLIMITED);
- writer_printf(wctx, "%s=", ini_escape_str(&buf, key));
- av_bprint_clear(&buf);
- writer_printf(wctx, "%s\n", ini_escape_str(&buf, value));
- av_bprint_finalize(&buf, NULL);
-}
-
-static void ini_print_int(WriterContext *wctx, const char *key, int64_t value)
-{
- writer_printf(wctx, "%s=%"PRId64"\n", key, value);
-}
-
-static const Writer ini_writer = {
- .name = "ini",
- .priv_size = sizeof(INIContext),
- .print_section_header = ini_print_section_header,
- .print_integer = ini_print_int,
- .print_string = ini_print_str,
- .flags = WRITER_FLAG_DISPLAY_OPTIONAL_FIELDS|WRITER_FLAG_PUT_PACKETS_AND_FRAMES_IN_SAME_CHAPTER,
- .priv_class = &ini_class,
-};
-
-/* JSON output */
-
-typedef struct JSONContext {
- const AVClass *class;
- int indent_level;
- int compact;
- const char *item_sep, *item_start_end;
-} JSONContext;
-
-#undef OFFSET
-#define OFFSET(x) offsetof(JSONContext, x)
-
-static const AVOption json_options[]= {
- { "compact", "enable compact output", OFFSET(compact), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1 },
- { "c", "enable compact output", OFFSET(compact), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1 },
- { NULL }
-};
-
-DEFINE_WRITER_CLASS(json);
-
-static av_cold int json_init(WriterContext *wctx)
-{
- JSONContext *json = wctx->priv;
-
- json->item_sep = json->compact ? ", " : ",\n";
- json->item_start_end = json->compact ? " " : "\n";
-
- return 0;
-}
-
-static const char *json_escape_str(AVBPrint *dst, const char *src, void *log_ctx)
-{
- static const char json_escape[] = {'"', '\\', '\b', '\f', '\n', '\r', '\t', 0};
- static const char json_subst[] = {'"', '\\', 'b', 'f', 'n', 'r', 't', 0};
- const char *p;
-
- for (p = src; *p; p++) {
- char *s = strchr(json_escape, *p);
- if (s) {
- av_bprint_chars(dst, '\\', 1);
- av_bprint_chars(dst, json_subst[s - json_escape], 1);
- } else if ((unsigned char)*p < 32) {
- av_bprintf(dst, "\\u00%02x", *p & 0xff);
- } else {
- av_bprint_chars(dst, *p, 1);
- }
- }
- return dst->str;
-}
-
-#define JSON_INDENT() writer_printf(wctx, "%*c", json->indent_level * 4, ' ')
-
-static void json_print_section_header(WriterContext *wctx, const void *data)
-{
- JSONContext *json = wctx->priv;
- AVBPrint buf;
- const struct section *section = wctx->section[wctx->level];
- const struct section *parent_section = wctx->level ?
- wctx->section[wctx->level-1] : NULL;
-
- if (wctx->level && wctx->nb_item[wctx->level-1])
- writer_put_str(wctx, ",\n");
-
- if (section->flags & SECTION_FLAG_IS_WRAPPER) {
- writer_put_str(wctx, "{\n");
- json->indent_level++;
- } else {
- av_bprint_init(&buf, 1, AV_BPRINT_SIZE_UNLIMITED);
- json_escape_str(&buf, section->name, wctx);
- JSON_INDENT();
-
- json->indent_level++;
- if (section->flags & SECTION_FLAG_IS_ARRAY) {
- writer_printf(wctx, "\"%s\": [\n", buf.str);
- } else if (parent_section && !(parent_section->flags & SECTION_FLAG_IS_ARRAY)) {
- writer_printf(wctx, "\"%s\": {%s", buf.str, json->item_start_end);
- } else {
- writer_printf(wctx, "{%s", json->item_start_end);
-
- /* this is required so the parser can distinguish between packets and frames */
- if (parent_section && parent_section->id == SECTION_ID_PACKETS_AND_FRAMES) {
- if (!json->compact)
- JSON_INDENT();
- writer_printf(wctx, "\"type\": \"%s\"", section->name);
- wctx->nb_item[wctx->level]++;
- }
- }
- av_bprint_finalize(&buf, NULL);
- }
-}
-
-static void json_print_section_footer(WriterContext *wctx)
-{
- JSONContext *json = wctx->priv;
- const struct section *section = wctx->section[wctx->level];
-
- if (wctx->level == 0) {
- json->indent_level--;
- writer_put_str(wctx, "\n}\n");
- } else if (section->flags & SECTION_FLAG_IS_ARRAY) {
- writer_w8(wctx, '\n');
- json->indent_level--;
- JSON_INDENT();
- writer_w8(wctx, ']');
- } else {
- writer_put_str(wctx, json->item_start_end);
- json->indent_level--;
- if (!json->compact)
- JSON_INDENT();
- writer_w8(wctx, '}');
- }
-}
-
-static inline void json_print_item_str(WriterContext *wctx,
- const char *key, const char *value)
-{
- AVBPrint buf;
-
- av_bprint_init(&buf, 1, AV_BPRINT_SIZE_UNLIMITED);
- writer_printf(wctx, "\"%s\":", json_escape_str(&buf, key, wctx));
- av_bprint_clear(&buf);
- writer_printf(wctx, " \"%s\"", json_escape_str(&buf, value, wctx));
- av_bprint_finalize(&buf, NULL);
-}
-
-static void json_print_str(WriterContext *wctx, const char *key, const char *value)
-{
- JSONContext *json = wctx->priv;
- const struct section *parent_section = wctx->level ?
- wctx->section[wctx->level-1] : NULL;
-
- if (wctx->nb_item[wctx->level] || (parent_section && parent_section->id == SECTION_ID_PACKETS_AND_FRAMES))
- writer_put_str(wctx, json->item_sep);
- if (!json->compact)
- JSON_INDENT();
- json_print_item_str(wctx, key, value);
-}
-
-static void json_print_int(WriterContext *wctx, const char *key, int64_t value)
-{
- JSONContext *json = wctx->priv;
- const struct section *parent_section = wctx->level ?
- wctx->section[wctx->level-1] : NULL;
- AVBPrint buf;
-
- if (wctx->nb_item[wctx->level] || (parent_section && parent_section->id == SECTION_ID_PACKETS_AND_FRAMES))
- writer_put_str(wctx, json->item_sep);
- if (!json->compact)
- JSON_INDENT();
-
- av_bprint_init(&buf, 1, AV_BPRINT_SIZE_UNLIMITED);
- writer_printf(wctx, "\"%s\": %"PRId64, json_escape_str(&buf, key, wctx), value);
- av_bprint_finalize(&buf, NULL);
-}
-
-static const Writer json_writer = {
- .name = "json",
- .priv_size = sizeof(JSONContext),
- .init = json_init,
- .print_section_header = json_print_section_header,
- .print_section_footer = json_print_section_footer,
- .print_integer = json_print_int,
- .print_string = json_print_str,
- .flags = WRITER_FLAG_PUT_PACKETS_AND_FRAMES_IN_SAME_CHAPTER,
- .priv_class = &json_class,
-};
-
-/* XML output */
-
-typedef struct XMLContext {
- const AVClass *class;
- int within_tag;
- int indent_level;
- int fully_qualified;
- int xsd_strict;
-} XMLContext;
-
-#undef OFFSET
-#define OFFSET(x) offsetof(XMLContext, x)
-
-static const AVOption xml_options[] = {
- {"fully_qualified", "specify if the output should be fully qualified", OFFSET(fully_qualified), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1 },
- {"q", "specify if the output should be fully qualified", OFFSET(fully_qualified), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1 },
- {"xsd_strict", "ensure that the output is XSD compliant", OFFSET(xsd_strict), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1 },
- {"x", "ensure that the output is XSD compliant", OFFSET(xsd_strict), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1 },
- {NULL},
-};
-
-DEFINE_WRITER_CLASS(xml);
-
-static av_cold int xml_init(WriterContext *wctx)
-{
- XMLContext *xml = wctx->priv;
-
- if (xml->xsd_strict) {
- xml->fully_qualified = 1;
-#define CHECK_COMPLIANCE(opt, opt_name) \
- if (opt) { \
- av_log(wctx, AV_LOG_ERROR, \
- "XSD-compliant output selected but option '%s' was selected, XML output may be non-compliant.\n" \
- "You need to disable such option with '-no%s'\n", opt_name, opt_name); \
- return AVERROR(EINVAL); \
- }
- CHECK_COMPLIANCE(show_private_data, "private");
- CHECK_COMPLIANCE(show_value_unit, "unit");
- CHECK_COMPLIANCE(use_value_prefix, "prefix");
- }
-
- return 0;
-}
-
-#define XML_INDENT() writer_printf(wctx, "%*c", xml->indent_level * 4, ' ')
-
-static void xml_print_section_header(WriterContext *wctx, const void *data)
-{
- XMLContext *xml = wctx->priv;
- const struct section *section = wctx->section[wctx->level];
- const struct section *parent_section = wctx->level ?
- wctx->section[wctx->level-1] : NULL;
-
- if (wctx->level == 0) {
- const char *qual = " xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" "
- "xmlns:ffprobe=\"http://www.ffmpeg.org/schema/ffprobe\" "
- "xsi:schemaLocation=\"http://www.ffmpeg.org/schema/ffprobe ffprobe.xsd\"";
-
- writer_put_str(wctx, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
- writer_printf(wctx, "<%sffprobe%s>\n",
- xml->fully_qualified ? "ffprobe:" : "",
- xml->fully_qualified ? qual : "");
- return;
- }
-
- if (xml->within_tag) {
- xml->within_tag = 0;
- writer_put_str(wctx, ">\n");
- }
-
- if (parent_section && (parent_section->flags & SECTION_FLAG_IS_WRAPPER) &&
- wctx->level && wctx->nb_item[wctx->level-1])
- writer_w8(wctx, '\n');
- xml->indent_level++;
-
- if (section->flags & (SECTION_FLAG_IS_ARRAY|SECTION_FLAG_HAS_VARIABLE_FIELDS)) {
- XML_INDENT(); writer_printf(wctx, "<%s", section->name);
-
- if (section->flags & SECTION_FLAG_HAS_TYPE) {
- AVBPrint buf;
- av_bprint_init(&buf, 1, AV_BPRINT_SIZE_UNLIMITED);
- av_bprint_escape(&buf, section->get_type(data), NULL,
- AV_ESCAPE_MODE_XML, AV_ESCAPE_FLAG_XML_DOUBLE_QUOTES);
- writer_printf(wctx, " type=\"%s\"", buf.str);
- }
- writer_printf(wctx, ">\n", section->name);
- } else {
- XML_INDENT(); writer_printf(wctx, "<%s ", section->name);
- xml->within_tag = 1;
- }
-}
-
-static void xml_print_section_footer(WriterContext *wctx)
-{
- XMLContext *xml = wctx->priv;
- const struct section *section = wctx->section[wctx->level];
-
- if (wctx->level == 0) {
- writer_printf(wctx, "</%sffprobe>\n", xml->fully_qualified ? "ffprobe:" : "");
- } else if (xml->within_tag) {
- xml->within_tag = 0;
- writer_put_str(wctx, "/>\n");
- xml->indent_level--;
- } else {
- XML_INDENT(); writer_printf(wctx, "</%s>\n", section->name);
- xml->indent_level--;
- }
-}
-
-static void xml_print_value(WriterContext *wctx, const char *key,
- const char *str, int64_t num, const int is_int)
-{
- AVBPrint buf;
- XMLContext *xml = wctx->priv;
- const struct section *section = wctx->section[wctx->level];
-
- av_bprint_init(&buf, 1, AV_BPRINT_SIZE_UNLIMITED);
-
- if (section->flags & SECTION_FLAG_HAS_VARIABLE_FIELDS) {
- xml->indent_level++;
- XML_INDENT();
- av_bprint_escape(&buf, key, NULL,
- AV_ESCAPE_MODE_XML, AV_ESCAPE_FLAG_XML_DOUBLE_QUOTES);
- writer_printf(wctx, "<%s key=\"%s\"",
- section->element_name, buf.str);
- av_bprint_clear(&buf);
-
- if (is_int) {
- writer_printf(wctx, " value=\"%"PRId64"\"/>\n", num);
- } else {
- av_bprint_escape(&buf, str, NULL,
- AV_ESCAPE_MODE_XML, AV_ESCAPE_FLAG_XML_DOUBLE_QUOTES);
- writer_printf(wctx, " value=\"%s\"/>\n", buf.str);
- }
- xml->indent_level--;
- } else {
- if (wctx->nb_item[wctx->level])
- writer_w8(wctx, ' ');
-
- if (is_int) {
- writer_printf(wctx, "%s=\"%"PRId64"\"", key, num);
- } else {
- av_bprint_escape(&buf, str, NULL,
- AV_ESCAPE_MODE_XML, AV_ESCAPE_FLAG_XML_DOUBLE_QUOTES);
- writer_printf(wctx, "%s=\"%s\"", key, buf.str);
- }
- }
-
- av_bprint_finalize(&buf, NULL);
-}
-
-static inline void xml_print_str(WriterContext *wctx, const char *key, const char *value) {
- xml_print_value(wctx, key, value, 0, 0);
-}
-
-static void xml_print_int(WriterContext *wctx, const char *key, int64_t value)
-{
- xml_print_value(wctx, key, NULL, value, 1);
-}
-
-static Writer xml_writer = {
- .name = "xml",
- .priv_size = sizeof(XMLContext),
- .init = xml_init,
- .print_section_header = xml_print_section_header,
- .print_section_footer = xml_print_section_footer,
- .print_integer = xml_print_int,
- .print_string = xml_print_str,
- .flags = WRITER_FLAG_PUT_PACKETS_AND_FRAMES_IN_SAME_CHAPTER,
- .priv_class = &xml_class,
-};
-
-static void writer_register_all(void)
-{
- static int initialized;
-
- if (initialized)
- return;
- initialized = 1;
-
- writer_register(&default_writer);
- writer_register(&compact_writer);
- writer_register(&csv_writer);
- writer_register(&flat_writer);
- writer_register(&ini_writer);
- writer_register(&json_writer);
- writer_register(&xml_writer);
-}
#define print_fmt(k, f, ...) do { \
av_bprint_clear(&pbuf); \
av_bprintf(&pbuf, f, __VA_ARGS__); \
- writer_print_string(w, k, pbuf.str, 0); \
+ avtext_print_string(w, k, pbuf.str, 0); \
} while (0)
#define print_list_fmt(k, f, n, m, ...) do { \
@@ -2000,28 +424,19 @@ static void writer_register_all(void)
av_bprintf(&pbuf, f, __VA_ARGS__); \
} \
} \
- writer_print_string(w, k, pbuf.str, 0); \
+ avtext_print_string(w, k, pbuf.str, 0); \
} while (0)
-#define print_int(k, v) writer_print_integer(w, k, v)
-#define print_q(k, v, s) writer_print_rational(w, k, v, s)
-#define print_str(k, v) writer_print_string(w, k, v, 0)
-#define print_str_opt(k, v) writer_print_string(w, k, v, PRINT_STRING_OPT)
-#define print_str_validate(k, v) writer_print_string(w, k, v, PRINT_STRING_VALIDATE)
-#define print_time(k, v, tb) writer_print_time(w, k, v, tb, 0)
-#define print_ts(k, v) writer_print_ts(w, k, v, 0)
-#define print_duration_time(k, v, tb) writer_print_time(w, k, v, tb, 1)
-#define print_duration_ts(k, v) writer_print_ts(w, k, v, 1)
-#define print_val(k, v, u) do { \
- struct unit_value uv; \
- uv.val.i = v; \
- uv.unit = u; \
- writer_print_string(w, k, value_string(val_str, sizeof(val_str), uv), 0); \
-} while (0)
-
-#define print_section_header(s) writer_print_section_header(w, NULL, s)
-#define print_section_header_data(s, d) writer_print_section_header(w, d, s)
-#define print_section_footer(s) writer_print_section_footer(w, s)
+#define print_int(k, v) avtext_print_integer(w, k, v)
+#define print_q(k, v, s) avtext_print_rational(w, k, v, s)
+#define print_str(k, v) avtext_print_string(w, k, v, 0)
+#define print_str_opt(k, v) avtext_print_string(w, k, v, AV_TEXTFORMAT_PRINT_STRING_OPTIONAL)
+#define print_str_validate(k, v) avtext_print_string(w, k, v, AV_TEXTFORMAT_PRINT_STRING_VALIDATE)
+#define print_time(k, v, tb) avtext_print_time(w, k, v, tb, 0)
+#define print_ts(k, v) avtext_print_ts(w, k, v, 0)
+#define print_duration_time(k, v, tb) avtext_print_time(w, k, v, tb, 1)
+#define print_duration_ts(k, v) avtext_print_ts(w, k, v, 1)
+#define print_val(k, v, u) avtext_print_unit_int(w, k, v, u)
#define REALLOCZ_ARRAY_STREAM(ptr, cur_n, new_n) \
{ \
@@ -2529,7 +944,7 @@ static void print_pkt_side_data(WriterContext *w,
double rotation = av_display_rotation_get((int32_t *)sd->data);
if (isnan(rotation))
rotation = 0;
- writer_print_integers(w, "displaymatrix", sd->data, 9, " %11d", 3, 4, 1);
+ avtext_print_integers(w, "displaymatrix", sd->data, 9, " %11d", 3, 4, 1);
print_int("rotation", rotation);
} else if (sd->type == AV_PKT_DATA_STEREO3D) {
const AVStereo3D *stereo = (AVStereo3D *)sd->data;
@@ -2626,8 +1041,8 @@ static void print_pkt_side_data(WriterContext *w,
} else if (sd->type == AV_PKT_DATA_WEBVTT_IDENTIFIER ||
sd->type == AV_PKT_DATA_WEBVTT_SETTINGS) {
if (do_show_data)
- writer_print_data(w, "data", sd->data, sd->size);
- writer_print_data_hash(w, "data_hash", sd->data, sd->size);
+ avtext_print_data(w, "data", sd->data, sd->size);
+ avtext_print_data_hash(w, "data_hash", sd->data, sd->size);
} else if (sd->type == AV_PKT_DATA_FRAME_CROPPING && sd->size >= sizeof(uint32_t) * 4) {
print_int("crop_top", AV_RL32(sd->data));
print_int("crop_bottom", AV_RL32(sd->data + 4));
@@ -2754,7 +1169,6 @@ static int show_log(WriterContext *w, int section_ids, int section_id, int log_l
static void show_packet(WriterContext *w, InputFile *ifile, AVPacket *pkt, int packet_idx)
{
- char val_str[128];
AVStream *st = ifile->streams[pkt->stream_index].st;
AVBPrint pbuf;
const char *s;
@@ -2780,8 +1194,8 @@ static void show_packet(WriterContext *w, InputFile *ifile, AVPacket *pkt, int p
pkt->flags & AV_PKT_FLAG_DISCARD ? 'D' : '_',
pkt->flags & AV_PKT_FLAG_CORRUPT ? 'C' : '_');
if (do_show_data)
- writer_print_data(w, "data", pkt->data, pkt->size);
- writer_print_data_hash(w, "data_hash", pkt->data, pkt->size);
+ avtext_print_data(w, "data", pkt->data, pkt->size);
+ avtext_print_data_hash(w, "data_hash", pkt->data, pkt->size);
if (pkt->side_data_elems) {
size_t size;
@@ -2850,7 +1264,7 @@ static void print_frame_side_data(WriterContext *w,
double rotation = av_display_rotation_get((int32_t *)sd->data);
if (isnan(rotation))
rotation = 0;
- writer_print_integers(w, "displaymatrix", sd->data, 9, " %11d", 3, 4, 1);
+ avtext_print_integers(w, "displaymatrix", sd->data, 9, " %11d", 3, 4, 1);
print_int("rotation", rotation);
} else if (sd->type == AV_FRAME_DATA_AFD && sd->size > 0) {
print_int("active_format", *sd->data);
@@ -3450,12 +1864,12 @@ static int show_stream(WriterContext *w, AVFormatContext *fmt_ctx, int stream_id
if (nb_streams_packets[stream_idx]) print_fmt ("nb_read_packets", "%"PRIu64, nb_streams_packets[stream_idx]);
else print_str_opt("nb_read_packets", "N/A");
if (do_show_data)
- writer_print_data(w, "extradata", par->extradata,
+ avtext_print_data(w, "extradata", par->extradata,
par->extradata_size);
if (par->extradata_size > 0) {
print_int("extradata_size", par->extradata_size);
- writer_print_data_hash(w, "extradata_hash", par->extradata,
+ avtext_print_data_hash(w, "extradata_hash", par->extradata,
par->extradata_size);
}
@@ -3829,7 +2243,6 @@ static int show_chapters(WriterContext *w, InputFile *ifile)
static int show_format(WriterContext *w, InputFile *ifile)
{
AVFormatContext *fmt_ctx = ifile->fmt_ctx;
- char val_str[128];
int64_t size = fmt_ctx->pb ? avio_size(fmt_ctx->pb) : -1;
int ret = 0;
@@ -4005,7 +2418,7 @@ static void close_input_file(InputFile *ifile)
avformat_close_input(&ifile->fmt_ctx);
}
-static int probe_file(WriterContext *wctx, const char *filename,
+static int probe_file(WriterContext *tctx, const char *filename,
const char *print_filename)
{
InputFile ifile = { 0 };
@@ -4047,40 +2460,40 @@ static int probe_file(WriterContext *wctx, const char *filename,
if (do_read_frames || do_read_packets) {
if (do_show_frames && do_show_packets &&
- wctx->writer->flags & WRITER_FLAG_PUT_PACKETS_AND_FRAMES_IN_SAME_CHAPTER)
+ tctx->formatter->flags & AV_TEXTFORMAT_FLAG_SUPPORTS_MIXED_ARRAY_CONTENT)
section_id = SECTION_ID_PACKETS_AND_FRAMES;
else if (do_show_packets && !do_show_frames)
section_id = SECTION_ID_PACKETS;
else // (!do_show_packets && do_show_frames)
section_id = SECTION_ID_FRAMES;
if (do_show_frames || do_show_packets)
- writer_print_section_header(wctx, NULL, section_id);
- ret = read_packets(wctx, &ifile);
+ writer_print_section_header(tctx, NULL, section_id);
+ ret = read_packets(tctx, &ifile);
if (do_show_frames || do_show_packets)
- writer_print_section_footer(wctx);
+ writer_print_section_footer(tctx);
CHECK_END;
}
if (do_show_programs) {
- ret = show_programs(wctx, &ifile);
+ ret = show_programs(tctx, &ifile);
CHECK_END;
}
if (do_show_stream_groups) {
- ret = show_stream_groups(wctx, &ifile);
+ ret = show_stream_groups(tctx, &ifile);
CHECK_END;
}
if (do_show_streams) {
- ret = show_streams(wctx, &ifile);
+ ret = show_streams(tctx, &ifile);
CHECK_END;
}
if (do_show_chapters) {
- ret = show_chapters(wctx, &ifile);
+ ret = show_chapters(tctx, &ifile);
CHECK_END;
}
if (do_show_format) {
- ret = show_format(wctx, &ifile);
+ ret = show_format(tctx, &ifile);
CHECK_END;
}
@@ -4229,11 +2642,11 @@ static int opt_format(void *optctx, const char *opt, const char *arg)
static inline void mark_section_show_entries(SectionID section_id,
int show_all_entries, AVDictionary *entries)
{
- struct section *section = §ions[section_id];
+ struct AVTextFormatSection *section = §ions[section_id];
section->show_all_entries = show_all_entries;
if (show_all_entries) {
- for (const SectionID *id = section->children_ids; *id != -1; id++)
+ for (const int *id = section->children_ids; *id != -1; id++)
mark_section_show_entries(*id, show_all_entries, entries);
} else {
av_dict_copy(§ion->entries_to_show, entries, 0);
@@ -4246,7 +2659,7 @@ static int match_section(const char *section_name,
int i, ret = 0;
for (i = 0; i < FF_ARRAY_ELEMS(sections); i++) {
- const struct section *section = §ions[i];
+ const struct AVTextFormatSection *section = §ions[i];
if (!strcmp(section_name, section->name) ||
(section->unique_name && !strcmp(section_name, section->unique_name))) {
av_log(NULL, AV_LOG_DEBUG,
@@ -4518,13 +2931,13 @@ static int opt_pretty(void *optctx, const char *opt, const char *arg)
static void print_section(SectionID id, int level)
{
- const SectionID *pid;
- const struct section *section = §ions[id];
+ const int *pid;
+ const struct AVTextFormatSection *section = §ions[id];
printf("%c%c%c%c",
- section->flags & SECTION_FLAG_IS_WRAPPER ? 'W' : '.',
- section->flags & SECTION_FLAG_IS_ARRAY ? 'A' : '.',
- section->flags & SECTION_FLAG_HAS_VARIABLE_FIELDS ? 'V' : '.',
- section->flags & SECTION_FLAG_HAS_TYPE ? 'T' : '.');
+ section->flags & AV_TEXTFORMAT_SECTION_FLAG_IS_WRAPPER ? 'W' : '.',
+ section->flags & AV_TEXTFORMAT_SECTION_FLAG_IS_ARRAY ? 'A' : '.',
+ section->flags & AV_TEXTFORMAT_SECTION_FLAG_HAS_VARIABLE_FIELDS ? 'V' : '.',
+ section->flags & AV_TEXTFORMAT_SECTION_FLAG_HAS_TYPE ? 'T' : '.');
printf("%*c %s", level * 4, ' ', section->name);
if (section->unique_name)
printf("/%s", section->unique_name);
@@ -4627,10 +3040,10 @@ static const OptionDef real_options[] = {
static inline int check_section_show_entries(int section_id)
{
- struct section *section = §ions[section_id];
+ struct AVTextFormatSection *section = §ions[section_id];
if (sections[section_id].show_all_entries || sections[section_id].entries_to_show)
return 1;
- for (const SectionID *id = section->children_ids; *id != -1; id++)
+ for (const int *id = section->children_ids; *id != -1; id++)
if (check_section_show_entries(*id))
return 1;
return 0;
@@ -4643,10 +3056,11 @@ static inline int check_section_show_entries(int section_id)
int main(int argc, char **argv)
{
- const Writer *w;
- WriterContext *wctx;
+ const AVTextFormatter *f;
+ WriterContext *tctx;
+ AVTextWriterContext *wctx;
char *buf;
- char *w_name = NULL, *w_args = NULL;
+ char *f_name = NULL, *f_args = NULL;
int ret, input_ret, i;
init_dynload();
@@ -4708,58 +3122,51 @@ int main(int argc, char **argv)
goto end;
}
- writer_register_all();
-
if (!output_format)
output_format = av_strdup("default");
if (!output_format) {
ret = AVERROR(ENOMEM);
goto end;
}
- w_name = av_strtok(output_format, "=", &buf);
- if (!w_name) {
+ f_name = av_strtok(output_format, "=", &buf);
+ if (!f_name) {
av_log(NULL, AV_LOG_ERROR,
"No name specified for the output format\n");
ret = AVERROR(EINVAL);
goto end;
}
- w_args = buf;
-
- if (show_data_hash) {
- if ((ret = av_hash_alloc(&hash, show_data_hash)) < 0) {
- if (ret == AVERROR(EINVAL)) {
- const char *n;
- av_log(NULL, AV_LOG_ERROR,
- "Unknown hash algorithm '%s'\nKnown algorithms:",
- show_data_hash);
- for (i = 0; (n = av_hash_names(i)); i++)
- av_log(NULL, AV_LOG_ERROR, " %s", n);
- av_log(NULL, AV_LOG_ERROR, "\n");
- }
- goto end;
- }
- }
+ f_args = buf;
- w = writer_get_by_name(w_name);
- if (!w) {
- av_log(NULL, AV_LOG_ERROR, "Unknown output format with name '%s'\n", w_name);
+ f = avtext_get_formatter_by_name(f_name);
+ if (!f) {
+ av_log(NULL, AV_LOG_ERROR, "Unknown output format with name '%s'\n", f_name);
ret = AVERROR(EINVAL);
goto end;
}
- if ((ret = writer_open(&wctx, w, w_args,
- sections, FF_ARRAY_ELEMS(sections), output_filename)) >= 0) {
- if (w == &xml_writer)
- wctx->string_validation_utf8_flags |= AV_UTF8_FLAG_EXCLUDE_XML_INVALID_CONTROL_CODES;
+ if (output_filename) {
+ ret = avtextwriter_create_file(&wctx, output_filename, 1);
+ } else
+ ret = avtextwriter_create_stdout(&wctx);
- writer_print_section_header(wctx, NULL, SECTION_ID_ROOT);
+ if (ret < 0)
+ goto end;
+
+ if ((ret = avtext_context_open(&tctx, f, wctx, f_args,
+ sections, FF_ARRAY_ELEMS(sections), show_value_unit,
+ use_value_prefix, use_byte_value_binary_prefix, use_value_sexagesimal_format,
+ show_optional_fields, show_data_hash)) >= 0) {
+ if (f == &avtextformatter_xml)
+ tctx->string_validation_utf8_flags |= AV_UTF8_FLAG_EXCLUDE_XML_INVALID_CONTROL_CODES;
+
+ writer_print_section_header(tctx, NULL, SECTION_ID_ROOT);
if (do_show_program_version)
- ffprobe_show_program_version(wctx);
+ ffprobe_show_program_version(tctx);
if (do_show_library_versions)
- ffprobe_show_library_versions(wctx);
+ ffprobe_show_library_versions(tctx);
if (do_show_pixel_formats)
- ffprobe_show_pixel_formats(wctx);
+ ffprobe_show_pixel_formats(tctx);
if (!input_filename &&
((do_show_format || do_show_programs || do_show_stream_groups || do_show_streams || do_show_chapters || do_show_packets || do_show_error) ||
@@ -4769,17 +3176,22 @@ int main(int argc, char **argv)
av_log(NULL, AV_LOG_ERROR, "Use -h to get full help or, even better, run 'man %s'.\n", program_name);
ret = AVERROR(EINVAL);
} else if (input_filename) {
- ret = probe_file(wctx, input_filename, print_input_filename);
+ ret = probe_file(tctx, input_filename, print_input_filename);
if (ret < 0 && do_show_error)
- show_error(wctx, ret);
+ show_error(tctx, ret);
}
input_ret = ret;
- writer_print_section_footer(wctx);
- ret = writer_close(&wctx);
+ avtext_print_section_footer(tctx);
+
+ ret = avtextwriter_context_close(&wctx);
+ if (ret < 0)
+ av_log(NULL, AV_LOG_ERROR, "Writing output failed (closing writer): %s\n", av_err2str(ret));
+
+ ret = avtext_context_close(&tctx);
if (ret < 0)
- av_log(NULL, AV_LOG_ERROR, "Writing output failed: %s\n", av_err2str(ret));
+ av_log(NULL, AV_LOG_ERROR, "Writing output failed (closing formatter): %s\n", av_err2str(ret));
ret = FFMIN(ret, input_ret);
}
@@ -4790,7 +3202,6 @@ end:
av_freep(&input_filename);
av_freep(&print_input_filename);
av_freep(&read_intervals);
- av_hash_freep(&hash);
uninit_opts();
for (i = 0; i < FF_ARRAY_ELEMS(sections); i++)
--
ffmpeg-codebot
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 108+ messages in thread
* [FFmpeg-devel] [PATCH v6 3/8] fftools/ffprobe: Rename writer_print_section_* and WriterContext
2025-03-08 20:16 ` [FFmpeg-devel] [PATCH v6 0/8] print_graphs: Complete Filtergraph Printing ffmpegagent
2025-03-08 20:16 ` [FFmpeg-devel] [PATCH v6 1/8] fftools/textformat: Extract and generalize textformat api from ffprobe.c softworkz
2025-03-08 20:16 ` [FFmpeg-devel] [PATCH v6 2/8] fftools/ffprobe: Change to use textformat api softworkz
@ 2025-03-08 20:16 ` softworkz
2025-03-08 20:16 ` [FFmpeg-devel] [PATCH v6 4/8] fftools/ffmpeg_filter: Move some declaration to new header file softworkz
` (6 subsequent siblings)
9 siblings, 0 replies; 108+ messages in thread
From: softworkz @ 2025-03-08 20:16 UTC (permalink / raw)
To: ffmpeg-devel; +Cc: softworkz
From: softworkz <softworkz@hotmail.com>
separated for better clarity of the preceding commit
Signed-off-by: softworkz <softworkz@hotmail.com>
ren
---
fftools/ffprobe.c | 361 +++++++++++++++++++++++-----------------------
1 file changed, 178 insertions(+), 183 deletions(-)
diff --git a/fftools/ffprobe.c b/fftools/ffprobe.c
index f398057df7..4a90bc4824 100644
--- a/fftools/ffprobe.c
+++ b/fftools/ffprobe.c
@@ -71,11 +71,6 @@
#include "libavutil/thread.h"
-// TEMPORARY DEFINES
-#define writer_print_section_header(w, d, s) avtext_print_section_header(w, d, s)
-#define writer_print_section_footer(w) avtext_print_section_footer(w)
-#define WriterContext AVTextFormatContext
-
// attached as opaque_ref to packets/frames
typedef struct FrameData {
int64_t pkt_pos;
@@ -446,25 +441,25 @@ static void log_callback(void *ptr, int level, const char *fmt, va_list vl)
memset( (ptr) + (cur_n), 0, ((new_n) - (cur_n)) * sizeof(*(ptr)) ); \
}
-static inline int show_tags(WriterContext *w, AVDictionary *tags, int section_id)
+static inline int show_tags(AVTextFormatContext *w, AVDictionary *tags, int section_id)
{
const AVDictionaryEntry *tag = NULL;
int ret = 0;
if (!tags)
return 0;
- writer_print_section_header(w, NULL, section_id);
+ avtext_print_section_header(w, NULL, section_id);
while ((tag = av_dict_iterate(tags, tag))) {
if ((ret = print_str_validate(tag->key, tag->value)) < 0)
break;
}
- writer_print_section_footer(w);
+ avtext_print_section_footer(w);
return ret;
}
-static void print_dovi_metadata(WriterContext *w, const AVDOVIMetadata *dovi)
+static void print_dovi_metadata(AVTextFormatContext *w, const AVDOVIMetadata *dovi)
{
if (!dovi)
return;
@@ -519,15 +514,15 @@ static void print_dovi_metadata(WriterContext *w, const AVDOVIMetadata *dovi)
print_int("num_x_partitions", mapping->num_x_partitions);
print_int("num_y_partitions", mapping->num_y_partitions);
- writer_print_section_header(w, NULL, SECTION_ID_FRAME_SIDE_DATA_COMPONENT_LIST);
+ avtext_print_section_header(w, NULL, SECTION_ID_FRAME_SIDE_DATA_COMPONENT_LIST);
for (int c = 0; c < 3; c++) {
const AVDOVIReshapingCurve *curve = &mapping->curves[c];
- writer_print_section_header(w, "Reshaping curve", SECTION_ID_FRAME_SIDE_DATA_COMPONENT);
+ avtext_print_section_header(w, "Reshaping curve", SECTION_ID_FRAME_SIDE_DATA_COMPONENT);
print_list_fmt("pivots", "%"PRIu16, curve->num_pivots, 1, curve->pivots[idx]);
- writer_print_section_header(w, NULL, SECTION_ID_FRAME_SIDE_DATA_PIECE_LIST);
+ avtext_print_section_header(w, NULL, SECTION_ID_FRAME_SIDE_DATA_PIECE_LIST);
for (int i = 0; i < curve->num_pivots - 1; i++) {
AVBPrint piece_buf;
@@ -545,7 +540,7 @@ static void print_dovi_metadata(WriterContext *w, const AVDOVIMetadata *dovi)
}
av_bprintf(&piece_buf, " mapping");
- writer_print_section_header(w, piece_buf.str, SECTION_ID_FRAME_SIDE_DATA_PIECE);
+ avtext_print_section_header(w, piece_buf.str, SECTION_ID_FRAME_SIDE_DATA_PIECE);
print_int("mapping_idc", curve->mapping_idc[i]);
switch (curve->mapping_idc[i]) {
case AV_DOVI_MAPPING_POLYNOMIAL:
@@ -569,11 +564,11 @@ static void print_dovi_metadata(WriterContext *w, const AVDOVIMetadata *dovi)
}
// SECTION_ID_FRAME_SIDE_DATA_PIECE
- writer_print_section_footer(w);
+ avtext_print_section_footer(w);
}
// SECTION_ID_FRAME_SIDE_DATA_PIECE_LIST
- writer_print_section_footer(w);
+ avtext_print_section_footer(w);
if (mapping->nlq_method_idc != AV_DOVI_NLQ_NONE) {
const AVDOVINLQParams *nlq = &mapping->nlq[c];
@@ -589,11 +584,11 @@ static void print_dovi_metadata(WriterContext *w, const AVDOVIMetadata *dovi)
}
// SECTION_ID_FRAME_SIDE_DATA_COMPONENT
- writer_print_section_footer(w);
+ avtext_print_section_footer(w);
}
// SECTION_ID_FRAME_SIDE_DATA_COMPONENT_LIST
- writer_print_section_footer(w);
+ avtext_print_section_footer(w);
// color metadata
print_int("dm_metadata_id", color->dm_metadata_id);
@@ -626,7 +621,7 @@ static void print_dovi_metadata(WriterContext *w, const AVDOVIMetadata *dovi)
}
}
-static void print_dynamic_hdr10_plus(WriterContext *w, const AVDynamicHDRPlus *metadata)
+static void print_dynamic_hdr10_plus(AVTextFormatContext *w, const AVDynamicHDRPlus *metadata)
{
if (!metadata)
return;
@@ -725,7 +720,7 @@ static void print_dynamic_hdr10_plus(WriterContext *w, const AVDynamicHDRPlus *m
}
}
-static void print_dynamic_hdr_vivid(WriterContext *w, const AVDynamicHDRVivid *metadata)
+static void print_dynamic_hdr_vivid(AVTextFormatContext *w, const AVDynamicHDRVivid *metadata)
{
if (!metadata)
return;
@@ -795,7 +790,7 @@ static void print_dynamic_hdr_vivid(WriterContext *w, const AVDynamicHDRVivid *m
}
}
-static void print_ambient_viewing_environment(WriterContext *w,
+static void print_ambient_viewing_environment(AVTextFormatContext *w,
const AVAmbientViewingEnvironment *env)
{
if (!env)
@@ -806,7 +801,7 @@ static void print_ambient_viewing_environment(WriterContext *w,
print_q("ambient_light_y", env->ambient_light_y, '/');
}
-static void print_film_grain_params(WriterContext *w,
+static void print_film_grain_params(AVTextFormatContext *w,
const AVFilmGrainParams *fgp)
{
const char *color_range, *color_primaries, *color_trc, *color_space;
@@ -852,10 +847,10 @@ static void print_film_grain_params(WriterContext *w,
print_int("overlap_flag", aom->overlap_flag);
print_int("limit_output_range", aom->limit_output_range);
- writer_print_section_header(w, NULL, SECTION_ID_FRAME_SIDE_DATA_COMPONENT_LIST);
+ avtext_print_section_header(w, NULL, SECTION_ID_FRAME_SIDE_DATA_COMPONENT_LIST);
if (aom->num_y_points) {
- writer_print_section_header(w, NULL, SECTION_ID_FRAME_SIDE_DATA_COMPONENT);
+ avtext_print_section_header(w, NULL, SECTION_ID_FRAME_SIDE_DATA_COMPONENT);
print_int("bit_depth_luma", fgp->bit_depth_luma);
print_list_fmt("y_points_value", "%"PRIu8, aom->num_y_points, 1, aom->y_points[idx][0]);
@@ -863,14 +858,14 @@ static void print_film_grain_params(WriterContext *w,
print_list_fmt("ar_coeffs_y", "%"PRId8, num_ar_coeffs_y, 1, aom->ar_coeffs_y[idx]);
// SECTION_ID_FRAME_SIDE_DATA_COMPONENT
- writer_print_section_footer(w);
+ avtext_print_section_footer(w);
}
for (int uv = 0; uv < 2; uv++) {
if (!aom->num_uv_points[uv] && !aom->chroma_scaling_from_luma)
continue;
- writer_print_section_header(w, NULL, SECTION_ID_FRAME_SIDE_DATA_COMPONENT);
+ avtext_print_section_header(w, NULL, SECTION_ID_FRAME_SIDE_DATA_COMPONENT);
print_int("bit_depth_chroma", fgp->bit_depth_chroma);
print_list_fmt("uv_points_value", "%"PRIu8, aom->num_uv_points[uv], 1, aom->uv_points[uv][idx][0]);
@@ -881,11 +876,11 @@ static void print_film_grain_params(WriterContext *w,
print_int("uv_offset", aom->uv_offset[uv]);
// SECTION_ID_FRAME_SIDE_DATA_COMPONENT
- writer_print_section_footer(w);
+ avtext_print_section_footer(w);
}
// SECTION_ID_FRAME_SIDE_DATA_COMPONENT_LIST
- writer_print_section_footer(w);
+ avtext_print_section_footer(w);
break;
}
case AV_FILM_GRAIN_PARAMS_H274: {
@@ -894,36 +889,36 @@ static void print_film_grain_params(WriterContext *w,
print_int("blending_mode_id", h274->blending_mode_id);
print_int("log2_scale_factor", h274->log2_scale_factor);
- writer_print_section_header(w, NULL, SECTION_ID_FRAME_SIDE_DATA_COMPONENT_LIST);
+ avtext_print_section_header(w, NULL, SECTION_ID_FRAME_SIDE_DATA_COMPONENT_LIST);
for (int c = 0; c < 3; c++) {
if (!h274->component_model_present[c])
continue;
- writer_print_section_header(w, NULL, SECTION_ID_FRAME_SIDE_DATA_COMPONENT);
+ avtext_print_section_header(w, NULL, SECTION_ID_FRAME_SIDE_DATA_COMPONENT);
print_int(c ? "bit_depth_chroma" : "bit_depth_luma", c ? fgp->bit_depth_chroma : fgp->bit_depth_luma);
- writer_print_section_header(w, NULL, SECTION_ID_FRAME_SIDE_DATA_PIECE_LIST);
+ avtext_print_section_header(w, NULL, SECTION_ID_FRAME_SIDE_DATA_PIECE_LIST);
for (int i = 0; i < h274->num_intensity_intervals[c]; i++) {
- writer_print_section_header(w, NULL, SECTION_ID_FRAME_SIDE_DATA_PIECE);
+ avtext_print_section_header(w, NULL, SECTION_ID_FRAME_SIDE_DATA_PIECE);
print_int("intensity_interval_lower_bound", h274->intensity_interval_lower_bound[c][i]);
print_int("intensity_interval_upper_bound", h274->intensity_interval_upper_bound[c][i]);
print_list_fmt("comp_model_value", "%"PRId16, h274->num_model_values[c], 1, h274->comp_model_value[c][i][idx]);
// SECTION_ID_FRAME_SIDE_DATA_PIECE
- writer_print_section_footer(w);
+ avtext_print_section_footer(w);
}
// SECTION_ID_FRAME_SIDE_DATA_PIECE_LIST
- writer_print_section_footer(w);
+ avtext_print_section_footer(w);
// SECTION_ID_FRAME_SIDE_DATA_COMPONENT
- writer_print_section_footer(w);
+ avtext_print_section_footer(w);
}
// SECTION_ID_FRAME_SIDE_DATA_COMPONENT_LIST
- writer_print_section_footer(w);
+ avtext_print_section_footer(w);
break;
}
}
@@ -931,14 +926,14 @@ static void print_film_grain_params(WriterContext *w,
av_bprint_finalize(&pbuf, NULL);
}
-static void print_pkt_side_data(WriterContext *w,
+static void print_pkt_side_data(AVTextFormatContext *w,
AVCodecParameters *par,
const AVPacketSideData *sd,
SectionID id_data)
{
const char *name = av_packet_side_data_name(sd->type);
- writer_print_section_header(w, sd, id_data);
+ avtext_print_section_header(w, sd, id_data);
print_str("side_data_type", name ? name : "unknown");
if (sd->type == AV_PKT_DATA_DISPLAYMATRIX && sd->size >= 9*4) {
double rotation = av_display_rotation_get((int32_t *)sd->data);
@@ -1053,7 +1048,7 @@ static void print_pkt_side_data(WriterContext *w,
}
}
-static void print_private_data(WriterContext *w, void *priv_data)
+static void print_private_data(AVTextFormatContext *w, void *priv_data)
{
const AVOption *opt = NULL;
while (opt = av_opt_next(priv_data, opt)) {
@@ -1066,7 +1061,7 @@ static void print_private_data(WriterContext *w, void *priv_data)
}
}
-static void print_color_range(WriterContext *w, enum AVColorRange color_range)
+static void print_color_range(AVTextFormatContext *w, enum AVColorRange color_range)
{
const char *val = av_color_range_name(color_range);
if (!val || color_range == AVCOL_RANGE_UNSPECIFIED) {
@@ -1076,7 +1071,7 @@ static void print_color_range(WriterContext *w, enum AVColorRange color_range)
}
}
-static void print_color_space(WriterContext *w, enum AVColorSpace color_space)
+static void print_color_space(AVTextFormatContext *w, enum AVColorSpace color_space)
{
const char *val = av_color_space_name(color_space);
if (!val || color_space == AVCOL_SPC_UNSPECIFIED) {
@@ -1086,7 +1081,7 @@ static void print_color_space(WriterContext *w, enum AVColorSpace color_space)
}
}
-static void print_primaries(WriterContext *w, enum AVColorPrimaries color_primaries)
+static void print_primaries(AVTextFormatContext *w, enum AVColorPrimaries color_primaries)
{
const char *val = av_color_primaries_name(color_primaries);
if (!val || color_primaries == AVCOL_PRI_UNSPECIFIED) {
@@ -1096,7 +1091,7 @@ static void print_primaries(WriterContext *w, enum AVColorPrimaries color_primar
}
}
-static void print_color_trc(WriterContext *w, enum AVColorTransferCharacteristic color_trc)
+static void print_color_trc(AVTextFormatContext *w, enum AVColorTransferCharacteristic color_trc)
{
const char *val = av_color_transfer_name(color_trc);
if (!val || color_trc == AVCOL_TRC_UNSPECIFIED) {
@@ -1106,7 +1101,7 @@ static void print_color_trc(WriterContext *w, enum AVColorTransferCharacteristic
}
}
-static void print_chroma_location(WriterContext *w, enum AVChromaLocation chroma_location)
+static void print_chroma_location(AVTextFormatContext *w, enum AVChromaLocation chroma_location)
{
const char *val = av_chroma_location_name(chroma_location);
if (!val || chroma_location == AVCHROMA_LOC_UNSPECIFIED) {
@@ -1132,7 +1127,7 @@ static void clear_log(int need_lock)
ff_mutex_unlock(&log_mutex);
}
-static int show_log(WriterContext *w, int section_ids, int section_id, int log_level)
+static int show_log(AVTextFormatContext *w, int section_ids, int section_id, int log_level)
{
int i;
ff_mutex_lock(&log_mutex);
@@ -1140,11 +1135,11 @@ static int show_log(WriterContext *w, int section_ids, int section_id, int log_l
ff_mutex_unlock(&log_mutex);
return 0;
}
- writer_print_section_header(w, NULL, section_ids);
+ avtext_print_section_header(w, NULL, section_ids);
for (i=0; i<log_buffer_size; i++) {
if (log_buffer[i].log_level <= log_level) {
- writer_print_section_header(w, NULL, section_id);
+ avtext_print_section_header(w, NULL, section_id);
print_str("context", log_buffer[i].context_name);
print_int("level", log_buffer[i].log_level);
print_int("category", log_buffer[i].category);
@@ -1156,18 +1151,18 @@ static int show_log(WriterContext *w, int section_ids, int section_id, int log_l
print_str_opt("parent_category", "N/A");
}
print_str("message", log_buffer[i].log_message);
- writer_print_section_footer(w);
+ avtext_print_section_footer(w);
}
}
clear_log(0);
ff_mutex_unlock(&log_mutex);
- writer_print_section_footer(w);
+ avtext_print_section_footer(w);
return 0;
}
-static void show_packet(WriterContext *w, InputFile *ifile, AVPacket *pkt, int packet_idx)
+static void show_packet(AVTextFormatContext *w, InputFile *ifile, AVPacket *pkt, int packet_idx)
{
AVStream *st = ifile->streams[pkt->stream_index].st;
AVBPrint pbuf;
@@ -1175,7 +1170,7 @@ static void show_packet(WriterContext *w, InputFile *ifile, AVPacket *pkt, int p
av_bprint_init(&pbuf, 1, AV_BPRINT_SIZE_UNLIMITED);
- writer_print_section_header(w, NULL, SECTION_ID_PACKET);
+ avtext_print_section_header(w, NULL, SECTION_ID_PACKET);
s = av_get_media_type_string(st->codecpar->codec_type);
if (s) print_str ("codec_type", s);
@@ -1209,29 +1204,29 @@ static void show_packet(WriterContext *w, InputFile *ifile, AVPacket *pkt, int p
av_dict_free(&dict);
}
- writer_print_section_header(w, NULL, SECTION_ID_PACKET_SIDE_DATA_LIST);
+ avtext_print_section_header(w, NULL, SECTION_ID_PACKET_SIDE_DATA_LIST);
for (int i = 0; i < pkt->side_data_elems; i++) {
print_pkt_side_data(w, st->codecpar, &pkt->side_data[i],
SECTION_ID_PACKET_SIDE_DATA);
- writer_print_section_footer(w);
+ avtext_print_section_footer(w);
}
- writer_print_section_footer(w);
+ avtext_print_section_footer(w);
}
- writer_print_section_footer(w);
+ avtext_print_section_footer(w);
av_bprint_finalize(&pbuf, NULL);
fflush(stdout);
}
-static void show_subtitle(WriterContext *w, AVSubtitle *sub, AVStream *stream,
+static void show_subtitle(AVTextFormatContext *w, AVSubtitle *sub, AVStream *stream,
AVFormatContext *fmt_ctx)
{
AVBPrint pbuf;
av_bprint_init(&pbuf, 1, AV_BPRINT_SIZE_UNLIMITED);
- writer_print_section_header(w, NULL, SECTION_ID_SUBTITLE);
+ avtext_print_section_header(w, NULL, SECTION_ID_SUBTITLE);
print_str ("media_type", "subtitle");
print_ts ("pts", sub->pts);
@@ -1241,23 +1236,23 @@ static void show_subtitle(WriterContext *w, AVSubtitle *sub, AVStream *stream,
print_int ("end_display_time", sub->end_display_time);
print_int ("num_rects", sub->num_rects);
- writer_print_section_footer(w);
+ avtext_print_section_footer(w);
av_bprint_finalize(&pbuf, NULL);
fflush(stdout);
}
-static void print_frame_side_data(WriterContext *w,
+static void print_frame_side_data(AVTextFormatContext *w,
const AVFrame *frame,
const AVStream *stream)
{
- writer_print_section_header(w, NULL, SECTION_ID_FRAME_SIDE_DATA_LIST);
+ avtext_print_section_header(w, NULL, SECTION_ID_FRAME_SIDE_DATA_LIST);
for (int i = 0; i < frame->nb_side_data; i++) {
const AVFrameSideData *sd = frame->side_data[i];
const char *name;
- writer_print_section_header(w, sd, SECTION_ID_FRAME_SIDE_DATA);
+ avtext_print_section_header(w, sd, SECTION_ID_FRAME_SIDE_DATA);
name = av_frame_side_data_name(sd->type);
print_str("side_data_type", name ? name : "unknown");
if (sd->type == AV_FRAME_DATA_DISPLAYMATRIX && sd->size >= 9*4) {
@@ -1275,15 +1270,15 @@ static void print_frame_side_data(WriterContext *w,
} else if (sd->type == AV_FRAME_DATA_S12M_TIMECODE && sd->size == 16) {
uint32_t *tc = (uint32_t*)sd->data;
int m = FFMIN(tc[0],3);
- writer_print_section_header(w, NULL, SECTION_ID_FRAME_SIDE_DATA_TIMECODE_LIST);
+ avtext_print_section_header(w, NULL, SECTION_ID_FRAME_SIDE_DATA_TIMECODE_LIST);
for (int j = 1; j <= m ; j++) {
char tcbuf[AV_TIMECODE_STR_SIZE];
av_timecode_make_smpte_tc_string2(tcbuf, stream->avg_frame_rate, tc[j], 0, 0);
- writer_print_section_header(w, NULL, SECTION_ID_FRAME_SIDE_DATA_TIMECODE);
+ avtext_print_section_header(w, NULL, SECTION_ID_FRAME_SIDE_DATA_TIMECODE);
print_str("value", tcbuf);
- writer_print_section_footer(w);
+ avtext_print_section_footer(w);
}
- writer_print_section_footer(w);
+ avtext_print_section_footer(w);
} else if (sd->type == AV_FRAME_DATA_MASTERING_DISPLAY_METADATA) {
AVMasteringDisplayMetadata *metadata = (AVMasteringDisplayMetadata *)sd->data;
@@ -1328,12 +1323,12 @@ static void print_frame_side_data(WriterContext *w,
} else if (sd->type == AV_FRAME_DATA_VIEW_ID) {
print_int("view_id", *(int*)sd->data);
}
- writer_print_section_footer(w);
+ avtext_print_section_footer(w);
}
- writer_print_section_footer(w);
+ avtext_print_section_footer(w);
}
-static void show_frame(WriterContext *w, AVFrame *frame, AVStream *stream,
+static void show_frame(AVTextFormatContext *w, AVFrame *frame, AVStream *stream,
AVFormatContext *fmt_ctx)
{
FrameData *fd = frame->opaque_ref ? (FrameData*)frame->opaque_ref->data : NULL;
@@ -1343,7 +1338,7 @@ static void show_frame(WriterContext *w, AVFrame *frame, AVStream *stream,
av_bprint_init(&pbuf, 1, AV_BPRINT_SIZE_UNLIMITED);
- writer_print_section_header(w, NULL, SECTION_ID_FRAME);
+ avtext_print_section_header(w, NULL, SECTION_ID_FRAME);
s = av_get_media_type_string(stream->codecpar->codec_type);
if (s) print_str ("media_type", s);
@@ -1415,13 +1410,13 @@ static void show_frame(WriterContext *w, AVFrame *frame, AVStream *stream,
if (frame->nb_side_data)
print_frame_side_data(w, frame, stream);
- writer_print_section_footer(w);
+ avtext_print_section_footer(w);
av_bprint_finalize(&pbuf, NULL);
fflush(stdout);
}
-static av_always_inline int process_frame(WriterContext *w,
+static av_always_inline int process_frame(AVTextFormatContext *w,
InputFile *ifile,
AVFrame *frame, const AVPacket *pkt,
int *packet_new)
@@ -1518,7 +1513,7 @@ static void log_read_interval(const ReadInterval *interval, void *log_ctx, int l
av_log(log_ctx, log_level, "\n");
}
-static int read_interval_packets(WriterContext *w, InputFile *ifile,
+static int read_interval_packets(AVTextFormatContext *w, InputFile *ifile,
const ReadInterval *interval, int64_t *cur_ts)
{
AVFormatContext *fmt_ctx = ifile->fmt_ctx;
@@ -1643,7 +1638,7 @@ end:
return ret;
}
-static int read_packets(WriterContext *w, InputFile *ifile)
+static int read_packets(AVTextFormatContext *w, InputFile *ifile)
{
AVFormatContext *fmt_ctx = ifile->fmt_ctx;
int i, ret = 0;
@@ -1663,22 +1658,22 @@ static int read_packets(WriterContext *w, InputFile *ifile)
return ret;
}
-static void print_dispositions(WriterContext *w, uint32_t disposition, SectionID section_id)
+static void print_dispositions(AVTextFormatContext *w, uint32_t disposition, SectionID section_id)
{
- writer_print_section_header(w, NULL, section_id);
+ avtext_print_section_header(w, NULL, section_id);
for (int i = 0; i < sizeof(disposition) * CHAR_BIT; i++) {
const char *disposition_str = av_disposition_to_string(1U << i);
if (disposition_str)
print_int(disposition_str, !!(disposition & (1U << i)));
}
- writer_print_section_footer(w);
+ avtext_print_section_footer(w);
}
#define IN_PROGRAM 1
#define IN_STREAM_GROUP 2
-static int show_stream(WriterContext *w, AVFormatContext *fmt_ctx, int stream_idx, InputStream *ist, int container)
+static int show_stream(AVTextFormatContext *w, AVFormatContext *fmt_ctx, int stream_idx, InputStream *ist, int container)
{
AVStream *stream = ist->st;
AVCodecParameters *par;
@@ -1710,7 +1705,7 @@ static int show_stream(WriterContext *w, AVFormatContext *fmt_ctx, int stream_id
av_bprint_init(&pbuf, 1, AV_BPRINT_SIZE_UNLIMITED);
- writer_print_section_header(w, NULL, section_header[container]);
+ avtext_print_section_header(w, NULL, section_header[container]);
print_int("index", stream->index);
@@ -1885,45 +1880,45 @@ static int show_stream(WriterContext *w, AVFormatContext *fmt_ctx, int stream_id
}
if (stream->codecpar->nb_coded_side_data) {
- writer_print_section_header(w, NULL, SECTION_ID_STREAM_SIDE_DATA_LIST);
+ avtext_print_section_header(w, NULL, SECTION_ID_STREAM_SIDE_DATA_LIST);
for (int i = 0; i < stream->codecpar->nb_coded_side_data; i++) {
print_pkt_side_data(w, stream->codecpar, &stream->codecpar->coded_side_data[i],
SECTION_ID_STREAM_SIDE_DATA);
- writer_print_section_footer(w);
+ avtext_print_section_footer(w);
}
- writer_print_section_footer(w);
+ avtext_print_section_footer(w);
}
- writer_print_section_footer(w);
+ avtext_print_section_footer(w);
av_bprint_finalize(&pbuf, NULL);
fflush(stdout);
return ret;
}
-static int show_streams(WriterContext *w, InputFile *ifile)
+static int show_streams(AVTextFormatContext *w, InputFile *ifile)
{
AVFormatContext *fmt_ctx = ifile->fmt_ctx;
int i, ret = 0;
- writer_print_section_header(w, NULL, SECTION_ID_STREAMS);
+ avtext_print_section_header(w, NULL, SECTION_ID_STREAMS);
for (i = 0; i < ifile->nb_streams; i++)
if (selected_streams[i]) {
ret = show_stream(w, fmt_ctx, i, &ifile->streams[i], 0);
if (ret < 0)
break;
}
- writer_print_section_footer(w);
+ avtext_print_section_footer(w);
return ret;
}
-static int show_program(WriterContext *w, InputFile *ifile, AVProgram *program)
+static int show_program(AVTextFormatContext *w, InputFile *ifile, AVProgram *program)
{
AVFormatContext *fmt_ctx = ifile->fmt_ctx;
int i, ret = 0;
- writer_print_section_header(w, NULL, SECTION_ID_PROGRAM);
+ avtext_print_section_header(w, NULL, SECTION_ID_PROGRAM);
print_int("program_id", program->id);
print_int("program_num", program->program_num);
print_int("nb_streams", program->nb_stream_indexes);
@@ -1934,7 +1929,7 @@ static int show_program(WriterContext *w, InputFile *ifile, AVProgram *program)
if (ret < 0)
goto end;
- writer_print_section_header(w, NULL, SECTION_ID_PROGRAM_STREAMS);
+ avtext_print_section_header(w, NULL, SECTION_ID_PROGRAM_STREAMS);
for (i = 0; i < program->nb_stream_indexes; i++) {
if (selected_streams[program->stream_index[i]]) {
ret = show_stream(w, fmt_ctx, program->stream_index[i], &ifile->streams[program->stream_index[i]], IN_PROGRAM);
@@ -1942,19 +1937,19 @@ static int show_program(WriterContext *w, InputFile *ifile, AVProgram *program)
break;
}
}
- writer_print_section_footer(w);
+ avtext_print_section_footer(w);
end:
- writer_print_section_footer(w);
+ avtext_print_section_footer(w);
return ret;
}
-static int show_programs(WriterContext *w, InputFile *ifile)
+static int show_programs(AVTextFormatContext *w, InputFile *ifile)
{
AVFormatContext *fmt_ctx = ifile->fmt_ctx;
int i, ret = 0;
- writer_print_section_header(w, NULL, SECTION_ID_PROGRAMS);
+ avtext_print_section_header(w, NULL, SECTION_ID_PROGRAMS);
for (i = 0; i < fmt_ctx->nb_programs; i++) {
AVProgram *program = fmt_ctx->programs[i];
if (!program)
@@ -1963,14 +1958,14 @@ static int show_programs(WriterContext *w, InputFile *ifile)
if (ret < 0)
break;
}
- writer_print_section_footer(w);
+ avtext_print_section_footer(w);
return ret;
}
-static void print_tile_grid_params(WriterContext *w, const AVStreamGroup *stg,
+static void print_tile_grid_params(AVTextFormatContext *w, const AVStreamGroup *stg,
const AVStreamGroupTileGrid *tile_grid)
{
- writer_print_section_header(w, stg, SECTION_ID_STREAM_GROUP_COMPONENT);
+ avtext_print_section_header(w, stg, SECTION_ID_STREAM_GROUP_COMPONENT);
print_int("nb_tiles", tile_grid->nb_tiles);
print_int("coded_width", tile_grid->coded_width);
print_int("coded_height", tile_grid->coded_height);
@@ -1978,19 +1973,19 @@ static void print_tile_grid_params(WriterContext *w, const AVStreamGroup *stg,
print_int("vertical_offset", tile_grid->vertical_offset);
print_int("width", tile_grid->width);
print_int("height", tile_grid->height);
- writer_print_section_header(w, NULL, SECTION_ID_STREAM_GROUP_SUBCOMPONENTS);
+ avtext_print_section_header(w, NULL, SECTION_ID_STREAM_GROUP_SUBCOMPONENTS);
for (int i = 0; i < tile_grid->nb_tiles; i++) {
- writer_print_section_header(w, "tile_offset", SECTION_ID_STREAM_GROUP_SUBCOMPONENT);
+ avtext_print_section_header(w, "tile_offset", SECTION_ID_STREAM_GROUP_SUBCOMPONENT);
print_int("stream_index", tile_grid->offsets[i].idx);
print_int("tile_horizontal_offset", tile_grid->offsets[i].horizontal);
print_int("tile_vertical_offset", tile_grid->offsets[i].vertical);
- writer_print_section_footer(w);
+ avtext_print_section_footer(w);
}
- writer_print_section_footer(w);
- writer_print_section_footer(w);
+ avtext_print_section_footer(w);
+ avtext_print_section_footer(w);
}
-static void print_iamf_param_definition(WriterContext *w, const char *name,
+static void print_iamf_param_definition(AVTextFormatContext *w, const char *name,
const AVIAMFParamDefinition *param, SectionID section_id)
{
SectionID subsection_id, parameter_section_id;
@@ -1998,7 +1993,7 @@ static void print_iamf_param_definition(WriterContext *w, const char *name,
av_assert0(subsection_id != -1);
parameter_section_id = sections[subsection_id].children_ids[0];
av_assert0(parameter_section_id != -1);
- writer_print_section_header(w, "IAMF Param Definition", section_id);
+ avtext_print_section_header(w, "IAMF Param Definition", section_id);
print_str("name", name);
print_int("nb_subblocks", param->nb_subblocks);
print_int("type", param->type);
@@ -2007,56 +2002,56 @@ static void print_iamf_param_definition(WriterContext *w, const char *name,
print_int("duration", param->duration);
print_int("constant_subblock_duration", param->constant_subblock_duration);
if (param->nb_subblocks > 0)
- writer_print_section_header(w, NULL, subsection_id);
+ avtext_print_section_header(w, NULL, subsection_id);
for (int i = 0; i < param->nb_subblocks; i++) {
const void *subblock = av_iamf_param_definition_get_subblock(param, i);
switch(param->type) {
case AV_IAMF_PARAMETER_DEFINITION_MIX_GAIN: {
const AVIAMFMixGain *mix = subblock;
- writer_print_section_header(w, "IAMF Mix Gain Parameters", parameter_section_id);
+ avtext_print_section_header(w, "IAMF Mix Gain Parameters", parameter_section_id);
print_int("subblock_duration", mix->subblock_duration);
print_int("animation_type", mix->animation_type);
print_q("start_point_value", mix->start_point_value, '/');
print_q("end_point_value", mix->end_point_value, '/');
print_q("control_point_value", mix->control_point_value, '/');
print_q("control_point_relative_time", mix->control_point_relative_time, '/');
- writer_print_section_footer(w); // parameter_section_id
+ avtext_print_section_footer(w); // parameter_section_id
break;
}
case AV_IAMF_PARAMETER_DEFINITION_DEMIXING: {
const AVIAMFDemixingInfo *demix = subblock;
- writer_print_section_header(w, "IAMF Demixing Info", parameter_section_id);
+ avtext_print_section_header(w, "IAMF Demixing Info", parameter_section_id);
print_int("subblock_duration", demix->subblock_duration);
print_int("dmixp_mode", demix->dmixp_mode);
- writer_print_section_footer(w); // parameter_section_id
+ avtext_print_section_footer(w); // parameter_section_id
break;
}
case AV_IAMF_PARAMETER_DEFINITION_RECON_GAIN: {
const AVIAMFReconGain *recon = subblock;
- writer_print_section_header(w, "IAMF Recon Gain", parameter_section_id);
+ avtext_print_section_header(w, "IAMF Recon Gain", parameter_section_id);
print_int("subblock_duration", recon->subblock_duration);
- writer_print_section_footer(w); // parameter_section_id
+ avtext_print_section_footer(w); // parameter_section_id
break;
}
}
}
if (param->nb_subblocks > 0)
- writer_print_section_footer(w); // subsection_id
- writer_print_section_footer(w); // section_id
+ avtext_print_section_footer(w); // subsection_id
+ avtext_print_section_footer(w); // section_id
}
-static void print_iamf_audio_element_params(WriterContext *w, const AVStreamGroup *stg,
+static void print_iamf_audio_element_params(AVTextFormatContext *w, const AVStreamGroup *stg,
const AVIAMFAudioElement *audio_element)
{
- writer_print_section_header(w, stg, SECTION_ID_STREAM_GROUP_COMPONENT);
+ avtext_print_section_header(w, stg, SECTION_ID_STREAM_GROUP_COMPONENT);
print_int("nb_layers", audio_element->nb_layers);
print_int("audio_element_type", audio_element->audio_element_type);
print_int("default_w", audio_element->default_w);
- writer_print_section_header(w, NULL, SECTION_ID_STREAM_GROUP_SUBCOMPONENTS);
+ avtext_print_section_header(w, NULL, SECTION_ID_STREAM_GROUP_SUBCOMPONENTS);
for (int i = 0; i < audio_element->nb_layers; i++) {
const AVIAMFLayer *layer = audio_element->layers[i];
char val_str[128];
- writer_print_section_header(w, "IAMF Audio Layer", SECTION_ID_STREAM_GROUP_SUBCOMPONENT);
+ avtext_print_section_header(w, "IAMF Audio Layer", SECTION_ID_STREAM_GROUP_SUBCOMPONENT);
av_channel_layout_describe(&layer->ch_layout, val_str, sizeof(val_str));
print_str("channel_layout", val_str);
if (audio_element->audio_element_type == AV_IAMF_AUDIO_ELEMENT_TYPE_CHANNEL) {
@@ -2064,7 +2059,7 @@ static void print_iamf_audio_element_params(WriterContext *w, const AVStreamGrou
print_q("output_gain", layer->output_gain, '/');
} else if (audio_element->audio_element_type == AV_IAMF_AUDIO_ELEMENT_TYPE_SCENE)
print_int("ambisonics_mode", layer->ambisonics_mode);
- writer_print_section_footer(w); // SECTION_ID_STREAM_GROUP_SUBCOMPONENT
+ avtext_print_section_footer(w); // SECTION_ID_STREAM_GROUP_SUBCOMPONENT
}
if (audio_element->demixing_info)
print_iamf_param_definition(w, "demixing_info", audio_element->demixing_info,
@@ -2072,36 +2067,36 @@ static void print_iamf_audio_element_params(WriterContext *w, const AVStreamGrou
if (audio_element->recon_gain_info)
print_iamf_param_definition(w, "recon_gain_info", audio_element->recon_gain_info,
SECTION_ID_STREAM_GROUP_SUBCOMPONENT);
- writer_print_section_footer(w); // SECTION_ID_STREAM_GROUP_SUBCOMPONENTS
- writer_print_section_footer(w); // SECTION_ID_STREAM_GROUP_COMPONENT
+ avtext_print_section_footer(w); // SECTION_ID_STREAM_GROUP_SUBCOMPONENTS
+ avtext_print_section_footer(w); // SECTION_ID_STREAM_GROUP_COMPONENT
}
-static void print_iamf_submix_params(WriterContext *w, const AVIAMFSubmix *submix)
+static void print_iamf_submix_params(AVTextFormatContext *w, const AVIAMFSubmix *submix)
{
- writer_print_section_header(w, "IAMF Submix", SECTION_ID_STREAM_GROUP_SUBCOMPONENT);
+ avtext_print_section_header(w, "IAMF Submix", SECTION_ID_STREAM_GROUP_SUBCOMPONENT);
print_int("nb_elements", submix->nb_elements);
print_int("nb_layouts", submix->nb_layouts);
print_q("default_mix_gain", submix->default_mix_gain, '/');
- writer_print_section_header(w, NULL, SECTION_ID_STREAM_GROUP_PIECES);
+ avtext_print_section_header(w, NULL, SECTION_ID_STREAM_GROUP_PIECES);
for (int i = 0; i < submix->nb_elements; i++) {
const AVIAMFSubmixElement *element = submix->elements[i];
- writer_print_section_header(w, "IAMF Submix Element", SECTION_ID_STREAM_GROUP_PIECE);
+ avtext_print_section_header(w, "IAMF Submix Element", SECTION_ID_STREAM_GROUP_PIECE);
print_int("stream_id", element->audio_element_id);
print_q("default_mix_gain", element->default_mix_gain, '/');
print_int("headphones_rendering_mode", element->headphones_rendering_mode);
- writer_print_section_header(w, NULL, SECTION_ID_STREAM_GROUP_SUBPIECES);
+ avtext_print_section_header(w, NULL, SECTION_ID_STREAM_GROUP_SUBPIECES);
if (element->annotations) {
const AVDictionaryEntry *annotation = NULL;
- writer_print_section_header(w, "IAMF Annotations", SECTION_ID_STREAM_GROUP_SUBPIECE);
+ avtext_print_section_header(w, "IAMF Annotations", SECTION_ID_STREAM_GROUP_SUBPIECE);
while (annotation = av_dict_iterate(element->annotations, annotation))
print_str(annotation->key, annotation->value);
- writer_print_section_footer(w); // SECTION_ID_STREAM_GROUP_SUBPIECE
+ avtext_print_section_footer(w); // SECTION_ID_STREAM_GROUP_SUBPIECE
}
if (element->element_mix_config)
print_iamf_param_definition(w, "element_mix_config", element->element_mix_config,
SECTION_ID_STREAM_GROUP_SUBPIECE);
- writer_print_section_footer(w); // SECTION_ID_STREAM_GROUP_SUBPIECES
- writer_print_section_footer(w); // SECTION_ID_STREAM_GROUP_PIECE
+ avtext_print_section_footer(w); // SECTION_ID_STREAM_GROUP_SUBPIECES
+ avtext_print_section_footer(w); // SECTION_ID_STREAM_GROUP_PIECE
}
if (submix->output_mix_config)
print_iamf_param_definition(w, "output_mix_config", submix->output_mix_config,
@@ -2109,7 +2104,7 @@ static void print_iamf_submix_params(WriterContext *w, const AVIAMFSubmix *submi
for (int i = 0; i < submix->nb_layouts; i++) {
const AVIAMFSubmixLayout *layout = submix->layouts[i];
char val_str[128];
- writer_print_section_header(w, "IAMF Submix Layout", SECTION_ID_STREAM_GROUP_PIECE);
+ avtext_print_section_header(w, "IAMF Submix Layout", SECTION_ID_STREAM_GROUP_PIECE);
av_channel_layout_describe(&layout->sound_system, val_str, sizeof(val_str));
print_str("sound_system", val_str);
print_q("integrated_loudness", layout->integrated_loudness, '/');
@@ -2117,51 +2112,51 @@ static void print_iamf_submix_params(WriterContext *w, const AVIAMFSubmix *submi
print_q("true_peak", layout->true_peak, '/');
print_q("dialogue_anchored_loudness", layout->dialogue_anchored_loudness, '/');
print_q("album_anchored_loudness", layout->album_anchored_loudness, '/');
- writer_print_section_footer(w); // SECTION_ID_STREAM_GROUP_PIECE
+ avtext_print_section_footer(w); // SECTION_ID_STREAM_GROUP_PIECE
}
- writer_print_section_footer(w); // SECTION_ID_STREAM_GROUP_PIECES
- writer_print_section_footer(w); // SECTION_ID_STREAM_GROUP_SUBCOMPONENT
+ avtext_print_section_footer(w); // SECTION_ID_STREAM_GROUP_PIECES
+ avtext_print_section_footer(w); // SECTION_ID_STREAM_GROUP_SUBCOMPONENT
}
-static void print_iamf_mix_presentation_params(WriterContext *w, const AVStreamGroup *stg,
+static void print_iamf_mix_presentation_params(AVTextFormatContext *w, const AVStreamGroup *stg,
const AVIAMFMixPresentation *mix_presentation)
{
- writer_print_section_header(w, stg, SECTION_ID_STREAM_GROUP_COMPONENT);
+ avtext_print_section_header(w, stg, SECTION_ID_STREAM_GROUP_COMPONENT);
print_int("nb_submixes", mix_presentation->nb_submixes);
- writer_print_section_header(w, NULL, SECTION_ID_STREAM_GROUP_SUBCOMPONENTS);
+ avtext_print_section_header(w, NULL, SECTION_ID_STREAM_GROUP_SUBCOMPONENTS);
if (mix_presentation->annotations) {
const AVDictionaryEntry *annotation = NULL;
- writer_print_section_header(w, "IAMF Annotations", SECTION_ID_STREAM_GROUP_SUBCOMPONENT);
+ avtext_print_section_header(w, "IAMF Annotations", SECTION_ID_STREAM_GROUP_SUBCOMPONENT);
while (annotation = av_dict_iterate(mix_presentation->annotations, annotation))
print_str(annotation->key, annotation->value);
- writer_print_section_footer(w); // SECTION_ID_STREAM_GROUP_SUBCOMPONENT
+ avtext_print_section_footer(w); // SECTION_ID_STREAM_GROUP_SUBCOMPONENT
}
for (int i = 0; i < mix_presentation->nb_submixes; i++)
print_iamf_submix_params(w, mix_presentation->submixes[i]);
- writer_print_section_footer(w); // SECTION_ID_STREAM_GROUP_SUBCOMPONENTS
- writer_print_section_footer(w); // SECTION_ID_STREAM_GROUP_COMPONENT
+ avtext_print_section_footer(w); // SECTION_ID_STREAM_GROUP_SUBCOMPONENTS
+ avtext_print_section_footer(w); // SECTION_ID_STREAM_GROUP_COMPONENT
}
-static void print_stream_group_params(WriterContext *w, AVStreamGroup *stg)
+static void print_stream_group_params(AVTextFormatContext *w, AVStreamGroup *stg)
{
- writer_print_section_header(w, NULL, SECTION_ID_STREAM_GROUP_COMPONENTS);
+ avtext_print_section_header(w, NULL, SECTION_ID_STREAM_GROUP_COMPONENTS);
if (stg->type == AV_STREAM_GROUP_PARAMS_TILE_GRID)
print_tile_grid_params(w, stg, stg->params.tile_grid);
else if (stg->type == AV_STREAM_GROUP_PARAMS_IAMF_AUDIO_ELEMENT)
print_iamf_audio_element_params(w, stg, stg->params.iamf_audio_element);
else if (stg->type == AV_STREAM_GROUP_PARAMS_IAMF_MIX_PRESENTATION)
print_iamf_mix_presentation_params(w, stg, stg->params.iamf_mix_presentation);
- writer_print_section_footer(w); // SECTION_ID_STREAM_GROUP_COMPONENTS
+ avtext_print_section_footer(w); // SECTION_ID_STREAM_GROUP_COMPONENTS
}
-static int show_stream_group(WriterContext *w, InputFile *ifile, AVStreamGroup *stg)
+static int show_stream_group(AVTextFormatContext *w, InputFile *ifile, AVStreamGroup *stg)
{
AVFormatContext *fmt_ctx = ifile->fmt_ctx;
AVBPrint pbuf;
int i, ret = 0;
av_bprint_init(&pbuf, 1, AV_BPRINT_SIZE_UNLIMITED);
- writer_print_section_header(w, NULL, SECTION_ID_STREAM_GROUP);
+ avtext_print_section_header(w, NULL, SECTION_ID_STREAM_GROUP);
print_int("index", stg->index);
if (fmt_ctx->iformat->flags & AVFMT_SHOW_IDS) print_fmt ("id", "0x%"PRIx64, stg->id);
else print_str_opt("id", "N/A");
@@ -2182,7 +2177,7 @@ static int show_stream_group(WriterContext *w, InputFile *ifile, AVStreamGroup *
if (ret < 0)
goto end;
- writer_print_section_header(w, NULL, SECTION_ID_STREAM_GROUP_STREAMS);
+ avtext_print_section_header(w, NULL, SECTION_ID_STREAM_GROUP_STREAMS);
for (i = 0; i < stg->nb_streams; i++) {
if (selected_streams[stg->streams[i]->index]) {
ret = show_stream(w, fmt_ctx, stg->streams[i]->index, &ifile->streams[stg->streams[i]->index], IN_STREAM_GROUP);
@@ -2190,20 +2185,20 @@ static int show_stream_group(WriterContext *w, InputFile *ifile, AVStreamGroup *
break;
}
}
- writer_print_section_footer(w);
+ avtext_print_section_footer(w);
end:
av_bprint_finalize(&pbuf, NULL);
- writer_print_section_footer(w);
+ avtext_print_section_footer(w);
return ret;
}
-static int show_stream_groups(WriterContext *w, InputFile *ifile)
+static int show_stream_groups(AVTextFormatContext *w, InputFile *ifile)
{
AVFormatContext *fmt_ctx = ifile->fmt_ctx;
int i, ret = 0;
- writer_print_section_header(w, NULL, SECTION_ID_STREAM_GROUPS);
+ avtext_print_section_header(w, NULL, SECTION_ID_STREAM_GROUPS);
for (i = 0; i < fmt_ctx->nb_stream_groups; i++) {
AVStreamGroup *stg = fmt_ctx->stream_groups[i];
@@ -2211,20 +2206,20 @@ static int show_stream_groups(WriterContext *w, InputFile *ifile)
if (ret < 0)
break;
}
- writer_print_section_footer(w);
+ avtext_print_section_footer(w);
return ret;
}
-static int show_chapters(WriterContext *w, InputFile *ifile)
+static int show_chapters(AVTextFormatContext *w, InputFile *ifile)
{
AVFormatContext *fmt_ctx = ifile->fmt_ctx;
int i, ret = 0;
- writer_print_section_header(w, NULL, SECTION_ID_CHAPTERS);
+ avtext_print_section_header(w, NULL, SECTION_ID_CHAPTERS);
for (i = 0; i < fmt_ctx->nb_chapters; i++) {
AVChapter *chapter = fmt_ctx->chapters[i];
- writer_print_section_header(w, NULL, SECTION_ID_CHAPTER);
+ avtext_print_section_header(w, NULL, SECTION_ID_CHAPTER);
print_int("id", chapter->id);
print_q ("time_base", chapter->time_base, '/');
print_int("start", chapter->start);
@@ -2233,20 +2228,20 @@ static int show_chapters(WriterContext *w, InputFile *ifile)
print_time("end_time", chapter->end, &chapter->time_base);
if (do_show_chapter_tags)
ret = show_tags(w, chapter->metadata, SECTION_ID_CHAPTER_TAGS);
- writer_print_section_footer(w);
+ avtext_print_section_footer(w);
}
- writer_print_section_footer(w);
+ avtext_print_section_footer(w);
return ret;
}
-static int show_format(WriterContext *w, InputFile *ifile)
+static int show_format(AVTextFormatContext *w, InputFile *ifile)
{
AVFormatContext *fmt_ctx = ifile->fmt_ctx;
int64_t size = fmt_ctx->pb ? avio_size(fmt_ctx->pb) : -1;
int ret = 0;
- writer_print_section_header(w, NULL, SECTION_ID_FORMAT);
+ avtext_print_section_header(w, NULL, SECTION_ID_FORMAT);
print_str_validate("filename", fmt_ctx->url);
print_int("nb_streams", fmt_ctx->nb_streams);
print_int("nb_programs", fmt_ctx->nb_programs);
@@ -2266,17 +2261,17 @@ static int show_format(WriterContext *w, InputFile *ifile)
if (do_show_format_tags)
ret = show_tags(w, fmt_ctx->metadata, SECTION_ID_FORMAT_TAGS);
- writer_print_section_footer(w);
+ avtext_print_section_footer(w);
fflush(stdout);
return ret;
}
-static void show_error(WriterContext *w, int err)
+static void show_error(AVTextFormatContext *w, int err)
{
- writer_print_section_header(w, NULL, SECTION_ID_ERROR);
+ avtext_print_section_header(w, NULL, SECTION_ID_ERROR);
print_int("code", err);
print_str("string", av_err2str(err));
- writer_print_section_footer(w);
+ avtext_print_section_footer(w);
}
static int open_input_file(InputFile *ifile, const char *filename,
@@ -2418,7 +2413,7 @@ static void close_input_file(InputFile *ifile)
avformat_close_input(&ifile->fmt_ctx);
}
-static int probe_file(WriterContext *tctx, const char *filename,
+static int probe_file(AVTextFormatContext *tctx, const char *filename,
const char *print_filename)
{
InputFile ifile = { 0 };
@@ -2467,10 +2462,10 @@ static int probe_file(WriterContext *tctx, const char *filename,
else // (!do_show_packets && do_show_frames)
section_id = SECTION_ID_FRAMES;
if (do_show_frames || do_show_packets)
- writer_print_section_header(tctx, NULL, section_id);
+ avtext_print_section_header(tctx, NULL, section_id);
ret = read_packets(tctx, &ifile);
if (do_show_frames || do_show_packets)
- writer_print_section_footer(tctx);
+ avtext_print_section_footer(tctx);
CHECK_END;
}
@@ -2516,18 +2511,18 @@ static void show_usage(void)
av_log(NULL, AV_LOG_INFO, "\n");
}
-static void ffprobe_show_program_version(WriterContext *w)
+static void ffprobe_show_program_version(AVTextFormatContext *w)
{
AVBPrint pbuf;
av_bprint_init(&pbuf, 1, AV_BPRINT_SIZE_UNLIMITED);
- writer_print_section_header(w, NULL, SECTION_ID_PROGRAM_VERSION);
+ avtext_print_section_header(w, NULL, SECTION_ID_PROGRAM_VERSION);
print_str("version", FFMPEG_VERSION);
print_fmt("copyright", "Copyright (c) %d-%d the FFmpeg developers",
program_birth_year, CONFIG_THIS_YEAR);
print_str("compiler_ident", CC_IDENT);
print_str("configuration", FFMPEG_CONFIGURATION);
- writer_print_section_footer(w);
+ avtext_print_section_footer(w);
av_bprint_finalize(&pbuf, NULL);
}
@@ -2536,20 +2531,20 @@ static void ffprobe_show_program_version(WriterContext *w)
do { \
if (CONFIG_##LIBNAME) { \
unsigned int version = libname##_version(); \
- writer_print_section_header(w, NULL, SECTION_ID_LIBRARY_VERSION); \
+ avtext_print_section_header(w, NULL, SECTION_ID_LIBRARY_VERSION); \
print_str("name", "lib" #libname); \
print_int("major", LIB##LIBNAME##_VERSION_MAJOR); \
print_int("minor", LIB##LIBNAME##_VERSION_MINOR); \
print_int("micro", LIB##LIBNAME##_VERSION_MICRO); \
print_int("version", version); \
print_str("ident", LIB##LIBNAME##_IDENT); \
- writer_print_section_footer(w); \
+ avtext_print_section_footer(w); \
} \
} while (0)
-static void ffprobe_show_library_versions(WriterContext *w)
+static void ffprobe_show_library_versions(AVTextFormatContext *w)
{
- writer_print_section_header(w, NULL, SECTION_ID_LIBRARY_VERSIONS);
+ avtext_print_section_header(w, NULL, SECTION_ID_LIBRARY_VERSIONS);
SHOW_LIB_VERSION(avutil, AVUTIL);
SHOW_LIB_VERSION(avcodec, AVCODEC);
SHOW_LIB_VERSION(avformat, AVFORMAT);
@@ -2558,7 +2553,7 @@ static void ffprobe_show_library_versions(WriterContext *w)
SHOW_LIB_VERSION(swscale, SWSCALE);
SHOW_LIB_VERSION(swresample, SWRESAMPLE);
SHOW_LIB_VERSION(postproc, POSTPROC);
- writer_print_section_footer(w);
+ avtext_print_section_footer(w);
}
#define PRINT_PIX_FMT_FLAG(flagname, name) \
@@ -2566,14 +2561,14 @@ static void ffprobe_show_library_versions(WriterContext *w)
print_int(name, !!(pixdesc->flags & AV_PIX_FMT_FLAG_##flagname)); \
} while (0)
-static void ffprobe_show_pixel_formats(WriterContext *w)
+static void ffprobe_show_pixel_formats(AVTextFormatContext *w)
{
const AVPixFmtDescriptor *pixdesc = NULL;
int i, n;
- writer_print_section_header(w, NULL, SECTION_ID_PIXEL_FORMATS);
+ avtext_print_section_header(w, NULL, SECTION_ID_PIXEL_FORMATS);
while (pixdesc = av_pix_fmt_desc_next(pixdesc)) {
- writer_print_section_header(w, NULL, SECTION_ID_PIXEL_FORMAT);
+ avtext_print_section_header(w, NULL, SECTION_ID_PIXEL_FORMAT);
print_str("name", pixdesc->name);
print_int("nb_components", pixdesc->nb_components);
if ((pixdesc->nb_components >= 3) && !(pixdesc->flags & AV_PIX_FMT_FLAG_RGB)) {
@@ -2587,7 +2582,7 @@ static void ffprobe_show_pixel_formats(WriterContext *w)
if (n) print_int ("bits_per_pixel", n);
else print_str_opt("bits_per_pixel", "N/A");
if (do_show_pixel_format_flags) {
- writer_print_section_header(w, NULL, SECTION_ID_PIXEL_FORMAT_FLAGS);
+ avtext_print_section_header(w, NULL, SECTION_ID_PIXEL_FORMAT_FLAGS);
PRINT_PIX_FMT_FLAG(BE, "big_endian");
PRINT_PIX_FMT_FLAG(PAL, "palette");
PRINT_PIX_FMT_FLAG(BITSTREAM, "bitstream");
@@ -2595,21 +2590,21 @@ static void ffprobe_show_pixel_formats(WriterContext *w)
PRINT_PIX_FMT_FLAG(PLANAR, "planar");
PRINT_PIX_FMT_FLAG(RGB, "rgb");
PRINT_PIX_FMT_FLAG(ALPHA, "alpha");
- writer_print_section_footer(w);
+ avtext_print_section_footer(w);
}
if (do_show_pixel_format_components && (pixdesc->nb_components > 0)) {
- writer_print_section_header(w, NULL, SECTION_ID_PIXEL_FORMAT_COMPONENTS);
+ avtext_print_section_header(w, NULL, SECTION_ID_PIXEL_FORMAT_COMPONENTS);
for (i = 0; i < pixdesc->nb_components; i++) {
- writer_print_section_header(w, NULL, SECTION_ID_PIXEL_FORMAT_COMPONENT);
+ avtext_print_section_header(w, NULL, SECTION_ID_PIXEL_FORMAT_COMPONENT);
print_int("index", i + 1);
print_int("bit_depth", pixdesc->comp[i].depth);
- writer_print_section_footer(w);
+ avtext_print_section_footer(w);
}
- writer_print_section_footer(w);
+ avtext_print_section_footer(w);
}
- writer_print_section_footer(w);
+ avtext_print_section_footer(w);
}
- writer_print_section_footer(w);
+ avtext_print_section_footer(w);
}
static int opt_show_optional_fields(void *optctx, const char *opt, const char *arg)
@@ -3057,7 +3052,7 @@ static inline int check_section_show_entries(int section_id)
int main(int argc, char **argv)
{
const AVTextFormatter *f;
- WriterContext *tctx;
+ AVTextFormatContext *tctx;
AVTextWriterContext *wctx;
char *buf;
char *f_name = NULL, *f_args = NULL;
@@ -3159,7 +3154,7 @@ int main(int argc, char **argv)
if (f == &avtextformatter_xml)
tctx->string_validation_utf8_flags |= AV_UTF8_FLAG_EXCLUDE_XML_INVALID_CONTROL_CODES;
- writer_print_section_header(tctx, NULL, SECTION_ID_ROOT);
+ avtext_print_section_header(tctx, NULL, SECTION_ID_ROOT);
if (do_show_program_version)
ffprobe_show_program_version(tctx);
--
ffmpeg-codebot
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 108+ messages in thread
* [FFmpeg-devel] [PATCH v6 4/8] fftools/ffmpeg_filter: Move some declaration to new header file
2025-03-08 20:16 ` [FFmpeg-devel] [PATCH v6 0/8] print_graphs: Complete Filtergraph Printing ffmpegagent
` (2 preceding siblings ...)
2025-03-08 20:16 ` [FFmpeg-devel] [PATCH v6 3/8] fftools/ffprobe: Rename writer_print_section_* and WriterContext softworkz
@ 2025-03-08 20:16 ` softworkz
2025-03-10 21:47 ` Stefano Sabatini
2025-03-08 20:16 ` [FFmpeg-devel] [PATCH v6 5/8] avfilter/avfilter: Add avfilter_link_get_hw_frames_ctx() softworkz
` (5 subsequent siblings)
9 siblings, 1 reply; 108+ messages in thread
From: softworkz @ 2025-03-08 20:16 UTC (permalink / raw)
To: ffmpeg-devel; +Cc: softworkz
From: softworkz <softworkz@hotmail.com>
to allow print_graph to access the information.
Signed-off-by: softworkz <softworkz@hotmail.com>
---
fftools/ffmpeg_filter.c | 188 +-------------------------------
fftools/ffmpeg_filter.h | 232 ++++++++++++++++++++++++++++++++++++++++
2 files changed, 233 insertions(+), 187 deletions(-)
create mode 100644 fftools/ffmpeg_filter.h
diff --git a/fftools/ffmpeg_filter.c b/fftools/ffmpeg_filter.c
index 800e2a3f06..6de4e87ade 100644
--- a/fftools/ffmpeg_filter.c
+++ b/fftools/ffmpeg_filter.c
@@ -21,6 +21,7 @@
#include <stdint.h>
#include "ffmpeg.h"
+#include "ffmpeg_filter.h"
#include "libavfilter/avfilter.h"
#include "libavfilter/buffersink.h"
@@ -42,44 +43,6 @@
// FIXME private header, used for mid_pred()
#include "libavcodec/mathops.h"
-typedef struct FilterGraphPriv {
- FilterGraph fg;
-
- // name used for logging
- char log_name[32];
-
- int is_simple;
- // true when the filtergraph contains only meta filters
- // that do not modify the frame data
- int is_meta;
- // source filters are present in the graph
- int have_sources;
- int disable_conversions;
-
- unsigned nb_outputs_done;
-
- const char *graph_desc;
-
- int nb_threads;
-
- // frame for temporarily holding output from the filtergraph
- AVFrame *frame;
- // frame for sending output to the encoder
- AVFrame *frame_enc;
-
- Scheduler *sch;
- unsigned sch_idx;
-} FilterGraphPriv;
-
-static FilterGraphPriv *fgp_from_fg(FilterGraph *fg)
-{
- return (FilterGraphPriv*)fg;
-}
-
-static const FilterGraphPriv *cfgp_from_cfg(const FilterGraph *fg)
-{
- return (const FilterGraphPriv*)fg;
-}
// data that is local to the filter thread and not visible outside of it
typedef struct FilterGraphThread {
@@ -102,155 +65,6 @@ typedef struct FilterGraphThread {
uint8_t *eof_out;
} FilterGraphThread;
-typedef struct InputFilterPriv {
- InputFilter ifilter;
-
- InputFilterOptions opts;
-
- int index;
-
- AVFilterContext *filter;
-
- // used to hold submitted input
- AVFrame *frame;
-
- /* for filters that are not yet bound to an input stream,
- * this stores the input linklabel, if any */
- uint8_t *linklabel;
-
- // filter data type
- enum AVMediaType type;
- // source data type: AVMEDIA_TYPE_SUBTITLE for sub2video,
- // same as type otherwise
- enum AVMediaType type_src;
-
- int eof;
- int bound;
-
- // parameters configured for this input
- int format;
-
- int width, height;
- AVRational sample_aspect_ratio;
- enum AVColorSpace color_space;
- enum AVColorRange color_range;
-
- int sample_rate;
- AVChannelLayout ch_layout;
-
- AVRational time_base;
-
- AVFrameSideData **side_data;
- int nb_side_data;
-
- AVFifo *frame_queue;
-
- AVBufferRef *hw_frames_ctx;
-
- int displaymatrix_present;
- int displaymatrix_applied;
- int32_t displaymatrix[9];
-
- int downmixinfo_present;
- AVDownmixInfo downmixinfo;
-
- struct {
- AVFrame *frame;
-
- int64_t last_pts;
- int64_t end_pts;
-
- ///< marks if sub2video_update should force an initialization
- unsigned int initialize;
- } sub2video;
-} InputFilterPriv;
-
-static InputFilterPriv *ifp_from_ifilter(InputFilter *ifilter)
-{
- return (InputFilterPriv*)ifilter;
-}
-
-typedef struct FPSConvContext {
- AVFrame *last_frame;
- /* number of frames emitted by the video-encoding sync code */
- int64_t frame_number;
- /* history of nb_frames_prev, i.e. the number of times the
- * previous frame was duplicated by vsync code in recent
- * do_video_out() calls */
- int64_t frames_prev_hist[3];
-
- uint64_t dup_warning;
-
- int last_dropped;
- int dropped_keyframe;
-
- enum VideoSyncMethod vsync_method;
-
- AVRational framerate;
- AVRational framerate_max;
- const AVRational *framerate_supported;
- int framerate_clip;
-} FPSConvContext;
-
-typedef struct OutputFilterPriv {
- OutputFilter ofilter;
-
- int index;
-
- void *log_parent;
- char log_name[32];
-
- char *name;
-
- AVFilterContext *filter;
-
- /* desired output stream properties */
- int format;
- int width, height;
- int sample_rate;
- AVChannelLayout ch_layout;
- enum AVColorSpace color_space;
- enum AVColorRange color_range;
-
- AVFrameSideData **side_data;
- int nb_side_data;
-
- // time base in which the output is sent to our downstream
- // does not need to match the filtersink's timebase
- AVRational tb_out;
- // at least one frame with the above timebase was sent
- // to our downstream, so it cannot change anymore
- int tb_out_locked;
-
- AVRational sample_aspect_ratio;
-
- AVDictionary *sws_opts;
- AVDictionary *swr_opts;
-
- // those are only set if no format is specified and the encoder gives us multiple options
- // They point directly to the relevant lists of the encoder.
- const int *formats;
- const AVChannelLayout *ch_layouts;
- const int *sample_rates;
- const enum AVColorSpace *color_spaces;
- const enum AVColorRange *color_ranges;
-
- AVRational enc_timebase;
- int64_t trim_start_us;
- int64_t trim_duration_us;
- // offset for output timestamps, in AV_TIME_BASE_Q
- int64_t ts_offset;
- int64_t next_pts;
- FPSConvContext fps;
-
- unsigned flags;
-} OutputFilterPriv;
-
-static OutputFilterPriv *ofp_from_ofilter(OutputFilter *ofilter)
-{
- return (OutputFilterPriv*)ofilter;
-}
-
typedef struct FilterCommand {
char *target;
char *command;
diff --git a/fftools/ffmpeg_filter.h b/fftools/ffmpeg_filter.h
new file mode 100644
index 0000000000..94296c5eac
--- /dev/null
+++ b/fftools/ffmpeg_filter.h
@@ -0,0 +1,232 @@
+/*
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef FFTOOLS_FFMPEG_FILTER_H
+#define FFTOOLS_FFMPEG_FILTER_H
+
+#include "ffmpeg.h"
+
+#include <stdint.h>
+
+#include "ffmpeg_sched.h"
+#include "sync_queue.h"
+
+#include "libavfilter/avfilter.h"
+
+#include "libavutil/avutil.h"
+#include "libavutil/dict.h"
+#include "libavutil/fifo.h"
+#include "libavutil/pixfmt.h"
+#include "libavutil/rational.h"
+#include "libavutil/bprint.h"
+#include "libavutil/channel_layout.h"
+#include "libavutil/downmix_info.h"
+
+typedef struct FilterGraphPriv {
+ FilterGraph fg;
+
+ // name used for logging
+ char log_name[32];
+
+ int is_simple;
+ // true when the filtergraph contains only meta filters
+ // that do not modify the frame data
+ int is_meta;
+ // source filters are present in the graph
+ int have_sources;
+ int disable_conversions;
+
+ unsigned nb_outputs_done;
+
+ const char *graph_desc;
+
+ int nb_threads;
+
+ // frame for temporarily holding output from the filtergraph
+ AVFrame *frame;
+ // frame for sending output to the encoder
+ AVFrame *frame_enc;
+
+ Scheduler *sch;
+ unsigned sch_idx;
+
+ AVBPrint graph_print_buf;
+
+} FilterGraphPriv;
+
+static inline FilterGraphPriv *fgp_from_fg(FilterGraph *fg)
+{
+ return (FilterGraphPriv*)fg;
+}
+
+static inline const FilterGraphPriv *cfgp_from_cfg(const FilterGraph *fg)
+{
+ return (const FilterGraphPriv*)fg;
+}
+
+typedef struct InputFilterPriv {
+ InputFilter ifilter;
+
+ InputFilterOptions opts;
+
+ int index;
+
+ AVFilterContext *filter;
+
+ // used to hold submitted input
+ AVFrame *frame;
+
+ /* for filters that are not yet bound to an input stream,
+ * this stores the input linklabel, if any */
+ uint8_t *linklabel;
+
+ // filter data type
+ enum AVMediaType type;
+ // source data type: AVMEDIA_TYPE_SUBTITLE for sub2video,
+ // same as type otherwise
+ enum AVMediaType type_src;
+
+ int eof;
+ int bound;
+
+ // parameters configured for this input
+ int format;
+
+ int width, height;
+ AVRational sample_aspect_ratio;
+ enum AVColorSpace color_space;
+ enum AVColorRange color_range;
+
+ int sample_rate;
+ AVChannelLayout ch_layout;
+
+ AVRational time_base;
+
+ AVFrameSideData **side_data;
+ int nb_side_data;
+
+ AVFifo *frame_queue;
+
+ AVBufferRef *hw_frames_ctx;
+
+ int displaymatrix_present;
+ int displaymatrix_applied;
+ int32_t displaymatrix[9];
+
+ int downmixinfo_present;
+ AVDownmixInfo downmixinfo;
+
+ struct {
+ AVFrame *frame;
+
+ int64_t last_pts;
+ int64_t end_pts;
+
+ ///< marks if sub2video_update should force an initialization
+ unsigned int initialize;
+ } sub2video;
+} InputFilterPriv;
+
+static inline InputFilterPriv *ifp_from_ifilter(InputFilter *ifilter)
+{
+ return (InputFilterPriv*)ifilter;
+}
+
+typedef struct FPSConvContext {
+ AVFrame *last_frame;
+ /* number of frames emitted by the video-encoding sync code */
+ int64_t frame_number;
+ /* history of nb_frames_prev, i.e. the number of times the
+ * previous frame was duplicated by vsync code in recent
+ * do_video_out() calls */
+ int64_t frames_prev_hist[3];
+
+ uint64_t dup_warning;
+
+ int last_dropped;
+ int dropped_keyframe;
+
+ enum VideoSyncMethod vsync_method;
+
+ AVRational framerate;
+ AVRational framerate_max;
+ const AVRational *framerate_supported;
+ int framerate_clip;
+} FPSConvContext;
+
+
+typedef struct OutputFilterPriv {
+ OutputFilter ofilter;
+
+ int index;
+
+ void *log_parent;
+ char log_name[32];
+
+ char *name;
+
+ AVFilterContext *filter;
+
+ /* desired output stream properties */
+ int format;
+ int width, height;
+ int sample_rate;
+ AVChannelLayout ch_layout;
+ enum AVColorSpace color_space;
+ enum AVColorRange color_range;
+
+ AVFrameSideData **side_data;
+ int nb_side_data;
+
+ // time base in which the output is sent to our downstream
+ // does not need to match the filtersink's timebase
+ AVRational tb_out;
+ // at least one frame with the above timebase was sent
+ // to our downstream, so it cannot change anymore
+ int tb_out_locked;
+
+ AVRational sample_aspect_ratio;
+
+ AVDictionary *sws_opts;
+ AVDictionary *swr_opts;
+
+ // those are only set if no format is specified and the encoder gives us multiple options
+ // They point directly to the relevant lists of the encoder.
+ const int *formats;
+ const AVChannelLayout *ch_layouts;
+ const int *sample_rates;
+ const enum AVColorSpace *color_spaces;
+ const enum AVColorRange *color_ranges;
+
+ AVRational enc_timebase;
+ int64_t trim_start_us;
+ int64_t trim_duration_us;
+ // offset for output timestamps, in AV_TIME_BASE_Q
+ int64_t ts_offset;
+ int64_t next_pts;
+ FPSConvContext fps;
+
+ unsigned flags;
+} OutputFilterPriv;
+
+static inline OutputFilterPriv *ofp_from_ofilter(OutputFilter *ofilter)
+{
+ return (OutputFilterPriv*)ofilter;
+}
+
+#endif /* FFTOOLS_FFMPEG_FILTER_H */
--
ffmpeg-codebot
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 108+ messages in thread
* [FFmpeg-devel] [PATCH v6 5/8] avfilter/avfilter: Add avfilter_link_get_hw_frames_ctx()
2025-03-08 20:16 ` [FFmpeg-devel] [PATCH v6 0/8] print_graphs: Complete Filtergraph Printing ffmpegagent
` (3 preceding siblings ...)
2025-03-08 20:16 ` [FFmpeg-devel] [PATCH v6 4/8] fftools/ffmpeg_filter: Move some declaration to new header file softworkz
@ 2025-03-08 20:16 ` softworkz
2025-03-10 22:11 ` Stefano Sabatini
2025-03-08 20:16 ` [FFmpeg-devel] [PATCH v6 6/8] fftools/ffmpeg_graphprint: Add options for filtergraph printing softworkz
` (4 subsequent siblings)
9 siblings, 1 reply; 108+ messages in thread
From: softworkz @ 2025-03-08 20:16 UTC (permalink / raw)
To: ffmpeg-devel; +Cc: softworkz
From: softworkz <softworkz@hotmail.com>
---
doc/APIchanges | 3 +++
libavfilter/avfilter.c | 9 +++++++++
libavfilter/avfilter.h | 12 ++++++++++++
libavfilter/version.h | 2 +-
4 files changed, 25 insertions(+), 1 deletion(-)
diff --git a/doc/APIchanges b/doc/APIchanges
index 5a64836e25..354716399d 100644
--- a/doc/APIchanges
+++ b/doc/APIchanges
@@ -2,6 +2,9 @@ The last version increases of all libraries were on 2024-03-07
API changes, most recent first:
+2025-02-xx - xxxxxxxxxx - lavfi 10.10.100 - avfilter.h
+ Add avfilter_link_get_hw_frames_ctx().
+
2025-03-01 - xxxxxxxxxx - lavu 59.58.100 - pixfmt.h
Add AV_PIX_FMT_GRAY32BE and AV_PIX_FMT_GRAY32LE.
diff --git a/libavfilter/avfilter.c b/libavfilter/avfilter.c
index e732556ffa..13abd7e8ad 100644
--- a/libavfilter/avfilter.c
+++ b/libavfilter/avfilter.c
@@ -1006,6 +1006,15 @@ enum AVMediaType avfilter_pad_get_type(const AVFilterPad *pads, int pad_idx)
return pads[pad_idx].type;
}
+AVBufferRef *avfilter_link_get_hw_frames_ctx(AVFilterLink *link)
+{
+ FilterLink* plink = ff_filter_link(link);
+ if (plink->hw_frames_ctx)
+ return av_buffer_ref(plink->hw_frames_ctx);
+
+ return NULL;
+}
+
static int default_filter_frame(AVFilterLink *link, AVFrame *frame)
{
return ff_filter_frame(link->dst->outputs[0], frame);
diff --git a/libavfilter/avfilter.h b/libavfilter/avfilter.h
index 4520d5f978..27c50520b3 100644
--- a/libavfilter/avfilter.h
+++ b/libavfilter/avfilter.h
@@ -96,6 +96,18 @@ const char *avfilter_pad_get_name(const AVFilterPad *pads, int pad_idx);
*/
enum AVMediaType avfilter_pad_get_type(const AVFilterPad *pads, int pad_idx);
+/**
+ * Get the hardware frames context of a filter link.
+ *
+ * @param link an AVFilterLink
+ *
+ * @return a ref-counted copy of the link's hw_frames_ctx if there's a hardware
+ * frames context associated with the link or NULL otherwise.
+ * The returned AVBufferRef needs to be released with av_buffer_unref()
+ * when it's no longer used.
+ */
+AVBufferRef* avfilter_link_get_hw_frames_ctx(AVFilterLink *link);
+
/**
* Lists of formats / etc. supported by an end of a link.
*
diff --git a/libavfilter/version.h b/libavfilter/version.h
index 77f38cb9b4..4a69d6be98 100644
--- a/libavfilter/version.h
+++ b/libavfilter/version.h
@@ -31,7 +31,7 @@
#include "version_major.h"
-#define LIBAVFILTER_VERSION_MINOR 9
+#define LIBAVFILTER_VERSION_MINOR 10
#define LIBAVFILTER_VERSION_MICRO 100
--
ffmpeg-codebot
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 108+ messages in thread
* Re: [FFmpeg-devel] [PATCH v6 5/8] avfilter/avfilter: Add avfilter_link_get_hw_frames_ctx()
2025-03-08 20:16 ` [FFmpeg-devel] [PATCH v6 5/8] avfilter/avfilter: Add avfilter_link_get_hw_frames_ctx() softworkz
@ 2025-03-10 22:11 ` Stefano Sabatini
0 siblings, 0 replies; 108+ messages in thread
From: Stefano Sabatini @ 2025-03-10 22:11 UTC (permalink / raw)
To: FFmpeg development discussions and patches; +Cc: softworkz
On date Saturday 2025-03-08 20:16:31 +0000, softworkz wrote:
> From: softworkz <softworkz@hotmail.com>
>
> ---
> doc/APIchanges | 3 +++
> libavfilter/avfilter.c | 9 +++++++++
> libavfilter/avfilter.h | 12 ++++++++++++
> libavfilter/version.h | 2 +-
> 4 files changed, 25 insertions(+), 1 deletion(-)
>
> diff --git a/doc/APIchanges b/doc/APIchanges
> index 5a64836e25..354716399d 100644
> --- a/doc/APIchanges
> +++ b/doc/APIchanges
> @@ -2,6 +2,9 @@ The last version increases of all libraries were on 2024-03-07
>
> API changes, most recent first:
>
> +2025-02-xx - xxxxxxxxxx - lavfi 10.10.100 - avfilter.h
> + Add avfilter_link_get_hw_frames_ctx().
> +
> 2025-03-01 - xxxxxxxxxx - lavu 59.58.100 - pixfmt.h
> Add AV_PIX_FMT_GRAY32BE and AV_PIX_FMT_GRAY32LE.
Unrelated but we should automate this xxx filling.
> diff --git a/libavfilter/avfilter.c b/libavfilter/avfilter.c
> index e732556ffa..13abd7e8ad 100644
> --- a/libavfilter/avfilter.c
> +++ b/libavfilter/avfilter.c
> @@ -1006,6 +1006,15 @@ enum AVMediaType avfilter_pad_get_type(const AVFilterPad *pads, int pad_idx)
> return pads[pad_idx].type;
> }
>
> +AVBufferRef *avfilter_link_get_hw_frames_ctx(AVFilterLink *link)
> +{
> + FilterLink* plink = ff_filter_link(link);
nit: FilterLink *plink style is more kosher
> + if (plink->hw_frames_ctx)
> + return av_buffer_ref(plink->hw_frames_ctx);
> +
> + return NULL;
> +}
> +
> static int default_filter_frame(AVFilterLink *link, AVFrame *frame)
> {
> return ff_filter_frame(link->dst->outputs[0], frame);
> diff --git a/libavfilter/avfilter.h b/libavfilter/avfilter.h
> index 4520d5f978..27c50520b3 100644
> --- a/libavfilter/avfilter.h
> +++ b/libavfilter/avfilter.h
> @@ -96,6 +96,18 @@ const char *avfilter_pad_get_name(const AVFilterPad *pads, int pad_idx);
> */
> enum AVMediaType avfilter_pad_get_type(const AVFilterPad *pads, int pad_idx);
>
> +/**
> + * Get the hardware frames context of a filter link.
> + *
> + * @param link an AVFilterLink
> + *
> + * @return a ref-counted copy of the link's hw_frames_ctx if there's a hardware
of the link's hw_frames_ctx *field* ...
> + * frames context associated with the link or NULL otherwise.
> + * The returned AVBufferRef needs to be released with av_buffer_unref()
> + * when it's no longer used.
nit++: "there is... it is..." to aid non-native readers
[...]
Looks good to me otherwise.
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 108+ messages in thread
* [FFmpeg-devel] [PATCH v6 6/8] fftools/ffmpeg_graphprint: Add options for filtergraph printing
2025-03-08 20:16 ` [FFmpeg-devel] [PATCH v6 0/8] print_graphs: Complete Filtergraph Printing ffmpegagent
` (4 preceding siblings ...)
2025-03-08 20:16 ` [FFmpeg-devel] [PATCH v6 5/8] avfilter/avfilter: Add avfilter_link_get_hw_frames_ctx() softworkz
@ 2025-03-08 20:16 ` softworkz
2025-03-10 23:03 ` Stefano Sabatini
2025-03-08 20:16 ` [FFmpeg-devel] [PATCH v6 7/8] fftools: Enable filtergraph printing and update docs softworkz
` (3 subsequent siblings)
9 siblings, 1 reply; 108+ messages in thread
From: softworkz @ 2025-03-08 20:16 UTC (permalink / raw)
To: ffmpeg-devel; +Cc: softworkz
From: softworkz <softworkz@hotmail.com>
The key benefits are:
- Different to other graph printing methods, this is outputting:
- all graphs with runtime state
(including auto-inserted filters)
- each graph with its inputs and outputs
- all filters with their in- and output pads
- all connections between all input- and output pads
- for each connection:
- the runtime-negotiated format and media type
- the hw context
- if video hw context, both: hw pixfmt + sw pixfmt
- Output can either be printed to stdout or written to specified file
- Output is machine-readable
- Use the same output implementation as ffprobe, supporting multiple
formats
Signed-off-by: softworkz <softworkz@hotmail.com>
---
fftools/Makefile | 11 +
fftools/ffmpeg.h | 3 +
fftools/ffmpeg_graphprint.c | 518 ++++++++++++++++++++++++++++++++++++
fftools/ffmpeg_graphprint.h | 35 +++
fftools/ffmpeg_opt.c | 12 +
5 files changed, 579 insertions(+)
create mode 100644 fftools/ffmpeg_graphprint.c
create mode 100644 fftools/ffmpeg_graphprint.h
diff --git a/fftools/Makefile b/fftools/Makefile
index 664b73b161..03cdbd4b6e 100644
--- a/fftools/Makefile
+++ b/fftools/Makefile
@@ -19,8 +19,19 @@ OBJS-ffmpeg += \
fftools/ffmpeg_mux_init.o \
fftools/ffmpeg_opt.o \
fftools/ffmpeg_sched.o \
+ fftools/ffmpeg_graphprint.o \
fftools/sync_queue.o \
fftools/thread_queue.o \
+ fftools/textformat/avtextformat.o \
+ fftools/textformat/tf_compact.o \
+ fftools/textformat/tf_default.o \
+ fftools/textformat/tf_flat.o \
+ fftools/textformat/tf_ini.o \
+ fftools/textformat/tf_json.o \
+ fftools/textformat/tf_xml.o \
+ fftools/textformat/tw_avio.o \
+ fftools/textformat/tw_buffer.o \
+ fftools/textformat/tw_stdout.o \
OBJS-ffprobe += \
fftools/textformat/avtextformat.o \
diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h
index 86a3e10c6b..9880236162 100644
--- a/fftools/ffmpeg.h
+++ b/fftools/ffmpeg.h
@@ -715,6 +715,9 @@ extern float max_error_rate;
extern char *filter_nbthreads;
extern int filter_complex_nbthreads;
extern int vstats_version;
+extern int print_graphs;
+extern char* print_graphs_file;
+extern char* print_graphs_format;
extern int auto_conversion_filters;
extern const AVIOInterruptCB int_cb;
diff --git a/fftools/ffmpeg_graphprint.c b/fftools/ffmpeg_graphprint.c
new file mode 100644
index 0000000000..dd6862679e
--- /dev/null
+++ b/fftools/ffmpeg_graphprint.c
@@ -0,0 +1,518 @@
+/*
+ * Copyright (c) 2018 - softworkz
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+/**
+ * @file
+ * output writers for filtergraph details
+ */
+
+#include "config.h"
+
+#include <string.h>
+
+#include "ffmpeg_graphprint.h"
+#include "ffmpeg_filter.h"
+
+#include "libavutil/avassert.h"
+#include "libavutil/avstring.h"
+#include "libavutil/pixdesc.h"
+#include "libavutil/dict.h"
+#include "libavutil/common.h"
+#include "libavfilter/avfilter.h"
+#include "libavutil/buffer.h"
+#include "libavutil/hwcontext.h"
+#include "textformat/avtextformat.h"
+
+typedef enum {
+ SECTION_ID_ROOT,
+ SECTION_ID_PROGRAM_VERSION,
+ SECTION_ID_FILTERGRAPHS,
+ SECTION_ID_FILTERGRAPH,
+ SECTION_ID_INPUTS,
+ SECTION_ID_INPUT,
+ SECTION_ID_OUTPUTS,
+ SECTION_ID_OUTPUT,
+ SECTION_ID_FILTERS,
+ SECTION_ID_FILTER,
+ SECTION_ID_HWDEViCECONTEXT,
+ SECTION_ID_HWFRAMESCONTEXT,
+ SECTION_ID_ERROR,
+ SECTION_ID_LOG,
+ SECTION_ID_LOGS,
+} SectionID;
+
+static struct AVTextFormatSection sections[] = {
+ [SECTION_ID_ROOT] = { SECTION_ID_ROOT, "GraphDescription", AV_TEXTFORMAT_SECTION_FLAG_IS_WRAPPER,
+ { SECTION_ID_ERROR, SECTION_ID_PROGRAM_VERSION, SECTION_ID_FILTERGRAPHS, SECTION_ID_LOGS, -1} },
+ [SECTION_ID_PROGRAM_VERSION] = { SECTION_ID_PROGRAM_VERSION, "ProgramVersion", 0, { -1 } },
+
+ [SECTION_ID_FILTERGRAPHS] = { SECTION_ID_FILTERGRAPHS, "Graphs", AV_TEXTFORMAT_SECTION_FLAG_IS_ARRAY, { SECTION_ID_FILTERGRAPH, -1 } },
+ [SECTION_ID_FILTERGRAPH] = { SECTION_ID_FILTERGRAPH, "Graph", 0, { SECTION_ID_INPUTS, SECTION_ID_OUTPUTS, SECTION_ID_FILTERS, -1 }, },
+
+ [SECTION_ID_INPUTS] = { SECTION_ID_INPUTS, "Inputs", AV_TEXTFORMAT_SECTION_FLAG_IS_ARRAY, { SECTION_ID_INPUT, SECTION_ID_ERROR, -1 } },
+ [SECTION_ID_INPUT] = { SECTION_ID_INPUT, "Input", 0, { SECTION_ID_HWFRAMESCONTEXT, SECTION_ID_ERROR, -1 }, },
+
+ [SECTION_ID_OUTPUTS] = { SECTION_ID_OUTPUTS, "Outputs", AV_TEXTFORMAT_SECTION_FLAG_IS_ARRAY, { SECTION_ID_OUTPUT, SECTION_ID_ERROR, -1 } },
+ [SECTION_ID_OUTPUT] = { SECTION_ID_OUTPUT, "Output", 0, { SECTION_ID_HWFRAMESCONTEXT, SECTION_ID_ERROR, -1 }, },
+
+ [SECTION_ID_FILTERS] = { SECTION_ID_FILTERS, "Filters", AV_TEXTFORMAT_SECTION_FLAG_IS_ARRAY, { SECTION_ID_FILTER, SECTION_ID_ERROR, -1 } },
+ [SECTION_ID_FILTER] = { SECTION_ID_FILTER, "Filter", 0, { SECTION_ID_HWDEViCECONTEXT, SECTION_ID_ERROR, -1 }, },
+
+ [SECTION_ID_HWDEViCECONTEXT] = { SECTION_ID_HWDEViCECONTEXT, "HwDeviceContext", 0, { SECTION_ID_ERROR, -1 }, },
+ [SECTION_ID_HWFRAMESCONTEXT] = { SECTION_ID_HWFRAMESCONTEXT, "HwFramesContext", 0, { SECTION_ID_ERROR, -1 }, },
+
+ [SECTION_ID_ERROR] = { SECTION_ID_ERROR, "Error", 0, { -1 } },
+ [SECTION_ID_LOGS] = { SECTION_ID_LOGS, "Log", AV_TEXTFORMAT_SECTION_FLAG_IS_ARRAY, { SECTION_ID_LOG, -1 } },
+ [SECTION_ID_LOG] = { SECTION_ID_LOG, "LogEntry", 0, { -1 }, },
+};
+
+/* Text Format API Shortcuts */
+#define print_int(k, v) avtext_print_integer(w, k, v)
+#define print_q(k, v, s) avtext_print_rational(w, k, v, s)
+#define print_str(k, v) avtext_print_string(w, k, v, 0)
+
+static void print_hwdevicecontext(AVTextFormatContext *w, const AVHWDeviceContext *hw_device_context)
+{
+ avtext_print_section_header(w, NULL, SECTION_ID_HWDEViCECONTEXT);
+
+ print_int("HasHwDeviceContext", 1);
+ print_str("DeviceType", av_hwdevice_get_type_name(hw_device_context->type));
+
+ avtext_print_section_footer(w); // SECTION_ID_HWDEViCECONTEXT
+}
+
+static void print_hwframescontext(AVTextFormatContext *w, const AVHWFramesContext *hw_frames_context)
+{
+ const AVPixFmtDescriptor* pixdescHw;
+ const AVPixFmtDescriptor* pixdescSw;
+
+ avtext_print_section_header(w, NULL, SECTION_ID_HWFRAMESCONTEXT);
+
+ print_int("HasHwFramesContext", 1);
+
+ pixdescHw = av_pix_fmt_desc_get(hw_frames_context->format);
+ if (pixdescHw) {
+ print_str("HwPixelFormat", pixdescHw->name);
+ print_str("HwPixelFormatAlias", pixdescHw->alias);
+ }
+
+ pixdescSw = av_pix_fmt_desc_get(hw_frames_context->sw_format);
+ if (pixdescSw) {
+ print_str("SwPixelFormat", pixdescSw->name);
+ print_str("SwPixelFormatAlias", pixdescSw->alias);
+ }
+
+ print_int("Width", hw_frames_context->width);
+ print_int("Height", hw_frames_context->height);
+
+ print_hwdevicecontext(w, hw_frames_context->device_ctx);
+
+ avtext_print_section_footer(w); // SECTION_ID_HWFRAMESCONTEXT
+}
+
+static void print_link(AVTextFormatContext *w, AVFilterLink *link)
+{
+ AVBufferRef *hw_frames_ctx;
+ char layoutString[64];
+
+ switch (link->type) {
+ case AVMEDIA_TYPE_VIDEO:
+ print_str("Format", av_x_if_null(av_get_pix_fmt_name(link->format), "?"));
+ print_int("Width", link->w);
+ print_int("Height", link->h);
+ print_q("SAR", link->sample_aspect_ratio, ':');
+ print_q("TimeBase", link->time_base, '/');
+ break;
+
+ ////case AVMEDIA_TYPE_SUBTITLE:
+ //// print_str("Format", av_x_if_null(av_get_subtitle_fmt_name(link->format), "?"));
+ //// print_int("Width", link->w);
+ //// print_int("Height", link->h);
+ //// print_q("TimeBase", link->time_base, '/');
+ //// break;
+
+ case AVMEDIA_TYPE_AUDIO:
+ av_channel_layout_describe(&link->ch_layout, layoutString, sizeof(layoutString));
+ print_str("ChannelString", layoutString);
+ print_int("Channels", link->ch_layout.nb_channels);
+ ////print_int("ChannelLayout", link->ch_layout);
+ print_int("SampleRate", link->sample_rate);
+ break;
+ }
+
+ hw_frames_ctx = avfilter_link_get_hw_frames_ctx(link);
+
+ if (hw_frames_ctx && hw_frames_ctx->buffer) {
+ print_hwframescontext(w, (AVHWFramesContext *)hw_frames_ctx->data);
+ }
+}
+
+static void print_filter(AVTextFormatContext *w, const AVFilterContext* filter)
+{
+ avtext_print_section_header(w, NULL, SECTION_ID_FILTER);
+
+ print_str("Name", filter->name);
+
+ if (filter->filter) {
+ print_str("Name2", filter->filter->name);
+ print_str("Description", filter->filter->description);
+ }
+
+ if (filter->hw_device_ctx) {
+ AVHWDeviceContext* decCtx = (AVHWDeviceContext*)filter->hw_device_ctx->data;
+ print_hwdevicecontext(w, decCtx);
+ }
+
+ avtext_print_section_header(w, NULL, SECTION_ID_INPUTS);
+
+ for (unsigned i = 0; i < filter->nb_inputs; i++) {
+ AVFilterLink *link = filter->inputs[i];
+ avtext_print_section_header(w, NULL, SECTION_ID_INPUT);
+
+ print_str("SourceName", link->src->name);
+ print_str("SourcePadName", avfilter_pad_get_name(link->srcpad, 0));
+ print_str("DestPadName", avfilter_pad_get_name(link->dstpad, 0));
+
+ print_link(w, link);
+
+ avtext_print_section_footer(w); // SECTION_ID_INPUT
+ }
+
+ avtext_print_section_footer(w); // SECTION_ID_INPUTS
+
+ avtext_print_section_header(w, NULL, SECTION_ID_OUTPUTS);
+
+ for (unsigned i = 0; i < filter->nb_outputs; i++) {
+ AVFilterLink *link = filter->outputs[i];
+ avtext_print_section_header(w, NULL, SECTION_ID_OUTPUT);
+
+ print_str("DestName", link->dst->name);
+ print_str("DestPadName", avfilter_pad_get_name(link->dstpad, 0));
+ print_str("SourceName", link->src->name);
+
+ print_link(w, link);
+
+ avtext_print_section_footer(w); // SECTION_ID_OUTPUT
+ }
+
+ avtext_print_section_footer(w); // SECTION_ID_OUTPUTS
+
+ avtext_print_section_footer(w); // SECTION_ID_FILTER
+}
+
+static void init_sections(void)
+{
+ for (unsigned i = 0; i < FF_ARRAY_ELEMS(sections); i++)
+ sections[i].show_all_entries = 1;
+}
+
+static void print_filtergraph_single(AVTextFormatContext *w, FilterGraph* fg, AVFilterGraph *graph)
+{
+ char layoutString[64];
+ FilterGraphPriv *fgp = fgp_from_fg(fg);
+
+ print_int("GraphIndex", fg->index);
+ print_str("Description", fgp->graph_desc);
+
+ avtext_print_section_header(w, NULL, SECTION_ID_INPUTS);
+
+ for (int i = 0; i < fg->nb_inputs; i++) {
+ InputFilterPriv* ifilter = ifp_from_ifilter(fg->inputs[i]);
+ enum AVMediaType mediaType = ifilter->type;
+
+ avtext_print_section_header(w, NULL, SECTION_ID_INPUT);
+
+ print_str("Name1", (char*)ifilter->ifilter.name);
+
+ if (ifilter->filter) {
+ print_str("Name2", ifilter->filter->name);
+ print_str("Name3", ifilter->filter->filter->name);
+ print_str("Description", ifilter->filter->filter->description);
+ }
+
+ print_str("MediaType", av_get_media_type_string(mediaType));
+ print_int("MediaTypeId", mediaType);
+
+ switch (ifilter->type) {
+ case AVMEDIA_TYPE_VIDEO:
+ case AVMEDIA_TYPE_SUBTITLE:
+ print_str("Format", av_x_if_null(av_get_pix_fmt_name(ifilter->format), "?"));
+ print_int("Width", ifilter->width);
+ print_int("Height", ifilter->height);
+ print_q("SAR", ifilter->sample_aspect_ratio, ':');
+ break;
+ case AVMEDIA_TYPE_AUDIO:
+
+ av_channel_layout_describe(&ifilter->ch_layout, layoutString, sizeof(layoutString));
+ print_str("ChannelString", layoutString);
+ print_int("SampleRate", ifilter->sample_rate);
+ break;
+ case AVMEDIA_TYPE_ATTACHMENT:
+ case AVMEDIA_TYPE_DATA:
+ break;
+ }
+
+ if (ifilter->hw_frames_ctx)
+ print_hwframescontext(w, (AVHWFramesContext*)ifilter->hw_frames_ctx->data);
+ else if (ifilter->filter && ifilter->filter->hw_device_ctx) {
+ AVHWDeviceContext* devCtx = (AVHWDeviceContext*)ifilter->filter->hw_device_ctx->data;
+ print_hwdevicecontext(w, devCtx);
+ }
+
+ avtext_print_section_footer(w); // SECTION_ID_INPUT
+ }
+
+ avtext_print_section_footer(w); // SECTION_ID_INPUTS
+
+
+ avtext_print_section_header(w, NULL, SECTION_ID_OUTPUTS);
+
+ for (int i = 0; i < fg->nb_outputs; i++) {
+ OutputFilterPriv *ofilter = ofp_from_ofilter(fg->outputs[i]);
+ enum AVMediaType mediaType = AVMEDIA_TYPE_UNKNOWN;
+
+ avtext_print_section_header(w, NULL, SECTION_ID_OUTPUT);
+ print_str("Name1", ofilter->name);
+
+ if (ofilter->filter) {
+ print_str("Name2", ofilter->filter->name);
+ print_str("Name3", ofilter->filter->filter->name);
+ print_str("Description", ofilter->filter->filter->description);
+
+ if (ofilter->filter->nb_inputs > 0)
+ mediaType = ofilter->filter->inputs[0]->type;
+ }
+
+ print_str("MediaType", av_get_media_type_string(mediaType));
+ print_int("MediaTypeId", mediaType);
+
+ switch (ofilter->ofilter.type) {
+ case AVMEDIA_TYPE_VIDEO:
+ case AVMEDIA_TYPE_SUBTITLE:
+ print_str("Format", av_x_if_null(av_get_pix_fmt_name(ofilter->format), "?"));
+ print_int("Width", ofilter->width);
+ print_int("Height", ofilter->height);
+ break;
+ case AVMEDIA_TYPE_AUDIO:
+
+ av_channel_layout_describe(&ofilter->ch_layout, layoutString, sizeof(layoutString));
+ print_str("ChannelString", layoutString);
+ print_int("SampleRate", ofilter->sample_rate);
+ break;
+ case AVMEDIA_TYPE_ATTACHMENT:
+ case AVMEDIA_TYPE_DATA:
+ break;
+ }
+
+ if (ofilter->filter && ofilter->filter->hw_device_ctx) {
+ AVHWDeviceContext* devCtx = (AVHWDeviceContext*)ofilter->filter->hw_device_ctx->data;
+ print_hwdevicecontext(w, devCtx);
+ }
+
+ avtext_print_section_footer(w); // SECTION_ID_OUTPUT
+ }
+
+ avtext_print_section_footer(w); // SECTION_ID_OUTPUTS
+
+
+ avtext_print_section_header(w, NULL, SECTION_ID_FILTERS);
+
+ if (graph) {
+ for (unsigned i = 0; i < graph->nb_filters; i++) {
+ AVFilterContext *filter = graph->filters[i];
+ avtext_print_section_header(w, NULL, SECTION_ID_FILTER);
+
+ print_filter(w, filter);
+
+ avtext_print_section_footer(w); // SECTION_ID_FILTER
+ }
+ }
+
+ avtext_print_section_footer(w); // SECTION_ID_FILTERS
+}
+
+int print_filtergraph(FilterGraph *fg, AVFilterGraph *graph)
+{
+ const AVTextFormatter *text_formatter;
+ AVTextFormatContext *tctx;
+ AVTextWriterContext *wctx;
+ char *w_name, *w_args;
+ int ret;
+ FilterGraphPriv *fgp = fgp_from_fg(fg);
+ AVBPrint *target_buf = &fgp->graph_print_buf;
+
+ init_sections();
+
+ if (target_buf->len)
+ av_bprint_finalize(target_buf, NULL);
+
+ av_bprint_init(target_buf, 0, AV_BPRINT_SIZE_UNLIMITED);
+
+ if (!print_graphs_format)
+ print_graphs_format = av_strdup("default");
+ if (!print_graphs_format)
+ return AVERROR(ENOMEM);
+
+ w_name = av_strtok(print_graphs_format, "=", &w_args);
+ if (!w_name) {
+ av_log(NULL, AV_LOG_ERROR, "No name specified for the filter graph output format\n");
+ return AVERROR(EINVAL);
+ }
+
+ text_formatter = avtext_get_formatter_by_name(w_name);
+ if (text_formatter == NULL) {
+ av_log(NULL, AV_LOG_ERROR, "Unknown filter graph output format with name '%s'\n", w_name);
+ return AVERROR(EINVAL);
+ }
+
+ ret = avtextwriter_create_buffer(&wctx, target_buf);
+ if (ret < 0) {
+ av_log(NULL, AV_LOG_ERROR, "avtextwriter_create_buffer failed. Error code %d\n", ret);
+ return AVERROR(EINVAL);
+ }
+
+ if ((ret = avtext_context_open(&tctx, text_formatter, wctx, w_args, sections, FF_ARRAY_ELEMS(sections), 0, 0, 0, 0, -1, NULL)) >= 0) {
+ avtext_print_section_header(tctx, NULL, SECTION_ID_ROOT);
+ avtext_print_section_header(tctx, NULL, SECTION_ID_FILTERGRAPHS);
+ avtext_print_section_header(tctx, NULL, SECTION_ID_FILTERGRAPH);
+
+ av_bprint_clear(target_buf);
+
+ print_filtergraph_single(tctx, fg, graph);
+
+ avtext_context_close(&tctx);
+ avtextwriter_context_close(&wctx);
+ } else
+ return ret;
+
+ return 0;
+}
+
+int print_filtergraphs(FilterGraph **graphs, int nb_graphs, OutputFile **ofiles, int nb_ofiles)
+{
+ const AVTextFormatter *text_formatter;
+ AVTextFormatContext *tctx;
+ AVTextWriterContext *wctx;
+ AVBPrint target_buf;
+ char *buf, *w_name, *w_args;
+ int ret;
+
+ init_sections();
+
+ if (!print_graphs_format)
+ print_graphs_format = av_strdup("default");
+ if (!print_graphs_format) {
+ return AVERROR(ENOMEM);
+ }
+
+ w_name = av_strtok(print_graphs_format, "=", &buf);
+ if (!w_name) {
+ av_log(NULL, AV_LOG_ERROR, "No name specified for the filter graph output format\n");
+ return AVERROR(EINVAL);
+ }
+ w_args = buf;
+
+ text_formatter = avtext_get_formatter_by_name(w_name);
+ if (text_formatter == NULL) {
+ av_log(NULL, AV_LOG_ERROR, "Unknown filter graph output format with name '%s'\n", w_name);
+ return AVERROR(EINVAL);
+ }
+
+ av_bprint_init(&target_buf, 0, AV_BPRINT_SIZE_UNLIMITED);
+
+ ret = avtextwriter_create_buffer(&wctx, &target_buf);
+ if (ret < 0) {
+ av_log(NULL, AV_LOG_ERROR, "avtextwriter_create_buffer failed. Error code %d\n", ret);
+ return AVERROR(EINVAL);
+ }
+
+ if ((ret = avtext_context_open(&tctx, text_formatter, wctx, w_args, sections, FF_ARRAY_ELEMS(sections), 0, 0, 0, 0, -1, NULL)) >= 0) {
+ avtext_print_section_header(tctx, NULL, SECTION_ID_ROOT);
+
+ avtext_print_section_header(tctx, NULL, SECTION_ID_FILTERGRAPHS);
+
+ for (int i = 0; i < nb_graphs; i++) {
+
+ FilterGraphPriv *fgp = fgp_from_fg(graphs[i]);
+ AVBPrint *graph_buf = &fgp->graph_print_buf;
+
+ if (graph_buf->len > 0) {
+ avtext_print_section_header(tctx, NULL, SECTION_ID_FILTERGRAPH);
+
+ av_bprint_append_data(&target_buf, graph_buf->str, graph_buf->len);
+ av_bprint_finalize(graph_buf, NULL);
+
+ avtext_print_section_footer(tctx); // SECTION_ID_FILTERGRAPH
+ }
+ }
+
+ for (int n = 0; n < nb_ofiles; n++) {
+ OutputFile *of = ofiles[n];
+
+ for (int i = 0; i < of->nb_streams; i++) {
+ OutputStream *ost = of->streams[i];
+
+ if (ost->fg_simple) {
+ FilterGraphPriv *fgp = fgp_from_fg(ost->fg_simple);
+ AVBPrint *graph_buf = &fgp->graph_print_buf;
+
+ if (graph_buf->len > 0) {
+ avtext_print_section_header(tctx, NULL, SECTION_ID_FILTERGRAPH);
+
+ av_bprint_append_data(&target_buf, graph_buf->str, graph_buf->len);
+ av_bprint_finalize(graph_buf, NULL);
+
+ avtext_print_section_footer(tctx); // SECTION_ID_FILTERGRAPH
+ }
+ }
+ }
+ }
+
+ avtext_print_section_footer(tctx); // SECTION_ID_FILTERGRAPHS
+ avtext_print_section_footer(tctx); // SECTION_ID_ROOT
+
+ if (print_graphs_file) {
+ AVIOContext *avio = NULL;
+
+ ret = avio_open2(&avio, print_graphs_file, AVIO_FLAG_WRITE, NULL, NULL);
+ if (ret < 0) {
+ av_log(NULL, AV_LOG_ERROR, "Failed to open graph output file, \"%s\": %s\n",
+ print_graphs_file, av_err2str(ret));
+ return ret;
+ }
+
+ avio_write(avio, (const unsigned char*)target_buf.str, FFMIN(target_buf.len, target_buf.size - 1));
+ avio_flush(avio);
+
+ if ((ret = avio_closep(&avio)) < 0)
+ av_log(NULL, AV_LOG_ERROR, "Error closing graph output file, loss of information possible: %s\n", av_err2str(ret));
+ }
+
+ if (print_graphs) {
+ printf("%s", target_buf.str);
+ av_log(NULL, AV_LOG_INFO, "%s %c", target_buf.str, '\n');
+ }
+
+ avtext_context_close(&tctx);
+ avtextwriter_context_close(&wctx);
+ }
+
+ return 0;
+}
diff --git a/fftools/ffmpeg_graphprint.h b/fftools/ffmpeg_graphprint.h
new file mode 100644
index 0000000000..e95a0773ba
--- /dev/null
+++ b/fftools/ffmpeg_graphprint.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2018 - softworkz
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef FFTOOLS_FFMPEG_GRAPHPRINT_H
+#define FFTOOLS_FFMPEG_GRAPHPRINT_H
+
+#include <stdint.h>
+
+#include "config.h"
+#include "ffmpeg.h"
+#include "libavutil/avutil.h"
+#include "libavutil/bprint.h"
+#include "textformat/avtextformat.h"
+
+int print_filtergraphs(FilterGraph **graphs, int nb_graphs, OutputFile **output_files, int nb_output_files);
+int print_filtergraph(FilterGraph *fg, AVFilterGraph *graph);
+
+#endif /* FFTOOLS_FFMPEG_GRAPHPRINT_H */
diff --git a/fftools/ffmpeg_opt.c b/fftools/ffmpeg_opt.c
index 27a9fc9e42..f63d253f53 100644
--- a/fftools/ffmpeg_opt.c
+++ b/fftools/ffmpeg_opt.c
@@ -75,6 +75,9 @@ float max_error_rate = 2.0/3;
char *filter_nbthreads;
int filter_complex_nbthreads = 0;
int vstats_version = 2;
+int print_graphs = 0;
+char* print_graphs_file = NULL;
+char* print_graphs_format = NULL;
int auto_conversion_filters = 1;
int64_t stats_period = 500000;
@@ -1733,6 +1736,15 @@ const OptionDef options[] = {
{ .func_arg = opt_filter_complex_script },
"deprecated, use -/filter_complex instead", "filename" },
#endif
+ { "print_graphs", OPT_TYPE_BOOL, 0,
+ { &print_graphs },
+ "prints filtergraph details to stderr" },
+ { "print_graphs_file", OPT_TYPE_STRING, 0,
+ { &print_graphs_file },
+ "writes graph details to a file", "filename" },
+ { "print_graphs_format", OPT_TYPE_STRING, 0,
+ { &print_graphs_format },
+ "set the output printing format (available formats are: default, compact, csv, flat, ini, json, xml)", "format" },
{ "auto_conversion_filters", OPT_TYPE_BOOL, OPT_EXPERT,
{ &auto_conversion_filters },
"enable automatic conversion filters globally" },
--
ffmpeg-codebot
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 108+ messages in thread
* Re: [FFmpeg-devel] [PATCH v6 6/8] fftools/ffmpeg_graphprint: Add options for filtergraph printing
2025-03-08 20:16 ` [FFmpeg-devel] [PATCH v6 6/8] fftools/ffmpeg_graphprint: Add options for filtergraph printing softworkz
@ 2025-03-10 23:03 ` Stefano Sabatini
2025-03-12 4:01 ` Soft Works
0 siblings, 1 reply; 108+ messages in thread
From: Stefano Sabatini @ 2025-03-10 23:03 UTC (permalink / raw)
To: FFmpeg development discussions and patches; +Cc: softworkz
On date Saturday 2025-03-08 20:16:32 +0000, softworkz wrote:
> From: softworkz <softworkz@hotmail.com>
>
> The key benefits are:
>
> - Different to other graph printing methods, this is outputting:
> - all graphs with runtime state
> (including auto-inserted filters)
> - each graph with its inputs and outputs
> - all filters with their in- and output pads
> - all connections between all input- and output pads
> - for each connection:
> - the runtime-negotiated format and media type
> - the hw context
> - if video hw context, both: hw pixfmt + sw pixfmt
> - Output can either be printed to stdout or written to specified file
> - Output is machine-readable
> - Use the same output implementation as ffprobe, supporting multiple
> formats
>
> Signed-off-by: softworkz <softworkz@hotmail.com>
> ---
> fftools/Makefile | 11 +
> fftools/ffmpeg.h | 3 +
> fftools/ffmpeg_graphprint.c | 518 ++++++++++++++++++++++++++++++++++++
> fftools/ffmpeg_graphprint.h | 35 +++
> fftools/ffmpeg_opt.c | 12 +
> 5 files changed, 579 insertions(+)
> create mode 100644 fftools/ffmpeg_graphprint.c
> create mode 100644 fftools/ffmpeg_graphprint.h
>
> diff --git a/fftools/Makefile b/fftools/Makefile
> index 664b73b161..03cdbd4b6e 100644
> --- a/fftools/Makefile
> +++ b/fftools/Makefile
> @@ -19,8 +19,19 @@ OBJS-ffmpeg += \
> fftools/ffmpeg_mux_init.o \
> fftools/ffmpeg_opt.o \
> fftools/ffmpeg_sched.o \
> + fftools/ffmpeg_graphprint.o \
> fftools/sync_queue.o \
> fftools/thread_queue.o \
> + fftools/textformat/avtextformat.o \
> + fftools/textformat/tf_compact.o \
> + fftools/textformat/tf_default.o \
> + fftools/textformat/tf_flat.o \
> + fftools/textformat/tf_ini.o \
> + fftools/textformat/tf_json.o \
> + fftools/textformat/tf_xml.o \
> + fftools/textformat/tw_avio.o \
> + fftools/textformat/tw_buffer.o \
> + fftools/textformat/tw_stdout.o \
>
> OBJS-ffprobe += \
> fftools/textformat/avtextformat.o \
> diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h
> index 86a3e10c6b..9880236162 100644
> --- a/fftools/ffmpeg.h
> +++ b/fftools/ffmpeg.h
> @@ -715,6 +715,9 @@ extern float max_error_rate;
> extern char *filter_nbthreads;
> extern int filter_complex_nbthreads;
> extern int vstats_version;
> +extern int print_graphs;
> +extern char* print_graphs_file;
> +extern char* print_graphs_format;
style: char *VAR here and below (also make sure to run patcheck in
case it spots other style issues)
> extern int auto_conversion_filters;
>
> extern const AVIOInterruptCB int_cb;
> diff --git a/fftools/ffmpeg_graphprint.c b/fftools/ffmpeg_graphprint.c
> new file mode 100644
> index 0000000000..dd6862679e
> --- /dev/null
> +++ b/fftools/ffmpeg_graphprint.c
> @@ -0,0 +1,518 @@
> +/*
> + * Copyright (c) 2018 - softworkz
2018?
> + *
> + * This file is part of FFmpeg.
> + *
> + * FFmpeg is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU Lesser General Public
> + * License as published by the Free Software Foundation; either
> + * version 2.1 of the License, or (at your option) any later version.
> + *
> + * FFmpeg is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
> + * Lesser General Public License for more details.
> + *
> + * You should have received a copy of the GNU Lesser General Public
> + * License along with FFmpeg; if not, write to the Free Software
> + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
> + */
> +
> +/**
> + * @file
> + * output writers for filtergraph details
> + */
> +
> +#include "config.h"
> +
> +#include <string.h>
> +
> +#include "ffmpeg_graphprint.h"
> +#include "ffmpeg_filter.h"
> +
> +#include "libavutil/avassert.h"
> +#include "libavutil/avstring.h"
> +#include "libavutil/pixdesc.h"
> +#include "libavutil/dict.h"
> +#include "libavutil/common.h"
> +#include "libavfilter/avfilter.h"
> +#include "libavutil/buffer.h"
> +#include "libavutil/hwcontext.h"
> +#include "textformat/avtextformat.h"
> +
> +typedef enum {
> + SECTION_ID_ROOT,
> + SECTION_ID_PROGRAM_VERSION,
> + SECTION_ID_FILTERGRAPHS,
> + SECTION_ID_FILTERGRAPH,
> + SECTION_ID_INPUTS,
> + SECTION_ID_INPUT,
> + SECTION_ID_OUTPUTS,
> + SECTION_ID_OUTPUT,
> + SECTION_ID_FILTERS,
> + SECTION_ID_FILTER,
> + SECTION_ID_HWDEViCECONTEXT,
> + SECTION_ID_HWFRAMESCONTEXT,
> + SECTION_ID_ERROR,
> + SECTION_ID_LOG,
> + SECTION_ID_LOGS,
> +} SectionID;
> +
> +static struct AVTextFormatSection sections[] = {
> + [SECTION_ID_ROOT] = { SECTION_ID_ROOT, "GraphDescription", AV_TEXTFORMAT_SECTION_FLAG_IS_WRAPPER,
> + { SECTION_ID_ERROR, SECTION_ID_PROGRAM_VERSION, SECTION_ID_FILTERGRAPHS, SECTION_ID_LOGS, -1} },
more readable if you move indent this to the right to explain it is
not on the same level
> + [SECTION_ID_PROGRAM_VERSION] = { SECTION_ID_PROGRAM_VERSION, "ProgramVersion", 0, { -1 } },
> +
> + [SECTION_ID_FILTERGRAPHS] = { SECTION_ID_FILTERGRAPHS, "Graphs", AV_TEXTFORMAT_SECTION_FLAG_IS_ARRAY, { SECTION_ID_FILTERGRAPH, -1 } },
> + [SECTION_ID_FILTERGRAPH] = { SECTION_ID_FILTERGRAPH, "Graph", 0, { SECTION_ID_INPUTS, SECTION_ID_OUTPUTS, SECTION_ID_FILTERS, -1 }, },
> +
> + [SECTION_ID_INPUTS] = { SECTION_ID_INPUTS, "Inputs", AV_TEXTFORMAT_SECTION_FLAG_IS_ARRAY, { SECTION_ID_INPUT, SECTION_ID_ERROR, -1 } },
> + [SECTION_ID_INPUT] = { SECTION_ID_INPUT, "Input", 0, { SECTION_ID_HWFRAMESCONTEXT, SECTION_ID_ERROR, -1 }, },
> +
> + [SECTION_ID_OUTPUTS] = { SECTION_ID_OUTPUTS, "Outputs", AV_TEXTFORMAT_SECTION_FLAG_IS_ARRAY, { SECTION_ID_OUTPUT, SECTION_ID_ERROR, -1 } },
> + [SECTION_ID_OUTPUT] = { SECTION_ID_OUTPUT, "Output", 0, { SECTION_ID_HWFRAMESCONTEXT, SECTION_ID_ERROR, -1 }, },
> +
> + [SECTION_ID_FILTERS] = { SECTION_ID_FILTERS, "Filters", AV_TEXTFORMAT_SECTION_FLAG_IS_ARRAY, { SECTION_ID_FILTER, SECTION_ID_ERROR, -1 } },
> + [SECTION_ID_FILTER] = { SECTION_ID_FILTER, "Filter", 0, { SECTION_ID_HWDEViCECONTEXT, SECTION_ID_ERROR, -1 }, },
> +
> + [SECTION_ID_HWDEViCECONTEXT] = { SECTION_ID_HWDEViCECONTEXT, "HwDeviceContext", 0, { SECTION_ID_ERROR, -1 }, },
MIXEDSTyLE is expected?
> + [SECTION_ID_HWFRAMESCONTEXT] = { SECTION_ID_HWFRAMESCONTEXT, "HwFramesContext", 0, { SECTION_ID_ERROR, -1 }, },
> +
> + [SECTION_ID_ERROR] = { SECTION_ID_ERROR, "Error", 0, { -1 } },
> + [SECTION_ID_LOGS] = { SECTION_ID_LOGS, "Log", AV_TEXTFORMAT_SECTION_FLAG_IS_ARRAY, { SECTION_ID_LOG, -1 } },
> + [SECTION_ID_LOG] = { SECTION_ID_LOG, "LogEntry", 0, { -1 }, },
Why not Logs/Log? It's OK but I'd keep ID and names in synch to
simplify reading/editing.
> +};
> +
> +/* Text Format API Shortcuts */
> +#define print_int(k, v) avtext_print_integer(w, k, v)
> +#define print_q(k, v, s) avtext_print_rational(w, k, v, s)
> +#define print_str(k, v) avtext_print_string(w, k, v, 0)
> +
> +static void print_hwdevicecontext(AVTextFormatContext *w, const AVHWDeviceContext *hw_device_context)
> +{
> + avtext_print_section_header(w, NULL, SECTION_ID_HWDEViCECONTEXT);
> +
> + print_int("HasHwDeviceContext", 1);
Is this even needed? If missing I'd expect type to be none. Or not?
> + print_str("DeviceType", av_hwdevice_get_type_name(hw_device_context->type));
> +
> + avtext_print_section_footer(w); // SECTION_ID_HWDEViCECONTEXT
> +}
> +
> +static void print_hwframescontext(AVTextFormatContext *w, const AVHWFramesContext *hw_frames_context)
> +{
> + const AVPixFmtDescriptor* pixdescHw;
> + const AVPixFmtDescriptor* pixdescSw;
let's not mix snakes and camels
> +
> + avtext_print_section_header(w, NULL, SECTION_ID_HWFRAMESCONTEXT);
> +
> + print_int("HasHwFramesContext", 1);
again, probably not needed since in this case you can deduct the info
from a missing hw/sw pixdesc?
> + pixdescHw = av_pix_fmt_desc_get(hw_frames_context->format);
> + if (pixdescHw) {
> + print_str("HwPixelFormat", pixdescHw->name);
> + print_str("HwPixelFormatAlias", pixdescHw->alias);
> + }
> +
> + pixdescSw = av_pix_fmt_desc_get(hw_frames_context->sw_format);
> + if (pixdescSw) {
> + print_str("SwPixelFormat", pixdescSw->name);
> + print_str("SwPixelFormatAlias", pixdescSw->alias);
> + }
> +
> + print_int("Width", hw_frames_context->width);
> + print_int("Height", hw_frames_context->height);
is this meaningful in case of no context? Or should we rather skip them?
> +
> + print_hwdevicecontext(w, hw_frames_context->device_ctx);
> +
> + avtext_print_section_footer(w); // SECTION_ID_HWFRAMESCONTEXT
> +}
> +
> +static void print_link(AVTextFormatContext *w, AVFilterLink *link)
> +{
> + AVBufferRef *hw_frames_ctx;
> + char layoutString[64];
> +
> + switch (link->type) {
> + case AVMEDIA_TYPE_VIDEO:
> + print_str("Format", av_x_if_null(av_get_pix_fmt_name(link->format), "?"));
> + print_int("Width", link->w);
> + print_int("Height", link->h);
> + print_q("SAR", link->sample_aspect_ratio, ':');
> + print_q("TimeBase", link->time_base, '/');
> + break;
> +
> + ////case AVMEDIA_TYPE_SUBTITLE:
> + //// print_str("Format", av_x_if_null(av_get_subtitle_fmt_name(link->format), "?"));
> + //// print_int("Width", link->w);
> + //// print_int("Height", link->h);
> + //// print_q("TimeBase", link->time_base, '/');
> + //// break;
I guess this does not exist yet right?
> +
> + case AVMEDIA_TYPE_AUDIO:
> + av_channel_layout_describe(&link->ch_layout, layoutString, sizeof(layoutString));
> + print_str("ChannelString", layoutString);
> + print_int("Channels", link->ch_layout.nb_channels);
> + ////print_int("ChannelLayout", link->ch_layout);
development leftover?
> + print_int("SampleRate", link->sample_rate);
> + break;
> + }
> +
> + hw_frames_ctx = avfilter_link_get_hw_frames_ctx(link);
> +
> + if (hw_frames_ctx && hw_frames_ctx->buffer) {
> + print_hwframescontext(w, (AVHWFramesContext *)hw_frames_ctx->data);
weird reindent
> + }
> +}
> +
> +static void print_filter(AVTextFormatContext *w, const AVFilterContext* filter)
> +{
> + avtext_print_section_header(w, NULL, SECTION_ID_FILTER);
> +
> + print_str("Name", filter->name);
> +
> + if (filter->filter) {
> + print_str("Name2", filter->filter->name);
something more descriptive such as "class name"?
> + print_str("Description", filter->filter->description);
> + }
> +
> + if (filter->hw_device_ctx) {
> + AVHWDeviceContext* decCtx = (AVHWDeviceContext*)filter->hw_device_ctx->data;
again, use snake_case for overall consistency
> + print_hwdevicecontext(w, decCtx);
> + }
> +
> + avtext_print_section_header(w, NULL, SECTION_ID_INPUTS);
> +
> + for (unsigned i = 0; i < filter->nb_inputs; i++) {
> + AVFilterLink *link = filter->inputs[i];
> + avtext_print_section_header(w, NULL, SECTION_ID_INPUT);
> +
> + print_str("SourceName", link->src->name);
> + print_str("SourcePadName", avfilter_pad_get_name(link->srcpad, 0));
> + print_str("DestPadName", avfilter_pad_get_name(link->dstpad, 0));
> +
> + print_link(w, link);
> +
> + avtext_print_section_footer(w); // SECTION_ID_INPUT
> + }
> +
> + avtext_print_section_footer(w); // SECTION_ID_INPUTS
> +
> + avtext_print_section_header(w, NULL, SECTION_ID_OUTPUTS);
> +
> + for (unsigned i = 0; i < filter->nb_outputs; i++) {
> + AVFilterLink *link = filter->outputs[i];
> + avtext_print_section_header(w, NULL, SECTION_ID_OUTPUT);
> +
> + print_str("DestName", link->dst->name);
> + print_str("DestPadName", avfilter_pad_get_name(link->dstpad, 0));
> + print_str("SourceName", link->src->name);
possibly unrelated, but I'm a bit surprised by the asymmetry
> +
> + print_link(w, link);
> +
> + avtext_print_section_footer(w); // SECTION_ID_OUTPUT
> + }
> +
> + avtext_print_section_footer(w); // SECTION_ID_OUTPUTS
> +
> + avtext_print_section_footer(w); // SECTION_ID_FILTER
> +}
> +
> +static void init_sections(void)
> +{
> + for (unsigned i = 0; i < FF_ARRAY_ELEMS(sections); i++)
> + sections[i].show_all_entries = 1;
> +}
> +
> +static void print_filtergraph_single(AVTextFormatContext *w, FilterGraph* fg, AVFilterGraph *graph)
mixed type*var styles
> +{
> + char layoutString[64];
snake_case, here and below
> + FilterGraphPriv *fgp = fgp_from_fg(fg);
> +
> + print_int("GraphIndex", fg->index);
> + print_str("Description", fgp->graph_desc);
> +
> + avtext_print_section_header(w, NULL, SECTION_ID_INPUTS);
> +
> + for (int i = 0; i < fg->nb_inputs; i++) {
> + InputFilterPriv* ifilter = ifp_from_ifilter(fg->inputs[i]);
> + enum AVMediaType mediaType = ifilter->type;
> +
> + avtext_print_section_header(w, NULL, SECTION_ID_INPUT);
> +
> + print_str("Name1", (char*)ifilter->ifilter.name);
> +
> + if (ifilter->filter) {
> + print_str("Name2", ifilter->filter->name);
> + print_str("Name3", ifilter->filter->filter->name);
ditto, although I'm a bit lost about what the thricely nested bird is
> + print_str("Description", ifilter->filter->filter->description);
> + }
> +
> + print_str("MediaType", av_get_media_type_string(mediaType));
> + print_int("MediaTypeId", mediaType);
> +
> + switch (ifilter->type) {
> + case AVMEDIA_TYPE_VIDEO:
> + case AVMEDIA_TYPE_SUBTITLE:
> + print_str("Format", av_x_if_null(av_get_pix_fmt_name(ifilter->format), "?"));
nit++: drop double space
> + print_int("Width", ifilter->width);
> + print_int("Height", ifilter->height);
> + print_q("SAR", ifilter->sample_aspect_ratio, ':');
> + break;
> + case AVMEDIA_TYPE_AUDIO:
> +
weird empty line
> + av_channel_layout_describe(&ifilter->ch_layout, layoutString, sizeof(layoutString));
> + print_str("ChannelString", layoutString);
> + print_int("SampleRate", ifilter->sample_rate);
> + break;
> + case AVMEDIA_TYPE_ATTACHMENT:
> + case AVMEDIA_TYPE_DATA:
> + break;
> + }
> +
> + if (ifilter->hw_frames_ctx)
> + print_hwframescontext(w, (AVHWFramesContext*)ifilter->hw_frames_ctx->data);
> + else if (ifilter->filter && ifilter->filter->hw_device_ctx) {
> + AVHWDeviceContext* devCtx = (AVHWDeviceContext*)ifilter->filter->hw_device_ctx->data;
> + print_hwdevicecontext(w, devCtx);
> + }
nit+: style if () { ... } else if () {...} should be slightly more
readable
> +
> + avtext_print_section_footer(w); // SECTION_ID_INPUT
> + }
> +
> + avtext_print_section_footer(w); // SECTION_ID_INPUTS
> +
> +
drop double emtpy line
> + avtext_print_section_header(w, NULL, SECTION_ID_OUTPUTS);
> +
> + for (int i = 0; i < fg->nb_outputs; i++) {
> + OutputFilterPriv *ofilter = ofp_from_ofilter(fg->outputs[i]);
> + enum AVMediaType mediaType = AVMEDIA_TYPE_UNKNOWN;
> +
> + avtext_print_section_header(w, NULL, SECTION_ID_OUTPUT);
> + print_str("Name1", ofilter->name);
> +
> + if (ofilter->filter) {
> + print_str("Name2", ofilter->filter->name);
> + print_str("Name3", ofilter->filter->filter->name);
ditto, having more descriptive names would help user big times
> + print_str("Description", ofilter->filter->filter->description);
> +
> + if (ofilter->filter->nb_inputs > 0)
> + mediaType = ofilter->filter->inputs[0]->type;
> + }
> +
> + print_str("MediaType", av_get_media_type_string(mediaType));
> + print_int("MediaTypeId", mediaType);
yes but... this might be broken if you make assumption based on the
value (might change when bumping major) so should be probably drop
> +
> + switch (ofilter->ofilter.type) {
> + case AVMEDIA_TYPE_VIDEO:
> + case AVMEDIA_TYPE_SUBTITLE:
> + print_str("Format", av_x_if_null(av_get_pix_fmt_name(ofilter->format), "?"));
double space
also you can probably use a function/macro to factorized duplicated pattern
> + print_int("Width", ofilter->width);
> + print_int("Height", ofilter->height);
> + break;
> + case AVMEDIA_TYPE_AUDIO:
> +
> + av_channel_layout_describe(&ofilter->ch_layout, layoutString, sizeof(layoutString));
> + print_str("ChannelString", layoutString);
ChannelLayout? We don't print other representations anyway so there is
no ambiguity here
> + print_int("SampleRate", ofilter->sample_rate);
> + break;
> + case AVMEDIA_TYPE_ATTACHMENT:
> + case AVMEDIA_TYPE_DATA:
> + break;
> + }
> +
> + if (ofilter->filter && ofilter->filter->hw_device_ctx) {
> + AVHWDeviceContext* devCtx = (AVHWDeviceContext*)ofilter->filter->hw_device_ctx->data;
style
> + print_hwdevicecontext(w, devCtx);
> + }
> +
> + avtext_print_section_footer(w); // SECTION_ID_OUTPUT
> + }
> +
> + avtext_print_section_footer(w); // SECTION_ID_OUTPUTS
> +
> +
> + avtext_print_section_header(w, NULL, SECTION_ID_FILTERS);
> +
> + if (graph) {
> + for (unsigned i = 0; i < graph->nb_filters; i++) {
> + AVFilterContext *filter = graph->filters[i];
> + avtext_print_section_header(w, NULL, SECTION_ID_FILTER);
> +
> + print_filter(w, filter);
> +
> + avtext_print_section_footer(w); // SECTION_ID_FILTER
> + }
> + }
> +
> + avtext_print_section_footer(w); // SECTION_ID_FILTERS
> +}
> +
> +int print_filtergraph(FilterGraph *fg, AVFilterGraph *graph)
> +{
> + const AVTextFormatter *text_formatter;
> + AVTextFormatContext *tctx;
> + AVTextWriterContext *wctx;
> + char *w_name, *w_args;
> + int ret;
> + FilterGraphPriv *fgp = fgp_from_fg(fg);
> + AVBPrint *target_buf = &fgp->graph_print_buf;
> +
> + init_sections();
> +
> + if (target_buf->len)
> + av_bprint_finalize(target_buf, NULL);
> +
> + av_bprint_init(target_buf, 0, AV_BPRINT_SIZE_UNLIMITED);
> +
> + if (!print_graphs_format)
> + print_graphs_format = av_strdup("default");
> + if (!print_graphs_format)
> + return AVERROR(ENOMEM);
> +
> + w_name = av_strtok(print_graphs_format, "=", &w_args);
> + if (!w_name) {
> + av_log(NULL, AV_LOG_ERROR, "No name specified for the filter graph output format\n");
> + return AVERROR(EINVAL);
> + }
> +
> + text_formatter = avtext_get_formatter_by_name(w_name);
> + if (text_formatter == NULL) {
if (!text_formatter)
?
for consistencty with the line above
> + av_log(NULL, AV_LOG_ERROR, "Unknown filter graph output format with name '%s'\n", w_name);
double space
> + return AVERROR(EINVAL);
> + }
> +
> + ret = avtextwriter_create_buffer(&wctx, target_buf);
> + if (ret < 0) {
> + av_log(NULL, AV_LOG_ERROR, "avtextwriter_create_buffer failed. Error code %d\n", ret);
Is this function already logging? If not it probably should, if yes
this is log is probably redundant.
> + return AVERROR(EINVAL);
why not propagating the error?
> + }
> +
> + if ((ret = avtext_context_open(&tctx, text_formatter, wctx, w_args, sections, FF_ARRAY_ELEMS(sections), 0, 0, 0, 0, -1, NULL)) >= 0) {
> + avtext_print_section_header(tctx, NULL, SECTION_ID_ROOT);
> + avtext_print_section_header(tctx, NULL, SECTION_ID_FILTERGRAPHS);
> + avtext_print_section_header(tctx, NULL, SECTION_ID_FILTERGRAPH);
> +
> + av_bprint_clear(target_buf);
If I understand this is printing the sections and then discarding the
generated buffer, right? Maybe add a not to explain why this is done
(I don't know...).
> +
> + print_filtergraph_single(tctx, fg, graph);
> +
> + avtext_context_close(&tctx);
> + avtextwriter_context_close(&wctx);
> + } else
> + return ret;
> +
> + return 0;
> +}
> +
> +int print_filtergraphs(FilterGraph **graphs, int nb_graphs, OutputFile **ofiles, int nb_ofiles)
> +{
> + const AVTextFormatter *text_formatter;
> + AVTextFormatContext *tctx;
> + AVTextWriterContext *wctx;
> + AVBPrint target_buf;
> + char *buf, *w_name, *w_args;
> + int ret;
> +
> + init_sections();
> +
> + if (!print_graphs_format)
> + print_graphs_format = av_strdup("default");
> + if (!print_graphs_format) {
> + return AVERROR(ENOMEM);
> + }
> +
> + w_name = av_strtok(print_graphs_format, "=", &buf);
> + if (!w_name) {
> + av_log(NULL, AV_LOG_ERROR, "No name specified for the filter graph output format\n");
> + return AVERROR(EINVAL);
> + }
> + w_args = buf;
> +
> + text_formatter = avtext_get_formatter_by_name(w_name);
> + if (text_formatter == NULL) {
> + av_log(NULL, AV_LOG_ERROR, "Unknown filter graph output format with name '%s'\n", w_name);
double space
> + return AVERROR(EINVAL);
> + }
> +
> + av_bprint_init(&target_buf, 0, AV_BPRINT_SIZE_UNLIMITED);
> +
> + ret = avtextwriter_create_buffer(&wctx, &target_buf);
> + if (ret < 0) {
> + av_log(NULL, AV_LOG_ERROR, "avtextwriter_create_buffer failed. Error code %d\n", ret);
ditto
> + return AVERROR(EINVAL);
> + }
> +
> + if ((ret = avtext_context_open(&tctx, text_formatter, wctx, w_args, sections, FF_ARRAY_ELEMS(sections), 0, 0, 0, 0, -1, NULL)) >= 0) {
> + avtext_print_section_header(tctx, NULL, SECTION_ID_ROOT);
> +
> + avtext_print_section_header(tctx, NULL, SECTION_ID_FILTERGRAPHS);
> +
> + for (int i = 0; i < nb_graphs; i++) {
> +
> + FilterGraphPriv *fgp = fgp_from_fg(graphs[i]);
> + AVBPrint *graph_buf = &fgp->graph_print_buf;
> +
> + if (graph_buf->len > 0) {
> + avtext_print_section_header(tctx, NULL, SECTION_ID_FILTERGRAPH);
> +
> + av_bprint_append_data(&target_buf, graph_buf->str, graph_buf->len);
> + av_bprint_finalize(graph_buf, NULL);
> +
> + avtext_print_section_footer(tctx); // SECTION_ID_FILTERGRAPH
> + }
> + }
> +
> + for (int n = 0; n < nb_ofiles; n++) {
> + OutputFile *of = ofiles[n];
> +
> + for (int i = 0; i < of->nb_streams; i++) {
> + OutputStream *ost = of->streams[i];
> +
> + if (ost->fg_simple) {
> + FilterGraphPriv *fgp = fgp_from_fg(ost->fg_simple);
> + AVBPrint *graph_buf = &fgp->graph_print_buf;
> +
> + if (graph_buf->len > 0) {
> + avtext_print_section_header(tctx, NULL, SECTION_ID_FILTERGRAPH);
> +
> + av_bprint_append_data(&target_buf, graph_buf->str, graph_buf->len);
> + av_bprint_finalize(graph_buf, NULL);
> +
> + avtext_print_section_footer(tctx); // SECTION_ID_FILTERGRAPH
> + }
> + }
> + }
> + }
> +
> + avtext_print_section_footer(tctx); // SECTION_ID_FILTERGRAPHS
> + avtext_print_section_footer(tctx); // SECTION_ID_ROOT
> +
> + if (print_graphs_file) {
> + AVIOContext *avio = NULL;
> +
> + ret = avio_open2(&avio, print_graphs_file, AVIO_FLAG_WRITE, NULL, NULL);
> + if (ret < 0) {
> + av_log(NULL, AV_LOG_ERROR, "Failed to open graph output file, \"%s\": %s\n",
> + print_graphs_file, av_err2str(ret));
> + return ret;
> + }
> +
> + avio_write(avio, (const unsigned char*)target_buf.str, FFMIN(target_buf.len, target_buf.size - 1));
> + avio_flush(avio);
> +
> + if ((ret = avio_closep(&avio)) < 0)
> + av_log(NULL, AV_LOG_ERROR, "Error closing graph output file, loss of information possible: %s\n", av_err2str(ret));
> + }
> +
> + if (print_graphs) {
> + printf("%s", target_buf.str);
> + av_log(NULL, AV_LOG_INFO, "%s %c", target_buf.str, '\n');
why it not hardcoding the newline in the message?
> + }
> +
> + avtext_context_close(&tctx);
> + avtextwriter_context_close(&wctx);
> + }
> +
> + return 0;
> +}
> diff --git a/fftools/ffmpeg_graphprint.h b/fftools/ffmpeg_graphprint.h
> new file mode 100644
> index 0000000000..e95a0773ba
> --- /dev/null
> +++ b/fftools/ffmpeg_graphprint.h
> @@ -0,0 +1,35 @@
> +/*
> + * Copyright (c) 2018 - softworkz
> + *
> + * This file is part of FFmpeg.
> + *
> + * FFmpeg is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU Lesser General Public
> + * License as published by the Free Software Foundation; either
> + * version 2.1 of the License, or (at your option) any later version.
> + *
> + * FFmpeg is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
> + * Lesser General Public License for more details.
> + *
> + * You should have received a copy of the GNU Lesser General Public
> + * License along with FFmpeg; if not, write to the Free Software
> + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
> + */
> +
> +#ifndef FFTOOLS_FFMPEG_GRAPHPRINT_H
> +#define FFTOOLS_FFMPEG_GRAPHPRINT_H
> +
> +#include <stdint.h>
> +
> +#include "config.h"
> +#include "ffmpeg.h"
> +#include "libavutil/avutil.h"
> +#include "libavutil/bprint.h"
> +#include "textformat/avtextformat.h"
> +
> +int print_filtergraphs(FilterGraph **graphs, int nb_graphs, OutputFile **output_files, int nb_output_files);
> +int print_filtergraph(FilterGraph *fg, AVFilterGraph *graph);
> +
> +#endif /* FFTOOLS_FFMPEG_GRAPHPRINT_H */
> diff --git a/fftools/ffmpeg_opt.c b/fftools/ffmpeg_opt.c
> index 27a9fc9e42..f63d253f53 100644
> --- a/fftools/ffmpeg_opt.c
> +++ b/fftools/ffmpeg_opt.c
> @@ -75,6 +75,9 @@ float max_error_rate = 2.0/3;
> char *filter_nbthreads;
> int filter_complex_nbthreads = 0;
> int vstats_version = 2;
> +int print_graphs = 0;
> +char* print_graphs_file = NULL;
> +char* print_graphs_format = NULL;
char *print_graphs_xxx = NULL;
> int auto_conversion_filters = 1;
> int64_t stats_period = 500000;
>
> @@ -1733,6 +1736,15 @@ const OptionDef options[] = {
> { .func_arg = opt_filter_complex_script },
> "deprecated, use -/filter_complex instead", "filename" },
> #endif
> + { "print_graphs", OPT_TYPE_BOOL, 0,
> + { &print_graphs },
> + "prints filtergraph details to stderr" },
prints -> print
why to stderr not stdout? that's what's generally exepected on unix*
> + { "print_graphs_file", OPT_TYPE_STRING, 0,
> + { &print_graphs_file },
> + "writes graph details to a file", "filename" },
write graph ...
> + { "print_graphs_format", OPT_TYPE_STRING, 0,
> + { &print_graphs_format },
> + "set the output printing format (available formats are: default, compact, csv, flat, ini, json, xml)", "format" },
non blocking but it would be good to avoid the hardcode in a case a
new format is added (or we'll skip update)
[...]
About the output style, this is using FooBar style against foo_bar
employed by ffprobe itself. I'm not against this, but I wonder if this
was considered and if using a more consistent style across tools is
helpful.
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 108+ messages in thread
* Re: [FFmpeg-devel] [PATCH v6 6/8] fftools/ffmpeg_graphprint: Add options for filtergraph printing
2025-03-10 23:03 ` Stefano Sabatini
@ 2025-03-12 4:01 ` Soft Works
0 siblings, 0 replies; 108+ messages in thread
From: Soft Works @ 2025-03-12 4:01 UTC (permalink / raw)
To: Stefano Sabatini, FFmpeg development discussions and patches
> -----Original Message-----
> From: Stefano Sabatini <stefasab@gmail.com>
> Sent: Dienstag, 11. März 2025 00:03
> To: FFmpeg development discussions and patches <ffmpeg-devel@ffmpeg.org>
> Cc: softworkz <softworkz@hotmail.com>
> Subject: Re: [FFmpeg-devel] [PATCH v6 6/8] fftools/ffmpeg_graphprint:
> Add options for filtergraph printing
Hi Stefano,
I've made all of your changes unless mentioned below, ran patcheck, found two or three more bits, but a lot of its output is not applicable I suppose.
Here are some notes:
> > + [SECTION_ID_HWFRAMESCONTEXT] = { SECTION_ID_HWFRAMESCONTEXT, "HwFramesContext", 0, { SECTION_ID_ERROR, -1 }, },
> > +
> > + [SECTION_ID_ERROR] = { SECTION_ID_ERROR, "Error", 0, { -1 } },
>
> > + [SECTION_ID_LOGS] = { SECTION_ID_LOGS, "Log", AV_TEXTFORMAT_SECTION_FLAG_IS_ARRAY, { SECTION_ID_LOG, -1 } },
> > + [SECTION_ID_LOG] = { SECTION_ID_LOG, "LogEntry", 0, { -1 }, },
>
> Why not Logs/Log? It's OK but I'd keep ID and names in synch to
> simplify reading/editing.
The last three ones weren't even used - removed.
> > +static void print_hwdevicecontext(AVTextFormatContext *w, const AVHWDeviceContext *hw_device_context)
> > +{
> > + avtext_print_section_header(w, NULL, SECTION_ID_HWDEViCECONTEXT);
> > +
>
> > + print_int("HasHwDeviceContext", 1);
> > + print_str("DeviceType", av_hwdevice_get_type_name(hw_device_context->type));
>
>
> Is this even needed? If missing I'd expect type to be none. Or not?
av_hwdevice_get_type_name does not return "none" but NULL for the "none" enum id.
The reasoning was slightly different, though: Typically, you deserialize JSON (or XML) into an object model. If the DeviceType is not present in the target object model (missing enum member), the cannot be deserialized which means that it gets lost - including the information that there was a device context in place. The HasHwDeviceContext (and similar members) prevents that by separating presence and type information.
But I have reduced these that now and also dropped the extra section for hw_device_context.
> > + print_str("SwPixelFormatAlias", pixdescSw->alias);
> > + }
> > +
>
> > + print_int("Width", hw_frames_context->width);
> > + print_int("Height", hw_frames_context->height);
>
> is this meaningful in case of no context? Or should we rather skip them?
What do you mean by "no context"?. The function is only entered if a hwframes context exists.
In that case it's interesting to know width and height of the frames context as it may differ from the presentation frame size.
> > + ////case AVMEDIA_TYPE_SUBTITLE:
> > + //// print_str("Format", av_x_if_null(av_get_subtitle_fmt_name(link->format), "?"));
> > + //// print_int("Width", link->w);
> > + //// print_int("Height", link->h);
> > + //// print_q("TimeBase", link->time_base, '/');
> > + //// break;
>
> I guess this does not exist yet right?
This does exist and is working, just not in ffmpeg yet (https://github.com/ffstaging/FFmpeg/pull/18)
But it's only av_get_subtitle_fmt_name(), so I left just that line commented. (I can also remove it if it should)
> > + avtext_print_section_header(w, NULL, SECTION_ID_FILTER);
> > +
> > + print_str("Name", filter->name);
> > +
> > + if (filter->filter) {
>
> > + print_str("Name2", filter->filter->name);
>
> something more descriptive such as "class name"?
I've made it more clear now. There's a filter_id and a filter_name, no more name2/3.
> > + print_str("DestName", link->dst->name);
> > + print_str("DestPadName", avfilter_pad_get_name(link->dstpad, 0));
> > + print_str("SourceName", link->src->name);
>
> possibly unrelated, but I'm a bit surprised by the asymmetry
In case you meant why there's no SourcePadName in this snippet, that's because the source is the filter under which these ouputs are shown. I have changed that now, so there's pad_index, pad_name, dest_filter_id and dest_pad_name for outputs and similar for inputs.
Generally, there's asymmetry in quite a number of cases. What might explain it somewhat is that those graphs have a fixed direction.
> > + if ((ret = avtext_context_open(&tctx, text_formatter, wctx, w_args, sections, FF_ARRAY_ELEMS(sections), 0, 0, 0, 0, -1, NULL)) >= 0) {
>
> > + avtext_print_section_header(tctx, NULL, SECTION_ID_ROOT);
> > + avtext_print_section_header(tctx, NULL, SECTION_ID_FILTERGRAPHS);
> > + avtext_print_section_header(tctx, NULL, SECTION_ID_FILTERGRAPH);
> > +
> > + av_bprint_clear(target_buf);
>
> If I understand this is printing the sections and then discarding the
> generated buffer, right? Maybe add a not to explain why this is done
Done:
// Due to the threading model each graph needs to print itself into a buffer
// from its own thread. The actual printing happens short before cleanup in ffmpeg.c
// where all grahps are assembled together. To make this work, we need to put the
// formatting context into the same state like it would be when printing all at once,
// so here we print the section headers and clear the buffer to get into the right state.
> > + if (print_graphs) {
> > + printf("%s", target_buf.str);
>
> > + av_log(NULL, AV_LOG_INFO, "%s %c", target_buf.str, '\n');
>
> why it not hardcoding the newline in the message?
I can't remember, not sure which or whether there was a good reason.
> > + { "print_graphs_format", OPT_TYPE_STRING, 0,
> > + { &print_graphs_format },
>
> > + "set the output printing format (available formats are: default, compact, csv, flat, ini, json, xml)", "format" },
>
> non blocking but it would be good to avoid the hardcode in a case a
> new format is added (or we'll skip update)
There's again the problem of static initialization order. While I'm sure that this could be worked out in some tricky way, I wonder whether that's worth the effort. When was the last time that a new text format has been added? And when some new format gets added, it will need to be "hard-coded" in the doc files and at various other places anyway.
> About the output style, this is using FooBar style against foo_bar
> employed by ffprobe itself. I'm not against this, but I wonder if this
> was considered and if using a more consistent style across tools is
> helpful.
Back then, I hadn't thought much about it. I just did what I thought is natural for JSON and XML documents.
Even though it will cause me some headaches, your point is undeniably valid, so I've reworked everything to snake case and also adjusted the naming of some elements for better clarity.
Thanks again for your reviews,
best wishes,
sw
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 108+ messages in thread
* [FFmpeg-devel] [PATCH v6 7/8] fftools: Enable filtergraph printing and update docs
2025-03-08 20:16 ` [FFmpeg-devel] [PATCH v6 0/8] print_graphs: Complete Filtergraph Printing ffmpegagent
` (5 preceding siblings ...)
2025-03-08 20:16 ` [FFmpeg-devel] [PATCH v6 6/8] fftools/ffmpeg_graphprint: Add options for filtergraph printing softworkz
@ 2025-03-08 20:16 ` softworkz
2025-03-10 23:04 ` Stefano Sabatini
2025-03-08 20:16 ` [FFmpeg-devel] [PATCH v6 8/8] fftools/ffprobe: Rename AVTextFormatContext variables (w => tfc) softworkz
` (2 subsequent siblings)
9 siblings, 1 reply; 108+ messages in thread
From: softworkz @ 2025-03-08 20:16 UTC (permalink / raw)
To: ffmpeg-devel; +Cc: softworkz
From: softworkz <softworkz@hotmail.com>
Enables filtergraph printing and adds the options to the docs
Signed-off-by: softworkz <softworkz@hotmail.com>
---
doc/ffmpeg.texi | 10 ++++++++++
fftools/ffmpeg.c | 4 ++++
fftools/ffmpeg_filter.c | 5 +++++
3 files changed, 19 insertions(+)
diff --git a/doc/ffmpeg.texi b/doc/ffmpeg.texi
index fca220a334..0f1a253183 100644
--- a/doc/ffmpeg.texi
+++ b/doc/ffmpeg.texi
@@ -1388,6 +1388,16 @@ It is on by default, to explicitly disable it you need to specify @code{-nostats
@item -stats_period @var{time} (@emph{global})
Set period at which encoding progress/statistics are updated. Default is 0.5 seconds.
+@item -print_graphs (@emph{global})
+Prints filtergraph details to stderr in the format set via -print_graphs_format.
+
+@item -print_graphs_file @var{filename} (@emph{global})
+Writes filtergraph details to the specified file in the format set via -print_graphs_format.
+
+@item -print_graphs_format @var{format} (@emph{global})
+Sets the output printing format (available formats are: default, compact, csv, flat, ini, json, xml)
+The default format is json.
+
@item -progress @var{url} (@emph{global})
Send program-friendly progress information to @var{url}.
diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c
index dc321fb4a2..b4bc76d788 100644
--- a/fftools/ffmpeg.c
+++ b/fftools/ffmpeg.c
@@ -81,6 +81,7 @@
#include "ffmpeg.h"
#include "ffmpeg_sched.h"
#include "ffmpeg_utils.h"
+#include "ffmpeg_graphprint.h"
const char program_name[] = "ffmpeg";
const int program_birth_year = 2000;
@@ -308,6 +309,9 @@ const AVIOInterruptCB int_cb = { decode_interrupt_cb, NULL };
static void ffmpeg_cleanup(int ret)
{
+ if (print_graphs || print_graphs_file)
+ print_filtergraphs(filtergraphs, nb_filtergraphs, output_files, nb_output_files);
+
if (do_benchmark) {
int64_t maxrss = getmaxrss() / 1024;
av_log(NULL, AV_LOG_INFO, "bench: maxrss=%"PRId64"KiB\n", maxrss);
diff --git a/fftools/ffmpeg_filter.c b/fftools/ffmpeg_filter.c
index 6de4e87ade..7198416ae9 100644
--- a/fftools/ffmpeg_filter.c
+++ b/fftools/ffmpeg_filter.c
@@ -22,6 +22,7 @@
#include "ffmpeg.h"
#include "ffmpeg_filter.h"
+#include "ffmpeg_graphprint.h"
#include "libavfilter/avfilter.h"
#include "libavfilter/buffersink.h"
@@ -2970,6 +2971,10 @@ read_frames:
}
finish:
+
+ if (print_graphs || print_graphs_file)
+ print_filtergraph(fg, fgt.graph);
+
// EOF is normal termination
if (ret == AVERROR_EOF)
ret = 0;
--
ffmpeg-codebot
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 108+ messages in thread
* Re: [FFmpeg-devel] [PATCH v6 7/8] fftools: Enable filtergraph printing and update docs
2025-03-08 20:16 ` [FFmpeg-devel] [PATCH v6 7/8] fftools: Enable filtergraph printing and update docs softworkz
@ 2025-03-10 23:04 ` Stefano Sabatini
2025-03-10 23:23 ` Soft Works
0 siblings, 1 reply; 108+ messages in thread
From: Stefano Sabatini @ 2025-03-10 23:04 UTC (permalink / raw)
To: FFmpeg development discussions and patches; +Cc: softworkz
On date Saturday 2025-03-08 20:16:33 +0000, softworkz wrote:
> From: softworkz <softworkz@hotmail.com>
>
> Enables filtergraph printing and adds the options to the docs
>
> Signed-off-by: softworkz <softworkz@hotmail.com>
> ---
> doc/ffmpeg.texi | 10 ++++++++++
> fftools/ffmpeg.c | 4 ++++
> fftools/ffmpeg_filter.c | 5 +++++
> 3 files changed, 19 insertions(+)
I'd merge this with the previous commit.
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 108+ messages in thread
* Re: [FFmpeg-devel] [PATCH v6 7/8] fftools: Enable filtergraph printing and update docs
2025-03-10 23:04 ` Stefano Sabatini
@ 2025-03-10 23:23 ` Soft Works
0 siblings, 0 replies; 108+ messages in thread
From: Soft Works @ 2025-03-10 23:23 UTC (permalink / raw)
To: Stefano Sabatini, FFmpeg development discussions and patches
> -----Original Message-----
> From: Stefano Sabatini <stefasab@gmail.com>
> Sent: Dienstag, 11. März 2025 00:04
> To: FFmpeg development discussions and patches <ffmpeg-devel@ffmpeg.org>
> Cc: softworkz <softworkz@hotmail.com>
> Subject: Re: [FFmpeg-devel] [PATCH v6 7/8] fftools: Enable filtergraph
> printing and update docs
>
> On date Saturday 2025-03-08 20:16:33 +0000, softworkz wrote:
> > From: softworkz <softworkz@hotmail.com>
> >
> > Enables filtergraph printing and adds the options to the docs
> >
> > Signed-off-by: softworkz <softworkz@hotmail.com>
> > ---
> > doc/ffmpeg.texi | 10 ++++++++++
> > fftools/ffmpeg.c | 4 ++++
> > fftools/ffmpeg_filter.c | 5 +++++
> > 3 files changed, 19 insertions(+)
>
> I'd merge this with the previous commit.
(ok! ^^)
Awesome, thanks a lot for your review!
Good points. I'll work through it and respond to the remainders then.
BTW, 2018 is not an error. The code has a long history. It was written then and been in production since then, first submitted publicly in 2021, blocked by the duplication of the ffprobe writers. Same again this time, but finally that's banged out of the way now 😊
sw
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 108+ messages in thread
* [FFmpeg-devel] [PATCH v6 8/8] fftools/ffprobe: Rename AVTextFormatContext variables (w => tfc)
2025-03-08 20:16 ` [FFmpeg-devel] [PATCH v6 0/8] print_graphs: Complete Filtergraph Printing ffmpegagent
` (6 preceding siblings ...)
2025-03-08 20:16 ` [FFmpeg-devel] [PATCH v6 7/8] fftools: Enable filtergraph printing and update docs softworkz
@ 2025-03-08 20:16 ` softworkz
2025-03-10 21:46 ` [FFmpeg-devel] [PATCH v6 0/8] print_graphs: Complete Filtergraph Printing Stefano Sabatini
2025-03-12 4:04 ` [FFmpeg-devel] [PATCH v7 0/7] " ffmpegagent
9 siblings, 0 replies; 108+ messages in thread
From: softworkz @ 2025-03-08 20:16 UTC (permalink / raw)
To: ffmpeg-devel; +Cc: softworkz
From: softworkz <softworkz@hotmail.com>
Signed-off-by: softworkz <softworkz@hotmail.com>
---
fftools/ffprobe.c | 512 +++++++++++++++++++++++-----------------------
1 file changed, 256 insertions(+), 256 deletions(-)
diff --git a/fftools/ffprobe.c b/fftools/ffprobe.c
index 4a90bc4824..9f869b41b3 100644
--- a/fftools/ffprobe.c
+++ b/fftools/ffprobe.c
@@ -407,7 +407,7 @@ static void log_callback(void *ptr, int level, const char *fmt, va_list vl)
#define print_fmt(k, f, ...) do { \
av_bprint_clear(&pbuf); \
av_bprintf(&pbuf, f, __VA_ARGS__); \
- avtext_print_string(w, k, pbuf.str, 0); \
+ avtext_print_string(tfc, k, pbuf.str, 0); \
} while (0)
#define print_list_fmt(k, f, n, m, ...) do { \
@@ -419,19 +419,19 @@ static void log_callback(void *ptr, int level, const char *fmt, va_list vl)
av_bprintf(&pbuf, f, __VA_ARGS__); \
} \
} \
- avtext_print_string(w, k, pbuf.str, 0); \
+ avtext_print_string(tfc, k, pbuf.str, 0); \
} while (0)
-#define print_int(k, v) avtext_print_integer(w, k, v)
-#define print_q(k, v, s) avtext_print_rational(w, k, v, s)
-#define print_str(k, v) avtext_print_string(w, k, v, 0)
-#define print_str_opt(k, v) avtext_print_string(w, k, v, AV_TEXTFORMAT_PRINT_STRING_OPTIONAL)
-#define print_str_validate(k, v) avtext_print_string(w, k, v, AV_TEXTFORMAT_PRINT_STRING_VALIDATE)
-#define print_time(k, v, tb) avtext_print_time(w, k, v, tb, 0)
-#define print_ts(k, v) avtext_print_ts(w, k, v, 0)
-#define print_duration_time(k, v, tb) avtext_print_time(w, k, v, tb, 1)
-#define print_duration_ts(k, v) avtext_print_ts(w, k, v, 1)
-#define print_val(k, v, u) avtext_print_unit_int(w, k, v, u)
+#define print_int(k, v) avtext_print_integer(tfc, k, v)
+#define print_q(k, v, s) avtext_print_rational(tfc, k, v, s)
+#define print_str(k, v) avtext_print_string(tfc, k, v, 0)
+#define print_str_opt(k, v) avtext_print_string(tfc, k, v, AV_TEXTFORMAT_PRINT_STRING_OPTIONAL)
+#define print_str_validate(k, v) avtext_print_string(tfc, k, v, AV_TEXTFORMAT_PRINT_STRING_VALIDATE)
+#define print_time(k, v, tb) avtext_print_time(tfc, k, v, tb, 0)
+#define print_ts(k, v) avtext_print_ts(tfc, k, v, 0)
+#define print_duration_time(k, v, tb) avtext_print_time(tfc, k, v, tb, 1)
+#define print_duration_ts(k, v) avtext_print_ts(tfc, k, v, 1)
+#define print_val(k, v, u) avtext_print_unit_int(tfc, k, v, u)
#define REALLOCZ_ARRAY_STREAM(ptr, cur_n, new_n) \
{ \
@@ -441,25 +441,25 @@ static void log_callback(void *ptr, int level, const char *fmt, va_list vl)
memset( (ptr) + (cur_n), 0, ((new_n) - (cur_n)) * sizeof(*(ptr)) ); \
}
-static inline int show_tags(AVTextFormatContext *w, AVDictionary *tags, int section_id)
+static inline int show_tags(AVTextFormatContext *tfc, AVDictionary *tags, int section_id)
{
const AVDictionaryEntry *tag = NULL;
int ret = 0;
if (!tags)
return 0;
- avtext_print_section_header(w, NULL, section_id);
+ avtext_print_section_header(tfc, NULL, section_id);
while ((tag = av_dict_iterate(tags, tag))) {
if ((ret = print_str_validate(tag->key, tag->value)) < 0)
break;
}
- avtext_print_section_footer(w);
+ avtext_print_section_footer(tfc);
return ret;
}
-static void print_dovi_metadata(AVTextFormatContext *w, const AVDOVIMetadata *dovi)
+static void print_dovi_metadata(AVTextFormatContext *tfc, const AVDOVIMetadata *dovi)
{
if (!dovi)
return;
@@ -514,15 +514,15 @@ static void print_dovi_metadata(AVTextFormatContext *w, const AVDOVIMetadata *do
print_int("num_x_partitions", mapping->num_x_partitions);
print_int("num_y_partitions", mapping->num_y_partitions);
- avtext_print_section_header(w, NULL, SECTION_ID_FRAME_SIDE_DATA_COMPONENT_LIST);
+ avtext_print_section_header(tfc, NULL, SECTION_ID_FRAME_SIDE_DATA_COMPONENT_LIST);
for (int c = 0; c < 3; c++) {
const AVDOVIReshapingCurve *curve = &mapping->curves[c];
- avtext_print_section_header(w, "Reshaping curve", SECTION_ID_FRAME_SIDE_DATA_COMPONENT);
+ avtext_print_section_header(tfc, "Reshaping curve", SECTION_ID_FRAME_SIDE_DATA_COMPONENT);
print_list_fmt("pivots", "%"PRIu16, curve->num_pivots, 1, curve->pivots[idx]);
- avtext_print_section_header(w, NULL, SECTION_ID_FRAME_SIDE_DATA_PIECE_LIST);
+ avtext_print_section_header(tfc, NULL, SECTION_ID_FRAME_SIDE_DATA_PIECE_LIST);
for (int i = 0; i < curve->num_pivots - 1; i++) {
AVBPrint piece_buf;
@@ -540,7 +540,7 @@ static void print_dovi_metadata(AVTextFormatContext *w, const AVDOVIMetadata *do
}
av_bprintf(&piece_buf, " mapping");
- avtext_print_section_header(w, piece_buf.str, SECTION_ID_FRAME_SIDE_DATA_PIECE);
+ avtext_print_section_header(tfc, piece_buf.str, SECTION_ID_FRAME_SIDE_DATA_PIECE);
print_int("mapping_idc", curve->mapping_idc[i]);
switch (curve->mapping_idc[i]) {
case AV_DOVI_MAPPING_POLYNOMIAL:
@@ -564,11 +564,11 @@ static void print_dovi_metadata(AVTextFormatContext *w, const AVDOVIMetadata *do
}
// SECTION_ID_FRAME_SIDE_DATA_PIECE
- avtext_print_section_footer(w);
+ avtext_print_section_footer(tfc);
}
// SECTION_ID_FRAME_SIDE_DATA_PIECE_LIST
- avtext_print_section_footer(w);
+ avtext_print_section_footer(tfc);
if (mapping->nlq_method_idc != AV_DOVI_NLQ_NONE) {
const AVDOVINLQParams *nlq = &mapping->nlq[c];
@@ -584,11 +584,11 @@ static void print_dovi_metadata(AVTextFormatContext *w, const AVDOVIMetadata *do
}
// SECTION_ID_FRAME_SIDE_DATA_COMPONENT
- avtext_print_section_footer(w);
+ avtext_print_section_footer(tfc);
}
// SECTION_ID_FRAME_SIDE_DATA_COMPONENT_LIST
- avtext_print_section_footer(w);
+ avtext_print_section_footer(tfc);
// color metadata
print_int("dm_metadata_id", color->dm_metadata_id);
@@ -621,7 +621,7 @@ static void print_dovi_metadata(AVTextFormatContext *w, const AVDOVIMetadata *do
}
}
-static void print_dynamic_hdr10_plus(AVTextFormatContext *w, const AVDynamicHDRPlus *metadata)
+static void print_dynamic_hdr10_plus(AVTextFormatContext *tfc, const AVDynamicHDRPlus *metadata)
{
if (!metadata)
return;
@@ -720,7 +720,7 @@ static void print_dynamic_hdr10_plus(AVTextFormatContext *w, const AVDynamicHDRP
}
}
-static void print_dynamic_hdr_vivid(AVTextFormatContext *w, const AVDynamicHDRVivid *metadata)
+static void print_dynamic_hdr_vivid(AVTextFormatContext *tfc, const AVDynamicHDRVivid *metadata)
{
if (!metadata)
return;
@@ -790,7 +790,7 @@ static void print_dynamic_hdr_vivid(AVTextFormatContext *w, const AVDynamicHDRVi
}
}
-static void print_ambient_viewing_environment(AVTextFormatContext *w,
+static void print_ambient_viewing_environment(AVTextFormatContext *tfc,
const AVAmbientViewingEnvironment *env)
{
if (!env)
@@ -801,7 +801,7 @@ static void print_ambient_viewing_environment(AVTextFormatContext *w,
print_q("ambient_light_y", env->ambient_light_y, '/');
}
-static void print_film_grain_params(AVTextFormatContext *w,
+static void print_film_grain_params(AVTextFormatContext *tfc,
const AVFilmGrainParams *fgp)
{
const char *color_range, *color_primaries, *color_trc, *color_space;
@@ -847,10 +847,10 @@ static void print_film_grain_params(AVTextFormatContext *w,
print_int("overlap_flag", aom->overlap_flag);
print_int("limit_output_range", aom->limit_output_range);
- avtext_print_section_header(w, NULL, SECTION_ID_FRAME_SIDE_DATA_COMPONENT_LIST);
+ avtext_print_section_header(tfc, NULL, SECTION_ID_FRAME_SIDE_DATA_COMPONENT_LIST);
if (aom->num_y_points) {
- avtext_print_section_header(w, NULL, SECTION_ID_FRAME_SIDE_DATA_COMPONENT);
+ avtext_print_section_header(tfc, NULL, SECTION_ID_FRAME_SIDE_DATA_COMPONENT);
print_int("bit_depth_luma", fgp->bit_depth_luma);
print_list_fmt("y_points_value", "%"PRIu8, aom->num_y_points, 1, aom->y_points[idx][0]);
@@ -858,14 +858,14 @@ static void print_film_grain_params(AVTextFormatContext *w,
print_list_fmt("ar_coeffs_y", "%"PRId8, num_ar_coeffs_y, 1, aom->ar_coeffs_y[idx]);
// SECTION_ID_FRAME_SIDE_DATA_COMPONENT
- avtext_print_section_footer(w);
+ avtext_print_section_footer(tfc);
}
for (int uv = 0; uv < 2; uv++) {
if (!aom->num_uv_points[uv] && !aom->chroma_scaling_from_luma)
continue;
- avtext_print_section_header(w, NULL, SECTION_ID_FRAME_SIDE_DATA_COMPONENT);
+ avtext_print_section_header(tfc, NULL, SECTION_ID_FRAME_SIDE_DATA_COMPONENT);
print_int("bit_depth_chroma", fgp->bit_depth_chroma);
print_list_fmt("uv_points_value", "%"PRIu8, aom->num_uv_points[uv], 1, aom->uv_points[uv][idx][0]);
@@ -876,11 +876,11 @@ static void print_film_grain_params(AVTextFormatContext *w,
print_int("uv_offset", aom->uv_offset[uv]);
// SECTION_ID_FRAME_SIDE_DATA_COMPONENT
- avtext_print_section_footer(w);
+ avtext_print_section_footer(tfc);
}
// SECTION_ID_FRAME_SIDE_DATA_COMPONENT_LIST
- avtext_print_section_footer(w);
+ avtext_print_section_footer(tfc);
break;
}
case AV_FILM_GRAIN_PARAMS_H274: {
@@ -889,36 +889,36 @@ static void print_film_grain_params(AVTextFormatContext *w,
print_int("blending_mode_id", h274->blending_mode_id);
print_int("log2_scale_factor", h274->log2_scale_factor);
- avtext_print_section_header(w, NULL, SECTION_ID_FRAME_SIDE_DATA_COMPONENT_LIST);
+ avtext_print_section_header(tfc, NULL, SECTION_ID_FRAME_SIDE_DATA_COMPONENT_LIST);
for (int c = 0; c < 3; c++) {
if (!h274->component_model_present[c])
continue;
- avtext_print_section_header(w, NULL, SECTION_ID_FRAME_SIDE_DATA_COMPONENT);
+ avtext_print_section_header(tfc, NULL, SECTION_ID_FRAME_SIDE_DATA_COMPONENT);
print_int(c ? "bit_depth_chroma" : "bit_depth_luma", c ? fgp->bit_depth_chroma : fgp->bit_depth_luma);
- avtext_print_section_header(w, NULL, SECTION_ID_FRAME_SIDE_DATA_PIECE_LIST);
+ avtext_print_section_header(tfc, NULL, SECTION_ID_FRAME_SIDE_DATA_PIECE_LIST);
for (int i = 0; i < h274->num_intensity_intervals[c]; i++) {
- avtext_print_section_header(w, NULL, SECTION_ID_FRAME_SIDE_DATA_PIECE);
+ avtext_print_section_header(tfc, NULL, SECTION_ID_FRAME_SIDE_DATA_PIECE);
print_int("intensity_interval_lower_bound", h274->intensity_interval_lower_bound[c][i]);
print_int("intensity_interval_upper_bound", h274->intensity_interval_upper_bound[c][i]);
print_list_fmt("comp_model_value", "%"PRId16, h274->num_model_values[c], 1, h274->comp_model_value[c][i][idx]);
// SECTION_ID_FRAME_SIDE_DATA_PIECE
- avtext_print_section_footer(w);
+ avtext_print_section_footer(tfc);
}
// SECTION_ID_FRAME_SIDE_DATA_PIECE_LIST
- avtext_print_section_footer(w);
+ avtext_print_section_footer(tfc);
// SECTION_ID_FRAME_SIDE_DATA_COMPONENT
- avtext_print_section_footer(w);
+ avtext_print_section_footer(tfc);
}
// SECTION_ID_FRAME_SIDE_DATA_COMPONENT_LIST
- avtext_print_section_footer(w);
+ avtext_print_section_footer(tfc);
break;
}
}
@@ -926,20 +926,20 @@ static void print_film_grain_params(AVTextFormatContext *w,
av_bprint_finalize(&pbuf, NULL);
}
-static void print_pkt_side_data(AVTextFormatContext *w,
+static void print_pkt_side_data(AVTextFormatContext *tfc,
AVCodecParameters *par,
const AVPacketSideData *sd,
SectionID id_data)
{
const char *name = av_packet_side_data_name(sd->type);
- avtext_print_section_header(w, sd, id_data);
+ avtext_print_section_header(tfc, sd, id_data);
print_str("side_data_type", name ? name : "unknown");
if (sd->type == AV_PKT_DATA_DISPLAYMATRIX && sd->size >= 9*4) {
double rotation = av_display_rotation_get((int32_t *)sd->data);
if (isnan(rotation))
rotation = 0;
- avtext_print_integers(w, "displaymatrix", sd->data, 9, " %11d", 3, 4, 1);
+ avtext_print_integers(tfc, "displaymatrix", sd->data, 9, " %11d", 3, 4, 1);
print_int("rotation", rotation);
} else if (sd->type == AV_PKT_DATA_STEREO3D) {
const AVStereo3D *stereo = (AVStereo3D *)sd->data;
@@ -998,10 +998,10 @@ static void print_pkt_side_data(AVTextFormatContext *w,
print_int("max_average", metadata->MaxFALL);
} else if (sd->type == AV_PKT_DATA_AMBIENT_VIEWING_ENVIRONMENT) {
print_ambient_viewing_environment(
- w, (const AVAmbientViewingEnvironment *)sd->data);
+ tfc, (const AVAmbientViewingEnvironment *)sd->data);
} else if (sd->type == AV_PKT_DATA_DYNAMIC_HDR10_PLUS) {
AVDynamicHDRPlus *metadata = (AVDynamicHDRPlus *)sd->data;
- print_dynamic_hdr10_plus(w, metadata);
+ print_dynamic_hdr10_plus(tfc, metadata);
} else if (sd->type == AV_PKT_DATA_DOVI_CONF) {
AVDOVIDecoderConfigurationRecord *dovi = (AVDOVIDecoderConfigurationRecord *)sd->data;
const char *comp = "unknown";
@@ -1036,8 +1036,8 @@ static void print_pkt_side_data(AVTextFormatContext *w,
} else if (sd->type == AV_PKT_DATA_WEBVTT_IDENTIFIER ||
sd->type == AV_PKT_DATA_WEBVTT_SETTINGS) {
if (do_show_data)
- avtext_print_data(w, "data", sd->data, sd->size);
- avtext_print_data_hash(w, "data_hash", sd->data, sd->size);
+ avtext_print_data(tfc, "data", sd->data, sd->size);
+ avtext_print_data_hash(tfc, "data_hash", sd->data, sd->size);
} else if (sd->type == AV_PKT_DATA_FRAME_CROPPING && sd->size >= sizeof(uint32_t) * 4) {
print_int("crop_top", AV_RL32(sd->data));
print_int("crop_bottom", AV_RL32(sd->data + 4));
@@ -1048,7 +1048,7 @@ static void print_pkt_side_data(AVTextFormatContext *w,
}
}
-static void print_private_data(AVTextFormatContext *w, void *priv_data)
+static void print_private_data(AVTextFormatContext *tfc, void *priv_data)
{
const AVOption *opt = NULL;
while (opt = av_opt_next(priv_data, opt)) {
@@ -1061,7 +1061,7 @@ static void print_private_data(AVTextFormatContext *w, void *priv_data)
}
}
-static void print_color_range(AVTextFormatContext *w, enum AVColorRange color_range)
+static void print_color_range(AVTextFormatContext *tfc, enum AVColorRange color_range)
{
const char *val = av_color_range_name(color_range);
if (!val || color_range == AVCOL_RANGE_UNSPECIFIED) {
@@ -1071,7 +1071,7 @@ static void print_color_range(AVTextFormatContext *w, enum AVColorRange color_ra
}
}
-static void print_color_space(AVTextFormatContext *w, enum AVColorSpace color_space)
+static void print_color_space(AVTextFormatContext *tfc, enum AVColorSpace color_space)
{
const char *val = av_color_space_name(color_space);
if (!val || color_space == AVCOL_SPC_UNSPECIFIED) {
@@ -1081,7 +1081,7 @@ static void print_color_space(AVTextFormatContext *w, enum AVColorSpace color_sp
}
}
-static void print_primaries(AVTextFormatContext *w, enum AVColorPrimaries color_primaries)
+static void print_primaries(AVTextFormatContext *tfc, enum AVColorPrimaries color_primaries)
{
const char *val = av_color_primaries_name(color_primaries);
if (!val || color_primaries == AVCOL_PRI_UNSPECIFIED) {
@@ -1091,7 +1091,7 @@ static void print_primaries(AVTextFormatContext *w, enum AVColorPrimaries color_
}
}
-static void print_color_trc(AVTextFormatContext *w, enum AVColorTransferCharacteristic color_trc)
+static void print_color_trc(AVTextFormatContext *tfc, enum AVColorTransferCharacteristic color_trc)
{
const char *val = av_color_transfer_name(color_trc);
if (!val || color_trc == AVCOL_TRC_UNSPECIFIED) {
@@ -1101,7 +1101,7 @@ static void print_color_trc(AVTextFormatContext *w, enum AVColorTransferCharacte
}
}
-static void print_chroma_location(AVTextFormatContext *w, enum AVChromaLocation chroma_location)
+static void print_chroma_location(AVTextFormatContext *tfc, enum AVChromaLocation chroma_location)
{
const char *val = av_chroma_location_name(chroma_location);
if (!val || chroma_location == AVCHROMA_LOC_UNSPECIFIED) {
@@ -1127,7 +1127,7 @@ static void clear_log(int need_lock)
ff_mutex_unlock(&log_mutex);
}
-static int show_log(AVTextFormatContext *w, int section_ids, int section_id, int log_level)
+static int show_log(AVTextFormatContext *tfc, int section_ids, int section_id, int log_level)
{
int i;
ff_mutex_lock(&log_mutex);
@@ -1135,11 +1135,11 @@ static int show_log(AVTextFormatContext *w, int section_ids, int section_id, int
ff_mutex_unlock(&log_mutex);
return 0;
}
- avtext_print_section_header(w, NULL, section_ids);
+ avtext_print_section_header(tfc, NULL, section_ids);
for (i=0; i<log_buffer_size; i++) {
if (log_buffer[i].log_level <= log_level) {
- avtext_print_section_header(w, NULL, section_id);
+ avtext_print_section_header(tfc, NULL, section_id);
print_str("context", log_buffer[i].context_name);
print_int("level", log_buffer[i].log_level);
print_int("category", log_buffer[i].category);
@@ -1151,18 +1151,18 @@ static int show_log(AVTextFormatContext *w, int section_ids, int section_id, int
print_str_opt("parent_category", "N/A");
}
print_str("message", log_buffer[i].log_message);
- avtext_print_section_footer(w);
+ avtext_print_section_footer(tfc);
}
}
clear_log(0);
ff_mutex_unlock(&log_mutex);
- avtext_print_section_footer(w);
+ avtext_print_section_footer(tfc);
return 0;
}
-static void show_packet(AVTextFormatContext *w, InputFile *ifile, AVPacket *pkt, int packet_idx)
+static void show_packet(AVTextFormatContext *tfc, InputFile *ifile, AVPacket *pkt, int packet_idx)
{
AVStream *st = ifile->streams[pkt->stream_index].st;
AVBPrint pbuf;
@@ -1170,7 +1170,7 @@ static void show_packet(AVTextFormatContext *w, InputFile *ifile, AVPacket *pkt,
av_bprint_init(&pbuf, 1, AV_BPRINT_SIZE_UNLIMITED);
- avtext_print_section_header(w, NULL, SECTION_ID_PACKET);
+ avtext_print_section_header(tfc, NULL, SECTION_ID_PACKET);
s = av_get_media_type_string(st->codecpar->codec_type);
if (s) print_str ("codec_type", s);
@@ -1189,8 +1189,8 @@ static void show_packet(AVTextFormatContext *w, InputFile *ifile, AVPacket *pkt,
pkt->flags & AV_PKT_FLAG_DISCARD ? 'D' : '_',
pkt->flags & AV_PKT_FLAG_CORRUPT ? 'C' : '_');
if (do_show_data)
- avtext_print_data(w, "data", pkt->data, pkt->size);
- avtext_print_data_hash(w, "data_hash", pkt->data, pkt->size);
+ avtext_print_data(tfc, "data", pkt->data, pkt->size);
+ avtext_print_data_hash(tfc, "data_hash", pkt->data, pkt->size);
if (pkt->side_data_elems) {
size_t size;
@@ -1200,33 +1200,33 @@ static void show_packet(AVTextFormatContext *w, InputFile *ifile, AVPacket *pkt,
if (side_metadata && size && do_show_packet_tags) {
AVDictionary *dict = NULL;
if (av_packet_unpack_dictionary(side_metadata, size, &dict) >= 0)
- show_tags(w, dict, SECTION_ID_PACKET_TAGS);
+ show_tags(tfc, dict, SECTION_ID_PACKET_TAGS);
av_dict_free(&dict);
}
- avtext_print_section_header(w, NULL, SECTION_ID_PACKET_SIDE_DATA_LIST);
+ avtext_print_section_header(tfc, NULL, SECTION_ID_PACKET_SIDE_DATA_LIST);
for (int i = 0; i < pkt->side_data_elems; i++) {
- print_pkt_side_data(w, st->codecpar, &pkt->side_data[i],
+ print_pkt_side_data(tfc, st->codecpar, &pkt->side_data[i],
SECTION_ID_PACKET_SIDE_DATA);
- avtext_print_section_footer(w);
+ avtext_print_section_footer(tfc);
}
- avtext_print_section_footer(w);
+ avtext_print_section_footer(tfc);
}
- avtext_print_section_footer(w);
+ avtext_print_section_footer(tfc);
av_bprint_finalize(&pbuf, NULL);
fflush(stdout);
}
-static void show_subtitle(AVTextFormatContext *w, AVSubtitle *sub, AVStream *stream,
+static void show_subtitle(AVTextFormatContext *tfc, AVSubtitle *sub, AVStream *stream,
AVFormatContext *fmt_ctx)
{
AVBPrint pbuf;
av_bprint_init(&pbuf, 1, AV_BPRINT_SIZE_UNLIMITED);
- avtext_print_section_header(w, NULL, SECTION_ID_SUBTITLE);
+ avtext_print_section_header(tfc, NULL, SECTION_ID_SUBTITLE);
print_str ("media_type", "subtitle");
print_ts ("pts", sub->pts);
@@ -1236,30 +1236,30 @@ static void show_subtitle(AVTextFormatContext *w, AVSubtitle *sub, AVStream *str
print_int ("end_display_time", sub->end_display_time);
print_int ("num_rects", sub->num_rects);
- avtext_print_section_footer(w);
+ avtext_print_section_footer(tfc);
av_bprint_finalize(&pbuf, NULL);
fflush(stdout);
}
-static void print_frame_side_data(AVTextFormatContext *w,
+static void print_frame_side_data(AVTextFormatContext *tfc,
const AVFrame *frame,
const AVStream *stream)
{
- avtext_print_section_header(w, NULL, SECTION_ID_FRAME_SIDE_DATA_LIST);
+ avtext_print_section_header(tfc, NULL, SECTION_ID_FRAME_SIDE_DATA_LIST);
for (int i = 0; i < frame->nb_side_data; i++) {
const AVFrameSideData *sd = frame->side_data[i];
const char *name;
- avtext_print_section_header(w, sd, SECTION_ID_FRAME_SIDE_DATA);
+ avtext_print_section_header(tfc, sd, SECTION_ID_FRAME_SIDE_DATA);
name = av_frame_side_data_name(sd->type);
print_str("side_data_type", name ? name : "unknown");
if (sd->type == AV_FRAME_DATA_DISPLAYMATRIX && sd->size >= 9*4) {
double rotation = av_display_rotation_get((int32_t *)sd->data);
if (isnan(rotation))
rotation = 0;
- avtext_print_integers(w, "displaymatrix", sd->data, 9, " %11d", 3, 4, 1);
+ avtext_print_integers(tfc, "displaymatrix", sd->data, 9, " %11d", 3, 4, 1);
print_int("rotation", rotation);
} else if (sd->type == AV_FRAME_DATA_AFD && sd->size > 0) {
print_int("active_format", *sd->data);
@@ -1270,15 +1270,15 @@ static void print_frame_side_data(AVTextFormatContext *w,
} else if (sd->type == AV_FRAME_DATA_S12M_TIMECODE && sd->size == 16) {
uint32_t *tc = (uint32_t*)sd->data;
int m = FFMIN(tc[0],3);
- avtext_print_section_header(w, NULL, SECTION_ID_FRAME_SIDE_DATA_TIMECODE_LIST);
+ avtext_print_section_header(tfc, NULL, SECTION_ID_FRAME_SIDE_DATA_TIMECODE_LIST);
for (int j = 1; j <= m ; j++) {
char tcbuf[AV_TIMECODE_STR_SIZE];
av_timecode_make_smpte_tc_string2(tcbuf, stream->avg_frame_rate, tc[j], 0, 0);
- avtext_print_section_header(w, NULL, SECTION_ID_FRAME_SIDE_DATA_TIMECODE);
+ avtext_print_section_header(tfc, NULL, SECTION_ID_FRAME_SIDE_DATA_TIMECODE);
print_str("value", tcbuf);
- avtext_print_section_footer(w);
+ avtext_print_section_footer(tfc);
}
- avtext_print_section_footer(w);
+ avtext_print_section_footer(tfc);
} else if (sd->type == AV_FRAME_DATA_MASTERING_DISPLAY_METADATA) {
AVMasteringDisplayMetadata *metadata = (AVMasteringDisplayMetadata *)sd->data;
@@ -1300,7 +1300,7 @@ static void print_frame_side_data(AVTextFormatContext *w,
}
} else if (sd->type == AV_FRAME_DATA_DYNAMIC_HDR_PLUS) {
AVDynamicHDRPlus *metadata = (AVDynamicHDRPlus *)sd->data;
- print_dynamic_hdr10_plus(w, metadata);
+ print_dynamic_hdr10_plus(tfc, metadata);
} else if (sd->type == AV_FRAME_DATA_CONTENT_LIGHT_LEVEL) {
AVContentLightMetadata *metadata = (AVContentLightMetadata *)sd->data;
print_int("max_content", metadata->MaxCLL);
@@ -1311,24 +1311,24 @@ static void print_frame_side_data(AVTextFormatContext *w,
print_str(tag->key, tag->value);
print_int("size", sd->size);
} else if (sd->type == AV_FRAME_DATA_DOVI_METADATA) {
- print_dovi_metadata(w, (const AVDOVIMetadata *)sd->data);
+ print_dovi_metadata(tfc, (const AVDOVIMetadata *)sd->data);
} else if (sd->type == AV_FRAME_DATA_DYNAMIC_HDR_VIVID) {
AVDynamicHDRVivid *metadata = (AVDynamicHDRVivid *)sd->data;
- print_dynamic_hdr_vivid(w, metadata);
+ print_dynamic_hdr_vivid(tfc, metadata);
} else if (sd->type == AV_FRAME_DATA_AMBIENT_VIEWING_ENVIRONMENT) {
- print_ambient_viewing_environment(w, (const AVAmbientViewingEnvironment *)sd->data);
+ print_ambient_viewing_environment(tfc, (const AVAmbientViewingEnvironment *)sd->data);
} else if (sd->type == AV_FRAME_DATA_FILM_GRAIN_PARAMS) {
AVFilmGrainParams *fgp = (AVFilmGrainParams *)sd->data;
- print_film_grain_params(w, fgp);
+ print_film_grain_params(tfc, fgp);
} else if (sd->type == AV_FRAME_DATA_VIEW_ID) {
print_int("view_id", *(int*)sd->data);
}
- avtext_print_section_footer(w);
+ avtext_print_section_footer(tfc);
}
- avtext_print_section_footer(w);
+ avtext_print_section_footer(tfc);
}
-static void show_frame(AVTextFormatContext *w, AVFrame *frame, AVStream *stream,
+static void show_frame(AVTextFormatContext *tfc, AVFrame *frame, AVStream *stream,
AVFormatContext *fmt_ctx)
{
FrameData *fd = frame->opaque_ref ? (FrameData*)frame->opaque_ref->data : NULL;
@@ -1338,7 +1338,7 @@ static void show_frame(AVTextFormatContext *w, AVFrame *frame, AVStream *stream,
av_bprint_init(&pbuf, 1, AV_BPRINT_SIZE_UNLIMITED);
- avtext_print_section_header(w, NULL, SECTION_ID_FRAME);
+ avtext_print_section_header(tfc, NULL, SECTION_ID_FRAME);
s = av_get_media_type_string(stream->codecpar->codec_type);
if (s) print_str ("media_type", s);
@@ -1383,11 +1383,11 @@ static void show_frame(AVTextFormatContext *w, AVFrame *frame, AVStream *stream,
print_int("lossless", !!(frame->flags & AV_FRAME_FLAG_LOSSLESS));
print_int("repeat_pict", frame->repeat_pict);
- print_color_range(w, frame->color_range);
- print_color_space(w, frame->colorspace);
- print_primaries(w, frame->color_primaries);
- print_color_trc(w, frame->color_trc);
- print_chroma_location(w, frame->chroma_location);
+ print_color_range(tfc, frame->color_range);
+ print_color_space(tfc, frame->colorspace);
+ print_primaries(tfc, frame->color_primaries);
+ print_color_trc(tfc, frame->color_trc);
+ print_chroma_location(tfc, frame->chroma_location);
break;
case AVMEDIA_TYPE_AUDIO:
@@ -1404,19 +1404,19 @@ static void show_frame(AVTextFormatContext *w, AVFrame *frame, AVStream *stream,
break;
}
if (do_show_frame_tags)
- show_tags(w, frame->metadata, SECTION_ID_FRAME_TAGS);
+ show_tags(tfc, frame->metadata, SECTION_ID_FRAME_TAGS);
if (do_show_log)
- show_log(w, SECTION_ID_FRAME_LOGS, SECTION_ID_FRAME_LOG, do_show_log);
+ show_log(tfc, SECTION_ID_FRAME_LOGS, SECTION_ID_FRAME_LOG, do_show_log);
if (frame->nb_side_data)
- print_frame_side_data(w, frame, stream);
+ print_frame_side_data(tfc, frame, stream);
- avtext_print_section_footer(w);
+ avtext_print_section_footer(tfc);
av_bprint_finalize(&pbuf, NULL);
fflush(stdout);
}
-static av_always_inline int process_frame(AVTextFormatContext *w,
+static av_always_inline int process_frame(AVTextFormatContext *tfc,
InputFile *ifile,
AVFrame *frame, const AVPacket *pkt,
int *packet_new)
@@ -1470,9 +1470,9 @@ static av_always_inline int process_frame(AVTextFormatContext *w,
nb_streams_frames[pkt->stream_index]++;
if (do_show_frames)
if (is_sub)
- show_subtitle(w, &sub, ifile->streams[pkt->stream_index].st, fmt_ctx);
+ show_subtitle(tfc, &sub, ifile->streams[pkt->stream_index].st, fmt_ctx);
else
- show_frame(w, frame, ifile->streams[pkt->stream_index].st, fmt_ctx);
+ show_frame(tfc, frame, ifile->streams[pkt->stream_index].st, fmt_ctx);
if (!is_sub && do_analyze_frames) {
for (int i = 0; i < frame->nb_side_data; i++) {
@@ -1513,7 +1513,7 @@ static void log_read_interval(const ReadInterval *interval, void *log_ctx, int l
av_log(log_ctx, log_level, "\n");
}
-static int read_interval_packets(AVTextFormatContext *w, InputFile *ifile,
+static int read_interval_packets(AVTextFormatContext *tfc, InputFile *ifile,
const ReadInterval *interval, int64_t *cur_ts)
{
AVFormatContext *fmt_ctx = ifile->fmt_ctx;
@@ -1596,7 +1596,7 @@ static int read_interval_packets(AVTextFormatContext *w, InputFile *ifile,
frame_count++;
if (do_read_packets) {
if (do_show_packets)
- show_packet(w, ifile, pkt, i++);
+ show_packet(tfc, ifile, pkt, i++);
nb_streams_packets[pkt->stream_index]++;
}
if (do_read_frames) {
@@ -1612,7 +1612,7 @@ static int read_interval_packets(AVTextFormatContext *w, InputFile *ifile,
fd->pkt_pos = pkt->pos;
fd->pkt_size = pkt->size;
- while (process_frame(w, ifile, frame, pkt, &packet_new) > 0);
+ while (process_frame(tfc, ifile, frame, pkt, &packet_new) > 0);
}
}
av_packet_unref(pkt);
@@ -1622,7 +1622,7 @@ static int read_interval_packets(AVTextFormatContext *w, InputFile *ifile,
for (i = 0; i < ifile->nb_streams; i++) {
pkt->stream_index = i;
if (do_read_frames) {
- while (process_frame(w, ifile, frame, pkt, &(int){1}) > 0);
+ while (process_frame(tfc, ifile, frame, pkt, &(int){1}) > 0);
if (ifile->streams[i].dec_ctx)
avcodec_flush_buffers(ifile->streams[i].dec_ctx);
}
@@ -1638,7 +1638,7 @@ end:
return ret;
}
-static int read_packets(AVTextFormatContext *w, InputFile *ifile)
+static int read_packets(AVTextFormatContext *tfc, InputFile *ifile)
{
AVFormatContext *fmt_ctx = ifile->fmt_ctx;
int i, ret = 0;
@@ -1646,10 +1646,10 @@ static int read_packets(AVTextFormatContext *w, InputFile *ifile)
if (read_intervals_nb == 0) {
ReadInterval interval = (ReadInterval) { .has_start = 0, .has_end = 0 };
- ret = read_interval_packets(w, ifile, &interval, &cur_ts);
+ ret = read_interval_packets(tfc, ifile, &interval, &cur_ts);
} else {
for (i = 0; i < read_intervals_nb; i++) {
- ret = read_interval_packets(w, ifile, &read_intervals[i], &cur_ts);
+ ret = read_interval_packets(tfc, ifile, &read_intervals[i], &cur_ts);
if (ret < 0)
break;
}
@@ -1658,22 +1658,22 @@ static int read_packets(AVTextFormatContext *w, InputFile *ifile)
return ret;
}
-static void print_dispositions(AVTextFormatContext *w, uint32_t disposition, SectionID section_id)
+static void print_dispositions(AVTextFormatContext *tfc, uint32_t disposition, SectionID section_id)
{
- avtext_print_section_header(w, NULL, section_id);
+ avtext_print_section_header(tfc, NULL, section_id);
for (int i = 0; i < sizeof(disposition) * CHAR_BIT; i++) {
const char *disposition_str = av_disposition_to_string(1U << i);
if (disposition_str)
print_int(disposition_str, !!(disposition & (1U << i)));
}
- avtext_print_section_footer(w);
+ avtext_print_section_footer(tfc);
}
#define IN_PROGRAM 1
#define IN_STREAM_GROUP 2
-static int show_stream(AVTextFormatContext *w, AVFormatContext *fmt_ctx, int stream_idx, InputStream *ist, int container)
+static int show_stream(AVTextFormatContext *tfc, AVFormatContext *fmt_ctx, int stream_idx, InputStream *ist, int container)
{
AVStream *stream = ist->st;
AVCodecParameters *par;
@@ -1705,7 +1705,7 @@ static int show_stream(AVTextFormatContext *w, AVFormatContext *fmt_ctx, int str
av_bprint_init(&pbuf, 1, AV_BPRINT_SIZE_UNLIMITED);
- avtext_print_section_header(w, NULL, section_header[container]);
+ avtext_print_section_header(tfc, NULL, section_header[container]);
print_int("index", stream->index);
@@ -1774,11 +1774,11 @@ static int show_stream(AVTextFormatContext *w, AVFormatContext *fmt_ctx, int str
else print_str_opt("pix_fmt", "unknown");
print_int("level", par->level);
- print_color_range(w, par->color_range);
- print_color_space(w, par->color_space);
- print_color_trc(w, par->color_trc);
- print_primaries(w, par->color_primaries);
- print_chroma_location(w, par->chroma_location);
+ print_color_range(tfc, par->color_range);
+ print_color_space(tfc, par->color_space);
+ print_color_trc(tfc, par->color_trc);
+ print_primaries(tfc, par->color_primaries);
+ print_chroma_location(tfc, par->chroma_location);
if (par->field_order == AV_FIELD_PROGRESSIVE)
print_str("field_order", "progressive");
@@ -1830,9 +1830,9 @@ static int show_stream(AVTextFormatContext *w, AVFormatContext *fmt_ctx, int str
if (show_private_data) {
if (dec_ctx && dec_ctx->codec->priv_class)
- print_private_data(w, dec_ctx->priv_data);
+ print_private_data(tfc, dec_ctx->priv_data);
if (fmt_ctx->iformat->priv_class)
- print_private_data(w, fmt_ctx->priv_data);
+ print_private_data(tfc, fmt_ctx->priv_data);
}
if (fmt_ctx->iformat->flags & AVFMT_SHOW_IDS) print_fmt ("id", "0x%x", stream->id);
@@ -1859,113 +1859,113 @@ static int show_stream(AVTextFormatContext *w, AVFormatContext *fmt_ctx, int str
if (nb_streams_packets[stream_idx]) print_fmt ("nb_read_packets", "%"PRIu64, nb_streams_packets[stream_idx]);
else print_str_opt("nb_read_packets", "N/A");
if (do_show_data)
- avtext_print_data(w, "extradata", par->extradata,
+ avtext_print_data(tfc, "extradata", par->extradata,
par->extradata_size);
if (par->extradata_size > 0) {
print_int("extradata_size", par->extradata_size);
- avtext_print_data_hash(w, "extradata_hash", par->extradata,
+ avtext_print_data_hash(tfc, "extradata_hash", par->extradata,
par->extradata_size);
}
/* Print disposition information */
if (do_show_stream_disposition) {
av_assert0(container < FF_ARRAY_ELEMS(section_disposition));
- print_dispositions(w, stream->disposition, section_disposition[container]);
+ print_dispositions(tfc, stream->disposition, section_disposition[container]);
}
if (do_show_stream_tags) {
av_assert0(container < FF_ARRAY_ELEMS(section_tags));
- ret = show_tags(w, stream->metadata, section_tags[container]);
+ ret = show_tags(tfc, stream->metadata, section_tags[container]);
}
if (stream->codecpar->nb_coded_side_data) {
- avtext_print_section_header(w, NULL, SECTION_ID_STREAM_SIDE_DATA_LIST);
+ avtext_print_section_header(tfc, NULL, SECTION_ID_STREAM_SIDE_DATA_LIST);
for (int i = 0; i < stream->codecpar->nb_coded_side_data; i++) {
- print_pkt_side_data(w, stream->codecpar, &stream->codecpar->coded_side_data[i],
+ print_pkt_side_data(tfc, stream->codecpar, &stream->codecpar->coded_side_data[i],
SECTION_ID_STREAM_SIDE_DATA);
- avtext_print_section_footer(w);
+ avtext_print_section_footer(tfc);
}
- avtext_print_section_footer(w);
+ avtext_print_section_footer(tfc);
}
- avtext_print_section_footer(w);
+ avtext_print_section_footer(tfc);
av_bprint_finalize(&pbuf, NULL);
fflush(stdout);
return ret;
}
-static int show_streams(AVTextFormatContext *w, InputFile *ifile)
+static int show_streams(AVTextFormatContext *tfc, InputFile *ifile)
{
AVFormatContext *fmt_ctx = ifile->fmt_ctx;
int i, ret = 0;
- avtext_print_section_header(w, NULL, SECTION_ID_STREAMS);
+ avtext_print_section_header(tfc, NULL, SECTION_ID_STREAMS);
for (i = 0; i < ifile->nb_streams; i++)
if (selected_streams[i]) {
- ret = show_stream(w, fmt_ctx, i, &ifile->streams[i], 0);
+ ret = show_stream(tfc, fmt_ctx, i, &ifile->streams[i], 0);
if (ret < 0)
break;
}
- avtext_print_section_footer(w);
+ avtext_print_section_footer(tfc);
return ret;
}
-static int show_program(AVTextFormatContext *w, InputFile *ifile, AVProgram *program)
+static int show_program(AVTextFormatContext *tfc, InputFile *ifile, AVProgram *program)
{
AVFormatContext *fmt_ctx = ifile->fmt_ctx;
int i, ret = 0;
- avtext_print_section_header(w, NULL, SECTION_ID_PROGRAM);
+ avtext_print_section_header(tfc, NULL, SECTION_ID_PROGRAM);
print_int("program_id", program->id);
print_int("program_num", program->program_num);
print_int("nb_streams", program->nb_stream_indexes);
print_int("pmt_pid", program->pmt_pid);
print_int("pcr_pid", program->pcr_pid);
if (do_show_program_tags)
- ret = show_tags(w, program->metadata, SECTION_ID_PROGRAM_TAGS);
+ ret = show_tags(tfc, program->metadata, SECTION_ID_PROGRAM_TAGS);
if (ret < 0)
goto end;
- avtext_print_section_header(w, NULL, SECTION_ID_PROGRAM_STREAMS);
+ avtext_print_section_header(tfc, NULL, SECTION_ID_PROGRAM_STREAMS);
for (i = 0; i < program->nb_stream_indexes; i++) {
if (selected_streams[program->stream_index[i]]) {
- ret = show_stream(w, fmt_ctx, program->stream_index[i], &ifile->streams[program->stream_index[i]], IN_PROGRAM);
+ ret = show_stream(tfc, fmt_ctx, program->stream_index[i], &ifile->streams[program->stream_index[i]], IN_PROGRAM);
if (ret < 0)
break;
}
}
- avtext_print_section_footer(w);
+ avtext_print_section_footer(tfc);
end:
- avtext_print_section_footer(w);
+ avtext_print_section_footer(tfc);
return ret;
}
-static int show_programs(AVTextFormatContext *w, InputFile *ifile)
+static int show_programs(AVTextFormatContext *tfc, InputFile *ifile)
{
AVFormatContext *fmt_ctx = ifile->fmt_ctx;
int i, ret = 0;
- avtext_print_section_header(w, NULL, SECTION_ID_PROGRAMS);
+ avtext_print_section_header(tfc, NULL, SECTION_ID_PROGRAMS);
for (i = 0; i < fmt_ctx->nb_programs; i++) {
AVProgram *program = fmt_ctx->programs[i];
if (!program)
continue;
- ret = show_program(w, ifile, program);
+ ret = show_program(tfc, ifile, program);
if (ret < 0)
break;
}
- avtext_print_section_footer(w);
+ avtext_print_section_footer(tfc);
return ret;
}
-static void print_tile_grid_params(AVTextFormatContext *w, const AVStreamGroup *stg,
+static void print_tile_grid_params(AVTextFormatContext *tfc, const AVStreamGroup *stg,
const AVStreamGroupTileGrid *tile_grid)
{
- avtext_print_section_header(w, stg, SECTION_ID_STREAM_GROUP_COMPONENT);
+ avtext_print_section_header(tfc, stg, SECTION_ID_STREAM_GROUP_COMPONENT);
print_int("nb_tiles", tile_grid->nb_tiles);
print_int("coded_width", tile_grid->coded_width);
print_int("coded_height", tile_grid->coded_height);
@@ -1973,19 +1973,19 @@ static void print_tile_grid_params(AVTextFormatContext *w, const AVStreamGroup *
print_int("vertical_offset", tile_grid->vertical_offset);
print_int("width", tile_grid->width);
print_int("height", tile_grid->height);
- avtext_print_section_header(w, NULL, SECTION_ID_STREAM_GROUP_SUBCOMPONENTS);
+ avtext_print_section_header(tfc, NULL, SECTION_ID_STREAM_GROUP_SUBCOMPONENTS);
for (int i = 0; i < tile_grid->nb_tiles; i++) {
- avtext_print_section_header(w, "tile_offset", SECTION_ID_STREAM_GROUP_SUBCOMPONENT);
+ avtext_print_section_header(tfc, "tile_offset", SECTION_ID_STREAM_GROUP_SUBCOMPONENT);
print_int("stream_index", tile_grid->offsets[i].idx);
print_int("tile_horizontal_offset", tile_grid->offsets[i].horizontal);
print_int("tile_vertical_offset", tile_grid->offsets[i].vertical);
- avtext_print_section_footer(w);
+ avtext_print_section_footer(tfc);
}
- avtext_print_section_footer(w);
- avtext_print_section_footer(w);
+ avtext_print_section_footer(tfc);
+ avtext_print_section_footer(tfc);
}
-static void print_iamf_param_definition(AVTextFormatContext *w, const char *name,
+static void print_iamf_param_definition(AVTextFormatContext *tfc, const char *name,
const AVIAMFParamDefinition *param, SectionID section_id)
{
SectionID subsection_id, parameter_section_id;
@@ -1993,7 +1993,7 @@ static void print_iamf_param_definition(AVTextFormatContext *w, const char *name
av_assert0(subsection_id != -1);
parameter_section_id = sections[subsection_id].children_ids[0];
av_assert0(parameter_section_id != -1);
- avtext_print_section_header(w, "IAMF Param Definition", section_id);
+ avtext_print_section_header(tfc, "IAMF Param Definition", section_id);
print_str("name", name);
print_int("nb_subblocks", param->nb_subblocks);
print_int("type", param->type);
@@ -2002,56 +2002,56 @@ static void print_iamf_param_definition(AVTextFormatContext *w, const char *name
print_int("duration", param->duration);
print_int("constant_subblock_duration", param->constant_subblock_duration);
if (param->nb_subblocks > 0)
- avtext_print_section_header(w, NULL, subsection_id);
+ avtext_print_section_header(tfc, NULL, subsection_id);
for (int i = 0; i < param->nb_subblocks; i++) {
const void *subblock = av_iamf_param_definition_get_subblock(param, i);
switch(param->type) {
case AV_IAMF_PARAMETER_DEFINITION_MIX_GAIN: {
const AVIAMFMixGain *mix = subblock;
- avtext_print_section_header(w, "IAMF Mix Gain Parameters", parameter_section_id);
+ avtext_print_section_header(tfc, "IAMF Mix Gain Parameters", parameter_section_id);
print_int("subblock_duration", mix->subblock_duration);
print_int("animation_type", mix->animation_type);
print_q("start_point_value", mix->start_point_value, '/');
print_q("end_point_value", mix->end_point_value, '/');
print_q("control_point_value", mix->control_point_value, '/');
print_q("control_point_relative_time", mix->control_point_relative_time, '/');
- avtext_print_section_footer(w); // parameter_section_id
+ avtext_print_section_footer(tfc); // parameter_section_id
break;
}
case AV_IAMF_PARAMETER_DEFINITION_DEMIXING: {
const AVIAMFDemixingInfo *demix = subblock;
- avtext_print_section_header(w, "IAMF Demixing Info", parameter_section_id);
+ avtext_print_section_header(tfc, "IAMF Demixing Info", parameter_section_id);
print_int("subblock_duration", demix->subblock_duration);
print_int("dmixp_mode", demix->dmixp_mode);
- avtext_print_section_footer(w); // parameter_section_id
+ avtext_print_section_footer(tfc); // parameter_section_id
break;
}
case AV_IAMF_PARAMETER_DEFINITION_RECON_GAIN: {
const AVIAMFReconGain *recon = subblock;
- avtext_print_section_header(w, "IAMF Recon Gain", parameter_section_id);
+ avtext_print_section_header(tfc, "IAMF Recon Gain", parameter_section_id);
print_int("subblock_duration", recon->subblock_duration);
- avtext_print_section_footer(w); // parameter_section_id
+ avtext_print_section_footer(tfc); // parameter_section_id
break;
}
}
}
if (param->nb_subblocks > 0)
- avtext_print_section_footer(w); // subsection_id
- avtext_print_section_footer(w); // section_id
+ avtext_print_section_footer(tfc); // subsection_id
+ avtext_print_section_footer(tfc); // section_id
}
-static void print_iamf_audio_element_params(AVTextFormatContext *w, const AVStreamGroup *stg,
+static void print_iamf_audio_element_params(AVTextFormatContext *tfc, const AVStreamGroup *stg,
const AVIAMFAudioElement *audio_element)
{
- avtext_print_section_header(w, stg, SECTION_ID_STREAM_GROUP_COMPONENT);
+ avtext_print_section_header(tfc, stg, SECTION_ID_STREAM_GROUP_COMPONENT);
print_int("nb_layers", audio_element->nb_layers);
print_int("audio_element_type", audio_element->audio_element_type);
print_int("default_w", audio_element->default_w);
- avtext_print_section_header(w, NULL, SECTION_ID_STREAM_GROUP_SUBCOMPONENTS);
+ avtext_print_section_header(tfc, NULL, SECTION_ID_STREAM_GROUP_SUBCOMPONENTS);
for (int i = 0; i < audio_element->nb_layers; i++) {
const AVIAMFLayer *layer = audio_element->layers[i];
char val_str[128];
- avtext_print_section_header(w, "IAMF Audio Layer", SECTION_ID_STREAM_GROUP_SUBCOMPONENT);
+ avtext_print_section_header(tfc, "IAMF Audio Layer", SECTION_ID_STREAM_GROUP_SUBCOMPONENT);
av_channel_layout_describe(&layer->ch_layout, val_str, sizeof(val_str));
print_str("channel_layout", val_str);
if (audio_element->audio_element_type == AV_IAMF_AUDIO_ELEMENT_TYPE_CHANNEL) {
@@ -2059,52 +2059,52 @@ static void print_iamf_audio_element_params(AVTextFormatContext *w, const AVStre
print_q("output_gain", layer->output_gain, '/');
} else if (audio_element->audio_element_type == AV_IAMF_AUDIO_ELEMENT_TYPE_SCENE)
print_int("ambisonics_mode", layer->ambisonics_mode);
- avtext_print_section_footer(w); // SECTION_ID_STREAM_GROUP_SUBCOMPONENT
+ avtext_print_section_footer(tfc); // SECTION_ID_STREAM_GROUP_SUBCOMPONENT
}
if (audio_element->demixing_info)
- print_iamf_param_definition(w, "demixing_info", audio_element->demixing_info,
+ print_iamf_param_definition(tfc, "demixing_info", audio_element->demixing_info,
SECTION_ID_STREAM_GROUP_SUBCOMPONENT);
if (audio_element->recon_gain_info)
- print_iamf_param_definition(w, "recon_gain_info", audio_element->recon_gain_info,
+ print_iamf_param_definition(tfc, "recon_gain_info", audio_element->recon_gain_info,
SECTION_ID_STREAM_GROUP_SUBCOMPONENT);
- avtext_print_section_footer(w); // SECTION_ID_STREAM_GROUP_SUBCOMPONENTS
- avtext_print_section_footer(w); // SECTION_ID_STREAM_GROUP_COMPONENT
+ avtext_print_section_footer(tfc); // SECTION_ID_STREAM_GROUP_SUBCOMPONENTS
+ avtext_print_section_footer(tfc); // SECTION_ID_STREAM_GROUP_COMPONENT
}
-static void print_iamf_submix_params(AVTextFormatContext *w, const AVIAMFSubmix *submix)
+static void print_iamf_submix_params(AVTextFormatContext *tfc, const AVIAMFSubmix *submix)
{
- avtext_print_section_header(w, "IAMF Submix", SECTION_ID_STREAM_GROUP_SUBCOMPONENT);
+ avtext_print_section_header(tfc, "IAMF Submix", SECTION_ID_STREAM_GROUP_SUBCOMPONENT);
print_int("nb_elements", submix->nb_elements);
print_int("nb_layouts", submix->nb_layouts);
print_q("default_mix_gain", submix->default_mix_gain, '/');
- avtext_print_section_header(w, NULL, SECTION_ID_STREAM_GROUP_PIECES);
+ avtext_print_section_header(tfc, NULL, SECTION_ID_STREAM_GROUP_PIECES);
for (int i = 0; i < submix->nb_elements; i++) {
const AVIAMFSubmixElement *element = submix->elements[i];
- avtext_print_section_header(w, "IAMF Submix Element", SECTION_ID_STREAM_GROUP_PIECE);
+ avtext_print_section_header(tfc, "IAMF Submix Element", SECTION_ID_STREAM_GROUP_PIECE);
print_int("stream_id", element->audio_element_id);
print_q("default_mix_gain", element->default_mix_gain, '/');
print_int("headphones_rendering_mode", element->headphones_rendering_mode);
- avtext_print_section_header(w, NULL, SECTION_ID_STREAM_GROUP_SUBPIECES);
+ avtext_print_section_header(tfc, NULL, SECTION_ID_STREAM_GROUP_SUBPIECES);
if (element->annotations) {
const AVDictionaryEntry *annotation = NULL;
- avtext_print_section_header(w, "IAMF Annotations", SECTION_ID_STREAM_GROUP_SUBPIECE);
+ avtext_print_section_header(tfc, "IAMF Annotations", SECTION_ID_STREAM_GROUP_SUBPIECE);
while (annotation = av_dict_iterate(element->annotations, annotation))
print_str(annotation->key, annotation->value);
- avtext_print_section_footer(w); // SECTION_ID_STREAM_GROUP_SUBPIECE
+ avtext_print_section_footer(tfc); // SECTION_ID_STREAM_GROUP_SUBPIECE
}
if (element->element_mix_config)
- print_iamf_param_definition(w, "element_mix_config", element->element_mix_config,
+ print_iamf_param_definition(tfc, "element_mix_config", element->element_mix_config,
SECTION_ID_STREAM_GROUP_SUBPIECE);
- avtext_print_section_footer(w); // SECTION_ID_STREAM_GROUP_SUBPIECES
- avtext_print_section_footer(w); // SECTION_ID_STREAM_GROUP_PIECE
+ avtext_print_section_footer(tfc); // SECTION_ID_STREAM_GROUP_SUBPIECES
+ avtext_print_section_footer(tfc); // SECTION_ID_STREAM_GROUP_PIECE
}
if (submix->output_mix_config)
- print_iamf_param_definition(w, "output_mix_config", submix->output_mix_config,
+ print_iamf_param_definition(tfc, "output_mix_config", submix->output_mix_config,
SECTION_ID_STREAM_GROUP_PIECE);
for (int i = 0; i < submix->nb_layouts; i++) {
const AVIAMFSubmixLayout *layout = submix->layouts[i];
char val_str[128];
- avtext_print_section_header(w, "IAMF Submix Layout", SECTION_ID_STREAM_GROUP_PIECE);
+ avtext_print_section_header(tfc, "IAMF Submix Layout", SECTION_ID_STREAM_GROUP_PIECE);
av_channel_layout_describe(&layout->sound_system, val_str, sizeof(val_str));
print_str("sound_system", val_str);
print_q("integrated_loudness", layout->integrated_loudness, '/');
@@ -2112,51 +2112,51 @@ static void print_iamf_submix_params(AVTextFormatContext *w, const AVIAMFSubmix
print_q("true_peak", layout->true_peak, '/');
print_q("dialogue_anchored_loudness", layout->dialogue_anchored_loudness, '/');
print_q("album_anchored_loudness", layout->album_anchored_loudness, '/');
- avtext_print_section_footer(w); // SECTION_ID_STREAM_GROUP_PIECE
+ avtext_print_section_footer(tfc); // SECTION_ID_STREAM_GROUP_PIECE
}
- avtext_print_section_footer(w); // SECTION_ID_STREAM_GROUP_PIECES
- avtext_print_section_footer(w); // SECTION_ID_STREAM_GROUP_SUBCOMPONENT
+ avtext_print_section_footer(tfc); // SECTION_ID_STREAM_GROUP_PIECES
+ avtext_print_section_footer(tfc); // SECTION_ID_STREAM_GROUP_SUBCOMPONENT
}
-static void print_iamf_mix_presentation_params(AVTextFormatContext *w, const AVStreamGroup *stg,
+static void print_iamf_mix_presentation_params(AVTextFormatContext *tfc, const AVStreamGroup *stg,
const AVIAMFMixPresentation *mix_presentation)
{
- avtext_print_section_header(w, stg, SECTION_ID_STREAM_GROUP_COMPONENT);
+ avtext_print_section_header(tfc, stg, SECTION_ID_STREAM_GROUP_COMPONENT);
print_int("nb_submixes", mix_presentation->nb_submixes);
- avtext_print_section_header(w, NULL, SECTION_ID_STREAM_GROUP_SUBCOMPONENTS);
+ avtext_print_section_header(tfc, NULL, SECTION_ID_STREAM_GROUP_SUBCOMPONENTS);
if (mix_presentation->annotations) {
const AVDictionaryEntry *annotation = NULL;
- avtext_print_section_header(w, "IAMF Annotations", SECTION_ID_STREAM_GROUP_SUBCOMPONENT);
+ avtext_print_section_header(tfc, "IAMF Annotations", SECTION_ID_STREAM_GROUP_SUBCOMPONENT);
while (annotation = av_dict_iterate(mix_presentation->annotations, annotation))
print_str(annotation->key, annotation->value);
- avtext_print_section_footer(w); // SECTION_ID_STREAM_GROUP_SUBCOMPONENT
+ avtext_print_section_footer(tfc); // SECTION_ID_STREAM_GROUP_SUBCOMPONENT
}
for (int i = 0; i < mix_presentation->nb_submixes; i++)
- print_iamf_submix_params(w, mix_presentation->submixes[i]);
- avtext_print_section_footer(w); // SECTION_ID_STREAM_GROUP_SUBCOMPONENTS
- avtext_print_section_footer(w); // SECTION_ID_STREAM_GROUP_COMPONENT
+ print_iamf_submix_params(tfc, mix_presentation->submixes[i]);
+ avtext_print_section_footer(tfc); // SECTION_ID_STREAM_GROUP_SUBCOMPONENTS
+ avtext_print_section_footer(tfc); // SECTION_ID_STREAM_GROUP_COMPONENT
}
-static void print_stream_group_params(AVTextFormatContext *w, AVStreamGroup *stg)
+static void print_stream_group_params(AVTextFormatContext *tfc, AVStreamGroup *stg)
{
- avtext_print_section_header(w, NULL, SECTION_ID_STREAM_GROUP_COMPONENTS);
+ avtext_print_section_header(tfc, NULL, SECTION_ID_STREAM_GROUP_COMPONENTS);
if (stg->type == AV_STREAM_GROUP_PARAMS_TILE_GRID)
- print_tile_grid_params(w, stg, stg->params.tile_grid);
+ print_tile_grid_params(tfc, stg, stg->params.tile_grid);
else if (stg->type == AV_STREAM_GROUP_PARAMS_IAMF_AUDIO_ELEMENT)
- print_iamf_audio_element_params(w, stg, stg->params.iamf_audio_element);
+ print_iamf_audio_element_params(tfc, stg, stg->params.iamf_audio_element);
else if (stg->type == AV_STREAM_GROUP_PARAMS_IAMF_MIX_PRESENTATION)
- print_iamf_mix_presentation_params(w, stg, stg->params.iamf_mix_presentation);
- avtext_print_section_footer(w); // SECTION_ID_STREAM_GROUP_COMPONENTS
+ print_iamf_mix_presentation_params(tfc, stg, stg->params.iamf_mix_presentation);
+ avtext_print_section_footer(tfc); // SECTION_ID_STREAM_GROUP_COMPONENTS
}
-static int show_stream_group(AVTextFormatContext *w, InputFile *ifile, AVStreamGroup *stg)
+static int show_stream_group(AVTextFormatContext *tfc, InputFile *ifile, AVStreamGroup *stg)
{
AVFormatContext *fmt_ctx = ifile->fmt_ctx;
AVBPrint pbuf;
int i, ret = 0;
av_bprint_init(&pbuf, 1, AV_BPRINT_SIZE_UNLIMITED);
- avtext_print_section_header(w, NULL, SECTION_ID_STREAM_GROUP);
+ avtext_print_section_header(tfc, NULL, SECTION_ID_STREAM_GROUP);
print_int("index", stg->index);
if (fmt_ctx->iformat->flags & AVFMT_SHOW_IDS) print_fmt ("id", "0x%"PRIx64, stg->id);
else print_str_opt("id", "N/A");
@@ -2166,60 +2166,60 @@ static int show_stream_group(AVTextFormatContext *w, InputFile *ifile, AVStreamG
else
print_str_opt("type", "unknown");
if (do_show_stream_group_components)
- print_stream_group_params(w, stg);
+ print_stream_group_params(tfc, stg);
/* Print disposition information */
if (do_show_stream_group_disposition)
- print_dispositions(w, stg->disposition, SECTION_ID_STREAM_GROUP_DISPOSITION);
+ print_dispositions(tfc, stg->disposition, SECTION_ID_STREAM_GROUP_DISPOSITION);
if (do_show_stream_group_tags)
- ret = show_tags(w, stg->metadata, SECTION_ID_STREAM_GROUP_TAGS);
+ ret = show_tags(tfc, stg->metadata, SECTION_ID_STREAM_GROUP_TAGS);
if (ret < 0)
goto end;
- avtext_print_section_header(w, NULL, SECTION_ID_STREAM_GROUP_STREAMS);
+ avtext_print_section_header(tfc, NULL, SECTION_ID_STREAM_GROUP_STREAMS);
for (i = 0; i < stg->nb_streams; i++) {
if (selected_streams[stg->streams[i]->index]) {
- ret = show_stream(w, fmt_ctx, stg->streams[i]->index, &ifile->streams[stg->streams[i]->index], IN_STREAM_GROUP);
+ ret = show_stream(tfc, fmt_ctx, stg->streams[i]->index, &ifile->streams[stg->streams[i]->index], IN_STREAM_GROUP);
if (ret < 0)
break;
}
}
- avtext_print_section_footer(w);
+ avtext_print_section_footer(tfc);
end:
av_bprint_finalize(&pbuf, NULL);
- avtext_print_section_footer(w);
+ avtext_print_section_footer(tfc);
return ret;
}
-static int show_stream_groups(AVTextFormatContext *w, InputFile *ifile)
+static int show_stream_groups(AVTextFormatContext *tfc, InputFile *ifile)
{
AVFormatContext *fmt_ctx = ifile->fmt_ctx;
int i, ret = 0;
- avtext_print_section_header(w, NULL, SECTION_ID_STREAM_GROUPS);
+ avtext_print_section_header(tfc, NULL, SECTION_ID_STREAM_GROUPS);
for (i = 0; i < fmt_ctx->nb_stream_groups; i++) {
AVStreamGroup *stg = fmt_ctx->stream_groups[i];
- ret = show_stream_group(w, ifile, stg);
+ ret = show_stream_group(tfc, ifile, stg);
if (ret < 0)
break;
}
- avtext_print_section_footer(w);
+ avtext_print_section_footer(tfc);
return ret;
}
-static int show_chapters(AVTextFormatContext *w, InputFile *ifile)
+static int show_chapters(AVTextFormatContext *tfc, InputFile *ifile)
{
AVFormatContext *fmt_ctx = ifile->fmt_ctx;
int i, ret = 0;
- avtext_print_section_header(w, NULL, SECTION_ID_CHAPTERS);
+ avtext_print_section_header(tfc, NULL, SECTION_ID_CHAPTERS);
for (i = 0; i < fmt_ctx->nb_chapters; i++) {
AVChapter *chapter = fmt_ctx->chapters[i];
- avtext_print_section_header(w, NULL, SECTION_ID_CHAPTER);
+ avtext_print_section_header(tfc, NULL, SECTION_ID_CHAPTER);
print_int("id", chapter->id);
print_q ("time_base", chapter->time_base, '/');
print_int("start", chapter->start);
@@ -2227,21 +2227,21 @@ static int show_chapters(AVTextFormatContext *w, InputFile *ifile)
print_int("end", chapter->end);
print_time("end_time", chapter->end, &chapter->time_base);
if (do_show_chapter_tags)
- ret = show_tags(w, chapter->metadata, SECTION_ID_CHAPTER_TAGS);
- avtext_print_section_footer(w);
+ ret = show_tags(tfc, chapter->metadata, SECTION_ID_CHAPTER_TAGS);
+ avtext_print_section_footer(tfc);
}
- avtext_print_section_footer(w);
+ avtext_print_section_footer(tfc);
return ret;
}
-static int show_format(AVTextFormatContext *w, InputFile *ifile)
+static int show_format(AVTextFormatContext *tfc, InputFile *ifile)
{
AVFormatContext *fmt_ctx = ifile->fmt_ctx;
int64_t size = fmt_ctx->pb ? avio_size(fmt_ctx->pb) : -1;
int ret = 0;
- avtext_print_section_header(w, NULL, SECTION_ID_FORMAT);
+ avtext_print_section_header(tfc, NULL, SECTION_ID_FORMAT);
print_str_validate("filename", fmt_ctx->url);
print_int("nb_streams", fmt_ctx->nb_streams);
print_int("nb_programs", fmt_ctx->nb_programs);
@@ -2259,19 +2259,19 @@ static int show_format(AVTextFormatContext *w, InputFile *ifile)
else print_str_opt("bit_rate", "N/A");
print_int("probe_score", fmt_ctx->probe_score);
if (do_show_format_tags)
- ret = show_tags(w, fmt_ctx->metadata, SECTION_ID_FORMAT_TAGS);
+ ret = show_tags(tfc, fmt_ctx->metadata, SECTION_ID_FORMAT_TAGS);
- avtext_print_section_footer(w);
+ avtext_print_section_footer(tfc);
fflush(stdout);
return ret;
}
-static void show_error(AVTextFormatContext *w, int err)
+static void show_error(AVTextFormatContext *tfc, int err)
{
- avtext_print_section_header(w, NULL, SECTION_ID_ERROR);
+ avtext_print_section_header(tfc, NULL, SECTION_ID_ERROR);
print_int("code", err);
print_str("string", av_err2str(err));
- avtext_print_section_footer(w);
+ avtext_print_section_footer(tfc);
}
static int open_input_file(InputFile *ifile, const char *filename,
@@ -2413,7 +2413,7 @@ static void close_input_file(InputFile *ifile)
avformat_close_input(&ifile->fmt_ctx);
}
-static int probe_file(AVTextFormatContext *tctx, const char *filename,
+static int probe_file(AVTextFormatContext *tfc, const char *filename,
const char *print_filename)
{
InputFile ifile = { 0 };
@@ -2455,40 +2455,40 @@ static int probe_file(AVTextFormatContext *tctx, const char *filename,
if (do_read_frames || do_read_packets) {
if (do_show_frames && do_show_packets &&
- tctx->formatter->flags & AV_TEXTFORMAT_FLAG_SUPPORTS_MIXED_ARRAY_CONTENT)
+ tfc->formatter->flags & AV_TEXTFORMAT_FLAG_SUPPORTS_MIXED_ARRAY_CONTENT)
section_id = SECTION_ID_PACKETS_AND_FRAMES;
else if (do_show_packets && !do_show_frames)
section_id = SECTION_ID_PACKETS;
else // (!do_show_packets && do_show_frames)
section_id = SECTION_ID_FRAMES;
if (do_show_frames || do_show_packets)
- avtext_print_section_header(tctx, NULL, section_id);
- ret = read_packets(tctx, &ifile);
+ avtext_print_section_header(tfc, NULL, section_id);
+ ret = read_packets(tfc, &ifile);
if (do_show_frames || do_show_packets)
- avtext_print_section_footer(tctx);
+ avtext_print_section_footer(tfc);
CHECK_END;
}
if (do_show_programs) {
- ret = show_programs(tctx, &ifile);
+ ret = show_programs(tfc, &ifile);
CHECK_END;
}
if (do_show_stream_groups) {
- ret = show_stream_groups(tctx, &ifile);
+ ret = show_stream_groups(tfc, &ifile);
CHECK_END;
}
if (do_show_streams) {
- ret = show_streams(tctx, &ifile);
+ ret = show_streams(tfc, &ifile);
CHECK_END;
}
if (do_show_chapters) {
- ret = show_chapters(tctx, &ifile);
+ ret = show_chapters(tfc, &ifile);
CHECK_END;
}
if (do_show_format) {
- ret = show_format(tctx, &ifile);
+ ret = show_format(tfc, &ifile);
CHECK_END;
}
@@ -2511,18 +2511,18 @@ static void show_usage(void)
av_log(NULL, AV_LOG_INFO, "\n");
}
-static void ffprobe_show_program_version(AVTextFormatContext *w)
+static void ffprobe_show_program_version(AVTextFormatContext *tfc)
{
AVBPrint pbuf;
av_bprint_init(&pbuf, 1, AV_BPRINT_SIZE_UNLIMITED);
- avtext_print_section_header(w, NULL, SECTION_ID_PROGRAM_VERSION);
+ avtext_print_section_header(tfc, NULL, SECTION_ID_PROGRAM_VERSION);
print_str("version", FFMPEG_VERSION);
print_fmt("copyright", "Copyright (c) %d-%d the FFmpeg developers",
program_birth_year, CONFIG_THIS_YEAR);
print_str("compiler_ident", CC_IDENT);
print_str("configuration", FFMPEG_CONFIGURATION);
- avtext_print_section_footer(w);
+ avtext_print_section_footer(tfc);
av_bprint_finalize(&pbuf, NULL);
}
@@ -2531,20 +2531,20 @@ static void ffprobe_show_program_version(AVTextFormatContext *w)
do { \
if (CONFIG_##LIBNAME) { \
unsigned int version = libname##_version(); \
- avtext_print_section_header(w, NULL, SECTION_ID_LIBRARY_VERSION); \
+ avtext_print_section_header(tfc, NULL, SECTION_ID_LIBRARY_VERSION); \
print_str("name", "lib" #libname); \
print_int("major", LIB##LIBNAME##_VERSION_MAJOR); \
print_int("minor", LIB##LIBNAME##_VERSION_MINOR); \
print_int("micro", LIB##LIBNAME##_VERSION_MICRO); \
print_int("version", version); \
print_str("ident", LIB##LIBNAME##_IDENT); \
- avtext_print_section_footer(w); \
+ avtext_print_section_footer(tfc); \
} \
} while (0)
-static void ffprobe_show_library_versions(AVTextFormatContext *w)
+static void ffprobe_show_library_versions(AVTextFormatContext *tfc)
{
- avtext_print_section_header(w, NULL, SECTION_ID_LIBRARY_VERSIONS);
+ avtext_print_section_header(tfc, NULL, SECTION_ID_LIBRARY_VERSIONS);
SHOW_LIB_VERSION(avutil, AVUTIL);
SHOW_LIB_VERSION(avcodec, AVCODEC);
SHOW_LIB_VERSION(avformat, AVFORMAT);
@@ -2553,7 +2553,7 @@ static void ffprobe_show_library_versions(AVTextFormatContext *w)
SHOW_LIB_VERSION(swscale, SWSCALE);
SHOW_LIB_VERSION(swresample, SWRESAMPLE);
SHOW_LIB_VERSION(postproc, POSTPROC);
- avtext_print_section_footer(w);
+ avtext_print_section_footer(tfc);
}
#define PRINT_PIX_FMT_FLAG(flagname, name) \
@@ -2561,14 +2561,14 @@ static void ffprobe_show_library_versions(AVTextFormatContext *w)
print_int(name, !!(pixdesc->flags & AV_PIX_FMT_FLAG_##flagname)); \
} while (0)
-static void ffprobe_show_pixel_formats(AVTextFormatContext *w)
+static void ffprobe_show_pixel_formats(AVTextFormatContext *tfc)
{
const AVPixFmtDescriptor *pixdesc = NULL;
int i, n;
- avtext_print_section_header(w, NULL, SECTION_ID_PIXEL_FORMATS);
+ avtext_print_section_header(tfc, NULL, SECTION_ID_PIXEL_FORMATS);
while (pixdesc = av_pix_fmt_desc_next(pixdesc)) {
- avtext_print_section_header(w, NULL, SECTION_ID_PIXEL_FORMAT);
+ avtext_print_section_header(tfc, NULL, SECTION_ID_PIXEL_FORMAT);
print_str("name", pixdesc->name);
print_int("nb_components", pixdesc->nb_components);
if ((pixdesc->nb_components >= 3) && !(pixdesc->flags & AV_PIX_FMT_FLAG_RGB)) {
@@ -2582,7 +2582,7 @@ static void ffprobe_show_pixel_formats(AVTextFormatContext *w)
if (n) print_int ("bits_per_pixel", n);
else print_str_opt("bits_per_pixel", "N/A");
if (do_show_pixel_format_flags) {
- avtext_print_section_header(w, NULL, SECTION_ID_PIXEL_FORMAT_FLAGS);
+ avtext_print_section_header(tfc, NULL, SECTION_ID_PIXEL_FORMAT_FLAGS);
PRINT_PIX_FMT_FLAG(BE, "big_endian");
PRINT_PIX_FMT_FLAG(PAL, "palette");
PRINT_PIX_FMT_FLAG(BITSTREAM, "bitstream");
@@ -2590,21 +2590,21 @@ static void ffprobe_show_pixel_formats(AVTextFormatContext *w)
PRINT_PIX_FMT_FLAG(PLANAR, "planar");
PRINT_PIX_FMT_FLAG(RGB, "rgb");
PRINT_PIX_FMT_FLAG(ALPHA, "alpha");
- avtext_print_section_footer(w);
+ avtext_print_section_footer(tfc);
}
if (do_show_pixel_format_components && (pixdesc->nb_components > 0)) {
- avtext_print_section_header(w, NULL, SECTION_ID_PIXEL_FORMAT_COMPONENTS);
+ avtext_print_section_header(tfc, NULL, SECTION_ID_PIXEL_FORMAT_COMPONENTS);
for (i = 0; i < pixdesc->nb_components; i++) {
- avtext_print_section_header(w, NULL, SECTION_ID_PIXEL_FORMAT_COMPONENT);
+ avtext_print_section_header(tfc, NULL, SECTION_ID_PIXEL_FORMAT_COMPONENT);
print_int("index", i + 1);
print_int("bit_depth", pixdesc->comp[i].depth);
- avtext_print_section_footer(w);
+ avtext_print_section_footer(tfc);
}
- avtext_print_section_footer(w);
+ avtext_print_section_footer(tfc);
}
- avtext_print_section_footer(w);
+ avtext_print_section_footer(tfc);
}
- avtext_print_section_footer(w);
+ avtext_print_section_footer(tfc);
}
static int opt_show_optional_fields(void *optctx, const char *opt, const char *arg)
--
ffmpeg-codebot
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 108+ messages in thread
* Re: [FFmpeg-devel] [PATCH v6 0/8] print_graphs: Complete Filtergraph Printing
2025-03-08 20:16 ` [FFmpeg-devel] [PATCH v6 0/8] print_graphs: Complete Filtergraph Printing ffmpegagent
` (7 preceding siblings ...)
2025-03-08 20:16 ` [FFmpeg-devel] [PATCH v6 8/8] fftools/ffprobe: Rename AVTextFormatContext variables (w => tfc) softworkz
@ 2025-03-10 21:46 ` Stefano Sabatini
2025-03-12 4:04 ` [FFmpeg-devel] [PATCH v7 0/7] " ffmpegagent
9 siblings, 0 replies; 108+ messages in thread
From: Stefano Sabatini @ 2025-03-10 21:46 UTC (permalink / raw)
To: FFmpeg development discussions and patches; +Cc: softworkz
On date Saturday 2025-03-08 20:16:26 +0000, ffmpegagent wrote:
> This new version of the patchset starts by extracting the text formatting
> and writing APIs from ffprobe.c into a subfolder under fftools. The type
> naming follows public API naming style, ramping up for making it a public
> API in the future without another big renaming.
>
> The extraction of the text formatting APIs can be followed in smaller steps
> in the recent patchset "[RFC] avtextformat: Transform text writing into an
> independent API". To make this more review-friendly, the ffprobe changes are
> done in two steps. The 2nd commit includes all essential changes while the
> large part of renamings is deferred to the 3rd commit (containing renamings
> only).
>
> The graph-printing uses the extracted APIs. It supports all ffprobe output
> formats now. Otherwise it's functional equivalent to the previous version:
>
> * Different to other graph printing methods, this is outputting:
> * both, simple and complex filtergraphs
> * all graphs with runtime state (including auto-inserted filters)
> * each graph with its inputs and outputs
> * all filters with their in- and output pads
> * all connections between all input- and output pads
> * for each connection:
> * the runtime-negotiated format and media type
> * the hw context
> * if video hw context, both: hw pixfmt + sw pixfmt
> * Output can either be printed to stdout or written to specified file
> * Output is machine-readable
Patch 1-3,8 approved on my side and can be already merged.
I'll review the other ones but it's best if other ones can review them
(e.g. Nicolas or Anton).
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 108+ messages in thread
* [FFmpeg-devel] [PATCH v7 0/7] print_graphs: Complete Filtergraph Printing
2025-03-08 20:16 ` [FFmpeg-devel] [PATCH v6 0/8] print_graphs: Complete Filtergraph Printing ffmpegagent
` (8 preceding siblings ...)
2025-03-10 21:46 ` [FFmpeg-devel] [PATCH v6 0/8] print_graphs: Complete Filtergraph Printing Stefano Sabatini
@ 2025-03-12 4:04 ` ffmpegagent
2025-03-12 4:04 ` [FFmpeg-devel] [PATCH v7 1/7] fftools/textformat: Extract and generalize textformat api from ffprobe.c softworkz
` (7 more replies)
9 siblings, 8 replies; 108+ messages in thread
From: ffmpegagent @ 2025-03-12 4:04 UTC (permalink / raw)
To: ffmpeg-devel; +Cc: softworkz
This new version of the patchset starts by extracting the text formatting
and writing APIs from ffprobe.c into a subfolder under fftools. The type
naming follows public API naming style, ramping up for making it a public
API in the future without another big renaming.
The extraction of the text formatting APIs can be followed in smaller steps
in the recent patchset "[RFC] avtextformat: Transform text writing into an
independent API". To make this more review-friendly, the ffprobe changes are
done in two steps. The 2nd commit includes all essential changes while the
large part of renamings is deferred to the 3rd commit (containing renamings
only).
The graph-printing uses the extracted APIs. It supports all ffprobe output
formats now. Otherwise it's functional equivalent to the previous version:
* Different to other graph printing methods, this is outputting:
* both, simple and complex filtergraphs
* all graphs with runtime state (including auto-inserted filters)
* each graph with its inputs and outputs
* all filters with their in- and output pads
* all connections between all input- and output pads
* for each connection:
* the runtime-negotiated format and media type
* the hw context
* if video hw context, both: hw pixfmt + sw pixfmt
* Output can either be printed to stdout or written to specified file
* Output is machine-readable
Right after filtergraph configuration, the connection details are often not
complete yet. On the other side, when waiting too long or if an error occurs
somewhere, the graph info might never be printed. Experience has shown, that
the most suitable and realiable point in time for printing graph information
is right before cleanup.
Due to the changes for multi-threading, this is no longer doable as easy as
before, so the following method is used: Each filtergraph initiates its own
graph printing short before cleanup into a buffer. Before final cleanup in
ffmpeg.c, the outputs from the individual graphs are pieced together for the
actual output to file or console. (the structure according to the output
format remains valid)
Example output:
https://gist.github.com/softworkz/2a9e8699b288f5d40fa381c2a496e165
Update V2
* Change NULL checks to match common code style
* Add Add avfilter_link_get_hw_frames_ctx() function to avoid importing
filters.h
* Do the same without including avfilter/filters.h (as per note from
Andreas Reinhardt)
Update V3
* Includes extraction and generalization of the text formatting APIs
* All output formats supported now
Update V4
* Fix "new warnings" were generated
* Fix missing colon in commit message
* Rebase due to changesin ApiChanges
Update V5
* Fix copyright headers
* Return proper error codes rather than -1
* Fix misnamed local functions
* Fix typo
* Rename 'w' in ffprobe.c to 'tfc'
Update V6
* Fix commit message (8)
* Revert renaming of context in main()
Update V7
* Fix code style issues in ffmpeg_graphprint and other files
* Rename w > tfc in ffmpeg_graphprint
* Use snake_case for output element names
* Rework ouitput
* Reduce properties for inputs and outputs
* Use clear names for filters and src/dest
* Add color_range and color_space properties
* Drop extra device_context section
* Remove unused section definitions (as per notes by Stefano Sabatini,
thanks!)
softworkz (7):
fftools/textformat: Extract and generalize textformat api from
ffprobe.c
fftools/ffprobe: Change to use textformat api
fftools/ffprobe: Rename writer_print_section_* and WriterContext
fftools/ffmpeg_filter: Move some declaration to new header file
avfilter/avfilter: Add avfilter_link_get_hw_frames_ctx()
fftools/ffmpeg_graphprint: Add options for filtergraph printing
fftools/ffprobe: Rename AVTextFormatContext variables (w => tfc)
doc/APIchanges | 3 +
doc/ffmpeg.texi | 11 +
fftools/Makefile | 23 +
fftools/ffmpeg.c | 4 +
fftools/ffmpeg.h | 3 +
fftools/ffmpeg_filter.c | 193 +--
fftools/ffmpeg_filter.h | 232 +++
fftools/ffmpeg_graphprint.c | 470 ++++++
fftools/ffmpeg_graphprint.h | 35 +
fftools/ffmpeg_opt.c | 12 +
fftools/ffprobe.c | 2296 +++++-----------------------
fftools/textformat/avtextformat.c | 674 ++++++++
fftools/textformat/avtextformat.h | 171 +++
fftools/textformat/avtextwriters.h | 68 +
fftools/textformat/tf_compact.c | 282 ++++
fftools/textformat/tf_default.c | 145 ++
fftools/textformat/tf_flat.c | 174 +++
fftools/textformat/tf_ini.c | 160 ++
fftools/textformat/tf_json.c | 215 +++
fftools/textformat/tf_xml.c | 221 +++
fftools/textformat/tw_avio.c | 129 ++
fftools/textformat/tw_buffer.c | 92 ++
fftools/textformat/tw_stdout.c | 82 +
libavfilter/avfilter.c | 9 +
libavfilter/avfilter.h | 12 +
libavfilter/version.h | 2 +-
26 files changed, 3585 insertions(+), 2133 deletions(-)
create mode 100644 fftools/ffmpeg_filter.h
create mode 100644 fftools/ffmpeg_graphprint.c
create mode 100644 fftools/ffmpeg_graphprint.h
create mode 100644 fftools/textformat/avtextformat.c
create mode 100644 fftools/textformat/avtextformat.h
create mode 100644 fftools/textformat/avtextwriters.h
create mode 100644 fftools/textformat/tf_compact.c
create mode 100644 fftools/textformat/tf_default.c
create mode 100644 fftools/textformat/tf_flat.c
create mode 100644 fftools/textformat/tf_ini.c
create mode 100644 fftools/textformat/tf_json.c
create mode 100644 fftools/textformat/tf_xml.c
create mode 100644 fftools/textformat/tw_avio.c
create mode 100644 fftools/textformat/tw_buffer.c
create mode 100644 fftools/textformat/tw_stdout.c
base-commit: 0b097ed9f141f57e2b91f0704c721a9eff0204c0
Published-As: https://github.com/ffstaging/FFmpeg/releases/tag/pr-ffstaging-52%2Fsoftworkz%2Fsubmit_print_graphs5-v7
Fetch-It-Via: git fetch https://github.com/ffstaging/FFmpeg pr-ffstaging-52/softworkz/submit_print_graphs5-v7
Pull-Request: https://github.com/ffstaging/FFmpeg/pull/52
Range-diff vs v6:
1: b26a45ea0e = 1: f379c77e88 fftools/textformat: Extract and generalize textformat api from ffprobe.c
2: 2eb2b4ded5 = 2: 67bc38ac96 fftools/ffprobe: Change to use textformat api
3: 5ab9ac2a28 = 3: 52c41fdcd0 fftools/ffprobe: Rename writer_print_section_* and WriterContext
4: 85735035e4 = 4: 21480a08b1 fftools/ffmpeg_filter: Move some declaration to new header file
5: 811c5ab35c ! 5: 70ba7a8bc9 avfilter/avfilter: Add avfilter_link_get_hw_frames_ctx()
@@ doc/APIchanges: The last version increases of all libraries were on 2024-03-07
+2025-02-xx - xxxxxxxxxx - lavfi 10.10.100 - avfilter.h
+ Add avfilter_link_get_hw_frames_ctx().
+
- 2025-03-01 - xxxxxxxxxx - lavu 59.58.100 - pixfmt.h
- Add AV_PIX_FMT_GRAY32BE and AV_PIX_FMT_GRAY32LE.
-
+ 2025-03-10 - xxxxxxxxxx - lavu 59.59.100 - pixfmt.h
+ Add AV_PIX_FMT_YAF16BE, AV_PIX_FMT_YAF16LE, AV_PIX_FMT_YAF32BE,
+ and AV_PIX_FMT_YAF32LE.
## libavfilter/avfilter.c ##
@@ libavfilter/avfilter.c: enum AVMediaType avfilter_pad_get_type(const AVFilterPad *pads, int pad_idx)
@@ libavfilter/avfilter.c: enum AVMediaType avfilter_pad_get_type(const AVFilterPad
+AVBufferRef *avfilter_link_get_hw_frames_ctx(AVFilterLink *link)
+{
-+ FilterLink* plink = ff_filter_link(link);
++ FilterLink *plink = ff_filter_link(link);
+ if (plink->hw_frames_ctx)
+ return av_buffer_ref(plink->hw_frames_ctx);
+
@@ libavfilter/avfilter.h: const char *avfilter_pad_get_name(const AVFilterPad *pad
+ *
+ * @param link an AVFilterLink
+ *
-+ * @return a ref-counted copy of the link's hw_frames_ctx if there's a hardware
-+ * frames context associated with the link or NULL otherwise.
++ * @return a ref-counted copy of the link's hw_frames_ctx field if there is
++ * a hardware frames context associated with the link or NULL otherwise.
+ * The returned AVBufferRef needs to be released with av_buffer_unref()
-+ * when it's no longer used.
++ * when it is no longer used.
+ */
+AVBufferRef* avfilter_link_get_hw_frames_ctx(AVFilterLink *link);
+
6: 8ae08a7006 ! 6: a30ded4d62 fftools/ffmpeg_graphprint: Add options for filtergraph printing
@@ Metadata
## Commit message ##
fftools/ffmpeg_graphprint: Add options for filtergraph printing
+ Enables filtergraph printing and adds the options to the docs
+
The key benefits are:
- Different to other graph printing methods, this is outputting:
@@ Commit message
Signed-off-by: softworkz <softworkz@hotmail.com>
+ ## doc/ffmpeg.texi ##
+@@ doc/ffmpeg.texi: It is on by default, to explicitly disable it you need to specify @code{-nostats
+ @item -stats_period @var{time} (@emph{global})
+ Set period at which encoding progress/statistics are updated. Default is 0.5 seconds.
+
++@item -print_graphs (@emph{global})
++Prints filtergraph details to stderr in the format set via -print_graphs_format.
++
++@item -print_graphs_file @var{filename} (@emph{global})
++Writes filtergraph details to the specified file in the format set via -print_graphs_format.
++Use a dash (-) for the file name to write to stdout.
++
++@item -print_graphs_format @var{format} (@emph{global})
++Sets the output printing format (available formats are: default, compact, csv, flat, ini, json, xml)
++The default format is json.
++
+ @item -progress @var{url} (@emph{global})
+ Send program-friendly progress information to @var{url}.
+
+
## fftools/Makefile ##
@@ fftools/Makefile: OBJS-ffmpeg += \
fftools/ffmpeg_mux_init.o \
@@ fftools/Makefile: OBJS-ffmpeg += \
OBJS-ffprobe += \
fftools/textformat/avtextformat.o \
+ ## fftools/ffmpeg.c ##
+@@
+ #include "ffmpeg.h"
+ #include "ffmpeg_sched.h"
+ #include "ffmpeg_utils.h"
++#include "ffmpeg_graphprint.h"
+
+ const char program_name[] = "ffmpeg";
+ const int program_birth_year = 2000;
+@@ fftools/ffmpeg.c: const AVIOInterruptCB int_cb = { decode_interrupt_cb, NULL };
+
+ static void ffmpeg_cleanup(int ret)
+ {
++ if (print_graphs || print_graphs_file)
++ print_filtergraphs(filtergraphs, nb_filtergraphs, output_files, nb_output_files);
++
+ if (do_benchmark) {
+ int64_t maxrss = getmaxrss() / 1024;
+ av_log(NULL, AV_LOG_INFO, "bench: maxrss=%"PRId64"KiB\n", maxrss);
+
## fftools/ffmpeg.h ##
@@ fftools/ffmpeg.h: extern float max_error_rate;
extern char *filter_nbthreads;
extern int filter_complex_nbthreads;
extern int vstats_version;
+extern int print_graphs;
-+extern char* print_graphs_file;
-+extern char* print_graphs_format;
++extern char *print_graphs_file;
++extern char *print_graphs_format;
extern int auto_conversion_filters;
extern const AVIOInterruptCB int_cb;
+ ## fftools/ffmpeg_filter.c ##
+@@
+
+ #include "ffmpeg.h"
+ #include "ffmpeg_filter.h"
++#include "ffmpeg_graphprint.h"
+
+ #include "libavfilter/avfilter.h"
+ #include "libavfilter/buffersink.h"
+@@ fftools/ffmpeg_filter.c: read_frames:
+ }
+
+ finish:
++
++ if (print_graphs || print_graphs_file)
++ print_filtergraph(fg, fgt.graph);
++
+ // EOF is normal termination
+ if (ret == AVERROR_EOF)
+ ret = 0;
+
## fftools/ffmpeg_graphprint.c (new) ##
@@
+/*
@@ fftools/ffmpeg_graphprint.c (new)
+ SECTION_ID_OUTPUT,
+ SECTION_ID_FILTERS,
+ SECTION_ID_FILTER,
-+ SECTION_ID_HWDEViCECONTEXT,
+ SECTION_ID_HWFRAMESCONTEXT,
-+ SECTION_ID_ERROR,
-+ SECTION_ID_LOG,
-+ SECTION_ID_LOGS,
+} SectionID;
+
+static struct AVTextFormatSection sections[] = {
-+ [SECTION_ID_ROOT] = { SECTION_ID_ROOT, "GraphDescription", AV_TEXTFORMAT_SECTION_FLAG_IS_WRAPPER,
-+ { SECTION_ID_ERROR, SECTION_ID_PROGRAM_VERSION, SECTION_ID_FILTERGRAPHS, SECTION_ID_LOGS, -1} },
-+ [SECTION_ID_PROGRAM_VERSION] = { SECTION_ID_PROGRAM_VERSION, "ProgramVersion", 0, { -1 } },
-+
-+ [SECTION_ID_FILTERGRAPHS] = { SECTION_ID_FILTERGRAPHS, "Graphs", AV_TEXTFORMAT_SECTION_FLAG_IS_ARRAY, { SECTION_ID_FILTERGRAPH, -1 } },
-+ [SECTION_ID_FILTERGRAPH] = { SECTION_ID_FILTERGRAPH, "Graph", 0, { SECTION_ID_INPUTS, SECTION_ID_OUTPUTS, SECTION_ID_FILTERS, -1 }, },
++ [SECTION_ID_ROOT] = { SECTION_ID_ROOT, "graph_description", AV_TEXTFORMAT_SECTION_FLAG_IS_WRAPPER,
++ { SECTION_ID_PROGRAM_VERSION, SECTION_ID_FILTERGRAPHS, -1} },
++ [SECTION_ID_PROGRAM_VERSION] = { SECTION_ID_PROGRAM_VERSION, "program_version", 0, { -1 } },
+
-+ [SECTION_ID_INPUTS] = { SECTION_ID_INPUTS, "Inputs", AV_TEXTFORMAT_SECTION_FLAG_IS_ARRAY, { SECTION_ID_INPUT, SECTION_ID_ERROR, -1 } },
-+ [SECTION_ID_INPUT] = { SECTION_ID_INPUT, "Input", 0, { SECTION_ID_HWFRAMESCONTEXT, SECTION_ID_ERROR, -1 }, },
++ [SECTION_ID_FILTERGRAPHS] = { SECTION_ID_FILTERGRAPHS, "graphs", AV_TEXTFORMAT_SECTION_FLAG_IS_ARRAY, { SECTION_ID_FILTERGRAPH, -1 } },
++ [SECTION_ID_FILTERGRAPH] = { SECTION_ID_FILTERGRAPH, "graph", 0, { SECTION_ID_INPUTS, SECTION_ID_OUTPUTS, SECTION_ID_FILTERS, -1 }, },
+
-+ [SECTION_ID_OUTPUTS] = { SECTION_ID_OUTPUTS, "Outputs", AV_TEXTFORMAT_SECTION_FLAG_IS_ARRAY, { SECTION_ID_OUTPUT, SECTION_ID_ERROR, -1 } },
-+ [SECTION_ID_OUTPUT] = { SECTION_ID_OUTPUT, "Output", 0, { SECTION_ID_HWFRAMESCONTEXT, SECTION_ID_ERROR, -1 }, },
++ [SECTION_ID_INPUTS] = { SECTION_ID_INPUTS, "inputs", AV_TEXTFORMAT_SECTION_FLAG_IS_ARRAY, { SECTION_ID_INPUT, -1 } },
++ [SECTION_ID_INPUT] = { SECTION_ID_INPUT, "input", 0, { SECTION_ID_HWFRAMESCONTEXT, -1 }, },
+
-+ [SECTION_ID_FILTERS] = { SECTION_ID_FILTERS, "Filters", AV_TEXTFORMAT_SECTION_FLAG_IS_ARRAY, { SECTION_ID_FILTER, SECTION_ID_ERROR, -1 } },
-+ [SECTION_ID_FILTER] = { SECTION_ID_FILTER, "Filter", 0, { SECTION_ID_HWDEViCECONTEXT, SECTION_ID_ERROR, -1 }, },
++ [SECTION_ID_OUTPUTS] = { SECTION_ID_OUTPUTS, "outputs", AV_TEXTFORMAT_SECTION_FLAG_IS_ARRAY, { SECTION_ID_OUTPUT, -1 } },
++ [SECTION_ID_OUTPUT] = { SECTION_ID_OUTPUT, "output", 0, { SECTION_ID_HWFRAMESCONTEXT, -1 }, },
+
-+ [SECTION_ID_HWDEViCECONTEXT] = { SECTION_ID_HWDEViCECONTEXT, "HwDeviceContext", 0, { SECTION_ID_ERROR, -1 }, },
-+ [SECTION_ID_HWFRAMESCONTEXT] = { SECTION_ID_HWFRAMESCONTEXT, "HwFramesContext", 0, { SECTION_ID_ERROR, -1 }, },
++ [SECTION_ID_FILTERS] = { SECTION_ID_FILTERS, "filters", AV_TEXTFORMAT_SECTION_FLAG_IS_ARRAY, { SECTION_ID_FILTER, -1 } },
++ [SECTION_ID_FILTER] = { SECTION_ID_FILTER, "filter", 0, { -1 }, },
+
-+ [SECTION_ID_ERROR] = { SECTION_ID_ERROR, "Error", 0, { -1 } },
-+ [SECTION_ID_LOGS] = { SECTION_ID_LOGS, "Log", AV_TEXTFORMAT_SECTION_FLAG_IS_ARRAY, { SECTION_ID_LOG, -1 } },
-+ [SECTION_ID_LOG] = { SECTION_ID_LOG, "LogEntry", 0, { -1 }, },
++ [SECTION_ID_HWFRAMESCONTEXT] = { SECTION_ID_HWFRAMESCONTEXT, "hw_frames_context", 0, { -1 }, },
+};
+
+/* Text Format API Shortcuts */
-+#define print_int(k, v) avtext_print_integer(w, k, v)
-+#define print_q(k, v, s) avtext_print_rational(w, k, v, s)
-+#define print_str(k, v) avtext_print_string(w, k, v, 0)
++#define print_int(k, v) avtext_print_integer(tfc, k, v)
++#define print_q(k, v, s) avtext_print_rational(tfc, k, v, s)
++#define print_str(k, v) avtext_print_string(tfc, k, v, 0)
+
-+static void print_hwdevicecontext(AVTextFormatContext *w, const AVHWDeviceContext *hw_device_context)
++static void print_hwdevicecontext(AVTextFormatContext *tfc, const AVHWDeviceContext *hw_device_context)
+{
-+ avtext_print_section_header(w, NULL, SECTION_ID_HWDEViCECONTEXT);
-+
-+ print_int("HasHwDeviceContext", 1);
-+ print_str("DeviceType", av_hwdevice_get_type_name(hw_device_context->type));
-+
-+ avtext_print_section_footer(w); // SECTION_ID_HWDEViCECONTEXT
++ print_int("has_hw_device_context", 1);
++ print_str("hw_device_type", av_hwdevice_get_type_name(hw_device_context->type));
+}
+
-+static void print_hwframescontext(AVTextFormatContext *w, const AVHWFramesContext *hw_frames_context)
++static void print_hwframescontext(AVTextFormatContext *tfc, const AVHWFramesContext *hw_frames_context)
+{
-+ const AVPixFmtDescriptor* pixdescHw;
-+ const AVPixFmtDescriptor* pixdescSw;
++ const AVPixFmtDescriptor* pix_desc_hw;
++ const AVPixFmtDescriptor* pix_desc_sw;
+
-+ avtext_print_section_header(w, NULL, SECTION_ID_HWFRAMESCONTEXT);
++ avtext_print_section_header(tfc, NULL, SECTION_ID_HWFRAMESCONTEXT);
+
-+ print_int("HasHwFramesContext", 1);
++ print_int("has_hw_frames_context", 1);
++ print_str("hw_device_type", av_hwdevice_get_type_name(hw_frames_context->device_ctx->type));
+
-+ pixdescHw = av_pix_fmt_desc_get(hw_frames_context->format);
-+ if (pixdescHw) {
-+ print_str("HwPixelFormat", pixdescHw->name);
-+ print_str("HwPixelFormatAlias", pixdescHw->alias);
++ pix_desc_hw = av_pix_fmt_desc_get(hw_frames_context->format);
++ if (pix_desc_hw) {
++ print_str("hw_pixel_format", pix_desc_hw->name);
++ if (pix_desc_hw->alias)
++ print_str("hw_pixel_format_alias", pix_desc_hw->alias);
+ }
+
-+ pixdescSw = av_pix_fmt_desc_get(hw_frames_context->sw_format);
-+ if (pixdescSw) {
-+ print_str("SwPixelFormat", pixdescSw->name);
-+ print_str("SwPixelFormatAlias", pixdescSw->alias);
++ pix_desc_sw = av_pix_fmt_desc_get(hw_frames_context->sw_format);
++ if (pix_desc_sw) {
++ print_str("sw_pixel_format", pix_desc_sw->name);
++ if (pix_desc_sw->alias)
++ print_str("sw_pixel_format_alias", pix_desc_sw->alias);
+ }
+
-+ print_int("Width", hw_frames_context->width);
-+ print_int("Height", hw_frames_context->height);
-+
-+ print_hwdevicecontext(w, hw_frames_context->device_ctx);
++ print_int("width", hw_frames_context->width);
++ print_int("height", hw_frames_context->height);
++ print_int("initial_pool_size", hw_frames_context->initial_pool_size);
+
-+ avtext_print_section_footer(w); // SECTION_ID_HWFRAMESCONTEXT
++ avtext_print_section_footer(tfc); // SECTION_ID_HWFRAMESCONTEXT
+}
+
-+static void print_link(AVTextFormatContext *w, AVFilterLink *link)
++static void print_link(AVTextFormatContext *tfc, AVFilterLink *link)
+{
+ AVBufferRef *hw_frames_ctx;
-+ char layoutString[64];
++ char layout_string[64];
++
++ print_str("media_type", av_get_media_type_string(link->type));
+
+ switch (link->type) {
+ case AVMEDIA_TYPE_VIDEO:
-+ print_str("Format", av_x_if_null(av_get_pix_fmt_name(link->format), "?"));
-+ print_int("Width", link->w);
-+ print_int("Height", link->h);
-+ print_q("SAR", link->sample_aspect_ratio, ':');
-+ print_q("TimeBase", link->time_base, '/');
++ print_str("format", av_x_if_null(av_get_pix_fmt_name(link->format), "?"));
++ print_int("width", link->w);
++ print_int("height", link->h);
++ print_q("sar", link->sample_aspect_ratio, ':');
++ print_str("color_range", av_color_range_name(link->color_range));
++ print_str("color_space", av_color_space_name(link->colorspace));
+ break;
+
-+ ////case AVMEDIA_TYPE_SUBTITLE:
-+ //// print_str("Format", av_x_if_null(av_get_subtitle_fmt_name(link->format), "?"));
-+ //// print_int("Width", link->w);
-+ //// print_int("Height", link->h);
-+ //// print_q("TimeBase", link->time_base, '/');
-+ //// break;
++ case AVMEDIA_TYPE_SUBTITLE:
++ ////print_str("format", av_x_if_null(av_get_subtitle_fmt_name(link->format), "?"));
++ print_int("width", link->w);
++ print_int("height", link->h);
++ break;
+
+ case AVMEDIA_TYPE_AUDIO:
-+ av_channel_layout_describe(&link->ch_layout, layoutString, sizeof(layoutString));
-+ print_str("ChannelString", layoutString);
-+ print_int("Channels", link->ch_layout.nb_channels);
-+ ////print_int("ChannelLayout", link->ch_layout);
-+ print_int("SampleRate", link->sample_rate);
++ av_channel_layout_describe(&link->ch_layout, layout_string, sizeof(layout_string));
++ print_str("channel_layout", layout_string);
++ print_int("channels", link->ch_layout.nb_channels);
++ print_int("sample_rate", link->sample_rate);
+ break;
+ }
+
++ print_q("time_base", link->time_base, '/');
++
+ hw_frames_ctx = avfilter_link_get_hw_frames_ctx(link);
+
-+ if (hw_frames_ctx && hw_frames_ctx->buffer) {
-+ print_hwframescontext(w, (AVHWFramesContext *)hw_frames_ctx->data);
-+ }
++ if (hw_frames_ctx && hw_frames_ctx->data)
++ print_hwframescontext(tfc, (AVHWFramesContext *)hw_frames_ctx->data);
+}
+
-+static void print_filter(AVTextFormatContext *w, const AVFilterContext* filter)
++static void print_filter(AVTextFormatContext *tfc, const AVFilterContext* filter)
+{
-+ avtext_print_section_header(w, NULL, SECTION_ID_FILTER);
++ avtext_print_section_header(tfc, NULL, SECTION_ID_FILTER);
+
-+ print_str("Name", filter->name);
++ print_str("filter_id", filter->name);
+
+ if (filter->filter) {
-+ print_str("Name2", filter->filter->name);
-+ print_str("Description", filter->filter->description);
++ print_str("filter_name", filter->filter->name);
++ print_str("description", filter->filter->description);
+ }
+
+ if (filter->hw_device_ctx) {
-+ AVHWDeviceContext* decCtx = (AVHWDeviceContext*)filter->hw_device_ctx->data;
-+ print_hwdevicecontext(w, decCtx);
++ AVHWDeviceContext* device_context = (AVHWDeviceContext*)filter->hw_device_ctx->data;
++ print_hwdevicecontext(tfc, device_context);
++ if (filter->extra_hw_frames > 0)
++ print_int("extra_hw_frames", filter->extra_hw_frames);
+ }
+
-+ avtext_print_section_header(w, NULL, SECTION_ID_INPUTS);
++ avtext_print_section_header(tfc, NULL, SECTION_ID_INPUTS);
+
+ for (unsigned i = 0; i < filter->nb_inputs; i++) {
+ AVFilterLink *link = filter->inputs[i];
-+ avtext_print_section_header(w, NULL, SECTION_ID_INPUT);
++ avtext_print_section_header(tfc, NULL, SECTION_ID_INPUT);
+
-+ print_str("SourceName", link->src->name);
-+ print_str("SourcePadName", avfilter_pad_get_name(link->srcpad, 0));
-+ print_str("DestPadName", avfilter_pad_get_name(link->dstpad, 0));
++ print_int("input_index", i);
++ print_str("pad_name", avfilter_pad_get_name(link->dstpad, 0));;
++ print_str("source_filter_id", link->src->name);
++ print_str("source_pad_name", avfilter_pad_get_name(link->srcpad, 0));
+
-+ print_link(w, link);
++ print_link(tfc, link);
+
-+ avtext_print_section_footer(w); // SECTION_ID_INPUT
++ avtext_print_section_footer(tfc); // SECTION_ID_INPUT
+ }
+
-+ avtext_print_section_footer(w); // SECTION_ID_INPUTS
++ avtext_print_section_footer(tfc); // SECTION_ID_INPUTS
+
-+ avtext_print_section_header(w, NULL, SECTION_ID_OUTPUTS);
++ avtext_print_section_header(tfc, NULL, SECTION_ID_OUTPUTS);
+
+ for (unsigned i = 0; i < filter->nb_outputs; i++) {
+ AVFilterLink *link = filter->outputs[i];
-+ avtext_print_section_header(w, NULL, SECTION_ID_OUTPUT);
++ avtext_print_section_header(tfc, NULL, SECTION_ID_OUTPUT);
+
-+ print_str("DestName", link->dst->name);
-+ print_str("DestPadName", avfilter_pad_get_name(link->dstpad, 0));
-+ print_str("SourceName", link->src->name);
++ print_int("output_index", i);
++ print_str("pad_name", avfilter_pad_get_name(link->srcpad, 0));
++ print_str("dest_filter_id", link->dst->name);
++ print_str("dest_pad_name", avfilter_pad_get_name(link->dstpad, 0));
+
-+ print_link(w, link);
++ print_link(tfc, link);
+
-+ avtext_print_section_footer(w); // SECTION_ID_OUTPUT
++ avtext_print_section_footer(tfc); // SECTION_ID_OUTPUT
+ }
+
-+ avtext_print_section_footer(w); // SECTION_ID_OUTPUTS
++ avtext_print_section_footer(tfc); // SECTION_ID_OUTPUTS
+
-+ avtext_print_section_footer(w); // SECTION_ID_FILTER
++ avtext_print_section_footer(tfc); // SECTION_ID_FILTER
+}
+
+static void init_sections(void)
@@ fftools/ffmpeg_graphprint.c (new)
+ sections[i].show_all_entries = 1;
+}
+
-+static void print_filtergraph_single(AVTextFormatContext *w, FilterGraph* fg, AVFilterGraph *graph)
++static void print_filtergraph_single(AVTextFormatContext *tfc, FilterGraph *fg, AVFilterGraph *graph)
+{
-+ char layoutString[64];
+ FilterGraphPriv *fgp = fgp_from_fg(fg);
+
-+ print_int("GraphIndex", fg->index);
-+ print_str("Description", fgp->graph_desc);
++ print_int("graph_index", fg->index);
++ print_str("description", fgp->graph_desc);
+
-+ avtext_print_section_header(w, NULL, SECTION_ID_INPUTS);
++ avtext_print_section_header(tfc, NULL, SECTION_ID_INPUTS);
+
+ for (int i = 0; i < fg->nb_inputs; i++) {
+ InputFilterPriv* ifilter = ifp_from_ifilter(fg->inputs[i]);
-+ enum AVMediaType mediaType = ifilter->type;
-+
-+ avtext_print_section_header(w, NULL, SECTION_ID_INPUT);
-+
-+ print_str("Name1", (char*)ifilter->ifilter.name);
++ enum AVMediaType media_type = ifilter->type;
+
-+ if (ifilter->filter) {
-+ print_str("Name2", ifilter->filter->name);
-+ print_str("Name3", ifilter->filter->filter->name);
-+ print_str("Description", ifilter->filter->filter->description);
-+ }
++ avtext_print_section_header(tfc, NULL, SECTION_ID_INPUT);
+
-+ print_str("MediaType", av_get_media_type_string(mediaType));
-+ print_int("MediaTypeId", mediaType);
++ print_int("input_index", ifilter->index);
+
-+ switch (ifilter->type) {
-+ case AVMEDIA_TYPE_VIDEO:
-+ case AVMEDIA_TYPE_SUBTITLE:
-+ print_str("Format", av_x_if_null(av_get_pix_fmt_name(ifilter->format), "?"));
-+ print_int("Width", ifilter->width);
-+ print_int("Height", ifilter->height);
-+ print_q("SAR", ifilter->sample_aspect_ratio, ':');
-+ break;
-+ case AVMEDIA_TYPE_AUDIO:
++ if (ifilter->linklabel)
++ print_str("link_label", (const char*)ifilter->linklabel);
+
-+ av_channel_layout_describe(&ifilter->ch_layout, layoutString, sizeof(layoutString));
-+ print_str("ChannelString", layoutString);
-+ print_int("SampleRate", ifilter->sample_rate);
-+ break;
-+ case AVMEDIA_TYPE_ATTACHMENT:
-+ case AVMEDIA_TYPE_DATA:
-+ break;
++ if (ifilter->filter) {
++ print_str("filter_id", ifilter->filter->name);
++ print_str("filter_name", ifilter->filter->filter->name);
+ }
+
-+ if (ifilter->hw_frames_ctx)
-+ print_hwframescontext(w, (AVHWFramesContext*)ifilter->hw_frames_ctx->data);
-+ else if (ifilter->filter && ifilter->filter->hw_device_ctx) {
-+ AVHWDeviceContext* devCtx = (AVHWDeviceContext*)ifilter->filter->hw_device_ctx->data;
-+ print_hwdevicecontext(w, devCtx);
-+ }
++ print_str("media_type", av_get_media_type_string(media_type));
+
-+ avtext_print_section_footer(w); // SECTION_ID_INPUT
++ avtext_print_section_footer(tfc); // SECTION_ID_INPUT
+ }
+
-+ avtext_print_section_footer(w); // SECTION_ID_INPUTS
-+
++ avtext_print_section_footer(tfc); // SECTION_ID_INPUTS
+
-+ avtext_print_section_header(w, NULL, SECTION_ID_OUTPUTS);
++ avtext_print_section_header(tfc, NULL, SECTION_ID_OUTPUTS);
+
+ for (int i = 0; i < fg->nb_outputs; i++) {
+ OutputFilterPriv *ofilter = ofp_from_ofilter(fg->outputs[i]);
-+ enum AVMediaType mediaType = AVMEDIA_TYPE_UNKNOWN;
+
-+ avtext_print_section_header(w, NULL, SECTION_ID_OUTPUT);
-+ print_str("Name1", ofilter->name);
++ avtext_print_section_header(tfc, NULL, SECTION_ID_OUTPUT);
+
-+ if (ofilter->filter) {
-+ print_str("Name2", ofilter->filter->name);
-+ print_str("Name3", ofilter->filter->filter->name);
-+ print_str("Description", ofilter->filter->filter->description);
++ print_int("output_index", ofilter->index);
+
-+ if (ofilter->filter->nb_inputs > 0)
-+ mediaType = ofilter->filter->inputs[0]->type;
-+ }
++ print_str("name", ofilter->name);
+
-+ print_str("MediaType", av_get_media_type_string(mediaType));
-+ print_int("MediaTypeId", mediaType);
++ if (fg->outputs[i]->linklabel)
++ print_str("link_label", (const char*)fg->outputs[i]->linklabel);
+
-+ switch (ofilter->ofilter.type) {
-+ case AVMEDIA_TYPE_VIDEO:
-+ case AVMEDIA_TYPE_SUBTITLE:
-+ print_str("Format", av_x_if_null(av_get_pix_fmt_name(ofilter->format), "?"));
-+ print_int("Width", ofilter->width);
-+ print_int("Height", ofilter->height);
-+ break;
-+ case AVMEDIA_TYPE_AUDIO:
-+
-+ av_channel_layout_describe(&ofilter->ch_layout, layoutString, sizeof(layoutString));
-+ print_str("ChannelString", layoutString);
-+ print_int("SampleRate", ofilter->sample_rate);
-+ break;
-+ case AVMEDIA_TYPE_ATTACHMENT:
-+ case AVMEDIA_TYPE_DATA:
-+ break;
++ if (ofilter->filter) {
++ print_str("filter_id", ofilter->filter->name);
++ print_str("filter_name", ofilter->filter->filter->name);
+ }
+
-+ if (ofilter->filter && ofilter->filter->hw_device_ctx) {
-+ AVHWDeviceContext* devCtx = (AVHWDeviceContext*)ofilter->filter->hw_device_ctx->data;
-+ print_hwdevicecontext(w, devCtx);
-+ }
++ print_str("media_type", av_get_media_type_string(fg->outputs[i]->type));
+
-+ avtext_print_section_footer(w); // SECTION_ID_OUTPUT
++ avtext_print_section_footer(tfc); // SECTION_ID_OUTPUT
+ }
+
-+ avtext_print_section_footer(w); // SECTION_ID_OUTPUTS
-+
++ avtext_print_section_footer(tfc); // SECTION_ID_OUTPUTS
+
-+ avtext_print_section_header(w, NULL, SECTION_ID_FILTERS);
++ avtext_print_section_header(tfc, NULL, SECTION_ID_FILTERS);
+
+ if (graph) {
+ for (unsigned i = 0; i < graph->nb_filters; i++) {
+ AVFilterContext *filter = graph->filters[i];
-+ avtext_print_section_header(w, NULL, SECTION_ID_FILTER);
++ avtext_print_section_header(tfc, NULL, SECTION_ID_FILTER);
+
-+ print_filter(w, filter);
++ print_filter(tfc, filter);
+
-+ avtext_print_section_footer(w); // SECTION_ID_FILTER
++ avtext_print_section_footer(tfc); // SECTION_ID_FILTER
+ }
+ }
+
-+ avtext_print_section_footer(w); // SECTION_ID_FILTERS
++ avtext_print_section_footer(tfc); // SECTION_ID_FILTERS
+}
+
+int print_filtergraph(FilterGraph *fg, AVFilterGraph *graph)
@@ fftools/ffmpeg_graphprint.c (new)
+ }
+
+ text_formatter = avtext_get_formatter_by_name(w_name);
-+ if (text_formatter == NULL) {
-+ av_log(NULL, AV_LOG_ERROR, "Unknown filter graph output format with name '%s'\n", w_name);
++ if (!text_formatter ) {
++ av_log(NULL, AV_LOG_ERROR, "Unknown filter graph output format with name '%s'\n", w_name);
+ return AVERROR(EINVAL);
+ }
+
@@ fftools/ffmpeg_graphprint.c (new)
+ }
+
+ if ((ret = avtext_context_open(&tctx, text_formatter, wctx, w_args, sections, FF_ARRAY_ELEMS(sections), 0, 0, 0, 0, -1, NULL)) >= 0) {
++
++ // Due to the threading model each graph needs to print itself into a buffer
++ // from its own thread. The actual printing happens short before cleanup in ffmpeg.c
++ // where all grahps are assembled together. To make this work, we need to put the
++ // formatting context into the same state like it would be when printing all at once,
++ // so here we print the section headers and clear the buffer to get into the right state.
+ avtext_print_section_header(tctx, NULL, SECTION_ID_ROOT);
+ avtext_print_section_header(tctx, NULL, SECTION_ID_FILTERGRAPHS);
+ avtext_print_section_header(tctx, NULL, SECTION_ID_FILTERGRAPH);
@@ fftools/ffmpeg_graphprint.c (new)
+ w_args = buf;
+
+ text_formatter = avtext_get_formatter_by_name(w_name);
-+ if (text_formatter == NULL) {
-+ av_log(NULL, AV_LOG_ERROR, "Unknown filter graph output format with name '%s'\n", w_name);
++ if (!text_formatter) {
++ av_log(NULL, AV_LOG_ERROR, "Unknown filter graph output format with name '%s'\n", w_name);
+ return AVERROR(EINVAL);
+ }
+
@@ fftools/ffmpeg_graphprint.c (new)
+ ret = avtextwriter_create_buffer(&wctx, &target_buf);
+ if (ret < 0) {
+ av_log(NULL, AV_LOG_ERROR, "avtextwriter_create_buffer failed. Error code %d\n", ret);
-+ return AVERROR(EINVAL);
++ return ret;
+ }
+
+ if ((ret = avtext_context_open(&tctx, text_formatter, wctx, w_args, sections, FF_ARRAY_ELEMS(sections), 0, 0, 0, 0, -1, NULL)) >= 0) {
@@ fftools/ffmpeg_graphprint.c (new)
+ if (print_graphs_file) {
+ AVIOContext *avio = NULL;
+
-+ ret = avio_open2(&avio, print_graphs_file, AVIO_FLAG_WRITE, NULL, NULL);
-+ if (ret < 0) {
-+ av_log(NULL, AV_LOG_ERROR, "Failed to open graph output file, \"%s\": %s\n",
-+ print_graphs_file, av_err2str(ret));
-+ return ret;
-+ }
++ if (!strcmp(print_graphs_file, "-")) {
++ printf("%s", target_buf.str);
++ } else {
++ ret = avio_open2(&avio, print_graphs_file, AVIO_FLAG_WRITE, NULL, NULL);
++ if (ret < 0) {
++ av_log(NULL, AV_LOG_ERROR, "Failed to open graph output file, \"%s\": %s\n",
++ print_graphs_file, av_err2str(ret));
++ return ret;
++ }
+
-+ avio_write(avio, (const unsigned char*)target_buf.str, FFMIN(target_buf.len, target_buf.size - 1));
-+ avio_flush(avio);
++ avio_write(avio, (const unsigned char*)target_buf.str, FFMIN(target_buf.len, target_buf.size - 1));
++ avio_flush(avio);
+
-+ if ((ret = avio_closep(&avio)) < 0)
-+ av_log(NULL, AV_LOG_ERROR, "Error closing graph output file, loss of information possible: %s\n", av_err2str(ret));
++ if ((ret = avio_closep(&avio)) < 0)
++ av_log(NULL, AV_LOG_ERROR, "Error closing graph output file, loss of information possible: %s\n", av_err2str(ret));
++ }
+ }
+
-+ if (print_graphs) {
-+ printf("%s", target_buf.str);
++ if (print_graphs)
+ av_log(NULL, AV_LOG_INFO, "%s %c", target_buf.str, '\n');
-+ }
+
+ avtext_context_close(&tctx);
+ avtextwriter_context_close(&wctx);
@@ fftools/ffmpeg_opt.c: float max_error_rate = 2.0/3;
int filter_complex_nbthreads = 0;
int vstats_version = 2;
+int print_graphs = 0;
-+char* print_graphs_file = NULL;
-+char* print_graphs_format = NULL;
++char *print_graphs_file = NULL;
++char *print_graphs_format = NULL;
int auto_conversion_filters = 1;
int64_t stats_period = 500000;
@@ fftools/ffmpeg_opt.c: const OptionDef options[] = {
#endif
+ { "print_graphs", OPT_TYPE_BOOL, 0,
+ { &print_graphs },
-+ "prints filtergraph details to stderr" },
++ "print filtergraph details to stderr" },
+ { "print_graphs_file", OPT_TYPE_STRING, 0,
+ { &print_graphs_file },
-+ "writes graph details to a file", "filename" },
++ "write graph details to a file", "filename" },
+ { "print_graphs_format", OPT_TYPE_STRING, 0,
+ { &print_graphs_format },
+ "set the output printing format (available formats are: default, compact, csv, flat, ini, json, xml)", "format" },
{ "auto_conversion_filters", OPT_TYPE_BOOL, OPT_EXPERT,
{ &auto_conversion_filters },
"enable automatic conversion filters globally" },
+
+ ## fftools/textformat/avtextformat.c ##
+@@ fftools/textformat/avtextformat.c: static char *value_string(AVTextFormatContext *tctx, char *buf, int buf_size, st
+ vali = vald;
+ }
+
+- if (show_float || (tctx->use_value_prefix && vald != (int64_t)vald))
++ if (show_float || (tctx->use_value_prefix && vald != (int64_t)vald)) {
+ snprintf(buf, buf_size, "%f", vald);
+- else
++ } else {
+ snprintf(buf, buf_size, "%"PRId64, vali);
++ }
++
+ av_strlcatf(buf, buf_size, "%s%s%s", *prefix_string || tctx->show_value_unit ? " " : "",
+ prefix_string, tctx->show_value_unit ? uv.unit : "");
+ }
+
+ ## fftools/textformat/avtextformat.h ##
+@@ fftools/textformat/avtextformat.h: typedef struct AVTextFormatter {
+ #define SECTION_MAX_NB_SECTIONS 100
+
+ struct AVTextFormatContext {
+- const AVClass *class; ///< class of the formatter
+- const AVTextFormatter *formatter; ///< the AVTextFormatter of which this is an instance
+- AVTextWriterContext *writer; ///< the AVTextWriterContext
++ const AVClass *class; ///< class of the formatter
++ const AVTextFormatter *formatter; ///< the AVTextFormatter of which this is an instance
++ AVTextWriterContext *writer; ///< the AVTextWriterContext
+
+- char *name; ///< name of this formatter instance
+- void *priv; ///< private data for use by the filter
++ char *name; ///< name of this formatter instance
++ void *priv; ///< private data for use by the filter
+
+ const struct AVTextFormatSection *sections; ///< array containing all sections
+- int nb_sections; ///< number of sections
++ int nb_sections; ///< number of sections
+
+- int level; ///< current level, starting from 0
++ int level; ///< current level, starting from 0
+
+ /** number of the item printed in the given section, starting from 0 */
+ unsigned int nb_item[SECTION_MAX_NB_LEVELS];
+@@ fftools/textformat/avtextformat.h: void avtext_print_data(AVTextFormatContext *tctx, const char *name, const uint8_
+
+ void avtext_print_data_hash(AVTextFormatContext *tctx, const char *name, const uint8_t *data, int size);
+
+-void avtext_print_integers(AVTextFormatContext *tctx, const char *name, uint8_t *data, int size,
++void avtext_print_integers(AVTextFormatContext *tctx, const char *name, uint8_t *data, int size,
+ const char *format, int columns, int bytes, int offset_add);
+
+ const AVTextFormatter *avtext_get_formatter_by_name(const char *name);
7: 03663768dd < -: ---------- fftools: Enable filtergraph printing and update docs
8: 0caab91adc = 7: fcfcc5f7df fftools/ffprobe: Rename AVTextFormatContext variables (w => tfc)
--
ffmpeg-codebot
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 108+ messages in thread
* [FFmpeg-devel] [PATCH v7 1/7] fftools/textformat: Extract and generalize textformat api from ffprobe.c
2025-03-12 4:04 ` [FFmpeg-devel] [PATCH v7 0/7] " ffmpegagent
@ 2025-03-12 4:04 ` softworkz
2025-03-12 4:04 ` [FFmpeg-devel] [PATCH v7 2/7] fftools/ffprobe: Change to use textformat api softworkz
` (6 subsequent siblings)
7 siblings, 0 replies; 108+ messages in thread
From: softworkz @ 2025-03-12 4:04 UTC (permalink / raw)
To: ffmpeg-devel; +Cc: softworkz
From: softworkz <softworkz@hotmail.com>
Signed-off-by: softworkz <softworkz@hotmail.com>
---
fftools/textformat/avtextformat.c | 672 +++++++++++++++++++++++++++++
fftools/textformat/avtextformat.h | 171 ++++++++
fftools/textformat/avtextwriters.h | 68 +++
fftools/textformat/tf_compact.c | 282 ++++++++++++
fftools/textformat/tf_default.c | 145 +++++++
fftools/textformat/tf_flat.c | 174 ++++++++
fftools/textformat/tf_ini.c | 160 +++++++
fftools/textformat/tf_json.c | 215 +++++++++
fftools/textformat/tf_xml.c | 221 ++++++++++
fftools/textformat/tw_avio.c | 129 ++++++
fftools/textformat/tw_buffer.c | 92 ++++
fftools/textformat/tw_stdout.c | 82 ++++
12 files changed, 2411 insertions(+)
create mode 100644 fftools/textformat/avtextformat.c
create mode 100644 fftools/textformat/avtextformat.h
create mode 100644 fftools/textformat/avtextwriters.h
create mode 100644 fftools/textformat/tf_compact.c
create mode 100644 fftools/textformat/tf_default.c
create mode 100644 fftools/textformat/tf_flat.c
create mode 100644 fftools/textformat/tf_ini.c
create mode 100644 fftools/textformat/tf_json.c
create mode 100644 fftools/textformat/tf_xml.c
create mode 100644 fftools/textformat/tw_avio.c
create mode 100644 fftools/textformat/tw_buffer.c
create mode 100644 fftools/textformat/tw_stdout.c
diff --git a/fftools/textformat/avtextformat.c b/fftools/textformat/avtextformat.c
new file mode 100644
index 0000000000..6c09f9d2cd
--- /dev/null
+++ b/fftools/textformat/avtextformat.c
@@ -0,0 +1,672 @@
+/*
+ * Copyright (c) The FFmpeg developers
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <limits.h>
+#include <stdarg.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "libavutil/mem.h"
+#include "libavutil/avassert.h"
+#include "libavutil/bprint.h"
+#include "libavutil/error.h"
+#include "libavutil/hash.h"
+#include "libavutil/intreadwrite.h"
+#include "libavutil/macros.h"
+#include "libavutil/opt.h"
+#include "avtextformat.h"
+
+#define SECTION_ID_NONE -1
+
+#define SHOW_OPTIONAL_FIELDS_AUTO -1
+#define SHOW_OPTIONAL_FIELDS_NEVER 0
+#define SHOW_OPTIONAL_FIELDS_ALWAYS 1
+
+static const struct {
+ double bin_val;
+ double dec_val;
+ const char *bin_str;
+ const char *dec_str;
+} si_prefixes[] = {
+ { 1.0, 1.0, "", "" },
+ { 1.024e3, 1e3, "Ki", "K" },
+ { 1.048576e6, 1e6, "Mi", "M" },
+ { 1.073741824e9, 1e9, "Gi", "G" },
+ { 1.099511627776e12, 1e12, "Ti", "T" },
+ { 1.125899906842624e15, 1e15, "Pi", "P" },
+};
+
+static const char *textcontext_get_formatter_name(void *p)
+{
+ AVTextFormatContext *tctx = p;
+ return tctx->formatter->name;
+}
+
+#define OFFSET(x) offsetof(AVTextFormatContext, x)
+
+static const AVOption textcontext_options[] = {
+ { "string_validation", "set string validation mode",
+ OFFSET(string_validation), AV_OPT_TYPE_INT, {.i64=AV_TEXTFORMAT_STRING_VALIDATION_REPLACE}, 0, AV_TEXTFORMAT_STRING_VALIDATION_NB-1, .unit = "sv" },
+ { "sv", "set string validation mode",
+ OFFSET(string_validation), AV_OPT_TYPE_INT, {.i64=AV_TEXTFORMAT_STRING_VALIDATION_REPLACE}, 0, AV_TEXTFORMAT_STRING_VALIDATION_NB-1, .unit = "sv" },
+ { "ignore", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = AV_TEXTFORMAT_STRING_VALIDATION_IGNORE}, .unit = "sv" },
+ { "replace", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = AV_TEXTFORMAT_STRING_VALIDATION_REPLACE}, .unit = "sv" },
+ { "fail", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = AV_TEXTFORMAT_STRING_VALIDATION_FAIL}, .unit = "sv" },
+ { "string_validation_replacement", "set string validation replacement string", OFFSET(string_validation_replacement), AV_OPT_TYPE_STRING, {.str=""}},
+ { "svr", "set string validation replacement string", OFFSET(string_validation_replacement), AV_OPT_TYPE_STRING, {.str="\xEF\xBF\xBD"}},
+ { NULL }
+};
+
+static void *textcontext_child_next(void *obj, void *prev)
+{
+ AVTextFormatContext *ctx = obj;
+ if (!prev && ctx->formatter && ctx->formatter->priv_class && ctx->priv)
+ return ctx->priv;
+ return NULL;
+}
+
+static const AVClass textcontext_class = {
+ .class_name = "AVTextContext",
+ .item_name = textcontext_get_formatter_name,
+ .option = textcontext_options,
+ .version = LIBAVUTIL_VERSION_INT,
+ .child_next = textcontext_child_next,
+};
+
+static void bprint_bytes(AVBPrint *bp, const uint8_t *ubuf, size_t ubuf_size)
+{
+ int i;
+ av_bprintf(bp, "0X");
+ for (i = 0; i < ubuf_size; i++)
+ av_bprintf(bp, "%02X", ubuf[i]);
+}
+
+int avtext_context_close(AVTextFormatContext **ptctx)
+{
+ AVTextFormatContext *tctx = *ptctx;
+ int i;
+ int ret = 0;
+
+ if (!tctx)
+ return EINVAL;
+
+ av_hash_freep(&tctx->hash);
+
+ av_hash_freep(&tctx->hash);
+
+ if (tctx->formatter->uninit)
+ tctx->formatter->uninit(tctx);
+ for (i = 0; i < SECTION_MAX_NB_LEVELS; i++)
+ av_bprint_finalize(&tctx->section_pbuf[i], NULL);
+ if (tctx->formatter->priv_class)
+ av_opt_free(tctx->priv);
+ av_freep(&tctx->priv);
+ av_opt_free(tctx);
+ av_freep(ptctx);
+ return ret;
+}
+
+
+int avtext_context_open(AVTextFormatContext **ptctx, const AVTextFormatter *formatter, AVTextWriterContext *writer_context, const char *args,
+ const struct AVTextFormatSection *sections, int nb_sections,
+ int show_value_unit,
+ int use_value_prefix,
+ int use_byte_value_binary_prefix,
+ int use_value_sexagesimal_format,
+ int show_optional_fields,
+ char *show_data_hash)
+{
+ AVTextFormatContext *tctx;
+ int i, ret = 0;
+
+ if (!(tctx = av_mallocz(sizeof(AVTextFormatContext)))) {
+ ret = AVERROR(ENOMEM);
+ goto fail;
+ }
+
+ if (!(tctx->priv = av_mallocz(formatter->priv_size))) {
+ ret = AVERROR(ENOMEM);
+ goto fail;
+ }
+
+ tctx->show_value_unit = show_value_unit;
+ tctx->use_value_prefix = use_value_prefix;
+ tctx->use_byte_value_binary_prefix = use_byte_value_binary_prefix;
+ tctx->use_value_sexagesimal_format = use_value_sexagesimal_format;
+ tctx->show_optional_fields = show_optional_fields;
+
+ if (nb_sections > SECTION_MAX_NB_SECTIONS) {
+ 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);
+ ret = AVERROR(EINVAL);
+ goto fail;
+ }
+
+ tctx->class = &textcontext_class;
+ tctx->formatter = formatter;
+ tctx->level = -1;
+ tctx->sections = sections;
+ tctx->nb_sections = nb_sections;
+ tctx->writer = writer_context;
+
+ av_opt_set_defaults(tctx);
+
+ if (formatter->priv_class) {
+ void *priv_ctx = tctx->priv;
+ *(const AVClass **)priv_ctx = formatter->priv_class;
+ av_opt_set_defaults(priv_ctx);
+ }
+
+ /* convert options to dictionary */
+ if (args) {
+ AVDictionary *opts = NULL;
+ const AVDictionaryEntry *opt = NULL;
+
+ if ((ret = av_dict_parse_string(&opts, args, "=", ":", 0)) < 0) {
+ av_log(tctx, AV_LOG_ERROR, "Failed to parse option string '%s' provided to textformat context\n", args);
+ av_dict_free(&opts);
+ goto fail;
+ }
+
+ while ((opt = av_dict_iterate(opts, opt))) {
+ if ((ret = av_opt_set(tctx, opt->key, opt->value, AV_OPT_SEARCH_CHILDREN)) < 0) {
+ av_log(tctx, AV_LOG_ERROR, "Failed to set option '%s' with value '%s' provided to textformat context\n",
+ opt->key, opt->value);
+ av_dict_free(&opts);
+ goto fail;
+ }
+ }
+
+ av_dict_free(&opts);
+ }
+
+ if (show_data_hash) {
+ if ((ret = av_hash_alloc(&tctx->hash, show_data_hash)) < 0) {
+ if (ret == AVERROR(EINVAL)) {
+ const char *n;
+ av_log(NULL, AV_LOG_ERROR, "Unknown hash algorithm '%s'\nKnown algorithms:", show_data_hash);
+ for (i = 0; (n = av_hash_names(i)); i++)
+ av_log(NULL, AV_LOG_ERROR, " %s", n);
+ av_log(NULL, AV_LOG_ERROR, "\n");
+ }
+ return ret;
+ }
+ }
+
+ /* validate replace string */
+ {
+ const uint8_t *p = tctx->string_validation_replacement;
+ const uint8_t *endp = p + strlen(p);
+ while (*p) {
+ const uint8_t *p0 = p;
+ int32_t code;
+ ret = av_utf8_decode(&code, &p, endp, tctx->string_validation_utf8_flags);
+ if (ret < 0) {
+ AVBPrint bp;
+ av_bprint_init(&bp, 0, AV_BPRINT_SIZE_AUTOMATIC);
+ bprint_bytes(&bp, p0, p-p0),
+ av_log(tctx, AV_LOG_ERROR,
+ "Invalid UTF8 sequence %s found in string validation replace '%s'\n",
+ bp.str, tctx->string_validation_replacement);
+ return ret;
+ }
+ }
+ }
+
+ for (i = 0; i < SECTION_MAX_NB_LEVELS; i++)
+ av_bprint_init(&tctx->section_pbuf[i], 1, AV_BPRINT_SIZE_UNLIMITED);
+
+ if (tctx->formatter->init)
+ ret = tctx->formatter->init(tctx);
+ if (ret < 0)
+ goto fail;
+
+ *ptctx = tctx;
+
+ return 0;
+
+fail:
+ avtext_context_close(&tctx);
+ return ret;
+}
+
+/* Temporary definitions during refactoring */
+static const char unit_second_str[] = "s" ;
+static const char unit_hertz_str[] = "Hz" ;
+static const char unit_byte_str[] = "byte" ;
+static const char unit_bit_per_second_str[] = "bit/s";
+
+
+void avtext_print_section_header(AVTextFormatContext *tctx,
+ const void *data,
+ int section_id)
+{
+ tctx->level++;
+ av_assert0(tctx->level < SECTION_MAX_NB_LEVELS);
+
+ tctx->nb_item[tctx->level] = 0;
+ memset(tctx->nb_item_type[tctx->level], 0, sizeof(tctx->nb_item_type[tctx->level]));
+ tctx->section[tctx->level] = &tctx->sections[section_id];
+
+ if (tctx->formatter->print_section_header)
+ tctx->formatter->print_section_header(tctx, data);
+}
+
+void avtext_print_section_footer(AVTextFormatContext *tctx)
+{
+ int section_id = tctx->section[tctx->level]->id;
+ int parent_section_id = tctx->level ?
+ tctx->section[tctx->level-1]->id : SECTION_ID_NONE;
+
+ if (parent_section_id != SECTION_ID_NONE) {
+ tctx->nb_item[tctx->level - 1]++;
+ tctx->nb_item_type[tctx->level - 1][section_id]++;
+ }
+
+ if (tctx->formatter->print_section_footer)
+ tctx->formatter->print_section_footer(tctx);
+ tctx->level--;
+}
+
+void avtext_print_integer(AVTextFormatContext *tctx,
+ const char *key, int64_t val)
+{
+ const struct AVTextFormatSection *section = tctx->section[tctx->level];
+
+ if (section->show_all_entries || av_dict_get(section->entries_to_show, key, NULL, 0)) {
+ tctx->formatter->print_integer(tctx, key, val);
+ tctx->nb_item[tctx->level]++;
+ }
+}
+
+static inline int validate_string(AVTextFormatContext *tctx, char **dstp, const char *src)
+{
+ const uint8_t *p, *endp;
+ AVBPrint dstbuf;
+ int invalid_chars_nb = 0, ret = 0;
+
+ av_bprint_init(&dstbuf, 0, AV_BPRINT_SIZE_UNLIMITED);
+
+ endp = src + strlen(src);
+ for (p = src; *p;) {
+ uint32_t code;
+ int invalid = 0;
+ const uint8_t *p0 = p;
+
+ if (av_utf8_decode(&code, &p, endp, tctx->string_validation_utf8_flags) < 0) {
+ AVBPrint bp;
+ av_bprint_init(&bp, 0, AV_BPRINT_SIZE_AUTOMATIC);
+ bprint_bytes(&bp, p0, p-p0);
+ av_log(tctx, AV_LOG_DEBUG,
+ "Invalid UTF-8 sequence %s found in string '%s'\n", bp.str, src);
+ invalid = 1;
+ }
+
+ if (invalid) {
+ invalid_chars_nb++;
+
+ switch (tctx->string_validation) {
+ case AV_TEXTFORMAT_STRING_VALIDATION_FAIL:
+ av_log(tctx, AV_LOG_ERROR,
+ "Invalid UTF-8 sequence found in string '%s'\n", src);
+ ret = AVERROR_INVALIDDATA;
+ goto end;
+ break;
+
+ case AV_TEXTFORMAT_STRING_VALIDATION_REPLACE:
+ av_bprintf(&dstbuf, "%s", tctx->string_validation_replacement);
+ break;
+ }
+ }
+
+ if (!invalid || tctx->string_validation == AV_TEXTFORMAT_STRING_VALIDATION_IGNORE)
+ av_bprint_append_data(&dstbuf, p0, p-p0);
+ }
+
+ if (invalid_chars_nb && tctx->string_validation == AV_TEXTFORMAT_STRING_VALIDATION_REPLACE) {
+ av_log(tctx, AV_LOG_WARNING,
+ "%d invalid UTF-8 sequence(s) found in string '%s', replaced with '%s'\n",
+ invalid_chars_nb, src, tctx->string_validation_replacement);
+ }
+
+end:
+ av_bprint_finalize(&dstbuf, dstp);
+ return ret;
+}
+
+struct unit_value {
+ union { double d; int64_t i; } val;
+ const char *unit;
+};
+
+static char *value_string(AVTextFormatContext *tctx, char *buf, int buf_size, struct unit_value uv)
+{
+ double vald;
+ int64_t vali;
+ int show_float = 0;
+
+ if (uv.unit == unit_second_str) {
+ vald = uv.val.d;
+ show_float = 1;
+ } else {
+ vald = vali = uv.val.i;
+ }
+
+ if (uv.unit == unit_second_str && tctx->use_value_sexagesimal_format) {
+ double secs;
+ int hours, mins;
+ secs = vald;
+ mins = (int)secs / 60;
+ secs = secs - mins * 60;
+ hours = mins / 60;
+ mins %= 60;
+ snprintf(buf, buf_size, "%d:%02d:%09.6f", hours, mins, secs);
+ } else {
+ const char *prefix_string = "";
+
+ if (tctx->use_value_prefix && vald > 1) {
+ int64_t index;
+
+ if (uv.unit == unit_byte_str && tctx->use_byte_value_binary_prefix) {
+ index = (int64_t) (log2(vald)) / 10;
+ index = av_clip(index, 0, FF_ARRAY_ELEMS(si_prefixes) - 1);
+ vald /= si_prefixes[index].bin_val;
+ prefix_string = si_prefixes[index].bin_str;
+ } else {
+ index = (int64_t) (log10(vald)) / 3;
+ index = av_clip(index, 0, FF_ARRAY_ELEMS(si_prefixes) - 1);
+ vald /= si_prefixes[index].dec_val;
+ prefix_string = si_prefixes[index].dec_str;
+ }
+ vali = vald;
+ }
+
+ if (show_float || (tctx->use_value_prefix && vald != (int64_t)vald))
+ snprintf(buf, buf_size, "%f", vald);
+ else
+ snprintf(buf, buf_size, "%"PRId64, vali);
+ av_strlcatf(buf, buf_size, "%s%s%s", *prefix_string || tctx->show_value_unit ? " " : "",
+ prefix_string, tctx->show_value_unit ? uv.unit : "");
+ }
+
+ return buf;
+}
+
+
+void avtext_print_unit_int(AVTextFormatContext *tctx, const char *key, int value, const char *unit)
+{
+ char val_str[128];
+ struct unit_value uv;
+ uv.val.i = value;
+ uv.unit = unit;
+ avtext_print_string(tctx, key, value_string(tctx, val_str, sizeof(val_str), uv), 0);
+}
+
+
+int avtext_print_string(AVTextFormatContext *tctx, const char *key, const char *val, int flags)
+{
+ const struct AVTextFormatSection *section = tctx->section[tctx->level];
+ int ret = 0;
+
+ if (tctx->show_optional_fields == SHOW_OPTIONAL_FIELDS_NEVER ||
+ (tctx->show_optional_fields == SHOW_OPTIONAL_FIELDS_AUTO
+ && (flags & AV_TEXTFORMAT_PRINT_STRING_OPTIONAL)
+ && !(tctx->formatter->flags & AV_TEXTFORMAT_FLAG_SUPPORTS_OPTIONAL_FIELDS)))
+ return 0;
+
+ if (section->show_all_entries || av_dict_get(section->entries_to_show, key, NULL, 0)) {
+ if (flags & AV_TEXTFORMAT_PRINT_STRING_VALIDATE) {
+ char *key1 = NULL, *val1 = NULL;
+ ret = validate_string(tctx, &key1, key);
+ if (ret < 0) goto end;
+ ret = validate_string(tctx, &val1, val);
+ if (ret < 0) goto end;
+ tctx->formatter->print_string(tctx, key1, val1);
+ end:
+ if (ret < 0) {
+ av_log(tctx, AV_LOG_ERROR,
+ "Invalid key=value string combination %s=%s in section %s\n",
+ key, val, section->unique_name);
+ }
+ av_free(key1);
+ av_free(val1);
+ } else {
+ tctx->formatter->print_string(tctx, key, val);
+ }
+
+ tctx->nb_item[tctx->level]++;
+ }
+
+ return ret;
+}
+
+void avtext_print_rational(AVTextFormatContext *tctx,
+ const char *key, AVRational q, char sep)
+{
+ AVBPrint buf;
+ av_bprint_init(&buf, 0, AV_BPRINT_SIZE_AUTOMATIC);
+ av_bprintf(&buf, "%d%c%d", q.num, sep, q.den);
+ avtext_print_string(tctx, key, buf.str, 0);
+}
+
+void avtext_print_time(AVTextFormatContext *tctx, const char *key,
+ int64_t ts, const AVRational *time_base, int is_duration)
+{
+ char buf[128];
+
+ if ((!is_duration && ts == AV_NOPTS_VALUE) || (is_duration && ts == 0)) {
+ avtext_print_string(tctx, key, "N/A", AV_TEXTFORMAT_PRINT_STRING_OPTIONAL);
+ } else {
+ double d = ts * av_q2d(*time_base);
+ struct unit_value uv;
+ uv.val.d = d;
+ uv.unit = unit_second_str;
+ value_string(tctx, buf, sizeof(buf), uv);
+ avtext_print_string(tctx, key, buf, 0);
+ }
+}
+
+void avtext_print_ts(AVTextFormatContext *tctx, const char *key, int64_t ts, int is_duration)
+{
+ if ((!is_duration && ts == AV_NOPTS_VALUE) || (is_duration && ts == 0)) {
+ avtext_print_string(tctx, key, "N/A", AV_TEXTFORMAT_PRINT_STRING_OPTIONAL);
+ } else {
+ avtext_print_integer(tctx, key, ts);
+ }
+}
+
+void avtext_print_data(AVTextFormatContext *tctx, const char *name,
+ const uint8_t *data, int size)
+{
+ AVBPrint bp;
+ int offset = 0, l, i;
+
+ av_bprint_init(&bp, 0, AV_BPRINT_SIZE_UNLIMITED);
+ av_bprintf(&bp, "\n");
+ while (size) {
+ av_bprintf(&bp, "%08x: ", offset);
+ l = FFMIN(size, 16);
+ for (i = 0; i < l; i++) {
+ av_bprintf(&bp, "%02x", data[i]);
+ if (i & 1)
+ av_bprintf(&bp, " ");
+ }
+ av_bprint_chars(&bp, ' ', 41 - 2 * i - i / 2);
+ for (i = 0; i < l; i++)
+ av_bprint_chars(&bp, data[i] - 32U < 95 ? data[i] : '.', 1);
+ av_bprintf(&bp, "\n");
+ offset += l;
+ data += l;
+ size -= l;
+ }
+ avtext_print_string(tctx, name, bp.str, 0);
+ av_bprint_finalize(&bp, NULL);
+}
+
+void avtext_print_data_hash(AVTextFormatContext *tctx, const char *name,
+ const uint8_t *data, int size)
+{
+ char *p, buf[AV_HASH_MAX_SIZE * 2 + 64] = { 0 };
+
+ if (!tctx->hash)
+ return;
+ av_hash_init(tctx->hash);
+ av_hash_update(tctx->hash, data, size);
+ snprintf(buf, sizeof(buf), "%s:", av_hash_get_name(tctx->hash));
+ p = buf + strlen(buf);
+ av_hash_final_hex(tctx->hash, p, buf + sizeof(buf) - p);
+ avtext_print_string(tctx, name, buf, 0);
+}
+
+void avtext_print_integers(AVTextFormatContext *tctx, const char *name,
+ uint8_t *data, int size, const char *format,
+ int columns, int bytes, int offset_add)
+{
+ AVBPrint bp;
+ int offset = 0, l, i;
+
+ av_bprint_init(&bp, 0, AV_BPRINT_SIZE_UNLIMITED);
+ av_bprintf(&bp, "\n");
+ while (size) {
+ av_bprintf(&bp, "%08x: ", offset);
+ l = FFMIN(size, columns);
+ for (i = 0; i < l; i++) {
+ if (bytes == 1) av_bprintf(&bp, format, *data);
+ else if (bytes == 2) av_bprintf(&bp, format, AV_RN16(data));
+ else if (bytes == 4) av_bprintf(&bp, format, AV_RN32(data));
+ data += bytes;
+ size --;
+ }
+ av_bprintf(&bp, "\n");
+ offset += offset_add;
+ }
+ avtext_print_string(tctx, name, bp.str, 0);
+ av_bprint_finalize(&bp, NULL);
+}
+
+static const char *writercontext_get_writer_name(void *p)
+{
+ AVTextWriterContext *wctx = p;
+ return wctx->writer->name;
+}
+
+static void *writercontext_child_next(void *obj, void *prev)
+{
+ AVTextFormatContext *ctx = obj;
+ if (!prev && ctx->formatter && ctx->formatter->priv_class && ctx->priv)
+ return ctx->priv;
+ return NULL;
+}
+
+static const AVClass textwriter_class = {
+ .class_name = "AVTextWriterContext",
+ .item_name = writercontext_get_writer_name,
+ .version = LIBAVUTIL_VERSION_INT,
+ .child_next = writercontext_child_next,
+};
+
+
+int avtextwriter_context_close(AVTextWriterContext **pwctx)
+{
+ AVTextWriterContext *wctx = *pwctx;
+ int ret = 0;
+
+ if (!wctx)
+ return EINVAL;
+
+ if (wctx->writer->uninit)
+ wctx->writer->uninit(wctx);
+ if (wctx->writer->priv_class)
+ av_opt_free(wctx->priv);
+ av_freep(&wctx->priv);
+ av_freep(pwctx);
+ return ret;
+}
+
+
+int avtextwriter_context_open(AVTextWriterContext **pwctx, const AVTextWriter *writer)
+{
+ AVTextWriterContext *wctx;
+ int ret = 0;
+
+ if (!(wctx = av_mallocz(sizeof(AVTextWriterContext)))) {
+ ret = AVERROR(ENOMEM);
+ goto fail;
+ }
+
+ if (!(wctx->priv = av_mallocz(writer->priv_size))) {
+ ret = AVERROR(ENOMEM);
+ goto fail;
+ }
+
+ if (writer->priv_class) {
+ void *priv_ctx = wctx->priv;
+ *(const AVClass **)priv_ctx = writer->priv_class;
+ av_opt_set_defaults(priv_ctx);
+ }
+
+ wctx->class = &textwriter_class;
+ wctx->writer = writer;
+
+ av_opt_set_defaults(wctx);
+
+
+ if (wctx->writer->init)
+ ret = wctx->writer->init(wctx);
+ if (ret < 0)
+ goto fail;
+
+ *pwctx = wctx;
+
+ return 0;
+
+fail:
+ avtextwriter_context_close(&wctx);
+ return ret;
+}
+
+static const AVTextFormatter *registered_formatters[7+1];
+static void formatters_register_all(void)
+{
+ static int initialized;
+
+ if (initialized)
+ return;
+ initialized = 1;
+
+ registered_formatters[0] = &avtextformatter_default;
+ registered_formatters[1] = &avtextformatter_compact;
+ registered_formatters[2] = &avtextformatter_csv;
+ registered_formatters[3] = &avtextformatter_flat;
+ registered_formatters[4] = &avtextformatter_ini;
+ registered_formatters[5] = &avtextformatter_json;
+ registered_formatters[6] = &avtextformatter_xml;
+}
+
+const AVTextFormatter *avtext_get_formatter_by_name(const char *name)
+{
+ formatters_register_all();
+
+ for (int i = 0; registered_formatters[i]; i++)
+ if (!strcmp(registered_formatters[i]->name, name))
+ return registered_formatters[i];
+
+ return NULL;
+}
diff --git a/fftools/textformat/avtextformat.h b/fftools/textformat/avtextformat.h
new file mode 100644
index 0000000000..4689499246
--- /dev/null
+++ b/fftools/textformat/avtextformat.h
@@ -0,0 +1,171 @@
+/*
+ * Copyright (c) The FFmpeg developers
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef FFTOOLS_TEXTFORMAT_AVTEXTFORMAT_H
+#define FFTOOLS_TEXTFORMAT_AVTEXTFORMAT_H
+
+#include <stddef.h>
+#include <stdint.h>
+#include "libavutil/attributes.h"
+#include "libavutil/dict.h"
+#include "libavformat/avio.h"
+#include "libavutil/bprint.h"
+#include "libavutil/rational.h"
+#include "libavutil/hash.h"
+#include "avtextwriters.h"
+
+#define SECTION_MAX_NB_CHILDREN 11
+
+
+struct AVTextFormatSection {
+ int id; ///< unique id identifying a section
+ const char *name;
+
+#define AV_TEXTFORMAT_SECTION_FLAG_IS_WRAPPER 1 ///< the section only contains other sections, but has no data at its own level
+#define AV_TEXTFORMAT_SECTION_FLAG_IS_ARRAY 2 ///< the section contains an array of elements of the same type
+#define AV_TEXTFORMAT_SECTION_FLAG_HAS_VARIABLE_FIELDS 4 ///< the section may contain a variable number of fields with variable keys.
+ /// For these sections the element_name field is mandatory.
+#define AV_TEXTFORMAT_SECTION_FLAG_HAS_TYPE 8 ///< the section contains a type to distinguish multiple nested elements
+#define AV_TEXTFORMAT_SECTION_FLAG_NUMBERING_BY_TYPE 16 ///< the items in this array section should be numbered individually by type
+
+ int flags;
+ const int children_ids[SECTION_MAX_NB_CHILDREN+1]; ///< list of children section IDS, terminated by -1
+ const char *element_name; ///< name of the contained element, if provided
+ const char *unique_name; ///< unique section name, in case the name is ambiguous
+ AVDictionary *entries_to_show;
+ const char *(* get_type)(const void *data); ///< function returning a type if defined, must be defined when SECTION_FLAG_HAS_TYPE is defined
+ int show_all_entries;
+} AVTextFormatSection;
+
+typedef struct AVTextFormatContext AVTextFormatContext;
+
+#define AV_TEXTFORMAT_FLAG_SUPPORTS_OPTIONAL_FIELDS 1
+#define AV_TEXTFORMAT_FLAG_SUPPORTS_MIXED_ARRAY_CONTENT 2
+
+typedef enum {
+ AV_TEXTFORMAT_STRING_VALIDATION_FAIL,
+ AV_TEXTFORMAT_STRING_VALIDATION_REPLACE,
+ AV_TEXTFORMAT_STRING_VALIDATION_IGNORE,
+ AV_TEXTFORMAT_STRING_VALIDATION_NB
+} StringValidation;
+
+typedef struct AVTextFormatter {
+ const AVClass *priv_class; ///< private class of the formatter, if any
+ int priv_size; ///< private size for the formatter context
+ const char *name;
+
+ int (*init) (AVTextFormatContext *tctx);
+ void (*uninit)(AVTextFormatContext *tctx);
+
+ void (*print_section_header)(AVTextFormatContext *tctx, const void *data);
+ void (*print_section_footer)(AVTextFormatContext *tctx);
+ void (*print_integer) (AVTextFormatContext *tctx, const char *, int64_t);
+ void (*print_rational) (AVTextFormatContext *tctx, AVRational *q, char *sep);
+ void (*print_string) (AVTextFormatContext *tctx, const char *, const char *);
+ int flags; ///< a combination or AV_TEXTFORMAT__FLAG_*
+} AVTextFormatter;
+
+#define SECTION_MAX_NB_LEVELS 12
+#define SECTION_MAX_NB_SECTIONS 100
+
+struct AVTextFormatContext {
+ const AVClass *class; ///< class of the formatter
+ const AVTextFormatter *formatter; ///< the AVTextFormatter of which this is an instance
+ AVTextWriterContext *writer; ///< the AVTextWriterContext
+
+ char *name; ///< name of this formatter instance
+ void *priv; ///< private data for use by the filter
+
+ const struct AVTextFormatSection *sections; ///< array containing all sections
+ int nb_sections; ///< number of sections
+
+ int level; ///< current level, starting from 0
+
+ /** number of the item printed in the given section, starting from 0 */
+ unsigned int nb_item[SECTION_MAX_NB_LEVELS];
+ unsigned int nb_item_type[SECTION_MAX_NB_LEVELS][SECTION_MAX_NB_SECTIONS];
+
+ /** section per each level */
+ const struct AVTextFormatSection *section[SECTION_MAX_NB_LEVELS];
+ AVBPrint section_pbuf[SECTION_MAX_NB_LEVELS]; ///< generic print buffer dedicated to each section,
+ /// used by various formatters
+
+ int show_optional_fields;
+ int show_value_unit;
+ int use_value_prefix;
+ int use_byte_value_binary_prefix;
+ int use_value_sexagesimal_format;
+
+ struct AVHashContext *hash;
+
+ int string_validation;
+ char *string_validation_replacement;
+ unsigned int string_validation_utf8_flags;
+};
+
+#define AV_TEXTFORMAT_PRINT_STRING_OPTIONAL 1
+#define AV_TEXTFORMAT_PRINT_STRING_VALIDATE 2
+
+int avtext_context_open(AVTextFormatContext **ptctx, const AVTextFormatter *formatter, AVTextWriterContext *writer_context, const char *args,
+ const struct AVTextFormatSection *sections, int nb_sections,
+ int show_value_unit,
+ int use_value_prefix,
+ int use_byte_value_binary_prefix,
+ int use_value_sexagesimal_format,
+ int show_optional_fields,
+ char *show_data_hash);
+
+int avtext_context_close(AVTextFormatContext **tctx);
+
+
+void avtext_print_section_header(AVTextFormatContext *tctx, const void *data, int section_id);
+
+void avtext_print_section_footer(AVTextFormatContext *tctx);
+
+void avtext_print_integer(AVTextFormatContext *tctx, const char *key, int64_t val);
+
+int avtext_print_string(AVTextFormatContext *tctx, const char *key, const char *val, int flags);
+
+void avtext_print_unit_int(AVTextFormatContext *tctx, const char *key, int value, const char *unit);
+
+void avtext_print_rational(AVTextFormatContext *tctx, const char *key, AVRational q, char sep);
+
+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);
+
+void avtext_print_data(AVTextFormatContext *tctx, const char *name, const uint8_t *data, int size);
+
+void avtext_print_data_hash(AVTextFormatContext *tctx, const char *name, const uint8_t *data, int size);
+
+void avtext_print_integers(AVTextFormatContext *tctx, const char *name, uint8_t *data, int size,
+ const char *format, int columns, int bytes, int offset_add);
+
+const AVTextFormatter *avtext_get_formatter_by_name(const char *name);
+
+extern const AVTextFormatter avtextformatter_default;
+extern const AVTextFormatter avtextformatter_compact;
+extern const AVTextFormatter avtextformatter_csv;
+extern const AVTextFormatter avtextformatter_flat;
+extern const AVTextFormatter avtextformatter_ini;
+extern const AVTextFormatter avtextformatter_json;
+extern const AVTextFormatter avtextformatter_xml;
+
+#endif /* FFTOOLS_TEXTFORMAT_AVTEXTFORMAT_H */
diff --git a/fftools/textformat/avtextwriters.h b/fftools/textformat/avtextwriters.h
new file mode 100644
index 0000000000..a62f2c8906
--- /dev/null
+++ b/fftools/textformat/avtextwriters.h
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) The FFmpeg developers
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef FFTOOLS_TEXTFORMAT_AVTEXTWRITERS_H
+#define FFTOOLS_TEXTFORMAT_AVTEXTWRITERS_H
+
+#include <stddef.h>
+#include <stdint.h>
+#include "libavutil/attributes.h"
+#include "libavutil/dict.h"
+#include "libavformat/avio.h"
+#include "libavutil/bprint.h"
+#include "libavutil/rational.h"
+#include "libavutil/hash.h"
+
+typedef struct AVTextWriterContext AVTextWriterContext;
+
+typedef struct AVTextWriter {
+ const AVClass *priv_class; ///< private class of the writer, if any
+ int priv_size; ///< private size for the writer private class
+ const char *name;
+
+ int (* init)(AVTextWriterContext *wctx);
+ void (* uninit)(AVTextWriterContext *wctx);
+ void (* writer_w8)(AVTextWriterContext *wctx, int b);
+ void (* writer_put_str)(AVTextWriterContext *wctx, const char *str);
+ void (* writer_printf)(AVTextWriterContext *wctx, const char *fmt, ...);
+} AVTextWriter;
+
+typedef struct AVTextWriterContext {
+ const AVClass *class; ///< class of the writer
+ const AVTextWriter *writer;
+ const char *name;
+ void *priv; ///< private data for use by the writer
+
+} AVTextWriterContext;
+
+
+int avtextwriter_context_open(AVTextWriterContext **pwctx, const AVTextWriter *writer);
+
+int avtextwriter_context_close(AVTextWriterContext **pwctx);
+
+int avtextwriter_create_stdout(AVTextWriterContext **pwctx);
+
+int avtextwriter_create_avio(AVTextWriterContext **pwctx, AVIOContext *avio_ctx, int close_on_uninit);
+
+int avtextwriter_create_file(AVTextWriterContext **pwctx, const char *output_filename, int close_on_uninit);
+
+int avtextwriter_create_buffer(AVTextWriterContext **pwctx, AVBPrint *buffer);
+
+#endif /* FFTOOLS_TEXTFORMAT_AVTEXTWRITERS_H */
diff --git a/fftools/textformat/tf_compact.c b/fftools/textformat/tf_compact.c
new file mode 100644
index 0000000000..825b67bc6e
--- /dev/null
+++ b/fftools/textformat/tf_compact.c
@@ -0,0 +1,282 @@
+/*
+ * Copyright (c) The FFmpeg developers
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <limits.h>
+#include <stdarg.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "avtextformat.h"
+#include <libavutil/mem.h>
+#include <libavutil/avassert.h>
+#include <libavutil/bprint.h>
+#include <libavutil/error.h>
+#include <libavutil/macros.h>
+#include <libavutil/opt.h>
+
+
+#define writer_w8(wctx_, b_) (wctx_)->writer->writer->writer_w8((wctx_)->writer, b_)
+#define writer_put_str(wctx_, str_) (wctx_)->writer->writer->writer_put_str((wctx_)->writer, str_)
+#define writer_printf(wctx_, fmt_, ...) (wctx_)->writer->writer->writer_printf((wctx_)->writer, fmt_, __VA_ARGS__)
+
+
+#define DEFINE_FORMATTER_CLASS(name) \
+static const char *name##_get_name(void *ctx) \
+{ \
+ return #name ; \
+} \
+static const AVClass name##_class = { \
+ .class_name = #name, \
+ .item_name = name##_get_name, \
+ .option = name##_options \
+}
+
+
+/* Compact output */
+
+/**
+ * Apply C-language-like string escaping.
+ */
+static const char *c_escape_str(AVBPrint *dst, const char *src, const char sep, void *log_ctx)
+{
+ const char *p;
+
+ for (p = src; *p; p++) {
+ switch (*p) {
+ case '\b': av_bprintf(dst, "%s", "\\b"); break;
+ case '\f': av_bprintf(dst, "%s", "\\f"); break;
+ case '\n': av_bprintf(dst, "%s", "\\n"); break;
+ case '\r': av_bprintf(dst, "%s", "\\r"); break;
+ case '\\': av_bprintf(dst, "%s", "\\\\"); break;
+ default:
+ if (*p == sep)
+ av_bprint_chars(dst, '\\', 1);
+ av_bprint_chars(dst, *p, 1);
+ }
+ }
+ return dst->str;
+}
+
+/**
+ * Quote fields containing special characters, check RFC4180.
+ */
+static const char *csv_escape_str(AVBPrint *dst, const char *src, const char sep, void *log_ctx)
+{
+ char meta_chars[] = { sep, '"', '\n', '\r', '\0' };
+ int needs_quoting = !!src[strcspn(src, meta_chars)];
+
+ if (needs_quoting)
+ av_bprint_chars(dst, '"', 1);
+
+ for (; *src; src++) {
+ if (*src == '"')
+ av_bprint_chars(dst, '"', 1);
+ av_bprint_chars(dst, *src, 1);
+ }
+ if (needs_quoting)
+ av_bprint_chars(dst, '"', 1);
+ return dst->str;
+}
+
+static const char *none_escape_str(AVBPrint *dst, const char *src, const char sep, void *log_ctx)
+{
+ return src;
+}
+
+typedef struct CompactContext {
+ const AVClass *class;
+ char *item_sep_str;
+ char item_sep;
+ int nokey;
+ int print_section;
+ char *escape_mode_str;
+ const char * (*escape_str)(AVBPrint *dst, const char *src, const char sep, void *log_ctx);
+ int nested_section[SECTION_MAX_NB_LEVELS];
+ int has_nested_elems[SECTION_MAX_NB_LEVELS];
+ int terminate_line[SECTION_MAX_NB_LEVELS];
+} CompactContext;
+
+#undef OFFSET
+#define OFFSET(x) offsetof(CompactContext, x)
+
+static const AVOption compact_options[]= {
+ {"item_sep", "set item separator", OFFSET(item_sep_str), AV_OPT_TYPE_STRING, {.str="|"}, 0, 0 },
+ {"s", "set item separator", OFFSET(item_sep_str), AV_OPT_TYPE_STRING, {.str="|"}, 0, 0 },
+ {"nokey", "force no key printing", OFFSET(nokey), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1 },
+ {"nk", "force no key printing", OFFSET(nokey), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1 },
+ {"escape", "set escape mode", OFFSET(escape_mode_str), AV_OPT_TYPE_STRING, {.str="c"}, 0, 0 },
+ {"e", "set escape mode", OFFSET(escape_mode_str), AV_OPT_TYPE_STRING, {.str="c"}, 0, 0 },
+ {"print_section", "print section name", OFFSET(print_section), AV_OPT_TYPE_BOOL, {.i64=1}, 0, 1 },
+ {"p", "print section name", OFFSET(print_section), AV_OPT_TYPE_BOOL, {.i64=1}, 0, 1 },
+ {NULL},
+};
+
+DEFINE_FORMATTER_CLASS(compact);
+
+static av_cold int compact_init(AVTextFormatContext *wctx)
+{
+ CompactContext *compact = wctx->priv;
+
+ if (strlen(compact->item_sep_str) != 1) {
+ av_log(wctx, AV_LOG_ERROR, "Item separator '%s' specified, but must contain a single character\n",
+ compact->item_sep_str);
+ return AVERROR(EINVAL);
+ }
+ compact->item_sep = compact->item_sep_str[0];
+
+ if (!strcmp(compact->escape_mode_str, "none")) compact->escape_str = none_escape_str;
+ else if (!strcmp(compact->escape_mode_str, "c" )) compact->escape_str = c_escape_str;
+ else if (!strcmp(compact->escape_mode_str, "csv" )) compact->escape_str = csv_escape_str;
+ else {
+ av_log(wctx, AV_LOG_ERROR, "Unknown escape mode '%s'\n", compact->escape_mode_str);
+ return AVERROR(EINVAL);
+ }
+
+ return 0;
+}
+
+static void compact_print_section_header(AVTextFormatContext *wctx, const void *data)
+{
+ CompactContext *compact = wctx->priv;
+ const struct AVTextFormatSection *section = wctx->section[wctx->level];
+ const struct AVTextFormatSection *parent_section = wctx->level ?
+ wctx->section[wctx->level-1] : NULL;
+ compact->terminate_line[wctx->level] = 1;
+ compact->has_nested_elems[wctx->level] = 0;
+
+ av_bprint_clear(&wctx->section_pbuf[wctx->level]);
+ if (parent_section &&
+ (section->flags & AV_TEXTFORMAT_SECTION_FLAG_HAS_TYPE ||
+ (!(section->flags & AV_TEXTFORMAT_SECTION_FLAG_IS_ARRAY) &&
+ !(parent_section->flags & (AV_TEXTFORMAT_SECTION_FLAG_IS_WRAPPER|AV_TEXTFORMAT_SECTION_FLAG_IS_ARRAY))))) {
+
+ /* define a prefix for elements not contained in an array or
+ in a wrapper, or for array elements with a type */
+ const char *element_name = (char *)av_x_if_null(section->element_name, section->name);
+ AVBPrint *section_pbuf = &wctx->section_pbuf[wctx->level];
+
+ compact->nested_section[wctx->level] = 1;
+ compact->has_nested_elems[wctx->level-1] = 1;
+
+ av_bprintf(section_pbuf, "%s%s",
+ wctx->section_pbuf[wctx->level-1].str, element_name);
+
+ if (section->flags & AV_TEXTFORMAT_SECTION_FLAG_HAS_TYPE) {
+ // add /TYPE to prefix
+ av_bprint_chars(section_pbuf, '/', 1);
+
+ // normalize section type, replace special characters and lower case
+ for (const char *p = section->get_type(data); *p; p++) {
+ char c =
+ (*p >= '0' && *p <= '9') ||
+ (*p >= 'a' && *p <= 'z') ||
+ (*p >= 'A' && *p <= 'Z') ? av_tolower(*p) : '_';
+ av_bprint_chars(section_pbuf, c, 1);
+ }
+ }
+ av_bprint_chars(section_pbuf, ':', 1);
+
+ wctx->nb_item[wctx->level] = wctx->nb_item[wctx->level-1];
+ } else {
+ if (parent_section && !(parent_section->flags & (AV_TEXTFORMAT_SECTION_FLAG_IS_WRAPPER|AV_TEXTFORMAT_SECTION_FLAG_IS_ARRAY)) &&
+ wctx->level && wctx->nb_item[wctx->level-1])
+ writer_w8(wctx, compact->item_sep);
+ if (compact->print_section &&
+ !(section->flags & (AV_TEXTFORMAT_SECTION_FLAG_IS_WRAPPER|AV_TEXTFORMAT_SECTION_FLAG_IS_ARRAY)))
+ writer_printf(wctx, "%s%c", section->name, compact->item_sep);
+ }
+}
+
+static void compact_print_section_footer(AVTextFormatContext *wctx)
+{
+ CompactContext *compact = wctx->priv;
+
+ if (!compact->nested_section[wctx->level] &&
+ compact->terminate_line[wctx->level] &&
+ !(wctx->section[wctx->level]->flags & (AV_TEXTFORMAT_SECTION_FLAG_IS_WRAPPER|AV_TEXTFORMAT_SECTION_FLAG_IS_ARRAY)))
+ writer_w8(wctx, '\n');
+}
+
+static void compact_print_str(AVTextFormatContext *wctx, const char *key, const char *value)
+{
+ CompactContext *compact = wctx->priv;
+ AVBPrint buf;
+
+ if (wctx->nb_item[wctx->level]) writer_w8(wctx, compact->item_sep);
+ if (!compact->nokey)
+ writer_printf(wctx, "%s%s=", wctx->section_pbuf[wctx->level].str, key);
+ av_bprint_init(&buf, 1, AV_BPRINT_SIZE_UNLIMITED);
+ writer_put_str(wctx, compact->escape_str(&buf, value, compact->item_sep, wctx));
+ av_bprint_finalize(&buf, NULL);
+}
+
+static void compact_print_int(AVTextFormatContext *wctx, const char *key, int64_t value)
+{
+ CompactContext *compact = wctx->priv;
+
+ if (wctx->nb_item[wctx->level]) writer_w8(wctx, compact->item_sep);
+ if (!compact->nokey)
+ writer_printf(wctx, "%s%s=", wctx->section_pbuf[wctx->level].str, key);
+ writer_printf(wctx, "%"PRId64, value);
+}
+
+const AVTextFormatter avtextformatter_compact = {
+ .name = "compact",
+ .priv_size = sizeof(CompactContext),
+ .init = compact_init,
+ .print_section_header = compact_print_section_header,
+ .print_section_footer = compact_print_section_footer,
+ .print_integer = compact_print_int,
+ .print_string = compact_print_str,
+ .flags = AV_TEXTFORMAT_FLAG_SUPPORTS_OPTIONAL_FIELDS,
+ .priv_class = &compact_class,
+};
+
+/* CSV output */
+
+#undef OFFSET
+#define OFFSET(x) offsetof(CompactContext, x)
+
+static const AVOption csv_options[] = {
+ {"item_sep", "set item separator", OFFSET(item_sep_str), AV_OPT_TYPE_STRING, {.str=","}, 0, 0 },
+ {"s", "set item separator", OFFSET(item_sep_str), AV_OPT_TYPE_STRING, {.str=","}, 0, 0 },
+ {"nokey", "force no key printing", OFFSET(nokey), AV_OPT_TYPE_BOOL, {.i64=1}, 0, 1 },
+ {"nk", "force no key printing", OFFSET(nokey), AV_OPT_TYPE_BOOL, {.i64=1}, 0, 1 },
+ {"escape", "set escape mode", OFFSET(escape_mode_str), AV_OPT_TYPE_STRING, {.str="csv"}, 0, 0 },
+ {"e", "set escape mode", OFFSET(escape_mode_str), AV_OPT_TYPE_STRING, {.str="csv"}, 0, 0 },
+ {"print_section", "print section name", OFFSET(print_section), AV_OPT_TYPE_BOOL, {.i64=1}, 0, 1 },
+ {"p", "print section name", OFFSET(print_section), AV_OPT_TYPE_BOOL, {.i64=1}, 0, 1 },
+ {NULL},
+};
+
+DEFINE_FORMATTER_CLASS(csv);
+
+const AVTextFormatter avtextformatter_csv = {
+ .name = "csv",
+ .priv_size = sizeof(CompactContext),
+ .init = compact_init,
+ .print_section_header = compact_print_section_header,
+ .print_section_footer = compact_print_section_footer,
+ .print_integer = compact_print_int,
+ .print_string = compact_print_str,
+ .flags = AV_TEXTFORMAT_FLAG_SUPPORTS_OPTIONAL_FIELDS,
+ .priv_class = &csv_class,
+};
diff --git a/fftools/textformat/tf_default.c b/fftools/textformat/tf_default.c
new file mode 100644
index 0000000000..7369992f01
--- /dev/null
+++ b/fftools/textformat/tf_default.c
@@ -0,0 +1,145 @@
+/*
+ * Copyright (c) The FFmpeg developers
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <limits.h>
+#include <stdarg.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "avtextformat.h"
+#include <libavutil/mem.h>
+#include <libavutil/avassert.h>
+#include <libavutil/bprint.h>
+#include <libavutil/opt.h>
+
+#define writer_w8(wctx_, b_) (wctx_)->writer->writer->writer_w8((wctx_)->writer, b_)
+#define writer_put_str(wctx_, str_) (wctx_)->writer->writer->writer_put_str((wctx_)->writer, str_)
+#define writer_printf(wctx_, fmt_, ...) (wctx_)->writer->writer->writer_printf((wctx_)->writer, fmt_, __VA_ARGS__)
+
+#define DEFINE_FORMATTER_CLASS(name) \
+static const char *name##_get_name(void *ctx) \
+{ \
+ return #name ; \
+} \
+static const AVClass name##_class = { \
+ .class_name = #name, \
+ .item_name = name##_get_name, \
+ .option = name##_options \
+}
+
+/* Default output */
+
+typedef struct DefaultContext {
+ const AVClass *class;
+ int nokey;
+ int noprint_wrappers;
+ int nested_section[SECTION_MAX_NB_LEVELS];
+} DefaultContext;
+
+#undef OFFSET
+#define OFFSET(x) offsetof(DefaultContext, x)
+
+static const AVOption default_options[] = {
+ { "noprint_wrappers", "do not print headers and footers", OFFSET(noprint_wrappers), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1 },
+ { "nw", "do not print headers and footers", OFFSET(noprint_wrappers), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1 },
+ { "nokey", "force no key printing", OFFSET(nokey), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1 },
+ { "nk", "force no key printing", OFFSET(nokey), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1 },
+ {NULL},
+};
+
+DEFINE_FORMATTER_CLASS(default);
+
+/* lame uppercasing routine, assumes the string is lower case ASCII */
+static inline char *upcase_string(char *dst, size_t dst_size, const char *src)
+{
+ int i;
+ for (i = 0; src[i] && i < dst_size-1; i++)
+ dst[i] = av_toupper(src[i]);
+ dst[i] = 0;
+ return dst;
+}
+
+static void default_print_section_header(AVTextFormatContext *wctx, const void *data)
+{
+ DefaultContext *def = wctx->priv;
+ char buf[32];
+ const struct AVTextFormatSection *section = wctx->section[wctx->level];
+ const struct AVTextFormatSection *parent_section = wctx->level ?
+ wctx->section[wctx->level-1] : NULL;
+
+ av_bprint_clear(&wctx->section_pbuf[wctx->level]);
+ if (parent_section &&
+ !(parent_section->flags & (AV_TEXTFORMAT_SECTION_FLAG_IS_WRAPPER|AV_TEXTFORMAT_SECTION_FLAG_IS_ARRAY))) {
+ def->nested_section[wctx->level] = 1;
+ av_bprintf(&wctx->section_pbuf[wctx->level], "%s%s:",
+ wctx->section_pbuf[wctx->level-1].str,
+ upcase_string(buf, sizeof(buf),
+ av_x_if_null(section->element_name, section->name)));
+ }
+
+ if (def->noprint_wrappers || def->nested_section[wctx->level])
+ return;
+
+ if (!(section->flags & (AV_TEXTFORMAT_SECTION_FLAG_IS_WRAPPER|AV_TEXTFORMAT_SECTION_FLAG_IS_ARRAY)))
+ writer_printf(wctx, "[%s]\n", upcase_string(buf, sizeof(buf), section->name));
+}
+
+static void default_print_section_footer(AVTextFormatContext *wctx)
+{
+ DefaultContext *def = wctx->priv;
+ const struct AVTextFormatSection *section = wctx->section[wctx->level];
+ char buf[32];
+
+ if (def->noprint_wrappers || def->nested_section[wctx->level])
+ return;
+
+ if (!(section->flags & (AV_TEXTFORMAT_SECTION_FLAG_IS_WRAPPER|AV_TEXTFORMAT_SECTION_FLAG_IS_ARRAY)))
+ writer_printf(wctx, "[/%s]\n", upcase_string(buf, sizeof(buf), section->name));
+}
+
+static void default_print_str(AVTextFormatContext *wctx, const char *key, const char *value)
+{
+ DefaultContext *def = wctx->priv;
+
+ if (!def->nokey)
+ writer_printf(wctx, "%s%s=", wctx->section_pbuf[wctx->level].str, key);
+ writer_printf(wctx, "%s\n", value);
+}
+
+static void default_print_int(AVTextFormatContext *wctx, const char *key, int64_t value)
+{
+ DefaultContext *def = wctx->priv;
+
+ if (!def->nokey)
+ writer_printf(wctx, "%s%s=", wctx->section_pbuf[wctx->level].str, key);
+ writer_printf(wctx, "%"PRId64"\n", value);
+}
+
+const AVTextFormatter avtextformatter_default = {
+ .name = "default",
+ .priv_size = sizeof(DefaultContext),
+ .print_section_header = default_print_section_header,
+ .print_section_footer = default_print_section_footer,
+ .print_integer = default_print_int,
+ .print_string = default_print_str,
+ .flags = AV_TEXTFORMAT_FLAG_SUPPORTS_OPTIONAL_FIELDS,
+ .priv_class = &default_class,
+};
\ No newline at end of file
diff --git a/fftools/textformat/tf_flat.c b/fftools/textformat/tf_flat.c
new file mode 100644
index 0000000000..6971593c77
--- /dev/null
+++ b/fftools/textformat/tf_flat.c
@@ -0,0 +1,174 @@
+/*
+ * Copyright (c) The FFmpeg developers
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <limits.h>
+#include <stdarg.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "avtextformat.h"
+#include <libavutil/mem.h>
+#include <libavutil/avassert.h>
+#include <libavutil/bprint.h>
+#include <libavutil/error.h>
+#include <libavutil/macros.h>
+#include <libavutil/opt.h>
+
+#define writer_w8(wctx_, b_) (wctx_)->writer->writer->writer_w8((wctx_)->writer, b_)
+#define writer_put_str(wctx_, str_) (wctx_)->writer->writer->writer_put_str((wctx_)->writer, str_)
+#define writer_printf(wctx_, fmt_, ...) (wctx_)->writer->writer->writer_printf((wctx_)->writer, fmt_, __VA_ARGS__)
+
+#define DEFINE_FORMATTER_CLASS(name) \
+static const char *name##_get_name(void *ctx) \
+{ \
+ return #name ; \
+} \
+static const AVClass name##_class = { \
+ .class_name = #name, \
+ .item_name = name##_get_name, \
+ .option = name##_options \
+}
+
+
+/* Flat output */
+
+typedef struct FlatContext {
+ const AVClass *class;
+ const char *sep_str;
+ char sep;
+ int hierarchical;
+} FlatContext;
+
+#undef OFFSET
+#define OFFSET(x) offsetof(FlatContext, x)
+
+static const AVOption flat_options[]= {
+ {"sep_char", "set separator", OFFSET(sep_str), AV_OPT_TYPE_STRING, {.str="."}, 0, 0 },
+ {"s", "set separator", OFFSET(sep_str), AV_OPT_TYPE_STRING, {.str="."}, 0, 0 },
+ {"hierarchical", "specify if the section specification should be hierarchical", OFFSET(hierarchical), AV_OPT_TYPE_BOOL, {.i64=1}, 0, 1 },
+ {"h", "specify if the section specification should be hierarchical", OFFSET(hierarchical), AV_OPT_TYPE_BOOL, {.i64=1}, 0, 1 },
+ {NULL},
+};
+
+DEFINE_FORMATTER_CLASS(flat);
+
+static av_cold int flat_init(AVTextFormatContext *wctx)
+{
+ FlatContext *flat = wctx->priv;
+
+ if (strlen(flat->sep_str) != 1) {
+ av_log(wctx, AV_LOG_ERROR, "Item separator '%s' specified, but must contain a single character\n",
+ flat->sep_str);
+ return AVERROR(EINVAL);
+ }
+ flat->sep = flat->sep_str[0];
+
+ return 0;
+}
+
+static const char *flat_escape_key_str(AVBPrint *dst, const char *src, const char sep)
+{
+ const char *p;
+
+ for (p = src; *p; p++) {
+ if (!((*p >= '0' && *p <= '9') ||
+ (*p >= 'a' && *p <= 'z') ||
+ (*p >= 'A' && *p <= 'Z')))
+ av_bprint_chars(dst, '_', 1);
+ else
+ av_bprint_chars(dst, *p, 1);
+ }
+ return dst->str;
+}
+
+static const char *flat_escape_value_str(AVBPrint *dst, const char *src)
+{
+ const char *p;
+
+ for (p = src; *p; p++) {
+ switch (*p) {
+ case '\n': av_bprintf(dst, "%s", "\\n"); break;
+ case '\r': av_bprintf(dst, "%s", "\\r"); break;
+ case '\\': av_bprintf(dst, "%s", "\\\\"); break;
+ case '"': av_bprintf(dst, "%s", "\\\""); break;
+ case '`': av_bprintf(dst, "%s", "\\`"); break;
+ case '$': av_bprintf(dst, "%s", "\\$"); break;
+ default: av_bprint_chars(dst, *p, 1); break;
+ }
+ }
+ return dst->str;
+}
+
+static void flat_print_section_header(AVTextFormatContext *wctx, const void *data)
+{
+ FlatContext *flat = wctx->priv;
+ AVBPrint *buf = &wctx->section_pbuf[wctx->level];
+ const struct AVTextFormatSection *section = wctx->section[wctx->level];
+ const struct AVTextFormatSection *parent_section = wctx->level ?
+ wctx->section[wctx->level-1] : NULL;
+
+ /* build section header */
+ av_bprint_clear(buf);
+ if (!parent_section)
+ return;
+ av_bprintf(buf, "%s", wctx->section_pbuf[wctx->level-1].str);
+
+ if (flat->hierarchical ||
+ !(section->flags & (AV_TEXTFORMAT_SECTION_FLAG_IS_ARRAY|AV_TEXTFORMAT_SECTION_FLAG_IS_WRAPPER))) {
+ av_bprintf(buf, "%s%s", wctx->section[wctx->level]->name, flat->sep_str);
+
+ if (parent_section->flags & AV_TEXTFORMAT_SECTION_FLAG_IS_ARRAY) {
+ int n = parent_section->flags & AV_TEXTFORMAT_SECTION_FLAG_NUMBERING_BY_TYPE ?
+ wctx->nb_item_type[wctx->level-1][section->id] :
+ wctx->nb_item[wctx->level-1];
+ av_bprintf(buf, "%d%s", n, flat->sep_str);
+ }
+ }
+}
+
+static void flat_print_int(AVTextFormatContext *wctx, const char *key, int64_t value)
+{
+ writer_printf(wctx, "%s%s=%"PRId64"\n", wctx->section_pbuf[wctx->level].str, key, value);
+}
+
+static void flat_print_str(AVTextFormatContext *wctx, const char *key, const char *value)
+{
+ FlatContext *flat = wctx->priv;
+ AVBPrint buf;
+
+ writer_put_str(wctx, wctx->section_pbuf[wctx->level].str);
+ av_bprint_init(&buf, 1, AV_BPRINT_SIZE_UNLIMITED);
+ writer_printf(wctx, "%s=", flat_escape_key_str(&buf, key, flat->sep));
+ av_bprint_clear(&buf);
+ writer_printf(wctx, "\"%s\"\n", flat_escape_value_str(&buf, value));
+ av_bprint_finalize(&buf, NULL);
+}
+
+const AVTextFormatter avtextformatter_flat = {
+ .name = "flat",
+ .priv_size = sizeof(FlatContext),
+ .init = flat_init,
+ .print_section_header = flat_print_section_header,
+ .print_integer = flat_print_int,
+ .print_string = flat_print_str,
+ .flags = AV_TEXTFORMAT_FLAG_SUPPORTS_OPTIONAL_FIELDS|AV_TEXTFORMAT_FLAG_SUPPORTS_MIXED_ARRAY_CONTENT,
+ .priv_class = &flat_class,
+};
diff --git a/fftools/textformat/tf_ini.c b/fftools/textformat/tf_ini.c
new file mode 100644
index 0000000000..1f4216069f
--- /dev/null
+++ b/fftools/textformat/tf_ini.c
@@ -0,0 +1,160 @@
+/*
+ * Copyright (c) The FFmpeg developers
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <limits.h>
+#include <stdarg.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "avtextformat.h"
+#include <libavutil/mem.h>
+#include <libavutil/avassert.h>
+#include <libavutil/bprint.h>
+#include <libavutil/opt.h>
+
+#define writer_w8(wctx_, b_) (wctx_)->writer->writer->writer_w8((wctx_)->writer, b_)
+#define writer_put_str(wctx_, str_) (wctx_)->writer->writer->writer_put_str((wctx_)->writer, str_)
+#define writer_printf(wctx_, fmt_, ...) (wctx_)->writer->writer->writer_printf((wctx_)->writer, fmt_, __VA_ARGS__)
+
+#define DEFINE_FORMATTER_CLASS(name) \
+static const char *name##_get_name(void *ctx) \
+{ \
+ return #name ; \
+} \
+static const AVClass name##_class = { \
+ .class_name = #name, \
+ .item_name = name##_get_name, \
+ .option = name##_options \
+}
+
+/* Default output */
+
+typedef struct DefaultContext {
+ const AVClass *class;
+ int nokey;
+ int noprint_wrappers;
+ int nested_section[SECTION_MAX_NB_LEVELS];
+} DefaultContext;
+
+/* INI format output */
+
+typedef struct INIContext {
+ const AVClass *class;
+ int hierarchical;
+} INIContext;
+
+#undef OFFSET
+#define OFFSET(x) offsetof(INIContext, x)
+
+static const AVOption ini_options[] = {
+ {"hierarchical", "specify if the section specification should be hierarchical", OFFSET(hierarchical), AV_OPT_TYPE_BOOL, {.i64=1}, 0, 1 },
+ {"h", "specify if the section specification should be hierarchical", OFFSET(hierarchical), AV_OPT_TYPE_BOOL, {.i64=1}, 0, 1 },
+ {NULL},
+};
+
+DEFINE_FORMATTER_CLASS(ini);
+
+static char *ini_escape_str(AVBPrint *dst, const char *src)
+{
+ int i = 0;
+ char c = 0;
+
+ while (c = src[i++]) {
+ switch (c) {
+ case '\b': av_bprintf(dst, "%s", "\\b"); break;
+ case '\f': av_bprintf(dst, "%s", "\\f"); break;
+ case '\n': av_bprintf(dst, "%s", "\\n"); break;
+ case '\r': av_bprintf(dst, "%s", "\\r"); break;
+ case '\t': av_bprintf(dst, "%s", "\\t"); break;
+ case '\\':
+ case '#' :
+ case '=' :
+ case ':' : av_bprint_chars(dst, '\\', 1);
+ default:
+ if ((unsigned char)c < 32)
+ av_bprintf(dst, "\\x00%02x", c & 0xff);
+ else
+ av_bprint_chars(dst, c, 1);
+ break;
+ }
+ }
+ return dst->str;
+}
+
+static void ini_print_section_header(AVTextFormatContext *wctx, const void *data)
+{
+ INIContext *ini = wctx->priv;
+ AVBPrint *buf = &wctx->section_pbuf[wctx->level];
+ const struct AVTextFormatSection *section = wctx->section[wctx->level];
+ const struct AVTextFormatSection *parent_section = wctx->level ?
+ wctx->section[wctx->level-1] : NULL;
+
+ av_bprint_clear(buf);
+ if (!parent_section) {
+ writer_put_str(wctx, "# ffprobe output\n\n");
+ return;
+ }
+
+ if (wctx->nb_item[wctx->level-1])
+ writer_w8(wctx, '\n');
+
+ av_bprintf(buf, "%s", wctx->section_pbuf[wctx->level-1].str);
+ if (ini->hierarchical ||
+ !(section->flags & (AV_TEXTFORMAT_SECTION_FLAG_IS_ARRAY|AV_TEXTFORMAT_SECTION_FLAG_IS_WRAPPER))) {
+ av_bprintf(buf, "%s%s", buf->str[0] ? "." : "", wctx->section[wctx->level]->name);
+
+ if (parent_section->flags & AV_TEXTFORMAT_SECTION_FLAG_IS_ARRAY) {
+ int n = parent_section->flags & AV_TEXTFORMAT_SECTION_FLAG_NUMBERING_BY_TYPE ?
+ wctx->nb_item_type[wctx->level-1][section->id] :
+ wctx->nb_item[wctx->level-1];
+ av_bprintf(buf, ".%d", n);
+ }
+ }
+
+ if (!(section->flags & (AV_TEXTFORMAT_SECTION_FLAG_IS_ARRAY|AV_TEXTFORMAT_SECTION_FLAG_IS_WRAPPER)))
+ writer_printf(wctx, "[%s]\n", buf->str);
+}
+
+static void ini_print_str(AVTextFormatContext *wctx, const char *key, const char *value)
+{
+ AVBPrint buf;
+
+ av_bprint_init(&buf, 1, AV_BPRINT_SIZE_UNLIMITED);
+ writer_printf(wctx, "%s=", ini_escape_str(&buf, key));
+ av_bprint_clear(&buf);
+ writer_printf(wctx, "%s\n", ini_escape_str(&buf, value));
+ av_bprint_finalize(&buf, NULL);
+}
+
+static void ini_print_int(AVTextFormatContext *wctx, const char *key, int64_t value)
+{
+ writer_printf(wctx, "%s=%"PRId64"\n", key, value);
+}
+
+const AVTextFormatter avtextformatter_ini = {
+ .name = "ini",
+ .priv_size = sizeof(INIContext),
+ .print_section_header = ini_print_section_header,
+ .print_integer = ini_print_int,
+ .print_string = ini_print_str,
+ .flags = AV_TEXTFORMAT_FLAG_SUPPORTS_OPTIONAL_FIELDS|AV_TEXTFORMAT_FLAG_SUPPORTS_MIXED_ARRAY_CONTENT,
+ .priv_class = &ini_class,
+};
diff --git a/fftools/textformat/tf_json.c b/fftools/textformat/tf_json.c
new file mode 100644
index 0000000000..de27a36e7e
--- /dev/null
+++ b/fftools/textformat/tf_json.c
@@ -0,0 +1,215 @@
+/*
+ * Copyright (c) The FFmpeg developers
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <limits.h>
+#include <stdarg.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "avtextformat.h"
+#include <libavutil/mem.h>
+#include <libavutil/avassert.h>
+#include <libavutil/bprint.h>
+#include <libavutil/opt.h>
+
+#define writer_w8(wctx_, b_) (wctx_)->writer->writer->writer_w8((wctx_)->writer, b_)
+#define writer_put_str(wctx_, str_) (wctx_)->writer->writer->writer_put_str((wctx_)->writer, str_)
+#define writer_printf(wctx_, fmt_, ...) (wctx_)->writer->writer->writer_printf((wctx_)->writer, fmt_, __VA_ARGS__)
+
+#define DEFINE_FORMATTER_CLASS(name) \
+static const char *name##_get_name(void *ctx) \
+{ \
+ return #name ; \
+} \
+static const AVClass name##_class = { \
+ .class_name = #name, \
+ .item_name = name##_get_name, \
+ .option = name##_options \
+}
+
+
+/* JSON output */
+
+typedef struct JSONContext {
+ const AVClass *class;
+ int indent_level;
+ int compact;
+ const char *item_sep, *item_start_end;
+} JSONContext;
+
+#undef OFFSET
+#define OFFSET(x) offsetof(JSONContext, x)
+
+static const AVOption json_options[]= {
+ { "compact", "enable compact output", OFFSET(compact), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1 },
+ { "c", "enable compact output", OFFSET(compact), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1 },
+ { NULL }
+};
+
+DEFINE_FORMATTER_CLASS(json);
+
+static av_cold int json_init(AVTextFormatContext *wctx)
+{
+ JSONContext *json = wctx->priv;
+
+ json->item_sep = json->compact ? ", " : ",\n";
+ json->item_start_end = json->compact ? " " : "\n";
+
+ return 0;
+}
+
+static const char *json_escape_str(AVBPrint *dst, const char *src, void *log_ctx)
+{
+ static const char json_escape[] = {'"', '\\', '\b', '\f', '\n', '\r', '\t', 0};
+ static const char json_subst[] = {'"', '\\', 'b', 'f', 'n', 'r', 't', 0};
+ const char *p;
+
+ for (p = src; *p; p++) {
+ char *s = strchr(json_escape, *p);
+ if (s) {
+ av_bprint_chars(dst, '\\', 1);
+ av_bprint_chars(dst, json_subst[s - json_escape], 1);
+ } else if ((unsigned char)*p < 32) {
+ av_bprintf(dst, "\\u00%02x", *p & 0xff);
+ } else {
+ av_bprint_chars(dst, *p, 1);
+ }
+ }
+ return dst->str;
+}
+
+#define JSON_INDENT() writer_printf(wctx, "%*c", json->indent_level * 4, ' ')
+
+static void json_print_section_header(AVTextFormatContext *wctx, const void *data)
+{
+ JSONContext *json = wctx->priv;
+ AVBPrint buf;
+ const struct AVTextFormatSection *section = wctx->section[wctx->level];
+ const struct AVTextFormatSection *parent_section = wctx->level ?
+ wctx->section[wctx->level-1] : NULL;
+
+ if (wctx->level && wctx->nb_item[wctx->level-1])
+ writer_put_str(wctx, ",\n");
+
+ if (section->flags & AV_TEXTFORMAT_SECTION_FLAG_IS_WRAPPER) {
+ writer_put_str(wctx, "{\n");
+ json->indent_level++;
+ } else {
+ av_bprint_init(&buf, 1, AV_BPRINT_SIZE_UNLIMITED);
+ json_escape_str(&buf, section->name, wctx);
+ JSON_INDENT();
+
+ json->indent_level++;
+ if (section->flags & AV_TEXTFORMAT_SECTION_FLAG_IS_ARRAY) {
+ writer_printf(wctx, "\"%s\": [\n", buf.str);
+ } else if (parent_section && !(parent_section->flags & AV_TEXTFORMAT_SECTION_FLAG_IS_ARRAY)) {
+ writer_printf(wctx, "\"%s\": {%s", buf.str, json->item_start_end);
+ } else {
+ writer_printf(wctx, "{%s", json->item_start_end);
+
+ /* this is required so the parser can distinguish between packets and frames */
+ if (parent_section && parent_section->flags & AV_TEXTFORMAT_SECTION_FLAG_NUMBERING_BY_TYPE) {
+ if (!json->compact)
+ JSON_INDENT();
+ writer_printf(wctx, "\"type\": \"%s\"", section->name);
+ wctx->nb_item[wctx->level]++;
+ }
+ }
+ av_bprint_finalize(&buf, NULL);
+ }
+}
+
+static void json_print_section_footer(AVTextFormatContext *wctx)
+{
+ JSONContext *json = wctx->priv;
+ const struct AVTextFormatSection *section = wctx->section[wctx->level];
+
+ if (wctx->level == 0) {
+ json->indent_level--;
+ writer_put_str(wctx, "\n}\n");
+ } else if (section->flags & AV_TEXTFORMAT_SECTION_FLAG_IS_ARRAY) {
+ writer_w8(wctx, '\n');
+ json->indent_level--;
+ JSON_INDENT();
+ writer_w8(wctx, ']');
+ } else {
+ writer_put_str(wctx, json->item_start_end);
+ json->indent_level--;
+ if (!json->compact)
+ JSON_INDENT();
+ writer_w8(wctx, '}');
+ }
+}
+
+static inline void json_print_item_str(AVTextFormatContext *wctx,
+ const char *key, const char *value)
+{
+ AVBPrint buf;
+
+ av_bprint_init(&buf, 1, AV_BPRINT_SIZE_UNLIMITED);
+ writer_printf(wctx, "\"%s\":", json_escape_str(&buf, key, wctx));
+ av_bprint_clear(&buf);
+ writer_printf(wctx, " \"%s\"", json_escape_str(&buf, value, wctx));
+ av_bprint_finalize(&buf, NULL);
+}
+
+static void json_print_str(AVTextFormatContext *wctx, const char *key, const char *value)
+{
+ JSONContext *json = wctx->priv;
+ const struct AVTextFormatSection *parent_section = wctx->level ?
+ wctx->section[wctx->level-1] : NULL;
+
+ if (wctx->nb_item[wctx->level] || (parent_section && parent_section->flags & AV_TEXTFORMAT_SECTION_FLAG_NUMBERING_BY_TYPE))
+ writer_put_str(wctx, json->item_sep);
+ if (!json->compact)
+ JSON_INDENT();
+ json_print_item_str(wctx, key, value);
+}
+
+static void json_print_int(AVTextFormatContext *wctx, const char *key, int64_t value)
+{
+ JSONContext *json = wctx->priv;
+ const struct AVTextFormatSection *parent_section = wctx->level ?
+ wctx->section[wctx->level-1] : NULL;
+ AVBPrint buf;
+
+ if (wctx->nb_item[wctx->level] || (parent_section && parent_section->flags & AV_TEXTFORMAT_SECTION_FLAG_NUMBERING_BY_TYPE))
+ writer_put_str(wctx, json->item_sep);
+ if (!json->compact)
+ JSON_INDENT();
+
+ av_bprint_init(&buf, 1, AV_BPRINT_SIZE_UNLIMITED);
+ writer_printf(wctx, "\"%s\": %"PRId64, json_escape_str(&buf, key, wctx), value);
+ av_bprint_finalize(&buf, NULL);
+}
+
+const AVTextFormatter avtextformatter_json = {
+ .name = "json",
+ .priv_size = sizeof(JSONContext),
+ .init = json_init,
+ .print_section_header = json_print_section_header,
+ .print_section_footer = json_print_section_footer,
+ .print_integer = json_print_int,
+ .print_string = json_print_str,
+ .flags = AV_TEXTFORMAT_FLAG_SUPPORTS_MIXED_ARRAY_CONTENT,
+ .priv_class = &json_class,
+};
+
diff --git a/fftools/textformat/tf_xml.c b/fftools/textformat/tf_xml.c
new file mode 100644
index 0000000000..57171c4cb3
--- /dev/null
+++ b/fftools/textformat/tf_xml.c
@@ -0,0 +1,221 @@
+/*
+ * Copyright (c) The FFmpeg developers
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <limits.h>
+#include <stdarg.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "avtextformat.h"
+#include <libavutil/mem.h>
+#include <libavutil/avassert.h>
+#include <libavutil/bprint.h>
+#include <libavutil/error.h>
+#include <libavutil/macros.h>
+#include <libavutil/opt.h>
+
+#define writer_w8(wctx_, b_) (wctx_)->writer->writer->writer_w8((wctx_)->writer, b_)
+#define writer_put_str(wctx_, str_) (wctx_)->writer->writer->writer_put_str((wctx_)->writer, str_)
+#define writer_printf(wctx_, fmt_, ...) (wctx_)->writer->writer->writer_printf((wctx_)->writer, fmt_, __VA_ARGS__)
+
+#define DEFINE_FORMATTER_CLASS(name) \
+static const char *name##_get_name(void *ctx) \
+{ \
+ return #name ; \
+} \
+static const AVClass name##_class = { \
+ .class_name = #name, \
+ .item_name = name##_get_name, \
+ .option = name##_options \
+}
+
+/* XML output */
+
+typedef struct XMLContext {
+ const AVClass *class;
+ int within_tag;
+ int indent_level;
+ int fully_qualified;
+ int xsd_strict;
+} XMLContext;
+
+#undef OFFSET
+#define OFFSET(x) offsetof(XMLContext, x)
+
+static const AVOption xml_options[] = {
+ {"fully_qualified", "specify if the output should be fully qualified", OFFSET(fully_qualified), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1 },
+ {"q", "specify if the output should be fully qualified", OFFSET(fully_qualified), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1 },
+ {"xsd_strict", "ensure that the output is XSD compliant", OFFSET(xsd_strict), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1 },
+ {"x", "ensure that the output is XSD compliant", OFFSET(xsd_strict), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1 },
+ {NULL},
+};
+
+DEFINE_FORMATTER_CLASS(xml);
+
+static av_cold int xml_init(AVTextFormatContext *wctx)
+{
+ XMLContext *xml = wctx->priv;
+
+ if (xml->xsd_strict) {
+ xml->fully_qualified = 1;
+#define CHECK_COMPLIANCE(opt, opt_name) \
+ if (opt) { \
+ av_log(wctx, AV_LOG_ERROR, \
+ "XSD-compliant output selected but option '%s' was selected, XML output may be non-compliant.\n" \
+ "You need to disable such option with '-no%s'\n", opt_name, opt_name); \
+ return AVERROR(EINVAL); \
+ }
+ ////CHECK_COMPLIANCE(show_private_data, "private");
+ CHECK_COMPLIANCE(wctx->show_value_unit, "unit");
+ CHECK_COMPLIANCE(wctx->use_value_prefix, "prefix");
+ }
+
+ return 0;
+}
+
+#define XML_INDENT() writer_printf(wctx, "%*c", xml->indent_level * 4, ' ')
+
+static void xml_print_section_header(AVTextFormatContext *wctx, const void *data)
+{
+ XMLContext *xml = wctx->priv;
+ const struct AVTextFormatSection *section = wctx->section[wctx->level];
+ const struct AVTextFormatSection *parent_section = wctx->level ?
+ wctx->section[wctx->level-1] : NULL;
+
+ if (wctx->level == 0) {
+ const char *qual = " xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" "
+ "xmlns:ffprobe=\"http://www.ffmpeg.org/schema/ffprobe\" "
+ "xsi:schemaLocation=\"http://www.ffmpeg.org/schema/ffprobe ffprobe.xsd\"";
+
+ writer_put_str(wctx, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
+ writer_printf(wctx, "<%sffprobe%s>\n",
+ xml->fully_qualified ? "ffprobe:" : "",
+ xml->fully_qualified ? qual : "");
+ return;
+ }
+
+ if (xml->within_tag) {
+ xml->within_tag = 0;
+ writer_put_str(wctx, ">\n");
+ }
+
+ if (parent_section && (parent_section->flags & AV_TEXTFORMAT_SECTION_FLAG_IS_WRAPPER) &&
+ wctx->level && wctx->nb_item[wctx->level-1])
+ writer_w8(wctx, '\n');
+ xml->indent_level++;
+
+ if (section->flags & (AV_TEXTFORMAT_SECTION_FLAG_IS_ARRAY|AV_TEXTFORMAT_SECTION_FLAG_HAS_VARIABLE_FIELDS)) {
+ XML_INDENT(); writer_printf(wctx, "<%s", section->name);
+
+ if (section->flags & AV_TEXTFORMAT_SECTION_FLAG_HAS_TYPE) {
+ AVBPrint buf;
+ av_bprint_init(&buf, 1, AV_BPRINT_SIZE_UNLIMITED);
+ av_bprint_escape(&buf, section->get_type(data), NULL,
+ AV_ESCAPE_MODE_XML, AV_ESCAPE_FLAG_XML_DOUBLE_QUOTES);
+ writer_printf(wctx, " type=\"%s\"", buf.str);
+ }
+ writer_printf(wctx, ">\n", section->name);
+ } else {
+ XML_INDENT(); writer_printf(wctx, "<%s ", section->name);
+ xml->within_tag = 1;
+ }
+}
+
+static void xml_print_section_footer(AVTextFormatContext *wctx)
+{
+ XMLContext *xml = wctx->priv;
+ const struct AVTextFormatSection *section = wctx->section[wctx->level];
+
+ if (wctx->level == 0) {
+ writer_printf(wctx, "</%sffprobe>\n", xml->fully_qualified ? "ffprobe:" : "");
+ } else if (xml->within_tag) {
+ xml->within_tag = 0;
+ writer_put_str(wctx, "/>\n");
+ xml->indent_level--;
+ } else {
+ XML_INDENT(); writer_printf(wctx, "</%s>\n", section->name);
+ xml->indent_level--;
+ }
+}
+
+static void xml_print_value(AVTextFormatContext *wctx, const char *key,
+ const char *str, int64_t num, const int is_int)
+{
+ AVBPrint buf;
+ XMLContext *xml = wctx->priv;
+ const struct AVTextFormatSection *section = wctx->section[wctx->level];
+
+ av_bprint_init(&buf, 1, AV_BPRINT_SIZE_UNLIMITED);
+
+ if (section->flags & AV_TEXTFORMAT_SECTION_FLAG_HAS_VARIABLE_FIELDS) {
+ xml->indent_level++;
+ XML_INDENT();
+ av_bprint_escape(&buf, key, NULL,
+ AV_ESCAPE_MODE_XML, AV_ESCAPE_FLAG_XML_DOUBLE_QUOTES);
+ writer_printf(wctx, "<%s key=\"%s\"",
+ section->element_name, buf.str);
+ av_bprint_clear(&buf);
+
+ if (is_int) {
+ writer_printf(wctx, " value=\"%"PRId64"\"/>\n", num);
+ } else {
+ av_bprint_escape(&buf, str, NULL,
+ AV_ESCAPE_MODE_XML, AV_ESCAPE_FLAG_XML_DOUBLE_QUOTES);
+ writer_printf(wctx, " value=\"%s\"/>\n", buf.str);
+ }
+ xml->indent_level--;
+ } else {
+ if (wctx->nb_item[wctx->level])
+ writer_w8(wctx, ' ');
+
+ if (is_int) {
+ writer_printf(wctx, "%s=\"%"PRId64"\"", key, num);
+ } else {
+ av_bprint_escape(&buf, str, NULL,
+ AV_ESCAPE_MODE_XML, AV_ESCAPE_FLAG_XML_DOUBLE_QUOTES);
+ writer_printf(wctx, "%s=\"%s\"", key, buf.str);
+ }
+ }
+
+ av_bprint_finalize(&buf, NULL);
+}
+
+static inline void xml_print_str(AVTextFormatContext *wctx, const char *key, const char *value) {
+ xml_print_value(wctx, key, value, 0, 0);
+}
+
+static void xml_print_int(AVTextFormatContext *wctx, const char *key, int64_t value)
+{
+ xml_print_value(wctx, key, NULL, value, 1);
+}
+
+const AVTextFormatter avtextformatter_xml = {
+ .name = "xml",
+ .priv_size = sizeof(XMLContext),
+ .init = xml_init,
+ .print_section_header = xml_print_section_header,
+ .print_section_footer = xml_print_section_footer,
+ .print_integer = xml_print_int,
+ .print_string = xml_print_str,
+ .flags = AV_TEXTFORMAT_FLAG_SUPPORTS_MIXED_ARRAY_CONTENT,
+ .priv_class = &xml_class,
+};
+
diff --git a/fftools/textformat/tw_avio.c b/fftools/textformat/tw_avio.c
new file mode 100644
index 0000000000..d335d35a56
--- /dev/null
+++ b/fftools/textformat/tw_avio.c
@@ -0,0 +1,129 @@
+/*
+ * Copyright (c) The FFmpeg developers
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <limits.h>
+#include <stdarg.h>
+
+#include "avtextwriters.h"
+#include "libavutil/opt.h"
+
+/* AVIO Writer */
+
+# define WRITER_NAME "aviowriter"
+
+typedef struct IOWriterContext {
+ const AVClass *class;
+ AVIOContext *avio_context;
+ int close_on_uninit;
+} IOWriterContext;
+
+static const char *iowriter_get_name(void *ctx)
+{
+ return WRITER_NAME;
+}
+
+static const AVClass iowriter_class = {
+ .class_name = WRITER_NAME,
+ .item_name = iowriter_get_name,
+};
+
+static av_cold void iowriter_uninit(AVTextWriterContext *wctx)
+{
+ IOWriterContext *ctx = wctx->priv;
+
+ if (ctx->close_on_uninit && ctx->avio_context) {
+ avio_flush(ctx->avio_context);
+ avio_close(ctx->avio_context);
+ }
+}
+
+static void io_w8(AVTextWriterContext *wctx, int b)
+{
+ IOWriterContext *ctx = wctx->priv;
+ avio_w8(ctx->avio_context, b);
+}
+
+static void io_put_str(AVTextWriterContext *wctx, const char *str)
+{
+ IOWriterContext *ctx = wctx->priv;
+ avio_write(ctx->avio_context, str, strlen(str));
+}
+
+static void io_printf(AVTextWriterContext *wctx, const char *fmt, ...)
+{
+ IOWriterContext *ctx = wctx->priv;
+ va_list ap;
+
+ va_start(ap, fmt);
+ avio_vprintf(ctx->avio_context, fmt, ap);
+ va_end(ap);
+}
+
+
+const AVTextWriter avtextwriter_avio = {
+ .name = WRITER_NAME,
+ .priv_size = sizeof(IOWriterContext),
+ .uninit = iowriter_uninit,
+ .priv_class = &iowriter_class,
+ .writer_put_str = io_put_str,
+ .writer_printf = io_printf,
+ .writer_w8 = io_w8
+};
+
+int avtextwriter_create_file(AVTextWriterContext **pwctx, const char *output_filename, int close_on_uninit)
+{
+ IOWriterContext *ctx;
+ int ret;
+
+
+ ret = avtextwriter_context_open(pwctx, &avtextwriter_avio);
+ if (ret < 0)
+ return ret;
+
+ ctx = (*pwctx)->priv;
+
+ if ((ret = avio_open(&ctx->avio_context, output_filename, AVIO_FLAG_WRITE)) < 0) {
+ av_log(ctx, AV_LOG_ERROR,
+ "Failed to open output '%s' with error: %s\n", output_filename, av_err2str(ret));
+ avtextwriter_context_close(pwctx);
+ return ret;
+ }
+
+ ctx->close_on_uninit = close_on_uninit;
+
+ return ret;
+}
+
+
+int avtextwriter_create_avio(AVTextWriterContext **pwctx, AVIOContext *avio_ctx, int close_on_uninit)
+{
+ IOWriterContext *ctx;
+ int ret;
+
+ ret = avtextwriter_context_open(pwctx, &avtextwriter_avio);
+ if (ret < 0)
+ return ret;
+
+ ctx = (*pwctx)->priv;
+ ctx->avio_context = avio_ctx;
+ ctx->close_on_uninit = close_on_uninit;
+
+ return ret;
+}
diff --git a/fftools/textformat/tw_buffer.c b/fftools/textformat/tw_buffer.c
new file mode 100644
index 0000000000..f8b38414a6
--- /dev/null
+++ b/fftools/textformat/tw_buffer.c
@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) The FFmpeg developers
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <limits.h>
+#include <stdarg.h>
+
+#include "avtextwriters.h"
+#include "libavutil/opt.h"
+#include "libavutil/bprint.h"
+
+/* Buffer Writer */
+
+# define WRITER_NAME "bufferwriter"
+
+typedef struct BufferWriterContext {
+ const AVClass *class;
+ AVBPrint *buffer;
+} BufferWriterContext;
+
+static const char *bufferwriter_get_name(void *ctx)
+{
+ return WRITER_NAME;
+}
+
+static const AVClass bufferwriter_class = {
+ .class_name = WRITER_NAME,
+ .item_name = bufferwriter_get_name,
+};
+
+static void buffer_w8(AVTextWriterContext *wctx, int b)
+{
+ BufferWriterContext *ctx = wctx->priv;
+ av_bprintf(ctx->buffer, "%c", b);
+}
+
+static void buffer_put_str(AVTextWriterContext *wctx, const char *str)
+{
+ BufferWriterContext *ctx = wctx->priv;
+ av_bprintf(ctx->buffer, "%s", str);
+}
+
+static void buffer_printf(AVTextWriterContext *wctx, const char *fmt, ...)
+{
+ BufferWriterContext *ctx = wctx->priv;
+
+ va_list vargs;
+ va_start(vargs, fmt);
+ av_vbprintf(ctx->buffer, fmt, vargs);
+ va_end(vargs);
+}
+
+
+const AVTextWriter avtextwriter_buffer = {
+ .name = WRITER_NAME,
+ .priv_size = sizeof(BufferWriterContext),
+ .priv_class = &bufferwriter_class,
+ .writer_put_str = buffer_put_str,
+ .writer_printf = buffer_printf,
+ .writer_w8 = buffer_w8
+};
+
+int avtextwriter_create_buffer(AVTextWriterContext **pwctx, AVBPrint *buffer)
+{
+ BufferWriterContext *ctx;
+ int ret;
+
+ ret = avtextwriter_context_open(pwctx, &avtextwriter_buffer);
+ if (ret < 0)
+ return ret;
+
+ ctx = (*pwctx)->priv;
+ ctx->buffer = buffer;
+
+ return ret;
+}
diff --git a/fftools/textformat/tw_stdout.c b/fftools/textformat/tw_stdout.c
new file mode 100644
index 0000000000..23de6f671f
--- /dev/null
+++ b/fftools/textformat/tw_stdout.c
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) The FFmpeg developers
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <stdarg.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "avtextwriters.h"
+#include "libavutil/opt.h"
+
+/* STDOUT Writer */
+
+# define WRITER_NAME "stdoutwriter"
+
+typedef struct StdOutWriterContext {
+ const AVClass *class;
+} StdOutWriterContext;
+
+static const char *stdoutwriter_get_name(void *ctx)
+{
+ return WRITER_NAME;
+}
+
+static const AVClass stdoutwriter_class = {
+ .class_name = WRITER_NAME,
+ .item_name = stdoutwriter_get_name,
+};
+
+static inline void stdout_w8(AVTextWriterContext *wctx, int b)
+{
+ printf("%c", b);
+}
+
+static inline void stdout_put_str(AVTextWriterContext *wctx, const char *str)
+{
+ printf("%s", str);
+}
+
+static inline void stdout_printf(AVTextWriterContext *wctx, const char *fmt, ...)
+{
+ va_list ap;
+
+ va_start(ap, fmt);
+ vprintf(fmt, ap);
+ va_end(ap);
+}
+
+
+static const AVTextWriter avtextwriter_stdout = {
+ .name = WRITER_NAME,
+ .priv_size = sizeof(StdOutWriterContext),
+ .priv_class = &stdoutwriter_class,
+ .writer_put_str = stdout_put_str,
+ .writer_printf = stdout_printf,
+ .writer_w8 = stdout_w8
+};
+
+int avtextwriter_create_stdout(AVTextWriterContext **pwctx)
+{
+ int ret;
+
+ ret = avtextwriter_context_open(pwctx, &avtextwriter_stdout);
+
+ return ret;
+}
--
ffmpeg-codebot
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 108+ messages in thread
* [FFmpeg-devel] [PATCH v7 2/7] fftools/ffprobe: Change to use textformat api
2025-03-12 4:04 ` [FFmpeg-devel] [PATCH v7 0/7] " ffmpegagent
2025-03-12 4:04 ` [FFmpeg-devel] [PATCH v7 1/7] fftools/textformat: Extract and generalize textformat api from ffprobe.c softworkz
@ 2025-03-12 4:04 ` softworkz
2025-03-13 11:55 ` Michael Niedermayer
2025-03-12 4:04 ` [FFmpeg-devel] [PATCH v7 3/7] fftools/ffprobe: Rename writer_print_section_* and WriterContext softworkz
` (5 subsequent siblings)
7 siblings, 1 reply; 108+ messages in thread
From: softworkz @ 2025-03-12 4:04 UTC (permalink / raw)
To: ffmpeg-devel; +Cc: softworkz
From: softworkz <softworkz@hotmail.com>
Signed-off-by: softworkz <softworkz@hotmail.com>
---
fftools/Makefile | 12 +
fftools/ffprobe.c | 1849 ++++-----------------------------------------
2 files changed, 142 insertions(+), 1719 deletions(-)
diff --git a/fftools/Makefile b/fftools/Makefile
index 4499799818..664b73b161 100644
--- a/fftools/Makefile
+++ b/fftools/Makefile
@@ -22,6 +22,18 @@ OBJS-ffmpeg += \
fftools/sync_queue.o \
fftools/thread_queue.o \
+OBJS-ffprobe += \
+ fftools/textformat/avtextformat.o \
+ fftools/textformat/tf_compact.o \
+ fftools/textformat/tf_default.o \
+ fftools/textformat/tf_flat.o \
+ fftools/textformat/tf_ini.o \
+ fftools/textformat/tf_json.o \
+ fftools/textformat/tf_xml.o \
+ fftools/textformat/tw_avio.o \
+ fftools/textformat/tw_buffer.o \
+ fftools/textformat/tw_stdout.o \
+
OBJS-ffplay += fftools/ffplay_renderer.o
define DOFFTOOL
diff --git a/fftools/ffprobe.c b/fftools/ffprobe.c
index 7341731d2f..f398057df7 100644
--- a/fftools/ffprobe.c
+++ b/fftools/ffprobe.c
@@ -40,7 +40,6 @@
#include "libavutil/channel_layout.h"
#include "libavutil/display.h"
#include "libavutil/film_grain_params.h"
-#include "libavutil/hash.h"
#include "libavutil/hdr_dynamic_metadata.h"
#include "libavutil/iamf.h"
#include "libavutil/mastering_display_metadata.h"
@@ -66,11 +65,17 @@
#include "libpostproc/postprocess.h"
#include "libpostproc/version.h"
#include "libavfilter/version.h"
+#include "textformat/avtextformat.h"
#include "cmdutils.h"
#include "opt_common.h"
#include "libavutil/thread.h"
+// TEMPORARY DEFINES
+#define writer_print_section_header(w, d, s) avtext_print_section_header(w, d, s)
+#define writer_print_section_footer(w) avtext_print_section_footer(w)
+#define WriterContext AVTextFormatContext
+
// attached as opaque_ref to packets/frames
typedef struct FrameData {
int64_t pkt_pos;
@@ -156,10 +161,7 @@ static int find_stream_info = 1;
/* section structure definition */
-#define SECTION_MAX_NB_CHILDREN 11
-
typedef enum {
- SECTION_ID_NONE = -1,
SECTION_ID_CHAPTER,
SECTION_ID_CHAPTER_TAGS,
SECTION_ID_CHAPTERS,
@@ -228,25 +230,6 @@ typedef enum {
SECTION_ID_SUBTITLE,
} SectionID;
-struct section {
- int id; ///< unique id identifying a section
- const char *name;
-
-#define SECTION_FLAG_IS_WRAPPER 1 ///< the section only contains other sections, but has no data at its own level
-#define SECTION_FLAG_IS_ARRAY 2 ///< the section contains an array of elements of the same type
-#define SECTION_FLAG_HAS_VARIABLE_FIELDS 4 ///< the section may contain a variable number of fields with variable keys.
- /// For these sections the element_name field is mandatory.
-#define SECTION_FLAG_HAS_TYPE 8 ///< the section contains a type to distinguish multiple nested elements
-
- int flags;
- const SectionID children_ids[SECTION_MAX_NB_CHILDREN+1]; ///< list of children section IDS, terminated by -1
- const char *element_name; ///< name of the contained element, if provided
- const char *unique_name; ///< unique section name, in case the name is ambiguous
- AVDictionary *entries_to_show;
- const char *(* get_type)(const void *data); ///< function returning a type if defined, must be defined when SECTION_FLAG_HAS_TYPE is defined
- int show_all_entries;
-};
-
static const char *get_packet_side_data_type(const void *data)
{
const AVPacketSideData *sd = (const AVPacketSideData *)data;
@@ -270,75 +253,75 @@ static const char *get_stream_group_type(const void *data)
return av_x_if_null(avformat_stream_group_name(stg->type), "unknown");
}
-static struct section sections[] = {
- [SECTION_ID_CHAPTERS] = { SECTION_ID_CHAPTERS, "chapters", SECTION_FLAG_IS_ARRAY, { SECTION_ID_CHAPTER, -1 } },
+static struct AVTextFormatSection sections[] = {
+ [SECTION_ID_CHAPTERS] = { SECTION_ID_CHAPTERS, "chapters", AV_TEXTFORMAT_SECTION_FLAG_IS_ARRAY, { SECTION_ID_CHAPTER, -1 } },
[SECTION_ID_CHAPTER] = { SECTION_ID_CHAPTER, "chapter", 0, { SECTION_ID_CHAPTER_TAGS, -1 } },
- [SECTION_ID_CHAPTER_TAGS] = { SECTION_ID_CHAPTER_TAGS, "tags", SECTION_FLAG_HAS_VARIABLE_FIELDS, { -1 }, .element_name = "tag", .unique_name = "chapter_tags" },
+ [SECTION_ID_CHAPTER_TAGS] = { SECTION_ID_CHAPTER_TAGS, "tags", AV_TEXTFORMAT_SECTION_FLAG_HAS_VARIABLE_FIELDS, { -1 }, .element_name = "tag", .unique_name = "chapter_tags" },
[SECTION_ID_ERROR] = { SECTION_ID_ERROR, "error", 0, { -1 } },
[SECTION_ID_FORMAT] = { SECTION_ID_FORMAT, "format", 0, { SECTION_ID_FORMAT_TAGS, -1 } },
- [SECTION_ID_FORMAT_TAGS] = { SECTION_ID_FORMAT_TAGS, "tags", SECTION_FLAG_HAS_VARIABLE_FIELDS, { -1 }, .element_name = "tag", .unique_name = "format_tags" },
- [SECTION_ID_FRAMES] = { SECTION_ID_FRAMES, "frames", SECTION_FLAG_IS_ARRAY, { SECTION_ID_FRAME, SECTION_ID_SUBTITLE, -1 } },
+ [SECTION_ID_FORMAT_TAGS] = { SECTION_ID_FORMAT_TAGS, "tags", AV_TEXTFORMAT_SECTION_FLAG_HAS_VARIABLE_FIELDS, { -1 }, .element_name = "tag", .unique_name = "format_tags" },
+ [SECTION_ID_FRAMES] = { SECTION_ID_FRAMES, "frames", AV_TEXTFORMAT_SECTION_FLAG_IS_ARRAY, { SECTION_ID_FRAME, SECTION_ID_SUBTITLE, -1 } },
[SECTION_ID_FRAME] = { SECTION_ID_FRAME, "frame", 0, { SECTION_ID_FRAME_TAGS, SECTION_ID_FRAME_SIDE_DATA_LIST, SECTION_ID_FRAME_LOGS, -1 } },
- [SECTION_ID_FRAME_TAGS] = { SECTION_ID_FRAME_TAGS, "tags", SECTION_FLAG_HAS_VARIABLE_FIELDS, { -1 }, .element_name = "tag", .unique_name = "frame_tags" },
- [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" },
- [SECTION_ID_FRAME_SIDE_DATA] = { SECTION_ID_FRAME_SIDE_DATA, "side_data", SECTION_FLAG_HAS_VARIABLE_FIELDS|SECTION_FLAG_HAS_TYPE, { SECTION_ID_FRAME_SIDE_DATA_TIMECODE_LIST, SECTION_ID_FRAME_SIDE_DATA_COMPONENT_LIST, -1 }, .unique_name = "frame_side_data", .element_name = "side_datum", .get_type = get_frame_side_data_type },
- [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 } },
+ [SECTION_ID_FRAME_TAGS] = { SECTION_ID_FRAME_TAGS, "tags", AV_TEXTFORMAT_SECTION_FLAG_HAS_VARIABLE_FIELDS, { -1 }, .element_name = "tag", .unique_name = "frame_tags" },
+ [SECTION_ID_FRAME_SIDE_DATA_LIST] ={ SECTION_ID_FRAME_SIDE_DATA_LIST, "side_data_list", AV_TEXTFORMAT_SECTION_FLAG_IS_ARRAY, { SECTION_ID_FRAME_SIDE_DATA, -1 }, .element_name = "side_data", .unique_name = "frame_side_data_list" },
+ [SECTION_ID_FRAME_SIDE_DATA] = { SECTION_ID_FRAME_SIDE_DATA, "side_data", AV_TEXTFORMAT_SECTION_FLAG_HAS_VARIABLE_FIELDS|AV_TEXTFORMAT_SECTION_FLAG_HAS_TYPE, { SECTION_ID_FRAME_SIDE_DATA_TIMECODE_LIST, SECTION_ID_FRAME_SIDE_DATA_COMPONENT_LIST, -1 }, .unique_name = "frame_side_data", .element_name = "side_datum", .get_type = get_frame_side_data_type },
+ [SECTION_ID_FRAME_SIDE_DATA_TIMECODE_LIST] = { SECTION_ID_FRAME_SIDE_DATA_TIMECODE_LIST, "timecodes", AV_TEXTFORMAT_SECTION_FLAG_IS_ARRAY, { SECTION_ID_FRAME_SIDE_DATA_TIMECODE, -1 } },
[SECTION_ID_FRAME_SIDE_DATA_TIMECODE] = { SECTION_ID_FRAME_SIDE_DATA_TIMECODE, "timecode", 0, { -1 } },
- [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 }, .element_name = "component", .unique_name = "frame_side_data_components" },
- [SECTION_ID_FRAME_SIDE_DATA_COMPONENT] = { SECTION_ID_FRAME_SIDE_DATA_COMPONENT, "component", SECTION_FLAG_HAS_VARIABLE_FIELDS|SECTION_FLAG_HAS_TYPE, { SECTION_ID_FRAME_SIDE_DATA_PIECE_LIST, -1 }, .unique_name = "frame_side_data_component", .element_name = "component_entry", .get_type = get_raw_string_type },
- [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 }, .element_name = "piece", .unique_name = "frame_side_data_pieces" },
- [SECTION_ID_FRAME_SIDE_DATA_PIECE] = { SECTION_ID_FRAME_SIDE_DATA_PIECE, "piece", SECTION_FLAG_HAS_VARIABLE_FIELDS|SECTION_FLAG_HAS_TYPE, { -1 }, .element_name = "piece_entry", .unique_name = "frame_side_data_piece", .get_type = get_raw_string_type },
- [SECTION_ID_FRAME_LOGS] = { SECTION_ID_FRAME_LOGS, "logs", SECTION_FLAG_IS_ARRAY, { SECTION_ID_FRAME_LOG, -1 } },
+ [SECTION_ID_FRAME_SIDE_DATA_COMPONENT_LIST] = { SECTION_ID_FRAME_SIDE_DATA_COMPONENT_LIST, "components", AV_TEXTFORMAT_SECTION_FLAG_IS_ARRAY, { SECTION_ID_FRAME_SIDE_DATA_COMPONENT, -1 }, .element_name = "component", .unique_name = "frame_side_data_components" },
+ [SECTION_ID_FRAME_SIDE_DATA_COMPONENT] = { SECTION_ID_FRAME_SIDE_DATA_COMPONENT, "component", AV_TEXTFORMAT_SECTION_FLAG_HAS_VARIABLE_FIELDS|AV_TEXTFORMAT_SECTION_FLAG_HAS_TYPE, { SECTION_ID_FRAME_SIDE_DATA_PIECE_LIST, -1 }, .unique_name = "frame_side_data_component", .element_name = "component_entry", .get_type = get_raw_string_type },
+ [SECTION_ID_FRAME_SIDE_DATA_PIECE_LIST] = { SECTION_ID_FRAME_SIDE_DATA_PIECE_LIST, "pieces", AV_TEXTFORMAT_SECTION_FLAG_IS_ARRAY, { SECTION_ID_FRAME_SIDE_DATA_PIECE, -1 }, .element_name = "piece", .unique_name = "frame_side_data_pieces" },
+ [SECTION_ID_FRAME_SIDE_DATA_PIECE] = { SECTION_ID_FRAME_SIDE_DATA_PIECE, "piece", AV_TEXTFORMAT_SECTION_FLAG_HAS_VARIABLE_FIELDS|AV_TEXTFORMAT_SECTION_FLAG_HAS_TYPE, { -1 }, .element_name = "piece_entry", .unique_name = "frame_side_data_piece", .get_type = get_raw_string_type },
+ [SECTION_ID_FRAME_LOGS] = { SECTION_ID_FRAME_LOGS, "logs", AV_TEXTFORMAT_SECTION_FLAG_IS_ARRAY, { SECTION_ID_FRAME_LOG, -1 } },
[SECTION_ID_FRAME_LOG] = { SECTION_ID_FRAME_LOG, "log", 0, { -1 }, },
- [SECTION_ID_LIBRARY_VERSIONS] = { SECTION_ID_LIBRARY_VERSIONS, "library_versions", SECTION_FLAG_IS_ARRAY, { SECTION_ID_LIBRARY_VERSION, -1 } },
+ [SECTION_ID_LIBRARY_VERSIONS] = { SECTION_ID_LIBRARY_VERSIONS, "library_versions", AV_TEXTFORMAT_SECTION_FLAG_IS_ARRAY, { SECTION_ID_LIBRARY_VERSION, -1 } },
[SECTION_ID_LIBRARY_VERSION] = { SECTION_ID_LIBRARY_VERSION, "library_version", 0, { -1 } },
- [SECTION_ID_PACKETS] = { SECTION_ID_PACKETS, "packets", SECTION_FLAG_IS_ARRAY, { SECTION_ID_PACKET, -1} },
- [SECTION_ID_PACKETS_AND_FRAMES] = { SECTION_ID_PACKETS_AND_FRAMES, "packets_and_frames", SECTION_FLAG_IS_ARRAY, { SECTION_ID_PACKET, -1} },
+ [SECTION_ID_PACKETS] = { SECTION_ID_PACKETS, "packets", AV_TEXTFORMAT_SECTION_FLAG_IS_ARRAY, { SECTION_ID_PACKET, -1} },
+ [SECTION_ID_PACKETS_AND_FRAMES] = { SECTION_ID_PACKETS_AND_FRAMES, "packets_and_frames", AV_TEXTFORMAT_SECTION_FLAG_IS_ARRAY | AV_TEXTFORMAT_SECTION_FLAG_NUMBERING_BY_TYPE, { SECTION_ID_PACKET, -1} },
[SECTION_ID_PACKET] = { SECTION_ID_PACKET, "packet", 0, { SECTION_ID_PACKET_TAGS, SECTION_ID_PACKET_SIDE_DATA_LIST, -1 } },
- [SECTION_ID_PACKET_TAGS] = { SECTION_ID_PACKET_TAGS, "tags", SECTION_FLAG_HAS_VARIABLE_FIELDS, { -1 }, .element_name = "tag", .unique_name = "packet_tags" },
- [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" },
- [SECTION_ID_PACKET_SIDE_DATA] = { SECTION_ID_PACKET_SIDE_DATA, "side_data", SECTION_FLAG_HAS_VARIABLE_FIELDS|SECTION_FLAG_HAS_TYPE, { -1 }, .unique_name = "packet_side_data", .element_name = "side_datum", .get_type = get_packet_side_data_type },
- [SECTION_ID_PIXEL_FORMATS] = { SECTION_ID_PIXEL_FORMATS, "pixel_formats", SECTION_FLAG_IS_ARRAY, { SECTION_ID_PIXEL_FORMAT, -1 } },
+ [SECTION_ID_PACKET_TAGS] = { SECTION_ID_PACKET_TAGS, "tags", AV_TEXTFORMAT_SECTION_FLAG_HAS_VARIABLE_FIELDS, { -1 }, .element_name = "tag", .unique_name = "packet_tags" },
+ [SECTION_ID_PACKET_SIDE_DATA_LIST] ={ SECTION_ID_PACKET_SIDE_DATA_LIST, "side_data_list", AV_TEXTFORMAT_SECTION_FLAG_IS_ARRAY, { SECTION_ID_PACKET_SIDE_DATA, -1 }, .element_name = "side_data", .unique_name = "packet_side_data_list" },
+ [SECTION_ID_PACKET_SIDE_DATA] = { SECTION_ID_PACKET_SIDE_DATA, "side_data", AV_TEXTFORMAT_SECTION_FLAG_HAS_VARIABLE_FIELDS|AV_TEXTFORMAT_SECTION_FLAG_HAS_TYPE, { -1 }, .unique_name = "packet_side_data", .element_name = "side_datum", .get_type = get_packet_side_data_type },
+ [SECTION_ID_PIXEL_FORMATS] = { SECTION_ID_PIXEL_FORMATS, "pixel_formats", AV_TEXTFORMAT_SECTION_FLAG_IS_ARRAY, { SECTION_ID_PIXEL_FORMAT, -1 } },
[SECTION_ID_PIXEL_FORMAT] = { SECTION_ID_PIXEL_FORMAT, "pixel_format", 0, { SECTION_ID_PIXEL_FORMAT_FLAGS, SECTION_ID_PIXEL_FORMAT_COMPONENTS, -1 } },
[SECTION_ID_PIXEL_FORMAT_FLAGS] = { SECTION_ID_PIXEL_FORMAT_FLAGS, "flags", 0, { -1 }, .unique_name = "pixel_format_flags" },
- [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" },
+ [SECTION_ID_PIXEL_FORMAT_COMPONENTS] = { SECTION_ID_PIXEL_FORMAT_COMPONENTS, "components", AV_TEXTFORMAT_SECTION_FLAG_IS_ARRAY, {SECTION_ID_PIXEL_FORMAT_COMPONENT, -1 }, .unique_name = "pixel_format_components" },
[SECTION_ID_PIXEL_FORMAT_COMPONENT] = { SECTION_ID_PIXEL_FORMAT_COMPONENT, "component", 0, { -1 } },
[SECTION_ID_PROGRAM_STREAM_DISPOSITION] = { SECTION_ID_PROGRAM_STREAM_DISPOSITION, "disposition", 0, { -1 }, .unique_name = "program_stream_disposition" },
- [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" },
+ [SECTION_ID_PROGRAM_STREAM_TAGS] = { SECTION_ID_PROGRAM_STREAM_TAGS, "tags", AV_TEXTFORMAT_SECTION_FLAG_HAS_VARIABLE_FIELDS, { -1 }, .element_name = "tag", .unique_name = "program_stream_tags" },
[SECTION_ID_PROGRAM] = { SECTION_ID_PROGRAM, "program", 0, { SECTION_ID_PROGRAM_TAGS, SECTION_ID_PROGRAM_STREAMS, -1 } },
- [SECTION_ID_PROGRAM_STREAMS] = { SECTION_ID_PROGRAM_STREAMS, "streams", SECTION_FLAG_IS_ARRAY, { SECTION_ID_PROGRAM_STREAM, -1 }, .unique_name = "program_streams" },
+ [SECTION_ID_PROGRAM_STREAMS] = { SECTION_ID_PROGRAM_STREAMS, "streams", AV_TEXTFORMAT_SECTION_FLAG_IS_ARRAY, { SECTION_ID_PROGRAM_STREAM, -1 }, .unique_name = "program_streams" },
[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" },
- [SECTION_ID_PROGRAM_TAGS] = { SECTION_ID_PROGRAM_TAGS, "tags", SECTION_FLAG_HAS_VARIABLE_FIELDS, { -1 }, .element_name = "tag", .unique_name = "program_tags" },
+ [SECTION_ID_PROGRAM_TAGS] = { SECTION_ID_PROGRAM_TAGS, "tags", AV_TEXTFORMAT_SECTION_FLAG_HAS_VARIABLE_FIELDS, { -1 }, .element_name = "tag", .unique_name = "program_tags" },
[SECTION_ID_PROGRAM_VERSION] = { SECTION_ID_PROGRAM_VERSION, "program_version", 0, { -1 } },
- [SECTION_ID_PROGRAMS] = { SECTION_ID_PROGRAMS, "programs", SECTION_FLAG_IS_ARRAY, { SECTION_ID_PROGRAM, -1 } },
+ [SECTION_ID_PROGRAMS] = { SECTION_ID_PROGRAMS, "programs", AV_TEXTFORMAT_SECTION_FLAG_IS_ARRAY, { SECTION_ID_PROGRAM, -1 } },
[SECTION_ID_STREAM_GROUP_STREAM_DISPOSITION] = { SECTION_ID_STREAM_GROUP_STREAM_DISPOSITION, "disposition", 0, { -1 }, .unique_name = "stream_group_stream_disposition" },
- [SECTION_ID_STREAM_GROUP_STREAM_TAGS] = { SECTION_ID_STREAM_GROUP_STREAM_TAGS, "tags", SECTION_FLAG_HAS_VARIABLE_FIELDS, { -1 }, .element_name = "tag", .unique_name = "stream_group_stream_tags" },
+ [SECTION_ID_STREAM_GROUP_STREAM_TAGS] = { SECTION_ID_STREAM_GROUP_STREAM_TAGS, "tags", AV_TEXTFORMAT_SECTION_FLAG_HAS_VARIABLE_FIELDS, { -1 }, .element_name = "tag", .unique_name = "stream_group_stream_tags" },
[SECTION_ID_STREAM_GROUP] = { SECTION_ID_STREAM_GROUP, "stream_group", 0, { SECTION_ID_STREAM_GROUP_TAGS, SECTION_ID_STREAM_GROUP_DISPOSITION, SECTION_ID_STREAM_GROUP_COMPONENTS, SECTION_ID_STREAM_GROUP_STREAMS, -1 } },
- [SECTION_ID_STREAM_GROUP_COMPONENTS] = { SECTION_ID_STREAM_GROUP_COMPONENTS, "components", SECTION_FLAG_IS_ARRAY, { SECTION_ID_STREAM_GROUP_COMPONENT, -1 }, .element_name = "component", .unique_name = "stream_group_components" },
- [SECTION_ID_STREAM_GROUP_COMPONENT] = { SECTION_ID_STREAM_GROUP_COMPONENT, "component", SECTION_FLAG_HAS_VARIABLE_FIELDS|SECTION_FLAG_HAS_TYPE, { SECTION_ID_STREAM_GROUP_SUBCOMPONENTS, -1 }, .unique_name = "stream_group_component", .element_name = "component_entry", .get_type = get_stream_group_type },
- [SECTION_ID_STREAM_GROUP_SUBCOMPONENTS] = { SECTION_ID_STREAM_GROUP_SUBCOMPONENTS, "subcomponents", SECTION_FLAG_IS_ARRAY, { SECTION_ID_STREAM_GROUP_SUBCOMPONENT, -1 }, .element_name = "component" },
- [SECTION_ID_STREAM_GROUP_SUBCOMPONENT] = { SECTION_ID_STREAM_GROUP_SUBCOMPONENT, "subcomponent", SECTION_FLAG_HAS_VARIABLE_FIELDS|SECTION_FLAG_HAS_TYPE, { SECTION_ID_STREAM_GROUP_PIECES, -1 }, .element_name = "subcomponent_entry", .get_type = get_raw_string_type },
- [SECTION_ID_STREAM_GROUP_PIECES] = { SECTION_ID_STREAM_GROUP_PIECES, "pieces", SECTION_FLAG_IS_ARRAY, { SECTION_ID_STREAM_GROUP_PIECE, -1 }, .element_name = "piece", .unique_name = "stream_group_pieces" },
- [SECTION_ID_STREAM_GROUP_PIECE] = { SECTION_ID_STREAM_GROUP_PIECE, "piece", SECTION_FLAG_HAS_VARIABLE_FIELDS|SECTION_FLAG_HAS_TYPE, { SECTION_ID_STREAM_GROUP_SUBPIECES, -1 }, .unique_name = "stream_group_piece", .element_name = "piece_entry", .get_type = get_raw_string_type },
- [SECTION_ID_STREAM_GROUP_SUBPIECES] = { SECTION_ID_STREAM_GROUP_SUBPIECES, "subpieces", SECTION_FLAG_IS_ARRAY, { SECTION_ID_STREAM_GROUP_SUBPIECE, -1 }, .element_name = "subpiece" },
- [SECTION_ID_STREAM_GROUP_SUBPIECE] = { SECTION_ID_STREAM_GROUP_SUBPIECE, "subpiece", SECTION_FLAG_HAS_VARIABLE_FIELDS|SECTION_FLAG_HAS_TYPE, { SECTION_ID_STREAM_GROUP_BLOCKS, -1 }, .element_name = "subpiece_entry", .get_type = get_raw_string_type },
- [SECTION_ID_STREAM_GROUP_BLOCKS] = { SECTION_ID_STREAM_GROUP_BLOCKS, "blocks", SECTION_FLAG_IS_ARRAY, { SECTION_ID_STREAM_GROUP_BLOCK, -1 }, .element_name = "block" },
- [SECTION_ID_STREAM_GROUP_BLOCK] = { SECTION_ID_STREAM_GROUP_BLOCK, "block", SECTION_FLAG_HAS_VARIABLE_FIELDS|SECTION_FLAG_HAS_TYPE, { -1 }, .element_name = "block_entry", .get_type = get_raw_string_type },
- [SECTION_ID_STREAM_GROUP_STREAMS] = { SECTION_ID_STREAM_GROUP_STREAMS, "streams", SECTION_FLAG_IS_ARRAY, { SECTION_ID_STREAM_GROUP_STREAM, -1 }, .unique_name = "stream_group_streams" },
+ [SECTION_ID_STREAM_GROUP_COMPONENTS] = { SECTION_ID_STREAM_GROUP_COMPONENTS, "components", AV_TEXTFORMAT_SECTION_FLAG_IS_ARRAY, { SECTION_ID_STREAM_GROUP_COMPONENT, -1 }, .element_name = "component", .unique_name = "stream_group_components" },
+ [SECTION_ID_STREAM_GROUP_COMPONENT] = { SECTION_ID_STREAM_GROUP_COMPONENT, "component", AV_TEXTFORMAT_SECTION_FLAG_HAS_VARIABLE_FIELDS|AV_TEXTFORMAT_SECTION_FLAG_HAS_TYPE, { SECTION_ID_STREAM_GROUP_SUBCOMPONENTS, -1 }, .unique_name = "stream_group_component", .element_name = "component_entry", .get_type = get_stream_group_type },
+ [SECTION_ID_STREAM_GROUP_SUBCOMPONENTS] = { SECTION_ID_STREAM_GROUP_SUBCOMPONENTS, "subcomponents", AV_TEXTFORMAT_SECTION_FLAG_IS_ARRAY, { SECTION_ID_STREAM_GROUP_SUBCOMPONENT, -1 }, .element_name = "component" },
+ [SECTION_ID_STREAM_GROUP_SUBCOMPONENT] = { SECTION_ID_STREAM_GROUP_SUBCOMPONENT, "subcomponent", AV_TEXTFORMAT_SECTION_FLAG_HAS_VARIABLE_FIELDS|AV_TEXTFORMAT_SECTION_FLAG_HAS_TYPE, { SECTION_ID_STREAM_GROUP_PIECES, -1 }, .element_name = "subcomponent_entry", .get_type = get_raw_string_type },
+ [SECTION_ID_STREAM_GROUP_PIECES] = { SECTION_ID_STREAM_GROUP_PIECES, "pieces", AV_TEXTFORMAT_SECTION_FLAG_IS_ARRAY, { SECTION_ID_STREAM_GROUP_PIECE, -1 }, .element_name = "piece", .unique_name = "stream_group_pieces" },
+ [SECTION_ID_STREAM_GROUP_PIECE] = { SECTION_ID_STREAM_GROUP_PIECE, "piece", AV_TEXTFORMAT_SECTION_FLAG_HAS_VARIABLE_FIELDS|AV_TEXTFORMAT_SECTION_FLAG_HAS_TYPE, { SECTION_ID_STREAM_GROUP_SUBPIECES, -1 }, .unique_name = "stream_group_piece", .element_name = "piece_entry", .get_type = get_raw_string_type },
+ [SECTION_ID_STREAM_GROUP_SUBPIECES] = { SECTION_ID_STREAM_GROUP_SUBPIECES, "subpieces", AV_TEXTFORMAT_SECTION_FLAG_IS_ARRAY, { SECTION_ID_STREAM_GROUP_SUBPIECE, -1 }, .element_name = "subpiece" },
+ [SECTION_ID_STREAM_GROUP_SUBPIECE] = { SECTION_ID_STREAM_GROUP_SUBPIECE, "subpiece", AV_TEXTFORMAT_SECTION_FLAG_HAS_VARIABLE_FIELDS|AV_TEXTFORMAT_SECTION_FLAG_HAS_TYPE, { SECTION_ID_STREAM_GROUP_BLOCKS, -1 }, .element_name = "subpiece_entry", .get_type = get_raw_string_type },
+ [SECTION_ID_STREAM_GROUP_BLOCKS] = { SECTION_ID_STREAM_GROUP_BLOCKS, "blocks", AV_TEXTFORMAT_SECTION_FLAG_IS_ARRAY, { SECTION_ID_STREAM_GROUP_BLOCK, -1 }, .element_name = "block" },
+ [SECTION_ID_STREAM_GROUP_BLOCK] = { SECTION_ID_STREAM_GROUP_BLOCK, "block", AV_TEXTFORMAT_SECTION_FLAG_HAS_VARIABLE_FIELDS|AV_TEXTFORMAT_SECTION_FLAG_HAS_TYPE, { -1 }, .element_name = "block_entry", .get_type = get_raw_string_type },
+ [SECTION_ID_STREAM_GROUP_STREAMS] = { SECTION_ID_STREAM_GROUP_STREAMS, "streams", AV_TEXTFORMAT_SECTION_FLAG_IS_ARRAY, { SECTION_ID_STREAM_GROUP_STREAM, -1 }, .unique_name = "stream_group_streams" },
[SECTION_ID_STREAM_GROUP_STREAM] = { SECTION_ID_STREAM_GROUP_STREAM, "stream", 0, { SECTION_ID_STREAM_GROUP_STREAM_DISPOSITION, SECTION_ID_STREAM_GROUP_STREAM_TAGS, -1 }, .unique_name = "stream_group_stream" },
[SECTION_ID_STREAM_GROUP_DISPOSITION] = { SECTION_ID_STREAM_GROUP_DISPOSITION, "disposition", 0, { -1 }, .unique_name = "stream_group_disposition" },
- [SECTION_ID_STREAM_GROUP_TAGS] = { SECTION_ID_STREAM_GROUP_TAGS, "tags", SECTION_FLAG_HAS_VARIABLE_FIELDS, { -1 }, .element_name = "tag", .unique_name = "stream_group_tags" },
- [SECTION_ID_STREAM_GROUPS] = { SECTION_ID_STREAM_GROUPS, "stream_groups", SECTION_FLAG_IS_ARRAY, { SECTION_ID_STREAM_GROUP, -1 } },
- [SECTION_ID_ROOT] = { SECTION_ID_ROOT, "root", SECTION_FLAG_IS_WRAPPER,
+ [SECTION_ID_STREAM_GROUP_TAGS] = { SECTION_ID_STREAM_GROUP_TAGS, "tags", AV_TEXTFORMAT_SECTION_FLAG_HAS_VARIABLE_FIELDS, { -1 }, .element_name = "tag", .unique_name = "stream_group_tags" },
+ [SECTION_ID_STREAM_GROUPS] = { SECTION_ID_STREAM_GROUPS, "stream_groups", AV_TEXTFORMAT_SECTION_FLAG_IS_ARRAY, { SECTION_ID_STREAM_GROUP, -1 } },
+ [SECTION_ID_ROOT] = { SECTION_ID_ROOT, "root", AV_TEXTFORMAT_SECTION_FLAG_IS_WRAPPER,
{ SECTION_ID_CHAPTERS, SECTION_ID_FORMAT, SECTION_ID_FRAMES, SECTION_ID_PROGRAMS, SECTION_ID_STREAM_GROUPS, SECTION_ID_STREAMS,
SECTION_ID_PACKETS, SECTION_ID_ERROR, SECTION_ID_PROGRAM_VERSION, SECTION_ID_LIBRARY_VERSIONS,
SECTION_ID_PIXEL_FORMATS, -1} },
- [SECTION_ID_STREAMS] = { SECTION_ID_STREAMS, "streams", SECTION_FLAG_IS_ARRAY, { SECTION_ID_STREAM, -1 } },
+ [SECTION_ID_STREAMS] = { SECTION_ID_STREAMS, "streams", AV_TEXTFORMAT_SECTION_FLAG_IS_ARRAY, { SECTION_ID_STREAM, -1 } },
[SECTION_ID_STREAM] = { SECTION_ID_STREAM, "stream", 0, { SECTION_ID_STREAM_DISPOSITION, SECTION_ID_STREAM_TAGS, SECTION_ID_STREAM_SIDE_DATA_LIST, -1 } },
[SECTION_ID_STREAM_DISPOSITION] = { SECTION_ID_STREAM_DISPOSITION, "disposition", 0, { -1 }, .unique_name = "stream_disposition" },
- [SECTION_ID_STREAM_TAGS] = { SECTION_ID_STREAM_TAGS, "tags", SECTION_FLAG_HAS_VARIABLE_FIELDS, { -1 }, .element_name = "tag", .unique_name = "stream_tags" },
- [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" },
- [SECTION_ID_STREAM_SIDE_DATA] = { SECTION_ID_STREAM_SIDE_DATA, "side_data", SECTION_FLAG_HAS_TYPE|SECTION_FLAG_HAS_VARIABLE_FIELDS, { -1 }, .unique_name = "stream_side_data", .element_name = "side_datum", .get_type = get_packet_side_data_type },
+ [SECTION_ID_STREAM_TAGS] = { SECTION_ID_STREAM_TAGS, "tags", AV_TEXTFORMAT_SECTION_FLAG_HAS_VARIABLE_FIELDS, { -1 }, .element_name = "tag", .unique_name = "stream_tags" },
+ [SECTION_ID_STREAM_SIDE_DATA_LIST] ={ SECTION_ID_STREAM_SIDE_DATA_LIST, "side_data_list", AV_TEXTFORMAT_SECTION_FLAG_IS_ARRAY, { SECTION_ID_STREAM_SIDE_DATA, -1 }, .element_name = "side_data", .unique_name = "stream_side_data_list" },
+ [SECTION_ID_STREAM_SIDE_DATA] = { SECTION_ID_STREAM_SIDE_DATA, "side_data", AV_TEXTFORMAT_SECTION_FLAG_HAS_TYPE|AV_TEXTFORMAT_SECTION_FLAG_HAS_VARIABLE_FIELDS, { -1 }, .unique_name = "stream_side_data", .element_name = "side_datum", .get_type = get_packet_side_data_type },
[SECTION_ID_SUBTITLE] = { SECTION_ID_SUBTITLE, "subtitle", 0, { -1 } },
};
@@ -350,22 +333,6 @@ static const char *print_input_filename;
static const AVInputFormat *iformat = NULL;
static const char *output_filename = NULL;
-static struct AVHashContext *hash;
-
-static const struct {
- double bin_val;
- double dec_val;
- const char *bin_str;
- const char *dec_str;
-} si_prefixes[] = {
- { 1.0, 1.0, "", "" },
- { 1.024e3, 1e3, "Ki", "K" },
- { 1.048576e6, 1e6, "Mi", "M" },
- { 1.073741824e9, 1e9, "Gi", "G" },
- { 1.099511627776e12, 1e12, "Ti", "T" },
- { 1.125899906842624e15, 1e15, "Pi", "P" },
-};
-
static const char unit_second_str[] = "s" ;
static const char unit_hertz_str[] = "Hz" ;
static const char unit_byte_str[] = "byte" ;
@@ -441,1554 +408,11 @@ static void log_callback(void *ptr, int level, const char *fmt, va_list vl)
#endif
}
-struct unit_value {
- union { double d; int64_t i; } val;
- const char *unit;
-};
-
-static char *value_string(char *buf, int buf_size, struct unit_value uv)
-{
- double vald;
- int64_t vali;
- int show_float = 0;
-
- if (uv.unit == unit_second_str) {
- vald = uv.val.d;
- show_float = 1;
- } else {
- vald = vali = uv.val.i;
- }
-
- if (uv.unit == unit_second_str && use_value_sexagesimal_format) {
- double secs;
- int hours, mins;
- secs = vald;
- mins = (int)secs / 60;
- secs = secs - mins * 60;
- hours = mins / 60;
- mins %= 60;
- snprintf(buf, buf_size, "%d:%02d:%09.6f", hours, mins, secs);
- } else {
- const char *prefix_string = "";
-
- if (use_value_prefix && vald > 1) {
- int64_t index;
-
- if (uv.unit == unit_byte_str && use_byte_value_binary_prefix) {
- index = (int64_t) (log2(vald)) / 10;
- index = av_clip(index, 0, FF_ARRAY_ELEMS(si_prefixes) - 1);
- vald /= si_prefixes[index].bin_val;
- prefix_string = si_prefixes[index].bin_str;
- } else {
- index = (int64_t) (log10(vald)) / 3;
- index = av_clip(index, 0, FF_ARRAY_ELEMS(si_prefixes) - 1);
- vald /= si_prefixes[index].dec_val;
- prefix_string = si_prefixes[index].dec_str;
- }
- vali = vald;
- }
-
- if (show_float || (use_value_prefix && vald != (int64_t)vald))
- snprintf(buf, buf_size, "%f", vald);
- else
- snprintf(buf, buf_size, "%"PRId64, vali);
- av_strlcatf(buf, buf_size, "%s%s%s", *prefix_string || show_value_unit ? " " : "",
- prefix_string, show_value_unit ? uv.unit : "");
- }
-
- return buf;
-}
-
-/* WRITERS API */
-
-typedef struct WriterContext WriterContext;
-
-#define WRITER_FLAG_DISPLAY_OPTIONAL_FIELDS 1
-#define WRITER_FLAG_PUT_PACKETS_AND_FRAMES_IN_SAME_CHAPTER 2
-
-typedef enum {
- WRITER_STRING_VALIDATION_FAIL,
- WRITER_STRING_VALIDATION_REPLACE,
- WRITER_STRING_VALIDATION_IGNORE,
- WRITER_STRING_VALIDATION_NB
-} StringValidation;
-
-typedef struct Writer {
- const AVClass *priv_class; ///< private class of the writer, if any
- int priv_size; ///< private size for the writer context
- const char *name;
-
- int (*init) (WriterContext *wctx);
- void (*uninit)(WriterContext *wctx);
-
- void (*print_section_header)(WriterContext *wctx, const void *data);
- void (*print_section_footer)(WriterContext *wctx);
- void (*print_integer) (WriterContext *wctx, const char *, int64_t);
- void (*print_rational) (WriterContext *wctx, AVRational *q, char *sep);
- void (*print_string) (WriterContext *wctx, const char *, const char *);
- int flags; ///< a combination or WRITER_FLAG_*
-} Writer;
-
-#define SECTION_MAX_NB_LEVELS 12
-
-struct WriterContext {
- const AVClass *class; ///< class of the writer
- const Writer *writer; ///< the Writer of which this is an instance
- AVIOContext *avio; ///< the I/O context used to write
-
- void (* writer_w8)(WriterContext *wctx, int b);
- void (* writer_put_str)(WriterContext *wctx, const char *str);
- void (* writer_printf)(WriterContext *wctx, const char *fmt, ...);
-
- char *name; ///< name of this writer instance
- void *priv; ///< private data for use by the filter
-
- const struct section *sections; ///< array containing all sections
- int nb_sections; ///< number of sections
-
- int level; ///< current level, starting from 0
-
- /** number of the item printed in the given section, starting from 0 */
- unsigned int nb_item[SECTION_MAX_NB_LEVELS];
-
- /** section per each level */
- const struct section *section[SECTION_MAX_NB_LEVELS];
- AVBPrint section_pbuf[SECTION_MAX_NB_LEVELS]; ///< generic print buffer dedicated to each section,
- /// used by various writers
-
- unsigned int nb_section_packet; ///< number of the packet section in case we are in "packets_and_frames" section
- unsigned int nb_section_frame; ///< number of the frame section in case we are in "packets_and_frames" section
- unsigned int nb_section_packet_frame; ///< nb_section_packet or nb_section_frame according if is_packets_and_frames
-
- int string_validation;
- char *string_validation_replacement;
- unsigned int string_validation_utf8_flags;
-};
-
-static const char *writer_get_name(void *p)
-{
- WriterContext *wctx = p;
- return wctx->writer->name;
-}
-
-#define OFFSET(x) offsetof(WriterContext, x)
-
-static const AVOption writer_options[] = {
- { "string_validation", "set string validation mode",
- OFFSET(string_validation), AV_OPT_TYPE_INT, {.i64=WRITER_STRING_VALIDATION_REPLACE}, 0, WRITER_STRING_VALIDATION_NB-1, .unit = "sv" },
- { "sv", "set string validation mode",
- OFFSET(string_validation), AV_OPT_TYPE_INT, {.i64=WRITER_STRING_VALIDATION_REPLACE}, 0, WRITER_STRING_VALIDATION_NB-1, .unit = "sv" },
- { "ignore", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = WRITER_STRING_VALIDATION_IGNORE}, .unit = "sv" },
- { "replace", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = WRITER_STRING_VALIDATION_REPLACE}, .unit = "sv" },
- { "fail", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = WRITER_STRING_VALIDATION_FAIL}, .unit = "sv" },
- { "string_validation_replacement", "set string validation replacement string", OFFSET(string_validation_replacement), AV_OPT_TYPE_STRING, {.str=""}},
- { "svr", "set string validation replacement string", OFFSET(string_validation_replacement), AV_OPT_TYPE_STRING, {.str="\xEF\xBF\xBD"}},
- { NULL }
-};
-
-static void *writer_child_next(void *obj, void *prev)
-{
- WriterContext *ctx = obj;
- if (!prev && ctx->writer && ctx->writer->priv_class && ctx->priv)
- return ctx->priv;
- return NULL;
-}
-
-static const AVClass writer_class = {
- .class_name = "Writer",
- .item_name = writer_get_name,
- .option = writer_options,
- .version = LIBAVUTIL_VERSION_INT,
- .child_next = writer_child_next,
-};
-
-static int writer_close(WriterContext **wctx)
-{
- int i;
- int ret = 0;
-
- if (!*wctx)
- return -1;
-
- if ((*wctx)->writer->uninit)
- (*wctx)->writer->uninit(*wctx);
- for (i = 0; i < SECTION_MAX_NB_LEVELS; i++)
- av_bprint_finalize(&(*wctx)->section_pbuf[i], NULL);
- if ((*wctx)->writer->priv_class)
- av_opt_free((*wctx)->priv);
- av_freep(&((*wctx)->priv));
- av_opt_free(*wctx);
- if ((*wctx)->avio) {
- avio_flush((*wctx)->avio);
- ret = avio_close((*wctx)->avio);
- }
- av_freep(wctx);
- return ret;
-}
-
-static void bprint_bytes(AVBPrint *bp, const uint8_t *ubuf, size_t ubuf_size)
-{
- int i;
- av_bprintf(bp, "0X");
- for (i = 0; i < ubuf_size; i++)
- av_bprintf(bp, "%02X", ubuf[i]);
-}
-
-static inline void writer_w8_avio(WriterContext *wctx, int b)
-{
- avio_w8(wctx->avio, b);
-}
-
-static inline void writer_put_str_avio(WriterContext *wctx, const char *str)
-{
- avio_write(wctx->avio, str, strlen(str));
-}
-
-static inline void writer_printf_avio(WriterContext *wctx, const char *fmt, ...)
-{
- va_list ap;
-
- va_start(ap, fmt);
- avio_vprintf(wctx->avio, fmt, ap);
- va_end(ap);
-}
-
-static inline void writer_w8_printf(WriterContext *wctx, int b)
-{
- printf("%c", b);
-}
-
-static inline void writer_put_str_printf(WriterContext *wctx, const char *str)
-{
- printf("%s", str);
-}
-
-static inline void writer_printf_printf(WriterContext *wctx, const char *fmt, ...)
-{
- va_list ap;
-
- va_start(ap, fmt);
- vprintf(fmt, ap);
- va_end(ap);
-}
-
-static int writer_open(WriterContext **wctx, const Writer *writer, const char *args,
- const struct section *sections, int nb_sections, const char *output)
-{
- int i, ret = 0;
-
- if (!(*wctx = av_mallocz(sizeof(WriterContext)))) {
- ret = AVERROR(ENOMEM);
- goto fail;
- }
-
- if (!((*wctx)->priv = av_mallocz(writer->priv_size))) {
- ret = AVERROR(ENOMEM);
- goto fail;
- }
-
- (*wctx)->class = &writer_class;
- (*wctx)->writer = writer;
- (*wctx)->level = -1;
- (*wctx)->sections = sections;
- (*wctx)->nb_sections = nb_sections;
-
- av_opt_set_defaults(*wctx);
-
- if (writer->priv_class) {
- void *priv_ctx = (*wctx)->priv;
- *((const AVClass **)priv_ctx) = writer->priv_class;
- av_opt_set_defaults(priv_ctx);
- }
-
- /* convert options to dictionary */
- if (args) {
- AVDictionary *opts = NULL;
- const AVDictionaryEntry *opt = NULL;
-
- if ((ret = av_dict_parse_string(&opts, args, "=", ":", 0)) < 0) {
- av_log(*wctx, AV_LOG_ERROR, "Failed to parse option string '%s' provided to writer context\n", args);
- av_dict_free(&opts);
- goto fail;
- }
-
- while ((opt = av_dict_iterate(opts, opt))) {
- if ((ret = av_opt_set(*wctx, opt->key, opt->value, AV_OPT_SEARCH_CHILDREN)) < 0) {
- av_log(*wctx, AV_LOG_ERROR, "Failed to set option '%s' with value '%s' provided to writer context\n",
- opt->key, opt->value);
- av_dict_free(&opts);
- goto fail;
- }
- }
-
- av_dict_free(&opts);
- }
-
- /* validate replace string */
- {
- const uint8_t *p = (*wctx)->string_validation_replacement;
- const uint8_t *endp = p + strlen(p);
- while (*p) {
- const uint8_t *p0 = p;
- int32_t code;
- ret = av_utf8_decode(&code, &p, endp, (*wctx)->string_validation_utf8_flags);
- if (ret < 0) {
- AVBPrint bp;
- av_bprint_init(&bp, 0, AV_BPRINT_SIZE_AUTOMATIC);
- bprint_bytes(&bp, p0, p-p0),
- av_log(wctx, AV_LOG_ERROR,
- "Invalid UTF8 sequence %s found in string validation replace '%s'\n",
- bp.str, (*wctx)->string_validation_replacement);
- return ret;
- }
- }
- }
-
- if (!output_filename) {
- (*wctx)->writer_w8 = writer_w8_printf;
- (*wctx)->writer_put_str = writer_put_str_printf;
- (*wctx)->writer_printf = writer_printf_printf;
- } else {
- if ((ret = avio_open(&(*wctx)->avio, output, AVIO_FLAG_WRITE)) < 0) {
- av_log(*wctx, AV_LOG_ERROR,
- "Failed to open output '%s' with error: %s\n", output, av_err2str(ret));
- goto fail;
- }
- (*wctx)->writer_w8 = writer_w8_avio;
- (*wctx)->writer_put_str = writer_put_str_avio;
- (*wctx)->writer_printf = writer_printf_avio;
- }
-
- for (i = 0; i < SECTION_MAX_NB_LEVELS; i++)
- av_bprint_init(&(*wctx)->section_pbuf[i], 1, AV_BPRINT_SIZE_UNLIMITED);
-
- if ((*wctx)->writer->init)
- ret = (*wctx)->writer->init(*wctx);
- if (ret < 0)
- goto fail;
-
- return 0;
-
-fail:
- writer_close(wctx);
- return ret;
-}
-
-static inline void writer_print_section_header(WriterContext *wctx,
- const void *data,
- int section_id)
-{
- int parent_section_id;
- wctx->level++;
- av_assert0(wctx->level < SECTION_MAX_NB_LEVELS);
- parent_section_id = wctx->level ?
- (wctx->section[wctx->level-1])->id : SECTION_ID_NONE;
-
- wctx->nb_item[wctx->level] = 0;
- wctx->section[wctx->level] = &wctx->sections[section_id];
-
- if (section_id == SECTION_ID_PACKETS_AND_FRAMES) {
- wctx->nb_section_packet = wctx->nb_section_frame =
- wctx->nb_section_packet_frame = 0;
- } else if (parent_section_id == SECTION_ID_PACKETS_AND_FRAMES) {
- wctx->nb_section_packet_frame = section_id == SECTION_ID_PACKET ?
- wctx->nb_section_packet : wctx->nb_section_frame;
- }
-
- if (wctx->writer->print_section_header)
- wctx->writer->print_section_header(wctx, data);
-}
-
-static inline void writer_print_section_footer(WriterContext *wctx)
-{
- int section_id = wctx->section[wctx->level]->id;
- int parent_section_id = wctx->level ?
- wctx->section[wctx->level-1]->id : SECTION_ID_NONE;
-
- if (parent_section_id != SECTION_ID_NONE)
- wctx->nb_item[wctx->level-1]++;
- if (parent_section_id == SECTION_ID_PACKETS_AND_FRAMES) {
- if (section_id == SECTION_ID_PACKET) wctx->nb_section_packet++;
- else wctx->nb_section_frame++;
- }
- if (wctx->writer->print_section_footer)
- wctx->writer->print_section_footer(wctx);
- wctx->level--;
-}
-
-static inline void writer_print_integer(WriterContext *wctx,
- const char *key, int64_t val)
-{
- const struct section *section = wctx->section[wctx->level];
-
- if (section->show_all_entries || av_dict_get(section->entries_to_show, key, NULL, 0)) {
- wctx->writer->print_integer(wctx, key, val);
- wctx->nb_item[wctx->level]++;
- }
-}
-
-static inline int validate_string(WriterContext *wctx, char **dstp, const char *src)
-{
- const uint8_t *p, *endp;
- AVBPrint dstbuf;
- int invalid_chars_nb = 0, ret = 0;
-
- av_bprint_init(&dstbuf, 0, AV_BPRINT_SIZE_UNLIMITED);
-
- endp = src + strlen(src);
- for (p = src; *p;) {
- uint32_t code;
- int invalid = 0;
- const uint8_t *p0 = p;
-
- if (av_utf8_decode(&code, &p, endp, wctx->string_validation_utf8_flags) < 0) {
- AVBPrint bp;
- av_bprint_init(&bp, 0, AV_BPRINT_SIZE_AUTOMATIC);
- bprint_bytes(&bp, p0, p-p0);
- av_log(wctx, AV_LOG_DEBUG,
- "Invalid UTF-8 sequence %s found in string '%s'\n", bp.str, src);
- invalid = 1;
- }
-
- if (invalid) {
- invalid_chars_nb++;
-
- switch (wctx->string_validation) {
- case WRITER_STRING_VALIDATION_FAIL:
- av_log(wctx, AV_LOG_ERROR,
- "Invalid UTF-8 sequence found in string '%s'\n", src);
- ret = AVERROR_INVALIDDATA;
- goto end;
- break;
-
- case WRITER_STRING_VALIDATION_REPLACE:
- av_bprintf(&dstbuf, "%s", wctx->string_validation_replacement);
- break;
- }
- }
-
- if (!invalid || wctx->string_validation == WRITER_STRING_VALIDATION_IGNORE)
- av_bprint_append_data(&dstbuf, p0, p-p0);
- }
-
- if (invalid_chars_nb && wctx->string_validation == WRITER_STRING_VALIDATION_REPLACE) {
- av_log(wctx, AV_LOG_WARNING,
- "%d invalid UTF-8 sequence(s) found in string '%s', replaced with '%s'\n",
- invalid_chars_nb, src, wctx->string_validation_replacement);
- }
-
-end:
- av_bprint_finalize(&dstbuf, dstp);
- return ret;
-}
-
-#define PRINT_STRING_OPT 1
-#define PRINT_STRING_VALIDATE 2
-
-static inline int writer_print_string(WriterContext *wctx,
- const char *key, const char *val, int flags)
-{
- const struct section *section = wctx->section[wctx->level];
- int ret = 0;
-
- if (show_optional_fields == SHOW_OPTIONAL_FIELDS_NEVER ||
- (show_optional_fields == SHOW_OPTIONAL_FIELDS_AUTO
- && (flags & PRINT_STRING_OPT)
- && !(wctx->writer->flags & WRITER_FLAG_DISPLAY_OPTIONAL_FIELDS)))
- return 0;
-
- if (section->show_all_entries || av_dict_get(section->entries_to_show, key, NULL, 0)) {
- if (flags & PRINT_STRING_VALIDATE) {
- char *key1 = NULL, *val1 = NULL;
- ret = validate_string(wctx, &key1, key);
- if (ret < 0) goto end;
- ret = validate_string(wctx, &val1, val);
- if (ret < 0) goto end;
- wctx->writer->print_string(wctx, key1, val1);
- end:
- if (ret < 0) {
- av_log(wctx, AV_LOG_ERROR,
- "Invalid key=value string combination %s=%s in section %s\n",
- key, val, section->unique_name);
- }
- av_free(key1);
- av_free(val1);
- } else {
- wctx->writer->print_string(wctx, key, val);
- }
-
- wctx->nb_item[wctx->level]++;
- }
-
- return ret;
-}
-
-static inline void writer_print_rational(WriterContext *wctx,
- const char *key, AVRational q, char sep)
-{
- AVBPrint buf;
- av_bprint_init(&buf, 0, AV_BPRINT_SIZE_AUTOMATIC);
- av_bprintf(&buf, "%d%c%d", q.num, sep, q.den);
- writer_print_string(wctx, key, buf.str, 0);
-}
-
-static void writer_print_time(WriterContext *wctx, const char *key,
- int64_t ts, const AVRational *time_base, int is_duration)
-{
- char buf[128];
-
- if ((!is_duration && ts == AV_NOPTS_VALUE) || (is_duration && ts == 0)) {
- writer_print_string(wctx, key, "N/A", PRINT_STRING_OPT);
- } else {
- double d = ts * av_q2d(*time_base);
- struct unit_value uv;
- uv.val.d = d;
- uv.unit = unit_second_str;
- value_string(buf, sizeof(buf), uv);
- writer_print_string(wctx, key, buf, 0);
- }
-}
-
-static void writer_print_ts(WriterContext *wctx, const char *key, int64_t ts, int is_duration)
-{
- if ((!is_duration && ts == AV_NOPTS_VALUE) || (is_duration && ts == 0)) {
- writer_print_string(wctx, key, "N/A", PRINT_STRING_OPT);
- } else {
- writer_print_integer(wctx, key, ts);
- }
-}
-
-static void writer_print_data(WriterContext *wctx, const char *name,
- const uint8_t *data, int size)
-{
- AVBPrint bp;
- int offset = 0, l, i;
-
- av_bprint_init(&bp, 0, AV_BPRINT_SIZE_UNLIMITED);
- av_bprintf(&bp, "\n");
- while (size) {
- av_bprintf(&bp, "%08x: ", offset);
- l = FFMIN(size, 16);
- for (i = 0; i < l; i++) {
- av_bprintf(&bp, "%02x", data[i]);
- if (i & 1)
- av_bprintf(&bp, " ");
- }
- av_bprint_chars(&bp, ' ', 41 - 2 * i - i / 2);
- for (i = 0; i < l; i++)
- av_bprint_chars(&bp, data[i] - 32U < 95 ? data[i] : '.', 1);
- av_bprintf(&bp, "\n");
- offset += l;
- data += l;
- size -= l;
- }
- writer_print_string(wctx, name, bp.str, 0);
- av_bprint_finalize(&bp, NULL);
-}
-
-static void writer_print_data_hash(WriterContext *wctx, const char *name,
- const uint8_t *data, int size)
-{
- char *p, buf[AV_HASH_MAX_SIZE * 2 + 64] = { 0 };
-
- if (!hash)
- return;
- av_hash_init(hash);
- av_hash_update(hash, data, size);
- snprintf(buf, sizeof(buf), "%s:", av_hash_get_name(hash));
- p = buf + strlen(buf);
- av_hash_final_hex(hash, p, buf + sizeof(buf) - p);
- writer_print_string(wctx, name, buf, 0);
-}
-
-static void writer_print_integers(WriterContext *wctx, const char *name,
- uint8_t *data, int size, const char *format,
- int columns, int bytes, int offset_add)
-{
- AVBPrint bp;
- int offset = 0, l, i;
-
- av_bprint_init(&bp, 0, AV_BPRINT_SIZE_UNLIMITED);
- av_bprintf(&bp, "\n");
- while (size) {
- av_bprintf(&bp, "%08x: ", offset);
- l = FFMIN(size, columns);
- for (i = 0; i < l; i++) {
- if (bytes == 1) av_bprintf(&bp, format, *data);
- else if (bytes == 2) av_bprintf(&bp, format, AV_RN16(data));
- else if (bytes == 4) av_bprintf(&bp, format, AV_RN32(data));
- data += bytes;
- size --;
- }
- av_bprintf(&bp, "\n");
- offset += offset_add;
- }
- writer_print_string(wctx, name, bp.str, 0);
- av_bprint_finalize(&bp, NULL);
-}
-
-#define writer_w8(wctx_, b_) (wctx_)->writer_w8(wctx_, b_)
-#define writer_put_str(wctx_, str_) (wctx_)->writer_put_str(wctx_, str_)
-#define writer_printf(wctx_, fmt_, ...) (wctx_)->writer_printf(wctx_, fmt_, __VA_ARGS__)
-
-#define MAX_REGISTERED_WRITERS_NB 64
-
-static const Writer *registered_writers[MAX_REGISTERED_WRITERS_NB + 1];
-
-static int writer_register(const Writer *writer)
-{
- static int next_registered_writer_idx = 0;
-
- if (next_registered_writer_idx == MAX_REGISTERED_WRITERS_NB)
- return AVERROR(ENOMEM);
-
- registered_writers[next_registered_writer_idx++] = writer;
- return 0;
-}
-
-static const Writer *writer_get_by_name(const char *name)
-{
- int i;
-
- for (i = 0; registered_writers[i]; i++)
- if (!strcmp(registered_writers[i]->name, name))
- return registered_writers[i];
-
- return NULL;
-}
-
-
-/* WRITERS */
-
-#define DEFINE_WRITER_CLASS(name) \
-static const char *name##_get_name(void *ctx) \
-{ \
- return #name ; \
-} \
-static const AVClass name##_class = { \
- .class_name = #name, \
- .item_name = name##_get_name, \
- .option = name##_options \
-}
-
-/* Default output */
-
-typedef struct DefaultContext {
- const AVClass *class;
- int nokey;
- int noprint_wrappers;
- int nested_section[SECTION_MAX_NB_LEVELS];
-} DefaultContext;
-
-#undef OFFSET
-#define OFFSET(x) offsetof(DefaultContext, x)
-
-static const AVOption default_options[] = {
- { "noprint_wrappers", "do not print headers and footers", OFFSET(noprint_wrappers), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1 },
- { "nw", "do not print headers and footers", OFFSET(noprint_wrappers), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1 },
- { "nokey", "force no key printing", OFFSET(nokey), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1 },
- { "nk", "force no key printing", OFFSET(nokey), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1 },
- {NULL},
-};
-
-DEFINE_WRITER_CLASS(default);
-
-/* lame uppercasing routine, assumes the string is lower case ASCII */
-static inline char *upcase_string(char *dst, size_t dst_size, const char *src)
-{
- int i;
- for (i = 0; src[i] && i < dst_size-1; i++)
- dst[i] = av_toupper(src[i]);
- dst[i] = 0;
- return dst;
-}
-
-static void default_print_section_header(WriterContext *wctx, const void *data)
-{
- DefaultContext *def = wctx->priv;
- char buf[32];
- const struct section *section = wctx->section[wctx->level];
- const struct section *parent_section = wctx->level ?
- wctx->section[wctx->level-1] : NULL;
-
- av_bprint_clear(&wctx->section_pbuf[wctx->level]);
- if (parent_section &&
- !(parent_section->flags & (SECTION_FLAG_IS_WRAPPER|SECTION_FLAG_IS_ARRAY))) {
- def->nested_section[wctx->level] = 1;
- av_bprintf(&wctx->section_pbuf[wctx->level], "%s%s:",
- wctx->section_pbuf[wctx->level-1].str,
- upcase_string(buf, sizeof(buf),
- av_x_if_null(section->element_name, section->name)));
- }
-
- if (def->noprint_wrappers || def->nested_section[wctx->level])
- return;
-
- if (!(section->flags & (SECTION_FLAG_IS_WRAPPER|SECTION_FLAG_IS_ARRAY)))
- writer_printf(wctx, "[%s]\n", upcase_string(buf, sizeof(buf), section->name));
-}
-
-static void default_print_section_footer(WriterContext *wctx)
-{
- DefaultContext *def = wctx->priv;
- const struct section *section = wctx->section[wctx->level];
- char buf[32];
-
- if (def->noprint_wrappers || def->nested_section[wctx->level])
- return;
-
- if (!(section->flags & (SECTION_FLAG_IS_WRAPPER|SECTION_FLAG_IS_ARRAY)))
- writer_printf(wctx, "[/%s]\n", upcase_string(buf, sizeof(buf), section->name));
-}
-
-static void default_print_str(WriterContext *wctx, const char *key, const char *value)
-{
- DefaultContext *def = wctx->priv;
-
- if (!def->nokey)
- writer_printf(wctx, "%s%s=", wctx->section_pbuf[wctx->level].str, key);
- writer_printf(wctx, "%s\n", value);
-}
-
-static void default_print_int(WriterContext *wctx, const char *key, int64_t value)
-{
- DefaultContext *def = wctx->priv;
-
- if (!def->nokey)
- writer_printf(wctx, "%s%s=", wctx->section_pbuf[wctx->level].str, key);
- writer_printf(wctx, "%"PRId64"\n", value);
-}
-
-static const Writer default_writer = {
- .name = "default",
- .priv_size = sizeof(DefaultContext),
- .print_section_header = default_print_section_header,
- .print_section_footer = default_print_section_footer,
- .print_integer = default_print_int,
- .print_string = default_print_str,
- .flags = WRITER_FLAG_DISPLAY_OPTIONAL_FIELDS,
- .priv_class = &default_class,
-};
-
-/* Compact output */
-
-/**
- * Apply C-language-like string escaping.
- */
-static const char *c_escape_str(AVBPrint *dst, const char *src, const char sep, void *log_ctx)
-{
- const char *p;
-
- for (p = src; *p; p++) {
- switch (*p) {
- case '\b': av_bprintf(dst, "%s", "\\b"); break;
- case '\f': av_bprintf(dst, "%s", "\\f"); break;
- case '\n': av_bprintf(dst, "%s", "\\n"); break;
- case '\r': av_bprintf(dst, "%s", "\\r"); break;
- case '\\': av_bprintf(dst, "%s", "\\\\"); break;
- default:
- if (*p == sep)
- av_bprint_chars(dst, '\\', 1);
- av_bprint_chars(dst, *p, 1);
- }
- }
- return dst->str;
-}
-
-/**
- * Quote fields containing special characters, check RFC4180.
- */
-static const char *csv_escape_str(AVBPrint *dst, const char *src, const char sep, void *log_ctx)
-{
- char meta_chars[] = { sep, '"', '\n', '\r', '\0' };
- int needs_quoting = !!src[strcspn(src, meta_chars)];
-
- if (needs_quoting)
- av_bprint_chars(dst, '"', 1);
-
- for (; *src; src++) {
- if (*src == '"')
- av_bprint_chars(dst, '"', 1);
- av_bprint_chars(dst, *src, 1);
- }
- if (needs_quoting)
- av_bprint_chars(dst, '"', 1);
- return dst->str;
-}
-
-static const char *none_escape_str(AVBPrint *dst, const char *src, const char sep, void *log_ctx)
-{
- return src;
-}
-
-typedef struct CompactContext {
- const AVClass *class;
- char *item_sep_str;
- char item_sep;
- int nokey;
- int print_section;
- char *escape_mode_str;
- const char * (*escape_str)(AVBPrint *dst, const char *src, const char sep, void *log_ctx);
- int nested_section[SECTION_MAX_NB_LEVELS];
- int has_nested_elems[SECTION_MAX_NB_LEVELS];
- int terminate_line[SECTION_MAX_NB_LEVELS];
-} CompactContext;
-
-#undef OFFSET
-#define OFFSET(x) offsetof(CompactContext, x)
-
-static const AVOption compact_options[]= {
- {"item_sep", "set item separator", OFFSET(item_sep_str), AV_OPT_TYPE_STRING, {.str="|"}, 0, 0 },
- {"s", "set item separator", OFFSET(item_sep_str), AV_OPT_TYPE_STRING, {.str="|"}, 0, 0 },
- {"nokey", "force no key printing", OFFSET(nokey), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1 },
- {"nk", "force no key printing", OFFSET(nokey), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1 },
- {"escape", "set escape mode", OFFSET(escape_mode_str), AV_OPT_TYPE_STRING, {.str="c"}, 0, 0 },
- {"e", "set escape mode", OFFSET(escape_mode_str), AV_OPT_TYPE_STRING, {.str="c"}, 0, 0 },
- {"print_section", "print section name", OFFSET(print_section), AV_OPT_TYPE_BOOL, {.i64=1}, 0, 1 },
- {"p", "print section name", OFFSET(print_section), AV_OPT_TYPE_BOOL, {.i64=1}, 0, 1 },
- {NULL},
-};
-
-DEFINE_WRITER_CLASS(compact);
-
-static av_cold int compact_init(WriterContext *wctx)
-{
- CompactContext *compact = wctx->priv;
-
- if (strlen(compact->item_sep_str) != 1) {
- av_log(wctx, AV_LOG_ERROR, "Item separator '%s' specified, but must contain a single character\n",
- compact->item_sep_str);
- return AVERROR(EINVAL);
- }
- compact->item_sep = compact->item_sep_str[0];
-
- if (!strcmp(compact->escape_mode_str, "none")) compact->escape_str = none_escape_str;
- else if (!strcmp(compact->escape_mode_str, "c" )) compact->escape_str = c_escape_str;
- else if (!strcmp(compact->escape_mode_str, "csv" )) compact->escape_str = csv_escape_str;
- else {
- av_log(wctx, AV_LOG_ERROR, "Unknown escape mode '%s'\n", compact->escape_mode_str);
- return AVERROR(EINVAL);
- }
-
- return 0;
-}
-
-static void compact_print_section_header(WriterContext *wctx, const void *data)
-{
- CompactContext *compact = wctx->priv;
- const struct section *section = wctx->section[wctx->level];
- const struct section *parent_section = wctx->level ?
- wctx->section[wctx->level-1] : NULL;
- compact->terminate_line[wctx->level] = 1;
- compact->has_nested_elems[wctx->level] = 0;
-
- av_bprint_clear(&wctx->section_pbuf[wctx->level]);
- if (parent_section &&
- (section->flags & SECTION_FLAG_HAS_TYPE ||
- (!(section->flags & SECTION_FLAG_IS_ARRAY) &&
- !(parent_section->flags & (SECTION_FLAG_IS_WRAPPER|SECTION_FLAG_IS_ARRAY))))) {
-
- /* define a prefix for elements not contained in an array or
- in a wrapper, or for array elements with a type */
- const char *element_name = (char *)av_x_if_null(section->element_name, section->name);
- AVBPrint *section_pbuf = &wctx->section_pbuf[wctx->level];
-
- compact->nested_section[wctx->level] = 1;
- compact->has_nested_elems[wctx->level-1] = 1;
-
- av_bprintf(section_pbuf, "%s%s",
- wctx->section_pbuf[wctx->level-1].str, element_name);
-
- if (section->flags & SECTION_FLAG_HAS_TYPE) {
- // add /TYPE to prefix
- av_bprint_chars(section_pbuf, '/', 1);
-
- // normalize section type, replace special characters and lower case
- for (const char *p = section->get_type(data); *p; p++) {
- char c =
- (*p >= '0' && *p <= '9') ||
- (*p >= 'a' && *p <= 'z') ||
- (*p >= 'A' && *p <= 'Z') ? av_tolower(*p) : '_';
- av_bprint_chars(section_pbuf, c, 1);
- }
- }
- av_bprint_chars(section_pbuf, ':', 1);
-
- wctx->nb_item[wctx->level] = wctx->nb_item[wctx->level-1];
- } else {
- if (parent_section && !(parent_section->flags & (SECTION_FLAG_IS_WRAPPER|SECTION_FLAG_IS_ARRAY)) &&
- wctx->level && wctx->nb_item[wctx->level-1])
- writer_w8(wctx, compact->item_sep);
- if (compact->print_section &&
- !(section->flags & (SECTION_FLAG_IS_WRAPPER|SECTION_FLAG_IS_ARRAY)))
- writer_printf(wctx, "%s%c", section->name, compact->item_sep);
- }
-}
-
-static void compact_print_section_footer(WriterContext *wctx)
-{
- CompactContext *compact = wctx->priv;
-
- if (!compact->nested_section[wctx->level] &&
- compact->terminate_line[wctx->level] &&
- !(wctx->section[wctx->level]->flags & (SECTION_FLAG_IS_WRAPPER|SECTION_FLAG_IS_ARRAY)))
- writer_w8(wctx, '\n');
-}
-
-static void compact_print_str(WriterContext *wctx, const char *key, const char *value)
-{
- CompactContext *compact = wctx->priv;
- AVBPrint buf;
-
- if (wctx->nb_item[wctx->level]) writer_w8(wctx, compact->item_sep);
- if (!compact->nokey)
- writer_printf(wctx, "%s%s=", wctx->section_pbuf[wctx->level].str, key);
- av_bprint_init(&buf, 1, AV_BPRINT_SIZE_UNLIMITED);
- writer_put_str(wctx, compact->escape_str(&buf, value, compact->item_sep, wctx));
- av_bprint_finalize(&buf, NULL);
-}
-
-static void compact_print_int(WriterContext *wctx, const char *key, int64_t value)
-{
- CompactContext *compact = wctx->priv;
-
- if (wctx->nb_item[wctx->level]) writer_w8(wctx, compact->item_sep);
- if (!compact->nokey)
- writer_printf(wctx, "%s%s=", wctx->section_pbuf[wctx->level].str, key);
- writer_printf(wctx, "%"PRId64, value);
-}
-
-static const Writer compact_writer = {
- .name = "compact",
- .priv_size = sizeof(CompactContext),
- .init = compact_init,
- .print_section_header = compact_print_section_header,
- .print_section_footer = compact_print_section_footer,
- .print_integer = compact_print_int,
- .print_string = compact_print_str,
- .flags = WRITER_FLAG_DISPLAY_OPTIONAL_FIELDS,
- .priv_class = &compact_class,
-};
-
-/* CSV output */
-
-#undef OFFSET
-#define OFFSET(x) offsetof(CompactContext, x)
-
-static const AVOption csv_options[] = {
- {"item_sep", "set item separator", OFFSET(item_sep_str), AV_OPT_TYPE_STRING, {.str=","}, 0, 0 },
- {"s", "set item separator", OFFSET(item_sep_str), AV_OPT_TYPE_STRING, {.str=","}, 0, 0 },
- {"nokey", "force no key printing", OFFSET(nokey), AV_OPT_TYPE_BOOL, {.i64=1}, 0, 1 },
- {"nk", "force no key printing", OFFSET(nokey), AV_OPT_TYPE_BOOL, {.i64=1}, 0, 1 },
- {"escape", "set escape mode", OFFSET(escape_mode_str), AV_OPT_TYPE_STRING, {.str="csv"}, 0, 0 },
- {"e", "set escape mode", OFFSET(escape_mode_str), AV_OPT_TYPE_STRING, {.str="csv"}, 0, 0 },
- {"print_section", "print section name", OFFSET(print_section), AV_OPT_TYPE_BOOL, {.i64=1}, 0, 1 },
- {"p", "print section name", OFFSET(print_section), AV_OPT_TYPE_BOOL, {.i64=1}, 0, 1 },
- {NULL},
-};
-
-DEFINE_WRITER_CLASS(csv);
-
-static const Writer csv_writer = {
- .name = "csv",
- .priv_size = sizeof(CompactContext),
- .init = compact_init,
- .print_section_header = compact_print_section_header,
- .print_section_footer = compact_print_section_footer,
- .print_integer = compact_print_int,
- .print_string = compact_print_str,
- .flags = WRITER_FLAG_DISPLAY_OPTIONAL_FIELDS,
- .priv_class = &csv_class,
-};
-
-/* Flat output */
-
-typedef struct FlatContext {
- const AVClass *class;
- const char *sep_str;
- char sep;
- int hierarchical;
-} FlatContext;
-
-#undef OFFSET
-#define OFFSET(x) offsetof(FlatContext, x)
-
-static const AVOption flat_options[]= {
- {"sep_char", "set separator", OFFSET(sep_str), AV_OPT_TYPE_STRING, {.str="."}, 0, 0 },
- {"s", "set separator", OFFSET(sep_str), AV_OPT_TYPE_STRING, {.str="."}, 0, 0 },
- {"hierarchical", "specify if the section specification should be hierarchical", OFFSET(hierarchical), AV_OPT_TYPE_BOOL, {.i64=1}, 0, 1 },
- {"h", "specify if the section specification should be hierarchical", OFFSET(hierarchical), AV_OPT_TYPE_BOOL, {.i64=1}, 0, 1 },
- {NULL},
-};
-
-DEFINE_WRITER_CLASS(flat);
-
-static av_cold int flat_init(WriterContext *wctx)
-{
- FlatContext *flat = wctx->priv;
-
- if (strlen(flat->sep_str) != 1) {
- av_log(wctx, AV_LOG_ERROR, "Item separator '%s' specified, but must contain a single character\n",
- flat->sep_str);
- return AVERROR(EINVAL);
- }
- flat->sep = flat->sep_str[0];
-
- return 0;
-}
-
-static const char *flat_escape_key_str(AVBPrint *dst, const char *src, const char sep)
-{
- const char *p;
-
- for (p = src; *p; p++) {
- if (!((*p >= '0' && *p <= '9') ||
- (*p >= 'a' && *p <= 'z') ||
- (*p >= 'A' && *p <= 'Z')))
- av_bprint_chars(dst, '_', 1);
- else
- av_bprint_chars(dst, *p, 1);
- }
- return dst->str;
-}
-
-static const char *flat_escape_value_str(AVBPrint *dst, const char *src)
-{
- const char *p;
-
- for (p = src; *p; p++) {
- switch (*p) {
- case '\n': av_bprintf(dst, "%s", "\\n"); break;
- case '\r': av_bprintf(dst, "%s", "\\r"); break;
- case '\\': av_bprintf(dst, "%s", "\\\\"); break;
- case '"': av_bprintf(dst, "%s", "\\\""); break;
- case '`': av_bprintf(dst, "%s", "\\`"); break;
- case '$': av_bprintf(dst, "%s", "\\$"); break;
- default: av_bprint_chars(dst, *p, 1); break;
- }
- }
- return dst->str;
-}
-
-static void flat_print_section_header(WriterContext *wctx, const void *data)
-{
- FlatContext *flat = wctx->priv;
- AVBPrint *buf = &wctx->section_pbuf[wctx->level];
- const struct section *section = wctx->section[wctx->level];
- const struct section *parent_section = wctx->level ?
- wctx->section[wctx->level-1] : NULL;
-
- /* build section header */
- av_bprint_clear(buf);
- if (!parent_section)
- return;
- av_bprintf(buf, "%s", wctx->section_pbuf[wctx->level-1].str);
-
- if (flat->hierarchical ||
- !(section->flags & (SECTION_FLAG_IS_ARRAY|SECTION_FLAG_IS_WRAPPER))) {
- av_bprintf(buf, "%s%s", wctx->section[wctx->level]->name, flat->sep_str);
-
- if (parent_section->flags & SECTION_FLAG_IS_ARRAY) {
- int n = parent_section->id == SECTION_ID_PACKETS_AND_FRAMES ?
- wctx->nb_section_packet_frame : wctx->nb_item[wctx->level-1];
- av_bprintf(buf, "%d%s", n, flat->sep_str);
- }
- }
-}
-
-static void flat_print_int(WriterContext *wctx, const char *key, int64_t value)
-{
- writer_printf(wctx, "%s%s=%"PRId64"\n", wctx->section_pbuf[wctx->level].str, key, value);
-}
-
-static void flat_print_str(WriterContext *wctx, const char *key, const char *value)
-{
- FlatContext *flat = wctx->priv;
- AVBPrint buf;
-
- writer_put_str(wctx, wctx->section_pbuf[wctx->level].str);
- av_bprint_init(&buf, 1, AV_BPRINT_SIZE_UNLIMITED);
- writer_printf(wctx, "%s=", flat_escape_key_str(&buf, key, flat->sep));
- av_bprint_clear(&buf);
- writer_printf(wctx, "\"%s\"\n", flat_escape_value_str(&buf, value));
- av_bprint_finalize(&buf, NULL);
-}
-
-static const Writer flat_writer = {
- .name = "flat",
- .priv_size = sizeof(FlatContext),
- .init = flat_init,
- .print_section_header = flat_print_section_header,
- .print_integer = flat_print_int,
- .print_string = flat_print_str,
- .flags = WRITER_FLAG_DISPLAY_OPTIONAL_FIELDS|WRITER_FLAG_PUT_PACKETS_AND_FRAMES_IN_SAME_CHAPTER,
- .priv_class = &flat_class,
-};
-
-/* INI format output */
-
-typedef struct INIContext {
- const AVClass *class;
- int hierarchical;
-} INIContext;
-
-#undef OFFSET
-#define OFFSET(x) offsetof(INIContext, x)
-
-static const AVOption ini_options[] = {
- {"hierarchical", "specify if the section specification should be hierarchical", OFFSET(hierarchical), AV_OPT_TYPE_BOOL, {.i64=1}, 0, 1 },
- {"h", "specify if the section specification should be hierarchical", OFFSET(hierarchical), AV_OPT_TYPE_BOOL, {.i64=1}, 0, 1 },
- {NULL},
-};
-
-DEFINE_WRITER_CLASS(ini);
-
-static char *ini_escape_str(AVBPrint *dst, const char *src)
-{
- int i = 0;
- char c = 0;
-
- while (c = src[i++]) {
- switch (c) {
- case '\b': av_bprintf(dst, "%s", "\\b"); break;
- case '\f': av_bprintf(dst, "%s", "\\f"); break;
- case '\n': av_bprintf(dst, "%s", "\\n"); break;
- case '\r': av_bprintf(dst, "%s", "\\r"); break;
- case '\t': av_bprintf(dst, "%s", "\\t"); break;
- case '\\':
- case '#' :
- case '=' :
- case ':' : av_bprint_chars(dst, '\\', 1);
- default:
- if ((unsigned char)c < 32)
- av_bprintf(dst, "\\x00%02x", c & 0xff);
- else
- av_bprint_chars(dst, c, 1);
- break;
- }
- }
- return dst->str;
-}
-
-static void ini_print_section_header(WriterContext *wctx, const void *data)
-{
- INIContext *ini = wctx->priv;
- AVBPrint *buf = &wctx->section_pbuf[wctx->level];
- const struct section *section = wctx->section[wctx->level];
- const struct section *parent_section = wctx->level ?
- wctx->section[wctx->level-1] : NULL;
-
- av_bprint_clear(buf);
- if (!parent_section) {
- writer_put_str(wctx, "# ffprobe output\n\n");
- return;
- }
-
- if (wctx->nb_item[wctx->level-1])
- writer_w8(wctx, '\n');
-
- av_bprintf(buf, "%s", wctx->section_pbuf[wctx->level-1].str);
- if (ini->hierarchical ||
- !(section->flags & (SECTION_FLAG_IS_ARRAY|SECTION_FLAG_IS_WRAPPER))) {
- av_bprintf(buf, "%s%s", buf->str[0] ? "." : "", wctx->section[wctx->level]->name);
-
- if (parent_section->flags & SECTION_FLAG_IS_ARRAY) {
- int n = parent_section->id == SECTION_ID_PACKETS_AND_FRAMES ?
- wctx->nb_section_packet_frame : wctx->nb_item[wctx->level-1];
- av_bprintf(buf, ".%d", n);
- }
- }
-
- if (!(section->flags & (SECTION_FLAG_IS_ARRAY|SECTION_FLAG_IS_WRAPPER)))
- writer_printf(wctx, "[%s]\n", buf->str);
-}
-
-static void ini_print_str(WriterContext *wctx, const char *key, const char *value)
-{
- AVBPrint buf;
-
- av_bprint_init(&buf, 1, AV_BPRINT_SIZE_UNLIMITED);
- writer_printf(wctx, "%s=", ini_escape_str(&buf, key));
- av_bprint_clear(&buf);
- writer_printf(wctx, "%s\n", ini_escape_str(&buf, value));
- av_bprint_finalize(&buf, NULL);
-}
-
-static void ini_print_int(WriterContext *wctx, const char *key, int64_t value)
-{
- writer_printf(wctx, "%s=%"PRId64"\n", key, value);
-}
-
-static const Writer ini_writer = {
- .name = "ini",
- .priv_size = sizeof(INIContext),
- .print_section_header = ini_print_section_header,
- .print_integer = ini_print_int,
- .print_string = ini_print_str,
- .flags = WRITER_FLAG_DISPLAY_OPTIONAL_FIELDS|WRITER_FLAG_PUT_PACKETS_AND_FRAMES_IN_SAME_CHAPTER,
- .priv_class = &ini_class,
-};
-
-/* JSON output */
-
-typedef struct JSONContext {
- const AVClass *class;
- int indent_level;
- int compact;
- const char *item_sep, *item_start_end;
-} JSONContext;
-
-#undef OFFSET
-#define OFFSET(x) offsetof(JSONContext, x)
-
-static const AVOption json_options[]= {
- { "compact", "enable compact output", OFFSET(compact), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1 },
- { "c", "enable compact output", OFFSET(compact), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1 },
- { NULL }
-};
-
-DEFINE_WRITER_CLASS(json);
-
-static av_cold int json_init(WriterContext *wctx)
-{
- JSONContext *json = wctx->priv;
-
- json->item_sep = json->compact ? ", " : ",\n";
- json->item_start_end = json->compact ? " " : "\n";
-
- return 0;
-}
-
-static const char *json_escape_str(AVBPrint *dst, const char *src, void *log_ctx)
-{
- static const char json_escape[] = {'"', '\\', '\b', '\f', '\n', '\r', '\t', 0};
- static const char json_subst[] = {'"', '\\', 'b', 'f', 'n', 'r', 't', 0};
- const char *p;
-
- for (p = src; *p; p++) {
- char *s = strchr(json_escape, *p);
- if (s) {
- av_bprint_chars(dst, '\\', 1);
- av_bprint_chars(dst, json_subst[s - json_escape], 1);
- } else if ((unsigned char)*p < 32) {
- av_bprintf(dst, "\\u00%02x", *p & 0xff);
- } else {
- av_bprint_chars(dst, *p, 1);
- }
- }
- return dst->str;
-}
-
-#define JSON_INDENT() writer_printf(wctx, "%*c", json->indent_level * 4, ' ')
-
-static void json_print_section_header(WriterContext *wctx, const void *data)
-{
- JSONContext *json = wctx->priv;
- AVBPrint buf;
- const struct section *section = wctx->section[wctx->level];
- const struct section *parent_section = wctx->level ?
- wctx->section[wctx->level-1] : NULL;
-
- if (wctx->level && wctx->nb_item[wctx->level-1])
- writer_put_str(wctx, ",\n");
-
- if (section->flags & SECTION_FLAG_IS_WRAPPER) {
- writer_put_str(wctx, "{\n");
- json->indent_level++;
- } else {
- av_bprint_init(&buf, 1, AV_BPRINT_SIZE_UNLIMITED);
- json_escape_str(&buf, section->name, wctx);
- JSON_INDENT();
-
- json->indent_level++;
- if (section->flags & SECTION_FLAG_IS_ARRAY) {
- writer_printf(wctx, "\"%s\": [\n", buf.str);
- } else if (parent_section && !(parent_section->flags & SECTION_FLAG_IS_ARRAY)) {
- writer_printf(wctx, "\"%s\": {%s", buf.str, json->item_start_end);
- } else {
- writer_printf(wctx, "{%s", json->item_start_end);
-
- /* this is required so the parser can distinguish between packets and frames */
- if (parent_section && parent_section->id == SECTION_ID_PACKETS_AND_FRAMES) {
- if (!json->compact)
- JSON_INDENT();
- writer_printf(wctx, "\"type\": \"%s\"", section->name);
- wctx->nb_item[wctx->level]++;
- }
- }
- av_bprint_finalize(&buf, NULL);
- }
-}
-
-static void json_print_section_footer(WriterContext *wctx)
-{
- JSONContext *json = wctx->priv;
- const struct section *section = wctx->section[wctx->level];
-
- if (wctx->level == 0) {
- json->indent_level--;
- writer_put_str(wctx, "\n}\n");
- } else if (section->flags & SECTION_FLAG_IS_ARRAY) {
- writer_w8(wctx, '\n');
- json->indent_level--;
- JSON_INDENT();
- writer_w8(wctx, ']');
- } else {
- writer_put_str(wctx, json->item_start_end);
- json->indent_level--;
- if (!json->compact)
- JSON_INDENT();
- writer_w8(wctx, '}');
- }
-}
-
-static inline void json_print_item_str(WriterContext *wctx,
- const char *key, const char *value)
-{
- AVBPrint buf;
-
- av_bprint_init(&buf, 1, AV_BPRINT_SIZE_UNLIMITED);
- writer_printf(wctx, "\"%s\":", json_escape_str(&buf, key, wctx));
- av_bprint_clear(&buf);
- writer_printf(wctx, " \"%s\"", json_escape_str(&buf, value, wctx));
- av_bprint_finalize(&buf, NULL);
-}
-
-static void json_print_str(WriterContext *wctx, const char *key, const char *value)
-{
- JSONContext *json = wctx->priv;
- const struct section *parent_section = wctx->level ?
- wctx->section[wctx->level-1] : NULL;
-
- if (wctx->nb_item[wctx->level] || (parent_section && parent_section->id == SECTION_ID_PACKETS_AND_FRAMES))
- writer_put_str(wctx, json->item_sep);
- if (!json->compact)
- JSON_INDENT();
- json_print_item_str(wctx, key, value);
-}
-
-static void json_print_int(WriterContext *wctx, const char *key, int64_t value)
-{
- JSONContext *json = wctx->priv;
- const struct section *parent_section = wctx->level ?
- wctx->section[wctx->level-1] : NULL;
- AVBPrint buf;
-
- if (wctx->nb_item[wctx->level] || (parent_section && parent_section->id == SECTION_ID_PACKETS_AND_FRAMES))
- writer_put_str(wctx, json->item_sep);
- if (!json->compact)
- JSON_INDENT();
-
- av_bprint_init(&buf, 1, AV_BPRINT_SIZE_UNLIMITED);
- writer_printf(wctx, "\"%s\": %"PRId64, json_escape_str(&buf, key, wctx), value);
- av_bprint_finalize(&buf, NULL);
-}
-
-static const Writer json_writer = {
- .name = "json",
- .priv_size = sizeof(JSONContext),
- .init = json_init,
- .print_section_header = json_print_section_header,
- .print_section_footer = json_print_section_footer,
- .print_integer = json_print_int,
- .print_string = json_print_str,
- .flags = WRITER_FLAG_PUT_PACKETS_AND_FRAMES_IN_SAME_CHAPTER,
- .priv_class = &json_class,
-};
-
-/* XML output */
-
-typedef struct XMLContext {
- const AVClass *class;
- int within_tag;
- int indent_level;
- int fully_qualified;
- int xsd_strict;
-} XMLContext;
-
-#undef OFFSET
-#define OFFSET(x) offsetof(XMLContext, x)
-
-static const AVOption xml_options[] = {
- {"fully_qualified", "specify if the output should be fully qualified", OFFSET(fully_qualified), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1 },
- {"q", "specify if the output should be fully qualified", OFFSET(fully_qualified), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1 },
- {"xsd_strict", "ensure that the output is XSD compliant", OFFSET(xsd_strict), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1 },
- {"x", "ensure that the output is XSD compliant", OFFSET(xsd_strict), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1 },
- {NULL},
-};
-
-DEFINE_WRITER_CLASS(xml);
-
-static av_cold int xml_init(WriterContext *wctx)
-{
- XMLContext *xml = wctx->priv;
-
- if (xml->xsd_strict) {
- xml->fully_qualified = 1;
-#define CHECK_COMPLIANCE(opt, opt_name) \
- if (opt) { \
- av_log(wctx, AV_LOG_ERROR, \
- "XSD-compliant output selected but option '%s' was selected, XML output may be non-compliant.\n" \
- "You need to disable such option with '-no%s'\n", opt_name, opt_name); \
- return AVERROR(EINVAL); \
- }
- CHECK_COMPLIANCE(show_private_data, "private");
- CHECK_COMPLIANCE(show_value_unit, "unit");
- CHECK_COMPLIANCE(use_value_prefix, "prefix");
- }
-
- return 0;
-}
-
-#define XML_INDENT() writer_printf(wctx, "%*c", xml->indent_level * 4, ' ')
-
-static void xml_print_section_header(WriterContext *wctx, const void *data)
-{
- XMLContext *xml = wctx->priv;
- const struct section *section = wctx->section[wctx->level];
- const struct section *parent_section = wctx->level ?
- wctx->section[wctx->level-1] : NULL;
-
- if (wctx->level == 0) {
- const char *qual = " xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" "
- "xmlns:ffprobe=\"http://www.ffmpeg.org/schema/ffprobe\" "
- "xsi:schemaLocation=\"http://www.ffmpeg.org/schema/ffprobe ffprobe.xsd\"";
-
- writer_put_str(wctx, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
- writer_printf(wctx, "<%sffprobe%s>\n",
- xml->fully_qualified ? "ffprobe:" : "",
- xml->fully_qualified ? qual : "");
- return;
- }
-
- if (xml->within_tag) {
- xml->within_tag = 0;
- writer_put_str(wctx, ">\n");
- }
-
- if (parent_section && (parent_section->flags & SECTION_FLAG_IS_WRAPPER) &&
- wctx->level && wctx->nb_item[wctx->level-1])
- writer_w8(wctx, '\n');
- xml->indent_level++;
-
- if (section->flags & (SECTION_FLAG_IS_ARRAY|SECTION_FLAG_HAS_VARIABLE_FIELDS)) {
- XML_INDENT(); writer_printf(wctx, "<%s", section->name);
-
- if (section->flags & SECTION_FLAG_HAS_TYPE) {
- AVBPrint buf;
- av_bprint_init(&buf, 1, AV_BPRINT_SIZE_UNLIMITED);
- av_bprint_escape(&buf, section->get_type(data), NULL,
- AV_ESCAPE_MODE_XML, AV_ESCAPE_FLAG_XML_DOUBLE_QUOTES);
- writer_printf(wctx, " type=\"%s\"", buf.str);
- }
- writer_printf(wctx, ">\n", section->name);
- } else {
- XML_INDENT(); writer_printf(wctx, "<%s ", section->name);
- xml->within_tag = 1;
- }
-}
-
-static void xml_print_section_footer(WriterContext *wctx)
-{
- XMLContext *xml = wctx->priv;
- const struct section *section = wctx->section[wctx->level];
-
- if (wctx->level == 0) {
- writer_printf(wctx, "</%sffprobe>\n", xml->fully_qualified ? "ffprobe:" : "");
- } else if (xml->within_tag) {
- xml->within_tag = 0;
- writer_put_str(wctx, "/>\n");
- xml->indent_level--;
- } else {
- XML_INDENT(); writer_printf(wctx, "</%s>\n", section->name);
- xml->indent_level--;
- }
-}
-
-static void xml_print_value(WriterContext *wctx, const char *key,
- const char *str, int64_t num, const int is_int)
-{
- AVBPrint buf;
- XMLContext *xml = wctx->priv;
- const struct section *section = wctx->section[wctx->level];
-
- av_bprint_init(&buf, 1, AV_BPRINT_SIZE_UNLIMITED);
-
- if (section->flags & SECTION_FLAG_HAS_VARIABLE_FIELDS) {
- xml->indent_level++;
- XML_INDENT();
- av_bprint_escape(&buf, key, NULL,
- AV_ESCAPE_MODE_XML, AV_ESCAPE_FLAG_XML_DOUBLE_QUOTES);
- writer_printf(wctx, "<%s key=\"%s\"",
- section->element_name, buf.str);
- av_bprint_clear(&buf);
-
- if (is_int) {
- writer_printf(wctx, " value=\"%"PRId64"\"/>\n", num);
- } else {
- av_bprint_escape(&buf, str, NULL,
- AV_ESCAPE_MODE_XML, AV_ESCAPE_FLAG_XML_DOUBLE_QUOTES);
- writer_printf(wctx, " value=\"%s\"/>\n", buf.str);
- }
- xml->indent_level--;
- } else {
- if (wctx->nb_item[wctx->level])
- writer_w8(wctx, ' ');
-
- if (is_int) {
- writer_printf(wctx, "%s=\"%"PRId64"\"", key, num);
- } else {
- av_bprint_escape(&buf, str, NULL,
- AV_ESCAPE_MODE_XML, AV_ESCAPE_FLAG_XML_DOUBLE_QUOTES);
- writer_printf(wctx, "%s=\"%s\"", key, buf.str);
- }
- }
-
- av_bprint_finalize(&buf, NULL);
-}
-
-static inline void xml_print_str(WriterContext *wctx, const char *key, const char *value) {
- xml_print_value(wctx, key, value, 0, 0);
-}
-
-static void xml_print_int(WriterContext *wctx, const char *key, int64_t value)
-{
- xml_print_value(wctx, key, NULL, value, 1);
-}
-
-static Writer xml_writer = {
- .name = "xml",
- .priv_size = sizeof(XMLContext),
- .init = xml_init,
- .print_section_header = xml_print_section_header,
- .print_section_footer = xml_print_section_footer,
- .print_integer = xml_print_int,
- .print_string = xml_print_str,
- .flags = WRITER_FLAG_PUT_PACKETS_AND_FRAMES_IN_SAME_CHAPTER,
- .priv_class = &xml_class,
-};
-
-static void writer_register_all(void)
-{
- static int initialized;
-
- if (initialized)
- return;
- initialized = 1;
-
- writer_register(&default_writer);
- writer_register(&compact_writer);
- writer_register(&csv_writer);
- writer_register(&flat_writer);
- writer_register(&ini_writer);
- writer_register(&json_writer);
- writer_register(&xml_writer);
-}
#define print_fmt(k, f, ...) do { \
av_bprint_clear(&pbuf); \
av_bprintf(&pbuf, f, __VA_ARGS__); \
- writer_print_string(w, k, pbuf.str, 0); \
+ avtext_print_string(w, k, pbuf.str, 0); \
} while (0)
#define print_list_fmt(k, f, n, m, ...) do { \
@@ -2000,28 +424,19 @@ static void writer_register_all(void)
av_bprintf(&pbuf, f, __VA_ARGS__); \
} \
} \
- writer_print_string(w, k, pbuf.str, 0); \
+ avtext_print_string(w, k, pbuf.str, 0); \
} while (0)
-#define print_int(k, v) writer_print_integer(w, k, v)
-#define print_q(k, v, s) writer_print_rational(w, k, v, s)
-#define print_str(k, v) writer_print_string(w, k, v, 0)
-#define print_str_opt(k, v) writer_print_string(w, k, v, PRINT_STRING_OPT)
-#define print_str_validate(k, v) writer_print_string(w, k, v, PRINT_STRING_VALIDATE)
-#define print_time(k, v, tb) writer_print_time(w, k, v, tb, 0)
-#define print_ts(k, v) writer_print_ts(w, k, v, 0)
-#define print_duration_time(k, v, tb) writer_print_time(w, k, v, tb, 1)
-#define print_duration_ts(k, v) writer_print_ts(w, k, v, 1)
-#define print_val(k, v, u) do { \
- struct unit_value uv; \
- uv.val.i = v; \
- uv.unit = u; \
- writer_print_string(w, k, value_string(val_str, sizeof(val_str), uv), 0); \
-} while (0)
-
-#define print_section_header(s) writer_print_section_header(w, NULL, s)
-#define print_section_header_data(s, d) writer_print_section_header(w, d, s)
-#define print_section_footer(s) writer_print_section_footer(w, s)
+#define print_int(k, v) avtext_print_integer(w, k, v)
+#define print_q(k, v, s) avtext_print_rational(w, k, v, s)
+#define print_str(k, v) avtext_print_string(w, k, v, 0)
+#define print_str_opt(k, v) avtext_print_string(w, k, v, AV_TEXTFORMAT_PRINT_STRING_OPTIONAL)
+#define print_str_validate(k, v) avtext_print_string(w, k, v, AV_TEXTFORMAT_PRINT_STRING_VALIDATE)
+#define print_time(k, v, tb) avtext_print_time(w, k, v, tb, 0)
+#define print_ts(k, v) avtext_print_ts(w, k, v, 0)
+#define print_duration_time(k, v, tb) avtext_print_time(w, k, v, tb, 1)
+#define print_duration_ts(k, v) avtext_print_ts(w, k, v, 1)
+#define print_val(k, v, u) avtext_print_unit_int(w, k, v, u)
#define REALLOCZ_ARRAY_STREAM(ptr, cur_n, new_n) \
{ \
@@ -2529,7 +944,7 @@ static void print_pkt_side_data(WriterContext *w,
double rotation = av_display_rotation_get((int32_t *)sd->data);
if (isnan(rotation))
rotation = 0;
- writer_print_integers(w, "displaymatrix", sd->data, 9, " %11d", 3, 4, 1);
+ avtext_print_integers(w, "displaymatrix", sd->data, 9, " %11d", 3, 4, 1);
print_int("rotation", rotation);
} else if (sd->type == AV_PKT_DATA_STEREO3D) {
const AVStereo3D *stereo = (AVStereo3D *)sd->data;
@@ -2626,8 +1041,8 @@ static void print_pkt_side_data(WriterContext *w,
} else if (sd->type == AV_PKT_DATA_WEBVTT_IDENTIFIER ||
sd->type == AV_PKT_DATA_WEBVTT_SETTINGS) {
if (do_show_data)
- writer_print_data(w, "data", sd->data, sd->size);
- writer_print_data_hash(w, "data_hash", sd->data, sd->size);
+ avtext_print_data(w, "data", sd->data, sd->size);
+ avtext_print_data_hash(w, "data_hash", sd->data, sd->size);
} else if (sd->type == AV_PKT_DATA_FRAME_CROPPING && sd->size >= sizeof(uint32_t) * 4) {
print_int("crop_top", AV_RL32(sd->data));
print_int("crop_bottom", AV_RL32(sd->data + 4));
@@ -2754,7 +1169,6 @@ static int show_log(WriterContext *w, int section_ids, int section_id, int log_l
static void show_packet(WriterContext *w, InputFile *ifile, AVPacket *pkt, int packet_idx)
{
- char val_str[128];
AVStream *st = ifile->streams[pkt->stream_index].st;
AVBPrint pbuf;
const char *s;
@@ -2780,8 +1194,8 @@ static void show_packet(WriterContext *w, InputFile *ifile, AVPacket *pkt, int p
pkt->flags & AV_PKT_FLAG_DISCARD ? 'D' : '_',
pkt->flags & AV_PKT_FLAG_CORRUPT ? 'C' : '_');
if (do_show_data)
- writer_print_data(w, "data", pkt->data, pkt->size);
- writer_print_data_hash(w, "data_hash", pkt->data, pkt->size);
+ avtext_print_data(w, "data", pkt->data, pkt->size);
+ avtext_print_data_hash(w, "data_hash", pkt->data, pkt->size);
if (pkt->side_data_elems) {
size_t size;
@@ -2850,7 +1264,7 @@ static void print_frame_side_data(WriterContext *w,
double rotation = av_display_rotation_get((int32_t *)sd->data);
if (isnan(rotation))
rotation = 0;
- writer_print_integers(w, "displaymatrix", sd->data, 9, " %11d", 3, 4, 1);
+ avtext_print_integers(w, "displaymatrix", sd->data, 9, " %11d", 3, 4, 1);
print_int("rotation", rotation);
} else if (sd->type == AV_FRAME_DATA_AFD && sd->size > 0) {
print_int("active_format", *sd->data);
@@ -3450,12 +1864,12 @@ static int show_stream(WriterContext *w, AVFormatContext *fmt_ctx, int stream_id
if (nb_streams_packets[stream_idx]) print_fmt ("nb_read_packets", "%"PRIu64, nb_streams_packets[stream_idx]);
else print_str_opt("nb_read_packets", "N/A");
if (do_show_data)
- writer_print_data(w, "extradata", par->extradata,
+ avtext_print_data(w, "extradata", par->extradata,
par->extradata_size);
if (par->extradata_size > 0) {
print_int("extradata_size", par->extradata_size);
- writer_print_data_hash(w, "extradata_hash", par->extradata,
+ avtext_print_data_hash(w, "extradata_hash", par->extradata,
par->extradata_size);
}
@@ -3829,7 +2243,6 @@ static int show_chapters(WriterContext *w, InputFile *ifile)
static int show_format(WriterContext *w, InputFile *ifile)
{
AVFormatContext *fmt_ctx = ifile->fmt_ctx;
- char val_str[128];
int64_t size = fmt_ctx->pb ? avio_size(fmt_ctx->pb) : -1;
int ret = 0;
@@ -4005,7 +2418,7 @@ static void close_input_file(InputFile *ifile)
avformat_close_input(&ifile->fmt_ctx);
}
-static int probe_file(WriterContext *wctx, const char *filename,
+static int probe_file(WriterContext *tctx, const char *filename,
const char *print_filename)
{
InputFile ifile = { 0 };
@@ -4047,40 +2460,40 @@ static int probe_file(WriterContext *wctx, const char *filename,
if (do_read_frames || do_read_packets) {
if (do_show_frames && do_show_packets &&
- wctx->writer->flags & WRITER_FLAG_PUT_PACKETS_AND_FRAMES_IN_SAME_CHAPTER)
+ tctx->formatter->flags & AV_TEXTFORMAT_FLAG_SUPPORTS_MIXED_ARRAY_CONTENT)
section_id = SECTION_ID_PACKETS_AND_FRAMES;
else if (do_show_packets && !do_show_frames)
section_id = SECTION_ID_PACKETS;
else // (!do_show_packets && do_show_frames)
section_id = SECTION_ID_FRAMES;
if (do_show_frames || do_show_packets)
- writer_print_section_header(wctx, NULL, section_id);
- ret = read_packets(wctx, &ifile);
+ writer_print_section_header(tctx, NULL, section_id);
+ ret = read_packets(tctx, &ifile);
if (do_show_frames || do_show_packets)
- writer_print_section_footer(wctx);
+ writer_print_section_footer(tctx);
CHECK_END;
}
if (do_show_programs) {
- ret = show_programs(wctx, &ifile);
+ ret = show_programs(tctx, &ifile);
CHECK_END;
}
if (do_show_stream_groups) {
- ret = show_stream_groups(wctx, &ifile);
+ ret = show_stream_groups(tctx, &ifile);
CHECK_END;
}
if (do_show_streams) {
- ret = show_streams(wctx, &ifile);
+ ret = show_streams(tctx, &ifile);
CHECK_END;
}
if (do_show_chapters) {
- ret = show_chapters(wctx, &ifile);
+ ret = show_chapters(tctx, &ifile);
CHECK_END;
}
if (do_show_format) {
- ret = show_format(wctx, &ifile);
+ ret = show_format(tctx, &ifile);
CHECK_END;
}
@@ -4229,11 +2642,11 @@ static int opt_format(void *optctx, const char *opt, const char *arg)
static inline void mark_section_show_entries(SectionID section_id,
int show_all_entries, AVDictionary *entries)
{
- struct section *section = §ions[section_id];
+ struct AVTextFormatSection *section = §ions[section_id];
section->show_all_entries = show_all_entries;
if (show_all_entries) {
- for (const SectionID *id = section->children_ids; *id != -1; id++)
+ for (const int *id = section->children_ids; *id != -1; id++)
mark_section_show_entries(*id, show_all_entries, entries);
} else {
av_dict_copy(§ion->entries_to_show, entries, 0);
@@ -4246,7 +2659,7 @@ static int match_section(const char *section_name,
int i, ret = 0;
for (i = 0; i < FF_ARRAY_ELEMS(sections); i++) {
- const struct section *section = §ions[i];
+ const struct AVTextFormatSection *section = §ions[i];
if (!strcmp(section_name, section->name) ||
(section->unique_name && !strcmp(section_name, section->unique_name))) {
av_log(NULL, AV_LOG_DEBUG,
@@ -4518,13 +2931,13 @@ static int opt_pretty(void *optctx, const char *opt, const char *arg)
static void print_section(SectionID id, int level)
{
- const SectionID *pid;
- const struct section *section = §ions[id];
+ const int *pid;
+ const struct AVTextFormatSection *section = §ions[id];
printf("%c%c%c%c",
- section->flags & SECTION_FLAG_IS_WRAPPER ? 'W' : '.',
- section->flags & SECTION_FLAG_IS_ARRAY ? 'A' : '.',
- section->flags & SECTION_FLAG_HAS_VARIABLE_FIELDS ? 'V' : '.',
- section->flags & SECTION_FLAG_HAS_TYPE ? 'T' : '.');
+ section->flags & AV_TEXTFORMAT_SECTION_FLAG_IS_WRAPPER ? 'W' : '.',
+ section->flags & AV_TEXTFORMAT_SECTION_FLAG_IS_ARRAY ? 'A' : '.',
+ section->flags & AV_TEXTFORMAT_SECTION_FLAG_HAS_VARIABLE_FIELDS ? 'V' : '.',
+ section->flags & AV_TEXTFORMAT_SECTION_FLAG_HAS_TYPE ? 'T' : '.');
printf("%*c %s", level * 4, ' ', section->name);
if (section->unique_name)
printf("/%s", section->unique_name);
@@ -4627,10 +3040,10 @@ static const OptionDef real_options[] = {
static inline int check_section_show_entries(int section_id)
{
- struct section *section = §ions[section_id];
+ struct AVTextFormatSection *section = §ions[section_id];
if (sections[section_id].show_all_entries || sections[section_id].entries_to_show)
return 1;
- for (const SectionID *id = section->children_ids; *id != -1; id++)
+ for (const int *id = section->children_ids; *id != -1; id++)
if (check_section_show_entries(*id))
return 1;
return 0;
@@ -4643,10 +3056,11 @@ static inline int check_section_show_entries(int section_id)
int main(int argc, char **argv)
{
- const Writer *w;
- WriterContext *wctx;
+ const AVTextFormatter *f;
+ WriterContext *tctx;
+ AVTextWriterContext *wctx;
char *buf;
- char *w_name = NULL, *w_args = NULL;
+ char *f_name = NULL, *f_args = NULL;
int ret, input_ret, i;
init_dynload();
@@ -4708,58 +3122,51 @@ int main(int argc, char **argv)
goto end;
}
- writer_register_all();
-
if (!output_format)
output_format = av_strdup("default");
if (!output_format) {
ret = AVERROR(ENOMEM);
goto end;
}
- w_name = av_strtok(output_format, "=", &buf);
- if (!w_name) {
+ f_name = av_strtok(output_format, "=", &buf);
+ if (!f_name) {
av_log(NULL, AV_LOG_ERROR,
"No name specified for the output format\n");
ret = AVERROR(EINVAL);
goto end;
}
- w_args = buf;
-
- if (show_data_hash) {
- if ((ret = av_hash_alloc(&hash, show_data_hash)) < 0) {
- if (ret == AVERROR(EINVAL)) {
- const char *n;
- av_log(NULL, AV_LOG_ERROR,
- "Unknown hash algorithm '%s'\nKnown algorithms:",
- show_data_hash);
- for (i = 0; (n = av_hash_names(i)); i++)
- av_log(NULL, AV_LOG_ERROR, " %s", n);
- av_log(NULL, AV_LOG_ERROR, "\n");
- }
- goto end;
- }
- }
+ f_args = buf;
- w = writer_get_by_name(w_name);
- if (!w) {
- av_log(NULL, AV_LOG_ERROR, "Unknown output format with name '%s'\n", w_name);
+ f = avtext_get_formatter_by_name(f_name);
+ if (!f) {
+ av_log(NULL, AV_LOG_ERROR, "Unknown output format with name '%s'\n", f_name);
ret = AVERROR(EINVAL);
goto end;
}
- if ((ret = writer_open(&wctx, w, w_args,
- sections, FF_ARRAY_ELEMS(sections), output_filename)) >= 0) {
- if (w == &xml_writer)
- wctx->string_validation_utf8_flags |= AV_UTF8_FLAG_EXCLUDE_XML_INVALID_CONTROL_CODES;
+ if (output_filename) {
+ ret = avtextwriter_create_file(&wctx, output_filename, 1);
+ } else
+ ret = avtextwriter_create_stdout(&wctx);
- writer_print_section_header(wctx, NULL, SECTION_ID_ROOT);
+ if (ret < 0)
+ goto end;
+
+ if ((ret = avtext_context_open(&tctx, f, wctx, f_args,
+ sections, FF_ARRAY_ELEMS(sections), show_value_unit,
+ use_value_prefix, use_byte_value_binary_prefix, use_value_sexagesimal_format,
+ show_optional_fields, show_data_hash)) >= 0) {
+ if (f == &avtextformatter_xml)
+ tctx->string_validation_utf8_flags |= AV_UTF8_FLAG_EXCLUDE_XML_INVALID_CONTROL_CODES;
+
+ writer_print_section_header(tctx, NULL, SECTION_ID_ROOT);
if (do_show_program_version)
- ffprobe_show_program_version(wctx);
+ ffprobe_show_program_version(tctx);
if (do_show_library_versions)
- ffprobe_show_library_versions(wctx);
+ ffprobe_show_library_versions(tctx);
if (do_show_pixel_formats)
- ffprobe_show_pixel_formats(wctx);
+ ffprobe_show_pixel_formats(tctx);
if (!input_filename &&
((do_show_format || do_show_programs || do_show_stream_groups || do_show_streams || do_show_chapters || do_show_packets || do_show_error) ||
@@ -4769,17 +3176,22 @@ int main(int argc, char **argv)
av_log(NULL, AV_LOG_ERROR, "Use -h to get full help or, even better, run 'man %s'.\n", program_name);
ret = AVERROR(EINVAL);
} else if (input_filename) {
- ret = probe_file(wctx, input_filename, print_input_filename);
+ ret = probe_file(tctx, input_filename, print_input_filename);
if (ret < 0 && do_show_error)
- show_error(wctx, ret);
+ show_error(tctx, ret);
}
input_ret = ret;
- writer_print_section_footer(wctx);
- ret = writer_close(&wctx);
+ avtext_print_section_footer(tctx);
+
+ ret = avtextwriter_context_close(&wctx);
+ if (ret < 0)
+ av_log(NULL, AV_LOG_ERROR, "Writing output failed (closing writer): %s\n", av_err2str(ret));
+
+ ret = avtext_context_close(&tctx);
if (ret < 0)
- av_log(NULL, AV_LOG_ERROR, "Writing output failed: %s\n", av_err2str(ret));
+ av_log(NULL, AV_LOG_ERROR, "Writing output failed (closing formatter): %s\n", av_err2str(ret));
ret = FFMIN(ret, input_ret);
}
@@ -4790,7 +3202,6 @@ end:
av_freep(&input_filename);
av_freep(&print_input_filename);
av_freep(&read_intervals);
- av_hash_freep(&hash);
uninit_opts();
for (i = 0; i < FF_ARRAY_ELEMS(sections); i++)
--
ffmpeg-codebot
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 108+ messages in thread
* Re: [FFmpeg-devel] [PATCH v7 2/7] fftools/ffprobe: Change to use textformat api
2025-03-12 4:04 ` [FFmpeg-devel] [PATCH v7 2/7] fftools/ffprobe: Change to use textformat api softworkz
@ 2025-03-13 11:55 ` Michael Niedermayer
0 siblings, 0 replies; 108+ messages in thread
From: Michael Niedermayer @ 2025-03-13 11:55 UTC (permalink / raw)
To: FFmpeg development discussions and patches
[-- Attachment #1.1: Type: text/plain, Size: 837 bytes --]
On Wed, Mar 12, 2025 at 04:04:20AM +0000, softworkz wrote:
> From: softworkz <softworkz@hotmail.com>
>
> Signed-off-by: softworkz <softworkz@hotmail.com>
> ---
> fftools/Makefile | 12 +
> fftools/ffprobe.c | 1849 ++++-----------------------------------------
> 2 files changed, 142 insertions(+), 1719 deletions(-)
breaks build for x86-32
make
CC fftools/textformat/avtextformat.o
src/fftools/textformat/avtextformat.c:672:1: fatal error: opening dependency file fftools/textformat/avtextformat.d: No such file or directory
}
^
compilation terminated.
make: *** [src/ffbuild/common.mak:81: fftools/textformat/avtextformat.o] Error 1
thx
[...]
--
Michael GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB
There will always be a question for which you do not know the correct answer.
[-- Attachment #1.2: signature.asc --]
[-- Type: application/pgp-signature, Size: 195 bytes --]
[-- Attachment #2: Type: text/plain, Size: 251 bytes --]
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 108+ messages in thread
* [FFmpeg-devel] [PATCH v7 3/7] fftools/ffprobe: Rename writer_print_section_* and WriterContext
2025-03-12 4:04 ` [FFmpeg-devel] [PATCH v7 0/7] " ffmpegagent
2025-03-12 4:04 ` [FFmpeg-devel] [PATCH v7 1/7] fftools/textformat: Extract and generalize textformat api from ffprobe.c softworkz
2025-03-12 4:04 ` [FFmpeg-devel] [PATCH v7 2/7] fftools/ffprobe: Change to use textformat api softworkz
@ 2025-03-12 4:04 ` softworkz
2025-03-12 4:04 ` [FFmpeg-devel] [PATCH v7 4/7] fftools/ffmpeg_filter: Move some declaration to new header file softworkz
` (4 subsequent siblings)
7 siblings, 0 replies; 108+ messages in thread
From: softworkz @ 2025-03-12 4:04 UTC (permalink / raw)
To: ffmpeg-devel; +Cc: softworkz
From: softworkz <softworkz@hotmail.com>
separated for better clarity of the preceding commit
Signed-off-by: softworkz <softworkz@hotmail.com>
ren
---
fftools/ffprobe.c | 361 +++++++++++++++++++++++-----------------------
1 file changed, 178 insertions(+), 183 deletions(-)
diff --git a/fftools/ffprobe.c b/fftools/ffprobe.c
index f398057df7..4a90bc4824 100644
--- a/fftools/ffprobe.c
+++ b/fftools/ffprobe.c
@@ -71,11 +71,6 @@
#include "libavutil/thread.h"
-// TEMPORARY DEFINES
-#define writer_print_section_header(w, d, s) avtext_print_section_header(w, d, s)
-#define writer_print_section_footer(w) avtext_print_section_footer(w)
-#define WriterContext AVTextFormatContext
-
// attached as opaque_ref to packets/frames
typedef struct FrameData {
int64_t pkt_pos;
@@ -446,25 +441,25 @@ static void log_callback(void *ptr, int level, const char *fmt, va_list vl)
memset( (ptr) + (cur_n), 0, ((new_n) - (cur_n)) * sizeof(*(ptr)) ); \
}
-static inline int show_tags(WriterContext *w, AVDictionary *tags, int section_id)
+static inline int show_tags(AVTextFormatContext *w, AVDictionary *tags, int section_id)
{
const AVDictionaryEntry *tag = NULL;
int ret = 0;
if (!tags)
return 0;
- writer_print_section_header(w, NULL, section_id);
+ avtext_print_section_header(w, NULL, section_id);
while ((tag = av_dict_iterate(tags, tag))) {
if ((ret = print_str_validate(tag->key, tag->value)) < 0)
break;
}
- writer_print_section_footer(w);
+ avtext_print_section_footer(w);
return ret;
}
-static void print_dovi_metadata(WriterContext *w, const AVDOVIMetadata *dovi)
+static void print_dovi_metadata(AVTextFormatContext *w, const AVDOVIMetadata *dovi)
{
if (!dovi)
return;
@@ -519,15 +514,15 @@ static void print_dovi_metadata(WriterContext *w, const AVDOVIMetadata *dovi)
print_int("num_x_partitions", mapping->num_x_partitions);
print_int("num_y_partitions", mapping->num_y_partitions);
- writer_print_section_header(w, NULL, SECTION_ID_FRAME_SIDE_DATA_COMPONENT_LIST);
+ avtext_print_section_header(w, NULL, SECTION_ID_FRAME_SIDE_DATA_COMPONENT_LIST);
for (int c = 0; c < 3; c++) {
const AVDOVIReshapingCurve *curve = &mapping->curves[c];
- writer_print_section_header(w, "Reshaping curve", SECTION_ID_FRAME_SIDE_DATA_COMPONENT);
+ avtext_print_section_header(w, "Reshaping curve", SECTION_ID_FRAME_SIDE_DATA_COMPONENT);
print_list_fmt("pivots", "%"PRIu16, curve->num_pivots, 1, curve->pivots[idx]);
- writer_print_section_header(w, NULL, SECTION_ID_FRAME_SIDE_DATA_PIECE_LIST);
+ avtext_print_section_header(w, NULL, SECTION_ID_FRAME_SIDE_DATA_PIECE_LIST);
for (int i = 0; i < curve->num_pivots - 1; i++) {
AVBPrint piece_buf;
@@ -545,7 +540,7 @@ static void print_dovi_metadata(WriterContext *w, const AVDOVIMetadata *dovi)
}
av_bprintf(&piece_buf, " mapping");
- writer_print_section_header(w, piece_buf.str, SECTION_ID_FRAME_SIDE_DATA_PIECE);
+ avtext_print_section_header(w, piece_buf.str, SECTION_ID_FRAME_SIDE_DATA_PIECE);
print_int("mapping_idc", curve->mapping_idc[i]);
switch (curve->mapping_idc[i]) {
case AV_DOVI_MAPPING_POLYNOMIAL:
@@ -569,11 +564,11 @@ static void print_dovi_metadata(WriterContext *w, const AVDOVIMetadata *dovi)
}
// SECTION_ID_FRAME_SIDE_DATA_PIECE
- writer_print_section_footer(w);
+ avtext_print_section_footer(w);
}
// SECTION_ID_FRAME_SIDE_DATA_PIECE_LIST
- writer_print_section_footer(w);
+ avtext_print_section_footer(w);
if (mapping->nlq_method_idc != AV_DOVI_NLQ_NONE) {
const AVDOVINLQParams *nlq = &mapping->nlq[c];
@@ -589,11 +584,11 @@ static void print_dovi_metadata(WriterContext *w, const AVDOVIMetadata *dovi)
}
// SECTION_ID_FRAME_SIDE_DATA_COMPONENT
- writer_print_section_footer(w);
+ avtext_print_section_footer(w);
}
// SECTION_ID_FRAME_SIDE_DATA_COMPONENT_LIST
- writer_print_section_footer(w);
+ avtext_print_section_footer(w);
// color metadata
print_int("dm_metadata_id", color->dm_metadata_id);
@@ -626,7 +621,7 @@ static void print_dovi_metadata(WriterContext *w, const AVDOVIMetadata *dovi)
}
}
-static void print_dynamic_hdr10_plus(WriterContext *w, const AVDynamicHDRPlus *metadata)
+static void print_dynamic_hdr10_plus(AVTextFormatContext *w, const AVDynamicHDRPlus *metadata)
{
if (!metadata)
return;
@@ -725,7 +720,7 @@ static void print_dynamic_hdr10_plus(WriterContext *w, const AVDynamicHDRPlus *m
}
}
-static void print_dynamic_hdr_vivid(WriterContext *w, const AVDynamicHDRVivid *metadata)
+static void print_dynamic_hdr_vivid(AVTextFormatContext *w, const AVDynamicHDRVivid *metadata)
{
if (!metadata)
return;
@@ -795,7 +790,7 @@ static void print_dynamic_hdr_vivid(WriterContext *w, const AVDynamicHDRVivid *m
}
}
-static void print_ambient_viewing_environment(WriterContext *w,
+static void print_ambient_viewing_environment(AVTextFormatContext *w,
const AVAmbientViewingEnvironment *env)
{
if (!env)
@@ -806,7 +801,7 @@ static void print_ambient_viewing_environment(WriterContext *w,
print_q("ambient_light_y", env->ambient_light_y, '/');
}
-static void print_film_grain_params(WriterContext *w,
+static void print_film_grain_params(AVTextFormatContext *w,
const AVFilmGrainParams *fgp)
{
const char *color_range, *color_primaries, *color_trc, *color_space;
@@ -852,10 +847,10 @@ static void print_film_grain_params(WriterContext *w,
print_int("overlap_flag", aom->overlap_flag);
print_int("limit_output_range", aom->limit_output_range);
- writer_print_section_header(w, NULL, SECTION_ID_FRAME_SIDE_DATA_COMPONENT_LIST);
+ avtext_print_section_header(w, NULL, SECTION_ID_FRAME_SIDE_DATA_COMPONENT_LIST);
if (aom->num_y_points) {
- writer_print_section_header(w, NULL, SECTION_ID_FRAME_SIDE_DATA_COMPONENT);
+ avtext_print_section_header(w, NULL, SECTION_ID_FRAME_SIDE_DATA_COMPONENT);
print_int("bit_depth_luma", fgp->bit_depth_luma);
print_list_fmt("y_points_value", "%"PRIu8, aom->num_y_points, 1, aom->y_points[idx][0]);
@@ -863,14 +858,14 @@ static void print_film_grain_params(WriterContext *w,
print_list_fmt("ar_coeffs_y", "%"PRId8, num_ar_coeffs_y, 1, aom->ar_coeffs_y[idx]);
// SECTION_ID_FRAME_SIDE_DATA_COMPONENT
- writer_print_section_footer(w);
+ avtext_print_section_footer(w);
}
for (int uv = 0; uv < 2; uv++) {
if (!aom->num_uv_points[uv] && !aom->chroma_scaling_from_luma)
continue;
- writer_print_section_header(w, NULL, SECTION_ID_FRAME_SIDE_DATA_COMPONENT);
+ avtext_print_section_header(w, NULL, SECTION_ID_FRAME_SIDE_DATA_COMPONENT);
print_int("bit_depth_chroma", fgp->bit_depth_chroma);
print_list_fmt("uv_points_value", "%"PRIu8, aom->num_uv_points[uv], 1, aom->uv_points[uv][idx][0]);
@@ -881,11 +876,11 @@ static void print_film_grain_params(WriterContext *w,
print_int("uv_offset", aom->uv_offset[uv]);
// SECTION_ID_FRAME_SIDE_DATA_COMPONENT
- writer_print_section_footer(w);
+ avtext_print_section_footer(w);
}
// SECTION_ID_FRAME_SIDE_DATA_COMPONENT_LIST
- writer_print_section_footer(w);
+ avtext_print_section_footer(w);
break;
}
case AV_FILM_GRAIN_PARAMS_H274: {
@@ -894,36 +889,36 @@ static void print_film_grain_params(WriterContext *w,
print_int("blending_mode_id", h274->blending_mode_id);
print_int("log2_scale_factor", h274->log2_scale_factor);
- writer_print_section_header(w, NULL, SECTION_ID_FRAME_SIDE_DATA_COMPONENT_LIST);
+ avtext_print_section_header(w, NULL, SECTION_ID_FRAME_SIDE_DATA_COMPONENT_LIST);
for (int c = 0; c < 3; c++) {
if (!h274->component_model_present[c])
continue;
- writer_print_section_header(w, NULL, SECTION_ID_FRAME_SIDE_DATA_COMPONENT);
+ avtext_print_section_header(w, NULL, SECTION_ID_FRAME_SIDE_DATA_COMPONENT);
print_int(c ? "bit_depth_chroma" : "bit_depth_luma", c ? fgp->bit_depth_chroma : fgp->bit_depth_luma);
- writer_print_section_header(w, NULL, SECTION_ID_FRAME_SIDE_DATA_PIECE_LIST);
+ avtext_print_section_header(w, NULL, SECTION_ID_FRAME_SIDE_DATA_PIECE_LIST);
for (int i = 0; i < h274->num_intensity_intervals[c]; i++) {
- writer_print_section_header(w, NULL, SECTION_ID_FRAME_SIDE_DATA_PIECE);
+ avtext_print_section_header(w, NULL, SECTION_ID_FRAME_SIDE_DATA_PIECE);
print_int("intensity_interval_lower_bound", h274->intensity_interval_lower_bound[c][i]);
print_int("intensity_interval_upper_bound", h274->intensity_interval_upper_bound[c][i]);
print_list_fmt("comp_model_value", "%"PRId16, h274->num_model_values[c], 1, h274->comp_model_value[c][i][idx]);
// SECTION_ID_FRAME_SIDE_DATA_PIECE
- writer_print_section_footer(w);
+ avtext_print_section_footer(w);
}
// SECTION_ID_FRAME_SIDE_DATA_PIECE_LIST
- writer_print_section_footer(w);
+ avtext_print_section_footer(w);
// SECTION_ID_FRAME_SIDE_DATA_COMPONENT
- writer_print_section_footer(w);
+ avtext_print_section_footer(w);
}
// SECTION_ID_FRAME_SIDE_DATA_COMPONENT_LIST
- writer_print_section_footer(w);
+ avtext_print_section_footer(w);
break;
}
}
@@ -931,14 +926,14 @@ static void print_film_grain_params(WriterContext *w,
av_bprint_finalize(&pbuf, NULL);
}
-static void print_pkt_side_data(WriterContext *w,
+static void print_pkt_side_data(AVTextFormatContext *w,
AVCodecParameters *par,
const AVPacketSideData *sd,
SectionID id_data)
{
const char *name = av_packet_side_data_name(sd->type);
- writer_print_section_header(w, sd, id_data);
+ avtext_print_section_header(w, sd, id_data);
print_str("side_data_type", name ? name : "unknown");
if (sd->type == AV_PKT_DATA_DISPLAYMATRIX && sd->size >= 9*4) {
double rotation = av_display_rotation_get((int32_t *)sd->data);
@@ -1053,7 +1048,7 @@ static void print_pkt_side_data(WriterContext *w,
}
}
-static void print_private_data(WriterContext *w, void *priv_data)
+static void print_private_data(AVTextFormatContext *w, void *priv_data)
{
const AVOption *opt = NULL;
while (opt = av_opt_next(priv_data, opt)) {
@@ -1066,7 +1061,7 @@ static void print_private_data(WriterContext *w, void *priv_data)
}
}
-static void print_color_range(WriterContext *w, enum AVColorRange color_range)
+static void print_color_range(AVTextFormatContext *w, enum AVColorRange color_range)
{
const char *val = av_color_range_name(color_range);
if (!val || color_range == AVCOL_RANGE_UNSPECIFIED) {
@@ -1076,7 +1071,7 @@ static void print_color_range(WriterContext *w, enum AVColorRange color_range)
}
}
-static void print_color_space(WriterContext *w, enum AVColorSpace color_space)
+static void print_color_space(AVTextFormatContext *w, enum AVColorSpace color_space)
{
const char *val = av_color_space_name(color_space);
if (!val || color_space == AVCOL_SPC_UNSPECIFIED) {
@@ -1086,7 +1081,7 @@ static void print_color_space(WriterContext *w, enum AVColorSpace color_space)
}
}
-static void print_primaries(WriterContext *w, enum AVColorPrimaries color_primaries)
+static void print_primaries(AVTextFormatContext *w, enum AVColorPrimaries color_primaries)
{
const char *val = av_color_primaries_name(color_primaries);
if (!val || color_primaries == AVCOL_PRI_UNSPECIFIED) {
@@ -1096,7 +1091,7 @@ static void print_primaries(WriterContext *w, enum AVColorPrimaries color_primar
}
}
-static void print_color_trc(WriterContext *w, enum AVColorTransferCharacteristic color_trc)
+static void print_color_trc(AVTextFormatContext *w, enum AVColorTransferCharacteristic color_trc)
{
const char *val = av_color_transfer_name(color_trc);
if (!val || color_trc == AVCOL_TRC_UNSPECIFIED) {
@@ -1106,7 +1101,7 @@ static void print_color_trc(WriterContext *w, enum AVColorTransferCharacteristic
}
}
-static void print_chroma_location(WriterContext *w, enum AVChromaLocation chroma_location)
+static void print_chroma_location(AVTextFormatContext *w, enum AVChromaLocation chroma_location)
{
const char *val = av_chroma_location_name(chroma_location);
if (!val || chroma_location == AVCHROMA_LOC_UNSPECIFIED) {
@@ -1132,7 +1127,7 @@ static void clear_log(int need_lock)
ff_mutex_unlock(&log_mutex);
}
-static int show_log(WriterContext *w, int section_ids, int section_id, int log_level)
+static int show_log(AVTextFormatContext *w, int section_ids, int section_id, int log_level)
{
int i;
ff_mutex_lock(&log_mutex);
@@ -1140,11 +1135,11 @@ static int show_log(WriterContext *w, int section_ids, int section_id, int log_l
ff_mutex_unlock(&log_mutex);
return 0;
}
- writer_print_section_header(w, NULL, section_ids);
+ avtext_print_section_header(w, NULL, section_ids);
for (i=0; i<log_buffer_size; i++) {
if (log_buffer[i].log_level <= log_level) {
- writer_print_section_header(w, NULL, section_id);
+ avtext_print_section_header(w, NULL, section_id);
print_str("context", log_buffer[i].context_name);
print_int("level", log_buffer[i].log_level);
print_int("category", log_buffer[i].category);
@@ -1156,18 +1151,18 @@ static int show_log(WriterContext *w, int section_ids, int section_id, int log_l
print_str_opt("parent_category", "N/A");
}
print_str("message", log_buffer[i].log_message);
- writer_print_section_footer(w);
+ avtext_print_section_footer(w);
}
}
clear_log(0);
ff_mutex_unlock(&log_mutex);
- writer_print_section_footer(w);
+ avtext_print_section_footer(w);
return 0;
}
-static void show_packet(WriterContext *w, InputFile *ifile, AVPacket *pkt, int packet_idx)
+static void show_packet(AVTextFormatContext *w, InputFile *ifile, AVPacket *pkt, int packet_idx)
{
AVStream *st = ifile->streams[pkt->stream_index].st;
AVBPrint pbuf;
@@ -1175,7 +1170,7 @@ static void show_packet(WriterContext *w, InputFile *ifile, AVPacket *pkt, int p
av_bprint_init(&pbuf, 1, AV_BPRINT_SIZE_UNLIMITED);
- writer_print_section_header(w, NULL, SECTION_ID_PACKET);
+ avtext_print_section_header(w, NULL, SECTION_ID_PACKET);
s = av_get_media_type_string(st->codecpar->codec_type);
if (s) print_str ("codec_type", s);
@@ -1209,29 +1204,29 @@ static void show_packet(WriterContext *w, InputFile *ifile, AVPacket *pkt, int p
av_dict_free(&dict);
}
- writer_print_section_header(w, NULL, SECTION_ID_PACKET_SIDE_DATA_LIST);
+ avtext_print_section_header(w, NULL, SECTION_ID_PACKET_SIDE_DATA_LIST);
for (int i = 0; i < pkt->side_data_elems; i++) {
print_pkt_side_data(w, st->codecpar, &pkt->side_data[i],
SECTION_ID_PACKET_SIDE_DATA);
- writer_print_section_footer(w);
+ avtext_print_section_footer(w);
}
- writer_print_section_footer(w);
+ avtext_print_section_footer(w);
}
- writer_print_section_footer(w);
+ avtext_print_section_footer(w);
av_bprint_finalize(&pbuf, NULL);
fflush(stdout);
}
-static void show_subtitle(WriterContext *w, AVSubtitle *sub, AVStream *stream,
+static void show_subtitle(AVTextFormatContext *w, AVSubtitle *sub, AVStream *stream,
AVFormatContext *fmt_ctx)
{
AVBPrint pbuf;
av_bprint_init(&pbuf, 1, AV_BPRINT_SIZE_UNLIMITED);
- writer_print_section_header(w, NULL, SECTION_ID_SUBTITLE);
+ avtext_print_section_header(w, NULL, SECTION_ID_SUBTITLE);
print_str ("media_type", "subtitle");
print_ts ("pts", sub->pts);
@@ -1241,23 +1236,23 @@ static void show_subtitle(WriterContext *w, AVSubtitle *sub, AVStream *stream,
print_int ("end_display_time", sub->end_display_time);
print_int ("num_rects", sub->num_rects);
- writer_print_section_footer(w);
+ avtext_print_section_footer(w);
av_bprint_finalize(&pbuf, NULL);
fflush(stdout);
}
-static void print_frame_side_data(WriterContext *w,
+static void print_frame_side_data(AVTextFormatContext *w,
const AVFrame *frame,
const AVStream *stream)
{
- writer_print_section_header(w, NULL, SECTION_ID_FRAME_SIDE_DATA_LIST);
+ avtext_print_section_header(w, NULL, SECTION_ID_FRAME_SIDE_DATA_LIST);
for (int i = 0; i < frame->nb_side_data; i++) {
const AVFrameSideData *sd = frame->side_data[i];
const char *name;
- writer_print_section_header(w, sd, SECTION_ID_FRAME_SIDE_DATA);
+ avtext_print_section_header(w, sd, SECTION_ID_FRAME_SIDE_DATA);
name = av_frame_side_data_name(sd->type);
print_str("side_data_type", name ? name : "unknown");
if (sd->type == AV_FRAME_DATA_DISPLAYMATRIX && sd->size >= 9*4) {
@@ -1275,15 +1270,15 @@ static void print_frame_side_data(WriterContext *w,
} else if (sd->type == AV_FRAME_DATA_S12M_TIMECODE && sd->size == 16) {
uint32_t *tc = (uint32_t*)sd->data;
int m = FFMIN(tc[0],3);
- writer_print_section_header(w, NULL, SECTION_ID_FRAME_SIDE_DATA_TIMECODE_LIST);
+ avtext_print_section_header(w, NULL, SECTION_ID_FRAME_SIDE_DATA_TIMECODE_LIST);
for (int j = 1; j <= m ; j++) {
char tcbuf[AV_TIMECODE_STR_SIZE];
av_timecode_make_smpte_tc_string2(tcbuf, stream->avg_frame_rate, tc[j], 0, 0);
- writer_print_section_header(w, NULL, SECTION_ID_FRAME_SIDE_DATA_TIMECODE);
+ avtext_print_section_header(w, NULL, SECTION_ID_FRAME_SIDE_DATA_TIMECODE);
print_str("value", tcbuf);
- writer_print_section_footer(w);
+ avtext_print_section_footer(w);
}
- writer_print_section_footer(w);
+ avtext_print_section_footer(w);
} else if (sd->type == AV_FRAME_DATA_MASTERING_DISPLAY_METADATA) {
AVMasteringDisplayMetadata *metadata = (AVMasteringDisplayMetadata *)sd->data;
@@ -1328,12 +1323,12 @@ static void print_frame_side_data(WriterContext *w,
} else if (sd->type == AV_FRAME_DATA_VIEW_ID) {
print_int("view_id", *(int*)sd->data);
}
- writer_print_section_footer(w);
+ avtext_print_section_footer(w);
}
- writer_print_section_footer(w);
+ avtext_print_section_footer(w);
}
-static void show_frame(WriterContext *w, AVFrame *frame, AVStream *stream,
+static void show_frame(AVTextFormatContext *w, AVFrame *frame, AVStream *stream,
AVFormatContext *fmt_ctx)
{
FrameData *fd = frame->opaque_ref ? (FrameData*)frame->opaque_ref->data : NULL;
@@ -1343,7 +1338,7 @@ static void show_frame(WriterContext *w, AVFrame *frame, AVStream *stream,
av_bprint_init(&pbuf, 1, AV_BPRINT_SIZE_UNLIMITED);
- writer_print_section_header(w, NULL, SECTION_ID_FRAME);
+ avtext_print_section_header(w, NULL, SECTION_ID_FRAME);
s = av_get_media_type_string(stream->codecpar->codec_type);
if (s) print_str ("media_type", s);
@@ -1415,13 +1410,13 @@ static void show_frame(WriterContext *w, AVFrame *frame, AVStream *stream,
if (frame->nb_side_data)
print_frame_side_data(w, frame, stream);
- writer_print_section_footer(w);
+ avtext_print_section_footer(w);
av_bprint_finalize(&pbuf, NULL);
fflush(stdout);
}
-static av_always_inline int process_frame(WriterContext *w,
+static av_always_inline int process_frame(AVTextFormatContext *w,
InputFile *ifile,
AVFrame *frame, const AVPacket *pkt,
int *packet_new)
@@ -1518,7 +1513,7 @@ static void log_read_interval(const ReadInterval *interval, void *log_ctx, int l
av_log(log_ctx, log_level, "\n");
}
-static int read_interval_packets(WriterContext *w, InputFile *ifile,
+static int read_interval_packets(AVTextFormatContext *w, InputFile *ifile,
const ReadInterval *interval, int64_t *cur_ts)
{
AVFormatContext *fmt_ctx = ifile->fmt_ctx;
@@ -1643,7 +1638,7 @@ end:
return ret;
}
-static int read_packets(WriterContext *w, InputFile *ifile)
+static int read_packets(AVTextFormatContext *w, InputFile *ifile)
{
AVFormatContext *fmt_ctx = ifile->fmt_ctx;
int i, ret = 0;
@@ -1663,22 +1658,22 @@ static int read_packets(WriterContext *w, InputFile *ifile)
return ret;
}
-static void print_dispositions(WriterContext *w, uint32_t disposition, SectionID section_id)
+static void print_dispositions(AVTextFormatContext *w, uint32_t disposition, SectionID section_id)
{
- writer_print_section_header(w, NULL, section_id);
+ avtext_print_section_header(w, NULL, section_id);
for (int i = 0; i < sizeof(disposition) * CHAR_BIT; i++) {
const char *disposition_str = av_disposition_to_string(1U << i);
if (disposition_str)
print_int(disposition_str, !!(disposition & (1U << i)));
}
- writer_print_section_footer(w);
+ avtext_print_section_footer(w);
}
#define IN_PROGRAM 1
#define IN_STREAM_GROUP 2
-static int show_stream(WriterContext *w, AVFormatContext *fmt_ctx, int stream_idx, InputStream *ist, int container)
+static int show_stream(AVTextFormatContext *w, AVFormatContext *fmt_ctx, int stream_idx, InputStream *ist, int container)
{
AVStream *stream = ist->st;
AVCodecParameters *par;
@@ -1710,7 +1705,7 @@ static int show_stream(WriterContext *w, AVFormatContext *fmt_ctx, int stream_id
av_bprint_init(&pbuf, 1, AV_BPRINT_SIZE_UNLIMITED);
- writer_print_section_header(w, NULL, section_header[container]);
+ avtext_print_section_header(w, NULL, section_header[container]);
print_int("index", stream->index);
@@ -1885,45 +1880,45 @@ static int show_stream(WriterContext *w, AVFormatContext *fmt_ctx, int stream_id
}
if (stream->codecpar->nb_coded_side_data) {
- writer_print_section_header(w, NULL, SECTION_ID_STREAM_SIDE_DATA_LIST);
+ avtext_print_section_header(w, NULL, SECTION_ID_STREAM_SIDE_DATA_LIST);
for (int i = 0; i < stream->codecpar->nb_coded_side_data; i++) {
print_pkt_side_data(w, stream->codecpar, &stream->codecpar->coded_side_data[i],
SECTION_ID_STREAM_SIDE_DATA);
- writer_print_section_footer(w);
+ avtext_print_section_footer(w);
}
- writer_print_section_footer(w);
+ avtext_print_section_footer(w);
}
- writer_print_section_footer(w);
+ avtext_print_section_footer(w);
av_bprint_finalize(&pbuf, NULL);
fflush(stdout);
return ret;
}
-static int show_streams(WriterContext *w, InputFile *ifile)
+static int show_streams(AVTextFormatContext *w, InputFile *ifile)
{
AVFormatContext *fmt_ctx = ifile->fmt_ctx;
int i, ret = 0;
- writer_print_section_header(w, NULL, SECTION_ID_STREAMS);
+ avtext_print_section_header(w, NULL, SECTION_ID_STREAMS);
for (i = 0; i < ifile->nb_streams; i++)
if (selected_streams[i]) {
ret = show_stream(w, fmt_ctx, i, &ifile->streams[i], 0);
if (ret < 0)
break;
}
- writer_print_section_footer(w);
+ avtext_print_section_footer(w);
return ret;
}
-static int show_program(WriterContext *w, InputFile *ifile, AVProgram *program)
+static int show_program(AVTextFormatContext *w, InputFile *ifile, AVProgram *program)
{
AVFormatContext *fmt_ctx = ifile->fmt_ctx;
int i, ret = 0;
- writer_print_section_header(w, NULL, SECTION_ID_PROGRAM);
+ avtext_print_section_header(w, NULL, SECTION_ID_PROGRAM);
print_int("program_id", program->id);
print_int("program_num", program->program_num);
print_int("nb_streams", program->nb_stream_indexes);
@@ -1934,7 +1929,7 @@ static int show_program(WriterContext *w, InputFile *ifile, AVProgram *program)
if (ret < 0)
goto end;
- writer_print_section_header(w, NULL, SECTION_ID_PROGRAM_STREAMS);
+ avtext_print_section_header(w, NULL, SECTION_ID_PROGRAM_STREAMS);
for (i = 0; i < program->nb_stream_indexes; i++) {
if (selected_streams[program->stream_index[i]]) {
ret = show_stream(w, fmt_ctx, program->stream_index[i], &ifile->streams[program->stream_index[i]], IN_PROGRAM);
@@ -1942,19 +1937,19 @@ static int show_program(WriterContext *w, InputFile *ifile, AVProgram *program)
break;
}
}
- writer_print_section_footer(w);
+ avtext_print_section_footer(w);
end:
- writer_print_section_footer(w);
+ avtext_print_section_footer(w);
return ret;
}
-static int show_programs(WriterContext *w, InputFile *ifile)
+static int show_programs(AVTextFormatContext *w, InputFile *ifile)
{
AVFormatContext *fmt_ctx = ifile->fmt_ctx;
int i, ret = 0;
- writer_print_section_header(w, NULL, SECTION_ID_PROGRAMS);
+ avtext_print_section_header(w, NULL, SECTION_ID_PROGRAMS);
for (i = 0; i < fmt_ctx->nb_programs; i++) {
AVProgram *program = fmt_ctx->programs[i];
if (!program)
@@ -1963,14 +1958,14 @@ static int show_programs(WriterContext *w, InputFile *ifile)
if (ret < 0)
break;
}
- writer_print_section_footer(w);
+ avtext_print_section_footer(w);
return ret;
}
-static void print_tile_grid_params(WriterContext *w, const AVStreamGroup *stg,
+static void print_tile_grid_params(AVTextFormatContext *w, const AVStreamGroup *stg,
const AVStreamGroupTileGrid *tile_grid)
{
- writer_print_section_header(w, stg, SECTION_ID_STREAM_GROUP_COMPONENT);
+ avtext_print_section_header(w, stg, SECTION_ID_STREAM_GROUP_COMPONENT);
print_int("nb_tiles", tile_grid->nb_tiles);
print_int("coded_width", tile_grid->coded_width);
print_int("coded_height", tile_grid->coded_height);
@@ -1978,19 +1973,19 @@ static void print_tile_grid_params(WriterContext *w, const AVStreamGroup *stg,
print_int("vertical_offset", tile_grid->vertical_offset);
print_int("width", tile_grid->width);
print_int("height", tile_grid->height);
- writer_print_section_header(w, NULL, SECTION_ID_STREAM_GROUP_SUBCOMPONENTS);
+ avtext_print_section_header(w, NULL, SECTION_ID_STREAM_GROUP_SUBCOMPONENTS);
for (int i = 0; i < tile_grid->nb_tiles; i++) {
- writer_print_section_header(w, "tile_offset", SECTION_ID_STREAM_GROUP_SUBCOMPONENT);
+ avtext_print_section_header(w, "tile_offset", SECTION_ID_STREAM_GROUP_SUBCOMPONENT);
print_int("stream_index", tile_grid->offsets[i].idx);
print_int("tile_horizontal_offset", tile_grid->offsets[i].horizontal);
print_int("tile_vertical_offset", tile_grid->offsets[i].vertical);
- writer_print_section_footer(w);
+ avtext_print_section_footer(w);
}
- writer_print_section_footer(w);
- writer_print_section_footer(w);
+ avtext_print_section_footer(w);
+ avtext_print_section_footer(w);
}
-static void print_iamf_param_definition(WriterContext *w, const char *name,
+static void print_iamf_param_definition(AVTextFormatContext *w, const char *name,
const AVIAMFParamDefinition *param, SectionID section_id)
{
SectionID subsection_id, parameter_section_id;
@@ -1998,7 +1993,7 @@ static void print_iamf_param_definition(WriterContext *w, const char *name,
av_assert0(subsection_id != -1);
parameter_section_id = sections[subsection_id].children_ids[0];
av_assert0(parameter_section_id != -1);
- writer_print_section_header(w, "IAMF Param Definition", section_id);
+ avtext_print_section_header(w, "IAMF Param Definition", section_id);
print_str("name", name);
print_int("nb_subblocks", param->nb_subblocks);
print_int("type", param->type);
@@ -2007,56 +2002,56 @@ static void print_iamf_param_definition(WriterContext *w, const char *name,
print_int("duration", param->duration);
print_int("constant_subblock_duration", param->constant_subblock_duration);
if (param->nb_subblocks > 0)
- writer_print_section_header(w, NULL, subsection_id);
+ avtext_print_section_header(w, NULL, subsection_id);
for (int i = 0; i < param->nb_subblocks; i++) {
const void *subblock = av_iamf_param_definition_get_subblock(param, i);
switch(param->type) {
case AV_IAMF_PARAMETER_DEFINITION_MIX_GAIN: {
const AVIAMFMixGain *mix = subblock;
- writer_print_section_header(w, "IAMF Mix Gain Parameters", parameter_section_id);
+ avtext_print_section_header(w, "IAMF Mix Gain Parameters", parameter_section_id);
print_int("subblock_duration", mix->subblock_duration);
print_int("animation_type", mix->animation_type);
print_q("start_point_value", mix->start_point_value, '/');
print_q("end_point_value", mix->end_point_value, '/');
print_q("control_point_value", mix->control_point_value, '/');
print_q("control_point_relative_time", mix->control_point_relative_time, '/');
- writer_print_section_footer(w); // parameter_section_id
+ avtext_print_section_footer(w); // parameter_section_id
break;
}
case AV_IAMF_PARAMETER_DEFINITION_DEMIXING: {
const AVIAMFDemixingInfo *demix = subblock;
- writer_print_section_header(w, "IAMF Demixing Info", parameter_section_id);
+ avtext_print_section_header(w, "IAMF Demixing Info", parameter_section_id);
print_int("subblock_duration", demix->subblock_duration);
print_int("dmixp_mode", demix->dmixp_mode);
- writer_print_section_footer(w); // parameter_section_id
+ avtext_print_section_footer(w); // parameter_section_id
break;
}
case AV_IAMF_PARAMETER_DEFINITION_RECON_GAIN: {
const AVIAMFReconGain *recon = subblock;
- writer_print_section_header(w, "IAMF Recon Gain", parameter_section_id);
+ avtext_print_section_header(w, "IAMF Recon Gain", parameter_section_id);
print_int("subblock_duration", recon->subblock_duration);
- writer_print_section_footer(w); // parameter_section_id
+ avtext_print_section_footer(w); // parameter_section_id
break;
}
}
}
if (param->nb_subblocks > 0)
- writer_print_section_footer(w); // subsection_id
- writer_print_section_footer(w); // section_id
+ avtext_print_section_footer(w); // subsection_id
+ avtext_print_section_footer(w); // section_id
}
-static void print_iamf_audio_element_params(WriterContext *w, const AVStreamGroup *stg,
+static void print_iamf_audio_element_params(AVTextFormatContext *w, const AVStreamGroup *stg,
const AVIAMFAudioElement *audio_element)
{
- writer_print_section_header(w, stg, SECTION_ID_STREAM_GROUP_COMPONENT);
+ avtext_print_section_header(w, stg, SECTION_ID_STREAM_GROUP_COMPONENT);
print_int("nb_layers", audio_element->nb_layers);
print_int("audio_element_type", audio_element->audio_element_type);
print_int("default_w", audio_element->default_w);
- writer_print_section_header(w, NULL, SECTION_ID_STREAM_GROUP_SUBCOMPONENTS);
+ avtext_print_section_header(w, NULL, SECTION_ID_STREAM_GROUP_SUBCOMPONENTS);
for (int i = 0; i < audio_element->nb_layers; i++) {
const AVIAMFLayer *layer = audio_element->layers[i];
char val_str[128];
- writer_print_section_header(w, "IAMF Audio Layer", SECTION_ID_STREAM_GROUP_SUBCOMPONENT);
+ avtext_print_section_header(w, "IAMF Audio Layer", SECTION_ID_STREAM_GROUP_SUBCOMPONENT);
av_channel_layout_describe(&layer->ch_layout, val_str, sizeof(val_str));
print_str("channel_layout", val_str);
if (audio_element->audio_element_type == AV_IAMF_AUDIO_ELEMENT_TYPE_CHANNEL) {
@@ -2064,7 +2059,7 @@ static void print_iamf_audio_element_params(WriterContext *w, const AVStreamGrou
print_q("output_gain", layer->output_gain, '/');
} else if (audio_element->audio_element_type == AV_IAMF_AUDIO_ELEMENT_TYPE_SCENE)
print_int("ambisonics_mode", layer->ambisonics_mode);
- writer_print_section_footer(w); // SECTION_ID_STREAM_GROUP_SUBCOMPONENT
+ avtext_print_section_footer(w); // SECTION_ID_STREAM_GROUP_SUBCOMPONENT
}
if (audio_element->demixing_info)
print_iamf_param_definition(w, "demixing_info", audio_element->demixing_info,
@@ -2072,36 +2067,36 @@ static void print_iamf_audio_element_params(WriterContext *w, const AVStreamGrou
if (audio_element->recon_gain_info)
print_iamf_param_definition(w, "recon_gain_info", audio_element->recon_gain_info,
SECTION_ID_STREAM_GROUP_SUBCOMPONENT);
- writer_print_section_footer(w); // SECTION_ID_STREAM_GROUP_SUBCOMPONENTS
- writer_print_section_footer(w); // SECTION_ID_STREAM_GROUP_COMPONENT
+ avtext_print_section_footer(w); // SECTION_ID_STREAM_GROUP_SUBCOMPONENTS
+ avtext_print_section_footer(w); // SECTION_ID_STREAM_GROUP_COMPONENT
}
-static void print_iamf_submix_params(WriterContext *w, const AVIAMFSubmix *submix)
+static void print_iamf_submix_params(AVTextFormatContext *w, const AVIAMFSubmix *submix)
{
- writer_print_section_header(w, "IAMF Submix", SECTION_ID_STREAM_GROUP_SUBCOMPONENT);
+ avtext_print_section_header(w, "IAMF Submix", SECTION_ID_STREAM_GROUP_SUBCOMPONENT);
print_int("nb_elements", submix->nb_elements);
print_int("nb_layouts", submix->nb_layouts);
print_q("default_mix_gain", submix->default_mix_gain, '/');
- writer_print_section_header(w, NULL, SECTION_ID_STREAM_GROUP_PIECES);
+ avtext_print_section_header(w, NULL, SECTION_ID_STREAM_GROUP_PIECES);
for (int i = 0; i < submix->nb_elements; i++) {
const AVIAMFSubmixElement *element = submix->elements[i];
- writer_print_section_header(w, "IAMF Submix Element", SECTION_ID_STREAM_GROUP_PIECE);
+ avtext_print_section_header(w, "IAMF Submix Element", SECTION_ID_STREAM_GROUP_PIECE);
print_int("stream_id", element->audio_element_id);
print_q("default_mix_gain", element->default_mix_gain, '/');
print_int("headphones_rendering_mode", element->headphones_rendering_mode);
- writer_print_section_header(w, NULL, SECTION_ID_STREAM_GROUP_SUBPIECES);
+ avtext_print_section_header(w, NULL, SECTION_ID_STREAM_GROUP_SUBPIECES);
if (element->annotations) {
const AVDictionaryEntry *annotation = NULL;
- writer_print_section_header(w, "IAMF Annotations", SECTION_ID_STREAM_GROUP_SUBPIECE);
+ avtext_print_section_header(w, "IAMF Annotations", SECTION_ID_STREAM_GROUP_SUBPIECE);
while (annotation = av_dict_iterate(element->annotations, annotation))
print_str(annotation->key, annotation->value);
- writer_print_section_footer(w); // SECTION_ID_STREAM_GROUP_SUBPIECE
+ avtext_print_section_footer(w); // SECTION_ID_STREAM_GROUP_SUBPIECE
}
if (element->element_mix_config)
print_iamf_param_definition(w, "element_mix_config", element->element_mix_config,
SECTION_ID_STREAM_GROUP_SUBPIECE);
- writer_print_section_footer(w); // SECTION_ID_STREAM_GROUP_SUBPIECES
- writer_print_section_footer(w); // SECTION_ID_STREAM_GROUP_PIECE
+ avtext_print_section_footer(w); // SECTION_ID_STREAM_GROUP_SUBPIECES
+ avtext_print_section_footer(w); // SECTION_ID_STREAM_GROUP_PIECE
}
if (submix->output_mix_config)
print_iamf_param_definition(w, "output_mix_config", submix->output_mix_config,
@@ -2109,7 +2104,7 @@ static void print_iamf_submix_params(WriterContext *w, const AVIAMFSubmix *submi
for (int i = 0; i < submix->nb_layouts; i++) {
const AVIAMFSubmixLayout *layout = submix->layouts[i];
char val_str[128];
- writer_print_section_header(w, "IAMF Submix Layout", SECTION_ID_STREAM_GROUP_PIECE);
+ avtext_print_section_header(w, "IAMF Submix Layout", SECTION_ID_STREAM_GROUP_PIECE);
av_channel_layout_describe(&layout->sound_system, val_str, sizeof(val_str));
print_str("sound_system", val_str);
print_q("integrated_loudness", layout->integrated_loudness, '/');
@@ -2117,51 +2112,51 @@ static void print_iamf_submix_params(WriterContext *w, const AVIAMFSubmix *submi
print_q("true_peak", layout->true_peak, '/');
print_q("dialogue_anchored_loudness", layout->dialogue_anchored_loudness, '/');
print_q("album_anchored_loudness", layout->album_anchored_loudness, '/');
- writer_print_section_footer(w); // SECTION_ID_STREAM_GROUP_PIECE
+ avtext_print_section_footer(w); // SECTION_ID_STREAM_GROUP_PIECE
}
- writer_print_section_footer(w); // SECTION_ID_STREAM_GROUP_PIECES
- writer_print_section_footer(w); // SECTION_ID_STREAM_GROUP_SUBCOMPONENT
+ avtext_print_section_footer(w); // SECTION_ID_STREAM_GROUP_PIECES
+ avtext_print_section_footer(w); // SECTION_ID_STREAM_GROUP_SUBCOMPONENT
}
-static void print_iamf_mix_presentation_params(WriterContext *w, const AVStreamGroup *stg,
+static void print_iamf_mix_presentation_params(AVTextFormatContext *w, const AVStreamGroup *stg,
const AVIAMFMixPresentation *mix_presentation)
{
- writer_print_section_header(w, stg, SECTION_ID_STREAM_GROUP_COMPONENT);
+ avtext_print_section_header(w, stg, SECTION_ID_STREAM_GROUP_COMPONENT);
print_int("nb_submixes", mix_presentation->nb_submixes);
- writer_print_section_header(w, NULL, SECTION_ID_STREAM_GROUP_SUBCOMPONENTS);
+ avtext_print_section_header(w, NULL, SECTION_ID_STREAM_GROUP_SUBCOMPONENTS);
if (mix_presentation->annotations) {
const AVDictionaryEntry *annotation = NULL;
- writer_print_section_header(w, "IAMF Annotations", SECTION_ID_STREAM_GROUP_SUBCOMPONENT);
+ avtext_print_section_header(w, "IAMF Annotations", SECTION_ID_STREAM_GROUP_SUBCOMPONENT);
while (annotation = av_dict_iterate(mix_presentation->annotations, annotation))
print_str(annotation->key, annotation->value);
- writer_print_section_footer(w); // SECTION_ID_STREAM_GROUP_SUBCOMPONENT
+ avtext_print_section_footer(w); // SECTION_ID_STREAM_GROUP_SUBCOMPONENT
}
for (int i = 0; i < mix_presentation->nb_submixes; i++)
print_iamf_submix_params(w, mix_presentation->submixes[i]);
- writer_print_section_footer(w); // SECTION_ID_STREAM_GROUP_SUBCOMPONENTS
- writer_print_section_footer(w); // SECTION_ID_STREAM_GROUP_COMPONENT
+ avtext_print_section_footer(w); // SECTION_ID_STREAM_GROUP_SUBCOMPONENTS
+ avtext_print_section_footer(w); // SECTION_ID_STREAM_GROUP_COMPONENT
}
-static void print_stream_group_params(WriterContext *w, AVStreamGroup *stg)
+static void print_stream_group_params(AVTextFormatContext *w, AVStreamGroup *stg)
{
- writer_print_section_header(w, NULL, SECTION_ID_STREAM_GROUP_COMPONENTS);
+ avtext_print_section_header(w, NULL, SECTION_ID_STREAM_GROUP_COMPONENTS);
if (stg->type == AV_STREAM_GROUP_PARAMS_TILE_GRID)
print_tile_grid_params(w, stg, stg->params.tile_grid);
else if (stg->type == AV_STREAM_GROUP_PARAMS_IAMF_AUDIO_ELEMENT)
print_iamf_audio_element_params(w, stg, stg->params.iamf_audio_element);
else if (stg->type == AV_STREAM_GROUP_PARAMS_IAMF_MIX_PRESENTATION)
print_iamf_mix_presentation_params(w, stg, stg->params.iamf_mix_presentation);
- writer_print_section_footer(w); // SECTION_ID_STREAM_GROUP_COMPONENTS
+ avtext_print_section_footer(w); // SECTION_ID_STREAM_GROUP_COMPONENTS
}
-static int show_stream_group(WriterContext *w, InputFile *ifile, AVStreamGroup *stg)
+static int show_stream_group(AVTextFormatContext *w, InputFile *ifile, AVStreamGroup *stg)
{
AVFormatContext *fmt_ctx = ifile->fmt_ctx;
AVBPrint pbuf;
int i, ret = 0;
av_bprint_init(&pbuf, 1, AV_BPRINT_SIZE_UNLIMITED);
- writer_print_section_header(w, NULL, SECTION_ID_STREAM_GROUP);
+ avtext_print_section_header(w, NULL, SECTION_ID_STREAM_GROUP);
print_int("index", stg->index);
if (fmt_ctx->iformat->flags & AVFMT_SHOW_IDS) print_fmt ("id", "0x%"PRIx64, stg->id);
else print_str_opt("id", "N/A");
@@ -2182,7 +2177,7 @@ static int show_stream_group(WriterContext *w, InputFile *ifile, AVStreamGroup *
if (ret < 0)
goto end;
- writer_print_section_header(w, NULL, SECTION_ID_STREAM_GROUP_STREAMS);
+ avtext_print_section_header(w, NULL, SECTION_ID_STREAM_GROUP_STREAMS);
for (i = 0; i < stg->nb_streams; i++) {
if (selected_streams[stg->streams[i]->index]) {
ret = show_stream(w, fmt_ctx, stg->streams[i]->index, &ifile->streams[stg->streams[i]->index], IN_STREAM_GROUP);
@@ -2190,20 +2185,20 @@ static int show_stream_group(WriterContext *w, InputFile *ifile, AVStreamGroup *
break;
}
}
- writer_print_section_footer(w);
+ avtext_print_section_footer(w);
end:
av_bprint_finalize(&pbuf, NULL);
- writer_print_section_footer(w);
+ avtext_print_section_footer(w);
return ret;
}
-static int show_stream_groups(WriterContext *w, InputFile *ifile)
+static int show_stream_groups(AVTextFormatContext *w, InputFile *ifile)
{
AVFormatContext *fmt_ctx = ifile->fmt_ctx;
int i, ret = 0;
- writer_print_section_header(w, NULL, SECTION_ID_STREAM_GROUPS);
+ avtext_print_section_header(w, NULL, SECTION_ID_STREAM_GROUPS);
for (i = 0; i < fmt_ctx->nb_stream_groups; i++) {
AVStreamGroup *stg = fmt_ctx->stream_groups[i];
@@ -2211,20 +2206,20 @@ static int show_stream_groups(WriterContext *w, InputFile *ifile)
if (ret < 0)
break;
}
- writer_print_section_footer(w);
+ avtext_print_section_footer(w);
return ret;
}
-static int show_chapters(WriterContext *w, InputFile *ifile)
+static int show_chapters(AVTextFormatContext *w, InputFile *ifile)
{
AVFormatContext *fmt_ctx = ifile->fmt_ctx;
int i, ret = 0;
- writer_print_section_header(w, NULL, SECTION_ID_CHAPTERS);
+ avtext_print_section_header(w, NULL, SECTION_ID_CHAPTERS);
for (i = 0; i < fmt_ctx->nb_chapters; i++) {
AVChapter *chapter = fmt_ctx->chapters[i];
- writer_print_section_header(w, NULL, SECTION_ID_CHAPTER);
+ avtext_print_section_header(w, NULL, SECTION_ID_CHAPTER);
print_int("id", chapter->id);
print_q ("time_base", chapter->time_base, '/');
print_int("start", chapter->start);
@@ -2233,20 +2228,20 @@ static int show_chapters(WriterContext *w, InputFile *ifile)
print_time("end_time", chapter->end, &chapter->time_base);
if (do_show_chapter_tags)
ret = show_tags(w, chapter->metadata, SECTION_ID_CHAPTER_TAGS);
- writer_print_section_footer(w);
+ avtext_print_section_footer(w);
}
- writer_print_section_footer(w);
+ avtext_print_section_footer(w);
return ret;
}
-static int show_format(WriterContext *w, InputFile *ifile)
+static int show_format(AVTextFormatContext *w, InputFile *ifile)
{
AVFormatContext *fmt_ctx = ifile->fmt_ctx;
int64_t size = fmt_ctx->pb ? avio_size(fmt_ctx->pb) : -1;
int ret = 0;
- writer_print_section_header(w, NULL, SECTION_ID_FORMAT);
+ avtext_print_section_header(w, NULL, SECTION_ID_FORMAT);
print_str_validate("filename", fmt_ctx->url);
print_int("nb_streams", fmt_ctx->nb_streams);
print_int("nb_programs", fmt_ctx->nb_programs);
@@ -2266,17 +2261,17 @@ static int show_format(WriterContext *w, InputFile *ifile)
if (do_show_format_tags)
ret = show_tags(w, fmt_ctx->metadata, SECTION_ID_FORMAT_TAGS);
- writer_print_section_footer(w);
+ avtext_print_section_footer(w);
fflush(stdout);
return ret;
}
-static void show_error(WriterContext *w, int err)
+static void show_error(AVTextFormatContext *w, int err)
{
- writer_print_section_header(w, NULL, SECTION_ID_ERROR);
+ avtext_print_section_header(w, NULL, SECTION_ID_ERROR);
print_int("code", err);
print_str("string", av_err2str(err));
- writer_print_section_footer(w);
+ avtext_print_section_footer(w);
}
static int open_input_file(InputFile *ifile, const char *filename,
@@ -2418,7 +2413,7 @@ static void close_input_file(InputFile *ifile)
avformat_close_input(&ifile->fmt_ctx);
}
-static int probe_file(WriterContext *tctx, const char *filename,
+static int probe_file(AVTextFormatContext *tctx, const char *filename,
const char *print_filename)
{
InputFile ifile = { 0 };
@@ -2467,10 +2462,10 @@ static int probe_file(WriterContext *tctx, const char *filename,
else // (!do_show_packets && do_show_frames)
section_id = SECTION_ID_FRAMES;
if (do_show_frames || do_show_packets)
- writer_print_section_header(tctx, NULL, section_id);
+ avtext_print_section_header(tctx, NULL, section_id);
ret = read_packets(tctx, &ifile);
if (do_show_frames || do_show_packets)
- writer_print_section_footer(tctx);
+ avtext_print_section_footer(tctx);
CHECK_END;
}
@@ -2516,18 +2511,18 @@ static void show_usage(void)
av_log(NULL, AV_LOG_INFO, "\n");
}
-static void ffprobe_show_program_version(WriterContext *w)
+static void ffprobe_show_program_version(AVTextFormatContext *w)
{
AVBPrint pbuf;
av_bprint_init(&pbuf, 1, AV_BPRINT_SIZE_UNLIMITED);
- writer_print_section_header(w, NULL, SECTION_ID_PROGRAM_VERSION);
+ avtext_print_section_header(w, NULL, SECTION_ID_PROGRAM_VERSION);
print_str("version", FFMPEG_VERSION);
print_fmt("copyright", "Copyright (c) %d-%d the FFmpeg developers",
program_birth_year, CONFIG_THIS_YEAR);
print_str("compiler_ident", CC_IDENT);
print_str("configuration", FFMPEG_CONFIGURATION);
- writer_print_section_footer(w);
+ avtext_print_section_footer(w);
av_bprint_finalize(&pbuf, NULL);
}
@@ -2536,20 +2531,20 @@ static void ffprobe_show_program_version(WriterContext *w)
do { \
if (CONFIG_##LIBNAME) { \
unsigned int version = libname##_version(); \
- writer_print_section_header(w, NULL, SECTION_ID_LIBRARY_VERSION); \
+ avtext_print_section_header(w, NULL, SECTION_ID_LIBRARY_VERSION); \
print_str("name", "lib" #libname); \
print_int("major", LIB##LIBNAME##_VERSION_MAJOR); \
print_int("minor", LIB##LIBNAME##_VERSION_MINOR); \
print_int("micro", LIB##LIBNAME##_VERSION_MICRO); \
print_int("version", version); \
print_str("ident", LIB##LIBNAME##_IDENT); \
- writer_print_section_footer(w); \
+ avtext_print_section_footer(w); \
} \
} while (0)
-static void ffprobe_show_library_versions(WriterContext *w)
+static void ffprobe_show_library_versions(AVTextFormatContext *w)
{
- writer_print_section_header(w, NULL, SECTION_ID_LIBRARY_VERSIONS);
+ avtext_print_section_header(w, NULL, SECTION_ID_LIBRARY_VERSIONS);
SHOW_LIB_VERSION(avutil, AVUTIL);
SHOW_LIB_VERSION(avcodec, AVCODEC);
SHOW_LIB_VERSION(avformat, AVFORMAT);
@@ -2558,7 +2553,7 @@ static void ffprobe_show_library_versions(WriterContext *w)
SHOW_LIB_VERSION(swscale, SWSCALE);
SHOW_LIB_VERSION(swresample, SWRESAMPLE);
SHOW_LIB_VERSION(postproc, POSTPROC);
- writer_print_section_footer(w);
+ avtext_print_section_footer(w);
}
#define PRINT_PIX_FMT_FLAG(flagname, name) \
@@ -2566,14 +2561,14 @@ static void ffprobe_show_library_versions(WriterContext *w)
print_int(name, !!(pixdesc->flags & AV_PIX_FMT_FLAG_##flagname)); \
} while (0)
-static void ffprobe_show_pixel_formats(WriterContext *w)
+static void ffprobe_show_pixel_formats(AVTextFormatContext *w)
{
const AVPixFmtDescriptor *pixdesc = NULL;
int i, n;
- writer_print_section_header(w, NULL, SECTION_ID_PIXEL_FORMATS);
+ avtext_print_section_header(w, NULL, SECTION_ID_PIXEL_FORMATS);
while (pixdesc = av_pix_fmt_desc_next(pixdesc)) {
- writer_print_section_header(w, NULL, SECTION_ID_PIXEL_FORMAT);
+ avtext_print_section_header(w, NULL, SECTION_ID_PIXEL_FORMAT);
print_str("name", pixdesc->name);
print_int("nb_components", pixdesc->nb_components);
if ((pixdesc->nb_components >= 3) && !(pixdesc->flags & AV_PIX_FMT_FLAG_RGB)) {
@@ -2587,7 +2582,7 @@ static void ffprobe_show_pixel_formats(WriterContext *w)
if (n) print_int ("bits_per_pixel", n);
else print_str_opt("bits_per_pixel", "N/A");
if (do_show_pixel_format_flags) {
- writer_print_section_header(w, NULL, SECTION_ID_PIXEL_FORMAT_FLAGS);
+ avtext_print_section_header(w, NULL, SECTION_ID_PIXEL_FORMAT_FLAGS);
PRINT_PIX_FMT_FLAG(BE, "big_endian");
PRINT_PIX_FMT_FLAG(PAL, "palette");
PRINT_PIX_FMT_FLAG(BITSTREAM, "bitstream");
@@ -2595,21 +2590,21 @@ static void ffprobe_show_pixel_formats(WriterContext *w)
PRINT_PIX_FMT_FLAG(PLANAR, "planar");
PRINT_PIX_FMT_FLAG(RGB, "rgb");
PRINT_PIX_FMT_FLAG(ALPHA, "alpha");
- writer_print_section_footer(w);
+ avtext_print_section_footer(w);
}
if (do_show_pixel_format_components && (pixdesc->nb_components > 0)) {
- writer_print_section_header(w, NULL, SECTION_ID_PIXEL_FORMAT_COMPONENTS);
+ avtext_print_section_header(w, NULL, SECTION_ID_PIXEL_FORMAT_COMPONENTS);
for (i = 0; i < pixdesc->nb_components; i++) {
- writer_print_section_header(w, NULL, SECTION_ID_PIXEL_FORMAT_COMPONENT);
+ avtext_print_section_header(w, NULL, SECTION_ID_PIXEL_FORMAT_COMPONENT);
print_int("index", i + 1);
print_int("bit_depth", pixdesc->comp[i].depth);
- writer_print_section_footer(w);
+ avtext_print_section_footer(w);
}
- writer_print_section_footer(w);
+ avtext_print_section_footer(w);
}
- writer_print_section_footer(w);
+ avtext_print_section_footer(w);
}
- writer_print_section_footer(w);
+ avtext_print_section_footer(w);
}
static int opt_show_optional_fields(void *optctx, const char *opt, const char *arg)
@@ -3057,7 +3052,7 @@ static inline int check_section_show_entries(int section_id)
int main(int argc, char **argv)
{
const AVTextFormatter *f;
- WriterContext *tctx;
+ AVTextFormatContext *tctx;
AVTextWriterContext *wctx;
char *buf;
char *f_name = NULL, *f_args = NULL;
@@ -3159,7 +3154,7 @@ int main(int argc, char **argv)
if (f == &avtextformatter_xml)
tctx->string_validation_utf8_flags |= AV_UTF8_FLAG_EXCLUDE_XML_INVALID_CONTROL_CODES;
- writer_print_section_header(tctx, NULL, SECTION_ID_ROOT);
+ avtext_print_section_header(tctx, NULL, SECTION_ID_ROOT);
if (do_show_program_version)
ffprobe_show_program_version(tctx);
--
ffmpeg-codebot
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 108+ messages in thread
* [FFmpeg-devel] [PATCH v7 4/7] fftools/ffmpeg_filter: Move some declaration to new header file
2025-03-12 4:04 ` [FFmpeg-devel] [PATCH v7 0/7] " ffmpegagent
` (2 preceding siblings ...)
2025-03-12 4:04 ` [FFmpeg-devel] [PATCH v7 3/7] fftools/ffprobe: Rename writer_print_section_* and WriterContext softworkz
@ 2025-03-12 4:04 ` softworkz
2025-03-12 4:04 ` [FFmpeg-devel] [PATCH v7 5/7] avfilter/avfilter: Add avfilter_link_get_hw_frames_ctx() softworkz
` (3 subsequent siblings)
7 siblings, 0 replies; 108+ messages in thread
From: softworkz @ 2025-03-12 4:04 UTC (permalink / raw)
To: ffmpeg-devel; +Cc: softworkz
From: softworkz <softworkz@hotmail.com>
to allow print_graph to access the information.
Signed-off-by: softworkz <softworkz@hotmail.com>
---
fftools/ffmpeg_filter.c | 188 +-------------------------------
fftools/ffmpeg_filter.h | 232 ++++++++++++++++++++++++++++++++++++++++
2 files changed, 233 insertions(+), 187 deletions(-)
create mode 100644 fftools/ffmpeg_filter.h
diff --git a/fftools/ffmpeg_filter.c b/fftools/ffmpeg_filter.c
index cd8a4abc52..e6bfc72265 100644
--- a/fftools/ffmpeg_filter.c
+++ b/fftools/ffmpeg_filter.c
@@ -21,6 +21,7 @@
#include <stdint.h>
#include "ffmpeg.h"
+#include "ffmpeg_filter.h"
#include "libavfilter/avfilter.h"
#include "libavfilter/buffersink.h"
@@ -42,44 +43,6 @@
// FIXME private header, used for mid_pred()
#include "libavcodec/mathops.h"
-typedef struct FilterGraphPriv {
- FilterGraph fg;
-
- // name used for logging
- char log_name[32];
-
- int is_simple;
- // true when the filtergraph contains only meta filters
- // that do not modify the frame data
- int is_meta;
- // source filters are present in the graph
- int have_sources;
- int disable_conversions;
-
- unsigned nb_outputs_done;
-
- const char *graph_desc;
-
- int nb_threads;
-
- // frame for temporarily holding output from the filtergraph
- AVFrame *frame;
- // frame for sending output to the encoder
- AVFrame *frame_enc;
-
- Scheduler *sch;
- unsigned sch_idx;
-} FilterGraphPriv;
-
-static FilterGraphPriv *fgp_from_fg(FilterGraph *fg)
-{
- return (FilterGraphPriv*)fg;
-}
-
-static const FilterGraphPriv *cfgp_from_cfg(const FilterGraph *fg)
-{
- return (const FilterGraphPriv*)fg;
-}
// data that is local to the filter thread and not visible outside of it
typedef struct FilterGraphThread {
@@ -102,155 +65,6 @@ typedef struct FilterGraphThread {
uint8_t *eof_out;
} FilterGraphThread;
-typedef struct InputFilterPriv {
- InputFilter ifilter;
-
- InputFilterOptions opts;
-
- int index;
-
- AVFilterContext *filter;
-
- // used to hold submitted input
- AVFrame *frame;
-
- /* for filters that are not yet bound to an input stream,
- * this stores the input linklabel, if any */
- uint8_t *linklabel;
-
- // filter data type
- enum AVMediaType type;
- // source data type: AVMEDIA_TYPE_SUBTITLE for sub2video,
- // same as type otherwise
- enum AVMediaType type_src;
-
- int eof;
- int bound;
-
- // parameters configured for this input
- int format;
-
- int width, height;
- AVRational sample_aspect_ratio;
- enum AVColorSpace color_space;
- enum AVColorRange color_range;
-
- int sample_rate;
- AVChannelLayout ch_layout;
-
- AVRational time_base;
-
- AVFrameSideData **side_data;
- int nb_side_data;
-
- AVFifo *frame_queue;
-
- AVBufferRef *hw_frames_ctx;
-
- int displaymatrix_present;
- int displaymatrix_applied;
- int32_t displaymatrix[9];
-
- int downmixinfo_present;
- AVDownmixInfo downmixinfo;
-
- struct {
- AVFrame *frame;
-
- int64_t last_pts;
- int64_t end_pts;
-
- ///< marks if sub2video_update should force an initialization
- unsigned int initialize;
- } sub2video;
-} InputFilterPriv;
-
-static InputFilterPriv *ifp_from_ifilter(InputFilter *ifilter)
-{
- return (InputFilterPriv*)ifilter;
-}
-
-typedef struct FPSConvContext {
- AVFrame *last_frame;
- /* number of frames emitted by the video-encoding sync code */
- int64_t frame_number;
- /* history of nb_frames_prev, i.e. the number of times the
- * previous frame was duplicated by vsync code in recent
- * do_video_out() calls */
- int64_t frames_prev_hist[3];
-
- uint64_t dup_warning;
-
- int last_dropped;
- int dropped_keyframe;
-
- enum VideoSyncMethod vsync_method;
-
- AVRational framerate;
- AVRational framerate_max;
- const AVRational *framerate_supported;
- int framerate_clip;
-} FPSConvContext;
-
-typedef struct OutputFilterPriv {
- OutputFilter ofilter;
-
- int index;
-
- void *log_parent;
- char log_name[32];
-
- char *name;
-
- AVFilterContext *filter;
-
- /* desired output stream properties */
- int format;
- int width, height;
- int sample_rate;
- AVChannelLayout ch_layout;
- enum AVColorSpace color_space;
- enum AVColorRange color_range;
-
- AVFrameSideData **side_data;
- int nb_side_data;
-
- // time base in which the output is sent to our downstream
- // does not need to match the filtersink's timebase
- AVRational tb_out;
- // at least one frame with the above timebase was sent
- // to our downstream, so it cannot change anymore
- int tb_out_locked;
-
- AVRational sample_aspect_ratio;
-
- AVDictionary *sws_opts;
- AVDictionary *swr_opts;
-
- // those are only set if no format is specified and the encoder gives us multiple options
- // They point directly to the relevant lists of the encoder.
- const int *formats;
- const AVChannelLayout *ch_layouts;
- const int *sample_rates;
- const enum AVColorSpace *color_spaces;
- const enum AVColorRange *color_ranges;
-
- AVRational enc_timebase;
- int64_t trim_start_us;
- int64_t trim_duration_us;
- // offset for output timestamps, in AV_TIME_BASE_Q
- int64_t ts_offset;
- int64_t next_pts;
- FPSConvContext fps;
-
- unsigned flags;
-} OutputFilterPriv;
-
-static OutputFilterPriv *ofp_from_ofilter(OutputFilter *ofilter)
-{
- return (OutputFilterPriv*)ofilter;
-}
-
typedef struct FilterCommand {
char *target;
char *command;
diff --git a/fftools/ffmpeg_filter.h b/fftools/ffmpeg_filter.h
new file mode 100644
index 0000000000..94296c5eac
--- /dev/null
+++ b/fftools/ffmpeg_filter.h
@@ -0,0 +1,232 @@
+/*
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef FFTOOLS_FFMPEG_FILTER_H
+#define FFTOOLS_FFMPEG_FILTER_H
+
+#include "ffmpeg.h"
+
+#include <stdint.h>
+
+#include "ffmpeg_sched.h"
+#include "sync_queue.h"
+
+#include "libavfilter/avfilter.h"
+
+#include "libavutil/avutil.h"
+#include "libavutil/dict.h"
+#include "libavutil/fifo.h"
+#include "libavutil/pixfmt.h"
+#include "libavutil/rational.h"
+#include "libavutil/bprint.h"
+#include "libavutil/channel_layout.h"
+#include "libavutil/downmix_info.h"
+
+typedef struct FilterGraphPriv {
+ FilterGraph fg;
+
+ // name used for logging
+ char log_name[32];
+
+ int is_simple;
+ // true when the filtergraph contains only meta filters
+ // that do not modify the frame data
+ int is_meta;
+ // source filters are present in the graph
+ int have_sources;
+ int disable_conversions;
+
+ unsigned nb_outputs_done;
+
+ const char *graph_desc;
+
+ int nb_threads;
+
+ // frame for temporarily holding output from the filtergraph
+ AVFrame *frame;
+ // frame for sending output to the encoder
+ AVFrame *frame_enc;
+
+ Scheduler *sch;
+ unsigned sch_idx;
+
+ AVBPrint graph_print_buf;
+
+} FilterGraphPriv;
+
+static inline FilterGraphPriv *fgp_from_fg(FilterGraph *fg)
+{
+ return (FilterGraphPriv*)fg;
+}
+
+static inline const FilterGraphPriv *cfgp_from_cfg(const FilterGraph *fg)
+{
+ return (const FilterGraphPriv*)fg;
+}
+
+typedef struct InputFilterPriv {
+ InputFilter ifilter;
+
+ InputFilterOptions opts;
+
+ int index;
+
+ AVFilterContext *filter;
+
+ // used to hold submitted input
+ AVFrame *frame;
+
+ /* for filters that are not yet bound to an input stream,
+ * this stores the input linklabel, if any */
+ uint8_t *linklabel;
+
+ // filter data type
+ enum AVMediaType type;
+ // source data type: AVMEDIA_TYPE_SUBTITLE for sub2video,
+ // same as type otherwise
+ enum AVMediaType type_src;
+
+ int eof;
+ int bound;
+
+ // parameters configured for this input
+ int format;
+
+ int width, height;
+ AVRational sample_aspect_ratio;
+ enum AVColorSpace color_space;
+ enum AVColorRange color_range;
+
+ int sample_rate;
+ AVChannelLayout ch_layout;
+
+ AVRational time_base;
+
+ AVFrameSideData **side_data;
+ int nb_side_data;
+
+ AVFifo *frame_queue;
+
+ AVBufferRef *hw_frames_ctx;
+
+ int displaymatrix_present;
+ int displaymatrix_applied;
+ int32_t displaymatrix[9];
+
+ int downmixinfo_present;
+ AVDownmixInfo downmixinfo;
+
+ struct {
+ AVFrame *frame;
+
+ int64_t last_pts;
+ int64_t end_pts;
+
+ ///< marks if sub2video_update should force an initialization
+ unsigned int initialize;
+ } sub2video;
+} InputFilterPriv;
+
+static inline InputFilterPriv *ifp_from_ifilter(InputFilter *ifilter)
+{
+ return (InputFilterPriv*)ifilter;
+}
+
+typedef struct FPSConvContext {
+ AVFrame *last_frame;
+ /* number of frames emitted by the video-encoding sync code */
+ int64_t frame_number;
+ /* history of nb_frames_prev, i.e. the number of times the
+ * previous frame was duplicated by vsync code in recent
+ * do_video_out() calls */
+ int64_t frames_prev_hist[3];
+
+ uint64_t dup_warning;
+
+ int last_dropped;
+ int dropped_keyframe;
+
+ enum VideoSyncMethod vsync_method;
+
+ AVRational framerate;
+ AVRational framerate_max;
+ const AVRational *framerate_supported;
+ int framerate_clip;
+} FPSConvContext;
+
+
+typedef struct OutputFilterPriv {
+ OutputFilter ofilter;
+
+ int index;
+
+ void *log_parent;
+ char log_name[32];
+
+ char *name;
+
+ AVFilterContext *filter;
+
+ /* desired output stream properties */
+ int format;
+ int width, height;
+ int sample_rate;
+ AVChannelLayout ch_layout;
+ enum AVColorSpace color_space;
+ enum AVColorRange color_range;
+
+ AVFrameSideData **side_data;
+ int nb_side_data;
+
+ // time base in which the output is sent to our downstream
+ // does not need to match the filtersink's timebase
+ AVRational tb_out;
+ // at least one frame with the above timebase was sent
+ // to our downstream, so it cannot change anymore
+ int tb_out_locked;
+
+ AVRational sample_aspect_ratio;
+
+ AVDictionary *sws_opts;
+ AVDictionary *swr_opts;
+
+ // those are only set if no format is specified and the encoder gives us multiple options
+ // They point directly to the relevant lists of the encoder.
+ const int *formats;
+ const AVChannelLayout *ch_layouts;
+ const int *sample_rates;
+ const enum AVColorSpace *color_spaces;
+ const enum AVColorRange *color_ranges;
+
+ AVRational enc_timebase;
+ int64_t trim_start_us;
+ int64_t trim_duration_us;
+ // offset for output timestamps, in AV_TIME_BASE_Q
+ int64_t ts_offset;
+ int64_t next_pts;
+ FPSConvContext fps;
+
+ unsigned flags;
+} OutputFilterPriv;
+
+static inline OutputFilterPriv *ofp_from_ofilter(OutputFilter *ofilter)
+{
+ return (OutputFilterPriv*)ofilter;
+}
+
+#endif /* FFTOOLS_FFMPEG_FILTER_H */
--
ffmpeg-codebot
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 108+ messages in thread
* [FFmpeg-devel] [PATCH v7 5/7] avfilter/avfilter: Add avfilter_link_get_hw_frames_ctx()
2025-03-12 4:04 ` [FFmpeg-devel] [PATCH v7 0/7] " ffmpegagent
` (3 preceding siblings ...)
2025-03-12 4:04 ` [FFmpeg-devel] [PATCH v7 4/7] fftools/ffmpeg_filter: Move some declaration to new header file softworkz
@ 2025-03-12 4:04 ` softworkz
2025-03-12 4:04 ` [FFmpeg-devel] [PATCH v7 6/7] fftools/ffmpeg_graphprint: Add options for filtergraph printing softworkz
` (2 subsequent siblings)
7 siblings, 0 replies; 108+ messages in thread
From: softworkz @ 2025-03-12 4:04 UTC (permalink / raw)
To: ffmpeg-devel; +Cc: softworkz
From: softworkz <softworkz@hotmail.com>
---
doc/APIchanges | 3 +++
libavfilter/avfilter.c | 9 +++++++++
libavfilter/avfilter.h | 12 ++++++++++++
libavfilter/version.h | 2 +-
4 files changed, 25 insertions(+), 1 deletion(-)
diff --git a/doc/APIchanges b/doc/APIchanges
index 7da9297b01..923c880902 100644
--- a/doc/APIchanges
+++ b/doc/APIchanges
@@ -2,6 +2,9 @@ The last version increases of all libraries were on 2024-03-07
API changes, most recent first:
+2025-02-xx - xxxxxxxxxx - lavfi 10.10.100 - avfilter.h
+ Add avfilter_link_get_hw_frames_ctx().
+
2025-03-10 - xxxxxxxxxx - lavu 59.59.100 - pixfmt.h
Add AV_PIX_FMT_YAF16BE, AV_PIX_FMT_YAF16LE, AV_PIX_FMT_YAF32BE,
and AV_PIX_FMT_YAF32LE.
diff --git a/libavfilter/avfilter.c b/libavfilter/avfilter.c
index e732556ffa..a7385891c3 100644
--- a/libavfilter/avfilter.c
+++ b/libavfilter/avfilter.c
@@ -1006,6 +1006,15 @@ enum AVMediaType avfilter_pad_get_type(const AVFilterPad *pads, int pad_idx)
return pads[pad_idx].type;
}
+AVBufferRef *avfilter_link_get_hw_frames_ctx(AVFilterLink *link)
+{
+ FilterLink *plink = ff_filter_link(link);
+ if (plink->hw_frames_ctx)
+ return av_buffer_ref(plink->hw_frames_ctx);
+
+ return NULL;
+}
+
static int default_filter_frame(AVFilterLink *link, AVFrame *frame)
{
return ff_filter_frame(link->dst->outputs[0], frame);
diff --git a/libavfilter/avfilter.h b/libavfilter/avfilter.h
index 4520d5f978..f293178c99 100644
--- a/libavfilter/avfilter.h
+++ b/libavfilter/avfilter.h
@@ -96,6 +96,18 @@ const char *avfilter_pad_get_name(const AVFilterPad *pads, int pad_idx);
*/
enum AVMediaType avfilter_pad_get_type(const AVFilterPad *pads, int pad_idx);
+/**
+ * Get the hardware frames context of a filter link.
+ *
+ * @param link an AVFilterLink
+ *
+ * @return a ref-counted copy of the link's hw_frames_ctx field if there is
+ * a hardware frames context associated with the link or NULL otherwise.
+ * The returned AVBufferRef needs to be released with av_buffer_unref()
+ * when it is no longer used.
+ */
+AVBufferRef* avfilter_link_get_hw_frames_ctx(AVFilterLink *link);
+
/**
* Lists of formats / etc. supported by an end of a link.
*
diff --git a/libavfilter/version.h b/libavfilter/version.h
index 77f38cb9b4..4a69d6be98 100644
--- a/libavfilter/version.h
+++ b/libavfilter/version.h
@@ -31,7 +31,7 @@
#include "version_major.h"
-#define LIBAVFILTER_VERSION_MINOR 9
+#define LIBAVFILTER_VERSION_MINOR 10
#define LIBAVFILTER_VERSION_MICRO 100
--
ffmpeg-codebot
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 108+ messages in thread
* [FFmpeg-devel] [PATCH v7 6/7] fftools/ffmpeg_graphprint: Add options for filtergraph printing
2025-03-12 4:04 ` [FFmpeg-devel] [PATCH v7 0/7] " ffmpegagent
` (4 preceding siblings ...)
2025-03-12 4:04 ` [FFmpeg-devel] [PATCH v7 5/7] avfilter/avfilter: Add avfilter_link_get_hw_frames_ctx() softworkz
@ 2025-03-12 4:04 ` softworkz
2025-03-12 4:04 ` [FFmpeg-devel] [PATCH v7 7/7] fftools/ffprobe: Rename AVTextFormatContext variables (w => tfc) softworkz
2025-03-19 17:04 ` [FFmpeg-devel] [PATCH v8 0/4] print_graphs: Complete Filtergraph Printing ffmpegagent
7 siblings, 0 replies; 108+ messages in thread
From: softworkz @ 2025-03-12 4:04 UTC (permalink / raw)
To: ffmpeg-devel; +Cc: softworkz
From: softworkz <softworkz@hotmail.com>
Enables filtergraph printing and adds the options to the docs
The key benefits are:
- Different to other graph printing methods, this is outputting:
- all graphs with runtime state
(including auto-inserted filters)
- each graph with its inputs and outputs
- all filters with their in- and output pads
- all connections between all input- and output pads
- for each connection:
- the runtime-negotiated format and media type
- the hw context
- if video hw context, both: hw pixfmt + sw pixfmt
- Output can either be printed to stdout or written to specified file
- Output is machine-readable
- Use the same output implementation as ffprobe, supporting multiple
formats
Signed-off-by: softworkz <softworkz@hotmail.com>
---
doc/ffmpeg.texi | 11 +
fftools/Makefile | 11 +
fftools/ffmpeg.c | 4 +
fftools/ffmpeg.h | 3 +
fftools/ffmpeg_filter.c | 5 +
fftools/ffmpeg_graphprint.c | 470 ++++++++++++++++++++++++++++++
fftools/ffmpeg_graphprint.h | 35 +++
fftools/ffmpeg_opt.c | 12 +
fftools/textformat/avtextformat.c | 6 +-
fftools/textformat/avtextformat.h | 16 +-
10 files changed, 563 insertions(+), 10 deletions(-)
create mode 100644 fftools/ffmpeg_graphprint.c
create mode 100644 fftools/ffmpeg_graphprint.h
diff --git a/doc/ffmpeg.texi b/doc/ffmpeg.texi
index fca220a334..14fc75c033 100644
--- a/doc/ffmpeg.texi
+++ b/doc/ffmpeg.texi
@@ -1388,6 +1388,17 @@ It is on by default, to explicitly disable it you need to specify @code{-nostats
@item -stats_period @var{time} (@emph{global})
Set period at which encoding progress/statistics are updated. Default is 0.5 seconds.
+@item -print_graphs (@emph{global})
+Prints filtergraph details to stderr in the format set via -print_graphs_format.
+
+@item -print_graphs_file @var{filename} (@emph{global})
+Writes filtergraph details to the specified file in the format set via -print_graphs_format.
+Use a dash (-) for the file name to write to stdout.
+
+@item -print_graphs_format @var{format} (@emph{global})
+Sets the output printing format (available formats are: default, compact, csv, flat, ini, json, xml)
+The default format is json.
+
@item -progress @var{url} (@emph{global})
Send program-friendly progress information to @var{url}.
diff --git a/fftools/Makefile b/fftools/Makefile
index 664b73b161..03cdbd4b6e 100644
--- a/fftools/Makefile
+++ b/fftools/Makefile
@@ -19,8 +19,19 @@ OBJS-ffmpeg += \
fftools/ffmpeg_mux_init.o \
fftools/ffmpeg_opt.o \
fftools/ffmpeg_sched.o \
+ fftools/ffmpeg_graphprint.o \
fftools/sync_queue.o \
fftools/thread_queue.o \
+ fftools/textformat/avtextformat.o \
+ fftools/textformat/tf_compact.o \
+ fftools/textformat/tf_default.o \
+ fftools/textformat/tf_flat.o \
+ fftools/textformat/tf_ini.o \
+ fftools/textformat/tf_json.o \
+ fftools/textformat/tf_xml.o \
+ fftools/textformat/tw_avio.o \
+ fftools/textformat/tw_buffer.o \
+ fftools/textformat/tw_stdout.o \
OBJS-ffprobe += \
fftools/textformat/avtextformat.o \
diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c
index dc321fb4a2..b4bc76d788 100644
--- a/fftools/ffmpeg.c
+++ b/fftools/ffmpeg.c
@@ -81,6 +81,7 @@
#include "ffmpeg.h"
#include "ffmpeg_sched.h"
#include "ffmpeg_utils.h"
+#include "ffmpeg_graphprint.h"
const char program_name[] = "ffmpeg";
const int program_birth_year = 2000;
@@ -308,6 +309,9 @@ const AVIOInterruptCB int_cb = { decode_interrupt_cb, NULL };
static void ffmpeg_cleanup(int ret)
{
+ if (print_graphs || print_graphs_file)
+ print_filtergraphs(filtergraphs, nb_filtergraphs, output_files, nb_output_files);
+
if (do_benchmark) {
int64_t maxrss = getmaxrss() / 1024;
av_log(NULL, AV_LOG_INFO, "bench: maxrss=%"PRId64"KiB\n", maxrss);
diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h
index 86a3e10c6b..4c92c7b40a 100644
--- a/fftools/ffmpeg.h
+++ b/fftools/ffmpeg.h
@@ -715,6 +715,9 @@ extern float max_error_rate;
extern char *filter_nbthreads;
extern int filter_complex_nbthreads;
extern int vstats_version;
+extern int print_graphs;
+extern char *print_graphs_file;
+extern char *print_graphs_format;
extern int auto_conversion_filters;
extern const AVIOInterruptCB int_cb;
diff --git a/fftools/ffmpeg_filter.c b/fftools/ffmpeg_filter.c
index e6bfc72265..3e2337ea41 100644
--- a/fftools/ffmpeg_filter.c
+++ b/fftools/ffmpeg_filter.c
@@ -22,6 +22,7 @@
#include "ffmpeg.h"
#include "ffmpeg_filter.h"
+#include "ffmpeg_graphprint.h"
#include "libavfilter/avfilter.h"
#include "libavfilter/buffersink.h"
@@ -2974,6 +2975,10 @@ read_frames:
}
finish:
+
+ if (print_graphs || print_graphs_file)
+ print_filtergraph(fg, fgt.graph);
+
// EOF is normal termination
if (ret == AVERROR_EOF)
ret = 0;
diff --git a/fftools/ffmpeg_graphprint.c b/fftools/ffmpeg_graphprint.c
new file mode 100644
index 0000000000..7efbfcdef9
--- /dev/null
+++ b/fftools/ffmpeg_graphprint.c
@@ -0,0 +1,470 @@
+/*
+ * Copyright (c) 2018 - softworkz
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+/**
+ * @file
+ * output writers for filtergraph details
+ */
+
+#include "config.h"
+
+#include <string.h>
+
+#include "ffmpeg_graphprint.h"
+#include "ffmpeg_filter.h"
+
+#include "libavutil/avassert.h"
+#include "libavutil/avstring.h"
+#include "libavutil/pixdesc.h"
+#include "libavutil/dict.h"
+#include "libavutil/common.h"
+#include "libavfilter/avfilter.h"
+#include "libavutil/buffer.h"
+#include "libavutil/hwcontext.h"
+#include "textformat/avtextformat.h"
+
+typedef enum {
+ SECTION_ID_ROOT,
+ SECTION_ID_PROGRAM_VERSION,
+ SECTION_ID_FILTERGRAPHS,
+ SECTION_ID_FILTERGRAPH,
+ SECTION_ID_INPUTS,
+ SECTION_ID_INPUT,
+ SECTION_ID_OUTPUTS,
+ SECTION_ID_OUTPUT,
+ SECTION_ID_FILTERS,
+ SECTION_ID_FILTER,
+ SECTION_ID_HWFRAMESCONTEXT,
+} SectionID;
+
+static struct AVTextFormatSection sections[] = {
+ [SECTION_ID_ROOT] = { SECTION_ID_ROOT, "graph_description", AV_TEXTFORMAT_SECTION_FLAG_IS_WRAPPER,
+ { SECTION_ID_PROGRAM_VERSION, SECTION_ID_FILTERGRAPHS, -1} },
+ [SECTION_ID_PROGRAM_VERSION] = { SECTION_ID_PROGRAM_VERSION, "program_version", 0, { -1 } },
+
+ [SECTION_ID_FILTERGRAPHS] = { SECTION_ID_FILTERGRAPHS, "graphs", AV_TEXTFORMAT_SECTION_FLAG_IS_ARRAY, { SECTION_ID_FILTERGRAPH, -1 } },
+ [SECTION_ID_FILTERGRAPH] = { SECTION_ID_FILTERGRAPH, "graph", 0, { SECTION_ID_INPUTS, SECTION_ID_OUTPUTS, SECTION_ID_FILTERS, -1 }, },
+
+ [SECTION_ID_INPUTS] = { SECTION_ID_INPUTS, "inputs", AV_TEXTFORMAT_SECTION_FLAG_IS_ARRAY, { SECTION_ID_INPUT, -1 } },
+ [SECTION_ID_INPUT] = { SECTION_ID_INPUT, "input", 0, { SECTION_ID_HWFRAMESCONTEXT, -1 }, },
+
+ [SECTION_ID_OUTPUTS] = { SECTION_ID_OUTPUTS, "outputs", AV_TEXTFORMAT_SECTION_FLAG_IS_ARRAY, { SECTION_ID_OUTPUT, -1 } },
+ [SECTION_ID_OUTPUT] = { SECTION_ID_OUTPUT, "output", 0, { SECTION_ID_HWFRAMESCONTEXT, -1 }, },
+
+ [SECTION_ID_FILTERS] = { SECTION_ID_FILTERS, "filters", AV_TEXTFORMAT_SECTION_FLAG_IS_ARRAY, { SECTION_ID_FILTER, -1 } },
+ [SECTION_ID_FILTER] = { SECTION_ID_FILTER, "filter", 0, { -1 }, },
+
+ [SECTION_ID_HWFRAMESCONTEXT] = { SECTION_ID_HWFRAMESCONTEXT, "hw_frames_context", 0, { -1 }, },
+};
+
+/* Text Format API Shortcuts */
+#define print_int(k, v) avtext_print_integer(tfc, k, v)
+#define print_q(k, v, s) avtext_print_rational(tfc, k, v, s)
+#define print_str(k, v) avtext_print_string(tfc, k, v, 0)
+
+static void print_hwdevicecontext(AVTextFormatContext *tfc, const AVHWDeviceContext *hw_device_context)
+{
+ print_int("has_hw_device_context", 1);
+ print_str("hw_device_type", av_hwdevice_get_type_name(hw_device_context->type));
+}
+
+static void print_hwframescontext(AVTextFormatContext *tfc, const AVHWFramesContext *hw_frames_context)
+{
+ const AVPixFmtDescriptor* pix_desc_hw;
+ const AVPixFmtDescriptor* pix_desc_sw;
+
+ avtext_print_section_header(tfc, NULL, SECTION_ID_HWFRAMESCONTEXT);
+
+ print_int("has_hw_frames_context", 1);
+ print_str("hw_device_type", av_hwdevice_get_type_name(hw_frames_context->device_ctx->type));
+
+ pix_desc_hw = av_pix_fmt_desc_get(hw_frames_context->format);
+ if (pix_desc_hw) {
+ print_str("hw_pixel_format", pix_desc_hw->name);
+ if (pix_desc_hw->alias)
+ print_str("hw_pixel_format_alias", pix_desc_hw->alias);
+ }
+
+ pix_desc_sw = av_pix_fmt_desc_get(hw_frames_context->sw_format);
+ if (pix_desc_sw) {
+ print_str("sw_pixel_format", pix_desc_sw->name);
+ if (pix_desc_sw->alias)
+ print_str("sw_pixel_format_alias", pix_desc_sw->alias);
+ }
+
+ print_int("width", hw_frames_context->width);
+ print_int("height", hw_frames_context->height);
+ print_int("initial_pool_size", hw_frames_context->initial_pool_size);
+
+ avtext_print_section_footer(tfc); // SECTION_ID_HWFRAMESCONTEXT
+}
+
+static void print_link(AVTextFormatContext *tfc, AVFilterLink *link)
+{
+ AVBufferRef *hw_frames_ctx;
+ char layout_string[64];
+
+ print_str("media_type", av_get_media_type_string(link->type));
+
+ switch (link->type) {
+ case AVMEDIA_TYPE_VIDEO:
+ print_str("format", av_x_if_null(av_get_pix_fmt_name(link->format), "?"));
+ print_int("width", link->w);
+ print_int("height", link->h);
+ print_q("sar", link->sample_aspect_ratio, ':');
+ print_str("color_range", av_color_range_name(link->color_range));
+ print_str("color_space", av_color_space_name(link->colorspace));
+ break;
+
+ case AVMEDIA_TYPE_SUBTITLE:
+ ////print_str("format", av_x_if_null(av_get_subtitle_fmt_name(link->format), "?"));
+ print_int("width", link->w);
+ print_int("height", link->h);
+ break;
+
+ case AVMEDIA_TYPE_AUDIO:
+ av_channel_layout_describe(&link->ch_layout, layout_string, sizeof(layout_string));
+ print_str("channel_layout", layout_string);
+ print_int("channels", link->ch_layout.nb_channels);
+ print_int("sample_rate", link->sample_rate);
+ break;
+ }
+
+ print_q("time_base", link->time_base, '/');
+
+ hw_frames_ctx = avfilter_link_get_hw_frames_ctx(link);
+
+ if (hw_frames_ctx && hw_frames_ctx->data)
+ print_hwframescontext(tfc, (AVHWFramesContext *)hw_frames_ctx->data);
+}
+
+static void print_filter(AVTextFormatContext *tfc, const AVFilterContext* filter)
+{
+ avtext_print_section_header(tfc, NULL, SECTION_ID_FILTER);
+
+ print_str("filter_id", filter->name);
+
+ if (filter->filter) {
+ print_str("filter_name", filter->filter->name);
+ print_str("description", filter->filter->description);
+ }
+
+ if (filter->hw_device_ctx) {
+ AVHWDeviceContext* device_context = (AVHWDeviceContext*)filter->hw_device_ctx->data;
+ print_hwdevicecontext(tfc, device_context);
+ if (filter->extra_hw_frames > 0)
+ print_int("extra_hw_frames", filter->extra_hw_frames);
+ }
+
+ avtext_print_section_header(tfc, NULL, SECTION_ID_INPUTS);
+
+ for (unsigned i = 0; i < filter->nb_inputs; i++) {
+ AVFilterLink *link = filter->inputs[i];
+ avtext_print_section_header(tfc, NULL, SECTION_ID_INPUT);
+
+ print_int("input_index", i);
+ print_str("pad_name", avfilter_pad_get_name(link->dstpad, 0));;
+ print_str("source_filter_id", link->src->name);
+ print_str("source_pad_name", avfilter_pad_get_name(link->srcpad, 0));
+
+ print_link(tfc, link);
+
+ avtext_print_section_footer(tfc); // SECTION_ID_INPUT
+ }
+
+ avtext_print_section_footer(tfc); // SECTION_ID_INPUTS
+
+ avtext_print_section_header(tfc, NULL, SECTION_ID_OUTPUTS);
+
+ for (unsigned i = 0; i < filter->nb_outputs; i++) {
+ AVFilterLink *link = filter->outputs[i];
+ avtext_print_section_header(tfc, NULL, SECTION_ID_OUTPUT);
+
+ print_int("output_index", i);
+ print_str("pad_name", avfilter_pad_get_name(link->srcpad, 0));
+ print_str("dest_filter_id", link->dst->name);
+ print_str("dest_pad_name", avfilter_pad_get_name(link->dstpad, 0));
+
+ print_link(tfc, link);
+
+ avtext_print_section_footer(tfc); // SECTION_ID_OUTPUT
+ }
+
+ avtext_print_section_footer(tfc); // SECTION_ID_OUTPUTS
+
+ avtext_print_section_footer(tfc); // SECTION_ID_FILTER
+}
+
+static void init_sections(void)
+{
+ for (unsigned i = 0; i < FF_ARRAY_ELEMS(sections); i++)
+ sections[i].show_all_entries = 1;
+}
+
+static void print_filtergraph_single(AVTextFormatContext *tfc, FilterGraph *fg, AVFilterGraph *graph)
+{
+ FilterGraphPriv *fgp = fgp_from_fg(fg);
+
+ print_int("graph_index", fg->index);
+ print_str("description", fgp->graph_desc);
+
+ avtext_print_section_header(tfc, NULL, SECTION_ID_INPUTS);
+
+ for (int i = 0; i < fg->nb_inputs; i++) {
+ InputFilterPriv* ifilter = ifp_from_ifilter(fg->inputs[i]);
+ enum AVMediaType media_type = ifilter->type;
+
+ avtext_print_section_header(tfc, NULL, SECTION_ID_INPUT);
+
+ print_int("input_index", ifilter->index);
+
+ if (ifilter->linklabel)
+ print_str("link_label", (const char*)ifilter->linklabel);
+
+ if (ifilter->filter) {
+ print_str("filter_id", ifilter->filter->name);
+ print_str("filter_name", ifilter->filter->filter->name);
+ }
+
+ print_str("media_type", av_get_media_type_string(media_type));
+
+ avtext_print_section_footer(tfc); // SECTION_ID_INPUT
+ }
+
+ avtext_print_section_footer(tfc); // SECTION_ID_INPUTS
+
+ avtext_print_section_header(tfc, NULL, SECTION_ID_OUTPUTS);
+
+ for (int i = 0; i < fg->nb_outputs; i++) {
+ OutputFilterPriv *ofilter = ofp_from_ofilter(fg->outputs[i]);
+
+ avtext_print_section_header(tfc, NULL, SECTION_ID_OUTPUT);
+
+ print_int("output_index", ofilter->index);
+
+ print_str("name", ofilter->name);
+
+ if (fg->outputs[i]->linklabel)
+ print_str("link_label", (const char*)fg->outputs[i]->linklabel);
+
+ if (ofilter->filter) {
+ print_str("filter_id", ofilter->filter->name);
+ print_str("filter_name", ofilter->filter->filter->name);
+ }
+
+ print_str("media_type", av_get_media_type_string(fg->outputs[i]->type));
+
+ avtext_print_section_footer(tfc); // SECTION_ID_OUTPUT
+ }
+
+ avtext_print_section_footer(tfc); // SECTION_ID_OUTPUTS
+
+ avtext_print_section_header(tfc, NULL, SECTION_ID_FILTERS);
+
+ if (graph) {
+ for (unsigned i = 0; i < graph->nb_filters; i++) {
+ AVFilterContext *filter = graph->filters[i];
+ avtext_print_section_header(tfc, NULL, SECTION_ID_FILTER);
+
+ print_filter(tfc, filter);
+
+ avtext_print_section_footer(tfc); // SECTION_ID_FILTER
+ }
+ }
+
+ avtext_print_section_footer(tfc); // SECTION_ID_FILTERS
+}
+
+int print_filtergraph(FilterGraph *fg, AVFilterGraph *graph)
+{
+ const AVTextFormatter *text_formatter;
+ AVTextFormatContext *tctx;
+ AVTextWriterContext *wctx;
+ char *w_name, *w_args;
+ int ret;
+ FilterGraphPriv *fgp = fgp_from_fg(fg);
+ AVBPrint *target_buf = &fgp->graph_print_buf;
+
+ init_sections();
+
+ if (target_buf->len)
+ av_bprint_finalize(target_buf, NULL);
+
+ av_bprint_init(target_buf, 0, AV_BPRINT_SIZE_UNLIMITED);
+
+ if (!print_graphs_format)
+ print_graphs_format = av_strdup("default");
+ if (!print_graphs_format)
+ return AVERROR(ENOMEM);
+
+ w_name = av_strtok(print_graphs_format, "=", &w_args);
+ if (!w_name) {
+ av_log(NULL, AV_LOG_ERROR, "No name specified for the filter graph output format\n");
+ return AVERROR(EINVAL);
+ }
+
+ text_formatter = avtext_get_formatter_by_name(w_name);
+ if (!text_formatter ) {
+ av_log(NULL, AV_LOG_ERROR, "Unknown filter graph output format with name '%s'\n", w_name);
+ return AVERROR(EINVAL);
+ }
+
+ ret = avtextwriter_create_buffer(&wctx, target_buf);
+ if (ret < 0) {
+ av_log(NULL, AV_LOG_ERROR, "avtextwriter_create_buffer failed. Error code %d\n", ret);
+ return AVERROR(EINVAL);
+ }
+
+ if ((ret = avtext_context_open(&tctx, text_formatter, wctx, w_args, sections, FF_ARRAY_ELEMS(sections), 0, 0, 0, 0, -1, NULL)) >= 0) {
+
+ // Due to the threading model each graph needs to print itself into a buffer
+ // from its own thread. The actual printing happens short before cleanup in ffmpeg.c
+ // where all grahps are assembled together. To make this work, we need to put the
+ // formatting context into the same state like it would be when printing all at once,
+ // so here we print the section headers and clear the buffer to get into the right state.
+ avtext_print_section_header(tctx, NULL, SECTION_ID_ROOT);
+ avtext_print_section_header(tctx, NULL, SECTION_ID_FILTERGRAPHS);
+ avtext_print_section_header(tctx, NULL, SECTION_ID_FILTERGRAPH);
+
+ av_bprint_clear(target_buf);
+
+ print_filtergraph_single(tctx, fg, graph);
+
+ avtext_context_close(&tctx);
+ avtextwriter_context_close(&wctx);
+ } else
+ return ret;
+
+ return 0;
+}
+
+int print_filtergraphs(FilterGraph **graphs, int nb_graphs, OutputFile **ofiles, int nb_ofiles)
+{
+ const AVTextFormatter *text_formatter;
+ AVTextFormatContext *tctx;
+ AVTextWriterContext *wctx;
+ AVBPrint target_buf;
+ char *buf, *w_name, *w_args;
+ int ret;
+
+ init_sections();
+
+ if (!print_graphs_format)
+ print_graphs_format = av_strdup("default");
+ if (!print_graphs_format) {
+ return AVERROR(ENOMEM);
+ }
+
+ w_name = av_strtok(print_graphs_format, "=", &buf);
+ if (!w_name) {
+ av_log(NULL, AV_LOG_ERROR, "No name specified for the filter graph output format\n");
+ return AVERROR(EINVAL);
+ }
+ w_args = buf;
+
+ text_formatter = avtext_get_formatter_by_name(w_name);
+ if (!text_formatter) {
+ av_log(NULL, AV_LOG_ERROR, "Unknown filter graph output format with name '%s'\n", w_name);
+ return AVERROR(EINVAL);
+ }
+
+ av_bprint_init(&target_buf, 0, AV_BPRINT_SIZE_UNLIMITED);
+
+ ret = avtextwriter_create_buffer(&wctx, &target_buf);
+ if (ret < 0) {
+ av_log(NULL, AV_LOG_ERROR, "avtextwriter_create_buffer failed. Error code %d\n", ret);
+ return ret;
+ }
+
+ if ((ret = avtext_context_open(&tctx, text_formatter, wctx, w_args, sections, FF_ARRAY_ELEMS(sections), 0, 0, 0, 0, -1, NULL)) >= 0) {
+ avtext_print_section_header(tctx, NULL, SECTION_ID_ROOT);
+
+ avtext_print_section_header(tctx, NULL, SECTION_ID_FILTERGRAPHS);
+
+ for (int i = 0; i < nb_graphs; i++) {
+
+ FilterGraphPriv *fgp = fgp_from_fg(graphs[i]);
+ AVBPrint *graph_buf = &fgp->graph_print_buf;
+
+ if (graph_buf->len > 0) {
+ avtext_print_section_header(tctx, NULL, SECTION_ID_FILTERGRAPH);
+
+ av_bprint_append_data(&target_buf, graph_buf->str, graph_buf->len);
+ av_bprint_finalize(graph_buf, NULL);
+
+ avtext_print_section_footer(tctx); // SECTION_ID_FILTERGRAPH
+ }
+ }
+
+ for (int n = 0; n < nb_ofiles; n++) {
+ OutputFile *of = ofiles[n];
+
+ for (int i = 0; i < of->nb_streams; i++) {
+ OutputStream *ost = of->streams[i];
+
+ if (ost->fg_simple) {
+ FilterGraphPriv *fgp = fgp_from_fg(ost->fg_simple);
+ AVBPrint *graph_buf = &fgp->graph_print_buf;
+
+ if (graph_buf->len > 0) {
+ avtext_print_section_header(tctx, NULL, SECTION_ID_FILTERGRAPH);
+
+ av_bprint_append_data(&target_buf, graph_buf->str, graph_buf->len);
+ av_bprint_finalize(graph_buf, NULL);
+
+ avtext_print_section_footer(tctx); // SECTION_ID_FILTERGRAPH
+ }
+ }
+ }
+ }
+
+ avtext_print_section_footer(tctx); // SECTION_ID_FILTERGRAPHS
+ avtext_print_section_footer(tctx); // SECTION_ID_ROOT
+
+ if (print_graphs_file) {
+ AVIOContext *avio = NULL;
+
+ if (!strcmp(print_graphs_file, "-")) {
+ printf("%s", target_buf.str);
+ } else {
+ ret = avio_open2(&avio, print_graphs_file, AVIO_FLAG_WRITE, NULL, NULL);
+ if (ret < 0) {
+ av_log(NULL, AV_LOG_ERROR, "Failed to open graph output file, \"%s\": %s\n",
+ print_graphs_file, av_err2str(ret));
+ return ret;
+ }
+
+ avio_write(avio, (const unsigned char*)target_buf.str, FFMIN(target_buf.len, target_buf.size - 1));
+ avio_flush(avio);
+
+ if ((ret = avio_closep(&avio)) < 0)
+ av_log(NULL, AV_LOG_ERROR, "Error closing graph output file, loss of information possible: %s\n", av_err2str(ret));
+ }
+ }
+
+ if (print_graphs)
+ av_log(NULL, AV_LOG_INFO, "%s %c", target_buf.str, '\n');
+
+ avtext_context_close(&tctx);
+ avtextwriter_context_close(&wctx);
+ }
+
+ return 0;
+}
diff --git a/fftools/ffmpeg_graphprint.h b/fftools/ffmpeg_graphprint.h
new file mode 100644
index 0000000000..e95a0773ba
--- /dev/null
+++ b/fftools/ffmpeg_graphprint.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2018 - softworkz
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef FFTOOLS_FFMPEG_GRAPHPRINT_H
+#define FFTOOLS_FFMPEG_GRAPHPRINT_H
+
+#include <stdint.h>
+
+#include "config.h"
+#include "ffmpeg.h"
+#include "libavutil/avutil.h"
+#include "libavutil/bprint.h"
+#include "textformat/avtextformat.h"
+
+int print_filtergraphs(FilterGraph **graphs, int nb_graphs, OutputFile **output_files, int nb_output_files);
+int print_filtergraph(FilterGraph *fg, AVFilterGraph *graph);
+
+#endif /* FFTOOLS_FFMPEG_GRAPHPRINT_H */
diff --git a/fftools/ffmpeg_opt.c b/fftools/ffmpeg_opt.c
index 27a9fc9e42..fe4ee637e3 100644
--- a/fftools/ffmpeg_opt.c
+++ b/fftools/ffmpeg_opt.c
@@ -75,6 +75,9 @@ float max_error_rate = 2.0/3;
char *filter_nbthreads;
int filter_complex_nbthreads = 0;
int vstats_version = 2;
+int print_graphs = 0;
+char *print_graphs_file = NULL;
+char *print_graphs_format = NULL;
int auto_conversion_filters = 1;
int64_t stats_period = 500000;
@@ -1733,6 +1736,15 @@ const OptionDef options[] = {
{ .func_arg = opt_filter_complex_script },
"deprecated, use -/filter_complex instead", "filename" },
#endif
+ { "print_graphs", OPT_TYPE_BOOL, 0,
+ { &print_graphs },
+ "print filtergraph details to stderr" },
+ { "print_graphs_file", OPT_TYPE_STRING, 0,
+ { &print_graphs_file },
+ "write graph details to a file", "filename" },
+ { "print_graphs_format", OPT_TYPE_STRING, 0,
+ { &print_graphs_format },
+ "set the output printing format (available formats are: default, compact, csv, flat, ini, json, xml)", "format" },
{ "auto_conversion_filters", OPT_TYPE_BOOL, OPT_EXPERT,
{ &auto_conversion_filters },
"enable automatic conversion filters globally" },
diff --git a/fftools/textformat/avtextformat.c b/fftools/textformat/avtextformat.c
index 6c09f9d2cd..7f5bebfafa 100644
--- a/fftools/textformat/avtextformat.c
+++ b/fftools/textformat/avtextformat.c
@@ -398,10 +398,12 @@ static char *value_string(AVTextFormatContext *tctx, char *buf, int buf_size, st
vali = vald;
}
- if (show_float || (tctx->use_value_prefix && vald != (int64_t)vald))
+ if (show_float || (tctx->use_value_prefix && vald != (int64_t)vald)) {
snprintf(buf, buf_size, "%f", vald);
- else
+ } else {
snprintf(buf, buf_size, "%"PRId64, vali);
+ }
+
av_strlcatf(buf, buf_size, "%s%s%s", *prefix_string || tctx->show_value_unit ? " " : "",
prefix_string, tctx->show_value_unit ? uv.unit : "");
}
diff --git a/fftools/textformat/avtextformat.h b/fftools/textformat/avtextformat.h
index 4689499246..03754c760f 100644
--- a/fftools/textformat/avtextformat.h
+++ b/fftools/textformat/avtextformat.h
@@ -86,17 +86,17 @@ typedef struct AVTextFormatter {
#define SECTION_MAX_NB_SECTIONS 100
struct AVTextFormatContext {
- const AVClass *class; ///< class of the formatter
- const AVTextFormatter *formatter; ///< the AVTextFormatter of which this is an instance
- AVTextWriterContext *writer; ///< the AVTextWriterContext
+ const AVClass *class; ///< class of the formatter
+ const AVTextFormatter *formatter; ///< the AVTextFormatter of which this is an instance
+ AVTextWriterContext *writer; ///< the AVTextWriterContext
- char *name; ///< name of this formatter instance
- void *priv; ///< private data for use by the filter
+ char *name; ///< name of this formatter instance
+ void *priv; ///< private data for use by the filter
const struct AVTextFormatSection *sections; ///< array containing all sections
- int nb_sections; ///< number of sections
+ int nb_sections; ///< number of sections
- int level; ///< current level, starting from 0
+ int level; ///< current level, starting from 0
/** number of the item printed in the given section, starting from 0 */
unsigned int nb_item[SECTION_MAX_NB_LEVELS];
@@ -155,7 +155,7 @@ void avtext_print_data(AVTextFormatContext *tctx, const char *name, const uint8_
void avtext_print_data_hash(AVTextFormatContext *tctx, const char *name, const uint8_t *data, int size);
-void avtext_print_integers(AVTextFormatContext *tctx, const char *name, uint8_t *data, int size,
+void avtext_print_integers(AVTextFormatContext *tctx, const char *name, uint8_t *data, int size,
const char *format, int columns, int bytes, int offset_add);
const AVTextFormatter *avtext_get_formatter_by_name(const char *name);
--
ffmpeg-codebot
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 108+ messages in thread
* [FFmpeg-devel] [PATCH v7 7/7] fftools/ffprobe: Rename AVTextFormatContext variables (w => tfc)
2025-03-12 4:04 ` [FFmpeg-devel] [PATCH v7 0/7] " ffmpegagent
` (5 preceding siblings ...)
2025-03-12 4:04 ` [FFmpeg-devel] [PATCH v7 6/7] fftools/ffmpeg_graphprint: Add options for filtergraph printing softworkz
@ 2025-03-12 4:04 ` softworkz
2025-03-19 17:04 ` [FFmpeg-devel] [PATCH v8 0/4] print_graphs: Complete Filtergraph Printing ffmpegagent
7 siblings, 0 replies; 108+ messages in thread
From: softworkz @ 2025-03-12 4:04 UTC (permalink / raw)
To: ffmpeg-devel; +Cc: softworkz
From: softworkz <softworkz@hotmail.com>
Signed-off-by: softworkz <softworkz@hotmail.com>
---
fftools/ffprobe.c | 512 +++++++++++++++++++++++-----------------------
1 file changed, 256 insertions(+), 256 deletions(-)
diff --git a/fftools/ffprobe.c b/fftools/ffprobe.c
index 4a90bc4824..9f869b41b3 100644
--- a/fftools/ffprobe.c
+++ b/fftools/ffprobe.c
@@ -407,7 +407,7 @@ static void log_callback(void *ptr, int level, const char *fmt, va_list vl)
#define print_fmt(k, f, ...) do { \
av_bprint_clear(&pbuf); \
av_bprintf(&pbuf, f, __VA_ARGS__); \
- avtext_print_string(w, k, pbuf.str, 0); \
+ avtext_print_string(tfc, k, pbuf.str, 0); \
} while (0)
#define print_list_fmt(k, f, n, m, ...) do { \
@@ -419,19 +419,19 @@ static void log_callback(void *ptr, int level, const char *fmt, va_list vl)
av_bprintf(&pbuf, f, __VA_ARGS__); \
} \
} \
- avtext_print_string(w, k, pbuf.str, 0); \
+ avtext_print_string(tfc, k, pbuf.str, 0); \
} while (0)
-#define print_int(k, v) avtext_print_integer(w, k, v)
-#define print_q(k, v, s) avtext_print_rational(w, k, v, s)
-#define print_str(k, v) avtext_print_string(w, k, v, 0)
-#define print_str_opt(k, v) avtext_print_string(w, k, v, AV_TEXTFORMAT_PRINT_STRING_OPTIONAL)
-#define print_str_validate(k, v) avtext_print_string(w, k, v, AV_TEXTFORMAT_PRINT_STRING_VALIDATE)
-#define print_time(k, v, tb) avtext_print_time(w, k, v, tb, 0)
-#define print_ts(k, v) avtext_print_ts(w, k, v, 0)
-#define print_duration_time(k, v, tb) avtext_print_time(w, k, v, tb, 1)
-#define print_duration_ts(k, v) avtext_print_ts(w, k, v, 1)
-#define print_val(k, v, u) avtext_print_unit_int(w, k, v, u)
+#define print_int(k, v) avtext_print_integer(tfc, k, v)
+#define print_q(k, v, s) avtext_print_rational(tfc, k, v, s)
+#define print_str(k, v) avtext_print_string(tfc, k, v, 0)
+#define print_str_opt(k, v) avtext_print_string(tfc, k, v, AV_TEXTFORMAT_PRINT_STRING_OPTIONAL)
+#define print_str_validate(k, v) avtext_print_string(tfc, k, v, AV_TEXTFORMAT_PRINT_STRING_VALIDATE)
+#define print_time(k, v, tb) avtext_print_time(tfc, k, v, tb, 0)
+#define print_ts(k, v) avtext_print_ts(tfc, k, v, 0)
+#define print_duration_time(k, v, tb) avtext_print_time(tfc, k, v, tb, 1)
+#define print_duration_ts(k, v) avtext_print_ts(tfc, k, v, 1)
+#define print_val(k, v, u) avtext_print_unit_int(tfc, k, v, u)
#define REALLOCZ_ARRAY_STREAM(ptr, cur_n, new_n) \
{ \
@@ -441,25 +441,25 @@ static void log_callback(void *ptr, int level, const char *fmt, va_list vl)
memset( (ptr) + (cur_n), 0, ((new_n) - (cur_n)) * sizeof(*(ptr)) ); \
}
-static inline int show_tags(AVTextFormatContext *w, AVDictionary *tags, int section_id)
+static inline int show_tags(AVTextFormatContext *tfc, AVDictionary *tags, int section_id)
{
const AVDictionaryEntry *tag = NULL;
int ret = 0;
if (!tags)
return 0;
- avtext_print_section_header(w, NULL, section_id);
+ avtext_print_section_header(tfc, NULL, section_id);
while ((tag = av_dict_iterate(tags, tag))) {
if ((ret = print_str_validate(tag->key, tag->value)) < 0)
break;
}
- avtext_print_section_footer(w);
+ avtext_print_section_footer(tfc);
return ret;
}
-static void print_dovi_metadata(AVTextFormatContext *w, const AVDOVIMetadata *dovi)
+static void print_dovi_metadata(AVTextFormatContext *tfc, const AVDOVIMetadata *dovi)
{
if (!dovi)
return;
@@ -514,15 +514,15 @@ static void print_dovi_metadata(AVTextFormatContext *w, const AVDOVIMetadata *do
print_int("num_x_partitions", mapping->num_x_partitions);
print_int("num_y_partitions", mapping->num_y_partitions);
- avtext_print_section_header(w, NULL, SECTION_ID_FRAME_SIDE_DATA_COMPONENT_LIST);
+ avtext_print_section_header(tfc, NULL, SECTION_ID_FRAME_SIDE_DATA_COMPONENT_LIST);
for (int c = 0; c < 3; c++) {
const AVDOVIReshapingCurve *curve = &mapping->curves[c];
- avtext_print_section_header(w, "Reshaping curve", SECTION_ID_FRAME_SIDE_DATA_COMPONENT);
+ avtext_print_section_header(tfc, "Reshaping curve", SECTION_ID_FRAME_SIDE_DATA_COMPONENT);
print_list_fmt("pivots", "%"PRIu16, curve->num_pivots, 1, curve->pivots[idx]);
- avtext_print_section_header(w, NULL, SECTION_ID_FRAME_SIDE_DATA_PIECE_LIST);
+ avtext_print_section_header(tfc, NULL, SECTION_ID_FRAME_SIDE_DATA_PIECE_LIST);
for (int i = 0; i < curve->num_pivots - 1; i++) {
AVBPrint piece_buf;
@@ -540,7 +540,7 @@ static void print_dovi_metadata(AVTextFormatContext *w, const AVDOVIMetadata *do
}
av_bprintf(&piece_buf, " mapping");
- avtext_print_section_header(w, piece_buf.str, SECTION_ID_FRAME_SIDE_DATA_PIECE);
+ avtext_print_section_header(tfc, piece_buf.str, SECTION_ID_FRAME_SIDE_DATA_PIECE);
print_int("mapping_idc", curve->mapping_idc[i]);
switch (curve->mapping_idc[i]) {
case AV_DOVI_MAPPING_POLYNOMIAL:
@@ -564,11 +564,11 @@ static void print_dovi_metadata(AVTextFormatContext *w, const AVDOVIMetadata *do
}
// SECTION_ID_FRAME_SIDE_DATA_PIECE
- avtext_print_section_footer(w);
+ avtext_print_section_footer(tfc);
}
// SECTION_ID_FRAME_SIDE_DATA_PIECE_LIST
- avtext_print_section_footer(w);
+ avtext_print_section_footer(tfc);
if (mapping->nlq_method_idc != AV_DOVI_NLQ_NONE) {
const AVDOVINLQParams *nlq = &mapping->nlq[c];
@@ -584,11 +584,11 @@ static void print_dovi_metadata(AVTextFormatContext *w, const AVDOVIMetadata *do
}
// SECTION_ID_FRAME_SIDE_DATA_COMPONENT
- avtext_print_section_footer(w);
+ avtext_print_section_footer(tfc);
}
// SECTION_ID_FRAME_SIDE_DATA_COMPONENT_LIST
- avtext_print_section_footer(w);
+ avtext_print_section_footer(tfc);
// color metadata
print_int("dm_metadata_id", color->dm_metadata_id);
@@ -621,7 +621,7 @@ static void print_dovi_metadata(AVTextFormatContext *w, const AVDOVIMetadata *do
}
}
-static void print_dynamic_hdr10_plus(AVTextFormatContext *w, const AVDynamicHDRPlus *metadata)
+static void print_dynamic_hdr10_plus(AVTextFormatContext *tfc, const AVDynamicHDRPlus *metadata)
{
if (!metadata)
return;
@@ -720,7 +720,7 @@ static void print_dynamic_hdr10_plus(AVTextFormatContext *w, const AVDynamicHDRP
}
}
-static void print_dynamic_hdr_vivid(AVTextFormatContext *w, const AVDynamicHDRVivid *metadata)
+static void print_dynamic_hdr_vivid(AVTextFormatContext *tfc, const AVDynamicHDRVivid *metadata)
{
if (!metadata)
return;
@@ -790,7 +790,7 @@ static void print_dynamic_hdr_vivid(AVTextFormatContext *w, const AVDynamicHDRVi
}
}
-static void print_ambient_viewing_environment(AVTextFormatContext *w,
+static void print_ambient_viewing_environment(AVTextFormatContext *tfc,
const AVAmbientViewingEnvironment *env)
{
if (!env)
@@ -801,7 +801,7 @@ static void print_ambient_viewing_environment(AVTextFormatContext *w,
print_q("ambient_light_y", env->ambient_light_y, '/');
}
-static void print_film_grain_params(AVTextFormatContext *w,
+static void print_film_grain_params(AVTextFormatContext *tfc,
const AVFilmGrainParams *fgp)
{
const char *color_range, *color_primaries, *color_trc, *color_space;
@@ -847,10 +847,10 @@ static void print_film_grain_params(AVTextFormatContext *w,
print_int("overlap_flag", aom->overlap_flag);
print_int("limit_output_range", aom->limit_output_range);
- avtext_print_section_header(w, NULL, SECTION_ID_FRAME_SIDE_DATA_COMPONENT_LIST);
+ avtext_print_section_header(tfc, NULL, SECTION_ID_FRAME_SIDE_DATA_COMPONENT_LIST);
if (aom->num_y_points) {
- avtext_print_section_header(w, NULL, SECTION_ID_FRAME_SIDE_DATA_COMPONENT);
+ avtext_print_section_header(tfc, NULL, SECTION_ID_FRAME_SIDE_DATA_COMPONENT);
print_int("bit_depth_luma", fgp->bit_depth_luma);
print_list_fmt("y_points_value", "%"PRIu8, aom->num_y_points, 1, aom->y_points[idx][0]);
@@ -858,14 +858,14 @@ static void print_film_grain_params(AVTextFormatContext *w,
print_list_fmt("ar_coeffs_y", "%"PRId8, num_ar_coeffs_y, 1, aom->ar_coeffs_y[idx]);
// SECTION_ID_FRAME_SIDE_DATA_COMPONENT
- avtext_print_section_footer(w);
+ avtext_print_section_footer(tfc);
}
for (int uv = 0; uv < 2; uv++) {
if (!aom->num_uv_points[uv] && !aom->chroma_scaling_from_luma)
continue;
- avtext_print_section_header(w, NULL, SECTION_ID_FRAME_SIDE_DATA_COMPONENT);
+ avtext_print_section_header(tfc, NULL, SECTION_ID_FRAME_SIDE_DATA_COMPONENT);
print_int("bit_depth_chroma", fgp->bit_depth_chroma);
print_list_fmt("uv_points_value", "%"PRIu8, aom->num_uv_points[uv], 1, aom->uv_points[uv][idx][0]);
@@ -876,11 +876,11 @@ static void print_film_grain_params(AVTextFormatContext *w,
print_int("uv_offset", aom->uv_offset[uv]);
// SECTION_ID_FRAME_SIDE_DATA_COMPONENT
- avtext_print_section_footer(w);
+ avtext_print_section_footer(tfc);
}
// SECTION_ID_FRAME_SIDE_DATA_COMPONENT_LIST
- avtext_print_section_footer(w);
+ avtext_print_section_footer(tfc);
break;
}
case AV_FILM_GRAIN_PARAMS_H274: {
@@ -889,36 +889,36 @@ static void print_film_grain_params(AVTextFormatContext *w,
print_int("blending_mode_id", h274->blending_mode_id);
print_int("log2_scale_factor", h274->log2_scale_factor);
- avtext_print_section_header(w, NULL, SECTION_ID_FRAME_SIDE_DATA_COMPONENT_LIST);
+ avtext_print_section_header(tfc, NULL, SECTION_ID_FRAME_SIDE_DATA_COMPONENT_LIST);
for (int c = 0; c < 3; c++) {
if (!h274->component_model_present[c])
continue;
- avtext_print_section_header(w, NULL, SECTION_ID_FRAME_SIDE_DATA_COMPONENT);
+ avtext_print_section_header(tfc, NULL, SECTION_ID_FRAME_SIDE_DATA_COMPONENT);
print_int(c ? "bit_depth_chroma" : "bit_depth_luma", c ? fgp->bit_depth_chroma : fgp->bit_depth_luma);
- avtext_print_section_header(w, NULL, SECTION_ID_FRAME_SIDE_DATA_PIECE_LIST);
+ avtext_print_section_header(tfc, NULL, SECTION_ID_FRAME_SIDE_DATA_PIECE_LIST);
for (int i = 0; i < h274->num_intensity_intervals[c]; i++) {
- avtext_print_section_header(w, NULL, SECTION_ID_FRAME_SIDE_DATA_PIECE);
+ avtext_print_section_header(tfc, NULL, SECTION_ID_FRAME_SIDE_DATA_PIECE);
print_int("intensity_interval_lower_bound", h274->intensity_interval_lower_bound[c][i]);
print_int("intensity_interval_upper_bound", h274->intensity_interval_upper_bound[c][i]);
print_list_fmt("comp_model_value", "%"PRId16, h274->num_model_values[c], 1, h274->comp_model_value[c][i][idx]);
// SECTION_ID_FRAME_SIDE_DATA_PIECE
- avtext_print_section_footer(w);
+ avtext_print_section_footer(tfc);
}
// SECTION_ID_FRAME_SIDE_DATA_PIECE_LIST
- avtext_print_section_footer(w);
+ avtext_print_section_footer(tfc);
// SECTION_ID_FRAME_SIDE_DATA_COMPONENT
- avtext_print_section_footer(w);
+ avtext_print_section_footer(tfc);
}
// SECTION_ID_FRAME_SIDE_DATA_COMPONENT_LIST
- avtext_print_section_footer(w);
+ avtext_print_section_footer(tfc);
break;
}
}
@@ -926,20 +926,20 @@ static void print_film_grain_params(AVTextFormatContext *w,
av_bprint_finalize(&pbuf, NULL);
}
-static void print_pkt_side_data(AVTextFormatContext *w,
+static void print_pkt_side_data(AVTextFormatContext *tfc,
AVCodecParameters *par,
const AVPacketSideData *sd,
SectionID id_data)
{
const char *name = av_packet_side_data_name(sd->type);
- avtext_print_section_header(w, sd, id_data);
+ avtext_print_section_header(tfc, sd, id_data);
print_str("side_data_type", name ? name : "unknown");
if (sd->type == AV_PKT_DATA_DISPLAYMATRIX && sd->size >= 9*4) {
double rotation = av_display_rotation_get((int32_t *)sd->data);
if (isnan(rotation))
rotation = 0;
- avtext_print_integers(w, "displaymatrix", sd->data, 9, " %11d", 3, 4, 1);
+ avtext_print_integers(tfc, "displaymatrix", sd->data, 9, " %11d", 3, 4, 1);
print_int("rotation", rotation);
} else if (sd->type == AV_PKT_DATA_STEREO3D) {
const AVStereo3D *stereo = (AVStereo3D *)sd->data;
@@ -998,10 +998,10 @@ static void print_pkt_side_data(AVTextFormatContext *w,
print_int("max_average", metadata->MaxFALL);
} else if (sd->type == AV_PKT_DATA_AMBIENT_VIEWING_ENVIRONMENT) {
print_ambient_viewing_environment(
- w, (const AVAmbientViewingEnvironment *)sd->data);
+ tfc, (const AVAmbientViewingEnvironment *)sd->data);
} else if (sd->type == AV_PKT_DATA_DYNAMIC_HDR10_PLUS) {
AVDynamicHDRPlus *metadata = (AVDynamicHDRPlus *)sd->data;
- print_dynamic_hdr10_plus(w, metadata);
+ print_dynamic_hdr10_plus(tfc, metadata);
} else if (sd->type == AV_PKT_DATA_DOVI_CONF) {
AVDOVIDecoderConfigurationRecord *dovi = (AVDOVIDecoderConfigurationRecord *)sd->data;
const char *comp = "unknown";
@@ -1036,8 +1036,8 @@ static void print_pkt_side_data(AVTextFormatContext *w,
} else if (sd->type == AV_PKT_DATA_WEBVTT_IDENTIFIER ||
sd->type == AV_PKT_DATA_WEBVTT_SETTINGS) {
if (do_show_data)
- avtext_print_data(w, "data", sd->data, sd->size);
- avtext_print_data_hash(w, "data_hash", sd->data, sd->size);
+ avtext_print_data(tfc, "data", sd->data, sd->size);
+ avtext_print_data_hash(tfc, "data_hash", sd->data, sd->size);
} else if (sd->type == AV_PKT_DATA_FRAME_CROPPING && sd->size >= sizeof(uint32_t) * 4) {
print_int("crop_top", AV_RL32(sd->data));
print_int("crop_bottom", AV_RL32(sd->data + 4));
@@ -1048,7 +1048,7 @@ static void print_pkt_side_data(AVTextFormatContext *w,
}
}
-static void print_private_data(AVTextFormatContext *w, void *priv_data)
+static void print_private_data(AVTextFormatContext *tfc, void *priv_data)
{
const AVOption *opt = NULL;
while (opt = av_opt_next(priv_data, opt)) {
@@ -1061,7 +1061,7 @@ static void print_private_data(AVTextFormatContext *w, void *priv_data)
}
}
-static void print_color_range(AVTextFormatContext *w, enum AVColorRange color_range)
+static void print_color_range(AVTextFormatContext *tfc, enum AVColorRange color_range)
{
const char *val = av_color_range_name(color_range);
if (!val || color_range == AVCOL_RANGE_UNSPECIFIED) {
@@ -1071,7 +1071,7 @@ static void print_color_range(AVTextFormatContext *w, enum AVColorRange color_ra
}
}
-static void print_color_space(AVTextFormatContext *w, enum AVColorSpace color_space)
+static void print_color_space(AVTextFormatContext *tfc, enum AVColorSpace color_space)
{
const char *val = av_color_space_name(color_space);
if (!val || color_space == AVCOL_SPC_UNSPECIFIED) {
@@ -1081,7 +1081,7 @@ static void print_color_space(AVTextFormatContext *w, enum AVColorSpace color_sp
}
}
-static void print_primaries(AVTextFormatContext *w, enum AVColorPrimaries color_primaries)
+static void print_primaries(AVTextFormatContext *tfc, enum AVColorPrimaries color_primaries)
{
const char *val = av_color_primaries_name(color_primaries);
if (!val || color_primaries == AVCOL_PRI_UNSPECIFIED) {
@@ -1091,7 +1091,7 @@ static void print_primaries(AVTextFormatContext *w, enum AVColorPrimaries color_
}
}
-static void print_color_trc(AVTextFormatContext *w, enum AVColorTransferCharacteristic color_trc)
+static void print_color_trc(AVTextFormatContext *tfc, enum AVColorTransferCharacteristic color_trc)
{
const char *val = av_color_transfer_name(color_trc);
if (!val || color_trc == AVCOL_TRC_UNSPECIFIED) {
@@ -1101,7 +1101,7 @@ static void print_color_trc(AVTextFormatContext *w, enum AVColorTransferCharacte
}
}
-static void print_chroma_location(AVTextFormatContext *w, enum AVChromaLocation chroma_location)
+static void print_chroma_location(AVTextFormatContext *tfc, enum AVChromaLocation chroma_location)
{
const char *val = av_chroma_location_name(chroma_location);
if (!val || chroma_location == AVCHROMA_LOC_UNSPECIFIED) {
@@ -1127,7 +1127,7 @@ static void clear_log(int need_lock)
ff_mutex_unlock(&log_mutex);
}
-static int show_log(AVTextFormatContext *w, int section_ids, int section_id, int log_level)
+static int show_log(AVTextFormatContext *tfc, int section_ids, int section_id, int log_level)
{
int i;
ff_mutex_lock(&log_mutex);
@@ -1135,11 +1135,11 @@ static int show_log(AVTextFormatContext *w, int section_ids, int section_id, int
ff_mutex_unlock(&log_mutex);
return 0;
}
- avtext_print_section_header(w, NULL, section_ids);
+ avtext_print_section_header(tfc, NULL, section_ids);
for (i=0; i<log_buffer_size; i++) {
if (log_buffer[i].log_level <= log_level) {
- avtext_print_section_header(w, NULL, section_id);
+ avtext_print_section_header(tfc, NULL, section_id);
print_str("context", log_buffer[i].context_name);
print_int("level", log_buffer[i].log_level);
print_int("category", log_buffer[i].category);
@@ -1151,18 +1151,18 @@ static int show_log(AVTextFormatContext *w, int section_ids, int section_id, int
print_str_opt("parent_category", "N/A");
}
print_str("message", log_buffer[i].log_message);
- avtext_print_section_footer(w);
+ avtext_print_section_footer(tfc);
}
}
clear_log(0);
ff_mutex_unlock(&log_mutex);
- avtext_print_section_footer(w);
+ avtext_print_section_footer(tfc);
return 0;
}
-static void show_packet(AVTextFormatContext *w, InputFile *ifile, AVPacket *pkt, int packet_idx)
+static void show_packet(AVTextFormatContext *tfc, InputFile *ifile, AVPacket *pkt, int packet_idx)
{
AVStream *st = ifile->streams[pkt->stream_index].st;
AVBPrint pbuf;
@@ -1170,7 +1170,7 @@ static void show_packet(AVTextFormatContext *w, InputFile *ifile, AVPacket *pkt,
av_bprint_init(&pbuf, 1, AV_BPRINT_SIZE_UNLIMITED);
- avtext_print_section_header(w, NULL, SECTION_ID_PACKET);
+ avtext_print_section_header(tfc, NULL, SECTION_ID_PACKET);
s = av_get_media_type_string(st->codecpar->codec_type);
if (s) print_str ("codec_type", s);
@@ -1189,8 +1189,8 @@ static void show_packet(AVTextFormatContext *w, InputFile *ifile, AVPacket *pkt,
pkt->flags & AV_PKT_FLAG_DISCARD ? 'D' : '_',
pkt->flags & AV_PKT_FLAG_CORRUPT ? 'C' : '_');
if (do_show_data)
- avtext_print_data(w, "data", pkt->data, pkt->size);
- avtext_print_data_hash(w, "data_hash", pkt->data, pkt->size);
+ avtext_print_data(tfc, "data", pkt->data, pkt->size);
+ avtext_print_data_hash(tfc, "data_hash", pkt->data, pkt->size);
if (pkt->side_data_elems) {
size_t size;
@@ -1200,33 +1200,33 @@ static void show_packet(AVTextFormatContext *w, InputFile *ifile, AVPacket *pkt,
if (side_metadata && size && do_show_packet_tags) {
AVDictionary *dict = NULL;
if (av_packet_unpack_dictionary(side_metadata, size, &dict) >= 0)
- show_tags(w, dict, SECTION_ID_PACKET_TAGS);
+ show_tags(tfc, dict, SECTION_ID_PACKET_TAGS);
av_dict_free(&dict);
}
- avtext_print_section_header(w, NULL, SECTION_ID_PACKET_SIDE_DATA_LIST);
+ avtext_print_section_header(tfc, NULL, SECTION_ID_PACKET_SIDE_DATA_LIST);
for (int i = 0; i < pkt->side_data_elems; i++) {
- print_pkt_side_data(w, st->codecpar, &pkt->side_data[i],
+ print_pkt_side_data(tfc, st->codecpar, &pkt->side_data[i],
SECTION_ID_PACKET_SIDE_DATA);
- avtext_print_section_footer(w);
+ avtext_print_section_footer(tfc);
}
- avtext_print_section_footer(w);
+ avtext_print_section_footer(tfc);
}
- avtext_print_section_footer(w);
+ avtext_print_section_footer(tfc);
av_bprint_finalize(&pbuf, NULL);
fflush(stdout);
}
-static void show_subtitle(AVTextFormatContext *w, AVSubtitle *sub, AVStream *stream,
+static void show_subtitle(AVTextFormatContext *tfc, AVSubtitle *sub, AVStream *stream,
AVFormatContext *fmt_ctx)
{
AVBPrint pbuf;
av_bprint_init(&pbuf, 1, AV_BPRINT_SIZE_UNLIMITED);
- avtext_print_section_header(w, NULL, SECTION_ID_SUBTITLE);
+ avtext_print_section_header(tfc, NULL, SECTION_ID_SUBTITLE);
print_str ("media_type", "subtitle");
print_ts ("pts", sub->pts);
@@ -1236,30 +1236,30 @@ static void show_subtitle(AVTextFormatContext *w, AVSubtitle *sub, AVStream *str
print_int ("end_display_time", sub->end_display_time);
print_int ("num_rects", sub->num_rects);
- avtext_print_section_footer(w);
+ avtext_print_section_footer(tfc);
av_bprint_finalize(&pbuf, NULL);
fflush(stdout);
}
-static void print_frame_side_data(AVTextFormatContext *w,
+static void print_frame_side_data(AVTextFormatContext *tfc,
const AVFrame *frame,
const AVStream *stream)
{
- avtext_print_section_header(w, NULL, SECTION_ID_FRAME_SIDE_DATA_LIST);
+ avtext_print_section_header(tfc, NULL, SECTION_ID_FRAME_SIDE_DATA_LIST);
for (int i = 0; i < frame->nb_side_data; i++) {
const AVFrameSideData *sd = frame->side_data[i];
const char *name;
- avtext_print_section_header(w, sd, SECTION_ID_FRAME_SIDE_DATA);
+ avtext_print_section_header(tfc, sd, SECTION_ID_FRAME_SIDE_DATA);
name = av_frame_side_data_name(sd->type);
print_str("side_data_type", name ? name : "unknown");
if (sd->type == AV_FRAME_DATA_DISPLAYMATRIX && sd->size >= 9*4) {
double rotation = av_display_rotation_get((int32_t *)sd->data);
if (isnan(rotation))
rotation = 0;
- avtext_print_integers(w, "displaymatrix", sd->data, 9, " %11d", 3, 4, 1);
+ avtext_print_integers(tfc, "displaymatrix", sd->data, 9, " %11d", 3, 4, 1);
print_int("rotation", rotation);
} else if (sd->type == AV_FRAME_DATA_AFD && sd->size > 0) {
print_int("active_format", *sd->data);
@@ -1270,15 +1270,15 @@ static void print_frame_side_data(AVTextFormatContext *w,
} else if (sd->type == AV_FRAME_DATA_S12M_TIMECODE && sd->size == 16) {
uint32_t *tc = (uint32_t*)sd->data;
int m = FFMIN(tc[0],3);
- avtext_print_section_header(w, NULL, SECTION_ID_FRAME_SIDE_DATA_TIMECODE_LIST);
+ avtext_print_section_header(tfc, NULL, SECTION_ID_FRAME_SIDE_DATA_TIMECODE_LIST);
for (int j = 1; j <= m ; j++) {
char tcbuf[AV_TIMECODE_STR_SIZE];
av_timecode_make_smpte_tc_string2(tcbuf, stream->avg_frame_rate, tc[j], 0, 0);
- avtext_print_section_header(w, NULL, SECTION_ID_FRAME_SIDE_DATA_TIMECODE);
+ avtext_print_section_header(tfc, NULL, SECTION_ID_FRAME_SIDE_DATA_TIMECODE);
print_str("value", tcbuf);
- avtext_print_section_footer(w);
+ avtext_print_section_footer(tfc);
}
- avtext_print_section_footer(w);
+ avtext_print_section_footer(tfc);
} else if (sd->type == AV_FRAME_DATA_MASTERING_DISPLAY_METADATA) {
AVMasteringDisplayMetadata *metadata = (AVMasteringDisplayMetadata *)sd->data;
@@ -1300,7 +1300,7 @@ static void print_frame_side_data(AVTextFormatContext *w,
}
} else if (sd->type == AV_FRAME_DATA_DYNAMIC_HDR_PLUS) {
AVDynamicHDRPlus *metadata = (AVDynamicHDRPlus *)sd->data;
- print_dynamic_hdr10_plus(w, metadata);
+ print_dynamic_hdr10_plus(tfc, metadata);
} else if (sd->type == AV_FRAME_DATA_CONTENT_LIGHT_LEVEL) {
AVContentLightMetadata *metadata = (AVContentLightMetadata *)sd->data;
print_int("max_content", metadata->MaxCLL);
@@ -1311,24 +1311,24 @@ static void print_frame_side_data(AVTextFormatContext *w,
print_str(tag->key, tag->value);
print_int("size", sd->size);
} else if (sd->type == AV_FRAME_DATA_DOVI_METADATA) {
- print_dovi_metadata(w, (const AVDOVIMetadata *)sd->data);
+ print_dovi_metadata(tfc, (const AVDOVIMetadata *)sd->data);
} else if (sd->type == AV_FRAME_DATA_DYNAMIC_HDR_VIVID) {
AVDynamicHDRVivid *metadata = (AVDynamicHDRVivid *)sd->data;
- print_dynamic_hdr_vivid(w, metadata);
+ print_dynamic_hdr_vivid(tfc, metadata);
} else if (sd->type == AV_FRAME_DATA_AMBIENT_VIEWING_ENVIRONMENT) {
- print_ambient_viewing_environment(w, (const AVAmbientViewingEnvironment *)sd->data);
+ print_ambient_viewing_environment(tfc, (const AVAmbientViewingEnvironment *)sd->data);
} else if (sd->type == AV_FRAME_DATA_FILM_GRAIN_PARAMS) {
AVFilmGrainParams *fgp = (AVFilmGrainParams *)sd->data;
- print_film_grain_params(w, fgp);
+ print_film_grain_params(tfc, fgp);
} else if (sd->type == AV_FRAME_DATA_VIEW_ID) {
print_int("view_id", *(int*)sd->data);
}
- avtext_print_section_footer(w);
+ avtext_print_section_footer(tfc);
}
- avtext_print_section_footer(w);
+ avtext_print_section_footer(tfc);
}
-static void show_frame(AVTextFormatContext *w, AVFrame *frame, AVStream *stream,
+static void show_frame(AVTextFormatContext *tfc, AVFrame *frame, AVStream *stream,
AVFormatContext *fmt_ctx)
{
FrameData *fd = frame->opaque_ref ? (FrameData*)frame->opaque_ref->data : NULL;
@@ -1338,7 +1338,7 @@ static void show_frame(AVTextFormatContext *w, AVFrame *frame, AVStream *stream,
av_bprint_init(&pbuf, 1, AV_BPRINT_SIZE_UNLIMITED);
- avtext_print_section_header(w, NULL, SECTION_ID_FRAME);
+ avtext_print_section_header(tfc, NULL, SECTION_ID_FRAME);
s = av_get_media_type_string(stream->codecpar->codec_type);
if (s) print_str ("media_type", s);
@@ -1383,11 +1383,11 @@ static void show_frame(AVTextFormatContext *w, AVFrame *frame, AVStream *stream,
print_int("lossless", !!(frame->flags & AV_FRAME_FLAG_LOSSLESS));
print_int("repeat_pict", frame->repeat_pict);
- print_color_range(w, frame->color_range);
- print_color_space(w, frame->colorspace);
- print_primaries(w, frame->color_primaries);
- print_color_trc(w, frame->color_trc);
- print_chroma_location(w, frame->chroma_location);
+ print_color_range(tfc, frame->color_range);
+ print_color_space(tfc, frame->colorspace);
+ print_primaries(tfc, frame->color_primaries);
+ print_color_trc(tfc, frame->color_trc);
+ print_chroma_location(tfc, frame->chroma_location);
break;
case AVMEDIA_TYPE_AUDIO:
@@ -1404,19 +1404,19 @@ static void show_frame(AVTextFormatContext *w, AVFrame *frame, AVStream *stream,
break;
}
if (do_show_frame_tags)
- show_tags(w, frame->metadata, SECTION_ID_FRAME_TAGS);
+ show_tags(tfc, frame->metadata, SECTION_ID_FRAME_TAGS);
if (do_show_log)
- show_log(w, SECTION_ID_FRAME_LOGS, SECTION_ID_FRAME_LOG, do_show_log);
+ show_log(tfc, SECTION_ID_FRAME_LOGS, SECTION_ID_FRAME_LOG, do_show_log);
if (frame->nb_side_data)
- print_frame_side_data(w, frame, stream);
+ print_frame_side_data(tfc, frame, stream);
- avtext_print_section_footer(w);
+ avtext_print_section_footer(tfc);
av_bprint_finalize(&pbuf, NULL);
fflush(stdout);
}
-static av_always_inline int process_frame(AVTextFormatContext *w,
+static av_always_inline int process_frame(AVTextFormatContext *tfc,
InputFile *ifile,
AVFrame *frame, const AVPacket *pkt,
int *packet_new)
@@ -1470,9 +1470,9 @@ static av_always_inline int process_frame(AVTextFormatContext *w,
nb_streams_frames[pkt->stream_index]++;
if (do_show_frames)
if (is_sub)
- show_subtitle(w, &sub, ifile->streams[pkt->stream_index].st, fmt_ctx);
+ show_subtitle(tfc, &sub, ifile->streams[pkt->stream_index].st, fmt_ctx);
else
- show_frame(w, frame, ifile->streams[pkt->stream_index].st, fmt_ctx);
+ show_frame(tfc, frame, ifile->streams[pkt->stream_index].st, fmt_ctx);
if (!is_sub && do_analyze_frames) {
for (int i = 0; i < frame->nb_side_data; i++) {
@@ -1513,7 +1513,7 @@ static void log_read_interval(const ReadInterval *interval, void *log_ctx, int l
av_log(log_ctx, log_level, "\n");
}
-static int read_interval_packets(AVTextFormatContext *w, InputFile *ifile,
+static int read_interval_packets(AVTextFormatContext *tfc, InputFile *ifile,
const ReadInterval *interval, int64_t *cur_ts)
{
AVFormatContext *fmt_ctx = ifile->fmt_ctx;
@@ -1596,7 +1596,7 @@ static int read_interval_packets(AVTextFormatContext *w, InputFile *ifile,
frame_count++;
if (do_read_packets) {
if (do_show_packets)
- show_packet(w, ifile, pkt, i++);
+ show_packet(tfc, ifile, pkt, i++);
nb_streams_packets[pkt->stream_index]++;
}
if (do_read_frames) {
@@ -1612,7 +1612,7 @@ static int read_interval_packets(AVTextFormatContext *w, InputFile *ifile,
fd->pkt_pos = pkt->pos;
fd->pkt_size = pkt->size;
- while (process_frame(w, ifile, frame, pkt, &packet_new) > 0);
+ while (process_frame(tfc, ifile, frame, pkt, &packet_new) > 0);
}
}
av_packet_unref(pkt);
@@ -1622,7 +1622,7 @@ static int read_interval_packets(AVTextFormatContext *w, InputFile *ifile,
for (i = 0; i < ifile->nb_streams; i++) {
pkt->stream_index = i;
if (do_read_frames) {
- while (process_frame(w, ifile, frame, pkt, &(int){1}) > 0);
+ while (process_frame(tfc, ifile, frame, pkt, &(int){1}) > 0);
if (ifile->streams[i].dec_ctx)
avcodec_flush_buffers(ifile->streams[i].dec_ctx);
}
@@ -1638,7 +1638,7 @@ end:
return ret;
}
-static int read_packets(AVTextFormatContext *w, InputFile *ifile)
+static int read_packets(AVTextFormatContext *tfc, InputFile *ifile)
{
AVFormatContext *fmt_ctx = ifile->fmt_ctx;
int i, ret = 0;
@@ -1646,10 +1646,10 @@ static int read_packets(AVTextFormatContext *w, InputFile *ifile)
if (read_intervals_nb == 0) {
ReadInterval interval = (ReadInterval) { .has_start = 0, .has_end = 0 };
- ret = read_interval_packets(w, ifile, &interval, &cur_ts);
+ ret = read_interval_packets(tfc, ifile, &interval, &cur_ts);
} else {
for (i = 0; i < read_intervals_nb; i++) {
- ret = read_interval_packets(w, ifile, &read_intervals[i], &cur_ts);
+ ret = read_interval_packets(tfc, ifile, &read_intervals[i], &cur_ts);
if (ret < 0)
break;
}
@@ -1658,22 +1658,22 @@ static int read_packets(AVTextFormatContext *w, InputFile *ifile)
return ret;
}
-static void print_dispositions(AVTextFormatContext *w, uint32_t disposition, SectionID section_id)
+static void print_dispositions(AVTextFormatContext *tfc, uint32_t disposition, SectionID section_id)
{
- avtext_print_section_header(w, NULL, section_id);
+ avtext_print_section_header(tfc, NULL, section_id);
for (int i = 0; i < sizeof(disposition) * CHAR_BIT; i++) {
const char *disposition_str = av_disposition_to_string(1U << i);
if (disposition_str)
print_int(disposition_str, !!(disposition & (1U << i)));
}
- avtext_print_section_footer(w);
+ avtext_print_section_footer(tfc);
}
#define IN_PROGRAM 1
#define IN_STREAM_GROUP 2
-static int show_stream(AVTextFormatContext *w, AVFormatContext *fmt_ctx, int stream_idx, InputStream *ist, int container)
+static int show_stream(AVTextFormatContext *tfc, AVFormatContext *fmt_ctx, int stream_idx, InputStream *ist, int container)
{
AVStream *stream = ist->st;
AVCodecParameters *par;
@@ -1705,7 +1705,7 @@ static int show_stream(AVTextFormatContext *w, AVFormatContext *fmt_ctx, int str
av_bprint_init(&pbuf, 1, AV_BPRINT_SIZE_UNLIMITED);
- avtext_print_section_header(w, NULL, section_header[container]);
+ avtext_print_section_header(tfc, NULL, section_header[container]);
print_int("index", stream->index);
@@ -1774,11 +1774,11 @@ static int show_stream(AVTextFormatContext *w, AVFormatContext *fmt_ctx, int str
else print_str_opt("pix_fmt", "unknown");
print_int("level", par->level);
- print_color_range(w, par->color_range);
- print_color_space(w, par->color_space);
- print_color_trc(w, par->color_trc);
- print_primaries(w, par->color_primaries);
- print_chroma_location(w, par->chroma_location);
+ print_color_range(tfc, par->color_range);
+ print_color_space(tfc, par->color_space);
+ print_color_trc(tfc, par->color_trc);
+ print_primaries(tfc, par->color_primaries);
+ print_chroma_location(tfc, par->chroma_location);
if (par->field_order == AV_FIELD_PROGRESSIVE)
print_str("field_order", "progressive");
@@ -1830,9 +1830,9 @@ static int show_stream(AVTextFormatContext *w, AVFormatContext *fmt_ctx, int str
if (show_private_data) {
if (dec_ctx && dec_ctx->codec->priv_class)
- print_private_data(w, dec_ctx->priv_data);
+ print_private_data(tfc, dec_ctx->priv_data);
if (fmt_ctx->iformat->priv_class)
- print_private_data(w, fmt_ctx->priv_data);
+ print_private_data(tfc, fmt_ctx->priv_data);
}
if (fmt_ctx->iformat->flags & AVFMT_SHOW_IDS) print_fmt ("id", "0x%x", stream->id);
@@ -1859,113 +1859,113 @@ static int show_stream(AVTextFormatContext *w, AVFormatContext *fmt_ctx, int str
if (nb_streams_packets[stream_idx]) print_fmt ("nb_read_packets", "%"PRIu64, nb_streams_packets[stream_idx]);
else print_str_opt("nb_read_packets", "N/A");
if (do_show_data)
- avtext_print_data(w, "extradata", par->extradata,
+ avtext_print_data(tfc, "extradata", par->extradata,
par->extradata_size);
if (par->extradata_size > 0) {
print_int("extradata_size", par->extradata_size);
- avtext_print_data_hash(w, "extradata_hash", par->extradata,
+ avtext_print_data_hash(tfc, "extradata_hash", par->extradata,
par->extradata_size);
}
/* Print disposition information */
if (do_show_stream_disposition) {
av_assert0(container < FF_ARRAY_ELEMS(section_disposition));
- print_dispositions(w, stream->disposition, section_disposition[container]);
+ print_dispositions(tfc, stream->disposition, section_disposition[container]);
}
if (do_show_stream_tags) {
av_assert0(container < FF_ARRAY_ELEMS(section_tags));
- ret = show_tags(w, stream->metadata, section_tags[container]);
+ ret = show_tags(tfc, stream->metadata, section_tags[container]);
}
if (stream->codecpar->nb_coded_side_data) {
- avtext_print_section_header(w, NULL, SECTION_ID_STREAM_SIDE_DATA_LIST);
+ avtext_print_section_header(tfc, NULL, SECTION_ID_STREAM_SIDE_DATA_LIST);
for (int i = 0; i < stream->codecpar->nb_coded_side_data; i++) {
- print_pkt_side_data(w, stream->codecpar, &stream->codecpar->coded_side_data[i],
+ print_pkt_side_data(tfc, stream->codecpar, &stream->codecpar->coded_side_data[i],
SECTION_ID_STREAM_SIDE_DATA);
- avtext_print_section_footer(w);
+ avtext_print_section_footer(tfc);
}
- avtext_print_section_footer(w);
+ avtext_print_section_footer(tfc);
}
- avtext_print_section_footer(w);
+ avtext_print_section_footer(tfc);
av_bprint_finalize(&pbuf, NULL);
fflush(stdout);
return ret;
}
-static int show_streams(AVTextFormatContext *w, InputFile *ifile)
+static int show_streams(AVTextFormatContext *tfc, InputFile *ifile)
{
AVFormatContext *fmt_ctx = ifile->fmt_ctx;
int i, ret = 0;
- avtext_print_section_header(w, NULL, SECTION_ID_STREAMS);
+ avtext_print_section_header(tfc, NULL, SECTION_ID_STREAMS);
for (i = 0; i < ifile->nb_streams; i++)
if (selected_streams[i]) {
- ret = show_stream(w, fmt_ctx, i, &ifile->streams[i], 0);
+ ret = show_stream(tfc, fmt_ctx, i, &ifile->streams[i], 0);
if (ret < 0)
break;
}
- avtext_print_section_footer(w);
+ avtext_print_section_footer(tfc);
return ret;
}
-static int show_program(AVTextFormatContext *w, InputFile *ifile, AVProgram *program)
+static int show_program(AVTextFormatContext *tfc, InputFile *ifile, AVProgram *program)
{
AVFormatContext *fmt_ctx = ifile->fmt_ctx;
int i, ret = 0;
- avtext_print_section_header(w, NULL, SECTION_ID_PROGRAM);
+ avtext_print_section_header(tfc, NULL, SECTION_ID_PROGRAM);
print_int("program_id", program->id);
print_int("program_num", program->program_num);
print_int("nb_streams", program->nb_stream_indexes);
print_int("pmt_pid", program->pmt_pid);
print_int("pcr_pid", program->pcr_pid);
if (do_show_program_tags)
- ret = show_tags(w, program->metadata, SECTION_ID_PROGRAM_TAGS);
+ ret = show_tags(tfc, program->metadata, SECTION_ID_PROGRAM_TAGS);
if (ret < 0)
goto end;
- avtext_print_section_header(w, NULL, SECTION_ID_PROGRAM_STREAMS);
+ avtext_print_section_header(tfc, NULL, SECTION_ID_PROGRAM_STREAMS);
for (i = 0; i < program->nb_stream_indexes; i++) {
if (selected_streams[program->stream_index[i]]) {
- ret = show_stream(w, fmt_ctx, program->stream_index[i], &ifile->streams[program->stream_index[i]], IN_PROGRAM);
+ ret = show_stream(tfc, fmt_ctx, program->stream_index[i], &ifile->streams[program->stream_index[i]], IN_PROGRAM);
if (ret < 0)
break;
}
}
- avtext_print_section_footer(w);
+ avtext_print_section_footer(tfc);
end:
- avtext_print_section_footer(w);
+ avtext_print_section_footer(tfc);
return ret;
}
-static int show_programs(AVTextFormatContext *w, InputFile *ifile)
+static int show_programs(AVTextFormatContext *tfc, InputFile *ifile)
{
AVFormatContext *fmt_ctx = ifile->fmt_ctx;
int i, ret = 0;
- avtext_print_section_header(w, NULL, SECTION_ID_PROGRAMS);
+ avtext_print_section_header(tfc, NULL, SECTION_ID_PROGRAMS);
for (i = 0; i < fmt_ctx->nb_programs; i++) {
AVProgram *program = fmt_ctx->programs[i];
if (!program)
continue;
- ret = show_program(w, ifile, program);
+ ret = show_program(tfc, ifile, program);
if (ret < 0)
break;
}
- avtext_print_section_footer(w);
+ avtext_print_section_footer(tfc);
return ret;
}
-static void print_tile_grid_params(AVTextFormatContext *w, const AVStreamGroup *stg,
+static void print_tile_grid_params(AVTextFormatContext *tfc, const AVStreamGroup *stg,
const AVStreamGroupTileGrid *tile_grid)
{
- avtext_print_section_header(w, stg, SECTION_ID_STREAM_GROUP_COMPONENT);
+ avtext_print_section_header(tfc, stg, SECTION_ID_STREAM_GROUP_COMPONENT);
print_int("nb_tiles", tile_grid->nb_tiles);
print_int("coded_width", tile_grid->coded_width);
print_int("coded_height", tile_grid->coded_height);
@@ -1973,19 +1973,19 @@ static void print_tile_grid_params(AVTextFormatContext *w, const AVStreamGroup *
print_int("vertical_offset", tile_grid->vertical_offset);
print_int("width", tile_grid->width);
print_int("height", tile_grid->height);
- avtext_print_section_header(w, NULL, SECTION_ID_STREAM_GROUP_SUBCOMPONENTS);
+ avtext_print_section_header(tfc, NULL, SECTION_ID_STREAM_GROUP_SUBCOMPONENTS);
for (int i = 0; i < tile_grid->nb_tiles; i++) {
- avtext_print_section_header(w, "tile_offset", SECTION_ID_STREAM_GROUP_SUBCOMPONENT);
+ avtext_print_section_header(tfc, "tile_offset", SECTION_ID_STREAM_GROUP_SUBCOMPONENT);
print_int("stream_index", tile_grid->offsets[i].idx);
print_int("tile_horizontal_offset", tile_grid->offsets[i].horizontal);
print_int("tile_vertical_offset", tile_grid->offsets[i].vertical);
- avtext_print_section_footer(w);
+ avtext_print_section_footer(tfc);
}
- avtext_print_section_footer(w);
- avtext_print_section_footer(w);
+ avtext_print_section_footer(tfc);
+ avtext_print_section_footer(tfc);
}
-static void print_iamf_param_definition(AVTextFormatContext *w, const char *name,
+static void print_iamf_param_definition(AVTextFormatContext *tfc, const char *name,
const AVIAMFParamDefinition *param, SectionID section_id)
{
SectionID subsection_id, parameter_section_id;
@@ -1993,7 +1993,7 @@ static void print_iamf_param_definition(AVTextFormatContext *w, const char *name
av_assert0(subsection_id != -1);
parameter_section_id = sections[subsection_id].children_ids[0];
av_assert0(parameter_section_id != -1);
- avtext_print_section_header(w, "IAMF Param Definition", section_id);
+ avtext_print_section_header(tfc, "IAMF Param Definition", section_id);
print_str("name", name);
print_int("nb_subblocks", param->nb_subblocks);
print_int("type", param->type);
@@ -2002,56 +2002,56 @@ static void print_iamf_param_definition(AVTextFormatContext *w, const char *name
print_int("duration", param->duration);
print_int("constant_subblock_duration", param->constant_subblock_duration);
if (param->nb_subblocks > 0)
- avtext_print_section_header(w, NULL, subsection_id);
+ avtext_print_section_header(tfc, NULL, subsection_id);
for (int i = 0; i < param->nb_subblocks; i++) {
const void *subblock = av_iamf_param_definition_get_subblock(param, i);
switch(param->type) {
case AV_IAMF_PARAMETER_DEFINITION_MIX_GAIN: {
const AVIAMFMixGain *mix = subblock;
- avtext_print_section_header(w, "IAMF Mix Gain Parameters", parameter_section_id);
+ avtext_print_section_header(tfc, "IAMF Mix Gain Parameters", parameter_section_id);
print_int("subblock_duration", mix->subblock_duration);
print_int("animation_type", mix->animation_type);
print_q("start_point_value", mix->start_point_value, '/');
print_q("end_point_value", mix->end_point_value, '/');
print_q("control_point_value", mix->control_point_value, '/');
print_q("control_point_relative_time", mix->control_point_relative_time, '/');
- avtext_print_section_footer(w); // parameter_section_id
+ avtext_print_section_footer(tfc); // parameter_section_id
break;
}
case AV_IAMF_PARAMETER_DEFINITION_DEMIXING: {
const AVIAMFDemixingInfo *demix = subblock;
- avtext_print_section_header(w, "IAMF Demixing Info", parameter_section_id);
+ avtext_print_section_header(tfc, "IAMF Demixing Info", parameter_section_id);
print_int("subblock_duration", demix->subblock_duration);
print_int("dmixp_mode", demix->dmixp_mode);
- avtext_print_section_footer(w); // parameter_section_id
+ avtext_print_section_footer(tfc); // parameter_section_id
break;
}
case AV_IAMF_PARAMETER_DEFINITION_RECON_GAIN: {
const AVIAMFReconGain *recon = subblock;
- avtext_print_section_header(w, "IAMF Recon Gain", parameter_section_id);
+ avtext_print_section_header(tfc, "IAMF Recon Gain", parameter_section_id);
print_int("subblock_duration", recon->subblock_duration);
- avtext_print_section_footer(w); // parameter_section_id
+ avtext_print_section_footer(tfc); // parameter_section_id
break;
}
}
}
if (param->nb_subblocks > 0)
- avtext_print_section_footer(w); // subsection_id
- avtext_print_section_footer(w); // section_id
+ avtext_print_section_footer(tfc); // subsection_id
+ avtext_print_section_footer(tfc); // section_id
}
-static void print_iamf_audio_element_params(AVTextFormatContext *w, const AVStreamGroup *stg,
+static void print_iamf_audio_element_params(AVTextFormatContext *tfc, const AVStreamGroup *stg,
const AVIAMFAudioElement *audio_element)
{
- avtext_print_section_header(w, stg, SECTION_ID_STREAM_GROUP_COMPONENT);
+ avtext_print_section_header(tfc, stg, SECTION_ID_STREAM_GROUP_COMPONENT);
print_int("nb_layers", audio_element->nb_layers);
print_int("audio_element_type", audio_element->audio_element_type);
print_int("default_w", audio_element->default_w);
- avtext_print_section_header(w, NULL, SECTION_ID_STREAM_GROUP_SUBCOMPONENTS);
+ avtext_print_section_header(tfc, NULL, SECTION_ID_STREAM_GROUP_SUBCOMPONENTS);
for (int i = 0; i < audio_element->nb_layers; i++) {
const AVIAMFLayer *layer = audio_element->layers[i];
char val_str[128];
- avtext_print_section_header(w, "IAMF Audio Layer", SECTION_ID_STREAM_GROUP_SUBCOMPONENT);
+ avtext_print_section_header(tfc, "IAMF Audio Layer", SECTION_ID_STREAM_GROUP_SUBCOMPONENT);
av_channel_layout_describe(&layer->ch_layout, val_str, sizeof(val_str));
print_str("channel_layout", val_str);
if (audio_element->audio_element_type == AV_IAMF_AUDIO_ELEMENT_TYPE_CHANNEL) {
@@ -2059,52 +2059,52 @@ static void print_iamf_audio_element_params(AVTextFormatContext *w, const AVStre
print_q("output_gain", layer->output_gain, '/');
} else if (audio_element->audio_element_type == AV_IAMF_AUDIO_ELEMENT_TYPE_SCENE)
print_int("ambisonics_mode", layer->ambisonics_mode);
- avtext_print_section_footer(w); // SECTION_ID_STREAM_GROUP_SUBCOMPONENT
+ avtext_print_section_footer(tfc); // SECTION_ID_STREAM_GROUP_SUBCOMPONENT
}
if (audio_element->demixing_info)
- print_iamf_param_definition(w, "demixing_info", audio_element->demixing_info,
+ print_iamf_param_definition(tfc, "demixing_info", audio_element->demixing_info,
SECTION_ID_STREAM_GROUP_SUBCOMPONENT);
if (audio_element->recon_gain_info)
- print_iamf_param_definition(w, "recon_gain_info", audio_element->recon_gain_info,
+ print_iamf_param_definition(tfc, "recon_gain_info", audio_element->recon_gain_info,
SECTION_ID_STREAM_GROUP_SUBCOMPONENT);
- avtext_print_section_footer(w); // SECTION_ID_STREAM_GROUP_SUBCOMPONENTS
- avtext_print_section_footer(w); // SECTION_ID_STREAM_GROUP_COMPONENT
+ avtext_print_section_footer(tfc); // SECTION_ID_STREAM_GROUP_SUBCOMPONENTS
+ avtext_print_section_footer(tfc); // SECTION_ID_STREAM_GROUP_COMPONENT
}
-static void print_iamf_submix_params(AVTextFormatContext *w, const AVIAMFSubmix *submix)
+static void print_iamf_submix_params(AVTextFormatContext *tfc, const AVIAMFSubmix *submix)
{
- avtext_print_section_header(w, "IAMF Submix", SECTION_ID_STREAM_GROUP_SUBCOMPONENT);
+ avtext_print_section_header(tfc, "IAMF Submix", SECTION_ID_STREAM_GROUP_SUBCOMPONENT);
print_int("nb_elements", submix->nb_elements);
print_int("nb_layouts", submix->nb_layouts);
print_q("default_mix_gain", submix->default_mix_gain, '/');
- avtext_print_section_header(w, NULL, SECTION_ID_STREAM_GROUP_PIECES);
+ avtext_print_section_header(tfc, NULL, SECTION_ID_STREAM_GROUP_PIECES);
for (int i = 0; i < submix->nb_elements; i++) {
const AVIAMFSubmixElement *element = submix->elements[i];
- avtext_print_section_header(w, "IAMF Submix Element", SECTION_ID_STREAM_GROUP_PIECE);
+ avtext_print_section_header(tfc, "IAMF Submix Element", SECTION_ID_STREAM_GROUP_PIECE);
print_int("stream_id", element->audio_element_id);
print_q("default_mix_gain", element->default_mix_gain, '/');
print_int("headphones_rendering_mode", element->headphones_rendering_mode);
- avtext_print_section_header(w, NULL, SECTION_ID_STREAM_GROUP_SUBPIECES);
+ avtext_print_section_header(tfc, NULL, SECTION_ID_STREAM_GROUP_SUBPIECES);
if (element->annotations) {
const AVDictionaryEntry *annotation = NULL;
- avtext_print_section_header(w, "IAMF Annotations", SECTION_ID_STREAM_GROUP_SUBPIECE);
+ avtext_print_section_header(tfc, "IAMF Annotations", SECTION_ID_STREAM_GROUP_SUBPIECE);
while (annotation = av_dict_iterate(element->annotations, annotation))
print_str(annotation->key, annotation->value);
- avtext_print_section_footer(w); // SECTION_ID_STREAM_GROUP_SUBPIECE
+ avtext_print_section_footer(tfc); // SECTION_ID_STREAM_GROUP_SUBPIECE
}
if (element->element_mix_config)
- print_iamf_param_definition(w, "element_mix_config", element->element_mix_config,
+ print_iamf_param_definition(tfc, "element_mix_config", element->element_mix_config,
SECTION_ID_STREAM_GROUP_SUBPIECE);
- avtext_print_section_footer(w); // SECTION_ID_STREAM_GROUP_SUBPIECES
- avtext_print_section_footer(w); // SECTION_ID_STREAM_GROUP_PIECE
+ avtext_print_section_footer(tfc); // SECTION_ID_STREAM_GROUP_SUBPIECES
+ avtext_print_section_footer(tfc); // SECTION_ID_STREAM_GROUP_PIECE
}
if (submix->output_mix_config)
- print_iamf_param_definition(w, "output_mix_config", submix->output_mix_config,
+ print_iamf_param_definition(tfc, "output_mix_config", submix->output_mix_config,
SECTION_ID_STREAM_GROUP_PIECE);
for (int i = 0; i < submix->nb_layouts; i++) {
const AVIAMFSubmixLayout *layout = submix->layouts[i];
char val_str[128];
- avtext_print_section_header(w, "IAMF Submix Layout", SECTION_ID_STREAM_GROUP_PIECE);
+ avtext_print_section_header(tfc, "IAMF Submix Layout", SECTION_ID_STREAM_GROUP_PIECE);
av_channel_layout_describe(&layout->sound_system, val_str, sizeof(val_str));
print_str("sound_system", val_str);
print_q("integrated_loudness", layout->integrated_loudness, '/');
@@ -2112,51 +2112,51 @@ static void print_iamf_submix_params(AVTextFormatContext *w, const AVIAMFSubmix
print_q("true_peak", layout->true_peak, '/');
print_q("dialogue_anchored_loudness", layout->dialogue_anchored_loudness, '/');
print_q("album_anchored_loudness", layout->album_anchored_loudness, '/');
- avtext_print_section_footer(w); // SECTION_ID_STREAM_GROUP_PIECE
+ avtext_print_section_footer(tfc); // SECTION_ID_STREAM_GROUP_PIECE
}
- avtext_print_section_footer(w); // SECTION_ID_STREAM_GROUP_PIECES
- avtext_print_section_footer(w); // SECTION_ID_STREAM_GROUP_SUBCOMPONENT
+ avtext_print_section_footer(tfc); // SECTION_ID_STREAM_GROUP_PIECES
+ avtext_print_section_footer(tfc); // SECTION_ID_STREAM_GROUP_SUBCOMPONENT
}
-static void print_iamf_mix_presentation_params(AVTextFormatContext *w, const AVStreamGroup *stg,
+static void print_iamf_mix_presentation_params(AVTextFormatContext *tfc, const AVStreamGroup *stg,
const AVIAMFMixPresentation *mix_presentation)
{
- avtext_print_section_header(w, stg, SECTION_ID_STREAM_GROUP_COMPONENT);
+ avtext_print_section_header(tfc, stg, SECTION_ID_STREAM_GROUP_COMPONENT);
print_int("nb_submixes", mix_presentation->nb_submixes);
- avtext_print_section_header(w, NULL, SECTION_ID_STREAM_GROUP_SUBCOMPONENTS);
+ avtext_print_section_header(tfc, NULL, SECTION_ID_STREAM_GROUP_SUBCOMPONENTS);
if (mix_presentation->annotations) {
const AVDictionaryEntry *annotation = NULL;
- avtext_print_section_header(w, "IAMF Annotations", SECTION_ID_STREAM_GROUP_SUBCOMPONENT);
+ avtext_print_section_header(tfc, "IAMF Annotations", SECTION_ID_STREAM_GROUP_SUBCOMPONENT);
while (annotation = av_dict_iterate(mix_presentation->annotations, annotation))
print_str(annotation->key, annotation->value);
- avtext_print_section_footer(w); // SECTION_ID_STREAM_GROUP_SUBCOMPONENT
+ avtext_print_section_footer(tfc); // SECTION_ID_STREAM_GROUP_SUBCOMPONENT
}
for (int i = 0; i < mix_presentation->nb_submixes; i++)
- print_iamf_submix_params(w, mix_presentation->submixes[i]);
- avtext_print_section_footer(w); // SECTION_ID_STREAM_GROUP_SUBCOMPONENTS
- avtext_print_section_footer(w); // SECTION_ID_STREAM_GROUP_COMPONENT
+ print_iamf_submix_params(tfc, mix_presentation->submixes[i]);
+ avtext_print_section_footer(tfc); // SECTION_ID_STREAM_GROUP_SUBCOMPONENTS
+ avtext_print_section_footer(tfc); // SECTION_ID_STREAM_GROUP_COMPONENT
}
-static void print_stream_group_params(AVTextFormatContext *w, AVStreamGroup *stg)
+static void print_stream_group_params(AVTextFormatContext *tfc, AVStreamGroup *stg)
{
- avtext_print_section_header(w, NULL, SECTION_ID_STREAM_GROUP_COMPONENTS);
+ avtext_print_section_header(tfc, NULL, SECTION_ID_STREAM_GROUP_COMPONENTS);
if (stg->type == AV_STREAM_GROUP_PARAMS_TILE_GRID)
- print_tile_grid_params(w, stg, stg->params.tile_grid);
+ print_tile_grid_params(tfc, stg, stg->params.tile_grid);
else if (stg->type == AV_STREAM_GROUP_PARAMS_IAMF_AUDIO_ELEMENT)
- print_iamf_audio_element_params(w, stg, stg->params.iamf_audio_element);
+ print_iamf_audio_element_params(tfc, stg, stg->params.iamf_audio_element);
else if (stg->type == AV_STREAM_GROUP_PARAMS_IAMF_MIX_PRESENTATION)
- print_iamf_mix_presentation_params(w, stg, stg->params.iamf_mix_presentation);
- avtext_print_section_footer(w); // SECTION_ID_STREAM_GROUP_COMPONENTS
+ print_iamf_mix_presentation_params(tfc, stg, stg->params.iamf_mix_presentation);
+ avtext_print_section_footer(tfc); // SECTION_ID_STREAM_GROUP_COMPONENTS
}
-static int show_stream_group(AVTextFormatContext *w, InputFile *ifile, AVStreamGroup *stg)
+static int show_stream_group(AVTextFormatContext *tfc, InputFile *ifile, AVStreamGroup *stg)
{
AVFormatContext *fmt_ctx = ifile->fmt_ctx;
AVBPrint pbuf;
int i, ret = 0;
av_bprint_init(&pbuf, 1, AV_BPRINT_SIZE_UNLIMITED);
- avtext_print_section_header(w, NULL, SECTION_ID_STREAM_GROUP);
+ avtext_print_section_header(tfc, NULL, SECTION_ID_STREAM_GROUP);
print_int("index", stg->index);
if (fmt_ctx->iformat->flags & AVFMT_SHOW_IDS) print_fmt ("id", "0x%"PRIx64, stg->id);
else print_str_opt("id", "N/A");
@@ -2166,60 +2166,60 @@ static int show_stream_group(AVTextFormatContext *w, InputFile *ifile, AVStreamG
else
print_str_opt("type", "unknown");
if (do_show_stream_group_components)
- print_stream_group_params(w, stg);
+ print_stream_group_params(tfc, stg);
/* Print disposition information */
if (do_show_stream_group_disposition)
- print_dispositions(w, stg->disposition, SECTION_ID_STREAM_GROUP_DISPOSITION);
+ print_dispositions(tfc, stg->disposition, SECTION_ID_STREAM_GROUP_DISPOSITION);
if (do_show_stream_group_tags)
- ret = show_tags(w, stg->metadata, SECTION_ID_STREAM_GROUP_TAGS);
+ ret = show_tags(tfc, stg->metadata, SECTION_ID_STREAM_GROUP_TAGS);
if (ret < 0)
goto end;
- avtext_print_section_header(w, NULL, SECTION_ID_STREAM_GROUP_STREAMS);
+ avtext_print_section_header(tfc, NULL, SECTION_ID_STREAM_GROUP_STREAMS);
for (i = 0; i < stg->nb_streams; i++) {
if (selected_streams[stg->streams[i]->index]) {
- ret = show_stream(w, fmt_ctx, stg->streams[i]->index, &ifile->streams[stg->streams[i]->index], IN_STREAM_GROUP);
+ ret = show_stream(tfc, fmt_ctx, stg->streams[i]->index, &ifile->streams[stg->streams[i]->index], IN_STREAM_GROUP);
if (ret < 0)
break;
}
}
- avtext_print_section_footer(w);
+ avtext_print_section_footer(tfc);
end:
av_bprint_finalize(&pbuf, NULL);
- avtext_print_section_footer(w);
+ avtext_print_section_footer(tfc);
return ret;
}
-static int show_stream_groups(AVTextFormatContext *w, InputFile *ifile)
+static int show_stream_groups(AVTextFormatContext *tfc, InputFile *ifile)
{
AVFormatContext *fmt_ctx = ifile->fmt_ctx;
int i, ret = 0;
- avtext_print_section_header(w, NULL, SECTION_ID_STREAM_GROUPS);
+ avtext_print_section_header(tfc, NULL, SECTION_ID_STREAM_GROUPS);
for (i = 0; i < fmt_ctx->nb_stream_groups; i++) {
AVStreamGroup *stg = fmt_ctx->stream_groups[i];
- ret = show_stream_group(w, ifile, stg);
+ ret = show_stream_group(tfc, ifile, stg);
if (ret < 0)
break;
}
- avtext_print_section_footer(w);
+ avtext_print_section_footer(tfc);
return ret;
}
-static int show_chapters(AVTextFormatContext *w, InputFile *ifile)
+static int show_chapters(AVTextFormatContext *tfc, InputFile *ifile)
{
AVFormatContext *fmt_ctx = ifile->fmt_ctx;
int i, ret = 0;
- avtext_print_section_header(w, NULL, SECTION_ID_CHAPTERS);
+ avtext_print_section_header(tfc, NULL, SECTION_ID_CHAPTERS);
for (i = 0; i < fmt_ctx->nb_chapters; i++) {
AVChapter *chapter = fmt_ctx->chapters[i];
- avtext_print_section_header(w, NULL, SECTION_ID_CHAPTER);
+ avtext_print_section_header(tfc, NULL, SECTION_ID_CHAPTER);
print_int("id", chapter->id);
print_q ("time_base", chapter->time_base, '/');
print_int("start", chapter->start);
@@ -2227,21 +2227,21 @@ static int show_chapters(AVTextFormatContext *w, InputFile *ifile)
print_int("end", chapter->end);
print_time("end_time", chapter->end, &chapter->time_base);
if (do_show_chapter_tags)
- ret = show_tags(w, chapter->metadata, SECTION_ID_CHAPTER_TAGS);
- avtext_print_section_footer(w);
+ ret = show_tags(tfc, chapter->metadata, SECTION_ID_CHAPTER_TAGS);
+ avtext_print_section_footer(tfc);
}
- avtext_print_section_footer(w);
+ avtext_print_section_footer(tfc);
return ret;
}
-static int show_format(AVTextFormatContext *w, InputFile *ifile)
+static int show_format(AVTextFormatContext *tfc, InputFile *ifile)
{
AVFormatContext *fmt_ctx = ifile->fmt_ctx;
int64_t size = fmt_ctx->pb ? avio_size(fmt_ctx->pb) : -1;
int ret = 0;
- avtext_print_section_header(w, NULL, SECTION_ID_FORMAT);
+ avtext_print_section_header(tfc, NULL, SECTION_ID_FORMAT);
print_str_validate("filename", fmt_ctx->url);
print_int("nb_streams", fmt_ctx->nb_streams);
print_int("nb_programs", fmt_ctx->nb_programs);
@@ -2259,19 +2259,19 @@ static int show_format(AVTextFormatContext *w, InputFile *ifile)
else print_str_opt("bit_rate", "N/A");
print_int("probe_score", fmt_ctx->probe_score);
if (do_show_format_tags)
- ret = show_tags(w, fmt_ctx->metadata, SECTION_ID_FORMAT_TAGS);
+ ret = show_tags(tfc, fmt_ctx->metadata, SECTION_ID_FORMAT_TAGS);
- avtext_print_section_footer(w);
+ avtext_print_section_footer(tfc);
fflush(stdout);
return ret;
}
-static void show_error(AVTextFormatContext *w, int err)
+static void show_error(AVTextFormatContext *tfc, int err)
{
- avtext_print_section_header(w, NULL, SECTION_ID_ERROR);
+ avtext_print_section_header(tfc, NULL, SECTION_ID_ERROR);
print_int("code", err);
print_str("string", av_err2str(err));
- avtext_print_section_footer(w);
+ avtext_print_section_footer(tfc);
}
static int open_input_file(InputFile *ifile, const char *filename,
@@ -2413,7 +2413,7 @@ static void close_input_file(InputFile *ifile)
avformat_close_input(&ifile->fmt_ctx);
}
-static int probe_file(AVTextFormatContext *tctx, const char *filename,
+static int probe_file(AVTextFormatContext *tfc, const char *filename,
const char *print_filename)
{
InputFile ifile = { 0 };
@@ -2455,40 +2455,40 @@ static int probe_file(AVTextFormatContext *tctx, const char *filename,
if (do_read_frames || do_read_packets) {
if (do_show_frames && do_show_packets &&
- tctx->formatter->flags & AV_TEXTFORMAT_FLAG_SUPPORTS_MIXED_ARRAY_CONTENT)
+ tfc->formatter->flags & AV_TEXTFORMAT_FLAG_SUPPORTS_MIXED_ARRAY_CONTENT)
section_id = SECTION_ID_PACKETS_AND_FRAMES;
else if (do_show_packets && !do_show_frames)
section_id = SECTION_ID_PACKETS;
else // (!do_show_packets && do_show_frames)
section_id = SECTION_ID_FRAMES;
if (do_show_frames || do_show_packets)
- avtext_print_section_header(tctx, NULL, section_id);
- ret = read_packets(tctx, &ifile);
+ avtext_print_section_header(tfc, NULL, section_id);
+ ret = read_packets(tfc, &ifile);
if (do_show_frames || do_show_packets)
- avtext_print_section_footer(tctx);
+ avtext_print_section_footer(tfc);
CHECK_END;
}
if (do_show_programs) {
- ret = show_programs(tctx, &ifile);
+ ret = show_programs(tfc, &ifile);
CHECK_END;
}
if (do_show_stream_groups) {
- ret = show_stream_groups(tctx, &ifile);
+ ret = show_stream_groups(tfc, &ifile);
CHECK_END;
}
if (do_show_streams) {
- ret = show_streams(tctx, &ifile);
+ ret = show_streams(tfc, &ifile);
CHECK_END;
}
if (do_show_chapters) {
- ret = show_chapters(tctx, &ifile);
+ ret = show_chapters(tfc, &ifile);
CHECK_END;
}
if (do_show_format) {
- ret = show_format(tctx, &ifile);
+ ret = show_format(tfc, &ifile);
CHECK_END;
}
@@ -2511,18 +2511,18 @@ static void show_usage(void)
av_log(NULL, AV_LOG_INFO, "\n");
}
-static void ffprobe_show_program_version(AVTextFormatContext *w)
+static void ffprobe_show_program_version(AVTextFormatContext *tfc)
{
AVBPrint pbuf;
av_bprint_init(&pbuf, 1, AV_BPRINT_SIZE_UNLIMITED);
- avtext_print_section_header(w, NULL, SECTION_ID_PROGRAM_VERSION);
+ avtext_print_section_header(tfc, NULL, SECTION_ID_PROGRAM_VERSION);
print_str("version", FFMPEG_VERSION);
print_fmt("copyright", "Copyright (c) %d-%d the FFmpeg developers",
program_birth_year, CONFIG_THIS_YEAR);
print_str("compiler_ident", CC_IDENT);
print_str("configuration", FFMPEG_CONFIGURATION);
- avtext_print_section_footer(w);
+ avtext_print_section_footer(tfc);
av_bprint_finalize(&pbuf, NULL);
}
@@ -2531,20 +2531,20 @@ static void ffprobe_show_program_version(AVTextFormatContext *w)
do { \
if (CONFIG_##LIBNAME) { \
unsigned int version = libname##_version(); \
- avtext_print_section_header(w, NULL, SECTION_ID_LIBRARY_VERSION); \
+ avtext_print_section_header(tfc, NULL, SECTION_ID_LIBRARY_VERSION); \
print_str("name", "lib" #libname); \
print_int("major", LIB##LIBNAME##_VERSION_MAJOR); \
print_int("minor", LIB##LIBNAME##_VERSION_MINOR); \
print_int("micro", LIB##LIBNAME##_VERSION_MICRO); \
print_int("version", version); \
print_str("ident", LIB##LIBNAME##_IDENT); \
- avtext_print_section_footer(w); \
+ avtext_print_section_footer(tfc); \
} \
} while (0)
-static void ffprobe_show_library_versions(AVTextFormatContext *w)
+static void ffprobe_show_library_versions(AVTextFormatContext *tfc)
{
- avtext_print_section_header(w, NULL, SECTION_ID_LIBRARY_VERSIONS);
+ avtext_print_section_header(tfc, NULL, SECTION_ID_LIBRARY_VERSIONS);
SHOW_LIB_VERSION(avutil, AVUTIL);
SHOW_LIB_VERSION(avcodec, AVCODEC);
SHOW_LIB_VERSION(avformat, AVFORMAT);
@@ -2553,7 +2553,7 @@ static void ffprobe_show_library_versions(AVTextFormatContext *w)
SHOW_LIB_VERSION(swscale, SWSCALE);
SHOW_LIB_VERSION(swresample, SWRESAMPLE);
SHOW_LIB_VERSION(postproc, POSTPROC);
- avtext_print_section_footer(w);
+ avtext_print_section_footer(tfc);
}
#define PRINT_PIX_FMT_FLAG(flagname, name) \
@@ -2561,14 +2561,14 @@ static void ffprobe_show_library_versions(AVTextFormatContext *w)
print_int(name, !!(pixdesc->flags & AV_PIX_FMT_FLAG_##flagname)); \
} while (0)
-static void ffprobe_show_pixel_formats(AVTextFormatContext *w)
+static void ffprobe_show_pixel_formats(AVTextFormatContext *tfc)
{
const AVPixFmtDescriptor *pixdesc = NULL;
int i, n;
- avtext_print_section_header(w, NULL, SECTION_ID_PIXEL_FORMATS);
+ avtext_print_section_header(tfc, NULL, SECTION_ID_PIXEL_FORMATS);
while (pixdesc = av_pix_fmt_desc_next(pixdesc)) {
- avtext_print_section_header(w, NULL, SECTION_ID_PIXEL_FORMAT);
+ avtext_print_section_header(tfc, NULL, SECTION_ID_PIXEL_FORMAT);
print_str("name", pixdesc->name);
print_int("nb_components", pixdesc->nb_components);
if ((pixdesc->nb_components >= 3) && !(pixdesc->flags & AV_PIX_FMT_FLAG_RGB)) {
@@ -2582,7 +2582,7 @@ static void ffprobe_show_pixel_formats(AVTextFormatContext *w)
if (n) print_int ("bits_per_pixel", n);
else print_str_opt("bits_per_pixel", "N/A");
if (do_show_pixel_format_flags) {
- avtext_print_section_header(w, NULL, SECTION_ID_PIXEL_FORMAT_FLAGS);
+ avtext_print_section_header(tfc, NULL, SECTION_ID_PIXEL_FORMAT_FLAGS);
PRINT_PIX_FMT_FLAG(BE, "big_endian");
PRINT_PIX_FMT_FLAG(PAL, "palette");
PRINT_PIX_FMT_FLAG(BITSTREAM, "bitstream");
@@ -2590,21 +2590,21 @@ static void ffprobe_show_pixel_formats(AVTextFormatContext *w)
PRINT_PIX_FMT_FLAG(PLANAR, "planar");
PRINT_PIX_FMT_FLAG(RGB, "rgb");
PRINT_PIX_FMT_FLAG(ALPHA, "alpha");
- avtext_print_section_footer(w);
+ avtext_print_section_footer(tfc);
}
if (do_show_pixel_format_components && (pixdesc->nb_components > 0)) {
- avtext_print_section_header(w, NULL, SECTION_ID_PIXEL_FORMAT_COMPONENTS);
+ avtext_print_section_header(tfc, NULL, SECTION_ID_PIXEL_FORMAT_COMPONENTS);
for (i = 0; i < pixdesc->nb_components; i++) {
- avtext_print_section_header(w, NULL, SECTION_ID_PIXEL_FORMAT_COMPONENT);
+ avtext_print_section_header(tfc, NULL, SECTION_ID_PIXEL_FORMAT_COMPONENT);
print_int("index", i + 1);
print_int("bit_depth", pixdesc->comp[i].depth);
- avtext_print_section_footer(w);
+ avtext_print_section_footer(tfc);
}
- avtext_print_section_footer(w);
+ avtext_print_section_footer(tfc);
}
- avtext_print_section_footer(w);
+ avtext_print_section_footer(tfc);
}
- avtext_print_section_footer(w);
+ avtext_print_section_footer(tfc);
}
static int opt_show_optional_fields(void *optctx, const char *opt, const char *arg)
--
ffmpeg-codebot
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 108+ messages in thread
* [FFmpeg-devel] [PATCH v8 0/4] print_graphs: Complete Filtergraph Printing
2025-03-12 4:04 ` [FFmpeg-devel] [PATCH v7 0/7] " ffmpegagent
` (6 preceding siblings ...)
2025-03-12 4:04 ` [FFmpeg-devel] [PATCH v7 7/7] fftools/ffprobe: Rename AVTextFormatContext variables (w => tfc) softworkz
@ 2025-03-19 17:04 ` ffmpegagent
2025-03-19 17:04 ` [FFmpeg-devel] [PATCH v8 1/4] fftools/textformat: Extract and generalize textformat api from ffprobe.c softworkz
` (5 more replies)
7 siblings, 6 replies; 108+ messages in thread
From: ffmpegagent @ 2025-03-19 17:04 UTC (permalink / raw)
To: ffmpeg-devel; +Cc: softworkz
Due to the additional work on graph visualization (see
https://lists.ffmpeg.org/pipermail/ffmpeg-devel/2025-March/341296.html), I
have removed the two graph printing commits from this patchset rather than
adding to it, as to avoid wasting the effort already spent on reviewing.
So, now it's a graph printing patchset without graph printing :-)
All other commits are unchanged from the previous version. I'm also
resubmitting to give it a final run of the tests on various platforms.
Thanks
softworkz (4):
fftools/textformat: Extract and generalize textformat api from
ffprobe.c
fftools/ffprobe: Change to use textformat api
fftools/ffprobe: Rename writer_print_section_* and WriterContext
fftools/ffprobe: Rename AVTextFormatContext variables (w => tfc)
fftools/Makefile | 12 +
fftools/ffprobe.c | 2296 +++++-----------------------
fftools/textformat/avtextformat.c | 672 ++++++++
fftools/textformat/avtextformat.h | 171 +++
fftools/textformat/avtextwriters.h | 68 +
fftools/textformat/tf_compact.c | 282 ++++
fftools/textformat/tf_default.c | 145 ++
fftools/textformat/tf_flat.c | 174 +++
fftools/textformat/tf_ini.c | 160 ++
fftools/textformat/tf_json.c | 215 +++
fftools/textformat/tf_xml.c | 221 +++
fftools/textformat/tw_avio.c | 129 ++
fftools/textformat/tw_buffer.c | 92 ++
fftools/textformat/tw_stdout.c | 82 +
14 files changed, 2774 insertions(+), 1945 deletions(-)
create mode 100644 fftools/textformat/avtextformat.c
create mode 100644 fftools/textformat/avtextformat.h
create mode 100644 fftools/textformat/avtextwriters.h
create mode 100644 fftools/textformat/tf_compact.c
create mode 100644 fftools/textformat/tf_default.c
create mode 100644 fftools/textformat/tf_flat.c
create mode 100644 fftools/textformat/tf_ini.c
create mode 100644 fftools/textformat/tf_json.c
create mode 100644 fftools/textformat/tf_xml.c
create mode 100644 fftools/textformat/tw_avio.c
create mode 100644 fftools/textformat/tw_buffer.c
create mode 100644 fftools/textformat/tw_stdout.c
base-commit: 0b097ed9f141f57e2b91f0704c721a9eff0204c0
Published-As: https://github.com/ffstaging/FFmpeg/releases/tag/pr-ffstaging-52%2Fsoftworkz%2Fsubmit_print_graphs5-v8
Fetch-It-Via: git fetch https://github.com/ffstaging/FFmpeg pr-ffstaging-52/softworkz/submit_print_graphs5-v8
Pull-Request: https://github.com/ffstaging/FFmpeg/pull/52
Range-diff vs v7:
1: f379c77e88 = 1: f379c77e88 fftools/textformat: Extract and generalize textformat api from ffprobe.c
2: 67bc38ac96 = 2: 67bc38ac96 fftools/ffprobe: Change to use textformat api
3: 52c41fdcd0 = 3: 52c41fdcd0 fftools/ffprobe: Rename writer_print_section_* and WriterContext
4: 21480a08b1 < -: ---------- fftools/ffmpeg_filter: Move some declaration to new header file
5: 70ba7a8bc9 < -: ---------- avfilter/avfilter: Add avfilter_link_get_hw_frames_ctx()
6: a30ded4d62 < -: ---------- fftools/ffmpeg_graphprint: Add options for filtergraph printing
7: fcfcc5f7df = 4: e85abafb4d fftools/ffprobe: Rename AVTextFormatContext variables (w => tfc)
--
ffmpeg-codebot
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 108+ messages in thread
* [FFmpeg-devel] [PATCH v8 1/4] fftools/textformat: Extract and generalize textformat api from ffprobe.c
2025-03-19 17:04 ` [FFmpeg-devel] [PATCH v8 0/4] print_graphs: Complete Filtergraph Printing ffmpegagent
@ 2025-03-19 17:04 ` softworkz
2025-03-19 17:04 ` [FFmpeg-devel] [PATCH v8 2/4] fftools/ffprobe: Change to use textformat api softworkz
` (4 subsequent siblings)
5 siblings, 0 replies; 108+ messages in thread
From: softworkz @ 2025-03-19 17:04 UTC (permalink / raw)
To: ffmpeg-devel; +Cc: softworkz
From: softworkz <softworkz@hotmail.com>
Signed-off-by: softworkz <softworkz@hotmail.com>
---
fftools/textformat/avtextformat.c | 672 +++++++++++++++++++++++++++++
fftools/textformat/avtextformat.h | 171 ++++++++
fftools/textformat/avtextwriters.h | 68 +++
fftools/textformat/tf_compact.c | 282 ++++++++++++
fftools/textformat/tf_default.c | 145 +++++++
fftools/textformat/tf_flat.c | 174 ++++++++
fftools/textformat/tf_ini.c | 160 +++++++
fftools/textformat/tf_json.c | 215 +++++++++
fftools/textformat/tf_xml.c | 221 ++++++++++
fftools/textformat/tw_avio.c | 129 ++++++
fftools/textformat/tw_buffer.c | 92 ++++
fftools/textformat/tw_stdout.c | 82 ++++
12 files changed, 2411 insertions(+)
create mode 100644 fftools/textformat/avtextformat.c
create mode 100644 fftools/textformat/avtextformat.h
create mode 100644 fftools/textformat/avtextwriters.h
create mode 100644 fftools/textformat/tf_compact.c
create mode 100644 fftools/textformat/tf_default.c
create mode 100644 fftools/textformat/tf_flat.c
create mode 100644 fftools/textformat/tf_ini.c
create mode 100644 fftools/textformat/tf_json.c
create mode 100644 fftools/textformat/tf_xml.c
create mode 100644 fftools/textformat/tw_avio.c
create mode 100644 fftools/textformat/tw_buffer.c
create mode 100644 fftools/textformat/tw_stdout.c
diff --git a/fftools/textformat/avtextformat.c b/fftools/textformat/avtextformat.c
new file mode 100644
index 0000000000..6c09f9d2cd
--- /dev/null
+++ b/fftools/textformat/avtextformat.c
@@ -0,0 +1,672 @@
+/*
+ * Copyright (c) The FFmpeg developers
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <limits.h>
+#include <stdarg.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "libavutil/mem.h"
+#include "libavutil/avassert.h"
+#include "libavutil/bprint.h"
+#include "libavutil/error.h"
+#include "libavutil/hash.h"
+#include "libavutil/intreadwrite.h"
+#include "libavutil/macros.h"
+#include "libavutil/opt.h"
+#include "avtextformat.h"
+
+#define SECTION_ID_NONE -1
+
+#define SHOW_OPTIONAL_FIELDS_AUTO -1
+#define SHOW_OPTIONAL_FIELDS_NEVER 0
+#define SHOW_OPTIONAL_FIELDS_ALWAYS 1
+
+static const struct {
+ double bin_val;
+ double dec_val;
+ const char *bin_str;
+ const char *dec_str;
+} si_prefixes[] = {
+ { 1.0, 1.0, "", "" },
+ { 1.024e3, 1e3, "Ki", "K" },
+ { 1.048576e6, 1e6, "Mi", "M" },
+ { 1.073741824e9, 1e9, "Gi", "G" },
+ { 1.099511627776e12, 1e12, "Ti", "T" },
+ { 1.125899906842624e15, 1e15, "Pi", "P" },
+};
+
+static const char *textcontext_get_formatter_name(void *p)
+{
+ AVTextFormatContext *tctx = p;
+ return tctx->formatter->name;
+}
+
+#define OFFSET(x) offsetof(AVTextFormatContext, x)
+
+static const AVOption textcontext_options[] = {
+ { "string_validation", "set string validation mode",
+ OFFSET(string_validation), AV_OPT_TYPE_INT, {.i64=AV_TEXTFORMAT_STRING_VALIDATION_REPLACE}, 0, AV_TEXTFORMAT_STRING_VALIDATION_NB-1, .unit = "sv" },
+ { "sv", "set string validation mode",
+ OFFSET(string_validation), AV_OPT_TYPE_INT, {.i64=AV_TEXTFORMAT_STRING_VALIDATION_REPLACE}, 0, AV_TEXTFORMAT_STRING_VALIDATION_NB-1, .unit = "sv" },
+ { "ignore", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = AV_TEXTFORMAT_STRING_VALIDATION_IGNORE}, .unit = "sv" },
+ { "replace", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = AV_TEXTFORMAT_STRING_VALIDATION_REPLACE}, .unit = "sv" },
+ { "fail", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = AV_TEXTFORMAT_STRING_VALIDATION_FAIL}, .unit = "sv" },
+ { "string_validation_replacement", "set string validation replacement string", OFFSET(string_validation_replacement), AV_OPT_TYPE_STRING, {.str=""}},
+ { "svr", "set string validation replacement string", OFFSET(string_validation_replacement), AV_OPT_TYPE_STRING, {.str="\xEF\xBF\xBD"}},
+ { NULL }
+};
+
+static void *textcontext_child_next(void *obj, void *prev)
+{
+ AVTextFormatContext *ctx = obj;
+ if (!prev && ctx->formatter && ctx->formatter->priv_class && ctx->priv)
+ return ctx->priv;
+ return NULL;
+}
+
+static const AVClass textcontext_class = {
+ .class_name = "AVTextContext",
+ .item_name = textcontext_get_formatter_name,
+ .option = textcontext_options,
+ .version = LIBAVUTIL_VERSION_INT,
+ .child_next = textcontext_child_next,
+};
+
+static void bprint_bytes(AVBPrint *bp, const uint8_t *ubuf, size_t ubuf_size)
+{
+ int i;
+ av_bprintf(bp, "0X");
+ for (i = 0; i < ubuf_size; i++)
+ av_bprintf(bp, "%02X", ubuf[i]);
+}
+
+int avtext_context_close(AVTextFormatContext **ptctx)
+{
+ AVTextFormatContext *tctx = *ptctx;
+ int i;
+ int ret = 0;
+
+ if (!tctx)
+ return EINVAL;
+
+ av_hash_freep(&tctx->hash);
+
+ av_hash_freep(&tctx->hash);
+
+ if (tctx->formatter->uninit)
+ tctx->formatter->uninit(tctx);
+ for (i = 0; i < SECTION_MAX_NB_LEVELS; i++)
+ av_bprint_finalize(&tctx->section_pbuf[i], NULL);
+ if (tctx->formatter->priv_class)
+ av_opt_free(tctx->priv);
+ av_freep(&tctx->priv);
+ av_opt_free(tctx);
+ av_freep(ptctx);
+ return ret;
+}
+
+
+int avtext_context_open(AVTextFormatContext **ptctx, const AVTextFormatter *formatter, AVTextWriterContext *writer_context, const char *args,
+ const struct AVTextFormatSection *sections, int nb_sections,
+ int show_value_unit,
+ int use_value_prefix,
+ int use_byte_value_binary_prefix,
+ int use_value_sexagesimal_format,
+ int show_optional_fields,
+ char *show_data_hash)
+{
+ AVTextFormatContext *tctx;
+ int i, ret = 0;
+
+ if (!(tctx = av_mallocz(sizeof(AVTextFormatContext)))) {
+ ret = AVERROR(ENOMEM);
+ goto fail;
+ }
+
+ if (!(tctx->priv = av_mallocz(formatter->priv_size))) {
+ ret = AVERROR(ENOMEM);
+ goto fail;
+ }
+
+ tctx->show_value_unit = show_value_unit;
+ tctx->use_value_prefix = use_value_prefix;
+ tctx->use_byte_value_binary_prefix = use_byte_value_binary_prefix;
+ tctx->use_value_sexagesimal_format = use_value_sexagesimal_format;
+ tctx->show_optional_fields = show_optional_fields;
+
+ if (nb_sections > SECTION_MAX_NB_SECTIONS) {
+ 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);
+ ret = AVERROR(EINVAL);
+ goto fail;
+ }
+
+ tctx->class = &textcontext_class;
+ tctx->formatter = formatter;
+ tctx->level = -1;
+ tctx->sections = sections;
+ tctx->nb_sections = nb_sections;
+ tctx->writer = writer_context;
+
+ av_opt_set_defaults(tctx);
+
+ if (formatter->priv_class) {
+ void *priv_ctx = tctx->priv;
+ *(const AVClass **)priv_ctx = formatter->priv_class;
+ av_opt_set_defaults(priv_ctx);
+ }
+
+ /* convert options to dictionary */
+ if (args) {
+ AVDictionary *opts = NULL;
+ const AVDictionaryEntry *opt = NULL;
+
+ if ((ret = av_dict_parse_string(&opts, args, "=", ":", 0)) < 0) {
+ av_log(tctx, AV_LOG_ERROR, "Failed to parse option string '%s' provided to textformat context\n", args);
+ av_dict_free(&opts);
+ goto fail;
+ }
+
+ while ((opt = av_dict_iterate(opts, opt))) {
+ if ((ret = av_opt_set(tctx, opt->key, opt->value, AV_OPT_SEARCH_CHILDREN)) < 0) {
+ av_log(tctx, AV_LOG_ERROR, "Failed to set option '%s' with value '%s' provided to textformat context\n",
+ opt->key, opt->value);
+ av_dict_free(&opts);
+ goto fail;
+ }
+ }
+
+ av_dict_free(&opts);
+ }
+
+ if (show_data_hash) {
+ if ((ret = av_hash_alloc(&tctx->hash, show_data_hash)) < 0) {
+ if (ret == AVERROR(EINVAL)) {
+ const char *n;
+ av_log(NULL, AV_LOG_ERROR, "Unknown hash algorithm '%s'\nKnown algorithms:", show_data_hash);
+ for (i = 0; (n = av_hash_names(i)); i++)
+ av_log(NULL, AV_LOG_ERROR, " %s", n);
+ av_log(NULL, AV_LOG_ERROR, "\n");
+ }
+ return ret;
+ }
+ }
+
+ /* validate replace string */
+ {
+ const uint8_t *p = tctx->string_validation_replacement;
+ const uint8_t *endp = p + strlen(p);
+ while (*p) {
+ const uint8_t *p0 = p;
+ int32_t code;
+ ret = av_utf8_decode(&code, &p, endp, tctx->string_validation_utf8_flags);
+ if (ret < 0) {
+ AVBPrint bp;
+ av_bprint_init(&bp, 0, AV_BPRINT_SIZE_AUTOMATIC);
+ bprint_bytes(&bp, p0, p-p0),
+ av_log(tctx, AV_LOG_ERROR,
+ "Invalid UTF8 sequence %s found in string validation replace '%s'\n",
+ bp.str, tctx->string_validation_replacement);
+ return ret;
+ }
+ }
+ }
+
+ for (i = 0; i < SECTION_MAX_NB_LEVELS; i++)
+ av_bprint_init(&tctx->section_pbuf[i], 1, AV_BPRINT_SIZE_UNLIMITED);
+
+ if (tctx->formatter->init)
+ ret = tctx->formatter->init(tctx);
+ if (ret < 0)
+ goto fail;
+
+ *ptctx = tctx;
+
+ return 0;
+
+fail:
+ avtext_context_close(&tctx);
+ return ret;
+}
+
+/* Temporary definitions during refactoring */
+static const char unit_second_str[] = "s" ;
+static const char unit_hertz_str[] = "Hz" ;
+static const char unit_byte_str[] = "byte" ;
+static const char unit_bit_per_second_str[] = "bit/s";
+
+
+void avtext_print_section_header(AVTextFormatContext *tctx,
+ const void *data,
+ int section_id)
+{
+ tctx->level++;
+ av_assert0(tctx->level < SECTION_MAX_NB_LEVELS);
+
+ tctx->nb_item[tctx->level] = 0;
+ memset(tctx->nb_item_type[tctx->level], 0, sizeof(tctx->nb_item_type[tctx->level]));
+ tctx->section[tctx->level] = &tctx->sections[section_id];
+
+ if (tctx->formatter->print_section_header)
+ tctx->formatter->print_section_header(tctx, data);
+}
+
+void avtext_print_section_footer(AVTextFormatContext *tctx)
+{
+ int section_id = tctx->section[tctx->level]->id;
+ int parent_section_id = tctx->level ?
+ tctx->section[tctx->level-1]->id : SECTION_ID_NONE;
+
+ if (parent_section_id != SECTION_ID_NONE) {
+ tctx->nb_item[tctx->level - 1]++;
+ tctx->nb_item_type[tctx->level - 1][section_id]++;
+ }
+
+ if (tctx->formatter->print_section_footer)
+ tctx->formatter->print_section_footer(tctx);
+ tctx->level--;
+}
+
+void avtext_print_integer(AVTextFormatContext *tctx,
+ const char *key, int64_t val)
+{
+ const struct AVTextFormatSection *section = tctx->section[tctx->level];
+
+ if (section->show_all_entries || av_dict_get(section->entries_to_show, key, NULL, 0)) {
+ tctx->formatter->print_integer(tctx, key, val);
+ tctx->nb_item[tctx->level]++;
+ }
+}
+
+static inline int validate_string(AVTextFormatContext *tctx, char **dstp, const char *src)
+{
+ const uint8_t *p, *endp;
+ AVBPrint dstbuf;
+ int invalid_chars_nb = 0, ret = 0;
+
+ av_bprint_init(&dstbuf, 0, AV_BPRINT_SIZE_UNLIMITED);
+
+ endp = src + strlen(src);
+ for (p = src; *p;) {
+ uint32_t code;
+ int invalid = 0;
+ const uint8_t *p0 = p;
+
+ if (av_utf8_decode(&code, &p, endp, tctx->string_validation_utf8_flags) < 0) {
+ AVBPrint bp;
+ av_bprint_init(&bp, 0, AV_BPRINT_SIZE_AUTOMATIC);
+ bprint_bytes(&bp, p0, p-p0);
+ av_log(tctx, AV_LOG_DEBUG,
+ "Invalid UTF-8 sequence %s found in string '%s'\n", bp.str, src);
+ invalid = 1;
+ }
+
+ if (invalid) {
+ invalid_chars_nb++;
+
+ switch (tctx->string_validation) {
+ case AV_TEXTFORMAT_STRING_VALIDATION_FAIL:
+ av_log(tctx, AV_LOG_ERROR,
+ "Invalid UTF-8 sequence found in string '%s'\n", src);
+ ret = AVERROR_INVALIDDATA;
+ goto end;
+ break;
+
+ case AV_TEXTFORMAT_STRING_VALIDATION_REPLACE:
+ av_bprintf(&dstbuf, "%s", tctx->string_validation_replacement);
+ break;
+ }
+ }
+
+ if (!invalid || tctx->string_validation == AV_TEXTFORMAT_STRING_VALIDATION_IGNORE)
+ av_bprint_append_data(&dstbuf, p0, p-p0);
+ }
+
+ if (invalid_chars_nb && tctx->string_validation == AV_TEXTFORMAT_STRING_VALIDATION_REPLACE) {
+ av_log(tctx, AV_LOG_WARNING,
+ "%d invalid UTF-8 sequence(s) found in string '%s', replaced with '%s'\n",
+ invalid_chars_nb, src, tctx->string_validation_replacement);
+ }
+
+end:
+ av_bprint_finalize(&dstbuf, dstp);
+ return ret;
+}
+
+struct unit_value {
+ union { double d; int64_t i; } val;
+ const char *unit;
+};
+
+static char *value_string(AVTextFormatContext *tctx, char *buf, int buf_size, struct unit_value uv)
+{
+ double vald;
+ int64_t vali;
+ int show_float = 0;
+
+ if (uv.unit == unit_second_str) {
+ vald = uv.val.d;
+ show_float = 1;
+ } else {
+ vald = vali = uv.val.i;
+ }
+
+ if (uv.unit == unit_second_str && tctx->use_value_sexagesimal_format) {
+ double secs;
+ int hours, mins;
+ secs = vald;
+ mins = (int)secs / 60;
+ secs = secs - mins * 60;
+ hours = mins / 60;
+ mins %= 60;
+ snprintf(buf, buf_size, "%d:%02d:%09.6f", hours, mins, secs);
+ } else {
+ const char *prefix_string = "";
+
+ if (tctx->use_value_prefix && vald > 1) {
+ int64_t index;
+
+ if (uv.unit == unit_byte_str && tctx->use_byte_value_binary_prefix) {
+ index = (int64_t) (log2(vald)) / 10;
+ index = av_clip(index, 0, FF_ARRAY_ELEMS(si_prefixes) - 1);
+ vald /= si_prefixes[index].bin_val;
+ prefix_string = si_prefixes[index].bin_str;
+ } else {
+ index = (int64_t) (log10(vald)) / 3;
+ index = av_clip(index, 0, FF_ARRAY_ELEMS(si_prefixes) - 1);
+ vald /= si_prefixes[index].dec_val;
+ prefix_string = si_prefixes[index].dec_str;
+ }
+ vali = vald;
+ }
+
+ if (show_float || (tctx->use_value_prefix && vald != (int64_t)vald))
+ snprintf(buf, buf_size, "%f", vald);
+ else
+ snprintf(buf, buf_size, "%"PRId64, vali);
+ av_strlcatf(buf, buf_size, "%s%s%s", *prefix_string || tctx->show_value_unit ? " " : "",
+ prefix_string, tctx->show_value_unit ? uv.unit : "");
+ }
+
+ return buf;
+}
+
+
+void avtext_print_unit_int(AVTextFormatContext *tctx, const char *key, int value, const char *unit)
+{
+ char val_str[128];
+ struct unit_value uv;
+ uv.val.i = value;
+ uv.unit = unit;
+ avtext_print_string(tctx, key, value_string(tctx, val_str, sizeof(val_str), uv), 0);
+}
+
+
+int avtext_print_string(AVTextFormatContext *tctx, const char *key, const char *val, int flags)
+{
+ const struct AVTextFormatSection *section = tctx->section[tctx->level];
+ int ret = 0;
+
+ if (tctx->show_optional_fields == SHOW_OPTIONAL_FIELDS_NEVER ||
+ (tctx->show_optional_fields == SHOW_OPTIONAL_FIELDS_AUTO
+ && (flags & AV_TEXTFORMAT_PRINT_STRING_OPTIONAL)
+ && !(tctx->formatter->flags & AV_TEXTFORMAT_FLAG_SUPPORTS_OPTIONAL_FIELDS)))
+ return 0;
+
+ if (section->show_all_entries || av_dict_get(section->entries_to_show, key, NULL, 0)) {
+ if (flags & AV_TEXTFORMAT_PRINT_STRING_VALIDATE) {
+ char *key1 = NULL, *val1 = NULL;
+ ret = validate_string(tctx, &key1, key);
+ if (ret < 0) goto end;
+ ret = validate_string(tctx, &val1, val);
+ if (ret < 0) goto end;
+ tctx->formatter->print_string(tctx, key1, val1);
+ end:
+ if (ret < 0) {
+ av_log(tctx, AV_LOG_ERROR,
+ "Invalid key=value string combination %s=%s in section %s\n",
+ key, val, section->unique_name);
+ }
+ av_free(key1);
+ av_free(val1);
+ } else {
+ tctx->formatter->print_string(tctx, key, val);
+ }
+
+ tctx->nb_item[tctx->level]++;
+ }
+
+ return ret;
+}
+
+void avtext_print_rational(AVTextFormatContext *tctx,
+ const char *key, AVRational q, char sep)
+{
+ AVBPrint buf;
+ av_bprint_init(&buf, 0, AV_BPRINT_SIZE_AUTOMATIC);
+ av_bprintf(&buf, "%d%c%d", q.num, sep, q.den);
+ avtext_print_string(tctx, key, buf.str, 0);
+}
+
+void avtext_print_time(AVTextFormatContext *tctx, const char *key,
+ int64_t ts, const AVRational *time_base, int is_duration)
+{
+ char buf[128];
+
+ if ((!is_duration && ts == AV_NOPTS_VALUE) || (is_duration && ts == 0)) {
+ avtext_print_string(tctx, key, "N/A", AV_TEXTFORMAT_PRINT_STRING_OPTIONAL);
+ } else {
+ double d = ts * av_q2d(*time_base);
+ struct unit_value uv;
+ uv.val.d = d;
+ uv.unit = unit_second_str;
+ value_string(tctx, buf, sizeof(buf), uv);
+ avtext_print_string(tctx, key, buf, 0);
+ }
+}
+
+void avtext_print_ts(AVTextFormatContext *tctx, const char *key, int64_t ts, int is_duration)
+{
+ if ((!is_duration && ts == AV_NOPTS_VALUE) || (is_duration && ts == 0)) {
+ avtext_print_string(tctx, key, "N/A", AV_TEXTFORMAT_PRINT_STRING_OPTIONAL);
+ } else {
+ avtext_print_integer(tctx, key, ts);
+ }
+}
+
+void avtext_print_data(AVTextFormatContext *tctx, const char *name,
+ const uint8_t *data, int size)
+{
+ AVBPrint bp;
+ int offset = 0, l, i;
+
+ av_bprint_init(&bp, 0, AV_BPRINT_SIZE_UNLIMITED);
+ av_bprintf(&bp, "\n");
+ while (size) {
+ av_bprintf(&bp, "%08x: ", offset);
+ l = FFMIN(size, 16);
+ for (i = 0; i < l; i++) {
+ av_bprintf(&bp, "%02x", data[i]);
+ if (i & 1)
+ av_bprintf(&bp, " ");
+ }
+ av_bprint_chars(&bp, ' ', 41 - 2 * i - i / 2);
+ for (i = 0; i < l; i++)
+ av_bprint_chars(&bp, data[i] - 32U < 95 ? data[i] : '.', 1);
+ av_bprintf(&bp, "\n");
+ offset += l;
+ data += l;
+ size -= l;
+ }
+ avtext_print_string(tctx, name, bp.str, 0);
+ av_bprint_finalize(&bp, NULL);
+}
+
+void avtext_print_data_hash(AVTextFormatContext *tctx, const char *name,
+ const uint8_t *data, int size)
+{
+ char *p, buf[AV_HASH_MAX_SIZE * 2 + 64] = { 0 };
+
+ if (!tctx->hash)
+ return;
+ av_hash_init(tctx->hash);
+ av_hash_update(tctx->hash, data, size);
+ snprintf(buf, sizeof(buf), "%s:", av_hash_get_name(tctx->hash));
+ p = buf + strlen(buf);
+ av_hash_final_hex(tctx->hash, p, buf + sizeof(buf) - p);
+ avtext_print_string(tctx, name, buf, 0);
+}
+
+void avtext_print_integers(AVTextFormatContext *tctx, const char *name,
+ uint8_t *data, int size, const char *format,
+ int columns, int bytes, int offset_add)
+{
+ AVBPrint bp;
+ int offset = 0, l, i;
+
+ av_bprint_init(&bp, 0, AV_BPRINT_SIZE_UNLIMITED);
+ av_bprintf(&bp, "\n");
+ while (size) {
+ av_bprintf(&bp, "%08x: ", offset);
+ l = FFMIN(size, columns);
+ for (i = 0; i < l; i++) {
+ if (bytes == 1) av_bprintf(&bp, format, *data);
+ else if (bytes == 2) av_bprintf(&bp, format, AV_RN16(data));
+ else if (bytes == 4) av_bprintf(&bp, format, AV_RN32(data));
+ data += bytes;
+ size --;
+ }
+ av_bprintf(&bp, "\n");
+ offset += offset_add;
+ }
+ avtext_print_string(tctx, name, bp.str, 0);
+ av_bprint_finalize(&bp, NULL);
+}
+
+static const char *writercontext_get_writer_name(void *p)
+{
+ AVTextWriterContext *wctx = p;
+ return wctx->writer->name;
+}
+
+static void *writercontext_child_next(void *obj, void *prev)
+{
+ AVTextFormatContext *ctx = obj;
+ if (!prev && ctx->formatter && ctx->formatter->priv_class && ctx->priv)
+ return ctx->priv;
+ return NULL;
+}
+
+static const AVClass textwriter_class = {
+ .class_name = "AVTextWriterContext",
+ .item_name = writercontext_get_writer_name,
+ .version = LIBAVUTIL_VERSION_INT,
+ .child_next = writercontext_child_next,
+};
+
+
+int avtextwriter_context_close(AVTextWriterContext **pwctx)
+{
+ AVTextWriterContext *wctx = *pwctx;
+ int ret = 0;
+
+ if (!wctx)
+ return EINVAL;
+
+ if (wctx->writer->uninit)
+ wctx->writer->uninit(wctx);
+ if (wctx->writer->priv_class)
+ av_opt_free(wctx->priv);
+ av_freep(&wctx->priv);
+ av_freep(pwctx);
+ return ret;
+}
+
+
+int avtextwriter_context_open(AVTextWriterContext **pwctx, const AVTextWriter *writer)
+{
+ AVTextWriterContext *wctx;
+ int ret = 0;
+
+ if (!(wctx = av_mallocz(sizeof(AVTextWriterContext)))) {
+ ret = AVERROR(ENOMEM);
+ goto fail;
+ }
+
+ if (!(wctx->priv = av_mallocz(writer->priv_size))) {
+ ret = AVERROR(ENOMEM);
+ goto fail;
+ }
+
+ if (writer->priv_class) {
+ void *priv_ctx = wctx->priv;
+ *(const AVClass **)priv_ctx = writer->priv_class;
+ av_opt_set_defaults(priv_ctx);
+ }
+
+ wctx->class = &textwriter_class;
+ wctx->writer = writer;
+
+ av_opt_set_defaults(wctx);
+
+
+ if (wctx->writer->init)
+ ret = wctx->writer->init(wctx);
+ if (ret < 0)
+ goto fail;
+
+ *pwctx = wctx;
+
+ return 0;
+
+fail:
+ avtextwriter_context_close(&wctx);
+ return ret;
+}
+
+static const AVTextFormatter *registered_formatters[7+1];
+static void formatters_register_all(void)
+{
+ static int initialized;
+
+ if (initialized)
+ return;
+ initialized = 1;
+
+ registered_formatters[0] = &avtextformatter_default;
+ registered_formatters[1] = &avtextformatter_compact;
+ registered_formatters[2] = &avtextformatter_csv;
+ registered_formatters[3] = &avtextformatter_flat;
+ registered_formatters[4] = &avtextformatter_ini;
+ registered_formatters[5] = &avtextformatter_json;
+ registered_formatters[6] = &avtextformatter_xml;
+}
+
+const AVTextFormatter *avtext_get_formatter_by_name(const char *name)
+{
+ formatters_register_all();
+
+ for (int i = 0; registered_formatters[i]; i++)
+ if (!strcmp(registered_formatters[i]->name, name))
+ return registered_formatters[i];
+
+ return NULL;
+}
diff --git a/fftools/textformat/avtextformat.h b/fftools/textformat/avtextformat.h
new file mode 100644
index 0000000000..4689499246
--- /dev/null
+++ b/fftools/textformat/avtextformat.h
@@ -0,0 +1,171 @@
+/*
+ * Copyright (c) The FFmpeg developers
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef FFTOOLS_TEXTFORMAT_AVTEXTFORMAT_H
+#define FFTOOLS_TEXTFORMAT_AVTEXTFORMAT_H
+
+#include <stddef.h>
+#include <stdint.h>
+#include "libavutil/attributes.h"
+#include "libavutil/dict.h"
+#include "libavformat/avio.h"
+#include "libavutil/bprint.h"
+#include "libavutil/rational.h"
+#include "libavutil/hash.h"
+#include "avtextwriters.h"
+
+#define SECTION_MAX_NB_CHILDREN 11
+
+
+struct AVTextFormatSection {
+ int id; ///< unique id identifying a section
+ const char *name;
+
+#define AV_TEXTFORMAT_SECTION_FLAG_IS_WRAPPER 1 ///< the section only contains other sections, but has no data at its own level
+#define AV_TEXTFORMAT_SECTION_FLAG_IS_ARRAY 2 ///< the section contains an array of elements of the same type
+#define AV_TEXTFORMAT_SECTION_FLAG_HAS_VARIABLE_FIELDS 4 ///< the section may contain a variable number of fields with variable keys.
+ /// For these sections the element_name field is mandatory.
+#define AV_TEXTFORMAT_SECTION_FLAG_HAS_TYPE 8 ///< the section contains a type to distinguish multiple nested elements
+#define AV_TEXTFORMAT_SECTION_FLAG_NUMBERING_BY_TYPE 16 ///< the items in this array section should be numbered individually by type
+
+ int flags;
+ const int children_ids[SECTION_MAX_NB_CHILDREN+1]; ///< list of children section IDS, terminated by -1
+ const char *element_name; ///< name of the contained element, if provided
+ const char *unique_name; ///< unique section name, in case the name is ambiguous
+ AVDictionary *entries_to_show;
+ const char *(* get_type)(const void *data); ///< function returning a type if defined, must be defined when SECTION_FLAG_HAS_TYPE is defined
+ int show_all_entries;
+} AVTextFormatSection;
+
+typedef struct AVTextFormatContext AVTextFormatContext;
+
+#define AV_TEXTFORMAT_FLAG_SUPPORTS_OPTIONAL_FIELDS 1
+#define AV_TEXTFORMAT_FLAG_SUPPORTS_MIXED_ARRAY_CONTENT 2
+
+typedef enum {
+ AV_TEXTFORMAT_STRING_VALIDATION_FAIL,
+ AV_TEXTFORMAT_STRING_VALIDATION_REPLACE,
+ AV_TEXTFORMAT_STRING_VALIDATION_IGNORE,
+ AV_TEXTFORMAT_STRING_VALIDATION_NB
+} StringValidation;
+
+typedef struct AVTextFormatter {
+ const AVClass *priv_class; ///< private class of the formatter, if any
+ int priv_size; ///< private size for the formatter context
+ const char *name;
+
+ int (*init) (AVTextFormatContext *tctx);
+ void (*uninit)(AVTextFormatContext *tctx);
+
+ void (*print_section_header)(AVTextFormatContext *tctx, const void *data);
+ void (*print_section_footer)(AVTextFormatContext *tctx);
+ void (*print_integer) (AVTextFormatContext *tctx, const char *, int64_t);
+ void (*print_rational) (AVTextFormatContext *tctx, AVRational *q, char *sep);
+ void (*print_string) (AVTextFormatContext *tctx, const char *, const char *);
+ int flags; ///< a combination or AV_TEXTFORMAT__FLAG_*
+} AVTextFormatter;
+
+#define SECTION_MAX_NB_LEVELS 12
+#define SECTION_MAX_NB_SECTIONS 100
+
+struct AVTextFormatContext {
+ const AVClass *class; ///< class of the formatter
+ const AVTextFormatter *formatter; ///< the AVTextFormatter of which this is an instance
+ AVTextWriterContext *writer; ///< the AVTextWriterContext
+
+ char *name; ///< name of this formatter instance
+ void *priv; ///< private data for use by the filter
+
+ const struct AVTextFormatSection *sections; ///< array containing all sections
+ int nb_sections; ///< number of sections
+
+ int level; ///< current level, starting from 0
+
+ /** number of the item printed in the given section, starting from 0 */
+ unsigned int nb_item[SECTION_MAX_NB_LEVELS];
+ unsigned int nb_item_type[SECTION_MAX_NB_LEVELS][SECTION_MAX_NB_SECTIONS];
+
+ /** section per each level */
+ const struct AVTextFormatSection *section[SECTION_MAX_NB_LEVELS];
+ AVBPrint section_pbuf[SECTION_MAX_NB_LEVELS]; ///< generic print buffer dedicated to each section,
+ /// used by various formatters
+
+ int show_optional_fields;
+ int show_value_unit;
+ int use_value_prefix;
+ int use_byte_value_binary_prefix;
+ int use_value_sexagesimal_format;
+
+ struct AVHashContext *hash;
+
+ int string_validation;
+ char *string_validation_replacement;
+ unsigned int string_validation_utf8_flags;
+};
+
+#define AV_TEXTFORMAT_PRINT_STRING_OPTIONAL 1
+#define AV_TEXTFORMAT_PRINT_STRING_VALIDATE 2
+
+int avtext_context_open(AVTextFormatContext **ptctx, const AVTextFormatter *formatter, AVTextWriterContext *writer_context, const char *args,
+ const struct AVTextFormatSection *sections, int nb_sections,
+ int show_value_unit,
+ int use_value_prefix,
+ int use_byte_value_binary_prefix,
+ int use_value_sexagesimal_format,
+ int show_optional_fields,
+ char *show_data_hash);
+
+int avtext_context_close(AVTextFormatContext **tctx);
+
+
+void avtext_print_section_header(AVTextFormatContext *tctx, const void *data, int section_id);
+
+void avtext_print_section_footer(AVTextFormatContext *tctx);
+
+void avtext_print_integer(AVTextFormatContext *tctx, const char *key, int64_t val);
+
+int avtext_print_string(AVTextFormatContext *tctx, const char *key, const char *val, int flags);
+
+void avtext_print_unit_int(AVTextFormatContext *tctx, const char *key, int value, const char *unit);
+
+void avtext_print_rational(AVTextFormatContext *tctx, const char *key, AVRational q, char sep);
+
+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);
+
+void avtext_print_data(AVTextFormatContext *tctx, const char *name, const uint8_t *data, int size);
+
+void avtext_print_data_hash(AVTextFormatContext *tctx, const char *name, const uint8_t *data, int size);
+
+void avtext_print_integers(AVTextFormatContext *tctx, const char *name, uint8_t *data, int size,
+ const char *format, int columns, int bytes, int offset_add);
+
+const AVTextFormatter *avtext_get_formatter_by_name(const char *name);
+
+extern const AVTextFormatter avtextformatter_default;
+extern const AVTextFormatter avtextformatter_compact;
+extern const AVTextFormatter avtextformatter_csv;
+extern const AVTextFormatter avtextformatter_flat;
+extern const AVTextFormatter avtextformatter_ini;
+extern const AVTextFormatter avtextformatter_json;
+extern const AVTextFormatter avtextformatter_xml;
+
+#endif /* FFTOOLS_TEXTFORMAT_AVTEXTFORMAT_H */
diff --git a/fftools/textformat/avtextwriters.h b/fftools/textformat/avtextwriters.h
new file mode 100644
index 0000000000..a62f2c8906
--- /dev/null
+++ b/fftools/textformat/avtextwriters.h
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) The FFmpeg developers
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef FFTOOLS_TEXTFORMAT_AVTEXTWRITERS_H
+#define FFTOOLS_TEXTFORMAT_AVTEXTWRITERS_H
+
+#include <stddef.h>
+#include <stdint.h>
+#include "libavutil/attributes.h"
+#include "libavutil/dict.h"
+#include "libavformat/avio.h"
+#include "libavutil/bprint.h"
+#include "libavutil/rational.h"
+#include "libavutil/hash.h"
+
+typedef struct AVTextWriterContext AVTextWriterContext;
+
+typedef struct AVTextWriter {
+ const AVClass *priv_class; ///< private class of the writer, if any
+ int priv_size; ///< private size for the writer private class
+ const char *name;
+
+ int (* init)(AVTextWriterContext *wctx);
+ void (* uninit)(AVTextWriterContext *wctx);
+ void (* writer_w8)(AVTextWriterContext *wctx, int b);
+ void (* writer_put_str)(AVTextWriterContext *wctx, const char *str);
+ void (* writer_printf)(AVTextWriterContext *wctx, const char *fmt, ...);
+} AVTextWriter;
+
+typedef struct AVTextWriterContext {
+ const AVClass *class; ///< class of the writer
+ const AVTextWriter *writer;
+ const char *name;
+ void *priv; ///< private data for use by the writer
+
+} AVTextWriterContext;
+
+
+int avtextwriter_context_open(AVTextWriterContext **pwctx, const AVTextWriter *writer);
+
+int avtextwriter_context_close(AVTextWriterContext **pwctx);
+
+int avtextwriter_create_stdout(AVTextWriterContext **pwctx);
+
+int avtextwriter_create_avio(AVTextWriterContext **pwctx, AVIOContext *avio_ctx, int close_on_uninit);
+
+int avtextwriter_create_file(AVTextWriterContext **pwctx, const char *output_filename, int close_on_uninit);
+
+int avtextwriter_create_buffer(AVTextWriterContext **pwctx, AVBPrint *buffer);
+
+#endif /* FFTOOLS_TEXTFORMAT_AVTEXTWRITERS_H */
diff --git a/fftools/textformat/tf_compact.c b/fftools/textformat/tf_compact.c
new file mode 100644
index 0000000000..825b67bc6e
--- /dev/null
+++ b/fftools/textformat/tf_compact.c
@@ -0,0 +1,282 @@
+/*
+ * Copyright (c) The FFmpeg developers
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <limits.h>
+#include <stdarg.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "avtextformat.h"
+#include <libavutil/mem.h>
+#include <libavutil/avassert.h>
+#include <libavutil/bprint.h>
+#include <libavutil/error.h>
+#include <libavutil/macros.h>
+#include <libavutil/opt.h>
+
+
+#define writer_w8(wctx_, b_) (wctx_)->writer->writer->writer_w8((wctx_)->writer, b_)
+#define writer_put_str(wctx_, str_) (wctx_)->writer->writer->writer_put_str((wctx_)->writer, str_)
+#define writer_printf(wctx_, fmt_, ...) (wctx_)->writer->writer->writer_printf((wctx_)->writer, fmt_, __VA_ARGS__)
+
+
+#define DEFINE_FORMATTER_CLASS(name) \
+static const char *name##_get_name(void *ctx) \
+{ \
+ return #name ; \
+} \
+static const AVClass name##_class = { \
+ .class_name = #name, \
+ .item_name = name##_get_name, \
+ .option = name##_options \
+}
+
+
+/* Compact output */
+
+/**
+ * Apply C-language-like string escaping.
+ */
+static const char *c_escape_str(AVBPrint *dst, const char *src, const char sep, void *log_ctx)
+{
+ const char *p;
+
+ for (p = src; *p; p++) {
+ switch (*p) {
+ case '\b': av_bprintf(dst, "%s", "\\b"); break;
+ case '\f': av_bprintf(dst, "%s", "\\f"); break;
+ case '\n': av_bprintf(dst, "%s", "\\n"); break;
+ case '\r': av_bprintf(dst, "%s", "\\r"); break;
+ case '\\': av_bprintf(dst, "%s", "\\\\"); break;
+ default:
+ if (*p == sep)
+ av_bprint_chars(dst, '\\', 1);
+ av_bprint_chars(dst, *p, 1);
+ }
+ }
+ return dst->str;
+}
+
+/**
+ * Quote fields containing special characters, check RFC4180.
+ */
+static const char *csv_escape_str(AVBPrint *dst, const char *src, const char sep, void *log_ctx)
+{
+ char meta_chars[] = { sep, '"', '\n', '\r', '\0' };
+ int needs_quoting = !!src[strcspn(src, meta_chars)];
+
+ if (needs_quoting)
+ av_bprint_chars(dst, '"', 1);
+
+ for (; *src; src++) {
+ if (*src == '"')
+ av_bprint_chars(dst, '"', 1);
+ av_bprint_chars(dst, *src, 1);
+ }
+ if (needs_quoting)
+ av_bprint_chars(dst, '"', 1);
+ return dst->str;
+}
+
+static const char *none_escape_str(AVBPrint *dst, const char *src, const char sep, void *log_ctx)
+{
+ return src;
+}
+
+typedef struct CompactContext {
+ const AVClass *class;
+ char *item_sep_str;
+ char item_sep;
+ int nokey;
+ int print_section;
+ char *escape_mode_str;
+ const char * (*escape_str)(AVBPrint *dst, const char *src, const char sep, void *log_ctx);
+ int nested_section[SECTION_MAX_NB_LEVELS];
+ int has_nested_elems[SECTION_MAX_NB_LEVELS];
+ int terminate_line[SECTION_MAX_NB_LEVELS];
+} CompactContext;
+
+#undef OFFSET
+#define OFFSET(x) offsetof(CompactContext, x)
+
+static const AVOption compact_options[]= {
+ {"item_sep", "set item separator", OFFSET(item_sep_str), AV_OPT_TYPE_STRING, {.str="|"}, 0, 0 },
+ {"s", "set item separator", OFFSET(item_sep_str), AV_OPT_TYPE_STRING, {.str="|"}, 0, 0 },
+ {"nokey", "force no key printing", OFFSET(nokey), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1 },
+ {"nk", "force no key printing", OFFSET(nokey), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1 },
+ {"escape", "set escape mode", OFFSET(escape_mode_str), AV_OPT_TYPE_STRING, {.str="c"}, 0, 0 },
+ {"e", "set escape mode", OFFSET(escape_mode_str), AV_OPT_TYPE_STRING, {.str="c"}, 0, 0 },
+ {"print_section", "print section name", OFFSET(print_section), AV_OPT_TYPE_BOOL, {.i64=1}, 0, 1 },
+ {"p", "print section name", OFFSET(print_section), AV_OPT_TYPE_BOOL, {.i64=1}, 0, 1 },
+ {NULL},
+};
+
+DEFINE_FORMATTER_CLASS(compact);
+
+static av_cold int compact_init(AVTextFormatContext *wctx)
+{
+ CompactContext *compact = wctx->priv;
+
+ if (strlen(compact->item_sep_str) != 1) {
+ av_log(wctx, AV_LOG_ERROR, "Item separator '%s' specified, but must contain a single character\n",
+ compact->item_sep_str);
+ return AVERROR(EINVAL);
+ }
+ compact->item_sep = compact->item_sep_str[0];
+
+ if (!strcmp(compact->escape_mode_str, "none")) compact->escape_str = none_escape_str;
+ else if (!strcmp(compact->escape_mode_str, "c" )) compact->escape_str = c_escape_str;
+ else if (!strcmp(compact->escape_mode_str, "csv" )) compact->escape_str = csv_escape_str;
+ else {
+ av_log(wctx, AV_LOG_ERROR, "Unknown escape mode '%s'\n", compact->escape_mode_str);
+ return AVERROR(EINVAL);
+ }
+
+ return 0;
+}
+
+static void compact_print_section_header(AVTextFormatContext *wctx, const void *data)
+{
+ CompactContext *compact = wctx->priv;
+ const struct AVTextFormatSection *section = wctx->section[wctx->level];
+ const struct AVTextFormatSection *parent_section = wctx->level ?
+ wctx->section[wctx->level-1] : NULL;
+ compact->terminate_line[wctx->level] = 1;
+ compact->has_nested_elems[wctx->level] = 0;
+
+ av_bprint_clear(&wctx->section_pbuf[wctx->level]);
+ if (parent_section &&
+ (section->flags & AV_TEXTFORMAT_SECTION_FLAG_HAS_TYPE ||
+ (!(section->flags & AV_TEXTFORMAT_SECTION_FLAG_IS_ARRAY) &&
+ !(parent_section->flags & (AV_TEXTFORMAT_SECTION_FLAG_IS_WRAPPER|AV_TEXTFORMAT_SECTION_FLAG_IS_ARRAY))))) {
+
+ /* define a prefix for elements not contained in an array or
+ in a wrapper, or for array elements with a type */
+ const char *element_name = (char *)av_x_if_null(section->element_name, section->name);
+ AVBPrint *section_pbuf = &wctx->section_pbuf[wctx->level];
+
+ compact->nested_section[wctx->level] = 1;
+ compact->has_nested_elems[wctx->level-1] = 1;
+
+ av_bprintf(section_pbuf, "%s%s",
+ wctx->section_pbuf[wctx->level-1].str, element_name);
+
+ if (section->flags & AV_TEXTFORMAT_SECTION_FLAG_HAS_TYPE) {
+ // add /TYPE to prefix
+ av_bprint_chars(section_pbuf, '/', 1);
+
+ // normalize section type, replace special characters and lower case
+ for (const char *p = section->get_type(data); *p; p++) {
+ char c =
+ (*p >= '0' && *p <= '9') ||
+ (*p >= 'a' && *p <= 'z') ||
+ (*p >= 'A' && *p <= 'Z') ? av_tolower(*p) : '_';
+ av_bprint_chars(section_pbuf, c, 1);
+ }
+ }
+ av_bprint_chars(section_pbuf, ':', 1);
+
+ wctx->nb_item[wctx->level] = wctx->nb_item[wctx->level-1];
+ } else {
+ if (parent_section && !(parent_section->flags & (AV_TEXTFORMAT_SECTION_FLAG_IS_WRAPPER|AV_TEXTFORMAT_SECTION_FLAG_IS_ARRAY)) &&
+ wctx->level && wctx->nb_item[wctx->level-1])
+ writer_w8(wctx, compact->item_sep);
+ if (compact->print_section &&
+ !(section->flags & (AV_TEXTFORMAT_SECTION_FLAG_IS_WRAPPER|AV_TEXTFORMAT_SECTION_FLAG_IS_ARRAY)))
+ writer_printf(wctx, "%s%c", section->name, compact->item_sep);
+ }
+}
+
+static void compact_print_section_footer(AVTextFormatContext *wctx)
+{
+ CompactContext *compact = wctx->priv;
+
+ if (!compact->nested_section[wctx->level] &&
+ compact->terminate_line[wctx->level] &&
+ !(wctx->section[wctx->level]->flags & (AV_TEXTFORMAT_SECTION_FLAG_IS_WRAPPER|AV_TEXTFORMAT_SECTION_FLAG_IS_ARRAY)))
+ writer_w8(wctx, '\n');
+}
+
+static void compact_print_str(AVTextFormatContext *wctx, const char *key, const char *value)
+{
+ CompactContext *compact = wctx->priv;
+ AVBPrint buf;
+
+ if (wctx->nb_item[wctx->level]) writer_w8(wctx, compact->item_sep);
+ if (!compact->nokey)
+ writer_printf(wctx, "%s%s=", wctx->section_pbuf[wctx->level].str, key);
+ av_bprint_init(&buf, 1, AV_BPRINT_SIZE_UNLIMITED);
+ writer_put_str(wctx, compact->escape_str(&buf, value, compact->item_sep, wctx));
+ av_bprint_finalize(&buf, NULL);
+}
+
+static void compact_print_int(AVTextFormatContext *wctx, const char *key, int64_t value)
+{
+ CompactContext *compact = wctx->priv;
+
+ if (wctx->nb_item[wctx->level]) writer_w8(wctx, compact->item_sep);
+ if (!compact->nokey)
+ writer_printf(wctx, "%s%s=", wctx->section_pbuf[wctx->level].str, key);
+ writer_printf(wctx, "%"PRId64, value);
+}
+
+const AVTextFormatter avtextformatter_compact = {
+ .name = "compact",
+ .priv_size = sizeof(CompactContext),
+ .init = compact_init,
+ .print_section_header = compact_print_section_header,
+ .print_section_footer = compact_print_section_footer,
+ .print_integer = compact_print_int,
+ .print_string = compact_print_str,
+ .flags = AV_TEXTFORMAT_FLAG_SUPPORTS_OPTIONAL_FIELDS,
+ .priv_class = &compact_class,
+};
+
+/* CSV output */
+
+#undef OFFSET
+#define OFFSET(x) offsetof(CompactContext, x)
+
+static const AVOption csv_options[] = {
+ {"item_sep", "set item separator", OFFSET(item_sep_str), AV_OPT_TYPE_STRING, {.str=","}, 0, 0 },
+ {"s", "set item separator", OFFSET(item_sep_str), AV_OPT_TYPE_STRING, {.str=","}, 0, 0 },
+ {"nokey", "force no key printing", OFFSET(nokey), AV_OPT_TYPE_BOOL, {.i64=1}, 0, 1 },
+ {"nk", "force no key printing", OFFSET(nokey), AV_OPT_TYPE_BOOL, {.i64=1}, 0, 1 },
+ {"escape", "set escape mode", OFFSET(escape_mode_str), AV_OPT_TYPE_STRING, {.str="csv"}, 0, 0 },
+ {"e", "set escape mode", OFFSET(escape_mode_str), AV_OPT_TYPE_STRING, {.str="csv"}, 0, 0 },
+ {"print_section", "print section name", OFFSET(print_section), AV_OPT_TYPE_BOOL, {.i64=1}, 0, 1 },
+ {"p", "print section name", OFFSET(print_section), AV_OPT_TYPE_BOOL, {.i64=1}, 0, 1 },
+ {NULL},
+};
+
+DEFINE_FORMATTER_CLASS(csv);
+
+const AVTextFormatter avtextformatter_csv = {
+ .name = "csv",
+ .priv_size = sizeof(CompactContext),
+ .init = compact_init,
+ .print_section_header = compact_print_section_header,
+ .print_section_footer = compact_print_section_footer,
+ .print_integer = compact_print_int,
+ .print_string = compact_print_str,
+ .flags = AV_TEXTFORMAT_FLAG_SUPPORTS_OPTIONAL_FIELDS,
+ .priv_class = &csv_class,
+};
diff --git a/fftools/textformat/tf_default.c b/fftools/textformat/tf_default.c
new file mode 100644
index 0000000000..7369992f01
--- /dev/null
+++ b/fftools/textformat/tf_default.c
@@ -0,0 +1,145 @@
+/*
+ * Copyright (c) The FFmpeg developers
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <limits.h>
+#include <stdarg.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "avtextformat.h"
+#include <libavutil/mem.h>
+#include <libavutil/avassert.h>
+#include <libavutil/bprint.h>
+#include <libavutil/opt.h>
+
+#define writer_w8(wctx_, b_) (wctx_)->writer->writer->writer_w8((wctx_)->writer, b_)
+#define writer_put_str(wctx_, str_) (wctx_)->writer->writer->writer_put_str((wctx_)->writer, str_)
+#define writer_printf(wctx_, fmt_, ...) (wctx_)->writer->writer->writer_printf((wctx_)->writer, fmt_, __VA_ARGS__)
+
+#define DEFINE_FORMATTER_CLASS(name) \
+static const char *name##_get_name(void *ctx) \
+{ \
+ return #name ; \
+} \
+static const AVClass name##_class = { \
+ .class_name = #name, \
+ .item_name = name##_get_name, \
+ .option = name##_options \
+}
+
+/* Default output */
+
+typedef struct DefaultContext {
+ const AVClass *class;
+ int nokey;
+ int noprint_wrappers;
+ int nested_section[SECTION_MAX_NB_LEVELS];
+} DefaultContext;
+
+#undef OFFSET
+#define OFFSET(x) offsetof(DefaultContext, x)
+
+static const AVOption default_options[] = {
+ { "noprint_wrappers", "do not print headers and footers", OFFSET(noprint_wrappers), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1 },
+ { "nw", "do not print headers and footers", OFFSET(noprint_wrappers), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1 },
+ { "nokey", "force no key printing", OFFSET(nokey), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1 },
+ { "nk", "force no key printing", OFFSET(nokey), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1 },
+ {NULL},
+};
+
+DEFINE_FORMATTER_CLASS(default);
+
+/* lame uppercasing routine, assumes the string is lower case ASCII */
+static inline char *upcase_string(char *dst, size_t dst_size, const char *src)
+{
+ int i;
+ for (i = 0; src[i] && i < dst_size-1; i++)
+ dst[i] = av_toupper(src[i]);
+ dst[i] = 0;
+ return dst;
+}
+
+static void default_print_section_header(AVTextFormatContext *wctx, const void *data)
+{
+ DefaultContext *def = wctx->priv;
+ char buf[32];
+ const struct AVTextFormatSection *section = wctx->section[wctx->level];
+ const struct AVTextFormatSection *parent_section = wctx->level ?
+ wctx->section[wctx->level-1] : NULL;
+
+ av_bprint_clear(&wctx->section_pbuf[wctx->level]);
+ if (parent_section &&
+ !(parent_section->flags & (AV_TEXTFORMAT_SECTION_FLAG_IS_WRAPPER|AV_TEXTFORMAT_SECTION_FLAG_IS_ARRAY))) {
+ def->nested_section[wctx->level] = 1;
+ av_bprintf(&wctx->section_pbuf[wctx->level], "%s%s:",
+ wctx->section_pbuf[wctx->level-1].str,
+ upcase_string(buf, sizeof(buf),
+ av_x_if_null(section->element_name, section->name)));
+ }
+
+ if (def->noprint_wrappers || def->nested_section[wctx->level])
+ return;
+
+ if (!(section->flags & (AV_TEXTFORMAT_SECTION_FLAG_IS_WRAPPER|AV_TEXTFORMAT_SECTION_FLAG_IS_ARRAY)))
+ writer_printf(wctx, "[%s]\n", upcase_string(buf, sizeof(buf), section->name));
+}
+
+static void default_print_section_footer(AVTextFormatContext *wctx)
+{
+ DefaultContext *def = wctx->priv;
+ const struct AVTextFormatSection *section = wctx->section[wctx->level];
+ char buf[32];
+
+ if (def->noprint_wrappers || def->nested_section[wctx->level])
+ return;
+
+ if (!(section->flags & (AV_TEXTFORMAT_SECTION_FLAG_IS_WRAPPER|AV_TEXTFORMAT_SECTION_FLAG_IS_ARRAY)))
+ writer_printf(wctx, "[/%s]\n", upcase_string(buf, sizeof(buf), section->name));
+}
+
+static void default_print_str(AVTextFormatContext *wctx, const char *key, const char *value)
+{
+ DefaultContext *def = wctx->priv;
+
+ if (!def->nokey)
+ writer_printf(wctx, "%s%s=", wctx->section_pbuf[wctx->level].str, key);
+ writer_printf(wctx, "%s\n", value);
+}
+
+static void default_print_int(AVTextFormatContext *wctx, const char *key, int64_t value)
+{
+ DefaultContext *def = wctx->priv;
+
+ if (!def->nokey)
+ writer_printf(wctx, "%s%s=", wctx->section_pbuf[wctx->level].str, key);
+ writer_printf(wctx, "%"PRId64"\n", value);
+}
+
+const AVTextFormatter avtextformatter_default = {
+ .name = "default",
+ .priv_size = sizeof(DefaultContext),
+ .print_section_header = default_print_section_header,
+ .print_section_footer = default_print_section_footer,
+ .print_integer = default_print_int,
+ .print_string = default_print_str,
+ .flags = AV_TEXTFORMAT_FLAG_SUPPORTS_OPTIONAL_FIELDS,
+ .priv_class = &default_class,
+};
\ No newline at end of file
diff --git a/fftools/textformat/tf_flat.c b/fftools/textformat/tf_flat.c
new file mode 100644
index 0000000000..6971593c77
--- /dev/null
+++ b/fftools/textformat/tf_flat.c
@@ -0,0 +1,174 @@
+/*
+ * Copyright (c) The FFmpeg developers
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <limits.h>
+#include <stdarg.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "avtextformat.h"
+#include <libavutil/mem.h>
+#include <libavutil/avassert.h>
+#include <libavutil/bprint.h>
+#include <libavutil/error.h>
+#include <libavutil/macros.h>
+#include <libavutil/opt.h>
+
+#define writer_w8(wctx_, b_) (wctx_)->writer->writer->writer_w8((wctx_)->writer, b_)
+#define writer_put_str(wctx_, str_) (wctx_)->writer->writer->writer_put_str((wctx_)->writer, str_)
+#define writer_printf(wctx_, fmt_, ...) (wctx_)->writer->writer->writer_printf((wctx_)->writer, fmt_, __VA_ARGS__)
+
+#define DEFINE_FORMATTER_CLASS(name) \
+static const char *name##_get_name(void *ctx) \
+{ \
+ return #name ; \
+} \
+static const AVClass name##_class = { \
+ .class_name = #name, \
+ .item_name = name##_get_name, \
+ .option = name##_options \
+}
+
+
+/* Flat output */
+
+typedef struct FlatContext {
+ const AVClass *class;
+ const char *sep_str;
+ char sep;
+ int hierarchical;
+} FlatContext;
+
+#undef OFFSET
+#define OFFSET(x) offsetof(FlatContext, x)
+
+static const AVOption flat_options[]= {
+ {"sep_char", "set separator", OFFSET(sep_str), AV_OPT_TYPE_STRING, {.str="."}, 0, 0 },
+ {"s", "set separator", OFFSET(sep_str), AV_OPT_TYPE_STRING, {.str="."}, 0, 0 },
+ {"hierarchical", "specify if the section specification should be hierarchical", OFFSET(hierarchical), AV_OPT_TYPE_BOOL, {.i64=1}, 0, 1 },
+ {"h", "specify if the section specification should be hierarchical", OFFSET(hierarchical), AV_OPT_TYPE_BOOL, {.i64=1}, 0, 1 },
+ {NULL},
+};
+
+DEFINE_FORMATTER_CLASS(flat);
+
+static av_cold int flat_init(AVTextFormatContext *wctx)
+{
+ FlatContext *flat = wctx->priv;
+
+ if (strlen(flat->sep_str) != 1) {
+ av_log(wctx, AV_LOG_ERROR, "Item separator '%s' specified, but must contain a single character\n",
+ flat->sep_str);
+ return AVERROR(EINVAL);
+ }
+ flat->sep = flat->sep_str[0];
+
+ return 0;
+}
+
+static const char *flat_escape_key_str(AVBPrint *dst, const char *src, const char sep)
+{
+ const char *p;
+
+ for (p = src; *p; p++) {
+ if (!((*p >= '0' && *p <= '9') ||
+ (*p >= 'a' && *p <= 'z') ||
+ (*p >= 'A' && *p <= 'Z')))
+ av_bprint_chars(dst, '_', 1);
+ else
+ av_bprint_chars(dst, *p, 1);
+ }
+ return dst->str;
+}
+
+static const char *flat_escape_value_str(AVBPrint *dst, const char *src)
+{
+ const char *p;
+
+ for (p = src; *p; p++) {
+ switch (*p) {
+ case '\n': av_bprintf(dst, "%s", "\\n"); break;
+ case '\r': av_bprintf(dst, "%s", "\\r"); break;
+ case '\\': av_bprintf(dst, "%s", "\\\\"); break;
+ case '"': av_bprintf(dst, "%s", "\\\""); break;
+ case '`': av_bprintf(dst, "%s", "\\`"); break;
+ case '$': av_bprintf(dst, "%s", "\\$"); break;
+ default: av_bprint_chars(dst, *p, 1); break;
+ }
+ }
+ return dst->str;
+}
+
+static void flat_print_section_header(AVTextFormatContext *wctx, const void *data)
+{
+ FlatContext *flat = wctx->priv;
+ AVBPrint *buf = &wctx->section_pbuf[wctx->level];
+ const struct AVTextFormatSection *section = wctx->section[wctx->level];
+ const struct AVTextFormatSection *parent_section = wctx->level ?
+ wctx->section[wctx->level-1] : NULL;
+
+ /* build section header */
+ av_bprint_clear(buf);
+ if (!parent_section)
+ return;
+ av_bprintf(buf, "%s", wctx->section_pbuf[wctx->level-1].str);
+
+ if (flat->hierarchical ||
+ !(section->flags & (AV_TEXTFORMAT_SECTION_FLAG_IS_ARRAY|AV_TEXTFORMAT_SECTION_FLAG_IS_WRAPPER))) {
+ av_bprintf(buf, "%s%s", wctx->section[wctx->level]->name, flat->sep_str);
+
+ if (parent_section->flags & AV_TEXTFORMAT_SECTION_FLAG_IS_ARRAY) {
+ int n = parent_section->flags & AV_TEXTFORMAT_SECTION_FLAG_NUMBERING_BY_TYPE ?
+ wctx->nb_item_type[wctx->level-1][section->id] :
+ wctx->nb_item[wctx->level-1];
+ av_bprintf(buf, "%d%s", n, flat->sep_str);
+ }
+ }
+}
+
+static void flat_print_int(AVTextFormatContext *wctx, const char *key, int64_t value)
+{
+ writer_printf(wctx, "%s%s=%"PRId64"\n", wctx->section_pbuf[wctx->level].str, key, value);
+}
+
+static void flat_print_str(AVTextFormatContext *wctx, const char *key, const char *value)
+{
+ FlatContext *flat = wctx->priv;
+ AVBPrint buf;
+
+ writer_put_str(wctx, wctx->section_pbuf[wctx->level].str);
+ av_bprint_init(&buf, 1, AV_BPRINT_SIZE_UNLIMITED);
+ writer_printf(wctx, "%s=", flat_escape_key_str(&buf, key, flat->sep));
+ av_bprint_clear(&buf);
+ writer_printf(wctx, "\"%s\"\n", flat_escape_value_str(&buf, value));
+ av_bprint_finalize(&buf, NULL);
+}
+
+const AVTextFormatter avtextformatter_flat = {
+ .name = "flat",
+ .priv_size = sizeof(FlatContext),
+ .init = flat_init,
+ .print_section_header = flat_print_section_header,
+ .print_integer = flat_print_int,
+ .print_string = flat_print_str,
+ .flags = AV_TEXTFORMAT_FLAG_SUPPORTS_OPTIONAL_FIELDS|AV_TEXTFORMAT_FLAG_SUPPORTS_MIXED_ARRAY_CONTENT,
+ .priv_class = &flat_class,
+};
diff --git a/fftools/textformat/tf_ini.c b/fftools/textformat/tf_ini.c
new file mode 100644
index 0000000000..1f4216069f
--- /dev/null
+++ b/fftools/textformat/tf_ini.c
@@ -0,0 +1,160 @@
+/*
+ * Copyright (c) The FFmpeg developers
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <limits.h>
+#include <stdarg.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "avtextformat.h"
+#include <libavutil/mem.h>
+#include <libavutil/avassert.h>
+#include <libavutil/bprint.h>
+#include <libavutil/opt.h>
+
+#define writer_w8(wctx_, b_) (wctx_)->writer->writer->writer_w8((wctx_)->writer, b_)
+#define writer_put_str(wctx_, str_) (wctx_)->writer->writer->writer_put_str((wctx_)->writer, str_)
+#define writer_printf(wctx_, fmt_, ...) (wctx_)->writer->writer->writer_printf((wctx_)->writer, fmt_, __VA_ARGS__)
+
+#define DEFINE_FORMATTER_CLASS(name) \
+static const char *name##_get_name(void *ctx) \
+{ \
+ return #name ; \
+} \
+static const AVClass name##_class = { \
+ .class_name = #name, \
+ .item_name = name##_get_name, \
+ .option = name##_options \
+}
+
+/* Default output */
+
+typedef struct DefaultContext {
+ const AVClass *class;
+ int nokey;
+ int noprint_wrappers;
+ int nested_section[SECTION_MAX_NB_LEVELS];
+} DefaultContext;
+
+/* INI format output */
+
+typedef struct INIContext {
+ const AVClass *class;
+ int hierarchical;
+} INIContext;
+
+#undef OFFSET
+#define OFFSET(x) offsetof(INIContext, x)
+
+static const AVOption ini_options[] = {
+ {"hierarchical", "specify if the section specification should be hierarchical", OFFSET(hierarchical), AV_OPT_TYPE_BOOL, {.i64=1}, 0, 1 },
+ {"h", "specify if the section specification should be hierarchical", OFFSET(hierarchical), AV_OPT_TYPE_BOOL, {.i64=1}, 0, 1 },
+ {NULL},
+};
+
+DEFINE_FORMATTER_CLASS(ini);
+
+static char *ini_escape_str(AVBPrint *dst, const char *src)
+{
+ int i = 0;
+ char c = 0;
+
+ while (c = src[i++]) {
+ switch (c) {
+ case '\b': av_bprintf(dst, "%s", "\\b"); break;
+ case '\f': av_bprintf(dst, "%s", "\\f"); break;
+ case '\n': av_bprintf(dst, "%s", "\\n"); break;
+ case '\r': av_bprintf(dst, "%s", "\\r"); break;
+ case '\t': av_bprintf(dst, "%s", "\\t"); break;
+ case '\\':
+ case '#' :
+ case '=' :
+ case ':' : av_bprint_chars(dst, '\\', 1);
+ default:
+ if ((unsigned char)c < 32)
+ av_bprintf(dst, "\\x00%02x", c & 0xff);
+ else
+ av_bprint_chars(dst, c, 1);
+ break;
+ }
+ }
+ return dst->str;
+}
+
+static void ini_print_section_header(AVTextFormatContext *wctx, const void *data)
+{
+ INIContext *ini = wctx->priv;
+ AVBPrint *buf = &wctx->section_pbuf[wctx->level];
+ const struct AVTextFormatSection *section = wctx->section[wctx->level];
+ const struct AVTextFormatSection *parent_section = wctx->level ?
+ wctx->section[wctx->level-1] : NULL;
+
+ av_bprint_clear(buf);
+ if (!parent_section) {
+ writer_put_str(wctx, "# ffprobe output\n\n");
+ return;
+ }
+
+ if (wctx->nb_item[wctx->level-1])
+ writer_w8(wctx, '\n');
+
+ av_bprintf(buf, "%s", wctx->section_pbuf[wctx->level-1].str);
+ if (ini->hierarchical ||
+ !(section->flags & (AV_TEXTFORMAT_SECTION_FLAG_IS_ARRAY|AV_TEXTFORMAT_SECTION_FLAG_IS_WRAPPER))) {
+ av_bprintf(buf, "%s%s", buf->str[0] ? "." : "", wctx->section[wctx->level]->name);
+
+ if (parent_section->flags & AV_TEXTFORMAT_SECTION_FLAG_IS_ARRAY) {
+ int n = parent_section->flags & AV_TEXTFORMAT_SECTION_FLAG_NUMBERING_BY_TYPE ?
+ wctx->nb_item_type[wctx->level-1][section->id] :
+ wctx->nb_item[wctx->level-1];
+ av_bprintf(buf, ".%d", n);
+ }
+ }
+
+ if (!(section->flags & (AV_TEXTFORMAT_SECTION_FLAG_IS_ARRAY|AV_TEXTFORMAT_SECTION_FLAG_IS_WRAPPER)))
+ writer_printf(wctx, "[%s]\n", buf->str);
+}
+
+static void ini_print_str(AVTextFormatContext *wctx, const char *key, const char *value)
+{
+ AVBPrint buf;
+
+ av_bprint_init(&buf, 1, AV_BPRINT_SIZE_UNLIMITED);
+ writer_printf(wctx, "%s=", ini_escape_str(&buf, key));
+ av_bprint_clear(&buf);
+ writer_printf(wctx, "%s\n", ini_escape_str(&buf, value));
+ av_bprint_finalize(&buf, NULL);
+}
+
+static void ini_print_int(AVTextFormatContext *wctx, const char *key, int64_t value)
+{
+ writer_printf(wctx, "%s=%"PRId64"\n", key, value);
+}
+
+const AVTextFormatter avtextformatter_ini = {
+ .name = "ini",
+ .priv_size = sizeof(INIContext),
+ .print_section_header = ini_print_section_header,
+ .print_integer = ini_print_int,
+ .print_string = ini_print_str,
+ .flags = AV_TEXTFORMAT_FLAG_SUPPORTS_OPTIONAL_FIELDS|AV_TEXTFORMAT_FLAG_SUPPORTS_MIXED_ARRAY_CONTENT,
+ .priv_class = &ini_class,
+};
diff --git a/fftools/textformat/tf_json.c b/fftools/textformat/tf_json.c
new file mode 100644
index 0000000000..de27a36e7e
--- /dev/null
+++ b/fftools/textformat/tf_json.c
@@ -0,0 +1,215 @@
+/*
+ * Copyright (c) The FFmpeg developers
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <limits.h>
+#include <stdarg.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "avtextformat.h"
+#include <libavutil/mem.h>
+#include <libavutil/avassert.h>
+#include <libavutil/bprint.h>
+#include <libavutil/opt.h>
+
+#define writer_w8(wctx_, b_) (wctx_)->writer->writer->writer_w8((wctx_)->writer, b_)
+#define writer_put_str(wctx_, str_) (wctx_)->writer->writer->writer_put_str((wctx_)->writer, str_)
+#define writer_printf(wctx_, fmt_, ...) (wctx_)->writer->writer->writer_printf((wctx_)->writer, fmt_, __VA_ARGS__)
+
+#define DEFINE_FORMATTER_CLASS(name) \
+static const char *name##_get_name(void *ctx) \
+{ \
+ return #name ; \
+} \
+static const AVClass name##_class = { \
+ .class_name = #name, \
+ .item_name = name##_get_name, \
+ .option = name##_options \
+}
+
+
+/* JSON output */
+
+typedef struct JSONContext {
+ const AVClass *class;
+ int indent_level;
+ int compact;
+ const char *item_sep, *item_start_end;
+} JSONContext;
+
+#undef OFFSET
+#define OFFSET(x) offsetof(JSONContext, x)
+
+static const AVOption json_options[]= {
+ { "compact", "enable compact output", OFFSET(compact), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1 },
+ { "c", "enable compact output", OFFSET(compact), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1 },
+ { NULL }
+};
+
+DEFINE_FORMATTER_CLASS(json);
+
+static av_cold int json_init(AVTextFormatContext *wctx)
+{
+ JSONContext *json = wctx->priv;
+
+ json->item_sep = json->compact ? ", " : ",\n";
+ json->item_start_end = json->compact ? " " : "\n";
+
+ return 0;
+}
+
+static const char *json_escape_str(AVBPrint *dst, const char *src, void *log_ctx)
+{
+ static const char json_escape[] = {'"', '\\', '\b', '\f', '\n', '\r', '\t', 0};
+ static const char json_subst[] = {'"', '\\', 'b', 'f', 'n', 'r', 't', 0};
+ const char *p;
+
+ for (p = src; *p; p++) {
+ char *s = strchr(json_escape, *p);
+ if (s) {
+ av_bprint_chars(dst, '\\', 1);
+ av_bprint_chars(dst, json_subst[s - json_escape], 1);
+ } else if ((unsigned char)*p < 32) {
+ av_bprintf(dst, "\\u00%02x", *p & 0xff);
+ } else {
+ av_bprint_chars(dst, *p, 1);
+ }
+ }
+ return dst->str;
+}
+
+#define JSON_INDENT() writer_printf(wctx, "%*c", json->indent_level * 4, ' ')
+
+static void json_print_section_header(AVTextFormatContext *wctx, const void *data)
+{
+ JSONContext *json = wctx->priv;
+ AVBPrint buf;
+ const struct AVTextFormatSection *section = wctx->section[wctx->level];
+ const struct AVTextFormatSection *parent_section = wctx->level ?
+ wctx->section[wctx->level-1] : NULL;
+
+ if (wctx->level && wctx->nb_item[wctx->level-1])
+ writer_put_str(wctx, ",\n");
+
+ if (section->flags & AV_TEXTFORMAT_SECTION_FLAG_IS_WRAPPER) {
+ writer_put_str(wctx, "{\n");
+ json->indent_level++;
+ } else {
+ av_bprint_init(&buf, 1, AV_BPRINT_SIZE_UNLIMITED);
+ json_escape_str(&buf, section->name, wctx);
+ JSON_INDENT();
+
+ json->indent_level++;
+ if (section->flags & AV_TEXTFORMAT_SECTION_FLAG_IS_ARRAY) {
+ writer_printf(wctx, "\"%s\": [\n", buf.str);
+ } else if (parent_section && !(parent_section->flags & AV_TEXTFORMAT_SECTION_FLAG_IS_ARRAY)) {
+ writer_printf(wctx, "\"%s\": {%s", buf.str, json->item_start_end);
+ } else {
+ writer_printf(wctx, "{%s", json->item_start_end);
+
+ /* this is required so the parser can distinguish between packets and frames */
+ if (parent_section && parent_section->flags & AV_TEXTFORMAT_SECTION_FLAG_NUMBERING_BY_TYPE) {
+ if (!json->compact)
+ JSON_INDENT();
+ writer_printf(wctx, "\"type\": \"%s\"", section->name);
+ wctx->nb_item[wctx->level]++;
+ }
+ }
+ av_bprint_finalize(&buf, NULL);
+ }
+}
+
+static void json_print_section_footer(AVTextFormatContext *wctx)
+{
+ JSONContext *json = wctx->priv;
+ const struct AVTextFormatSection *section = wctx->section[wctx->level];
+
+ if (wctx->level == 0) {
+ json->indent_level--;
+ writer_put_str(wctx, "\n}\n");
+ } else if (section->flags & AV_TEXTFORMAT_SECTION_FLAG_IS_ARRAY) {
+ writer_w8(wctx, '\n');
+ json->indent_level--;
+ JSON_INDENT();
+ writer_w8(wctx, ']');
+ } else {
+ writer_put_str(wctx, json->item_start_end);
+ json->indent_level--;
+ if (!json->compact)
+ JSON_INDENT();
+ writer_w8(wctx, '}');
+ }
+}
+
+static inline void json_print_item_str(AVTextFormatContext *wctx,
+ const char *key, const char *value)
+{
+ AVBPrint buf;
+
+ av_bprint_init(&buf, 1, AV_BPRINT_SIZE_UNLIMITED);
+ writer_printf(wctx, "\"%s\":", json_escape_str(&buf, key, wctx));
+ av_bprint_clear(&buf);
+ writer_printf(wctx, " \"%s\"", json_escape_str(&buf, value, wctx));
+ av_bprint_finalize(&buf, NULL);
+}
+
+static void json_print_str(AVTextFormatContext *wctx, const char *key, const char *value)
+{
+ JSONContext *json = wctx->priv;
+ const struct AVTextFormatSection *parent_section = wctx->level ?
+ wctx->section[wctx->level-1] : NULL;
+
+ if (wctx->nb_item[wctx->level] || (parent_section && parent_section->flags & AV_TEXTFORMAT_SECTION_FLAG_NUMBERING_BY_TYPE))
+ writer_put_str(wctx, json->item_sep);
+ if (!json->compact)
+ JSON_INDENT();
+ json_print_item_str(wctx, key, value);
+}
+
+static void json_print_int(AVTextFormatContext *wctx, const char *key, int64_t value)
+{
+ JSONContext *json = wctx->priv;
+ const struct AVTextFormatSection *parent_section = wctx->level ?
+ wctx->section[wctx->level-1] : NULL;
+ AVBPrint buf;
+
+ if (wctx->nb_item[wctx->level] || (parent_section && parent_section->flags & AV_TEXTFORMAT_SECTION_FLAG_NUMBERING_BY_TYPE))
+ writer_put_str(wctx, json->item_sep);
+ if (!json->compact)
+ JSON_INDENT();
+
+ av_bprint_init(&buf, 1, AV_BPRINT_SIZE_UNLIMITED);
+ writer_printf(wctx, "\"%s\": %"PRId64, json_escape_str(&buf, key, wctx), value);
+ av_bprint_finalize(&buf, NULL);
+}
+
+const AVTextFormatter avtextformatter_json = {
+ .name = "json",
+ .priv_size = sizeof(JSONContext),
+ .init = json_init,
+ .print_section_header = json_print_section_header,
+ .print_section_footer = json_print_section_footer,
+ .print_integer = json_print_int,
+ .print_string = json_print_str,
+ .flags = AV_TEXTFORMAT_FLAG_SUPPORTS_MIXED_ARRAY_CONTENT,
+ .priv_class = &json_class,
+};
+
diff --git a/fftools/textformat/tf_xml.c b/fftools/textformat/tf_xml.c
new file mode 100644
index 0000000000..57171c4cb3
--- /dev/null
+++ b/fftools/textformat/tf_xml.c
@@ -0,0 +1,221 @@
+/*
+ * Copyright (c) The FFmpeg developers
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <limits.h>
+#include <stdarg.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "avtextformat.h"
+#include <libavutil/mem.h>
+#include <libavutil/avassert.h>
+#include <libavutil/bprint.h>
+#include <libavutil/error.h>
+#include <libavutil/macros.h>
+#include <libavutil/opt.h>
+
+#define writer_w8(wctx_, b_) (wctx_)->writer->writer->writer_w8((wctx_)->writer, b_)
+#define writer_put_str(wctx_, str_) (wctx_)->writer->writer->writer_put_str((wctx_)->writer, str_)
+#define writer_printf(wctx_, fmt_, ...) (wctx_)->writer->writer->writer_printf((wctx_)->writer, fmt_, __VA_ARGS__)
+
+#define DEFINE_FORMATTER_CLASS(name) \
+static const char *name##_get_name(void *ctx) \
+{ \
+ return #name ; \
+} \
+static const AVClass name##_class = { \
+ .class_name = #name, \
+ .item_name = name##_get_name, \
+ .option = name##_options \
+}
+
+/* XML output */
+
+typedef struct XMLContext {
+ const AVClass *class;
+ int within_tag;
+ int indent_level;
+ int fully_qualified;
+ int xsd_strict;
+} XMLContext;
+
+#undef OFFSET
+#define OFFSET(x) offsetof(XMLContext, x)
+
+static const AVOption xml_options[] = {
+ {"fully_qualified", "specify if the output should be fully qualified", OFFSET(fully_qualified), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1 },
+ {"q", "specify if the output should be fully qualified", OFFSET(fully_qualified), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1 },
+ {"xsd_strict", "ensure that the output is XSD compliant", OFFSET(xsd_strict), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1 },
+ {"x", "ensure that the output is XSD compliant", OFFSET(xsd_strict), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1 },
+ {NULL},
+};
+
+DEFINE_FORMATTER_CLASS(xml);
+
+static av_cold int xml_init(AVTextFormatContext *wctx)
+{
+ XMLContext *xml = wctx->priv;
+
+ if (xml->xsd_strict) {
+ xml->fully_qualified = 1;
+#define CHECK_COMPLIANCE(opt, opt_name) \
+ if (opt) { \
+ av_log(wctx, AV_LOG_ERROR, \
+ "XSD-compliant output selected but option '%s' was selected, XML output may be non-compliant.\n" \
+ "You need to disable such option with '-no%s'\n", opt_name, opt_name); \
+ return AVERROR(EINVAL); \
+ }
+ ////CHECK_COMPLIANCE(show_private_data, "private");
+ CHECK_COMPLIANCE(wctx->show_value_unit, "unit");
+ CHECK_COMPLIANCE(wctx->use_value_prefix, "prefix");
+ }
+
+ return 0;
+}
+
+#define XML_INDENT() writer_printf(wctx, "%*c", xml->indent_level * 4, ' ')
+
+static void xml_print_section_header(AVTextFormatContext *wctx, const void *data)
+{
+ XMLContext *xml = wctx->priv;
+ const struct AVTextFormatSection *section = wctx->section[wctx->level];
+ const struct AVTextFormatSection *parent_section = wctx->level ?
+ wctx->section[wctx->level-1] : NULL;
+
+ if (wctx->level == 0) {
+ const char *qual = " xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" "
+ "xmlns:ffprobe=\"http://www.ffmpeg.org/schema/ffprobe\" "
+ "xsi:schemaLocation=\"http://www.ffmpeg.org/schema/ffprobe ffprobe.xsd\"";
+
+ writer_put_str(wctx, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
+ writer_printf(wctx, "<%sffprobe%s>\n",
+ xml->fully_qualified ? "ffprobe:" : "",
+ xml->fully_qualified ? qual : "");
+ return;
+ }
+
+ if (xml->within_tag) {
+ xml->within_tag = 0;
+ writer_put_str(wctx, ">\n");
+ }
+
+ if (parent_section && (parent_section->flags & AV_TEXTFORMAT_SECTION_FLAG_IS_WRAPPER) &&
+ wctx->level && wctx->nb_item[wctx->level-1])
+ writer_w8(wctx, '\n');
+ xml->indent_level++;
+
+ if (section->flags & (AV_TEXTFORMAT_SECTION_FLAG_IS_ARRAY|AV_TEXTFORMAT_SECTION_FLAG_HAS_VARIABLE_FIELDS)) {
+ XML_INDENT(); writer_printf(wctx, "<%s", section->name);
+
+ if (section->flags & AV_TEXTFORMAT_SECTION_FLAG_HAS_TYPE) {
+ AVBPrint buf;
+ av_bprint_init(&buf, 1, AV_BPRINT_SIZE_UNLIMITED);
+ av_bprint_escape(&buf, section->get_type(data), NULL,
+ AV_ESCAPE_MODE_XML, AV_ESCAPE_FLAG_XML_DOUBLE_QUOTES);
+ writer_printf(wctx, " type=\"%s\"", buf.str);
+ }
+ writer_printf(wctx, ">\n", section->name);
+ } else {
+ XML_INDENT(); writer_printf(wctx, "<%s ", section->name);
+ xml->within_tag = 1;
+ }
+}
+
+static void xml_print_section_footer(AVTextFormatContext *wctx)
+{
+ XMLContext *xml = wctx->priv;
+ const struct AVTextFormatSection *section = wctx->section[wctx->level];
+
+ if (wctx->level == 0) {
+ writer_printf(wctx, "</%sffprobe>\n", xml->fully_qualified ? "ffprobe:" : "");
+ } else if (xml->within_tag) {
+ xml->within_tag = 0;
+ writer_put_str(wctx, "/>\n");
+ xml->indent_level--;
+ } else {
+ XML_INDENT(); writer_printf(wctx, "</%s>\n", section->name);
+ xml->indent_level--;
+ }
+}
+
+static void xml_print_value(AVTextFormatContext *wctx, const char *key,
+ const char *str, int64_t num, const int is_int)
+{
+ AVBPrint buf;
+ XMLContext *xml = wctx->priv;
+ const struct AVTextFormatSection *section = wctx->section[wctx->level];
+
+ av_bprint_init(&buf, 1, AV_BPRINT_SIZE_UNLIMITED);
+
+ if (section->flags & AV_TEXTFORMAT_SECTION_FLAG_HAS_VARIABLE_FIELDS) {
+ xml->indent_level++;
+ XML_INDENT();
+ av_bprint_escape(&buf, key, NULL,
+ AV_ESCAPE_MODE_XML, AV_ESCAPE_FLAG_XML_DOUBLE_QUOTES);
+ writer_printf(wctx, "<%s key=\"%s\"",
+ section->element_name, buf.str);
+ av_bprint_clear(&buf);
+
+ if (is_int) {
+ writer_printf(wctx, " value=\"%"PRId64"\"/>\n", num);
+ } else {
+ av_bprint_escape(&buf, str, NULL,
+ AV_ESCAPE_MODE_XML, AV_ESCAPE_FLAG_XML_DOUBLE_QUOTES);
+ writer_printf(wctx, " value=\"%s\"/>\n", buf.str);
+ }
+ xml->indent_level--;
+ } else {
+ if (wctx->nb_item[wctx->level])
+ writer_w8(wctx, ' ');
+
+ if (is_int) {
+ writer_printf(wctx, "%s=\"%"PRId64"\"", key, num);
+ } else {
+ av_bprint_escape(&buf, str, NULL,
+ AV_ESCAPE_MODE_XML, AV_ESCAPE_FLAG_XML_DOUBLE_QUOTES);
+ writer_printf(wctx, "%s=\"%s\"", key, buf.str);
+ }
+ }
+
+ av_bprint_finalize(&buf, NULL);
+}
+
+static inline void xml_print_str(AVTextFormatContext *wctx, const char *key, const char *value) {
+ xml_print_value(wctx, key, value, 0, 0);
+}
+
+static void xml_print_int(AVTextFormatContext *wctx, const char *key, int64_t value)
+{
+ xml_print_value(wctx, key, NULL, value, 1);
+}
+
+const AVTextFormatter avtextformatter_xml = {
+ .name = "xml",
+ .priv_size = sizeof(XMLContext),
+ .init = xml_init,
+ .print_section_header = xml_print_section_header,
+ .print_section_footer = xml_print_section_footer,
+ .print_integer = xml_print_int,
+ .print_string = xml_print_str,
+ .flags = AV_TEXTFORMAT_FLAG_SUPPORTS_MIXED_ARRAY_CONTENT,
+ .priv_class = &xml_class,
+};
+
diff --git a/fftools/textformat/tw_avio.c b/fftools/textformat/tw_avio.c
new file mode 100644
index 0000000000..d335d35a56
--- /dev/null
+++ b/fftools/textformat/tw_avio.c
@@ -0,0 +1,129 @@
+/*
+ * Copyright (c) The FFmpeg developers
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <limits.h>
+#include <stdarg.h>
+
+#include "avtextwriters.h"
+#include "libavutil/opt.h"
+
+/* AVIO Writer */
+
+# define WRITER_NAME "aviowriter"
+
+typedef struct IOWriterContext {
+ const AVClass *class;
+ AVIOContext *avio_context;
+ int close_on_uninit;
+} IOWriterContext;
+
+static const char *iowriter_get_name(void *ctx)
+{
+ return WRITER_NAME;
+}
+
+static const AVClass iowriter_class = {
+ .class_name = WRITER_NAME,
+ .item_name = iowriter_get_name,
+};
+
+static av_cold void iowriter_uninit(AVTextWriterContext *wctx)
+{
+ IOWriterContext *ctx = wctx->priv;
+
+ if (ctx->close_on_uninit && ctx->avio_context) {
+ avio_flush(ctx->avio_context);
+ avio_close(ctx->avio_context);
+ }
+}
+
+static void io_w8(AVTextWriterContext *wctx, int b)
+{
+ IOWriterContext *ctx = wctx->priv;
+ avio_w8(ctx->avio_context, b);
+}
+
+static void io_put_str(AVTextWriterContext *wctx, const char *str)
+{
+ IOWriterContext *ctx = wctx->priv;
+ avio_write(ctx->avio_context, str, strlen(str));
+}
+
+static void io_printf(AVTextWriterContext *wctx, const char *fmt, ...)
+{
+ IOWriterContext *ctx = wctx->priv;
+ va_list ap;
+
+ va_start(ap, fmt);
+ avio_vprintf(ctx->avio_context, fmt, ap);
+ va_end(ap);
+}
+
+
+const AVTextWriter avtextwriter_avio = {
+ .name = WRITER_NAME,
+ .priv_size = sizeof(IOWriterContext),
+ .uninit = iowriter_uninit,
+ .priv_class = &iowriter_class,
+ .writer_put_str = io_put_str,
+ .writer_printf = io_printf,
+ .writer_w8 = io_w8
+};
+
+int avtextwriter_create_file(AVTextWriterContext **pwctx, const char *output_filename, int close_on_uninit)
+{
+ IOWriterContext *ctx;
+ int ret;
+
+
+ ret = avtextwriter_context_open(pwctx, &avtextwriter_avio);
+ if (ret < 0)
+ return ret;
+
+ ctx = (*pwctx)->priv;
+
+ if ((ret = avio_open(&ctx->avio_context, output_filename, AVIO_FLAG_WRITE)) < 0) {
+ av_log(ctx, AV_LOG_ERROR,
+ "Failed to open output '%s' with error: %s\n", output_filename, av_err2str(ret));
+ avtextwriter_context_close(pwctx);
+ return ret;
+ }
+
+ ctx->close_on_uninit = close_on_uninit;
+
+ return ret;
+}
+
+
+int avtextwriter_create_avio(AVTextWriterContext **pwctx, AVIOContext *avio_ctx, int close_on_uninit)
+{
+ IOWriterContext *ctx;
+ int ret;
+
+ ret = avtextwriter_context_open(pwctx, &avtextwriter_avio);
+ if (ret < 0)
+ return ret;
+
+ ctx = (*pwctx)->priv;
+ ctx->avio_context = avio_ctx;
+ ctx->close_on_uninit = close_on_uninit;
+
+ return ret;
+}
diff --git a/fftools/textformat/tw_buffer.c b/fftools/textformat/tw_buffer.c
new file mode 100644
index 0000000000..f8b38414a6
--- /dev/null
+++ b/fftools/textformat/tw_buffer.c
@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) The FFmpeg developers
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <limits.h>
+#include <stdarg.h>
+
+#include "avtextwriters.h"
+#include "libavutil/opt.h"
+#include "libavutil/bprint.h"
+
+/* Buffer Writer */
+
+# define WRITER_NAME "bufferwriter"
+
+typedef struct BufferWriterContext {
+ const AVClass *class;
+ AVBPrint *buffer;
+} BufferWriterContext;
+
+static const char *bufferwriter_get_name(void *ctx)
+{
+ return WRITER_NAME;
+}
+
+static const AVClass bufferwriter_class = {
+ .class_name = WRITER_NAME,
+ .item_name = bufferwriter_get_name,
+};
+
+static void buffer_w8(AVTextWriterContext *wctx, int b)
+{
+ BufferWriterContext *ctx = wctx->priv;
+ av_bprintf(ctx->buffer, "%c", b);
+}
+
+static void buffer_put_str(AVTextWriterContext *wctx, const char *str)
+{
+ BufferWriterContext *ctx = wctx->priv;
+ av_bprintf(ctx->buffer, "%s", str);
+}
+
+static void buffer_printf(AVTextWriterContext *wctx, const char *fmt, ...)
+{
+ BufferWriterContext *ctx = wctx->priv;
+
+ va_list vargs;
+ va_start(vargs, fmt);
+ av_vbprintf(ctx->buffer, fmt, vargs);
+ va_end(vargs);
+}
+
+
+const AVTextWriter avtextwriter_buffer = {
+ .name = WRITER_NAME,
+ .priv_size = sizeof(BufferWriterContext),
+ .priv_class = &bufferwriter_class,
+ .writer_put_str = buffer_put_str,
+ .writer_printf = buffer_printf,
+ .writer_w8 = buffer_w8
+};
+
+int avtextwriter_create_buffer(AVTextWriterContext **pwctx, AVBPrint *buffer)
+{
+ BufferWriterContext *ctx;
+ int ret;
+
+ ret = avtextwriter_context_open(pwctx, &avtextwriter_buffer);
+ if (ret < 0)
+ return ret;
+
+ ctx = (*pwctx)->priv;
+ ctx->buffer = buffer;
+
+ return ret;
+}
diff --git a/fftools/textformat/tw_stdout.c b/fftools/textformat/tw_stdout.c
new file mode 100644
index 0000000000..23de6f671f
--- /dev/null
+++ b/fftools/textformat/tw_stdout.c
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) The FFmpeg developers
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <stdarg.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "avtextwriters.h"
+#include "libavutil/opt.h"
+
+/* STDOUT Writer */
+
+# define WRITER_NAME "stdoutwriter"
+
+typedef struct StdOutWriterContext {
+ const AVClass *class;
+} StdOutWriterContext;
+
+static const char *stdoutwriter_get_name(void *ctx)
+{
+ return WRITER_NAME;
+}
+
+static const AVClass stdoutwriter_class = {
+ .class_name = WRITER_NAME,
+ .item_name = stdoutwriter_get_name,
+};
+
+static inline void stdout_w8(AVTextWriterContext *wctx, int b)
+{
+ printf("%c", b);
+}
+
+static inline void stdout_put_str(AVTextWriterContext *wctx, const char *str)
+{
+ printf("%s", str);
+}
+
+static inline void stdout_printf(AVTextWriterContext *wctx, const char *fmt, ...)
+{
+ va_list ap;
+
+ va_start(ap, fmt);
+ vprintf(fmt, ap);
+ va_end(ap);
+}
+
+
+static const AVTextWriter avtextwriter_stdout = {
+ .name = WRITER_NAME,
+ .priv_size = sizeof(StdOutWriterContext),
+ .priv_class = &stdoutwriter_class,
+ .writer_put_str = stdout_put_str,
+ .writer_printf = stdout_printf,
+ .writer_w8 = stdout_w8
+};
+
+int avtextwriter_create_stdout(AVTextWriterContext **pwctx)
+{
+ int ret;
+
+ ret = avtextwriter_context_open(pwctx, &avtextwriter_stdout);
+
+ return ret;
+}
--
ffmpeg-codebot
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 108+ messages in thread
* [FFmpeg-devel] [PATCH v8 2/4] fftools/ffprobe: Change to use textformat api
2025-03-19 17:04 ` [FFmpeg-devel] [PATCH v8 0/4] print_graphs: Complete Filtergraph Printing ffmpegagent
2025-03-19 17:04 ` [FFmpeg-devel] [PATCH v8 1/4] fftools/textformat: Extract and generalize textformat api from ffprobe.c softworkz
@ 2025-03-19 17:04 ` softworkz
2025-03-22 1:22 ` Michael Niedermayer
2025-03-19 17:04 ` [FFmpeg-devel] [PATCH v8 3/4] fftools/ffprobe: Rename writer_print_section_* and WriterContext softworkz
` (3 subsequent siblings)
5 siblings, 1 reply; 108+ messages in thread
From: softworkz @ 2025-03-19 17:04 UTC (permalink / raw)
To: ffmpeg-devel; +Cc: softworkz
From: softworkz <softworkz@hotmail.com>
Signed-off-by: softworkz <softworkz@hotmail.com>
---
fftools/Makefile | 12 +
fftools/ffprobe.c | 1849 ++++-----------------------------------------
2 files changed, 142 insertions(+), 1719 deletions(-)
diff --git a/fftools/Makefile b/fftools/Makefile
index 4499799818..664b73b161 100644
--- a/fftools/Makefile
+++ b/fftools/Makefile
@@ -22,6 +22,18 @@ OBJS-ffmpeg += \
fftools/sync_queue.o \
fftools/thread_queue.o \
+OBJS-ffprobe += \
+ fftools/textformat/avtextformat.o \
+ fftools/textformat/tf_compact.o \
+ fftools/textformat/tf_default.o \
+ fftools/textformat/tf_flat.o \
+ fftools/textformat/tf_ini.o \
+ fftools/textformat/tf_json.o \
+ fftools/textformat/tf_xml.o \
+ fftools/textformat/tw_avio.o \
+ fftools/textformat/tw_buffer.o \
+ fftools/textformat/tw_stdout.o \
+
OBJS-ffplay += fftools/ffplay_renderer.o
define DOFFTOOL
diff --git a/fftools/ffprobe.c b/fftools/ffprobe.c
index 7341731d2f..f398057df7 100644
--- a/fftools/ffprobe.c
+++ b/fftools/ffprobe.c
@@ -40,7 +40,6 @@
#include "libavutil/channel_layout.h"
#include "libavutil/display.h"
#include "libavutil/film_grain_params.h"
-#include "libavutil/hash.h"
#include "libavutil/hdr_dynamic_metadata.h"
#include "libavutil/iamf.h"
#include "libavutil/mastering_display_metadata.h"
@@ -66,11 +65,17 @@
#include "libpostproc/postprocess.h"
#include "libpostproc/version.h"
#include "libavfilter/version.h"
+#include "textformat/avtextformat.h"
#include "cmdutils.h"
#include "opt_common.h"
#include "libavutil/thread.h"
+// TEMPORARY DEFINES
+#define writer_print_section_header(w, d, s) avtext_print_section_header(w, d, s)
+#define writer_print_section_footer(w) avtext_print_section_footer(w)
+#define WriterContext AVTextFormatContext
+
// attached as opaque_ref to packets/frames
typedef struct FrameData {
int64_t pkt_pos;
@@ -156,10 +161,7 @@ static int find_stream_info = 1;
/* section structure definition */
-#define SECTION_MAX_NB_CHILDREN 11
-
typedef enum {
- SECTION_ID_NONE = -1,
SECTION_ID_CHAPTER,
SECTION_ID_CHAPTER_TAGS,
SECTION_ID_CHAPTERS,
@@ -228,25 +230,6 @@ typedef enum {
SECTION_ID_SUBTITLE,
} SectionID;
-struct section {
- int id; ///< unique id identifying a section
- const char *name;
-
-#define SECTION_FLAG_IS_WRAPPER 1 ///< the section only contains other sections, but has no data at its own level
-#define SECTION_FLAG_IS_ARRAY 2 ///< the section contains an array of elements of the same type
-#define SECTION_FLAG_HAS_VARIABLE_FIELDS 4 ///< the section may contain a variable number of fields with variable keys.
- /// For these sections the element_name field is mandatory.
-#define SECTION_FLAG_HAS_TYPE 8 ///< the section contains a type to distinguish multiple nested elements
-
- int flags;
- const SectionID children_ids[SECTION_MAX_NB_CHILDREN+1]; ///< list of children section IDS, terminated by -1
- const char *element_name; ///< name of the contained element, if provided
- const char *unique_name; ///< unique section name, in case the name is ambiguous
- AVDictionary *entries_to_show;
- const char *(* get_type)(const void *data); ///< function returning a type if defined, must be defined when SECTION_FLAG_HAS_TYPE is defined
- int show_all_entries;
-};
-
static const char *get_packet_side_data_type(const void *data)
{
const AVPacketSideData *sd = (const AVPacketSideData *)data;
@@ -270,75 +253,75 @@ static const char *get_stream_group_type(const void *data)
return av_x_if_null(avformat_stream_group_name(stg->type), "unknown");
}
-static struct section sections[] = {
- [SECTION_ID_CHAPTERS] = { SECTION_ID_CHAPTERS, "chapters", SECTION_FLAG_IS_ARRAY, { SECTION_ID_CHAPTER, -1 } },
+static struct AVTextFormatSection sections[] = {
+ [SECTION_ID_CHAPTERS] = { SECTION_ID_CHAPTERS, "chapters", AV_TEXTFORMAT_SECTION_FLAG_IS_ARRAY, { SECTION_ID_CHAPTER, -1 } },
[SECTION_ID_CHAPTER] = { SECTION_ID_CHAPTER, "chapter", 0, { SECTION_ID_CHAPTER_TAGS, -1 } },
- [SECTION_ID_CHAPTER_TAGS] = { SECTION_ID_CHAPTER_TAGS, "tags", SECTION_FLAG_HAS_VARIABLE_FIELDS, { -1 }, .element_name = "tag", .unique_name = "chapter_tags" },
+ [SECTION_ID_CHAPTER_TAGS] = { SECTION_ID_CHAPTER_TAGS, "tags", AV_TEXTFORMAT_SECTION_FLAG_HAS_VARIABLE_FIELDS, { -1 }, .element_name = "tag", .unique_name = "chapter_tags" },
[SECTION_ID_ERROR] = { SECTION_ID_ERROR, "error", 0, { -1 } },
[SECTION_ID_FORMAT] = { SECTION_ID_FORMAT, "format", 0, { SECTION_ID_FORMAT_TAGS, -1 } },
- [SECTION_ID_FORMAT_TAGS] = { SECTION_ID_FORMAT_TAGS, "tags", SECTION_FLAG_HAS_VARIABLE_FIELDS, { -1 }, .element_name = "tag", .unique_name = "format_tags" },
- [SECTION_ID_FRAMES] = { SECTION_ID_FRAMES, "frames", SECTION_FLAG_IS_ARRAY, { SECTION_ID_FRAME, SECTION_ID_SUBTITLE, -1 } },
+ [SECTION_ID_FORMAT_TAGS] = { SECTION_ID_FORMAT_TAGS, "tags", AV_TEXTFORMAT_SECTION_FLAG_HAS_VARIABLE_FIELDS, { -1 }, .element_name = "tag", .unique_name = "format_tags" },
+ [SECTION_ID_FRAMES] = { SECTION_ID_FRAMES, "frames", AV_TEXTFORMAT_SECTION_FLAG_IS_ARRAY, { SECTION_ID_FRAME, SECTION_ID_SUBTITLE, -1 } },
[SECTION_ID_FRAME] = { SECTION_ID_FRAME, "frame", 0, { SECTION_ID_FRAME_TAGS, SECTION_ID_FRAME_SIDE_DATA_LIST, SECTION_ID_FRAME_LOGS, -1 } },
- [SECTION_ID_FRAME_TAGS] = { SECTION_ID_FRAME_TAGS, "tags", SECTION_FLAG_HAS_VARIABLE_FIELDS, { -1 }, .element_name = "tag", .unique_name = "frame_tags" },
- [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" },
- [SECTION_ID_FRAME_SIDE_DATA] = { SECTION_ID_FRAME_SIDE_DATA, "side_data", SECTION_FLAG_HAS_VARIABLE_FIELDS|SECTION_FLAG_HAS_TYPE, { SECTION_ID_FRAME_SIDE_DATA_TIMECODE_LIST, SECTION_ID_FRAME_SIDE_DATA_COMPONENT_LIST, -1 }, .unique_name = "frame_side_data", .element_name = "side_datum", .get_type = get_frame_side_data_type },
- [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 } },
+ [SECTION_ID_FRAME_TAGS] = { SECTION_ID_FRAME_TAGS, "tags", AV_TEXTFORMAT_SECTION_FLAG_HAS_VARIABLE_FIELDS, { -1 }, .element_name = "tag", .unique_name = "frame_tags" },
+ [SECTION_ID_FRAME_SIDE_DATA_LIST] ={ SECTION_ID_FRAME_SIDE_DATA_LIST, "side_data_list", AV_TEXTFORMAT_SECTION_FLAG_IS_ARRAY, { SECTION_ID_FRAME_SIDE_DATA, -1 }, .element_name = "side_data", .unique_name = "frame_side_data_list" },
+ [SECTION_ID_FRAME_SIDE_DATA] = { SECTION_ID_FRAME_SIDE_DATA, "side_data", AV_TEXTFORMAT_SECTION_FLAG_HAS_VARIABLE_FIELDS|AV_TEXTFORMAT_SECTION_FLAG_HAS_TYPE, { SECTION_ID_FRAME_SIDE_DATA_TIMECODE_LIST, SECTION_ID_FRAME_SIDE_DATA_COMPONENT_LIST, -1 }, .unique_name = "frame_side_data", .element_name = "side_datum", .get_type = get_frame_side_data_type },
+ [SECTION_ID_FRAME_SIDE_DATA_TIMECODE_LIST] = { SECTION_ID_FRAME_SIDE_DATA_TIMECODE_LIST, "timecodes", AV_TEXTFORMAT_SECTION_FLAG_IS_ARRAY, { SECTION_ID_FRAME_SIDE_DATA_TIMECODE, -1 } },
[SECTION_ID_FRAME_SIDE_DATA_TIMECODE] = { SECTION_ID_FRAME_SIDE_DATA_TIMECODE, "timecode", 0, { -1 } },
- [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 }, .element_name = "component", .unique_name = "frame_side_data_components" },
- [SECTION_ID_FRAME_SIDE_DATA_COMPONENT] = { SECTION_ID_FRAME_SIDE_DATA_COMPONENT, "component", SECTION_FLAG_HAS_VARIABLE_FIELDS|SECTION_FLAG_HAS_TYPE, { SECTION_ID_FRAME_SIDE_DATA_PIECE_LIST, -1 }, .unique_name = "frame_side_data_component", .element_name = "component_entry", .get_type = get_raw_string_type },
- [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 }, .element_name = "piece", .unique_name = "frame_side_data_pieces" },
- [SECTION_ID_FRAME_SIDE_DATA_PIECE] = { SECTION_ID_FRAME_SIDE_DATA_PIECE, "piece", SECTION_FLAG_HAS_VARIABLE_FIELDS|SECTION_FLAG_HAS_TYPE, { -1 }, .element_name = "piece_entry", .unique_name = "frame_side_data_piece", .get_type = get_raw_string_type },
- [SECTION_ID_FRAME_LOGS] = { SECTION_ID_FRAME_LOGS, "logs", SECTION_FLAG_IS_ARRAY, { SECTION_ID_FRAME_LOG, -1 } },
+ [SECTION_ID_FRAME_SIDE_DATA_COMPONENT_LIST] = { SECTION_ID_FRAME_SIDE_DATA_COMPONENT_LIST, "components", AV_TEXTFORMAT_SECTION_FLAG_IS_ARRAY, { SECTION_ID_FRAME_SIDE_DATA_COMPONENT, -1 }, .element_name = "component", .unique_name = "frame_side_data_components" },
+ [SECTION_ID_FRAME_SIDE_DATA_COMPONENT] = { SECTION_ID_FRAME_SIDE_DATA_COMPONENT, "component", AV_TEXTFORMAT_SECTION_FLAG_HAS_VARIABLE_FIELDS|AV_TEXTFORMAT_SECTION_FLAG_HAS_TYPE, { SECTION_ID_FRAME_SIDE_DATA_PIECE_LIST, -1 }, .unique_name = "frame_side_data_component", .element_name = "component_entry", .get_type = get_raw_string_type },
+ [SECTION_ID_FRAME_SIDE_DATA_PIECE_LIST] = { SECTION_ID_FRAME_SIDE_DATA_PIECE_LIST, "pieces", AV_TEXTFORMAT_SECTION_FLAG_IS_ARRAY, { SECTION_ID_FRAME_SIDE_DATA_PIECE, -1 }, .element_name = "piece", .unique_name = "frame_side_data_pieces" },
+ [SECTION_ID_FRAME_SIDE_DATA_PIECE] = { SECTION_ID_FRAME_SIDE_DATA_PIECE, "piece", AV_TEXTFORMAT_SECTION_FLAG_HAS_VARIABLE_FIELDS|AV_TEXTFORMAT_SECTION_FLAG_HAS_TYPE, { -1 }, .element_name = "piece_entry", .unique_name = "frame_side_data_piece", .get_type = get_raw_string_type },
+ [SECTION_ID_FRAME_LOGS] = { SECTION_ID_FRAME_LOGS, "logs", AV_TEXTFORMAT_SECTION_FLAG_IS_ARRAY, { SECTION_ID_FRAME_LOG, -1 } },
[SECTION_ID_FRAME_LOG] = { SECTION_ID_FRAME_LOG, "log", 0, { -1 }, },
- [SECTION_ID_LIBRARY_VERSIONS] = { SECTION_ID_LIBRARY_VERSIONS, "library_versions", SECTION_FLAG_IS_ARRAY, { SECTION_ID_LIBRARY_VERSION, -1 } },
+ [SECTION_ID_LIBRARY_VERSIONS] = { SECTION_ID_LIBRARY_VERSIONS, "library_versions", AV_TEXTFORMAT_SECTION_FLAG_IS_ARRAY, { SECTION_ID_LIBRARY_VERSION, -1 } },
[SECTION_ID_LIBRARY_VERSION] = { SECTION_ID_LIBRARY_VERSION, "library_version", 0, { -1 } },
- [SECTION_ID_PACKETS] = { SECTION_ID_PACKETS, "packets", SECTION_FLAG_IS_ARRAY, { SECTION_ID_PACKET, -1} },
- [SECTION_ID_PACKETS_AND_FRAMES] = { SECTION_ID_PACKETS_AND_FRAMES, "packets_and_frames", SECTION_FLAG_IS_ARRAY, { SECTION_ID_PACKET, -1} },
+ [SECTION_ID_PACKETS] = { SECTION_ID_PACKETS, "packets", AV_TEXTFORMAT_SECTION_FLAG_IS_ARRAY, { SECTION_ID_PACKET, -1} },
+ [SECTION_ID_PACKETS_AND_FRAMES] = { SECTION_ID_PACKETS_AND_FRAMES, "packets_and_frames", AV_TEXTFORMAT_SECTION_FLAG_IS_ARRAY | AV_TEXTFORMAT_SECTION_FLAG_NUMBERING_BY_TYPE, { SECTION_ID_PACKET, -1} },
[SECTION_ID_PACKET] = { SECTION_ID_PACKET, "packet", 0, { SECTION_ID_PACKET_TAGS, SECTION_ID_PACKET_SIDE_DATA_LIST, -1 } },
- [SECTION_ID_PACKET_TAGS] = { SECTION_ID_PACKET_TAGS, "tags", SECTION_FLAG_HAS_VARIABLE_FIELDS, { -1 }, .element_name = "tag", .unique_name = "packet_tags" },
- [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" },
- [SECTION_ID_PACKET_SIDE_DATA] = { SECTION_ID_PACKET_SIDE_DATA, "side_data", SECTION_FLAG_HAS_VARIABLE_FIELDS|SECTION_FLAG_HAS_TYPE, { -1 }, .unique_name = "packet_side_data", .element_name = "side_datum", .get_type = get_packet_side_data_type },
- [SECTION_ID_PIXEL_FORMATS] = { SECTION_ID_PIXEL_FORMATS, "pixel_formats", SECTION_FLAG_IS_ARRAY, { SECTION_ID_PIXEL_FORMAT, -1 } },
+ [SECTION_ID_PACKET_TAGS] = { SECTION_ID_PACKET_TAGS, "tags", AV_TEXTFORMAT_SECTION_FLAG_HAS_VARIABLE_FIELDS, { -1 }, .element_name = "tag", .unique_name = "packet_tags" },
+ [SECTION_ID_PACKET_SIDE_DATA_LIST] ={ SECTION_ID_PACKET_SIDE_DATA_LIST, "side_data_list", AV_TEXTFORMAT_SECTION_FLAG_IS_ARRAY, { SECTION_ID_PACKET_SIDE_DATA, -1 }, .element_name = "side_data", .unique_name = "packet_side_data_list" },
+ [SECTION_ID_PACKET_SIDE_DATA] = { SECTION_ID_PACKET_SIDE_DATA, "side_data", AV_TEXTFORMAT_SECTION_FLAG_HAS_VARIABLE_FIELDS|AV_TEXTFORMAT_SECTION_FLAG_HAS_TYPE, { -1 }, .unique_name = "packet_side_data", .element_name = "side_datum", .get_type = get_packet_side_data_type },
+ [SECTION_ID_PIXEL_FORMATS] = { SECTION_ID_PIXEL_FORMATS, "pixel_formats", AV_TEXTFORMAT_SECTION_FLAG_IS_ARRAY, { SECTION_ID_PIXEL_FORMAT, -1 } },
[SECTION_ID_PIXEL_FORMAT] = { SECTION_ID_PIXEL_FORMAT, "pixel_format", 0, { SECTION_ID_PIXEL_FORMAT_FLAGS, SECTION_ID_PIXEL_FORMAT_COMPONENTS, -1 } },
[SECTION_ID_PIXEL_FORMAT_FLAGS] = { SECTION_ID_PIXEL_FORMAT_FLAGS, "flags", 0, { -1 }, .unique_name = "pixel_format_flags" },
- [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" },
+ [SECTION_ID_PIXEL_FORMAT_COMPONENTS] = { SECTION_ID_PIXEL_FORMAT_COMPONENTS, "components", AV_TEXTFORMAT_SECTION_FLAG_IS_ARRAY, {SECTION_ID_PIXEL_FORMAT_COMPONENT, -1 }, .unique_name = "pixel_format_components" },
[SECTION_ID_PIXEL_FORMAT_COMPONENT] = { SECTION_ID_PIXEL_FORMAT_COMPONENT, "component", 0, { -1 } },
[SECTION_ID_PROGRAM_STREAM_DISPOSITION] = { SECTION_ID_PROGRAM_STREAM_DISPOSITION, "disposition", 0, { -1 }, .unique_name = "program_stream_disposition" },
- [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" },
+ [SECTION_ID_PROGRAM_STREAM_TAGS] = { SECTION_ID_PROGRAM_STREAM_TAGS, "tags", AV_TEXTFORMAT_SECTION_FLAG_HAS_VARIABLE_FIELDS, { -1 }, .element_name = "tag", .unique_name = "program_stream_tags" },
[SECTION_ID_PROGRAM] = { SECTION_ID_PROGRAM, "program", 0, { SECTION_ID_PROGRAM_TAGS, SECTION_ID_PROGRAM_STREAMS, -1 } },
- [SECTION_ID_PROGRAM_STREAMS] = { SECTION_ID_PROGRAM_STREAMS, "streams", SECTION_FLAG_IS_ARRAY, { SECTION_ID_PROGRAM_STREAM, -1 }, .unique_name = "program_streams" },
+ [SECTION_ID_PROGRAM_STREAMS] = { SECTION_ID_PROGRAM_STREAMS, "streams", AV_TEXTFORMAT_SECTION_FLAG_IS_ARRAY, { SECTION_ID_PROGRAM_STREAM, -1 }, .unique_name = "program_streams" },
[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" },
- [SECTION_ID_PROGRAM_TAGS] = { SECTION_ID_PROGRAM_TAGS, "tags", SECTION_FLAG_HAS_VARIABLE_FIELDS, { -1 }, .element_name = "tag", .unique_name = "program_tags" },
+ [SECTION_ID_PROGRAM_TAGS] = { SECTION_ID_PROGRAM_TAGS, "tags", AV_TEXTFORMAT_SECTION_FLAG_HAS_VARIABLE_FIELDS, { -1 }, .element_name = "tag", .unique_name = "program_tags" },
[SECTION_ID_PROGRAM_VERSION] = { SECTION_ID_PROGRAM_VERSION, "program_version", 0, { -1 } },
- [SECTION_ID_PROGRAMS] = { SECTION_ID_PROGRAMS, "programs", SECTION_FLAG_IS_ARRAY, { SECTION_ID_PROGRAM, -1 } },
+ [SECTION_ID_PROGRAMS] = { SECTION_ID_PROGRAMS, "programs", AV_TEXTFORMAT_SECTION_FLAG_IS_ARRAY, { SECTION_ID_PROGRAM, -1 } },
[SECTION_ID_STREAM_GROUP_STREAM_DISPOSITION] = { SECTION_ID_STREAM_GROUP_STREAM_DISPOSITION, "disposition", 0, { -1 }, .unique_name = "stream_group_stream_disposition" },
- [SECTION_ID_STREAM_GROUP_STREAM_TAGS] = { SECTION_ID_STREAM_GROUP_STREAM_TAGS, "tags", SECTION_FLAG_HAS_VARIABLE_FIELDS, { -1 }, .element_name = "tag", .unique_name = "stream_group_stream_tags" },
+ [SECTION_ID_STREAM_GROUP_STREAM_TAGS] = { SECTION_ID_STREAM_GROUP_STREAM_TAGS, "tags", AV_TEXTFORMAT_SECTION_FLAG_HAS_VARIABLE_FIELDS, { -1 }, .element_name = "tag", .unique_name = "stream_group_stream_tags" },
[SECTION_ID_STREAM_GROUP] = { SECTION_ID_STREAM_GROUP, "stream_group", 0, { SECTION_ID_STREAM_GROUP_TAGS, SECTION_ID_STREAM_GROUP_DISPOSITION, SECTION_ID_STREAM_GROUP_COMPONENTS, SECTION_ID_STREAM_GROUP_STREAMS, -1 } },
- [SECTION_ID_STREAM_GROUP_COMPONENTS] = { SECTION_ID_STREAM_GROUP_COMPONENTS, "components", SECTION_FLAG_IS_ARRAY, { SECTION_ID_STREAM_GROUP_COMPONENT, -1 }, .element_name = "component", .unique_name = "stream_group_components" },
- [SECTION_ID_STREAM_GROUP_COMPONENT] = { SECTION_ID_STREAM_GROUP_COMPONENT, "component", SECTION_FLAG_HAS_VARIABLE_FIELDS|SECTION_FLAG_HAS_TYPE, { SECTION_ID_STREAM_GROUP_SUBCOMPONENTS, -1 }, .unique_name = "stream_group_component", .element_name = "component_entry", .get_type = get_stream_group_type },
- [SECTION_ID_STREAM_GROUP_SUBCOMPONENTS] = { SECTION_ID_STREAM_GROUP_SUBCOMPONENTS, "subcomponents", SECTION_FLAG_IS_ARRAY, { SECTION_ID_STREAM_GROUP_SUBCOMPONENT, -1 }, .element_name = "component" },
- [SECTION_ID_STREAM_GROUP_SUBCOMPONENT] = { SECTION_ID_STREAM_GROUP_SUBCOMPONENT, "subcomponent", SECTION_FLAG_HAS_VARIABLE_FIELDS|SECTION_FLAG_HAS_TYPE, { SECTION_ID_STREAM_GROUP_PIECES, -1 }, .element_name = "subcomponent_entry", .get_type = get_raw_string_type },
- [SECTION_ID_STREAM_GROUP_PIECES] = { SECTION_ID_STREAM_GROUP_PIECES, "pieces", SECTION_FLAG_IS_ARRAY, { SECTION_ID_STREAM_GROUP_PIECE, -1 }, .element_name = "piece", .unique_name = "stream_group_pieces" },
- [SECTION_ID_STREAM_GROUP_PIECE] = { SECTION_ID_STREAM_GROUP_PIECE, "piece", SECTION_FLAG_HAS_VARIABLE_FIELDS|SECTION_FLAG_HAS_TYPE, { SECTION_ID_STREAM_GROUP_SUBPIECES, -1 }, .unique_name = "stream_group_piece", .element_name = "piece_entry", .get_type = get_raw_string_type },
- [SECTION_ID_STREAM_GROUP_SUBPIECES] = { SECTION_ID_STREAM_GROUP_SUBPIECES, "subpieces", SECTION_FLAG_IS_ARRAY, { SECTION_ID_STREAM_GROUP_SUBPIECE, -1 }, .element_name = "subpiece" },
- [SECTION_ID_STREAM_GROUP_SUBPIECE] = { SECTION_ID_STREAM_GROUP_SUBPIECE, "subpiece", SECTION_FLAG_HAS_VARIABLE_FIELDS|SECTION_FLAG_HAS_TYPE, { SECTION_ID_STREAM_GROUP_BLOCKS, -1 }, .element_name = "subpiece_entry", .get_type = get_raw_string_type },
- [SECTION_ID_STREAM_GROUP_BLOCKS] = { SECTION_ID_STREAM_GROUP_BLOCKS, "blocks", SECTION_FLAG_IS_ARRAY, { SECTION_ID_STREAM_GROUP_BLOCK, -1 }, .element_name = "block" },
- [SECTION_ID_STREAM_GROUP_BLOCK] = { SECTION_ID_STREAM_GROUP_BLOCK, "block", SECTION_FLAG_HAS_VARIABLE_FIELDS|SECTION_FLAG_HAS_TYPE, { -1 }, .element_name = "block_entry", .get_type = get_raw_string_type },
- [SECTION_ID_STREAM_GROUP_STREAMS] = { SECTION_ID_STREAM_GROUP_STREAMS, "streams", SECTION_FLAG_IS_ARRAY, { SECTION_ID_STREAM_GROUP_STREAM, -1 }, .unique_name = "stream_group_streams" },
+ [SECTION_ID_STREAM_GROUP_COMPONENTS] = { SECTION_ID_STREAM_GROUP_COMPONENTS, "components", AV_TEXTFORMAT_SECTION_FLAG_IS_ARRAY, { SECTION_ID_STREAM_GROUP_COMPONENT, -1 }, .element_name = "component", .unique_name = "stream_group_components" },
+ [SECTION_ID_STREAM_GROUP_COMPONENT] = { SECTION_ID_STREAM_GROUP_COMPONENT, "component", AV_TEXTFORMAT_SECTION_FLAG_HAS_VARIABLE_FIELDS|AV_TEXTFORMAT_SECTION_FLAG_HAS_TYPE, { SECTION_ID_STREAM_GROUP_SUBCOMPONENTS, -1 }, .unique_name = "stream_group_component", .element_name = "component_entry", .get_type = get_stream_group_type },
+ [SECTION_ID_STREAM_GROUP_SUBCOMPONENTS] = { SECTION_ID_STREAM_GROUP_SUBCOMPONENTS, "subcomponents", AV_TEXTFORMAT_SECTION_FLAG_IS_ARRAY, { SECTION_ID_STREAM_GROUP_SUBCOMPONENT, -1 }, .element_name = "component" },
+ [SECTION_ID_STREAM_GROUP_SUBCOMPONENT] = { SECTION_ID_STREAM_GROUP_SUBCOMPONENT, "subcomponent", AV_TEXTFORMAT_SECTION_FLAG_HAS_VARIABLE_FIELDS|AV_TEXTFORMAT_SECTION_FLAG_HAS_TYPE, { SECTION_ID_STREAM_GROUP_PIECES, -1 }, .element_name = "subcomponent_entry", .get_type = get_raw_string_type },
+ [SECTION_ID_STREAM_GROUP_PIECES] = { SECTION_ID_STREAM_GROUP_PIECES, "pieces", AV_TEXTFORMAT_SECTION_FLAG_IS_ARRAY, { SECTION_ID_STREAM_GROUP_PIECE, -1 }, .element_name = "piece", .unique_name = "stream_group_pieces" },
+ [SECTION_ID_STREAM_GROUP_PIECE] = { SECTION_ID_STREAM_GROUP_PIECE, "piece", AV_TEXTFORMAT_SECTION_FLAG_HAS_VARIABLE_FIELDS|AV_TEXTFORMAT_SECTION_FLAG_HAS_TYPE, { SECTION_ID_STREAM_GROUP_SUBPIECES, -1 }, .unique_name = "stream_group_piece", .element_name = "piece_entry", .get_type = get_raw_string_type },
+ [SECTION_ID_STREAM_GROUP_SUBPIECES] = { SECTION_ID_STREAM_GROUP_SUBPIECES, "subpieces", AV_TEXTFORMAT_SECTION_FLAG_IS_ARRAY, { SECTION_ID_STREAM_GROUP_SUBPIECE, -1 }, .element_name = "subpiece" },
+ [SECTION_ID_STREAM_GROUP_SUBPIECE] = { SECTION_ID_STREAM_GROUP_SUBPIECE, "subpiece", AV_TEXTFORMAT_SECTION_FLAG_HAS_VARIABLE_FIELDS|AV_TEXTFORMAT_SECTION_FLAG_HAS_TYPE, { SECTION_ID_STREAM_GROUP_BLOCKS, -1 }, .element_name = "subpiece_entry", .get_type = get_raw_string_type },
+ [SECTION_ID_STREAM_GROUP_BLOCKS] = { SECTION_ID_STREAM_GROUP_BLOCKS, "blocks", AV_TEXTFORMAT_SECTION_FLAG_IS_ARRAY, { SECTION_ID_STREAM_GROUP_BLOCK, -1 }, .element_name = "block" },
+ [SECTION_ID_STREAM_GROUP_BLOCK] = { SECTION_ID_STREAM_GROUP_BLOCK, "block", AV_TEXTFORMAT_SECTION_FLAG_HAS_VARIABLE_FIELDS|AV_TEXTFORMAT_SECTION_FLAG_HAS_TYPE, { -1 }, .element_name = "block_entry", .get_type = get_raw_string_type },
+ [SECTION_ID_STREAM_GROUP_STREAMS] = { SECTION_ID_STREAM_GROUP_STREAMS, "streams", AV_TEXTFORMAT_SECTION_FLAG_IS_ARRAY, { SECTION_ID_STREAM_GROUP_STREAM, -1 }, .unique_name = "stream_group_streams" },
[SECTION_ID_STREAM_GROUP_STREAM] = { SECTION_ID_STREAM_GROUP_STREAM, "stream", 0, { SECTION_ID_STREAM_GROUP_STREAM_DISPOSITION, SECTION_ID_STREAM_GROUP_STREAM_TAGS, -1 }, .unique_name = "stream_group_stream" },
[SECTION_ID_STREAM_GROUP_DISPOSITION] = { SECTION_ID_STREAM_GROUP_DISPOSITION, "disposition", 0, { -1 }, .unique_name = "stream_group_disposition" },
- [SECTION_ID_STREAM_GROUP_TAGS] = { SECTION_ID_STREAM_GROUP_TAGS, "tags", SECTION_FLAG_HAS_VARIABLE_FIELDS, { -1 }, .element_name = "tag", .unique_name = "stream_group_tags" },
- [SECTION_ID_STREAM_GROUPS] = { SECTION_ID_STREAM_GROUPS, "stream_groups", SECTION_FLAG_IS_ARRAY, { SECTION_ID_STREAM_GROUP, -1 } },
- [SECTION_ID_ROOT] = { SECTION_ID_ROOT, "root", SECTION_FLAG_IS_WRAPPER,
+ [SECTION_ID_STREAM_GROUP_TAGS] = { SECTION_ID_STREAM_GROUP_TAGS, "tags", AV_TEXTFORMAT_SECTION_FLAG_HAS_VARIABLE_FIELDS, { -1 }, .element_name = "tag", .unique_name = "stream_group_tags" },
+ [SECTION_ID_STREAM_GROUPS] = { SECTION_ID_STREAM_GROUPS, "stream_groups", AV_TEXTFORMAT_SECTION_FLAG_IS_ARRAY, { SECTION_ID_STREAM_GROUP, -1 } },
+ [SECTION_ID_ROOT] = { SECTION_ID_ROOT, "root", AV_TEXTFORMAT_SECTION_FLAG_IS_WRAPPER,
{ SECTION_ID_CHAPTERS, SECTION_ID_FORMAT, SECTION_ID_FRAMES, SECTION_ID_PROGRAMS, SECTION_ID_STREAM_GROUPS, SECTION_ID_STREAMS,
SECTION_ID_PACKETS, SECTION_ID_ERROR, SECTION_ID_PROGRAM_VERSION, SECTION_ID_LIBRARY_VERSIONS,
SECTION_ID_PIXEL_FORMATS, -1} },
- [SECTION_ID_STREAMS] = { SECTION_ID_STREAMS, "streams", SECTION_FLAG_IS_ARRAY, { SECTION_ID_STREAM, -1 } },
+ [SECTION_ID_STREAMS] = { SECTION_ID_STREAMS, "streams", AV_TEXTFORMAT_SECTION_FLAG_IS_ARRAY, { SECTION_ID_STREAM, -1 } },
[SECTION_ID_STREAM] = { SECTION_ID_STREAM, "stream", 0, { SECTION_ID_STREAM_DISPOSITION, SECTION_ID_STREAM_TAGS, SECTION_ID_STREAM_SIDE_DATA_LIST, -1 } },
[SECTION_ID_STREAM_DISPOSITION] = { SECTION_ID_STREAM_DISPOSITION, "disposition", 0, { -1 }, .unique_name = "stream_disposition" },
- [SECTION_ID_STREAM_TAGS] = { SECTION_ID_STREAM_TAGS, "tags", SECTION_FLAG_HAS_VARIABLE_FIELDS, { -1 }, .element_name = "tag", .unique_name = "stream_tags" },
- [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" },
- [SECTION_ID_STREAM_SIDE_DATA] = { SECTION_ID_STREAM_SIDE_DATA, "side_data", SECTION_FLAG_HAS_TYPE|SECTION_FLAG_HAS_VARIABLE_FIELDS, { -1 }, .unique_name = "stream_side_data", .element_name = "side_datum", .get_type = get_packet_side_data_type },
+ [SECTION_ID_STREAM_TAGS] = { SECTION_ID_STREAM_TAGS, "tags", AV_TEXTFORMAT_SECTION_FLAG_HAS_VARIABLE_FIELDS, { -1 }, .element_name = "tag", .unique_name = "stream_tags" },
+ [SECTION_ID_STREAM_SIDE_DATA_LIST] ={ SECTION_ID_STREAM_SIDE_DATA_LIST, "side_data_list", AV_TEXTFORMAT_SECTION_FLAG_IS_ARRAY, { SECTION_ID_STREAM_SIDE_DATA, -1 }, .element_name = "side_data", .unique_name = "stream_side_data_list" },
+ [SECTION_ID_STREAM_SIDE_DATA] = { SECTION_ID_STREAM_SIDE_DATA, "side_data", AV_TEXTFORMAT_SECTION_FLAG_HAS_TYPE|AV_TEXTFORMAT_SECTION_FLAG_HAS_VARIABLE_FIELDS, { -1 }, .unique_name = "stream_side_data", .element_name = "side_datum", .get_type = get_packet_side_data_type },
[SECTION_ID_SUBTITLE] = { SECTION_ID_SUBTITLE, "subtitle", 0, { -1 } },
};
@@ -350,22 +333,6 @@ static const char *print_input_filename;
static const AVInputFormat *iformat = NULL;
static const char *output_filename = NULL;
-static struct AVHashContext *hash;
-
-static const struct {
- double bin_val;
- double dec_val;
- const char *bin_str;
- const char *dec_str;
-} si_prefixes[] = {
- { 1.0, 1.0, "", "" },
- { 1.024e3, 1e3, "Ki", "K" },
- { 1.048576e6, 1e6, "Mi", "M" },
- { 1.073741824e9, 1e9, "Gi", "G" },
- { 1.099511627776e12, 1e12, "Ti", "T" },
- { 1.125899906842624e15, 1e15, "Pi", "P" },
-};
-
static const char unit_second_str[] = "s" ;
static const char unit_hertz_str[] = "Hz" ;
static const char unit_byte_str[] = "byte" ;
@@ -441,1554 +408,11 @@ static void log_callback(void *ptr, int level, const char *fmt, va_list vl)
#endif
}
-struct unit_value {
- union { double d; int64_t i; } val;
- const char *unit;
-};
-
-static char *value_string(char *buf, int buf_size, struct unit_value uv)
-{
- double vald;
- int64_t vali;
- int show_float = 0;
-
- if (uv.unit == unit_second_str) {
- vald = uv.val.d;
- show_float = 1;
- } else {
- vald = vali = uv.val.i;
- }
-
- if (uv.unit == unit_second_str && use_value_sexagesimal_format) {
- double secs;
- int hours, mins;
- secs = vald;
- mins = (int)secs / 60;
- secs = secs - mins * 60;
- hours = mins / 60;
- mins %= 60;
- snprintf(buf, buf_size, "%d:%02d:%09.6f", hours, mins, secs);
- } else {
- const char *prefix_string = "";
-
- if (use_value_prefix && vald > 1) {
- int64_t index;
-
- if (uv.unit == unit_byte_str && use_byte_value_binary_prefix) {
- index = (int64_t) (log2(vald)) / 10;
- index = av_clip(index, 0, FF_ARRAY_ELEMS(si_prefixes) - 1);
- vald /= si_prefixes[index].bin_val;
- prefix_string = si_prefixes[index].bin_str;
- } else {
- index = (int64_t) (log10(vald)) / 3;
- index = av_clip(index, 0, FF_ARRAY_ELEMS(si_prefixes) - 1);
- vald /= si_prefixes[index].dec_val;
- prefix_string = si_prefixes[index].dec_str;
- }
- vali = vald;
- }
-
- if (show_float || (use_value_prefix && vald != (int64_t)vald))
- snprintf(buf, buf_size, "%f", vald);
- else
- snprintf(buf, buf_size, "%"PRId64, vali);
- av_strlcatf(buf, buf_size, "%s%s%s", *prefix_string || show_value_unit ? " " : "",
- prefix_string, show_value_unit ? uv.unit : "");
- }
-
- return buf;
-}
-
-/* WRITERS API */
-
-typedef struct WriterContext WriterContext;
-
-#define WRITER_FLAG_DISPLAY_OPTIONAL_FIELDS 1
-#define WRITER_FLAG_PUT_PACKETS_AND_FRAMES_IN_SAME_CHAPTER 2
-
-typedef enum {
- WRITER_STRING_VALIDATION_FAIL,
- WRITER_STRING_VALIDATION_REPLACE,
- WRITER_STRING_VALIDATION_IGNORE,
- WRITER_STRING_VALIDATION_NB
-} StringValidation;
-
-typedef struct Writer {
- const AVClass *priv_class; ///< private class of the writer, if any
- int priv_size; ///< private size for the writer context
- const char *name;
-
- int (*init) (WriterContext *wctx);
- void (*uninit)(WriterContext *wctx);
-
- void (*print_section_header)(WriterContext *wctx, const void *data);
- void (*print_section_footer)(WriterContext *wctx);
- void (*print_integer) (WriterContext *wctx, const char *, int64_t);
- void (*print_rational) (WriterContext *wctx, AVRational *q, char *sep);
- void (*print_string) (WriterContext *wctx, const char *, const char *);
- int flags; ///< a combination or WRITER_FLAG_*
-} Writer;
-
-#define SECTION_MAX_NB_LEVELS 12
-
-struct WriterContext {
- const AVClass *class; ///< class of the writer
- const Writer *writer; ///< the Writer of which this is an instance
- AVIOContext *avio; ///< the I/O context used to write
-
- void (* writer_w8)(WriterContext *wctx, int b);
- void (* writer_put_str)(WriterContext *wctx, const char *str);
- void (* writer_printf)(WriterContext *wctx, const char *fmt, ...);
-
- char *name; ///< name of this writer instance
- void *priv; ///< private data for use by the filter
-
- const struct section *sections; ///< array containing all sections
- int nb_sections; ///< number of sections
-
- int level; ///< current level, starting from 0
-
- /** number of the item printed in the given section, starting from 0 */
- unsigned int nb_item[SECTION_MAX_NB_LEVELS];
-
- /** section per each level */
- const struct section *section[SECTION_MAX_NB_LEVELS];
- AVBPrint section_pbuf[SECTION_MAX_NB_LEVELS]; ///< generic print buffer dedicated to each section,
- /// used by various writers
-
- unsigned int nb_section_packet; ///< number of the packet section in case we are in "packets_and_frames" section
- unsigned int nb_section_frame; ///< number of the frame section in case we are in "packets_and_frames" section
- unsigned int nb_section_packet_frame; ///< nb_section_packet or nb_section_frame according if is_packets_and_frames
-
- int string_validation;
- char *string_validation_replacement;
- unsigned int string_validation_utf8_flags;
-};
-
-static const char *writer_get_name(void *p)
-{
- WriterContext *wctx = p;
- return wctx->writer->name;
-}
-
-#define OFFSET(x) offsetof(WriterContext, x)
-
-static const AVOption writer_options[] = {
- { "string_validation", "set string validation mode",
- OFFSET(string_validation), AV_OPT_TYPE_INT, {.i64=WRITER_STRING_VALIDATION_REPLACE}, 0, WRITER_STRING_VALIDATION_NB-1, .unit = "sv" },
- { "sv", "set string validation mode",
- OFFSET(string_validation), AV_OPT_TYPE_INT, {.i64=WRITER_STRING_VALIDATION_REPLACE}, 0, WRITER_STRING_VALIDATION_NB-1, .unit = "sv" },
- { "ignore", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = WRITER_STRING_VALIDATION_IGNORE}, .unit = "sv" },
- { "replace", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = WRITER_STRING_VALIDATION_REPLACE}, .unit = "sv" },
- { "fail", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = WRITER_STRING_VALIDATION_FAIL}, .unit = "sv" },
- { "string_validation_replacement", "set string validation replacement string", OFFSET(string_validation_replacement), AV_OPT_TYPE_STRING, {.str=""}},
- { "svr", "set string validation replacement string", OFFSET(string_validation_replacement), AV_OPT_TYPE_STRING, {.str="\xEF\xBF\xBD"}},
- { NULL }
-};
-
-static void *writer_child_next(void *obj, void *prev)
-{
- WriterContext *ctx = obj;
- if (!prev && ctx->writer && ctx->writer->priv_class && ctx->priv)
- return ctx->priv;
- return NULL;
-}
-
-static const AVClass writer_class = {
- .class_name = "Writer",
- .item_name = writer_get_name,
- .option = writer_options,
- .version = LIBAVUTIL_VERSION_INT,
- .child_next = writer_child_next,
-};
-
-static int writer_close(WriterContext **wctx)
-{
- int i;
- int ret = 0;
-
- if (!*wctx)
- return -1;
-
- if ((*wctx)->writer->uninit)
- (*wctx)->writer->uninit(*wctx);
- for (i = 0; i < SECTION_MAX_NB_LEVELS; i++)
- av_bprint_finalize(&(*wctx)->section_pbuf[i], NULL);
- if ((*wctx)->writer->priv_class)
- av_opt_free((*wctx)->priv);
- av_freep(&((*wctx)->priv));
- av_opt_free(*wctx);
- if ((*wctx)->avio) {
- avio_flush((*wctx)->avio);
- ret = avio_close((*wctx)->avio);
- }
- av_freep(wctx);
- return ret;
-}
-
-static void bprint_bytes(AVBPrint *bp, const uint8_t *ubuf, size_t ubuf_size)
-{
- int i;
- av_bprintf(bp, "0X");
- for (i = 0; i < ubuf_size; i++)
- av_bprintf(bp, "%02X", ubuf[i]);
-}
-
-static inline void writer_w8_avio(WriterContext *wctx, int b)
-{
- avio_w8(wctx->avio, b);
-}
-
-static inline void writer_put_str_avio(WriterContext *wctx, const char *str)
-{
- avio_write(wctx->avio, str, strlen(str));
-}
-
-static inline void writer_printf_avio(WriterContext *wctx, const char *fmt, ...)
-{
- va_list ap;
-
- va_start(ap, fmt);
- avio_vprintf(wctx->avio, fmt, ap);
- va_end(ap);
-}
-
-static inline void writer_w8_printf(WriterContext *wctx, int b)
-{
- printf("%c", b);
-}
-
-static inline void writer_put_str_printf(WriterContext *wctx, const char *str)
-{
- printf("%s", str);
-}
-
-static inline void writer_printf_printf(WriterContext *wctx, const char *fmt, ...)
-{
- va_list ap;
-
- va_start(ap, fmt);
- vprintf(fmt, ap);
- va_end(ap);
-}
-
-static int writer_open(WriterContext **wctx, const Writer *writer, const char *args,
- const struct section *sections, int nb_sections, const char *output)
-{
- int i, ret = 0;
-
- if (!(*wctx = av_mallocz(sizeof(WriterContext)))) {
- ret = AVERROR(ENOMEM);
- goto fail;
- }
-
- if (!((*wctx)->priv = av_mallocz(writer->priv_size))) {
- ret = AVERROR(ENOMEM);
- goto fail;
- }
-
- (*wctx)->class = &writer_class;
- (*wctx)->writer = writer;
- (*wctx)->level = -1;
- (*wctx)->sections = sections;
- (*wctx)->nb_sections = nb_sections;
-
- av_opt_set_defaults(*wctx);
-
- if (writer->priv_class) {
- void *priv_ctx = (*wctx)->priv;
- *((const AVClass **)priv_ctx) = writer->priv_class;
- av_opt_set_defaults(priv_ctx);
- }
-
- /* convert options to dictionary */
- if (args) {
- AVDictionary *opts = NULL;
- const AVDictionaryEntry *opt = NULL;
-
- if ((ret = av_dict_parse_string(&opts, args, "=", ":", 0)) < 0) {
- av_log(*wctx, AV_LOG_ERROR, "Failed to parse option string '%s' provided to writer context\n", args);
- av_dict_free(&opts);
- goto fail;
- }
-
- while ((opt = av_dict_iterate(opts, opt))) {
- if ((ret = av_opt_set(*wctx, opt->key, opt->value, AV_OPT_SEARCH_CHILDREN)) < 0) {
- av_log(*wctx, AV_LOG_ERROR, "Failed to set option '%s' with value '%s' provided to writer context\n",
- opt->key, opt->value);
- av_dict_free(&opts);
- goto fail;
- }
- }
-
- av_dict_free(&opts);
- }
-
- /* validate replace string */
- {
- const uint8_t *p = (*wctx)->string_validation_replacement;
- const uint8_t *endp = p + strlen(p);
- while (*p) {
- const uint8_t *p0 = p;
- int32_t code;
- ret = av_utf8_decode(&code, &p, endp, (*wctx)->string_validation_utf8_flags);
- if (ret < 0) {
- AVBPrint bp;
- av_bprint_init(&bp, 0, AV_BPRINT_SIZE_AUTOMATIC);
- bprint_bytes(&bp, p0, p-p0),
- av_log(wctx, AV_LOG_ERROR,
- "Invalid UTF8 sequence %s found in string validation replace '%s'\n",
- bp.str, (*wctx)->string_validation_replacement);
- return ret;
- }
- }
- }
-
- if (!output_filename) {
- (*wctx)->writer_w8 = writer_w8_printf;
- (*wctx)->writer_put_str = writer_put_str_printf;
- (*wctx)->writer_printf = writer_printf_printf;
- } else {
- if ((ret = avio_open(&(*wctx)->avio, output, AVIO_FLAG_WRITE)) < 0) {
- av_log(*wctx, AV_LOG_ERROR,
- "Failed to open output '%s' with error: %s\n", output, av_err2str(ret));
- goto fail;
- }
- (*wctx)->writer_w8 = writer_w8_avio;
- (*wctx)->writer_put_str = writer_put_str_avio;
- (*wctx)->writer_printf = writer_printf_avio;
- }
-
- for (i = 0; i < SECTION_MAX_NB_LEVELS; i++)
- av_bprint_init(&(*wctx)->section_pbuf[i], 1, AV_BPRINT_SIZE_UNLIMITED);
-
- if ((*wctx)->writer->init)
- ret = (*wctx)->writer->init(*wctx);
- if (ret < 0)
- goto fail;
-
- return 0;
-
-fail:
- writer_close(wctx);
- return ret;
-}
-
-static inline void writer_print_section_header(WriterContext *wctx,
- const void *data,
- int section_id)
-{
- int parent_section_id;
- wctx->level++;
- av_assert0(wctx->level < SECTION_MAX_NB_LEVELS);
- parent_section_id = wctx->level ?
- (wctx->section[wctx->level-1])->id : SECTION_ID_NONE;
-
- wctx->nb_item[wctx->level] = 0;
- wctx->section[wctx->level] = &wctx->sections[section_id];
-
- if (section_id == SECTION_ID_PACKETS_AND_FRAMES) {
- wctx->nb_section_packet = wctx->nb_section_frame =
- wctx->nb_section_packet_frame = 0;
- } else if (parent_section_id == SECTION_ID_PACKETS_AND_FRAMES) {
- wctx->nb_section_packet_frame = section_id == SECTION_ID_PACKET ?
- wctx->nb_section_packet : wctx->nb_section_frame;
- }
-
- if (wctx->writer->print_section_header)
- wctx->writer->print_section_header(wctx, data);
-}
-
-static inline void writer_print_section_footer(WriterContext *wctx)
-{
- int section_id = wctx->section[wctx->level]->id;
- int parent_section_id = wctx->level ?
- wctx->section[wctx->level-1]->id : SECTION_ID_NONE;
-
- if (parent_section_id != SECTION_ID_NONE)
- wctx->nb_item[wctx->level-1]++;
- if (parent_section_id == SECTION_ID_PACKETS_AND_FRAMES) {
- if (section_id == SECTION_ID_PACKET) wctx->nb_section_packet++;
- else wctx->nb_section_frame++;
- }
- if (wctx->writer->print_section_footer)
- wctx->writer->print_section_footer(wctx);
- wctx->level--;
-}
-
-static inline void writer_print_integer(WriterContext *wctx,
- const char *key, int64_t val)
-{
- const struct section *section = wctx->section[wctx->level];
-
- if (section->show_all_entries || av_dict_get(section->entries_to_show, key, NULL, 0)) {
- wctx->writer->print_integer(wctx, key, val);
- wctx->nb_item[wctx->level]++;
- }
-}
-
-static inline int validate_string(WriterContext *wctx, char **dstp, const char *src)
-{
- const uint8_t *p, *endp;
- AVBPrint dstbuf;
- int invalid_chars_nb = 0, ret = 0;
-
- av_bprint_init(&dstbuf, 0, AV_BPRINT_SIZE_UNLIMITED);
-
- endp = src + strlen(src);
- for (p = src; *p;) {
- uint32_t code;
- int invalid = 0;
- const uint8_t *p0 = p;
-
- if (av_utf8_decode(&code, &p, endp, wctx->string_validation_utf8_flags) < 0) {
- AVBPrint bp;
- av_bprint_init(&bp, 0, AV_BPRINT_SIZE_AUTOMATIC);
- bprint_bytes(&bp, p0, p-p0);
- av_log(wctx, AV_LOG_DEBUG,
- "Invalid UTF-8 sequence %s found in string '%s'\n", bp.str, src);
- invalid = 1;
- }
-
- if (invalid) {
- invalid_chars_nb++;
-
- switch (wctx->string_validation) {
- case WRITER_STRING_VALIDATION_FAIL:
- av_log(wctx, AV_LOG_ERROR,
- "Invalid UTF-8 sequence found in string '%s'\n", src);
- ret = AVERROR_INVALIDDATA;
- goto end;
- break;
-
- case WRITER_STRING_VALIDATION_REPLACE:
- av_bprintf(&dstbuf, "%s", wctx->string_validation_replacement);
- break;
- }
- }
-
- if (!invalid || wctx->string_validation == WRITER_STRING_VALIDATION_IGNORE)
- av_bprint_append_data(&dstbuf, p0, p-p0);
- }
-
- if (invalid_chars_nb && wctx->string_validation == WRITER_STRING_VALIDATION_REPLACE) {
- av_log(wctx, AV_LOG_WARNING,
- "%d invalid UTF-8 sequence(s) found in string '%s', replaced with '%s'\n",
- invalid_chars_nb, src, wctx->string_validation_replacement);
- }
-
-end:
- av_bprint_finalize(&dstbuf, dstp);
- return ret;
-}
-
-#define PRINT_STRING_OPT 1
-#define PRINT_STRING_VALIDATE 2
-
-static inline int writer_print_string(WriterContext *wctx,
- const char *key, const char *val, int flags)
-{
- const struct section *section = wctx->section[wctx->level];
- int ret = 0;
-
- if (show_optional_fields == SHOW_OPTIONAL_FIELDS_NEVER ||
- (show_optional_fields == SHOW_OPTIONAL_FIELDS_AUTO
- && (flags & PRINT_STRING_OPT)
- && !(wctx->writer->flags & WRITER_FLAG_DISPLAY_OPTIONAL_FIELDS)))
- return 0;
-
- if (section->show_all_entries || av_dict_get(section->entries_to_show, key, NULL, 0)) {
- if (flags & PRINT_STRING_VALIDATE) {
- char *key1 = NULL, *val1 = NULL;
- ret = validate_string(wctx, &key1, key);
- if (ret < 0) goto end;
- ret = validate_string(wctx, &val1, val);
- if (ret < 0) goto end;
- wctx->writer->print_string(wctx, key1, val1);
- end:
- if (ret < 0) {
- av_log(wctx, AV_LOG_ERROR,
- "Invalid key=value string combination %s=%s in section %s\n",
- key, val, section->unique_name);
- }
- av_free(key1);
- av_free(val1);
- } else {
- wctx->writer->print_string(wctx, key, val);
- }
-
- wctx->nb_item[wctx->level]++;
- }
-
- return ret;
-}
-
-static inline void writer_print_rational(WriterContext *wctx,
- const char *key, AVRational q, char sep)
-{
- AVBPrint buf;
- av_bprint_init(&buf, 0, AV_BPRINT_SIZE_AUTOMATIC);
- av_bprintf(&buf, "%d%c%d", q.num, sep, q.den);
- writer_print_string(wctx, key, buf.str, 0);
-}
-
-static void writer_print_time(WriterContext *wctx, const char *key,
- int64_t ts, const AVRational *time_base, int is_duration)
-{
- char buf[128];
-
- if ((!is_duration && ts == AV_NOPTS_VALUE) || (is_duration && ts == 0)) {
- writer_print_string(wctx, key, "N/A", PRINT_STRING_OPT);
- } else {
- double d = ts * av_q2d(*time_base);
- struct unit_value uv;
- uv.val.d = d;
- uv.unit = unit_second_str;
- value_string(buf, sizeof(buf), uv);
- writer_print_string(wctx, key, buf, 0);
- }
-}
-
-static void writer_print_ts(WriterContext *wctx, const char *key, int64_t ts, int is_duration)
-{
- if ((!is_duration && ts == AV_NOPTS_VALUE) || (is_duration && ts == 0)) {
- writer_print_string(wctx, key, "N/A", PRINT_STRING_OPT);
- } else {
- writer_print_integer(wctx, key, ts);
- }
-}
-
-static void writer_print_data(WriterContext *wctx, const char *name,
- const uint8_t *data, int size)
-{
- AVBPrint bp;
- int offset = 0, l, i;
-
- av_bprint_init(&bp, 0, AV_BPRINT_SIZE_UNLIMITED);
- av_bprintf(&bp, "\n");
- while (size) {
- av_bprintf(&bp, "%08x: ", offset);
- l = FFMIN(size, 16);
- for (i = 0; i < l; i++) {
- av_bprintf(&bp, "%02x", data[i]);
- if (i & 1)
- av_bprintf(&bp, " ");
- }
- av_bprint_chars(&bp, ' ', 41 - 2 * i - i / 2);
- for (i = 0; i < l; i++)
- av_bprint_chars(&bp, data[i] - 32U < 95 ? data[i] : '.', 1);
- av_bprintf(&bp, "\n");
- offset += l;
- data += l;
- size -= l;
- }
- writer_print_string(wctx, name, bp.str, 0);
- av_bprint_finalize(&bp, NULL);
-}
-
-static void writer_print_data_hash(WriterContext *wctx, const char *name,
- const uint8_t *data, int size)
-{
- char *p, buf[AV_HASH_MAX_SIZE * 2 + 64] = { 0 };
-
- if (!hash)
- return;
- av_hash_init(hash);
- av_hash_update(hash, data, size);
- snprintf(buf, sizeof(buf), "%s:", av_hash_get_name(hash));
- p = buf + strlen(buf);
- av_hash_final_hex(hash, p, buf + sizeof(buf) - p);
- writer_print_string(wctx, name, buf, 0);
-}
-
-static void writer_print_integers(WriterContext *wctx, const char *name,
- uint8_t *data, int size, const char *format,
- int columns, int bytes, int offset_add)
-{
- AVBPrint bp;
- int offset = 0, l, i;
-
- av_bprint_init(&bp, 0, AV_BPRINT_SIZE_UNLIMITED);
- av_bprintf(&bp, "\n");
- while (size) {
- av_bprintf(&bp, "%08x: ", offset);
- l = FFMIN(size, columns);
- for (i = 0; i < l; i++) {
- if (bytes == 1) av_bprintf(&bp, format, *data);
- else if (bytes == 2) av_bprintf(&bp, format, AV_RN16(data));
- else if (bytes == 4) av_bprintf(&bp, format, AV_RN32(data));
- data += bytes;
- size --;
- }
- av_bprintf(&bp, "\n");
- offset += offset_add;
- }
- writer_print_string(wctx, name, bp.str, 0);
- av_bprint_finalize(&bp, NULL);
-}
-
-#define writer_w8(wctx_, b_) (wctx_)->writer_w8(wctx_, b_)
-#define writer_put_str(wctx_, str_) (wctx_)->writer_put_str(wctx_, str_)
-#define writer_printf(wctx_, fmt_, ...) (wctx_)->writer_printf(wctx_, fmt_, __VA_ARGS__)
-
-#define MAX_REGISTERED_WRITERS_NB 64
-
-static const Writer *registered_writers[MAX_REGISTERED_WRITERS_NB + 1];
-
-static int writer_register(const Writer *writer)
-{
- static int next_registered_writer_idx = 0;
-
- if (next_registered_writer_idx == MAX_REGISTERED_WRITERS_NB)
- return AVERROR(ENOMEM);
-
- registered_writers[next_registered_writer_idx++] = writer;
- return 0;
-}
-
-static const Writer *writer_get_by_name(const char *name)
-{
- int i;
-
- for (i = 0; registered_writers[i]; i++)
- if (!strcmp(registered_writers[i]->name, name))
- return registered_writers[i];
-
- return NULL;
-}
-
-
-/* WRITERS */
-
-#define DEFINE_WRITER_CLASS(name) \
-static const char *name##_get_name(void *ctx) \
-{ \
- return #name ; \
-} \
-static const AVClass name##_class = { \
- .class_name = #name, \
- .item_name = name##_get_name, \
- .option = name##_options \
-}
-
-/* Default output */
-
-typedef struct DefaultContext {
- const AVClass *class;
- int nokey;
- int noprint_wrappers;
- int nested_section[SECTION_MAX_NB_LEVELS];
-} DefaultContext;
-
-#undef OFFSET
-#define OFFSET(x) offsetof(DefaultContext, x)
-
-static const AVOption default_options[] = {
- { "noprint_wrappers", "do not print headers and footers", OFFSET(noprint_wrappers), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1 },
- { "nw", "do not print headers and footers", OFFSET(noprint_wrappers), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1 },
- { "nokey", "force no key printing", OFFSET(nokey), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1 },
- { "nk", "force no key printing", OFFSET(nokey), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1 },
- {NULL},
-};
-
-DEFINE_WRITER_CLASS(default);
-
-/* lame uppercasing routine, assumes the string is lower case ASCII */
-static inline char *upcase_string(char *dst, size_t dst_size, const char *src)
-{
- int i;
- for (i = 0; src[i] && i < dst_size-1; i++)
- dst[i] = av_toupper(src[i]);
- dst[i] = 0;
- return dst;
-}
-
-static void default_print_section_header(WriterContext *wctx, const void *data)
-{
- DefaultContext *def = wctx->priv;
- char buf[32];
- const struct section *section = wctx->section[wctx->level];
- const struct section *parent_section = wctx->level ?
- wctx->section[wctx->level-1] : NULL;
-
- av_bprint_clear(&wctx->section_pbuf[wctx->level]);
- if (parent_section &&
- !(parent_section->flags & (SECTION_FLAG_IS_WRAPPER|SECTION_FLAG_IS_ARRAY))) {
- def->nested_section[wctx->level] = 1;
- av_bprintf(&wctx->section_pbuf[wctx->level], "%s%s:",
- wctx->section_pbuf[wctx->level-1].str,
- upcase_string(buf, sizeof(buf),
- av_x_if_null(section->element_name, section->name)));
- }
-
- if (def->noprint_wrappers || def->nested_section[wctx->level])
- return;
-
- if (!(section->flags & (SECTION_FLAG_IS_WRAPPER|SECTION_FLAG_IS_ARRAY)))
- writer_printf(wctx, "[%s]\n", upcase_string(buf, sizeof(buf), section->name));
-}
-
-static void default_print_section_footer(WriterContext *wctx)
-{
- DefaultContext *def = wctx->priv;
- const struct section *section = wctx->section[wctx->level];
- char buf[32];
-
- if (def->noprint_wrappers || def->nested_section[wctx->level])
- return;
-
- if (!(section->flags & (SECTION_FLAG_IS_WRAPPER|SECTION_FLAG_IS_ARRAY)))
- writer_printf(wctx, "[/%s]\n", upcase_string(buf, sizeof(buf), section->name));
-}
-
-static void default_print_str(WriterContext *wctx, const char *key, const char *value)
-{
- DefaultContext *def = wctx->priv;
-
- if (!def->nokey)
- writer_printf(wctx, "%s%s=", wctx->section_pbuf[wctx->level].str, key);
- writer_printf(wctx, "%s\n", value);
-}
-
-static void default_print_int(WriterContext *wctx, const char *key, int64_t value)
-{
- DefaultContext *def = wctx->priv;
-
- if (!def->nokey)
- writer_printf(wctx, "%s%s=", wctx->section_pbuf[wctx->level].str, key);
- writer_printf(wctx, "%"PRId64"\n", value);
-}
-
-static const Writer default_writer = {
- .name = "default",
- .priv_size = sizeof(DefaultContext),
- .print_section_header = default_print_section_header,
- .print_section_footer = default_print_section_footer,
- .print_integer = default_print_int,
- .print_string = default_print_str,
- .flags = WRITER_FLAG_DISPLAY_OPTIONAL_FIELDS,
- .priv_class = &default_class,
-};
-
-/* Compact output */
-
-/**
- * Apply C-language-like string escaping.
- */
-static const char *c_escape_str(AVBPrint *dst, const char *src, const char sep, void *log_ctx)
-{
- const char *p;
-
- for (p = src; *p; p++) {
- switch (*p) {
- case '\b': av_bprintf(dst, "%s", "\\b"); break;
- case '\f': av_bprintf(dst, "%s", "\\f"); break;
- case '\n': av_bprintf(dst, "%s", "\\n"); break;
- case '\r': av_bprintf(dst, "%s", "\\r"); break;
- case '\\': av_bprintf(dst, "%s", "\\\\"); break;
- default:
- if (*p == sep)
- av_bprint_chars(dst, '\\', 1);
- av_bprint_chars(dst, *p, 1);
- }
- }
- return dst->str;
-}
-
-/**
- * Quote fields containing special characters, check RFC4180.
- */
-static const char *csv_escape_str(AVBPrint *dst, const char *src, const char sep, void *log_ctx)
-{
- char meta_chars[] = { sep, '"', '\n', '\r', '\0' };
- int needs_quoting = !!src[strcspn(src, meta_chars)];
-
- if (needs_quoting)
- av_bprint_chars(dst, '"', 1);
-
- for (; *src; src++) {
- if (*src == '"')
- av_bprint_chars(dst, '"', 1);
- av_bprint_chars(dst, *src, 1);
- }
- if (needs_quoting)
- av_bprint_chars(dst, '"', 1);
- return dst->str;
-}
-
-static const char *none_escape_str(AVBPrint *dst, const char *src, const char sep, void *log_ctx)
-{
- return src;
-}
-
-typedef struct CompactContext {
- const AVClass *class;
- char *item_sep_str;
- char item_sep;
- int nokey;
- int print_section;
- char *escape_mode_str;
- const char * (*escape_str)(AVBPrint *dst, const char *src, const char sep, void *log_ctx);
- int nested_section[SECTION_MAX_NB_LEVELS];
- int has_nested_elems[SECTION_MAX_NB_LEVELS];
- int terminate_line[SECTION_MAX_NB_LEVELS];
-} CompactContext;
-
-#undef OFFSET
-#define OFFSET(x) offsetof(CompactContext, x)
-
-static const AVOption compact_options[]= {
- {"item_sep", "set item separator", OFFSET(item_sep_str), AV_OPT_TYPE_STRING, {.str="|"}, 0, 0 },
- {"s", "set item separator", OFFSET(item_sep_str), AV_OPT_TYPE_STRING, {.str="|"}, 0, 0 },
- {"nokey", "force no key printing", OFFSET(nokey), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1 },
- {"nk", "force no key printing", OFFSET(nokey), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1 },
- {"escape", "set escape mode", OFFSET(escape_mode_str), AV_OPT_TYPE_STRING, {.str="c"}, 0, 0 },
- {"e", "set escape mode", OFFSET(escape_mode_str), AV_OPT_TYPE_STRING, {.str="c"}, 0, 0 },
- {"print_section", "print section name", OFFSET(print_section), AV_OPT_TYPE_BOOL, {.i64=1}, 0, 1 },
- {"p", "print section name", OFFSET(print_section), AV_OPT_TYPE_BOOL, {.i64=1}, 0, 1 },
- {NULL},
-};
-
-DEFINE_WRITER_CLASS(compact);
-
-static av_cold int compact_init(WriterContext *wctx)
-{
- CompactContext *compact = wctx->priv;
-
- if (strlen(compact->item_sep_str) != 1) {
- av_log(wctx, AV_LOG_ERROR, "Item separator '%s' specified, but must contain a single character\n",
- compact->item_sep_str);
- return AVERROR(EINVAL);
- }
- compact->item_sep = compact->item_sep_str[0];
-
- if (!strcmp(compact->escape_mode_str, "none")) compact->escape_str = none_escape_str;
- else if (!strcmp(compact->escape_mode_str, "c" )) compact->escape_str = c_escape_str;
- else if (!strcmp(compact->escape_mode_str, "csv" )) compact->escape_str = csv_escape_str;
- else {
- av_log(wctx, AV_LOG_ERROR, "Unknown escape mode '%s'\n", compact->escape_mode_str);
- return AVERROR(EINVAL);
- }
-
- return 0;
-}
-
-static void compact_print_section_header(WriterContext *wctx, const void *data)
-{
- CompactContext *compact = wctx->priv;
- const struct section *section = wctx->section[wctx->level];
- const struct section *parent_section = wctx->level ?
- wctx->section[wctx->level-1] : NULL;
- compact->terminate_line[wctx->level] = 1;
- compact->has_nested_elems[wctx->level] = 0;
-
- av_bprint_clear(&wctx->section_pbuf[wctx->level]);
- if (parent_section &&
- (section->flags & SECTION_FLAG_HAS_TYPE ||
- (!(section->flags & SECTION_FLAG_IS_ARRAY) &&
- !(parent_section->flags & (SECTION_FLAG_IS_WRAPPER|SECTION_FLAG_IS_ARRAY))))) {
-
- /* define a prefix for elements not contained in an array or
- in a wrapper, or for array elements with a type */
- const char *element_name = (char *)av_x_if_null(section->element_name, section->name);
- AVBPrint *section_pbuf = &wctx->section_pbuf[wctx->level];
-
- compact->nested_section[wctx->level] = 1;
- compact->has_nested_elems[wctx->level-1] = 1;
-
- av_bprintf(section_pbuf, "%s%s",
- wctx->section_pbuf[wctx->level-1].str, element_name);
-
- if (section->flags & SECTION_FLAG_HAS_TYPE) {
- // add /TYPE to prefix
- av_bprint_chars(section_pbuf, '/', 1);
-
- // normalize section type, replace special characters and lower case
- for (const char *p = section->get_type(data); *p; p++) {
- char c =
- (*p >= '0' && *p <= '9') ||
- (*p >= 'a' && *p <= 'z') ||
- (*p >= 'A' && *p <= 'Z') ? av_tolower(*p) : '_';
- av_bprint_chars(section_pbuf, c, 1);
- }
- }
- av_bprint_chars(section_pbuf, ':', 1);
-
- wctx->nb_item[wctx->level] = wctx->nb_item[wctx->level-1];
- } else {
- if (parent_section && !(parent_section->flags & (SECTION_FLAG_IS_WRAPPER|SECTION_FLAG_IS_ARRAY)) &&
- wctx->level && wctx->nb_item[wctx->level-1])
- writer_w8(wctx, compact->item_sep);
- if (compact->print_section &&
- !(section->flags & (SECTION_FLAG_IS_WRAPPER|SECTION_FLAG_IS_ARRAY)))
- writer_printf(wctx, "%s%c", section->name, compact->item_sep);
- }
-}
-
-static void compact_print_section_footer(WriterContext *wctx)
-{
- CompactContext *compact = wctx->priv;
-
- if (!compact->nested_section[wctx->level] &&
- compact->terminate_line[wctx->level] &&
- !(wctx->section[wctx->level]->flags & (SECTION_FLAG_IS_WRAPPER|SECTION_FLAG_IS_ARRAY)))
- writer_w8(wctx, '\n');
-}
-
-static void compact_print_str(WriterContext *wctx, const char *key, const char *value)
-{
- CompactContext *compact = wctx->priv;
- AVBPrint buf;
-
- if (wctx->nb_item[wctx->level]) writer_w8(wctx, compact->item_sep);
- if (!compact->nokey)
- writer_printf(wctx, "%s%s=", wctx->section_pbuf[wctx->level].str, key);
- av_bprint_init(&buf, 1, AV_BPRINT_SIZE_UNLIMITED);
- writer_put_str(wctx, compact->escape_str(&buf, value, compact->item_sep, wctx));
- av_bprint_finalize(&buf, NULL);
-}
-
-static void compact_print_int(WriterContext *wctx, const char *key, int64_t value)
-{
- CompactContext *compact = wctx->priv;
-
- if (wctx->nb_item[wctx->level]) writer_w8(wctx, compact->item_sep);
- if (!compact->nokey)
- writer_printf(wctx, "%s%s=", wctx->section_pbuf[wctx->level].str, key);
- writer_printf(wctx, "%"PRId64, value);
-}
-
-static const Writer compact_writer = {
- .name = "compact",
- .priv_size = sizeof(CompactContext),
- .init = compact_init,
- .print_section_header = compact_print_section_header,
- .print_section_footer = compact_print_section_footer,
- .print_integer = compact_print_int,
- .print_string = compact_print_str,
- .flags = WRITER_FLAG_DISPLAY_OPTIONAL_FIELDS,
- .priv_class = &compact_class,
-};
-
-/* CSV output */
-
-#undef OFFSET
-#define OFFSET(x) offsetof(CompactContext, x)
-
-static const AVOption csv_options[] = {
- {"item_sep", "set item separator", OFFSET(item_sep_str), AV_OPT_TYPE_STRING, {.str=","}, 0, 0 },
- {"s", "set item separator", OFFSET(item_sep_str), AV_OPT_TYPE_STRING, {.str=","}, 0, 0 },
- {"nokey", "force no key printing", OFFSET(nokey), AV_OPT_TYPE_BOOL, {.i64=1}, 0, 1 },
- {"nk", "force no key printing", OFFSET(nokey), AV_OPT_TYPE_BOOL, {.i64=1}, 0, 1 },
- {"escape", "set escape mode", OFFSET(escape_mode_str), AV_OPT_TYPE_STRING, {.str="csv"}, 0, 0 },
- {"e", "set escape mode", OFFSET(escape_mode_str), AV_OPT_TYPE_STRING, {.str="csv"}, 0, 0 },
- {"print_section", "print section name", OFFSET(print_section), AV_OPT_TYPE_BOOL, {.i64=1}, 0, 1 },
- {"p", "print section name", OFFSET(print_section), AV_OPT_TYPE_BOOL, {.i64=1}, 0, 1 },
- {NULL},
-};
-
-DEFINE_WRITER_CLASS(csv);
-
-static const Writer csv_writer = {
- .name = "csv",
- .priv_size = sizeof(CompactContext),
- .init = compact_init,
- .print_section_header = compact_print_section_header,
- .print_section_footer = compact_print_section_footer,
- .print_integer = compact_print_int,
- .print_string = compact_print_str,
- .flags = WRITER_FLAG_DISPLAY_OPTIONAL_FIELDS,
- .priv_class = &csv_class,
-};
-
-/* Flat output */
-
-typedef struct FlatContext {
- const AVClass *class;
- const char *sep_str;
- char sep;
- int hierarchical;
-} FlatContext;
-
-#undef OFFSET
-#define OFFSET(x) offsetof(FlatContext, x)
-
-static const AVOption flat_options[]= {
- {"sep_char", "set separator", OFFSET(sep_str), AV_OPT_TYPE_STRING, {.str="."}, 0, 0 },
- {"s", "set separator", OFFSET(sep_str), AV_OPT_TYPE_STRING, {.str="."}, 0, 0 },
- {"hierarchical", "specify if the section specification should be hierarchical", OFFSET(hierarchical), AV_OPT_TYPE_BOOL, {.i64=1}, 0, 1 },
- {"h", "specify if the section specification should be hierarchical", OFFSET(hierarchical), AV_OPT_TYPE_BOOL, {.i64=1}, 0, 1 },
- {NULL},
-};
-
-DEFINE_WRITER_CLASS(flat);
-
-static av_cold int flat_init(WriterContext *wctx)
-{
- FlatContext *flat = wctx->priv;
-
- if (strlen(flat->sep_str) != 1) {
- av_log(wctx, AV_LOG_ERROR, "Item separator '%s' specified, but must contain a single character\n",
- flat->sep_str);
- return AVERROR(EINVAL);
- }
- flat->sep = flat->sep_str[0];
-
- return 0;
-}
-
-static const char *flat_escape_key_str(AVBPrint *dst, const char *src, const char sep)
-{
- const char *p;
-
- for (p = src; *p; p++) {
- if (!((*p >= '0' && *p <= '9') ||
- (*p >= 'a' && *p <= 'z') ||
- (*p >= 'A' && *p <= 'Z')))
- av_bprint_chars(dst, '_', 1);
- else
- av_bprint_chars(dst, *p, 1);
- }
- return dst->str;
-}
-
-static const char *flat_escape_value_str(AVBPrint *dst, const char *src)
-{
- const char *p;
-
- for (p = src; *p; p++) {
- switch (*p) {
- case '\n': av_bprintf(dst, "%s", "\\n"); break;
- case '\r': av_bprintf(dst, "%s", "\\r"); break;
- case '\\': av_bprintf(dst, "%s", "\\\\"); break;
- case '"': av_bprintf(dst, "%s", "\\\""); break;
- case '`': av_bprintf(dst, "%s", "\\`"); break;
- case '$': av_bprintf(dst, "%s", "\\$"); break;
- default: av_bprint_chars(dst, *p, 1); break;
- }
- }
- return dst->str;
-}
-
-static void flat_print_section_header(WriterContext *wctx, const void *data)
-{
- FlatContext *flat = wctx->priv;
- AVBPrint *buf = &wctx->section_pbuf[wctx->level];
- const struct section *section = wctx->section[wctx->level];
- const struct section *parent_section = wctx->level ?
- wctx->section[wctx->level-1] : NULL;
-
- /* build section header */
- av_bprint_clear(buf);
- if (!parent_section)
- return;
- av_bprintf(buf, "%s", wctx->section_pbuf[wctx->level-1].str);
-
- if (flat->hierarchical ||
- !(section->flags & (SECTION_FLAG_IS_ARRAY|SECTION_FLAG_IS_WRAPPER))) {
- av_bprintf(buf, "%s%s", wctx->section[wctx->level]->name, flat->sep_str);
-
- if (parent_section->flags & SECTION_FLAG_IS_ARRAY) {
- int n = parent_section->id == SECTION_ID_PACKETS_AND_FRAMES ?
- wctx->nb_section_packet_frame : wctx->nb_item[wctx->level-1];
- av_bprintf(buf, "%d%s", n, flat->sep_str);
- }
- }
-}
-
-static void flat_print_int(WriterContext *wctx, const char *key, int64_t value)
-{
- writer_printf(wctx, "%s%s=%"PRId64"\n", wctx->section_pbuf[wctx->level].str, key, value);
-}
-
-static void flat_print_str(WriterContext *wctx, const char *key, const char *value)
-{
- FlatContext *flat = wctx->priv;
- AVBPrint buf;
-
- writer_put_str(wctx, wctx->section_pbuf[wctx->level].str);
- av_bprint_init(&buf, 1, AV_BPRINT_SIZE_UNLIMITED);
- writer_printf(wctx, "%s=", flat_escape_key_str(&buf, key, flat->sep));
- av_bprint_clear(&buf);
- writer_printf(wctx, "\"%s\"\n", flat_escape_value_str(&buf, value));
- av_bprint_finalize(&buf, NULL);
-}
-
-static const Writer flat_writer = {
- .name = "flat",
- .priv_size = sizeof(FlatContext),
- .init = flat_init,
- .print_section_header = flat_print_section_header,
- .print_integer = flat_print_int,
- .print_string = flat_print_str,
- .flags = WRITER_FLAG_DISPLAY_OPTIONAL_FIELDS|WRITER_FLAG_PUT_PACKETS_AND_FRAMES_IN_SAME_CHAPTER,
- .priv_class = &flat_class,
-};
-
-/* INI format output */
-
-typedef struct INIContext {
- const AVClass *class;
- int hierarchical;
-} INIContext;
-
-#undef OFFSET
-#define OFFSET(x) offsetof(INIContext, x)
-
-static const AVOption ini_options[] = {
- {"hierarchical", "specify if the section specification should be hierarchical", OFFSET(hierarchical), AV_OPT_TYPE_BOOL, {.i64=1}, 0, 1 },
- {"h", "specify if the section specification should be hierarchical", OFFSET(hierarchical), AV_OPT_TYPE_BOOL, {.i64=1}, 0, 1 },
- {NULL},
-};
-
-DEFINE_WRITER_CLASS(ini);
-
-static char *ini_escape_str(AVBPrint *dst, const char *src)
-{
- int i = 0;
- char c = 0;
-
- while (c = src[i++]) {
- switch (c) {
- case '\b': av_bprintf(dst, "%s", "\\b"); break;
- case '\f': av_bprintf(dst, "%s", "\\f"); break;
- case '\n': av_bprintf(dst, "%s", "\\n"); break;
- case '\r': av_bprintf(dst, "%s", "\\r"); break;
- case '\t': av_bprintf(dst, "%s", "\\t"); break;
- case '\\':
- case '#' :
- case '=' :
- case ':' : av_bprint_chars(dst, '\\', 1);
- default:
- if ((unsigned char)c < 32)
- av_bprintf(dst, "\\x00%02x", c & 0xff);
- else
- av_bprint_chars(dst, c, 1);
- break;
- }
- }
- return dst->str;
-}
-
-static void ini_print_section_header(WriterContext *wctx, const void *data)
-{
- INIContext *ini = wctx->priv;
- AVBPrint *buf = &wctx->section_pbuf[wctx->level];
- const struct section *section = wctx->section[wctx->level];
- const struct section *parent_section = wctx->level ?
- wctx->section[wctx->level-1] : NULL;
-
- av_bprint_clear(buf);
- if (!parent_section) {
- writer_put_str(wctx, "# ffprobe output\n\n");
- return;
- }
-
- if (wctx->nb_item[wctx->level-1])
- writer_w8(wctx, '\n');
-
- av_bprintf(buf, "%s", wctx->section_pbuf[wctx->level-1].str);
- if (ini->hierarchical ||
- !(section->flags & (SECTION_FLAG_IS_ARRAY|SECTION_FLAG_IS_WRAPPER))) {
- av_bprintf(buf, "%s%s", buf->str[0] ? "." : "", wctx->section[wctx->level]->name);
-
- if (parent_section->flags & SECTION_FLAG_IS_ARRAY) {
- int n = parent_section->id == SECTION_ID_PACKETS_AND_FRAMES ?
- wctx->nb_section_packet_frame : wctx->nb_item[wctx->level-1];
- av_bprintf(buf, ".%d", n);
- }
- }
-
- if (!(section->flags & (SECTION_FLAG_IS_ARRAY|SECTION_FLAG_IS_WRAPPER)))
- writer_printf(wctx, "[%s]\n", buf->str);
-}
-
-static void ini_print_str(WriterContext *wctx, const char *key, const char *value)
-{
- AVBPrint buf;
-
- av_bprint_init(&buf, 1, AV_BPRINT_SIZE_UNLIMITED);
- writer_printf(wctx, "%s=", ini_escape_str(&buf, key));
- av_bprint_clear(&buf);
- writer_printf(wctx, "%s\n", ini_escape_str(&buf, value));
- av_bprint_finalize(&buf, NULL);
-}
-
-static void ini_print_int(WriterContext *wctx, const char *key, int64_t value)
-{
- writer_printf(wctx, "%s=%"PRId64"\n", key, value);
-}
-
-static const Writer ini_writer = {
- .name = "ini",
- .priv_size = sizeof(INIContext),
- .print_section_header = ini_print_section_header,
- .print_integer = ini_print_int,
- .print_string = ini_print_str,
- .flags = WRITER_FLAG_DISPLAY_OPTIONAL_FIELDS|WRITER_FLAG_PUT_PACKETS_AND_FRAMES_IN_SAME_CHAPTER,
- .priv_class = &ini_class,
-};
-
-/* JSON output */
-
-typedef struct JSONContext {
- const AVClass *class;
- int indent_level;
- int compact;
- const char *item_sep, *item_start_end;
-} JSONContext;
-
-#undef OFFSET
-#define OFFSET(x) offsetof(JSONContext, x)
-
-static const AVOption json_options[]= {
- { "compact", "enable compact output", OFFSET(compact), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1 },
- { "c", "enable compact output", OFFSET(compact), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1 },
- { NULL }
-};
-
-DEFINE_WRITER_CLASS(json);
-
-static av_cold int json_init(WriterContext *wctx)
-{
- JSONContext *json = wctx->priv;
-
- json->item_sep = json->compact ? ", " : ",\n";
- json->item_start_end = json->compact ? " " : "\n";
-
- return 0;
-}
-
-static const char *json_escape_str(AVBPrint *dst, const char *src, void *log_ctx)
-{
- static const char json_escape[] = {'"', '\\', '\b', '\f', '\n', '\r', '\t', 0};
- static const char json_subst[] = {'"', '\\', 'b', 'f', 'n', 'r', 't', 0};
- const char *p;
-
- for (p = src; *p; p++) {
- char *s = strchr(json_escape, *p);
- if (s) {
- av_bprint_chars(dst, '\\', 1);
- av_bprint_chars(dst, json_subst[s - json_escape], 1);
- } else if ((unsigned char)*p < 32) {
- av_bprintf(dst, "\\u00%02x", *p & 0xff);
- } else {
- av_bprint_chars(dst, *p, 1);
- }
- }
- return dst->str;
-}
-
-#define JSON_INDENT() writer_printf(wctx, "%*c", json->indent_level * 4, ' ')
-
-static void json_print_section_header(WriterContext *wctx, const void *data)
-{
- JSONContext *json = wctx->priv;
- AVBPrint buf;
- const struct section *section = wctx->section[wctx->level];
- const struct section *parent_section = wctx->level ?
- wctx->section[wctx->level-1] : NULL;
-
- if (wctx->level && wctx->nb_item[wctx->level-1])
- writer_put_str(wctx, ",\n");
-
- if (section->flags & SECTION_FLAG_IS_WRAPPER) {
- writer_put_str(wctx, "{\n");
- json->indent_level++;
- } else {
- av_bprint_init(&buf, 1, AV_BPRINT_SIZE_UNLIMITED);
- json_escape_str(&buf, section->name, wctx);
- JSON_INDENT();
-
- json->indent_level++;
- if (section->flags & SECTION_FLAG_IS_ARRAY) {
- writer_printf(wctx, "\"%s\": [\n", buf.str);
- } else if (parent_section && !(parent_section->flags & SECTION_FLAG_IS_ARRAY)) {
- writer_printf(wctx, "\"%s\": {%s", buf.str, json->item_start_end);
- } else {
- writer_printf(wctx, "{%s", json->item_start_end);
-
- /* this is required so the parser can distinguish between packets and frames */
- if (parent_section && parent_section->id == SECTION_ID_PACKETS_AND_FRAMES) {
- if (!json->compact)
- JSON_INDENT();
- writer_printf(wctx, "\"type\": \"%s\"", section->name);
- wctx->nb_item[wctx->level]++;
- }
- }
- av_bprint_finalize(&buf, NULL);
- }
-}
-
-static void json_print_section_footer(WriterContext *wctx)
-{
- JSONContext *json = wctx->priv;
- const struct section *section = wctx->section[wctx->level];
-
- if (wctx->level == 0) {
- json->indent_level--;
- writer_put_str(wctx, "\n}\n");
- } else if (section->flags & SECTION_FLAG_IS_ARRAY) {
- writer_w8(wctx, '\n');
- json->indent_level--;
- JSON_INDENT();
- writer_w8(wctx, ']');
- } else {
- writer_put_str(wctx, json->item_start_end);
- json->indent_level--;
- if (!json->compact)
- JSON_INDENT();
- writer_w8(wctx, '}');
- }
-}
-
-static inline void json_print_item_str(WriterContext *wctx,
- const char *key, const char *value)
-{
- AVBPrint buf;
-
- av_bprint_init(&buf, 1, AV_BPRINT_SIZE_UNLIMITED);
- writer_printf(wctx, "\"%s\":", json_escape_str(&buf, key, wctx));
- av_bprint_clear(&buf);
- writer_printf(wctx, " \"%s\"", json_escape_str(&buf, value, wctx));
- av_bprint_finalize(&buf, NULL);
-}
-
-static void json_print_str(WriterContext *wctx, const char *key, const char *value)
-{
- JSONContext *json = wctx->priv;
- const struct section *parent_section = wctx->level ?
- wctx->section[wctx->level-1] : NULL;
-
- if (wctx->nb_item[wctx->level] || (parent_section && parent_section->id == SECTION_ID_PACKETS_AND_FRAMES))
- writer_put_str(wctx, json->item_sep);
- if (!json->compact)
- JSON_INDENT();
- json_print_item_str(wctx, key, value);
-}
-
-static void json_print_int(WriterContext *wctx, const char *key, int64_t value)
-{
- JSONContext *json = wctx->priv;
- const struct section *parent_section = wctx->level ?
- wctx->section[wctx->level-1] : NULL;
- AVBPrint buf;
-
- if (wctx->nb_item[wctx->level] || (parent_section && parent_section->id == SECTION_ID_PACKETS_AND_FRAMES))
- writer_put_str(wctx, json->item_sep);
- if (!json->compact)
- JSON_INDENT();
-
- av_bprint_init(&buf, 1, AV_BPRINT_SIZE_UNLIMITED);
- writer_printf(wctx, "\"%s\": %"PRId64, json_escape_str(&buf, key, wctx), value);
- av_bprint_finalize(&buf, NULL);
-}
-
-static const Writer json_writer = {
- .name = "json",
- .priv_size = sizeof(JSONContext),
- .init = json_init,
- .print_section_header = json_print_section_header,
- .print_section_footer = json_print_section_footer,
- .print_integer = json_print_int,
- .print_string = json_print_str,
- .flags = WRITER_FLAG_PUT_PACKETS_AND_FRAMES_IN_SAME_CHAPTER,
- .priv_class = &json_class,
-};
-
-/* XML output */
-
-typedef struct XMLContext {
- const AVClass *class;
- int within_tag;
- int indent_level;
- int fully_qualified;
- int xsd_strict;
-} XMLContext;
-
-#undef OFFSET
-#define OFFSET(x) offsetof(XMLContext, x)
-
-static const AVOption xml_options[] = {
- {"fully_qualified", "specify if the output should be fully qualified", OFFSET(fully_qualified), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1 },
- {"q", "specify if the output should be fully qualified", OFFSET(fully_qualified), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1 },
- {"xsd_strict", "ensure that the output is XSD compliant", OFFSET(xsd_strict), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1 },
- {"x", "ensure that the output is XSD compliant", OFFSET(xsd_strict), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1 },
- {NULL},
-};
-
-DEFINE_WRITER_CLASS(xml);
-
-static av_cold int xml_init(WriterContext *wctx)
-{
- XMLContext *xml = wctx->priv;
-
- if (xml->xsd_strict) {
- xml->fully_qualified = 1;
-#define CHECK_COMPLIANCE(opt, opt_name) \
- if (opt) { \
- av_log(wctx, AV_LOG_ERROR, \
- "XSD-compliant output selected but option '%s' was selected, XML output may be non-compliant.\n" \
- "You need to disable such option with '-no%s'\n", opt_name, opt_name); \
- return AVERROR(EINVAL); \
- }
- CHECK_COMPLIANCE(show_private_data, "private");
- CHECK_COMPLIANCE(show_value_unit, "unit");
- CHECK_COMPLIANCE(use_value_prefix, "prefix");
- }
-
- return 0;
-}
-
-#define XML_INDENT() writer_printf(wctx, "%*c", xml->indent_level * 4, ' ')
-
-static void xml_print_section_header(WriterContext *wctx, const void *data)
-{
- XMLContext *xml = wctx->priv;
- const struct section *section = wctx->section[wctx->level];
- const struct section *parent_section = wctx->level ?
- wctx->section[wctx->level-1] : NULL;
-
- if (wctx->level == 0) {
- const char *qual = " xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" "
- "xmlns:ffprobe=\"http://www.ffmpeg.org/schema/ffprobe\" "
- "xsi:schemaLocation=\"http://www.ffmpeg.org/schema/ffprobe ffprobe.xsd\"";
-
- writer_put_str(wctx, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
- writer_printf(wctx, "<%sffprobe%s>\n",
- xml->fully_qualified ? "ffprobe:" : "",
- xml->fully_qualified ? qual : "");
- return;
- }
-
- if (xml->within_tag) {
- xml->within_tag = 0;
- writer_put_str(wctx, ">\n");
- }
-
- if (parent_section && (parent_section->flags & SECTION_FLAG_IS_WRAPPER) &&
- wctx->level && wctx->nb_item[wctx->level-1])
- writer_w8(wctx, '\n');
- xml->indent_level++;
-
- if (section->flags & (SECTION_FLAG_IS_ARRAY|SECTION_FLAG_HAS_VARIABLE_FIELDS)) {
- XML_INDENT(); writer_printf(wctx, "<%s", section->name);
-
- if (section->flags & SECTION_FLAG_HAS_TYPE) {
- AVBPrint buf;
- av_bprint_init(&buf, 1, AV_BPRINT_SIZE_UNLIMITED);
- av_bprint_escape(&buf, section->get_type(data), NULL,
- AV_ESCAPE_MODE_XML, AV_ESCAPE_FLAG_XML_DOUBLE_QUOTES);
- writer_printf(wctx, " type=\"%s\"", buf.str);
- }
- writer_printf(wctx, ">\n", section->name);
- } else {
- XML_INDENT(); writer_printf(wctx, "<%s ", section->name);
- xml->within_tag = 1;
- }
-}
-
-static void xml_print_section_footer(WriterContext *wctx)
-{
- XMLContext *xml = wctx->priv;
- const struct section *section = wctx->section[wctx->level];
-
- if (wctx->level == 0) {
- writer_printf(wctx, "</%sffprobe>\n", xml->fully_qualified ? "ffprobe:" : "");
- } else if (xml->within_tag) {
- xml->within_tag = 0;
- writer_put_str(wctx, "/>\n");
- xml->indent_level--;
- } else {
- XML_INDENT(); writer_printf(wctx, "</%s>\n", section->name);
- xml->indent_level--;
- }
-}
-
-static void xml_print_value(WriterContext *wctx, const char *key,
- const char *str, int64_t num, const int is_int)
-{
- AVBPrint buf;
- XMLContext *xml = wctx->priv;
- const struct section *section = wctx->section[wctx->level];
-
- av_bprint_init(&buf, 1, AV_BPRINT_SIZE_UNLIMITED);
-
- if (section->flags & SECTION_FLAG_HAS_VARIABLE_FIELDS) {
- xml->indent_level++;
- XML_INDENT();
- av_bprint_escape(&buf, key, NULL,
- AV_ESCAPE_MODE_XML, AV_ESCAPE_FLAG_XML_DOUBLE_QUOTES);
- writer_printf(wctx, "<%s key=\"%s\"",
- section->element_name, buf.str);
- av_bprint_clear(&buf);
-
- if (is_int) {
- writer_printf(wctx, " value=\"%"PRId64"\"/>\n", num);
- } else {
- av_bprint_escape(&buf, str, NULL,
- AV_ESCAPE_MODE_XML, AV_ESCAPE_FLAG_XML_DOUBLE_QUOTES);
- writer_printf(wctx, " value=\"%s\"/>\n", buf.str);
- }
- xml->indent_level--;
- } else {
- if (wctx->nb_item[wctx->level])
- writer_w8(wctx, ' ');
-
- if (is_int) {
- writer_printf(wctx, "%s=\"%"PRId64"\"", key, num);
- } else {
- av_bprint_escape(&buf, str, NULL,
- AV_ESCAPE_MODE_XML, AV_ESCAPE_FLAG_XML_DOUBLE_QUOTES);
- writer_printf(wctx, "%s=\"%s\"", key, buf.str);
- }
- }
-
- av_bprint_finalize(&buf, NULL);
-}
-
-static inline void xml_print_str(WriterContext *wctx, const char *key, const char *value) {
- xml_print_value(wctx, key, value, 0, 0);
-}
-
-static void xml_print_int(WriterContext *wctx, const char *key, int64_t value)
-{
- xml_print_value(wctx, key, NULL, value, 1);
-}
-
-static Writer xml_writer = {
- .name = "xml",
- .priv_size = sizeof(XMLContext),
- .init = xml_init,
- .print_section_header = xml_print_section_header,
- .print_section_footer = xml_print_section_footer,
- .print_integer = xml_print_int,
- .print_string = xml_print_str,
- .flags = WRITER_FLAG_PUT_PACKETS_AND_FRAMES_IN_SAME_CHAPTER,
- .priv_class = &xml_class,
-};
-
-static void writer_register_all(void)
-{
- static int initialized;
-
- if (initialized)
- return;
- initialized = 1;
-
- writer_register(&default_writer);
- writer_register(&compact_writer);
- writer_register(&csv_writer);
- writer_register(&flat_writer);
- writer_register(&ini_writer);
- writer_register(&json_writer);
- writer_register(&xml_writer);
-}
#define print_fmt(k, f, ...) do { \
av_bprint_clear(&pbuf); \
av_bprintf(&pbuf, f, __VA_ARGS__); \
- writer_print_string(w, k, pbuf.str, 0); \
+ avtext_print_string(w, k, pbuf.str, 0); \
} while (0)
#define print_list_fmt(k, f, n, m, ...) do { \
@@ -2000,28 +424,19 @@ static void writer_register_all(void)
av_bprintf(&pbuf, f, __VA_ARGS__); \
} \
} \
- writer_print_string(w, k, pbuf.str, 0); \
+ avtext_print_string(w, k, pbuf.str, 0); \
} while (0)
-#define print_int(k, v) writer_print_integer(w, k, v)
-#define print_q(k, v, s) writer_print_rational(w, k, v, s)
-#define print_str(k, v) writer_print_string(w, k, v, 0)
-#define print_str_opt(k, v) writer_print_string(w, k, v, PRINT_STRING_OPT)
-#define print_str_validate(k, v) writer_print_string(w, k, v, PRINT_STRING_VALIDATE)
-#define print_time(k, v, tb) writer_print_time(w, k, v, tb, 0)
-#define print_ts(k, v) writer_print_ts(w, k, v, 0)
-#define print_duration_time(k, v, tb) writer_print_time(w, k, v, tb, 1)
-#define print_duration_ts(k, v) writer_print_ts(w, k, v, 1)
-#define print_val(k, v, u) do { \
- struct unit_value uv; \
- uv.val.i = v; \
- uv.unit = u; \
- writer_print_string(w, k, value_string(val_str, sizeof(val_str), uv), 0); \
-} while (0)
-
-#define print_section_header(s) writer_print_section_header(w, NULL, s)
-#define print_section_header_data(s, d) writer_print_section_header(w, d, s)
-#define print_section_footer(s) writer_print_section_footer(w, s)
+#define print_int(k, v) avtext_print_integer(w, k, v)
+#define print_q(k, v, s) avtext_print_rational(w, k, v, s)
+#define print_str(k, v) avtext_print_string(w, k, v, 0)
+#define print_str_opt(k, v) avtext_print_string(w, k, v, AV_TEXTFORMAT_PRINT_STRING_OPTIONAL)
+#define print_str_validate(k, v) avtext_print_string(w, k, v, AV_TEXTFORMAT_PRINT_STRING_VALIDATE)
+#define print_time(k, v, tb) avtext_print_time(w, k, v, tb, 0)
+#define print_ts(k, v) avtext_print_ts(w, k, v, 0)
+#define print_duration_time(k, v, tb) avtext_print_time(w, k, v, tb, 1)
+#define print_duration_ts(k, v) avtext_print_ts(w, k, v, 1)
+#define print_val(k, v, u) avtext_print_unit_int(w, k, v, u)
#define REALLOCZ_ARRAY_STREAM(ptr, cur_n, new_n) \
{ \
@@ -2529,7 +944,7 @@ static void print_pkt_side_data(WriterContext *w,
double rotation = av_display_rotation_get((int32_t *)sd->data);
if (isnan(rotation))
rotation = 0;
- writer_print_integers(w, "displaymatrix", sd->data, 9, " %11d", 3, 4, 1);
+ avtext_print_integers(w, "displaymatrix", sd->data, 9, " %11d", 3, 4, 1);
print_int("rotation", rotation);
} else if (sd->type == AV_PKT_DATA_STEREO3D) {
const AVStereo3D *stereo = (AVStereo3D *)sd->data;
@@ -2626,8 +1041,8 @@ static void print_pkt_side_data(WriterContext *w,
} else if (sd->type == AV_PKT_DATA_WEBVTT_IDENTIFIER ||
sd->type == AV_PKT_DATA_WEBVTT_SETTINGS) {
if (do_show_data)
- writer_print_data(w, "data", sd->data, sd->size);
- writer_print_data_hash(w, "data_hash", sd->data, sd->size);
+ avtext_print_data(w, "data", sd->data, sd->size);
+ avtext_print_data_hash(w, "data_hash", sd->data, sd->size);
} else if (sd->type == AV_PKT_DATA_FRAME_CROPPING && sd->size >= sizeof(uint32_t) * 4) {
print_int("crop_top", AV_RL32(sd->data));
print_int("crop_bottom", AV_RL32(sd->data + 4));
@@ -2754,7 +1169,6 @@ static int show_log(WriterContext *w, int section_ids, int section_id, int log_l
static void show_packet(WriterContext *w, InputFile *ifile, AVPacket *pkt, int packet_idx)
{
- char val_str[128];
AVStream *st = ifile->streams[pkt->stream_index].st;
AVBPrint pbuf;
const char *s;
@@ -2780,8 +1194,8 @@ static void show_packet(WriterContext *w, InputFile *ifile, AVPacket *pkt, int p
pkt->flags & AV_PKT_FLAG_DISCARD ? 'D' : '_',
pkt->flags & AV_PKT_FLAG_CORRUPT ? 'C' : '_');
if (do_show_data)
- writer_print_data(w, "data", pkt->data, pkt->size);
- writer_print_data_hash(w, "data_hash", pkt->data, pkt->size);
+ avtext_print_data(w, "data", pkt->data, pkt->size);
+ avtext_print_data_hash(w, "data_hash", pkt->data, pkt->size);
if (pkt->side_data_elems) {
size_t size;
@@ -2850,7 +1264,7 @@ static void print_frame_side_data(WriterContext *w,
double rotation = av_display_rotation_get((int32_t *)sd->data);
if (isnan(rotation))
rotation = 0;
- writer_print_integers(w, "displaymatrix", sd->data, 9, " %11d", 3, 4, 1);
+ avtext_print_integers(w, "displaymatrix", sd->data, 9, " %11d", 3, 4, 1);
print_int("rotation", rotation);
} else if (sd->type == AV_FRAME_DATA_AFD && sd->size > 0) {
print_int("active_format", *sd->data);
@@ -3450,12 +1864,12 @@ static int show_stream(WriterContext *w, AVFormatContext *fmt_ctx, int stream_id
if (nb_streams_packets[stream_idx]) print_fmt ("nb_read_packets", "%"PRIu64, nb_streams_packets[stream_idx]);
else print_str_opt("nb_read_packets", "N/A");
if (do_show_data)
- writer_print_data(w, "extradata", par->extradata,
+ avtext_print_data(w, "extradata", par->extradata,
par->extradata_size);
if (par->extradata_size > 0) {
print_int("extradata_size", par->extradata_size);
- writer_print_data_hash(w, "extradata_hash", par->extradata,
+ avtext_print_data_hash(w, "extradata_hash", par->extradata,
par->extradata_size);
}
@@ -3829,7 +2243,6 @@ static int show_chapters(WriterContext *w, InputFile *ifile)
static int show_format(WriterContext *w, InputFile *ifile)
{
AVFormatContext *fmt_ctx = ifile->fmt_ctx;
- char val_str[128];
int64_t size = fmt_ctx->pb ? avio_size(fmt_ctx->pb) : -1;
int ret = 0;
@@ -4005,7 +2418,7 @@ static void close_input_file(InputFile *ifile)
avformat_close_input(&ifile->fmt_ctx);
}
-static int probe_file(WriterContext *wctx, const char *filename,
+static int probe_file(WriterContext *tctx, const char *filename,
const char *print_filename)
{
InputFile ifile = { 0 };
@@ -4047,40 +2460,40 @@ static int probe_file(WriterContext *wctx, const char *filename,
if (do_read_frames || do_read_packets) {
if (do_show_frames && do_show_packets &&
- wctx->writer->flags & WRITER_FLAG_PUT_PACKETS_AND_FRAMES_IN_SAME_CHAPTER)
+ tctx->formatter->flags & AV_TEXTFORMAT_FLAG_SUPPORTS_MIXED_ARRAY_CONTENT)
section_id = SECTION_ID_PACKETS_AND_FRAMES;
else if (do_show_packets && !do_show_frames)
section_id = SECTION_ID_PACKETS;
else // (!do_show_packets && do_show_frames)
section_id = SECTION_ID_FRAMES;
if (do_show_frames || do_show_packets)
- writer_print_section_header(wctx, NULL, section_id);
- ret = read_packets(wctx, &ifile);
+ writer_print_section_header(tctx, NULL, section_id);
+ ret = read_packets(tctx, &ifile);
if (do_show_frames || do_show_packets)
- writer_print_section_footer(wctx);
+ writer_print_section_footer(tctx);
CHECK_END;
}
if (do_show_programs) {
- ret = show_programs(wctx, &ifile);
+ ret = show_programs(tctx, &ifile);
CHECK_END;
}
if (do_show_stream_groups) {
- ret = show_stream_groups(wctx, &ifile);
+ ret = show_stream_groups(tctx, &ifile);
CHECK_END;
}
if (do_show_streams) {
- ret = show_streams(wctx, &ifile);
+ ret = show_streams(tctx, &ifile);
CHECK_END;
}
if (do_show_chapters) {
- ret = show_chapters(wctx, &ifile);
+ ret = show_chapters(tctx, &ifile);
CHECK_END;
}
if (do_show_format) {
- ret = show_format(wctx, &ifile);
+ ret = show_format(tctx, &ifile);
CHECK_END;
}
@@ -4229,11 +2642,11 @@ static int opt_format(void *optctx, const char *opt, const char *arg)
static inline void mark_section_show_entries(SectionID section_id,
int show_all_entries, AVDictionary *entries)
{
- struct section *section = §ions[section_id];
+ struct AVTextFormatSection *section = §ions[section_id];
section->show_all_entries = show_all_entries;
if (show_all_entries) {
- for (const SectionID *id = section->children_ids; *id != -1; id++)
+ for (const int *id = section->children_ids; *id != -1; id++)
mark_section_show_entries(*id, show_all_entries, entries);
} else {
av_dict_copy(§ion->entries_to_show, entries, 0);
@@ -4246,7 +2659,7 @@ static int match_section(const char *section_name,
int i, ret = 0;
for (i = 0; i < FF_ARRAY_ELEMS(sections); i++) {
- const struct section *section = §ions[i];
+ const struct AVTextFormatSection *section = §ions[i];
if (!strcmp(section_name, section->name) ||
(section->unique_name && !strcmp(section_name, section->unique_name))) {
av_log(NULL, AV_LOG_DEBUG,
@@ -4518,13 +2931,13 @@ static int opt_pretty(void *optctx, const char *opt, const char *arg)
static void print_section(SectionID id, int level)
{
- const SectionID *pid;
- const struct section *section = §ions[id];
+ const int *pid;
+ const struct AVTextFormatSection *section = §ions[id];
printf("%c%c%c%c",
- section->flags & SECTION_FLAG_IS_WRAPPER ? 'W' : '.',
- section->flags & SECTION_FLAG_IS_ARRAY ? 'A' : '.',
- section->flags & SECTION_FLAG_HAS_VARIABLE_FIELDS ? 'V' : '.',
- section->flags & SECTION_FLAG_HAS_TYPE ? 'T' : '.');
+ section->flags & AV_TEXTFORMAT_SECTION_FLAG_IS_WRAPPER ? 'W' : '.',
+ section->flags & AV_TEXTFORMAT_SECTION_FLAG_IS_ARRAY ? 'A' : '.',
+ section->flags & AV_TEXTFORMAT_SECTION_FLAG_HAS_VARIABLE_FIELDS ? 'V' : '.',
+ section->flags & AV_TEXTFORMAT_SECTION_FLAG_HAS_TYPE ? 'T' : '.');
printf("%*c %s", level * 4, ' ', section->name);
if (section->unique_name)
printf("/%s", section->unique_name);
@@ -4627,10 +3040,10 @@ static const OptionDef real_options[] = {
static inline int check_section_show_entries(int section_id)
{
- struct section *section = §ions[section_id];
+ struct AVTextFormatSection *section = §ions[section_id];
if (sections[section_id].show_all_entries || sections[section_id].entries_to_show)
return 1;
- for (const SectionID *id = section->children_ids; *id != -1; id++)
+ for (const int *id = section->children_ids; *id != -1; id++)
if (check_section_show_entries(*id))
return 1;
return 0;
@@ -4643,10 +3056,11 @@ static inline int check_section_show_entries(int section_id)
int main(int argc, char **argv)
{
- const Writer *w;
- WriterContext *wctx;
+ const AVTextFormatter *f;
+ WriterContext *tctx;
+ AVTextWriterContext *wctx;
char *buf;
- char *w_name = NULL, *w_args = NULL;
+ char *f_name = NULL, *f_args = NULL;
int ret, input_ret, i;
init_dynload();
@@ -4708,58 +3122,51 @@ int main(int argc, char **argv)
goto end;
}
- writer_register_all();
-
if (!output_format)
output_format = av_strdup("default");
if (!output_format) {
ret = AVERROR(ENOMEM);
goto end;
}
- w_name = av_strtok(output_format, "=", &buf);
- if (!w_name) {
+ f_name = av_strtok(output_format, "=", &buf);
+ if (!f_name) {
av_log(NULL, AV_LOG_ERROR,
"No name specified for the output format\n");
ret = AVERROR(EINVAL);
goto end;
}
- w_args = buf;
-
- if (show_data_hash) {
- if ((ret = av_hash_alloc(&hash, show_data_hash)) < 0) {
- if (ret == AVERROR(EINVAL)) {
- const char *n;
- av_log(NULL, AV_LOG_ERROR,
- "Unknown hash algorithm '%s'\nKnown algorithms:",
- show_data_hash);
- for (i = 0; (n = av_hash_names(i)); i++)
- av_log(NULL, AV_LOG_ERROR, " %s", n);
- av_log(NULL, AV_LOG_ERROR, "\n");
- }
- goto end;
- }
- }
+ f_args = buf;
- w = writer_get_by_name(w_name);
- if (!w) {
- av_log(NULL, AV_LOG_ERROR, "Unknown output format with name '%s'\n", w_name);
+ f = avtext_get_formatter_by_name(f_name);
+ if (!f) {
+ av_log(NULL, AV_LOG_ERROR, "Unknown output format with name '%s'\n", f_name);
ret = AVERROR(EINVAL);
goto end;
}
- if ((ret = writer_open(&wctx, w, w_args,
- sections, FF_ARRAY_ELEMS(sections), output_filename)) >= 0) {
- if (w == &xml_writer)
- wctx->string_validation_utf8_flags |= AV_UTF8_FLAG_EXCLUDE_XML_INVALID_CONTROL_CODES;
+ if (output_filename) {
+ ret = avtextwriter_create_file(&wctx, output_filename, 1);
+ } else
+ ret = avtextwriter_create_stdout(&wctx);
- writer_print_section_header(wctx, NULL, SECTION_ID_ROOT);
+ if (ret < 0)
+ goto end;
+
+ if ((ret = avtext_context_open(&tctx, f, wctx, f_args,
+ sections, FF_ARRAY_ELEMS(sections), show_value_unit,
+ use_value_prefix, use_byte_value_binary_prefix, use_value_sexagesimal_format,
+ show_optional_fields, show_data_hash)) >= 0) {
+ if (f == &avtextformatter_xml)
+ tctx->string_validation_utf8_flags |= AV_UTF8_FLAG_EXCLUDE_XML_INVALID_CONTROL_CODES;
+
+ writer_print_section_header(tctx, NULL, SECTION_ID_ROOT);
if (do_show_program_version)
- ffprobe_show_program_version(wctx);
+ ffprobe_show_program_version(tctx);
if (do_show_library_versions)
- ffprobe_show_library_versions(wctx);
+ ffprobe_show_library_versions(tctx);
if (do_show_pixel_formats)
- ffprobe_show_pixel_formats(wctx);
+ ffprobe_show_pixel_formats(tctx);
if (!input_filename &&
((do_show_format || do_show_programs || do_show_stream_groups || do_show_streams || do_show_chapters || do_show_packets || do_show_error) ||
@@ -4769,17 +3176,22 @@ int main(int argc, char **argv)
av_log(NULL, AV_LOG_ERROR, "Use -h to get full help or, even better, run 'man %s'.\n", program_name);
ret = AVERROR(EINVAL);
} else if (input_filename) {
- ret = probe_file(wctx, input_filename, print_input_filename);
+ ret = probe_file(tctx, input_filename, print_input_filename);
if (ret < 0 && do_show_error)
- show_error(wctx, ret);
+ show_error(tctx, ret);
}
input_ret = ret;
- writer_print_section_footer(wctx);
- ret = writer_close(&wctx);
+ avtext_print_section_footer(tctx);
+
+ ret = avtextwriter_context_close(&wctx);
+ if (ret < 0)
+ av_log(NULL, AV_LOG_ERROR, "Writing output failed (closing writer): %s\n", av_err2str(ret));
+
+ ret = avtext_context_close(&tctx);
if (ret < 0)
- av_log(NULL, AV_LOG_ERROR, "Writing output failed: %s\n", av_err2str(ret));
+ av_log(NULL, AV_LOG_ERROR, "Writing output failed (closing formatter): %s\n", av_err2str(ret));
ret = FFMIN(ret, input_ret);
}
@@ -4790,7 +3202,6 @@ end:
av_freep(&input_filename);
av_freep(&print_input_filename);
av_freep(&read_intervals);
- av_hash_freep(&hash);
uninit_opts();
for (i = 0; i < FF_ARRAY_ELEMS(sections); i++)
--
ffmpeg-codebot
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 108+ messages in thread
* Re: [FFmpeg-devel] [PATCH v8 2/4] fftools/ffprobe: Change to use textformat api
2025-03-19 17:04 ` [FFmpeg-devel] [PATCH v8 2/4] fftools/ffprobe: Change to use textformat api softworkz
@ 2025-03-22 1:22 ` Michael Niedermayer
2025-03-22 1:36 ` Soft Works
0 siblings, 1 reply; 108+ messages in thread
From: Michael Niedermayer @ 2025-03-22 1:22 UTC (permalink / raw)
To: FFmpeg development discussions and patches
[-- Attachment #1.1: Type: text/plain, Size: 3553 bytes --]
On Wed, Mar 19, 2025 at 05:04:11PM +0000, softworkz wrote:
> From: softworkz <softworkz@hotmail.com>
>
> Signed-off-by: softworkz <softworkz@hotmail.com>
> ---
> fftools/Makefile | 12 +
> fftools/ffprobe.c | 1849 ++++-----------------------------------------
> 2 files changed, 142 insertions(+), 1719 deletions(-)
seems to fail build on mingw64 (out of tree build)
make -k
CC fftools/textformat/avtextformat.o
src/fftools/textformat/avtextformat.c:672:1: fatal error: opening dependency file fftools/textformat/avtextformat.d: No such file or directory
672 | }
| ^
compilation terminated.
make: *** [src/ffbuild/common.mak:81: fftools/textformat/avtextformat.o] Error 1
CC fftools/textformat/tf_compact.o
src/fftools/textformat/tf_compact.c:282:1: fatal error: opening dependency file fftools/textformat/tf_compact.d: No such file or directory
282 | };
| ^
compilation terminated.
make: *** [src/ffbuild/common.mak:81: fftools/textformat/tf_compact.o] Error 1
CC fftools/textformat/tf_default.o
src/fftools/textformat/tf_default.c:145:1: fatal error: opening dependency file fftools/textformat/tf_default.d: No such file or directory
145 | };
| ^
compilation terminated.
make: *** [src/ffbuild/common.mak:81: fftools/textformat/tf_default.o] Error 1
CC fftools/textformat/tf_flat.o
src/fftools/textformat/tf_flat.c:174:1: fatal error: opening dependency file fftools/textformat/tf_flat.d: No such file or directory
174 | };
| ^
compilation terminated.
make: *** [src/ffbuild/common.mak:81: fftools/textformat/tf_flat.o] Error 1
CC fftools/textformat/tf_ini.o
src/fftools/textformat/tf_ini.c:160:1: fatal error: opening dependency file fftools/textformat/tf_ini.d: No such file or directory
160 | };
| ^
compilation terminated.
make: *** [src/ffbuild/common.mak:81: fftools/textformat/tf_ini.o] Error 1
CC fftools/textformat/tf_json.o
src/fftools/textformat/tf_json.c:214:1: fatal error: opening dependency file fftools/textformat/tf_json.d: No such file or directory
214 | };
| ^
compilation terminated.
make: *** [src/ffbuild/common.mak:81: fftools/textformat/tf_json.o] Error 1
CC fftools/textformat/tf_xml.o
src/fftools/textformat/tf_xml.c:220:1: fatal error: opening dependency file fftools/textformat/tf_xml.d: No such file or directory
220 | };
| ^
compilation terminated.
make: *** [src/ffbuild/common.mak:81: fftools/textformat/tf_xml.o] Error 1
CC fftools/textformat/tw_avio.o
src/fftools/textformat/tw_avio.c:129:1: fatal error: opening dependency file fftools/textformat/tw_avio.d: No such file or directory
129 | }
| ^
compilation terminated.
make: *** [src/ffbuild/common.mak:81: fftools/textformat/tw_avio.o] Error 1
CC fftools/textformat/tw_buffer.o
src/fftools/textformat/tw_buffer.c:92:1: fatal error: opening dependency file fftools/textformat/tw_buffer.d: No such file or directory
92 | }
| ^
compilation terminated.
make: *** [src/ffbuild/common.mak:81: fftools/textformat/tw_buffer.o] Error 1
CC fftools/textformat/tw_stdout.o
src/fftools/textformat/tw_stdout.c:82:1: fatal error: opening dependency file fftools/textformat/tw_stdout.d: No such file or directory
82 | }
| ^
compilation terminated.
make: *** [src/ffbuild/common.mak:81: fftools/textformat/tw_stdout.o] Error 1
make: Target 'all' not remade because of errors.
[...]
--
Michael GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB
You can kill me, but you cannot change the truth.
[-- Attachment #1.2: signature.asc --]
[-- Type: application/pgp-signature, Size: 195 bytes --]
[-- Attachment #2: Type: text/plain, Size: 251 bytes --]
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 108+ messages in thread
* Re: [FFmpeg-devel] [PATCH v8 2/4] fftools/ffprobe: Change to use textformat api
2025-03-22 1:22 ` Michael Niedermayer
@ 2025-03-22 1:36 ` Soft Works
2025-03-22 2:04 ` Soft Works
2025-03-22 17:29 ` Michael Niedermayer
0 siblings, 2 replies; 108+ messages in thread
From: Soft Works @ 2025-03-22 1:36 UTC (permalink / raw)
To: FFmpeg development discussions and patches
> -----Original Message-----
> From: ffmpeg-devel <ffmpeg-devel-bounces@ffmpeg.org> On Behalf Of
> Michael Niedermayer
> Sent: Samstag, 22. März 2025 02:23
> To: FFmpeg development discussions and patches <ffmpeg-devel@ffmpeg.org>
> Subject: Re: [FFmpeg-devel] [PATCH v8 2/4] fftools/ffprobe: Change to
> use textformat api
>
> On Wed, Mar 19, 2025 at 05:04:11PM +0000, softworkz wrote:
> > From: softworkz <softworkz@hotmail.com>
> >
> > Signed-off-by: softworkz <softworkz@hotmail.com>
> > ---
> > fftools/Makefile | 12 +
> > fftools/ffprobe.c | 1849 ++++----------------------------------------
> -
> > 2 files changed, 142 insertions(+), 1719 deletions(-)
>
> seems to fail build on mingw64 (out of tree build)
>
> make -k
> CC fftools/textformat/avtextformat.o
> src/fftools/textformat/avtextformat.c:672:1: fatal error: opening
> dependency file fftools/textformat/avtextformat.d: No such file or
> directory
> 672 | }
> | ^
> compilation terminated.
> make: *** [src/ffbuild/common.mak:81: fftools/textformat/avtextformat.o]
> Error 1
> CC fftools/textformat/tf_compact.o
> src/fftools/textformat/tf_compact.c:282:1: fatal error: opening
> dependency file fftools/textformat/tf_compact.d: No such file or
> directory
> 282 | };
> | ^
> compilation terminated.
> make: *** [src/ffbuild/common.mak:81: fftools/textformat/tf_compact.o]
> Error 1
> CC fftools/textformat/tf_default.o
> src/fftools/textformat/tf_default.c:145:1: fatal error: opening
> dependency file fftools/textformat/tf_default.d: No such file or
> directory
> 145 | };
> | ^
> compilation terminated.
> make: *** [src/ffbuild/common.mak:81: fftools/textformat/tf_default.o]
> Error 1
> CC fftools/textformat/tf_flat.o
> src/fftools/textformat/tf_flat.c:174:1: fatal error: opening dependency
> file fftools/textformat/tf_flat.d: No such file or directory
> 174 | };
> | ^
> compilation terminated.
> make: *** [src/ffbuild/common.mak:81: fftools/textformat/tf_flat.o]
> Error 1
> CC fftools/textformat/tf_ini.o
> src/fftools/textformat/tf_ini.c:160:1: fatal error: opening dependency
> file fftools/textformat/tf_ini.d: No such file or directory
> 160 | };
> | ^
> compilation terminated.
> make: *** [src/ffbuild/common.mak:81: fftools/textformat/tf_ini.o] Error
> 1
> CC fftools/textformat/tf_json.o
> src/fftools/textformat/tf_json.c:214:1: fatal error: opening dependency
> file fftools/textformat/tf_json.d: No such file or directory
> 214 | };
> | ^
> compilation terminated.
> make: *** [src/ffbuild/common.mak:81: fftools/textformat/tf_json.o]
> Error 1
> CC fftools/textformat/tf_xml.o
> src/fftools/textformat/tf_xml.c:220:1: fatal error: opening dependency
> file fftools/textformat/tf_xml.d: No such file or directory
> 220 | };
> | ^
> compilation terminated.
> make: *** [src/ffbuild/common.mak:81: fftools/textformat/tf_xml.o] Error
> 1
> CC fftools/textformat/tw_avio.o
> src/fftools/textformat/tw_avio.c:129:1: fatal error: opening dependency
> file fftools/textformat/tw_avio.d: No such file or directory
> 129 | }
> | ^
> compilation terminated.
> make: *** [src/ffbuild/common.mak:81: fftools/textformat/tw_avio.o]
> Error 1
> CC fftools/textformat/tw_buffer.o
> src/fftools/textformat/tw_buffer.c:92:1: fatal error: opening dependency
> file fftools/textformat/tw_buffer.d: No such file or directory
> 92 | }
> | ^
> compilation terminated.
> make: *** [src/ffbuild/common.mak:81: fftools/textformat/tw_buffer.o]
> Error 1
> CC fftools/textformat/tw_stdout.o
> src/fftools/textformat/tw_stdout.c:82:1: fatal error: opening dependency
> file fftools/textformat/tw_stdout.d: No such file or directory
> 82 | }
> | ^
> compilation terminated.
> make: *** [src/ffbuild/common.mak:81: fftools/textformat/tw_stdout.o]
> Error 1
> make: Target 'all' not remade because of errors.
>
Seems like the same issue as the x86_32 build.
Does it also happen when you do ./configure without cccache? (or maybe ccache --clear)
Thanks
sw
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 108+ messages in thread
* Re: [FFmpeg-devel] [PATCH v8 2/4] fftools/ffprobe: Change to use textformat api
2025-03-22 1:36 ` Soft Works
@ 2025-03-22 2:04 ` Soft Works
2025-03-22 17:29 ` Michael Niedermayer
1 sibling, 0 replies; 108+ messages in thread
From: Soft Works @ 2025-03-22 2:04 UTC (permalink / raw)
To: FFmpeg development discussions and patches
> -----Original Message-----
> From: ffmpeg-devel <ffmpeg-devel-bounces@ffmpeg.org> On Behalf Of Soft
> Works
> Sent: Samstag, 22. März 2025 02:36
> To: FFmpeg development discussions and patches <ffmpeg-devel@ffmpeg.org>
> Subject: Re: [FFmpeg-devel] [PATCH v8 2/4] fftools/ffprobe: Change to
> use textformat api
>
>
>
> > -----Original Message-----
> > From: ffmpeg-devel <ffmpeg-devel-bounces@ffmpeg.org> On Behalf Of
> > Michael Niedermayer
> > Sent: Samstag, 22. März 2025 02:23
> > To: FFmpeg development discussions and patches <ffmpeg-
> devel@ffmpeg.org>
> > Subject: Re: [FFmpeg-devel] [PATCH v8 2/4] fftools/ffprobe: Change to
> > use textformat api
> >
> > On Wed, Mar 19, 2025 at 05:04:11PM +0000, softworkz wrote:
> > > From: softworkz <softworkz@hotmail.com>
> > >
> > > Signed-off-by: softworkz <softworkz@hotmail.com>
> > > ---
> > > fftools/Makefile | 12 +
> > > fftools/ffprobe.c | 1849 ++++--------------------------------------
> --
> > -
> > > 2 files changed, 142 insertions(+), 1719 deletions(-)
> >
> > seems to fail build on mingw64 (out of tree build)
> >
> > make -k
> > CC fftools/textformat/avtextformat.o
> > src/fftools/textformat/avtextformat.c:672:1: fatal error: opening
> > dependency file fftools/textformat/avtextformat.d: No such file or
> > directory
> > 672 | }
> > | ^
> > compilation terminated.
> > make: *** [src/ffbuild/common.mak:81:
> fftools/textformat/avtextformat.o]
> > Error 1
> > CC fftools/textformat/tf_compact.o
> > src/fftools/textformat/tf_compact.c:282:1: fatal error: opening
> > dependency file fftools/textformat/tf_compact.d: No such file or
> > directory
> > 282 | };
> > | ^
> > compilation terminated.
> > make: *** [src/ffbuild/common.mak:81: fftools/textformat/tf_compact.o]
> > Error 1
> > CC fftools/textformat/tf_default.o
> > src/fftools/textformat/tf_default.c:145:1: fatal error: opening
> > dependency file fftools/textformat/tf_default.d: No such file or
> > directory
> > 145 | };
> > | ^
> > compilation terminated.
> > make: *** [src/ffbuild/common.mak:81: fftools/textformat/tf_default.o]
> > Error 1
> > CC fftools/textformat/tf_flat.o
> > src/fftools/textformat/tf_flat.c:174:1: fatal error: opening
> dependency
> > file fftools/textformat/tf_flat.d: No such file or directory
> > 174 | };
> > | ^
> > compilation terminated.
> > make: *** [src/ffbuild/common.mak:81: fftools/textformat/tf_flat.o]
> > Error 1
> > CC fftools/textformat/tf_ini.o
> > src/fftools/textformat/tf_ini.c:160:1: fatal error: opening dependency
> > file fftools/textformat/tf_ini.d: No such file or directory
> > 160 | };
> > | ^
> > compilation terminated.
> > make: *** [src/ffbuild/common.mak:81: fftools/textformat/tf_ini.o]
> Error
> > 1
> > CC fftools/textformat/tf_json.o
> > src/fftools/textformat/tf_json.c:214:1: fatal error: opening
> dependency
> > file fftools/textformat/tf_json.d: No such file or directory
> > 214 | };
> > | ^
> > compilation terminated.
> > make: *** [src/ffbuild/common.mak:81: fftools/textformat/tf_json.o]
> > Error 1
> > CC fftools/textformat/tf_xml.o
> > src/fftools/textformat/tf_xml.c:220:1: fatal error: opening dependency
> > file fftools/textformat/tf_xml.d: No such file or directory
> > 220 | };
> > | ^
> > compilation terminated.
> > make: *** [src/ffbuild/common.mak:81: fftools/textformat/tf_xml.o]
> Error
> > 1
> > CC fftools/textformat/tw_avio.o
> > src/fftools/textformat/tw_avio.c:129:1: fatal error: opening
> dependency
> > file fftools/textformat/tw_avio.d: No such file or directory
> > 129 | }
> > | ^
> > compilation terminated.
> > make: *** [src/ffbuild/common.mak:81: fftools/textformat/tw_avio.o]
> > Error 1
> > CC fftools/textformat/tw_buffer.o
> > src/fftools/textformat/tw_buffer.c:92:1: fatal error: opening
> dependency
> > file fftools/textformat/tw_buffer.d: No such file or directory
> > 92 | }
> > | ^
> > compilation terminated.
> > make: *** [src/ffbuild/common.mak:81: fftools/textformat/tw_buffer.o]
> > Error 1
> > CC fftools/textformat/tw_stdout.o
> > src/fftools/textformat/tw_stdout.c:82:1: fatal error: opening
> dependency
> > file fftools/textformat/tw_stdout.d: No such file or directory
> > 82 | }
> > | ^
> > compilation terminated.
> > make: *** [src/ffbuild/common.mak:81: fftools/textformat/tw_stdout.o]
> > Error 1
> > make: Target 'all' not remade because of errors.
> >
>
> Seems like the same issue as the x86_32 build.
> Does it also happen when you do ./configure without cccache? (or maybe
> ccache --clear)
>
>
Or does it happen because of having down-tree items in the makefile?
OBJS-ffmpeg += \
fftools/ffmpeg_dec.o \
fftools/ffmpeg_demux.o \
fftools/objpool.o \
[..]
fftools/ffmpeg_graphprint.o \
fftools/sync_queue.o \
fftools/thread_queue.o \
fftools/textformat/avtextformat.o \
fftools/textformat/tf_compact.o \
fftools/textformat/tf_default.o \
fftools/textformat/tf_flat.o \
Is it mandatory for some reason (other than clarity and modularity) to have a separate makefile in each subfolder?
Thanks
sw
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 108+ messages in thread
* Re: [FFmpeg-devel] [PATCH v8 2/4] fftools/ffprobe: Change to use textformat api
2025-03-22 1:36 ` Soft Works
2025-03-22 2:04 ` Soft Works
@ 2025-03-22 17:29 ` Michael Niedermayer
2025-03-22 23:11 ` Soft Works
1 sibling, 1 reply; 108+ messages in thread
From: Michael Niedermayer @ 2025-03-22 17:29 UTC (permalink / raw)
To: FFmpeg development discussions and patches
[-- Attachment #1.1: Type: text/plain, Size: 6280 bytes --]
Hi
On Sat, Mar 22, 2025 at 01:36:05AM +0000, Soft Works wrote:
>
>
> > -----Original Message-----
> > From: ffmpeg-devel <ffmpeg-devel-bounces@ffmpeg.org> On Behalf Of
> > Michael Niedermayer
> > Sent: Samstag, 22. März 2025 02:23
> > To: FFmpeg development discussions and patches <ffmpeg-devel@ffmpeg.org>
> > Subject: Re: [FFmpeg-devel] [PATCH v8 2/4] fftools/ffprobe: Change to
> > use textformat api
> >
> > On Wed, Mar 19, 2025 at 05:04:11PM +0000, softworkz wrote:
> > > From: softworkz <softworkz@hotmail.com>
> > >
> > > Signed-off-by: softworkz <softworkz@hotmail.com>
> > > ---
> > > fftools/Makefile | 12 +
> > > fftools/ffprobe.c | 1849 ++++----------------------------------------
> > -
> > > 2 files changed, 142 insertions(+), 1719 deletions(-)
> >
> > seems to fail build on mingw64 (out of tree build)
> >
> > make -k
> > CC fftools/textformat/avtextformat.o
> > src/fftools/textformat/avtextformat.c:672:1: fatal error: opening
> > dependency file fftools/textformat/avtextformat.d: No such file or
> > directory
> > 672 | }
> > | ^
> > compilation terminated.
> > make: *** [src/ffbuild/common.mak:81: fftools/textformat/avtextformat.o]
> > Error 1
> > CC fftools/textformat/tf_compact.o
> > src/fftools/textformat/tf_compact.c:282:1: fatal error: opening
> > dependency file fftools/textformat/tf_compact.d: No such file or
> > directory
> > 282 | };
> > | ^
> > compilation terminated.
> > make: *** [src/ffbuild/common.mak:81: fftools/textformat/tf_compact.o]
> > Error 1
> > CC fftools/textformat/tf_default.o
> > src/fftools/textformat/tf_default.c:145:1: fatal error: opening
> > dependency file fftools/textformat/tf_default.d: No such file or
> > directory
> > 145 | };
> > | ^
> > compilation terminated.
> > make: *** [src/ffbuild/common.mak:81: fftools/textformat/tf_default.o]
> > Error 1
> > CC fftools/textformat/tf_flat.o
> > src/fftools/textformat/tf_flat.c:174:1: fatal error: opening dependency
> > file fftools/textformat/tf_flat.d: No such file or directory
> > 174 | };
> > | ^
> > compilation terminated.
> > make: *** [src/ffbuild/common.mak:81: fftools/textformat/tf_flat.o]
> > Error 1
> > CC fftools/textformat/tf_ini.o
> > src/fftools/textformat/tf_ini.c:160:1: fatal error: opening dependency
> > file fftools/textformat/tf_ini.d: No such file or directory
> > 160 | };
> > | ^
> > compilation terminated.
> > make: *** [src/ffbuild/common.mak:81: fftools/textformat/tf_ini.o] Error
> > 1
> > CC fftools/textformat/tf_json.o
> > src/fftools/textformat/tf_json.c:214:1: fatal error: opening dependency
> > file fftools/textformat/tf_json.d: No such file or directory
> > 214 | };
> > | ^
> > compilation terminated.
> > make: *** [src/ffbuild/common.mak:81: fftools/textformat/tf_json.o]
> > Error 1
> > CC fftools/textformat/tf_xml.o
> > src/fftools/textformat/tf_xml.c:220:1: fatal error: opening dependency
> > file fftools/textformat/tf_xml.d: No such file or directory
> > 220 | };
> > | ^
> > compilation terminated.
> > make: *** [src/ffbuild/common.mak:81: fftools/textformat/tf_xml.o] Error
> > 1
> > CC fftools/textformat/tw_avio.o
> > src/fftools/textformat/tw_avio.c:129:1: fatal error: opening dependency
> > file fftools/textformat/tw_avio.d: No such file or directory
> > 129 | }
> > | ^
> > compilation terminated.
> > make: *** [src/ffbuild/common.mak:81: fftools/textformat/tw_avio.o]
> > Error 1
> > CC fftools/textformat/tw_buffer.o
> > src/fftools/textformat/tw_buffer.c:92:1: fatal error: opening dependency
> > file fftools/textformat/tw_buffer.d: No such file or directory
> > 92 | }
> > | ^
> > compilation terminated.
> > make: *** [src/ffbuild/common.mak:81: fftools/textformat/tw_buffer.o]
> > Error 1
> > CC fftools/textformat/tw_stdout.o
> > src/fftools/textformat/tw_stdout.c:82:1: fatal error: opening dependency
> > file fftools/textformat/tw_stdout.d: No such file or directory
> > 82 | }
> > | ^
> > compilation terminated.
> > make: *** [src/ffbuild/common.mak:81: fftools/textformat/tw_stdout.o]
> > Error 1
> > make: Target 'all' not remade because of errors.
> >
>
> Seems like the same issue as the x86_32 build.
> Does it also happen when you do ./configure without cccache? (or maybe ccache --clear)
no relation to ccache, but it happens only in out of tree builds
../configure --enable-gpl --samples=/home/michael/fate/fate-suite/ --cross-prefix=/usr/i686-linux-gnu/bin/ --cc=i686-linux-gnu-gcc-7 --arch=x86_32 --target-os=linux --enable-cross-compile --assert-level=2 --enable-gpl --enable-pthreads --enable-debug=3 && make -j32
src/fftools/textformat/tf_default.c:145:1: fatal error: opening dependency file fftools/textformat/tf_default.d: No such file or directory
};
^
compilation terminated.
make: *** [src/ffbuild/common.mak:81: fftools/textformat/tf_default.o] Error 1
make: *** Waiting for unfinished jobs....
src/fftools/textformat/tf_compact.c:282:1: fatal error: opening dependency file fftools/textformat/tf_compact.d: No such file or directory
};
^
compilation terminated.
make: *** [src/ffbuild/common.mak:81: fftools/textformat/tf_compact.o] Error 1
src/fftools/textformat/tf_flat.c:174:1: fatal error: opening dependency file fftools/textformat/tf_flat.d: No such file or directory
};
^
compilation terminated.
make: *** [src/ffbuild/common.mak:81: fftools/textformat/tf_flat.o] Error 1
src/fftools/textformat/avtextformat.c:672:1: fatal error: opening dependency file fftools/textformat/avtextformat.d: No such file or directory
}
^
compilation terminated.
make: *** [src/ffbuild/common.mak:81: fftools/textformat/avtextformat.o] Error 1
also make distclean doesnt help
this works:
./configure --enable-gpl --samples=/home/michael/fate/fate-suite/ --cross-prefix=/usr/i686-linux-gnu/bin/ --cc=i686-linux-gnu-gcc-7 --arch=x86_32 --target-os=linux --enable-cross-compile --assert-level=2 --enable-gpl --enable-pthreads --enable-debug=3 && make -j32
[...]
--
Michael GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB
Democracy is the form of government in which you can choose your dictator
[-- Attachment #1.2: signature.asc --]
[-- Type: application/pgp-signature, Size: 195 bytes --]
[-- Attachment #2: Type: text/plain, Size: 251 bytes --]
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 108+ messages in thread
* Re: [FFmpeg-devel] [PATCH v8 2/4] fftools/ffprobe: Change to use textformat api
2025-03-22 17:29 ` Michael Niedermayer
@ 2025-03-22 23:11 ` Soft Works
0 siblings, 0 replies; 108+ messages in thread
From: Soft Works @ 2025-03-22 23:11 UTC (permalink / raw)
To: FFmpeg development discussions and patches
> -----Original Message-----
> From: ffmpeg-devel <ffmpeg-devel-bounces@ffmpeg.org> On Behalf Of
> Michael Niedermayer
> Sent: Samstag, 22. März 2025 18:30
> To: FFmpeg development discussions and patches <ffmpeg-devel@ffmpeg.org>
> Subject: Re: [FFmpeg-devel] [PATCH v8 2/4] fftools/ffprobe: Change to
> use textformat api
>
> Hi
>
> On Sat, Mar 22, 2025 at 01:36:05AM +0000, Soft Works wrote:
> >
> >
> > > -----Original Message-----
> > > From: ffmpeg-devel <ffmpeg-devel-bounces@ffmpeg.org> On Behalf Of
> > > Michael Niedermayer
> > > Sent: Samstag, 22. März 2025 02:23
> > > To: FFmpeg development discussions and patches <ffmpeg-
> devel@ffmpeg.org>
> > > Subject: Re: [FFmpeg-devel] [PATCH v8 2/4] fftools/ffprobe: Change
> to
> > > use textformat api
> > >
> > > On Wed, Mar 19, 2025 at 05:04:11PM +0000, softworkz wrote:
> > > > From: softworkz <softworkz@hotmail.com>
> > > >
> > > > Signed-off-by: softworkz <softworkz@hotmail.com>
> > > > ---
> > > > fftools/Makefile | 12 +
> > > > fftools/ffprobe.c | 1849 ++++------------------------------------
> ----
> > > -
> > > > 2 files changed, 142 insertions(+), 1719 deletions(-)
> > >
> > > seems to fail build on mingw64 (out of tree build)
> > >
> > > make -k
> > > CC fftools/textformat/avtextformat.o
> > > src/fftools/textformat/avtextformat.c:672:1: fatal error: opening
> > > dependency file fftools/textformat/avtextformat.d: No such file or
> > > directory
> > > 672 | }
> > > | ^
> > > compilation terminated.
> > > make: *** [src/ffbuild/common.mak:81:
> fftools/textformat/avtextformat.o]
> > > Error 1
> > > CC fftools/textformat/tf_compact.o
> > > src/fftools/textformat/tf_compact.c:282:1: fatal error: opening
> > > dependency file fftools/textformat/tf_compact.d: No such file or
> > > directory
> > > 282 | };
> > > | ^
> > > compilation terminated.
> > > make: *** [src/ffbuild/common.mak:81:
> fftools/textformat/tf_compact.o]
> > > Error 1
> > > CC fftools/textformat/tf_default.o
> > > src/fftools/textformat/tf_default.c:145:1: fatal error: opening
> > > dependency file fftools/textformat/tf_default.d: No such file or
> > > directory
> > > 145 | };
> > > | ^
> > > compilation terminated.
> > > make: *** [src/ffbuild/common.mak:81:
> fftools/textformat/tf_default.o]
> > > Error 1
> > > CC fftools/textformat/tf_flat.o
> > > src/fftools/textformat/tf_flat.c:174:1: fatal error: opening
> dependency
> > > file fftools/textformat/tf_flat.d: No such file or directory
> > > 174 | };
> > > | ^
> > > compilation terminated.
> > > make: *** [src/ffbuild/common.mak:81: fftools/textformat/tf_flat.o]
> > > Error 1
> > > CC fftools/textformat/tf_ini.o
> > > src/fftools/textformat/tf_ini.c:160:1: fatal error: opening
> dependency
> > > file fftools/textformat/tf_ini.d: No such file or directory
> > > 160 | };
> > > | ^
> > > compilation terminated.
> > > make: *** [src/ffbuild/common.mak:81: fftools/textformat/tf_ini.o]
> Error
> > > 1
> > > CC fftools/textformat/tf_json.o
> > > src/fftools/textformat/tf_json.c:214:1: fatal error: opening
> dependency
> > > file fftools/textformat/tf_json.d: No such file or directory
> > > 214 | };
> > > | ^
> > > compilation terminated.
> > > make: *** [src/ffbuild/common.mak:81: fftools/textformat/tf_json.o]
> > > Error 1
> > > CC fftools/textformat/tf_xml.o
> > > src/fftools/textformat/tf_xml.c:220:1: fatal error: opening
> dependency
> > > file fftools/textformat/tf_xml.d: No such file or directory
> > > 220 | };
> > > | ^
> > > compilation terminated.
> > > make: *** [src/ffbuild/common.mak:81: fftools/textformat/tf_xml.o]
> Error
> > > 1
> > > CC fftools/textformat/tw_avio.o
> > > src/fftools/textformat/tw_avio.c:129:1: fatal error: opening
> dependency
> > > file fftools/textformat/tw_avio.d: No such file or directory
> > > 129 | }
> > > | ^
> > > compilation terminated.
> > > make: *** [src/ffbuild/common.mak:81: fftools/textformat/tw_avio.o]
> > > Error 1
> > > CC fftools/textformat/tw_buffer.o
> > > src/fftools/textformat/tw_buffer.c:92:1: fatal error: opening
> dependency
> > > file fftools/textformat/tw_buffer.d: No such file or directory
> > > 92 | }
> > > | ^
> > > compilation terminated.
> > > make: *** [src/ffbuild/common.mak:81:
> fftools/textformat/tw_buffer.o]
> > > Error 1
> > > CC fftools/textformat/tw_stdout.o
> > > src/fftools/textformat/tw_stdout.c:82:1: fatal error: opening
> dependency
> > > file fftools/textformat/tw_stdout.d: No such file or directory
> > > 82 | }
> > > | ^
> > > compilation terminated.
> > > make: *** [src/ffbuild/common.mak:81:
> fftools/textformat/tw_stdout.o]
> > > Error 1
> > > make: Target 'all' not remade because of errors.
> > >
> >
> > Seems like the same issue as the x86_32 build.
> > Does it also happen when you do ./configure without cccache? (or maybe
> ccache --clear)
>
> no relation to ccache, but it happens only in out of tree builds
>
> ../configure --enable-gpl --samples=/home/michael/fate/fate-suite/ --
> cross-prefix=/usr/i686-linux-gnu/bin/ --cc=i686-linux-gnu-gcc-7 --
> arch=x86_32 --target-os=linux --enable-cross-compile --assert-level=2
> --enable-gpl --enable-pthreads --enable-debug=3 && make -j32
>
> src/fftools/textformat/tf_default.c:145:1: fatal error: opening
> dependency file fftools/textformat/tf_default.d: No such file or
> directory
> };
> ^
> compilation terminated.
Ah - yes of course, it needs to create the directory first in that case.
Reproduced, fixed, new patchset coming.
Thank you very much 😊
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 108+ messages in thread
* [FFmpeg-devel] [PATCH v8 3/4] fftools/ffprobe: Rename writer_print_section_* and WriterContext
2025-03-19 17:04 ` [FFmpeg-devel] [PATCH v8 0/4] print_graphs: Complete Filtergraph Printing ffmpegagent
2025-03-19 17:04 ` [FFmpeg-devel] [PATCH v8 1/4] fftools/textformat: Extract and generalize textformat api from ffprobe.c softworkz
2025-03-19 17:04 ` [FFmpeg-devel] [PATCH v8 2/4] fftools/ffprobe: Change to use textformat api softworkz
@ 2025-03-19 17:04 ` softworkz
2025-03-19 17:04 ` [FFmpeg-devel] [PATCH v8 4/4] fftools/ffprobe: Rename AVTextFormatContext variables (w => tfc) softworkz
` (2 subsequent siblings)
5 siblings, 0 replies; 108+ messages in thread
From: softworkz @ 2025-03-19 17:04 UTC (permalink / raw)
To: ffmpeg-devel; +Cc: softworkz
From: softworkz <softworkz@hotmail.com>
separated for better clarity of the preceding commit
Signed-off-by: softworkz <softworkz@hotmail.com>
ren
---
fftools/ffprobe.c | 361 +++++++++++++++++++++++-----------------------
1 file changed, 178 insertions(+), 183 deletions(-)
diff --git a/fftools/ffprobe.c b/fftools/ffprobe.c
index f398057df7..4a90bc4824 100644
--- a/fftools/ffprobe.c
+++ b/fftools/ffprobe.c
@@ -71,11 +71,6 @@
#include "libavutil/thread.h"
-// TEMPORARY DEFINES
-#define writer_print_section_header(w, d, s) avtext_print_section_header(w, d, s)
-#define writer_print_section_footer(w) avtext_print_section_footer(w)
-#define WriterContext AVTextFormatContext
-
// attached as opaque_ref to packets/frames
typedef struct FrameData {
int64_t pkt_pos;
@@ -446,25 +441,25 @@ static void log_callback(void *ptr, int level, const char *fmt, va_list vl)
memset( (ptr) + (cur_n), 0, ((new_n) - (cur_n)) * sizeof(*(ptr)) ); \
}
-static inline int show_tags(WriterContext *w, AVDictionary *tags, int section_id)
+static inline int show_tags(AVTextFormatContext *w, AVDictionary *tags, int section_id)
{
const AVDictionaryEntry *tag = NULL;
int ret = 0;
if (!tags)
return 0;
- writer_print_section_header(w, NULL, section_id);
+ avtext_print_section_header(w, NULL, section_id);
while ((tag = av_dict_iterate(tags, tag))) {
if ((ret = print_str_validate(tag->key, tag->value)) < 0)
break;
}
- writer_print_section_footer(w);
+ avtext_print_section_footer(w);
return ret;
}
-static void print_dovi_metadata(WriterContext *w, const AVDOVIMetadata *dovi)
+static void print_dovi_metadata(AVTextFormatContext *w, const AVDOVIMetadata *dovi)
{
if (!dovi)
return;
@@ -519,15 +514,15 @@ static void print_dovi_metadata(WriterContext *w, const AVDOVIMetadata *dovi)
print_int("num_x_partitions", mapping->num_x_partitions);
print_int("num_y_partitions", mapping->num_y_partitions);
- writer_print_section_header(w, NULL, SECTION_ID_FRAME_SIDE_DATA_COMPONENT_LIST);
+ avtext_print_section_header(w, NULL, SECTION_ID_FRAME_SIDE_DATA_COMPONENT_LIST);
for (int c = 0; c < 3; c++) {
const AVDOVIReshapingCurve *curve = &mapping->curves[c];
- writer_print_section_header(w, "Reshaping curve", SECTION_ID_FRAME_SIDE_DATA_COMPONENT);
+ avtext_print_section_header(w, "Reshaping curve", SECTION_ID_FRAME_SIDE_DATA_COMPONENT);
print_list_fmt("pivots", "%"PRIu16, curve->num_pivots, 1, curve->pivots[idx]);
- writer_print_section_header(w, NULL, SECTION_ID_FRAME_SIDE_DATA_PIECE_LIST);
+ avtext_print_section_header(w, NULL, SECTION_ID_FRAME_SIDE_DATA_PIECE_LIST);
for (int i = 0; i < curve->num_pivots - 1; i++) {
AVBPrint piece_buf;
@@ -545,7 +540,7 @@ static void print_dovi_metadata(WriterContext *w, const AVDOVIMetadata *dovi)
}
av_bprintf(&piece_buf, " mapping");
- writer_print_section_header(w, piece_buf.str, SECTION_ID_FRAME_SIDE_DATA_PIECE);
+ avtext_print_section_header(w, piece_buf.str, SECTION_ID_FRAME_SIDE_DATA_PIECE);
print_int("mapping_idc", curve->mapping_idc[i]);
switch (curve->mapping_idc[i]) {
case AV_DOVI_MAPPING_POLYNOMIAL:
@@ -569,11 +564,11 @@ static void print_dovi_metadata(WriterContext *w, const AVDOVIMetadata *dovi)
}
// SECTION_ID_FRAME_SIDE_DATA_PIECE
- writer_print_section_footer(w);
+ avtext_print_section_footer(w);
}
// SECTION_ID_FRAME_SIDE_DATA_PIECE_LIST
- writer_print_section_footer(w);
+ avtext_print_section_footer(w);
if (mapping->nlq_method_idc != AV_DOVI_NLQ_NONE) {
const AVDOVINLQParams *nlq = &mapping->nlq[c];
@@ -589,11 +584,11 @@ static void print_dovi_metadata(WriterContext *w, const AVDOVIMetadata *dovi)
}
// SECTION_ID_FRAME_SIDE_DATA_COMPONENT
- writer_print_section_footer(w);
+ avtext_print_section_footer(w);
}
// SECTION_ID_FRAME_SIDE_DATA_COMPONENT_LIST
- writer_print_section_footer(w);
+ avtext_print_section_footer(w);
// color metadata
print_int("dm_metadata_id", color->dm_metadata_id);
@@ -626,7 +621,7 @@ static void print_dovi_metadata(WriterContext *w, const AVDOVIMetadata *dovi)
}
}
-static void print_dynamic_hdr10_plus(WriterContext *w, const AVDynamicHDRPlus *metadata)
+static void print_dynamic_hdr10_plus(AVTextFormatContext *w, const AVDynamicHDRPlus *metadata)
{
if (!metadata)
return;
@@ -725,7 +720,7 @@ static void print_dynamic_hdr10_plus(WriterContext *w, const AVDynamicHDRPlus *m
}
}
-static void print_dynamic_hdr_vivid(WriterContext *w, const AVDynamicHDRVivid *metadata)
+static void print_dynamic_hdr_vivid(AVTextFormatContext *w, const AVDynamicHDRVivid *metadata)
{
if (!metadata)
return;
@@ -795,7 +790,7 @@ static void print_dynamic_hdr_vivid(WriterContext *w, const AVDynamicHDRVivid *m
}
}
-static void print_ambient_viewing_environment(WriterContext *w,
+static void print_ambient_viewing_environment(AVTextFormatContext *w,
const AVAmbientViewingEnvironment *env)
{
if (!env)
@@ -806,7 +801,7 @@ static void print_ambient_viewing_environment(WriterContext *w,
print_q("ambient_light_y", env->ambient_light_y, '/');
}
-static void print_film_grain_params(WriterContext *w,
+static void print_film_grain_params(AVTextFormatContext *w,
const AVFilmGrainParams *fgp)
{
const char *color_range, *color_primaries, *color_trc, *color_space;
@@ -852,10 +847,10 @@ static void print_film_grain_params(WriterContext *w,
print_int("overlap_flag", aom->overlap_flag);
print_int("limit_output_range", aom->limit_output_range);
- writer_print_section_header(w, NULL, SECTION_ID_FRAME_SIDE_DATA_COMPONENT_LIST);
+ avtext_print_section_header(w, NULL, SECTION_ID_FRAME_SIDE_DATA_COMPONENT_LIST);
if (aom->num_y_points) {
- writer_print_section_header(w, NULL, SECTION_ID_FRAME_SIDE_DATA_COMPONENT);
+ avtext_print_section_header(w, NULL, SECTION_ID_FRAME_SIDE_DATA_COMPONENT);
print_int("bit_depth_luma", fgp->bit_depth_luma);
print_list_fmt("y_points_value", "%"PRIu8, aom->num_y_points, 1, aom->y_points[idx][0]);
@@ -863,14 +858,14 @@ static void print_film_grain_params(WriterContext *w,
print_list_fmt("ar_coeffs_y", "%"PRId8, num_ar_coeffs_y, 1, aom->ar_coeffs_y[idx]);
// SECTION_ID_FRAME_SIDE_DATA_COMPONENT
- writer_print_section_footer(w);
+ avtext_print_section_footer(w);
}
for (int uv = 0; uv < 2; uv++) {
if (!aom->num_uv_points[uv] && !aom->chroma_scaling_from_luma)
continue;
- writer_print_section_header(w, NULL, SECTION_ID_FRAME_SIDE_DATA_COMPONENT);
+ avtext_print_section_header(w, NULL, SECTION_ID_FRAME_SIDE_DATA_COMPONENT);
print_int("bit_depth_chroma", fgp->bit_depth_chroma);
print_list_fmt("uv_points_value", "%"PRIu8, aom->num_uv_points[uv], 1, aom->uv_points[uv][idx][0]);
@@ -881,11 +876,11 @@ static void print_film_grain_params(WriterContext *w,
print_int("uv_offset", aom->uv_offset[uv]);
// SECTION_ID_FRAME_SIDE_DATA_COMPONENT
- writer_print_section_footer(w);
+ avtext_print_section_footer(w);
}
// SECTION_ID_FRAME_SIDE_DATA_COMPONENT_LIST
- writer_print_section_footer(w);
+ avtext_print_section_footer(w);
break;
}
case AV_FILM_GRAIN_PARAMS_H274: {
@@ -894,36 +889,36 @@ static void print_film_grain_params(WriterContext *w,
print_int("blending_mode_id", h274->blending_mode_id);
print_int("log2_scale_factor", h274->log2_scale_factor);
- writer_print_section_header(w, NULL, SECTION_ID_FRAME_SIDE_DATA_COMPONENT_LIST);
+ avtext_print_section_header(w, NULL, SECTION_ID_FRAME_SIDE_DATA_COMPONENT_LIST);
for (int c = 0; c < 3; c++) {
if (!h274->component_model_present[c])
continue;
- writer_print_section_header(w, NULL, SECTION_ID_FRAME_SIDE_DATA_COMPONENT);
+ avtext_print_section_header(w, NULL, SECTION_ID_FRAME_SIDE_DATA_COMPONENT);
print_int(c ? "bit_depth_chroma" : "bit_depth_luma", c ? fgp->bit_depth_chroma : fgp->bit_depth_luma);
- writer_print_section_header(w, NULL, SECTION_ID_FRAME_SIDE_DATA_PIECE_LIST);
+ avtext_print_section_header(w, NULL, SECTION_ID_FRAME_SIDE_DATA_PIECE_LIST);
for (int i = 0; i < h274->num_intensity_intervals[c]; i++) {
- writer_print_section_header(w, NULL, SECTION_ID_FRAME_SIDE_DATA_PIECE);
+ avtext_print_section_header(w, NULL, SECTION_ID_FRAME_SIDE_DATA_PIECE);
print_int("intensity_interval_lower_bound", h274->intensity_interval_lower_bound[c][i]);
print_int("intensity_interval_upper_bound", h274->intensity_interval_upper_bound[c][i]);
print_list_fmt("comp_model_value", "%"PRId16, h274->num_model_values[c], 1, h274->comp_model_value[c][i][idx]);
// SECTION_ID_FRAME_SIDE_DATA_PIECE
- writer_print_section_footer(w);
+ avtext_print_section_footer(w);
}
// SECTION_ID_FRAME_SIDE_DATA_PIECE_LIST
- writer_print_section_footer(w);
+ avtext_print_section_footer(w);
// SECTION_ID_FRAME_SIDE_DATA_COMPONENT
- writer_print_section_footer(w);
+ avtext_print_section_footer(w);
}
// SECTION_ID_FRAME_SIDE_DATA_COMPONENT_LIST
- writer_print_section_footer(w);
+ avtext_print_section_footer(w);
break;
}
}
@@ -931,14 +926,14 @@ static void print_film_grain_params(WriterContext *w,
av_bprint_finalize(&pbuf, NULL);
}
-static void print_pkt_side_data(WriterContext *w,
+static void print_pkt_side_data(AVTextFormatContext *w,
AVCodecParameters *par,
const AVPacketSideData *sd,
SectionID id_data)
{
const char *name = av_packet_side_data_name(sd->type);
- writer_print_section_header(w, sd, id_data);
+ avtext_print_section_header(w, sd, id_data);
print_str("side_data_type", name ? name : "unknown");
if (sd->type == AV_PKT_DATA_DISPLAYMATRIX && sd->size >= 9*4) {
double rotation = av_display_rotation_get((int32_t *)sd->data);
@@ -1053,7 +1048,7 @@ static void print_pkt_side_data(WriterContext *w,
}
}
-static void print_private_data(WriterContext *w, void *priv_data)
+static void print_private_data(AVTextFormatContext *w, void *priv_data)
{
const AVOption *opt = NULL;
while (opt = av_opt_next(priv_data, opt)) {
@@ -1066,7 +1061,7 @@ static void print_private_data(WriterContext *w, void *priv_data)
}
}
-static void print_color_range(WriterContext *w, enum AVColorRange color_range)
+static void print_color_range(AVTextFormatContext *w, enum AVColorRange color_range)
{
const char *val = av_color_range_name(color_range);
if (!val || color_range == AVCOL_RANGE_UNSPECIFIED) {
@@ -1076,7 +1071,7 @@ static void print_color_range(WriterContext *w, enum AVColorRange color_range)
}
}
-static void print_color_space(WriterContext *w, enum AVColorSpace color_space)
+static void print_color_space(AVTextFormatContext *w, enum AVColorSpace color_space)
{
const char *val = av_color_space_name(color_space);
if (!val || color_space == AVCOL_SPC_UNSPECIFIED) {
@@ -1086,7 +1081,7 @@ static void print_color_space(WriterContext *w, enum AVColorSpace color_space)
}
}
-static void print_primaries(WriterContext *w, enum AVColorPrimaries color_primaries)
+static void print_primaries(AVTextFormatContext *w, enum AVColorPrimaries color_primaries)
{
const char *val = av_color_primaries_name(color_primaries);
if (!val || color_primaries == AVCOL_PRI_UNSPECIFIED) {
@@ -1096,7 +1091,7 @@ static void print_primaries(WriterContext *w, enum AVColorPrimaries color_primar
}
}
-static void print_color_trc(WriterContext *w, enum AVColorTransferCharacteristic color_trc)
+static void print_color_trc(AVTextFormatContext *w, enum AVColorTransferCharacteristic color_trc)
{
const char *val = av_color_transfer_name(color_trc);
if (!val || color_trc == AVCOL_TRC_UNSPECIFIED) {
@@ -1106,7 +1101,7 @@ static void print_color_trc(WriterContext *w, enum AVColorTransferCharacteristic
}
}
-static void print_chroma_location(WriterContext *w, enum AVChromaLocation chroma_location)
+static void print_chroma_location(AVTextFormatContext *w, enum AVChromaLocation chroma_location)
{
const char *val = av_chroma_location_name(chroma_location);
if (!val || chroma_location == AVCHROMA_LOC_UNSPECIFIED) {
@@ -1132,7 +1127,7 @@ static void clear_log(int need_lock)
ff_mutex_unlock(&log_mutex);
}
-static int show_log(WriterContext *w, int section_ids, int section_id, int log_level)
+static int show_log(AVTextFormatContext *w, int section_ids, int section_id, int log_level)
{
int i;
ff_mutex_lock(&log_mutex);
@@ -1140,11 +1135,11 @@ static int show_log(WriterContext *w, int section_ids, int section_id, int log_l
ff_mutex_unlock(&log_mutex);
return 0;
}
- writer_print_section_header(w, NULL, section_ids);
+ avtext_print_section_header(w, NULL, section_ids);
for (i=0; i<log_buffer_size; i++) {
if (log_buffer[i].log_level <= log_level) {
- writer_print_section_header(w, NULL, section_id);
+ avtext_print_section_header(w, NULL, section_id);
print_str("context", log_buffer[i].context_name);
print_int("level", log_buffer[i].log_level);
print_int("category", log_buffer[i].category);
@@ -1156,18 +1151,18 @@ static int show_log(WriterContext *w, int section_ids, int section_id, int log_l
print_str_opt("parent_category", "N/A");
}
print_str("message", log_buffer[i].log_message);
- writer_print_section_footer(w);
+ avtext_print_section_footer(w);
}
}
clear_log(0);
ff_mutex_unlock(&log_mutex);
- writer_print_section_footer(w);
+ avtext_print_section_footer(w);
return 0;
}
-static void show_packet(WriterContext *w, InputFile *ifile, AVPacket *pkt, int packet_idx)
+static void show_packet(AVTextFormatContext *w, InputFile *ifile, AVPacket *pkt, int packet_idx)
{
AVStream *st = ifile->streams[pkt->stream_index].st;
AVBPrint pbuf;
@@ -1175,7 +1170,7 @@ static void show_packet(WriterContext *w, InputFile *ifile, AVPacket *pkt, int p
av_bprint_init(&pbuf, 1, AV_BPRINT_SIZE_UNLIMITED);
- writer_print_section_header(w, NULL, SECTION_ID_PACKET);
+ avtext_print_section_header(w, NULL, SECTION_ID_PACKET);
s = av_get_media_type_string(st->codecpar->codec_type);
if (s) print_str ("codec_type", s);
@@ -1209,29 +1204,29 @@ static void show_packet(WriterContext *w, InputFile *ifile, AVPacket *pkt, int p
av_dict_free(&dict);
}
- writer_print_section_header(w, NULL, SECTION_ID_PACKET_SIDE_DATA_LIST);
+ avtext_print_section_header(w, NULL, SECTION_ID_PACKET_SIDE_DATA_LIST);
for (int i = 0; i < pkt->side_data_elems; i++) {
print_pkt_side_data(w, st->codecpar, &pkt->side_data[i],
SECTION_ID_PACKET_SIDE_DATA);
- writer_print_section_footer(w);
+ avtext_print_section_footer(w);
}
- writer_print_section_footer(w);
+ avtext_print_section_footer(w);
}
- writer_print_section_footer(w);
+ avtext_print_section_footer(w);
av_bprint_finalize(&pbuf, NULL);
fflush(stdout);
}
-static void show_subtitle(WriterContext *w, AVSubtitle *sub, AVStream *stream,
+static void show_subtitle(AVTextFormatContext *w, AVSubtitle *sub, AVStream *stream,
AVFormatContext *fmt_ctx)
{
AVBPrint pbuf;
av_bprint_init(&pbuf, 1, AV_BPRINT_SIZE_UNLIMITED);
- writer_print_section_header(w, NULL, SECTION_ID_SUBTITLE);
+ avtext_print_section_header(w, NULL, SECTION_ID_SUBTITLE);
print_str ("media_type", "subtitle");
print_ts ("pts", sub->pts);
@@ -1241,23 +1236,23 @@ static void show_subtitle(WriterContext *w, AVSubtitle *sub, AVStream *stream,
print_int ("end_display_time", sub->end_display_time);
print_int ("num_rects", sub->num_rects);
- writer_print_section_footer(w);
+ avtext_print_section_footer(w);
av_bprint_finalize(&pbuf, NULL);
fflush(stdout);
}
-static void print_frame_side_data(WriterContext *w,
+static void print_frame_side_data(AVTextFormatContext *w,
const AVFrame *frame,
const AVStream *stream)
{
- writer_print_section_header(w, NULL, SECTION_ID_FRAME_SIDE_DATA_LIST);
+ avtext_print_section_header(w, NULL, SECTION_ID_FRAME_SIDE_DATA_LIST);
for (int i = 0; i < frame->nb_side_data; i++) {
const AVFrameSideData *sd = frame->side_data[i];
const char *name;
- writer_print_section_header(w, sd, SECTION_ID_FRAME_SIDE_DATA);
+ avtext_print_section_header(w, sd, SECTION_ID_FRAME_SIDE_DATA);
name = av_frame_side_data_name(sd->type);
print_str("side_data_type", name ? name : "unknown");
if (sd->type == AV_FRAME_DATA_DISPLAYMATRIX && sd->size >= 9*4) {
@@ -1275,15 +1270,15 @@ static void print_frame_side_data(WriterContext *w,
} else if (sd->type == AV_FRAME_DATA_S12M_TIMECODE && sd->size == 16) {
uint32_t *tc = (uint32_t*)sd->data;
int m = FFMIN(tc[0],3);
- writer_print_section_header(w, NULL, SECTION_ID_FRAME_SIDE_DATA_TIMECODE_LIST);
+ avtext_print_section_header(w, NULL, SECTION_ID_FRAME_SIDE_DATA_TIMECODE_LIST);
for (int j = 1; j <= m ; j++) {
char tcbuf[AV_TIMECODE_STR_SIZE];
av_timecode_make_smpte_tc_string2(tcbuf, stream->avg_frame_rate, tc[j], 0, 0);
- writer_print_section_header(w, NULL, SECTION_ID_FRAME_SIDE_DATA_TIMECODE);
+ avtext_print_section_header(w, NULL, SECTION_ID_FRAME_SIDE_DATA_TIMECODE);
print_str("value", tcbuf);
- writer_print_section_footer(w);
+ avtext_print_section_footer(w);
}
- writer_print_section_footer(w);
+ avtext_print_section_footer(w);
} else if (sd->type == AV_FRAME_DATA_MASTERING_DISPLAY_METADATA) {
AVMasteringDisplayMetadata *metadata = (AVMasteringDisplayMetadata *)sd->data;
@@ -1328,12 +1323,12 @@ static void print_frame_side_data(WriterContext *w,
} else if (sd->type == AV_FRAME_DATA_VIEW_ID) {
print_int("view_id", *(int*)sd->data);
}
- writer_print_section_footer(w);
+ avtext_print_section_footer(w);
}
- writer_print_section_footer(w);
+ avtext_print_section_footer(w);
}
-static void show_frame(WriterContext *w, AVFrame *frame, AVStream *stream,
+static void show_frame(AVTextFormatContext *w, AVFrame *frame, AVStream *stream,
AVFormatContext *fmt_ctx)
{
FrameData *fd = frame->opaque_ref ? (FrameData*)frame->opaque_ref->data : NULL;
@@ -1343,7 +1338,7 @@ static void show_frame(WriterContext *w, AVFrame *frame, AVStream *stream,
av_bprint_init(&pbuf, 1, AV_BPRINT_SIZE_UNLIMITED);
- writer_print_section_header(w, NULL, SECTION_ID_FRAME);
+ avtext_print_section_header(w, NULL, SECTION_ID_FRAME);
s = av_get_media_type_string(stream->codecpar->codec_type);
if (s) print_str ("media_type", s);
@@ -1415,13 +1410,13 @@ static void show_frame(WriterContext *w, AVFrame *frame, AVStream *stream,
if (frame->nb_side_data)
print_frame_side_data(w, frame, stream);
- writer_print_section_footer(w);
+ avtext_print_section_footer(w);
av_bprint_finalize(&pbuf, NULL);
fflush(stdout);
}
-static av_always_inline int process_frame(WriterContext *w,
+static av_always_inline int process_frame(AVTextFormatContext *w,
InputFile *ifile,
AVFrame *frame, const AVPacket *pkt,
int *packet_new)
@@ -1518,7 +1513,7 @@ static void log_read_interval(const ReadInterval *interval, void *log_ctx, int l
av_log(log_ctx, log_level, "\n");
}
-static int read_interval_packets(WriterContext *w, InputFile *ifile,
+static int read_interval_packets(AVTextFormatContext *w, InputFile *ifile,
const ReadInterval *interval, int64_t *cur_ts)
{
AVFormatContext *fmt_ctx = ifile->fmt_ctx;
@@ -1643,7 +1638,7 @@ end:
return ret;
}
-static int read_packets(WriterContext *w, InputFile *ifile)
+static int read_packets(AVTextFormatContext *w, InputFile *ifile)
{
AVFormatContext *fmt_ctx = ifile->fmt_ctx;
int i, ret = 0;
@@ -1663,22 +1658,22 @@ static int read_packets(WriterContext *w, InputFile *ifile)
return ret;
}
-static void print_dispositions(WriterContext *w, uint32_t disposition, SectionID section_id)
+static void print_dispositions(AVTextFormatContext *w, uint32_t disposition, SectionID section_id)
{
- writer_print_section_header(w, NULL, section_id);
+ avtext_print_section_header(w, NULL, section_id);
for (int i = 0; i < sizeof(disposition) * CHAR_BIT; i++) {
const char *disposition_str = av_disposition_to_string(1U << i);
if (disposition_str)
print_int(disposition_str, !!(disposition & (1U << i)));
}
- writer_print_section_footer(w);
+ avtext_print_section_footer(w);
}
#define IN_PROGRAM 1
#define IN_STREAM_GROUP 2
-static int show_stream(WriterContext *w, AVFormatContext *fmt_ctx, int stream_idx, InputStream *ist, int container)
+static int show_stream(AVTextFormatContext *w, AVFormatContext *fmt_ctx, int stream_idx, InputStream *ist, int container)
{
AVStream *stream = ist->st;
AVCodecParameters *par;
@@ -1710,7 +1705,7 @@ static int show_stream(WriterContext *w, AVFormatContext *fmt_ctx, int stream_id
av_bprint_init(&pbuf, 1, AV_BPRINT_SIZE_UNLIMITED);
- writer_print_section_header(w, NULL, section_header[container]);
+ avtext_print_section_header(w, NULL, section_header[container]);
print_int("index", stream->index);
@@ -1885,45 +1880,45 @@ static int show_stream(WriterContext *w, AVFormatContext *fmt_ctx, int stream_id
}
if (stream->codecpar->nb_coded_side_data) {
- writer_print_section_header(w, NULL, SECTION_ID_STREAM_SIDE_DATA_LIST);
+ avtext_print_section_header(w, NULL, SECTION_ID_STREAM_SIDE_DATA_LIST);
for (int i = 0; i < stream->codecpar->nb_coded_side_data; i++) {
print_pkt_side_data(w, stream->codecpar, &stream->codecpar->coded_side_data[i],
SECTION_ID_STREAM_SIDE_DATA);
- writer_print_section_footer(w);
+ avtext_print_section_footer(w);
}
- writer_print_section_footer(w);
+ avtext_print_section_footer(w);
}
- writer_print_section_footer(w);
+ avtext_print_section_footer(w);
av_bprint_finalize(&pbuf, NULL);
fflush(stdout);
return ret;
}
-static int show_streams(WriterContext *w, InputFile *ifile)
+static int show_streams(AVTextFormatContext *w, InputFile *ifile)
{
AVFormatContext *fmt_ctx = ifile->fmt_ctx;
int i, ret = 0;
- writer_print_section_header(w, NULL, SECTION_ID_STREAMS);
+ avtext_print_section_header(w, NULL, SECTION_ID_STREAMS);
for (i = 0; i < ifile->nb_streams; i++)
if (selected_streams[i]) {
ret = show_stream(w, fmt_ctx, i, &ifile->streams[i], 0);
if (ret < 0)
break;
}
- writer_print_section_footer(w);
+ avtext_print_section_footer(w);
return ret;
}
-static int show_program(WriterContext *w, InputFile *ifile, AVProgram *program)
+static int show_program(AVTextFormatContext *w, InputFile *ifile, AVProgram *program)
{
AVFormatContext *fmt_ctx = ifile->fmt_ctx;
int i, ret = 0;
- writer_print_section_header(w, NULL, SECTION_ID_PROGRAM);
+ avtext_print_section_header(w, NULL, SECTION_ID_PROGRAM);
print_int("program_id", program->id);
print_int("program_num", program->program_num);
print_int("nb_streams", program->nb_stream_indexes);
@@ -1934,7 +1929,7 @@ static int show_program(WriterContext *w, InputFile *ifile, AVProgram *program)
if (ret < 0)
goto end;
- writer_print_section_header(w, NULL, SECTION_ID_PROGRAM_STREAMS);
+ avtext_print_section_header(w, NULL, SECTION_ID_PROGRAM_STREAMS);
for (i = 0; i < program->nb_stream_indexes; i++) {
if (selected_streams[program->stream_index[i]]) {
ret = show_stream(w, fmt_ctx, program->stream_index[i], &ifile->streams[program->stream_index[i]], IN_PROGRAM);
@@ -1942,19 +1937,19 @@ static int show_program(WriterContext *w, InputFile *ifile, AVProgram *program)
break;
}
}
- writer_print_section_footer(w);
+ avtext_print_section_footer(w);
end:
- writer_print_section_footer(w);
+ avtext_print_section_footer(w);
return ret;
}
-static int show_programs(WriterContext *w, InputFile *ifile)
+static int show_programs(AVTextFormatContext *w, InputFile *ifile)
{
AVFormatContext *fmt_ctx = ifile->fmt_ctx;
int i, ret = 0;
- writer_print_section_header(w, NULL, SECTION_ID_PROGRAMS);
+ avtext_print_section_header(w, NULL, SECTION_ID_PROGRAMS);
for (i = 0; i < fmt_ctx->nb_programs; i++) {
AVProgram *program = fmt_ctx->programs[i];
if (!program)
@@ -1963,14 +1958,14 @@ static int show_programs(WriterContext *w, InputFile *ifile)
if (ret < 0)
break;
}
- writer_print_section_footer(w);
+ avtext_print_section_footer(w);
return ret;
}
-static void print_tile_grid_params(WriterContext *w, const AVStreamGroup *stg,
+static void print_tile_grid_params(AVTextFormatContext *w, const AVStreamGroup *stg,
const AVStreamGroupTileGrid *tile_grid)
{
- writer_print_section_header(w, stg, SECTION_ID_STREAM_GROUP_COMPONENT);
+ avtext_print_section_header(w, stg, SECTION_ID_STREAM_GROUP_COMPONENT);
print_int("nb_tiles", tile_grid->nb_tiles);
print_int("coded_width", tile_grid->coded_width);
print_int("coded_height", tile_grid->coded_height);
@@ -1978,19 +1973,19 @@ static void print_tile_grid_params(WriterContext *w, const AVStreamGroup *stg,
print_int("vertical_offset", tile_grid->vertical_offset);
print_int("width", tile_grid->width);
print_int("height", tile_grid->height);
- writer_print_section_header(w, NULL, SECTION_ID_STREAM_GROUP_SUBCOMPONENTS);
+ avtext_print_section_header(w, NULL, SECTION_ID_STREAM_GROUP_SUBCOMPONENTS);
for (int i = 0; i < tile_grid->nb_tiles; i++) {
- writer_print_section_header(w, "tile_offset", SECTION_ID_STREAM_GROUP_SUBCOMPONENT);
+ avtext_print_section_header(w, "tile_offset", SECTION_ID_STREAM_GROUP_SUBCOMPONENT);
print_int("stream_index", tile_grid->offsets[i].idx);
print_int("tile_horizontal_offset", tile_grid->offsets[i].horizontal);
print_int("tile_vertical_offset", tile_grid->offsets[i].vertical);
- writer_print_section_footer(w);
+ avtext_print_section_footer(w);
}
- writer_print_section_footer(w);
- writer_print_section_footer(w);
+ avtext_print_section_footer(w);
+ avtext_print_section_footer(w);
}
-static void print_iamf_param_definition(WriterContext *w, const char *name,
+static void print_iamf_param_definition(AVTextFormatContext *w, const char *name,
const AVIAMFParamDefinition *param, SectionID section_id)
{
SectionID subsection_id, parameter_section_id;
@@ -1998,7 +1993,7 @@ static void print_iamf_param_definition(WriterContext *w, const char *name,
av_assert0(subsection_id != -1);
parameter_section_id = sections[subsection_id].children_ids[0];
av_assert0(parameter_section_id != -1);
- writer_print_section_header(w, "IAMF Param Definition", section_id);
+ avtext_print_section_header(w, "IAMF Param Definition", section_id);
print_str("name", name);
print_int("nb_subblocks", param->nb_subblocks);
print_int("type", param->type);
@@ -2007,56 +2002,56 @@ static void print_iamf_param_definition(WriterContext *w, const char *name,
print_int("duration", param->duration);
print_int("constant_subblock_duration", param->constant_subblock_duration);
if (param->nb_subblocks > 0)
- writer_print_section_header(w, NULL, subsection_id);
+ avtext_print_section_header(w, NULL, subsection_id);
for (int i = 0; i < param->nb_subblocks; i++) {
const void *subblock = av_iamf_param_definition_get_subblock(param, i);
switch(param->type) {
case AV_IAMF_PARAMETER_DEFINITION_MIX_GAIN: {
const AVIAMFMixGain *mix = subblock;
- writer_print_section_header(w, "IAMF Mix Gain Parameters", parameter_section_id);
+ avtext_print_section_header(w, "IAMF Mix Gain Parameters", parameter_section_id);
print_int("subblock_duration", mix->subblock_duration);
print_int("animation_type", mix->animation_type);
print_q("start_point_value", mix->start_point_value, '/');
print_q("end_point_value", mix->end_point_value, '/');
print_q("control_point_value", mix->control_point_value, '/');
print_q("control_point_relative_time", mix->control_point_relative_time, '/');
- writer_print_section_footer(w); // parameter_section_id
+ avtext_print_section_footer(w); // parameter_section_id
break;
}
case AV_IAMF_PARAMETER_DEFINITION_DEMIXING: {
const AVIAMFDemixingInfo *demix = subblock;
- writer_print_section_header(w, "IAMF Demixing Info", parameter_section_id);
+ avtext_print_section_header(w, "IAMF Demixing Info", parameter_section_id);
print_int("subblock_duration", demix->subblock_duration);
print_int("dmixp_mode", demix->dmixp_mode);
- writer_print_section_footer(w); // parameter_section_id
+ avtext_print_section_footer(w); // parameter_section_id
break;
}
case AV_IAMF_PARAMETER_DEFINITION_RECON_GAIN: {
const AVIAMFReconGain *recon = subblock;
- writer_print_section_header(w, "IAMF Recon Gain", parameter_section_id);
+ avtext_print_section_header(w, "IAMF Recon Gain", parameter_section_id);
print_int("subblock_duration", recon->subblock_duration);
- writer_print_section_footer(w); // parameter_section_id
+ avtext_print_section_footer(w); // parameter_section_id
break;
}
}
}
if (param->nb_subblocks > 0)
- writer_print_section_footer(w); // subsection_id
- writer_print_section_footer(w); // section_id
+ avtext_print_section_footer(w); // subsection_id
+ avtext_print_section_footer(w); // section_id
}
-static void print_iamf_audio_element_params(WriterContext *w, const AVStreamGroup *stg,
+static void print_iamf_audio_element_params(AVTextFormatContext *w, const AVStreamGroup *stg,
const AVIAMFAudioElement *audio_element)
{
- writer_print_section_header(w, stg, SECTION_ID_STREAM_GROUP_COMPONENT);
+ avtext_print_section_header(w, stg, SECTION_ID_STREAM_GROUP_COMPONENT);
print_int("nb_layers", audio_element->nb_layers);
print_int("audio_element_type", audio_element->audio_element_type);
print_int("default_w", audio_element->default_w);
- writer_print_section_header(w, NULL, SECTION_ID_STREAM_GROUP_SUBCOMPONENTS);
+ avtext_print_section_header(w, NULL, SECTION_ID_STREAM_GROUP_SUBCOMPONENTS);
for (int i = 0; i < audio_element->nb_layers; i++) {
const AVIAMFLayer *layer = audio_element->layers[i];
char val_str[128];
- writer_print_section_header(w, "IAMF Audio Layer", SECTION_ID_STREAM_GROUP_SUBCOMPONENT);
+ avtext_print_section_header(w, "IAMF Audio Layer", SECTION_ID_STREAM_GROUP_SUBCOMPONENT);
av_channel_layout_describe(&layer->ch_layout, val_str, sizeof(val_str));
print_str("channel_layout", val_str);
if (audio_element->audio_element_type == AV_IAMF_AUDIO_ELEMENT_TYPE_CHANNEL) {
@@ -2064,7 +2059,7 @@ static void print_iamf_audio_element_params(WriterContext *w, const AVStreamGrou
print_q("output_gain", layer->output_gain, '/');
} else if (audio_element->audio_element_type == AV_IAMF_AUDIO_ELEMENT_TYPE_SCENE)
print_int("ambisonics_mode", layer->ambisonics_mode);
- writer_print_section_footer(w); // SECTION_ID_STREAM_GROUP_SUBCOMPONENT
+ avtext_print_section_footer(w); // SECTION_ID_STREAM_GROUP_SUBCOMPONENT
}
if (audio_element->demixing_info)
print_iamf_param_definition(w, "demixing_info", audio_element->demixing_info,
@@ -2072,36 +2067,36 @@ static void print_iamf_audio_element_params(WriterContext *w, const AVStreamGrou
if (audio_element->recon_gain_info)
print_iamf_param_definition(w, "recon_gain_info", audio_element->recon_gain_info,
SECTION_ID_STREAM_GROUP_SUBCOMPONENT);
- writer_print_section_footer(w); // SECTION_ID_STREAM_GROUP_SUBCOMPONENTS
- writer_print_section_footer(w); // SECTION_ID_STREAM_GROUP_COMPONENT
+ avtext_print_section_footer(w); // SECTION_ID_STREAM_GROUP_SUBCOMPONENTS
+ avtext_print_section_footer(w); // SECTION_ID_STREAM_GROUP_COMPONENT
}
-static void print_iamf_submix_params(WriterContext *w, const AVIAMFSubmix *submix)
+static void print_iamf_submix_params(AVTextFormatContext *w, const AVIAMFSubmix *submix)
{
- writer_print_section_header(w, "IAMF Submix", SECTION_ID_STREAM_GROUP_SUBCOMPONENT);
+ avtext_print_section_header(w, "IAMF Submix", SECTION_ID_STREAM_GROUP_SUBCOMPONENT);
print_int("nb_elements", submix->nb_elements);
print_int("nb_layouts", submix->nb_layouts);
print_q("default_mix_gain", submix->default_mix_gain, '/');
- writer_print_section_header(w, NULL, SECTION_ID_STREAM_GROUP_PIECES);
+ avtext_print_section_header(w, NULL, SECTION_ID_STREAM_GROUP_PIECES);
for (int i = 0; i < submix->nb_elements; i++) {
const AVIAMFSubmixElement *element = submix->elements[i];
- writer_print_section_header(w, "IAMF Submix Element", SECTION_ID_STREAM_GROUP_PIECE);
+ avtext_print_section_header(w, "IAMF Submix Element", SECTION_ID_STREAM_GROUP_PIECE);
print_int("stream_id", element->audio_element_id);
print_q("default_mix_gain", element->default_mix_gain, '/');
print_int("headphones_rendering_mode", element->headphones_rendering_mode);
- writer_print_section_header(w, NULL, SECTION_ID_STREAM_GROUP_SUBPIECES);
+ avtext_print_section_header(w, NULL, SECTION_ID_STREAM_GROUP_SUBPIECES);
if (element->annotations) {
const AVDictionaryEntry *annotation = NULL;
- writer_print_section_header(w, "IAMF Annotations", SECTION_ID_STREAM_GROUP_SUBPIECE);
+ avtext_print_section_header(w, "IAMF Annotations", SECTION_ID_STREAM_GROUP_SUBPIECE);
while (annotation = av_dict_iterate(element->annotations, annotation))
print_str(annotation->key, annotation->value);
- writer_print_section_footer(w); // SECTION_ID_STREAM_GROUP_SUBPIECE
+ avtext_print_section_footer(w); // SECTION_ID_STREAM_GROUP_SUBPIECE
}
if (element->element_mix_config)
print_iamf_param_definition(w, "element_mix_config", element->element_mix_config,
SECTION_ID_STREAM_GROUP_SUBPIECE);
- writer_print_section_footer(w); // SECTION_ID_STREAM_GROUP_SUBPIECES
- writer_print_section_footer(w); // SECTION_ID_STREAM_GROUP_PIECE
+ avtext_print_section_footer(w); // SECTION_ID_STREAM_GROUP_SUBPIECES
+ avtext_print_section_footer(w); // SECTION_ID_STREAM_GROUP_PIECE
}
if (submix->output_mix_config)
print_iamf_param_definition(w, "output_mix_config", submix->output_mix_config,
@@ -2109,7 +2104,7 @@ static void print_iamf_submix_params(WriterContext *w, const AVIAMFSubmix *submi
for (int i = 0; i < submix->nb_layouts; i++) {
const AVIAMFSubmixLayout *layout = submix->layouts[i];
char val_str[128];
- writer_print_section_header(w, "IAMF Submix Layout", SECTION_ID_STREAM_GROUP_PIECE);
+ avtext_print_section_header(w, "IAMF Submix Layout", SECTION_ID_STREAM_GROUP_PIECE);
av_channel_layout_describe(&layout->sound_system, val_str, sizeof(val_str));
print_str("sound_system", val_str);
print_q("integrated_loudness", layout->integrated_loudness, '/');
@@ -2117,51 +2112,51 @@ static void print_iamf_submix_params(WriterContext *w, const AVIAMFSubmix *submi
print_q("true_peak", layout->true_peak, '/');
print_q("dialogue_anchored_loudness", layout->dialogue_anchored_loudness, '/');
print_q("album_anchored_loudness", layout->album_anchored_loudness, '/');
- writer_print_section_footer(w); // SECTION_ID_STREAM_GROUP_PIECE
+ avtext_print_section_footer(w); // SECTION_ID_STREAM_GROUP_PIECE
}
- writer_print_section_footer(w); // SECTION_ID_STREAM_GROUP_PIECES
- writer_print_section_footer(w); // SECTION_ID_STREAM_GROUP_SUBCOMPONENT
+ avtext_print_section_footer(w); // SECTION_ID_STREAM_GROUP_PIECES
+ avtext_print_section_footer(w); // SECTION_ID_STREAM_GROUP_SUBCOMPONENT
}
-static void print_iamf_mix_presentation_params(WriterContext *w, const AVStreamGroup *stg,
+static void print_iamf_mix_presentation_params(AVTextFormatContext *w, const AVStreamGroup *stg,
const AVIAMFMixPresentation *mix_presentation)
{
- writer_print_section_header(w, stg, SECTION_ID_STREAM_GROUP_COMPONENT);
+ avtext_print_section_header(w, stg, SECTION_ID_STREAM_GROUP_COMPONENT);
print_int("nb_submixes", mix_presentation->nb_submixes);
- writer_print_section_header(w, NULL, SECTION_ID_STREAM_GROUP_SUBCOMPONENTS);
+ avtext_print_section_header(w, NULL, SECTION_ID_STREAM_GROUP_SUBCOMPONENTS);
if (mix_presentation->annotations) {
const AVDictionaryEntry *annotation = NULL;
- writer_print_section_header(w, "IAMF Annotations", SECTION_ID_STREAM_GROUP_SUBCOMPONENT);
+ avtext_print_section_header(w, "IAMF Annotations", SECTION_ID_STREAM_GROUP_SUBCOMPONENT);
while (annotation = av_dict_iterate(mix_presentation->annotations, annotation))
print_str(annotation->key, annotation->value);
- writer_print_section_footer(w); // SECTION_ID_STREAM_GROUP_SUBCOMPONENT
+ avtext_print_section_footer(w); // SECTION_ID_STREAM_GROUP_SUBCOMPONENT
}
for (int i = 0; i < mix_presentation->nb_submixes; i++)
print_iamf_submix_params(w, mix_presentation->submixes[i]);
- writer_print_section_footer(w); // SECTION_ID_STREAM_GROUP_SUBCOMPONENTS
- writer_print_section_footer(w); // SECTION_ID_STREAM_GROUP_COMPONENT
+ avtext_print_section_footer(w); // SECTION_ID_STREAM_GROUP_SUBCOMPONENTS
+ avtext_print_section_footer(w); // SECTION_ID_STREAM_GROUP_COMPONENT
}
-static void print_stream_group_params(WriterContext *w, AVStreamGroup *stg)
+static void print_stream_group_params(AVTextFormatContext *w, AVStreamGroup *stg)
{
- writer_print_section_header(w, NULL, SECTION_ID_STREAM_GROUP_COMPONENTS);
+ avtext_print_section_header(w, NULL, SECTION_ID_STREAM_GROUP_COMPONENTS);
if (stg->type == AV_STREAM_GROUP_PARAMS_TILE_GRID)
print_tile_grid_params(w, stg, stg->params.tile_grid);
else if (stg->type == AV_STREAM_GROUP_PARAMS_IAMF_AUDIO_ELEMENT)
print_iamf_audio_element_params(w, stg, stg->params.iamf_audio_element);
else if (stg->type == AV_STREAM_GROUP_PARAMS_IAMF_MIX_PRESENTATION)
print_iamf_mix_presentation_params(w, stg, stg->params.iamf_mix_presentation);
- writer_print_section_footer(w); // SECTION_ID_STREAM_GROUP_COMPONENTS
+ avtext_print_section_footer(w); // SECTION_ID_STREAM_GROUP_COMPONENTS
}
-static int show_stream_group(WriterContext *w, InputFile *ifile, AVStreamGroup *stg)
+static int show_stream_group(AVTextFormatContext *w, InputFile *ifile, AVStreamGroup *stg)
{
AVFormatContext *fmt_ctx = ifile->fmt_ctx;
AVBPrint pbuf;
int i, ret = 0;
av_bprint_init(&pbuf, 1, AV_BPRINT_SIZE_UNLIMITED);
- writer_print_section_header(w, NULL, SECTION_ID_STREAM_GROUP);
+ avtext_print_section_header(w, NULL, SECTION_ID_STREAM_GROUP);
print_int("index", stg->index);
if (fmt_ctx->iformat->flags & AVFMT_SHOW_IDS) print_fmt ("id", "0x%"PRIx64, stg->id);
else print_str_opt("id", "N/A");
@@ -2182,7 +2177,7 @@ static int show_stream_group(WriterContext *w, InputFile *ifile, AVStreamGroup *
if (ret < 0)
goto end;
- writer_print_section_header(w, NULL, SECTION_ID_STREAM_GROUP_STREAMS);
+ avtext_print_section_header(w, NULL, SECTION_ID_STREAM_GROUP_STREAMS);
for (i = 0; i < stg->nb_streams; i++) {
if (selected_streams[stg->streams[i]->index]) {
ret = show_stream(w, fmt_ctx, stg->streams[i]->index, &ifile->streams[stg->streams[i]->index], IN_STREAM_GROUP);
@@ -2190,20 +2185,20 @@ static int show_stream_group(WriterContext *w, InputFile *ifile, AVStreamGroup *
break;
}
}
- writer_print_section_footer(w);
+ avtext_print_section_footer(w);
end:
av_bprint_finalize(&pbuf, NULL);
- writer_print_section_footer(w);
+ avtext_print_section_footer(w);
return ret;
}
-static int show_stream_groups(WriterContext *w, InputFile *ifile)
+static int show_stream_groups(AVTextFormatContext *w, InputFile *ifile)
{
AVFormatContext *fmt_ctx = ifile->fmt_ctx;
int i, ret = 0;
- writer_print_section_header(w, NULL, SECTION_ID_STREAM_GROUPS);
+ avtext_print_section_header(w, NULL, SECTION_ID_STREAM_GROUPS);
for (i = 0; i < fmt_ctx->nb_stream_groups; i++) {
AVStreamGroup *stg = fmt_ctx->stream_groups[i];
@@ -2211,20 +2206,20 @@ static int show_stream_groups(WriterContext *w, InputFile *ifile)
if (ret < 0)
break;
}
- writer_print_section_footer(w);
+ avtext_print_section_footer(w);
return ret;
}
-static int show_chapters(WriterContext *w, InputFile *ifile)
+static int show_chapters(AVTextFormatContext *w, InputFile *ifile)
{
AVFormatContext *fmt_ctx = ifile->fmt_ctx;
int i, ret = 0;
- writer_print_section_header(w, NULL, SECTION_ID_CHAPTERS);
+ avtext_print_section_header(w, NULL, SECTION_ID_CHAPTERS);
for (i = 0; i < fmt_ctx->nb_chapters; i++) {
AVChapter *chapter = fmt_ctx->chapters[i];
- writer_print_section_header(w, NULL, SECTION_ID_CHAPTER);
+ avtext_print_section_header(w, NULL, SECTION_ID_CHAPTER);
print_int("id", chapter->id);
print_q ("time_base", chapter->time_base, '/');
print_int("start", chapter->start);
@@ -2233,20 +2228,20 @@ static int show_chapters(WriterContext *w, InputFile *ifile)
print_time("end_time", chapter->end, &chapter->time_base);
if (do_show_chapter_tags)
ret = show_tags(w, chapter->metadata, SECTION_ID_CHAPTER_TAGS);
- writer_print_section_footer(w);
+ avtext_print_section_footer(w);
}
- writer_print_section_footer(w);
+ avtext_print_section_footer(w);
return ret;
}
-static int show_format(WriterContext *w, InputFile *ifile)
+static int show_format(AVTextFormatContext *w, InputFile *ifile)
{
AVFormatContext *fmt_ctx = ifile->fmt_ctx;
int64_t size = fmt_ctx->pb ? avio_size(fmt_ctx->pb) : -1;
int ret = 0;
- writer_print_section_header(w, NULL, SECTION_ID_FORMAT);
+ avtext_print_section_header(w, NULL, SECTION_ID_FORMAT);
print_str_validate("filename", fmt_ctx->url);
print_int("nb_streams", fmt_ctx->nb_streams);
print_int("nb_programs", fmt_ctx->nb_programs);
@@ -2266,17 +2261,17 @@ static int show_format(WriterContext *w, InputFile *ifile)
if (do_show_format_tags)
ret = show_tags(w, fmt_ctx->metadata, SECTION_ID_FORMAT_TAGS);
- writer_print_section_footer(w);
+ avtext_print_section_footer(w);
fflush(stdout);
return ret;
}
-static void show_error(WriterContext *w, int err)
+static void show_error(AVTextFormatContext *w, int err)
{
- writer_print_section_header(w, NULL, SECTION_ID_ERROR);
+ avtext_print_section_header(w, NULL, SECTION_ID_ERROR);
print_int("code", err);
print_str("string", av_err2str(err));
- writer_print_section_footer(w);
+ avtext_print_section_footer(w);
}
static int open_input_file(InputFile *ifile, const char *filename,
@@ -2418,7 +2413,7 @@ static void close_input_file(InputFile *ifile)
avformat_close_input(&ifile->fmt_ctx);
}
-static int probe_file(WriterContext *tctx, const char *filename,
+static int probe_file(AVTextFormatContext *tctx, const char *filename,
const char *print_filename)
{
InputFile ifile = { 0 };
@@ -2467,10 +2462,10 @@ static int probe_file(WriterContext *tctx, const char *filename,
else // (!do_show_packets && do_show_frames)
section_id = SECTION_ID_FRAMES;
if (do_show_frames || do_show_packets)
- writer_print_section_header(tctx, NULL, section_id);
+ avtext_print_section_header(tctx, NULL, section_id);
ret = read_packets(tctx, &ifile);
if (do_show_frames || do_show_packets)
- writer_print_section_footer(tctx);
+ avtext_print_section_footer(tctx);
CHECK_END;
}
@@ -2516,18 +2511,18 @@ static void show_usage(void)
av_log(NULL, AV_LOG_INFO, "\n");
}
-static void ffprobe_show_program_version(WriterContext *w)
+static void ffprobe_show_program_version(AVTextFormatContext *w)
{
AVBPrint pbuf;
av_bprint_init(&pbuf, 1, AV_BPRINT_SIZE_UNLIMITED);
- writer_print_section_header(w, NULL, SECTION_ID_PROGRAM_VERSION);
+ avtext_print_section_header(w, NULL, SECTION_ID_PROGRAM_VERSION);
print_str("version", FFMPEG_VERSION);
print_fmt("copyright", "Copyright (c) %d-%d the FFmpeg developers",
program_birth_year, CONFIG_THIS_YEAR);
print_str("compiler_ident", CC_IDENT);
print_str("configuration", FFMPEG_CONFIGURATION);
- writer_print_section_footer(w);
+ avtext_print_section_footer(w);
av_bprint_finalize(&pbuf, NULL);
}
@@ -2536,20 +2531,20 @@ static void ffprobe_show_program_version(WriterContext *w)
do { \
if (CONFIG_##LIBNAME) { \
unsigned int version = libname##_version(); \
- writer_print_section_header(w, NULL, SECTION_ID_LIBRARY_VERSION); \
+ avtext_print_section_header(w, NULL, SECTION_ID_LIBRARY_VERSION); \
print_str("name", "lib" #libname); \
print_int("major", LIB##LIBNAME##_VERSION_MAJOR); \
print_int("minor", LIB##LIBNAME##_VERSION_MINOR); \
print_int("micro", LIB##LIBNAME##_VERSION_MICRO); \
print_int("version", version); \
print_str("ident", LIB##LIBNAME##_IDENT); \
- writer_print_section_footer(w); \
+ avtext_print_section_footer(w); \
} \
} while (0)
-static void ffprobe_show_library_versions(WriterContext *w)
+static void ffprobe_show_library_versions(AVTextFormatContext *w)
{
- writer_print_section_header(w, NULL, SECTION_ID_LIBRARY_VERSIONS);
+ avtext_print_section_header(w, NULL, SECTION_ID_LIBRARY_VERSIONS);
SHOW_LIB_VERSION(avutil, AVUTIL);
SHOW_LIB_VERSION(avcodec, AVCODEC);
SHOW_LIB_VERSION(avformat, AVFORMAT);
@@ -2558,7 +2553,7 @@ static void ffprobe_show_library_versions(WriterContext *w)
SHOW_LIB_VERSION(swscale, SWSCALE);
SHOW_LIB_VERSION(swresample, SWRESAMPLE);
SHOW_LIB_VERSION(postproc, POSTPROC);
- writer_print_section_footer(w);
+ avtext_print_section_footer(w);
}
#define PRINT_PIX_FMT_FLAG(flagname, name) \
@@ -2566,14 +2561,14 @@ static void ffprobe_show_library_versions(WriterContext *w)
print_int(name, !!(pixdesc->flags & AV_PIX_FMT_FLAG_##flagname)); \
} while (0)
-static void ffprobe_show_pixel_formats(WriterContext *w)
+static void ffprobe_show_pixel_formats(AVTextFormatContext *w)
{
const AVPixFmtDescriptor *pixdesc = NULL;
int i, n;
- writer_print_section_header(w, NULL, SECTION_ID_PIXEL_FORMATS);
+ avtext_print_section_header(w, NULL, SECTION_ID_PIXEL_FORMATS);
while (pixdesc = av_pix_fmt_desc_next(pixdesc)) {
- writer_print_section_header(w, NULL, SECTION_ID_PIXEL_FORMAT);
+ avtext_print_section_header(w, NULL, SECTION_ID_PIXEL_FORMAT);
print_str("name", pixdesc->name);
print_int("nb_components", pixdesc->nb_components);
if ((pixdesc->nb_components >= 3) && !(pixdesc->flags & AV_PIX_FMT_FLAG_RGB)) {
@@ -2587,7 +2582,7 @@ static void ffprobe_show_pixel_formats(WriterContext *w)
if (n) print_int ("bits_per_pixel", n);
else print_str_opt("bits_per_pixel", "N/A");
if (do_show_pixel_format_flags) {
- writer_print_section_header(w, NULL, SECTION_ID_PIXEL_FORMAT_FLAGS);
+ avtext_print_section_header(w, NULL, SECTION_ID_PIXEL_FORMAT_FLAGS);
PRINT_PIX_FMT_FLAG(BE, "big_endian");
PRINT_PIX_FMT_FLAG(PAL, "palette");
PRINT_PIX_FMT_FLAG(BITSTREAM, "bitstream");
@@ -2595,21 +2590,21 @@ static void ffprobe_show_pixel_formats(WriterContext *w)
PRINT_PIX_FMT_FLAG(PLANAR, "planar");
PRINT_PIX_FMT_FLAG(RGB, "rgb");
PRINT_PIX_FMT_FLAG(ALPHA, "alpha");
- writer_print_section_footer(w);
+ avtext_print_section_footer(w);
}
if (do_show_pixel_format_components && (pixdesc->nb_components > 0)) {
- writer_print_section_header(w, NULL, SECTION_ID_PIXEL_FORMAT_COMPONENTS);
+ avtext_print_section_header(w, NULL, SECTION_ID_PIXEL_FORMAT_COMPONENTS);
for (i = 0; i < pixdesc->nb_components; i++) {
- writer_print_section_header(w, NULL, SECTION_ID_PIXEL_FORMAT_COMPONENT);
+ avtext_print_section_header(w, NULL, SECTION_ID_PIXEL_FORMAT_COMPONENT);
print_int("index", i + 1);
print_int("bit_depth", pixdesc->comp[i].depth);
- writer_print_section_footer(w);
+ avtext_print_section_footer(w);
}
- writer_print_section_footer(w);
+ avtext_print_section_footer(w);
}
- writer_print_section_footer(w);
+ avtext_print_section_footer(w);
}
- writer_print_section_footer(w);
+ avtext_print_section_footer(w);
}
static int opt_show_optional_fields(void *optctx, const char *opt, const char *arg)
@@ -3057,7 +3052,7 @@ static inline int check_section_show_entries(int section_id)
int main(int argc, char **argv)
{
const AVTextFormatter *f;
- WriterContext *tctx;
+ AVTextFormatContext *tctx;
AVTextWriterContext *wctx;
char *buf;
char *f_name = NULL, *f_args = NULL;
@@ -3159,7 +3154,7 @@ int main(int argc, char **argv)
if (f == &avtextformatter_xml)
tctx->string_validation_utf8_flags |= AV_UTF8_FLAG_EXCLUDE_XML_INVALID_CONTROL_CODES;
- writer_print_section_header(tctx, NULL, SECTION_ID_ROOT);
+ avtext_print_section_header(tctx, NULL, SECTION_ID_ROOT);
if (do_show_program_version)
ffprobe_show_program_version(tctx);
--
ffmpeg-codebot
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 108+ messages in thread
* [FFmpeg-devel] [PATCH v8 4/4] fftools/ffprobe: Rename AVTextFormatContext variables (w => tfc)
2025-03-19 17:04 ` [FFmpeg-devel] [PATCH v8 0/4] print_graphs: Complete Filtergraph Printing ffmpegagent
` (2 preceding siblings ...)
2025-03-19 17:04 ` [FFmpeg-devel] [PATCH v8 3/4] fftools/ffprobe: Rename writer_print_section_* and WriterContext softworkz
@ 2025-03-19 17:04 ` softworkz
2025-03-21 18:04 ` [FFmpeg-devel] [PATCH v8 0/4] print_graphs: Complete Filtergraph Printing Stefano Sabatini
2025-03-23 3:42 ` [FFmpeg-devel] [PATCH v9 " ffmpegagent
5 siblings, 0 replies; 108+ messages in thread
From: softworkz @ 2025-03-19 17:04 UTC (permalink / raw)
To: ffmpeg-devel; +Cc: softworkz
From: softworkz <softworkz@hotmail.com>
Signed-off-by: softworkz <softworkz@hotmail.com>
---
fftools/ffprobe.c | 512 +++++++++++++++++++++++-----------------------
1 file changed, 256 insertions(+), 256 deletions(-)
diff --git a/fftools/ffprobe.c b/fftools/ffprobe.c
index 4a90bc4824..9f869b41b3 100644
--- a/fftools/ffprobe.c
+++ b/fftools/ffprobe.c
@@ -407,7 +407,7 @@ static void log_callback(void *ptr, int level, const char *fmt, va_list vl)
#define print_fmt(k, f, ...) do { \
av_bprint_clear(&pbuf); \
av_bprintf(&pbuf, f, __VA_ARGS__); \
- avtext_print_string(w, k, pbuf.str, 0); \
+ avtext_print_string(tfc, k, pbuf.str, 0); \
} while (0)
#define print_list_fmt(k, f, n, m, ...) do { \
@@ -419,19 +419,19 @@ static void log_callback(void *ptr, int level, const char *fmt, va_list vl)
av_bprintf(&pbuf, f, __VA_ARGS__); \
} \
} \
- avtext_print_string(w, k, pbuf.str, 0); \
+ avtext_print_string(tfc, k, pbuf.str, 0); \
} while (0)
-#define print_int(k, v) avtext_print_integer(w, k, v)
-#define print_q(k, v, s) avtext_print_rational(w, k, v, s)
-#define print_str(k, v) avtext_print_string(w, k, v, 0)
-#define print_str_opt(k, v) avtext_print_string(w, k, v, AV_TEXTFORMAT_PRINT_STRING_OPTIONAL)
-#define print_str_validate(k, v) avtext_print_string(w, k, v, AV_TEXTFORMAT_PRINT_STRING_VALIDATE)
-#define print_time(k, v, tb) avtext_print_time(w, k, v, tb, 0)
-#define print_ts(k, v) avtext_print_ts(w, k, v, 0)
-#define print_duration_time(k, v, tb) avtext_print_time(w, k, v, tb, 1)
-#define print_duration_ts(k, v) avtext_print_ts(w, k, v, 1)
-#define print_val(k, v, u) avtext_print_unit_int(w, k, v, u)
+#define print_int(k, v) avtext_print_integer(tfc, k, v)
+#define print_q(k, v, s) avtext_print_rational(tfc, k, v, s)
+#define print_str(k, v) avtext_print_string(tfc, k, v, 0)
+#define print_str_opt(k, v) avtext_print_string(tfc, k, v, AV_TEXTFORMAT_PRINT_STRING_OPTIONAL)
+#define print_str_validate(k, v) avtext_print_string(tfc, k, v, AV_TEXTFORMAT_PRINT_STRING_VALIDATE)
+#define print_time(k, v, tb) avtext_print_time(tfc, k, v, tb, 0)
+#define print_ts(k, v) avtext_print_ts(tfc, k, v, 0)
+#define print_duration_time(k, v, tb) avtext_print_time(tfc, k, v, tb, 1)
+#define print_duration_ts(k, v) avtext_print_ts(tfc, k, v, 1)
+#define print_val(k, v, u) avtext_print_unit_int(tfc, k, v, u)
#define REALLOCZ_ARRAY_STREAM(ptr, cur_n, new_n) \
{ \
@@ -441,25 +441,25 @@ static void log_callback(void *ptr, int level, const char *fmt, va_list vl)
memset( (ptr) + (cur_n), 0, ((new_n) - (cur_n)) * sizeof(*(ptr)) ); \
}
-static inline int show_tags(AVTextFormatContext *w, AVDictionary *tags, int section_id)
+static inline int show_tags(AVTextFormatContext *tfc, AVDictionary *tags, int section_id)
{
const AVDictionaryEntry *tag = NULL;
int ret = 0;
if (!tags)
return 0;
- avtext_print_section_header(w, NULL, section_id);
+ avtext_print_section_header(tfc, NULL, section_id);
while ((tag = av_dict_iterate(tags, tag))) {
if ((ret = print_str_validate(tag->key, tag->value)) < 0)
break;
}
- avtext_print_section_footer(w);
+ avtext_print_section_footer(tfc);
return ret;
}
-static void print_dovi_metadata(AVTextFormatContext *w, const AVDOVIMetadata *dovi)
+static void print_dovi_metadata(AVTextFormatContext *tfc, const AVDOVIMetadata *dovi)
{
if (!dovi)
return;
@@ -514,15 +514,15 @@ static void print_dovi_metadata(AVTextFormatContext *w, const AVDOVIMetadata *do
print_int("num_x_partitions", mapping->num_x_partitions);
print_int("num_y_partitions", mapping->num_y_partitions);
- avtext_print_section_header(w, NULL, SECTION_ID_FRAME_SIDE_DATA_COMPONENT_LIST);
+ avtext_print_section_header(tfc, NULL, SECTION_ID_FRAME_SIDE_DATA_COMPONENT_LIST);
for (int c = 0; c < 3; c++) {
const AVDOVIReshapingCurve *curve = &mapping->curves[c];
- avtext_print_section_header(w, "Reshaping curve", SECTION_ID_FRAME_SIDE_DATA_COMPONENT);
+ avtext_print_section_header(tfc, "Reshaping curve", SECTION_ID_FRAME_SIDE_DATA_COMPONENT);
print_list_fmt("pivots", "%"PRIu16, curve->num_pivots, 1, curve->pivots[idx]);
- avtext_print_section_header(w, NULL, SECTION_ID_FRAME_SIDE_DATA_PIECE_LIST);
+ avtext_print_section_header(tfc, NULL, SECTION_ID_FRAME_SIDE_DATA_PIECE_LIST);
for (int i = 0; i < curve->num_pivots - 1; i++) {
AVBPrint piece_buf;
@@ -540,7 +540,7 @@ static void print_dovi_metadata(AVTextFormatContext *w, const AVDOVIMetadata *do
}
av_bprintf(&piece_buf, " mapping");
- avtext_print_section_header(w, piece_buf.str, SECTION_ID_FRAME_SIDE_DATA_PIECE);
+ avtext_print_section_header(tfc, piece_buf.str, SECTION_ID_FRAME_SIDE_DATA_PIECE);
print_int("mapping_idc", curve->mapping_idc[i]);
switch (curve->mapping_idc[i]) {
case AV_DOVI_MAPPING_POLYNOMIAL:
@@ -564,11 +564,11 @@ static void print_dovi_metadata(AVTextFormatContext *w, const AVDOVIMetadata *do
}
// SECTION_ID_FRAME_SIDE_DATA_PIECE
- avtext_print_section_footer(w);
+ avtext_print_section_footer(tfc);
}
// SECTION_ID_FRAME_SIDE_DATA_PIECE_LIST
- avtext_print_section_footer(w);
+ avtext_print_section_footer(tfc);
if (mapping->nlq_method_idc != AV_DOVI_NLQ_NONE) {
const AVDOVINLQParams *nlq = &mapping->nlq[c];
@@ -584,11 +584,11 @@ static void print_dovi_metadata(AVTextFormatContext *w, const AVDOVIMetadata *do
}
// SECTION_ID_FRAME_SIDE_DATA_COMPONENT
- avtext_print_section_footer(w);
+ avtext_print_section_footer(tfc);
}
// SECTION_ID_FRAME_SIDE_DATA_COMPONENT_LIST
- avtext_print_section_footer(w);
+ avtext_print_section_footer(tfc);
// color metadata
print_int("dm_metadata_id", color->dm_metadata_id);
@@ -621,7 +621,7 @@ static void print_dovi_metadata(AVTextFormatContext *w, const AVDOVIMetadata *do
}
}
-static void print_dynamic_hdr10_plus(AVTextFormatContext *w, const AVDynamicHDRPlus *metadata)
+static void print_dynamic_hdr10_plus(AVTextFormatContext *tfc, const AVDynamicHDRPlus *metadata)
{
if (!metadata)
return;
@@ -720,7 +720,7 @@ static void print_dynamic_hdr10_plus(AVTextFormatContext *w, const AVDynamicHDRP
}
}
-static void print_dynamic_hdr_vivid(AVTextFormatContext *w, const AVDynamicHDRVivid *metadata)
+static void print_dynamic_hdr_vivid(AVTextFormatContext *tfc, const AVDynamicHDRVivid *metadata)
{
if (!metadata)
return;
@@ -790,7 +790,7 @@ static void print_dynamic_hdr_vivid(AVTextFormatContext *w, const AVDynamicHDRVi
}
}
-static void print_ambient_viewing_environment(AVTextFormatContext *w,
+static void print_ambient_viewing_environment(AVTextFormatContext *tfc,
const AVAmbientViewingEnvironment *env)
{
if (!env)
@@ -801,7 +801,7 @@ static void print_ambient_viewing_environment(AVTextFormatContext *w,
print_q("ambient_light_y", env->ambient_light_y, '/');
}
-static void print_film_grain_params(AVTextFormatContext *w,
+static void print_film_grain_params(AVTextFormatContext *tfc,
const AVFilmGrainParams *fgp)
{
const char *color_range, *color_primaries, *color_trc, *color_space;
@@ -847,10 +847,10 @@ static void print_film_grain_params(AVTextFormatContext *w,
print_int("overlap_flag", aom->overlap_flag);
print_int("limit_output_range", aom->limit_output_range);
- avtext_print_section_header(w, NULL, SECTION_ID_FRAME_SIDE_DATA_COMPONENT_LIST);
+ avtext_print_section_header(tfc, NULL, SECTION_ID_FRAME_SIDE_DATA_COMPONENT_LIST);
if (aom->num_y_points) {
- avtext_print_section_header(w, NULL, SECTION_ID_FRAME_SIDE_DATA_COMPONENT);
+ avtext_print_section_header(tfc, NULL, SECTION_ID_FRAME_SIDE_DATA_COMPONENT);
print_int("bit_depth_luma", fgp->bit_depth_luma);
print_list_fmt("y_points_value", "%"PRIu8, aom->num_y_points, 1, aom->y_points[idx][0]);
@@ -858,14 +858,14 @@ static void print_film_grain_params(AVTextFormatContext *w,
print_list_fmt("ar_coeffs_y", "%"PRId8, num_ar_coeffs_y, 1, aom->ar_coeffs_y[idx]);
// SECTION_ID_FRAME_SIDE_DATA_COMPONENT
- avtext_print_section_footer(w);
+ avtext_print_section_footer(tfc);
}
for (int uv = 0; uv < 2; uv++) {
if (!aom->num_uv_points[uv] && !aom->chroma_scaling_from_luma)
continue;
- avtext_print_section_header(w, NULL, SECTION_ID_FRAME_SIDE_DATA_COMPONENT);
+ avtext_print_section_header(tfc, NULL, SECTION_ID_FRAME_SIDE_DATA_COMPONENT);
print_int("bit_depth_chroma", fgp->bit_depth_chroma);
print_list_fmt("uv_points_value", "%"PRIu8, aom->num_uv_points[uv], 1, aom->uv_points[uv][idx][0]);
@@ -876,11 +876,11 @@ static void print_film_grain_params(AVTextFormatContext *w,
print_int("uv_offset", aom->uv_offset[uv]);
// SECTION_ID_FRAME_SIDE_DATA_COMPONENT
- avtext_print_section_footer(w);
+ avtext_print_section_footer(tfc);
}
// SECTION_ID_FRAME_SIDE_DATA_COMPONENT_LIST
- avtext_print_section_footer(w);
+ avtext_print_section_footer(tfc);
break;
}
case AV_FILM_GRAIN_PARAMS_H274: {
@@ -889,36 +889,36 @@ static void print_film_grain_params(AVTextFormatContext *w,
print_int("blending_mode_id", h274->blending_mode_id);
print_int("log2_scale_factor", h274->log2_scale_factor);
- avtext_print_section_header(w, NULL, SECTION_ID_FRAME_SIDE_DATA_COMPONENT_LIST);
+ avtext_print_section_header(tfc, NULL, SECTION_ID_FRAME_SIDE_DATA_COMPONENT_LIST);
for (int c = 0; c < 3; c++) {
if (!h274->component_model_present[c])
continue;
- avtext_print_section_header(w, NULL, SECTION_ID_FRAME_SIDE_DATA_COMPONENT);
+ avtext_print_section_header(tfc, NULL, SECTION_ID_FRAME_SIDE_DATA_COMPONENT);
print_int(c ? "bit_depth_chroma" : "bit_depth_luma", c ? fgp->bit_depth_chroma : fgp->bit_depth_luma);
- avtext_print_section_header(w, NULL, SECTION_ID_FRAME_SIDE_DATA_PIECE_LIST);
+ avtext_print_section_header(tfc, NULL, SECTION_ID_FRAME_SIDE_DATA_PIECE_LIST);
for (int i = 0; i < h274->num_intensity_intervals[c]; i++) {
- avtext_print_section_header(w, NULL, SECTION_ID_FRAME_SIDE_DATA_PIECE);
+ avtext_print_section_header(tfc, NULL, SECTION_ID_FRAME_SIDE_DATA_PIECE);
print_int("intensity_interval_lower_bound", h274->intensity_interval_lower_bound[c][i]);
print_int("intensity_interval_upper_bound", h274->intensity_interval_upper_bound[c][i]);
print_list_fmt("comp_model_value", "%"PRId16, h274->num_model_values[c], 1, h274->comp_model_value[c][i][idx]);
// SECTION_ID_FRAME_SIDE_DATA_PIECE
- avtext_print_section_footer(w);
+ avtext_print_section_footer(tfc);
}
// SECTION_ID_FRAME_SIDE_DATA_PIECE_LIST
- avtext_print_section_footer(w);
+ avtext_print_section_footer(tfc);
// SECTION_ID_FRAME_SIDE_DATA_COMPONENT
- avtext_print_section_footer(w);
+ avtext_print_section_footer(tfc);
}
// SECTION_ID_FRAME_SIDE_DATA_COMPONENT_LIST
- avtext_print_section_footer(w);
+ avtext_print_section_footer(tfc);
break;
}
}
@@ -926,20 +926,20 @@ static void print_film_grain_params(AVTextFormatContext *w,
av_bprint_finalize(&pbuf, NULL);
}
-static void print_pkt_side_data(AVTextFormatContext *w,
+static void print_pkt_side_data(AVTextFormatContext *tfc,
AVCodecParameters *par,
const AVPacketSideData *sd,
SectionID id_data)
{
const char *name = av_packet_side_data_name(sd->type);
- avtext_print_section_header(w, sd, id_data);
+ avtext_print_section_header(tfc, sd, id_data);
print_str("side_data_type", name ? name : "unknown");
if (sd->type == AV_PKT_DATA_DISPLAYMATRIX && sd->size >= 9*4) {
double rotation = av_display_rotation_get((int32_t *)sd->data);
if (isnan(rotation))
rotation = 0;
- avtext_print_integers(w, "displaymatrix", sd->data, 9, " %11d", 3, 4, 1);
+ avtext_print_integers(tfc, "displaymatrix", sd->data, 9, " %11d", 3, 4, 1);
print_int("rotation", rotation);
} else if (sd->type == AV_PKT_DATA_STEREO3D) {
const AVStereo3D *stereo = (AVStereo3D *)sd->data;
@@ -998,10 +998,10 @@ static void print_pkt_side_data(AVTextFormatContext *w,
print_int("max_average", metadata->MaxFALL);
} else if (sd->type == AV_PKT_DATA_AMBIENT_VIEWING_ENVIRONMENT) {
print_ambient_viewing_environment(
- w, (const AVAmbientViewingEnvironment *)sd->data);
+ tfc, (const AVAmbientViewingEnvironment *)sd->data);
} else if (sd->type == AV_PKT_DATA_DYNAMIC_HDR10_PLUS) {
AVDynamicHDRPlus *metadata = (AVDynamicHDRPlus *)sd->data;
- print_dynamic_hdr10_plus(w, metadata);
+ print_dynamic_hdr10_plus(tfc, metadata);
} else if (sd->type == AV_PKT_DATA_DOVI_CONF) {
AVDOVIDecoderConfigurationRecord *dovi = (AVDOVIDecoderConfigurationRecord *)sd->data;
const char *comp = "unknown";
@@ -1036,8 +1036,8 @@ static void print_pkt_side_data(AVTextFormatContext *w,
} else if (sd->type == AV_PKT_DATA_WEBVTT_IDENTIFIER ||
sd->type == AV_PKT_DATA_WEBVTT_SETTINGS) {
if (do_show_data)
- avtext_print_data(w, "data", sd->data, sd->size);
- avtext_print_data_hash(w, "data_hash", sd->data, sd->size);
+ avtext_print_data(tfc, "data", sd->data, sd->size);
+ avtext_print_data_hash(tfc, "data_hash", sd->data, sd->size);
} else if (sd->type == AV_PKT_DATA_FRAME_CROPPING && sd->size >= sizeof(uint32_t) * 4) {
print_int("crop_top", AV_RL32(sd->data));
print_int("crop_bottom", AV_RL32(sd->data + 4));
@@ -1048,7 +1048,7 @@ static void print_pkt_side_data(AVTextFormatContext *w,
}
}
-static void print_private_data(AVTextFormatContext *w, void *priv_data)
+static void print_private_data(AVTextFormatContext *tfc, void *priv_data)
{
const AVOption *opt = NULL;
while (opt = av_opt_next(priv_data, opt)) {
@@ -1061,7 +1061,7 @@ static void print_private_data(AVTextFormatContext *w, void *priv_data)
}
}
-static void print_color_range(AVTextFormatContext *w, enum AVColorRange color_range)
+static void print_color_range(AVTextFormatContext *tfc, enum AVColorRange color_range)
{
const char *val = av_color_range_name(color_range);
if (!val || color_range == AVCOL_RANGE_UNSPECIFIED) {
@@ -1071,7 +1071,7 @@ static void print_color_range(AVTextFormatContext *w, enum AVColorRange color_ra
}
}
-static void print_color_space(AVTextFormatContext *w, enum AVColorSpace color_space)
+static void print_color_space(AVTextFormatContext *tfc, enum AVColorSpace color_space)
{
const char *val = av_color_space_name(color_space);
if (!val || color_space == AVCOL_SPC_UNSPECIFIED) {
@@ -1081,7 +1081,7 @@ static void print_color_space(AVTextFormatContext *w, enum AVColorSpace color_sp
}
}
-static void print_primaries(AVTextFormatContext *w, enum AVColorPrimaries color_primaries)
+static void print_primaries(AVTextFormatContext *tfc, enum AVColorPrimaries color_primaries)
{
const char *val = av_color_primaries_name(color_primaries);
if (!val || color_primaries == AVCOL_PRI_UNSPECIFIED) {
@@ -1091,7 +1091,7 @@ static void print_primaries(AVTextFormatContext *w, enum AVColorPrimaries color_
}
}
-static void print_color_trc(AVTextFormatContext *w, enum AVColorTransferCharacteristic color_trc)
+static void print_color_trc(AVTextFormatContext *tfc, enum AVColorTransferCharacteristic color_trc)
{
const char *val = av_color_transfer_name(color_trc);
if (!val || color_trc == AVCOL_TRC_UNSPECIFIED) {
@@ -1101,7 +1101,7 @@ static void print_color_trc(AVTextFormatContext *w, enum AVColorTransferCharacte
}
}
-static void print_chroma_location(AVTextFormatContext *w, enum AVChromaLocation chroma_location)
+static void print_chroma_location(AVTextFormatContext *tfc, enum AVChromaLocation chroma_location)
{
const char *val = av_chroma_location_name(chroma_location);
if (!val || chroma_location == AVCHROMA_LOC_UNSPECIFIED) {
@@ -1127,7 +1127,7 @@ static void clear_log(int need_lock)
ff_mutex_unlock(&log_mutex);
}
-static int show_log(AVTextFormatContext *w, int section_ids, int section_id, int log_level)
+static int show_log(AVTextFormatContext *tfc, int section_ids, int section_id, int log_level)
{
int i;
ff_mutex_lock(&log_mutex);
@@ -1135,11 +1135,11 @@ static int show_log(AVTextFormatContext *w, int section_ids, int section_id, int
ff_mutex_unlock(&log_mutex);
return 0;
}
- avtext_print_section_header(w, NULL, section_ids);
+ avtext_print_section_header(tfc, NULL, section_ids);
for (i=0; i<log_buffer_size; i++) {
if (log_buffer[i].log_level <= log_level) {
- avtext_print_section_header(w, NULL, section_id);
+ avtext_print_section_header(tfc, NULL, section_id);
print_str("context", log_buffer[i].context_name);
print_int("level", log_buffer[i].log_level);
print_int("category", log_buffer[i].category);
@@ -1151,18 +1151,18 @@ static int show_log(AVTextFormatContext *w, int section_ids, int section_id, int
print_str_opt("parent_category", "N/A");
}
print_str("message", log_buffer[i].log_message);
- avtext_print_section_footer(w);
+ avtext_print_section_footer(tfc);
}
}
clear_log(0);
ff_mutex_unlock(&log_mutex);
- avtext_print_section_footer(w);
+ avtext_print_section_footer(tfc);
return 0;
}
-static void show_packet(AVTextFormatContext *w, InputFile *ifile, AVPacket *pkt, int packet_idx)
+static void show_packet(AVTextFormatContext *tfc, InputFile *ifile, AVPacket *pkt, int packet_idx)
{
AVStream *st = ifile->streams[pkt->stream_index].st;
AVBPrint pbuf;
@@ -1170,7 +1170,7 @@ static void show_packet(AVTextFormatContext *w, InputFile *ifile, AVPacket *pkt,
av_bprint_init(&pbuf, 1, AV_BPRINT_SIZE_UNLIMITED);
- avtext_print_section_header(w, NULL, SECTION_ID_PACKET);
+ avtext_print_section_header(tfc, NULL, SECTION_ID_PACKET);
s = av_get_media_type_string(st->codecpar->codec_type);
if (s) print_str ("codec_type", s);
@@ -1189,8 +1189,8 @@ static void show_packet(AVTextFormatContext *w, InputFile *ifile, AVPacket *pkt,
pkt->flags & AV_PKT_FLAG_DISCARD ? 'D' : '_',
pkt->flags & AV_PKT_FLAG_CORRUPT ? 'C' : '_');
if (do_show_data)
- avtext_print_data(w, "data", pkt->data, pkt->size);
- avtext_print_data_hash(w, "data_hash", pkt->data, pkt->size);
+ avtext_print_data(tfc, "data", pkt->data, pkt->size);
+ avtext_print_data_hash(tfc, "data_hash", pkt->data, pkt->size);
if (pkt->side_data_elems) {
size_t size;
@@ -1200,33 +1200,33 @@ static void show_packet(AVTextFormatContext *w, InputFile *ifile, AVPacket *pkt,
if (side_metadata && size && do_show_packet_tags) {
AVDictionary *dict = NULL;
if (av_packet_unpack_dictionary(side_metadata, size, &dict) >= 0)
- show_tags(w, dict, SECTION_ID_PACKET_TAGS);
+ show_tags(tfc, dict, SECTION_ID_PACKET_TAGS);
av_dict_free(&dict);
}
- avtext_print_section_header(w, NULL, SECTION_ID_PACKET_SIDE_DATA_LIST);
+ avtext_print_section_header(tfc, NULL, SECTION_ID_PACKET_SIDE_DATA_LIST);
for (int i = 0; i < pkt->side_data_elems; i++) {
- print_pkt_side_data(w, st->codecpar, &pkt->side_data[i],
+ print_pkt_side_data(tfc, st->codecpar, &pkt->side_data[i],
SECTION_ID_PACKET_SIDE_DATA);
- avtext_print_section_footer(w);
+ avtext_print_section_footer(tfc);
}
- avtext_print_section_footer(w);
+ avtext_print_section_footer(tfc);
}
- avtext_print_section_footer(w);
+ avtext_print_section_footer(tfc);
av_bprint_finalize(&pbuf, NULL);
fflush(stdout);
}
-static void show_subtitle(AVTextFormatContext *w, AVSubtitle *sub, AVStream *stream,
+static void show_subtitle(AVTextFormatContext *tfc, AVSubtitle *sub, AVStream *stream,
AVFormatContext *fmt_ctx)
{
AVBPrint pbuf;
av_bprint_init(&pbuf, 1, AV_BPRINT_SIZE_UNLIMITED);
- avtext_print_section_header(w, NULL, SECTION_ID_SUBTITLE);
+ avtext_print_section_header(tfc, NULL, SECTION_ID_SUBTITLE);
print_str ("media_type", "subtitle");
print_ts ("pts", sub->pts);
@@ -1236,30 +1236,30 @@ static void show_subtitle(AVTextFormatContext *w, AVSubtitle *sub, AVStream *str
print_int ("end_display_time", sub->end_display_time);
print_int ("num_rects", sub->num_rects);
- avtext_print_section_footer(w);
+ avtext_print_section_footer(tfc);
av_bprint_finalize(&pbuf, NULL);
fflush(stdout);
}
-static void print_frame_side_data(AVTextFormatContext *w,
+static void print_frame_side_data(AVTextFormatContext *tfc,
const AVFrame *frame,
const AVStream *stream)
{
- avtext_print_section_header(w, NULL, SECTION_ID_FRAME_SIDE_DATA_LIST);
+ avtext_print_section_header(tfc, NULL, SECTION_ID_FRAME_SIDE_DATA_LIST);
for (int i = 0; i < frame->nb_side_data; i++) {
const AVFrameSideData *sd = frame->side_data[i];
const char *name;
- avtext_print_section_header(w, sd, SECTION_ID_FRAME_SIDE_DATA);
+ avtext_print_section_header(tfc, sd, SECTION_ID_FRAME_SIDE_DATA);
name = av_frame_side_data_name(sd->type);
print_str("side_data_type", name ? name : "unknown");
if (sd->type == AV_FRAME_DATA_DISPLAYMATRIX && sd->size >= 9*4) {
double rotation = av_display_rotation_get((int32_t *)sd->data);
if (isnan(rotation))
rotation = 0;
- avtext_print_integers(w, "displaymatrix", sd->data, 9, " %11d", 3, 4, 1);
+ avtext_print_integers(tfc, "displaymatrix", sd->data, 9, " %11d", 3, 4, 1);
print_int("rotation", rotation);
} else if (sd->type == AV_FRAME_DATA_AFD && sd->size > 0) {
print_int("active_format", *sd->data);
@@ -1270,15 +1270,15 @@ static void print_frame_side_data(AVTextFormatContext *w,
} else if (sd->type == AV_FRAME_DATA_S12M_TIMECODE && sd->size == 16) {
uint32_t *tc = (uint32_t*)sd->data;
int m = FFMIN(tc[0],3);
- avtext_print_section_header(w, NULL, SECTION_ID_FRAME_SIDE_DATA_TIMECODE_LIST);
+ avtext_print_section_header(tfc, NULL, SECTION_ID_FRAME_SIDE_DATA_TIMECODE_LIST);
for (int j = 1; j <= m ; j++) {
char tcbuf[AV_TIMECODE_STR_SIZE];
av_timecode_make_smpte_tc_string2(tcbuf, stream->avg_frame_rate, tc[j], 0, 0);
- avtext_print_section_header(w, NULL, SECTION_ID_FRAME_SIDE_DATA_TIMECODE);
+ avtext_print_section_header(tfc, NULL, SECTION_ID_FRAME_SIDE_DATA_TIMECODE);
print_str("value", tcbuf);
- avtext_print_section_footer(w);
+ avtext_print_section_footer(tfc);
}
- avtext_print_section_footer(w);
+ avtext_print_section_footer(tfc);
} else if (sd->type == AV_FRAME_DATA_MASTERING_DISPLAY_METADATA) {
AVMasteringDisplayMetadata *metadata = (AVMasteringDisplayMetadata *)sd->data;
@@ -1300,7 +1300,7 @@ static void print_frame_side_data(AVTextFormatContext *w,
}
} else if (sd->type == AV_FRAME_DATA_DYNAMIC_HDR_PLUS) {
AVDynamicHDRPlus *metadata = (AVDynamicHDRPlus *)sd->data;
- print_dynamic_hdr10_plus(w, metadata);
+ print_dynamic_hdr10_plus(tfc, metadata);
} else if (sd->type == AV_FRAME_DATA_CONTENT_LIGHT_LEVEL) {
AVContentLightMetadata *metadata = (AVContentLightMetadata *)sd->data;
print_int("max_content", metadata->MaxCLL);
@@ -1311,24 +1311,24 @@ static void print_frame_side_data(AVTextFormatContext *w,
print_str(tag->key, tag->value);
print_int("size", sd->size);
} else if (sd->type == AV_FRAME_DATA_DOVI_METADATA) {
- print_dovi_metadata(w, (const AVDOVIMetadata *)sd->data);
+ print_dovi_metadata(tfc, (const AVDOVIMetadata *)sd->data);
} else if (sd->type == AV_FRAME_DATA_DYNAMIC_HDR_VIVID) {
AVDynamicHDRVivid *metadata = (AVDynamicHDRVivid *)sd->data;
- print_dynamic_hdr_vivid(w, metadata);
+ print_dynamic_hdr_vivid(tfc, metadata);
} else if (sd->type == AV_FRAME_DATA_AMBIENT_VIEWING_ENVIRONMENT) {
- print_ambient_viewing_environment(w, (const AVAmbientViewingEnvironment *)sd->data);
+ print_ambient_viewing_environment(tfc, (const AVAmbientViewingEnvironment *)sd->data);
} else if (sd->type == AV_FRAME_DATA_FILM_GRAIN_PARAMS) {
AVFilmGrainParams *fgp = (AVFilmGrainParams *)sd->data;
- print_film_grain_params(w, fgp);
+ print_film_grain_params(tfc, fgp);
} else if (sd->type == AV_FRAME_DATA_VIEW_ID) {
print_int("view_id", *(int*)sd->data);
}
- avtext_print_section_footer(w);
+ avtext_print_section_footer(tfc);
}
- avtext_print_section_footer(w);
+ avtext_print_section_footer(tfc);
}
-static void show_frame(AVTextFormatContext *w, AVFrame *frame, AVStream *stream,
+static void show_frame(AVTextFormatContext *tfc, AVFrame *frame, AVStream *stream,
AVFormatContext *fmt_ctx)
{
FrameData *fd = frame->opaque_ref ? (FrameData*)frame->opaque_ref->data : NULL;
@@ -1338,7 +1338,7 @@ static void show_frame(AVTextFormatContext *w, AVFrame *frame, AVStream *stream,
av_bprint_init(&pbuf, 1, AV_BPRINT_SIZE_UNLIMITED);
- avtext_print_section_header(w, NULL, SECTION_ID_FRAME);
+ avtext_print_section_header(tfc, NULL, SECTION_ID_FRAME);
s = av_get_media_type_string(stream->codecpar->codec_type);
if (s) print_str ("media_type", s);
@@ -1383,11 +1383,11 @@ static void show_frame(AVTextFormatContext *w, AVFrame *frame, AVStream *stream,
print_int("lossless", !!(frame->flags & AV_FRAME_FLAG_LOSSLESS));
print_int("repeat_pict", frame->repeat_pict);
- print_color_range(w, frame->color_range);
- print_color_space(w, frame->colorspace);
- print_primaries(w, frame->color_primaries);
- print_color_trc(w, frame->color_trc);
- print_chroma_location(w, frame->chroma_location);
+ print_color_range(tfc, frame->color_range);
+ print_color_space(tfc, frame->colorspace);
+ print_primaries(tfc, frame->color_primaries);
+ print_color_trc(tfc, frame->color_trc);
+ print_chroma_location(tfc, frame->chroma_location);
break;
case AVMEDIA_TYPE_AUDIO:
@@ -1404,19 +1404,19 @@ static void show_frame(AVTextFormatContext *w, AVFrame *frame, AVStream *stream,
break;
}
if (do_show_frame_tags)
- show_tags(w, frame->metadata, SECTION_ID_FRAME_TAGS);
+ show_tags(tfc, frame->metadata, SECTION_ID_FRAME_TAGS);
if (do_show_log)
- show_log(w, SECTION_ID_FRAME_LOGS, SECTION_ID_FRAME_LOG, do_show_log);
+ show_log(tfc, SECTION_ID_FRAME_LOGS, SECTION_ID_FRAME_LOG, do_show_log);
if (frame->nb_side_data)
- print_frame_side_data(w, frame, stream);
+ print_frame_side_data(tfc, frame, stream);
- avtext_print_section_footer(w);
+ avtext_print_section_footer(tfc);
av_bprint_finalize(&pbuf, NULL);
fflush(stdout);
}
-static av_always_inline int process_frame(AVTextFormatContext *w,
+static av_always_inline int process_frame(AVTextFormatContext *tfc,
InputFile *ifile,
AVFrame *frame, const AVPacket *pkt,
int *packet_new)
@@ -1470,9 +1470,9 @@ static av_always_inline int process_frame(AVTextFormatContext *w,
nb_streams_frames[pkt->stream_index]++;
if (do_show_frames)
if (is_sub)
- show_subtitle(w, &sub, ifile->streams[pkt->stream_index].st, fmt_ctx);
+ show_subtitle(tfc, &sub, ifile->streams[pkt->stream_index].st, fmt_ctx);
else
- show_frame(w, frame, ifile->streams[pkt->stream_index].st, fmt_ctx);
+ show_frame(tfc, frame, ifile->streams[pkt->stream_index].st, fmt_ctx);
if (!is_sub && do_analyze_frames) {
for (int i = 0; i < frame->nb_side_data; i++) {
@@ -1513,7 +1513,7 @@ static void log_read_interval(const ReadInterval *interval, void *log_ctx, int l
av_log(log_ctx, log_level, "\n");
}
-static int read_interval_packets(AVTextFormatContext *w, InputFile *ifile,
+static int read_interval_packets(AVTextFormatContext *tfc, InputFile *ifile,
const ReadInterval *interval, int64_t *cur_ts)
{
AVFormatContext *fmt_ctx = ifile->fmt_ctx;
@@ -1596,7 +1596,7 @@ static int read_interval_packets(AVTextFormatContext *w, InputFile *ifile,
frame_count++;
if (do_read_packets) {
if (do_show_packets)
- show_packet(w, ifile, pkt, i++);
+ show_packet(tfc, ifile, pkt, i++);
nb_streams_packets[pkt->stream_index]++;
}
if (do_read_frames) {
@@ -1612,7 +1612,7 @@ static int read_interval_packets(AVTextFormatContext *w, InputFile *ifile,
fd->pkt_pos = pkt->pos;
fd->pkt_size = pkt->size;
- while (process_frame(w, ifile, frame, pkt, &packet_new) > 0);
+ while (process_frame(tfc, ifile, frame, pkt, &packet_new) > 0);
}
}
av_packet_unref(pkt);
@@ -1622,7 +1622,7 @@ static int read_interval_packets(AVTextFormatContext *w, InputFile *ifile,
for (i = 0; i < ifile->nb_streams; i++) {
pkt->stream_index = i;
if (do_read_frames) {
- while (process_frame(w, ifile, frame, pkt, &(int){1}) > 0);
+ while (process_frame(tfc, ifile, frame, pkt, &(int){1}) > 0);
if (ifile->streams[i].dec_ctx)
avcodec_flush_buffers(ifile->streams[i].dec_ctx);
}
@@ -1638,7 +1638,7 @@ end:
return ret;
}
-static int read_packets(AVTextFormatContext *w, InputFile *ifile)
+static int read_packets(AVTextFormatContext *tfc, InputFile *ifile)
{
AVFormatContext *fmt_ctx = ifile->fmt_ctx;
int i, ret = 0;
@@ -1646,10 +1646,10 @@ static int read_packets(AVTextFormatContext *w, InputFile *ifile)
if (read_intervals_nb == 0) {
ReadInterval interval = (ReadInterval) { .has_start = 0, .has_end = 0 };
- ret = read_interval_packets(w, ifile, &interval, &cur_ts);
+ ret = read_interval_packets(tfc, ifile, &interval, &cur_ts);
} else {
for (i = 0; i < read_intervals_nb; i++) {
- ret = read_interval_packets(w, ifile, &read_intervals[i], &cur_ts);
+ ret = read_interval_packets(tfc, ifile, &read_intervals[i], &cur_ts);
if (ret < 0)
break;
}
@@ -1658,22 +1658,22 @@ static int read_packets(AVTextFormatContext *w, InputFile *ifile)
return ret;
}
-static void print_dispositions(AVTextFormatContext *w, uint32_t disposition, SectionID section_id)
+static void print_dispositions(AVTextFormatContext *tfc, uint32_t disposition, SectionID section_id)
{
- avtext_print_section_header(w, NULL, section_id);
+ avtext_print_section_header(tfc, NULL, section_id);
for (int i = 0; i < sizeof(disposition) * CHAR_BIT; i++) {
const char *disposition_str = av_disposition_to_string(1U << i);
if (disposition_str)
print_int(disposition_str, !!(disposition & (1U << i)));
}
- avtext_print_section_footer(w);
+ avtext_print_section_footer(tfc);
}
#define IN_PROGRAM 1
#define IN_STREAM_GROUP 2
-static int show_stream(AVTextFormatContext *w, AVFormatContext *fmt_ctx, int stream_idx, InputStream *ist, int container)
+static int show_stream(AVTextFormatContext *tfc, AVFormatContext *fmt_ctx, int stream_idx, InputStream *ist, int container)
{
AVStream *stream = ist->st;
AVCodecParameters *par;
@@ -1705,7 +1705,7 @@ static int show_stream(AVTextFormatContext *w, AVFormatContext *fmt_ctx, int str
av_bprint_init(&pbuf, 1, AV_BPRINT_SIZE_UNLIMITED);
- avtext_print_section_header(w, NULL, section_header[container]);
+ avtext_print_section_header(tfc, NULL, section_header[container]);
print_int("index", stream->index);
@@ -1774,11 +1774,11 @@ static int show_stream(AVTextFormatContext *w, AVFormatContext *fmt_ctx, int str
else print_str_opt("pix_fmt", "unknown");
print_int("level", par->level);
- print_color_range(w, par->color_range);
- print_color_space(w, par->color_space);
- print_color_trc(w, par->color_trc);
- print_primaries(w, par->color_primaries);
- print_chroma_location(w, par->chroma_location);
+ print_color_range(tfc, par->color_range);
+ print_color_space(tfc, par->color_space);
+ print_color_trc(tfc, par->color_trc);
+ print_primaries(tfc, par->color_primaries);
+ print_chroma_location(tfc, par->chroma_location);
if (par->field_order == AV_FIELD_PROGRESSIVE)
print_str("field_order", "progressive");
@@ -1830,9 +1830,9 @@ static int show_stream(AVTextFormatContext *w, AVFormatContext *fmt_ctx, int str
if (show_private_data) {
if (dec_ctx && dec_ctx->codec->priv_class)
- print_private_data(w, dec_ctx->priv_data);
+ print_private_data(tfc, dec_ctx->priv_data);
if (fmt_ctx->iformat->priv_class)
- print_private_data(w, fmt_ctx->priv_data);
+ print_private_data(tfc, fmt_ctx->priv_data);
}
if (fmt_ctx->iformat->flags & AVFMT_SHOW_IDS) print_fmt ("id", "0x%x", stream->id);
@@ -1859,113 +1859,113 @@ static int show_stream(AVTextFormatContext *w, AVFormatContext *fmt_ctx, int str
if (nb_streams_packets[stream_idx]) print_fmt ("nb_read_packets", "%"PRIu64, nb_streams_packets[stream_idx]);
else print_str_opt("nb_read_packets", "N/A");
if (do_show_data)
- avtext_print_data(w, "extradata", par->extradata,
+ avtext_print_data(tfc, "extradata", par->extradata,
par->extradata_size);
if (par->extradata_size > 0) {
print_int("extradata_size", par->extradata_size);
- avtext_print_data_hash(w, "extradata_hash", par->extradata,
+ avtext_print_data_hash(tfc, "extradata_hash", par->extradata,
par->extradata_size);
}
/* Print disposition information */
if (do_show_stream_disposition) {
av_assert0(container < FF_ARRAY_ELEMS(section_disposition));
- print_dispositions(w, stream->disposition, section_disposition[container]);
+ print_dispositions(tfc, stream->disposition, section_disposition[container]);
}
if (do_show_stream_tags) {
av_assert0(container < FF_ARRAY_ELEMS(section_tags));
- ret = show_tags(w, stream->metadata, section_tags[container]);
+ ret = show_tags(tfc, stream->metadata, section_tags[container]);
}
if (stream->codecpar->nb_coded_side_data) {
- avtext_print_section_header(w, NULL, SECTION_ID_STREAM_SIDE_DATA_LIST);
+ avtext_print_section_header(tfc, NULL, SECTION_ID_STREAM_SIDE_DATA_LIST);
for (int i = 0; i < stream->codecpar->nb_coded_side_data; i++) {
- print_pkt_side_data(w, stream->codecpar, &stream->codecpar->coded_side_data[i],
+ print_pkt_side_data(tfc, stream->codecpar, &stream->codecpar->coded_side_data[i],
SECTION_ID_STREAM_SIDE_DATA);
- avtext_print_section_footer(w);
+ avtext_print_section_footer(tfc);
}
- avtext_print_section_footer(w);
+ avtext_print_section_footer(tfc);
}
- avtext_print_section_footer(w);
+ avtext_print_section_footer(tfc);
av_bprint_finalize(&pbuf, NULL);
fflush(stdout);
return ret;
}
-static int show_streams(AVTextFormatContext *w, InputFile *ifile)
+static int show_streams(AVTextFormatContext *tfc, InputFile *ifile)
{
AVFormatContext *fmt_ctx = ifile->fmt_ctx;
int i, ret = 0;
- avtext_print_section_header(w, NULL, SECTION_ID_STREAMS);
+ avtext_print_section_header(tfc, NULL, SECTION_ID_STREAMS);
for (i = 0; i < ifile->nb_streams; i++)
if (selected_streams[i]) {
- ret = show_stream(w, fmt_ctx, i, &ifile->streams[i], 0);
+ ret = show_stream(tfc, fmt_ctx, i, &ifile->streams[i], 0);
if (ret < 0)
break;
}
- avtext_print_section_footer(w);
+ avtext_print_section_footer(tfc);
return ret;
}
-static int show_program(AVTextFormatContext *w, InputFile *ifile, AVProgram *program)
+static int show_program(AVTextFormatContext *tfc, InputFile *ifile, AVProgram *program)
{
AVFormatContext *fmt_ctx = ifile->fmt_ctx;
int i, ret = 0;
- avtext_print_section_header(w, NULL, SECTION_ID_PROGRAM);
+ avtext_print_section_header(tfc, NULL, SECTION_ID_PROGRAM);
print_int("program_id", program->id);
print_int("program_num", program->program_num);
print_int("nb_streams", program->nb_stream_indexes);
print_int("pmt_pid", program->pmt_pid);
print_int("pcr_pid", program->pcr_pid);
if (do_show_program_tags)
- ret = show_tags(w, program->metadata, SECTION_ID_PROGRAM_TAGS);
+ ret = show_tags(tfc, program->metadata, SECTION_ID_PROGRAM_TAGS);
if (ret < 0)
goto end;
- avtext_print_section_header(w, NULL, SECTION_ID_PROGRAM_STREAMS);
+ avtext_print_section_header(tfc, NULL, SECTION_ID_PROGRAM_STREAMS);
for (i = 0; i < program->nb_stream_indexes; i++) {
if (selected_streams[program->stream_index[i]]) {
- ret = show_stream(w, fmt_ctx, program->stream_index[i], &ifile->streams[program->stream_index[i]], IN_PROGRAM);
+ ret = show_stream(tfc, fmt_ctx, program->stream_index[i], &ifile->streams[program->stream_index[i]], IN_PROGRAM);
if (ret < 0)
break;
}
}
- avtext_print_section_footer(w);
+ avtext_print_section_footer(tfc);
end:
- avtext_print_section_footer(w);
+ avtext_print_section_footer(tfc);
return ret;
}
-static int show_programs(AVTextFormatContext *w, InputFile *ifile)
+static int show_programs(AVTextFormatContext *tfc, InputFile *ifile)
{
AVFormatContext *fmt_ctx = ifile->fmt_ctx;
int i, ret = 0;
- avtext_print_section_header(w, NULL, SECTION_ID_PROGRAMS);
+ avtext_print_section_header(tfc, NULL, SECTION_ID_PROGRAMS);
for (i = 0; i < fmt_ctx->nb_programs; i++) {
AVProgram *program = fmt_ctx->programs[i];
if (!program)
continue;
- ret = show_program(w, ifile, program);
+ ret = show_program(tfc, ifile, program);
if (ret < 0)
break;
}
- avtext_print_section_footer(w);
+ avtext_print_section_footer(tfc);
return ret;
}
-static void print_tile_grid_params(AVTextFormatContext *w, const AVStreamGroup *stg,
+static void print_tile_grid_params(AVTextFormatContext *tfc, const AVStreamGroup *stg,
const AVStreamGroupTileGrid *tile_grid)
{
- avtext_print_section_header(w, stg, SECTION_ID_STREAM_GROUP_COMPONENT);
+ avtext_print_section_header(tfc, stg, SECTION_ID_STREAM_GROUP_COMPONENT);
print_int("nb_tiles", tile_grid->nb_tiles);
print_int("coded_width", tile_grid->coded_width);
print_int("coded_height", tile_grid->coded_height);
@@ -1973,19 +1973,19 @@ static void print_tile_grid_params(AVTextFormatContext *w, const AVStreamGroup *
print_int("vertical_offset", tile_grid->vertical_offset);
print_int("width", tile_grid->width);
print_int("height", tile_grid->height);
- avtext_print_section_header(w, NULL, SECTION_ID_STREAM_GROUP_SUBCOMPONENTS);
+ avtext_print_section_header(tfc, NULL, SECTION_ID_STREAM_GROUP_SUBCOMPONENTS);
for (int i = 0; i < tile_grid->nb_tiles; i++) {
- avtext_print_section_header(w, "tile_offset", SECTION_ID_STREAM_GROUP_SUBCOMPONENT);
+ avtext_print_section_header(tfc, "tile_offset", SECTION_ID_STREAM_GROUP_SUBCOMPONENT);
print_int("stream_index", tile_grid->offsets[i].idx);
print_int("tile_horizontal_offset", tile_grid->offsets[i].horizontal);
print_int("tile_vertical_offset", tile_grid->offsets[i].vertical);
- avtext_print_section_footer(w);
+ avtext_print_section_footer(tfc);
}
- avtext_print_section_footer(w);
- avtext_print_section_footer(w);
+ avtext_print_section_footer(tfc);
+ avtext_print_section_footer(tfc);
}
-static void print_iamf_param_definition(AVTextFormatContext *w, const char *name,
+static void print_iamf_param_definition(AVTextFormatContext *tfc, const char *name,
const AVIAMFParamDefinition *param, SectionID section_id)
{
SectionID subsection_id, parameter_section_id;
@@ -1993,7 +1993,7 @@ static void print_iamf_param_definition(AVTextFormatContext *w, const char *name
av_assert0(subsection_id != -1);
parameter_section_id = sections[subsection_id].children_ids[0];
av_assert0(parameter_section_id != -1);
- avtext_print_section_header(w, "IAMF Param Definition", section_id);
+ avtext_print_section_header(tfc, "IAMF Param Definition", section_id);
print_str("name", name);
print_int("nb_subblocks", param->nb_subblocks);
print_int("type", param->type);
@@ -2002,56 +2002,56 @@ static void print_iamf_param_definition(AVTextFormatContext *w, const char *name
print_int("duration", param->duration);
print_int("constant_subblock_duration", param->constant_subblock_duration);
if (param->nb_subblocks > 0)
- avtext_print_section_header(w, NULL, subsection_id);
+ avtext_print_section_header(tfc, NULL, subsection_id);
for (int i = 0; i < param->nb_subblocks; i++) {
const void *subblock = av_iamf_param_definition_get_subblock(param, i);
switch(param->type) {
case AV_IAMF_PARAMETER_DEFINITION_MIX_GAIN: {
const AVIAMFMixGain *mix = subblock;
- avtext_print_section_header(w, "IAMF Mix Gain Parameters", parameter_section_id);
+ avtext_print_section_header(tfc, "IAMF Mix Gain Parameters", parameter_section_id);
print_int("subblock_duration", mix->subblock_duration);
print_int("animation_type", mix->animation_type);
print_q("start_point_value", mix->start_point_value, '/');
print_q("end_point_value", mix->end_point_value, '/');
print_q("control_point_value", mix->control_point_value, '/');
print_q("control_point_relative_time", mix->control_point_relative_time, '/');
- avtext_print_section_footer(w); // parameter_section_id
+ avtext_print_section_footer(tfc); // parameter_section_id
break;
}
case AV_IAMF_PARAMETER_DEFINITION_DEMIXING: {
const AVIAMFDemixingInfo *demix = subblock;
- avtext_print_section_header(w, "IAMF Demixing Info", parameter_section_id);
+ avtext_print_section_header(tfc, "IAMF Demixing Info", parameter_section_id);
print_int("subblock_duration", demix->subblock_duration);
print_int("dmixp_mode", demix->dmixp_mode);
- avtext_print_section_footer(w); // parameter_section_id
+ avtext_print_section_footer(tfc); // parameter_section_id
break;
}
case AV_IAMF_PARAMETER_DEFINITION_RECON_GAIN: {
const AVIAMFReconGain *recon = subblock;
- avtext_print_section_header(w, "IAMF Recon Gain", parameter_section_id);
+ avtext_print_section_header(tfc, "IAMF Recon Gain", parameter_section_id);
print_int("subblock_duration", recon->subblock_duration);
- avtext_print_section_footer(w); // parameter_section_id
+ avtext_print_section_footer(tfc); // parameter_section_id
break;
}
}
}
if (param->nb_subblocks > 0)
- avtext_print_section_footer(w); // subsection_id
- avtext_print_section_footer(w); // section_id
+ avtext_print_section_footer(tfc); // subsection_id
+ avtext_print_section_footer(tfc); // section_id
}
-static void print_iamf_audio_element_params(AVTextFormatContext *w, const AVStreamGroup *stg,
+static void print_iamf_audio_element_params(AVTextFormatContext *tfc, const AVStreamGroup *stg,
const AVIAMFAudioElement *audio_element)
{
- avtext_print_section_header(w, stg, SECTION_ID_STREAM_GROUP_COMPONENT);
+ avtext_print_section_header(tfc, stg, SECTION_ID_STREAM_GROUP_COMPONENT);
print_int("nb_layers", audio_element->nb_layers);
print_int("audio_element_type", audio_element->audio_element_type);
print_int("default_w", audio_element->default_w);
- avtext_print_section_header(w, NULL, SECTION_ID_STREAM_GROUP_SUBCOMPONENTS);
+ avtext_print_section_header(tfc, NULL, SECTION_ID_STREAM_GROUP_SUBCOMPONENTS);
for (int i = 0; i < audio_element->nb_layers; i++) {
const AVIAMFLayer *layer = audio_element->layers[i];
char val_str[128];
- avtext_print_section_header(w, "IAMF Audio Layer", SECTION_ID_STREAM_GROUP_SUBCOMPONENT);
+ avtext_print_section_header(tfc, "IAMF Audio Layer", SECTION_ID_STREAM_GROUP_SUBCOMPONENT);
av_channel_layout_describe(&layer->ch_layout, val_str, sizeof(val_str));
print_str("channel_layout", val_str);
if (audio_element->audio_element_type == AV_IAMF_AUDIO_ELEMENT_TYPE_CHANNEL) {
@@ -2059,52 +2059,52 @@ static void print_iamf_audio_element_params(AVTextFormatContext *w, const AVStre
print_q("output_gain", layer->output_gain, '/');
} else if (audio_element->audio_element_type == AV_IAMF_AUDIO_ELEMENT_TYPE_SCENE)
print_int("ambisonics_mode", layer->ambisonics_mode);
- avtext_print_section_footer(w); // SECTION_ID_STREAM_GROUP_SUBCOMPONENT
+ avtext_print_section_footer(tfc); // SECTION_ID_STREAM_GROUP_SUBCOMPONENT
}
if (audio_element->demixing_info)
- print_iamf_param_definition(w, "demixing_info", audio_element->demixing_info,
+ print_iamf_param_definition(tfc, "demixing_info", audio_element->demixing_info,
SECTION_ID_STREAM_GROUP_SUBCOMPONENT);
if (audio_element->recon_gain_info)
- print_iamf_param_definition(w, "recon_gain_info", audio_element->recon_gain_info,
+ print_iamf_param_definition(tfc, "recon_gain_info", audio_element->recon_gain_info,
SECTION_ID_STREAM_GROUP_SUBCOMPONENT);
- avtext_print_section_footer(w); // SECTION_ID_STREAM_GROUP_SUBCOMPONENTS
- avtext_print_section_footer(w); // SECTION_ID_STREAM_GROUP_COMPONENT
+ avtext_print_section_footer(tfc); // SECTION_ID_STREAM_GROUP_SUBCOMPONENTS
+ avtext_print_section_footer(tfc); // SECTION_ID_STREAM_GROUP_COMPONENT
}
-static void print_iamf_submix_params(AVTextFormatContext *w, const AVIAMFSubmix *submix)
+static void print_iamf_submix_params(AVTextFormatContext *tfc, const AVIAMFSubmix *submix)
{
- avtext_print_section_header(w, "IAMF Submix", SECTION_ID_STREAM_GROUP_SUBCOMPONENT);
+ avtext_print_section_header(tfc, "IAMF Submix", SECTION_ID_STREAM_GROUP_SUBCOMPONENT);
print_int("nb_elements", submix->nb_elements);
print_int("nb_layouts", submix->nb_layouts);
print_q("default_mix_gain", submix->default_mix_gain, '/');
- avtext_print_section_header(w, NULL, SECTION_ID_STREAM_GROUP_PIECES);
+ avtext_print_section_header(tfc, NULL, SECTION_ID_STREAM_GROUP_PIECES);
for (int i = 0; i < submix->nb_elements; i++) {
const AVIAMFSubmixElement *element = submix->elements[i];
- avtext_print_section_header(w, "IAMF Submix Element", SECTION_ID_STREAM_GROUP_PIECE);
+ avtext_print_section_header(tfc, "IAMF Submix Element", SECTION_ID_STREAM_GROUP_PIECE);
print_int("stream_id", element->audio_element_id);
print_q("default_mix_gain", element->default_mix_gain, '/');
print_int("headphones_rendering_mode", element->headphones_rendering_mode);
- avtext_print_section_header(w, NULL, SECTION_ID_STREAM_GROUP_SUBPIECES);
+ avtext_print_section_header(tfc, NULL, SECTION_ID_STREAM_GROUP_SUBPIECES);
if (element->annotations) {
const AVDictionaryEntry *annotation = NULL;
- avtext_print_section_header(w, "IAMF Annotations", SECTION_ID_STREAM_GROUP_SUBPIECE);
+ avtext_print_section_header(tfc, "IAMF Annotations", SECTION_ID_STREAM_GROUP_SUBPIECE);
while (annotation = av_dict_iterate(element->annotations, annotation))
print_str(annotation->key, annotation->value);
- avtext_print_section_footer(w); // SECTION_ID_STREAM_GROUP_SUBPIECE
+ avtext_print_section_footer(tfc); // SECTION_ID_STREAM_GROUP_SUBPIECE
}
if (element->element_mix_config)
- print_iamf_param_definition(w, "element_mix_config", element->element_mix_config,
+ print_iamf_param_definition(tfc, "element_mix_config", element->element_mix_config,
SECTION_ID_STREAM_GROUP_SUBPIECE);
- avtext_print_section_footer(w); // SECTION_ID_STREAM_GROUP_SUBPIECES
- avtext_print_section_footer(w); // SECTION_ID_STREAM_GROUP_PIECE
+ avtext_print_section_footer(tfc); // SECTION_ID_STREAM_GROUP_SUBPIECES
+ avtext_print_section_footer(tfc); // SECTION_ID_STREAM_GROUP_PIECE
}
if (submix->output_mix_config)
- print_iamf_param_definition(w, "output_mix_config", submix->output_mix_config,
+ print_iamf_param_definition(tfc, "output_mix_config", submix->output_mix_config,
SECTION_ID_STREAM_GROUP_PIECE);
for (int i = 0; i < submix->nb_layouts; i++) {
const AVIAMFSubmixLayout *layout = submix->layouts[i];
char val_str[128];
- avtext_print_section_header(w, "IAMF Submix Layout", SECTION_ID_STREAM_GROUP_PIECE);
+ avtext_print_section_header(tfc, "IAMF Submix Layout", SECTION_ID_STREAM_GROUP_PIECE);
av_channel_layout_describe(&layout->sound_system, val_str, sizeof(val_str));
print_str("sound_system", val_str);
print_q("integrated_loudness", layout->integrated_loudness, '/');
@@ -2112,51 +2112,51 @@ static void print_iamf_submix_params(AVTextFormatContext *w, const AVIAMFSubmix
print_q("true_peak", layout->true_peak, '/');
print_q("dialogue_anchored_loudness", layout->dialogue_anchored_loudness, '/');
print_q("album_anchored_loudness", layout->album_anchored_loudness, '/');
- avtext_print_section_footer(w); // SECTION_ID_STREAM_GROUP_PIECE
+ avtext_print_section_footer(tfc); // SECTION_ID_STREAM_GROUP_PIECE
}
- avtext_print_section_footer(w); // SECTION_ID_STREAM_GROUP_PIECES
- avtext_print_section_footer(w); // SECTION_ID_STREAM_GROUP_SUBCOMPONENT
+ avtext_print_section_footer(tfc); // SECTION_ID_STREAM_GROUP_PIECES
+ avtext_print_section_footer(tfc); // SECTION_ID_STREAM_GROUP_SUBCOMPONENT
}
-static void print_iamf_mix_presentation_params(AVTextFormatContext *w, const AVStreamGroup *stg,
+static void print_iamf_mix_presentation_params(AVTextFormatContext *tfc, const AVStreamGroup *stg,
const AVIAMFMixPresentation *mix_presentation)
{
- avtext_print_section_header(w, stg, SECTION_ID_STREAM_GROUP_COMPONENT);
+ avtext_print_section_header(tfc, stg, SECTION_ID_STREAM_GROUP_COMPONENT);
print_int("nb_submixes", mix_presentation->nb_submixes);
- avtext_print_section_header(w, NULL, SECTION_ID_STREAM_GROUP_SUBCOMPONENTS);
+ avtext_print_section_header(tfc, NULL, SECTION_ID_STREAM_GROUP_SUBCOMPONENTS);
if (mix_presentation->annotations) {
const AVDictionaryEntry *annotation = NULL;
- avtext_print_section_header(w, "IAMF Annotations", SECTION_ID_STREAM_GROUP_SUBCOMPONENT);
+ avtext_print_section_header(tfc, "IAMF Annotations", SECTION_ID_STREAM_GROUP_SUBCOMPONENT);
while (annotation = av_dict_iterate(mix_presentation->annotations, annotation))
print_str(annotation->key, annotation->value);
- avtext_print_section_footer(w); // SECTION_ID_STREAM_GROUP_SUBCOMPONENT
+ avtext_print_section_footer(tfc); // SECTION_ID_STREAM_GROUP_SUBCOMPONENT
}
for (int i = 0; i < mix_presentation->nb_submixes; i++)
- print_iamf_submix_params(w, mix_presentation->submixes[i]);
- avtext_print_section_footer(w); // SECTION_ID_STREAM_GROUP_SUBCOMPONENTS
- avtext_print_section_footer(w); // SECTION_ID_STREAM_GROUP_COMPONENT
+ print_iamf_submix_params(tfc, mix_presentation->submixes[i]);
+ avtext_print_section_footer(tfc); // SECTION_ID_STREAM_GROUP_SUBCOMPONENTS
+ avtext_print_section_footer(tfc); // SECTION_ID_STREAM_GROUP_COMPONENT
}
-static void print_stream_group_params(AVTextFormatContext *w, AVStreamGroup *stg)
+static void print_stream_group_params(AVTextFormatContext *tfc, AVStreamGroup *stg)
{
- avtext_print_section_header(w, NULL, SECTION_ID_STREAM_GROUP_COMPONENTS);
+ avtext_print_section_header(tfc, NULL, SECTION_ID_STREAM_GROUP_COMPONENTS);
if (stg->type == AV_STREAM_GROUP_PARAMS_TILE_GRID)
- print_tile_grid_params(w, stg, stg->params.tile_grid);
+ print_tile_grid_params(tfc, stg, stg->params.tile_grid);
else if (stg->type == AV_STREAM_GROUP_PARAMS_IAMF_AUDIO_ELEMENT)
- print_iamf_audio_element_params(w, stg, stg->params.iamf_audio_element);
+ print_iamf_audio_element_params(tfc, stg, stg->params.iamf_audio_element);
else if (stg->type == AV_STREAM_GROUP_PARAMS_IAMF_MIX_PRESENTATION)
- print_iamf_mix_presentation_params(w, stg, stg->params.iamf_mix_presentation);
- avtext_print_section_footer(w); // SECTION_ID_STREAM_GROUP_COMPONENTS
+ print_iamf_mix_presentation_params(tfc, stg, stg->params.iamf_mix_presentation);
+ avtext_print_section_footer(tfc); // SECTION_ID_STREAM_GROUP_COMPONENTS
}
-static int show_stream_group(AVTextFormatContext *w, InputFile *ifile, AVStreamGroup *stg)
+static int show_stream_group(AVTextFormatContext *tfc, InputFile *ifile, AVStreamGroup *stg)
{
AVFormatContext *fmt_ctx = ifile->fmt_ctx;
AVBPrint pbuf;
int i, ret = 0;
av_bprint_init(&pbuf, 1, AV_BPRINT_SIZE_UNLIMITED);
- avtext_print_section_header(w, NULL, SECTION_ID_STREAM_GROUP);
+ avtext_print_section_header(tfc, NULL, SECTION_ID_STREAM_GROUP);
print_int("index", stg->index);
if (fmt_ctx->iformat->flags & AVFMT_SHOW_IDS) print_fmt ("id", "0x%"PRIx64, stg->id);
else print_str_opt("id", "N/A");
@@ -2166,60 +2166,60 @@ static int show_stream_group(AVTextFormatContext *w, InputFile *ifile, AVStreamG
else
print_str_opt("type", "unknown");
if (do_show_stream_group_components)
- print_stream_group_params(w, stg);
+ print_stream_group_params(tfc, stg);
/* Print disposition information */
if (do_show_stream_group_disposition)
- print_dispositions(w, stg->disposition, SECTION_ID_STREAM_GROUP_DISPOSITION);
+ print_dispositions(tfc, stg->disposition, SECTION_ID_STREAM_GROUP_DISPOSITION);
if (do_show_stream_group_tags)
- ret = show_tags(w, stg->metadata, SECTION_ID_STREAM_GROUP_TAGS);
+ ret = show_tags(tfc, stg->metadata, SECTION_ID_STREAM_GROUP_TAGS);
if (ret < 0)
goto end;
- avtext_print_section_header(w, NULL, SECTION_ID_STREAM_GROUP_STREAMS);
+ avtext_print_section_header(tfc, NULL, SECTION_ID_STREAM_GROUP_STREAMS);
for (i = 0; i < stg->nb_streams; i++) {
if (selected_streams[stg->streams[i]->index]) {
- ret = show_stream(w, fmt_ctx, stg->streams[i]->index, &ifile->streams[stg->streams[i]->index], IN_STREAM_GROUP);
+ ret = show_stream(tfc, fmt_ctx, stg->streams[i]->index, &ifile->streams[stg->streams[i]->index], IN_STREAM_GROUP);
if (ret < 0)
break;
}
}
- avtext_print_section_footer(w);
+ avtext_print_section_footer(tfc);
end:
av_bprint_finalize(&pbuf, NULL);
- avtext_print_section_footer(w);
+ avtext_print_section_footer(tfc);
return ret;
}
-static int show_stream_groups(AVTextFormatContext *w, InputFile *ifile)
+static int show_stream_groups(AVTextFormatContext *tfc, InputFile *ifile)
{
AVFormatContext *fmt_ctx = ifile->fmt_ctx;
int i, ret = 0;
- avtext_print_section_header(w, NULL, SECTION_ID_STREAM_GROUPS);
+ avtext_print_section_header(tfc, NULL, SECTION_ID_STREAM_GROUPS);
for (i = 0; i < fmt_ctx->nb_stream_groups; i++) {
AVStreamGroup *stg = fmt_ctx->stream_groups[i];
- ret = show_stream_group(w, ifile, stg);
+ ret = show_stream_group(tfc, ifile, stg);
if (ret < 0)
break;
}
- avtext_print_section_footer(w);
+ avtext_print_section_footer(tfc);
return ret;
}
-static int show_chapters(AVTextFormatContext *w, InputFile *ifile)
+static int show_chapters(AVTextFormatContext *tfc, InputFile *ifile)
{
AVFormatContext *fmt_ctx = ifile->fmt_ctx;
int i, ret = 0;
- avtext_print_section_header(w, NULL, SECTION_ID_CHAPTERS);
+ avtext_print_section_header(tfc, NULL, SECTION_ID_CHAPTERS);
for (i = 0; i < fmt_ctx->nb_chapters; i++) {
AVChapter *chapter = fmt_ctx->chapters[i];
- avtext_print_section_header(w, NULL, SECTION_ID_CHAPTER);
+ avtext_print_section_header(tfc, NULL, SECTION_ID_CHAPTER);
print_int("id", chapter->id);
print_q ("time_base", chapter->time_base, '/');
print_int("start", chapter->start);
@@ -2227,21 +2227,21 @@ static int show_chapters(AVTextFormatContext *w, InputFile *ifile)
print_int("end", chapter->end);
print_time("end_time", chapter->end, &chapter->time_base);
if (do_show_chapter_tags)
- ret = show_tags(w, chapter->metadata, SECTION_ID_CHAPTER_TAGS);
- avtext_print_section_footer(w);
+ ret = show_tags(tfc, chapter->metadata, SECTION_ID_CHAPTER_TAGS);
+ avtext_print_section_footer(tfc);
}
- avtext_print_section_footer(w);
+ avtext_print_section_footer(tfc);
return ret;
}
-static int show_format(AVTextFormatContext *w, InputFile *ifile)
+static int show_format(AVTextFormatContext *tfc, InputFile *ifile)
{
AVFormatContext *fmt_ctx = ifile->fmt_ctx;
int64_t size = fmt_ctx->pb ? avio_size(fmt_ctx->pb) : -1;
int ret = 0;
- avtext_print_section_header(w, NULL, SECTION_ID_FORMAT);
+ avtext_print_section_header(tfc, NULL, SECTION_ID_FORMAT);
print_str_validate("filename", fmt_ctx->url);
print_int("nb_streams", fmt_ctx->nb_streams);
print_int("nb_programs", fmt_ctx->nb_programs);
@@ -2259,19 +2259,19 @@ static int show_format(AVTextFormatContext *w, InputFile *ifile)
else print_str_opt("bit_rate", "N/A");
print_int("probe_score", fmt_ctx->probe_score);
if (do_show_format_tags)
- ret = show_tags(w, fmt_ctx->metadata, SECTION_ID_FORMAT_TAGS);
+ ret = show_tags(tfc, fmt_ctx->metadata, SECTION_ID_FORMAT_TAGS);
- avtext_print_section_footer(w);
+ avtext_print_section_footer(tfc);
fflush(stdout);
return ret;
}
-static void show_error(AVTextFormatContext *w, int err)
+static void show_error(AVTextFormatContext *tfc, int err)
{
- avtext_print_section_header(w, NULL, SECTION_ID_ERROR);
+ avtext_print_section_header(tfc, NULL, SECTION_ID_ERROR);
print_int("code", err);
print_str("string", av_err2str(err));
- avtext_print_section_footer(w);
+ avtext_print_section_footer(tfc);
}
static int open_input_file(InputFile *ifile, const char *filename,
@@ -2413,7 +2413,7 @@ static void close_input_file(InputFile *ifile)
avformat_close_input(&ifile->fmt_ctx);
}
-static int probe_file(AVTextFormatContext *tctx, const char *filename,
+static int probe_file(AVTextFormatContext *tfc, const char *filename,
const char *print_filename)
{
InputFile ifile = { 0 };
@@ -2455,40 +2455,40 @@ static int probe_file(AVTextFormatContext *tctx, const char *filename,
if (do_read_frames || do_read_packets) {
if (do_show_frames && do_show_packets &&
- tctx->formatter->flags & AV_TEXTFORMAT_FLAG_SUPPORTS_MIXED_ARRAY_CONTENT)
+ tfc->formatter->flags & AV_TEXTFORMAT_FLAG_SUPPORTS_MIXED_ARRAY_CONTENT)
section_id = SECTION_ID_PACKETS_AND_FRAMES;
else if (do_show_packets && !do_show_frames)
section_id = SECTION_ID_PACKETS;
else // (!do_show_packets && do_show_frames)
section_id = SECTION_ID_FRAMES;
if (do_show_frames || do_show_packets)
- avtext_print_section_header(tctx, NULL, section_id);
- ret = read_packets(tctx, &ifile);
+ avtext_print_section_header(tfc, NULL, section_id);
+ ret = read_packets(tfc, &ifile);
if (do_show_frames || do_show_packets)
- avtext_print_section_footer(tctx);
+ avtext_print_section_footer(tfc);
CHECK_END;
}
if (do_show_programs) {
- ret = show_programs(tctx, &ifile);
+ ret = show_programs(tfc, &ifile);
CHECK_END;
}
if (do_show_stream_groups) {
- ret = show_stream_groups(tctx, &ifile);
+ ret = show_stream_groups(tfc, &ifile);
CHECK_END;
}
if (do_show_streams) {
- ret = show_streams(tctx, &ifile);
+ ret = show_streams(tfc, &ifile);
CHECK_END;
}
if (do_show_chapters) {
- ret = show_chapters(tctx, &ifile);
+ ret = show_chapters(tfc, &ifile);
CHECK_END;
}
if (do_show_format) {
- ret = show_format(tctx, &ifile);
+ ret = show_format(tfc, &ifile);
CHECK_END;
}
@@ -2511,18 +2511,18 @@ static void show_usage(void)
av_log(NULL, AV_LOG_INFO, "\n");
}
-static void ffprobe_show_program_version(AVTextFormatContext *w)
+static void ffprobe_show_program_version(AVTextFormatContext *tfc)
{
AVBPrint pbuf;
av_bprint_init(&pbuf, 1, AV_BPRINT_SIZE_UNLIMITED);
- avtext_print_section_header(w, NULL, SECTION_ID_PROGRAM_VERSION);
+ avtext_print_section_header(tfc, NULL, SECTION_ID_PROGRAM_VERSION);
print_str("version", FFMPEG_VERSION);
print_fmt("copyright", "Copyright (c) %d-%d the FFmpeg developers",
program_birth_year, CONFIG_THIS_YEAR);
print_str("compiler_ident", CC_IDENT);
print_str("configuration", FFMPEG_CONFIGURATION);
- avtext_print_section_footer(w);
+ avtext_print_section_footer(tfc);
av_bprint_finalize(&pbuf, NULL);
}
@@ -2531,20 +2531,20 @@ static void ffprobe_show_program_version(AVTextFormatContext *w)
do { \
if (CONFIG_##LIBNAME) { \
unsigned int version = libname##_version(); \
- avtext_print_section_header(w, NULL, SECTION_ID_LIBRARY_VERSION); \
+ avtext_print_section_header(tfc, NULL, SECTION_ID_LIBRARY_VERSION); \
print_str("name", "lib" #libname); \
print_int("major", LIB##LIBNAME##_VERSION_MAJOR); \
print_int("minor", LIB##LIBNAME##_VERSION_MINOR); \
print_int("micro", LIB##LIBNAME##_VERSION_MICRO); \
print_int("version", version); \
print_str("ident", LIB##LIBNAME##_IDENT); \
- avtext_print_section_footer(w); \
+ avtext_print_section_footer(tfc); \
} \
} while (0)
-static void ffprobe_show_library_versions(AVTextFormatContext *w)
+static void ffprobe_show_library_versions(AVTextFormatContext *tfc)
{
- avtext_print_section_header(w, NULL, SECTION_ID_LIBRARY_VERSIONS);
+ avtext_print_section_header(tfc, NULL, SECTION_ID_LIBRARY_VERSIONS);
SHOW_LIB_VERSION(avutil, AVUTIL);
SHOW_LIB_VERSION(avcodec, AVCODEC);
SHOW_LIB_VERSION(avformat, AVFORMAT);
@@ -2553,7 +2553,7 @@ static void ffprobe_show_library_versions(AVTextFormatContext *w)
SHOW_LIB_VERSION(swscale, SWSCALE);
SHOW_LIB_VERSION(swresample, SWRESAMPLE);
SHOW_LIB_VERSION(postproc, POSTPROC);
- avtext_print_section_footer(w);
+ avtext_print_section_footer(tfc);
}
#define PRINT_PIX_FMT_FLAG(flagname, name) \
@@ -2561,14 +2561,14 @@ static void ffprobe_show_library_versions(AVTextFormatContext *w)
print_int(name, !!(pixdesc->flags & AV_PIX_FMT_FLAG_##flagname)); \
} while (0)
-static void ffprobe_show_pixel_formats(AVTextFormatContext *w)
+static void ffprobe_show_pixel_formats(AVTextFormatContext *tfc)
{
const AVPixFmtDescriptor *pixdesc = NULL;
int i, n;
- avtext_print_section_header(w, NULL, SECTION_ID_PIXEL_FORMATS);
+ avtext_print_section_header(tfc, NULL, SECTION_ID_PIXEL_FORMATS);
while (pixdesc = av_pix_fmt_desc_next(pixdesc)) {
- avtext_print_section_header(w, NULL, SECTION_ID_PIXEL_FORMAT);
+ avtext_print_section_header(tfc, NULL, SECTION_ID_PIXEL_FORMAT);
print_str("name", pixdesc->name);
print_int("nb_components", pixdesc->nb_components);
if ((pixdesc->nb_components >= 3) && !(pixdesc->flags & AV_PIX_FMT_FLAG_RGB)) {
@@ -2582,7 +2582,7 @@ static void ffprobe_show_pixel_formats(AVTextFormatContext *w)
if (n) print_int ("bits_per_pixel", n);
else print_str_opt("bits_per_pixel", "N/A");
if (do_show_pixel_format_flags) {
- avtext_print_section_header(w, NULL, SECTION_ID_PIXEL_FORMAT_FLAGS);
+ avtext_print_section_header(tfc, NULL, SECTION_ID_PIXEL_FORMAT_FLAGS);
PRINT_PIX_FMT_FLAG(BE, "big_endian");
PRINT_PIX_FMT_FLAG(PAL, "palette");
PRINT_PIX_FMT_FLAG(BITSTREAM, "bitstream");
@@ -2590,21 +2590,21 @@ static void ffprobe_show_pixel_formats(AVTextFormatContext *w)
PRINT_PIX_FMT_FLAG(PLANAR, "planar");
PRINT_PIX_FMT_FLAG(RGB, "rgb");
PRINT_PIX_FMT_FLAG(ALPHA, "alpha");
- avtext_print_section_footer(w);
+ avtext_print_section_footer(tfc);
}
if (do_show_pixel_format_components && (pixdesc->nb_components > 0)) {
- avtext_print_section_header(w, NULL, SECTION_ID_PIXEL_FORMAT_COMPONENTS);
+ avtext_print_section_header(tfc, NULL, SECTION_ID_PIXEL_FORMAT_COMPONENTS);
for (i = 0; i < pixdesc->nb_components; i++) {
- avtext_print_section_header(w, NULL, SECTION_ID_PIXEL_FORMAT_COMPONENT);
+ avtext_print_section_header(tfc, NULL, SECTION_ID_PIXEL_FORMAT_COMPONENT);
print_int("index", i + 1);
print_int("bit_depth", pixdesc->comp[i].depth);
- avtext_print_section_footer(w);
+ avtext_print_section_footer(tfc);
}
- avtext_print_section_footer(w);
+ avtext_print_section_footer(tfc);
}
- avtext_print_section_footer(w);
+ avtext_print_section_footer(tfc);
}
- avtext_print_section_footer(w);
+ avtext_print_section_footer(tfc);
}
static int opt_show_optional_fields(void *optctx, const char *opt, const char *arg)
--
ffmpeg-codebot
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 108+ messages in thread
* Re: [FFmpeg-devel] [PATCH v8 0/4] print_graphs: Complete Filtergraph Printing
2025-03-19 17:04 ` [FFmpeg-devel] [PATCH v8 0/4] print_graphs: Complete Filtergraph Printing ffmpegagent
` (3 preceding siblings ...)
2025-03-19 17:04 ` [FFmpeg-devel] [PATCH v8 4/4] fftools/ffprobe: Rename AVTextFormatContext variables (w => tfc) softworkz
@ 2025-03-21 18:04 ` Stefano Sabatini
2025-03-21 18:52 ` Soft Works
2025-03-23 3:42 ` [FFmpeg-devel] [PATCH v9 " ffmpegagent
5 siblings, 1 reply; 108+ messages in thread
From: Stefano Sabatini @ 2025-03-21 18:04 UTC (permalink / raw)
To: FFmpeg development discussions and patches; +Cc: softworkz
On date Wednesday 2025-03-19 17:04:09 +0000, ffmpegagent wrote:
> Due to the additional work on graph visualization (see
> https://lists.ffmpeg.org/pipermail/ffmpeg-devel/2025-March/341296.html), I
> have removed the two graph printing commits from this patchset rather than
> adding to it, as to avoid wasting the effort already spent on reviewing.
>
> So, now it's a graph printing patchset without graph printing :-)
>
> All other commits are unchanged from the previous version. I'm also
> resubmitting to give it a final run of the tests on various platforms.
>
> Thanks
>
> softworkz (4):
> fftools/textformat: Extract and generalize textformat api from
> ffprobe.c
> fftools/ffprobe: Change to use textformat api
> fftools/ffprobe: Rename writer_print_section_* and WriterContext
> fftools/ffprobe: Rename AVTextFormatContext variables (w => tfc)
I'm fine with the changes assuming it passes fate.
I don't know if you have push commit rights, if needed I will locally
test and push them after a few days to let other developers to
comment.
Thanks.
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 108+ messages in thread
* Re: [FFmpeg-devel] [PATCH v8 0/4] print_graphs: Complete Filtergraph Printing
2025-03-21 18:04 ` [FFmpeg-devel] [PATCH v8 0/4] print_graphs: Complete Filtergraph Printing Stefano Sabatini
@ 2025-03-21 18:52 ` Soft Works
2025-03-22 0:12 ` Michael Niedermayer
0 siblings, 1 reply; 108+ messages in thread
From: Soft Works @ 2025-03-21 18:52 UTC (permalink / raw)
To: Stefano Sabatini, FFmpeg development discussions and patches
> -----Original Message-----
> From: Stefano Sabatini <stefasab@gmail.com>
> Sent: Freitag, 21. März 2025 19:05
> To: FFmpeg development discussions and patches <ffmpeg-devel@ffmpeg.org>
> Cc: softworkz <softworkz@hotmail.com>
> Subject: Re: [FFmpeg-devel] [PATCH v8 0/4] print_graphs: Complete
> Filtergraph Printing
>
> On date Wednesday 2025-03-19 17:04:09 +0000, ffmpegagent wrote:
> > Due to the additional work on graph visualization (see
> > https://lists.ffmpeg.org/pipermail/ffmpeg-devel/2025-
> March/341296.html), I
> > have removed the two graph printing commits from this patchset rather
> than
> > adding to it, as to avoid wasting the effort already spent on
> reviewing.
> >
> > So, now it's a graph printing patchset without graph printing :-)
> >
> > All other commits are unchanged from the previous version. I'm also
> > resubmitting to give it a final run of the tests on various platforms.
> >
> > Thanks
> >
> > softworkz (4):
> > fftools/textformat: Extract and generalize textformat api from
> > ffprobe.c
> > fftools/ffprobe: Change to use textformat api
> > fftools/ffprobe: Rename writer_print_section_* and WriterContext
> > fftools/ffprobe: Rename AVTextFormatContext variables (w => tfc)
>
> I'm fine with the changes assuming it passes fate.
It's all green on Patchwork and on the GitHub CI, as well as locally.
Michael had reported a file-not-found compilation error with an x86-32 target. It appears to be an issue with ccache and the fact that there's a new subfolder (which rarely happens).
I used the same configure he gave me (except no ccache) and couldn't reproduce.
> I don't know if you have push commit rights,
I was going to ask Michael about it, but for now it would be great when you would be able to push it.
Thanks
sw
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 108+ messages in thread
* Re: [FFmpeg-devel] [PATCH v8 0/4] print_graphs: Complete Filtergraph Printing
2025-03-21 18:52 ` Soft Works
@ 2025-03-22 0:12 ` Michael Niedermayer
2025-03-22 0:46 ` Soft Works
0 siblings, 1 reply; 108+ messages in thread
From: Michael Niedermayer @ 2025-03-22 0:12 UTC (permalink / raw)
To: FFmpeg development discussions and patches
[-- Attachment #1.1: Type: text/plain, Size: 2361 bytes --]
Hi
On Fri, Mar 21, 2025 at 06:52:20PM +0000, Soft Works wrote:
>
>
> > -----Original Message-----
> > From: Stefano Sabatini <stefasab@gmail.com>
> > Sent: Freitag, 21. März 2025 19:05
> > To: FFmpeg development discussions and patches <ffmpeg-devel@ffmpeg.org>
> > Cc: softworkz <softworkz@hotmail.com>
> > Subject: Re: [FFmpeg-devel] [PATCH v8 0/4] print_graphs: Complete
> > Filtergraph Printing
> >
> > On date Wednesday 2025-03-19 17:04:09 +0000, ffmpegagent wrote:
> > > Due to the additional work on graph visualization (see
> > > https://lists.ffmpeg.org/pipermail/ffmpeg-devel/2025-
> > March/341296.html), I
> > > have removed the two graph printing commits from this patchset rather
> > than
> > > adding to it, as to avoid wasting the effort already spent on
> > reviewing.
> > >
> > > So, now it's a graph printing patchset without graph printing :-)
> > >
> > > All other commits are unchanged from the previous version. I'm also
> > > resubmitting to give it a final run of the tests on various platforms.
> > >
> > > Thanks
> > >
> > > softworkz (4):
> > > fftools/textformat: Extract and generalize textformat api from
> > > ffprobe.c
> > > fftools/ffprobe: Change to use textformat api
> > > fftools/ffprobe: Rename writer_print_section_* and WriterContext
> > > fftools/ffprobe: Rename AVTextFormatContext variables (w => tfc)
> >
> > I'm fine with the changes assuming it passes fate.
>
> It's all green on Patchwork and on the GitHub CI, as well as locally.
>
> Michael had reported a file-not-found compilation error with an x86-32 target. It appears to be an issue with ccache and the fact that there's a new subfolder (which rarely happens).
> I used the same configure he gave me (except no ccache) and couldn't reproduce.
>
> > I don't know if you have push commit rights,
>
> I was going to ask Michael about it, but for now it would be great when you would be able to push it.
Iam happy to give you push access as soon as you are listed in the
MAINTAINER file. We have used that file as a way to keep the process
of giving git access open and transparent.
Please send some patch that adds you to MAINTAINERs
thx
[...]
--
Michael GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB
You can kill me, but you cannot change the truth.
[-- Attachment #1.2: signature.asc --]
[-- Type: application/pgp-signature, Size: 195 bytes --]
[-- Attachment #2: Type: text/plain, Size: 251 bytes --]
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 108+ messages in thread
* Re: [FFmpeg-devel] [PATCH v8 0/4] print_graphs: Complete Filtergraph Printing
2025-03-22 0:12 ` Michael Niedermayer
@ 2025-03-22 0:46 ` Soft Works
0 siblings, 0 replies; 108+ messages in thread
From: Soft Works @ 2025-03-22 0:46 UTC (permalink / raw)
To: FFmpeg development discussions and patches
> -----Original Message-----
> From: ffmpeg-devel <ffmpeg-devel-bounces@ffmpeg.org> On Behalf Of
> Michael Niedermayer
> Sent: Samstag, 22. März 2025 01:12
> To: FFmpeg development discussions and patches <ffmpeg-devel@ffmpeg.org>
> Subject: Re: [FFmpeg-devel] [PATCH v8 0/4] print_graphs: Complete
> Filtergraph Printing
>
> Hi
>
> On Fri, Mar 21, 2025 at 06:52:20PM +0000, Soft Works wrote:
> >
> >
> > > -----Original Message-----
> > > From: Stefano Sabatini <stefasab@gmail.com>
> > > Sent: Freitag, 21. März 2025 19:05
> > > To: FFmpeg development discussions and patches <ffmpeg-
> devel@ffmpeg.org>
> > > Cc: softworkz <softworkz@hotmail.com>
> > > Subject: Re: [FFmpeg-devel] [PATCH v8 0/4] print_graphs: Complete
> > > Filtergraph Printing
> > >
> > > On date Wednesday 2025-03-19 17:04:09 +0000, ffmpegagent wrote:
> > > > Due to the additional work on graph visualization (see
> > > > https://lists.ffmpeg.org/pipermail/ffmpeg-devel/2025-
> > > March/341296.html), I
> > > > have removed the two graph printing commits from this patchset
> rather
> > > than
> > > > adding to it, as to avoid wasting the effort already spent on
> > > reviewing.
> > > >
> > > > So, now it's a graph printing patchset without graph printing :-)
> > > >
> > > > All other commits are unchanged from the previous version. I'm
> also
> > > > resubmitting to give it a final run of the tests on various
> platforms.
> > > >
> > > > Thanks
> > > >
> > > > softworkz (4):
> > > > fftools/textformat: Extract and generalize textformat api from
> > > > ffprobe.c
> > > > fftools/ffprobe: Change to use textformat api
> > > > fftools/ffprobe: Rename writer_print_section_* and WriterContext
> > > > fftools/ffprobe: Rename AVTextFormatContext variables (w => tfc)
> > >
> > > I'm fine with the changes assuming it passes fate.
> >
> > It's all green on Patchwork and on the GitHub CI, as well as locally.
> >
> > Michael had reported a file-not-found compilation error with an x86-32
> target. It appears to be an issue with ccache and the fact that there's
> a new subfolder (which rarely happens).
> > I used the same configure he gave me (except no ccache) and couldn't
> reproduce.
> >
>
> > > I don't know if you have push commit rights,
> >
> > I was going to ask Michael about it, but for now it would be great
> when you would be able to push it.
>
> Iam happy to give you push access as soon as you are listed in the
> MAINTAINER file. We have used that file as a way to keep the process
> of giving git access open and transparent.
>
> Please send some patch that adds you to MAINTAINERs
I would be willing to maintain subtitle filtering (as it's obviously not something that you can throw on the table and walk away), it's just not there yet :-)
And the graph printing of course, but same symptom as above.
So - for the time being - should I add myself to the bottom section, above the line "this list is incomplete"?
Thank you
sw
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 108+ messages in thread
* [FFmpeg-devel] [PATCH v9 0/4] print_graphs: Complete Filtergraph Printing
2025-03-19 17:04 ` [FFmpeg-devel] [PATCH v8 0/4] print_graphs: Complete Filtergraph Printing ffmpegagent
` (4 preceding siblings ...)
2025-03-21 18:04 ` [FFmpeg-devel] [PATCH v8 0/4] print_graphs: Complete Filtergraph Printing Stefano Sabatini
@ 2025-03-23 3:42 ` ffmpegagent
2025-03-23 3:42 ` [FFmpeg-devel] [PATCH v9 1/4] fftools/textformat: Extract and generalize textformat api from ffprobe.c softworkz
` (3 more replies)
5 siblings, 4 replies; 108+ messages in thread
From: ffmpegagent @ 2025-03-23 3:42 UTC (permalink / raw)
To: ffmpeg-devel; +Cc: softworkz
Due to the additional work on graph visualization (see
https://lists.ffmpeg.org/pipermail/ffmpeg-devel/2025-March/341296.html), I
have removed the two graph printing commits from this patchset rather than
adding to it, as to avoid wasting the effort already spent on reviewing.
So, now it's a graph printing patchset without graph printing :-)
All other commits are unchanged from the previous version. I'm also
resubmitting to give it a final run of the tests on various platforms.
V9
==
* Fix outdir creation for out-of-tree builds
(thanks, Michael)
softworkz (4):
fftools/textformat: Extract and generalize textformat api from
ffprobe.c
fftools/ffprobe: Change to use textformat api
fftools/ffprobe: Rename writer_print_section_* and WriterContext
fftools/ffprobe: Rename AVTextFormatContext variables (w => tfc)
fftools/Makefile | 15 +-
fftools/ffprobe.c | 2296 +++++-----------------------
fftools/textformat/avtextformat.c | 672 ++++++++
fftools/textformat/avtextformat.h | 171 +++
fftools/textformat/avtextwriters.h | 68 +
fftools/textformat/tf_compact.c | 282 ++++
fftools/textformat/tf_default.c | 145 ++
fftools/textformat/tf_flat.c | 174 +++
fftools/textformat/tf_ini.c | 160 ++
fftools/textformat/tf_json.c | 215 +++
fftools/textformat/tf_xml.c | 221 +++
fftools/textformat/tw_avio.c | 129 ++
fftools/textformat/tw_buffer.c | 92 ++
fftools/textformat/tw_stdout.c | 82 +
14 files changed, 2776 insertions(+), 1946 deletions(-)
create mode 100644 fftools/textformat/avtextformat.c
create mode 100644 fftools/textformat/avtextformat.h
create mode 100644 fftools/textformat/avtextwriters.h
create mode 100644 fftools/textformat/tf_compact.c
create mode 100644 fftools/textformat/tf_default.c
create mode 100644 fftools/textformat/tf_flat.c
create mode 100644 fftools/textformat/tf_ini.c
create mode 100644 fftools/textformat/tf_json.c
create mode 100644 fftools/textformat/tf_xml.c
create mode 100644 fftools/textformat/tw_avio.c
create mode 100644 fftools/textformat/tw_buffer.c
create mode 100644 fftools/textformat/tw_stdout.c
base-commit: 0b097ed9f141f57e2b91f0704c721a9eff0204c0
Published-As: https://github.com/ffstaging/FFmpeg/releases/tag/pr-ffstaging-52%2Fsoftworkz%2Fsubmit_print_graphs5-v9
Fetch-It-Via: git fetch https://github.com/ffstaging/FFmpeg pr-ffstaging-52/softworkz/submit_print_graphs5-v9
Pull-Request: https://github.com/ffstaging/FFmpeg/pull/52
Range-diff vs v8:
1: f379c77e88 = 1: f379c77e88 fftools/textformat: Extract and generalize textformat api from ffprobe.c
2: 67bc38ac96 ! 2: 5ebe2a6c20 fftools/ffprobe: Change to use textformat api
@@ fftools/Makefile: OBJS-ffmpeg += \
OBJS-ffplay += fftools/ffplay_renderer.o
define DOFFTOOL
+@@ fftools/Makefile: ifdef HAVE_GNU_WINDRES
+ OBJS-$(1) += fftools/fftoolsres.o
+ endif
+ $(1)$(PROGSSUF)_g$(EXESUF): $$(OBJS-$(1))
+-$$(OBJS-$(1)): | fftools
++$$(OBJS-$(1)): | fftools fftools/textformat
+ $$(OBJS-$(1)): CFLAGS += $(CFLAGS-$(1))
+ $(1)$(PROGSSUF)_g$(EXESUF): LDFLAGS += $(LDFLAGS-$(1))
+ $(1)$(PROGSSUF)_g$(EXESUF): FF_EXTRALIBS += $(EXTRALIBS-$(1))
+@@ fftools/Makefile: all: $(AVPROGS)
+
+ fftools/ffprobe.o fftools/cmdutils.o: libavutil/ffversion.h | fftools
+ OUTDIRS += fftools
++OUTDIRS += fftools/textformat
+
+ ifdef AVPROGS
+ install: install-progs install-data
## fftools/ffprobe.c ##
@@
3: 52c41fdcd0 = 3: 41dab9d31a fftools/ffprobe: Rename writer_print_section_* and WriterContext
4: e85abafb4d = 4: ae472da3e3 fftools/ffprobe: Rename AVTextFormatContext variables (w => tfc)
--
ffmpeg-codebot
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 108+ messages in thread
* [FFmpeg-devel] [PATCH v9 1/4] fftools/textformat: Extract and generalize textformat api from ffprobe.c
2025-03-23 3:42 ` [FFmpeg-devel] [PATCH v9 " ffmpegagent
@ 2025-03-23 3:42 ` softworkz
2025-03-23 3:42 ` [FFmpeg-devel] [PATCH v9 2/4] fftools/ffprobe: Change to use textformat api softworkz
` (2 subsequent siblings)
3 siblings, 0 replies; 108+ messages in thread
From: softworkz @ 2025-03-23 3:42 UTC (permalink / raw)
To: ffmpeg-devel; +Cc: softworkz
From: softworkz <softworkz@hotmail.com>
Signed-off-by: softworkz <softworkz@hotmail.com>
---
fftools/textformat/avtextformat.c | 672 +++++++++++++++++++++++++++++
fftools/textformat/avtextformat.h | 171 ++++++++
fftools/textformat/avtextwriters.h | 68 +++
fftools/textformat/tf_compact.c | 282 ++++++++++++
fftools/textformat/tf_default.c | 145 +++++++
fftools/textformat/tf_flat.c | 174 ++++++++
fftools/textformat/tf_ini.c | 160 +++++++
fftools/textformat/tf_json.c | 215 +++++++++
fftools/textformat/tf_xml.c | 221 ++++++++++
fftools/textformat/tw_avio.c | 129 ++++++
fftools/textformat/tw_buffer.c | 92 ++++
fftools/textformat/tw_stdout.c | 82 ++++
12 files changed, 2411 insertions(+)
create mode 100644 fftools/textformat/avtextformat.c
create mode 100644 fftools/textformat/avtextformat.h
create mode 100644 fftools/textformat/avtextwriters.h
create mode 100644 fftools/textformat/tf_compact.c
create mode 100644 fftools/textformat/tf_default.c
create mode 100644 fftools/textformat/tf_flat.c
create mode 100644 fftools/textformat/tf_ini.c
create mode 100644 fftools/textformat/tf_json.c
create mode 100644 fftools/textformat/tf_xml.c
create mode 100644 fftools/textformat/tw_avio.c
create mode 100644 fftools/textformat/tw_buffer.c
create mode 100644 fftools/textformat/tw_stdout.c
diff --git a/fftools/textformat/avtextformat.c b/fftools/textformat/avtextformat.c
new file mode 100644
index 0000000000..6c09f9d2cd
--- /dev/null
+++ b/fftools/textformat/avtextformat.c
@@ -0,0 +1,672 @@
+/*
+ * Copyright (c) The FFmpeg developers
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <limits.h>
+#include <stdarg.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "libavutil/mem.h"
+#include "libavutil/avassert.h"
+#include "libavutil/bprint.h"
+#include "libavutil/error.h"
+#include "libavutil/hash.h"
+#include "libavutil/intreadwrite.h"
+#include "libavutil/macros.h"
+#include "libavutil/opt.h"
+#include "avtextformat.h"
+
+#define SECTION_ID_NONE -1
+
+#define SHOW_OPTIONAL_FIELDS_AUTO -1
+#define SHOW_OPTIONAL_FIELDS_NEVER 0
+#define SHOW_OPTIONAL_FIELDS_ALWAYS 1
+
+static const struct {
+ double bin_val;
+ double dec_val;
+ const char *bin_str;
+ const char *dec_str;
+} si_prefixes[] = {
+ { 1.0, 1.0, "", "" },
+ { 1.024e3, 1e3, "Ki", "K" },
+ { 1.048576e6, 1e6, "Mi", "M" },
+ { 1.073741824e9, 1e9, "Gi", "G" },
+ { 1.099511627776e12, 1e12, "Ti", "T" },
+ { 1.125899906842624e15, 1e15, "Pi", "P" },
+};
+
+static const char *textcontext_get_formatter_name(void *p)
+{
+ AVTextFormatContext *tctx = p;
+ return tctx->formatter->name;
+}
+
+#define OFFSET(x) offsetof(AVTextFormatContext, x)
+
+static const AVOption textcontext_options[] = {
+ { "string_validation", "set string validation mode",
+ OFFSET(string_validation), AV_OPT_TYPE_INT, {.i64=AV_TEXTFORMAT_STRING_VALIDATION_REPLACE}, 0, AV_TEXTFORMAT_STRING_VALIDATION_NB-1, .unit = "sv" },
+ { "sv", "set string validation mode",
+ OFFSET(string_validation), AV_OPT_TYPE_INT, {.i64=AV_TEXTFORMAT_STRING_VALIDATION_REPLACE}, 0, AV_TEXTFORMAT_STRING_VALIDATION_NB-1, .unit = "sv" },
+ { "ignore", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = AV_TEXTFORMAT_STRING_VALIDATION_IGNORE}, .unit = "sv" },
+ { "replace", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = AV_TEXTFORMAT_STRING_VALIDATION_REPLACE}, .unit = "sv" },
+ { "fail", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = AV_TEXTFORMAT_STRING_VALIDATION_FAIL}, .unit = "sv" },
+ { "string_validation_replacement", "set string validation replacement string", OFFSET(string_validation_replacement), AV_OPT_TYPE_STRING, {.str=""}},
+ { "svr", "set string validation replacement string", OFFSET(string_validation_replacement), AV_OPT_TYPE_STRING, {.str="\xEF\xBF\xBD"}},
+ { NULL }
+};
+
+static void *textcontext_child_next(void *obj, void *prev)
+{
+ AVTextFormatContext *ctx = obj;
+ if (!prev && ctx->formatter && ctx->formatter->priv_class && ctx->priv)
+ return ctx->priv;
+ return NULL;
+}
+
+static const AVClass textcontext_class = {
+ .class_name = "AVTextContext",
+ .item_name = textcontext_get_formatter_name,
+ .option = textcontext_options,
+ .version = LIBAVUTIL_VERSION_INT,
+ .child_next = textcontext_child_next,
+};
+
+static void bprint_bytes(AVBPrint *bp, const uint8_t *ubuf, size_t ubuf_size)
+{
+ int i;
+ av_bprintf(bp, "0X");
+ for (i = 0; i < ubuf_size; i++)
+ av_bprintf(bp, "%02X", ubuf[i]);
+}
+
+int avtext_context_close(AVTextFormatContext **ptctx)
+{
+ AVTextFormatContext *tctx = *ptctx;
+ int i;
+ int ret = 0;
+
+ if (!tctx)
+ return EINVAL;
+
+ av_hash_freep(&tctx->hash);
+
+ av_hash_freep(&tctx->hash);
+
+ if (tctx->formatter->uninit)
+ tctx->formatter->uninit(tctx);
+ for (i = 0; i < SECTION_MAX_NB_LEVELS; i++)
+ av_bprint_finalize(&tctx->section_pbuf[i], NULL);
+ if (tctx->formatter->priv_class)
+ av_opt_free(tctx->priv);
+ av_freep(&tctx->priv);
+ av_opt_free(tctx);
+ av_freep(ptctx);
+ return ret;
+}
+
+
+int avtext_context_open(AVTextFormatContext **ptctx, const AVTextFormatter *formatter, AVTextWriterContext *writer_context, const char *args,
+ const struct AVTextFormatSection *sections, int nb_sections,
+ int show_value_unit,
+ int use_value_prefix,
+ int use_byte_value_binary_prefix,
+ int use_value_sexagesimal_format,
+ int show_optional_fields,
+ char *show_data_hash)
+{
+ AVTextFormatContext *tctx;
+ int i, ret = 0;
+
+ if (!(tctx = av_mallocz(sizeof(AVTextFormatContext)))) {
+ ret = AVERROR(ENOMEM);
+ goto fail;
+ }
+
+ if (!(tctx->priv = av_mallocz(formatter->priv_size))) {
+ ret = AVERROR(ENOMEM);
+ goto fail;
+ }
+
+ tctx->show_value_unit = show_value_unit;
+ tctx->use_value_prefix = use_value_prefix;
+ tctx->use_byte_value_binary_prefix = use_byte_value_binary_prefix;
+ tctx->use_value_sexagesimal_format = use_value_sexagesimal_format;
+ tctx->show_optional_fields = show_optional_fields;
+
+ if (nb_sections > SECTION_MAX_NB_SECTIONS) {
+ 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);
+ ret = AVERROR(EINVAL);
+ goto fail;
+ }
+
+ tctx->class = &textcontext_class;
+ tctx->formatter = formatter;
+ tctx->level = -1;
+ tctx->sections = sections;
+ tctx->nb_sections = nb_sections;
+ tctx->writer = writer_context;
+
+ av_opt_set_defaults(tctx);
+
+ if (formatter->priv_class) {
+ void *priv_ctx = tctx->priv;
+ *(const AVClass **)priv_ctx = formatter->priv_class;
+ av_opt_set_defaults(priv_ctx);
+ }
+
+ /* convert options to dictionary */
+ if (args) {
+ AVDictionary *opts = NULL;
+ const AVDictionaryEntry *opt = NULL;
+
+ if ((ret = av_dict_parse_string(&opts, args, "=", ":", 0)) < 0) {
+ av_log(tctx, AV_LOG_ERROR, "Failed to parse option string '%s' provided to textformat context\n", args);
+ av_dict_free(&opts);
+ goto fail;
+ }
+
+ while ((opt = av_dict_iterate(opts, opt))) {
+ if ((ret = av_opt_set(tctx, opt->key, opt->value, AV_OPT_SEARCH_CHILDREN)) < 0) {
+ av_log(tctx, AV_LOG_ERROR, "Failed to set option '%s' with value '%s' provided to textformat context\n",
+ opt->key, opt->value);
+ av_dict_free(&opts);
+ goto fail;
+ }
+ }
+
+ av_dict_free(&opts);
+ }
+
+ if (show_data_hash) {
+ if ((ret = av_hash_alloc(&tctx->hash, show_data_hash)) < 0) {
+ if (ret == AVERROR(EINVAL)) {
+ const char *n;
+ av_log(NULL, AV_LOG_ERROR, "Unknown hash algorithm '%s'\nKnown algorithms:", show_data_hash);
+ for (i = 0; (n = av_hash_names(i)); i++)
+ av_log(NULL, AV_LOG_ERROR, " %s", n);
+ av_log(NULL, AV_LOG_ERROR, "\n");
+ }
+ return ret;
+ }
+ }
+
+ /* validate replace string */
+ {
+ const uint8_t *p = tctx->string_validation_replacement;
+ const uint8_t *endp = p + strlen(p);
+ while (*p) {
+ const uint8_t *p0 = p;
+ int32_t code;
+ ret = av_utf8_decode(&code, &p, endp, tctx->string_validation_utf8_flags);
+ if (ret < 0) {
+ AVBPrint bp;
+ av_bprint_init(&bp, 0, AV_BPRINT_SIZE_AUTOMATIC);
+ bprint_bytes(&bp, p0, p-p0),
+ av_log(tctx, AV_LOG_ERROR,
+ "Invalid UTF8 sequence %s found in string validation replace '%s'\n",
+ bp.str, tctx->string_validation_replacement);
+ return ret;
+ }
+ }
+ }
+
+ for (i = 0; i < SECTION_MAX_NB_LEVELS; i++)
+ av_bprint_init(&tctx->section_pbuf[i], 1, AV_BPRINT_SIZE_UNLIMITED);
+
+ if (tctx->formatter->init)
+ ret = tctx->formatter->init(tctx);
+ if (ret < 0)
+ goto fail;
+
+ *ptctx = tctx;
+
+ return 0;
+
+fail:
+ avtext_context_close(&tctx);
+ return ret;
+}
+
+/* Temporary definitions during refactoring */
+static const char unit_second_str[] = "s" ;
+static const char unit_hertz_str[] = "Hz" ;
+static const char unit_byte_str[] = "byte" ;
+static const char unit_bit_per_second_str[] = "bit/s";
+
+
+void avtext_print_section_header(AVTextFormatContext *tctx,
+ const void *data,
+ int section_id)
+{
+ tctx->level++;
+ av_assert0(tctx->level < SECTION_MAX_NB_LEVELS);
+
+ tctx->nb_item[tctx->level] = 0;
+ memset(tctx->nb_item_type[tctx->level], 0, sizeof(tctx->nb_item_type[tctx->level]));
+ tctx->section[tctx->level] = &tctx->sections[section_id];
+
+ if (tctx->formatter->print_section_header)
+ tctx->formatter->print_section_header(tctx, data);
+}
+
+void avtext_print_section_footer(AVTextFormatContext *tctx)
+{
+ int section_id = tctx->section[tctx->level]->id;
+ int parent_section_id = tctx->level ?
+ tctx->section[tctx->level-1]->id : SECTION_ID_NONE;
+
+ if (parent_section_id != SECTION_ID_NONE) {
+ tctx->nb_item[tctx->level - 1]++;
+ tctx->nb_item_type[tctx->level - 1][section_id]++;
+ }
+
+ if (tctx->formatter->print_section_footer)
+ tctx->formatter->print_section_footer(tctx);
+ tctx->level--;
+}
+
+void avtext_print_integer(AVTextFormatContext *tctx,
+ const char *key, int64_t val)
+{
+ const struct AVTextFormatSection *section = tctx->section[tctx->level];
+
+ if (section->show_all_entries || av_dict_get(section->entries_to_show, key, NULL, 0)) {
+ tctx->formatter->print_integer(tctx, key, val);
+ tctx->nb_item[tctx->level]++;
+ }
+}
+
+static inline int validate_string(AVTextFormatContext *tctx, char **dstp, const char *src)
+{
+ const uint8_t *p, *endp;
+ AVBPrint dstbuf;
+ int invalid_chars_nb = 0, ret = 0;
+
+ av_bprint_init(&dstbuf, 0, AV_BPRINT_SIZE_UNLIMITED);
+
+ endp = src + strlen(src);
+ for (p = src; *p;) {
+ uint32_t code;
+ int invalid = 0;
+ const uint8_t *p0 = p;
+
+ if (av_utf8_decode(&code, &p, endp, tctx->string_validation_utf8_flags) < 0) {
+ AVBPrint bp;
+ av_bprint_init(&bp, 0, AV_BPRINT_SIZE_AUTOMATIC);
+ bprint_bytes(&bp, p0, p-p0);
+ av_log(tctx, AV_LOG_DEBUG,
+ "Invalid UTF-8 sequence %s found in string '%s'\n", bp.str, src);
+ invalid = 1;
+ }
+
+ if (invalid) {
+ invalid_chars_nb++;
+
+ switch (tctx->string_validation) {
+ case AV_TEXTFORMAT_STRING_VALIDATION_FAIL:
+ av_log(tctx, AV_LOG_ERROR,
+ "Invalid UTF-8 sequence found in string '%s'\n", src);
+ ret = AVERROR_INVALIDDATA;
+ goto end;
+ break;
+
+ case AV_TEXTFORMAT_STRING_VALIDATION_REPLACE:
+ av_bprintf(&dstbuf, "%s", tctx->string_validation_replacement);
+ break;
+ }
+ }
+
+ if (!invalid || tctx->string_validation == AV_TEXTFORMAT_STRING_VALIDATION_IGNORE)
+ av_bprint_append_data(&dstbuf, p0, p-p0);
+ }
+
+ if (invalid_chars_nb && tctx->string_validation == AV_TEXTFORMAT_STRING_VALIDATION_REPLACE) {
+ av_log(tctx, AV_LOG_WARNING,
+ "%d invalid UTF-8 sequence(s) found in string '%s', replaced with '%s'\n",
+ invalid_chars_nb, src, tctx->string_validation_replacement);
+ }
+
+end:
+ av_bprint_finalize(&dstbuf, dstp);
+ return ret;
+}
+
+struct unit_value {
+ union { double d; int64_t i; } val;
+ const char *unit;
+};
+
+static char *value_string(AVTextFormatContext *tctx, char *buf, int buf_size, struct unit_value uv)
+{
+ double vald;
+ int64_t vali;
+ int show_float = 0;
+
+ if (uv.unit == unit_second_str) {
+ vald = uv.val.d;
+ show_float = 1;
+ } else {
+ vald = vali = uv.val.i;
+ }
+
+ if (uv.unit == unit_second_str && tctx->use_value_sexagesimal_format) {
+ double secs;
+ int hours, mins;
+ secs = vald;
+ mins = (int)secs / 60;
+ secs = secs - mins * 60;
+ hours = mins / 60;
+ mins %= 60;
+ snprintf(buf, buf_size, "%d:%02d:%09.6f", hours, mins, secs);
+ } else {
+ const char *prefix_string = "";
+
+ if (tctx->use_value_prefix && vald > 1) {
+ int64_t index;
+
+ if (uv.unit == unit_byte_str && tctx->use_byte_value_binary_prefix) {
+ index = (int64_t) (log2(vald)) / 10;
+ index = av_clip(index, 0, FF_ARRAY_ELEMS(si_prefixes) - 1);
+ vald /= si_prefixes[index].bin_val;
+ prefix_string = si_prefixes[index].bin_str;
+ } else {
+ index = (int64_t) (log10(vald)) / 3;
+ index = av_clip(index, 0, FF_ARRAY_ELEMS(si_prefixes) - 1);
+ vald /= si_prefixes[index].dec_val;
+ prefix_string = si_prefixes[index].dec_str;
+ }
+ vali = vald;
+ }
+
+ if (show_float || (tctx->use_value_prefix && vald != (int64_t)vald))
+ snprintf(buf, buf_size, "%f", vald);
+ else
+ snprintf(buf, buf_size, "%"PRId64, vali);
+ av_strlcatf(buf, buf_size, "%s%s%s", *prefix_string || tctx->show_value_unit ? " " : "",
+ prefix_string, tctx->show_value_unit ? uv.unit : "");
+ }
+
+ return buf;
+}
+
+
+void avtext_print_unit_int(AVTextFormatContext *tctx, const char *key, int value, const char *unit)
+{
+ char val_str[128];
+ struct unit_value uv;
+ uv.val.i = value;
+ uv.unit = unit;
+ avtext_print_string(tctx, key, value_string(tctx, val_str, sizeof(val_str), uv), 0);
+}
+
+
+int avtext_print_string(AVTextFormatContext *tctx, const char *key, const char *val, int flags)
+{
+ const struct AVTextFormatSection *section = tctx->section[tctx->level];
+ int ret = 0;
+
+ if (tctx->show_optional_fields == SHOW_OPTIONAL_FIELDS_NEVER ||
+ (tctx->show_optional_fields == SHOW_OPTIONAL_FIELDS_AUTO
+ && (flags & AV_TEXTFORMAT_PRINT_STRING_OPTIONAL)
+ && !(tctx->formatter->flags & AV_TEXTFORMAT_FLAG_SUPPORTS_OPTIONAL_FIELDS)))
+ return 0;
+
+ if (section->show_all_entries || av_dict_get(section->entries_to_show, key, NULL, 0)) {
+ if (flags & AV_TEXTFORMAT_PRINT_STRING_VALIDATE) {
+ char *key1 = NULL, *val1 = NULL;
+ ret = validate_string(tctx, &key1, key);
+ if (ret < 0) goto end;
+ ret = validate_string(tctx, &val1, val);
+ if (ret < 0) goto end;
+ tctx->formatter->print_string(tctx, key1, val1);
+ end:
+ if (ret < 0) {
+ av_log(tctx, AV_LOG_ERROR,
+ "Invalid key=value string combination %s=%s in section %s\n",
+ key, val, section->unique_name);
+ }
+ av_free(key1);
+ av_free(val1);
+ } else {
+ tctx->formatter->print_string(tctx, key, val);
+ }
+
+ tctx->nb_item[tctx->level]++;
+ }
+
+ return ret;
+}
+
+void avtext_print_rational(AVTextFormatContext *tctx,
+ const char *key, AVRational q, char sep)
+{
+ AVBPrint buf;
+ av_bprint_init(&buf, 0, AV_BPRINT_SIZE_AUTOMATIC);
+ av_bprintf(&buf, "%d%c%d", q.num, sep, q.den);
+ avtext_print_string(tctx, key, buf.str, 0);
+}
+
+void avtext_print_time(AVTextFormatContext *tctx, const char *key,
+ int64_t ts, const AVRational *time_base, int is_duration)
+{
+ char buf[128];
+
+ if ((!is_duration && ts == AV_NOPTS_VALUE) || (is_duration && ts == 0)) {
+ avtext_print_string(tctx, key, "N/A", AV_TEXTFORMAT_PRINT_STRING_OPTIONAL);
+ } else {
+ double d = ts * av_q2d(*time_base);
+ struct unit_value uv;
+ uv.val.d = d;
+ uv.unit = unit_second_str;
+ value_string(tctx, buf, sizeof(buf), uv);
+ avtext_print_string(tctx, key, buf, 0);
+ }
+}
+
+void avtext_print_ts(AVTextFormatContext *tctx, const char *key, int64_t ts, int is_duration)
+{
+ if ((!is_duration && ts == AV_NOPTS_VALUE) || (is_duration && ts == 0)) {
+ avtext_print_string(tctx, key, "N/A", AV_TEXTFORMAT_PRINT_STRING_OPTIONAL);
+ } else {
+ avtext_print_integer(tctx, key, ts);
+ }
+}
+
+void avtext_print_data(AVTextFormatContext *tctx, const char *name,
+ const uint8_t *data, int size)
+{
+ AVBPrint bp;
+ int offset = 0, l, i;
+
+ av_bprint_init(&bp, 0, AV_BPRINT_SIZE_UNLIMITED);
+ av_bprintf(&bp, "\n");
+ while (size) {
+ av_bprintf(&bp, "%08x: ", offset);
+ l = FFMIN(size, 16);
+ for (i = 0; i < l; i++) {
+ av_bprintf(&bp, "%02x", data[i]);
+ if (i & 1)
+ av_bprintf(&bp, " ");
+ }
+ av_bprint_chars(&bp, ' ', 41 - 2 * i - i / 2);
+ for (i = 0; i < l; i++)
+ av_bprint_chars(&bp, data[i] - 32U < 95 ? data[i] : '.', 1);
+ av_bprintf(&bp, "\n");
+ offset += l;
+ data += l;
+ size -= l;
+ }
+ avtext_print_string(tctx, name, bp.str, 0);
+ av_bprint_finalize(&bp, NULL);
+}
+
+void avtext_print_data_hash(AVTextFormatContext *tctx, const char *name,
+ const uint8_t *data, int size)
+{
+ char *p, buf[AV_HASH_MAX_SIZE * 2 + 64] = { 0 };
+
+ if (!tctx->hash)
+ return;
+ av_hash_init(tctx->hash);
+ av_hash_update(tctx->hash, data, size);
+ snprintf(buf, sizeof(buf), "%s:", av_hash_get_name(tctx->hash));
+ p = buf + strlen(buf);
+ av_hash_final_hex(tctx->hash, p, buf + sizeof(buf) - p);
+ avtext_print_string(tctx, name, buf, 0);
+}
+
+void avtext_print_integers(AVTextFormatContext *tctx, const char *name,
+ uint8_t *data, int size, const char *format,
+ int columns, int bytes, int offset_add)
+{
+ AVBPrint bp;
+ int offset = 0, l, i;
+
+ av_bprint_init(&bp, 0, AV_BPRINT_SIZE_UNLIMITED);
+ av_bprintf(&bp, "\n");
+ while (size) {
+ av_bprintf(&bp, "%08x: ", offset);
+ l = FFMIN(size, columns);
+ for (i = 0; i < l; i++) {
+ if (bytes == 1) av_bprintf(&bp, format, *data);
+ else if (bytes == 2) av_bprintf(&bp, format, AV_RN16(data));
+ else if (bytes == 4) av_bprintf(&bp, format, AV_RN32(data));
+ data += bytes;
+ size --;
+ }
+ av_bprintf(&bp, "\n");
+ offset += offset_add;
+ }
+ avtext_print_string(tctx, name, bp.str, 0);
+ av_bprint_finalize(&bp, NULL);
+}
+
+static const char *writercontext_get_writer_name(void *p)
+{
+ AVTextWriterContext *wctx = p;
+ return wctx->writer->name;
+}
+
+static void *writercontext_child_next(void *obj, void *prev)
+{
+ AVTextFormatContext *ctx = obj;
+ if (!prev && ctx->formatter && ctx->formatter->priv_class && ctx->priv)
+ return ctx->priv;
+ return NULL;
+}
+
+static const AVClass textwriter_class = {
+ .class_name = "AVTextWriterContext",
+ .item_name = writercontext_get_writer_name,
+ .version = LIBAVUTIL_VERSION_INT,
+ .child_next = writercontext_child_next,
+};
+
+
+int avtextwriter_context_close(AVTextWriterContext **pwctx)
+{
+ AVTextWriterContext *wctx = *pwctx;
+ int ret = 0;
+
+ if (!wctx)
+ return EINVAL;
+
+ if (wctx->writer->uninit)
+ wctx->writer->uninit(wctx);
+ if (wctx->writer->priv_class)
+ av_opt_free(wctx->priv);
+ av_freep(&wctx->priv);
+ av_freep(pwctx);
+ return ret;
+}
+
+
+int avtextwriter_context_open(AVTextWriterContext **pwctx, const AVTextWriter *writer)
+{
+ AVTextWriterContext *wctx;
+ int ret = 0;
+
+ if (!(wctx = av_mallocz(sizeof(AVTextWriterContext)))) {
+ ret = AVERROR(ENOMEM);
+ goto fail;
+ }
+
+ if (!(wctx->priv = av_mallocz(writer->priv_size))) {
+ ret = AVERROR(ENOMEM);
+ goto fail;
+ }
+
+ if (writer->priv_class) {
+ void *priv_ctx = wctx->priv;
+ *(const AVClass **)priv_ctx = writer->priv_class;
+ av_opt_set_defaults(priv_ctx);
+ }
+
+ wctx->class = &textwriter_class;
+ wctx->writer = writer;
+
+ av_opt_set_defaults(wctx);
+
+
+ if (wctx->writer->init)
+ ret = wctx->writer->init(wctx);
+ if (ret < 0)
+ goto fail;
+
+ *pwctx = wctx;
+
+ return 0;
+
+fail:
+ avtextwriter_context_close(&wctx);
+ return ret;
+}
+
+static const AVTextFormatter *registered_formatters[7+1];
+static void formatters_register_all(void)
+{
+ static int initialized;
+
+ if (initialized)
+ return;
+ initialized = 1;
+
+ registered_formatters[0] = &avtextformatter_default;
+ registered_formatters[1] = &avtextformatter_compact;
+ registered_formatters[2] = &avtextformatter_csv;
+ registered_formatters[3] = &avtextformatter_flat;
+ registered_formatters[4] = &avtextformatter_ini;
+ registered_formatters[5] = &avtextformatter_json;
+ registered_formatters[6] = &avtextformatter_xml;
+}
+
+const AVTextFormatter *avtext_get_formatter_by_name(const char *name)
+{
+ formatters_register_all();
+
+ for (int i = 0; registered_formatters[i]; i++)
+ if (!strcmp(registered_formatters[i]->name, name))
+ return registered_formatters[i];
+
+ return NULL;
+}
diff --git a/fftools/textformat/avtextformat.h b/fftools/textformat/avtextformat.h
new file mode 100644
index 0000000000..4689499246
--- /dev/null
+++ b/fftools/textformat/avtextformat.h
@@ -0,0 +1,171 @@
+/*
+ * Copyright (c) The FFmpeg developers
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef FFTOOLS_TEXTFORMAT_AVTEXTFORMAT_H
+#define FFTOOLS_TEXTFORMAT_AVTEXTFORMAT_H
+
+#include <stddef.h>
+#include <stdint.h>
+#include "libavutil/attributes.h"
+#include "libavutil/dict.h"
+#include "libavformat/avio.h"
+#include "libavutil/bprint.h"
+#include "libavutil/rational.h"
+#include "libavutil/hash.h"
+#include "avtextwriters.h"
+
+#define SECTION_MAX_NB_CHILDREN 11
+
+
+struct AVTextFormatSection {
+ int id; ///< unique id identifying a section
+ const char *name;
+
+#define AV_TEXTFORMAT_SECTION_FLAG_IS_WRAPPER 1 ///< the section only contains other sections, but has no data at its own level
+#define AV_TEXTFORMAT_SECTION_FLAG_IS_ARRAY 2 ///< the section contains an array of elements of the same type
+#define AV_TEXTFORMAT_SECTION_FLAG_HAS_VARIABLE_FIELDS 4 ///< the section may contain a variable number of fields with variable keys.
+ /// For these sections the element_name field is mandatory.
+#define AV_TEXTFORMAT_SECTION_FLAG_HAS_TYPE 8 ///< the section contains a type to distinguish multiple nested elements
+#define AV_TEXTFORMAT_SECTION_FLAG_NUMBERING_BY_TYPE 16 ///< the items in this array section should be numbered individually by type
+
+ int flags;
+ const int children_ids[SECTION_MAX_NB_CHILDREN+1]; ///< list of children section IDS, terminated by -1
+ const char *element_name; ///< name of the contained element, if provided
+ const char *unique_name; ///< unique section name, in case the name is ambiguous
+ AVDictionary *entries_to_show;
+ const char *(* get_type)(const void *data); ///< function returning a type if defined, must be defined when SECTION_FLAG_HAS_TYPE is defined
+ int show_all_entries;
+} AVTextFormatSection;
+
+typedef struct AVTextFormatContext AVTextFormatContext;
+
+#define AV_TEXTFORMAT_FLAG_SUPPORTS_OPTIONAL_FIELDS 1
+#define AV_TEXTFORMAT_FLAG_SUPPORTS_MIXED_ARRAY_CONTENT 2
+
+typedef enum {
+ AV_TEXTFORMAT_STRING_VALIDATION_FAIL,
+ AV_TEXTFORMAT_STRING_VALIDATION_REPLACE,
+ AV_TEXTFORMAT_STRING_VALIDATION_IGNORE,
+ AV_TEXTFORMAT_STRING_VALIDATION_NB
+} StringValidation;
+
+typedef struct AVTextFormatter {
+ const AVClass *priv_class; ///< private class of the formatter, if any
+ int priv_size; ///< private size for the formatter context
+ const char *name;
+
+ int (*init) (AVTextFormatContext *tctx);
+ void (*uninit)(AVTextFormatContext *tctx);
+
+ void (*print_section_header)(AVTextFormatContext *tctx, const void *data);
+ void (*print_section_footer)(AVTextFormatContext *tctx);
+ void (*print_integer) (AVTextFormatContext *tctx, const char *, int64_t);
+ void (*print_rational) (AVTextFormatContext *tctx, AVRational *q, char *sep);
+ void (*print_string) (AVTextFormatContext *tctx, const char *, const char *);
+ int flags; ///< a combination or AV_TEXTFORMAT__FLAG_*
+} AVTextFormatter;
+
+#define SECTION_MAX_NB_LEVELS 12
+#define SECTION_MAX_NB_SECTIONS 100
+
+struct AVTextFormatContext {
+ const AVClass *class; ///< class of the formatter
+ const AVTextFormatter *formatter; ///< the AVTextFormatter of which this is an instance
+ AVTextWriterContext *writer; ///< the AVTextWriterContext
+
+ char *name; ///< name of this formatter instance
+ void *priv; ///< private data for use by the filter
+
+ const struct AVTextFormatSection *sections; ///< array containing all sections
+ int nb_sections; ///< number of sections
+
+ int level; ///< current level, starting from 0
+
+ /** number of the item printed in the given section, starting from 0 */
+ unsigned int nb_item[SECTION_MAX_NB_LEVELS];
+ unsigned int nb_item_type[SECTION_MAX_NB_LEVELS][SECTION_MAX_NB_SECTIONS];
+
+ /** section per each level */
+ const struct AVTextFormatSection *section[SECTION_MAX_NB_LEVELS];
+ AVBPrint section_pbuf[SECTION_MAX_NB_LEVELS]; ///< generic print buffer dedicated to each section,
+ /// used by various formatters
+
+ int show_optional_fields;
+ int show_value_unit;
+ int use_value_prefix;
+ int use_byte_value_binary_prefix;
+ int use_value_sexagesimal_format;
+
+ struct AVHashContext *hash;
+
+ int string_validation;
+ char *string_validation_replacement;
+ unsigned int string_validation_utf8_flags;
+};
+
+#define AV_TEXTFORMAT_PRINT_STRING_OPTIONAL 1
+#define AV_TEXTFORMAT_PRINT_STRING_VALIDATE 2
+
+int avtext_context_open(AVTextFormatContext **ptctx, const AVTextFormatter *formatter, AVTextWriterContext *writer_context, const char *args,
+ const struct AVTextFormatSection *sections, int nb_sections,
+ int show_value_unit,
+ int use_value_prefix,
+ int use_byte_value_binary_prefix,
+ int use_value_sexagesimal_format,
+ int show_optional_fields,
+ char *show_data_hash);
+
+int avtext_context_close(AVTextFormatContext **tctx);
+
+
+void avtext_print_section_header(AVTextFormatContext *tctx, const void *data, int section_id);
+
+void avtext_print_section_footer(AVTextFormatContext *tctx);
+
+void avtext_print_integer(AVTextFormatContext *tctx, const char *key, int64_t val);
+
+int avtext_print_string(AVTextFormatContext *tctx, const char *key, const char *val, int flags);
+
+void avtext_print_unit_int(AVTextFormatContext *tctx, const char *key, int value, const char *unit);
+
+void avtext_print_rational(AVTextFormatContext *tctx, const char *key, AVRational q, char sep);
+
+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);
+
+void avtext_print_data(AVTextFormatContext *tctx, const char *name, const uint8_t *data, int size);
+
+void avtext_print_data_hash(AVTextFormatContext *tctx, const char *name, const uint8_t *data, int size);
+
+void avtext_print_integers(AVTextFormatContext *tctx, const char *name, uint8_t *data, int size,
+ const char *format, int columns, int bytes, int offset_add);
+
+const AVTextFormatter *avtext_get_formatter_by_name(const char *name);
+
+extern const AVTextFormatter avtextformatter_default;
+extern const AVTextFormatter avtextformatter_compact;
+extern const AVTextFormatter avtextformatter_csv;
+extern const AVTextFormatter avtextformatter_flat;
+extern const AVTextFormatter avtextformatter_ini;
+extern const AVTextFormatter avtextformatter_json;
+extern const AVTextFormatter avtextformatter_xml;
+
+#endif /* FFTOOLS_TEXTFORMAT_AVTEXTFORMAT_H */
diff --git a/fftools/textformat/avtextwriters.h b/fftools/textformat/avtextwriters.h
new file mode 100644
index 0000000000..a62f2c8906
--- /dev/null
+++ b/fftools/textformat/avtextwriters.h
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) The FFmpeg developers
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef FFTOOLS_TEXTFORMAT_AVTEXTWRITERS_H
+#define FFTOOLS_TEXTFORMAT_AVTEXTWRITERS_H
+
+#include <stddef.h>
+#include <stdint.h>
+#include "libavutil/attributes.h"
+#include "libavutil/dict.h"
+#include "libavformat/avio.h"
+#include "libavutil/bprint.h"
+#include "libavutil/rational.h"
+#include "libavutil/hash.h"
+
+typedef struct AVTextWriterContext AVTextWriterContext;
+
+typedef struct AVTextWriter {
+ const AVClass *priv_class; ///< private class of the writer, if any
+ int priv_size; ///< private size for the writer private class
+ const char *name;
+
+ int (* init)(AVTextWriterContext *wctx);
+ void (* uninit)(AVTextWriterContext *wctx);
+ void (* writer_w8)(AVTextWriterContext *wctx, int b);
+ void (* writer_put_str)(AVTextWriterContext *wctx, const char *str);
+ void (* writer_printf)(AVTextWriterContext *wctx, const char *fmt, ...);
+} AVTextWriter;
+
+typedef struct AVTextWriterContext {
+ const AVClass *class; ///< class of the writer
+ const AVTextWriter *writer;
+ const char *name;
+ void *priv; ///< private data for use by the writer
+
+} AVTextWriterContext;
+
+
+int avtextwriter_context_open(AVTextWriterContext **pwctx, const AVTextWriter *writer);
+
+int avtextwriter_context_close(AVTextWriterContext **pwctx);
+
+int avtextwriter_create_stdout(AVTextWriterContext **pwctx);
+
+int avtextwriter_create_avio(AVTextWriterContext **pwctx, AVIOContext *avio_ctx, int close_on_uninit);
+
+int avtextwriter_create_file(AVTextWriterContext **pwctx, const char *output_filename, int close_on_uninit);
+
+int avtextwriter_create_buffer(AVTextWriterContext **pwctx, AVBPrint *buffer);
+
+#endif /* FFTOOLS_TEXTFORMAT_AVTEXTWRITERS_H */
diff --git a/fftools/textformat/tf_compact.c b/fftools/textformat/tf_compact.c
new file mode 100644
index 0000000000..825b67bc6e
--- /dev/null
+++ b/fftools/textformat/tf_compact.c
@@ -0,0 +1,282 @@
+/*
+ * Copyright (c) The FFmpeg developers
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <limits.h>
+#include <stdarg.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "avtextformat.h"
+#include <libavutil/mem.h>
+#include <libavutil/avassert.h>
+#include <libavutil/bprint.h>
+#include <libavutil/error.h>
+#include <libavutil/macros.h>
+#include <libavutil/opt.h>
+
+
+#define writer_w8(wctx_, b_) (wctx_)->writer->writer->writer_w8((wctx_)->writer, b_)
+#define writer_put_str(wctx_, str_) (wctx_)->writer->writer->writer_put_str((wctx_)->writer, str_)
+#define writer_printf(wctx_, fmt_, ...) (wctx_)->writer->writer->writer_printf((wctx_)->writer, fmt_, __VA_ARGS__)
+
+
+#define DEFINE_FORMATTER_CLASS(name) \
+static const char *name##_get_name(void *ctx) \
+{ \
+ return #name ; \
+} \
+static const AVClass name##_class = { \
+ .class_name = #name, \
+ .item_name = name##_get_name, \
+ .option = name##_options \
+}
+
+
+/* Compact output */
+
+/**
+ * Apply C-language-like string escaping.
+ */
+static const char *c_escape_str(AVBPrint *dst, const char *src, const char sep, void *log_ctx)
+{
+ const char *p;
+
+ for (p = src; *p; p++) {
+ switch (*p) {
+ case '\b': av_bprintf(dst, "%s", "\\b"); break;
+ case '\f': av_bprintf(dst, "%s", "\\f"); break;
+ case '\n': av_bprintf(dst, "%s", "\\n"); break;
+ case '\r': av_bprintf(dst, "%s", "\\r"); break;
+ case '\\': av_bprintf(dst, "%s", "\\\\"); break;
+ default:
+ if (*p == sep)
+ av_bprint_chars(dst, '\\', 1);
+ av_bprint_chars(dst, *p, 1);
+ }
+ }
+ return dst->str;
+}
+
+/**
+ * Quote fields containing special characters, check RFC4180.
+ */
+static const char *csv_escape_str(AVBPrint *dst, const char *src, const char sep, void *log_ctx)
+{
+ char meta_chars[] = { sep, '"', '\n', '\r', '\0' };
+ int needs_quoting = !!src[strcspn(src, meta_chars)];
+
+ if (needs_quoting)
+ av_bprint_chars(dst, '"', 1);
+
+ for (; *src; src++) {
+ if (*src == '"')
+ av_bprint_chars(dst, '"', 1);
+ av_bprint_chars(dst, *src, 1);
+ }
+ if (needs_quoting)
+ av_bprint_chars(dst, '"', 1);
+ return dst->str;
+}
+
+static const char *none_escape_str(AVBPrint *dst, const char *src, const char sep, void *log_ctx)
+{
+ return src;
+}
+
+typedef struct CompactContext {
+ const AVClass *class;
+ char *item_sep_str;
+ char item_sep;
+ int nokey;
+ int print_section;
+ char *escape_mode_str;
+ const char * (*escape_str)(AVBPrint *dst, const char *src, const char sep, void *log_ctx);
+ int nested_section[SECTION_MAX_NB_LEVELS];
+ int has_nested_elems[SECTION_MAX_NB_LEVELS];
+ int terminate_line[SECTION_MAX_NB_LEVELS];
+} CompactContext;
+
+#undef OFFSET
+#define OFFSET(x) offsetof(CompactContext, x)
+
+static const AVOption compact_options[]= {
+ {"item_sep", "set item separator", OFFSET(item_sep_str), AV_OPT_TYPE_STRING, {.str="|"}, 0, 0 },
+ {"s", "set item separator", OFFSET(item_sep_str), AV_OPT_TYPE_STRING, {.str="|"}, 0, 0 },
+ {"nokey", "force no key printing", OFFSET(nokey), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1 },
+ {"nk", "force no key printing", OFFSET(nokey), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1 },
+ {"escape", "set escape mode", OFFSET(escape_mode_str), AV_OPT_TYPE_STRING, {.str="c"}, 0, 0 },
+ {"e", "set escape mode", OFFSET(escape_mode_str), AV_OPT_TYPE_STRING, {.str="c"}, 0, 0 },
+ {"print_section", "print section name", OFFSET(print_section), AV_OPT_TYPE_BOOL, {.i64=1}, 0, 1 },
+ {"p", "print section name", OFFSET(print_section), AV_OPT_TYPE_BOOL, {.i64=1}, 0, 1 },
+ {NULL},
+};
+
+DEFINE_FORMATTER_CLASS(compact);
+
+static av_cold int compact_init(AVTextFormatContext *wctx)
+{
+ CompactContext *compact = wctx->priv;
+
+ if (strlen(compact->item_sep_str) != 1) {
+ av_log(wctx, AV_LOG_ERROR, "Item separator '%s' specified, but must contain a single character\n",
+ compact->item_sep_str);
+ return AVERROR(EINVAL);
+ }
+ compact->item_sep = compact->item_sep_str[0];
+
+ if (!strcmp(compact->escape_mode_str, "none")) compact->escape_str = none_escape_str;
+ else if (!strcmp(compact->escape_mode_str, "c" )) compact->escape_str = c_escape_str;
+ else if (!strcmp(compact->escape_mode_str, "csv" )) compact->escape_str = csv_escape_str;
+ else {
+ av_log(wctx, AV_LOG_ERROR, "Unknown escape mode '%s'\n", compact->escape_mode_str);
+ return AVERROR(EINVAL);
+ }
+
+ return 0;
+}
+
+static void compact_print_section_header(AVTextFormatContext *wctx, const void *data)
+{
+ CompactContext *compact = wctx->priv;
+ const struct AVTextFormatSection *section = wctx->section[wctx->level];
+ const struct AVTextFormatSection *parent_section = wctx->level ?
+ wctx->section[wctx->level-1] : NULL;
+ compact->terminate_line[wctx->level] = 1;
+ compact->has_nested_elems[wctx->level] = 0;
+
+ av_bprint_clear(&wctx->section_pbuf[wctx->level]);
+ if (parent_section &&
+ (section->flags & AV_TEXTFORMAT_SECTION_FLAG_HAS_TYPE ||
+ (!(section->flags & AV_TEXTFORMAT_SECTION_FLAG_IS_ARRAY) &&
+ !(parent_section->flags & (AV_TEXTFORMAT_SECTION_FLAG_IS_WRAPPER|AV_TEXTFORMAT_SECTION_FLAG_IS_ARRAY))))) {
+
+ /* define a prefix for elements not contained in an array or
+ in a wrapper, or for array elements with a type */
+ const char *element_name = (char *)av_x_if_null(section->element_name, section->name);
+ AVBPrint *section_pbuf = &wctx->section_pbuf[wctx->level];
+
+ compact->nested_section[wctx->level] = 1;
+ compact->has_nested_elems[wctx->level-1] = 1;
+
+ av_bprintf(section_pbuf, "%s%s",
+ wctx->section_pbuf[wctx->level-1].str, element_name);
+
+ if (section->flags & AV_TEXTFORMAT_SECTION_FLAG_HAS_TYPE) {
+ // add /TYPE to prefix
+ av_bprint_chars(section_pbuf, '/', 1);
+
+ // normalize section type, replace special characters and lower case
+ for (const char *p = section->get_type(data); *p; p++) {
+ char c =
+ (*p >= '0' && *p <= '9') ||
+ (*p >= 'a' && *p <= 'z') ||
+ (*p >= 'A' && *p <= 'Z') ? av_tolower(*p) : '_';
+ av_bprint_chars(section_pbuf, c, 1);
+ }
+ }
+ av_bprint_chars(section_pbuf, ':', 1);
+
+ wctx->nb_item[wctx->level] = wctx->nb_item[wctx->level-1];
+ } else {
+ if (parent_section && !(parent_section->flags & (AV_TEXTFORMAT_SECTION_FLAG_IS_WRAPPER|AV_TEXTFORMAT_SECTION_FLAG_IS_ARRAY)) &&
+ wctx->level && wctx->nb_item[wctx->level-1])
+ writer_w8(wctx, compact->item_sep);
+ if (compact->print_section &&
+ !(section->flags & (AV_TEXTFORMAT_SECTION_FLAG_IS_WRAPPER|AV_TEXTFORMAT_SECTION_FLAG_IS_ARRAY)))
+ writer_printf(wctx, "%s%c", section->name, compact->item_sep);
+ }
+}
+
+static void compact_print_section_footer(AVTextFormatContext *wctx)
+{
+ CompactContext *compact = wctx->priv;
+
+ if (!compact->nested_section[wctx->level] &&
+ compact->terminate_line[wctx->level] &&
+ !(wctx->section[wctx->level]->flags & (AV_TEXTFORMAT_SECTION_FLAG_IS_WRAPPER|AV_TEXTFORMAT_SECTION_FLAG_IS_ARRAY)))
+ writer_w8(wctx, '\n');
+}
+
+static void compact_print_str(AVTextFormatContext *wctx, const char *key, const char *value)
+{
+ CompactContext *compact = wctx->priv;
+ AVBPrint buf;
+
+ if (wctx->nb_item[wctx->level]) writer_w8(wctx, compact->item_sep);
+ if (!compact->nokey)
+ writer_printf(wctx, "%s%s=", wctx->section_pbuf[wctx->level].str, key);
+ av_bprint_init(&buf, 1, AV_BPRINT_SIZE_UNLIMITED);
+ writer_put_str(wctx, compact->escape_str(&buf, value, compact->item_sep, wctx));
+ av_bprint_finalize(&buf, NULL);
+}
+
+static void compact_print_int(AVTextFormatContext *wctx, const char *key, int64_t value)
+{
+ CompactContext *compact = wctx->priv;
+
+ if (wctx->nb_item[wctx->level]) writer_w8(wctx, compact->item_sep);
+ if (!compact->nokey)
+ writer_printf(wctx, "%s%s=", wctx->section_pbuf[wctx->level].str, key);
+ writer_printf(wctx, "%"PRId64, value);
+}
+
+const AVTextFormatter avtextformatter_compact = {
+ .name = "compact",
+ .priv_size = sizeof(CompactContext),
+ .init = compact_init,
+ .print_section_header = compact_print_section_header,
+ .print_section_footer = compact_print_section_footer,
+ .print_integer = compact_print_int,
+ .print_string = compact_print_str,
+ .flags = AV_TEXTFORMAT_FLAG_SUPPORTS_OPTIONAL_FIELDS,
+ .priv_class = &compact_class,
+};
+
+/* CSV output */
+
+#undef OFFSET
+#define OFFSET(x) offsetof(CompactContext, x)
+
+static const AVOption csv_options[] = {
+ {"item_sep", "set item separator", OFFSET(item_sep_str), AV_OPT_TYPE_STRING, {.str=","}, 0, 0 },
+ {"s", "set item separator", OFFSET(item_sep_str), AV_OPT_TYPE_STRING, {.str=","}, 0, 0 },
+ {"nokey", "force no key printing", OFFSET(nokey), AV_OPT_TYPE_BOOL, {.i64=1}, 0, 1 },
+ {"nk", "force no key printing", OFFSET(nokey), AV_OPT_TYPE_BOOL, {.i64=1}, 0, 1 },
+ {"escape", "set escape mode", OFFSET(escape_mode_str), AV_OPT_TYPE_STRING, {.str="csv"}, 0, 0 },
+ {"e", "set escape mode", OFFSET(escape_mode_str), AV_OPT_TYPE_STRING, {.str="csv"}, 0, 0 },
+ {"print_section", "print section name", OFFSET(print_section), AV_OPT_TYPE_BOOL, {.i64=1}, 0, 1 },
+ {"p", "print section name", OFFSET(print_section), AV_OPT_TYPE_BOOL, {.i64=1}, 0, 1 },
+ {NULL},
+};
+
+DEFINE_FORMATTER_CLASS(csv);
+
+const AVTextFormatter avtextformatter_csv = {
+ .name = "csv",
+ .priv_size = sizeof(CompactContext),
+ .init = compact_init,
+ .print_section_header = compact_print_section_header,
+ .print_section_footer = compact_print_section_footer,
+ .print_integer = compact_print_int,
+ .print_string = compact_print_str,
+ .flags = AV_TEXTFORMAT_FLAG_SUPPORTS_OPTIONAL_FIELDS,
+ .priv_class = &csv_class,
+};
diff --git a/fftools/textformat/tf_default.c b/fftools/textformat/tf_default.c
new file mode 100644
index 0000000000..7369992f01
--- /dev/null
+++ b/fftools/textformat/tf_default.c
@@ -0,0 +1,145 @@
+/*
+ * Copyright (c) The FFmpeg developers
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <limits.h>
+#include <stdarg.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "avtextformat.h"
+#include <libavutil/mem.h>
+#include <libavutil/avassert.h>
+#include <libavutil/bprint.h>
+#include <libavutil/opt.h>
+
+#define writer_w8(wctx_, b_) (wctx_)->writer->writer->writer_w8((wctx_)->writer, b_)
+#define writer_put_str(wctx_, str_) (wctx_)->writer->writer->writer_put_str((wctx_)->writer, str_)
+#define writer_printf(wctx_, fmt_, ...) (wctx_)->writer->writer->writer_printf((wctx_)->writer, fmt_, __VA_ARGS__)
+
+#define DEFINE_FORMATTER_CLASS(name) \
+static const char *name##_get_name(void *ctx) \
+{ \
+ return #name ; \
+} \
+static const AVClass name##_class = { \
+ .class_name = #name, \
+ .item_name = name##_get_name, \
+ .option = name##_options \
+}
+
+/* Default output */
+
+typedef struct DefaultContext {
+ const AVClass *class;
+ int nokey;
+ int noprint_wrappers;
+ int nested_section[SECTION_MAX_NB_LEVELS];
+} DefaultContext;
+
+#undef OFFSET
+#define OFFSET(x) offsetof(DefaultContext, x)
+
+static const AVOption default_options[] = {
+ { "noprint_wrappers", "do not print headers and footers", OFFSET(noprint_wrappers), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1 },
+ { "nw", "do not print headers and footers", OFFSET(noprint_wrappers), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1 },
+ { "nokey", "force no key printing", OFFSET(nokey), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1 },
+ { "nk", "force no key printing", OFFSET(nokey), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1 },
+ {NULL},
+};
+
+DEFINE_FORMATTER_CLASS(default);
+
+/* lame uppercasing routine, assumes the string is lower case ASCII */
+static inline char *upcase_string(char *dst, size_t dst_size, const char *src)
+{
+ int i;
+ for (i = 0; src[i] && i < dst_size-1; i++)
+ dst[i] = av_toupper(src[i]);
+ dst[i] = 0;
+ return dst;
+}
+
+static void default_print_section_header(AVTextFormatContext *wctx, const void *data)
+{
+ DefaultContext *def = wctx->priv;
+ char buf[32];
+ const struct AVTextFormatSection *section = wctx->section[wctx->level];
+ const struct AVTextFormatSection *parent_section = wctx->level ?
+ wctx->section[wctx->level-1] : NULL;
+
+ av_bprint_clear(&wctx->section_pbuf[wctx->level]);
+ if (parent_section &&
+ !(parent_section->flags & (AV_TEXTFORMAT_SECTION_FLAG_IS_WRAPPER|AV_TEXTFORMAT_SECTION_FLAG_IS_ARRAY))) {
+ def->nested_section[wctx->level] = 1;
+ av_bprintf(&wctx->section_pbuf[wctx->level], "%s%s:",
+ wctx->section_pbuf[wctx->level-1].str,
+ upcase_string(buf, sizeof(buf),
+ av_x_if_null(section->element_name, section->name)));
+ }
+
+ if (def->noprint_wrappers || def->nested_section[wctx->level])
+ return;
+
+ if (!(section->flags & (AV_TEXTFORMAT_SECTION_FLAG_IS_WRAPPER|AV_TEXTFORMAT_SECTION_FLAG_IS_ARRAY)))
+ writer_printf(wctx, "[%s]\n", upcase_string(buf, sizeof(buf), section->name));
+}
+
+static void default_print_section_footer(AVTextFormatContext *wctx)
+{
+ DefaultContext *def = wctx->priv;
+ const struct AVTextFormatSection *section = wctx->section[wctx->level];
+ char buf[32];
+
+ if (def->noprint_wrappers || def->nested_section[wctx->level])
+ return;
+
+ if (!(section->flags & (AV_TEXTFORMAT_SECTION_FLAG_IS_WRAPPER|AV_TEXTFORMAT_SECTION_FLAG_IS_ARRAY)))
+ writer_printf(wctx, "[/%s]\n", upcase_string(buf, sizeof(buf), section->name));
+}
+
+static void default_print_str(AVTextFormatContext *wctx, const char *key, const char *value)
+{
+ DefaultContext *def = wctx->priv;
+
+ if (!def->nokey)
+ writer_printf(wctx, "%s%s=", wctx->section_pbuf[wctx->level].str, key);
+ writer_printf(wctx, "%s\n", value);
+}
+
+static void default_print_int(AVTextFormatContext *wctx, const char *key, int64_t value)
+{
+ DefaultContext *def = wctx->priv;
+
+ if (!def->nokey)
+ writer_printf(wctx, "%s%s=", wctx->section_pbuf[wctx->level].str, key);
+ writer_printf(wctx, "%"PRId64"\n", value);
+}
+
+const AVTextFormatter avtextformatter_default = {
+ .name = "default",
+ .priv_size = sizeof(DefaultContext),
+ .print_section_header = default_print_section_header,
+ .print_section_footer = default_print_section_footer,
+ .print_integer = default_print_int,
+ .print_string = default_print_str,
+ .flags = AV_TEXTFORMAT_FLAG_SUPPORTS_OPTIONAL_FIELDS,
+ .priv_class = &default_class,
+};
\ No newline at end of file
diff --git a/fftools/textformat/tf_flat.c b/fftools/textformat/tf_flat.c
new file mode 100644
index 0000000000..6971593c77
--- /dev/null
+++ b/fftools/textformat/tf_flat.c
@@ -0,0 +1,174 @@
+/*
+ * Copyright (c) The FFmpeg developers
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <limits.h>
+#include <stdarg.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "avtextformat.h"
+#include <libavutil/mem.h>
+#include <libavutil/avassert.h>
+#include <libavutil/bprint.h>
+#include <libavutil/error.h>
+#include <libavutil/macros.h>
+#include <libavutil/opt.h>
+
+#define writer_w8(wctx_, b_) (wctx_)->writer->writer->writer_w8((wctx_)->writer, b_)
+#define writer_put_str(wctx_, str_) (wctx_)->writer->writer->writer_put_str((wctx_)->writer, str_)
+#define writer_printf(wctx_, fmt_, ...) (wctx_)->writer->writer->writer_printf((wctx_)->writer, fmt_, __VA_ARGS__)
+
+#define DEFINE_FORMATTER_CLASS(name) \
+static const char *name##_get_name(void *ctx) \
+{ \
+ return #name ; \
+} \
+static const AVClass name##_class = { \
+ .class_name = #name, \
+ .item_name = name##_get_name, \
+ .option = name##_options \
+}
+
+
+/* Flat output */
+
+typedef struct FlatContext {
+ const AVClass *class;
+ const char *sep_str;
+ char sep;
+ int hierarchical;
+} FlatContext;
+
+#undef OFFSET
+#define OFFSET(x) offsetof(FlatContext, x)
+
+static const AVOption flat_options[]= {
+ {"sep_char", "set separator", OFFSET(sep_str), AV_OPT_TYPE_STRING, {.str="."}, 0, 0 },
+ {"s", "set separator", OFFSET(sep_str), AV_OPT_TYPE_STRING, {.str="."}, 0, 0 },
+ {"hierarchical", "specify if the section specification should be hierarchical", OFFSET(hierarchical), AV_OPT_TYPE_BOOL, {.i64=1}, 0, 1 },
+ {"h", "specify if the section specification should be hierarchical", OFFSET(hierarchical), AV_OPT_TYPE_BOOL, {.i64=1}, 0, 1 },
+ {NULL},
+};
+
+DEFINE_FORMATTER_CLASS(flat);
+
+static av_cold int flat_init(AVTextFormatContext *wctx)
+{
+ FlatContext *flat = wctx->priv;
+
+ if (strlen(flat->sep_str) != 1) {
+ av_log(wctx, AV_LOG_ERROR, "Item separator '%s' specified, but must contain a single character\n",
+ flat->sep_str);
+ return AVERROR(EINVAL);
+ }
+ flat->sep = flat->sep_str[0];
+
+ return 0;
+}
+
+static const char *flat_escape_key_str(AVBPrint *dst, const char *src, const char sep)
+{
+ const char *p;
+
+ for (p = src; *p; p++) {
+ if (!((*p >= '0' && *p <= '9') ||
+ (*p >= 'a' && *p <= 'z') ||
+ (*p >= 'A' && *p <= 'Z')))
+ av_bprint_chars(dst, '_', 1);
+ else
+ av_bprint_chars(dst, *p, 1);
+ }
+ return dst->str;
+}
+
+static const char *flat_escape_value_str(AVBPrint *dst, const char *src)
+{
+ const char *p;
+
+ for (p = src; *p; p++) {
+ switch (*p) {
+ case '\n': av_bprintf(dst, "%s", "\\n"); break;
+ case '\r': av_bprintf(dst, "%s", "\\r"); break;
+ case '\\': av_bprintf(dst, "%s", "\\\\"); break;
+ case '"': av_bprintf(dst, "%s", "\\\""); break;
+ case '`': av_bprintf(dst, "%s", "\\`"); break;
+ case '$': av_bprintf(dst, "%s", "\\$"); break;
+ default: av_bprint_chars(dst, *p, 1); break;
+ }
+ }
+ return dst->str;
+}
+
+static void flat_print_section_header(AVTextFormatContext *wctx, const void *data)
+{
+ FlatContext *flat = wctx->priv;
+ AVBPrint *buf = &wctx->section_pbuf[wctx->level];
+ const struct AVTextFormatSection *section = wctx->section[wctx->level];
+ const struct AVTextFormatSection *parent_section = wctx->level ?
+ wctx->section[wctx->level-1] : NULL;
+
+ /* build section header */
+ av_bprint_clear(buf);
+ if (!parent_section)
+ return;
+ av_bprintf(buf, "%s", wctx->section_pbuf[wctx->level-1].str);
+
+ if (flat->hierarchical ||
+ !(section->flags & (AV_TEXTFORMAT_SECTION_FLAG_IS_ARRAY|AV_TEXTFORMAT_SECTION_FLAG_IS_WRAPPER))) {
+ av_bprintf(buf, "%s%s", wctx->section[wctx->level]->name, flat->sep_str);
+
+ if (parent_section->flags & AV_TEXTFORMAT_SECTION_FLAG_IS_ARRAY) {
+ int n = parent_section->flags & AV_TEXTFORMAT_SECTION_FLAG_NUMBERING_BY_TYPE ?
+ wctx->nb_item_type[wctx->level-1][section->id] :
+ wctx->nb_item[wctx->level-1];
+ av_bprintf(buf, "%d%s", n, flat->sep_str);
+ }
+ }
+}
+
+static void flat_print_int(AVTextFormatContext *wctx, const char *key, int64_t value)
+{
+ writer_printf(wctx, "%s%s=%"PRId64"\n", wctx->section_pbuf[wctx->level].str, key, value);
+}
+
+static void flat_print_str(AVTextFormatContext *wctx, const char *key, const char *value)
+{
+ FlatContext *flat = wctx->priv;
+ AVBPrint buf;
+
+ writer_put_str(wctx, wctx->section_pbuf[wctx->level].str);
+ av_bprint_init(&buf, 1, AV_BPRINT_SIZE_UNLIMITED);
+ writer_printf(wctx, "%s=", flat_escape_key_str(&buf, key, flat->sep));
+ av_bprint_clear(&buf);
+ writer_printf(wctx, "\"%s\"\n", flat_escape_value_str(&buf, value));
+ av_bprint_finalize(&buf, NULL);
+}
+
+const AVTextFormatter avtextformatter_flat = {
+ .name = "flat",
+ .priv_size = sizeof(FlatContext),
+ .init = flat_init,
+ .print_section_header = flat_print_section_header,
+ .print_integer = flat_print_int,
+ .print_string = flat_print_str,
+ .flags = AV_TEXTFORMAT_FLAG_SUPPORTS_OPTIONAL_FIELDS|AV_TEXTFORMAT_FLAG_SUPPORTS_MIXED_ARRAY_CONTENT,
+ .priv_class = &flat_class,
+};
diff --git a/fftools/textformat/tf_ini.c b/fftools/textformat/tf_ini.c
new file mode 100644
index 0000000000..1f4216069f
--- /dev/null
+++ b/fftools/textformat/tf_ini.c
@@ -0,0 +1,160 @@
+/*
+ * Copyright (c) The FFmpeg developers
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <limits.h>
+#include <stdarg.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "avtextformat.h"
+#include <libavutil/mem.h>
+#include <libavutil/avassert.h>
+#include <libavutil/bprint.h>
+#include <libavutil/opt.h>
+
+#define writer_w8(wctx_, b_) (wctx_)->writer->writer->writer_w8((wctx_)->writer, b_)
+#define writer_put_str(wctx_, str_) (wctx_)->writer->writer->writer_put_str((wctx_)->writer, str_)
+#define writer_printf(wctx_, fmt_, ...) (wctx_)->writer->writer->writer_printf((wctx_)->writer, fmt_, __VA_ARGS__)
+
+#define DEFINE_FORMATTER_CLASS(name) \
+static const char *name##_get_name(void *ctx) \
+{ \
+ return #name ; \
+} \
+static const AVClass name##_class = { \
+ .class_name = #name, \
+ .item_name = name##_get_name, \
+ .option = name##_options \
+}
+
+/* Default output */
+
+typedef struct DefaultContext {
+ const AVClass *class;
+ int nokey;
+ int noprint_wrappers;
+ int nested_section[SECTION_MAX_NB_LEVELS];
+} DefaultContext;
+
+/* INI format output */
+
+typedef struct INIContext {
+ const AVClass *class;
+ int hierarchical;
+} INIContext;
+
+#undef OFFSET
+#define OFFSET(x) offsetof(INIContext, x)
+
+static const AVOption ini_options[] = {
+ {"hierarchical", "specify if the section specification should be hierarchical", OFFSET(hierarchical), AV_OPT_TYPE_BOOL, {.i64=1}, 0, 1 },
+ {"h", "specify if the section specification should be hierarchical", OFFSET(hierarchical), AV_OPT_TYPE_BOOL, {.i64=1}, 0, 1 },
+ {NULL},
+};
+
+DEFINE_FORMATTER_CLASS(ini);
+
+static char *ini_escape_str(AVBPrint *dst, const char *src)
+{
+ int i = 0;
+ char c = 0;
+
+ while (c = src[i++]) {
+ switch (c) {
+ case '\b': av_bprintf(dst, "%s", "\\b"); break;
+ case '\f': av_bprintf(dst, "%s", "\\f"); break;
+ case '\n': av_bprintf(dst, "%s", "\\n"); break;
+ case '\r': av_bprintf(dst, "%s", "\\r"); break;
+ case '\t': av_bprintf(dst, "%s", "\\t"); break;
+ case '\\':
+ case '#' :
+ case '=' :
+ case ':' : av_bprint_chars(dst, '\\', 1);
+ default:
+ if ((unsigned char)c < 32)
+ av_bprintf(dst, "\\x00%02x", c & 0xff);
+ else
+ av_bprint_chars(dst, c, 1);
+ break;
+ }
+ }
+ return dst->str;
+}
+
+static void ini_print_section_header(AVTextFormatContext *wctx, const void *data)
+{
+ INIContext *ini = wctx->priv;
+ AVBPrint *buf = &wctx->section_pbuf[wctx->level];
+ const struct AVTextFormatSection *section = wctx->section[wctx->level];
+ const struct AVTextFormatSection *parent_section = wctx->level ?
+ wctx->section[wctx->level-1] : NULL;
+
+ av_bprint_clear(buf);
+ if (!parent_section) {
+ writer_put_str(wctx, "# ffprobe output\n\n");
+ return;
+ }
+
+ if (wctx->nb_item[wctx->level-1])
+ writer_w8(wctx, '\n');
+
+ av_bprintf(buf, "%s", wctx->section_pbuf[wctx->level-1].str);
+ if (ini->hierarchical ||
+ !(section->flags & (AV_TEXTFORMAT_SECTION_FLAG_IS_ARRAY|AV_TEXTFORMAT_SECTION_FLAG_IS_WRAPPER))) {
+ av_bprintf(buf, "%s%s", buf->str[0] ? "." : "", wctx->section[wctx->level]->name);
+
+ if (parent_section->flags & AV_TEXTFORMAT_SECTION_FLAG_IS_ARRAY) {
+ int n = parent_section->flags & AV_TEXTFORMAT_SECTION_FLAG_NUMBERING_BY_TYPE ?
+ wctx->nb_item_type[wctx->level-1][section->id] :
+ wctx->nb_item[wctx->level-1];
+ av_bprintf(buf, ".%d", n);
+ }
+ }
+
+ if (!(section->flags & (AV_TEXTFORMAT_SECTION_FLAG_IS_ARRAY|AV_TEXTFORMAT_SECTION_FLAG_IS_WRAPPER)))
+ writer_printf(wctx, "[%s]\n", buf->str);
+}
+
+static void ini_print_str(AVTextFormatContext *wctx, const char *key, const char *value)
+{
+ AVBPrint buf;
+
+ av_bprint_init(&buf, 1, AV_BPRINT_SIZE_UNLIMITED);
+ writer_printf(wctx, "%s=", ini_escape_str(&buf, key));
+ av_bprint_clear(&buf);
+ writer_printf(wctx, "%s\n", ini_escape_str(&buf, value));
+ av_bprint_finalize(&buf, NULL);
+}
+
+static void ini_print_int(AVTextFormatContext *wctx, const char *key, int64_t value)
+{
+ writer_printf(wctx, "%s=%"PRId64"\n", key, value);
+}
+
+const AVTextFormatter avtextformatter_ini = {
+ .name = "ini",
+ .priv_size = sizeof(INIContext),
+ .print_section_header = ini_print_section_header,
+ .print_integer = ini_print_int,
+ .print_string = ini_print_str,
+ .flags = AV_TEXTFORMAT_FLAG_SUPPORTS_OPTIONAL_FIELDS|AV_TEXTFORMAT_FLAG_SUPPORTS_MIXED_ARRAY_CONTENT,
+ .priv_class = &ini_class,
+};
diff --git a/fftools/textformat/tf_json.c b/fftools/textformat/tf_json.c
new file mode 100644
index 0000000000..de27a36e7e
--- /dev/null
+++ b/fftools/textformat/tf_json.c
@@ -0,0 +1,215 @@
+/*
+ * Copyright (c) The FFmpeg developers
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <limits.h>
+#include <stdarg.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "avtextformat.h"
+#include <libavutil/mem.h>
+#include <libavutil/avassert.h>
+#include <libavutil/bprint.h>
+#include <libavutil/opt.h>
+
+#define writer_w8(wctx_, b_) (wctx_)->writer->writer->writer_w8((wctx_)->writer, b_)
+#define writer_put_str(wctx_, str_) (wctx_)->writer->writer->writer_put_str((wctx_)->writer, str_)
+#define writer_printf(wctx_, fmt_, ...) (wctx_)->writer->writer->writer_printf((wctx_)->writer, fmt_, __VA_ARGS__)
+
+#define DEFINE_FORMATTER_CLASS(name) \
+static const char *name##_get_name(void *ctx) \
+{ \
+ return #name ; \
+} \
+static const AVClass name##_class = { \
+ .class_name = #name, \
+ .item_name = name##_get_name, \
+ .option = name##_options \
+}
+
+
+/* JSON output */
+
+typedef struct JSONContext {
+ const AVClass *class;
+ int indent_level;
+ int compact;
+ const char *item_sep, *item_start_end;
+} JSONContext;
+
+#undef OFFSET
+#define OFFSET(x) offsetof(JSONContext, x)
+
+static const AVOption json_options[]= {
+ { "compact", "enable compact output", OFFSET(compact), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1 },
+ { "c", "enable compact output", OFFSET(compact), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1 },
+ { NULL }
+};
+
+DEFINE_FORMATTER_CLASS(json);
+
+static av_cold int json_init(AVTextFormatContext *wctx)
+{
+ JSONContext *json = wctx->priv;
+
+ json->item_sep = json->compact ? ", " : ",\n";
+ json->item_start_end = json->compact ? " " : "\n";
+
+ return 0;
+}
+
+static const char *json_escape_str(AVBPrint *dst, const char *src, void *log_ctx)
+{
+ static const char json_escape[] = {'"', '\\', '\b', '\f', '\n', '\r', '\t', 0};
+ static const char json_subst[] = {'"', '\\', 'b', 'f', 'n', 'r', 't', 0};
+ const char *p;
+
+ for (p = src; *p; p++) {
+ char *s = strchr(json_escape, *p);
+ if (s) {
+ av_bprint_chars(dst, '\\', 1);
+ av_bprint_chars(dst, json_subst[s - json_escape], 1);
+ } else if ((unsigned char)*p < 32) {
+ av_bprintf(dst, "\\u00%02x", *p & 0xff);
+ } else {
+ av_bprint_chars(dst, *p, 1);
+ }
+ }
+ return dst->str;
+}
+
+#define JSON_INDENT() writer_printf(wctx, "%*c", json->indent_level * 4, ' ')
+
+static void json_print_section_header(AVTextFormatContext *wctx, const void *data)
+{
+ JSONContext *json = wctx->priv;
+ AVBPrint buf;
+ const struct AVTextFormatSection *section = wctx->section[wctx->level];
+ const struct AVTextFormatSection *parent_section = wctx->level ?
+ wctx->section[wctx->level-1] : NULL;
+
+ if (wctx->level && wctx->nb_item[wctx->level-1])
+ writer_put_str(wctx, ",\n");
+
+ if (section->flags & AV_TEXTFORMAT_SECTION_FLAG_IS_WRAPPER) {
+ writer_put_str(wctx, "{\n");
+ json->indent_level++;
+ } else {
+ av_bprint_init(&buf, 1, AV_BPRINT_SIZE_UNLIMITED);
+ json_escape_str(&buf, section->name, wctx);
+ JSON_INDENT();
+
+ json->indent_level++;
+ if (section->flags & AV_TEXTFORMAT_SECTION_FLAG_IS_ARRAY) {
+ writer_printf(wctx, "\"%s\": [\n", buf.str);
+ } else if (parent_section && !(parent_section->flags & AV_TEXTFORMAT_SECTION_FLAG_IS_ARRAY)) {
+ writer_printf(wctx, "\"%s\": {%s", buf.str, json->item_start_end);
+ } else {
+ writer_printf(wctx, "{%s", json->item_start_end);
+
+ /* this is required so the parser can distinguish between packets and frames */
+ if (parent_section && parent_section->flags & AV_TEXTFORMAT_SECTION_FLAG_NUMBERING_BY_TYPE) {
+ if (!json->compact)
+ JSON_INDENT();
+ writer_printf(wctx, "\"type\": \"%s\"", section->name);
+ wctx->nb_item[wctx->level]++;
+ }
+ }
+ av_bprint_finalize(&buf, NULL);
+ }
+}
+
+static void json_print_section_footer(AVTextFormatContext *wctx)
+{
+ JSONContext *json = wctx->priv;
+ const struct AVTextFormatSection *section = wctx->section[wctx->level];
+
+ if (wctx->level == 0) {
+ json->indent_level--;
+ writer_put_str(wctx, "\n}\n");
+ } else if (section->flags & AV_TEXTFORMAT_SECTION_FLAG_IS_ARRAY) {
+ writer_w8(wctx, '\n');
+ json->indent_level--;
+ JSON_INDENT();
+ writer_w8(wctx, ']');
+ } else {
+ writer_put_str(wctx, json->item_start_end);
+ json->indent_level--;
+ if (!json->compact)
+ JSON_INDENT();
+ writer_w8(wctx, '}');
+ }
+}
+
+static inline void json_print_item_str(AVTextFormatContext *wctx,
+ const char *key, const char *value)
+{
+ AVBPrint buf;
+
+ av_bprint_init(&buf, 1, AV_BPRINT_SIZE_UNLIMITED);
+ writer_printf(wctx, "\"%s\":", json_escape_str(&buf, key, wctx));
+ av_bprint_clear(&buf);
+ writer_printf(wctx, " \"%s\"", json_escape_str(&buf, value, wctx));
+ av_bprint_finalize(&buf, NULL);
+}
+
+static void json_print_str(AVTextFormatContext *wctx, const char *key, const char *value)
+{
+ JSONContext *json = wctx->priv;
+ const struct AVTextFormatSection *parent_section = wctx->level ?
+ wctx->section[wctx->level-1] : NULL;
+
+ if (wctx->nb_item[wctx->level] || (parent_section && parent_section->flags & AV_TEXTFORMAT_SECTION_FLAG_NUMBERING_BY_TYPE))
+ writer_put_str(wctx, json->item_sep);
+ if (!json->compact)
+ JSON_INDENT();
+ json_print_item_str(wctx, key, value);
+}
+
+static void json_print_int(AVTextFormatContext *wctx, const char *key, int64_t value)
+{
+ JSONContext *json = wctx->priv;
+ const struct AVTextFormatSection *parent_section = wctx->level ?
+ wctx->section[wctx->level-1] : NULL;
+ AVBPrint buf;
+
+ if (wctx->nb_item[wctx->level] || (parent_section && parent_section->flags & AV_TEXTFORMAT_SECTION_FLAG_NUMBERING_BY_TYPE))
+ writer_put_str(wctx, json->item_sep);
+ if (!json->compact)
+ JSON_INDENT();
+
+ av_bprint_init(&buf, 1, AV_BPRINT_SIZE_UNLIMITED);
+ writer_printf(wctx, "\"%s\": %"PRId64, json_escape_str(&buf, key, wctx), value);
+ av_bprint_finalize(&buf, NULL);
+}
+
+const AVTextFormatter avtextformatter_json = {
+ .name = "json",
+ .priv_size = sizeof(JSONContext),
+ .init = json_init,
+ .print_section_header = json_print_section_header,
+ .print_section_footer = json_print_section_footer,
+ .print_integer = json_print_int,
+ .print_string = json_print_str,
+ .flags = AV_TEXTFORMAT_FLAG_SUPPORTS_MIXED_ARRAY_CONTENT,
+ .priv_class = &json_class,
+};
+
diff --git a/fftools/textformat/tf_xml.c b/fftools/textformat/tf_xml.c
new file mode 100644
index 0000000000..57171c4cb3
--- /dev/null
+++ b/fftools/textformat/tf_xml.c
@@ -0,0 +1,221 @@
+/*
+ * Copyright (c) The FFmpeg developers
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <limits.h>
+#include <stdarg.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "avtextformat.h"
+#include <libavutil/mem.h>
+#include <libavutil/avassert.h>
+#include <libavutil/bprint.h>
+#include <libavutil/error.h>
+#include <libavutil/macros.h>
+#include <libavutil/opt.h>
+
+#define writer_w8(wctx_, b_) (wctx_)->writer->writer->writer_w8((wctx_)->writer, b_)
+#define writer_put_str(wctx_, str_) (wctx_)->writer->writer->writer_put_str((wctx_)->writer, str_)
+#define writer_printf(wctx_, fmt_, ...) (wctx_)->writer->writer->writer_printf((wctx_)->writer, fmt_, __VA_ARGS__)
+
+#define DEFINE_FORMATTER_CLASS(name) \
+static const char *name##_get_name(void *ctx) \
+{ \
+ return #name ; \
+} \
+static const AVClass name##_class = { \
+ .class_name = #name, \
+ .item_name = name##_get_name, \
+ .option = name##_options \
+}
+
+/* XML output */
+
+typedef struct XMLContext {
+ const AVClass *class;
+ int within_tag;
+ int indent_level;
+ int fully_qualified;
+ int xsd_strict;
+} XMLContext;
+
+#undef OFFSET
+#define OFFSET(x) offsetof(XMLContext, x)
+
+static const AVOption xml_options[] = {
+ {"fully_qualified", "specify if the output should be fully qualified", OFFSET(fully_qualified), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1 },
+ {"q", "specify if the output should be fully qualified", OFFSET(fully_qualified), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1 },
+ {"xsd_strict", "ensure that the output is XSD compliant", OFFSET(xsd_strict), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1 },
+ {"x", "ensure that the output is XSD compliant", OFFSET(xsd_strict), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1 },
+ {NULL},
+};
+
+DEFINE_FORMATTER_CLASS(xml);
+
+static av_cold int xml_init(AVTextFormatContext *wctx)
+{
+ XMLContext *xml = wctx->priv;
+
+ if (xml->xsd_strict) {
+ xml->fully_qualified = 1;
+#define CHECK_COMPLIANCE(opt, opt_name) \
+ if (opt) { \
+ av_log(wctx, AV_LOG_ERROR, \
+ "XSD-compliant output selected but option '%s' was selected, XML output may be non-compliant.\n" \
+ "You need to disable such option with '-no%s'\n", opt_name, opt_name); \
+ return AVERROR(EINVAL); \
+ }
+ ////CHECK_COMPLIANCE(show_private_data, "private");
+ CHECK_COMPLIANCE(wctx->show_value_unit, "unit");
+ CHECK_COMPLIANCE(wctx->use_value_prefix, "prefix");
+ }
+
+ return 0;
+}
+
+#define XML_INDENT() writer_printf(wctx, "%*c", xml->indent_level * 4, ' ')
+
+static void xml_print_section_header(AVTextFormatContext *wctx, const void *data)
+{
+ XMLContext *xml = wctx->priv;
+ const struct AVTextFormatSection *section = wctx->section[wctx->level];
+ const struct AVTextFormatSection *parent_section = wctx->level ?
+ wctx->section[wctx->level-1] : NULL;
+
+ if (wctx->level == 0) {
+ const char *qual = " xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" "
+ "xmlns:ffprobe=\"http://www.ffmpeg.org/schema/ffprobe\" "
+ "xsi:schemaLocation=\"http://www.ffmpeg.org/schema/ffprobe ffprobe.xsd\"";
+
+ writer_put_str(wctx, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
+ writer_printf(wctx, "<%sffprobe%s>\n",
+ xml->fully_qualified ? "ffprobe:" : "",
+ xml->fully_qualified ? qual : "");
+ return;
+ }
+
+ if (xml->within_tag) {
+ xml->within_tag = 0;
+ writer_put_str(wctx, ">\n");
+ }
+
+ if (parent_section && (parent_section->flags & AV_TEXTFORMAT_SECTION_FLAG_IS_WRAPPER) &&
+ wctx->level && wctx->nb_item[wctx->level-1])
+ writer_w8(wctx, '\n');
+ xml->indent_level++;
+
+ if (section->flags & (AV_TEXTFORMAT_SECTION_FLAG_IS_ARRAY|AV_TEXTFORMAT_SECTION_FLAG_HAS_VARIABLE_FIELDS)) {
+ XML_INDENT(); writer_printf(wctx, "<%s", section->name);
+
+ if (section->flags & AV_TEXTFORMAT_SECTION_FLAG_HAS_TYPE) {
+ AVBPrint buf;
+ av_bprint_init(&buf, 1, AV_BPRINT_SIZE_UNLIMITED);
+ av_bprint_escape(&buf, section->get_type(data), NULL,
+ AV_ESCAPE_MODE_XML, AV_ESCAPE_FLAG_XML_DOUBLE_QUOTES);
+ writer_printf(wctx, " type=\"%s\"", buf.str);
+ }
+ writer_printf(wctx, ">\n", section->name);
+ } else {
+ XML_INDENT(); writer_printf(wctx, "<%s ", section->name);
+ xml->within_tag = 1;
+ }
+}
+
+static void xml_print_section_footer(AVTextFormatContext *wctx)
+{
+ XMLContext *xml = wctx->priv;
+ const struct AVTextFormatSection *section = wctx->section[wctx->level];
+
+ if (wctx->level == 0) {
+ writer_printf(wctx, "</%sffprobe>\n", xml->fully_qualified ? "ffprobe:" : "");
+ } else if (xml->within_tag) {
+ xml->within_tag = 0;
+ writer_put_str(wctx, "/>\n");
+ xml->indent_level--;
+ } else {
+ XML_INDENT(); writer_printf(wctx, "</%s>\n", section->name);
+ xml->indent_level--;
+ }
+}
+
+static void xml_print_value(AVTextFormatContext *wctx, const char *key,
+ const char *str, int64_t num, const int is_int)
+{
+ AVBPrint buf;
+ XMLContext *xml = wctx->priv;
+ const struct AVTextFormatSection *section = wctx->section[wctx->level];
+
+ av_bprint_init(&buf, 1, AV_BPRINT_SIZE_UNLIMITED);
+
+ if (section->flags & AV_TEXTFORMAT_SECTION_FLAG_HAS_VARIABLE_FIELDS) {
+ xml->indent_level++;
+ XML_INDENT();
+ av_bprint_escape(&buf, key, NULL,
+ AV_ESCAPE_MODE_XML, AV_ESCAPE_FLAG_XML_DOUBLE_QUOTES);
+ writer_printf(wctx, "<%s key=\"%s\"",
+ section->element_name, buf.str);
+ av_bprint_clear(&buf);
+
+ if (is_int) {
+ writer_printf(wctx, " value=\"%"PRId64"\"/>\n", num);
+ } else {
+ av_bprint_escape(&buf, str, NULL,
+ AV_ESCAPE_MODE_XML, AV_ESCAPE_FLAG_XML_DOUBLE_QUOTES);
+ writer_printf(wctx, " value=\"%s\"/>\n", buf.str);
+ }
+ xml->indent_level--;
+ } else {
+ if (wctx->nb_item[wctx->level])
+ writer_w8(wctx, ' ');
+
+ if (is_int) {
+ writer_printf(wctx, "%s=\"%"PRId64"\"", key, num);
+ } else {
+ av_bprint_escape(&buf, str, NULL,
+ AV_ESCAPE_MODE_XML, AV_ESCAPE_FLAG_XML_DOUBLE_QUOTES);
+ writer_printf(wctx, "%s=\"%s\"", key, buf.str);
+ }
+ }
+
+ av_bprint_finalize(&buf, NULL);
+}
+
+static inline void xml_print_str(AVTextFormatContext *wctx, const char *key, const char *value) {
+ xml_print_value(wctx, key, value, 0, 0);
+}
+
+static void xml_print_int(AVTextFormatContext *wctx, const char *key, int64_t value)
+{
+ xml_print_value(wctx, key, NULL, value, 1);
+}
+
+const AVTextFormatter avtextformatter_xml = {
+ .name = "xml",
+ .priv_size = sizeof(XMLContext),
+ .init = xml_init,
+ .print_section_header = xml_print_section_header,
+ .print_section_footer = xml_print_section_footer,
+ .print_integer = xml_print_int,
+ .print_string = xml_print_str,
+ .flags = AV_TEXTFORMAT_FLAG_SUPPORTS_MIXED_ARRAY_CONTENT,
+ .priv_class = &xml_class,
+};
+
diff --git a/fftools/textformat/tw_avio.c b/fftools/textformat/tw_avio.c
new file mode 100644
index 0000000000..d335d35a56
--- /dev/null
+++ b/fftools/textformat/tw_avio.c
@@ -0,0 +1,129 @@
+/*
+ * Copyright (c) The FFmpeg developers
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <limits.h>
+#include <stdarg.h>
+
+#include "avtextwriters.h"
+#include "libavutil/opt.h"
+
+/* AVIO Writer */
+
+# define WRITER_NAME "aviowriter"
+
+typedef struct IOWriterContext {
+ const AVClass *class;
+ AVIOContext *avio_context;
+ int close_on_uninit;
+} IOWriterContext;
+
+static const char *iowriter_get_name(void *ctx)
+{
+ return WRITER_NAME;
+}
+
+static const AVClass iowriter_class = {
+ .class_name = WRITER_NAME,
+ .item_name = iowriter_get_name,
+};
+
+static av_cold void iowriter_uninit(AVTextWriterContext *wctx)
+{
+ IOWriterContext *ctx = wctx->priv;
+
+ if (ctx->close_on_uninit && ctx->avio_context) {
+ avio_flush(ctx->avio_context);
+ avio_close(ctx->avio_context);
+ }
+}
+
+static void io_w8(AVTextWriterContext *wctx, int b)
+{
+ IOWriterContext *ctx = wctx->priv;
+ avio_w8(ctx->avio_context, b);
+}
+
+static void io_put_str(AVTextWriterContext *wctx, const char *str)
+{
+ IOWriterContext *ctx = wctx->priv;
+ avio_write(ctx->avio_context, str, strlen(str));
+}
+
+static void io_printf(AVTextWriterContext *wctx, const char *fmt, ...)
+{
+ IOWriterContext *ctx = wctx->priv;
+ va_list ap;
+
+ va_start(ap, fmt);
+ avio_vprintf(ctx->avio_context, fmt, ap);
+ va_end(ap);
+}
+
+
+const AVTextWriter avtextwriter_avio = {
+ .name = WRITER_NAME,
+ .priv_size = sizeof(IOWriterContext),
+ .uninit = iowriter_uninit,
+ .priv_class = &iowriter_class,
+ .writer_put_str = io_put_str,
+ .writer_printf = io_printf,
+ .writer_w8 = io_w8
+};
+
+int avtextwriter_create_file(AVTextWriterContext **pwctx, const char *output_filename, int close_on_uninit)
+{
+ IOWriterContext *ctx;
+ int ret;
+
+
+ ret = avtextwriter_context_open(pwctx, &avtextwriter_avio);
+ if (ret < 0)
+ return ret;
+
+ ctx = (*pwctx)->priv;
+
+ if ((ret = avio_open(&ctx->avio_context, output_filename, AVIO_FLAG_WRITE)) < 0) {
+ av_log(ctx, AV_LOG_ERROR,
+ "Failed to open output '%s' with error: %s\n", output_filename, av_err2str(ret));
+ avtextwriter_context_close(pwctx);
+ return ret;
+ }
+
+ ctx->close_on_uninit = close_on_uninit;
+
+ return ret;
+}
+
+
+int avtextwriter_create_avio(AVTextWriterContext **pwctx, AVIOContext *avio_ctx, int close_on_uninit)
+{
+ IOWriterContext *ctx;
+ int ret;
+
+ ret = avtextwriter_context_open(pwctx, &avtextwriter_avio);
+ if (ret < 0)
+ return ret;
+
+ ctx = (*pwctx)->priv;
+ ctx->avio_context = avio_ctx;
+ ctx->close_on_uninit = close_on_uninit;
+
+ return ret;
+}
diff --git a/fftools/textformat/tw_buffer.c b/fftools/textformat/tw_buffer.c
new file mode 100644
index 0000000000..f8b38414a6
--- /dev/null
+++ b/fftools/textformat/tw_buffer.c
@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) The FFmpeg developers
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <limits.h>
+#include <stdarg.h>
+
+#include "avtextwriters.h"
+#include "libavutil/opt.h"
+#include "libavutil/bprint.h"
+
+/* Buffer Writer */
+
+# define WRITER_NAME "bufferwriter"
+
+typedef struct BufferWriterContext {
+ const AVClass *class;
+ AVBPrint *buffer;
+} BufferWriterContext;
+
+static const char *bufferwriter_get_name(void *ctx)
+{
+ return WRITER_NAME;
+}
+
+static const AVClass bufferwriter_class = {
+ .class_name = WRITER_NAME,
+ .item_name = bufferwriter_get_name,
+};
+
+static void buffer_w8(AVTextWriterContext *wctx, int b)
+{
+ BufferWriterContext *ctx = wctx->priv;
+ av_bprintf(ctx->buffer, "%c", b);
+}
+
+static void buffer_put_str(AVTextWriterContext *wctx, const char *str)
+{
+ BufferWriterContext *ctx = wctx->priv;
+ av_bprintf(ctx->buffer, "%s", str);
+}
+
+static void buffer_printf(AVTextWriterContext *wctx, const char *fmt, ...)
+{
+ BufferWriterContext *ctx = wctx->priv;
+
+ va_list vargs;
+ va_start(vargs, fmt);
+ av_vbprintf(ctx->buffer, fmt, vargs);
+ va_end(vargs);
+}
+
+
+const AVTextWriter avtextwriter_buffer = {
+ .name = WRITER_NAME,
+ .priv_size = sizeof(BufferWriterContext),
+ .priv_class = &bufferwriter_class,
+ .writer_put_str = buffer_put_str,
+ .writer_printf = buffer_printf,
+ .writer_w8 = buffer_w8
+};
+
+int avtextwriter_create_buffer(AVTextWriterContext **pwctx, AVBPrint *buffer)
+{
+ BufferWriterContext *ctx;
+ int ret;
+
+ ret = avtextwriter_context_open(pwctx, &avtextwriter_buffer);
+ if (ret < 0)
+ return ret;
+
+ ctx = (*pwctx)->priv;
+ ctx->buffer = buffer;
+
+ return ret;
+}
diff --git a/fftools/textformat/tw_stdout.c b/fftools/textformat/tw_stdout.c
new file mode 100644
index 0000000000..23de6f671f
--- /dev/null
+++ b/fftools/textformat/tw_stdout.c
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) The FFmpeg developers
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <stdarg.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "avtextwriters.h"
+#include "libavutil/opt.h"
+
+/* STDOUT Writer */
+
+# define WRITER_NAME "stdoutwriter"
+
+typedef struct StdOutWriterContext {
+ const AVClass *class;
+} StdOutWriterContext;
+
+static const char *stdoutwriter_get_name(void *ctx)
+{
+ return WRITER_NAME;
+}
+
+static const AVClass stdoutwriter_class = {
+ .class_name = WRITER_NAME,
+ .item_name = stdoutwriter_get_name,
+};
+
+static inline void stdout_w8(AVTextWriterContext *wctx, int b)
+{
+ printf("%c", b);
+}
+
+static inline void stdout_put_str(AVTextWriterContext *wctx, const char *str)
+{
+ printf("%s", str);
+}
+
+static inline void stdout_printf(AVTextWriterContext *wctx, const char *fmt, ...)
+{
+ va_list ap;
+
+ va_start(ap, fmt);
+ vprintf(fmt, ap);
+ va_end(ap);
+}
+
+
+static const AVTextWriter avtextwriter_stdout = {
+ .name = WRITER_NAME,
+ .priv_size = sizeof(StdOutWriterContext),
+ .priv_class = &stdoutwriter_class,
+ .writer_put_str = stdout_put_str,
+ .writer_printf = stdout_printf,
+ .writer_w8 = stdout_w8
+};
+
+int avtextwriter_create_stdout(AVTextWriterContext **pwctx)
+{
+ int ret;
+
+ ret = avtextwriter_context_open(pwctx, &avtextwriter_stdout);
+
+ return ret;
+}
--
ffmpeg-codebot
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 108+ messages in thread
* [FFmpeg-devel] [PATCH v9 2/4] fftools/ffprobe: Change to use textformat api
2025-03-23 3:42 ` [FFmpeg-devel] [PATCH v9 " ffmpegagent
2025-03-23 3:42 ` [FFmpeg-devel] [PATCH v9 1/4] fftools/textformat: Extract and generalize textformat api from ffprobe.c softworkz
@ 2025-03-23 3:42 ` softworkz
2025-03-23 3:42 ` [FFmpeg-devel] [PATCH v9 3/4] fftools/ffprobe: Rename writer_print_section_* and WriterContext softworkz
2025-03-23 3:42 ` [FFmpeg-devel] [PATCH v9 4/4] fftools/ffprobe: Rename AVTextFormatContext variables (w => tfc) softworkz
3 siblings, 0 replies; 108+ messages in thread
From: softworkz @ 2025-03-23 3:42 UTC (permalink / raw)
To: ffmpeg-devel; +Cc: softworkz
From: softworkz <softworkz@hotmail.com>
Signed-off-by: softworkz <softworkz@hotmail.com>
---
fftools/Makefile | 15 +-
fftools/ffprobe.c | 1849 ++++-----------------------------------------
2 files changed, 144 insertions(+), 1720 deletions(-)
diff --git a/fftools/Makefile b/fftools/Makefile
index 4499799818..e9c9891c34 100644
--- a/fftools/Makefile
+++ b/fftools/Makefile
@@ -22,6 +22,18 @@ OBJS-ffmpeg += \
fftools/sync_queue.o \
fftools/thread_queue.o \
+OBJS-ffprobe += \
+ fftools/textformat/avtextformat.o \
+ fftools/textformat/tf_compact.o \
+ fftools/textformat/tf_default.o \
+ fftools/textformat/tf_flat.o \
+ fftools/textformat/tf_ini.o \
+ fftools/textformat/tf_json.o \
+ fftools/textformat/tf_xml.o \
+ fftools/textformat/tw_avio.o \
+ fftools/textformat/tw_buffer.o \
+ fftools/textformat/tw_stdout.o \
+
OBJS-ffplay += fftools/ffplay_renderer.o
define DOFFTOOL
@@ -30,7 +42,7 @@ ifdef HAVE_GNU_WINDRES
OBJS-$(1) += fftools/fftoolsres.o
endif
$(1)$(PROGSSUF)_g$(EXESUF): $$(OBJS-$(1))
-$$(OBJS-$(1)): | fftools
+$$(OBJS-$(1)): | fftools fftools/textformat
$$(OBJS-$(1)): CFLAGS += $(CFLAGS-$(1))
$(1)$(PROGSSUF)_g$(EXESUF): LDFLAGS += $(LDFLAGS-$(1))
$(1)$(PROGSSUF)_g$(EXESUF): FF_EXTRALIBS += $(EXTRALIBS-$(1))
@@ -43,6 +55,7 @@ all: $(AVPROGS)
fftools/ffprobe.o fftools/cmdutils.o: libavutil/ffversion.h | fftools
OUTDIRS += fftools
+OUTDIRS += fftools/textformat
ifdef AVPROGS
install: install-progs install-data
diff --git a/fftools/ffprobe.c b/fftools/ffprobe.c
index 7341731d2f..f398057df7 100644
--- a/fftools/ffprobe.c
+++ b/fftools/ffprobe.c
@@ -40,7 +40,6 @@
#include "libavutil/channel_layout.h"
#include "libavutil/display.h"
#include "libavutil/film_grain_params.h"
-#include "libavutil/hash.h"
#include "libavutil/hdr_dynamic_metadata.h"
#include "libavutil/iamf.h"
#include "libavutil/mastering_display_metadata.h"
@@ -66,11 +65,17 @@
#include "libpostproc/postprocess.h"
#include "libpostproc/version.h"
#include "libavfilter/version.h"
+#include "textformat/avtextformat.h"
#include "cmdutils.h"
#include "opt_common.h"
#include "libavutil/thread.h"
+// TEMPORARY DEFINES
+#define writer_print_section_header(w, d, s) avtext_print_section_header(w, d, s)
+#define writer_print_section_footer(w) avtext_print_section_footer(w)
+#define WriterContext AVTextFormatContext
+
// attached as opaque_ref to packets/frames
typedef struct FrameData {
int64_t pkt_pos;
@@ -156,10 +161,7 @@ static int find_stream_info = 1;
/* section structure definition */
-#define SECTION_MAX_NB_CHILDREN 11
-
typedef enum {
- SECTION_ID_NONE = -1,
SECTION_ID_CHAPTER,
SECTION_ID_CHAPTER_TAGS,
SECTION_ID_CHAPTERS,
@@ -228,25 +230,6 @@ typedef enum {
SECTION_ID_SUBTITLE,
} SectionID;
-struct section {
- int id; ///< unique id identifying a section
- const char *name;
-
-#define SECTION_FLAG_IS_WRAPPER 1 ///< the section only contains other sections, but has no data at its own level
-#define SECTION_FLAG_IS_ARRAY 2 ///< the section contains an array of elements of the same type
-#define SECTION_FLAG_HAS_VARIABLE_FIELDS 4 ///< the section may contain a variable number of fields with variable keys.
- /// For these sections the element_name field is mandatory.
-#define SECTION_FLAG_HAS_TYPE 8 ///< the section contains a type to distinguish multiple nested elements
-
- int flags;
- const SectionID children_ids[SECTION_MAX_NB_CHILDREN+1]; ///< list of children section IDS, terminated by -1
- const char *element_name; ///< name of the contained element, if provided
- const char *unique_name; ///< unique section name, in case the name is ambiguous
- AVDictionary *entries_to_show;
- const char *(* get_type)(const void *data); ///< function returning a type if defined, must be defined when SECTION_FLAG_HAS_TYPE is defined
- int show_all_entries;
-};
-
static const char *get_packet_side_data_type(const void *data)
{
const AVPacketSideData *sd = (const AVPacketSideData *)data;
@@ -270,75 +253,75 @@ static const char *get_stream_group_type(const void *data)
return av_x_if_null(avformat_stream_group_name(stg->type), "unknown");
}
-static struct section sections[] = {
- [SECTION_ID_CHAPTERS] = { SECTION_ID_CHAPTERS, "chapters", SECTION_FLAG_IS_ARRAY, { SECTION_ID_CHAPTER, -1 } },
+static struct AVTextFormatSection sections[] = {
+ [SECTION_ID_CHAPTERS] = { SECTION_ID_CHAPTERS, "chapters", AV_TEXTFORMAT_SECTION_FLAG_IS_ARRAY, { SECTION_ID_CHAPTER, -1 } },
[SECTION_ID_CHAPTER] = { SECTION_ID_CHAPTER, "chapter", 0, { SECTION_ID_CHAPTER_TAGS, -1 } },
- [SECTION_ID_CHAPTER_TAGS] = { SECTION_ID_CHAPTER_TAGS, "tags", SECTION_FLAG_HAS_VARIABLE_FIELDS, { -1 }, .element_name = "tag", .unique_name = "chapter_tags" },
+ [SECTION_ID_CHAPTER_TAGS] = { SECTION_ID_CHAPTER_TAGS, "tags", AV_TEXTFORMAT_SECTION_FLAG_HAS_VARIABLE_FIELDS, { -1 }, .element_name = "tag", .unique_name = "chapter_tags" },
[SECTION_ID_ERROR] = { SECTION_ID_ERROR, "error", 0, { -1 } },
[SECTION_ID_FORMAT] = { SECTION_ID_FORMAT, "format", 0, { SECTION_ID_FORMAT_TAGS, -1 } },
- [SECTION_ID_FORMAT_TAGS] = { SECTION_ID_FORMAT_TAGS, "tags", SECTION_FLAG_HAS_VARIABLE_FIELDS, { -1 }, .element_name = "tag", .unique_name = "format_tags" },
- [SECTION_ID_FRAMES] = { SECTION_ID_FRAMES, "frames", SECTION_FLAG_IS_ARRAY, { SECTION_ID_FRAME, SECTION_ID_SUBTITLE, -1 } },
+ [SECTION_ID_FORMAT_TAGS] = { SECTION_ID_FORMAT_TAGS, "tags", AV_TEXTFORMAT_SECTION_FLAG_HAS_VARIABLE_FIELDS, { -1 }, .element_name = "tag", .unique_name = "format_tags" },
+ [SECTION_ID_FRAMES] = { SECTION_ID_FRAMES, "frames", AV_TEXTFORMAT_SECTION_FLAG_IS_ARRAY, { SECTION_ID_FRAME, SECTION_ID_SUBTITLE, -1 } },
[SECTION_ID_FRAME] = { SECTION_ID_FRAME, "frame", 0, { SECTION_ID_FRAME_TAGS, SECTION_ID_FRAME_SIDE_DATA_LIST, SECTION_ID_FRAME_LOGS, -1 } },
- [SECTION_ID_FRAME_TAGS] = { SECTION_ID_FRAME_TAGS, "tags", SECTION_FLAG_HAS_VARIABLE_FIELDS, { -1 }, .element_name = "tag", .unique_name = "frame_tags" },
- [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" },
- [SECTION_ID_FRAME_SIDE_DATA] = { SECTION_ID_FRAME_SIDE_DATA, "side_data", SECTION_FLAG_HAS_VARIABLE_FIELDS|SECTION_FLAG_HAS_TYPE, { SECTION_ID_FRAME_SIDE_DATA_TIMECODE_LIST, SECTION_ID_FRAME_SIDE_DATA_COMPONENT_LIST, -1 }, .unique_name = "frame_side_data", .element_name = "side_datum", .get_type = get_frame_side_data_type },
- [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 } },
+ [SECTION_ID_FRAME_TAGS] = { SECTION_ID_FRAME_TAGS, "tags", AV_TEXTFORMAT_SECTION_FLAG_HAS_VARIABLE_FIELDS, { -1 }, .element_name = "tag", .unique_name = "frame_tags" },
+ [SECTION_ID_FRAME_SIDE_DATA_LIST] ={ SECTION_ID_FRAME_SIDE_DATA_LIST, "side_data_list", AV_TEXTFORMAT_SECTION_FLAG_IS_ARRAY, { SECTION_ID_FRAME_SIDE_DATA, -1 }, .element_name = "side_data", .unique_name = "frame_side_data_list" },
+ [SECTION_ID_FRAME_SIDE_DATA] = { SECTION_ID_FRAME_SIDE_DATA, "side_data", AV_TEXTFORMAT_SECTION_FLAG_HAS_VARIABLE_FIELDS|AV_TEXTFORMAT_SECTION_FLAG_HAS_TYPE, { SECTION_ID_FRAME_SIDE_DATA_TIMECODE_LIST, SECTION_ID_FRAME_SIDE_DATA_COMPONENT_LIST, -1 }, .unique_name = "frame_side_data", .element_name = "side_datum", .get_type = get_frame_side_data_type },
+ [SECTION_ID_FRAME_SIDE_DATA_TIMECODE_LIST] = { SECTION_ID_FRAME_SIDE_DATA_TIMECODE_LIST, "timecodes", AV_TEXTFORMAT_SECTION_FLAG_IS_ARRAY, { SECTION_ID_FRAME_SIDE_DATA_TIMECODE, -1 } },
[SECTION_ID_FRAME_SIDE_DATA_TIMECODE] = { SECTION_ID_FRAME_SIDE_DATA_TIMECODE, "timecode", 0, { -1 } },
- [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 }, .element_name = "component", .unique_name = "frame_side_data_components" },
- [SECTION_ID_FRAME_SIDE_DATA_COMPONENT] = { SECTION_ID_FRAME_SIDE_DATA_COMPONENT, "component", SECTION_FLAG_HAS_VARIABLE_FIELDS|SECTION_FLAG_HAS_TYPE, { SECTION_ID_FRAME_SIDE_DATA_PIECE_LIST, -1 }, .unique_name = "frame_side_data_component", .element_name = "component_entry", .get_type = get_raw_string_type },
- [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 }, .element_name = "piece", .unique_name = "frame_side_data_pieces" },
- [SECTION_ID_FRAME_SIDE_DATA_PIECE] = { SECTION_ID_FRAME_SIDE_DATA_PIECE, "piece", SECTION_FLAG_HAS_VARIABLE_FIELDS|SECTION_FLAG_HAS_TYPE, { -1 }, .element_name = "piece_entry", .unique_name = "frame_side_data_piece", .get_type = get_raw_string_type },
- [SECTION_ID_FRAME_LOGS] = { SECTION_ID_FRAME_LOGS, "logs", SECTION_FLAG_IS_ARRAY, { SECTION_ID_FRAME_LOG, -1 } },
+ [SECTION_ID_FRAME_SIDE_DATA_COMPONENT_LIST] = { SECTION_ID_FRAME_SIDE_DATA_COMPONENT_LIST, "components", AV_TEXTFORMAT_SECTION_FLAG_IS_ARRAY, { SECTION_ID_FRAME_SIDE_DATA_COMPONENT, -1 }, .element_name = "component", .unique_name = "frame_side_data_components" },
+ [SECTION_ID_FRAME_SIDE_DATA_COMPONENT] = { SECTION_ID_FRAME_SIDE_DATA_COMPONENT, "component", AV_TEXTFORMAT_SECTION_FLAG_HAS_VARIABLE_FIELDS|AV_TEXTFORMAT_SECTION_FLAG_HAS_TYPE, { SECTION_ID_FRAME_SIDE_DATA_PIECE_LIST, -1 }, .unique_name = "frame_side_data_component", .element_name = "component_entry", .get_type = get_raw_string_type },
+ [SECTION_ID_FRAME_SIDE_DATA_PIECE_LIST] = { SECTION_ID_FRAME_SIDE_DATA_PIECE_LIST, "pieces", AV_TEXTFORMAT_SECTION_FLAG_IS_ARRAY, { SECTION_ID_FRAME_SIDE_DATA_PIECE, -1 }, .element_name = "piece", .unique_name = "frame_side_data_pieces" },
+ [SECTION_ID_FRAME_SIDE_DATA_PIECE] = { SECTION_ID_FRAME_SIDE_DATA_PIECE, "piece", AV_TEXTFORMAT_SECTION_FLAG_HAS_VARIABLE_FIELDS|AV_TEXTFORMAT_SECTION_FLAG_HAS_TYPE, { -1 }, .element_name = "piece_entry", .unique_name = "frame_side_data_piece", .get_type = get_raw_string_type },
+ [SECTION_ID_FRAME_LOGS] = { SECTION_ID_FRAME_LOGS, "logs", AV_TEXTFORMAT_SECTION_FLAG_IS_ARRAY, { SECTION_ID_FRAME_LOG, -1 } },
[SECTION_ID_FRAME_LOG] = { SECTION_ID_FRAME_LOG, "log", 0, { -1 }, },
- [SECTION_ID_LIBRARY_VERSIONS] = { SECTION_ID_LIBRARY_VERSIONS, "library_versions", SECTION_FLAG_IS_ARRAY, { SECTION_ID_LIBRARY_VERSION, -1 } },
+ [SECTION_ID_LIBRARY_VERSIONS] = { SECTION_ID_LIBRARY_VERSIONS, "library_versions", AV_TEXTFORMAT_SECTION_FLAG_IS_ARRAY, { SECTION_ID_LIBRARY_VERSION, -1 } },
[SECTION_ID_LIBRARY_VERSION] = { SECTION_ID_LIBRARY_VERSION, "library_version", 0, { -1 } },
- [SECTION_ID_PACKETS] = { SECTION_ID_PACKETS, "packets", SECTION_FLAG_IS_ARRAY, { SECTION_ID_PACKET, -1} },
- [SECTION_ID_PACKETS_AND_FRAMES] = { SECTION_ID_PACKETS_AND_FRAMES, "packets_and_frames", SECTION_FLAG_IS_ARRAY, { SECTION_ID_PACKET, -1} },
+ [SECTION_ID_PACKETS] = { SECTION_ID_PACKETS, "packets", AV_TEXTFORMAT_SECTION_FLAG_IS_ARRAY, { SECTION_ID_PACKET, -1} },
+ [SECTION_ID_PACKETS_AND_FRAMES] = { SECTION_ID_PACKETS_AND_FRAMES, "packets_and_frames", AV_TEXTFORMAT_SECTION_FLAG_IS_ARRAY | AV_TEXTFORMAT_SECTION_FLAG_NUMBERING_BY_TYPE, { SECTION_ID_PACKET, -1} },
[SECTION_ID_PACKET] = { SECTION_ID_PACKET, "packet", 0, { SECTION_ID_PACKET_TAGS, SECTION_ID_PACKET_SIDE_DATA_LIST, -1 } },
- [SECTION_ID_PACKET_TAGS] = { SECTION_ID_PACKET_TAGS, "tags", SECTION_FLAG_HAS_VARIABLE_FIELDS, { -1 }, .element_name = "tag", .unique_name = "packet_tags" },
- [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" },
- [SECTION_ID_PACKET_SIDE_DATA] = { SECTION_ID_PACKET_SIDE_DATA, "side_data", SECTION_FLAG_HAS_VARIABLE_FIELDS|SECTION_FLAG_HAS_TYPE, { -1 }, .unique_name = "packet_side_data", .element_name = "side_datum", .get_type = get_packet_side_data_type },
- [SECTION_ID_PIXEL_FORMATS] = { SECTION_ID_PIXEL_FORMATS, "pixel_formats", SECTION_FLAG_IS_ARRAY, { SECTION_ID_PIXEL_FORMAT, -1 } },
+ [SECTION_ID_PACKET_TAGS] = { SECTION_ID_PACKET_TAGS, "tags", AV_TEXTFORMAT_SECTION_FLAG_HAS_VARIABLE_FIELDS, { -1 }, .element_name = "tag", .unique_name = "packet_tags" },
+ [SECTION_ID_PACKET_SIDE_DATA_LIST] ={ SECTION_ID_PACKET_SIDE_DATA_LIST, "side_data_list", AV_TEXTFORMAT_SECTION_FLAG_IS_ARRAY, { SECTION_ID_PACKET_SIDE_DATA, -1 }, .element_name = "side_data", .unique_name = "packet_side_data_list" },
+ [SECTION_ID_PACKET_SIDE_DATA] = { SECTION_ID_PACKET_SIDE_DATA, "side_data", AV_TEXTFORMAT_SECTION_FLAG_HAS_VARIABLE_FIELDS|AV_TEXTFORMAT_SECTION_FLAG_HAS_TYPE, { -1 }, .unique_name = "packet_side_data", .element_name = "side_datum", .get_type = get_packet_side_data_type },
+ [SECTION_ID_PIXEL_FORMATS] = { SECTION_ID_PIXEL_FORMATS, "pixel_formats", AV_TEXTFORMAT_SECTION_FLAG_IS_ARRAY, { SECTION_ID_PIXEL_FORMAT, -1 } },
[SECTION_ID_PIXEL_FORMAT] = { SECTION_ID_PIXEL_FORMAT, "pixel_format", 0, { SECTION_ID_PIXEL_FORMAT_FLAGS, SECTION_ID_PIXEL_FORMAT_COMPONENTS, -1 } },
[SECTION_ID_PIXEL_FORMAT_FLAGS] = { SECTION_ID_PIXEL_FORMAT_FLAGS, "flags", 0, { -1 }, .unique_name = "pixel_format_flags" },
- [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" },
+ [SECTION_ID_PIXEL_FORMAT_COMPONENTS] = { SECTION_ID_PIXEL_FORMAT_COMPONENTS, "components", AV_TEXTFORMAT_SECTION_FLAG_IS_ARRAY, {SECTION_ID_PIXEL_FORMAT_COMPONENT, -1 }, .unique_name = "pixel_format_components" },
[SECTION_ID_PIXEL_FORMAT_COMPONENT] = { SECTION_ID_PIXEL_FORMAT_COMPONENT, "component", 0, { -1 } },
[SECTION_ID_PROGRAM_STREAM_DISPOSITION] = { SECTION_ID_PROGRAM_STREAM_DISPOSITION, "disposition", 0, { -1 }, .unique_name = "program_stream_disposition" },
- [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" },
+ [SECTION_ID_PROGRAM_STREAM_TAGS] = { SECTION_ID_PROGRAM_STREAM_TAGS, "tags", AV_TEXTFORMAT_SECTION_FLAG_HAS_VARIABLE_FIELDS, { -1 }, .element_name = "tag", .unique_name = "program_stream_tags" },
[SECTION_ID_PROGRAM] = { SECTION_ID_PROGRAM, "program", 0, { SECTION_ID_PROGRAM_TAGS, SECTION_ID_PROGRAM_STREAMS, -1 } },
- [SECTION_ID_PROGRAM_STREAMS] = { SECTION_ID_PROGRAM_STREAMS, "streams", SECTION_FLAG_IS_ARRAY, { SECTION_ID_PROGRAM_STREAM, -1 }, .unique_name = "program_streams" },
+ [SECTION_ID_PROGRAM_STREAMS] = { SECTION_ID_PROGRAM_STREAMS, "streams", AV_TEXTFORMAT_SECTION_FLAG_IS_ARRAY, { SECTION_ID_PROGRAM_STREAM, -1 }, .unique_name = "program_streams" },
[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" },
- [SECTION_ID_PROGRAM_TAGS] = { SECTION_ID_PROGRAM_TAGS, "tags", SECTION_FLAG_HAS_VARIABLE_FIELDS, { -1 }, .element_name = "tag", .unique_name = "program_tags" },
+ [SECTION_ID_PROGRAM_TAGS] = { SECTION_ID_PROGRAM_TAGS, "tags", AV_TEXTFORMAT_SECTION_FLAG_HAS_VARIABLE_FIELDS, { -1 }, .element_name = "tag", .unique_name = "program_tags" },
[SECTION_ID_PROGRAM_VERSION] = { SECTION_ID_PROGRAM_VERSION, "program_version", 0, { -1 } },
- [SECTION_ID_PROGRAMS] = { SECTION_ID_PROGRAMS, "programs", SECTION_FLAG_IS_ARRAY, { SECTION_ID_PROGRAM, -1 } },
+ [SECTION_ID_PROGRAMS] = { SECTION_ID_PROGRAMS, "programs", AV_TEXTFORMAT_SECTION_FLAG_IS_ARRAY, { SECTION_ID_PROGRAM, -1 } },
[SECTION_ID_STREAM_GROUP_STREAM_DISPOSITION] = { SECTION_ID_STREAM_GROUP_STREAM_DISPOSITION, "disposition", 0, { -1 }, .unique_name = "stream_group_stream_disposition" },
- [SECTION_ID_STREAM_GROUP_STREAM_TAGS] = { SECTION_ID_STREAM_GROUP_STREAM_TAGS, "tags", SECTION_FLAG_HAS_VARIABLE_FIELDS, { -1 }, .element_name = "tag", .unique_name = "stream_group_stream_tags" },
+ [SECTION_ID_STREAM_GROUP_STREAM_TAGS] = { SECTION_ID_STREAM_GROUP_STREAM_TAGS, "tags", AV_TEXTFORMAT_SECTION_FLAG_HAS_VARIABLE_FIELDS, { -1 }, .element_name = "tag", .unique_name = "stream_group_stream_tags" },
[SECTION_ID_STREAM_GROUP] = { SECTION_ID_STREAM_GROUP, "stream_group", 0, { SECTION_ID_STREAM_GROUP_TAGS, SECTION_ID_STREAM_GROUP_DISPOSITION, SECTION_ID_STREAM_GROUP_COMPONENTS, SECTION_ID_STREAM_GROUP_STREAMS, -1 } },
- [SECTION_ID_STREAM_GROUP_COMPONENTS] = { SECTION_ID_STREAM_GROUP_COMPONENTS, "components", SECTION_FLAG_IS_ARRAY, { SECTION_ID_STREAM_GROUP_COMPONENT, -1 }, .element_name = "component", .unique_name = "stream_group_components" },
- [SECTION_ID_STREAM_GROUP_COMPONENT] = { SECTION_ID_STREAM_GROUP_COMPONENT, "component", SECTION_FLAG_HAS_VARIABLE_FIELDS|SECTION_FLAG_HAS_TYPE, { SECTION_ID_STREAM_GROUP_SUBCOMPONENTS, -1 }, .unique_name = "stream_group_component", .element_name = "component_entry", .get_type = get_stream_group_type },
- [SECTION_ID_STREAM_GROUP_SUBCOMPONENTS] = { SECTION_ID_STREAM_GROUP_SUBCOMPONENTS, "subcomponents", SECTION_FLAG_IS_ARRAY, { SECTION_ID_STREAM_GROUP_SUBCOMPONENT, -1 }, .element_name = "component" },
- [SECTION_ID_STREAM_GROUP_SUBCOMPONENT] = { SECTION_ID_STREAM_GROUP_SUBCOMPONENT, "subcomponent", SECTION_FLAG_HAS_VARIABLE_FIELDS|SECTION_FLAG_HAS_TYPE, { SECTION_ID_STREAM_GROUP_PIECES, -1 }, .element_name = "subcomponent_entry", .get_type = get_raw_string_type },
- [SECTION_ID_STREAM_GROUP_PIECES] = { SECTION_ID_STREAM_GROUP_PIECES, "pieces", SECTION_FLAG_IS_ARRAY, { SECTION_ID_STREAM_GROUP_PIECE, -1 }, .element_name = "piece", .unique_name = "stream_group_pieces" },
- [SECTION_ID_STREAM_GROUP_PIECE] = { SECTION_ID_STREAM_GROUP_PIECE, "piece", SECTION_FLAG_HAS_VARIABLE_FIELDS|SECTION_FLAG_HAS_TYPE, { SECTION_ID_STREAM_GROUP_SUBPIECES, -1 }, .unique_name = "stream_group_piece", .element_name = "piece_entry", .get_type = get_raw_string_type },
- [SECTION_ID_STREAM_GROUP_SUBPIECES] = { SECTION_ID_STREAM_GROUP_SUBPIECES, "subpieces", SECTION_FLAG_IS_ARRAY, { SECTION_ID_STREAM_GROUP_SUBPIECE, -1 }, .element_name = "subpiece" },
- [SECTION_ID_STREAM_GROUP_SUBPIECE] = { SECTION_ID_STREAM_GROUP_SUBPIECE, "subpiece", SECTION_FLAG_HAS_VARIABLE_FIELDS|SECTION_FLAG_HAS_TYPE, { SECTION_ID_STREAM_GROUP_BLOCKS, -1 }, .element_name = "subpiece_entry", .get_type = get_raw_string_type },
- [SECTION_ID_STREAM_GROUP_BLOCKS] = { SECTION_ID_STREAM_GROUP_BLOCKS, "blocks", SECTION_FLAG_IS_ARRAY, { SECTION_ID_STREAM_GROUP_BLOCK, -1 }, .element_name = "block" },
- [SECTION_ID_STREAM_GROUP_BLOCK] = { SECTION_ID_STREAM_GROUP_BLOCK, "block", SECTION_FLAG_HAS_VARIABLE_FIELDS|SECTION_FLAG_HAS_TYPE, { -1 }, .element_name = "block_entry", .get_type = get_raw_string_type },
- [SECTION_ID_STREAM_GROUP_STREAMS] = { SECTION_ID_STREAM_GROUP_STREAMS, "streams", SECTION_FLAG_IS_ARRAY, { SECTION_ID_STREAM_GROUP_STREAM, -1 }, .unique_name = "stream_group_streams" },
+ [SECTION_ID_STREAM_GROUP_COMPONENTS] = { SECTION_ID_STREAM_GROUP_COMPONENTS, "components", AV_TEXTFORMAT_SECTION_FLAG_IS_ARRAY, { SECTION_ID_STREAM_GROUP_COMPONENT, -1 }, .element_name = "component", .unique_name = "stream_group_components" },
+ [SECTION_ID_STREAM_GROUP_COMPONENT] = { SECTION_ID_STREAM_GROUP_COMPONENT, "component", AV_TEXTFORMAT_SECTION_FLAG_HAS_VARIABLE_FIELDS|AV_TEXTFORMAT_SECTION_FLAG_HAS_TYPE, { SECTION_ID_STREAM_GROUP_SUBCOMPONENTS, -1 }, .unique_name = "stream_group_component", .element_name = "component_entry", .get_type = get_stream_group_type },
+ [SECTION_ID_STREAM_GROUP_SUBCOMPONENTS] = { SECTION_ID_STREAM_GROUP_SUBCOMPONENTS, "subcomponents", AV_TEXTFORMAT_SECTION_FLAG_IS_ARRAY, { SECTION_ID_STREAM_GROUP_SUBCOMPONENT, -1 }, .element_name = "component" },
+ [SECTION_ID_STREAM_GROUP_SUBCOMPONENT] = { SECTION_ID_STREAM_GROUP_SUBCOMPONENT, "subcomponent", AV_TEXTFORMAT_SECTION_FLAG_HAS_VARIABLE_FIELDS|AV_TEXTFORMAT_SECTION_FLAG_HAS_TYPE, { SECTION_ID_STREAM_GROUP_PIECES, -1 }, .element_name = "subcomponent_entry", .get_type = get_raw_string_type },
+ [SECTION_ID_STREAM_GROUP_PIECES] = { SECTION_ID_STREAM_GROUP_PIECES, "pieces", AV_TEXTFORMAT_SECTION_FLAG_IS_ARRAY, { SECTION_ID_STREAM_GROUP_PIECE, -1 }, .element_name = "piece", .unique_name = "stream_group_pieces" },
+ [SECTION_ID_STREAM_GROUP_PIECE] = { SECTION_ID_STREAM_GROUP_PIECE, "piece", AV_TEXTFORMAT_SECTION_FLAG_HAS_VARIABLE_FIELDS|AV_TEXTFORMAT_SECTION_FLAG_HAS_TYPE, { SECTION_ID_STREAM_GROUP_SUBPIECES, -1 }, .unique_name = "stream_group_piece", .element_name = "piece_entry", .get_type = get_raw_string_type },
+ [SECTION_ID_STREAM_GROUP_SUBPIECES] = { SECTION_ID_STREAM_GROUP_SUBPIECES, "subpieces", AV_TEXTFORMAT_SECTION_FLAG_IS_ARRAY, { SECTION_ID_STREAM_GROUP_SUBPIECE, -1 }, .element_name = "subpiece" },
+ [SECTION_ID_STREAM_GROUP_SUBPIECE] = { SECTION_ID_STREAM_GROUP_SUBPIECE, "subpiece", AV_TEXTFORMAT_SECTION_FLAG_HAS_VARIABLE_FIELDS|AV_TEXTFORMAT_SECTION_FLAG_HAS_TYPE, { SECTION_ID_STREAM_GROUP_BLOCKS, -1 }, .element_name = "subpiece_entry", .get_type = get_raw_string_type },
+ [SECTION_ID_STREAM_GROUP_BLOCKS] = { SECTION_ID_STREAM_GROUP_BLOCKS, "blocks", AV_TEXTFORMAT_SECTION_FLAG_IS_ARRAY, { SECTION_ID_STREAM_GROUP_BLOCK, -1 }, .element_name = "block" },
+ [SECTION_ID_STREAM_GROUP_BLOCK] = { SECTION_ID_STREAM_GROUP_BLOCK, "block", AV_TEXTFORMAT_SECTION_FLAG_HAS_VARIABLE_FIELDS|AV_TEXTFORMAT_SECTION_FLAG_HAS_TYPE, { -1 }, .element_name = "block_entry", .get_type = get_raw_string_type },
+ [SECTION_ID_STREAM_GROUP_STREAMS] = { SECTION_ID_STREAM_GROUP_STREAMS, "streams", AV_TEXTFORMAT_SECTION_FLAG_IS_ARRAY, { SECTION_ID_STREAM_GROUP_STREAM, -1 }, .unique_name = "stream_group_streams" },
[SECTION_ID_STREAM_GROUP_STREAM] = { SECTION_ID_STREAM_GROUP_STREAM, "stream", 0, { SECTION_ID_STREAM_GROUP_STREAM_DISPOSITION, SECTION_ID_STREAM_GROUP_STREAM_TAGS, -1 }, .unique_name = "stream_group_stream" },
[SECTION_ID_STREAM_GROUP_DISPOSITION] = { SECTION_ID_STREAM_GROUP_DISPOSITION, "disposition", 0, { -1 }, .unique_name = "stream_group_disposition" },
- [SECTION_ID_STREAM_GROUP_TAGS] = { SECTION_ID_STREAM_GROUP_TAGS, "tags", SECTION_FLAG_HAS_VARIABLE_FIELDS, { -1 }, .element_name = "tag", .unique_name = "stream_group_tags" },
- [SECTION_ID_STREAM_GROUPS] = { SECTION_ID_STREAM_GROUPS, "stream_groups", SECTION_FLAG_IS_ARRAY, { SECTION_ID_STREAM_GROUP, -1 } },
- [SECTION_ID_ROOT] = { SECTION_ID_ROOT, "root", SECTION_FLAG_IS_WRAPPER,
+ [SECTION_ID_STREAM_GROUP_TAGS] = { SECTION_ID_STREAM_GROUP_TAGS, "tags", AV_TEXTFORMAT_SECTION_FLAG_HAS_VARIABLE_FIELDS, { -1 }, .element_name = "tag", .unique_name = "stream_group_tags" },
+ [SECTION_ID_STREAM_GROUPS] = { SECTION_ID_STREAM_GROUPS, "stream_groups", AV_TEXTFORMAT_SECTION_FLAG_IS_ARRAY, { SECTION_ID_STREAM_GROUP, -1 } },
+ [SECTION_ID_ROOT] = { SECTION_ID_ROOT, "root", AV_TEXTFORMAT_SECTION_FLAG_IS_WRAPPER,
{ SECTION_ID_CHAPTERS, SECTION_ID_FORMAT, SECTION_ID_FRAMES, SECTION_ID_PROGRAMS, SECTION_ID_STREAM_GROUPS, SECTION_ID_STREAMS,
SECTION_ID_PACKETS, SECTION_ID_ERROR, SECTION_ID_PROGRAM_VERSION, SECTION_ID_LIBRARY_VERSIONS,
SECTION_ID_PIXEL_FORMATS, -1} },
- [SECTION_ID_STREAMS] = { SECTION_ID_STREAMS, "streams", SECTION_FLAG_IS_ARRAY, { SECTION_ID_STREAM, -1 } },
+ [SECTION_ID_STREAMS] = { SECTION_ID_STREAMS, "streams", AV_TEXTFORMAT_SECTION_FLAG_IS_ARRAY, { SECTION_ID_STREAM, -1 } },
[SECTION_ID_STREAM] = { SECTION_ID_STREAM, "stream", 0, { SECTION_ID_STREAM_DISPOSITION, SECTION_ID_STREAM_TAGS, SECTION_ID_STREAM_SIDE_DATA_LIST, -1 } },
[SECTION_ID_STREAM_DISPOSITION] = { SECTION_ID_STREAM_DISPOSITION, "disposition", 0, { -1 }, .unique_name = "stream_disposition" },
- [SECTION_ID_STREAM_TAGS] = { SECTION_ID_STREAM_TAGS, "tags", SECTION_FLAG_HAS_VARIABLE_FIELDS, { -1 }, .element_name = "tag", .unique_name = "stream_tags" },
- [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" },
- [SECTION_ID_STREAM_SIDE_DATA] = { SECTION_ID_STREAM_SIDE_DATA, "side_data", SECTION_FLAG_HAS_TYPE|SECTION_FLAG_HAS_VARIABLE_FIELDS, { -1 }, .unique_name = "stream_side_data", .element_name = "side_datum", .get_type = get_packet_side_data_type },
+ [SECTION_ID_STREAM_TAGS] = { SECTION_ID_STREAM_TAGS, "tags", AV_TEXTFORMAT_SECTION_FLAG_HAS_VARIABLE_FIELDS, { -1 }, .element_name = "tag", .unique_name = "stream_tags" },
+ [SECTION_ID_STREAM_SIDE_DATA_LIST] ={ SECTION_ID_STREAM_SIDE_DATA_LIST, "side_data_list", AV_TEXTFORMAT_SECTION_FLAG_IS_ARRAY, { SECTION_ID_STREAM_SIDE_DATA, -1 }, .element_name = "side_data", .unique_name = "stream_side_data_list" },
+ [SECTION_ID_STREAM_SIDE_DATA] = { SECTION_ID_STREAM_SIDE_DATA, "side_data", AV_TEXTFORMAT_SECTION_FLAG_HAS_TYPE|AV_TEXTFORMAT_SECTION_FLAG_HAS_VARIABLE_FIELDS, { -1 }, .unique_name = "stream_side_data", .element_name = "side_datum", .get_type = get_packet_side_data_type },
[SECTION_ID_SUBTITLE] = { SECTION_ID_SUBTITLE, "subtitle", 0, { -1 } },
};
@@ -350,22 +333,6 @@ static const char *print_input_filename;
static const AVInputFormat *iformat = NULL;
static const char *output_filename = NULL;
-static struct AVHashContext *hash;
-
-static const struct {
- double bin_val;
- double dec_val;
- const char *bin_str;
- const char *dec_str;
-} si_prefixes[] = {
- { 1.0, 1.0, "", "" },
- { 1.024e3, 1e3, "Ki", "K" },
- { 1.048576e6, 1e6, "Mi", "M" },
- { 1.073741824e9, 1e9, "Gi", "G" },
- { 1.099511627776e12, 1e12, "Ti", "T" },
- { 1.125899906842624e15, 1e15, "Pi", "P" },
-};
-
static const char unit_second_str[] = "s" ;
static const char unit_hertz_str[] = "Hz" ;
static const char unit_byte_str[] = "byte" ;
@@ -441,1554 +408,11 @@ static void log_callback(void *ptr, int level, const char *fmt, va_list vl)
#endif
}
-struct unit_value {
- union { double d; int64_t i; } val;
- const char *unit;
-};
-
-static char *value_string(char *buf, int buf_size, struct unit_value uv)
-{
- double vald;
- int64_t vali;
- int show_float = 0;
-
- if (uv.unit == unit_second_str) {
- vald = uv.val.d;
- show_float = 1;
- } else {
- vald = vali = uv.val.i;
- }
-
- if (uv.unit == unit_second_str && use_value_sexagesimal_format) {
- double secs;
- int hours, mins;
- secs = vald;
- mins = (int)secs / 60;
- secs = secs - mins * 60;
- hours = mins / 60;
- mins %= 60;
- snprintf(buf, buf_size, "%d:%02d:%09.6f", hours, mins, secs);
- } else {
- const char *prefix_string = "";
-
- if (use_value_prefix && vald > 1) {
- int64_t index;
-
- if (uv.unit == unit_byte_str && use_byte_value_binary_prefix) {
- index = (int64_t) (log2(vald)) / 10;
- index = av_clip(index, 0, FF_ARRAY_ELEMS(si_prefixes) - 1);
- vald /= si_prefixes[index].bin_val;
- prefix_string = si_prefixes[index].bin_str;
- } else {
- index = (int64_t) (log10(vald)) / 3;
- index = av_clip(index, 0, FF_ARRAY_ELEMS(si_prefixes) - 1);
- vald /= si_prefixes[index].dec_val;
- prefix_string = si_prefixes[index].dec_str;
- }
- vali = vald;
- }
-
- if (show_float || (use_value_prefix && vald != (int64_t)vald))
- snprintf(buf, buf_size, "%f", vald);
- else
- snprintf(buf, buf_size, "%"PRId64, vali);
- av_strlcatf(buf, buf_size, "%s%s%s", *prefix_string || show_value_unit ? " " : "",
- prefix_string, show_value_unit ? uv.unit : "");
- }
-
- return buf;
-}
-
-/* WRITERS API */
-
-typedef struct WriterContext WriterContext;
-
-#define WRITER_FLAG_DISPLAY_OPTIONAL_FIELDS 1
-#define WRITER_FLAG_PUT_PACKETS_AND_FRAMES_IN_SAME_CHAPTER 2
-
-typedef enum {
- WRITER_STRING_VALIDATION_FAIL,
- WRITER_STRING_VALIDATION_REPLACE,
- WRITER_STRING_VALIDATION_IGNORE,
- WRITER_STRING_VALIDATION_NB
-} StringValidation;
-
-typedef struct Writer {
- const AVClass *priv_class; ///< private class of the writer, if any
- int priv_size; ///< private size for the writer context
- const char *name;
-
- int (*init) (WriterContext *wctx);
- void (*uninit)(WriterContext *wctx);
-
- void (*print_section_header)(WriterContext *wctx, const void *data);
- void (*print_section_footer)(WriterContext *wctx);
- void (*print_integer) (WriterContext *wctx, const char *, int64_t);
- void (*print_rational) (WriterContext *wctx, AVRational *q, char *sep);
- void (*print_string) (WriterContext *wctx, const char *, const char *);
- int flags; ///< a combination or WRITER_FLAG_*
-} Writer;
-
-#define SECTION_MAX_NB_LEVELS 12
-
-struct WriterContext {
- const AVClass *class; ///< class of the writer
- const Writer *writer; ///< the Writer of which this is an instance
- AVIOContext *avio; ///< the I/O context used to write
-
- void (* writer_w8)(WriterContext *wctx, int b);
- void (* writer_put_str)(WriterContext *wctx, const char *str);
- void (* writer_printf)(WriterContext *wctx, const char *fmt, ...);
-
- char *name; ///< name of this writer instance
- void *priv; ///< private data for use by the filter
-
- const struct section *sections; ///< array containing all sections
- int nb_sections; ///< number of sections
-
- int level; ///< current level, starting from 0
-
- /** number of the item printed in the given section, starting from 0 */
- unsigned int nb_item[SECTION_MAX_NB_LEVELS];
-
- /** section per each level */
- const struct section *section[SECTION_MAX_NB_LEVELS];
- AVBPrint section_pbuf[SECTION_MAX_NB_LEVELS]; ///< generic print buffer dedicated to each section,
- /// used by various writers
-
- unsigned int nb_section_packet; ///< number of the packet section in case we are in "packets_and_frames" section
- unsigned int nb_section_frame; ///< number of the frame section in case we are in "packets_and_frames" section
- unsigned int nb_section_packet_frame; ///< nb_section_packet or nb_section_frame according if is_packets_and_frames
-
- int string_validation;
- char *string_validation_replacement;
- unsigned int string_validation_utf8_flags;
-};
-
-static const char *writer_get_name(void *p)
-{
- WriterContext *wctx = p;
- return wctx->writer->name;
-}
-
-#define OFFSET(x) offsetof(WriterContext, x)
-
-static const AVOption writer_options[] = {
- { "string_validation", "set string validation mode",
- OFFSET(string_validation), AV_OPT_TYPE_INT, {.i64=WRITER_STRING_VALIDATION_REPLACE}, 0, WRITER_STRING_VALIDATION_NB-1, .unit = "sv" },
- { "sv", "set string validation mode",
- OFFSET(string_validation), AV_OPT_TYPE_INT, {.i64=WRITER_STRING_VALIDATION_REPLACE}, 0, WRITER_STRING_VALIDATION_NB-1, .unit = "sv" },
- { "ignore", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = WRITER_STRING_VALIDATION_IGNORE}, .unit = "sv" },
- { "replace", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = WRITER_STRING_VALIDATION_REPLACE}, .unit = "sv" },
- { "fail", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = WRITER_STRING_VALIDATION_FAIL}, .unit = "sv" },
- { "string_validation_replacement", "set string validation replacement string", OFFSET(string_validation_replacement), AV_OPT_TYPE_STRING, {.str=""}},
- { "svr", "set string validation replacement string", OFFSET(string_validation_replacement), AV_OPT_TYPE_STRING, {.str="\xEF\xBF\xBD"}},
- { NULL }
-};
-
-static void *writer_child_next(void *obj, void *prev)
-{
- WriterContext *ctx = obj;
- if (!prev && ctx->writer && ctx->writer->priv_class && ctx->priv)
- return ctx->priv;
- return NULL;
-}
-
-static const AVClass writer_class = {
- .class_name = "Writer",
- .item_name = writer_get_name,
- .option = writer_options,
- .version = LIBAVUTIL_VERSION_INT,
- .child_next = writer_child_next,
-};
-
-static int writer_close(WriterContext **wctx)
-{
- int i;
- int ret = 0;
-
- if (!*wctx)
- return -1;
-
- if ((*wctx)->writer->uninit)
- (*wctx)->writer->uninit(*wctx);
- for (i = 0; i < SECTION_MAX_NB_LEVELS; i++)
- av_bprint_finalize(&(*wctx)->section_pbuf[i], NULL);
- if ((*wctx)->writer->priv_class)
- av_opt_free((*wctx)->priv);
- av_freep(&((*wctx)->priv));
- av_opt_free(*wctx);
- if ((*wctx)->avio) {
- avio_flush((*wctx)->avio);
- ret = avio_close((*wctx)->avio);
- }
- av_freep(wctx);
- return ret;
-}
-
-static void bprint_bytes(AVBPrint *bp, const uint8_t *ubuf, size_t ubuf_size)
-{
- int i;
- av_bprintf(bp, "0X");
- for (i = 0; i < ubuf_size; i++)
- av_bprintf(bp, "%02X", ubuf[i]);
-}
-
-static inline void writer_w8_avio(WriterContext *wctx, int b)
-{
- avio_w8(wctx->avio, b);
-}
-
-static inline void writer_put_str_avio(WriterContext *wctx, const char *str)
-{
- avio_write(wctx->avio, str, strlen(str));
-}
-
-static inline void writer_printf_avio(WriterContext *wctx, const char *fmt, ...)
-{
- va_list ap;
-
- va_start(ap, fmt);
- avio_vprintf(wctx->avio, fmt, ap);
- va_end(ap);
-}
-
-static inline void writer_w8_printf(WriterContext *wctx, int b)
-{
- printf("%c", b);
-}
-
-static inline void writer_put_str_printf(WriterContext *wctx, const char *str)
-{
- printf("%s", str);
-}
-
-static inline void writer_printf_printf(WriterContext *wctx, const char *fmt, ...)
-{
- va_list ap;
-
- va_start(ap, fmt);
- vprintf(fmt, ap);
- va_end(ap);
-}
-
-static int writer_open(WriterContext **wctx, const Writer *writer, const char *args,
- const struct section *sections, int nb_sections, const char *output)
-{
- int i, ret = 0;
-
- if (!(*wctx = av_mallocz(sizeof(WriterContext)))) {
- ret = AVERROR(ENOMEM);
- goto fail;
- }
-
- if (!((*wctx)->priv = av_mallocz(writer->priv_size))) {
- ret = AVERROR(ENOMEM);
- goto fail;
- }
-
- (*wctx)->class = &writer_class;
- (*wctx)->writer = writer;
- (*wctx)->level = -1;
- (*wctx)->sections = sections;
- (*wctx)->nb_sections = nb_sections;
-
- av_opt_set_defaults(*wctx);
-
- if (writer->priv_class) {
- void *priv_ctx = (*wctx)->priv;
- *((const AVClass **)priv_ctx) = writer->priv_class;
- av_opt_set_defaults(priv_ctx);
- }
-
- /* convert options to dictionary */
- if (args) {
- AVDictionary *opts = NULL;
- const AVDictionaryEntry *opt = NULL;
-
- if ((ret = av_dict_parse_string(&opts, args, "=", ":", 0)) < 0) {
- av_log(*wctx, AV_LOG_ERROR, "Failed to parse option string '%s' provided to writer context\n", args);
- av_dict_free(&opts);
- goto fail;
- }
-
- while ((opt = av_dict_iterate(opts, opt))) {
- if ((ret = av_opt_set(*wctx, opt->key, opt->value, AV_OPT_SEARCH_CHILDREN)) < 0) {
- av_log(*wctx, AV_LOG_ERROR, "Failed to set option '%s' with value '%s' provided to writer context\n",
- opt->key, opt->value);
- av_dict_free(&opts);
- goto fail;
- }
- }
-
- av_dict_free(&opts);
- }
-
- /* validate replace string */
- {
- const uint8_t *p = (*wctx)->string_validation_replacement;
- const uint8_t *endp = p + strlen(p);
- while (*p) {
- const uint8_t *p0 = p;
- int32_t code;
- ret = av_utf8_decode(&code, &p, endp, (*wctx)->string_validation_utf8_flags);
- if (ret < 0) {
- AVBPrint bp;
- av_bprint_init(&bp, 0, AV_BPRINT_SIZE_AUTOMATIC);
- bprint_bytes(&bp, p0, p-p0),
- av_log(wctx, AV_LOG_ERROR,
- "Invalid UTF8 sequence %s found in string validation replace '%s'\n",
- bp.str, (*wctx)->string_validation_replacement);
- return ret;
- }
- }
- }
-
- if (!output_filename) {
- (*wctx)->writer_w8 = writer_w8_printf;
- (*wctx)->writer_put_str = writer_put_str_printf;
- (*wctx)->writer_printf = writer_printf_printf;
- } else {
- if ((ret = avio_open(&(*wctx)->avio, output, AVIO_FLAG_WRITE)) < 0) {
- av_log(*wctx, AV_LOG_ERROR,
- "Failed to open output '%s' with error: %s\n", output, av_err2str(ret));
- goto fail;
- }
- (*wctx)->writer_w8 = writer_w8_avio;
- (*wctx)->writer_put_str = writer_put_str_avio;
- (*wctx)->writer_printf = writer_printf_avio;
- }
-
- for (i = 0; i < SECTION_MAX_NB_LEVELS; i++)
- av_bprint_init(&(*wctx)->section_pbuf[i], 1, AV_BPRINT_SIZE_UNLIMITED);
-
- if ((*wctx)->writer->init)
- ret = (*wctx)->writer->init(*wctx);
- if (ret < 0)
- goto fail;
-
- return 0;
-
-fail:
- writer_close(wctx);
- return ret;
-}
-
-static inline void writer_print_section_header(WriterContext *wctx,
- const void *data,
- int section_id)
-{
- int parent_section_id;
- wctx->level++;
- av_assert0(wctx->level < SECTION_MAX_NB_LEVELS);
- parent_section_id = wctx->level ?
- (wctx->section[wctx->level-1])->id : SECTION_ID_NONE;
-
- wctx->nb_item[wctx->level] = 0;
- wctx->section[wctx->level] = &wctx->sections[section_id];
-
- if (section_id == SECTION_ID_PACKETS_AND_FRAMES) {
- wctx->nb_section_packet = wctx->nb_section_frame =
- wctx->nb_section_packet_frame = 0;
- } else if (parent_section_id == SECTION_ID_PACKETS_AND_FRAMES) {
- wctx->nb_section_packet_frame = section_id == SECTION_ID_PACKET ?
- wctx->nb_section_packet : wctx->nb_section_frame;
- }
-
- if (wctx->writer->print_section_header)
- wctx->writer->print_section_header(wctx, data);
-}
-
-static inline void writer_print_section_footer(WriterContext *wctx)
-{
- int section_id = wctx->section[wctx->level]->id;
- int parent_section_id = wctx->level ?
- wctx->section[wctx->level-1]->id : SECTION_ID_NONE;
-
- if (parent_section_id != SECTION_ID_NONE)
- wctx->nb_item[wctx->level-1]++;
- if (parent_section_id == SECTION_ID_PACKETS_AND_FRAMES) {
- if (section_id == SECTION_ID_PACKET) wctx->nb_section_packet++;
- else wctx->nb_section_frame++;
- }
- if (wctx->writer->print_section_footer)
- wctx->writer->print_section_footer(wctx);
- wctx->level--;
-}
-
-static inline void writer_print_integer(WriterContext *wctx,
- const char *key, int64_t val)
-{
- const struct section *section = wctx->section[wctx->level];
-
- if (section->show_all_entries || av_dict_get(section->entries_to_show, key, NULL, 0)) {
- wctx->writer->print_integer(wctx, key, val);
- wctx->nb_item[wctx->level]++;
- }
-}
-
-static inline int validate_string(WriterContext *wctx, char **dstp, const char *src)
-{
- const uint8_t *p, *endp;
- AVBPrint dstbuf;
- int invalid_chars_nb = 0, ret = 0;
-
- av_bprint_init(&dstbuf, 0, AV_BPRINT_SIZE_UNLIMITED);
-
- endp = src + strlen(src);
- for (p = src; *p;) {
- uint32_t code;
- int invalid = 0;
- const uint8_t *p0 = p;
-
- if (av_utf8_decode(&code, &p, endp, wctx->string_validation_utf8_flags) < 0) {
- AVBPrint bp;
- av_bprint_init(&bp, 0, AV_BPRINT_SIZE_AUTOMATIC);
- bprint_bytes(&bp, p0, p-p0);
- av_log(wctx, AV_LOG_DEBUG,
- "Invalid UTF-8 sequence %s found in string '%s'\n", bp.str, src);
- invalid = 1;
- }
-
- if (invalid) {
- invalid_chars_nb++;
-
- switch (wctx->string_validation) {
- case WRITER_STRING_VALIDATION_FAIL:
- av_log(wctx, AV_LOG_ERROR,
- "Invalid UTF-8 sequence found in string '%s'\n", src);
- ret = AVERROR_INVALIDDATA;
- goto end;
- break;
-
- case WRITER_STRING_VALIDATION_REPLACE:
- av_bprintf(&dstbuf, "%s", wctx->string_validation_replacement);
- break;
- }
- }
-
- if (!invalid || wctx->string_validation == WRITER_STRING_VALIDATION_IGNORE)
- av_bprint_append_data(&dstbuf, p0, p-p0);
- }
-
- if (invalid_chars_nb && wctx->string_validation == WRITER_STRING_VALIDATION_REPLACE) {
- av_log(wctx, AV_LOG_WARNING,
- "%d invalid UTF-8 sequence(s) found in string '%s', replaced with '%s'\n",
- invalid_chars_nb, src, wctx->string_validation_replacement);
- }
-
-end:
- av_bprint_finalize(&dstbuf, dstp);
- return ret;
-}
-
-#define PRINT_STRING_OPT 1
-#define PRINT_STRING_VALIDATE 2
-
-static inline int writer_print_string(WriterContext *wctx,
- const char *key, const char *val, int flags)
-{
- const struct section *section = wctx->section[wctx->level];
- int ret = 0;
-
- if (show_optional_fields == SHOW_OPTIONAL_FIELDS_NEVER ||
- (show_optional_fields == SHOW_OPTIONAL_FIELDS_AUTO
- && (flags & PRINT_STRING_OPT)
- && !(wctx->writer->flags & WRITER_FLAG_DISPLAY_OPTIONAL_FIELDS)))
- return 0;
-
- if (section->show_all_entries || av_dict_get(section->entries_to_show, key, NULL, 0)) {
- if (flags & PRINT_STRING_VALIDATE) {
- char *key1 = NULL, *val1 = NULL;
- ret = validate_string(wctx, &key1, key);
- if (ret < 0) goto end;
- ret = validate_string(wctx, &val1, val);
- if (ret < 0) goto end;
- wctx->writer->print_string(wctx, key1, val1);
- end:
- if (ret < 0) {
- av_log(wctx, AV_LOG_ERROR,
- "Invalid key=value string combination %s=%s in section %s\n",
- key, val, section->unique_name);
- }
- av_free(key1);
- av_free(val1);
- } else {
- wctx->writer->print_string(wctx, key, val);
- }
-
- wctx->nb_item[wctx->level]++;
- }
-
- return ret;
-}
-
-static inline void writer_print_rational(WriterContext *wctx,
- const char *key, AVRational q, char sep)
-{
- AVBPrint buf;
- av_bprint_init(&buf, 0, AV_BPRINT_SIZE_AUTOMATIC);
- av_bprintf(&buf, "%d%c%d", q.num, sep, q.den);
- writer_print_string(wctx, key, buf.str, 0);
-}
-
-static void writer_print_time(WriterContext *wctx, const char *key,
- int64_t ts, const AVRational *time_base, int is_duration)
-{
- char buf[128];
-
- if ((!is_duration && ts == AV_NOPTS_VALUE) || (is_duration && ts == 0)) {
- writer_print_string(wctx, key, "N/A", PRINT_STRING_OPT);
- } else {
- double d = ts * av_q2d(*time_base);
- struct unit_value uv;
- uv.val.d = d;
- uv.unit = unit_second_str;
- value_string(buf, sizeof(buf), uv);
- writer_print_string(wctx, key, buf, 0);
- }
-}
-
-static void writer_print_ts(WriterContext *wctx, const char *key, int64_t ts, int is_duration)
-{
- if ((!is_duration && ts == AV_NOPTS_VALUE) || (is_duration && ts == 0)) {
- writer_print_string(wctx, key, "N/A", PRINT_STRING_OPT);
- } else {
- writer_print_integer(wctx, key, ts);
- }
-}
-
-static void writer_print_data(WriterContext *wctx, const char *name,
- const uint8_t *data, int size)
-{
- AVBPrint bp;
- int offset = 0, l, i;
-
- av_bprint_init(&bp, 0, AV_BPRINT_SIZE_UNLIMITED);
- av_bprintf(&bp, "\n");
- while (size) {
- av_bprintf(&bp, "%08x: ", offset);
- l = FFMIN(size, 16);
- for (i = 0; i < l; i++) {
- av_bprintf(&bp, "%02x", data[i]);
- if (i & 1)
- av_bprintf(&bp, " ");
- }
- av_bprint_chars(&bp, ' ', 41 - 2 * i - i / 2);
- for (i = 0; i < l; i++)
- av_bprint_chars(&bp, data[i] - 32U < 95 ? data[i] : '.', 1);
- av_bprintf(&bp, "\n");
- offset += l;
- data += l;
- size -= l;
- }
- writer_print_string(wctx, name, bp.str, 0);
- av_bprint_finalize(&bp, NULL);
-}
-
-static void writer_print_data_hash(WriterContext *wctx, const char *name,
- const uint8_t *data, int size)
-{
- char *p, buf[AV_HASH_MAX_SIZE * 2 + 64] = { 0 };
-
- if (!hash)
- return;
- av_hash_init(hash);
- av_hash_update(hash, data, size);
- snprintf(buf, sizeof(buf), "%s:", av_hash_get_name(hash));
- p = buf + strlen(buf);
- av_hash_final_hex(hash, p, buf + sizeof(buf) - p);
- writer_print_string(wctx, name, buf, 0);
-}
-
-static void writer_print_integers(WriterContext *wctx, const char *name,
- uint8_t *data, int size, const char *format,
- int columns, int bytes, int offset_add)
-{
- AVBPrint bp;
- int offset = 0, l, i;
-
- av_bprint_init(&bp, 0, AV_BPRINT_SIZE_UNLIMITED);
- av_bprintf(&bp, "\n");
- while (size) {
- av_bprintf(&bp, "%08x: ", offset);
- l = FFMIN(size, columns);
- for (i = 0; i < l; i++) {
- if (bytes == 1) av_bprintf(&bp, format, *data);
- else if (bytes == 2) av_bprintf(&bp, format, AV_RN16(data));
- else if (bytes == 4) av_bprintf(&bp, format, AV_RN32(data));
- data += bytes;
- size --;
- }
- av_bprintf(&bp, "\n");
- offset += offset_add;
- }
- writer_print_string(wctx, name, bp.str, 0);
- av_bprint_finalize(&bp, NULL);
-}
-
-#define writer_w8(wctx_, b_) (wctx_)->writer_w8(wctx_, b_)
-#define writer_put_str(wctx_, str_) (wctx_)->writer_put_str(wctx_, str_)
-#define writer_printf(wctx_, fmt_, ...) (wctx_)->writer_printf(wctx_, fmt_, __VA_ARGS__)
-
-#define MAX_REGISTERED_WRITERS_NB 64
-
-static const Writer *registered_writers[MAX_REGISTERED_WRITERS_NB + 1];
-
-static int writer_register(const Writer *writer)
-{
- static int next_registered_writer_idx = 0;
-
- if (next_registered_writer_idx == MAX_REGISTERED_WRITERS_NB)
- return AVERROR(ENOMEM);
-
- registered_writers[next_registered_writer_idx++] = writer;
- return 0;
-}
-
-static const Writer *writer_get_by_name(const char *name)
-{
- int i;
-
- for (i = 0; registered_writers[i]; i++)
- if (!strcmp(registered_writers[i]->name, name))
- return registered_writers[i];
-
- return NULL;
-}
-
-
-/* WRITERS */
-
-#define DEFINE_WRITER_CLASS(name) \
-static const char *name##_get_name(void *ctx) \
-{ \
- return #name ; \
-} \
-static const AVClass name##_class = { \
- .class_name = #name, \
- .item_name = name##_get_name, \
- .option = name##_options \
-}
-
-/* Default output */
-
-typedef struct DefaultContext {
- const AVClass *class;
- int nokey;
- int noprint_wrappers;
- int nested_section[SECTION_MAX_NB_LEVELS];
-} DefaultContext;
-
-#undef OFFSET
-#define OFFSET(x) offsetof(DefaultContext, x)
-
-static const AVOption default_options[] = {
- { "noprint_wrappers", "do not print headers and footers", OFFSET(noprint_wrappers), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1 },
- { "nw", "do not print headers and footers", OFFSET(noprint_wrappers), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1 },
- { "nokey", "force no key printing", OFFSET(nokey), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1 },
- { "nk", "force no key printing", OFFSET(nokey), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1 },
- {NULL},
-};
-
-DEFINE_WRITER_CLASS(default);
-
-/* lame uppercasing routine, assumes the string is lower case ASCII */
-static inline char *upcase_string(char *dst, size_t dst_size, const char *src)
-{
- int i;
- for (i = 0; src[i] && i < dst_size-1; i++)
- dst[i] = av_toupper(src[i]);
- dst[i] = 0;
- return dst;
-}
-
-static void default_print_section_header(WriterContext *wctx, const void *data)
-{
- DefaultContext *def = wctx->priv;
- char buf[32];
- const struct section *section = wctx->section[wctx->level];
- const struct section *parent_section = wctx->level ?
- wctx->section[wctx->level-1] : NULL;
-
- av_bprint_clear(&wctx->section_pbuf[wctx->level]);
- if (parent_section &&
- !(parent_section->flags & (SECTION_FLAG_IS_WRAPPER|SECTION_FLAG_IS_ARRAY))) {
- def->nested_section[wctx->level] = 1;
- av_bprintf(&wctx->section_pbuf[wctx->level], "%s%s:",
- wctx->section_pbuf[wctx->level-1].str,
- upcase_string(buf, sizeof(buf),
- av_x_if_null(section->element_name, section->name)));
- }
-
- if (def->noprint_wrappers || def->nested_section[wctx->level])
- return;
-
- if (!(section->flags & (SECTION_FLAG_IS_WRAPPER|SECTION_FLAG_IS_ARRAY)))
- writer_printf(wctx, "[%s]\n", upcase_string(buf, sizeof(buf), section->name));
-}
-
-static void default_print_section_footer(WriterContext *wctx)
-{
- DefaultContext *def = wctx->priv;
- const struct section *section = wctx->section[wctx->level];
- char buf[32];
-
- if (def->noprint_wrappers || def->nested_section[wctx->level])
- return;
-
- if (!(section->flags & (SECTION_FLAG_IS_WRAPPER|SECTION_FLAG_IS_ARRAY)))
- writer_printf(wctx, "[/%s]\n", upcase_string(buf, sizeof(buf), section->name));
-}
-
-static void default_print_str(WriterContext *wctx, const char *key, const char *value)
-{
- DefaultContext *def = wctx->priv;
-
- if (!def->nokey)
- writer_printf(wctx, "%s%s=", wctx->section_pbuf[wctx->level].str, key);
- writer_printf(wctx, "%s\n", value);
-}
-
-static void default_print_int(WriterContext *wctx, const char *key, int64_t value)
-{
- DefaultContext *def = wctx->priv;
-
- if (!def->nokey)
- writer_printf(wctx, "%s%s=", wctx->section_pbuf[wctx->level].str, key);
- writer_printf(wctx, "%"PRId64"\n", value);
-}
-
-static const Writer default_writer = {
- .name = "default",
- .priv_size = sizeof(DefaultContext),
- .print_section_header = default_print_section_header,
- .print_section_footer = default_print_section_footer,
- .print_integer = default_print_int,
- .print_string = default_print_str,
- .flags = WRITER_FLAG_DISPLAY_OPTIONAL_FIELDS,
- .priv_class = &default_class,
-};
-
-/* Compact output */
-
-/**
- * Apply C-language-like string escaping.
- */
-static const char *c_escape_str(AVBPrint *dst, const char *src, const char sep, void *log_ctx)
-{
- const char *p;
-
- for (p = src; *p; p++) {
- switch (*p) {
- case '\b': av_bprintf(dst, "%s", "\\b"); break;
- case '\f': av_bprintf(dst, "%s", "\\f"); break;
- case '\n': av_bprintf(dst, "%s", "\\n"); break;
- case '\r': av_bprintf(dst, "%s", "\\r"); break;
- case '\\': av_bprintf(dst, "%s", "\\\\"); break;
- default:
- if (*p == sep)
- av_bprint_chars(dst, '\\', 1);
- av_bprint_chars(dst, *p, 1);
- }
- }
- return dst->str;
-}
-
-/**
- * Quote fields containing special characters, check RFC4180.
- */
-static const char *csv_escape_str(AVBPrint *dst, const char *src, const char sep, void *log_ctx)
-{
- char meta_chars[] = { sep, '"', '\n', '\r', '\0' };
- int needs_quoting = !!src[strcspn(src, meta_chars)];
-
- if (needs_quoting)
- av_bprint_chars(dst, '"', 1);
-
- for (; *src; src++) {
- if (*src == '"')
- av_bprint_chars(dst, '"', 1);
- av_bprint_chars(dst, *src, 1);
- }
- if (needs_quoting)
- av_bprint_chars(dst, '"', 1);
- return dst->str;
-}
-
-static const char *none_escape_str(AVBPrint *dst, const char *src, const char sep, void *log_ctx)
-{
- return src;
-}
-
-typedef struct CompactContext {
- const AVClass *class;
- char *item_sep_str;
- char item_sep;
- int nokey;
- int print_section;
- char *escape_mode_str;
- const char * (*escape_str)(AVBPrint *dst, const char *src, const char sep, void *log_ctx);
- int nested_section[SECTION_MAX_NB_LEVELS];
- int has_nested_elems[SECTION_MAX_NB_LEVELS];
- int terminate_line[SECTION_MAX_NB_LEVELS];
-} CompactContext;
-
-#undef OFFSET
-#define OFFSET(x) offsetof(CompactContext, x)
-
-static const AVOption compact_options[]= {
- {"item_sep", "set item separator", OFFSET(item_sep_str), AV_OPT_TYPE_STRING, {.str="|"}, 0, 0 },
- {"s", "set item separator", OFFSET(item_sep_str), AV_OPT_TYPE_STRING, {.str="|"}, 0, 0 },
- {"nokey", "force no key printing", OFFSET(nokey), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1 },
- {"nk", "force no key printing", OFFSET(nokey), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1 },
- {"escape", "set escape mode", OFFSET(escape_mode_str), AV_OPT_TYPE_STRING, {.str="c"}, 0, 0 },
- {"e", "set escape mode", OFFSET(escape_mode_str), AV_OPT_TYPE_STRING, {.str="c"}, 0, 0 },
- {"print_section", "print section name", OFFSET(print_section), AV_OPT_TYPE_BOOL, {.i64=1}, 0, 1 },
- {"p", "print section name", OFFSET(print_section), AV_OPT_TYPE_BOOL, {.i64=1}, 0, 1 },
- {NULL},
-};
-
-DEFINE_WRITER_CLASS(compact);
-
-static av_cold int compact_init(WriterContext *wctx)
-{
- CompactContext *compact = wctx->priv;
-
- if (strlen(compact->item_sep_str) != 1) {
- av_log(wctx, AV_LOG_ERROR, "Item separator '%s' specified, but must contain a single character\n",
- compact->item_sep_str);
- return AVERROR(EINVAL);
- }
- compact->item_sep = compact->item_sep_str[0];
-
- if (!strcmp(compact->escape_mode_str, "none")) compact->escape_str = none_escape_str;
- else if (!strcmp(compact->escape_mode_str, "c" )) compact->escape_str = c_escape_str;
- else if (!strcmp(compact->escape_mode_str, "csv" )) compact->escape_str = csv_escape_str;
- else {
- av_log(wctx, AV_LOG_ERROR, "Unknown escape mode '%s'\n", compact->escape_mode_str);
- return AVERROR(EINVAL);
- }
-
- return 0;
-}
-
-static void compact_print_section_header(WriterContext *wctx, const void *data)
-{
- CompactContext *compact = wctx->priv;
- const struct section *section = wctx->section[wctx->level];
- const struct section *parent_section = wctx->level ?
- wctx->section[wctx->level-1] : NULL;
- compact->terminate_line[wctx->level] = 1;
- compact->has_nested_elems[wctx->level] = 0;
-
- av_bprint_clear(&wctx->section_pbuf[wctx->level]);
- if (parent_section &&
- (section->flags & SECTION_FLAG_HAS_TYPE ||
- (!(section->flags & SECTION_FLAG_IS_ARRAY) &&
- !(parent_section->flags & (SECTION_FLAG_IS_WRAPPER|SECTION_FLAG_IS_ARRAY))))) {
-
- /* define a prefix for elements not contained in an array or
- in a wrapper, or for array elements with a type */
- const char *element_name = (char *)av_x_if_null(section->element_name, section->name);
- AVBPrint *section_pbuf = &wctx->section_pbuf[wctx->level];
-
- compact->nested_section[wctx->level] = 1;
- compact->has_nested_elems[wctx->level-1] = 1;
-
- av_bprintf(section_pbuf, "%s%s",
- wctx->section_pbuf[wctx->level-1].str, element_name);
-
- if (section->flags & SECTION_FLAG_HAS_TYPE) {
- // add /TYPE to prefix
- av_bprint_chars(section_pbuf, '/', 1);
-
- // normalize section type, replace special characters and lower case
- for (const char *p = section->get_type(data); *p; p++) {
- char c =
- (*p >= '0' && *p <= '9') ||
- (*p >= 'a' && *p <= 'z') ||
- (*p >= 'A' && *p <= 'Z') ? av_tolower(*p) : '_';
- av_bprint_chars(section_pbuf, c, 1);
- }
- }
- av_bprint_chars(section_pbuf, ':', 1);
-
- wctx->nb_item[wctx->level] = wctx->nb_item[wctx->level-1];
- } else {
- if (parent_section && !(parent_section->flags & (SECTION_FLAG_IS_WRAPPER|SECTION_FLAG_IS_ARRAY)) &&
- wctx->level && wctx->nb_item[wctx->level-1])
- writer_w8(wctx, compact->item_sep);
- if (compact->print_section &&
- !(section->flags & (SECTION_FLAG_IS_WRAPPER|SECTION_FLAG_IS_ARRAY)))
- writer_printf(wctx, "%s%c", section->name, compact->item_sep);
- }
-}
-
-static void compact_print_section_footer(WriterContext *wctx)
-{
- CompactContext *compact = wctx->priv;
-
- if (!compact->nested_section[wctx->level] &&
- compact->terminate_line[wctx->level] &&
- !(wctx->section[wctx->level]->flags & (SECTION_FLAG_IS_WRAPPER|SECTION_FLAG_IS_ARRAY)))
- writer_w8(wctx, '\n');
-}
-
-static void compact_print_str(WriterContext *wctx, const char *key, const char *value)
-{
- CompactContext *compact = wctx->priv;
- AVBPrint buf;
-
- if (wctx->nb_item[wctx->level]) writer_w8(wctx, compact->item_sep);
- if (!compact->nokey)
- writer_printf(wctx, "%s%s=", wctx->section_pbuf[wctx->level].str, key);
- av_bprint_init(&buf, 1, AV_BPRINT_SIZE_UNLIMITED);
- writer_put_str(wctx, compact->escape_str(&buf, value, compact->item_sep, wctx));
- av_bprint_finalize(&buf, NULL);
-}
-
-static void compact_print_int(WriterContext *wctx, const char *key, int64_t value)
-{
- CompactContext *compact = wctx->priv;
-
- if (wctx->nb_item[wctx->level]) writer_w8(wctx, compact->item_sep);
- if (!compact->nokey)
- writer_printf(wctx, "%s%s=", wctx->section_pbuf[wctx->level].str, key);
- writer_printf(wctx, "%"PRId64, value);
-}
-
-static const Writer compact_writer = {
- .name = "compact",
- .priv_size = sizeof(CompactContext),
- .init = compact_init,
- .print_section_header = compact_print_section_header,
- .print_section_footer = compact_print_section_footer,
- .print_integer = compact_print_int,
- .print_string = compact_print_str,
- .flags = WRITER_FLAG_DISPLAY_OPTIONAL_FIELDS,
- .priv_class = &compact_class,
-};
-
-/* CSV output */
-
-#undef OFFSET
-#define OFFSET(x) offsetof(CompactContext, x)
-
-static const AVOption csv_options[] = {
- {"item_sep", "set item separator", OFFSET(item_sep_str), AV_OPT_TYPE_STRING, {.str=","}, 0, 0 },
- {"s", "set item separator", OFFSET(item_sep_str), AV_OPT_TYPE_STRING, {.str=","}, 0, 0 },
- {"nokey", "force no key printing", OFFSET(nokey), AV_OPT_TYPE_BOOL, {.i64=1}, 0, 1 },
- {"nk", "force no key printing", OFFSET(nokey), AV_OPT_TYPE_BOOL, {.i64=1}, 0, 1 },
- {"escape", "set escape mode", OFFSET(escape_mode_str), AV_OPT_TYPE_STRING, {.str="csv"}, 0, 0 },
- {"e", "set escape mode", OFFSET(escape_mode_str), AV_OPT_TYPE_STRING, {.str="csv"}, 0, 0 },
- {"print_section", "print section name", OFFSET(print_section), AV_OPT_TYPE_BOOL, {.i64=1}, 0, 1 },
- {"p", "print section name", OFFSET(print_section), AV_OPT_TYPE_BOOL, {.i64=1}, 0, 1 },
- {NULL},
-};
-
-DEFINE_WRITER_CLASS(csv);
-
-static const Writer csv_writer = {
- .name = "csv",
- .priv_size = sizeof(CompactContext),
- .init = compact_init,
- .print_section_header = compact_print_section_header,
- .print_section_footer = compact_print_section_footer,
- .print_integer = compact_print_int,
- .print_string = compact_print_str,
- .flags = WRITER_FLAG_DISPLAY_OPTIONAL_FIELDS,
- .priv_class = &csv_class,
-};
-
-/* Flat output */
-
-typedef struct FlatContext {
- const AVClass *class;
- const char *sep_str;
- char sep;
- int hierarchical;
-} FlatContext;
-
-#undef OFFSET
-#define OFFSET(x) offsetof(FlatContext, x)
-
-static const AVOption flat_options[]= {
- {"sep_char", "set separator", OFFSET(sep_str), AV_OPT_TYPE_STRING, {.str="."}, 0, 0 },
- {"s", "set separator", OFFSET(sep_str), AV_OPT_TYPE_STRING, {.str="."}, 0, 0 },
- {"hierarchical", "specify if the section specification should be hierarchical", OFFSET(hierarchical), AV_OPT_TYPE_BOOL, {.i64=1}, 0, 1 },
- {"h", "specify if the section specification should be hierarchical", OFFSET(hierarchical), AV_OPT_TYPE_BOOL, {.i64=1}, 0, 1 },
- {NULL},
-};
-
-DEFINE_WRITER_CLASS(flat);
-
-static av_cold int flat_init(WriterContext *wctx)
-{
- FlatContext *flat = wctx->priv;
-
- if (strlen(flat->sep_str) != 1) {
- av_log(wctx, AV_LOG_ERROR, "Item separator '%s' specified, but must contain a single character\n",
- flat->sep_str);
- return AVERROR(EINVAL);
- }
- flat->sep = flat->sep_str[0];
-
- return 0;
-}
-
-static const char *flat_escape_key_str(AVBPrint *dst, const char *src, const char sep)
-{
- const char *p;
-
- for (p = src; *p; p++) {
- if (!((*p >= '0' && *p <= '9') ||
- (*p >= 'a' && *p <= 'z') ||
- (*p >= 'A' && *p <= 'Z')))
- av_bprint_chars(dst, '_', 1);
- else
- av_bprint_chars(dst, *p, 1);
- }
- return dst->str;
-}
-
-static const char *flat_escape_value_str(AVBPrint *dst, const char *src)
-{
- const char *p;
-
- for (p = src; *p; p++) {
- switch (*p) {
- case '\n': av_bprintf(dst, "%s", "\\n"); break;
- case '\r': av_bprintf(dst, "%s", "\\r"); break;
- case '\\': av_bprintf(dst, "%s", "\\\\"); break;
- case '"': av_bprintf(dst, "%s", "\\\""); break;
- case '`': av_bprintf(dst, "%s", "\\`"); break;
- case '$': av_bprintf(dst, "%s", "\\$"); break;
- default: av_bprint_chars(dst, *p, 1); break;
- }
- }
- return dst->str;
-}
-
-static void flat_print_section_header(WriterContext *wctx, const void *data)
-{
- FlatContext *flat = wctx->priv;
- AVBPrint *buf = &wctx->section_pbuf[wctx->level];
- const struct section *section = wctx->section[wctx->level];
- const struct section *parent_section = wctx->level ?
- wctx->section[wctx->level-1] : NULL;
-
- /* build section header */
- av_bprint_clear(buf);
- if (!parent_section)
- return;
- av_bprintf(buf, "%s", wctx->section_pbuf[wctx->level-1].str);
-
- if (flat->hierarchical ||
- !(section->flags & (SECTION_FLAG_IS_ARRAY|SECTION_FLAG_IS_WRAPPER))) {
- av_bprintf(buf, "%s%s", wctx->section[wctx->level]->name, flat->sep_str);
-
- if (parent_section->flags & SECTION_FLAG_IS_ARRAY) {
- int n = parent_section->id == SECTION_ID_PACKETS_AND_FRAMES ?
- wctx->nb_section_packet_frame : wctx->nb_item[wctx->level-1];
- av_bprintf(buf, "%d%s", n, flat->sep_str);
- }
- }
-}
-
-static void flat_print_int(WriterContext *wctx, const char *key, int64_t value)
-{
- writer_printf(wctx, "%s%s=%"PRId64"\n", wctx->section_pbuf[wctx->level].str, key, value);
-}
-
-static void flat_print_str(WriterContext *wctx, const char *key, const char *value)
-{
- FlatContext *flat = wctx->priv;
- AVBPrint buf;
-
- writer_put_str(wctx, wctx->section_pbuf[wctx->level].str);
- av_bprint_init(&buf, 1, AV_BPRINT_SIZE_UNLIMITED);
- writer_printf(wctx, "%s=", flat_escape_key_str(&buf, key, flat->sep));
- av_bprint_clear(&buf);
- writer_printf(wctx, "\"%s\"\n", flat_escape_value_str(&buf, value));
- av_bprint_finalize(&buf, NULL);
-}
-
-static const Writer flat_writer = {
- .name = "flat",
- .priv_size = sizeof(FlatContext),
- .init = flat_init,
- .print_section_header = flat_print_section_header,
- .print_integer = flat_print_int,
- .print_string = flat_print_str,
- .flags = WRITER_FLAG_DISPLAY_OPTIONAL_FIELDS|WRITER_FLAG_PUT_PACKETS_AND_FRAMES_IN_SAME_CHAPTER,
- .priv_class = &flat_class,
-};
-
-/* INI format output */
-
-typedef struct INIContext {
- const AVClass *class;
- int hierarchical;
-} INIContext;
-
-#undef OFFSET
-#define OFFSET(x) offsetof(INIContext, x)
-
-static const AVOption ini_options[] = {
- {"hierarchical", "specify if the section specification should be hierarchical", OFFSET(hierarchical), AV_OPT_TYPE_BOOL, {.i64=1}, 0, 1 },
- {"h", "specify if the section specification should be hierarchical", OFFSET(hierarchical), AV_OPT_TYPE_BOOL, {.i64=1}, 0, 1 },
- {NULL},
-};
-
-DEFINE_WRITER_CLASS(ini);
-
-static char *ini_escape_str(AVBPrint *dst, const char *src)
-{
- int i = 0;
- char c = 0;
-
- while (c = src[i++]) {
- switch (c) {
- case '\b': av_bprintf(dst, "%s", "\\b"); break;
- case '\f': av_bprintf(dst, "%s", "\\f"); break;
- case '\n': av_bprintf(dst, "%s", "\\n"); break;
- case '\r': av_bprintf(dst, "%s", "\\r"); break;
- case '\t': av_bprintf(dst, "%s", "\\t"); break;
- case '\\':
- case '#' :
- case '=' :
- case ':' : av_bprint_chars(dst, '\\', 1);
- default:
- if ((unsigned char)c < 32)
- av_bprintf(dst, "\\x00%02x", c & 0xff);
- else
- av_bprint_chars(dst, c, 1);
- break;
- }
- }
- return dst->str;
-}
-
-static void ini_print_section_header(WriterContext *wctx, const void *data)
-{
- INIContext *ini = wctx->priv;
- AVBPrint *buf = &wctx->section_pbuf[wctx->level];
- const struct section *section = wctx->section[wctx->level];
- const struct section *parent_section = wctx->level ?
- wctx->section[wctx->level-1] : NULL;
-
- av_bprint_clear(buf);
- if (!parent_section) {
- writer_put_str(wctx, "# ffprobe output\n\n");
- return;
- }
-
- if (wctx->nb_item[wctx->level-1])
- writer_w8(wctx, '\n');
-
- av_bprintf(buf, "%s", wctx->section_pbuf[wctx->level-1].str);
- if (ini->hierarchical ||
- !(section->flags & (SECTION_FLAG_IS_ARRAY|SECTION_FLAG_IS_WRAPPER))) {
- av_bprintf(buf, "%s%s", buf->str[0] ? "." : "", wctx->section[wctx->level]->name);
-
- if (parent_section->flags & SECTION_FLAG_IS_ARRAY) {
- int n = parent_section->id == SECTION_ID_PACKETS_AND_FRAMES ?
- wctx->nb_section_packet_frame : wctx->nb_item[wctx->level-1];
- av_bprintf(buf, ".%d", n);
- }
- }
-
- if (!(section->flags & (SECTION_FLAG_IS_ARRAY|SECTION_FLAG_IS_WRAPPER)))
- writer_printf(wctx, "[%s]\n", buf->str);
-}
-
-static void ini_print_str(WriterContext *wctx, const char *key, const char *value)
-{
- AVBPrint buf;
-
- av_bprint_init(&buf, 1, AV_BPRINT_SIZE_UNLIMITED);
- writer_printf(wctx, "%s=", ini_escape_str(&buf, key));
- av_bprint_clear(&buf);
- writer_printf(wctx, "%s\n", ini_escape_str(&buf, value));
- av_bprint_finalize(&buf, NULL);
-}
-
-static void ini_print_int(WriterContext *wctx, const char *key, int64_t value)
-{
- writer_printf(wctx, "%s=%"PRId64"\n", key, value);
-}
-
-static const Writer ini_writer = {
- .name = "ini",
- .priv_size = sizeof(INIContext),
- .print_section_header = ini_print_section_header,
- .print_integer = ini_print_int,
- .print_string = ini_print_str,
- .flags = WRITER_FLAG_DISPLAY_OPTIONAL_FIELDS|WRITER_FLAG_PUT_PACKETS_AND_FRAMES_IN_SAME_CHAPTER,
- .priv_class = &ini_class,
-};
-
-/* JSON output */
-
-typedef struct JSONContext {
- const AVClass *class;
- int indent_level;
- int compact;
- const char *item_sep, *item_start_end;
-} JSONContext;
-
-#undef OFFSET
-#define OFFSET(x) offsetof(JSONContext, x)
-
-static const AVOption json_options[]= {
- { "compact", "enable compact output", OFFSET(compact), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1 },
- { "c", "enable compact output", OFFSET(compact), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1 },
- { NULL }
-};
-
-DEFINE_WRITER_CLASS(json);
-
-static av_cold int json_init(WriterContext *wctx)
-{
- JSONContext *json = wctx->priv;
-
- json->item_sep = json->compact ? ", " : ",\n";
- json->item_start_end = json->compact ? " " : "\n";
-
- return 0;
-}
-
-static const char *json_escape_str(AVBPrint *dst, const char *src, void *log_ctx)
-{
- static const char json_escape[] = {'"', '\\', '\b', '\f', '\n', '\r', '\t', 0};
- static const char json_subst[] = {'"', '\\', 'b', 'f', 'n', 'r', 't', 0};
- const char *p;
-
- for (p = src; *p; p++) {
- char *s = strchr(json_escape, *p);
- if (s) {
- av_bprint_chars(dst, '\\', 1);
- av_bprint_chars(dst, json_subst[s - json_escape], 1);
- } else if ((unsigned char)*p < 32) {
- av_bprintf(dst, "\\u00%02x", *p & 0xff);
- } else {
- av_bprint_chars(dst, *p, 1);
- }
- }
- return dst->str;
-}
-
-#define JSON_INDENT() writer_printf(wctx, "%*c", json->indent_level * 4, ' ')
-
-static void json_print_section_header(WriterContext *wctx, const void *data)
-{
- JSONContext *json = wctx->priv;
- AVBPrint buf;
- const struct section *section = wctx->section[wctx->level];
- const struct section *parent_section = wctx->level ?
- wctx->section[wctx->level-1] : NULL;
-
- if (wctx->level && wctx->nb_item[wctx->level-1])
- writer_put_str(wctx, ",\n");
-
- if (section->flags & SECTION_FLAG_IS_WRAPPER) {
- writer_put_str(wctx, "{\n");
- json->indent_level++;
- } else {
- av_bprint_init(&buf, 1, AV_BPRINT_SIZE_UNLIMITED);
- json_escape_str(&buf, section->name, wctx);
- JSON_INDENT();
-
- json->indent_level++;
- if (section->flags & SECTION_FLAG_IS_ARRAY) {
- writer_printf(wctx, "\"%s\": [\n", buf.str);
- } else if (parent_section && !(parent_section->flags & SECTION_FLAG_IS_ARRAY)) {
- writer_printf(wctx, "\"%s\": {%s", buf.str, json->item_start_end);
- } else {
- writer_printf(wctx, "{%s", json->item_start_end);
-
- /* this is required so the parser can distinguish between packets and frames */
- if (parent_section && parent_section->id == SECTION_ID_PACKETS_AND_FRAMES) {
- if (!json->compact)
- JSON_INDENT();
- writer_printf(wctx, "\"type\": \"%s\"", section->name);
- wctx->nb_item[wctx->level]++;
- }
- }
- av_bprint_finalize(&buf, NULL);
- }
-}
-
-static void json_print_section_footer(WriterContext *wctx)
-{
- JSONContext *json = wctx->priv;
- const struct section *section = wctx->section[wctx->level];
-
- if (wctx->level == 0) {
- json->indent_level--;
- writer_put_str(wctx, "\n}\n");
- } else if (section->flags & SECTION_FLAG_IS_ARRAY) {
- writer_w8(wctx, '\n');
- json->indent_level--;
- JSON_INDENT();
- writer_w8(wctx, ']');
- } else {
- writer_put_str(wctx, json->item_start_end);
- json->indent_level--;
- if (!json->compact)
- JSON_INDENT();
- writer_w8(wctx, '}');
- }
-}
-
-static inline void json_print_item_str(WriterContext *wctx,
- const char *key, const char *value)
-{
- AVBPrint buf;
-
- av_bprint_init(&buf, 1, AV_BPRINT_SIZE_UNLIMITED);
- writer_printf(wctx, "\"%s\":", json_escape_str(&buf, key, wctx));
- av_bprint_clear(&buf);
- writer_printf(wctx, " \"%s\"", json_escape_str(&buf, value, wctx));
- av_bprint_finalize(&buf, NULL);
-}
-
-static void json_print_str(WriterContext *wctx, const char *key, const char *value)
-{
- JSONContext *json = wctx->priv;
- const struct section *parent_section = wctx->level ?
- wctx->section[wctx->level-1] : NULL;
-
- if (wctx->nb_item[wctx->level] || (parent_section && parent_section->id == SECTION_ID_PACKETS_AND_FRAMES))
- writer_put_str(wctx, json->item_sep);
- if (!json->compact)
- JSON_INDENT();
- json_print_item_str(wctx, key, value);
-}
-
-static void json_print_int(WriterContext *wctx, const char *key, int64_t value)
-{
- JSONContext *json = wctx->priv;
- const struct section *parent_section = wctx->level ?
- wctx->section[wctx->level-1] : NULL;
- AVBPrint buf;
-
- if (wctx->nb_item[wctx->level] || (parent_section && parent_section->id == SECTION_ID_PACKETS_AND_FRAMES))
- writer_put_str(wctx, json->item_sep);
- if (!json->compact)
- JSON_INDENT();
-
- av_bprint_init(&buf, 1, AV_BPRINT_SIZE_UNLIMITED);
- writer_printf(wctx, "\"%s\": %"PRId64, json_escape_str(&buf, key, wctx), value);
- av_bprint_finalize(&buf, NULL);
-}
-
-static const Writer json_writer = {
- .name = "json",
- .priv_size = sizeof(JSONContext),
- .init = json_init,
- .print_section_header = json_print_section_header,
- .print_section_footer = json_print_section_footer,
- .print_integer = json_print_int,
- .print_string = json_print_str,
- .flags = WRITER_FLAG_PUT_PACKETS_AND_FRAMES_IN_SAME_CHAPTER,
- .priv_class = &json_class,
-};
-
-/* XML output */
-
-typedef struct XMLContext {
- const AVClass *class;
- int within_tag;
- int indent_level;
- int fully_qualified;
- int xsd_strict;
-} XMLContext;
-
-#undef OFFSET
-#define OFFSET(x) offsetof(XMLContext, x)
-
-static const AVOption xml_options[] = {
- {"fully_qualified", "specify if the output should be fully qualified", OFFSET(fully_qualified), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1 },
- {"q", "specify if the output should be fully qualified", OFFSET(fully_qualified), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1 },
- {"xsd_strict", "ensure that the output is XSD compliant", OFFSET(xsd_strict), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1 },
- {"x", "ensure that the output is XSD compliant", OFFSET(xsd_strict), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1 },
- {NULL},
-};
-
-DEFINE_WRITER_CLASS(xml);
-
-static av_cold int xml_init(WriterContext *wctx)
-{
- XMLContext *xml = wctx->priv;
-
- if (xml->xsd_strict) {
- xml->fully_qualified = 1;
-#define CHECK_COMPLIANCE(opt, opt_name) \
- if (opt) { \
- av_log(wctx, AV_LOG_ERROR, \
- "XSD-compliant output selected but option '%s' was selected, XML output may be non-compliant.\n" \
- "You need to disable such option with '-no%s'\n", opt_name, opt_name); \
- return AVERROR(EINVAL); \
- }
- CHECK_COMPLIANCE(show_private_data, "private");
- CHECK_COMPLIANCE(show_value_unit, "unit");
- CHECK_COMPLIANCE(use_value_prefix, "prefix");
- }
-
- return 0;
-}
-
-#define XML_INDENT() writer_printf(wctx, "%*c", xml->indent_level * 4, ' ')
-
-static void xml_print_section_header(WriterContext *wctx, const void *data)
-{
- XMLContext *xml = wctx->priv;
- const struct section *section = wctx->section[wctx->level];
- const struct section *parent_section = wctx->level ?
- wctx->section[wctx->level-1] : NULL;
-
- if (wctx->level == 0) {
- const char *qual = " xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" "
- "xmlns:ffprobe=\"http://www.ffmpeg.org/schema/ffprobe\" "
- "xsi:schemaLocation=\"http://www.ffmpeg.org/schema/ffprobe ffprobe.xsd\"";
-
- writer_put_str(wctx, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
- writer_printf(wctx, "<%sffprobe%s>\n",
- xml->fully_qualified ? "ffprobe:" : "",
- xml->fully_qualified ? qual : "");
- return;
- }
-
- if (xml->within_tag) {
- xml->within_tag = 0;
- writer_put_str(wctx, ">\n");
- }
-
- if (parent_section && (parent_section->flags & SECTION_FLAG_IS_WRAPPER) &&
- wctx->level && wctx->nb_item[wctx->level-1])
- writer_w8(wctx, '\n');
- xml->indent_level++;
-
- if (section->flags & (SECTION_FLAG_IS_ARRAY|SECTION_FLAG_HAS_VARIABLE_FIELDS)) {
- XML_INDENT(); writer_printf(wctx, "<%s", section->name);
-
- if (section->flags & SECTION_FLAG_HAS_TYPE) {
- AVBPrint buf;
- av_bprint_init(&buf, 1, AV_BPRINT_SIZE_UNLIMITED);
- av_bprint_escape(&buf, section->get_type(data), NULL,
- AV_ESCAPE_MODE_XML, AV_ESCAPE_FLAG_XML_DOUBLE_QUOTES);
- writer_printf(wctx, " type=\"%s\"", buf.str);
- }
- writer_printf(wctx, ">\n", section->name);
- } else {
- XML_INDENT(); writer_printf(wctx, "<%s ", section->name);
- xml->within_tag = 1;
- }
-}
-
-static void xml_print_section_footer(WriterContext *wctx)
-{
- XMLContext *xml = wctx->priv;
- const struct section *section = wctx->section[wctx->level];
-
- if (wctx->level == 0) {
- writer_printf(wctx, "</%sffprobe>\n", xml->fully_qualified ? "ffprobe:" : "");
- } else if (xml->within_tag) {
- xml->within_tag = 0;
- writer_put_str(wctx, "/>\n");
- xml->indent_level--;
- } else {
- XML_INDENT(); writer_printf(wctx, "</%s>\n", section->name);
- xml->indent_level--;
- }
-}
-
-static void xml_print_value(WriterContext *wctx, const char *key,
- const char *str, int64_t num, const int is_int)
-{
- AVBPrint buf;
- XMLContext *xml = wctx->priv;
- const struct section *section = wctx->section[wctx->level];
-
- av_bprint_init(&buf, 1, AV_BPRINT_SIZE_UNLIMITED);
-
- if (section->flags & SECTION_FLAG_HAS_VARIABLE_FIELDS) {
- xml->indent_level++;
- XML_INDENT();
- av_bprint_escape(&buf, key, NULL,
- AV_ESCAPE_MODE_XML, AV_ESCAPE_FLAG_XML_DOUBLE_QUOTES);
- writer_printf(wctx, "<%s key=\"%s\"",
- section->element_name, buf.str);
- av_bprint_clear(&buf);
-
- if (is_int) {
- writer_printf(wctx, " value=\"%"PRId64"\"/>\n", num);
- } else {
- av_bprint_escape(&buf, str, NULL,
- AV_ESCAPE_MODE_XML, AV_ESCAPE_FLAG_XML_DOUBLE_QUOTES);
- writer_printf(wctx, " value=\"%s\"/>\n", buf.str);
- }
- xml->indent_level--;
- } else {
- if (wctx->nb_item[wctx->level])
- writer_w8(wctx, ' ');
-
- if (is_int) {
- writer_printf(wctx, "%s=\"%"PRId64"\"", key, num);
- } else {
- av_bprint_escape(&buf, str, NULL,
- AV_ESCAPE_MODE_XML, AV_ESCAPE_FLAG_XML_DOUBLE_QUOTES);
- writer_printf(wctx, "%s=\"%s\"", key, buf.str);
- }
- }
-
- av_bprint_finalize(&buf, NULL);
-}
-
-static inline void xml_print_str(WriterContext *wctx, const char *key, const char *value) {
- xml_print_value(wctx, key, value, 0, 0);
-}
-
-static void xml_print_int(WriterContext *wctx, const char *key, int64_t value)
-{
- xml_print_value(wctx, key, NULL, value, 1);
-}
-
-static Writer xml_writer = {
- .name = "xml",
- .priv_size = sizeof(XMLContext),
- .init = xml_init,
- .print_section_header = xml_print_section_header,
- .print_section_footer = xml_print_section_footer,
- .print_integer = xml_print_int,
- .print_string = xml_print_str,
- .flags = WRITER_FLAG_PUT_PACKETS_AND_FRAMES_IN_SAME_CHAPTER,
- .priv_class = &xml_class,
-};
-
-static void writer_register_all(void)
-{
- static int initialized;
-
- if (initialized)
- return;
- initialized = 1;
-
- writer_register(&default_writer);
- writer_register(&compact_writer);
- writer_register(&csv_writer);
- writer_register(&flat_writer);
- writer_register(&ini_writer);
- writer_register(&json_writer);
- writer_register(&xml_writer);
-}
#define print_fmt(k, f, ...) do { \
av_bprint_clear(&pbuf); \
av_bprintf(&pbuf, f, __VA_ARGS__); \
- writer_print_string(w, k, pbuf.str, 0); \
+ avtext_print_string(w, k, pbuf.str, 0); \
} while (0)
#define print_list_fmt(k, f, n, m, ...) do { \
@@ -2000,28 +424,19 @@ static void writer_register_all(void)
av_bprintf(&pbuf, f, __VA_ARGS__); \
} \
} \
- writer_print_string(w, k, pbuf.str, 0); \
+ avtext_print_string(w, k, pbuf.str, 0); \
} while (0)
-#define print_int(k, v) writer_print_integer(w, k, v)
-#define print_q(k, v, s) writer_print_rational(w, k, v, s)
-#define print_str(k, v) writer_print_string(w, k, v, 0)
-#define print_str_opt(k, v) writer_print_string(w, k, v, PRINT_STRING_OPT)
-#define print_str_validate(k, v) writer_print_string(w, k, v, PRINT_STRING_VALIDATE)
-#define print_time(k, v, tb) writer_print_time(w, k, v, tb, 0)
-#define print_ts(k, v) writer_print_ts(w, k, v, 0)
-#define print_duration_time(k, v, tb) writer_print_time(w, k, v, tb, 1)
-#define print_duration_ts(k, v) writer_print_ts(w, k, v, 1)
-#define print_val(k, v, u) do { \
- struct unit_value uv; \
- uv.val.i = v; \
- uv.unit = u; \
- writer_print_string(w, k, value_string(val_str, sizeof(val_str), uv), 0); \
-} while (0)
-
-#define print_section_header(s) writer_print_section_header(w, NULL, s)
-#define print_section_header_data(s, d) writer_print_section_header(w, d, s)
-#define print_section_footer(s) writer_print_section_footer(w, s)
+#define print_int(k, v) avtext_print_integer(w, k, v)
+#define print_q(k, v, s) avtext_print_rational(w, k, v, s)
+#define print_str(k, v) avtext_print_string(w, k, v, 0)
+#define print_str_opt(k, v) avtext_print_string(w, k, v, AV_TEXTFORMAT_PRINT_STRING_OPTIONAL)
+#define print_str_validate(k, v) avtext_print_string(w, k, v, AV_TEXTFORMAT_PRINT_STRING_VALIDATE)
+#define print_time(k, v, tb) avtext_print_time(w, k, v, tb, 0)
+#define print_ts(k, v) avtext_print_ts(w, k, v, 0)
+#define print_duration_time(k, v, tb) avtext_print_time(w, k, v, tb, 1)
+#define print_duration_ts(k, v) avtext_print_ts(w, k, v, 1)
+#define print_val(k, v, u) avtext_print_unit_int(w, k, v, u)
#define REALLOCZ_ARRAY_STREAM(ptr, cur_n, new_n) \
{ \
@@ -2529,7 +944,7 @@ static void print_pkt_side_data(WriterContext *w,
double rotation = av_display_rotation_get((int32_t *)sd->data);
if (isnan(rotation))
rotation = 0;
- writer_print_integers(w, "displaymatrix", sd->data, 9, " %11d", 3, 4, 1);
+ avtext_print_integers(w, "displaymatrix", sd->data, 9, " %11d", 3, 4, 1);
print_int("rotation", rotation);
} else if (sd->type == AV_PKT_DATA_STEREO3D) {
const AVStereo3D *stereo = (AVStereo3D *)sd->data;
@@ -2626,8 +1041,8 @@ static void print_pkt_side_data(WriterContext *w,
} else if (sd->type == AV_PKT_DATA_WEBVTT_IDENTIFIER ||
sd->type == AV_PKT_DATA_WEBVTT_SETTINGS) {
if (do_show_data)
- writer_print_data(w, "data", sd->data, sd->size);
- writer_print_data_hash(w, "data_hash", sd->data, sd->size);
+ avtext_print_data(w, "data", sd->data, sd->size);
+ avtext_print_data_hash(w, "data_hash", sd->data, sd->size);
} else if (sd->type == AV_PKT_DATA_FRAME_CROPPING && sd->size >= sizeof(uint32_t) * 4) {
print_int("crop_top", AV_RL32(sd->data));
print_int("crop_bottom", AV_RL32(sd->data + 4));
@@ -2754,7 +1169,6 @@ static int show_log(WriterContext *w, int section_ids, int section_id, int log_l
static void show_packet(WriterContext *w, InputFile *ifile, AVPacket *pkt, int packet_idx)
{
- char val_str[128];
AVStream *st = ifile->streams[pkt->stream_index].st;
AVBPrint pbuf;
const char *s;
@@ -2780,8 +1194,8 @@ static void show_packet(WriterContext *w, InputFile *ifile, AVPacket *pkt, int p
pkt->flags & AV_PKT_FLAG_DISCARD ? 'D' : '_',
pkt->flags & AV_PKT_FLAG_CORRUPT ? 'C' : '_');
if (do_show_data)
- writer_print_data(w, "data", pkt->data, pkt->size);
- writer_print_data_hash(w, "data_hash", pkt->data, pkt->size);
+ avtext_print_data(w, "data", pkt->data, pkt->size);
+ avtext_print_data_hash(w, "data_hash", pkt->data, pkt->size);
if (pkt->side_data_elems) {
size_t size;
@@ -2850,7 +1264,7 @@ static void print_frame_side_data(WriterContext *w,
double rotation = av_display_rotation_get((int32_t *)sd->data);
if (isnan(rotation))
rotation = 0;
- writer_print_integers(w, "displaymatrix", sd->data, 9, " %11d", 3, 4, 1);
+ avtext_print_integers(w, "displaymatrix", sd->data, 9, " %11d", 3, 4, 1);
print_int("rotation", rotation);
} else if (sd->type == AV_FRAME_DATA_AFD && sd->size > 0) {
print_int("active_format", *sd->data);
@@ -3450,12 +1864,12 @@ static int show_stream(WriterContext *w, AVFormatContext *fmt_ctx, int stream_id
if (nb_streams_packets[stream_idx]) print_fmt ("nb_read_packets", "%"PRIu64, nb_streams_packets[stream_idx]);
else print_str_opt("nb_read_packets", "N/A");
if (do_show_data)
- writer_print_data(w, "extradata", par->extradata,
+ avtext_print_data(w, "extradata", par->extradata,
par->extradata_size);
if (par->extradata_size > 0) {
print_int("extradata_size", par->extradata_size);
- writer_print_data_hash(w, "extradata_hash", par->extradata,
+ avtext_print_data_hash(w, "extradata_hash", par->extradata,
par->extradata_size);
}
@@ -3829,7 +2243,6 @@ static int show_chapters(WriterContext *w, InputFile *ifile)
static int show_format(WriterContext *w, InputFile *ifile)
{
AVFormatContext *fmt_ctx = ifile->fmt_ctx;
- char val_str[128];
int64_t size = fmt_ctx->pb ? avio_size(fmt_ctx->pb) : -1;
int ret = 0;
@@ -4005,7 +2418,7 @@ static void close_input_file(InputFile *ifile)
avformat_close_input(&ifile->fmt_ctx);
}
-static int probe_file(WriterContext *wctx, const char *filename,
+static int probe_file(WriterContext *tctx, const char *filename,
const char *print_filename)
{
InputFile ifile = { 0 };
@@ -4047,40 +2460,40 @@ static int probe_file(WriterContext *wctx, const char *filename,
if (do_read_frames || do_read_packets) {
if (do_show_frames && do_show_packets &&
- wctx->writer->flags & WRITER_FLAG_PUT_PACKETS_AND_FRAMES_IN_SAME_CHAPTER)
+ tctx->formatter->flags & AV_TEXTFORMAT_FLAG_SUPPORTS_MIXED_ARRAY_CONTENT)
section_id = SECTION_ID_PACKETS_AND_FRAMES;
else if (do_show_packets && !do_show_frames)
section_id = SECTION_ID_PACKETS;
else // (!do_show_packets && do_show_frames)
section_id = SECTION_ID_FRAMES;
if (do_show_frames || do_show_packets)
- writer_print_section_header(wctx, NULL, section_id);
- ret = read_packets(wctx, &ifile);
+ writer_print_section_header(tctx, NULL, section_id);
+ ret = read_packets(tctx, &ifile);
if (do_show_frames || do_show_packets)
- writer_print_section_footer(wctx);
+ writer_print_section_footer(tctx);
CHECK_END;
}
if (do_show_programs) {
- ret = show_programs(wctx, &ifile);
+ ret = show_programs(tctx, &ifile);
CHECK_END;
}
if (do_show_stream_groups) {
- ret = show_stream_groups(wctx, &ifile);
+ ret = show_stream_groups(tctx, &ifile);
CHECK_END;
}
if (do_show_streams) {
- ret = show_streams(wctx, &ifile);
+ ret = show_streams(tctx, &ifile);
CHECK_END;
}
if (do_show_chapters) {
- ret = show_chapters(wctx, &ifile);
+ ret = show_chapters(tctx, &ifile);
CHECK_END;
}
if (do_show_format) {
- ret = show_format(wctx, &ifile);
+ ret = show_format(tctx, &ifile);
CHECK_END;
}
@@ -4229,11 +2642,11 @@ static int opt_format(void *optctx, const char *opt, const char *arg)
static inline void mark_section_show_entries(SectionID section_id,
int show_all_entries, AVDictionary *entries)
{
- struct section *section = §ions[section_id];
+ struct AVTextFormatSection *section = §ions[section_id];
section->show_all_entries = show_all_entries;
if (show_all_entries) {
- for (const SectionID *id = section->children_ids; *id != -1; id++)
+ for (const int *id = section->children_ids; *id != -1; id++)
mark_section_show_entries(*id, show_all_entries, entries);
} else {
av_dict_copy(§ion->entries_to_show, entries, 0);
@@ -4246,7 +2659,7 @@ static int match_section(const char *section_name,
int i, ret = 0;
for (i = 0; i < FF_ARRAY_ELEMS(sections); i++) {
- const struct section *section = §ions[i];
+ const struct AVTextFormatSection *section = §ions[i];
if (!strcmp(section_name, section->name) ||
(section->unique_name && !strcmp(section_name, section->unique_name))) {
av_log(NULL, AV_LOG_DEBUG,
@@ -4518,13 +2931,13 @@ static int opt_pretty(void *optctx, const char *opt, const char *arg)
static void print_section(SectionID id, int level)
{
- const SectionID *pid;
- const struct section *section = §ions[id];
+ const int *pid;
+ const struct AVTextFormatSection *section = §ions[id];
printf("%c%c%c%c",
- section->flags & SECTION_FLAG_IS_WRAPPER ? 'W' : '.',
- section->flags & SECTION_FLAG_IS_ARRAY ? 'A' : '.',
- section->flags & SECTION_FLAG_HAS_VARIABLE_FIELDS ? 'V' : '.',
- section->flags & SECTION_FLAG_HAS_TYPE ? 'T' : '.');
+ section->flags & AV_TEXTFORMAT_SECTION_FLAG_IS_WRAPPER ? 'W' : '.',
+ section->flags & AV_TEXTFORMAT_SECTION_FLAG_IS_ARRAY ? 'A' : '.',
+ section->flags & AV_TEXTFORMAT_SECTION_FLAG_HAS_VARIABLE_FIELDS ? 'V' : '.',
+ section->flags & AV_TEXTFORMAT_SECTION_FLAG_HAS_TYPE ? 'T' : '.');
printf("%*c %s", level * 4, ' ', section->name);
if (section->unique_name)
printf("/%s", section->unique_name);
@@ -4627,10 +3040,10 @@ static const OptionDef real_options[] = {
static inline int check_section_show_entries(int section_id)
{
- struct section *section = §ions[section_id];
+ struct AVTextFormatSection *section = §ions[section_id];
if (sections[section_id].show_all_entries || sections[section_id].entries_to_show)
return 1;
- for (const SectionID *id = section->children_ids; *id != -1; id++)
+ for (const int *id = section->children_ids; *id != -1; id++)
if (check_section_show_entries(*id))
return 1;
return 0;
@@ -4643,10 +3056,11 @@ static inline int check_section_show_entries(int section_id)
int main(int argc, char **argv)
{
- const Writer *w;
- WriterContext *wctx;
+ const AVTextFormatter *f;
+ WriterContext *tctx;
+ AVTextWriterContext *wctx;
char *buf;
- char *w_name = NULL, *w_args = NULL;
+ char *f_name = NULL, *f_args = NULL;
int ret, input_ret, i;
init_dynload();
@@ -4708,58 +3122,51 @@ int main(int argc, char **argv)
goto end;
}
- writer_register_all();
-
if (!output_format)
output_format = av_strdup("default");
if (!output_format) {
ret = AVERROR(ENOMEM);
goto end;
}
- w_name = av_strtok(output_format, "=", &buf);
- if (!w_name) {
+ f_name = av_strtok(output_format, "=", &buf);
+ if (!f_name) {
av_log(NULL, AV_LOG_ERROR,
"No name specified for the output format\n");
ret = AVERROR(EINVAL);
goto end;
}
- w_args = buf;
-
- if (show_data_hash) {
- if ((ret = av_hash_alloc(&hash, show_data_hash)) < 0) {
- if (ret == AVERROR(EINVAL)) {
- const char *n;
- av_log(NULL, AV_LOG_ERROR,
- "Unknown hash algorithm '%s'\nKnown algorithms:",
- show_data_hash);
- for (i = 0; (n = av_hash_names(i)); i++)
- av_log(NULL, AV_LOG_ERROR, " %s", n);
- av_log(NULL, AV_LOG_ERROR, "\n");
- }
- goto end;
- }
- }
+ f_args = buf;
- w = writer_get_by_name(w_name);
- if (!w) {
- av_log(NULL, AV_LOG_ERROR, "Unknown output format with name '%s'\n", w_name);
+ f = avtext_get_formatter_by_name(f_name);
+ if (!f) {
+ av_log(NULL, AV_LOG_ERROR, "Unknown output format with name '%s'\n", f_name);
ret = AVERROR(EINVAL);
goto end;
}
- if ((ret = writer_open(&wctx, w, w_args,
- sections, FF_ARRAY_ELEMS(sections), output_filename)) >= 0) {
- if (w == &xml_writer)
- wctx->string_validation_utf8_flags |= AV_UTF8_FLAG_EXCLUDE_XML_INVALID_CONTROL_CODES;
+ if (output_filename) {
+ ret = avtextwriter_create_file(&wctx, output_filename, 1);
+ } else
+ ret = avtextwriter_create_stdout(&wctx);
- writer_print_section_header(wctx, NULL, SECTION_ID_ROOT);
+ if (ret < 0)
+ goto end;
+
+ if ((ret = avtext_context_open(&tctx, f, wctx, f_args,
+ sections, FF_ARRAY_ELEMS(sections), show_value_unit,
+ use_value_prefix, use_byte_value_binary_prefix, use_value_sexagesimal_format,
+ show_optional_fields, show_data_hash)) >= 0) {
+ if (f == &avtextformatter_xml)
+ tctx->string_validation_utf8_flags |= AV_UTF8_FLAG_EXCLUDE_XML_INVALID_CONTROL_CODES;
+
+ writer_print_section_header(tctx, NULL, SECTION_ID_ROOT);
if (do_show_program_version)
- ffprobe_show_program_version(wctx);
+ ffprobe_show_program_version(tctx);
if (do_show_library_versions)
- ffprobe_show_library_versions(wctx);
+ ffprobe_show_library_versions(tctx);
if (do_show_pixel_formats)
- ffprobe_show_pixel_formats(wctx);
+ ffprobe_show_pixel_formats(tctx);
if (!input_filename &&
((do_show_format || do_show_programs || do_show_stream_groups || do_show_streams || do_show_chapters || do_show_packets || do_show_error) ||
@@ -4769,17 +3176,22 @@ int main(int argc, char **argv)
av_log(NULL, AV_LOG_ERROR, "Use -h to get full help or, even better, run 'man %s'.\n", program_name);
ret = AVERROR(EINVAL);
} else if (input_filename) {
- ret = probe_file(wctx, input_filename, print_input_filename);
+ ret = probe_file(tctx, input_filename, print_input_filename);
if (ret < 0 && do_show_error)
- show_error(wctx, ret);
+ show_error(tctx, ret);
}
input_ret = ret;
- writer_print_section_footer(wctx);
- ret = writer_close(&wctx);
+ avtext_print_section_footer(tctx);
+
+ ret = avtextwriter_context_close(&wctx);
+ if (ret < 0)
+ av_log(NULL, AV_LOG_ERROR, "Writing output failed (closing writer): %s\n", av_err2str(ret));
+
+ ret = avtext_context_close(&tctx);
if (ret < 0)
- av_log(NULL, AV_LOG_ERROR, "Writing output failed: %s\n", av_err2str(ret));
+ av_log(NULL, AV_LOG_ERROR, "Writing output failed (closing formatter): %s\n", av_err2str(ret));
ret = FFMIN(ret, input_ret);
}
@@ -4790,7 +3202,6 @@ end:
av_freep(&input_filename);
av_freep(&print_input_filename);
av_freep(&read_intervals);
- av_hash_freep(&hash);
uninit_opts();
for (i = 0; i < FF_ARRAY_ELEMS(sections); i++)
--
ffmpeg-codebot
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 108+ messages in thread
* [FFmpeg-devel] [PATCH v9 3/4] fftools/ffprobe: Rename writer_print_section_* and WriterContext
2025-03-23 3:42 ` [FFmpeg-devel] [PATCH v9 " ffmpegagent
2025-03-23 3:42 ` [FFmpeg-devel] [PATCH v9 1/4] fftools/textformat: Extract and generalize textformat api from ffprobe.c softworkz
2025-03-23 3:42 ` [FFmpeg-devel] [PATCH v9 2/4] fftools/ffprobe: Change to use textformat api softworkz
@ 2025-03-23 3:42 ` softworkz
2025-03-23 3:42 ` [FFmpeg-devel] [PATCH v9 4/4] fftools/ffprobe: Rename AVTextFormatContext variables (w => tfc) softworkz
3 siblings, 0 replies; 108+ messages in thread
From: softworkz @ 2025-03-23 3:42 UTC (permalink / raw)
To: ffmpeg-devel; +Cc: softworkz
From: softworkz <softworkz@hotmail.com>
separated for better clarity of the preceding commit
Signed-off-by: softworkz <softworkz@hotmail.com>
ren
---
fftools/ffprobe.c | 361 +++++++++++++++++++++++-----------------------
1 file changed, 178 insertions(+), 183 deletions(-)
diff --git a/fftools/ffprobe.c b/fftools/ffprobe.c
index f398057df7..4a90bc4824 100644
--- a/fftools/ffprobe.c
+++ b/fftools/ffprobe.c
@@ -71,11 +71,6 @@
#include "libavutil/thread.h"
-// TEMPORARY DEFINES
-#define writer_print_section_header(w, d, s) avtext_print_section_header(w, d, s)
-#define writer_print_section_footer(w) avtext_print_section_footer(w)
-#define WriterContext AVTextFormatContext
-
// attached as opaque_ref to packets/frames
typedef struct FrameData {
int64_t pkt_pos;
@@ -446,25 +441,25 @@ static void log_callback(void *ptr, int level, const char *fmt, va_list vl)
memset( (ptr) + (cur_n), 0, ((new_n) - (cur_n)) * sizeof(*(ptr)) ); \
}
-static inline int show_tags(WriterContext *w, AVDictionary *tags, int section_id)
+static inline int show_tags(AVTextFormatContext *w, AVDictionary *tags, int section_id)
{
const AVDictionaryEntry *tag = NULL;
int ret = 0;
if (!tags)
return 0;
- writer_print_section_header(w, NULL, section_id);
+ avtext_print_section_header(w, NULL, section_id);
while ((tag = av_dict_iterate(tags, tag))) {
if ((ret = print_str_validate(tag->key, tag->value)) < 0)
break;
}
- writer_print_section_footer(w);
+ avtext_print_section_footer(w);
return ret;
}
-static void print_dovi_metadata(WriterContext *w, const AVDOVIMetadata *dovi)
+static void print_dovi_metadata(AVTextFormatContext *w, const AVDOVIMetadata *dovi)
{
if (!dovi)
return;
@@ -519,15 +514,15 @@ static void print_dovi_metadata(WriterContext *w, const AVDOVIMetadata *dovi)
print_int("num_x_partitions", mapping->num_x_partitions);
print_int("num_y_partitions", mapping->num_y_partitions);
- writer_print_section_header(w, NULL, SECTION_ID_FRAME_SIDE_DATA_COMPONENT_LIST);
+ avtext_print_section_header(w, NULL, SECTION_ID_FRAME_SIDE_DATA_COMPONENT_LIST);
for (int c = 0; c < 3; c++) {
const AVDOVIReshapingCurve *curve = &mapping->curves[c];
- writer_print_section_header(w, "Reshaping curve", SECTION_ID_FRAME_SIDE_DATA_COMPONENT);
+ avtext_print_section_header(w, "Reshaping curve", SECTION_ID_FRAME_SIDE_DATA_COMPONENT);
print_list_fmt("pivots", "%"PRIu16, curve->num_pivots, 1, curve->pivots[idx]);
- writer_print_section_header(w, NULL, SECTION_ID_FRAME_SIDE_DATA_PIECE_LIST);
+ avtext_print_section_header(w, NULL, SECTION_ID_FRAME_SIDE_DATA_PIECE_LIST);
for (int i = 0; i < curve->num_pivots - 1; i++) {
AVBPrint piece_buf;
@@ -545,7 +540,7 @@ static void print_dovi_metadata(WriterContext *w, const AVDOVIMetadata *dovi)
}
av_bprintf(&piece_buf, " mapping");
- writer_print_section_header(w, piece_buf.str, SECTION_ID_FRAME_SIDE_DATA_PIECE);
+ avtext_print_section_header(w, piece_buf.str, SECTION_ID_FRAME_SIDE_DATA_PIECE);
print_int("mapping_idc", curve->mapping_idc[i]);
switch (curve->mapping_idc[i]) {
case AV_DOVI_MAPPING_POLYNOMIAL:
@@ -569,11 +564,11 @@ static void print_dovi_metadata(WriterContext *w, const AVDOVIMetadata *dovi)
}
// SECTION_ID_FRAME_SIDE_DATA_PIECE
- writer_print_section_footer(w);
+ avtext_print_section_footer(w);
}
// SECTION_ID_FRAME_SIDE_DATA_PIECE_LIST
- writer_print_section_footer(w);
+ avtext_print_section_footer(w);
if (mapping->nlq_method_idc != AV_DOVI_NLQ_NONE) {
const AVDOVINLQParams *nlq = &mapping->nlq[c];
@@ -589,11 +584,11 @@ static void print_dovi_metadata(WriterContext *w, const AVDOVIMetadata *dovi)
}
// SECTION_ID_FRAME_SIDE_DATA_COMPONENT
- writer_print_section_footer(w);
+ avtext_print_section_footer(w);
}
// SECTION_ID_FRAME_SIDE_DATA_COMPONENT_LIST
- writer_print_section_footer(w);
+ avtext_print_section_footer(w);
// color metadata
print_int("dm_metadata_id", color->dm_metadata_id);
@@ -626,7 +621,7 @@ static void print_dovi_metadata(WriterContext *w, const AVDOVIMetadata *dovi)
}
}
-static void print_dynamic_hdr10_plus(WriterContext *w, const AVDynamicHDRPlus *metadata)
+static void print_dynamic_hdr10_plus(AVTextFormatContext *w, const AVDynamicHDRPlus *metadata)
{
if (!metadata)
return;
@@ -725,7 +720,7 @@ static void print_dynamic_hdr10_plus(WriterContext *w, const AVDynamicHDRPlus *m
}
}
-static void print_dynamic_hdr_vivid(WriterContext *w, const AVDynamicHDRVivid *metadata)
+static void print_dynamic_hdr_vivid(AVTextFormatContext *w, const AVDynamicHDRVivid *metadata)
{
if (!metadata)
return;
@@ -795,7 +790,7 @@ static void print_dynamic_hdr_vivid(WriterContext *w, const AVDynamicHDRVivid *m
}
}
-static void print_ambient_viewing_environment(WriterContext *w,
+static void print_ambient_viewing_environment(AVTextFormatContext *w,
const AVAmbientViewingEnvironment *env)
{
if (!env)
@@ -806,7 +801,7 @@ static void print_ambient_viewing_environment(WriterContext *w,
print_q("ambient_light_y", env->ambient_light_y, '/');
}
-static void print_film_grain_params(WriterContext *w,
+static void print_film_grain_params(AVTextFormatContext *w,
const AVFilmGrainParams *fgp)
{
const char *color_range, *color_primaries, *color_trc, *color_space;
@@ -852,10 +847,10 @@ static void print_film_grain_params(WriterContext *w,
print_int("overlap_flag", aom->overlap_flag);
print_int("limit_output_range", aom->limit_output_range);
- writer_print_section_header(w, NULL, SECTION_ID_FRAME_SIDE_DATA_COMPONENT_LIST);
+ avtext_print_section_header(w, NULL, SECTION_ID_FRAME_SIDE_DATA_COMPONENT_LIST);
if (aom->num_y_points) {
- writer_print_section_header(w, NULL, SECTION_ID_FRAME_SIDE_DATA_COMPONENT);
+ avtext_print_section_header(w, NULL, SECTION_ID_FRAME_SIDE_DATA_COMPONENT);
print_int("bit_depth_luma", fgp->bit_depth_luma);
print_list_fmt("y_points_value", "%"PRIu8, aom->num_y_points, 1, aom->y_points[idx][0]);
@@ -863,14 +858,14 @@ static void print_film_grain_params(WriterContext *w,
print_list_fmt("ar_coeffs_y", "%"PRId8, num_ar_coeffs_y, 1, aom->ar_coeffs_y[idx]);
// SECTION_ID_FRAME_SIDE_DATA_COMPONENT
- writer_print_section_footer(w);
+ avtext_print_section_footer(w);
}
for (int uv = 0; uv < 2; uv++) {
if (!aom->num_uv_points[uv] && !aom->chroma_scaling_from_luma)
continue;
- writer_print_section_header(w, NULL, SECTION_ID_FRAME_SIDE_DATA_COMPONENT);
+ avtext_print_section_header(w, NULL, SECTION_ID_FRAME_SIDE_DATA_COMPONENT);
print_int("bit_depth_chroma", fgp->bit_depth_chroma);
print_list_fmt("uv_points_value", "%"PRIu8, aom->num_uv_points[uv], 1, aom->uv_points[uv][idx][0]);
@@ -881,11 +876,11 @@ static void print_film_grain_params(WriterContext *w,
print_int("uv_offset", aom->uv_offset[uv]);
// SECTION_ID_FRAME_SIDE_DATA_COMPONENT
- writer_print_section_footer(w);
+ avtext_print_section_footer(w);
}
// SECTION_ID_FRAME_SIDE_DATA_COMPONENT_LIST
- writer_print_section_footer(w);
+ avtext_print_section_footer(w);
break;
}
case AV_FILM_GRAIN_PARAMS_H274: {
@@ -894,36 +889,36 @@ static void print_film_grain_params(WriterContext *w,
print_int("blending_mode_id", h274->blending_mode_id);
print_int("log2_scale_factor", h274->log2_scale_factor);
- writer_print_section_header(w, NULL, SECTION_ID_FRAME_SIDE_DATA_COMPONENT_LIST);
+ avtext_print_section_header(w, NULL, SECTION_ID_FRAME_SIDE_DATA_COMPONENT_LIST);
for (int c = 0; c < 3; c++) {
if (!h274->component_model_present[c])
continue;
- writer_print_section_header(w, NULL, SECTION_ID_FRAME_SIDE_DATA_COMPONENT);
+ avtext_print_section_header(w, NULL, SECTION_ID_FRAME_SIDE_DATA_COMPONENT);
print_int(c ? "bit_depth_chroma" : "bit_depth_luma", c ? fgp->bit_depth_chroma : fgp->bit_depth_luma);
- writer_print_section_header(w, NULL, SECTION_ID_FRAME_SIDE_DATA_PIECE_LIST);
+ avtext_print_section_header(w, NULL, SECTION_ID_FRAME_SIDE_DATA_PIECE_LIST);
for (int i = 0; i < h274->num_intensity_intervals[c]; i++) {
- writer_print_section_header(w, NULL, SECTION_ID_FRAME_SIDE_DATA_PIECE);
+ avtext_print_section_header(w, NULL, SECTION_ID_FRAME_SIDE_DATA_PIECE);
print_int("intensity_interval_lower_bound", h274->intensity_interval_lower_bound[c][i]);
print_int("intensity_interval_upper_bound", h274->intensity_interval_upper_bound[c][i]);
print_list_fmt("comp_model_value", "%"PRId16, h274->num_model_values[c], 1, h274->comp_model_value[c][i][idx]);
// SECTION_ID_FRAME_SIDE_DATA_PIECE
- writer_print_section_footer(w);
+ avtext_print_section_footer(w);
}
// SECTION_ID_FRAME_SIDE_DATA_PIECE_LIST
- writer_print_section_footer(w);
+ avtext_print_section_footer(w);
// SECTION_ID_FRAME_SIDE_DATA_COMPONENT
- writer_print_section_footer(w);
+ avtext_print_section_footer(w);
}
// SECTION_ID_FRAME_SIDE_DATA_COMPONENT_LIST
- writer_print_section_footer(w);
+ avtext_print_section_footer(w);
break;
}
}
@@ -931,14 +926,14 @@ static void print_film_grain_params(WriterContext *w,
av_bprint_finalize(&pbuf, NULL);
}
-static void print_pkt_side_data(WriterContext *w,
+static void print_pkt_side_data(AVTextFormatContext *w,
AVCodecParameters *par,
const AVPacketSideData *sd,
SectionID id_data)
{
const char *name = av_packet_side_data_name(sd->type);
- writer_print_section_header(w, sd, id_data);
+ avtext_print_section_header(w, sd, id_data);
print_str("side_data_type", name ? name : "unknown");
if (sd->type == AV_PKT_DATA_DISPLAYMATRIX && sd->size >= 9*4) {
double rotation = av_display_rotation_get((int32_t *)sd->data);
@@ -1053,7 +1048,7 @@ static void print_pkt_side_data(WriterContext *w,
}
}
-static void print_private_data(WriterContext *w, void *priv_data)
+static void print_private_data(AVTextFormatContext *w, void *priv_data)
{
const AVOption *opt = NULL;
while (opt = av_opt_next(priv_data, opt)) {
@@ -1066,7 +1061,7 @@ static void print_private_data(WriterContext *w, void *priv_data)
}
}
-static void print_color_range(WriterContext *w, enum AVColorRange color_range)
+static void print_color_range(AVTextFormatContext *w, enum AVColorRange color_range)
{
const char *val = av_color_range_name(color_range);
if (!val || color_range == AVCOL_RANGE_UNSPECIFIED) {
@@ -1076,7 +1071,7 @@ static void print_color_range(WriterContext *w, enum AVColorRange color_range)
}
}
-static void print_color_space(WriterContext *w, enum AVColorSpace color_space)
+static void print_color_space(AVTextFormatContext *w, enum AVColorSpace color_space)
{
const char *val = av_color_space_name(color_space);
if (!val || color_space == AVCOL_SPC_UNSPECIFIED) {
@@ -1086,7 +1081,7 @@ static void print_color_space(WriterContext *w, enum AVColorSpace color_space)
}
}
-static void print_primaries(WriterContext *w, enum AVColorPrimaries color_primaries)
+static void print_primaries(AVTextFormatContext *w, enum AVColorPrimaries color_primaries)
{
const char *val = av_color_primaries_name(color_primaries);
if (!val || color_primaries == AVCOL_PRI_UNSPECIFIED) {
@@ -1096,7 +1091,7 @@ static void print_primaries(WriterContext *w, enum AVColorPrimaries color_primar
}
}
-static void print_color_trc(WriterContext *w, enum AVColorTransferCharacteristic color_trc)
+static void print_color_trc(AVTextFormatContext *w, enum AVColorTransferCharacteristic color_trc)
{
const char *val = av_color_transfer_name(color_trc);
if (!val || color_trc == AVCOL_TRC_UNSPECIFIED) {
@@ -1106,7 +1101,7 @@ static void print_color_trc(WriterContext *w, enum AVColorTransferCharacteristic
}
}
-static void print_chroma_location(WriterContext *w, enum AVChromaLocation chroma_location)
+static void print_chroma_location(AVTextFormatContext *w, enum AVChromaLocation chroma_location)
{
const char *val = av_chroma_location_name(chroma_location);
if (!val || chroma_location == AVCHROMA_LOC_UNSPECIFIED) {
@@ -1132,7 +1127,7 @@ static void clear_log(int need_lock)
ff_mutex_unlock(&log_mutex);
}
-static int show_log(WriterContext *w, int section_ids, int section_id, int log_level)
+static int show_log(AVTextFormatContext *w, int section_ids, int section_id, int log_level)
{
int i;
ff_mutex_lock(&log_mutex);
@@ -1140,11 +1135,11 @@ static int show_log(WriterContext *w, int section_ids, int section_id, int log_l
ff_mutex_unlock(&log_mutex);
return 0;
}
- writer_print_section_header(w, NULL, section_ids);
+ avtext_print_section_header(w, NULL, section_ids);
for (i=0; i<log_buffer_size; i++) {
if (log_buffer[i].log_level <= log_level) {
- writer_print_section_header(w, NULL, section_id);
+ avtext_print_section_header(w, NULL, section_id);
print_str("context", log_buffer[i].context_name);
print_int("level", log_buffer[i].log_level);
print_int("category", log_buffer[i].category);
@@ -1156,18 +1151,18 @@ static int show_log(WriterContext *w, int section_ids, int section_id, int log_l
print_str_opt("parent_category", "N/A");
}
print_str("message", log_buffer[i].log_message);
- writer_print_section_footer(w);
+ avtext_print_section_footer(w);
}
}
clear_log(0);
ff_mutex_unlock(&log_mutex);
- writer_print_section_footer(w);
+ avtext_print_section_footer(w);
return 0;
}
-static void show_packet(WriterContext *w, InputFile *ifile, AVPacket *pkt, int packet_idx)
+static void show_packet(AVTextFormatContext *w, InputFile *ifile, AVPacket *pkt, int packet_idx)
{
AVStream *st = ifile->streams[pkt->stream_index].st;
AVBPrint pbuf;
@@ -1175,7 +1170,7 @@ static void show_packet(WriterContext *w, InputFile *ifile, AVPacket *pkt, int p
av_bprint_init(&pbuf, 1, AV_BPRINT_SIZE_UNLIMITED);
- writer_print_section_header(w, NULL, SECTION_ID_PACKET);
+ avtext_print_section_header(w, NULL, SECTION_ID_PACKET);
s = av_get_media_type_string(st->codecpar->codec_type);
if (s) print_str ("codec_type", s);
@@ -1209,29 +1204,29 @@ static void show_packet(WriterContext *w, InputFile *ifile, AVPacket *pkt, int p
av_dict_free(&dict);
}
- writer_print_section_header(w, NULL, SECTION_ID_PACKET_SIDE_DATA_LIST);
+ avtext_print_section_header(w, NULL, SECTION_ID_PACKET_SIDE_DATA_LIST);
for (int i = 0; i < pkt->side_data_elems; i++) {
print_pkt_side_data(w, st->codecpar, &pkt->side_data[i],
SECTION_ID_PACKET_SIDE_DATA);
- writer_print_section_footer(w);
+ avtext_print_section_footer(w);
}
- writer_print_section_footer(w);
+ avtext_print_section_footer(w);
}
- writer_print_section_footer(w);
+ avtext_print_section_footer(w);
av_bprint_finalize(&pbuf, NULL);
fflush(stdout);
}
-static void show_subtitle(WriterContext *w, AVSubtitle *sub, AVStream *stream,
+static void show_subtitle(AVTextFormatContext *w, AVSubtitle *sub, AVStream *stream,
AVFormatContext *fmt_ctx)
{
AVBPrint pbuf;
av_bprint_init(&pbuf, 1, AV_BPRINT_SIZE_UNLIMITED);
- writer_print_section_header(w, NULL, SECTION_ID_SUBTITLE);
+ avtext_print_section_header(w, NULL, SECTION_ID_SUBTITLE);
print_str ("media_type", "subtitle");
print_ts ("pts", sub->pts);
@@ -1241,23 +1236,23 @@ static void show_subtitle(WriterContext *w, AVSubtitle *sub, AVStream *stream,
print_int ("end_display_time", sub->end_display_time);
print_int ("num_rects", sub->num_rects);
- writer_print_section_footer(w);
+ avtext_print_section_footer(w);
av_bprint_finalize(&pbuf, NULL);
fflush(stdout);
}
-static void print_frame_side_data(WriterContext *w,
+static void print_frame_side_data(AVTextFormatContext *w,
const AVFrame *frame,
const AVStream *stream)
{
- writer_print_section_header(w, NULL, SECTION_ID_FRAME_SIDE_DATA_LIST);
+ avtext_print_section_header(w, NULL, SECTION_ID_FRAME_SIDE_DATA_LIST);
for (int i = 0; i < frame->nb_side_data; i++) {
const AVFrameSideData *sd = frame->side_data[i];
const char *name;
- writer_print_section_header(w, sd, SECTION_ID_FRAME_SIDE_DATA);
+ avtext_print_section_header(w, sd, SECTION_ID_FRAME_SIDE_DATA);
name = av_frame_side_data_name(sd->type);
print_str("side_data_type", name ? name : "unknown");
if (sd->type == AV_FRAME_DATA_DISPLAYMATRIX && sd->size >= 9*4) {
@@ -1275,15 +1270,15 @@ static void print_frame_side_data(WriterContext *w,
} else if (sd->type == AV_FRAME_DATA_S12M_TIMECODE && sd->size == 16) {
uint32_t *tc = (uint32_t*)sd->data;
int m = FFMIN(tc[0],3);
- writer_print_section_header(w, NULL, SECTION_ID_FRAME_SIDE_DATA_TIMECODE_LIST);
+ avtext_print_section_header(w, NULL, SECTION_ID_FRAME_SIDE_DATA_TIMECODE_LIST);
for (int j = 1; j <= m ; j++) {
char tcbuf[AV_TIMECODE_STR_SIZE];
av_timecode_make_smpte_tc_string2(tcbuf, stream->avg_frame_rate, tc[j], 0, 0);
- writer_print_section_header(w, NULL, SECTION_ID_FRAME_SIDE_DATA_TIMECODE);
+ avtext_print_section_header(w, NULL, SECTION_ID_FRAME_SIDE_DATA_TIMECODE);
print_str("value", tcbuf);
- writer_print_section_footer(w);
+ avtext_print_section_footer(w);
}
- writer_print_section_footer(w);
+ avtext_print_section_footer(w);
} else if (sd->type == AV_FRAME_DATA_MASTERING_DISPLAY_METADATA) {
AVMasteringDisplayMetadata *metadata = (AVMasteringDisplayMetadata *)sd->data;
@@ -1328,12 +1323,12 @@ static void print_frame_side_data(WriterContext *w,
} else if (sd->type == AV_FRAME_DATA_VIEW_ID) {
print_int("view_id", *(int*)sd->data);
}
- writer_print_section_footer(w);
+ avtext_print_section_footer(w);
}
- writer_print_section_footer(w);
+ avtext_print_section_footer(w);
}
-static void show_frame(WriterContext *w, AVFrame *frame, AVStream *stream,
+static void show_frame(AVTextFormatContext *w, AVFrame *frame, AVStream *stream,
AVFormatContext *fmt_ctx)
{
FrameData *fd = frame->opaque_ref ? (FrameData*)frame->opaque_ref->data : NULL;
@@ -1343,7 +1338,7 @@ static void show_frame(WriterContext *w, AVFrame *frame, AVStream *stream,
av_bprint_init(&pbuf, 1, AV_BPRINT_SIZE_UNLIMITED);
- writer_print_section_header(w, NULL, SECTION_ID_FRAME);
+ avtext_print_section_header(w, NULL, SECTION_ID_FRAME);
s = av_get_media_type_string(stream->codecpar->codec_type);
if (s) print_str ("media_type", s);
@@ -1415,13 +1410,13 @@ static void show_frame(WriterContext *w, AVFrame *frame, AVStream *stream,
if (frame->nb_side_data)
print_frame_side_data(w, frame, stream);
- writer_print_section_footer(w);
+ avtext_print_section_footer(w);
av_bprint_finalize(&pbuf, NULL);
fflush(stdout);
}
-static av_always_inline int process_frame(WriterContext *w,
+static av_always_inline int process_frame(AVTextFormatContext *w,
InputFile *ifile,
AVFrame *frame, const AVPacket *pkt,
int *packet_new)
@@ -1518,7 +1513,7 @@ static void log_read_interval(const ReadInterval *interval, void *log_ctx, int l
av_log(log_ctx, log_level, "\n");
}
-static int read_interval_packets(WriterContext *w, InputFile *ifile,
+static int read_interval_packets(AVTextFormatContext *w, InputFile *ifile,
const ReadInterval *interval, int64_t *cur_ts)
{
AVFormatContext *fmt_ctx = ifile->fmt_ctx;
@@ -1643,7 +1638,7 @@ end:
return ret;
}
-static int read_packets(WriterContext *w, InputFile *ifile)
+static int read_packets(AVTextFormatContext *w, InputFile *ifile)
{
AVFormatContext *fmt_ctx = ifile->fmt_ctx;
int i, ret = 0;
@@ -1663,22 +1658,22 @@ static int read_packets(WriterContext *w, InputFile *ifile)
return ret;
}
-static void print_dispositions(WriterContext *w, uint32_t disposition, SectionID section_id)
+static void print_dispositions(AVTextFormatContext *w, uint32_t disposition, SectionID section_id)
{
- writer_print_section_header(w, NULL, section_id);
+ avtext_print_section_header(w, NULL, section_id);
for (int i = 0; i < sizeof(disposition) * CHAR_BIT; i++) {
const char *disposition_str = av_disposition_to_string(1U << i);
if (disposition_str)
print_int(disposition_str, !!(disposition & (1U << i)));
}
- writer_print_section_footer(w);
+ avtext_print_section_footer(w);
}
#define IN_PROGRAM 1
#define IN_STREAM_GROUP 2
-static int show_stream(WriterContext *w, AVFormatContext *fmt_ctx, int stream_idx, InputStream *ist, int container)
+static int show_stream(AVTextFormatContext *w, AVFormatContext *fmt_ctx, int stream_idx, InputStream *ist, int container)
{
AVStream *stream = ist->st;
AVCodecParameters *par;
@@ -1710,7 +1705,7 @@ static int show_stream(WriterContext *w, AVFormatContext *fmt_ctx, int stream_id
av_bprint_init(&pbuf, 1, AV_BPRINT_SIZE_UNLIMITED);
- writer_print_section_header(w, NULL, section_header[container]);
+ avtext_print_section_header(w, NULL, section_header[container]);
print_int("index", stream->index);
@@ -1885,45 +1880,45 @@ static int show_stream(WriterContext *w, AVFormatContext *fmt_ctx, int stream_id
}
if (stream->codecpar->nb_coded_side_data) {
- writer_print_section_header(w, NULL, SECTION_ID_STREAM_SIDE_DATA_LIST);
+ avtext_print_section_header(w, NULL, SECTION_ID_STREAM_SIDE_DATA_LIST);
for (int i = 0; i < stream->codecpar->nb_coded_side_data; i++) {
print_pkt_side_data(w, stream->codecpar, &stream->codecpar->coded_side_data[i],
SECTION_ID_STREAM_SIDE_DATA);
- writer_print_section_footer(w);
+ avtext_print_section_footer(w);
}
- writer_print_section_footer(w);
+ avtext_print_section_footer(w);
}
- writer_print_section_footer(w);
+ avtext_print_section_footer(w);
av_bprint_finalize(&pbuf, NULL);
fflush(stdout);
return ret;
}
-static int show_streams(WriterContext *w, InputFile *ifile)
+static int show_streams(AVTextFormatContext *w, InputFile *ifile)
{
AVFormatContext *fmt_ctx = ifile->fmt_ctx;
int i, ret = 0;
- writer_print_section_header(w, NULL, SECTION_ID_STREAMS);
+ avtext_print_section_header(w, NULL, SECTION_ID_STREAMS);
for (i = 0; i < ifile->nb_streams; i++)
if (selected_streams[i]) {
ret = show_stream(w, fmt_ctx, i, &ifile->streams[i], 0);
if (ret < 0)
break;
}
- writer_print_section_footer(w);
+ avtext_print_section_footer(w);
return ret;
}
-static int show_program(WriterContext *w, InputFile *ifile, AVProgram *program)
+static int show_program(AVTextFormatContext *w, InputFile *ifile, AVProgram *program)
{
AVFormatContext *fmt_ctx = ifile->fmt_ctx;
int i, ret = 0;
- writer_print_section_header(w, NULL, SECTION_ID_PROGRAM);
+ avtext_print_section_header(w, NULL, SECTION_ID_PROGRAM);
print_int("program_id", program->id);
print_int("program_num", program->program_num);
print_int("nb_streams", program->nb_stream_indexes);
@@ -1934,7 +1929,7 @@ static int show_program(WriterContext *w, InputFile *ifile, AVProgram *program)
if (ret < 0)
goto end;
- writer_print_section_header(w, NULL, SECTION_ID_PROGRAM_STREAMS);
+ avtext_print_section_header(w, NULL, SECTION_ID_PROGRAM_STREAMS);
for (i = 0; i < program->nb_stream_indexes; i++) {
if (selected_streams[program->stream_index[i]]) {
ret = show_stream(w, fmt_ctx, program->stream_index[i], &ifile->streams[program->stream_index[i]], IN_PROGRAM);
@@ -1942,19 +1937,19 @@ static int show_program(WriterContext *w, InputFile *ifile, AVProgram *program)
break;
}
}
- writer_print_section_footer(w);
+ avtext_print_section_footer(w);
end:
- writer_print_section_footer(w);
+ avtext_print_section_footer(w);
return ret;
}
-static int show_programs(WriterContext *w, InputFile *ifile)
+static int show_programs(AVTextFormatContext *w, InputFile *ifile)
{
AVFormatContext *fmt_ctx = ifile->fmt_ctx;
int i, ret = 0;
- writer_print_section_header(w, NULL, SECTION_ID_PROGRAMS);
+ avtext_print_section_header(w, NULL, SECTION_ID_PROGRAMS);
for (i = 0; i < fmt_ctx->nb_programs; i++) {
AVProgram *program = fmt_ctx->programs[i];
if (!program)
@@ -1963,14 +1958,14 @@ static int show_programs(WriterContext *w, InputFile *ifile)
if (ret < 0)
break;
}
- writer_print_section_footer(w);
+ avtext_print_section_footer(w);
return ret;
}
-static void print_tile_grid_params(WriterContext *w, const AVStreamGroup *stg,
+static void print_tile_grid_params(AVTextFormatContext *w, const AVStreamGroup *stg,
const AVStreamGroupTileGrid *tile_grid)
{
- writer_print_section_header(w, stg, SECTION_ID_STREAM_GROUP_COMPONENT);
+ avtext_print_section_header(w, stg, SECTION_ID_STREAM_GROUP_COMPONENT);
print_int("nb_tiles", tile_grid->nb_tiles);
print_int("coded_width", tile_grid->coded_width);
print_int("coded_height", tile_grid->coded_height);
@@ -1978,19 +1973,19 @@ static void print_tile_grid_params(WriterContext *w, const AVStreamGroup *stg,
print_int("vertical_offset", tile_grid->vertical_offset);
print_int("width", tile_grid->width);
print_int("height", tile_grid->height);
- writer_print_section_header(w, NULL, SECTION_ID_STREAM_GROUP_SUBCOMPONENTS);
+ avtext_print_section_header(w, NULL, SECTION_ID_STREAM_GROUP_SUBCOMPONENTS);
for (int i = 0; i < tile_grid->nb_tiles; i++) {
- writer_print_section_header(w, "tile_offset", SECTION_ID_STREAM_GROUP_SUBCOMPONENT);
+ avtext_print_section_header(w, "tile_offset", SECTION_ID_STREAM_GROUP_SUBCOMPONENT);
print_int("stream_index", tile_grid->offsets[i].idx);
print_int("tile_horizontal_offset", tile_grid->offsets[i].horizontal);
print_int("tile_vertical_offset", tile_grid->offsets[i].vertical);
- writer_print_section_footer(w);
+ avtext_print_section_footer(w);
}
- writer_print_section_footer(w);
- writer_print_section_footer(w);
+ avtext_print_section_footer(w);
+ avtext_print_section_footer(w);
}
-static void print_iamf_param_definition(WriterContext *w, const char *name,
+static void print_iamf_param_definition(AVTextFormatContext *w, const char *name,
const AVIAMFParamDefinition *param, SectionID section_id)
{
SectionID subsection_id, parameter_section_id;
@@ -1998,7 +1993,7 @@ static void print_iamf_param_definition(WriterContext *w, const char *name,
av_assert0(subsection_id != -1);
parameter_section_id = sections[subsection_id].children_ids[0];
av_assert0(parameter_section_id != -1);
- writer_print_section_header(w, "IAMF Param Definition", section_id);
+ avtext_print_section_header(w, "IAMF Param Definition", section_id);
print_str("name", name);
print_int("nb_subblocks", param->nb_subblocks);
print_int("type", param->type);
@@ -2007,56 +2002,56 @@ static void print_iamf_param_definition(WriterContext *w, const char *name,
print_int("duration", param->duration);
print_int("constant_subblock_duration", param->constant_subblock_duration);
if (param->nb_subblocks > 0)
- writer_print_section_header(w, NULL, subsection_id);
+ avtext_print_section_header(w, NULL, subsection_id);
for (int i = 0; i < param->nb_subblocks; i++) {
const void *subblock = av_iamf_param_definition_get_subblock(param, i);
switch(param->type) {
case AV_IAMF_PARAMETER_DEFINITION_MIX_GAIN: {
const AVIAMFMixGain *mix = subblock;
- writer_print_section_header(w, "IAMF Mix Gain Parameters", parameter_section_id);
+ avtext_print_section_header(w, "IAMF Mix Gain Parameters", parameter_section_id);
print_int("subblock_duration", mix->subblock_duration);
print_int("animation_type", mix->animation_type);
print_q("start_point_value", mix->start_point_value, '/');
print_q("end_point_value", mix->end_point_value, '/');
print_q("control_point_value", mix->control_point_value, '/');
print_q("control_point_relative_time", mix->control_point_relative_time, '/');
- writer_print_section_footer(w); // parameter_section_id
+ avtext_print_section_footer(w); // parameter_section_id
break;
}
case AV_IAMF_PARAMETER_DEFINITION_DEMIXING: {
const AVIAMFDemixingInfo *demix = subblock;
- writer_print_section_header(w, "IAMF Demixing Info", parameter_section_id);
+ avtext_print_section_header(w, "IAMF Demixing Info", parameter_section_id);
print_int("subblock_duration", demix->subblock_duration);
print_int("dmixp_mode", demix->dmixp_mode);
- writer_print_section_footer(w); // parameter_section_id
+ avtext_print_section_footer(w); // parameter_section_id
break;
}
case AV_IAMF_PARAMETER_DEFINITION_RECON_GAIN: {
const AVIAMFReconGain *recon = subblock;
- writer_print_section_header(w, "IAMF Recon Gain", parameter_section_id);
+ avtext_print_section_header(w, "IAMF Recon Gain", parameter_section_id);
print_int("subblock_duration", recon->subblock_duration);
- writer_print_section_footer(w); // parameter_section_id
+ avtext_print_section_footer(w); // parameter_section_id
break;
}
}
}
if (param->nb_subblocks > 0)
- writer_print_section_footer(w); // subsection_id
- writer_print_section_footer(w); // section_id
+ avtext_print_section_footer(w); // subsection_id
+ avtext_print_section_footer(w); // section_id
}
-static void print_iamf_audio_element_params(WriterContext *w, const AVStreamGroup *stg,
+static void print_iamf_audio_element_params(AVTextFormatContext *w, const AVStreamGroup *stg,
const AVIAMFAudioElement *audio_element)
{
- writer_print_section_header(w, stg, SECTION_ID_STREAM_GROUP_COMPONENT);
+ avtext_print_section_header(w, stg, SECTION_ID_STREAM_GROUP_COMPONENT);
print_int("nb_layers", audio_element->nb_layers);
print_int("audio_element_type", audio_element->audio_element_type);
print_int("default_w", audio_element->default_w);
- writer_print_section_header(w, NULL, SECTION_ID_STREAM_GROUP_SUBCOMPONENTS);
+ avtext_print_section_header(w, NULL, SECTION_ID_STREAM_GROUP_SUBCOMPONENTS);
for (int i = 0; i < audio_element->nb_layers; i++) {
const AVIAMFLayer *layer = audio_element->layers[i];
char val_str[128];
- writer_print_section_header(w, "IAMF Audio Layer", SECTION_ID_STREAM_GROUP_SUBCOMPONENT);
+ avtext_print_section_header(w, "IAMF Audio Layer", SECTION_ID_STREAM_GROUP_SUBCOMPONENT);
av_channel_layout_describe(&layer->ch_layout, val_str, sizeof(val_str));
print_str("channel_layout", val_str);
if (audio_element->audio_element_type == AV_IAMF_AUDIO_ELEMENT_TYPE_CHANNEL) {
@@ -2064,7 +2059,7 @@ static void print_iamf_audio_element_params(WriterContext *w, const AVStreamGrou
print_q("output_gain", layer->output_gain, '/');
} else if (audio_element->audio_element_type == AV_IAMF_AUDIO_ELEMENT_TYPE_SCENE)
print_int("ambisonics_mode", layer->ambisonics_mode);
- writer_print_section_footer(w); // SECTION_ID_STREAM_GROUP_SUBCOMPONENT
+ avtext_print_section_footer(w); // SECTION_ID_STREAM_GROUP_SUBCOMPONENT
}
if (audio_element->demixing_info)
print_iamf_param_definition(w, "demixing_info", audio_element->demixing_info,
@@ -2072,36 +2067,36 @@ static void print_iamf_audio_element_params(WriterContext *w, const AVStreamGrou
if (audio_element->recon_gain_info)
print_iamf_param_definition(w, "recon_gain_info", audio_element->recon_gain_info,
SECTION_ID_STREAM_GROUP_SUBCOMPONENT);
- writer_print_section_footer(w); // SECTION_ID_STREAM_GROUP_SUBCOMPONENTS
- writer_print_section_footer(w); // SECTION_ID_STREAM_GROUP_COMPONENT
+ avtext_print_section_footer(w); // SECTION_ID_STREAM_GROUP_SUBCOMPONENTS
+ avtext_print_section_footer(w); // SECTION_ID_STREAM_GROUP_COMPONENT
}
-static void print_iamf_submix_params(WriterContext *w, const AVIAMFSubmix *submix)
+static void print_iamf_submix_params(AVTextFormatContext *w, const AVIAMFSubmix *submix)
{
- writer_print_section_header(w, "IAMF Submix", SECTION_ID_STREAM_GROUP_SUBCOMPONENT);
+ avtext_print_section_header(w, "IAMF Submix", SECTION_ID_STREAM_GROUP_SUBCOMPONENT);
print_int("nb_elements", submix->nb_elements);
print_int("nb_layouts", submix->nb_layouts);
print_q("default_mix_gain", submix->default_mix_gain, '/');
- writer_print_section_header(w, NULL, SECTION_ID_STREAM_GROUP_PIECES);
+ avtext_print_section_header(w, NULL, SECTION_ID_STREAM_GROUP_PIECES);
for (int i = 0; i < submix->nb_elements; i++) {
const AVIAMFSubmixElement *element = submix->elements[i];
- writer_print_section_header(w, "IAMF Submix Element", SECTION_ID_STREAM_GROUP_PIECE);
+ avtext_print_section_header(w, "IAMF Submix Element", SECTION_ID_STREAM_GROUP_PIECE);
print_int("stream_id", element->audio_element_id);
print_q("default_mix_gain", element->default_mix_gain, '/');
print_int("headphones_rendering_mode", element->headphones_rendering_mode);
- writer_print_section_header(w, NULL, SECTION_ID_STREAM_GROUP_SUBPIECES);
+ avtext_print_section_header(w, NULL, SECTION_ID_STREAM_GROUP_SUBPIECES);
if (element->annotations) {
const AVDictionaryEntry *annotation = NULL;
- writer_print_section_header(w, "IAMF Annotations", SECTION_ID_STREAM_GROUP_SUBPIECE);
+ avtext_print_section_header(w, "IAMF Annotations", SECTION_ID_STREAM_GROUP_SUBPIECE);
while (annotation = av_dict_iterate(element->annotations, annotation))
print_str(annotation->key, annotation->value);
- writer_print_section_footer(w); // SECTION_ID_STREAM_GROUP_SUBPIECE
+ avtext_print_section_footer(w); // SECTION_ID_STREAM_GROUP_SUBPIECE
}
if (element->element_mix_config)
print_iamf_param_definition(w, "element_mix_config", element->element_mix_config,
SECTION_ID_STREAM_GROUP_SUBPIECE);
- writer_print_section_footer(w); // SECTION_ID_STREAM_GROUP_SUBPIECES
- writer_print_section_footer(w); // SECTION_ID_STREAM_GROUP_PIECE
+ avtext_print_section_footer(w); // SECTION_ID_STREAM_GROUP_SUBPIECES
+ avtext_print_section_footer(w); // SECTION_ID_STREAM_GROUP_PIECE
}
if (submix->output_mix_config)
print_iamf_param_definition(w, "output_mix_config", submix->output_mix_config,
@@ -2109,7 +2104,7 @@ static void print_iamf_submix_params(WriterContext *w, const AVIAMFSubmix *submi
for (int i = 0; i < submix->nb_layouts; i++) {
const AVIAMFSubmixLayout *layout = submix->layouts[i];
char val_str[128];
- writer_print_section_header(w, "IAMF Submix Layout", SECTION_ID_STREAM_GROUP_PIECE);
+ avtext_print_section_header(w, "IAMF Submix Layout", SECTION_ID_STREAM_GROUP_PIECE);
av_channel_layout_describe(&layout->sound_system, val_str, sizeof(val_str));
print_str("sound_system", val_str);
print_q("integrated_loudness", layout->integrated_loudness, '/');
@@ -2117,51 +2112,51 @@ static void print_iamf_submix_params(WriterContext *w, const AVIAMFSubmix *submi
print_q("true_peak", layout->true_peak, '/');
print_q("dialogue_anchored_loudness", layout->dialogue_anchored_loudness, '/');
print_q("album_anchored_loudness", layout->album_anchored_loudness, '/');
- writer_print_section_footer(w); // SECTION_ID_STREAM_GROUP_PIECE
+ avtext_print_section_footer(w); // SECTION_ID_STREAM_GROUP_PIECE
}
- writer_print_section_footer(w); // SECTION_ID_STREAM_GROUP_PIECES
- writer_print_section_footer(w); // SECTION_ID_STREAM_GROUP_SUBCOMPONENT
+ avtext_print_section_footer(w); // SECTION_ID_STREAM_GROUP_PIECES
+ avtext_print_section_footer(w); // SECTION_ID_STREAM_GROUP_SUBCOMPONENT
}
-static void print_iamf_mix_presentation_params(WriterContext *w, const AVStreamGroup *stg,
+static void print_iamf_mix_presentation_params(AVTextFormatContext *w, const AVStreamGroup *stg,
const AVIAMFMixPresentation *mix_presentation)
{
- writer_print_section_header(w, stg, SECTION_ID_STREAM_GROUP_COMPONENT);
+ avtext_print_section_header(w, stg, SECTION_ID_STREAM_GROUP_COMPONENT);
print_int("nb_submixes", mix_presentation->nb_submixes);
- writer_print_section_header(w, NULL, SECTION_ID_STREAM_GROUP_SUBCOMPONENTS);
+ avtext_print_section_header(w, NULL, SECTION_ID_STREAM_GROUP_SUBCOMPONENTS);
if (mix_presentation->annotations) {
const AVDictionaryEntry *annotation = NULL;
- writer_print_section_header(w, "IAMF Annotations", SECTION_ID_STREAM_GROUP_SUBCOMPONENT);
+ avtext_print_section_header(w, "IAMF Annotations", SECTION_ID_STREAM_GROUP_SUBCOMPONENT);
while (annotation = av_dict_iterate(mix_presentation->annotations, annotation))
print_str(annotation->key, annotation->value);
- writer_print_section_footer(w); // SECTION_ID_STREAM_GROUP_SUBCOMPONENT
+ avtext_print_section_footer(w); // SECTION_ID_STREAM_GROUP_SUBCOMPONENT
}
for (int i = 0; i < mix_presentation->nb_submixes; i++)
print_iamf_submix_params(w, mix_presentation->submixes[i]);
- writer_print_section_footer(w); // SECTION_ID_STREAM_GROUP_SUBCOMPONENTS
- writer_print_section_footer(w); // SECTION_ID_STREAM_GROUP_COMPONENT
+ avtext_print_section_footer(w); // SECTION_ID_STREAM_GROUP_SUBCOMPONENTS
+ avtext_print_section_footer(w); // SECTION_ID_STREAM_GROUP_COMPONENT
}
-static void print_stream_group_params(WriterContext *w, AVStreamGroup *stg)
+static void print_stream_group_params(AVTextFormatContext *w, AVStreamGroup *stg)
{
- writer_print_section_header(w, NULL, SECTION_ID_STREAM_GROUP_COMPONENTS);
+ avtext_print_section_header(w, NULL, SECTION_ID_STREAM_GROUP_COMPONENTS);
if (stg->type == AV_STREAM_GROUP_PARAMS_TILE_GRID)
print_tile_grid_params(w, stg, stg->params.tile_grid);
else if (stg->type == AV_STREAM_GROUP_PARAMS_IAMF_AUDIO_ELEMENT)
print_iamf_audio_element_params(w, stg, stg->params.iamf_audio_element);
else if (stg->type == AV_STREAM_GROUP_PARAMS_IAMF_MIX_PRESENTATION)
print_iamf_mix_presentation_params(w, stg, stg->params.iamf_mix_presentation);
- writer_print_section_footer(w); // SECTION_ID_STREAM_GROUP_COMPONENTS
+ avtext_print_section_footer(w); // SECTION_ID_STREAM_GROUP_COMPONENTS
}
-static int show_stream_group(WriterContext *w, InputFile *ifile, AVStreamGroup *stg)
+static int show_stream_group(AVTextFormatContext *w, InputFile *ifile, AVStreamGroup *stg)
{
AVFormatContext *fmt_ctx = ifile->fmt_ctx;
AVBPrint pbuf;
int i, ret = 0;
av_bprint_init(&pbuf, 1, AV_BPRINT_SIZE_UNLIMITED);
- writer_print_section_header(w, NULL, SECTION_ID_STREAM_GROUP);
+ avtext_print_section_header(w, NULL, SECTION_ID_STREAM_GROUP);
print_int("index", stg->index);
if (fmt_ctx->iformat->flags & AVFMT_SHOW_IDS) print_fmt ("id", "0x%"PRIx64, stg->id);
else print_str_opt("id", "N/A");
@@ -2182,7 +2177,7 @@ static int show_stream_group(WriterContext *w, InputFile *ifile, AVStreamGroup *
if (ret < 0)
goto end;
- writer_print_section_header(w, NULL, SECTION_ID_STREAM_GROUP_STREAMS);
+ avtext_print_section_header(w, NULL, SECTION_ID_STREAM_GROUP_STREAMS);
for (i = 0; i < stg->nb_streams; i++) {
if (selected_streams[stg->streams[i]->index]) {
ret = show_stream(w, fmt_ctx, stg->streams[i]->index, &ifile->streams[stg->streams[i]->index], IN_STREAM_GROUP);
@@ -2190,20 +2185,20 @@ static int show_stream_group(WriterContext *w, InputFile *ifile, AVStreamGroup *
break;
}
}
- writer_print_section_footer(w);
+ avtext_print_section_footer(w);
end:
av_bprint_finalize(&pbuf, NULL);
- writer_print_section_footer(w);
+ avtext_print_section_footer(w);
return ret;
}
-static int show_stream_groups(WriterContext *w, InputFile *ifile)
+static int show_stream_groups(AVTextFormatContext *w, InputFile *ifile)
{
AVFormatContext *fmt_ctx = ifile->fmt_ctx;
int i, ret = 0;
- writer_print_section_header(w, NULL, SECTION_ID_STREAM_GROUPS);
+ avtext_print_section_header(w, NULL, SECTION_ID_STREAM_GROUPS);
for (i = 0; i < fmt_ctx->nb_stream_groups; i++) {
AVStreamGroup *stg = fmt_ctx->stream_groups[i];
@@ -2211,20 +2206,20 @@ static int show_stream_groups(WriterContext *w, InputFile *ifile)
if (ret < 0)
break;
}
- writer_print_section_footer(w);
+ avtext_print_section_footer(w);
return ret;
}
-static int show_chapters(WriterContext *w, InputFile *ifile)
+static int show_chapters(AVTextFormatContext *w, InputFile *ifile)
{
AVFormatContext *fmt_ctx = ifile->fmt_ctx;
int i, ret = 0;
- writer_print_section_header(w, NULL, SECTION_ID_CHAPTERS);
+ avtext_print_section_header(w, NULL, SECTION_ID_CHAPTERS);
for (i = 0; i < fmt_ctx->nb_chapters; i++) {
AVChapter *chapter = fmt_ctx->chapters[i];
- writer_print_section_header(w, NULL, SECTION_ID_CHAPTER);
+ avtext_print_section_header(w, NULL, SECTION_ID_CHAPTER);
print_int("id", chapter->id);
print_q ("time_base", chapter->time_base, '/');
print_int("start", chapter->start);
@@ -2233,20 +2228,20 @@ static int show_chapters(WriterContext *w, InputFile *ifile)
print_time("end_time", chapter->end, &chapter->time_base);
if (do_show_chapter_tags)
ret = show_tags(w, chapter->metadata, SECTION_ID_CHAPTER_TAGS);
- writer_print_section_footer(w);
+ avtext_print_section_footer(w);
}
- writer_print_section_footer(w);
+ avtext_print_section_footer(w);
return ret;
}
-static int show_format(WriterContext *w, InputFile *ifile)
+static int show_format(AVTextFormatContext *w, InputFile *ifile)
{
AVFormatContext *fmt_ctx = ifile->fmt_ctx;
int64_t size = fmt_ctx->pb ? avio_size(fmt_ctx->pb) : -1;
int ret = 0;
- writer_print_section_header(w, NULL, SECTION_ID_FORMAT);
+ avtext_print_section_header(w, NULL, SECTION_ID_FORMAT);
print_str_validate("filename", fmt_ctx->url);
print_int("nb_streams", fmt_ctx->nb_streams);
print_int("nb_programs", fmt_ctx->nb_programs);
@@ -2266,17 +2261,17 @@ static int show_format(WriterContext *w, InputFile *ifile)
if (do_show_format_tags)
ret = show_tags(w, fmt_ctx->metadata, SECTION_ID_FORMAT_TAGS);
- writer_print_section_footer(w);
+ avtext_print_section_footer(w);
fflush(stdout);
return ret;
}
-static void show_error(WriterContext *w, int err)
+static void show_error(AVTextFormatContext *w, int err)
{
- writer_print_section_header(w, NULL, SECTION_ID_ERROR);
+ avtext_print_section_header(w, NULL, SECTION_ID_ERROR);
print_int("code", err);
print_str("string", av_err2str(err));
- writer_print_section_footer(w);
+ avtext_print_section_footer(w);
}
static int open_input_file(InputFile *ifile, const char *filename,
@@ -2418,7 +2413,7 @@ static void close_input_file(InputFile *ifile)
avformat_close_input(&ifile->fmt_ctx);
}
-static int probe_file(WriterContext *tctx, const char *filename,
+static int probe_file(AVTextFormatContext *tctx, const char *filename,
const char *print_filename)
{
InputFile ifile = { 0 };
@@ -2467,10 +2462,10 @@ static int probe_file(WriterContext *tctx, const char *filename,
else // (!do_show_packets && do_show_frames)
section_id = SECTION_ID_FRAMES;
if (do_show_frames || do_show_packets)
- writer_print_section_header(tctx, NULL, section_id);
+ avtext_print_section_header(tctx, NULL, section_id);
ret = read_packets(tctx, &ifile);
if (do_show_frames || do_show_packets)
- writer_print_section_footer(tctx);
+ avtext_print_section_footer(tctx);
CHECK_END;
}
@@ -2516,18 +2511,18 @@ static void show_usage(void)
av_log(NULL, AV_LOG_INFO, "\n");
}
-static void ffprobe_show_program_version(WriterContext *w)
+static void ffprobe_show_program_version(AVTextFormatContext *w)
{
AVBPrint pbuf;
av_bprint_init(&pbuf, 1, AV_BPRINT_SIZE_UNLIMITED);
- writer_print_section_header(w, NULL, SECTION_ID_PROGRAM_VERSION);
+ avtext_print_section_header(w, NULL, SECTION_ID_PROGRAM_VERSION);
print_str("version", FFMPEG_VERSION);
print_fmt("copyright", "Copyright (c) %d-%d the FFmpeg developers",
program_birth_year, CONFIG_THIS_YEAR);
print_str("compiler_ident", CC_IDENT);
print_str("configuration", FFMPEG_CONFIGURATION);
- writer_print_section_footer(w);
+ avtext_print_section_footer(w);
av_bprint_finalize(&pbuf, NULL);
}
@@ -2536,20 +2531,20 @@ static void ffprobe_show_program_version(WriterContext *w)
do { \
if (CONFIG_##LIBNAME) { \
unsigned int version = libname##_version(); \
- writer_print_section_header(w, NULL, SECTION_ID_LIBRARY_VERSION); \
+ avtext_print_section_header(w, NULL, SECTION_ID_LIBRARY_VERSION); \
print_str("name", "lib" #libname); \
print_int("major", LIB##LIBNAME##_VERSION_MAJOR); \
print_int("minor", LIB##LIBNAME##_VERSION_MINOR); \
print_int("micro", LIB##LIBNAME##_VERSION_MICRO); \
print_int("version", version); \
print_str("ident", LIB##LIBNAME##_IDENT); \
- writer_print_section_footer(w); \
+ avtext_print_section_footer(w); \
} \
} while (0)
-static void ffprobe_show_library_versions(WriterContext *w)
+static void ffprobe_show_library_versions(AVTextFormatContext *w)
{
- writer_print_section_header(w, NULL, SECTION_ID_LIBRARY_VERSIONS);
+ avtext_print_section_header(w, NULL, SECTION_ID_LIBRARY_VERSIONS);
SHOW_LIB_VERSION(avutil, AVUTIL);
SHOW_LIB_VERSION(avcodec, AVCODEC);
SHOW_LIB_VERSION(avformat, AVFORMAT);
@@ -2558,7 +2553,7 @@ static void ffprobe_show_library_versions(WriterContext *w)
SHOW_LIB_VERSION(swscale, SWSCALE);
SHOW_LIB_VERSION(swresample, SWRESAMPLE);
SHOW_LIB_VERSION(postproc, POSTPROC);
- writer_print_section_footer(w);
+ avtext_print_section_footer(w);
}
#define PRINT_PIX_FMT_FLAG(flagname, name) \
@@ -2566,14 +2561,14 @@ static void ffprobe_show_library_versions(WriterContext *w)
print_int(name, !!(pixdesc->flags & AV_PIX_FMT_FLAG_##flagname)); \
} while (0)
-static void ffprobe_show_pixel_formats(WriterContext *w)
+static void ffprobe_show_pixel_formats(AVTextFormatContext *w)
{
const AVPixFmtDescriptor *pixdesc = NULL;
int i, n;
- writer_print_section_header(w, NULL, SECTION_ID_PIXEL_FORMATS);
+ avtext_print_section_header(w, NULL, SECTION_ID_PIXEL_FORMATS);
while (pixdesc = av_pix_fmt_desc_next(pixdesc)) {
- writer_print_section_header(w, NULL, SECTION_ID_PIXEL_FORMAT);
+ avtext_print_section_header(w, NULL, SECTION_ID_PIXEL_FORMAT);
print_str("name", pixdesc->name);
print_int("nb_components", pixdesc->nb_components);
if ((pixdesc->nb_components >= 3) && !(pixdesc->flags & AV_PIX_FMT_FLAG_RGB)) {
@@ -2587,7 +2582,7 @@ static void ffprobe_show_pixel_formats(WriterContext *w)
if (n) print_int ("bits_per_pixel", n);
else print_str_opt("bits_per_pixel", "N/A");
if (do_show_pixel_format_flags) {
- writer_print_section_header(w, NULL, SECTION_ID_PIXEL_FORMAT_FLAGS);
+ avtext_print_section_header(w, NULL, SECTION_ID_PIXEL_FORMAT_FLAGS);
PRINT_PIX_FMT_FLAG(BE, "big_endian");
PRINT_PIX_FMT_FLAG(PAL, "palette");
PRINT_PIX_FMT_FLAG(BITSTREAM, "bitstream");
@@ -2595,21 +2590,21 @@ static void ffprobe_show_pixel_formats(WriterContext *w)
PRINT_PIX_FMT_FLAG(PLANAR, "planar");
PRINT_PIX_FMT_FLAG(RGB, "rgb");
PRINT_PIX_FMT_FLAG(ALPHA, "alpha");
- writer_print_section_footer(w);
+ avtext_print_section_footer(w);
}
if (do_show_pixel_format_components && (pixdesc->nb_components > 0)) {
- writer_print_section_header(w, NULL, SECTION_ID_PIXEL_FORMAT_COMPONENTS);
+ avtext_print_section_header(w, NULL, SECTION_ID_PIXEL_FORMAT_COMPONENTS);
for (i = 0; i < pixdesc->nb_components; i++) {
- writer_print_section_header(w, NULL, SECTION_ID_PIXEL_FORMAT_COMPONENT);
+ avtext_print_section_header(w, NULL, SECTION_ID_PIXEL_FORMAT_COMPONENT);
print_int("index", i + 1);
print_int("bit_depth", pixdesc->comp[i].depth);
- writer_print_section_footer(w);
+ avtext_print_section_footer(w);
}
- writer_print_section_footer(w);
+ avtext_print_section_footer(w);
}
- writer_print_section_footer(w);
+ avtext_print_section_footer(w);
}
- writer_print_section_footer(w);
+ avtext_print_section_footer(w);
}
static int opt_show_optional_fields(void *optctx, const char *opt, const char *arg)
@@ -3057,7 +3052,7 @@ static inline int check_section_show_entries(int section_id)
int main(int argc, char **argv)
{
const AVTextFormatter *f;
- WriterContext *tctx;
+ AVTextFormatContext *tctx;
AVTextWriterContext *wctx;
char *buf;
char *f_name = NULL, *f_args = NULL;
@@ -3159,7 +3154,7 @@ int main(int argc, char **argv)
if (f == &avtextformatter_xml)
tctx->string_validation_utf8_flags |= AV_UTF8_FLAG_EXCLUDE_XML_INVALID_CONTROL_CODES;
- writer_print_section_header(tctx, NULL, SECTION_ID_ROOT);
+ avtext_print_section_header(tctx, NULL, SECTION_ID_ROOT);
if (do_show_program_version)
ffprobe_show_program_version(tctx);
--
ffmpeg-codebot
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 108+ messages in thread
* [FFmpeg-devel] [PATCH v9 4/4] fftools/ffprobe: Rename AVTextFormatContext variables (w => tfc)
2025-03-23 3:42 ` [FFmpeg-devel] [PATCH v9 " ffmpegagent
` (2 preceding siblings ...)
2025-03-23 3:42 ` [FFmpeg-devel] [PATCH v9 3/4] fftools/ffprobe: Rename writer_print_section_* and WriterContext softworkz
@ 2025-03-23 3:42 ` softworkz
3 siblings, 0 replies; 108+ messages in thread
From: softworkz @ 2025-03-23 3:42 UTC (permalink / raw)
To: ffmpeg-devel; +Cc: softworkz
From: softworkz <softworkz@hotmail.com>
Signed-off-by: softworkz <softworkz@hotmail.com>
---
fftools/ffprobe.c | 512 +++++++++++++++++++++++-----------------------
1 file changed, 256 insertions(+), 256 deletions(-)
diff --git a/fftools/ffprobe.c b/fftools/ffprobe.c
index 4a90bc4824..9f869b41b3 100644
--- a/fftools/ffprobe.c
+++ b/fftools/ffprobe.c
@@ -407,7 +407,7 @@ static void log_callback(void *ptr, int level, const char *fmt, va_list vl)
#define print_fmt(k, f, ...) do { \
av_bprint_clear(&pbuf); \
av_bprintf(&pbuf, f, __VA_ARGS__); \
- avtext_print_string(w, k, pbuf.str, 0); \
+ avtext_print_string(tfc, k, pbuf.str, 0); \
} while (0)
#define print_list_fmt(k, f, n, m, ...) do { \
@@ -419,19 +419,19 @@ static void log_callback(void *ptr, int level, const char *fmt, va_list vl)
av_bprintf(&pbuf, f, __VA_ARGS__); \
} \
} \
- avtext_print_string(w, k, pbuf.str, 0); \
+ avtext_print_string(tfc, k, pbuf.str, 0); \
} while (0)
-#define print_int(k, v) avtext_print_integer(w, k, v)
-#define print_q(k, v, s) avtext_print_rational(w, k, v, s)
-#define print_str(k, v) avtext_print_string(w, k, v, 0)
-#define print_str_opt(k, v) avtext_print_string(w, k, v, AV_TEXTFORMAT_PRINT_STRING_OPTIONAL)
-#define print_str_validate(k, v) avtext_print_string(w, k, v, AV_TEXTFORMAT_PRINT_STRING_VALIDATE)
-#define print_time(k, v, tb) avtext_print_time(w, k, v, tb, 0)
-#define print_ts(k, v) avtext_print_ts(w, k, v, 0)
-#define print_duration_time(k, v, tb) avtext_print_time(w, k, v, tb, 1)
-#define print_duration_ts(k, v) avtext_print_ts(w, k, v, 1)
-#define print_val(k, v, u) avtext_print_unit_int(w, k, v, u)
+#define print_int(k, v) avtext_print_integer(tfc, k, v)
+#define print_q(k, v, s) avtext_print_rational(tfc, k, v, s)
+#define print_str(k, v) avtext_print_string(tfc, k, v, 0)
+#define print_str_opt(k, v) avtext_print_string(tfc, k, v, AV_TEXTFORMAT_PRINT_STRING_OPTIONAL)
+#define print_str_validate(k, v) avtext_print_string(tfc, k, v, AV_TEXTFORMAT_PRINT_STRING_VALIDATE)
+#define print_time(k, v, tb) avtext_print_time(tfc, k, v, tb, 0)
+#define print_ts(k, v) avtext_print_ts(tfc, k, v, 0)
+#define print_duration_time(k, v, tb) avtext_print_time(tfc, k, v, tb, 1)
+#define print_duration_ts(k, v) avtext_print_ts(tfc, k, v, 1)
+#define print_val(k, v, u) avtext_print_unit_int(tfc, k, v, u)
#define REALLOCZ_ARRAY_STREAM(ptr, cur_n, new_n) \
{ \
@@ -441,25 +441,25 @@ static void log_callback(void *ptr, int level, const char *fmt, va_list vl)
memset( (ptr) + (cur_n), 0, ((new_n) - (cur_n)) * sizeof(*(ptr)) ); \
}
-static inline int show_tags(AVTextFormatContext *w, AVDictionary *tags, int section_id)
+static inline int show_tags(AVTextFormatContext *tfc, AVDictionary *tags, int section_id)
{
const AVDictionaryEntry *tag = NULL;
int ret = 0;
if (!tags)
return 0;
- avtext_print_section_header(w, NULL, section_id);
+ avtext_print_section_header(tfc, NULL, section_id);
while ((tag = av_dict_iterate(tags, tag))) {
if ((ret = print_str_validate(tag->key, tag->value)) < 0)
break;
}
- avtext_print_section_footer(w);
+ avtext_print_section_footer(tfc);
return ret;
}
-static void print_dovi_metadata(AVTextFormatContext *w, const AVDOVIMetadata *dovi)
+static void print_dovi_metadata(AVTextFormatContext *tfc, const AVDOVIMetadata *dovi)
{
if (!dovi)
return;
@@ -514,15 +514,15 @@ static void print_dovi_metadata(AVTextFormatContext *w, const AVDOVIMetadata *do
print_int("num_x_partitions", mapping->num_x_partitions);
print_int("num_y_partitions", mapping->num_y_partitions);
- avtext_print_section_header(w, NULL, SECTION_ID_FRAME_SIDE_DATA_COMPONENT_LIST);
+ avtext_print_section_header(tfc, NULL, SECTION_ID_FRAME_SIDE_DATA_COMPONENT_LIST);
for (int c = 0; c < 3; c++) {
const AVDOVIReshapingCurve *curve = &mapping->curves[c];
- avtext_print_section_header(w, "Reshaping curve", SECTION_ID_FRAME_SIDE_DATA_COMPONENT);
+ avtext_print_section_header(tfc, "Reshaping curve", SECTION_ID_FRAME_SIDE_DATA_COMPONENT);
print_list_fmt("pivots", "%"PRIu16, curve->num_pivots, 1, curve->pivots[idx]);
- avtext_print_section_header(w, NULL, SECTION_ID_FRAME_SIDE_DATA_PIECE_LIST);
+ avtext_print_section_header(tfc, NULL, SECTION_ID_FRAME_SIDE_DATA_PIECE_LIST);
for (int i = 0; i < curve->num_pivots - 1; i++) {
AVBPrint piece_buf;
@@ -540,7 +540,7 @@ static void print_dovi_metadata(AVTextFormatContext *w, const AVDOVIMetadata *do
}
av_bprintf(&piece_buf, " mapping");
- avtext_print_section_header(w, piece_buf.str, SECTION_ID_FRAME_SIDE_DATA_PIECE);
+ avtext_print_section_header(tfc, piece_buf.str, SECTION_ID_FRAME_SIDE_DATA_PIECE);
print_int("mapping_idc", curve->mapping_idc[i]);
switch (curve->mapping_idc[i]) {
case AV_DOVI_MAPPING_POLYNOMIAL:
@@ -564,11 +564,11 @@ static void print_dovi_metadata(AVTextFormatContext *w, const AVDOVIMetadata *do
}
// SECTION_ID_FRAME_SIDE_DATA_PIECE
- avtext_print_section_footer(w);
+ avtext_print_section_footer(tfc);
}
// SECTION_ID_FRAME_SIDE_DATA_PIECE_LIST
- avtext_print_section_footer(w);
+ avtext_print_section_footer(tfc);
if (mapping->nlq_method_idc != AV_DOVI_NLQ_NONE) {
const AVDOVINLQParams *nlq = &mapping->nlq[c];
@@ -584,11 +584,11 @@ static void print_dovi_metadata(AVTextFormatContext *w, const AVDOVIMetadata *do
}
// SECTION_ID_FRAME_SIDE_DATA_COMPONENT
- avtext_print_section_footer(w);
+ avtext_print_section_footer(tfc);
}
// SECTION_ID_FRAME_SIDE_DATA_COMPONENT_LIST
- avtext_print_section_footer(w);
+ avtext_print_section_footer(tfc);
// color metadata
print_int("dm_metadata_id", color->dm_metadata_id);
@@ -621,7 +621,7 @@ static void print_dovi_metadata(AVTextFormatContext *w, const AVDOVIMetadata *do
}
}
-static void print_dynamic_hdr10_plus(AVTextFormatContext *w, const AVDynamicHDRPlus *metadata)
+static void print_dynamic_hdr10_plus(AVTextFormatContext *tfc, const AVDynamicHDRPlus *metadata)
{
if (!metadata)
return;
@@ -720,7 +720,7 @@ static void print_dynamic_hdr10_plus(AVTextFormatContext *w, const AVDynamicHDRP
}
}
-static void print_dynamic_hdr_vivid(AVTextFormatContext *w, const AVDynamicHDRVivid *metadata)
+static void print_dynamic_hdr_vivid(AVTextFormatContext *tfc, const AVDynamicHDRVivid *metadata)
{
if (!metadata)
return;
@@ -790,7 +790,7 @@ static void print_dynamic_hdr_vivid(AVTextFormatContext *w, const AVDynamicHDRVi
}
}
-static void print_ambient_viewing_environment(AVTextFormatContext *w,
+static void print_ambient_viewing_environment(AVTextFormatContext *tfc,
const AVAmbientViewingEnvironment *env)
{
if (!env)
@@ -801,7 +801,7 @@ static void print_ambient_viewing_environment(AVTextFormatContext *w,
print_q("ambient_light_y", env->ambient_light_y, '/');
}
-static void print_film_grain_params(AVTextFormatContext *w,
+static void print_film_grain_params(AVTextFormatContext *tfc,
const AVFilmGrainParams *fgp)
{
const char *color_range, *color_primaries, *color_trc, *color_space;
@@ -847,10 +847,10 @@ static void print_film_grain_params(AVTextFormatContext *w,
print_int("overlap_flag", aom->overlap_flag);
print_int("limit_output_range", aom->limit_output_range);
- avtext_print_section_header(w, NULL, SECTION_ID_FRAME_SIDE_DATA_COMPONENT_LIST);
+ avtext_print_section_header(tfc, NULL, SECTION_ID_FRAME_SIDE_DATA_COMPONENT_LIST);
if (aom->num_y_points) {
- avtext_print_section_header(w, NULL, SECTION_ID_FRAME_SIDE_DATA_COMPONENT);
+ avtext_print_section_header(tfc, NULL, SECTION_ID_FRAME_SIDE_DATA_COMPONENT);
print_int("bit_depth_luma", fgp->bit_depth_luma);
print_list_fmt("y_points_value", "%"PRIu8, aom->num_y_points, 1, aom->y_points[idx][0]);
@@ -858,14 +858,14 @@ static void print_film_grain_params(AVTextFormatContext *w,
print_list_fmt("ar_coeffs_y", "%"PRId8, num_ar_coeffs_y, 1, aom->ar_coeffs_y[idx]);
// SECTION_ID_FRAME_SIDE_DATA_COMPONENT
- avtext_print_section_footer(w);
+ avtext_print_section_footer(tfc);
}
for (int uv = 0; uv < 2; uv++) {
if (!aom->num_uv_points[uv] && !aom->chroma_scaling_from_luma)
continue;
- avtext_print_section_header(w, NULL, SECTION_ID_FRAME_SIDE_DATA_COMPONENT);
+ avtext_print_section_header(tfc, NULL, SECTION_ID_FRAME_SIDE_DATA_COMPONENT);
print_int("bit_depth_chroma", fgp->bit_depth_chroma);
print_list_fmt("uv_points_value", "%"PRIu8, aom->num_uv_points[uv], 1, aom->uv_points[uv][idx][0]);
@@ -876,11 +876,11 @@ static void print_film_grain_params(AVTextFormatContext *w,
print_int("uv_offset", aom->uv_offset[uv]);
// SECTION_ID_FRAME_SIDE_DATA_COMPONENT
- avtext_print_section_footer(w);
+ avtext_print_section_footer(tfc);
}
// SECTION_ID_FRAME_SIDE_DATA_COMPONENT_LIST
- avtext_print_section_footer(w);
+ avtext_print_section_footer(tfc);
break;
}
case AV_FILM_GRAIN_PARAMS_H274: {
@@ -889,36 +889,36 @@ static void print_film_grain_params(AVTextFormatContext *w,
print_int("blending_mode_id", h274->blending_mode_id);
print_int("log2_scale_factor", h274->log2_scale_factor);
- avtext_print_section_header(w, NULL, SECTION_ID_FRAME_SIDE_DATA_COMPONENT_LIST);
+ avtext_print_section_header(tfc, NULL, SECTION_ID_FRAME_SIDE_DATA_COMPONENT_LIST);
for (int c = 0; c < 3; c++) {
if (!h274->component_model_present[c])
continue;
- avtext_print_section_header(w, NULL, SECTION_ID_FRAME_SIDE_DATA_COMPONENT);
+ avtext_print_section_header(tfc, NULL, SECTION_ID_FRAME_SIDE_DATA_COMPONENT);
print_int(c ? "bit_depth_chroma" : "bit_depth_luma", c ? fgp->bit_depth_chroma : fgp->bit_depth_luma);
- avtext_print_section_header(w, NULL, SECTION_ID_FRAME_SIDE_DATA_PIECE_LIST);
+ avtext_print_section_header(tfc, NULL, SECTION_ID_FRAME_SIDE_DATA_PIECE_LIST);
for (int i = 0; i < h274->num_intensity_intervals[c]; i++) {
- avtext_print_section_header(w, NULL, SECTION_ID_FRAME_SIDE_DATA_PIECE);
+ avtext_print_section_header(tfc, NULL, SECTION_ID_FRAME_SIDE_DATA_PIECE);
print_int("intensity_interval_lower_bound", h274->intensity_interval_lower_bound[c][i]);
print_int("intensity_interval_upper_bound", h274->intensity_interval_upper_bound[c][i]);
print_list_fmt("comp_model_value", "%"PRId16, h274->num_model_values[c], 1, h274->comp_model_value[c][i][idx]);
// SECTION_ID_FRAME_SIDE_DATA_PIECE
- avtext_print_section_footer(w);
+ avtext_print_section_footer(tfc);
}
// SECTION_ID_FRAME_SIDE_DATA_PIECE_LIST
- avtext_print_section_footer(w);
+ avtext_print_section_footer(tfc);
// SECTION_ID_FRAME_SIDE_DATA_COMPONENT
- avtext_print_section_footer(w);
+ avtext_print_section_footer(tfc);
}
// SECTION_ID_FRAME_SIDE_DATA_COMPONENT_LIST
- avtext_print_section_footer(w);
+ avtext_print_section_footer(tfc);
break;
}
}
@@ -926,20 +926,20 @@ static void print_film_grain_params(AVTextFormatContext *w,
av_bprint_finalize(&pbuf, NULL);
}
-static void print_pkt_side_data(AVTextFormatContext *w,
+static void print_pkt_side_data(AVTextFormatContext *tfc,
AVCodecParameters *par,
const AVPacketSideData *sd,
SectionID id_data)
{
const char *name = av_packet_side_data_name(sd->type);
- avtext_print_section_header(w, sd, id_data);
+ avtext_print_section_header(tfc, sd, id_data);
print_str("side_data_type", name ? name : "unknown");
if (sd->type == AV_PKT_DATA_DISPLAYMATRIX && sd->size >= 9*4) {
double rotation = av_display_rotation_get((int32_t *)sd->data);
if (isnan(rotation))
rotation = 0;
- avtext_print_integers(w, "displaymatrix", sd->data, 9, " %11d", 3, 4, 1);
+ avtext_print_integers(tfc, "displaymatrix", sd->data, 9, " %11d", 3, 4, 1);
print_int("rotation", rotation);
} else if (sd->type == AV_PKT_DATA_STEREO3D) {
const AVStereo3D *stereo = (AVStereo3D *)sd->data;
@@ -998,10 +998,10 @@ static void print_pkt_side_data(AVTextFormatContext *w,
print_int("max_average", metadata->MaxFALL);
} else if (sd->type == AV_PKT_DATA_AMBIENT_VIEWING_ENVIRONMENT) {
print_ambient_viewing_environment(
- w, (const AVAmbientViewingEnvironment *)sd->data);
+ tfc, (const AVAmbientViewingEnvironment *)sd->data);
} else if (sd->type == AV_PKT_DATA_DYNAMIC_HDR10_PLUS) {
AVDynamicHDRPlus *metadata = (AVDynamicHDRPlus *)sd->data;
- print_dynamic_hdr10_plus(w, metadata);
+ print_dynamic_hdr10_plus(tfc, metadata);
} else if (sd->type == AV_PKT_DATA_DOVI_CONF) {
AVDOVIDecoderConfigurationRecord *dovi = (AVDOVIDecoderConfigurationRecord *)sd->data;
const char *comp = "unknown";
@@ -1036,8 +1036,8 @@ static void print_pkt_side_data(AVTextFormatContext *w,
} else if (sd->type == AV_PKT_DATA_WEBVTT_IDENTIFIER ||
sd->type == AV_PKT_DATA_WEBVTT_SETTINGS) {
if (do_show_data)
- avtext_print_data(w, "data", sd->data, sd->size);
- avtext_print_data_hash(w, "data_hash", sd->data, sd->size);
+ avtext_print_data(tfc, "data", sd->data, sd->size);
+ avtext_print_data_hash(tfc, "data_hash", sd->data, sd->size);
} else if (sd->type == AV_PKT_DATA_FRAME_CROPPING && sd->size >= sizeof(uint32_t) * 4) {
print_int("crop_top", AV_RL32(sd->data));
print_int("crop_bottom", AV_RL32(sd->data + 4));
@@ -1048,7 +1048,7 @@ static void print_pkt_side_data(AVTextFormatContext *w,
}
}
-static void print_private_data(AVTextFormatContext *w, void *priv_data)
+static void print_private_data(AVTextFormatContext *tfc, void *priv_data)
{
const AVOption *opt = NULL;
while (opt = av_opt_next(priv_data, opt)) {
@@ -1061,7 +1061,7 @@ static void print_private_data(AVTextFormatContext *w, void *priv_data)
}
}
-static void print_color_range(AVTextFormatContext *w, enum AVColorRange color_range)
+static void print_color_range(AVTextFormatContext *tfc, enum AVColorRange color_range)
{
const char *val = av_color_range_name(color_range);
if (!val || color_range == AVCOL_RANGE_UNSPECIFIED) {
@@ -1071,7 +1071,7 @@ static void print_color_range(AVTextFormatContext *w, enum AVColorRange color_ra
}
}
-static void print_color_space(AVTextFormatContext *w, enum AVColorSpace color_space)
+static void print_color_space(AVTextFormatContext *tfc, enum AVColorSpace color_space)
{
const char *val = av_color_space_name(color_space);
if (!val || color_space == AVCOL_SPC_UNSPECIFIED) {
@@ -1081,7 +1081,7 @@ static void print_color_space(AVTextFormatContext *w, enum AVColorSpace color_sp
}
}
-static void print_primaries(AVTextFormatContext *w, enum AVColorPrimaries color_primaries)
+static void print_primaries(AVTextFormatContext *tfc, enum AVColorPrimaries color_primaries)
{
const char *val = av_color_primaries_name(color_primaries);
if (!val || color_primaries == AVCOL_PRI_UNSPECIFIED) {
@@ -1091,7 +1091,7 @@ static void print_primaries(AVTextFormatContext *w, enum AVColorPrimaries color_
}
}
-static void print_color_trc(AVTextFormatContext *w, enum AVColorTransferCharacteristic color_trc)
+static void print_color_trc(AVTextFormatContext *tfc, enum AVColorTransferCharacteristic color_trc)
{
const char *val = av_color_transfer_name(color_trc);
if (!val || color_trc == AVCOL_TRC_UNSPECIFIED) {
@@ -1101,7 +1101,7 @@ static void print_color_trc(AVTextFormatContext *w, enum AVColorTransferCharacte
}
}
-static void print_chroma_location(AVTextFormatContext *w, enum AVChromaLocation chroma_location)
+static void print_chroma_location(AVTextFormatContext *tfc, enum AVChromaLocation chroma_location)
{
const char *val = av_chroma_location_name(chroma_location);
if (!val || chroma_location == AVCHROMA_LOC_UNSPECIFIED) {
@@ -1127,7 +1127,7 @@ static void clear_log(int need_lock)
ff_mutex_unlock(&log_mutex);
}
-static int show_log(AVTextFormatContext *w, int section_ids, int section_id, int log_level)
+static int show_log(AVTextFormatContext *tfc, int section_ids, int section_id, int log_level)
{
int i;
ff_mutex_lock(&log_mutex);
@@ -1135,11 +1135,11 @@ static int show_log(AVTextFormatContext *w, int section_ids, int section_id, int
ff_mutex_unlock(&log_mutex);
return 0;
}
- avtext_print_section_header(w, NULL, section_ids);
+ avtext_print_section_header(tfc, NULL, section_ids);
for (i=0; i<log_buffer_size; i++) {
if (log_buffer[i].log_level <= log_level) {
- avtext_print_section_header(w, NULL, section_id);
+ avtext_print_section_header(tfc, NULL, section_id);
print_str("context", log_buffer[i].context_name);
print_int("level", log_buffer[i].log_level);
print_int("category", log_buffer[i].category);
@@ -1151,18 +1151,18 @@ static int show_log(AVTextFormatContext *w, int section_ids, int section_id, int
print_str_opt("parent_category", "N/A");
}
print_str("message", log_buffer[i].log_message);
- avtext_print_section_footer(w);
+ avtext_print_section_footer(tfc);
}
}
clear_log(0);
ff_mutex_unlock(&log_mutex);
- avtext_print_section_footer(w);
+ avtext_print_section_footer(tfc);
return 0;
}
-static void show_packet(AVTextFormatContext *w, InputFile *ifile, AVPacket *pkt, int packet_idx)
+static void show_packet(AVTextFormatContext *tfc, InputFile *ifile, AVPacket *pkt, int packet_idx)
{
AVStream *st = ifile->streams[pkt->stream_index].st;
AVBPrint pbuf;
@@ -1170,7 +1170,7 @@ static void show_packet(AVTextFormatContext *w, InputFile *ifile, AVPacket *pkt,
av_bprint_init(&pbuf, 1, AV_BPRINT_SIZE_UNLIMITED);
- avtext_print_section_header(w, NULL, SECTION_ID_PACKET);
+ avtext_print_section_header(tfc, NULL, SECTION_ID_PACKET);
s = av_get_media_type_string(st->codecpar->codec_type);
if (s) print_str ("codec_type", s);
@@ -1189,8 +1189,8 @@ static void show_packet(AVTextFormatContext *w, InputFile *ifile, AVPacket *pkt,
pkt->flags & AV_PKT_FLAG_DISCARD ? 'D' : '_',
pkt->flags & AV_PKT_FLAG_CORRUPT ? 'C' : '_');
if (do_show_data)
- avtext_print_data(w, "data", pkt->data, pkt->size);
- avtext_print_data_hash(w, "data_hash", pkt->data, pkt->size);
+ avtext_print_data(tfc, "data", pkt->data, pkt->size);
+ avtext_print_data_hash(tfc, "data_hash", pkt->data, pkt->size);
if (pkt->side_data_elems) {
size_t size;
@@ -1200,33 +1200,33 @@ static void show_packet(AVTextFormatContext *w, InputFile *ifile, AVPacket *pkt,
if (side_metadata && size && do_show_packet_tags) {
AVDictionary *dict = NULL;
if (av_packet_unpack_dictionary(side_metadata, size, &dict) >= 0)
- show_tags(w, dict, SECTION_ID_PACKET_TAGS);
+ show_tags(tfc, dict, SECTION_ID_PACKET_TAGS);
av_dict_free(&dict);
}
- avtext_print_section_header(w, NULL, SECTION_ID_PACKET_SIDE_DATA_LIST);
+ avtext_print_section_header(tfc, NULL, SECTION_ID_PACKET_SIDE_DATA_LIST);
for (int i = 0; i < pkt->side_data_elems; i++) {
- print_pkt_side_data(w, st->codecpar, &pkt->side_data[i],
+ print_pkt_side_data(tfc, st->codecpar, &pkt->side_data[i],
SECTION_ID_PACKET_SIDE_DATA);
- avtext_print_section_footer(w);
+ avtext_print_section_footer(tfc);
}
- avtext_print_section_footer(w);
+ avtext_print_section_footer(tfc);
}
- avtext_print_section_footer(w);
+ avtext_print_section_footer(tfc);
av_bprint_finalize(&pbuf, NULL);
fflush(stdout);
}
-static void show_subtitle(AVTextFormatContext *w, AVSubtitle *sub, AVStream *stream,
+static void show_subtitle(AVTextFormatContext *tfc, AVSubtitle *sub, AVStream *stream,
AVFormatContext *fmt_ctx)
{
AVBPrint pbuf;
av_bprint_init(&pbuf, 1, AV_BPRINT_SIZE_UNLIMITED);
- avtext_print_section_header(w, NULL, SECTION_ID_SUBTITLE);
+ avtext_print_section_header(tfc, NULL, SECTION_ID_SUBTITLE);
print_str ("media_type", "subtitle");
print_ts ("pts", sub->pts);
@@ -1236,30 +1236,30 @@ static void show_subtitle(AVTextFormatContext *w, AVSubtitle *sub, AVStream *str
print_int ("end_display_time", sub->end_display_time);
print_int ("num_rects", sub->num_rects);
- avtext_print_section_footer(w);
+ avtext_print_section_footer(tfc);
av_bprint_finalize(&pbuf, NULL);
fflush(stdout);
}
-static void print_frame_side_data(AVTextFormatContext *w,
+static void print_frame_side_data(AVTextFormatContext *tfc,
const AVFrame *frame,
const AVStream *stream)
{
- avtext_print_section_header(w, NULL, SECTION_ID_FRAME_SIDE_DATA_LIST);
+ avtext_print_section_header(tfc, NULL, SECTION_ID_FRAME_SIDE_DATA_LIST);
for (int i = 0; i < frame->nb_side_data; i++) {
const AVFrameSideData *sd = frame->side_data[i];
const char *name;
- avtext_print_section_header(w, sd, SECTION_ID_FRAME_SIDE_DATA);
+ avtext_print_section_header(tfc, sd, SECTION_ID_FRAME_SIDE_DATA);
name = av_frame_side_data_name(sd->type);
print_str("side_data_type", name ? name : "unknown");
if (sd->type == AV_FRAME_DATA_DISPLAYMATRIX && sd->size >= 9*4) {
double rotation = av_display_rotation_get((int32_t *)sd->data);
if (isnan(rotation))
rotation = 0;
- avtext_print_integers(w, "displaymatrix", sd->data, 9, " %11d", 3, 4, 1);
+ avtext_print_integers(tfc, "displaymatrix", sd->data, 9, " %11d", 3, 4, 1);
print_int("rotation", rotation);
} else if (sd->type == AV_FRAME_DATA_AFD && sd->size > 0) {
print_int("active_format", *sd->data);
@@ -1270,15 +1270,15 @@ static void print_frame_side_data(AVTextFormatContext *w,
} else if (sd->type == AV_FRAME_DATA_S12M_TIMECODE && sd->size == 16) {
uint32_t *tc = (uint32_t*)sd->data;
int m = FFMIN(tc[0],3);
- avtext_print_section_header(w, NULL, SECTION_ID_FRAME_SIDE_DATA_TIMECODE_LIST);
+ avtext_print_section_header(tfc, NULL, SECTION_ID_FRAME_SIDE_DATA_TIMECODE_LIST);
for (int j = 1; j <= m ; j++) {
char tcbuf[AV_TIMECODE_STR_SIZE];
av_timecode_make_smpte_tc_string2(tcbuf, stream->avg_frame_rate, tc[j], 0, 0);
- avtext_print_section_header(w, NULL, SECTION_ID_FRAME_SIDE_DATA_TIMECODE);
+ avtext_print_section_header(tfc, NULL, SECTION_ID_FRAME_SIDE_DATA_TIMECODE);
print_str("value", tcbuf);
- avtext_print_section_footer(w);
+ avtext_print_section_footer(tfc);
}
- avtext_print_section_footer(w);
+ avtext_print_section_footer(tfc);
} else if (sd->type == AV_FRAME_DATA_MASTERING_DISPLAY_METADATA) {
AVMasteringDisplayMetadata *metadata = (AVMasteringDisplayMetadata *)sd->data;
@@ -1300,7 +1300,7 @@ static void print_frame_side_data(AVTextFormatContext *w,
}
} else if (sd->type == AV_FRAME_DATA_DYNAMIC_HDR_PLUS) {
AVDynamicHDRPlus *metadata = (AVDynamicHDRPlus *)sd->data;
- print_dynamic_hdr10_plus(w, metadata);
+ print_dynamic_hdr10_plus(tfc, metadata);
} else if (sd->type == AV_FRAME_DATA_CONTENT_LIGHT_LEVEL) {
AVContentLightMetadata *metadata = (AVContentLightMetadata *)sd->data;
print_int("max_content", metadata->MaxCLL);
@@ -1311,24 +1311,24 @@ static void print_frame_side_data(AVTextFormatContext *w,
print_str(tag->key, tag->value);
print_int("size", sd->size);
} else if (sd->type == AV_FRAME_DATA_DOVI_METADATA) {
- print_dovi_metadata(w, (const AVDOVIMetadata *)sd->data);
+ print_dovi_metadata(tfc, (const AVDOVIMetadata *)sd->data);
} else if (sd->type == AV_FRAME_DATA_DYNAMIC_HDR_VIVID) {
AVDynamicHDRVivid *metadata = (AVDynamicHDRVivid *)sd->data;
- print_dynamic_hdr_vivid(w, metadata);
+ print_dynamic_hdr_vivid(tfc, metadata);
} else if (sd->type == AV_FRAME_DATA_AMBIENT_VIEWING_ENVIRONMENT) {
- print_ambient_viewing_environment(w, (const AVAmbientViewingEnvironment *)sd->data);
+ print_ambient_viewing_environment(tfc, (const AVAmbientViewingEnvironment *)sd->data);
} else if (sd->type == AV_FRAME_DATA_FILM_GRAIN_PARAMS) {
AVFilmGrainParams *fgp = (AVFilmGrainParams *)sd->data;
- print_film_grain_params(w, fgp);
+ print_film_grain_params(tfc, fgp);
} else if (sd->type == AV_FRAME_DATA_VIEW_ID) {
print_int("view_id", *(int*)sd->data);
}
- avtext_print_section_footer(w);
+ avtext_print_section_footer(tfc);
}
- avtext_print_section_footer(w);
+ avtext_print_section_footer(tfc);
}
-static void show_frame(AVTextFormatContext *w, AVFrame *frame, AVStream *stream,
+static void show_frame(AVTextFormatContext *tfc, AVFrame *frame, AVStream *stream,
AVFormatContext *fmt_ctx)
{
FrameData *fd = frame->opaque_ref ? (FrameData*)frame->opaque_ref->data : NULL;
@@ -1338,7 +1338,7 @@ static void show_frame(AVTextFormatContext *w, AVFrame *frame, AVStream *stream,
av_bprint_init(&pbuf, 1, AV_BPRINT_SIZE_UNLIMITED);
- avtext_print_section_header(w, NULL, SECTION_ID_FRAME);
+ avtext_print_section_header(tfc, NULL, SECTION_ID_FRAME);
s = av_get_media_type_string(stream->codecpar->codec_type);
if (s) print_str ("media_type", s);
@@ -1383,11 +1383,11 @@ static void show_frame(AVTextFormatContext *w, AVFrame *frame, AVStream *stream,
print_int("lossless", !!(frame->flags & AV_FRAME_FLAG_LOSSLESS));
print_int("repeat_pict", frame->repeat_pict);
- print_color_range(w, frame->color_range);
- print_color_space(w, frame->colorspace);
- print_primaries(w, frame->color_primaries);
- print_color_trc(w, frame->color_trc);
- print_chroma_location(w, frame->chroma_location);
+ print_color_range(tfc, frame->color_range);
+ print_color_space(tfc, frame->colorspace);
+ print_primaries(tfc, frame->color_primaries);
+ print_color_trc(tfc, frame->color_trc);
+ print_chroma_location(tfc, frame->chroma_location);
break;
case AVMEDIA_TYPE_AUDIO:
@@ -1404,19 +1404,19 @@ static void show_frame(AVTextFormatContext *w, AVFrame *frame, AVStream *stream,
break;
}
if (do_show_frame_tags)
- show_tags(w, frame->metadata, SECTION_ID_FRAME_TAGS);
+ show_tags(tfc, frame->metadata, SECTION_ID_FRAME_TAGS);
if (do_show_log)
- show_log(w, SECTION_ID_FRAME_LOGS, SECTION_ID_FRAME_LOG, do_show_log);
+ show_log(tfc, SECTION_ID_FRAME_LOGS, SECTION_ID_FRAME_LOG, do_show_log);
if (frame->nb_side_data)
- print_frame_side_data(w, frame, stream);
+ print_frame_side_data(tfc, frame, stream);
- avtext_print_section_footer(w);
+ avtext_print_section_footer(tfc);
av_bprint_finalize(&pbuf, NULL);
fflush(stdout);
}
-static av_always_inline int process_frame(AVTextFormatContext *w,
+static av_always_inline int process_frame(AVTextFormatContext *tfc,
InputFile *ifile,
AVFrame *frame, const AVPacket *pkt,
int *packet_new)
@@ -1470,9 +1470,9 @@ static av_always_inline int process_frame(AVTextFormatContext *w,
nb_streams_frames[pkt->stream_index]++;
if (do_show_frames)
if (is_sub)
- show_subtitle(w, &sub, ifile->streams[pkt->stream_index].st, fmt_ctx);
+ show_subtitle(tfc, &sub, ifile->streams[pkt->stream_index].st, fmt_ctx);
else
- show_frame(w, frame, ifile->streams[pkt->stream_index].st, fmt_ctx);
+ show_frame(tfc, frame, ifile->streams[pkt->stream_index].st, fmt_ctx);
if (!is_sub && do_analyze_frames) {
for (int i = 0; i < frame->nb_side_data; i++) {
@@ -1513,7 +1513,7 @@ static void log_read_interval(const ReadInterval *interval, void *log_ctx, int l
av_log(log_ctx, log_level, "\n");
}
-static int read_interval_packets(AVTextFormatContext *w, InputFile *ifile,
+static int read_interval_packets(AVTextFormatContext *tfc, InputFile *ifile,
const ReadInterval *interval, int64_t *cur_ts)
{
AVFormatContext *fmt_ctx = ifile->fmt_ctx;
@@ -1596,7 +1596,7 @@ static int read_interval_packets(AVTextFormatContext *w, InputFile *ifile,
frame_count++;
if (do_read_packets) {
if (do_show_packets)
- show_packet(w, ifile, pkt, i++);
+ show_packet(tfc, ifile, pkt, i++);
nb_streams_packets[pkt->stream_index]++;
}
if (do_read_frames) {
@@ -1612,7 +1612,7 @@ static int read_interval_packets(AVTextFormatContext *w, InputFile *ifile,
fd->pkt_pos = pkt->pos;
fd->pkt_size = pkt->size;
- while (process_frame(w, ifile, frame, pkt, &packet_new) > 0);
+ while (process_frame(tfc, ifile, frame, pkt, &packet_new) > 0);
}
}
av_packet_unref(pkt);
@@ -1622,7 +1622,7 @@ static int read_interval_packets(AVTextFormatContext *w, InputFile *ifile,
for (i = 0; i < ifile->nb_streams; i++) {
pkt->stream_index = i;
if (do_read_frames) {
- while (process_frame(w, ifile, frame, pkt, &(int){1}) > 0);
+ while (process_frame(tfc, ifile, frame, pkt, &(int){1}) > 0);
if (ifile->streams[i].dec_ctx)
avcodec_flush_buffers(ifile->streams[i].dec_ctx);
}
@@ -1638,7 +1638,7 @@ end:
return ret;
}
-static int read_packets(AVTextFormatContext *w, InputFile *ifile)
+static int read_packets(AVTextFormatContext *tfc, InputFile *ifile)
{
AVFormatContext *fmt_ctx = ifile->fmt_ctx;
int i, ret = 0;
@@ -1646,10 +1646,10 @@ static int read_packets(AVTextFormatContext *w, InputFile *ifile)
if (read_intervals_nb == 0) {
ReadInterval interval = (ReadInterval) { .has_start = 0, .has_end = 0 };
- ret = read_interval_packets(w, ifile, &interval, &cur_ts);
+ ret = read_interval_packets(tfc, ifile, &interval, &cur_ts);
} else {
for (i = 0; i < read_intervals_nb; i++) {
- ret = read_interval_packets(w, ifile, &read_intervals[i], &cur_ts);
+ ret = read_interval_packets(tfc, ifile, &read_intervals[i], &cur_ts);
if (ret < 0)
break;
}
@@ -1658,22 +1658,22 @@ static int read_packets(AVTextFormatContext *w, InputFile *ifile)
return ret;
}
-static void print_dispositions(AVTextFormatContext *w, uint32_t disposition, SectionID section_id)
+static void print_dispositions(AVTextFormatContext *tfc, uint32_t disposition, SectionID section_id)
{
- avtext_print_section_header(w, NULL, section_id);
+ avtext_print_section_header(tfc, NULL, section_id);
for (int i = 0; i < sizeof(disposition) * CHAR_BIT; i++) {
const char *disposition_str = av_disposition_to_string(1U << i);
if (disposition_str)
print_int(disposition_str, !!(disposition & (1U << i)));
}
- avtext_print_section_footer(w);
+ avtext_print_section_footer(tfc);
}
#define IN_PROGRAM 1
#define IN_STREAM_GROUP 2
-static int show_stream(AVTextFormatContext *w, AVFormatContext *fmt_ctx, int stream_idx, InputStream *ist, int container)
+static int show_stream(AVTextFormatContext *tfc, AVFormatContext *fmt_ctx, int stream_idx, InputStream *ist, int container)
{
AVStream *stream = ist->st;
AVCodecParameters *par;
@@ -1705,7 +1705,7 @@ static int show_stream(AVTextFormatContext *w, AVFormatContext *fmt_ctx, int str
av_bprint_init(&pbuf, 1, AV_BPRINT_SIZE_UNLIMITED);
- avtext_print_section_header(w, NULL, section_header[container]);
+ avtext_print_section_header(tfc, NULL, section_header[container]);
print_int("index", stream->index);
@@ -1774,11 +1774,11 @@ static int show_stream(AVTextFormatContext *w, AVFormatContext *fmt_ctx, int str
else print_str_opt("pix_fmt", "unknown");
print_int("level", par->level);
- print_color_range(w, par->color_range);
- print_color_space(w, par->color_space);
- print_color_trc(w, par->color_trc);
- print_primaries(w, par->color_primaries);
- print_chroma_location(w, par->chroma_location);
+ print_color_range(tfc, par->color_range);
+ print_color_space(tfc, par->color_space);
+ print_color_trc(tfc, par->color_trc);
+ print_primaries(tfc, par->color_primaries);
+ print_chroma_location(tfc, par->chroma_location);
if (par->field_order == AV_FIELD_PROGRESSIVE)
print_str("field_order", "progressive");
@@ -1830,9 +1830,9 @@ static int show_stream(AVTextFormatContext *w, AVFormatContext *fmt_ctx, int str
if (show_private_data) {
if (dec_ctx && dec_ctx->codec->priv_class)
- print_private_data(w, dec_ctx->priv_data);
+ print_private_data(tfc, dec_ctx->priv_data);
if (fmt_ctx->iformat->priv_class)
- print_private_data(w, fmt_ctx->priv_data);
+ print_private_data(tfc, fmt_ctx->priv_data);
}
if (fmt_ctx->iformat->flags & AVFMT_SHOW_IDS) print_fmt ("id", "0x%x", stream->id);
@@ -1859,113 +1859,113 @@ static int show_stream(AVTextFormatContext *w, AVFormatContext *fmt_ctx, int str
if (nb_streams_packets[stream_idx]) print_fmt ("nb_read_packets", "%"PRIu64, nb_streams_packets[stream_idx]);
else print_str_opt("nb_read_packets", "N/A");
if (do_show_data)
- avtext_print_data(w, "extradata", par->extradata,
+ avtext_print_data(tfc, "extradata", par->extradata,
par->extradata_size);
if (par->extradata_size > 0) {
print_int("extradata_size", par->extradata_size);
- avtext_print_data_hash(w, "extradata_hash", par->extradata,
+ avtext_print_data_hash(tfc, "extradata_hash", par->extradata,
par->extradata_size);
}
/* Print disposition information */
if (do_show_stream_disposition) {
av_assert0(container < FF_ARRAY_ELEMS(section_disposition));
- print_dispositions(w, stream->disposition, section_disposition[container]);
+ print_dispositions(tfc, stream->disposition, section_disposition[container]);
}
if (do_show_stream_tags) {
av_assert0(container < FF_ARRAY_ELEMS(section_tags));
- ret = show_tags(w, stream->metadata, section_tags[container]);
+ ret = show_tags(tfc, stream->metadata, section_tags[container]);
}
if (stream->codecpar->nb_coded_side_data) {
- avtext_print_section_header(w, NULL, SECTION_ID_STREAM_SIDE_DATA_LIST);
+ avtext_print_section_header(tfc, NULL, SECTION_ID_STREAM_SIDE_DATA_LIST);
for (int i = 0; i < stream->codecpar->nb_coded_side_data; i++) {
- print_pkt_side_data(w, stream->codecpar, &stream->codecpar->coded_side_data[i],
+ print_pkt_side_data(tfc, stream->codecpar, &stream->codecpar->coded_side_data[i],
SECTION_ID_STREAM_SIDE_DATA);
- avtext_print_section_footer(w);
+ avtext_print_section_footer(tfc);
}
- avtext_print_section_footer(w);
+ avtext_print_section_footer(tfc);
}
- avtext_print_section_footer(w);
+ avtext_print_section_footer(tfc);
av_bprint_finalize(&pbuf, NULL);
fflush(stdout);
return ret;
}
-static int show_streams(AVTextFormatContext *w, InputFile *ifile)
+static int show_streams(AVTextFormatContext *tfc, InputFile *ifile)
{
AVFormatContext *fmt_ctx = ifile->fmt_ctx;
int i, ret = 0;
- avtext_print_section_header(w, NULL, SECTION_ID_STREAMS);
+ avtext_print_section_header(tfc, NULL, SECTION_ID_STREAMS);
for (i = 0; i < ifile->nb_streams; i++)
if (selected_streams[i]) {
- ret = show_stream(w, fmt_ctx, i, &ifile->streams[i], 0);
+ ret = show_stream(tfc, fmt_ctx, i, &ifile->streams[i], 0);
if (ret < 0)
break;
}
- avtext_print_section_footer(w);
+ avtext_print_section_footer(tfc);
return ret;
}
-static int show_program(AVTextFormatContext *w, InputFile *ifile, AVProgram *program)
+static int show_program(AVTextFormatContext *tfc, InputFile *ifile, AVProgram *program)
{
AVFormatContext *fmt_ctx = ifile->fmt_ctx;
int i, ret = 0;
- avtext_print_section_header(w, NULL, SECTION_ID_PROGRAM);
+ avtext_print_section_header(tfc, NULL, SECTION_ID_PROGRAM);
print_int("program_id", program->id);
print_int("program_num", program->program_num);
print_int("nb_streams", program->nb_stream_indexes);
print_int("pmt_pid", program->pmt_pid);
print_int("pcr_pid", program->pcr_pid);
if (do_show_program_tags)
- ret = show_tags(w, program->metadata, SECTION_ID_PROGRAM_TAGS);
+ ret = show_tags(tfc, program->metadata, SECTION_ID_PROGRAM_TAGS);
if (ret < 0)
goto end;
- avtext_print_section_header(w, NULL, SECTION_ID_PROGRAM_STREAMS);
+ avtext_print_section_header(tfc, NULL, SECTION_ID_PROGRAM_STREAMS);
for (i = 0; i < program->nb_stream_indexes; i++) {
if (selected_streams[program->stream_index[i]]) {
- ret = show_stream(w, fmt_ctx, program->stream_index[i], &ifile->streams[program->stream_index[i]], IN_PROGRAM);
+ ret = show_stream(tfc, fmt_ctx, program->stream_index[i], &ifile->streams[program->stream_index[i]], IN_PROGRAM);
if (ret < 0)
break;
}
}
- avtext_print_section_footer(w);
+ avtext_print_section_footer(tfc);
end:
- avtext_print_section_footer(w);
+ avtext_print_section_footer(tfc);
return ret;
}
-static int show_programs(AVTextFormatContext *w, InputFile *ifile)
+static int show_programs(AVTextFormatContext *tfc, InputFile *ifile)
{
AVFormatContext *fmt_ctx = ifile->fmt_ctx;
int i, ret = 0;
- avtext_print_section_header(w, NULL, SECTION_ID_PROGRAMS);
+ avtext_print_section_header(tfc, NULL, SECTION_ID_PROGRAMS);
for (i = 0; i < fmt_ctx->nb_programs; i++) {
AVProgram *program = fmt_ctx->programs[i];
if (!program)
continue;
- ret = show_program(w, ifile, program);
+ ret = show_program(tfc, ifile, program);
if (ret < 0)
break;
}
- avtext_print_section_footer(w);
+ avtext_print_section_footer(tfc);
return ret;
}
-static void print_tile_grid_params(AVTextFormatContext *w, const AVStreamGroup *stg,
+static void print_tile_grid_params(AVTextFormatContext *tfc, const AVStreamGroup *stg,
const AVStreamGroupTileGrid *tile_grid)
{
- avtext_print_section_header(w, stg, SECTION_ID_STREAM_GROUP_COMPONENT);
+ avtext_print_section_header(tfc, stg, SECTION_ID_STREAM_GROUP_COMPONENT);
print_int("nb_tiles", tile_grid->nb_tiles);
print_int("coded_width", tile_grid->coded_width);
print_int("coded_height", tile_grid->coded_height);
@@ -1973,19 +1973,19 @@ static void print_tile_grid_params(AVTextFormatContext *w, const AVStreamGroup *
print_int("vertical_offset", tile_grid->vertical_offset);
print_int("width", tile_grid->width);
print_int("height", tile_grid->height);
- avtext_print_section_header(w, NULL, SECTION_ID_STREAM_GROUP_SUBCOMPONENTS);
+ avtext_print_section_header(tfc, NULL, SECTION_ID_STREAM_GROUP_SUBCOMPONENTS);
for (int i = 0; i < tile_grid->nb_tiles; i++) {
- avtext_print_section_header(w, "tile_offset", SECTION_ID_STREAM_GROUP_SUBCOMPONENT);
+ avtext_print_section_header(tfc, "tile_offset", SECTION_ID_STREAM_GROUP_SUBCOMPONENT);
print_int("stream_index", tile_grid->offsets[i].idx);
print_int("tile_horizontal_offset", tile_grid->offsets[i].horizontal);
print_int("tile_vertical_offset", tile_grid->offsets[i].vertical);
- avtext_print_section_footer(w);
+ avtext_print_section_footer(tfc);
}
- avtext_print_section_footer(w);
- avtext_print_section_footer(w);
+ avtext_print_section_footer(tfc);
+ avtext_print_section_footer(tfc);
}
-static void print_iamf_param_definition(AVTextFormatContext *w, const char *name,
+static void print_iamf_param_definition(AVTextFormatContext *tfc, const char *name,
const AVIAMFParamDefinition *param, SectionID section_id)
{
SectionID subsection_id, parameter_section_id;
@@ -1993,7 +1993,7 @@ static void print_iamf_param_definition(AVTextFormatContext *w, const char *name
av_assert0(subsection_id != -1);
parameter_section_id = sections[subsection_id].children_ids[0];
av_assert0(parameter_section_id != -1);
- avtext_print_section_header(w, "IAMF Param Definition", section_id);
+ avtext_print_section_header(tfc, "IAMF Param Definition", section_id);
print_str("name", name);
print_int("nb_subblocks", param->nb_subblocks);
print_int("type", param->type);
@@ -2002,56 +2002,56 @@ static void print_iamf_param_definition(AVTextFormatContext *w, const char *name
print_int("duration", param->duration);
print_int("constant_subblock_duration", param->constant_subblock_duration);
if (param->nb_subblocks > 0)
- avtext_print_section_header(w, NULL, subsection_id);
+ avtext_print_section_header(tfc, NULL, subsection_id);
for (int i = 0; i < param->nb_subblocks; i++) {
const void *subblock = av_iamf_param_definition_get_subblock(param, i);
switch(param->type) {
case AV_IAMF_PARAMETER_DEFINITION_MIX_GAIN: {
const AVIAMFMixGain *mix = subblock;
- avtext_print_section_header(w, "IAMF Mix Gain Parameters", parameter_section_id);
+ avtext_print_section_header(tfc, "IAMF Mix Gain Parameters", parameter_section_id);
print_int("subblock_duration", mix->subblock_duration);
print_int("animation_type", mix->animation_type);
print_q("start_point_value", mix->start_point_value, '/');
print_q("end_point_value", mix->end_point_value, '/');
print_q("control_point_value", mix->control_point_value, '/');
print_q("control_point_relative_time", mix->control_point_relative_time, '/');
- avtext_print_section_footer(w); // parameter_section_id
+ avtext_print_section_footer(tfc); // parameter_section_id
break;
}
case AV_IAMF_PARAMETER_DEFINITION_DEMIXING: {
const AVIAMFDemixingInfo *demix = subblock;
- avtext_print_section_header(w, "IAMF Demixing Info", parameter_section_id);
+ avtext_print_section_header(tfc, "IAMF Demixing Info", parameter_section_id);
print_int("subblock_duration", demix->subblock_duration);
print_int("dmixp_mode", demix->dmixp_mode);
- avtext_print_section_footer(w); // parameter_section_id
+ avtext_print_section_footer(tfc); // parameter_section_id
break;
}
case AV_IAMF_PARAMETER_DEFINITION_RECON_GAIN: {
const AVIAMFReconGain *recon = subblock;
- avtext_print_section_header(w, "IAMF Recon Gain", parameter_section_id);
+ avtext_print_section_header(tfc, "IAMF Recon Gain", parameter_section_id);
print_int("subblock_duration", recon->subblock_duration);
- avtext_print_section_footer(w); // parameter_section_id
+ avtext_print_section_footer(tfc); // parameter_section_id
break;
}
}
}
if (param->nb_subblocks > 0)
- avtext_print_section_footer(w); // subsection_id
- avtext_print_section_footer(w); // section_id
+ avtext_print_section_footer(tfc); // subsection_id
+ avtext_print_section_footer(tfc); // section_id
}
-static void print_iamf_audio_element_params(AVTextFormatContext *w, const AVStreamGroup *stg,
+static void print_iamf_audio_element_params(AVTextFormatContext *tfc, const AVStreamGroup *stg,
const AVIAMFAudioElement *audio_element)
{
- avtext_print_section_header(w, stg, SECTION_ID_STREAM_GROUP_COMPONENT);
+ avtext_print_section_header(tfc, stg, SECTION_ID_STREAM_GROUP_COMPONENT);
print_int("nb_layers", audio_element->nb_layers);
print_int("audio_element_type", audio_element->audio_element_type);
print_int("default_w", audio_element->default_w);
- avtext_print_section_header(w, NULL, SECTION_ID_STREAM_GROUP_SUBCOMPONENTS);
+ avtext_print_section_header(tfc, NULL, SECTION_ID_STREAM_GROUP_SUBCOMPONENTS);
for (int i = 0; i < audio_element->nb_layers; i++) {
const AVIAMFLayer *layer = audio_element->layers[i];
char val_str[128];
- avtext_print_section_header(w, "IAMF Audio Layer", SECTION_ID_STREAM_GROUP_SUBCOMPONENT);
+ avtext_print_section_header(tfc, "IAMF Audio Layer", SECTION_ID_STREAM_GROUP_SUBCOMPONENT);
av_channel_layout_describe(&layer->ch_layout, val_str, sizeof(val_str));
print_str("channel_layout", val_str);
if (audio_element->audio_element_type == AV_IAMF_AUDIO_ELEMENT_TYPE_CHANNEL) {
@@ -2059,52 +2059,52 @@ static void print_iamf_audio_element_params(AVTextFormatContext *w, const AVStre
print_q("output_gain", layer->output_gain, '/');
} else if (audio_element->audio_element_type == AV_IAMF_AUDIO_ELEMENT_TYPE_SCENE)
print_int("ambisonics_mode", layer->ambisonics_mode);
- avtext_print_section_footer(w); // SECTION_ID_STREAM_GROUP_SUBCOMPONENT
+ avtext_print_section_footer(tfc); // SECTION_ID_STREAM_GROUP_SUBCOMPONENT
}
if (audio_element->demixing_info)
- print_iamf_param_definition(w, "demixing_info", audio_element->demixing_info,
+ print_iamf_param_definition(tfc, "demixing_info", audio_element->demixing_info,
SECTION_ID_STREAM_GROUP_SUBCOMPONENT);
if (audio_element->recon_gain_info)
- print_iamf_param_definition(w, "recon_gain_info", audio_element->recon_gain_info,
+ print_iamf_param_definition(tfc, "recon_gain_info", audio_element->recon_gain_info,
SECTION_ID_STREAM_GROUP_SUBCOMPONENT);
- avtext_print_section_footer(w); // SECTION_ID_STREAM_GROUP_SUBCOMPONENTS
- avtext_print_section_footer(w); // SECTION_ID_STREAM_GROUP_COMPONENT
+ avtext_print_section_footer(tfc); // SECTION_ID_STREAM_GROUP_SUBCOMPONENTS
+ avtext_print_section_footer(tfc); // SECTION_ID_STREAM_GROUP_COMPONENT
}
-static void print_iamf_submix_params(AVTextFormatContext *w, const AVIAMFSubmix *submix)
+static void print_iamf_submix_params(AVTextFormatContext *tfc, const AVIAMFSubmix *submix)
{
- avtext_print_section_header(w, "IAMF Submix", SECTION_ID_STREAM_GROUP_SUBCOMPONENT);
+ avtext_print_section_header(tfc, "IAMF Submix", SECTION_ID_STREAM_GROUP_SUBCOMPONENT);
print_int("nb_elements", submix->nb_elements);
print_int("nb_layouts", submix->nb_layouts);
print_q("default_mix_gain", submix->default_mix_gain, '/');
- avtext_print_section_header(w, NULL, SECTION_ID_STREAM_GROUP_PIECES);
+ avtext_print_section_header(tfc, NULL, SECTION_ID_STREAM_GROUP_PIECES);
for (int i = 0; i < submix->nb_elements; i++) {
const AVIAMFSubmixElement *element = submix->elements[i];
- avtext_print_section_header(w, "IAMF Submix Element", SECTION_ID_STREAM_GROUP_PIECE);
+ avtext_print_section_header(tfc, "IAMF Submix Element", SECTION_ID_STREAM_GROUP_PIECE);
print_int("stream_id", element->audio_element_id);
print_q("default_mix_gain", element->default_mix_gain, '/');
print_int("headphones_rendering_mode", element->headphones_rendering_mode);
- avtext_print_section_header(w, NULL, SECTION_ID_STREAM_GROUP_SUBPIECES);
+ avtext_print_section_header(tfc, NULL, SECTION_ID_STREAM_GROUP_SUBPIECES);
if (element->annotations) {
const AVDictionaryEntry *annotation = NULL;
- avtext_print_section_header(w, "IAMF Annotations", SECTION_ID_STREAM_GROUP_SUBPIECE);
+ avtext_print_section_header(tfc, "IAMF Annotations", SECTION_ID_STREAM_GROUP_SUBPIECE);
while (annotation = av_dict_iterate(element->annotations, annotation))
print_str(annotation->key, annotation->value);
- avtext_print_section_footer(w); // SECTION_ID_STREAM_GROUP_SUBPIECE
+ avtext_print_section_footer(tfc); // SECTION_ID_STREAM_GROUP_SUBPIECE
}
if (element->element_mix_config)
- print_iamf_param_definition(w, "element_mix_config", element->element_mix_config,
+ print_iamf_param_definition(tfc, "element_mix_config", element->element_mix_config,
SECTION_ID_STREAM_GROUP_SUBPIECE);
- avtext_print_section_footer(w); // SECTION_ID_STREAM_GROUP_SUBPIECES
- avtext_print_section_footer(w); // SECTION_ID_STREAM_GROUP_PIECE
+ avtext_print_section_footer(tfc); // SECTION_ID_STREAM_GROUP_SUBPIECES
+ avtext_print_section_footer(tfc); // SECTION_ID_STREAM_GROUP_PIECE
}
if (submix->output_mix_config)
- print_iamf_param_definition(w, "output_mix_config", submix->output_mix_config,
+ print_iamf_param_definition(tfc, "output_mix_config", submix->output_mix_config,
SECTION_ID_STREAM_GROUP_PIECE);
for (int i = 0; i < submix->nb_layouts; i++) {
const AVIAMFSubmixLayout *layout = submix->layouts[i];
char val_str[128];
- avtext_print_section_header(w, "IAMF Submix Layout", SECTION_ID_STREAM_GROUP_PIECE);
+ avtext_print_section_header(tfc, "IAMF Submix Layout", SECTION_ID_STREAM_GROUP_PIECE);
av_channel_layout_describe(&layout->sound_system, val_str, sizeof(val_str));
print_str("sound_system", val_str);
print_q("integrated_loudness", layout->integrated_loudness, '/');
@@ -2112,51 +2112,51 @@ static void print_iamf_submix_params(AVTextFormatContext *w, const AVIAMFSubmix
print_q("true_peak", layout->true_peak, '/');
print_q("dialogue_anchored_loudness", layout->dialogue_anchored_loudness, '/');
print_q("album_anchored_loudness", layout->album_anchored_loudness, '/');
- avtext_print_section_footer(w); // SECTION_ID_STREAM_GROUP_PIECE
+ avtext_print_section_footer(tfc); // SECTION_ID_STREAM_GROUP_PIECE
}
- avtext_print_section_footer(w); // SECTION_ID_STREAM_GROUP_PIECES
- avtext_print_section_footer(w); // SECTION_ID_STREAM_GROUP_SUBCOMPONENT
+ avtext_print_section_footer(tfc); // SECTION_ID_STREAM_GROUP_PIECES
+ avtext_print_section_footer(tfc); // SECTION_ID_STREAM_GROUP_SUBCOMPONENT
}
-static void print_iamf_mix_presentation_params(AVTextFormatContext *w, const AVStreamGroup *stg,
+static void print_iamf_mix_presentation_params(AVTextFormatContext *tfc, const AVStreamGroup *stg,
const AVIAMFMixPresentation *mix_presentation)
{
- avtext_print_section_header(w, stg, SECTION_ID_STREAM_GROUP_COMPONENT);
+ avtext_print_section_header(tfc, stg, SECTION_ID_STREAM_GROUP_COMPONENT);
print_int("nb_submixes", mix_presentation->nb_submixes);
- avtext_print_section_header(w, NULL, SECTION_ID_STREAM_GROUP_SUBCOMPONENTS);
+ avtext_print_section_header(tfc, NULL, SECTION_ID_STREAM_GROUP_SUBCOMPONENTS);
if (mix_presentation->annotations) {
const AVDictionaryEntry *annotation = NULL;
- avtext_print_section_header(w, "IAMF Annotations", SECTION_ID_STREAM_GROUP_SUBCOMPONENT);
+ avtext_print_section_header(tfc, "IAMF Annotations", SECTION_ID_STREAM_GROUP_SUBCOMPONENT);
while (annotation = av_dict_iterate(mix_presentation->annotations, annotation))
print_str(annotation->key, annotation->value);
- avtext_print_section_footer(w); // SECTION_ID_STREAM_GROUP_SUBCOMPONENT
+ avtext_print_section_footer(tfc); // SECTION_ID_STREAM_GROUP_SUBCOMPONENT
}
for (int i = 0; i < mix_presentation->nb_submixes; i++)
- print_iamf_submix_params(w, mix_presentation->submixes[i]);
- avtext_print_section_footer(w); // SECTION_ID_STREAM_GROUP_SUBCOMPONENTS
- avtext_print_section_footer(w); // SECTION_ID_STREAM_GROUP_COMPONENT
+ print_iamf_submix_params(tfc, mix_presentation->submixes[i]);
+ avtext_print_section_footer(tfc); // SECTION_ID_STREAM_GROUP_SUBCOMPONENTS
+ avtext_print_section_footer(tfc); // SECTION_ID_STREAM_GROUP_COMPONENT
}
-static void print_stream_group_params(AVTextFormatContext *w, AVStreamGroup *stg)
+static void print_stream_group_params(AVTextFormatContext *tfc, AVStreamGroup *stg)
{
- avtext_print_section_header(w, NULL, SECTION_ID_STREAM_GROUP_COMPONENTS);
+ avtext_print_section_header(tfc, NULL, SECTION_ID_STREAM_GROUP_COMPONENTS);
if (stg->type == AV_STREAM_GROUP_PARAMS_TILE_GRID)
- print_tile_grid_params(w, stg, stg->params.tile_grid);
+ print_tile_grid_params(tfc, stg, stg->params.tile_grid);
else if (stg->type == AV_STREAM_GROUP_PARAMS_IAMF_AUDIO_ELEMENT)
- print_iamf_audio_element_params(w, stg, stg->params.iamf_audio_element);
+ print_iamf_audio_element_params(tfc, stg, stg->params.iamf_audio_element);
else if (stg->type == AV_STREAM_GROUP_PARAMS_IAMF_MIX_PRESENTATION)
- print_iamf_mix_presentation_params(w, stg, stg->params.iamf_mix_presentation);
- avtext_print_section_footer(w); // SECTION_ID_STREAM_GROUP_COMPONENTS
+ print_iamf_mix_presentation_params(tfc, stg, stg->params.iamf_mix_presentation);
+ avtext_print_section_footer(tfc); // SECTION_ID_STREAM_GROUP_COMPONENTS
}
-static int show_stream_group(AVTextFormatContext *w, InputFile *ifile, AVStreamGroup *stg)
+static int show_stream_group(AVTextFormatContext *tfc, InputFile *ifile, AVStreamGroup *stg)
{
AVFormatContext *fmt_ctx = ifile->fmt_ctx;
AVBPrint pbuf;
int i, ret = 0;
av_bprint_init(&pbuf, 1, AV_BPRINT_SIZE_UNLIMITED);
- avtext_print_section_header(w, NULL, SECTION_ID_STREAM_GROUP);
+ avtext_print_section_header(tfc, NULL, SECTION_ID_STREAM_GROUP);
print_int("index", stg->index);
if (fmt_ctx->iformat->flags & AVFMT_SHOW_IDS) print_fmt ("id", "0x%"PRIx64, stg->id);
else print_str_opt("id", "N/A");
@@ -2166,60 +2166,60 @@ static int show_stream_group(AVTextFormatContext *w, InputFile *ifile, AVStreamG
else
print_str_opt("type", "unknown");
if (do_show_stream_group_components)
- print_stream_group_params(w, stg);
+ print_stream_group_params(tfc, stg);
/* Print disposition information */
if (do_show_stream_group_disposition)
- print_dispositions(w, stg->disposition, SECTION_ID_STREAM_GROUP_DISPOSITION);
+ print_dispositions(tfc, stg->disposition, SECTION_ID_STREAM_GROUP_DISPOSITION);
if (do_show_stream_group_tags)
- ret = show_tags(w, stg->metadata, SECTION_ID_STREAM_GROUP_TAGS);
+ ret = show_tags(tfc, stg->metadata, SECTION_ID_STREAM_GROUP_TAGS);
if (ret < 0)
goto end;
- avtext_print_section_header(w, NULL, SECTION_ID_STREAM_GROUP_STREAMS);
+ avtext_print_section_header(tfc, NULL, SECTION_ID_STREAM_GROUP_STREAMS);
for (i = 0; i < stg->nb_streams; i++) {
if (selected_streams[stg->streams[i]->index]) {
- ret = show_stream(w, fmt_ctx, stg->streams[i]->index, &ifile->streams[stg->streams[i]->index], IN_STREAM_GROUP);
+ ret = show_stream(tfc, fmt_ctx, stg->streams[i]->index, &ifile->streams[stg->streams[i]->index], IN_STREAM_GROUP);
if (ret < 0)
break;
}
}
- avtext_print_section_footer(w);
+ avtext_print_section_footer(tfc);
end:
av_bprint_finalize(&pbuf, NULL);
- avtext_print_section_footer(w);
+ avtext_print_section_footer(tfc);
return ret;
}
-static int show_stream_groups(AVTextFormatContext *w, InputFile *ifile)
+static int show_stream_groups(AVTextFormatContext *tfc, InputFile *ifile)
{
AVFormatContext *fmt_ctx = ifile->fmt_ctx;
int i, ret = 0;
- avtext_print_section_header(w, NULL, SECTION_ID_STREAM_GROUPS);
+ avtext_print_section_header(tfc, NULL, SECTION_ID_STREAM_GROUPS);
for (i = 0; i < fmt_ctx->nb_stream_groups; i++) {
AVStreamGroup *stg = fmt_ctx->stream_groups[i];
- ret = show_stream_group(w, ifile, stg);
+ ret = show_stream_group(tfc, ifile, stg);
if (ret < 0)
break;
}
- avtext_print_section_footer(w);
+ avtext_print_section_footer(tfc);
return ret;
}
-static int show_chapters(AVTextFormatContext *w, InputFile *ifile)
+static int show_chapters(AVTextFormatContext *tfc, InputFile *ifile)
{
AVFormatContext *fmt_ctx = ifile->fmt_ctx;
int i, ret = 0;
- avtext_print_section_header(w, NULL, SECTION_ID_CHAPTERS);
+ avtext_print_section_header(tfc, NULL, SECTION_ID_CHAPTERS);
for (i = 0; i < fmt_ctx->nb_chapters; i++) {
AVChapter *chapter = fmt_ctx->chapters[i];
- avtext_print_section_header(w, NULL, SECTION_ID_CHAPTER);
+ avtext_print_section_header(tfc, NULL, SECTION_ID_CHAPTER);
print_int("id", chapter->id);
print_q ("time_base", chapter->time_base, '/');
print_int("start", chapter->start);
@@ -2227,21 +2227,21 @@ static int show_chapters(AVTextFormatContext *w, InputFile *ifile)
print_int("end", chapter->end);
print_time("end_time", chapter->end, &chapter->time_base);
if (do_show_chapter_tags)
- ret = show_tags(w, chapter->metadata, SECTION_ID_CHAPTER_TAGS);
- avtext_print_section_footer(w);
+ ret = show_tags(tfc, chapter->metadata, SECTION_ID_CHAPTER_TAGS);
+ avtext_print_section_footer(tfc);
}
- avtext_print_section_footer(w);
+ avtext_print_section_footer(tfc);
return ret;
}
-static int show_format(AVTextFormatContext *w, InputFile *ifile)
+static int show_format(AVTextFormatContext *tfc, InputFile *ifile)
{
AVFormatContext *fmt_ctx = ifile->fmt_ctx;
int64_t size = fmt_ctx->pb ? avio_size(fmt_ctx->pb) : -1;
int ret = 0;
- avtext_print_section_header(w, NULL, SECTION_ID_FORMAT);
+ avtext_print_section_header(tfc, NULL, SECTION_ID_FORMAT);
print_str_validate("filename", fmt_ctx->url);
print_int("nb_streams", fmt_ctx->nb_streams);
print_int("nb_programs", fmt_ctx->nb_programs);
@@ -2259,19 +2259,19 @@ static int show_format(AVTextFormatContext *w, InputFile *ifile)
else print_str_opt("bit_rate", "N/A");
print_int("probe_score", fmt_ctx->probe_score);
if (do_show_format_tags)
- ret = show_tags(w, fmt_ctx->metadata, SECTION_ID_FORMAT_TAGS);
+ ret = show_tags(tfc, fmt_ctx->metadata, SECTION_ID_FORMAT_TAGS);
- avtext_print_section_footer(w);
+ avtext_print_section_footer(tfc);
fflush(stdout);
return ret;
}
-static void show_error(AVTextFormatContext *w, int err)
+static void show_error(AVTextFormatContext *tfc, int err)
{
- avtext_print_section_header(w, NULL, SECTION_ID_ERROR);
+ avtext_print_section_header(tfc, NULL, SECTION_ID_ERROR);
print_int("code", err);
print_str("string", av_err2str(err));
- avtext_print_section_footer(w);
+ avtext_print_section_footer(tfc);
}
static int open_input_file(InputFile *ifile, const char *filename,
@@ -2413,7 +2413,7 @@ static void close_input_file(InputFile *ifile)
avformat_close_input(&ifile->fmt_ctx);
}
-static int probe_file(AVTextFormatContext *tctx, const char *filename,
+static int probe_file(AVTextFormatContext *tfc, const char *filename,
const char *print_filename)
{
InputFile ifile = { 0 };
@@ -2455,40 +2455,40 @@ static int probe_file(AVTextFormatContext *tctx, const char *filename,
if (do_read_frames || do_read_packets) {
if (do_show_frames && do_show_packets &&
- tctx->formatter->flags & AV_TEXTFORMAT_FLAG_SUPPORTS_MIXED_ARRAY_CONTENT)
+ tfc->formatter->flags & AV_TEXTFORMAT_FLAG_SUPPORTS_MIXED_ARRAY_CONTENT)
section_id = SECTION_ID_PACKETS_AND_FRAMES;
else if (do_show_packets && !do_show_frames)
section_id = SECTION_ID_PACKETS;
else // (!do_show_packets && do_show_frames)
section_id = SECTION_ID_FRAMES;
if (do_show_frames || do_show_packets)
- avtext_print_section_header(tctx, NULL, section_id);
- ret = read_packets(tctx, &ifile);
+ avtext_print_section_header(tfc, NULL, section_id);
+ ret = read_packets(tfc, &ifile);
if (do_show_frames || do_show_packets)
- avtext_print_section_footer(tctx);
+ avtext_print_section_footer(tfc);
CHECK_END;
}
if (do_show_programs) {
- ret = show_programs(tctx, &ifile);
+ ret = show_programs(tfc, &ifile);
CHECK_END;
}
if (do_show_stream_groups) {
- ret = show_stream_groups(tctx, &ifile);
+ ret = show_stream_groups(tfc, &ifile);
CHECK_END;
}
if (do_show_streams) {
- ret = show_streams(tctx, &ifile);
+ ret = show_streams(tfc, &ifile);
CHECK_END;
}
if (do_show_chapters) {
- ret = show_chapters(tctx, &ifile);
+ ret = show_chapters(tfc, &ifile);
CHECK_END;
}
if (do_show_format) {
- ret = show_format(tctx, &ifile);
+ ret = show_format(tfc, &ifile);
CHECK_END;
}
@@ -2511,18 +2511,18 @@ static void show_usage(void)
av_log(NULL, AV_LOG_INFO, "\n");
}
-static void ffprobe_show_program_version(AVTextFormatContext *w)
+static void ffprobe_show_program_version(AVTextFormatContext *tfc)
{
AVBPrint pbuf;
av_bprint_init(&pbuf, 1, AV_BPRINT_SIZE_UNLIMITED);
- avtext_print_section_header(w, NULL, SECTION_ID_PROGRAM_VERSION);
+ avtext_print_section_header(tfc, NULL, SECTION_ID_PROGRAM_VERSION);
print_str("version", FFMPEG_VERSION);
print_fmt("copyright", "Copyright (c) %d-%d the FFmpeg developers",
program_birth_year, CONFIG_THIS_YEAR);
print_str("compiler_ident", CC_IDENT);
print_str("configuration", FFMPEG_CONFIGURATION);
- avtext_print_section_footer(w);
+ avtext_print_section_footer(tfc);
av_bprint_finalize(&pbuf, NULL);
}
@@ -2531,20 +2531,20 @@ static void ffprobe_show_program_version(AVTextFormatContext *w)
do { \
if (CONFIG_##LIBNAME) { \
unsigned int version = libname##_version(); \
- avtext_print_section_header(w, NULL, SECTION_ID_LIBRARY_VERSION); \
+ avtext_print_section_header(tfc, NULL, SECTION_ID_LIBRARY_VERSION); \
print_str("name", "lib" #libname); \
print_int("major", LIB##LIBNAME##_VERSION_MAJOR); \
print_int("minor", LIB##LIBNAME##_VERSION_MINOR); \
print_int("micro", LIB##LIBNAME##_VERSION_MICRO); \
print_int("version", version); \
print_str("ident", LIB##LIBNAME##_IDENT); \
- avtext_print_section_footer(w); \
+ avtext_print_section_footer(tfc); \
} \
} while (0)
-static void ffprobe_show_library_versions(AVTextFormatContext *w)
+static void ffprobe_show_library_versions(AVTextFormatContext *tfc)
{
- avtext_print_section_header(w, NULL, SECTION_ID_LIBRARY_VERSIONS);
+ avtext_print_section_header(tfc, NULL, SECTION_ID_LIBRARY_VERSIONS);
SHOW_LIB_VERSION(avutil, AVUTIL);
SHOW_LIB_VERSION(avcodec, AVCODEC);
SHOW_LIB_VERSION(avformat, AVFORMAT);
@@ -2553,7 +2553,7 @@ static void ffprobe_show_library_versions(AVTextFormatContext *w)
SHOW_LIB_VERSION(swscale, SWSCALE);
SHOW_LIB_VERSION(swresample, SWRESAMPLE);
SHOW_LIB_VERSION(postproc, POSTPROC);
- avtext_print_section_footer(w);
+ avtext_print_section_footer(tfc);
}
#define PRINT_PIX_FMT_FLAG(flagname, name) \
@@ -2561,14 +2561,14 @@ static void ffprobe_show_library_versions(AVTextFormatContext *w)
print_int(name, !!(pixdesc->flags & AV_PIX_FMT_FLAG_##flagname)); \
} while (0)
-static void ffprobe_show_pixel_formats(AVTextFormatContext *w)
+static void ffprobe_show_pixel_formats(AVTextFormatContext *tfc)
{
const AVPixFmtDescriptor *pixdesc = NULL;
int i, n;
- avtext_print_section_header(w, NULL, SECTION_ID_PIXEL_FORMATS);
+ avtext_print_section_header(tfc, NULL, SECTION_ID_PIXEL_FORMATS);
while (pixdesc = av_pix_fmt_desc_next(pixdesc)) {
- avtext_print_section_header(w, NULL, SECTION_ID_PIXEL_FORMAT);
+ avtext_print_section_header(tfc, NULL, SECTION_ID_PIXEL_FORMAT);
print_str("name", pixdesc->name);
print_int("nb_components", pixdesc->nb_components);
if ((pixdesc->nb_components >= 3) && !(pixdesc->flags & AV_PIX_FMT_FLAG_RGB)) {
@@ -2582,7 +2582,7 @@ static void ffprobe_show_pixel_formats(AVTextFormatContext *w)
if (n) print_int ("bits_per_pixel", n);
else print_str_opt("bits_per_pixel", "N/A");
if (do_show_pixel_format_flags) {
- avtext_print_section_header(w, NULL, SECTION_ID_PIXEL_FORMAT_FLAGS);
+ avtext_print_section_header(tfc, NULL, SECTION_ID_PIXEL_FORMAT_FLAGS);
PRINT_PIX_FMT_FLAG(BE, "big_endian");
PRINT_PIX_FMT_FLAG(PAL, "palette");
PRINT_PIX_FMT_FLAG(BITSTREAM, "bitstream");
@@ -2590,21 +2590,21 @@ static void ffprobe_show_pixel_formats(AVTextFormatContext *w)
PRINT_PIX_FMT_FLAG(PLANAR, "planar");
PRINT_PIX_FMT_FLAG(RGB, "rgb");
PRINT_PIX_FMT_FLAG(ALPHA, "alpha");
- avtext_print_section_footer(w);
+ avtext_print_section_footer(tfc);
}
if (do_show_pixel_format_components && (pixdesc->nb_components > 0)) {
- avtext_print_section_header(w, NULL, SECTION_ID_PIXEL_FORMAT_COMPONENTS);
+ avtext_print_section_header(tfc, NULL, SECTION_ID_PIXEL_FORMAT_COMPONENTS);
for (i = 0; i < pixdesc->nb_components; i++) {
- avtext_print_section_header(w, NULL, SECTION_ID_PIXEL_FORMAT_COMPONENT);
+ avtext_print_section_header(tfc, NULL, SECTION_ID_PIXEL_FORMAT_COMPONENT);
print_int("index", i + 1);
print_int("bit_depth", pixdesc->comp[i].depth);
- avtext_print_section_footer(w);
+ avtext_print_section_footer(tfc);
}
- avtext_print_section_footer(w);
+ avtext_print_section_footer(tfc);
}
- avtext_print_section_footer(w);
+ avtext_print_section_footer(tfc);
}
- avtext_print_section_footer(w);
+ avtext_print_section_footer(tfc);
}
static int opt_show_optional_fields(void *optctx, const char *opt, const char *arg)
--
ffmpeg-codebot
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 108+ messages in thread