[FFmpeg-devel] [PATCH 8/8] ffprobe/avtextformat: Split out text writers as independent classes
softworkz
ffmpegagent at gmail.com
Thu Feb 27 16:01:40 EET 2025
From: softworkz <softworkz at hotmail.com>
Signed-off-by: softworkz <softworkz at hotmail.com>
---
fftools/ffprobe.c | 20 +++-
libavutil/Makefile | 4 +
libavutil/avtextformat.h | 13 +--
libavutil/avtextwriters.h | 68 +++++++++++++
libavutil/textformat/avtextformat.c | 145 ++++++++++++++++------------
libavutil/textformat/tf_compact.c | 6 +-
libavutil/textformat/tf_default.c | 6 +-
libavutil/textformat/tf_flat.c | 6 +-
libavutil/textformat/tf_ini.c | 6 +-
libavutil/textformat/tf_json.c | 6 +-
libavutil/textformat/tf_xml.c | 6 +-
libavutil/textformat/tw_avio.c | 129 +++++++++++++++++++++++++
libavutil/textformat/tw_buffer.c | 91 +++++++++++++++++
libavutil/textformat/tw_stdout.c | 82 ++++++++++++++++
14 files changed, 499 insertions(+), 89 deletions(-)
create mode 100644 libavutil/avtextwriters.h
create mode 100644 libavutil/textformat/tw_avio.c
create mode 100644 libavutil/textformat/tw_buffer.c
create mode 100644 libavutil/textformat/tw_stdout.c
diff --git a/fftools/ffprobe.c b/fftools/ffprobe.c
index 28d499ac80..5ab1299442 100644
--- a/fftools/ffprobe.c
+++ b/fftools/ffprobe.c
@@ -3103,6 +3103,7 @@ int main(int argc, char **argv)
{
const AVTextFormatter *f;
AVTextFormatContext *tctx;
+ AVTextWriterContext *wctx;
char *buf;
char *f_name = NULL, *f_args = NULL;
int ret, input_ret, i;
@@ -3190,8 +3191,16 @@ int main(int argc, char **argv)
goto end;
}
- if ((ret = avtext_context_open(&tctx, f, f_args,
- sections, FF_ARRAY_ELEMS(sections), output_filename, show_value_unit,
+ if (output_filename) {
+ ret = avtextwriter_create_file(&wctx, output_filename, 1);
+ } else
+ ret = avtextwriter_create_stdout(&wctx);
+
+ 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)
@@ -3222,9 +3231,14 @@ int main(int argc, char **argv)
input_ret = ret;
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);
}
diff --git a/libavutil/Makefile b/libavutil/Makefile
index ce72aec1b7..09bcf3597d 100644
--- a/libavutil/Makefile
+++ b/libavutil/Makefile
@@ -10,6 +10,7 @@ HEADERS = adler32.h \
avassert.h \
avstring.h \
avtextformat.h \
+ avtextwriters.h \
avutil.h \
base64.h \
blowfish.h \
@@ -195,6 +196,9 @@ OBJS = adler32.o \
textformat/tf_ini.o \
textformat/tf_json.o \
textformat/tf_xml.o \
+ textformat/tw_avio.o \
+ textformat/tw_buffer.o \
+ textformat/tw_stdout.o \
tx.o \
tx_float.o \
tx_double.o \
diff --git a/libavutil/avtextformat.h b/libavutil/avtextformat.h
index 4f428d74c6..7c8e1315bf 100644
--- a/libavutil/avtextformat.h
+++ b/libavutil/avtextformat.h
@@ -29,6 +29,7 @@
#include "bprint.h"
#include "rational.h"
#include "libavutil/hash.h"
+#include "avtextwriters.h"
#define SECTION_MAX_NB_CHILDREN 11
@@ -53,7 +54,6 @@ struct AVTextFormatSection {
int show_all_entries;
};
-typedef struct AVTextFormatContext AVTextFormatContext;
#define AV_TEXTFORMAT_FLAG_SUPPORTS_OPTIONAL_FIELDS 1
#define AV_TEXTFORMAT_FLAG_SUPPORTS_MIXED_ARRAY_CONTENT 2
@@ -65,6 +65,8 @@ typedef enum {
AV_TEXTFORMAT_STRING_VALIDATION_NB
} StringValidation;
+typedef struct AVTextFormatContext AVTextFormatContext;
+
typedef struct AVTextFormatter {
const AVClass *priv_class; ///< private class of the formatter, if any
int priv_size; ///< private size for the formatter context
@@ -87,11 +89,7 @@ typedef struct AVTextFormatter {
struct AVTextFormatContext {
const AVClass *class; ///< class of the formatter
const AVTextFormatter *formatter; ///< the AVTextFormatter of which this is an instance
- AVIOContext *avio; ///< the I/O context used to write
-
- void (* writer_w8)(AVTextFormatContext *wctx, int b);
- void (* writer_put_str)(AVTextFormatContext *wctx, const char *str);
- void (* writer_printf)(AVTextFormatContext *wctx, const char *fmt, ...);
+ AVTextWriterContext *writer; ///< the AVTextWriterContext
char *name; ///< name of this formatter instance
void *priv; ///< private data for use by the filter
@@ -126,9 +124,8 @@ struct AVTextFormatContext {
#define AV_TEXTFORMAT_PRINT_STRING_OPTIONAL 1
#define AV_TEXTFORMAT_PRINT_STRING_VALIDATE 2
-int avtext_context_open(AVTextFormatContext **pwctx, const AVTextFormatter *formatter, const AVTextFormatter *writer, const char *args,
+int avtext_context_open(AVTextFormatContext **pwctx, const AVTextFormatter *formatter, const AVTextWriterContext *writer, const char *args,
const struct AVTextFormatSection *sections, int nb_sections,
- const char *output_filename,
int show_value_unit,
int use_value_prefix,
int use_byte_value_binary_prefix,
diff --git a/libavutil/avtextwriters.h b/libavutil/avtextwriters.h
new file mode 100644
index 0000000000..873a062777
--- /dev/null
+++ b/libavutil/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 AVUTIL_AVTEXTWRITERS_H
+#define AVUTIL_AVTEXTWRITERS_H
+
+#include <stddef.h>
+#include <stdint.h>
+#include "attributes.h"
+#include "dict.h"
+#include <libavformat/avio.h>
+#include "bprint.h"
+#include "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 /* AVUTIL_AVTEXTWRITERS_H */
diff --git a/libavutil/textformat/avtextformat.c b/libavutil/textformat/avtextformat.c
index 90b6545a88..b1cf93f63e 100644
--- a/libavutil/textformat/avtextformat.c
+++ b/libavutil/textformat/avtextformat.c
@@ -54,6 +54,7 @@ static const struct {
{ 1.125899906842624e15, 1e15, "Pi", "P" },
};
+
static const char *avtext_context_get_formatter_name(void *p)
{
AVTextFormatContext *wctx = p;
@@ -90,45 +91,6 @@ static const AVClass textcontext_class = {
.child_next = trextcontext_child_next,
};
-
-static inline void textoutput_w8_avio(AVTextFormatContext *wctx, int b)
-{
- avio_w8(wctx->avio, b);
-}
-
-static inline void textoutput_put_str_avio(AVTextFormatContext *wctx, const char *str)
-{
- avio_write(wctx->avio, str, strlen(str));
-}
-
-static inline void textoutput_printf_avio(AVTextFormatContext *wctx, const char *fmt, ...)
-{
- va_list ap;
-
- va_start(ap, fmt);
- avio_vprintf(wctx->avio, fmt, ap);
- va_end(ap);
-}
-
-static inline void textoutput_w8_printf(AVTextFormatContext *wctx, int b)
-{
- printf("%c", b);
-}
-
-static inline void textoutput_put_str_printf(AVTextFormatContext *wctx, const char *str)
-{
- printf("%s", str);
-}
-
-static inline void textoutput_printf_printf(AVTextFormatContext *wctx, const char *fmt, ...)
-{
- va_list ap;
-
- va_start(ap, fmt);
- vprintf(fmt, ap);
- va_end(ap);
-}
-
static void bprint_bytes(AVBPrint *bp, const uint8_t *ubuf, size_t ubuf_size)
{
int i;
@@ -156,18 +118,13 @@ int avtext_context_close(AVTextFormatContext **pwctx)
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(pwctx);
return ret;
}
-int avtext_context_open(AVTextFormatContext **pwctx, const AVTextFormatter *formatter, const AVTextFormatter *writer, const char *args,
+int avtext_context_open(AVTextFormatContext **pwctx, const AVTextFormatter *formatter, const AVTextWriterContext *writer_context, const char *args,
const struct AVTextFormatSection *sections, int nb_sections,
- const char *output_filename,
int show_value_unit,
int use_value_prefix,
int use_byte_value_binary_prefix,
@@ -204,6 +161,7 @@ int avtext_context_open(AVTextFormatContext **pwctx, const AVTextFormatter *form
wctx->level = -1;
wctx->sections = sections;
wctx->nb_sections = nb_sections;
+ wctx->writer = writer_context;
av_opt_set_defaults(wctx);
@@ -269,21 +227,6 @@ int avtext_context_open(AVTextFormatContext **pwctx, const AVTextFormatter *form
}
}
- if (!output_filename) {
- wctx->writer_w8 = textoutput_w8_printf;
- wctx->writer_put_str = textoutput_put_str_printf;
- wctx->writer_printf = textoutput_printf_printf;
- } else {
- if ((ret = avio_open(&wctx->avio, output_filename, AVIO_FLAG_WRITE)) < 0) {
- av_log(wctx, AV_LOG_ERROR,
- "Failed to open output '%s' with error: %s\n", output_filename, av_err2str(ret));
- goto fail;
- }
- wctx->writer_w8 = textoutput_w8_avio;
- wctx->writer_put_str = textoutput_put_str_avio;
- wctx->writer_printf = textoutput_printf_avio;
- }
-
for (i = 0; i < SECTION_MAX_NB_LEVELS; i++)
av_bprint_init(&wctx->section_pbuf[i], 1, AV_BPRINT_SIZE_UNLIMITED);
@@ -614,3 +557,85 @@ void avtext_print_integers(AVTextFormatContext *wctx, const char *name,
avtext_print_string(wctx, name, bp.str, 0);
av_bprint_finalize(&bp, NULL);
}
+
+static const char *avtextwriter_context_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 = avtextwriter_context_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 -1;
+
+ 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;
+}
+
diff --git a/libavutil/textformat/tf_compact.c b/libavutil/textformat/tf_compact.c
index fa8d3f2223..8d4078d3ab 100644
--- a/libavutil/textformat/tf_compact.c
+++ b/libavutil/textformat/tf_compact.c
@@ -36,9 +36,9 @@
#include "../opt.h"
-#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 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) \
diff --git a/libavutil/textformat/tf_default.c b/libavutil/textformat/tf_default.c
index 884d7160ff..8fa6615476 100644
--- a/libavutil/textformat/tf_default.c
+++ b/libavutil/textformat/tf_default.c
@@ -35,9 +35,9 @@
#include "../macros.h"
#include "../opt.h"
-#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 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) \
diff --git a/libavutil/textformat/tf_flat.c b/libavutil/textformat/tf_flat.c
index 767762dd0e..a6474e5ba0 100644
--- a/libavutil/textformat/tf_flat.c
+++ b/libavutil/textformat/tf_flat.c
@@ -35,9 +35,9 @@
#include "../macros.h"
#include "../opt.h"
-#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 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) \
diff --git a/libavutil/textformat/tf_ini.c b/libavutil/textformat/tf_ini.c
index 3d0c4ea564..d9fadcf9f0 100644
--- a/libavutil/textformat/tf_ini.c
+++ b/libavutil/textformat/tf_ini.c
@@ -35,9 +35,9 @@
#include "../macros.h"
#include "../opt.h"
-#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 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) \
diff --git a/libavutil/textformat/tf_json.c b/libavutil/textformat/tf_json.c
index c4dbf5a3d8..a18e27deae 100644
--- a/libavutil/textformat/tf_json.c
+++ b/libavutil/textformat/tf_json.c
@@ -35,9 +35,9 @@
#include "../macros.h"
#include "../opt.h"
-#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 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) \
diff --git a/libavutil/textformat/tf_xml.c b/libavutil/textformat/tf_xml.c
index 760d9fbf9d..a306c4203b 100644
--- a/libavutil/textformat/tf_xml.c
+++ b/libavutil/textformat/tf_xml.c
@@ -35,9 +35,9 @@
#include "../macros.h"
#include "../opt.h"
-#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 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) \
diff --git a/libavutil/textformat/tw_avio.c b/libavutil/textformat/tw_avio.c
new file mode 100644
index 0000000000..83437d2e6f
--- /dev/null
+++ b/libavutil/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 "../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/libavutil/textformat/tw_buffer.c b/libavutil/textformat/tw_buffer.c
new file mode 100644
index 0000000000..dbdd7759c9
--- /dev/null
+++ b/libavutil/textformat/tw_buffer.c
@@ -0,0 +1,91 @@
+/*
+ * 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 "../opt.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 = 0;
+
+ ret = avtextwriter_context_open(pwctx, &avtextwriter_buffer);
+ if (ret < 0)
+ return ret;
+
+ ctx = (*pwctx)->priv;
+ ctx->buffer = buffer;
+
+ return ret;
+}
diff --git a/libavutil/textformat/tw_stdout.c b/libavutil/textformat/tw_stdout.c
new file mode 100644
index 0000000000..4ea10f272e
--- /dev/null
+++ b/libavutil/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 "../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
More information about the ffmpeg-devel
mailing list