Browse code

vf_scale: Detecting changes of incoming frame properties and dinamically evaluate width and height expressions

Currently scale filter accepts expressions in its width and height
parameters but evaluates them only once at init and replaces them with
their actual values. Later on, if any parameter of incoming frames
changes - ie those were used in the original size expressions - then
they new values will not have any affect for width and heigth values.
They remain the same. This patch makes possible that width and height
expressions be evaluated frame-by-frame basis if width/height/sar/format
properties of incoming frame would change. To retain the current
behaviour and not to break any earlier app, a new config parameter has
been introduced. Its name is "eval" and it has two distinct values:
"init" and "frame". The default value is "init".
This feature is very usefull in case of DVBT mpeg-ts streams where SAR
may change time-by-time from 4/3 to 16/9 and vica-versa and the size
remains the same and you want to create a variable sized output with 1/1
SAR.

Signed-off-by: Bela Bodecs <bodecsb@vivanet.hu>
Reviewed-by: Paul B Mahol <onemda@gmail.com>
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>

Bela Bodecs authored on 2016/01/19 02:44:09
Showing 1 changed files
... ...
@@ -71,6 +71,13 @@ enum var_name {
71 71
     VARS_NB
72 72
 };
73 73
 
74
+enum EvalMode {
75
+    EVAL_MODE_INIT,
76
+    EVAL_MODE_FRAME,
77
+    EVAL_MODE_NB
78
+};
79
+
80
+
74 81
 typedef struct ScaleContext {
75 82
     const AVClass *class;
76 83
     struct SwsContext *sws;     ///< software scaler context
... ...
@@ -112,6 +119,9 @@ typedef struct ScaleContext {
112 112
     int force_original_aspect_ratio;
113 113
 
114 114
     int nb_slices;
115
+
116
+    int eval_mode;              ///< expression evaluation mode
117
+
115 118
 } ScaleContext;
116 119
 
117 120
 AVFilter ff_vf_scale2ref;
... ...
@@ -494,17 +504,25 @@ static int filter_frame(AVFilterLink *link, AVFrame *in)
494 494
 
495 495
     if(   in->width  != link->w
496 496
        || in->height != link->h
497
-       || in->format != link->format) {
497
+       || in->format != link->format
498
+       || in->sample_aspect_ratio.den != link->sample_aspect_ratio.den || in->sample_aspect_ratio.num != link->sample_aspect_ratio.num) {
498 499
         int ret;
499
-        snprintf(buf, sizeof(buf)-1, "%d", outlink->w);
500
-        av_opt_set(scale, "w", buf, 0);
501
-        snprintf(buf, sizeof(buf)-1, "%d", outlink->h);
502
-        av_opt_set(scale, "h", buf, 0);
500
+
501
+        if (scale->eval_mode == EVAL_MODE_INIT) {
502
+            snprintf(buf, sizeof(buf)-1, "%d", outlink->w);
503
+            av_opt_set(scale, "w", buf, 0);
504
+            snprintf(buf, sizeof(buf)-1, "%d", outlink->h);
505
+            av_opt_set(scale, "h", buf, 0);
506
+        }
503 507
 
504 508
         link->dst->inputs[0]->format = in->format;
505 509
         link->dst->inputs[0]->w      = in->width;
506 510
         link->dst->inputs[0]->h      = in->height;
507 511
 
512
+        link->dst->inputs[0]->sample_aspect_ratio.den = in->sample_aspect_ratio.den;
513
+        link->dst->inputs[0]->sample_aspect_ratio.num = in->sample_aspect_ratio.num;
514
+
515
+
508 516
         if ((ret = config_props(outlink)) < 0)
509 517
             return ret;
510 518
     }
... ...
@@ -665,6 +683,9 @@ static const AVOption scale_options[] = {
665 665
     { "param0", "Scaler param 0",             OFFSET(param[0]),  AV_OPT_TYPE_DOUBLE, { .dbl = SWS_PARAM_DEFAULT  }, INT_MIN, INT_MAX, FLAGS },
666 666
     { "param1", "Scaler param 1",             OFFSET(param[1]),  AV_OPT_TYPE_DOUBLE, { .dbl = SWS_PARAM_DEFAULT  }, INT_MIN, INT_MAX, FLAGS },
667 667
     { "nb_slices", "set the number of slices (debug purpose only)", OFFSET(nb_slices), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, FLAGS },
668
+    { "eval", "specify when to evaluate expressions", OFFSET(eval_mode), AV_OPT_TYPE_INT, {.i64 = EVAL_MODE_INIT}, 0, EVAL_MODE_NB-1, FLAGS, "eval" },
669
+         { "init",  "eval expressions once during initialization", 0, AV_OPT_TYPE_CONST, {.i64=EVAL_MODE_INIT},  .flags = FLAGS, .unit = "eval" },
670
+         { "frame", "eval expressions during initialization and per-frame", 0, AV_OPT_TYPE_CONST, {.i64=EVAL_MODE_FRAME}, .flags = FLAGS, .unit = "eval" },
668 671
     { NULL }
669 672
 };
670 673