From patchwork Mon Jul 8 10:48:46 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Lance Wang X-Patchwork-Id: 13855 Return-Path: X-Original-To: patchwork@ffaux-bg.ffmpeg.org Delivered-To: patchwork@ffaux-bg.ffmpeg.org Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org [79.124.17.100]) by ffaux.localdomain (Postfix) with ESMTP id 422A64496BC for ; Mon, 8 Jul 2019 13:49:04 +0300 (EEST) Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 1B46668AFD1; Mon, 8 Jul 2019 13:49:04 +0300 (EEST) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from mail-pl1-f173.google.com (mail-pl1-f173.google.com [209.85.214.173]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id 8C10968AF9C for ; Mon, 8 Jul 2019 13:48:57 +0300 (EEST) Received: by mail-pl1-f173.google.com with SMTP id w24so8053512plp.2 for ; Mon, 08 Jul 2019 03:48:57 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id; bh=IjWKumRC//2LKIBwOBEYjq0dX60iqxl43n9/WKxu4KM=; b=tSu7uz/khZhuszeL9GvZFtxQ0jQ7xAqhiJGDvx9eAJFUHC3DPu+78iosjssdUSUIca xao90EKCdcPbYPzdX9bz6qUsk2AdEvfQgcjdPXQcW6lZDVp2gLFfwd7ehaNLnzMnNBvt rD4hbHWFCtHU11En+hI2lOpcc4BRHrGP6yI6nbld34MEU0CKsS94mR0Eu0f/+34Xhnw7 Dp8DyoMeDrZiBBorXqwmqyA/uLjais60U9AAuFb6Lun62u9U3dh4lgsJ92tRiIo5u5jd KrL788bBI1aaOemyGF3ishYtR+tYzitL2dAbx13jVLR2iLiuVW5qy2bi3xlW7Id9Xnlb PGyw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id; bh=IjWKumRC//2LKIBwOBEYjq0dX60iqxl43n9/WKxu4KM=; b=aNM7LfDotdT5En+PWgtF60FA+2/9JEU+Sg4kyUly8x9pPF5bPQM/6laqIGpR4RkT65 5+KxE86YqxiyLbz+UUPY4WZiQYtjheLXFAnRI1nwv04l3cVUiu+fy2FWwtQHi5Ue2Zqh +4HYqSHs7uGVSDHp45xqtLYB9pF4Vk+xcrqiAEnX09YYs/YXM0cBQjEwBIbQb3OCx8IJ Z3dEg+HYTIyALfbB7TRIv+VpocN/2cAsn610cwwy8FUuSCS+qyflvhxEWeD/U3HHoFHx EwhJRf72oE+vx+m8zfDjVU9JlD0rpvh4MGDIdqvFAZt1ytsAkARvHD/ta5rJL3Vg3Wf7 5V9Q== X-Gm-Message-State: APjAAAVuqdTM2PrM4lGoi5vNpM+1mxRkGLQJYIdwOGekkC0SHpEplCf2 6jjGHqTgK5J1nirhZPUAg88Jy4uj X-Google-Smtp-Source: APXvYqwOUPyhAeDLPMNLUOdfbCRStbhKv90a6b6L9mlbRDT/tDZh17eUkPNxwniGdLk3RG0hyRN2RA== X-Received: by 2002:a17:902:968c:: with SMTP id n12mr1399130plp.59.1562582935564; Mon, 08 Jul 2019 03:48:55 -0700 (PDT) Received: from izj6c97garwn1o4y2zidq0z.localdomain ([47.90.99.151]) by smtp.gmail.com with ESMTPSA id x14sm20802037pfq.158.2019.07.08.03.48.54 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Mon, 08 Jul 2019 03:48:54 -0700 (PDT) From: lance.lmwang@gmail.com To: ffmpeg-devel@ffmpeg.org Date: Mon, 8 Jul 2019 18:48:46 +0800 Message-Id: <1562582926-27231-1-git-send-email-lance.lmwang@gmail.com> X-Mailer: git-send-email 1.8.3.1 Subject: [FFmpeg-devel] [PATCH] lavf/vf_stack: add keep_dar option for vstack and hstack X-BeenThere: ffmpeg-devel@ffmpeg.org X-Mailman-Version: 2.1.20 Precedence: list List-Id: FFmpeg development discussions and patches List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-To: FFmpeg development discussions and patches Cc: Limin Wang MIME-Version: 1.0 Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" From: Limin Wang It's useful to compare two 4K videos quality side by side on 4K TV. Signed-off-by: Limin Wang --- 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 }, };