Browse code

avfilter/f_metadata: add support for file output

Signed-off-by: Tobias Rapp <t.rapp@noa-archive.com>

Tobias Rapp authored on 2016/02/11 21:35:21
Showing 2 changed files
... ...
@@ -8526,6 +8526,12 @@ Float representation of @code{value} from metadata key.
8526 8526
 @item VALUE2
8527 8527
 Float representation of @code{value} as supplied by user in @code{value} option.
8528 8528
 @end table
8529
+
8530
+@item file
8531
+If specified in @code{print} mode, output is written to the named file. When
8532
+filename equals "-" data is written to standard output.
8533
+If @code{file} option is not set, output is written to the log with AV_LOG_INFO
8534
+loglevel.
8529 8535
 @end table
8530 8536
 
8531 8537
 @subsection Examples
... ...
@@ -81,8 +81,12 @@ typedef struct MetadataContext {
81 81
     AVExpr *expr;
82 82
     double var_values[VAR_VARS_NB];
83 83
 
84
+    FILE *file;
85
+    char *file_str;
86
+
84 87
     int (*compare)(struct MetadataContext *s,
85 88
                    const char *value1, const char *value2, size_t length);
89
+    void (*print)(AVFilterContext *ctx, const char *msg, ...) av_printf_format(2, 3);
86 90
 } MetadataContext;
87 91
 
88 92
 #define OFFSET(x) offsetof(MetadataContext, x)
... ...
@@ -104,6 +108,7 @@ static const AVOption filt_name##_options[] = {                     \
104 104
     {   "expr",    NULL, 0, AV_OPT_TYPE_CONST, {.i64 = METADATAF_EXPR    }, 0, 3, FLAGS, "function" }, \
105 105
     { "expr", "set expression for expr function", OFFSET(expr_str), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, FLAGS }, \
106 106
     { "length", "compare up to N chars for string function", OFFSET(length), AV_OPT_TYPE_INT,    {.i64 = INT_MAX }, 1, INT_MAX, FLAGS }, \
107
+    { "file", "set file where to print metadata information", OFFSET(file_str), AV_OPT_TYPE_STRING, {.str=NULL}, 0, 0, FLAGS }, \
107 108
     { NULL }                                                            \
108 109
 }
109 110
 
... ...
@@ -155,6 +160,27 @@ static int parse_expr(MetadataContext *s, const char *value1, const char *value2
155 155
     return av_expr_eval(s->expr, s->var_values, NULL);
156 156
 }
157 157
 
158
+static void print_log(AVFilterContext *ctx, const char *msg, ...)
159
+{
160
+    va_list argument_list;
161
+
162
+    va_start(argument_list, msg);
163
+    if (msg)
164
+        av_vlog(ctx, AV_LOG_INFO, msg, argument_list);
165
+    va_end(argument_list);
166
+}
167
+
168
+static void print_file(AVFilterContext *ctx, const char *msg, ...)
169
+{
170
+    MetadataContext *s = ctx->priv;
171
+    va_list argument_list;
172
+
173
+    va_start(argument_list, msg);
174
+    if (msg)
175
+        vfprintf(s->file, msg, argument_list);
176
+    va_end(argument_list);
177
+}
178
+
158 179
 static av_cold int init(AVFilterContext *ctx)
159 180
 {
160 181
     MetadataContext *s = ctx->priv;
... ...
@@ -203,9 +229,37 @@ static av_cold int init(AVFilterContext *ctx)
203 203
         }
204 204
     }
205 205
 
206
+    if (s->file_str) {
207
+        if (!strcmp(s->file_str, "-")) {
208
+            s->file = stdout;
209
+        } else {
210
+            s->file = fopen(s->file_str, "w");
211
+            if (!s->file) {
212
+                int err = AVERROR(errno);
213
+                char buf[128];
214
+                av_strerror(err, buf, sizeof(buf));
215
+                av_log(ctx, AV_LOG_ERROR, "Could not open file %s: %s\n",
216
+                       s->file_str, buf);
217
+                return err;
218
+            }
219
+        }
220
+        s->print = print_file;
221
+    } else {
222
+        s->print = print_log;
223
+    }
224
+
206 225
     return 0;
207 226
 }
208 227
 
228
+static av_cold void uninit(AVFilterContext *ctx)
229
+{
230
+    MetadataContext *s = ctx->priv;
231
+
232
+    if (s->file && s->file != stdout)
233
+        fclose(s->file);
234
+    s->file = NULL;
235
+}
236
+
209 237
 static int filter_frame(AVFilterLink *inlink, AVFrame *frame)
210 238
 {
211 239
     AVFilterContext *ctx = inlink->dst;
... ...
@@ -245,14 +299,14 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *frame)
245 245
         break;
246 246
     case METADATA_PRINT:
247 247
         if (!s->key && e) {
248
-            av_log(ctx, AV_LOG_INFO, "frame %"PRId64" pts %"PRId64"\n", inlink->frame_count, frame->pts);
249
-            av_log(ctx, AV_LOG_INFO, "%s=%s\n", e->key, e->value);
248
+            s->print(ctx, "frame %"PRId64" pts %"PRId64"\n", inlink->frame_count, frame->pts);
249
+            s->print(ctx, "%s=%s\n", e->key, e->value);
250 250
             while ((e = av_dict_get(metadata, "", e, AV_DICT_IGNORE_SUFFIX)) != NULL) {
251
-                av_log(ctx, AV_LOG_INFO, "%s=%s\n", e->key, e->value);
251
+                s->print(ctx, "%s=%s\n", e->key, e->value);
252 252
             }
253 253
         } else if (e && e->value && (!s->value || (e->value && s->compare(s, e->value, s->value, s->length)))) {
254
-            av_log(ctx, AV_LOG_INFO, "frame %"PRId64" pts %"PRId64"\n", inlink->frame_count, frame->pts);
255
-            av_log(ctx, AV_LOG_INFO, "%s=%s\n", s->key, e->value);
254
+            s->print(ctx, "frame %"PRId64" pts %"PRId64"\n", inlink->frame_count, frame->pts);
255
+            s->print(ctx, "%s=%s\n", s->key, e->value);
256 256
         }
257 257
         return ff_filter_frame(outlink, frame);
258 258
         break;
... ...
@@ -301,6 +355,7 @@ AVFilter ff_af_ametadata = {
301 301
     .priv_size     = sizeof(MetadataContext),
302 302
     .priv_class    = &ametadata_class,
303 303
     .init          = init,
304
+    .uninit        = uninit,
304 305
     .query_formats = ff_query_formats_all,
305 306
     .inputs        = ainputs,
306 307
     .outputs       = aoutputs,
... ...
@@ -336,6 +391,7 @@ AVFilter ff_vf_metadata = {
336 336
     .priv_size   = sizeof(MetadataContext),
337 337
     .priv_class  = &metadata_class,
338 338
     .init        = init,
339
+    .uninit      = uninit,
339 340
     .inputs      = inputs,
340 341
     .outputs     = outputs,
341 342
     .flags       = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC,