From patchwork Mon Aug 12 13:58:14 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Lars Kiesow X-Patchwork-Id: 14438 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 92334447A03 for ; Mon, 12 Aug 2019 16:58:58 +0300 (EEST) Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 714F868A7DE; Mon, 12 Aug 2019 16:58:58 +0300 (EEST) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from vm411.rz.uni-osnabrueck.de (vm411.rz.uni-osnabrueck.de [131.173.16.143]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id C45A468A274 for ; Mon, 12 Aug 2019 16:58:51 +0300 (EEST) Received: from vm411.rz.uni-osnabrueck.de (localhost [127.0.0.1]) by localhost (Postfix) with SMTP id BF3083036B9D; Mon, 12 Aug 2019 15:58:50 +0200 (CEST) Received: from lk.virtuos.at (lk.virtuos.uni-osnabrueck.de [131.173.168.31]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) (Authenticated sender: lkiesow) by vm411.rz.uni-osnabrueck.de (Postfix) with ESMTPSA; Mon, 12 Aug 2019 15:58:50 +0200 (CEST) From: Lars Kiesow To: ffmpeg-devel@ffmpeg.org Date: Mon, 12 Aug 2019 15:58:14 +0200 Message-Id: <20190812135814.14976-1-lkiesow@uos.de> X-Mailer: git-send-email 2.21.0 In-Reply-To: <20190811152418.GM3219@michaelspb> References: <20190811152418.GM3219@michaelspb> MIME-Version: 1.0 X-PMX-Version: vm411.rz.uni-osnabrueck.de (Univ. Osnabrueck) with PMX 6.4.6.2792898, Antispam-Engine: 2.7.2.2107409, Antispam-Data: 2019.8.12.135118, AntiVirus-Engine: 5.63.0, AntiVirus-Data: 2019.8.11.5630003 X-PMX-Spam: Gauge=IIIIIIII, Probability=8%, Report= HTML_00_01 0.05, HTML_00_10 0.05, SUPERLONG_LINE 0.05, BODY_SIZE_4000_4999 0, BODY_SIZE_5000_LESS 0, BODY_SIZE_7000_LESS 0, IN_REP_TO 0, MSG_THREAD 0, MULTIPLE_REAL_RCPTS 0, NO_URI_HTTPS 0, REFERENCES 0, __ANY_URI 0, __BODY_NO_MAILTO 0, __CC_NAME 0, __CC_NAME_DIFF_FROM_ACC 0, __CC_REAL_NAMES 0, __CP_MEDIA_BODY 0, __CTE 0, __FROM_DOMAIN_IN_ANY_CC1 0, __FROM_DOMAIN_IN_RCPT 0, __HAS_CC_HDR 0, __HAS_FROM 0, __HAS_MSGID 0, __HAS_REFERENCES 0, __HAS_X_MAILER 0, __IN_REP_TO 0, __MIME_TEXT_ONLY 0, __MIME_TEXT_P 0, __MIME_TEXT_P1 0, __MIME_VERSION 0, __NO_HTML_TAG_RAW 0, __REFERENCES 0, __SANE_MSGID 0, __TO_MALFORMED_2 0, __TO_NO_NAME 0, __URI_NO_WWW 0 X-PMX-Spam-Level: IIIIIIII Subject: [FFmpeg-devel] [PATCH] libavfilter/vf_scale: Ensure scaled video is divisible by n 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: Lars Kiesow Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" This patch adds a new option to the scale filter which ensures that the output resolution is divisible by the given integer when used together with `force_original_aspect_ratio`. This works similar to using `-n` in the `w` and `h` options. This option respects the value set for `force_original_aspect_ratio`, increasing or decreasing the resolution accordingly. The use case for this is to set a fixed target resolution using `w` and `h`, to use the `force_original_aspect_ratio` option to make sure that the video always fits in the defined bounding box regardless of aspect ratio, but to also make sure that the calculated output resolution is divisible by n so in can be encoded with certain encoders/options if that is required. Signed-off-by: Lars Kiesow --- doc/filters.texi | 12 ++++++++++++ libavfilter/vf_scale.c | 15 ++++++++++++++- 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/doc/filters.texi b/doc/filters.texi index e081cdc7bc..01262d845e 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -15369,6 +15369,18 @@ Please note that this is a different thing than specifying -1 for @option{w} or @option{h}, you still need to specify the output resolution for this option to work. +@item force_divisible_by Ensures that the output resolution is divisible by the +given integer when used together with @option{force_original_aspect_ratio}. This +works similar to using -n in the @option{w} and @option{h} options. + +This option respects the value set for @option{force_original_aspect_ratio}, +increasing or decreasing the resolution accordingly. This may slightly modify +the video's aspect ration. + +This can be handy, for example, if you want to have a video fit within a defined +resolution using the @option{force_original_aspect_ratio} option but have +encoder restrictions when it comes to width or height. + @end table The values of the @option{w} and @option{h} options are expressions diff --git a/libavfilter/vf_scale.c b/libavfilter/vf_scale.c index 7aebf56ad8..bf340b8e7b 100644 --- a/libavfilter/vf_scale.c +++ b/libavfilter/vf_scale.c @@ -86,6 +86,7 @@ typedef struct ScaleContext { int in_v_chr_pos; int force_original_aspect_ratio; + int force_divisible_by; int nb_slices; @@ -237,7 +238,8 @@ static int config_props(AVFilterLink *outlink) goto fail; /* Note that force_original_aspect_ratio may overwrite the previous set - * dimensions so that it is not divisible by the set factors anymore. */ + * dimensions so that it is not divisible by the set factors anymore + * unless force_divisible_by is defined as well */ if (scale->force_original_aspect_ratio) { int tmp_w = av_rescale(h, inlink->w, inlink->h); int tmp_h = av_rescale(w, inlink->h, inlink->w); @@ -245,9 +247,19 @@ static int config_props(AVFilterLink *outlink) if (scale->force_original_aspect_ratio == 1) { w = FFMIN(tmp_w, w); h = FFMIN(tmp_h, h); + if (scale->force_divisible_by > 1) { + // round down + w = w / scale->force_divisible_by * scale->force_divisible_by; + h = h / scale->force_divisible_by * scale->force_divisible_by; + } } else { w = FFMAX(tmp_w, w); h = FFMAX(tmp_h, h); + if (scale->force_divisible_by > 1) { + // round up + w = (w + scale->force_divisible_by - 1) / scale->force_divisible_by * scale->force_divisible_by; + h = (h + scale->force_divisible_by - 1) / scale->force_divisible_by * scale->force_divisible_by; + } } } @@ -600,6 +612,7 @@ static const AVOption scale_options[] = { { "disable", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = 0 }, 0, 0, FLAGS, "force_oar" }, { "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" }, + { "force_divisible_by", "enforce that the output resolution is divisible by a defined integer when force_original_aspect_ratio is used", OFFSET(force_divisible_by), AV_OPT_TYPE_INT, { .i64 = 1}, 1, 256, FLAGS }, { "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 },