[FFmpeg-devel] [PATCH] Added pipe output to metadata filter

sami.hult at gmail.com sami.hult at gmail.com
Wed Jun 22 15:26:24 CEST 2016


From: Sami Hult <sami.hult at gmail.com>

I added option mode=pipe which accepts file=(file descriptor) option. This way multiple streams can for example be silencedetected and the result directed to different outputs.

Example:

ffmpeg -i test.wav -filter_complex "silencedetect=n=-40dB:d=0.1,ametadata=mode=pipe:file=4" -f null - 4> test.txt

Also at the same time I converted mode=file output to avio.


Signed-off-by: Sami Hult <sami.hult at gmail.com>
---
 Changelog                |  1 +
 libavfilter/f_metadata.c | 52 +++++++++++++++++++++++++++++++-----------------
 2 files changed, 35 insertions(+), 18 deletions(-)

diff --git a/Changelog b/Changelog
index f6016f4..4909abf 100644
--- a/Changelog
+++ b/Changelog
@@ -42,6 +42,7 @@ version <next>:
 - OpenExr improvements (tile data and B44/B44A support)
 - BitJazz SheerVideo decoder
 - CUDA CUVID H264/HEVC decoder
+- Pipe output to metadata filter
 
 
 version 3.0:
diff --git a/libavfilter/f_metadata.c b/libavfilter/f_metadata.c
index ab07ccf..aa9fb92 100644
--- a/libavfilter/f_metadata.c
+++ b/libavfilter/f_metadata.c
@@ -31,6 +31,7 @@
 #include "libavutil/internal.h"
 #include "libavutil/opt.h"
 #include "libavutil/timestamp.h"
+#include "libavformat/avio.h"
 #include "avfilter.h"
 #include "audio.h"
 #include "formats.h"
@@ -43,6 +44,7 @@ enum MetadataMode {
     METADATA_MODIFY,
     METADATA_DELETE,
     METADATA_PRINT,
+    METADATA_PIPE,
     METADATA_NB
 };
 
@@ -80,7 +82,7 @@ typedef struct MetadataContext {
     AVExpr *expr;
     double var_values[VAR_VARS_NB];
 
-    FILE *file;
+    AVIOContext* avio_context;
     char *file_str;
 
     int (*compare)(struct MetadataContext *s,
@@ -97,6 +99,7 @@ static const AVOption filt_name##_options[] = { \
     {   "modify", "modify metadata",     0,              AV_OPT_TYPE_CONST,  {.i64 = METADATA_MODIFY }, 0, 0, FLAGS, "mode" }, \
     {   "delete", "delete metadata",     0,              AV_OPT_TYPE_CONST,  {.i64 = METADATA_DELETE }, 0, 0, FLAGS, "mode" }, \
     {   "print",  "print metadata",      0,              AV_OPT_TYPE_CONST,  {.i64 = METADATA_PRINT },  0, 0, FLAGS, "mode" }, \
+    {   "pipe",   "pipe metadata",       0,              AV_OPT_TYPE_CONST,  {.i64 = METADATA_PIPE },   0, 0, FLAGS, "mode" }, \
     { "key",   "set metadata key",       OFFSET(key),    AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, FLAGS }, \
     { "value", "set metadata value",     OFFSET(value),  AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, FLAGS }, \
     { "function", "function for comparing values", OFFSET(function), AV_OPT_TYPE_INT, {.i64 = 0 }, 0, METADATAF_NB-1, FLAGS, "function" }, \
@@ -180,17 +183,21 @@ static void print_file(AVFilterContext *ctx, const char *msg, ...)
     va_list argument_list;
 
     va_start(argument_list, msg);
-    if (msg)
-        vfprintf(s->file, msg, argument_list);
+    if (msg) {
+        char buf[128];
+        vsnprintf(buf, sizeof(buf), msg, argument_list);
+        avio_printf(s->avio_context, buf);
+    }
     va_end(argument_list);
 }
 
 static av_cold int init(AVFilterContext *ctx)
 {
     MetadataContext *s = ctx->priv;
+    char *url = NULL;
     int ret;
 
-    if (!s->key && s->mode != METADATA_PRINT) {
+    if (!s->key && s->mode != METADATA_PRINT && s->mode != METADATA_PIPE) {
         av_log(ctx, AV_LOG_WARNING, "Metadata key must be set\n");
         return AVERROR(EINVAL);
     }
@@ -236,25 +243,33 @@ static av_cold int init(AVFilterContext *ctx)
         }
     }
 
-    if (s->file_str) {
+    if (s->mode == METADATA_PIPE) {
+        url = av_asprintf("pipe:%s", s->file_str);
+        s->print = print_file;
+    } else if (s->mode == METADATA_PRINT) {
         if (!strcmp(s->file_str, "-")) {
-            s->file = stdout;
+            url = av_asprintf("pipe:1");
         } else {
-            s->file = fopen(s->file_str, "w");
-            if (!s->file) {
-                int err = AVERROR(errno);
-                char buf[128];
-                av_strerror(err, buf, sizeof(buf));
-                av_log(ctx, AV_LOG_ERROR, "Could not open file %s: %s\n",
-                       s->file_str, buf);
-                return err;
-            }
+            url = av_asprintf("file:%s", s->file_str);
         }
         s->print = print_file;
     } else {
         s->print = print_log;
     }
 
+    s->avio_context = NULL;
+    if (url) {
+        ret = avio_open(&s->avio_context, url, AVIO_FLAG_WRITE);
+        if (ret < 0) {
+            char buf[128];
+            av_strerror(ret, buf, sizeof(buf));
+            av_log(ctx, AV_LOG_ERROR, "Could not open %s: %s\n",
+                   url, buf);
+            return ret;
+        }
+        av_free(url);
+    }
+
     return 0;
 }
 
@@ -262,9 +277,9 @@ static av_cold void uninit(AVFilterContext *ctx)
 {
     MetadataContext *s = ctx->priv;
 
-    if (s->file && s->file != stdout)
-        fclose(s->file);
-    s->file = NULL;
+    if (s->avio_context) {
+        avio_closep(&s->avio_context);
+    }
 }
 
 static int filter_frame(AVFilterLink *inlink, AVFrame *frame)
@@ -305,6 +320,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *frame)
         return ff_filter_frame(outlink, frame);
         break;
     case METADATA_PRINT:
+    case METADATA_PIPE:
         if (!s->key && e) {
             s->print(ctx, "frame:%-4"PRId64" pts:%-7s pts_time:%-7s\n",
                      inlink->frame_count, av_ts2str(frame->pts), av_ts2timestr(frame->pts, &inlink->time_base));
-- 
2.1.4



More information about the ffmpeg-devel mailing list