Browse code

lavfi/overlay: add process_command callback

Stefano Sabatini authored on 2013/02/20 08:15:36
Showing 3 changed files
... ...
@@ -4279,7 +4279,8 @@ Set when the expressions for @option{x}, @option{y}, and
4279 4279
 It accepts the following values:
4280 4280
 @table @samp
4281 4281
 @item init
4282
-only evaluate expressions once during the filter initialization
4282
+only evaluate expressions once during the filter initialization or
4283
+when a command is processed
4283 4284
 
4284 4285
 @item frame
4285 4286
 evaluate expressions for each incoming frame
... ...
@@ -4360,6 +4361,20 @@ the @var{movie} filter.
4360 4360
 You can chain together more overlays but you should test the
4361 4361
 efficiency of such approach.
4362 4362
 
4363
+@subsection Commands
4364
+
4365
+This filter supports the following command:
4366
+@table @option
4367
+@item x
4368
+Set the @option{x} option expression.
4369
+
4370
+@item y
4371
+Set the @option{y} option expression.
4372
+
4373
+@item enable
4374
+Set the @option{enable} option expression.
4375
+@end table
4376
+
4363 4377
 @subsection Examples
4364 4378
 
4365 4379
 @itemize
... ...
@@ -30,7 +30,7 @@
30 30
 
31 31
 #define LIBAVFILTER_VERSION_MAJOR  3
32 32
 #define LIBAVFILTER_VERSION_MINOR  50
33
-#define LIBAVFILTER_VERSION_MICRO 102
33
+#define LIBAVFILTER_VERSION_MICRO 103
34 34
 
35 35
 #define LIBAVFILTER_VERSION_INT AV_VERSION_INT(LIBAVFILTER_VERSION_MAJOR, \
36 36
                                                LIBAVFILTER_VERSION_MINOR, \
... ...
@@ -164,6 +164,74 @@ static av_cold void uninit(AVFilterContext *ctx)
164 164
     av_expr_free(over->enable_pexpr); over->enable_pexpr = NULL;
165 165
 }
166 166
 
167
+static inline int normalize_xy(double d, int chroma_sub)
168
+{
169
+    if (isnan(d))
170
+        return INT_MAX;
171
+    return (int)d & ~((1 << chroma_sub) - 1);
172
+}
173
+
174
+enum EvalTarget { EVAL_XY, EVAL_ENABLE, EVAL_ALL };
175
+
176
+static void eval_expr(AVFilterContext *ctx, enum EvalTarget eval_tgt)
177
+{
178
+    OverlayContext  *over = ctx->priv;
179
+
180
+    if (eval_tgt == EVAL_XY || eval_tgt == EVAL_ALL) {
181
+        over->var_values[VAR_X] = av_expr_eval(over->x_pexpr, over->var_values, NULL);
182
+        over->var_values[VAR_Y] = av_expr_eval(over->y_pexpr, over->var_values, NULL);
183
+        over->var_values[VAR_X] = av_expr_eval(over->x_pexpr, over->var_values, NULL);
184
+        over->x = normalize_xy(over->var_values[VAR_X], over->hsub);
185
+        over->y = normalize_xy(over->var_values[VAR_Y], over->vsub);
186
+    }
187
+    if (eval_tgt == EVAL_ENABLE || eval_tgt == EVAL_ALL) {
188
+        over->enable = av_expr_eval(over->enable_pexpr, over->var_values, NULL);
189
+    }
190
+}
191
+
192
+static int set_expr(AVExpr **pexpr, const char *expr, void *log_ctx)
193
+{
194
+    int ret;
195
+
196
+    if (*pexpr)
197
+        av_expr_free(*pexpr);
198
+    *pexpr = NULL;
199
+    ret = av_expr_parse(pexpr, expr, var_names,
200
+                        NULL, NULL, NULL, NULL, 0, log_ctx);
201
+    if (ret < 0)
202
+        av_log(log_ctx, AV_LOG_ERROR,
203
+               "Error when evaluating the expression '%s'\n", expr);
204
+    return ret;
205
+}
206
+
207
+static int process_command(AVFilterContext *ctx, const char *cmd, const char *args,
208
+                           char *res, int res_len, int flags)
209
+{
210
+    OverlayContext *over = ctx->priv;
211
+    int ret;
212
+
213
+    if      (!strcmp(cmd, "x"))
214
+        ret = set_expr(&over->x_pexpr, args, ctx);
215
+    else if (!strcmp(cmd, "y"))
216
+        ret = set_expr(&over->y_pexpr, args, ctx);
217
+    else if (!strcmp(cmd, "enable"))
218
+        ret = set_expr(&over->enable_pexpr, args, ctx);
219
+    else
220
+        ret = AVERROR(ENOSYS);
221
+
222
+    if (ret < 0)
223
+        return ret;
224
+
225
+    if (over->eval_mode == EVAL_MODE_INIT) {
226
+        eval_expr(ctx, EVAL_ALL);
227
+        av_log(ctx, AV_LOG_VERBOSE, "x:%f xi:%d y:%f yi:%d enable:%f\n",
228
+               over->var_values[VAR_X], over->x,
229
+               over->var_values[VAR_Y], over->y,
230
+               over->enable);
231
+    }
232
+    return ret;
233
+}
234
+
167 235
 static int query_formats(AVFilterContext *ctx)
168 236
 {
169 237
     OverlayContext *over = ctx->priv;
... ...
@@ -244,30 +312,10 @@ static int config_input_main(AVFilterLink *inlink)
244 244
     return 0;
245 245
 }
246 246
 
247
-static inline int normalize_xy(double d, int chroma_sub)
248
-{
249
-    if (isnan(d))
250
-        return INT_MAX;
251
-    return (int)d & ~((1 << chroma_sub) - 1);
252
-}
253
-
254
-static void eval_expr(AVFilterContext *ctx)
255
-{
256
-    OverlayContext  *over = ctx->priv;
257
-
258
-    over->var_values[VAR_X] = av_expr_eval(over->x_pexpr, over->var_values, NULL);
259
-    over->var_values[VAR_Y] = av_expr_eval(over->y_pexpr, over->var_values, NULL);
260
-    over->var_values[VAR_X] = av_expr_eval(over->x_pexpr, over->var_values, NULL);
261
-    over->x = normalize_xy(over->var_values[VAR_X], over->hsub);
262
-    over->y = normalize_xy(over->var_values[VAR_Y], over->vsub);
263
-    over->enable = av_expr_eval(over->enable_pexpr, over->var_values, NULL);
264
-}
265
-
266 247
 static int config_input_overlay(AVFilterLink *inlink)
267 248
 {
268 249
     AVFilterContext *ctx  = inlink->dst;
269 250
     OverlayContext  *over = inlink->dst->priv;
270
-    char *expr;
271 251
     int ret;
272 252
     const AVPixFmtDescriptor *pix_desc = av_pix_fmt_desc_get(inlink->format);
273 253
 
... ...
@@ -287,25 +335,17 @@ static int config_input_overlay(AVFilterLink *inlink)
287 287
     over->var_values[VAR_T]     = NAN;
288 288
     over->var_values[VAR_POS]   = NAN;
289 289
 
290
-    expr = over->x_expr;
291
-    if ((ret = av_expr_parse(&over->x_pexpr, expr, var_names,
292
-                             NULL, NULL, NULL, NULL, 0, ctx)) < 0)
293
-        goto fail;
294
-    expr = over->y_expr;
295
-    if ((ret = av_expr_parse(&over->y_pexpr, expr, var_names,
296
-                             NULL, NULL, NULL, NULL, 0, ctx)) < 0)
297
-        goto fail;
298
-    expr = over->enable_expr;
299
-    if ((ret = av_expr_parse(&over->enable_pexpr, expr, var_names,
300
-                             NULL, NULL, NULL, NULL, 0, ctx)) < 0)
301
-        goto fail;
290
+    if ((ret = set_expr(&over->x_pexpr,      over->x_expr,      ctx)) < 0 ||
291
+        (ret = set_expr(&over->y_pexpr,      over->y_expr,      ctx)) < 0 ||
292
+        (ret = set_expr(&over->enable_pexpr, over->enable_expr, ctx)) < 0)
293
+        return ret;
302 294
 
303 295
     over->overlay_is_packed_rgb =
304 296
         ff_fill_rgba_map(over->overlay_rgba_map, inlink->format) >= 0;
305 297
     over->overlay_has_alpha = ff_fmt_is_in(inlink->format, alpha_pix_fmts);
306 298
 
307 299
     if (over->eval_mode == EVAL_MODE_INIT) {
308
-        eval_expr(ctx);
300
+        eval_expr(ctx, EVAL_ALL);
309 301
         av_log(ctx, AV_LOG_VERBOSE, "x:%f xi:%d y:%f yi:%d enable:%f\n",
310 302
                over->var_values[VAR_X], over->x,
311 303
                over->var_values[VAR_Y], over->y,
... ...
@@ -319,11 +359,6 @@ static int config_input_overlay(AVFilterLink *inlink)
319 319
            ctx->inputs[OVERLAY]->w, ctx->inputs[OVERLAY]->h,
320 320
            av_get_pix_fmt_name(ctx->inputs[OVERLAY]->format));
321 321
     return 0;
322
-
323
-fail:
324
-    av_log(NULL, AV_LOG_ERROR,
325
-           "Error when parsing the expression '%s'\n", expr);
326
-    return ret;
327 322
 }
328 323
 
329 324
 static int config_output(AVFilterLink *outlink)
... ...
@@ -581,7 +616,7 @@ static int try_filter_frame(AVFilterContext *ctx, AVFrame *mainpic)
581 581
                 NAN : mainpic->pts * av_q2d(inlink->time_base);
582 582
             over->var_values[VAR_POS] = pos == -1 ? NAN : pos;
583 583
 
584
-            eval_expr(ctx);
584
+            eval_expr(ctx, EVAL_ALL);
585 585
             av_log(ctx, AV_LOG_DEBUG, "n:%f t:%f pos:%f x:%f xi:%d y:%f yi:%d enable:%f\n",
586 586
                    over->var_values[VAR_N], over->var_values[VAR_T], over->var_values[VAR_POS],
587 587
                    over->var_values[VAR_X], over->x,
... ...
@@ -725,6 +760,7 @@ AVFilter avfilter_vf_overlay = {
725 725
     .priv_size = sizeof(OverlayContext),
726 726
 
727 727
     .query_formats = query_formats,
728
+    .process_command = process_command,
728 729
 
729 730
     .inputs    = avfilter_vf_overlay_inputs,
730 731
     .outputs   = avfilter_vf_overlay_outputs,