From patchwork Sun Feb 2 00:29:13 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Pavel Klimov X-Patchwork-Id: 17657 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 5331B44B9DD for ; Sun, 2 Feb 2020 02:29:45 +0200 (EET) Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 31C766882C0; Sun, 2 Feb 2020 02:29:45 +0200 (EET) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from mail.uralweb.ru (mail.uralweb.ru [213.142.46.7]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id E9C42688154 for ; Sun, 2 Feb 2020 02:29:37 +0200 (EET) Received: from uralweb.ru (unknown [91.238.137.108]) by mail.uralweb.ru (Postfix) with ESMTPSA id 146C1600075 for ; Sun, 2 Feb 2020 05:29:36 +0500 (+05) DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=uralweb.ru; s=uralweb.ru; t=1580603377; bh=xftU16iX1ZBunfHTuNXvJH5LAFHNu7ETLBryv31J6e8=; h=From:To:Subject:Date:In-Reply-To:References:From; b=k0gtShJPEiyW/0vQls7HFcydSAoQfBwXfbkVpkcXf7rJ7idD2MrIlH62y6R8nuuPW SWUz108ixZ0O8FwhTc5lm50rnanB05EJpmXlSNK+PTcc5qFX8LRCl9ko8rNiiqWnzu VnxorvTjWT0zwpUAm2K2/d2byzTwmr/zFZTgNem8= From: Pavel Klimov To: ffmpeg-devel@ffmpeg.org Date: Sun, 2 Feb 2020 05:29:13 +0500 Message-Id: <20200202002913.4864-2-r57shell@uralweb.ru> X-Mailer: git-send-email 2.17.0.windows.1 In-Reply-To: <20200202002913.4864-1-r57shell@uralweb.ru> References: <20200202002913.4864-1-r57shell@uralweb.ru> Subject: [FFmpeg-devel] [PATCH 1/1] libswscale: add area upscale 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 MIME-Version: 1.0 Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" area upscale is similar to neighbor upscale, just better with non integer factors. math comes from assumption that neighbor filter works fine, and then integrate it over pixel width. Signed-off-by: Pavel Klimov --- libswscale/options.c | 1 + libswscale/swscale.h | 1 + libswscale/utils.c | 30 +++++++++++++++++++++++++++++- 3 files changed, 31 insertions(+), 1 deletion(-) diff --git a/libswscale/options.c b/libswscale/options.c index 7eb2752543..bbf71997fb 100644 --- a/libswscale/options.c +++ b/libswscale/options.c @@ -41,6 +41,7 @@ static const AVOption swscale_options[] = { { "experimental", "experimental", 0, AV_OPT_TYPE_CONST, { .i64 = SWS_X }, INT_MIN, INT_MAX, VE, "sws_flags" }, { "neighbor", "nearest neighbor", 0, AV_OPT_TYPE_CONST, { .i64 = SWS_POINT }, INT_MIN, INT_MAX, VE, "sws_flags" }, { "area", "averaging area", 0, AV_OPT_TYPE_CONST, { .i64 = SWS_AREA }, INT_MIN, INT_MAX, VE, "sws_flags" }, + { "area_upscale", "averaging area upscale", 0, AV_OPT_TYPE_CONST, { .i64 = SWS_AREA_UPSCALE }, INT_MIN, INT_MAX, VE, "sws_flags" }, { "bicublin", "luma bicubic, chroma bilinear", 0, AV_OPT_TYPE_CONST, { .i64 = SWS_BICUBLIN }, INT_MIN, INT_MAX, VE, "sws_flags" }, { "gauss", "Gaussian", 0, AV_OPT_TYPE_CONST, { .i64 = SWS_GAUSS }, INT_MIN, INT_MAX, VE, "sws_flags" }, { "sinc", "sinc", 0, AV_OPT_TYPE_CONST, { .i64 = SWS_SINC }, INT_MIN, INT_MAX, VE, "sws_flags" }, diff --git a/libswscale/swscale.h b/libswscale/swscale.h index 7713f51ec6..1d677e0a94 100644 --- a/libswscale/swscale.h +++ b/libswscale/swscale.h @@ -66,6 +66,7 @@ const char *swscale_license(void); #define SWS_SINC 0x100 #define SWS_LANCZOS 0x200 #define SWS_SPLINE 0x400 +#define SWS_AREA_UPSCALE 0x800 #define SWS_SRC_V_CHR_DROP_MASK 0x30000 #define SWS_SRC_V_CHR_DROP_SHIFT 16 diff --git a/libswscale/utils.c b/libswscale/utils.c index b2c08a5983..b713c40812 100644 --- a/libswscale/utils.c +++ b/libswscale/utils.c @@ -316,6 +316,7 @@ typedef struct { static const ScaleAlgorithm scale_algorithms[] = { { SWS_AREA, "area averaging", 1 /* downscale only, for upscale it is bilinear */ }, + { SWS_AREA_UPSCALE, "area averaging upscale", 1 }, { SWS_BICUBIC, "bicubic", 4 }, { SWS_BICUBLIN, "luma bicubic / chroma bilinear", -1 }, { SWS_BILINEAR, "bilinear", 2 }, @@ -398,6 +399,32 @@ static av_cold int initFilter(int16_t **outFilter, int32_t **filterPos, } xDstInSrc += xInc; } + } else if (xInc <= (1 << 16) && (flags & SWS_AREA_UPSCALE)) { // area upscale + int i; + int64_t xDstInSrc; + double dInc, x, x1; + + filterSize = 2; + FF_ALLOC_ARRAY_OR_GOTO(NULL, filter, + dstW, sizeof(*filter) * filterSize, fail); + + xDstInSrc = ((dstPos*(int64_t)xInc)>>8) - ((srcPos*0x8000LL)>>7); + + xDstInSrc += (1 << 15) - xInc / 2; + dInc = (double)srcW / dstW * (1 << 16); + for (i = 0; i < dstW; i++) { + x = i * dInc; + + (*filterPos)[i] = (xDstInSrc + (int)x) >> 16; + x1 = xDstInSrc - ((*filterPos)[i] << 16) + x; + if (x1 + dInc <= (1 << 16)) { + filter[i * filterSize + 0] = fone; + filter[i * filterSize + 1] = 0; + } else { + filter[i * filterSize + 0] = fone * (((1 << 16) - x1) / dInc); + filter[i * filterSize + 1] = fone - filter[i * filterSize + 0]; + } + } } else { int64_t xDstInSrc; int sizeFactor = -1; @@ -471,7 +498,7 @@ static av_cold int initFilter(int16_t **outFilter, int32_t **filterPos, else c = pow(c, A); coeff = (c * 0.5 + 0.5) * fone; - } else if (flags & SWS_AREA) { + } else if (flags & (SWS_AREA | SWS_AREA_UPSCALE)) { int64_t d2 = d - (1 << 29); if (d2 * xInc < -(1LL << (29 + 16))) coeff = 1.0 * (1LL << (30 + 16)); @@ -1229,6 +1256,7 @@ av_cold int sws_init_context(SwsContext *c, SwsFilter *srcFilter, i = flags & (SWS_POINT | SWS_AREA | + SWS_AREA_UPSCALE | SWS_BILINEAR | SWS_FAST_BILINEAR | SWS_BICUBIC |