[FFmpeg-devel] [PATCH] lavf/vf_stack: add keep_dar option for vstack and hstack

Limin Wang lance.lmwang at gmail.com
Mon Jul 8 18:09:06 EEST 2019


On Mon, Jul 08, 2019 at 05:44:06PM +0530, Gyan wrote:
> 
> 
> On 08-07-2019 04:18 PM, lance.lmwang at gmail.com wrote:
> >From: Limin Wang <lance.lmwang at gmail.com>
> >
> >It's useful to compare two 4K videos quality side by side on 4K TV.
> >
> >Signed-off-by: Limin Wang <lance.lmwang at gmail.com>
> >---
> >  doc/filters.texi       |  6 ++++++
> >  libavfilter/vf_stack.c | 31 ++++++++++++++++++++++++++-----
> >  2 files changed, 32 insertions(+), 5 deletions(-)
> >
> >diff --git a/doc/filters.texi b/doc/filters.texi
> >index ee6a93ffbf..675b02fc34 100644
> >--- a/doc/filters.texi
> >+++ b/doc/filters.texi
> >@@ -11280,6 +11280,9 @@ The filter accept the following option:
> >  @item inputs
> >  Set number of input streams. Default is 2.
> >+ at item keep_dar
> >+stack with 1/nb_inputs of each inputs screen to keep the same DAR, Default is 0.
> >+
> >  @item shortest
> >  If set to 1, force the output to terminate when the shortest input
> >  terminates. Default value is 0.
> >@@ -18333,6 +18336,9 @@ The filter accept the following option:
> >  @item inputs
> >  Set number of input streams. Default is 2.
> >+ at item keep_dar
> >+stack with 1/nb_inputs of each inputs screen to keep the same DAR, Default is 0.
> >+
> >  @item shortest
> >  If set to 1, force the output to terminate when the shortest input
> >  terminates. Default value is 0.
> >diff --git a/libavfilter/vf_stack.c b/libavfilter/vf_stack.c
> >index 4d254e0013..9196b5b0b7 100644
> >--- a/libavfilter/vf_stack.c
> >+++ b/libavfilter/vf_stack.c
> >@@ -44,6 +44,7 @@ typedef struct StackContext {
> >      int is_vertical;
> >      int is_horizontal;
> >      int nb_planes;
> >+    int keep_dar;
> >      StackItem *items;
> >      AVFrame **frames;
> >@@ -123,7 +124,7 @@ static int process_frame(FFFrameSync *fs)
> >      StackContext *s = fs->opaque;
> >      AVFrame **in = s->frames;
> >      AVFrame *out;
> >-    int i, p, ret, offset[4] = { 0 };
> >+    int i, p, ret, offset[4] = { 0 }, in_offset[4] = { 0 };
> >      for (i = 0; i < s->nb_inputs; i++) {
> >          if ((ret = ff_framesync_get_frame(&s->fs, i, &in[i], 0)) < 0)
> >@@ -153,16 +154,25 @@ static int process_frame(FFFrameSync *fs)
> >          for (p = 0; p < s->nb_planes; p++) {
> >              if (s->is_vertical) {
> >+                if (s->keep_dar) {
> >+                    height[p] /= s->nb_inputs;
> >+                    in_offset[p] = i * height[p] * in[i]->linesize[p];
> >+                }
> >+
> >                  av_image_copy_plane(out->data[p] + offset[p] * out->linesize[p],
> >                                      out->linesize[p],
> >-                                    in[i]->data[p],
> >+                                    in[i]->data[p] + in_offset[p],
> >                                      in[i]->linesize[p],
> >                                      linesize[p], height[p]);
> >                  offset[p] += height[p];
> >              } else if (s->is_horizontal) {
> >+                if (s->keep_dar) {
> >+                    linesize[p] /= s->nb_inputs;
> >+                    in_offset[p] = i * in[i]->linesize[p] / s->nb_inputs;
> >+                }
> >                  av_image_copy_plane(out->data[p] + offset[p],
> >                                      out->linesize[p],
> >-                                    in[i]->data[p],
> >+                                    in[i]->data[p] + in_offset[p],
> >                                      in[i]->linesize[p],
> >                                      linesize[p], height[p]);
> >                  offset[p] += linesize[p];
> >@@ -197,20 +207,30 @@ static int config_output(AVFilterLink *outlink)
> >          return AVERROR_BUG;
> >      if (s->is_vertical) {
> >+        if (s->keep_dar)
> >+            height /= s->nb_inputs;
> >          for (i = 1; i < s->nb_inputs; i++) {
> >              if (ctx->inputs[i]->w != width) {
> >                  av_log(ctx, AV_LOG_ERROR, "Input %d width %d does not match input %d width %d.\n", i, ctx->inputs[i]->w, 0, width);
> >                  return AVERROR(EINVAL);
> >              }
> >-            height += ctx->inputs[i]->h;
> >+            if (!s->keep_dar)
> >+                height += ctx->inputs[i]->h;
> >+            else
> >+                height += ctx->inputs[i]->h / s->nb_inputs;
> >          }
> >      } else if (s->is_horizontal) {
> >+        if (s->keep_dar)
> >+            width /= s->nb_inputs;
> >          for (i = 1; i < s->nb_inputs; i++) {
> >              if (ctx->inputs[i]->h != height) {
> >                  av_log(ctx, AV_LOG_ERROR, "Input %d height %d does not match input %d height %d.\n", i, ctx->inputs[i]->h, 0, height);
> >                  return AVERROR(EINVAL);
> >              }
> >-            width += ctx->inputs[i]->w;
> >+            if (!s->keep_dar)
> >+                width += ctx->inputs[i]->w;
> >+            else
> >+                width += ctx->inputs[i]->w / s->nb_inputs;
> >          }
> >      } else {
> >          char *arg, *p = s->layout, *saveptr = NULL;
> >@@ -339,6 +359,7 @@ static int activate(AVFilterContext *ctx)
> >  #define FLAGS AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_FILTERING_PARAM
> >  static const AVOption stack_options[] = {
> >      { "inputs", "set number of inputs", OFFSET(nb_inputs), AV_OPT_TYPE_INT, {.i64=2}, 2, INT_MAX, .flags = FLAGS },
> >+    { "keep_dar", "stack with 1/nb_inputs of each inputs screen to keep the same DAR", OFFSET(keep_dar), AV_OPT_TYPE_INT, {.i64=0}, 0, 1, .flags = FLAGS },
> >      { "shortest", "force termination when the shortest input terminates", OFFSET(shortest), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, .flags = FLAGS },
> >      { NULL },
> >  };
> 
> Keep DAR of which input i.e. what if the inputs have different DARs?

I'm using it for comparing two same video quality, it's not general
for all condition anyway. 

> 
> The user can already emulate this by cropping inputs befoehand.
Yes, we can use the crop filter to get the same function, however the
command line isn't very direct to use and difficult to recall.


> 
> Gyan
> _______________________________________________
> ffmpeg-devel mailing list
> ffmpeg-devel at ffmpeg.org
> https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
> 
> To unsubscribe, visit link above, or email
> ffmpeg-devel-request at ffmpeg.org with subject "unsubscribe".


More information about the ffmpeg-devel mailing list