Hi All,

currently scale video  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
and you want to create a variable sized output with 1/1 SAR.


Please consider to put this patch into the official ffmpeg source tree.

thank you,

Bela Bodecs
>From d5d14ed4a8d0e3c06843b4e4cee2a156ac7fd344 Tue, 19 Jan 2016 16:06:27 +0100
From: Bela Bodecs <bode...@vivanet.hu>
Date: Mon, 18 Jan 2016 18:44:09 +0100
Subject: [PATCH] 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 <bode...@vivanet.hu>

diff --git a/libavfilter/vf_scale.c b/libavfilter/vf_scale.c
index 7eabe00..ac9d4c3 100644
--- a/libavfilter/vf_scale.c
+++ b/libavfilter/vf_scale.c
@@ -69,10 +69,17 @@
     VAR_OHSUB,
     VAR_OVSUB,
     VARS_NB
 };
 
+enum EvalMode {
+    EVAL_MODE_INIT,
+    EVAL_MODE_FRAME,
+    EVAL_MODE_NB
+};
+
+
 typedef struct ScaleContext {
     const AVClass *class;
     struct SwsContext *sws;     ///< software scaler context
     struct SwsContext *isws[2]; ///< software scaler context for interlaced material
     AVDictionary *opts;
@@ -110,10 +117,13 @@
     int in_v_chr_pos;
 
     int force_original_aspect_ratio;
 
     int nb_slices;
+
+    int eval_mode;              ///< expression evaluation mode
+
 } ScaleContext;
 
 AVFilter ff_vf_scale2ref;
 
 static av_cold int init_dict(AVFilterContext *ctx, AVDictionary **opts)
@@ -492,20 +502,28 @@
     if (av_frame_get_colorspace(in) == AVCOL_SPC_YCGCO)
         av_log(link->dst, AV_LOG_WARNING, "Detected unsupported YCgCo colorspace.\n");
 
     if(   in->width  != link->w
        || in->height != link->h
-       || in->format != link->format) {
+       || in->format != link->format
+       || in->sample_aspect_ratio.den != link->sample_aspect_ratio.den || in->sample_aspect_ratio.num != link->sample_aspect_ratio.num) {
         int ret;
-        snprintf(buf, sizeof(buf)-1, "%d", outlink->w);
-        av_opt_set(scale, "w", buf, 0);
-        snprintf(buf, sizeof(buf)-1, "%d", outlink->h);
-        av_opt_set(scale, "h", buf, 0);
+
+        if (scale->eval_mode == EVAL_MODE_INIT) {
+            snprintf(buf, sizeof(buf)-1, "%d", outlink->w);
+            av_opt_set(scale, "w", buf, 0);
+            snprintf(buf, sizeof(buf)-1, "%d", outlink->h);
+            av_opt_set(scale, "h", buf, 0);
+        }
 
         link->dst->inputs[0]->format = in->format;
         link->dst->inputs[0]->w      = in->width;
         link->dst->inputs[0]->h      = in->height;
+
+        link->dst->inputs[0]->sample_aspect_ratio.den = in->sample_aspect_ratio.den;
+        link->dst->inputs[0]->sample_aspect_ratio.num = in->sample_aspect_ratio.num;
+
 
         if ((ret = config_props(outlink)) < 0)
             return ret;
     }
 
@@ -663,10 +681,13 @@
     { "decrease", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = 1 }, 0, 0, FLAGS, "force_oar" },
     { "increase", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = 2 }, 0, 0, FLAGS, "force_oar" },
     { "param0", "Scaler param 0",             OFFSET(param[0]),  AV_OPT_TYPE_DOUBLE, { .dbl = SWS_PARAM_DEFAULT  }, INT_MIN, INT_MAX, FLAGS },
     { "param1", "Scaler param 1",             OFFSET(param[1]),  AV_OPT_TYPE_DOUBLE, { .dbl = SWS_PARAM_DEFAULT  }, INT_MIN, INT_MAX, FLAGS },
     { "nb_slices", "set the number of slices (debug purpose only)", OFFSET(nb_slices), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, FLAGS },
+    { "eval", "specify when to evaluate expressions", OFFSET(eval_mode), AV_OPT_TYPE_INT, {.i64 = EVAL_MODE_INIT}, 0, EVAL_MODE_NB-1, FLAGS, "eval" },
+         { "init",  "eval expressions once during initialization", 0, AV_OPT_TYPE_CONST, {.i64=EVAL_MODE_INIT},  .flags = FLAGS, .unit = "eval" },
+         { "frame", "eval expressions during initialization and per-frame", 0, AV_OPT_TYPE_CONST, {.i64=EVAL_MODE_FRAME}, .flags = FLAGS, .unit = "eval" },
     { NULL }
 };
 
 static const AVClass scale_class = {
     .class_name       = "scale",
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel

Reply via email to