* Re: [FFmpeg-devel] [PATCH 1/2] lavf/avio: add avio_vprintf()
[not found] ` <20210421215335.GC12140@mariano>
@ 2022-04-03 14:03 ` Stefano Sabatini
2022-06-09 19:03 ` Marton Balint
0 siblings, 1 reply; 9+ messages in thread
From: Stefano Sabatini @ 2022-04-03 14:03 UTC (permalink / raw)
To: FFmpeg development discussions and patches
[-- Attachment #1: Type: text/plain, Size: 531 bytes --]
On date Wednesday 2021-04-21 23:53:35 +0200, Stefano Sabatini wrote:
> On date Sunday 2021-04-18 23:30:57 +0200, Stefano Sabatini wrote:
> > This new function makes it possible to use avio_printf() functionality from
> > a function taking a variable list of arguments.
> > ---
> > doc/APIchanges | 3 +++
> > libavformat/avio.h | 6 ++++++
> > libavformat/aviobuf.c | 17 +++++++++++++----
> > libavformat/version.h | 2 +-
> > 4 files changed, 23 insertions(+), 5 deletions(-)
>
> Updated against master.
Updated.
[-- Attachment #2: 0001-lavf-avio-add-avio_vprintf.patch --]
[-- Type: text/x-diff, Size: 3001 bytes --]
From c4ac476c90b422ee876ee7e53ed942d693943bea Mon Sep 17 00:00:00 2001
From: Stefano Sabatini <stefasab@gmail.com>
Date: Sun, 18 Apr 2021 22:49:25 +0200
Subject: [PATCH 1/3] lavf/avio: add avio_vprintf()
This new function makes it possible to use avio_printf() functionality from
a function taking a variable list of arguments.
---
doc/APIchanges | 3 +++
libavformat/avio.h | 6 ++++++
libavformat/aviobuf.c | 17 +++++++++++++----
libavformat/version.h | 2 +-
4 files changed, 23 insertions(+), 5 deletions(-)
diff --git a/doc/APIchanges b/doc/APIchanges
index 1a9f0a303e..c2612efb93 100644
--- a/doc/APIchanges
+++ b/doc/APIchanges
@@ -13,6 +13,9 @@ libavutil: 2021-04-27
API changes, most recent first:
+2022-04-03 - xxxxxxxxxx - lavf 59.21.100 - avio.h
+ Add avio_vprintf(), similar to avio_printf() but allow to use it
+ from within a function taking a variable argument list as input.
2022-03-16 - xxxxxxxxxx - all libraries - version_major.h
Add lib<name>/version_major.h as new installed headers, which only
diff --git a/libavformat/avio.h b/libavformat/avio.h
index 3ed9175a9b..36c3d7b430 100644
--- a/libavformat/avio.h
+++ b/libavformat/avio.h
@@ -519,6 +519,12 @@ int64_t avio_size(AVIOContext *s);
*/
int avio_feof(AVIOContext *s);
+/**
+ * Writes a formatted string to the context taking a va_list.
+ * @return number of bytes written, < 0 on error.
+ */
+int avio_vprintf(AVIOContext *s, const char *fmt, va_list ap);
+
/**
* Writes a formatted string to the context.
* @return number of bytes written, < 0 on error.
diff --git a/libavformat/aviobuf.c b/libavformat/aviobuf.c
index 29d4bd7510..64184978c2 100644
--- a/libavformat/aviobuf.c
+++ b/libavformat/aviobuf.c
@@ -1289,15 +1289,12 @@ int avio_closep(AVIOContext **s)
return ret;
}
-int avio_printf(AVIOContext *s, const char *fmt, ...)
+int avio_vprintf(AVIOContext *s, const char *fmt, va_list ap)
{
- va_list ap;
AVBPrint bp;
av_bprint_init(&bp, 0, INT_MAX);
- va_start(ap, fmt);
av_vbprintf(&bp, fmt, ap);
- va_end(ap);
if (!av_bprint_is_complete(&bp)) {
av_bprint_finalize(&bp, NULL);
s->error = AVERROR(ENOMEM);
@@ -1308,6 +1305,18 @@ int avio_printf(AVIOContext *s, const char *fmt, ...)
return bp.len;
}
+int avio_printf(AVIOContext *s, const char *fmt, ...)
+{
+ va_list ap;
+ int ret;
+
+ va_start(ap, fmt);
+ ret = avio_vprintf(s, fmt, ap);
+ va_end(ap);
+
+ return ret;
+}
+
void avio_print_string_array(AVIOContext *s, const char *strings[])
{
for(; *strings; strings++)
diff --git a/libavformat/version.h b/libavformat/version.h
index f4a26c2870..2f54f57c02 100644
--- a/libavformat/version.h
+++ b/libavformat/version.h
@@ -31,7 +31,7 @@
#include "version_major.h"
-#define LIBAVFORMAT_VERSION_MINOR 20
+#define LIBAVFORMAT_VERSION_MINOR 21
#define LIBAVFORMAT_VERSION_MICRO 101
#define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \
--
2.25.1
[-- Attachment #3: 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] 9+ messages in thread
* Re: [FFmpeg-devel] [PATCH 2/2] ffprobe: add -o option
[not found] ` <20210421215704.GD12140@mariano>
@ 2022-04-03 14:06 ` Stefano Sabatini
2022-06-09 19:09 ` Marton Balint
0 siblings, 1 reply; 9+ messages in thread
From: Stefano Sabatini @ 2022-04-03 14:06 UTC (permalink / raw)
To: FFmpeg development discussions and patches
[-- Attachment #1: Type: text/plain, Size: 1001 bytes --]
On date Wednesday 2021-04-21 23:57:04 +0200, Stefano Sabatini wrote:
> On date Monday 2021-04-19 11:26:49 +0200, Michael Niedermayer wrote:
> > On Sun, Apr 18, 2021 at 11:30:58PM +0200, Stefano Sabatini wrote:
> > > This enables printing to a resource specified with -o OUTPUT.
> > >
> > > Address issue: http://trac.ffmpeg.org/ticket/8024
> > > ---
> > > doc/ffprobe.texi | 7 ++
> > > fftools/ffprobe.c | 174 ++++++++++++++++++++++++++++++----------------
> > > 2 files changed, 120 insertions(+), 61 deletions(-)
> >
> > This seems breaking some fate tests like fate-gaplessenc-itunes-to-ipod-aac
> >
> > I see 0 bytes in the output:
> > 73 3D 4B 44 00 73 69 64 65 5F 64 61 74 61 7C 0A 0A
> >
> > thx
>
> That's right, I'm still forgetting to run make fate :-)
> (avio_put_str() was adding the 0), should be fixed now.
>
> Thanks.
Updated again, now it's locally passing fate with FATE samples (don't
remember if other issues were spotted the past time).
Best regards,
Stefano
[-- Attachment #2: 0002-ffprobe-add-o-option.patch --]
[-- Type: text/x-diff, Size: 21134 bytes --]
From b65c0c22263767e5bd03e948ebe2ae34fe0b022c Mon Sep 17 00:00:00 2001
From: Stefano Sabatini <stefasab@gmail.com>
Date: Sun, 18 Apr 2021 23:11:01 +0200
Subject: [PATCH 2/3] ffprobe: add -o option
This enables printing to a resource specified with -o OUTPUT.
Address issue: http://trac.ffmpeg.org/ticket/8024
---
Changelog | 1 +
doc/ffprobe.texi | 7 ++
fftools/ffprobe.c | 174 ++++++++++++++++++++++++++++++----------------
3 files changed, 121 insertions(+), 61 deletions(-)
diff --git a/Changelog b/Changelog
index e173d43229..aa432938c6 100644
--- a/Changelog
+++ b/Changelog
@@ -7,6 +7,7 @@ version 5.1:
- pcm-bluray encoder
- DFPWM audio encoder/decoder and raw muxer/demuxer
- SITI filter
+- ffprobe -o option
version 5.0:
diff --git a/doc/ffprobe.texi b/doc/ffprobe.texi
index 59a397a225..a823563753 100644
--- a/doc/ffprobe.texi
+++ b/doc/ffprobe.texi
@@ -28,6 +28,9 @@ If a url is specified in input, ffprobe will try to open and
probe the url content. If the url cannot be opened or recognized as
a multimedia file, a positive exit code is returned.
+If no output is specified as output with @option{o} ffprobe will write
+to stdout.
+
ffprobe may be employed both as a standalone application or in
combination with a textual filter, which may perform more
sophisticated processing, e.g. statistical processing or plotting.
@@ -348,6 +351,10 @@ on the specific build.
@item -i @var{input_url}
Read @var{input_url}.
+@item -o @var{output_url}
+Write output to @var{output_url}. If not specified, the output is sent
+to stdout.
+
@end table
@c man end
diff --git a/fftools/ffprobe.c b/fftools/ffprobe.c
index 05c167eeb5..33d3a59667 100644
--- a/fftools/ffprobe.c
+++ b/fftools/ffprobe.c
@@ -281,6 +281,7 @@ static const OptionDef *options;
static const char *input_filename;
static const char *print_input_filename;
static const AVInputFormat *iformat = NULL;
+static const char *output_filename = NULL;
static struct AVHashContext *hash;
@@ -476,6 +477,7 @@ typedef struct Writer {
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
char *name; ///< name of this writer instance
void *priv; ///< private data for use by the filter
@@ -553,6 +555,10 @@ static void writer_close(WriterContext **wctx)
av_opt_free((*wctx)->priv);
av_freep(&((*wctx)->priv));
av_opt_free(*wctx);
+ if ((*wctx)->avio) {
+ avio_flush((*wctx)->avio);
+ avio_close((*wctx)->avio);
+ }
av_freep(wctx);
}
@@ -566,7 +572,7 @@ static void bprint_bytes(AVBPrint *bp, const uint8_t *ubuf, size_t ubuf_size)
static int writer_open(WriterContext **wctx, const Writer *writer, const char *args,
- const struct section *sections, int nb_sections)
+ const struct section *sections, int nb_sections, const char *url)
{
int i, ret = 0;
@@ -637,6 +643,9 @@ static int writer_open(WriterContext **wctx, const Writer *writer, const char *a
}
}
+ if ((ret = avio_open(&(*wctx)->avio, url, AVIO_FLAG_WRITE)) < 0)
+ goto fail;
+
for (i = 0; i < SECTION_MAX_NB_LEVELS; i++)
av_bprint_init(&(*wctx)->section_pbuf[i], 1, AV_BPRINT_SIZE_UNLIMITED);
@@ -904,6 +913,25 @@ static void writer_print_integers(WriterContext *wctx, const char *name,
av_bprint_finalize(&bp, NULL);
}
+static inline void writer_w8(WriterContext *wctx, int b)
+{
+ avio_w8(wctx->avio, b);
+}
+
+static inline void writer_put_str(WriterContext *wctx, const char *str)
+{
+ avio_write(wctx->avio, str, strlen(str));
+}
+
+static inline void writer_printf(WriterContext *wctx, const char *fmt, ...)
+{
+ va_list ap;
+
+ va_start(ap, fmt);
+ avio_vprintf(wctx->avio, fmt, ap);
+ va_end(ap);
+}
+
#define MAX_REGISTERED_WRITERS_NB 64
static const Writer *registered_writers[MAX_REGISTERED_WRITERS_NB + 1];
@@ -998,7 +1026,7 @@ static void default_print_section_header(WriterContext *wctx)
return;
if (!(section->flags & (SECTION_FLAG_IS_WRAPPER|SECTION_FLAG_IS_ARRAY)))
- printf("[%s]\n", upcase_string(buf, sizeof(buf), section->name));
+ writer_printf(wctx, "[%s]\n", upcase_string(buf, sizeof(buf), section->name));
}
static void default_print_section_footer(WriterContext *wctx)
@@ -1011,7 +1039,7 @@ static void default_print_section_footer(WriterContext *wctx)
return;
if (!(section->flags & (SECTION_FLAG_IS_WRAPPER|SECTION_FLAG_IS_ARRAY)))
- printf("[/%s]\n", upcase_string(buf, sizeof(buf), section->name));
+ 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)
@@ -1019,8 +1047,8 @@ static void default_print_str(WriterContext *wctx, const char *key, const char *
DefaultContext *def = wctx->priv;
if (!def->nokey)
- printf("%s%s=", wctx->section_pbuf[wctx->level].str, key);
- printf("%s\n", value);
+ 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, long long int value)
@@ -1028,8 +1056,8 @@ static void default_print_int(WriterContext *wctx, const char *key, long long in
DefaultContext *def = wctx->priv;
if (!def->nokey)
- printf("%s%s=", wctx->section_pbuf[wctx->level].str, key);
- printf("%lld\n", value);
+ writer_printf(wctx, "%s%s=", wctx->section_pbuf[wctx->level].str, key);
+ writer_printf(wctx, "%lld\n", value);
}
static const Writer default_writer = {
@@ -1171,10 +1199,10 @@ static void compact_print_section_header(WriterContext *wctx)
}
if (parent_section && !(parent_section->flags & (SECTION_FLAG_IS_WRAPPER|SECTION_FLAG_IS_ARRAY)) &&
wctx->level && wctx->nb_item[wctx->level-1])
- printf("%c", compact->item_sep);
+ writer_w8(wctx, compact->item_sep);
if (compact->print_section &&
!(section->flags & (SECTION_FLAG_IS_WRAPPER|SECTION_FLAG_IS_ARRAY)))
- printf("%s%c", section->name, compact->item_sep);
+ writer_printf(wctx, "%s%c", section->name, compact->item_sep);
}
}
@@ -1185,7 +1213,7 @@ static void compact_print_section_footer(WriterContext *wctx)
if (!compact->nested_section[wctx->level] &&
compact->terminate_line[wctx->level] &&
!(wctx->section[wctx->level]->flags & (SECTION_FLAG_IS_WRAPPER|SECTION_FLAG_IS_ARRAY)))
- printf("\n");
+ writer_w8(wctx, '\n');
}
static void compact_print_str(WriterContext *wctx, const char *key, const char *value)
@@ -1193,11 +1221,11 @@ static void compact_print_str(WriterContext *wctx, const char *key, const char *
CompactContext *compact = wctx->priv;
AVBPrint buf;
- if (wctx->nb_item[wctx->level]) printf("%c", compact->item_sep);
+ if (wctx->nb_item[wctx->level]) writer_w8(wctx, compact->item_sep);
if (!compact->nokey)
- printf("%s%s=", wctx->section_pbuf[wctx->level].str, key);
+ writer_printf(wctx, "%s%s=", wctx->section_pbuf[wctx->level].str, key);
av_bprint_init(&buf, 1, AV_BPRINT_SIZE_UNLIMITED);
- printf("%s", compact->escape_str(&buf, value, compact->item_sep, wctx));
+ writer_put_str(wctx, compact->escape_str(&buf, value, compact->item_sep, wctx));
av_bprint_finalize(&buf, NULL);
}
@@ -1205,10 +1233,10 @@ static void compact_print_int(WriterContext *wctx, const char *key, long long in
{
CompactContext *compact = wctx->priv;
- if (wctx->nb_item[wctx->level]) printf("%c", compact->item_sep);
+ if (wctx->nb_item[wctx->level]) writer_w8(wctx, compact->item_sep);
if (!compact->nokey)
- printf("%s%s=", wctx->section_pbuf[wctx->level].str, key);
- printf("%lld", value);
+ writer_printf(wctx, "%s%s=", wctx->section_pbuf[wctx->level].str, key);
+ writer_printf(wctx, "%lld", value);
}
static const Writer compact_writer = {
@@ -1351,7 +1379,7 @@ static void flat_print_section_header(WriterContext *wctx)
static void flat_print_int(WriterContext *wctx, const char *key, long long int value)
{
- printf("%s%s=%lld\n", wctx->section_pbuf[wctx->level].str, key, value);
+ writer_printf(wctx, "%s%s=%lld\n", wctx->section_pbuf[wctx->level].str, key, value);
}
static void flat_print_str(WriterContext *wctx, const char *key, const char *value)
@@ -1359,11 +1387,11 @@ static void flat_print_str(WriterContext *wctx, const char *key, const char *val
FlatContext *flat = wctx->priv;
AVBPrint buf;
- printf("%s", wctx->section_pbuf[wctx->level].str);
+ writer_put_str(wctx, wctx->section_pbuf[wctx->level].str);
av_bprint_init(&buf, 1, AV_BPRINT_SIZE_UNLIMITED);
- printf("%s=", flat_escape_key_str(&buf, key, flat->sep));
+ writer_printf(wctx, "%s=", flat_escape_key_str(&buf, key, flat->sep));
av_bprint_clear(&buf);
- printf("\"%s\"\n", flat_escape_value_str(&buf, value));
+ writer_printf(wctx, "\"%s\"\n", flat_escape_value_str(&buf, value));
av_bprint_finalize(&buf, NULL);
}
@@ -1433,12 +1461,12 @@ static void ini_print_section_header(WriterContext *wctx)
av_bprint_clear(buf);
if (!parent_section) {
- printf("# ffprobe output\n\n");
+ writer_put_str(wctx, "# ffprobe output\n\n");
return;
}
if (wctx->nb_item[wctx->level-1])
- printf("\n");
+ writer_w8(wctx, '\n');
av_bprintf(buf, "%s", wctx->section_pbuf[wctx->level-1].str);
if (ini->hierarchical ||
@@ -1453,7 +1481,7 @@ static void ini_print_section_header(WriterContext *wctx)
}
if (!(section->flags & (SECTION_FLAG_IS_ARRAY|SECTION_FLAG_IS_WRAPPER)))
- printf("[%s]\n", buf->str);
+ writer_printf(wctx, "[%s]\n", buf->str);
}
static void ini_print_str(WriterContext *wctx, const char *key, const char *value)
@@ -1461,15 +1489,15 @@ static void ini_print_str(WriterContext *wctx, const char *key, const char *valu
AVBPrint buf;
av_bprint_init(&buf, 1, AV_BPRINT_SIZE_UNLIMITED);
- printf("%s=", ini_escape_str(&buf, key));
+ writer_printf(wctx, "%s=", ini_escape_str(&buf, key));
av_bprint_clear(&buf);
- printf("%s\n", ini_escape_str(&buf, value));
+ 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, long long int value)
{
- printf("%s=%lld\n", key, value);
+ writer_printf(wctx, "%s=%lld\n", key, value);
}
static const Writer ini_writer = {
@@ -1532,7 +1560,7 @@ static const char *json_escape_str(AVBPrint *dst, const char *src, void *log_ctx
return dst->str;
}
-#define JSON_INDENT() printf("%*c", json->indent_level * 4, ' ')
+#define JSON_INDENT() writer_printf(wctx, "%*c", json->indent_level * 4, ' ')
static void json_print_section_header(WriterContext *wctx)
{
@@ -1543,10 +1571,10 @@ static void json_print_section_header(WriterContext *wctx)
wctx->section[wctx->level-1] : NULL;
if (wctx->level && wctx->nb_item[wctx->level-1])
- printf(",\n");
+ writer_put_str(wctx, ",\n");
if (section->flags & SECTION_FLAG_IS_WRAPPER) {
- printf("{\n");
+ writer_put_str(wctx, "{\n");
json->indent_level++;
} else {
av_bprint_init(&buf, 1, AV_BPRINT_SIZE_UNLIMITED);
@@ -1555,17 +1583,17 @@ static void json_print_section_header(WriterContext *wctx)
json->indent_level++;
if (section->flags & SECTION_FLAG_IS_ARRAY) {
- printf("\"%s\": [\n", buf.str);
+ writer_printf(wctx, "\"%s\": [\n", buf.str);
} else if (parent_section && !(parent_section->flags & SECTION_FLAG_IS_ARRAY)) {
- printf("\"%s\": {%s", buf.str, json->item_start_end);
+ writer_printf(wctx, "\"%s\": {%s", buf.str, json->item_start_end);
} else {
- printf("{%s", json->item_start_end);
+ 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();
- printf("\"type\": \"%s\"", section->name);
+ writer_printf(wctx, "\"type\": \"%s\"", section->name);
}
}
av_bprint_finalize(&buf, NULL);
@@ -1579,18 +1607,18 @@ static void json_print_section_footer(WriterContext *wctx)
if (wctx->level == 0) {
json->indent_level--;
- printf("\n}\n");
+ writer_put_str(wctx, "\n}\n");
} else if (section->flags & SECTION_FLAG_IS_ARRAY) {
- printf("\n");
+ writer_w8(wctx, '\n');
json->indent_level--;
JSON_INDENT();
- printf("]");
+ writer_w8(wctx, ']');
} else {
- printf("%s", json->item_start_end);
+ writer_put_str(wctx, json->item_start_end);
json->indent_level--;
if (!json->compact)
JSON_INDENT();
- printf("}");
+ writer_w8(wctx, '}');
}
}
@@ -1600,9 +1628,9 @@ static inline void json_print_item_str(WriterContext *wctx,
AVBPrint buf;
av_bprint_init(&buf, 1, AV_BPRINT_SIZE_UNLIMITED);
- printf("\"%s\":", json_escape_str(&buf, key, wctx));
+ writer_printf(wctx, "\"%s\":", json_escape_str(&buf, key, wctx));
av_bprint_clear(&buf);
- printf(" \"%s\"", json_escape_str(&buf, value, wctx));
+ writer_printf(wctx, " \"%s\"", json_escape_str(&buf, value, wctx));
av_bprint_finalize(&buf, NULL);
}
@@ -1613,7 +1641,7 @@ static void json_print_str(WriterContext *wctx, const char *key, const char *val
wctx->section[wctx->level-1] : NULL;
if (wctx->nb_item[wctx->level] || (parent_section && parent_section->id == SECTION_ID_PACKETS_AND_FRAMES))
- printf("%s", json->item_sep);
+ writer_put_str(wctx, json->item_sep);
if (!json->compact)
JSON_INDENT();
json_print_item_str(wctx, key, value);
@@ -1627,12 +1655,12 @@ static void json_print_int(WriterContext *wctx, const char *key, long long int v
AVBPrint buf;
if (wctx->nb_item[wctx->level] || (parent_section && parent_section->id == SECTION_ID_PACKETS_AND_FRAMES))
- printf("%s", json->item_sep);
+ writer_put_str(wctx, json->item_sep);
if (!json->compact)
JSON_INDENT();
av_bprint_init(&buf, 1, AV_BPRINT_SIZE_UNLIMITED);
- printf("\"%s\": %lld", json_escape_str(&buf, key, wctx), value);
+ writer_printf(wctx, "\"%s\": %lld", json_escape_str(&buf, key, wctx), value);
av_bprint_finalize(&buf, NULL);
}
@@ -1692,7 +1720,7 @@ static av_cold int xml_init(WriterContext *wctx)
return 0;
}
-#define XML_INDENT() printf("%*c", xml->indent_level * 4, ' ')
+#define XML_INDENT() writer_printf(wctx, "%*c", xml->indent_level * 4, ' ')
static void xml_print_section_header(WriterContext *wctx)
{
@@ -1706,8 +1734,8 @@ static void xml_print_section_header(WriterContext *wctx)
"xmlns:ffprobe=\"http://www.ffmpeg.org/schema/ffprobe\" "
"xsi:schemaLocation=\"http://www.ffmpeg.org/schema/ffprobe ffprobe.xsd\"";
- printf("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
- printf("<%sffprobe%s>\n",
+ 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;
@@ -1715,20 +1743,20 @@ static void xml_print_section_header(WriterContext *wctx)
if (xml->within_tag) {
xml->within_tag = 0;
- printf(">\n");
+ writer_put_str(wctx, ">\n");
}
if (section->flags & SECTION_FLAG_HAS_VARIABLE_FIELDS) {
xml->indent_level++;
} else {
if (parent_section && (parent_section->flags & SECTION_FLAG_IS_WRAPPER) &&
wctx->level && wctx->nb_item[wctx->level-1])
- printf("\n");
+ writer_w8(wctx, '\n');
xml->indent_level++;
if (section->flags & SECTION_FLAG_IS_ARRAY) {
- XML_INDENT(); printf("<%s>\n", section->name);
+ XML_INDENT(); writer_printf(wctx, "<%s>\n", section->name);
} else {
- XML_INDENT(); printf("<%s ", section->name);
+ XML_INDENT(); writer_printf(wctx, "<%s ", section->name);
xml->within_tag = 1;
}
}
@@ -1740,15 +1768,15 @@ static void xml_print_section_footer(WriterContext *wctx)
const struct section *section = wctx->section[wctx->level];
if (wctx->level == 0) {
- printf("</%sffprobe>\n", xml->fully_qualified ? "ffprobe:" : "");
+ writer_printf(wctx, "</%sffprobe>\n", xml->fully_qualified ? "ffprobe:" : "");
} else if (xml->within_tag) {
xml->within_tag = 0;
- printf("/>\n");
+ writer_put_str(wctx, "/>\n");
xml->indent_level--;
} else if (section->flags & SECTION_FLAG_HAS_VARIABLE_FIELDS) {
xml->indent_level--;
} else {
- XML_INDENT(); printf("</%s>\n", section->name);
+ XML_INDENT(); writer_printf(wctx, "</%s>\n", section->name);
xml->indent_level--;
}
}
@@ -1765,20 +1793,20 @@ static void xml_print_str(WriterContext *wctx, const char *key, const char *valu
XML_INDENT();
av_bprint_escape(&buf, key, NULL,
AV_ESCAPE_MODE_XML, AV_ESCAPE_FLAG_XML_DOUBLE_QUOTES);
- printf("<%s key=\"%s\"",
- section->element_name, buf.str);
+ writer_printf(wctx, "<%s key=\"%s\"",
+ section->element_name, buf.str);
av_bprint_clear(&buf);
av_bprint_escape(&buf, value, NULL,
AV_ESCAPE_MODE_XML, AV_ESCAPE_FLAG_XML_DOUBLE_QUOTES);
- printf(" value=\"%s\"/>\n", buf.str);
+ writer_printf(wctx, " value=\"%s\"/>\n", buf.str);
} else {
if (wctx->nb_item[wctx->level])
- printf(" ");
+ writer_w8(wctx, ' ');
av_bprint_escape(&buf, value, NULL,
AV_ESCAPE_MODE_XML, AV_ESCAPE_FLAG_XML_DOUBLE_QUOTES);
- printf("%s=\"%s\"", key, buf.str);
+ writer_printf(wctx, "%s=\"%s\"", key, buf.str);
}
av_bprint_finalize(&buf, NULL);
@@ -1787,8 +1815,8 @@ static void xml_print_str(WriterContext *wctx, const char *key, const char *valu
static void xml_print_int(WriterContext *wctx, const char *key, long long int value)
{
if (wctx->nb_item[wctx->level])
- printf(" ");
- printf("%s=\"%lld\"", key, value);
+ writer_w8(wctx, ' ');
+ writer_printf(wctx, "%s=\"%lld\"", key, value);
}
static Writer xml_writer = {
@@ -3641,6 +3669,25 @@ static int opt_input_file_i(void *optctx, const char *opt, const char *arg)
return 0;
}
+static void opt_output_file(void *optctx, const char *arg)
+{
+ if (output_filename) {
+ av_log(NULL, AV_LOG_ERROR,
+ "Argument '%s' provided as output filename, but '%s' was already specified.\n",
+ arg, output_filename);
+ exit_program(1);
+ }
+ if (!strcmp(arg, "-"))
+ arg = "pipe:";
+ output_filename = arg;
+}
+
+static int opt_output_file_o(void *optctx, const char *opt, const char *arg)
+{
+ opt_output_file(optctx, arg);
+ return 0;
+}
+
static int opt_print_filename(void *optctx, const char *opt, const char *arg)
{
print_input_filename = arg;
@@ -3903,6 +3950,7 @@ static const OptionDef real_options[] = {
{ "bitexact", OPT_BOOL, {&do_bitexact}, "force bitexact output" },
{ "read_intervals", HAS_ARG, {.func_arg = opt_read_intervals}, "set read intervals", "read_intervals" },
{ "i", HAS_ARG, {.func_arg = opt_input_file_i}, "read specified file", "input_file"},
+ { "o", HAS_ARG, {.func_arg = opt_output_file_o}, "write to specified output", "output_file"},
{ "print_filename", HAS_ARG, {.func_arg = opt_print_filename}, "override the printed input filename", "print_file"},
{ "find_stream_info", OPT_BOOL | OPT_INPUT | OPT_EXPERT, { &find_stream_info },
"read and decode the streams to fill missing information with heuristics" },
@@ -4029,8 +4077,12 @@ int main(int argc, char **argv)
goto end;
}
+ if (!output_filename) {
+ output_filename = "pipe:";
+ }
+
if ((ret = writer_open(&wctx, w, w_args,
- sections, FF_ARRAY_ELEMS(sections))) >= 0) {
+ 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;
--
2.25.1
[-- Attachment #3: 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] 9+ messages in thread
* Re: [FFmpeg-devel] [PATCH 1/2] lavf/avio: add avio_vprintf()
2022-04-03 14:03 ` [FFmpeg-devel] [PATCH 1/2] lavf/avio: add avio_vprintf() Stefano Sabatini
@ 2022-06-09 19:03 ` Marton Balint
2022-06-12 15:32 ` Stefano Sabatini
0 siblings, 1 reply; 9+ messages in thread
From: Marton Balint @ 2022-06-09 19:03 UTC (permalink / raw)
To: FFmpeg development discussions and patches
On Sun, 3 Apr 2022, Stefano Sabatini wrote:
> On date Wednesday 2021-04-21 23:53:35 +0200, Stefano Sabatini wrote:
>> On date Sunday 2021-04-18 23:30:57 +0200, Stefano Sabatini wrote:
>>> This new function makes it possible to use avio_printf() functionality from
>>> a function taking a variable list of arguments.
>>> ---
>>> doc/APIchanges | 3 +++
>>> libavformat/avio.h | 6 ++++++
>>> libavformat/aviobuf.c | 17 +++++++++++++----
>>> libavformat/version.h | 2 +-
>>> 4 files changed, 23 insertions(+), 5 deletions(-)
>>
>> Updated against master.
>
> Updated.
>
Will rebase and apply soon.
Regards,
Marton
_______________________________________________
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] 9+ messages in thread
* Re: [FFmpeg-devel] [PATCH 2/2] ffprobe: add -o option
2022-04-03 14:06 ` [FFmpeg-devel] [PATCH 2/2] ffprobe: add -o option Stefano Sabatini
@ 2022-06-09 19:09 ` Marton Balint
2022-06-12 15:33 ` Stefano Sabatini
0 siblings, 1 reply; 9+ messages in thread
From: Marton Balint @ 2022-06-09 19:09 UTC (permalink / raw)
To: FFmpeg development discussions and patches
On Sun, 3 Apr 2022, Stefano Sabatini wrote:
> On date Wednesday 2021-04-21 23:57:04 +0200, Stefano Sabatini wrote:
>> On date Monday 2021-04-19 11:26:49 +0200, Michael Niedermayer wrote:
>>> On Sun, Apr 18, 2021 at 11:30:58PM +0200, Stefano Sabatini wrote:
>>>> This enables printing to a resource specified with -o OUTPUT.
>>>>
>>>> Address issue: http://trac.ffmpeg.org/ticket/8024
>>>> ---
>>>> doc/ffprobe.texi | 7 ++
>>>> fftools/ffprobe.c | 174 ++++++++++++++++++++++++++++++----------------
>>>> 2 files changed, 120 insertions(+), 61 deletions(-)
>>>
>>> This seems breaking some fate tests like fate-gaplessenc-itunes-to-ipod-aac
>>>
>>> I see 0 bytes in the output:
>>> 73 3D 4B 44 00 73 69 64 65 5F 64 61 74 61 7C 0A 0A
>>>
>>> thx
>>
>> That's right, I'm still forgetting to run make fate :-)
>> (avio_put_str() was adding the 0), should be fixed now.
>>
>> Thanks.
>
> Updated again, now it's locally passing fate with FATE samples (don't
> remember if other issues were spotted the past time).
This looks good to me in general, so I intend to apply. One thing that we
might do is to keep writing to the standard output if no output file is
specified instead of using the special "pipe:" URL. This way ffprobe
keeps working even if the pipe protocol is not compiled into
ffmpeg/libavformat.
Regards,
Marton
_______________________________________________
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] 9+ messages in thread
* Re: [FFmpeg-devel] [PATCH 1/2] lavf/avio: add avio_vprintf()
2022-06-09 19:03 ` Marton Balint
@ 2022-06-12 15:32 ` Stefano Sabatini
2022-06-12 17:00 ` Nicolas George
0 siblings, 1 reply; 9+ messages in thread
From: Stefano Sabatini @ 2022-06-12 15:32 UTC (permalink / raw)
To: FFmpeg development discussions and patches
[-- Attachment #1: Type: text/plain, Size: 755 bytes --]
On date Thursday 2022-06-09 21:03:02 +0200, Marton Balint wrote:
>
>
> On Sun, 3 Apr 2022, Stefano Sabatini wrote:
>
> > On date Wednesday 2021-04-21 23:53:35 +0200, Stefano Sabatini wrote:
> > > On date Sunday 2021-04-18 23:30:57 +0200, Stefano Sabatini wrote:
> > > > This new function makes it possible to use avio_printf() functionality from
> > > > a function taking a variable list of arguments.
> > > > ---
> > > > doc/APIchanges | 3 +++
> > > > libavformat/avio.h | 6 ++++++
> > > > libavformat/aviobuf.c | 17 +++++++++++++----
> > > > libavformat/version.h | 2 +-
> > > > 4 files changed, 23 insertions(+), 5 deletions(-)
> > >
> > > Updated against master.
> >
> > Updated.
> >
>
> Will rebase and apply soon.
Updated.
[-- Attachment #2: 0001-lavf-avio-add-avio_vprintf.patch --]
[-- Type: text/x-diff, Size: 2978 bytes --]
From fd1fd40b5f7bc66de6428a8b46be43aad30b6c2d Mon Sep 17 00:00:00 2001
From: Stefano Sabatini <stefasab@gmail.com>
Date: Sun, 12 Jun 2022 13:15:26 +0200
Subject: [PATCH 1/2] lavf/avio: add avio_vprintf()
This new function makes it possible to use avio_printf() functionality from
a function taking a variable list of arguments.
---
doc/APIchanges | 4 ++++
libavformat/avio.h | 6 ++++++
libavformat/aviobuf.c | 17 +++++++++++++----
libavformat/version.h | 2 +-
4 files changed, 24 insertions(+), 5 deletions(-)
diff --git a/doc/APIchanges b/doc/APIchanges
index 337f1466d8..4f7a19d176 100644
--- a/doc/APIchanges
+++ b/doc/APIchanges
@@ -14,6 +14,10 @@ libavutil: 2021-04-27
API changes, most recent first:
+2022-06-12 - xxxxxxxxxx - lavf 59.25.100 - avio.h
+ Add avio_vprintf(), similar to avio_printf() but allow to use it
+ from within a function taking a variable argument list as input.
+
2022-05-23 - xxxxxxxxx - lavu 57.25.100 - avutil.h
Deprecate av_fopen_utf8() without replacement.
diff --git a/libavformat/avio.h b/libavformat/avio.h
index 3ed9175a9b..36c3d7b430 100644
--- a/libavformat/avio.h
+++ b/libavformat/avio.h
@@ -519,6 +519,12 @@ int64_t avio_size(AVIOContext *s);
*/
int avio_feof(AVIOContext *s);
+/**
+ * Writes a formatted string to the context taking a va_list.
+ * @return number of bytes written, < 0 on error.
+ */
+int avio_vprintf(AVIOContext *s, const char *fmt, va_list ap);
+
/**
* Writes a formatted string to the context.
* @return number of bytes written, < 0 on error.
diff --git a/libavformat/aviobuf.c b/libavformat/aviobuf.c
index 33bc3c2e20..b20b1a611a 100644
--- a/libavformat/aviobuf.c
+++ b/libavformat/aviobuf.c
@@ -1292,15 +1292,12 @@ int avio_closep(AVIOContext **s)
return ret;
}
-int avio_printf(AVIOContext *s, const char *fmt, ...)
+int avio_vprintf(AVIOContext *s, const char *fmt, va_list ap)
{
- va_list ap;
AVBPrint bp;
av_bprint_init(&bp, 0, INT_MAX);
- va_start(ap, fmt);
av_vbprintf(&bp, fmt, ap);
- va_end(ap);
if (!av_bprint_is_complete(&bp)) {
av_bprint_finalize(&bp, NULL);
s->error = AVERROR(ENOMEM);
@@ -1311,6 +1308,18 @@ int avio_printf(AVIOContext *s, const char *fmt, ...)
return bp.len;
}
+int avio_printf(AVIOContext *s, const char *fmt, ...)
+{
+ va_list ap;
+ int ret;
+
+ va_start(ap, fmt);
+ ret = avio_vprintf(s, fmt, ap);
+ va_end(ap);
+
+ return ret;
+}
+
void avio_print_string_array(AVIOContext *s, const char *strings[])
{
for(; *strings; strings++)
diff --git a/libavformat/version.h b/libavformat/version.h
index 6c2776460b..966ebb7ed3 100644
--- a/libavformat/version.h
+++ b/libavformat/version.h
@@ -31,7 +31,7 @@
#include "version_major.h"
-#define LIBAVFORMAT_VERSION_MINOR 24
+#define LIBAVFORMAT_VERSION_MINOR 25
#define LIBAVFORMAT_VERSION_MICRO 100
#define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \
--
2.25.1
[-- Attachment #3: 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] 9+ messages in thread
* Re: [FFmpeg-devel] [PATCH 2/2] ffprobe: add -o option
2022-06-09 19:09 ` Marton Balint
@ 2022-06-12 15:33 ` Stefano Sabatini
2022-06-13 20:47 ` Marton Balint
0 siblings, 1 reply; 9+ messages in thread
From: Stefano Sabatini @ 2022-06-12 15:33 UTC (permalink / raw)
To: FFmpeg development discussions and patches
[-- Attachment #1: Type: text/plain, Size: 597 bytes --]
On date Thursday 2022-06-09 21:09:02 +0200, Marton Balint wrote:
> On Sun, 3 Apr 2022, Stefano Sabatini wrote:
[...]
> > Updated again, now it's locally passing fate with FATE samples (don't
> > remember if other issues were spotted the past time).
>
> This looks good to me in general, so I intend to apply. One thing that we
> might do is to keep writing to the standard output if no output file is
> specified instead of using the special "pipe:" URL. This way ffprobe keeps
> working even if the pipe protocol is not compiled into ffmpeg/libavformat.
Sounds good, patch updated accordingly.
[-- Attachment #2: 0002-ffprobe-add-o-option.patch --]
[-- Type: text/x-diff, Size: 22494 bytes --]
From 0bb6e8850cfe2ea479fae18e3e6d6ec0af60c878 Mon Sep 17 00:00:00 2001
From: Stefano Sabatini <stefasab@gmail.com>
Date: Sun, 18 Apr 2021 23:11:01 +0200
Subject: [PATCH 2/2] ffprobe: add -o option
This enables printing to a resource specified with -o OUTPUT.
In case the output is not specified, prints to stdout as usual.
Address issue: http://trac.ffmpeg.org/ticket/8024
---
Changelog | 1 +
doc/ffprobe.texi | 7 ++
fftools/ffprobe.c | 209 ++++++++++++++++++++++++++++++++--------------
3 files changed, 156 insertions(+), 61 deletions(-)
diff --git a/Changelog b/Changelog
index d4ca674b1b..64a0c4f358 100644
--- a/Changelog
+++ b/Changelog
@@ -19,6 +19,7 @@ version 5.1:
- blurdetect filter
- tiltshelf audio filter
- QOI image format support
+- ffprobe -o option
version 5.0:
diff --git a/doc/ffprobe.texi b/doc/ffprobe.texi
index c61b8979b1..4dc9f577bb 100644
--- a/doc/ffprobe.texi
+++ b/doc/ffprobe.texi
@@ -28,6 +28,9 @@ If a url is specified in input, ffprobe will try to open and
probe the url content. If the url cannot be opened or recognized as
a multimedia file, a positive exit code is returned.
+If no output is specified as output with @option{o} ffprobe will write
+to stdout.
+
ffprobe may be employed both as a standalone application or in
combination with a textual filter, which may perform more
sophisticated processing, e.g. statistical processing or plotting.
@@ -348,6 +351,10 @@ on the specific build.
@item -i @var{input_url}
Read @var{input_url}.
+@item -o @var{output_url}
+Write output to @var{output_url}. If not specified, the output is sent
+to stdout.
+
@end table
@c man end
diff --git a/fftools/ffprobe.c b/fftools/ffprobe.c
index c44297c1fa..4e2fdbaec8 100644
--- a/fftools/ffprobe.c
+++ b/fftools/ffprobe.c
@@ -281,6 +281,7 @@ static const OptionDef *options;
static const char *input_filename;
static const char *print_input_filename;
static const AVInputFormat *iformat = NULL;
+static const char *output_filename = NULL;
static struct AVHashContext *hash;
@@ -476,6 +477,12 @@ typedef struct Writer {
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
@@ -553,6 +560,10 @@ static void writer_close(WriterContext **wctx)
av_opt_free((*wctx)->priv);
av_freep(&((*wctx)->priv));
av_opt_free(*wctx);
+ if ((*wctx)->avio) {
+ avio_flush((*wctx)->avio);
+ avio_close((*wctx)->avio);
+ }
av_freep(wctx);
}
@@ -564,9 +575,46 @@ static void bprint_bytes(AVBPrint *bp, const uint8_t *ubuf, size_t ubuf_size)
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 struct section *sections, int nb_sections, const char *output)
{
int i, ret = 0;
@@ -637,6 +685,21 @@ static int writer_open(WriterContext **wctx, const Writer *writer, const char *a
}
}
+ 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);
@@ -904,6 +967,10 @@ static void writer_print_integers(WriterContext *wctx, const char *name,
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];
@@ -998,7 +1065,7 @@ static void default_print_section_header(WriterContext *wctx)
return;
if (!(section->flags & (SECTION_FLAG_IS_WRAPPER|SECTION_FLAG_IS_ARRAY)))
- printf("[%s]\n", upcase_string(buf, sizeof(buf), section->name));
+ writer_printf(wctx, "[%s]\n", upcase_string(buf, sizeof(buf), section->name));
}
static void default_print_section_footer(WriterContext *wctx)
@@ -1011,7 +1078,7 @@ static void default_print_section_footer(WriterContext *wctx)
return;
if (!(section->flags & (SECTION_FLAG_IS_WRAPPER|SECTION_FLAG_IS_ARRAY)))
- printf("[/%s]\n", upcase_string(buf, sizeof(buf), section->name));
+ 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)
@@ -1019,8 +1086,8 @@ static void default_print_str(WriterContext *wctx, const char *key, const char *
DefaultContext *def = wctx->priv;
if (!def->nokey)
- printf("%s%s=", wctx->section_pbuf[wctx->level].str, key);
- printf("%s\n", value);
+ 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, long long int value)
@@ -1028,8 +1095,8 @@ static void default_print_int(WriterContext *wctx, const char *key, long long in
DefaultContext *def = wctx->priv;
if (!def->nokey)
- printf("%s%s=", wctx->section_pbuf[wctx->level].str, key);
- printf("%lld\n", value);
+ writer_printf(wctx, "%s%s=", wctx->section_pbuf[wctx->level].str, key);
+ writer_printf(wctx, "%lld\n", value);
}
static const Writer default_writer = {
@@ -1171,10 +1238,10 @@ static void compact_print_section_header(WriterContext *wctx)
}
if (parent_section && !(parent_section->flags & (SECTION_FLAG_IS_WRAPPER|SECTION_FLAG_IS_ARRAY)) &&
wctx->level && wctx->nb_item[wctx->level-1])
- printf("%c", compact->item_sep);
+ writer_w8(wctx, compact->item_sep);
if (compact->print_section &&
!(section->flags & (SECTION_FLAG_IS_WRAPPER|SECTION_FLAG_IS_ARRAY)))
- printf("%s%c", section->name, compact->item_sep);
+ writer_printf(wctx, "%s%c", section->name, compact->item_sep);
}
}
@@ -1185,7 +1252,7 @@ static void compact_print_section_footer(WriterContext *wctx)
if (!compact->nested_section[wctx->level] &&
compact->terminate_line[wctx->level] &&
!(wctx->section[wctx->level]->flags & (SECTION_FLAG_IS_WRAPPER|SECTION_FLAG_IS_ARRAY)))
- printf("\n");
+ writer_w8(wctx, '\n');
}
static void compact_print_str(WriterContext *wctx, const char *key, const char *value)
@@ -1193,11 +1260,11 @@ static void compact_print_str(WriterContext *wctx, const char *key, const char *
CompactContext *compact = wctx->priv;
AVBPrint buf;
- if (wctx->nb_item[wctx->level]) printf("%c", compact->item_sep);
+ if (wctx->nb_item[wctx->level]) writer_w8(wctx, compact->item_sep);
if (!compact->nokey)
- printf("%s%s=", wctx->section_pbuf[wctx->level].str, key);
+ writer_printf(wctx, "%s%s=", wctx->section_pbuf[wctx->level].str, key);
av_bprint_init(&buf, 1, AV_BPRINT_SIZE_UNLIMITED);
- printf("%s", compact->escape_str(&buf, value, compact->item_sep, wctx));
+ writer_put_str(wctx, compact->escape_str(&buf, value, compact->item_sep, wctx));
av_bprint_finalize(&buf, NULL);
}
@@ -1205,10 +1272,10 @@ static void compact_print_int(WriterContext *wctx, const char *key, long long in
{
CompactContext *compact = wctx->priv;
- if (wctx->nb_item[wctx->level]) printf("%c", compact->item_sep);
+ if (wctx->nb_item[wctx->level]) writer_w8(wctx, compact->item_sep);
if (!compact->nokey)
- printf("%s%s=", wctx->section_pbuf[wctx->level].str, key);
- printf("%lld", value);
+ writer_printf(wctx, "%s%s=", wctx->section_pbuf[wctx->level].str, key);
+ writer_printf(wctx, "%lld", value);
}
static const Writer compact_writer = {
@@ -1351,7 +1418,7 @@ static void flat_print_section_header(WriterContext *wctx)
static void flat_print_int(WriterContext *wctx, const char *key, long long int value)
{
- printf("%s%s=%lld\n", wctx->section_pbuf[wctx->level].str, key, value);
+ writer_printf(wctx, "%s%s=%lld\n", wctx->section_pbuf[wctx->level].str, key, value);
}
static void flat_print_str(WriterContext *wctx, const char *key, const char *value)
@@ -1359,11 +1426,11 @@ static void flat_print_str(WriterContext *wctx, const char *key, const char *val
FlatContext *flat = wctx->priv;
AVBPrint buf;
- printf("%s", wctx->section_pbuf[wctx->level].str);
+ writer_put_str(wctx, wctx->section_pbuf[wctx->level].str);
av_bprint_init(&buf, 1, AV_BPRINT_SIZE_UNLIMITED);
- printf("%s=", flat_escape_key_str(&buf, key, flat->sep));
+ writer_printf(wctx, "%s=", flat_escape_key_str(&buf, key, flat->sep));
av_bprint_clear(&buf);
- printf("\"%s\"\n", flat_escape_value_str(&buf, value));
+ writer_printf(wctx, "\"%s\"\n", flat_escape_value_str(&buf, value));
av_bprint_finalize(&buf, NULL);
}
@@ -1433,12 +1500,12 @@ static void ini_print_section_header(WriterContext *wctx)
av_bprint_clear(buf);
if (!parent_section) {
- printf("# ffprobe output\n\n");
+ writer_put_str(wctx, "# ffprobe output\n\n");
return;
}
if (wctx->nb_item[wctx->level-1])
- printf("\n");
+ writer_w8(wctx, '\n');
av_bprintf(buf, "%s", wctx->section_pbuf[wctx->level-1].str);
if (ini->hierarchical ||
@@ -1453,7 +1520,7 @@ static void ini_print_section_header(WriterContext *wctx)
}
if (!(section->flags & (SECTION_FLAG_IS_ARRAY|SECTION_FLAG_IS_WRAPPER)))
- printf("[%s]\n", buf->str);
+ writer_printf(wctx, "[%s]\n", buf->str);
}
static void ini_print_str(WriterContext *wctx, const char *key, const char *value)
@@ -1461,15 +1528,15 @@ static void ini_print_str(WriterContext *wctx, const char *key, const char *valu
AVBPrint buf;
av_bprint_init(&buf, 1, AV_BPRINT_SIZE_UNLIMITED);
- printf("%s=", ini_escape_str(&buf, key));
+ writer_printf(wctx, "%s=", ini_escape_str(&buf, key));
av_bprint_clear(&buf);
- printf("%s\n", ini_escape_str(&buf, value));
+ 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, long long int value)
{
- printf("%s=%lld\n", key, value);
+ writer_printf(wctx, "%s=%lld\n", key, value);
}
static const Writer ini_writer = {
@@ -1532,7 +1599,7 @@ static const char *json_escape_str(AVBPrint *dst, const char *src, void *log_ctx
return dst->str;
}
-#define JSON_INDENT() printf("%*c", json->indent_level * 4, ' ')
+#define JSON_INDENT() writer_printf(wctx, "%*c", json->indent_level * 4, ' ')
static void json_print_section_header(WriterContext *wctx)
{
@@ -1543,10 +1610,10 @@ static void json_print_section_header(WriterContext *wctx)
wctx->section[wctx->level-1] : NULL;
if (wctx->level && wctx->nb_item[wctx->level-1])
- printf(",\n");
+ writer_put_str(wctx, ",\n");
if (section->flags & SECTION_FLAG_IS_WRAPPER) {
- printf("{\n");
+ writer_put_str(wctx, "{\n");
json->indent_level++;
} else {
av_bprint_init(&buf, 1, AV_BPRINT_SIZE_UNLIMITED);
@@ -1555,17 +1622,17 @@ static void json_print_section_header(WriterContext *wctx)
json->indent_level++;
if (section->flags & SECTION_FLAG_IS_ARRAY) {
- printf("\"%s\": [\n", buf.str);
+ writer_printf(wctx, "\"%s\": [\n", buf.str);
} else if (parent_section && !(parent_section->flags & SECTION_FLAG_IS_ARRAY)) {
- printf("\"%s\": {%s", buf.str, json->item_start_end);
+ writer_printf(wctx, "\"%s\": {%s", buf.str, json->item_start_end);
} else {
- printf("{%s", json->item_start_end);
+ 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();
- printf("\"type\": \"%s\"", section->name);
+ writer_printf(wctx, "\"type\": \"%s\"", section->name);
wctx->nb_item[wctx->level]++;
}
}
@@ -1580,18 +1647,18 @@ static void json_print_section_footer(WriterContext *wctx)
if (wctx->level == 0) {
json->indent_level--;
- printf("\n}\n");
+ writer_put_str(wctx, "\n}\n");
} else if (section->flags & SECTION_FLAG_IS_ARRAY) {
- printf("\n");
+ writer_w8(wctx, '\n');
json->indent_level--;
JSON_INDENT();
- printf("]");
+ writer_w8(wctx, ']');
} else {
- printf("%s", json->item_start_end);
+ writer_put_str(wctx, json->item_start_end);
json->indent_level--;
if (!json->compact)
JSON_INDENT();
- printf("}");
+ writer_w8(wctx, '}');
}
}
@@ -1601,9 +1668,9 @@ static inline void json_print_item_str(WriterContext *wctx,
AVBPrint buf;
av_bprint_init(&buf, 1, AV_BPRINT_SIZE_UNLIMITED);
- printf("\"%s\":", json_escape_str(&buf, key, wctx));
+ writer_printf(wctx, "\"%s\":", json_escape_str(&buf, key, wctx));
av_bprint_clear(&buf);
- printf(" \"%s\"", json_escape_str(&buf, value, wctx));
+ writer_printf(wctx, " \"%s\"", json_escape_str(&buf, value, wctx));
av_bprint_finalize(&buf, NULL);
}
@@ -1614,7 +1681,7 @@ static void json_print_str(WriterContext *wctx, const char *key, const char *val
wctx->section[wctx->level-1] : NULL;
if (wctx->nb_item[wctx->level] || (parent_section && parent_section->id == SECTION_ID_PACKETS_AND_FRAMES))
- printf("%s", json->item_sep);
+ writer_put_str(wctx, json->item_sep);
if (!json->compact)
JSON_INDENT();
json_print_item_str(wctx, key, value);
@@ -1628,12 +1695,12 @@ static void json_print_int(WriterContext *wctx, const char *key, long long int v
AVBPrint buf;
if (wctx->nb_item[wctx->level] || (parent_section && parent_section->id == SECTION_ID_PACKETS_AND_FRAMES))
- printf("%s", json->item_sep);
+ writer_put_str(wctx, json->item_sep);
if (!json->compact)
JSON_INDENT();
av_bprint_init(&buf, 1, AV_BPRINT_SIZE_UNLIMITED);
- printf("\"%s\": %lld", json_escape_str(&buf, key, wctx), value);
+ writer_printf(wctx, "\"%s\": %lld", json_escape_str(&buf, key, wctx), value);
av_bprint_finalize(&buf, NULL);
}
@@ -1693,7 +1760,7 @@ static av_cold int xml_init(WriterContext *wctx)
return 0;
}
-#define XML_INDENT() printf("%*c", xml->indent_level * 4, ' ')
+#define XML_INDENT() writer_printf(wctx, "%*c", xml->indent_level * 4, ' ')
static void xml_print_section_header(WriterContext *wctx)
{
@@ -1707,8 +1774,8 @@ static void xml_print_section_header(WriterContext *wctx)
"xmlns:ffprobe=\"http://www.ffmpeg.org/schema/ffprobe\" "
"xsi:schemaLocation=\"http://www.ffmpeg.org/schema/ffprobe ffprobe.xsd\"";
- printf("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
- printf("<%sffprobe%s>\n",
+ 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;
@@ -1716,20 +1783,20 @@ static void xml_print_section_header(WriterContext *wctx)
if (xml->within_tag) {
xml->within_tag = 0;
- printf(">\n");
+ writer_put_str(wctx, ">\n");
}
if (section->flags & SECTION_FLAG_HAS_VARIABLE_FIELDS) {
xml->indent_level++;
} else {
if (parent_section && (parent_section->flags & SECTION_FLAG_IS_WRAPPER) &&
wctx->level && wctx->nb_item[wctx->level-1])
- printf("\n");
+ writer_w8(wctx, '\n');
xml->indent_level++;
if (section->flags & SECTION_FLAG_IS_ARRAY) {
- XML_INDENT(); printf("<%s>\n", section->name);
+ XML_INDENT(); writer_printf(wctx, "<%s>\n", section->name);
} else {
- XML_INDENT(); printf("<%s ", section->name);
+ XML_INDENT(); writer_printf(wctx, "<%s ", section->name);
xml->within_tag = 1;
}
}
@@ -1741,15 +1808,15 @@ static void xml_print_section_footer(WriterContext *wctx)
const struct section *section = wctx->section[wctx->level];
if (wctx->level == 0) {
- printf("</%sffprobe>\n", xml->fully_qualified ? "ffprobe:" : "");
+ writer_printf(wctx, "</%sffprobe>\n", xml->fully_qualified ? "ffprobe:" : "");
} else if (xml->within_tag) {
xml->within_tag = 0;
- printf("/>\n");
+ writer_put_str(wctx, "/>\n");
xml->indent_level--;
} else if (section->flags & SECTION_FLAG_HAS_VARIABLE_FIELDS) {
xml->indent_level--;
} else {
- XML_INDENT(); printf("</%s>\n", section->name);
+ XML_INDENT(); writer_printf(wctx, "</%s>\n", section->name);
xml->indent_level--;
}
}
@@ -1766,20 +1833,20 @@ static void xml_print_str(WriterContext *wctx, const char *key, const char *valu
XML_INDENT();
av_bprint_escape(&buf, key, NULL,
AV_ESCAPE_MODE_XML, AV_ESCAPE_FLAG_XML_DOUBLE_QUOTES);
- printf("<%s key=\"%s\"",
- section->element_name, buf.str);
+ writer_printf(wctx, "<%s key=\"%s\"",
+ section->element_name, buf.str);
av_bprint_clear(&buf);
av_bprint_escape(&buf, value, NULL,
AV_ESCAPE_MODE_XML, AV_ESCAPE_FLAG_XML_DOUBLE_QUOTES);
- printf(" value=\"%s\"/>\n", buf.str);
+ writer_printf(wctx, " value=\"%s\"/>\n", buf.str);
} else {
if (wctx->nb_item[wctx->level])
- printf(" ");
+ writer_w8(wctx, ' ');
av_bprint_escape(&buf, value, NULL,
AV_ESCAPE_MODE_XML, AV_ESCAPE_FLAG_XML_DOUBLE_QUOTES);
- printf("%s=\"%s\"", key, buf.str);
+ writer_printf(wctx, "%s=\"%s\"", key, buf.str);
}
av_bprint_finalize(&buf, NULL);
@@ -1788,8 +1855,8 @@ static void xml_print_str(WriterContext *wctx, const char *key, const char *valu
static void xml_print_int(WriterContext *wctx, const char *key, long long int value)
{
if (wctx->nb_item[wctx->level])
- printf(" ");
- printf("%s=\"%lld\"", key, value);
+ writer_w8(wctx, ' ');
+ writer_printf(wctx, "%s=\"%lld\"", key, value);
}
static Writer xml_writer = {
@@ -3642,6 +3709,25 @@ static int opt_input_file_i(void *optctx, const char *opt, const char *arg)
return 0;
}
+static void opt_output_file(void *optctx, const char *arg)
+{
+ if (output_filename) {
+ av_log(NULL, AV_LOG_ERROR,
+ "Argument '%s' provided as output filename, but '%s' was already specified.\n",
+ arg, output_filename);
+ exit_program(1);
+ }
+ if (!strcmp(arg, "-"))
+ arg = "pipe:";
+ output_filename = arg;
+}
+
+static int opt_output_file_o(void *optctx, const char *opt, const char *arg)
+{
+ opt_output_file(optctx, arg);
+ return 0;
+}
+
static int opt_print_filename(void *optctx, const char *opt, const char *arg)
{
print_input_filename = arg;
@@ -3904,6 +3990,7 @@ static const OptionDef real_options[] = {
{ "bitexact", OPT_BOOL, {&do_bitexact}, "force bitexact output" },
{ "read_intervals", HAS_ARG, {.func_arg = opt_read_intervals}, "set read intervals", "read_intervals" },
{ "i", HAS_ARG, {.func_arg = opt_input_file_i}, "read specified file", "input_file"},
+ { "o", HAS_ARG, {.func_arg = opt_output_file_o}, "write to specified output", "output_file"},
{ "print_filename", HAS_ARG, {.func_arg = opt_print_filename}, "override the printed input filename", "print_file"},
{ "find_stream_info", OPT_BOOL | OPT_INPUT | OPT_EXPERT, { &find_stream_info },
"read and decode the streams to fill missing information with heuristics" },
@@ -4031,7 +4118,7 @@ int main(int argc, char **argv)
}
if ((ret = writer_open(&wctx, w, w_args,
- sections, FF_ARRAY_ELEMS(sections))) >= 0) {
+ 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;
--
2.25.1
[-- Attachment #3: 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] 9+ messages in thread
* Re: [FFmpeg-devel] [PATCH 1/2] lavf/avio: add avio_vprintf()
2022-06-12 15:32 ` Stefano Sabatini
@ 2022-06-12 17:00 ` Nicolas George
2022-06-16 16:23 ` Soft Works
0 siblings, 1 reply; 9+ messages in thread
From: Nicolas George @ 2022-06-12 17:00 UTC (permalink / raw)
To: FFmpeg development discussions and patches
[-- Attachment #1.1: Type: text/plain, Size: 472 bytes --]
Stefano Sabatini (12022-06-12):
> Updated.
Hi. Since it is somewhat related, I would appreciate if you gave your
opinion on the option of having a good string API in FFmpeg:
https://ffmpeg.org/pipermail/ffmpeg-devel/2021-December/290226.html
Eventually, I would like to have the more generic writers from ffprobe
(JSON, XML) in lavu to be used by diagnostic filters. But I will not be
doing that with pedestrian strings.
Regards,
--
Nicolas George
[-- Attachment #1.2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 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] 9+ messages in thread
* Re: [FFmpeg-devel] [PATCH 2/2] ffprobe: add -o option
2022-06-12 15:33 ` Stefano Sabatini
@ 2022-06-13 20:47 ` Marton Balint
0 siblings, 0 replies; 9+ messages in thread
From: Marton Balint @ 2022-06-13 20:47 UTC (permalink / raw)
To: FFmpeg development discussions and patches
On Sun, 12 Jun 2022, Stefano Sabatini wrote:
> On date Thursday 2022-06-09 21:09:02 +0200, Marton Balint wrote:
>> On Sun, 3 Apr 2022, Stefano Sabatini wrote:
> [...]
>>> Updated again, now it's locally passing fate with FATE samples (don't
>>> remember if other issues were spotted the past time).
>>
>> This looks good to me in general, so I intend to apply. One thing that we
>> might do is to keep writing to the standard output if no output file is
>> specified instead of using the special "pipe:" URL. This way ffprobe keeps
>> working even if the pipe protocol is not compiled into ffmpeg/libavformat.
>
> Sounds good, patch updated accordingly.
Thanks, applied the series.
Regards,
Marton
_______________________________________________
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] 9+ messages in thread
* Re: [FFmpeg-devel] [PATCH 1/2] lavf/avio: add avio_vprintf()
2022-06-12 17:00 ` Nicolas George
@ 2022-06-16 16:23 ` Soft Works
0 siblings, 0 replies; 9+ messages in thread
From: Soft Works @ 2022-06-16 16:23 UTC (permalink / raw)
To: FFmpeg development discussions and patches
> -----Original Message-----
> From: ffmpeg-devel <ffmpeg-devel-bounces@ffmpeg.org> On Behalf Of
> Nicolas George
> Sent: Sunday, June 12, 2022 7:01 PM
> To: FFmpeg development discussions and patches <ffmpeg-
> devel@ffmpeg.org>
> Subject: Re: [FFmpeg-devel] [PATCH 1/2] lavf/avio: add avio_vprintf()
>
> Stefano Sabatini (12022-06-12):
> > Updated.
>
> Hi. Since it is somewhat related, I would appreciate if you gave your
> opinion on the option of having a good string API in FFmpeg:
>
> https://ffmpeg.org/pipermail/ffmpeg-devel/2021-December/290226.html
>
> Eventually, I would like to have the more generic writers from
> ffprobe
> (JSON, XML) in lavu to be used by diagnostic filters. But I will not
> be
> doing that with pedestrian strings.
Hi,
as mentioned a while ago, I am quite interested in this and I would be
glad when it would be possible to find a way for going forward.
My primary interest would be the generalization of ffprobe string
writing code, from which I have two duplicates by now. I had put further
work on hold as I became aware that were plans or proposals for this.
Now I've read your "Intro to AVWriter" from April 2021 and I have some
questions.
> ## Scenario 2: Concatenating the string into a message.
>
> Let us say you have two foobars to present to the user. Good old C:
>
> char msg[2500], foo1_buf[1000], foo2_buf[1000];
> av_foobar_to_string(foo1_buf, sizeof(foo1_buf), foo1);
> av_foobar_to_string(foo2_buf, sizeof(foo2_buf), foo2);
> snprintf(msg, sizeof(msg), "F%d = [ %s, %s ]", num, foo1_buf, foo2_buf);
>
> But it's ugly. Less ugly, but more complicated:
[skip that version]
> Well, that was the first thing AVWriter was meant to do: allow to build
> strings by concatenating them together. So, the AVWraper version of this
> code:
>
> char msg[2500];
> AVWriter wr = av_buf_writer_array(msg);
> av_writer_printf(wr, "F%d = [ ", num);
> av_foobar_write(wr, foo1);
> av_writer_print(wr, ", ");
> av_foobar_write(wr, foo2);
> av_writer_print(wr, " ]");
There are cases where it might be preferable to subsequently append to
a buffer like that, but it requires many lines of code and it's not as
easy to get a picture of how the produced string will actually look like.
Maybe you meant it just as one possible example to use AVWriter, but in
this context it looks like as if that's the supposed way to replace the
"Good old C" version?
When you would ask me which code I would _wish_ to be able to write
in this example case, then it would be this:
char msg[2500];
snprintf(msg, sizeof(msg), "F%d = [ %s, %s ]", num, foo1, foo2);
Of course it doesn't need to be snprintf, it could also be av_xprintf().
It would also be fine to have some macro around those params like
XX(foo1). Or a custom format specifier would also be fine.
Basically I think there are a number of possible ways, but I'm not sure
whether this would be possible with regards to the automatisms you
are planning to checking for a matching string conversion function?
This might be a tough one: it would be cool when this could be used
in av_log() calls for logging, but in this case it would be of course
required that the string writing will be performed upstream, only when
the log level condition would be satisfied. Could that even work?
PS: Yes, I have read it to the end; the mentioned av_writer_fmt()
might be related to what I'm asking, but I wasn't sure.
Thanks,
softworkz
_______________________________________________
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] 9+ messages in thread
end of thread, other threads:[~2022-06-16 16:24 UTC | newest]
Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
[not found] <20210418213058.24475-1-stefasab@gmail.com>
[not found] ` <20210421215335.GC12140@mariano>
2022-04-03 14:03 ` [FFmpeg-devel] [PATCH 1/2] lavf/avio: add avio_vprintf() Stefano Sabatini
2022-06-09 19:03 ` Marton Balint
2022-06-12 15:32 ` Stefano Sabatini
2022-06-12 17:00 ` Nicolas George
2022-06-16 16:23 ` Soft Works
[not found] ` <20210418213058.24475-2-stefasab@gmail.com>
[not found] ` <20210419092649.GJ4777@pb2>
[not found] ` <20210421215704.GD12140@mariano>
2022-04-03 14:06 ` [FFmpeg-devel] [PATCH 2/2] ffprobe: add -o option Stefano Sabatini
2022-06-09 19:09 ` Marton Balint
2022-06-12 15:33 ` Stefano Sabatini
2022-06-13 20:47 ` Marton Balint
Git Inbox Mirror of the ffmpeg-devel mailing list - see https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
This inbox may be cloned and mirrored by anyone:
git clone --mirror https://master.gitmailbox.com/ffmpegdev/0 ffmpegdev/git/0.git
# If you have public-inbox 1.1+ installed, you may
# initialize and index your mirror using the following commands:
public-inbox-init -V2 ffmpegdev ffmpegdev/ https://master.gitmailbox.com/ffmpegdev \
ffmpegdev@gitmailbox.com
public-inbox-index ffmpegdev
Example config snippet for mirrors.
AGPL code for this site: git clone https://public-inbox.org/public-inbox.git