From: Limin Wang <lance.lmw...@gmail.com> It's useful to compare two 4K videos quality side by side on 4K TV.
Signed-off-by: Limin Wang <lance.lmw...@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. +@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. +@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 }, }; -- 2.21.0 _______________________________________________ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".