From patchwork Tue Nov 12 09:50:35 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Niklas Haas X-Patchwork-Id: 52693 Delivered-To: ffmpegpatchwork2@gmail.com Received: by 2002:a05:612c:6704:20b0:4a6:637d:5226 with SMTP id mp4-n2csp140083vqb; Tue, 12 Nov 2024 01:52:33 -0800 (PST) X-Forwarded-Encrypted: i=2; AJvYcCVOlSxqx0s64cFhLt3THU+zbkC5OcNYyFYtYltqr2mfQNItWd6/mUPpMbdk2DERl5arKNSrjH0iEMJr1S8GQufu@gmail.com X-Google-Smtp-Source: AGHT+IGBbZXD8GAYqaK8+V1F3j5baE3eLoKDFWqrE2RnTCPzJn8iYwywEIhi3RevjmRXhEoJ+/5D X-Received: by 2002:a05:6402:268a:b0:5c9:59e6:e929 with SMTP id 4fb4d7f45d1cf-5cf0a26e08cmr20660340a12.0.1731405153199; Tue, 12 Nov 2024 01:52:33 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1731405153; cv=none; d=google.com; s=arc-20240605; b=QL6NXFIQn5dFxa3CRy6OGArdjIKBEcHAZ7ix4/rbHRWvlnYQtnybIC0HChmPMSjsHI R9Acx2t2cVGkjB9PQbuKpwIdlFFradS45GghzUTRJMFrP5+mprReev1Q48hLM4X3Y7wi s6waoIHqwdjxvh0Eus3QI9U95A1iw/XaRO+36SjEvPeM0Hlhk7BCHql1//pHJiR3DZj0 gS2nRM57eoXoZrFiAJnzqvPeV4+aCQQ15CDH471WlYEZAbipIURwfi1lZjqEp7lFfVQq pZQJ5VOcBrVDY/vn78sHgLikT4GeNGiuDibOqWkbU3xODhgNoGHsiZL+HMYZJ3gYGx24 52Jw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20240605; h=sender:errors-to:content-transfer-encoding:cc:reply-to :list-subscribe:list-help:list-post:list-archive:list-unsubscribe :list-id:precedence:subject:mime-version:references:in-reply-to :message-id:date:to:from:delivered-to; bh=tKlpFLu1jQurm859YAQfoEaJ7WoTrB/MKNX2YlNNA30=; fh=xmAeKtysnShNOmkhiJmYkS30uw4Fu2hvBJ7qlIwukxQ=; b=Dzi3gEkZB/fl+t1eP5V/1ERWwYWb7O/oYplV8S35af42rZOFW2IwpRmp6XZQclp72J JMMR3GH3e8iJQFAoGHy3mZYChuM48KaIAuSWtHMcPXluCJOzobBKh7Qwl579KoFDB04r jNU5WkyPjxfjat46J09uWt8cakS1LvG328MTlho2Mavf1MeQE/4Wia+t1peBZ4xe2ZGU yS1rGZQaN56PzJhzbIz87vg61u+a/2npx5S77WxonOxID/Muk4uxNmOiis3PO+YKbbzI jNYZbpcwgxrwG0NKUoCeUAF8t2wWK4oHfbuara7GBGr9lSRMIzAf43xr/AHZ++v3ELGl QKog==; dara=google.com ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org Return-Path: Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org. [79.124.17.100]) by mx.google.com with ESMTPS id 4fb4d7f45d1cf-5cf03c7d87fsi7958827a12.278.2024.11.12.01.52.32 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 12 Nov 2024 01:52:33 -0800 (PST) Received-SPF: pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) client-ip=79.124.17.100; Authentication-Results: mx.google.com; spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id BBC9568DE7E; Tue, 12 Nov 2024 11:52:06 +0200 (EET) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from haasn.dev (haasn.dev [78.46.187.166]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 46D9368DE16 for ; Tue, 12 Nov 2024 11:51:57 +0200 (EET) Received: from haasn.dev (unknown [10.30.1.1]) by haasn.dev (Postfix) with ESMTP id CF58540D16; Tue, 12 Nov 2024 10:51:56 +0100 (CET) From: Niklas Haas To: ffmpeg-devel@ffmpeg.org Date: Tue, 12 Nov 2024 10:50:35 +0100 Message-ID: <20241112095154.483778-2-ffmpeg@haasn.xyz> X-Mailer: git-send-email 2.47.0 In-Reply-To: <20241112095154.483778-1-ffmpeg@haasn.xyz> References: <20241112095154.483778-1-ffmpeg@haasn.xyz> MIME-Version: 1.0 Subject: [FFmpeg-devel] [PATCH v6 01/12] swscale/options: cosmetic changes X-BeenThere: ffmpeg-devel@ffmpeg.org X-Mailman-Version: 2.1.29 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: Niklas Haas Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" X-TUID: SVxX9/X/UYkW From: Niklas Haas Reorganize the list, fix whitespace, make indentation consistent, and rename some descriptions for clarity, consistency or informativeness. Sponsored-by: Sovereign Tech Fund Signed-off-by: Niklas Haas --- libswscale/options.c | 86 ++++++++++++++++++++++---------------------- 1 file changed, 44 insertions(+), 42 deletions(-) diff --git a/libswscale/options.c b/libswscale/options.c index 56b1d2235d..e64e289cf3 100644 --- a/libswscale/options.c +++ b/libswscale/options.c @@ -32,55 +32,57 @@ static const char *sws_context_to_name(void *ptr) #define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM static const AVOption swscale_options[] = { - { "sws_flags", "scaler flags", OFFSET(flags), AV_OPT_TYPE_FLAGS, { .i64 = SWS_BICUBIC }, 0, UINT_MAX, VE, .unit = "sws_flags" }, - { "fast_bilinear", "fast bilinear", 0, AV_OPT_TYPE_CONST, { .i64 = SWS_FAST_BILINEAR }, INT_MIN, INT_MAX, VE, .unit = "sws_flags" }, - { "bilinear", "bilinear", 0, AV_OPT_TYPE_CONST, { .i64 = SWS_BILINEAR }, INT_MIN, INT_MAX, VE, .unit = "sws_flags" }, - { "bicubic", "bicubic", 0, AV_OPT_TYPE_CONST, { .i64 = SWS_BICUBIC }, INT_MIN, INT_MAX, VE, .unit = "sws_flags" }, - { "experimental", "experimental", 0, AV_OPT_TYPE_CONST, { .i64 = SWS_X }, INT_MIN, INT_MAX, VE, .unit = "sws_flags" }, - { "neighbor", "nearest neighbor", 0, AV_OPT_TYPE_CONST, { .i64 = SWS_POINT }, INT_MIN, INT_MAX, VE, .unit = "sws_flags" }, - { "area", "averaging area", 0, AV_OPT_TYPE_CONST, { .i64 = SWS_AREA }, INT_MIN, INT_MAX, VE, .unit = "sws_flags" }, - { "bicublin", "luma bicubic, chroma bilinear", 0, AV_OPT_TYPE_CONST, { .i64 = SWS_BICUBLIN }, INT_MIN, INT_MAX, VE, .unit = "sws_flags" }, - { "gauss", "Gaussian", 0, AV_OPT_TYPE_CONST, { .i64 = SWS_GAUSS }, INT_MIN, INT_MAX, VE, .unit = "sws_flags" }, - { "sinc", "sinc", 0, AV_OPT_TYPE_CONST, { .i64 = SWS_SINC }, INT_MIN, INT_MAX, VE, .unit = "sws_flags" }, - { "lanczos", "Lanczos", 0, AV_OPT_TYPE_CONST, { .i64 = SWS_LANCZOS }, INT_MIN, INT_MAX, VE, .unit = "sws_flags" }, - { "spline", "natural bicubic spline", 0, AV_OPT_TYPE_CONST, { .i64 = SWS_SPLINE }, INT_MIN, INT_MAX, VE, .unit = "sws_flags" }, - { "print_info", "print info", 0, AV_OPT_TYPE_CONST, { .i64 = SWS_PRINT_INFO }, INT_MIN, INT_MAX, VE, .unit = "sws_flags" }, - { "accurate_rnd", "accurate rounding", 0, AV_OPT_TYPE_CONST, { .i64 = SWS_ACCURATE_RND }, INT_MIN, INT_MAX, VE, .unit = "sws_flags" }, - { "full_chroma_int", "full chroma interpolation", 0, AV_OPT_TYPE_CONST, { .i64 = SWS_FULL_CHR_H_INT }, INT_MIN, INT_MAX, VE, .unit = "sws_flags" }, - { "full_chroma_inp", "full chroma input", 0, AV_OPT_TYPE_CONST, { .i64 = SWS_FULL_CHR_H_INP }, INT_MIN, INT_MAX, VE, .unit = "sws_flags" }, - { "bitexact", "", 0, AV_OPT_TYPE_CONST, { .i64 = SWS_BITEXACT }, INT_MIN, INT_MAX, VE, .unit = "sws_flags" }, - { "error_diffusion", "error diffusion dither", 0, AV_OPT_TYPE_CONST, { .i64 = SWS_ERROR_DIFFUSION}, INT_MIN, INT_MAX, VE, .unit = "sws_flags" }, + { "sws_flags", "swscale flags", OFFSET(flags), AV_OPT_TYPE_FLAGS, { .i64 = SWS_BICUBIC }, .flags = VE, .unit = "sws_flags", .max = UINT_MAX }, + { "fast_bilinear", "fast bilinear", 0, AV_OPT_TYPE_CONST, { .i64 = SWS_FAST_BILINEAR }, .flags = VE, .unit = "sws_flags" }, + { "bilinear", "bilinear", 0, AV_OPT_TYPE_CONST, { .i64 = SWS_BILINEAR }, .flags = VE, .unit = "sws_flags" }, + { "bicubic", "bicubic", 0, AV_OPT_TYPE_CONST, { .i64 = SWS_BICUBIC }, .flags = VE, .unit = "sws_flags" }, + { "experimental", "experimental", 0, AV_OPT_TYPE_CONST, { .i64 = SWS_X }, .flags = VE, .unit = "sws_flags" }, + { "neighbor", "nearest neighbor", 0, AV_OPT_TYPE_CONST, { .i64 = SWS_POINT }, .flags = VE, .unit = "sws_flags" }, + { "area", "averaging area", 0, AV_OPT_TYPE_CONST, { .i64 = SWS_AREA }, .flags = VE, .unit = "sws_flags" }, + { "bicublin", "luma bicubic, chroma bilinear", 0, AV_OPT_TYPE_CONST, { .i64 = SWS_BICUBLIN }, .flags = VE, .unit = "sws_flags" }, + { "gauss", "gaussian approximation", 0, AV_OPT_TYPE_CONST, { .i64 = SWS_GAUSS }, .flags = VE, .unit = "sws_flags" }, + { "sinc", "sinc", 0, AV_OPT_TYPE_CONST, { .i64 = SWS_SINC }, .flags = VE, .unit = "sws_flags" }, + { "lanczos", "lanczos (sinc/sinc)", 0, AV_OPT_TYPE_CONST, { .i64 = SWS_LANCZOS }, .flags = VE, .unit = "sws_flags" }, + { "spline", "natural bicubic spline", 0, AV_OPT_TYPE_CONST, { .i64 = SWS_SPLINE }, .flags = VE, .unit = "sws_flags" }, + { "print_info", "print info", 0, AV_OPT_TYPE_CONST, { .i64 = SWS_PRINT_INFO }, .flags = VE, .unit = "sws_flags" }, + { "accurate_rnd", "accurate rounding", 0, AV_OPT_TYPE_CONST, { .i64 = SWS_ACCURATE_RND }, .flags = VE, .unit = "sws_flags" }, + { "full_chroma_int", "full chroma interpolation", 0, AV_OPT_TYPE_CONST, { .i64 = SWS_FULL_CHR_H_INT }, .flags = VE, .unit = "sws_flags" }, + { "full_chroma_inp", "full chroma input", 0, AV_OPT_TYPE_CONST, { .i64 = SWS_FULL_CHR_H_INP }, .flags = VE, .unit = "sws_flags" }, + { "bitexact", "bit-exact mode", 0, AV_OPT_TYPE_CONST, { .i64 = SWS_BITEXACT }, .flags = VE, .unit = "sws_flags" }, + { "error_diffusion", "error diffusion dither", 0, AV_OPT_TYPE_CONST, { .i64 = SWS_ERROR_DIFFUSION}, .flags = VE, .unit = "sws_flags" }, - { "srcw", "source width", OFFSET(srcW), AV_OPT_TYPE_INT, { .i64 = 16 }, 1, INT_MAX, VE }, - { "srch", "source height", OFFSET(srcH), AV_OPT_TYPE_INT, { .i64 = 16 }, 1, INT_MAX, VE }, - { "dstw", "destination width", OFFSET(dstW), AV_OPT_TYPE_INT, { .i64 = 16 }, 1, INT_MAX, VE }, - { "dsth", "destination height", OFFSET(dstH), AV_OPT_TYPE_INT, { .i64 = 16 }, 1, INT_MAX, VE }, + { "param0", "scaler param 0", OFFSET(param[0]), AV_OPT_TYPE_DOUBLE, { .dbl = SWS_PARAM_DEFAULT }, INT_MIN, INT_MAX, VE }, + { "param1", "scaler param 1", OFFSET(param[1]), AV_OPT_TYPE_DOUBLE, { .dbl = SWS_PARAM_DEFAULT }, INT_MIN, INT_MAX, VE }, + + { "srcw", "source width", OFFSET(srcW), AV_OPT_TYPE_INT, { .i64 = 16 }, 1, INT_MAX, VE }, + { "srch", "source height", OFFSET(srcH), AV_OPT_TYPE_INT, { .i64 = 16 }, 1, INT_MAX, VE }, + { "dstw", "destination width", OFFSET(dstW), AV_OPT_TYPE_INT, { .i64 = 16 }, 1, INT_MAX, VE }, + { "dsth", "destination height", OFFSET(dstH), AV_OPT_TYPE_INT, { .i64 = 16 }, 1, INT_MAX, VE }, { "src_format", "source format", OFFSET(srcFormat), AV_OPT_TYPE_PIXEL_FMT,{ .i64 = DEFAULT }, 0, INT_MAX, VE }, { "dst_format", "destination format", OFFSET(dstFormat), AV_OPT_TYPE_PIXEL_FMT,{ .i64 = DEFAULT }, 0, INT_MAX, VE }, - { "src_range", "source is full range", OFFSET(srcRange), AV_OPT_TYPE_BOOL, { .i64 = DEFAULT }, 0, 1, VE }, - { "dst_range", "destination is full range", OFFSET(dstRange), AV_OPT_TYPE_BOOL, { .i64 = DEFAULT }, 0, 1, VE }, - { "param0", "scaler param 0", OFFSET(param[0]), AV_OPT_TYPE_DOUBLE, { .dbl = SWS_PARAM_DEFAULT }, INT_MIN, INT_MAX, VE }, - { "param1", "scaler param 1", OFFSET(param[1]), AV_OPT_TYPE_DOUBLE, { .dbl = SWS_PARAM_DEFAULT }, INT_MIN, INT_MAX, VE }, + { "src_range", "source is full range", OFFSET(srcRange), AV_OPT_TYPE_BOOL, { .i64 = DEFAULT }, 0, 1, VE }, + { "dst_range", "destination is full range", OFFSET(dstRange), AV_OPT_TYPE_BOOL, { .i64 = DEFAULT }, 0, 1, VE }, + { "gamma", "gamma correct scaling", OFFSET(gamma_flag),AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, VE }, + + { "src_v_chr_pos", "source vertical chroma position in luma grid/256" , OFFSET(src_v_chr_pos), AV_OPT_TYPE_INT, { .i64 = -513 }, -513, 1024, VE }, + { "src_h_chr_pos", "source horizontal chroma position in luma grid/256", OFFSET(src_h_chr_pos), AV_OPT_TYPE_INT, { .i64 = -513 }, -513, 1024, VE }, + { "dst_v_chr_pos", "destination vertical chroma position in luma grid/256" , OFFSET(dst_v_chr_pos), AV_OPT_TYPE_INT, { .i64 = -513 }, -513, 1024, VE }, + { "dst_h_chr_pos", "destination horizontal chroma position in luma grid/256", OFFSET(dst_h_chr_pos), AV_OPT_TYPE_INT, { .i64 = -513 }, -513, 1024, VE }, - { "src_v_chr_pos", "source vertical chroma position in luma grid/256" , OFFSET(src_v_chr_pos), AV_OPT_TYPE_INT, { .i64 = -513 }, -513, 1024, VE }, - { "src_h_chr_pos", "source horizontal chroma position in luma grid/256", OFFSET(src_h_chr_pos), AV_OPT_TYPE_INT, { .i64 = -513 }, -513, 1024, VE }, - { "dst_v_chr_pos", "destination vertical chroma position in luma grid/256" , OFFSET(dst_v_chr_pos), AV_OPT_TYPE_INT, { .i64 = -513 }, -513, 1024, VE }, - { "dst_h_chr_pos", "destination horizontal chroma position in luma grid/256", OFFSET(dst_h_chr_pos), AV_OPT_TYPE_INT, { .i64 = -513 }, -513, 1024, VE }, + { "sws_dither", "set dithering algorithm", OFFSET(dither), AV_OPT_TYPE_INT, { .i64 = SWS_DITHER_AUTO }, .flags = VE, .unit = "sws_dither", .max = SWS_DITHER_NB - 1 }, + { "auto", "automatic selection", 0, AV_OPT_TYPE_CONST, { .i64 = SWS_DITHER_AUTO }, .flags = VE, .unit = "sws_dither" }, + { "bayer", "ordered matrix dither", 0, AV_OPT_TYPE_CONST, { .i64 = SWS_DITHER_BAYER }, .flags = VE, .unit = "sws_dither" }, + { "ed", "full error diffusion", 0, AV_OPT_TYPE_CONST, { .i64 = SWS_DITHER_ED }, .flags = VE, .unit = "sws_dither" }, + { "a_dither", "arithmetic addition dither", 0, AV_OPT_TYPE_CONST, { .i64 = SWS_DITHER_A_DITHER }, .flags = VE, .unit = "sws_dither" }, + { "x_dither", "arithmetic xor dither", 0, AV_OPT_TYPE_CONST, { .i64 = SWS_DITHER_X_DITHER }, .flags = VE, .unit = "sws_dither" }, - { "sws_dither", "set dithering algorithm", OFFSET(dither), AV_OPT_TYPE_INT, { .i64 = SWS_DITHER_AUTO }, 0, SWS_DITHER_NB, VE, .unit = "sws_dither" }, - { "auto", "leave choice to sws", 0, AV_OPT_TYPE_CONST, { .i64 = SWS_DITHER_AUTO }, INT_MIN, INT_MAX, VE, .unit = "sws_dither" }, - { "bayer", "bayer dither", 0, AV_OPT_TYPE_CONST, { .i64 = SWS_DITHER_BAYER }, INT_MIN, INT_MAX, VE, .unit = "sws_dither" }, - { "ed", "error diffusion", 0, AV_OPT_TYPE_CONST, { .i64 = SWS_DITHER_ED }, INT_MIN, INT_MAX, VE, .unit = "sws_dither" }, - { "a_dither", "arithmetic addition dither", 0, AV_OPT_TYPE_CONST, { .i64 = SWS_DITHER_A_DITHER}, INT_MIN, INT_MAX, VE, .unit = "sws_dither" }, - { "x_dither", "arithmetic xor dither", 0, AV_OPT_TYPE_CONST, { .i64 = SWS_DITHER_X_DITHER}, INT_MIN, INT_MAX, VE, .unit = "sws_dither" }, - { "gamma", "gamma correct scaling", OFFSET(gamma_flag),AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, VE }, - { "alphablend", "mode for alpha -> non alpha", OFFSET(alphablend),AV_OPT_TYPE_INT, { .i64 = SWS_ALPHA_BLEND_NONE}, 0, SWS_ALPHA_BLEND_NB-1, VE, .unit = "alphablend" }, - { "none", "ignore alpha", 0, AV_OPT_TYPE_CONST, { .i64 = SWS_ALPHA_BLEND_NONE}, INT_MIN, INT_MAX, VE, .unit = "alphablend" }, - { "uniform_color", "blend onto a uniform color", 0, AV_OPT_TYPE_CONST, { .i64 = SWS_ALPHA_BLEND_UNIFORM},INT_MIN, INT_MAX, VE, .unit = "alphablend" }, - { "checkerboard", "blend onto a checkerboard", 0, AV_OPT_TYPE_CONST, { .i64 = SWS_ALPHA_BLEND_CHECKERBOARD},INT_MIN, INT_MAX, VE, .unit = "alphablend" }, + { "alphablend", "mode for alpha -> non alpha", OFFSET(alphablend), AV_OPT_TYPE_INT, { .i64 = SWS_ALPHA_BLEND_NONE}, .flags = VE, .unit = "alphablend", .max = SWS_ALPHA_BLEND_NB - 1 }, + { "none", "ignore alpha", 0, AV_OPT_TYPE_CONST, { .i64 = SWS_ALPHA_BLEND_NONE}, .flags = VE, .unit = "alphablend" }, + { "uniform_color", "blend onto a uniform color", 0, AV_OPT_TYPE_CONST, { .i64 = SWS_ALPHA_BLEND_UNIFORM}, .flags = VE, .unit = "alphablend" }, + { "checkerboard", "blend onto a checkerboard", 0, AV_OPT_TYPE_CONST, { .i64 = SWS_ALPHA_BLEND_CHECKERBOARD}, .flags = VE, .unit = "alphablend" }, { "threads", "number of threads", OFFSET(nb_threads), AV_OPT_TYPE_INT, {.i64 = 1 }, 0, INT_MAX, VE, .unit = "threads" }, - { "auto", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = 0 }, .flags = VE, .unit = "threads" }, + { "auto", "automatic selection", 0, AV_OPT_TYPE_CONST, {.i64 = 0 }, .flags = VE, .unit = "threads" }, { NULL } }; From patchwork Tue Nov 12 09:50:36 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Niklas Haas X-Patchwork-Id: 52692 Delivered-To: ffmpegpatchwork2@gmail.com Received: by 2002:a05:612c:6704:20b0:4a6:637d:5226 with SMTP id mp4-n2csp139987vqb; Tue, 12 Nov 2024 01:52:21 -0800 (PST) X-Forwarded-Encrypted: i=2; AJvYcCXduwyWpcz3/FkkYc37+A46XGFsw7y/HBr81Q3dhS5U8fOLzluptmNoY2sX//mNbcbG+Oqn7cKfF4i6fSnROTvj@gmail.com X-Google-Smtp-Source: AGHT+IFWo+Sp5CdAsHBwLhZeqZ54Q3WcyROZT7WFizy/wpIrmVGoLnjyMeLmn5EVKq/MJbFRaR/V X-Received: by 2002:a17:907:9608:b0:a99:f94b:f92e with SMTP id a640c23a62f3a-a9eecab8086mr1486318966b.27.1731405141605; Tue, 12 Nov 2024 01:52:21 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1731405141; cv=none; d=google.com; s=arc-20240605; b=VjVGT6FU3KsA5xRU5SkaST9VYbOWxKGIAm52NUiYe5GdEu59cRtS/v6eb0rduvAT8d o9lnPdUlBSxYMJQdoiNiQStUQxIzSi/NZ6fSCSIYwajVp4m8ULRwjCwnshQ0kB7gKFCj fAnWYobfRejO3nnbbrVax/4Q041zjPDsR24+/FM+UpR5xnvrsnBsHbH7jn4YQPK+z4Bp nLpZI+BRyxY+bL2zc6pphScjcMvRq/97E7neUWzl68ZHztbLEZvv8Zm8WXhQVXvqZljc Hbiu6J81f0zY4be+Wq7KfgcAefYLJYMHIJOsMUPsIbtnNw+JoTUqtpBpRlUo2RoQ6qdm /meA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20240605; h=sender:errors-to:content-transfer-encoding:cc:reply-to :list-subscribe:list-help:list-post:list-archive:list-unsubscribe :list-id:precedence:subject:mime-version:references:in-reply-to :message-id:date:to:from:delivered-to; bh=hH52yPaWYc0zG5HDQ/d75nkEdQn5LqTYahOh4XljzRI=; fh=xmAeKtysnShNOmkhiJmYkS30uw4Fu2hvBJ7qlIwukxQ=; b=HRwa5xiXVwUlZ6Yr4z7obBAHp6kYoDhSulPdudz2UfB1LLHtetooxJ5koLERjAcZaS 7i05I2162d6Eob/6zjoBhGYlMzvqeXz1jcijJc5ciDjqrJjqBHrwci3X/WTatvDfPtKW UCj3vP1Gkef777bgtWoG5ED0ezMBA936n4ie+z5IkttQmSwFyGQXFCIHabKpzkFlzzJI WeDvZiwW6GjaXfWKEnWZdjCIBNfXFkd+Y/KEaYFDJ5EgY+xvSHMEBaONJ9UKqz/oURgc ZJ5KqtFbkUTVBi6IyWBjhTEzXOoB9mokjdDo017gShoPf0EMoD4sNqqzrl/nSA0MpMxE RIDA==; dara=google.com ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org Return-Path: Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org. [79.124.17.100]) by mx.google.com with ESMTPS id a640c23a62f3a-a9ee0a36a86si823793466b.206.2024.11.12.01.52.21 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 12 Nov 2024 01:52:21 -0800 (PST) Received-SPF: pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) client-ip=79.124.17.100; Authentication-Results: mx.google.com; spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 8C84D68DE17; Tue, 12 Nov 2024 11:52:05 +0200 (EET) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from haasn.dev (haasn.dev [78.46.187.166]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 4EA3D68DE17 for ; Tue, 12 Nov 2024 11:51:57 +0200 (EET) Received: from haasn.dev (unknown [10.30.1.1]) by haasn.dev (Postfix) with ESMTP id 1388D40D6F; Tue, 12 Nov 2024 10:51:57 +0100 (CET) From: Niklas Haas To: ffmpeg-devel@ffmpeg.org Date: Tue, 12 Nov 2024 10:50:36 +0100 Message-ID: <20241112095154.483778-3-ffmpeg@haasn.xyz> X-Mailer: git-send-email 2.47.0 In-Reply-To: <20241112095154.483778-1-ffmpeg@haasn.xyz> References: <20241112095154.483778-1-ffmpeg@haasn.xyz> MIME-Version: 1.0 Subject: [FFmpeg-devel] [PATCH v6 02/12] swscale/internal: use static_assert for enforcing offsets X-BeenThere: ffmpeg-devel@ffmpeg.org X-Mailman-Version: 2.1.29 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: Niklas Haas Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" X-TUID: KfOkAcJFG9IZ From: Niklas Haas Instead of sprinkling av_assert0 into random init functions. Sponsored-by: Sovereign Tech Fund Signed-off-by: Niklas Haas --- libswscale/swscale_internal.h | 11 +++++++++++ libswscale/utils.c | 2 -- libswscale/x86/swscale.c | 4 ---- 3 files changed, 11 insertions(+), 6 deletions(-) diff --git a/libswscale/swscale_internal.h b/libswscale/swscale_internal.h index 0035168997..0ab4e67270 100644 --- a/libswscale/swscale_internal.h +++ b/libswscale/swscale_internal.h @@ -22,6 +22,7 @@ #define SWSCALE_SWSCALE_INTERNAL_H #include +#include #include "config.h" #include "swscale.h" @@ -705,6 +706,16 @@ struct SwsInternal { }; //FIXME check init (where 0) +static_assert(offsetof(SwsInternal, redDither) + DITHER32_INT == offsetof(SwsInternal, dither32), + "dither32 must be at the same offset as redDither + DITHER32_INT"); + +#if ARCH_X86_64 +/* x86 yuv2gbrp uses the SwsInternal for yuv coefficients + if struct offsets change the asm needs to be updated too */ +static_assert(offsetof(SwsInternal, yuv2rgb_y_offset) == 40292, + "yuv2rgb_y_offset must be updated in x86 asm"); +#endif + SwsFunc ff_yuv2rgb_get_func_ptr(SwsInternal *c); int ff_yuv2rgb_c_init_tables(SwsInternal *c, const int inv_table[4], int fullRange, int brightness, diff --git a/libswscale/utils.c b/libswscale/utils.c index 5c21f9de4a..f71c63c17f 100644 --- a/libswscale/utils.c +++ b/libswscale/utils.c @@ -1228,8 +1228,6 @@ SwsContext *sws_alloc_context(void) { SwsInternal *c = av_mallocz(sizeof(SwsInternal)); - av_assert0(offsetof(SwsInternal, redDither) + DITHER32_INT == offsetof(SwsInternal, dither32)); - if (c) { c->av_class = &ff_sws_context_class; av_opt_set_defaults(c); diff --git a/libswscale/x86/swscale.c b/libswscale/x86/swscale.c index ceafdf4aef..40bfe4a2f6 100644 --- a/libswscale/x86/swscale.c +++ b/libswscale/x86/swscale.c @@ -791,10 +791,6 @@ switch(c->dstBpc){ \ if(c->flags & SWS_FULL_CHR_H_INT) { - /* yuv2gbrp uses the SwsInternal for yuv coefficients - if struct offsets change the asm needs to be updated too */ - av_assert0(offsetof(SwsInternal, yuv2rgb_y_offset) == 40292); - #define YUV2ANYX_FUNC_CASE(fmt, name, opt) \ case fmt: \ c->yuv2anyX = ff_yuv2##name##_full_X_##opt; \ From patchwork Tue Nov 12 09:50:37 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Niklas Haas X-Patchwork-Id: 52694 Delivered-To: ffmpegpatchwork2@gmail.com Received: by 2002:a05:612c:6704:20b0:4a6:637d:5226 with SMTP id mp4-n2csp140193vqb; Tue, 12 Nov 2024 01:52:46 -0800 (PST) X-Forwarded-Encrypted: i=2; AJvYcCUt7H8OziIS83N5mhNbNQPu/+QUVSQb5wg6Iv0/qZ/couXWc+94MezNQvJJb09Oro9VYDr0dG1XDw+ruxgcE5TF@gmail.com X-Google-Smtp-Source: AGHT+IEMKqJKePCNtM94hl3C6VG1SJ9HKgRinpI0Nhtm1J/d0ObnvOyZ5suPSyB11ch3bD61TVG2 X-Received: by 2002:a17:907:3e1a:b0:a9a:7f84:9409 with SMTP id a640c23a62f3a-a9eefe9bb9fmr568251466b.2.1731405166443; Tue, 12 Nov 2024 01:52:46 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1731405166; cv=none; d=google.com; s=arc-20240605; b=kjmzuz2ReSMs5BYV6mY41V1KFr2SN8VzXpp2WI/+xvY2dOUx8z9PpUvTr/8fHBjY7n oYBKF7vVUstF5PvF47EYkspBEuVSd5H1KepaKKOu7szrfQjjN0xW1nTROPEAnBjsSnYh df3D63J009vNWttXtbNlxI1zBGGftUe37i+22JA/Rth5YNJ56QaC+R0jJrJ7pxvIDi8x kWBAkvk8IfWGh4u4O0+8CqY4uVTPAk0T/bWbLp7LQKTRtZR+ndjDadCfyySQ7E4OvS17 B6Pea/svYkunn7VYjKLjlRk8be15cpGFg5t7U5hMIdGVGbxI2EBbwZCFBe+E3dOZr+Z9 J3Ow== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20240605; h=sender:errors-to:content-transfer-encoding:cc:reply-to :list-subscribe:list-help:list-post:list-archive:list-unsubscribe :list-id:precedence:subject:mime-version:references:in-reply-to :message-id:date:to:from:delivered-to; bh=6lDyVqxwuF3CGvMspvwm4GHSmQSdcvzn5i3LIcwCEwA=; fh=xmAeKtysnShNOmkhiJmYkS30uw4Fu2hvBJ7qlIwukxQ=; b=Hr0puh9AmgfaB17mm56c5FX3ysLOkrIjJiY9ouH3oOUqABjJVQeXrsUea2gHfAiwCU KWCDIBfl1yvoPv/ODkKP7nLZ1E2pD3RO3swPgwwZH9z5GLQ9Dv8G+9HPqvuA4mDjPpks Zy1ffFdwGyJ3q9j35rcw5yDeb5B8l//+l0JxUC2otAEwvR0etVZnW03PmHWhhtIROV0a CbvNKX9x0JE8LtyCrvVB9FHX/YbJnzUD0MowAkST9Ihv2seTrnAipni8InM075Dz9Tmz ERUA1uhXHX+jFjb34rGcJrYfcVh8xFpMViKHlWWLhCGSJHy7hw8de3k+lhzjLnQC0TxH U1Kg==; dara=google.com ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org Return-Path: Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org. [79.124.17.100]) by mx.google.com with ESMTPS id a640c23a62f3a-a9ee0dc13e0si760750466b.389.2024.11.12.01.52.46 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 12 Nov 2024 01:52:46 -0800 (PST) Received-SPF: pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) client-ip=79.124.17.100; Authentication-Results: mx.google.com; spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 3CE6F68DE36; Tue, 12 Nov 2024 11:52:08 +0200 (EET) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from haasn.dev (haasn.dev [78.46.187.166]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id A18DA68DE16 for ; Tue, 12 Nov 2024 11:51:57 +0200 (EET) Received: from haasn.dev (unknown [10.30.1.1]) by haasn.dev (Postfix) with ESMTP id 4E1A240E94; Tue, 12 Nov 2024 10:51:57 +0100 (CET) From: Niklas Haas To: ffmpeg-devel@ffmpeg.org Date: Tue, 12 Nov 2024 10:50:37 +0100 Message-ID: <20241112095154.483778-4-ffmpeg@haasn.xyz> X-Mailer: git-send-email 2.47.0 In-Reply-To: <20241112095154.483778-1-ffmpeg@haasn.xyz> References: <20241112095154.483778-1-ffmpeg@haasn.xyz> MIME-Version: 1.0 Subject: [FFmpeg-devel] [PATCH v6 03/12] swscale/internal: group user-facing options together X-BeenThere: ffmpeg-devel@ffmpeg.org X-Mailman-Version: 2.1.29 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: Niklas Haas Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" X-TUID: uhsVwH6voQJH From: Niklas Haas This is a preliminary step to separating these into a new struct. This commit contains no functional changes, it is a pure search-and-replace. Sponsored-by: Sovereign Tech Fund Signed-off-by: Niklas Haas --- libswscale/aarch64/swscale.c | 28 +- libswscale/aarch64/swscale_unscaled.c | 34 +- libswscale/alphablend.c | 16 +- libswscale/arm/swscale_unscaled.c | 24 +- libswscale/input.c | 2 +- libswscale/loongarch/input_lasx.c | 2 +- libswscale/loongarch/input_lsx.c | 2 +- libswscale/loongarch/output_lasx.c | 10 +- libswscale/loongarch/output_lsx.c | 10 +- libswscale/loongarch/swscale_init_loongarch.c | 28 +- libswscale/loongarch/swscale_lasx.c | 8 +- libswscale/loongarch/swscale_lsx.c | 8 +- libswscale/loongarch/yuv2rgb_lasx.c | 8 +- libswscale/loongarch/yuv2rgb_lsx.c | 12 +- libswscale/options.c | 32 +- libswscale/output.c | 24 +- libswscale/ppc/swscale_altivec.c | 6 +- libswscale/ppc/swscale_vsx.c | 18 +- libswscale/ppc/yuv2rgb_altivec.c | 18 +- libswscale/ppc/yuv2yuv_altivec.c | 14 +- libswscale/riscv/swscale.c | 4 +- libswscale/slice.c | 22 +- libswscale/swscale.c | 162 ++++----- libswscale/swscale_internal.h | 51 +-- libswscale/swscale_unscaled.c | 308 +++++++++--------- libswscale/utils.c | 275 ++++++++-------- libswscale/vscale.c | 10 +- libswscale/x86/output.asm | 2 +- libswscale/x86/swscale.c | 60 ++-- libswscale/x86/swscale_template.c | 20 +- libswscale/x86/yuv2rgb.c | 14 +- libswscale/yuv2rgb.c | 80 ++--- tests/checkasm/sw_gbrp.c | 16 +- tests/checkasm/sw_range_convert.c | 16 +- tests/checkasm/sw_rgb.c | 10 +- tests/checkasm/sw_scale.c | 18 +- 36 files changed, 692 insertions(+), 680 deletions(-) diff --git a/libswscale/aarch64/swscale.c b/libswscale/aarch64/swscale.c index 79b6272743..5173359e09 100644 --- a/libswscale/aarch64/swscale.c +++ b/libswscale/aarch64/swscale.c @@ -45,11 +45,11 @@ static void ff_hscale16to15_4_neon(SwsInternal *c, int16_t *_dst, int dstW, const uint8_t *_src, const int16_t *filter, const int32_t *filterPos, int filterSize) { - const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(c->srcFormat); + const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(c->opts.src_format); int sh = desc->comp[0].depth - 1; if (sh<15) { - sh = isAnyRGB(c->srcFormat) || c->srcFormat==AV_PIX_FMT_PAL8 ? 13 : (desc->comp[0].depth - 1); + sh = isAnyRGB(c->opts.src_format) || c->opts.src_format==AV_PIX_FMT_PAL8 ? 13 : (desc->comp[0].depth - 1); } else if (desc->flags & AV_PIX_FMT_FLAG_FLOAT) { /* float input are process like uint 16bpc */ sh = 16 - 1; } @@ -61,11 +61,11 @@ static void ff_hscale16to15_X8_neon(SwsInternal *c, int16_t *_dst, int dstW, const uint8_t *_src, const int16_t *filter, const int32_t *filterPos, int filterSize) { - const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(c->srcFormat); + const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(c->opts.src_format); int sh = desc->comp[0].depth - 1; if (sh<15) { - sh = isAnyRGB(c->srcFormat) || c->srcFormat==AV_PIX_FMT_PAL8 ? 13 : (desc->comp[0].depth - 1); + sh = isAnyRGB(c->opts.src_format) || c->opts.src_format==AV_PIX_FMT_PAL8 ? 13 : (desc->comp[0].depth - 1); } else if (desc->flags & AV_PIX_FMT_FLAG_FLOAT) { /* float input are process like uint 16bpc */ sh = 16 - 1; } @@ -77,11 +77,11 @@ static void ff_hscale16to15_X4_neon(SwsInternal *c, int16_t *_dst, int dstW, const uint8_t *_src, const int16_t *filter, const int32_t *filterPos, int filterSize) { - const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(c->srcFormat); + const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(c->opts.src_format); int sh = desc->comp[0].depth - 1; if (sh<15) { - sh = isAnyRGB(c->srcFormat) || c->srcFormat==AV_PIX_FMT_PAL8 ? 13 : (desc->comp[0].depth - 1); + sh = isAnyRGB(c->opts.src_format) || c->opts.src_format==AV_PIX_FMT_PAL8 ? 13 : (desc->comp[0].depth - 1); } else if (desc->flags & AV_PIX_FMT_FLAG_FLOAT) { /* float input are process like uint 16bpc */ sh = 16 - 1; } @@ -92,11 +92,11 @@ static void ff_hscale16to19_4_neon(SwsInternal *c, int16_t *_dst, int dstW, const uint8_t *_src, const int16_t *filter, const int32_t *filterPos, int filterSize) { - const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(c->srcFormat); + const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(c->opts.src_format); int bits = desc->comp[0].depth - 1; int sh = bits - 4; - if ((isAnyRGB(c->srcFormat) || c->srcFormat==AV_PIX_FMT_PAL8) && desc->comp[0].depth<16) { + if ((isAnyRGB(c->opts.src_format) || c->opts.src_format==AV_PIX_FMT_PAL8) && desc->comp[0].depth<16) { sh = 9; } else if (desc->flags & AV_PIX_FMT_FLAG_FLOAT) { /* float input are process like uint 16bpc */ sh = 16 - 1 - 4; @@ -110,11 +110,11 @@ static void ff_hscale16to19_X8_neon(SwsInternal *c, int16_t *_dst, int dstW, const uint8_t *_src, const int16_t *filter, const int32_t *filterPos, int filterSize) { - const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(c->srcFormat); + const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(c->opts.src_format); int bits = desc->comp[0].depth - 1; int sh = bits - 4; - if ((isAnyRGB(c->srcFormat) || c->srcFormat==AV_PIX_FMT_PAL8) && desc->comp[0].depth<16) { + if ((isAnyRGB(c->opts.src_format) || c->opts.src_format==AV_PIX_FMT_PAL8) && desc->comp[0].depth<16) { sh = 9; } else if (desc->flags & AV_PIX_FMT_FLAG_FLOAT) { /* float input are process like uint 16bpc */ sh = 16 - 1 - 4; @@ -128,11 +128,11 @@ static void ff_hscale16to19_X4_neon(SwsInternal *c, int16_t *_dst, int dstW, const uint8_t *_src, const int16_t *filter, const int32_t *filterPos, int filterSize) { - const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(c->srcFormat); + const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(c->opts.src_format); int bits = desc->comp[0].depth - 1; int sh = bits - 4; - if ((isAnyRGB(c->srcFormat) || c->srcFormat==AV_PIX_FMT_PAL8) && desc->comp[0].depth<16) { + if ((isAnyRGB(c->opts.src_format) || c->opts.src_format==AV_PIX_FMT_PAL8) && desc->comp[0].depth<16) { sh = 9; } else if (desc->flags & AV_PIX_FMT_FLAG_FLOAT) { /* float input are process like uint 16bpc */ sh = 16 - 1 - 4; @@ -229,7 +229,7 @@ av_cold void ff_sws_init_range_convert_aarch64(SwsInternal *c) if (have_neon(cpu_flags)) { if (c->dstBpc <= 14) { - if (c->srcRange) { + if (c->opts.src_range) { c->lumConvertRange = ff_lumRangeFromJpeg_neon; c->chrConvertRange = ff_chrRangeFromJpeg_neon; } else { @@ -251,7 +251,7 @@ av_cold void ff_sws_init_swscale_aarch64(SwsInternal *c) if (c->dstBpc == 8) { c->yuv2planeX = ff_yuv2planeX_8_neon; } - switch (c->srcFormat) { + switch (c->opts.src_format) { case AV_PIX_FMT_ABGR: c->lumToYV12 = ff_abgr32ToY_neon; if (c->chrSrcHSubSample) diff --git a/libswscale/aarch64/swscale_unscaled.c b/libswscale/aarch64/swscale_unscaled.c index 4f54120445..fdecafd94b 100644 --- a/libswscale/aarch64/swscale_unscaled.c +++ b/libswscale/aarch64/swscale_unscaled.c @@ -43,7 +43,7 @@ static int ifmt##_to_##ofmt##_neon_wrapper(SwsInternal *c, const uint8_t *const const int dstStride[]) { \ const int16_t yuv2rgb_table[] = { YUV_TO_RGB_TABLE }; \ \ - return ff_##ifmt##_to_##ofmt##_neon(c->srcW, srcSliceH, \ + return ff_##ifmt##_to_##ofmt##_neon(c->opts.src_w, srcSliceH, \ dst[0] + srcSliceY * dstStride[0], dstStride[0], \ src[0], srcStride[0], \ src[1], srcStride[1], \ @@ -71,7 +71,7 @@ static int ifmt##_to_##ofmt##_neon_wrapper(SwsInternal *c, const uint8_t *const const int dstStride[]) { \ const int16_t yuv2rgb_table[] = { YUV_TO_RGB_TABLE }; \ \ - return ff_##ifmt##_to_##ofmt##_neon(c->srcW, srcSliceH, \ + return ff_##ifmt##_to_##ofmt##_neon(c->opts.src_w, srcSliceH, \ dst[0] + srcSliceY * dstStride[0], dstStride[0], \ src[0], srcStride[0], \ src[1], srcStride[1], \ @@ -108,7 +108,7 @@ static int ifmt##_to_##ofmt##_neon_wrapper(SwsInternal *c, const uint8_t *const const int dstStride[]) { \ const int16_t yuv2rgb_table[] = { YUV_TO_RGB_TABLE }; \ \ - return ff_##ifmt##_to_##ofmt##_neon(c->srcW, srcSliceH, \ + return ff_##ifmt##_to_##ofmt##_neon(c->opts.src_w, srcSliceH, \ dst[0] + srcSliceY * dstStride[0], dstStride[0], \ src[0], srcStride[0], src[1], srcStride[1], \ yuv2rgb_table, \ @@ -133,7 +133,7 @@ static int ifmt##_to_##ofmt##_neon_wrapper(SwsInternal *c, const uint8_t *const const int dstStride[]) { \ const int16_t yuv2rgb_table[] = { YUV_TO_RGB_TABLE }; \ \ - return ff_##ifmt##_to_##ofmt##_neon(c->srcW, srcSliceH, \ + return ff_##ifmt##_to_##ofmt##_neon(c->opts.src_w, srcSliceH, \ dst[0] + srcSliceY * dstStride[0], dstStride[0], \ src[0], srcStride[0], src[1], srcStride[1], \ yuv2rgb_table, \ @@ -155,15 +155,17 @@ static int nv24_to_yuv420p_neon_wrapper(SwsInternal *c, const uint8_t *const src uint8_t *dst1 = dst[1] + dstStride[1] * srcSliceY / 2; uint8_t *dst2 = dst[2] + dstStride[2] * srcSliceY / 2; - ff_copyPlane(src[0], srcStride[0], srcSliceY, srcSliceH, c->srcW, + ff_copyPlane(src[0], srcStride[0], srcSliceY, srcSliceH, c->opts.src_w, dst[0], dstStride[0]); - if (c->srcFormat == AV_PIX_FMT_NV24) + if (c->opts.src_format == AV_PIX_FMT_NV24) ff_nv24_to_yuv420p_chroma_neon(dst1, dstStride[1], dst2, dstStride[2], - src[1], srcStride[1], c->srcW / 2, srcSliceH); + src[1], srcStride[1], c->opts.src_w / 2, + srcSliceH); else ff_nv24_to_yuv420p_chroma_neon(dst2, dstStride[2], dst1, dstStride[1], - src[1], srcStride[1], c->srcW / 2, srcSliceH); + src[1], srcStride[1], c->opts.src_w / 2, + srcSliceH); return srcSliceH; } @@ -183,10 +185,10 @@ DECLARE_FF_NVX_TO_ALL_RGBX_FUNCS(nv21) * assembly might be writing as much as 4*15=60 extra bytes at the end of the * line, which won't fit the 32-bytes buffer alignment. */ #define SET_FF_NVX_TO_RGBX_FUNC(ifmt, IFMT, ofmt, OFMT, accurate_rnd) do { \ - if (c->srcFormat == AV_PIX_FMT_##IFMT \ - && c->dstFormat == AV_PIX_FMT_##OFMT \ - && !(c->srcH & 1) \ - && !(c->srcW & 15) \ + if (c->opts.src_format == AV_PIX_FMT_##IFMT \ + && c->opts.dst_format == AV_PIX_FMT_##OFMT \ + && !(c->opts.src_h & 1) \ + && !(c->opts.src_w & 15) \ && !accurate_rnd) \ c->convert_unscaled = ifmt##_to_##ofmt##_neon_wrapper; \ } while (0) @@ -200,16 +202,16 @@ DECLARE_FF_NVX_TO_ALL_RGBX_FUNCS(nv21) } while (0) static void get_unscaled_swscale_neon(SwsInternal *c) { - int accurate_rnd = c->flags & SWS_ACCURATE_RND; + int accurate_rnd = c->opts.flags & SWS_ACCURATE_RND; SET_FF_NVX_TO_ALL_RGBX_FUNC(nv12, NV12, accurate_rnd); SET_FF_NVX_TO_ALL_RGBX_FUNC(nv21, NV21, accurate_rnd); SET_FF_NVX_TO_ALL_RGBX_FUNC(yuv420p, YUV420P, accurate_rnd); SET_FF_NVX_TO_ALL_RGBX_FUNC(yuv422p, YUV422P, accurate_rnd); - if (c->dstFormat == AV_PIX_FMT_YUV420P && - (c->srcFormat == AV_PIX_FMT_NV24 || c->srcFormat == AV_PIX_FMT_NV42) && - !(c->srcH & 1) && !(c->srcW & 15) && !accurate_rnd) + if (c->opts.dst_format == AV_PIX_FMT_YUV420P && + (c->opts.src_format == AV_PIX_FMT_NV24 || c->opts.src_format == AV_PIX_FMT_NV42) && + !(c->opts.src_h & 1) && !(c->opts.src_w & 15) && !accurate_rnd) c->convert_unscaled = nv24_to_yuv420p_neon_wrapper; } diff --git a/libswscale/alphablend.c b/libswscale/alphablend.c index 4ee23d3aee..f9484bcc91 100644 --- a/libswscale/alphablend.c +++ b/libswscale/alphablend.c @@ -24,10 +24,10 @@ int ff_sws_alphablendaway(SwsInternal *c, const uint8_t *const src[], const int srcStride[], int srcSliceY, int srcSliceH, uint8_t *const dst[], const int dstStride[]) { - const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(c->srcFormat); + const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(c->opts.src_format); int nb_components = desc->nb_components; int plane, x, ysrc; - int plane_count = isGray(c->srcFormat) ? 1 : 3; + int plane_count = isGray(c->opts.src_format) ? 1 : 3; int sixteen_bits = desc->comp[0].depth >= 9; unsigned off = 1<<(desc->comp[0].depth - 1); unsigned shift = desc->comp[0].depth; @@ -36,7 +36,7 @@ int ff_sws_alphablendaway(SwsInternal *c, const uint8_t *const src[], for (plane = 0; plane < plane_count; plane++) { int a = 0, b = 0; - if (c->alphablend == SWS_ALPHA_BLEND_CHECKERBOARD) { + if (c->opts.alpha_blend == SWS_ALPHA_BLEND_CHECKERBOARD) { a = (1<<(desc->comp[0].depth - 1))/2; b = 3*(1<<(desc->comp[0].depth-1))/2; } @@ -47,7 +47,7 @@ int ff_sws_alphablendaway(SwsInternal *c, const uint8_t *const src[], av_assert0(plane_count == nb_components - 1); if (desc->flags & AV_PIX_FMT_FLAG_PLANAR) { for (plane = 0; plane < plane_count; plane++) { - int w = plane ? c->chrSrcW : c->srcW; + int w = plane ? c->chrSrcW : c->opts.src_w; int x_subsample = plane ? desc->log2_chroma_w: 0; int y_subsample = plane ? desc->log2_chroma_h: 0; for (ysrc = 0; ysrc < AV_CEIL_RSHIFT(srcSliceH, y_subsample); ysrc++) { @@ -60,7 +60,7 @@ int ff_sws_alphablendaway(SwsInternal *c, const uint8_t *const src[], const uint16_t *s = (const uint16_t *)(src[plane ] + srcStride[plane ] * ysrc); const uint16_t *a = (const uint16_t *)(src[plane_count] + (srcStride[plane_count] * ysrc << y_subsample)); uint16_t *d = ( uint16_t *)(dst[plane ] + dstStride[plane ] * y); - if ((!isBE(c->srcFormat)) == !HAVE_BIGENDIAN) { + if ((!isBE(c->opts.src_format)) == !HAVE_BIGENDIAN) { for (x = 0; x < w; x++) { if (y_subsample) { alpha = (a[2*x] + a[2*x + 1] + 2 + @@ -101,7 +101,7 @@ int ff_sws_alphablendaway(SwsInternal *c, const uint8_t *const src[], const uint16_t *s = (const uint16_t *)(src[plane ] + srcStride[plane ] * ysrc); const uint16_t *a = (const uint16_t *)(src[plane_count] + srcStride[plane_count] * ysrc); uint16_t *d = ( uint16_t *)(dst[plane ] + dstStride[plane ] * y); - if ((!isBE(c->srcFormat)) == !HAVE_BIGENDIAN) { + if ((!isBE(c->opts.src_format)) == !HAVE_BIGENDIAN) { for (x = 0; x < w; x++) { unsigned u = s[x]*a[x] + target_table[((x^y)>>5)&1][plane]*(max-a[x]) + off; d[x] = av_clip((u + (u >> shift)) >> shift, 0, max); @@ -127,14 +127,14 @@ int ff_sws_alphablendaway(SwsInternal *c, const uint8_t *const src[], } } else { int alpha_pos = desc->comp[plane_count].offset; - int w = c->srcW; + int w = c->opts.src_w; for (ysrc = 0; ysrc < srcSliceH; ysrc++) { int y = ysrc + srcSliceY; if (sixteen_bits) { const uint16_t *s = (const uint16_t *)(src[0] + srcStride[0] * ysrc + 2*!alpha_pos); const uint16_t *a = (const uint16_t *)(src[0] + srcStride[0] * ysrc + alpha_pos); uint16_t *d = ( uint16_t *)(dst[0] + dstStride[0] * y); - if ((!isBE(c->srcFormat)) == !HAVE_BIGENDIAN) { + if ((!isBE(c->opts.src_format)) == !HAVE_BIGENDIAN) { for (x = 0; x < w; x++) { for (plane = 0; plane < plane_count; plane++) { int x_index = (plane_count + 1) * x; diff --git a/libswscale/arm/swscale_unscaled.c b/libswscale/arm/swscale_unscaled.c index 14685dbc50..5c3074a0cd 100644 --- a/libswscale/arm/swscale_unscaled.c +++ b/libswscale/arm/swscale_unscaled.c @@ -41,7 +41,7 @@ static int rgbx_to_nv12_neon_32_wrapper(SwsInternal *context, const uint8_t *con rgbx_to_nv12_neon_32(src[0] + srcSliceY * srcStride[0], dst[0] + srcSliceY * dstStride[0], dst[1] + (srcSliceY / 2) * dstStride[1], - context->srcW, srcSliceH, + context->opts.src_w, srcSliceH, dstStride[0], dstStride[1], srcStride[0], context->input_rgb2yuv_table); @@ -55,7 +55,7 @@ static int rgbx_to_nv12_neon_16_wrapper(SwsInternal *context, const uint8_t *con rgbx_to_nv12_neon_16(src[0] + srcSliceY * srcStride[0], dst[0] + srcSliceY * dstStride[0], dst[1] + (srcSliceY / 2) * dstStride[1], - context->srcW, srcSliceH, + context->opts.src_w, srcSliceH, dstStride[0], dstStride[1], srcStride[0], context->input_rgb2yuv_table); @@ -84,7 +84,7 @@ static int ifmt##_to_##ofmt##_neon_wrapper(SwsInternal *c, const uint8_t *const const int dstStride[]) { \ const int16_t yuv2rgb_table[] = { YUV_TO_RGB_TABLE }; \ \ - ff_##ifmt##_to_##ofmt##_neon(c->srcW, srcSliceH, \ + ff_##ifmt##_to_##ofmt##_neon(c->opts.src_w, srcSliceH, \ dst[0] + srcSliceY * dstStride[0], dstStride[0], \ src[0], srcStride[0], \ src[1], srcStride[1], \ @@ -120,7 +120,7 @@ static int ifmt##_to_##ofmt##_neon_wrapper(SwsInternal *c, const uint8_t *const const int dstStride[]) { \ const int16_t yuv2rgb_table[] = { YUV_TO_RGB_TABLE }; \ \ - ff_##ifmt##_to_##ofmt##_neon(c->srcW, srcSliceH, \ + ff_##ifmt##_to_##ofmt##_neon(c->opts.src_w, srcSliceH, \ dst[0] + srcSliceY * dstStride[0], dstStride[0], \ src[0], srcStride[0], src[1], srcStride[1], \ yuv2rgb_table, \ @@ -144,10 +144,10 @@ DECLARE_FF_NVX_TO_ALL_RGBX_FUNCS(nv21) * assembly might be writing as much as 4*15=60 extra bytes at the end of the * line, which won't fit the 32-bytes buffer alignment. */ #define SET_FF_NVX_TO_RGBX_FUNC(ifmt, IFMT, ofmt, OFMT, accurate_rnd) do { \ - if (c->srcFormat == AV_PIX_FMT_##IFMT \ - && c->dstFormat == AV_PIX_FMT_##OFMT \ - && !(c->srcH & 1) \ - && !(c->srcW & 15) \ + if (c->opts.src_format == AV_PIX_FMT_##IFMT \ + && c->opts.dst_format == AV_PIX_FMT_##OFMT \ + && !(c->opts.src_h & 1) \ + && !(c->opts.src_w & 15) \ && !accurate_rnd) { \ c->convert_unscaled = ifmt##_to_##ofmt##_neon_wrapper; \ } \ @@ -161,10 +161,10 @@ DECLARE_FF_NVX_TO_ALL_RGBX_FUNCS(nv21) } while (0) static void get_unscaled_swscale_neon(SwsInternal *c) { - int accurate_rnd = c->flags & SWS_ACCURATE_RND; - if (c->srcFormat == AV_PIX_FMT_RGBA - && c->dstFormat == AV_PIX_FMT_NV12 - && (c->srcW >= 16)) { + int accurate_rnd = c->opts.flags & SWS_ACCURATE_RND; + if (c->opts.src_format == AV_PIX_FMT_RGBA + && c->opts.dst_format == AV_PIX_FMT_NV12 + && (c->opts.src_w >= 16)) { c->convert_unscaled = accurate_rnd ? rgbx_to_nv12_neon_32_wrapper : rgbx_to_nv12_neon_16_wrapper; } diff --git a/libswscale/input.c b/libswscale/input.c index a298b92a05..9f9410f922 100644 --- a/libswscale/input.c +++ b/libswscale/input.c @@ -1563,7 +1563,7 @@ av_cold void ff_sws_init_input_funcs(SwsInternal *c, planarX_YV12_fn *readAlpPlanar, planarX2_YV12_fn *readChrPlanar) { - enum AVPixelFormat srcFormat = c->srcFormat; + enum AVPixelFormat srcFormat = c->opts.src_format; *chrToYV12 = NULL; switch (srcFormat) { diff --git a/libswscale/loongarch/input_lasx.c b/libswscale/loongarch/input_lasx.c index b682179c6e..046f395ae5 100644 --- a/libswscale/loongarch/input_lasx.c +++ b/libswscale/loongarch/input_lasx.c @@ -203,7 +203,7 @@ void planar_rgb_to_y_lasx(uint8_t *_dst, const uint8_t *src[4], int width, av_cold void ff_sws_init_input_lasx(SwsInternal *c) { - enum AVPixelFormat srcFormat = c->srcFormat; + enum AVPixelFormat srcFormat = c->opts.src_format; switch (srcFormat) { case AV_PIX_FMT_YUYV422: diff --git a/libswscale/loongarch/input_lsx.c b/libswscale/loongarch/input_lsx.c index 2bc7577961..c0e5627690 100644 --- a/libswscale/loongarch/input_lsx.c +++ b/libswscale/loongarch/input_lsx.c @@ -23,7 +23,7 @@ av_cold void ff_sws_init_input_lsx(SwsInternal *c) { - enum AVPixelFormat srcFormat = c->srcFormat; + enum AVPixelFormat srcFormat = c->opts.src_format; switch (srcFormat) { case AV_PIX_FMT_YUYV422: diff --git a/libswscale/loongarch/output_lasx.c b/libswscale/loongarch/output_lasx.c index 4e5ad3d802..21d0a501b0 100644 --- a/libswscale/loongarch/output_lasx.c +++ b/libswscale/loongarch/output_lasx.c @@ -888,7 +888,7 @@ static av_always_inline void yuv2rgb_write_full(SwsInternal *c, { int r,g,b; - switch (c->dither) { + switch (c->opts.dither) { default: case SWS_DITHER_AUTO: case SWS_DITHER_ED: @@ -1784,7 +1784,7 @@ av_cold void ff_sws_init_output_lasx(SwsInternal *c, yuv2packedX_fn *yuv2packedX, yuv2anyX_fn *yuv2anyX) { - enum AVPixelFormat dstFormat = c->dstFormat; + enum AVPixelFormat dstFormat = c->opts.dst_format; /* Add initialization once optimized */ if (isSemiPlanarYUV(dstFormat) && isDataInHighBits(dstFormat)) { @@ -1797,8 +1797,8 @@ av_cold void ff_sws_init_output_lasx(SwsInternal *c, *yuv2planeX = yuv2planeX_8_lasx; } - if(c->flags & SWS_FULL_CHR_H_INT) { - switch (c->dstFormat) { + if(c->opts.flags & SWS_FULL_CHR_H_INT) { + switch (c->opts.dst_format) { case AV_PIX_FMT_RGBA: #if CONFIG_SMALL c->yuv2packedX = yuv2rgba32_full_X_lasx; @@ -1911,7 +1911,7 @@ av_cold void ff_sws_init_output_lasx(SwsInternal *c, break; } } else { - switch (c->dstFormat) { + switch (c->opts.dst_format) { case AV_PIX_FMT_RGB32: case AV_PIX_FMT_BGR32: #if CONFIG_SMALL diff --git a/libswscale/loongarch/output_lsx.c b/libswscale/loongarch/output_lsx.c index 29fe30758a..24e6de5535 100644 --- a/libswscale/loongarch/output_lsx.c +++ b/libswscale/loongarch/output_lsx.c @@ -838,7 +838,7 @@ static av_always_inline void yuv2rgb_write_full(SwsInternal *c, { int r,g,b; - switch (c->dither) { + switch (c->opts.dither) { default: case SWS_DITHER_AUTO: case SWS_DITHER_ED: @@ -1633,7 +1633,7 @@ av_cold void ff_sws_init_output_lsx(SwsInternal *c, yuv2packedX_fn *yuv2packedX, yuv2anyX_fn *yuv2anyX) { - enum AVPixelFormat dstFormat = c->dstFormat; + enum AVPixelFormat dstFormat = c->opts.dst_format; /* Add initialization once optimized */ if (isSemiPlanarYUV(dstFormat) && isDataInHighBits(dstFormat)) { @@ -1646,8 +1646,8 @@ av_cold void ff_sws_init_output_lsx(SwsInternal *c, *yuv2planeX = yuv2planeX_8_lsx; } - if(c->flags & SWS_FULL_CHR_H_INT) { - switch (c->dstFormat) { + if(c->opts.flags & SWS_FULL_CHR_H_INT) { + switch (c->opts.dst_format) { case AV_PIX_FMT_RGBA: #if CONFIG_SMALL c->yuv2packedX = yuv2rgba32_full_X_lsx; @@ -1760,7 +1760,7 @@ av_cold void ff_sws_init_output_lsx(SwsInternal *c, break; } } else { - switch (c->dstFormat) { + switch (c->opts.dst_format) { case AV_PIX_FMT_RGB32: case AV_PIX_FMT_BGR32: #if CONFIG_SMALL diff --git a/libswscale/loongarch/swscale_init_loongarch.c b/libswscale/loongarch/swscale_init_loongarch.c index f02e957998..843fa08196 100644 --- a/libswscale/loongarch/swscale_init_loongarch.c +++ b/libswscale/loongarch/swscale_init_loongarch.c @@ -30,7 +30,7 @@ av_cold void ff_sws_init_range_convert_loongarch(SwsInternal *c) if (have_lsx(cpu_flags)) { if (c->dstBpc <= 14) { - if (c->srcRange) { + if (c->opts.src_range) { c->lumConvertRange = lumRangeFromJpeg_lsx; c->chrConvertRange = chrRangeFromJpeg_lsx; } else { @@ -42,7 +42,7 @@ av_cold void ff_sws_init_range_convert_loongarch(SwsInternal *c) #if HAVE_LASX if (have_lasx(cpu_flags)) { if (c->dstBpc <= 14) { - if (c->srcRange) { + if (c->opts,src_range) { c->lumConvertRange = lumRangeFromJpeg_lasx; c->chrConvertRange = chrRangeFromJpeg_lasx; } else { @@ -107,29 +107,29 @@ av_cold SwsFunc ff_yuv2rgb_init_loongarch(SwsInternal *c) int cpu_flags = av_get_cpu_flags(); #if HAVE_LASX if (have_lasx(cpu_flags)) { - if (c->srcFormat == AV_PIX_FMT_YUV420P) { - switch (c->dstFormat) { + if (c->opts.src_format == AV_PIX_FMT_YUV420P) { + switch (c->opts.dst_format) { case AV_PIX_FMT_RGB24: return yuv420_rgb24_lasx; case AV_PIX_FMT_BGR24: return yuv420_bgr24_lasx; case AV_PIX_FMT_RGBA: - if (CONFIG_SWSCALE_ALPHA && isALPHA(c->srcFormat)) { + if (CONFIG_SWSCALE_ALPHA && isALPHA(c->opts.src_format)) { break; } else return yuv420_rgba32_lasx; case AV_PIX_FMT_ARGB: - if (CONFIG_SWSCALE_ALPHA && isALPHA(c->srcFormat)) { + if (CONFIG_SWSCALE_ALPHA && isALPHA(c->opts.src_format)) { break; } else return yuv420_argb32_lasx; case AV_PIX_FMT_BGRA: - if (CONFIG_SWSCALE_ALPHA && isALPHA(c->srcFormat)) { + if (CONFIG_SWSCALE_ALPHA && isALPHA(c->opts.src_format)) { break; } else return yuv420_bgra32_lasx; case AV_PIX_FMT_ABGR: - if (CONFIG_SWSCALE_ALPHA && isALPHA(c->srcFormat)) { + if (CONFIG_SWSCALE_ALPHA && isALPHA(c->opts.src_format)) { break; } else return yuv420_abgr32_lasx; @@ -138,29 +138,29 @@ av_cold SwsFunc ff_yuv2rgb_init_loongarch(SwsInternal *c) } #endif // #if HAVE_LASX if (have_lsx(cpu_flags)) { - if (c->srcFormat == AV_PIX_FMT_YUV420P) { - switch (c->dstFormat) { + if (c->opts.src_format == AV_PIX_FMT_YUV420P) { + switch (c->opts.dst_format) { case AV_PIX_FMT_RGB24: return yuv420_rgb24_lsx; case AV_PIX_FMT_BGR24: return yuv420_bgr24_lsx; case AV_PIX_FMT_RGBA: - if (CONFIG_SWSCALE_ALPHA && isALPHA(c->srcFormat)) { + if (CONFIG_SWSCALE_ALPHA && isALPHA(c->opts.src_format)) { break; } else return yuv420_rgba32_lsx; case AV_PIX_FMT_ARGB: - if (CONFIG_SWSCALE_ALPHA && isALPHA(c->srcFormat)) { + if (CONFIG_SWSCALE_ALPHA && isALPHA(c->opts.src_format)) { break; } else return yuv420_argb32_lsx; case AV_PIX_FMT_BGRA: - if (CONFIG_SWSCALE_ALPHA && isALPHA(c->srcFormat)) { + if (CONFIG_SWSCALE_ALPHA && isALPHA(c->opts.src_format)) { break; } else return yuv420_bgra32_lsx; case AV_PIX_FMT_ABGR: - if (CONFIG_SWSCALE_ALPHA && isALPHA(c->srcFormat)) { + if (CONFIG_SWSCALE_ALPHA && isALPHA(c->opts.src_format)) { break; } else return yuv420_abgr32_lsx; diff --git a/libswscale/loongarch/swscale_lasx.c b/libswscale/loongarch/swscale_lasx.c index 79fa4c64b0..fcaca3123b 100644 --- a/libswscale/loongarch/swscale_lasx.c +++ b/libswscale/loongarch/swscale_lasx.c @@ -677,7 +677,7 @@ void ff_hscale_16_to_15_lasx(SwsInternal *c, int16_t *dst, int dstW, const uint8_t *_src, const int16_t *filter, const int32_t *filterPos, int filterSize) { - const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(c->srcFormat); + const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(c->opts.src_format); int i; const uint16_t *src = (const uint16_t *) _src; int sh = desc->comp[0].depth - 1; @@ -688,7 +688,7 @@ void ff_hscale_16_to_15_lasx(SwsInternal *c, int16_t *dst, int dstW, __m256i zero = __lasx_xvldi(0); if (sh < 15) { - sh = isAnyRGB(c->srcFormat) || c->srcFormat==AV_PIX_FMT_PAL8 ? 13 : + sh = isAnyRGB(c->opts.src_format) || c->opts.src_format==AV_PIX_FMT_PAL8 ? 13 : (desc->comp[0].depth - 1); } else if (desc->flags && AV_PIX_FMT_FLAG_FLOAT) { sh = 15; @@ -824,7 +824,7 @@ void ff_hscale_16_to_19_lasx(SwsInternal *c, int16_t *_dst, int dstW, const uint8_t *_src, const int16_t *filter, const int32_t *filterPos, int filterSize) { - const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(c->srcFormat); + const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(c->opts.src_format); int i; int32_t *dst = (int32_t *) _dst; const uint16_t *src = (const uint16_t *) _src; @@ -835,7 +835,7 @@ void ff_hscale_16_to_19_lasx(SwsInternal *c, int16_t *_dst, int dstW, __m256i shift; __m256i zero = __lasx_xvldi(0); - if ((isAnyRGB(c->srcFormat) || c->srcFormat == AV_PIX_FMT_PAL8) + if ((isAnyRGB(c->opts.src_format) || c->opts.src_format == AV_PIX_FMT_PAL8) && desc->comp[0].depth<16) { sh = 9; } else if (desc->flags & AV_PIX_FMT_FLAG_FLOAT) { diff --git a/libswscale/loongarch/swscale_lsx.c b/libswscale/loongarch/swscale_lsx.c index dbdaf18de6..fce09800fe 100644 --- a/libswscale/loongarch/swscale_lsx.c +++ b/libswscale/loongarch/swscale_lsx.c @@ -27,11 +27,11 @@ void ff_hscale_16_to_15_lsx(SwsInternal *c, int16_t *_dst, int dstW, const uint8_t *_src, const int16_t *filter, const int32_t *filterPos, int filterSize) { - const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(c->srcFormat); + const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(c->opts.src_format); int sh = desc->comp[0].depth - 1; if (sh < 15) { - sh = isAnyRGB(c->srcFormat) || c->srcFormat==AV_PIX_FMT_PAL8 ? 13 : + sh = isAnyRGB(c->opts.src_format) || c->opts.src_format==AV_PIX_FMT_PAL8 ? 13 : (desc->comp[0].depth - 1); } else if (desc->flags && AV_PIX_FMT_FLAG_FLOAT) { sh = 15; @@ -43,11 +43,11 @@ void ff_hscale_16_to_19_lsx(SwsInternal *c, int16_t *_dst, int dstW, const uint8_t *_src, const int16_t *filter, const int32_t *filterPos, int filterSize) { - const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(c->srcFormat); + const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(c->opts.src_format); int bits = desc->comp[0].depth - 1; int sh = bits - 4; - if ((isAnyRGB(c->srcFormat) || c->srcFormat==AV_PIX_FMT_PAL8) && desc->comp[0].depth<16) { + if ((isAnyRGB(c->opts.src_format) || c->opts.src_format==AV_PIX_FMT_PAL8) && desc->comp[0].depth<16) { sh = 9; } else if (desc->flags & AV_PIX_FMT_FLAG_FLOAT) { /* float input are process like uint 16bpc */ diff --git a/libswscale/loongarch/yuv2rgb_lasx.c b/libswscale/loongarch/yuv2rgb_lasx.c index 1b36d617b5..e9e4a63a0a 100644 --- a/libswscale/loongarch/yuv2rgb_lasx.c +++ b/libswscale/loongarch/yuv2rgb_lasx.c @@ -173,11 +173,11 @@ __m256i shuf3 = {0x1E0F0E1C0D0C1A0B, 0x0101010101010101, \ 0x1E0F0E1C0D0C1A0B, 0x0101010101010101}; \ YUV2RGB_LOAD_COE \ - y = (c->dstW + 7) & ~7; \ + y = (c->opts.dst_w + 7) & ~7; \ h_size = y >> 4; \ res = y & 15; \ \ - vshift = c->srcFormat != AV_PIX_FMT_YUV422P; \ + vshift = c->opts.src_format != AV_PIX_FMT_YUV422P; \ for (y = 0; y < srcSliceH; y += 2) { \ dst_type *image1 = (dst_type *)(dst[0] + (y + srcSliceY) * dstStride[0]);\ dst_type *image2 = (dst_type *)(image1 + dstStride[0]);\ @@ -199,11 +199,11 @@ __m256i a = __lasx_xvldi(0xFF); \ \ YUV2RGB_LOAD_COE \ - y = (c->dstW + 7) & ~7; \ + y = (c->opts.dst_w + 7) & ~7; \ h_size = y >> 4; \ res = y & 15; \ \ - vshift = c->srcFormat != AV_PIX_FMT_YUV422P; \ + vshift = c->opts.src_format != AV_PIX_FMT_YUV422P; \ for (y = 0; y < srcSliceH; y += 2) { \ int yd = y + srcSliceY; \ dst_type av_unused *r, *g, *b; \ diff --git a/libswscale/loongarch/yuv2rgb_lsx.c b/libswscale/loongarch/yuv2rgb_lsx.c index f2f424265f..6339d07d6c 100644 --- a/libswscale/loongarch/yuv2rgb_lsx.c +++ b/libswscale/loongarch/yuv2rgb_lsx.c @@ -128,9 +128,9 @@ \ YUV2RGB_LOAD_COE \ \ - h_size = c->dstW >> 4; \ - res = (c->dstW & 15) >> 1; \ - vshift = c->srcFormat != AV_PIX_FMT_YUV422P; \ + h_size = c->opts.dst_w >> 4; \ + res = (c->opts.dst_w & 15) >> 1; \ + vshift = c->opts.src_format != AV_PIX_FMT_YUV422P; \ for (y = 0; y < srcSliceH; y += 2) { \ dst_type av_unused *r, *g, *b; \ dst_type *image1 = (dst_type *)(dst[0] + (y + srcSliceY) * dstStride[0]);\ @@ -156,9 +156,9 @@ \ YUV2RGB_LOAD_COE \ \ - h_size = c->dstW >> 4; \ - res = (c->dstW & 15) >> 1; \ - vshift = c->srcFormat != AV_PIX_FMT_YUV422P; \ + h_size = c->opts.dst_w >> 4; \ + res = (c->opts.dst_w & 15) >> 1; \ + vshift = c->opts.src_format != AV_PIX_FMT_YUV422P; \ for (y = 0; y < srcSliceH; y += 2) { \ int yd = y + srcSliceY; \ dst_type av_unused *r, *g, *b; \ diff --git a/libswscale/options.c b/libswscale/options.c index e64e289cf3..6248e5f4b5 100644 --- a/libswscale/options.c +++ b/libswscale/options.c @@ -27,7 +27,7 @@ static const char *sws_context_to_name(void *ptr) return "swscaler"; } -#define OFFSET(x) offsetof(SwsInternal, x) +#define OFFSET(x) offsetof(SwsInternal, opts.x) #define DEFAULT 0 #define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM @@ -51,18 +51,18 @@ static const AVOption swscale_options[] = { { "bitexact", "bit-exact mode", 0, AV_OPT_TYPE_CONST, { .i64 = SWS_BITEXACT }, .flags = VE, .unit = "sws_flags" }, { "error_diffusion", "error diffusion dither", 0, AV_OPT_TYPE_CONST, { .i64 = SWS_ERROR_DIFFUSION}, .flags = VE, .unit = "sws_flags" }, - { "param0", "scaler param 0", OFFSET(param[0]), AV_OPT_TYPE_DOUBLE, { .dbl = SWS_PARAM_DEFAULT }, INT_MIN, INT_MAX, VE }, - { "param1", "scaler param 1", OFFSET(param[1]), AV_OPT_TYPE_DOUBLE, { .dbl = SWS_PARAM_DEFAULT }, INT_MIN, INT_MAX, VE }, + { "param0", "scaler param 0", OFFSET(scaler_params[0]), AV_OPT_TYPE_DOUBLE, { .dbl = SWS_PARAM_DEFAULT }, INT_MIN, INT_MAX, VE }, + { "param1", "scaler param 1", OFFSET(scaler_params[1]), AV_OPT_TYPE_DOUBLE, { .dbl = SWS_PARAM_DEFAULT }, INT_MIN, INT_MAX, VE }, - { "srcw", "source width", OFFSET(srcW), AV_OPT_TYPE_INT, { .i64 = 16 }, 1, INT_MAX, VE }, - { "srch", "source height", OFFSET(srcH), AV_OPT_TYPE_INT, { .i64 = 16 }, 1, INT_MAX, VE }, - { "dstw", "destination width", OFFSET(dstW), AV_OPT_TYPE_INT, { .i64 = 16 }, 1, INT_MAX, VE }, - { "dsth", "destination height", OFFSET(dstH), AV_OPT_TYPE_INT, { .i64 = 16 }, 1, INT_MAX, VE }, - { "src_format", "source format", OFFSET(srcFormat), AV_OPT_TYPE_PIXEL_FMT,{ .i64 = DEFAULT }, 0, INT_MAX, VE }, - { "dst_format", "destination format", OFFSET(dstFormat), AV_OPT_TYPE_PIXEL_FMT,{ .i64 = DEFAULT }, 0, INT_MAX, VE }, - { "src_range", "source is full range", OFFSET(srcRange), AV_OPT_TYPE_BOOL, { .i64 = DEFAULT }, 0, 1, VE }, - { "dst_range", "destination is full range", OFFSET(dstRange), AV_OPT_TYPE_BOOL, { .i64 = DEFAULT }, 0, 1, VE }, - { "gamma", "gamma correct scaling", OFFSET(gamma_flag),AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, VE }, + { "srcw", "source width", OFFSET(src_w), AV_OPT_TYPE_INT, { .i64 = 16 }, 1, INT_MAX, VE }, + { "srch", "source height", OFFSET(src_h), AV_OPT_TYPE_INT, { .i64 = 16 }, 1, INT_MAX, VE }, + { "dstw", "destination width", OFFSET(dst_w), AV_OPT_TYPE_INT, { .i64 = 16 }, 1, INT_MAX, VE }, + { "dsth", "destination height", OFFSET(dst_h), AV_OPT_TYPE_INT, { .i64 = 16 }, 1, INT_MAX, VE }, + { "src_format", "source format", OFFSET(src_format), AV_OPT_TYPE_PIXEL_FMT, { .i64 = DEFAULT }, 0, INT_MAX, VE }, + { "dst_format", "destination format", OFFSET(dst_format), AV_OPT_TYPE_PIXEL_FMT, { .i64 = DEFAULT }, 0, INT_MAX, VE }, + { "src_range", "source is full range", OFFSET(src_range), AV_OPT_TYPE_BOOL, { .i64 = DEFAULT }, 0, 1, VE }, + { "dst_range", "destination is full range", OFFSET(dst_range), AV_OPT_TYPE_BOOL, { .i64 = DEFAULT }, 0, 1, VE }, + { "gamma", "gamma correct scaling", OFFSET(gamma_flag), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, VE }, { "src_v_chr_pos", "source vertical chroma position in luma grid/256" , OFFSET(src_v_chr_pos), AV_OPT_TYPE_INT, { .i64 = -513 }, -513, 1024, VE }, { "src_h_chr_pos", "source horizontal chroma position in luma grid/256", OFFSET(src_h_chr_pos), AV_OPT_TYPE_INT, { .i64 = -513 }, -513, 1024, VE }, @@ -76,13 +76,13 @@ static const AVOption swscale_options[] = { { "a_dither", "arithmetic addition dither", 0, AV_OPT_TYPE_CONST, { .i64 = SWS_DITHER_A_DITHER }, .flags = VE, .unit = "sws_dither" }, { "x_dither", "arithmetic xor dither", 0, AV_OPT_TYPE_CONST, { .i64 = SWS_DITHER_X_DITHER }, .flags = VE, .unit = "sws_dither" }, - { "alphablend", "mode for alpha -> non alpha", OFFSET(alphablend), AV_OPT_TYPE_INT, { .i64 = SWS_ALPHA_BLEND_NONE}, .flags = VE, .unit = "alphablend", .max = SWS_ALPHA_BLEND_NB - 1 }, + { "alphablend", "mode for alpha -> non alpha", OFFSET(alpha_blend), AV_OPT_TYPE_INT, { .i64 = SWS_ALPHA_BLEND_NONE}, .flags = VE, .unit = "alphablend", .max = SWS_ALPHA_BLEND_NB - 1 }, { "none", "ignore alpha", 0, AV_OPT_TYPE_CONST, { .i64 = SWS_ALPHA_BLEND_NONE}, .flags = VE, .unit = "alphablend" }, { "uniform_color", "blend onto a uniform color", 0, AV_OPT_TYPE_CONST, { .i64 = SWS_ALPHA_BLEND_UNIFORM}, .flags = VE, .unit = "alphablend" }, { "checkerboard", "blend onto a checkerboard", 0, AV_OPT_TYPE_CONST, { .i64 = SWS_ALPHA_BLEND_CHECKERBOARD}, .flags = VE, .unit = "alphablend" }, - { "threads", "number of threads", OFFSET(nb_threads), AV_OPT_TYPE_INT, {.i64 = 1 }, 0, INT_MAX, VE, .unit = "threads" }, - { "auto", "automatic selection", 0, AV_OPT_TYPE_CONST, {.i64 = 0 }, .flags = VE, .unit = "threads" }, + { "threads", "number of threads", OFFSET(threads), AV_OPT_TYPE_INT, {.i64 = 1 }, .flags = VE, .unit = "threads", .max = INT_MAX }, + { "auto", "automatic selection", 0, AV_OPT_TYPE_CONST, {.i64 = 0 }, .flags = VE, .unit = "threads" }, { NULL } }; @@ -91,7 +91,7 @@ const AVClass ff_sws_context_class = { .class_name = "SWScaler", .item_name = sws_context_to_name, .option = swscale_options, - .parent_log_context_offset = OFFSET(parent), + .parent_log_context_offset = offsetof(SwsInternal, parent), .category = AV_CLASS_CATEGORY_SWSCALER, .version = LIBAVUTIL_VERSION_INT, }; diff --git a/libswscale/output.c b/libswscale/output.c index d9e741d0c9..656419b5c7 100644 --- a/libswscale/output.c +++ b/libswscale/output.c @@ -624,7 +624,7 @@ yuv2mono_X_c_template(SwsInternal *c, const int16_t *lumFilter, Y1 = av_clip_uint8(Y1); Y2 = av_clip_uint8(Y2); } - if (c->dither == SWS_DITHER_ED) { + if (c->opts.dither == SWS_DITHER_ED) { Y1 += (7*err + 1*c->dither_error[0][i] + 5*c->dither_error[0][i+1] + 3*c->dither_error[0][i+2] + 8 - 256)>>4; c->dither_error[0][i] = err; acc = 2*acc + (Y1 >= 128); @@ -662,7 +662,7 @@ yuv2mono_2_c_template(SwsInternal *c, const int16_t *buf[2], int i; av_assert2(yalpha <= 4096U); - if (c->dither == SWS_DITHER_ED) { + if (c->opts.dither == SWS_DITHER_ED) { int err = 0; unsigned acc = 0; for (i = 0; i < dstW; i +=2) { @@ -720,7 +720,7 @@ yuv2mono_1_c_template(SwsInternal *c, const int16_t *buf0, const uint8_t * const d128 = ff_dither_8x8_220[y & 7]; int i; - if (c->dither == SWS_DITHER_ED) { + if (c->opts.dither == SWS_DITHER_ED) { int err = 0; unsigned acc = 0; for (i = 0; i < dstW; i +=2) { @@ -1989,7 +1989,7 @@ static av_always_inline void yuv2rgb_write_full(SwsInternal *c, { int r,g,b; - switch (c->dither) { + switch (c->opts.dither) { case SWS_DITHER_NONE: if (isrgb8) { r = av_clip_uintp2(R >> 27, 3); @@ -2265,7 +2265,7 @@ yuv2gbrp_full_X_c(SwsInternal *c, const int16_t *lumFilter, const int16_t **alpSrc, uint8_t **dest, int dstW, int y) { - const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(c->dstFormat); + const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(c->opts.dst_format); int i; int hasAlpha = (desc->flags & AV_PIX_FMT_FLAG_ALPHA) && alpSrc; uint16_t **dest16 = (uint16_t**)dest; @@ -2328,7 +2328,7 @@ yuv2gbrp_full_X_c(SwsInternal *c, const int16_t *lumFilter, dest[3][i] = A >> 19; } } - if (SH != 22 && (!isBE(c->dstFormat)) != (!HAVE_BIGENDIAN)) { + if (SH != 22 && (!isBE(c->opts.dst_format)) != (!HAVE_BIGENDIAN)) { for (i = 0; i < dstW; i++) { dest16[0][i] = av_bswap16(dest16[0][i]); dest16[1][i] = av_bswap16(dest16[1][i]); @@ -2347,7 +2347,7 @@ yuv2gbrp16_full_X_c(SwsInternal *c, const int16_t *lumFilter, const int16_t **alpSrcx, uint8_t **dest, int dstW, int y) { - const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(c->dstFormat); + const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(c->opts.dst_format); int i; int hasAlpha = (desc->flags & AV_PIX_FMT_FLAG_ALPHA) && alpSrcx; uint16_t **dest16 = (uint16_t**)dest; @@ -2400,7 +2400,7 @@ yuv2gbrp16_full_X_c(SwsInternal *c, const int16_t *lumFilter, if (hasAlpha) dest16[3][i] = av_clip_uintp2(A, 30) >> 14; } - if ((!isBE(c->dstFormat)) != (!HAVE_BIGENDIAN)) { + if ((!isBE(c->opts.dst_format)) != (!HAVE_BIGENDIAN)) { for (i = 0; i < dstW; i++) { dest16[0][i] = av_bswap16(dest16[0][i]); dest16[1][i] = av_bswap16(dest16[1][i]); @@ -2419,7 +2419,7 @@ yuv2gbrpf32_full_X_c(SwsInternal *c, const int16_t *lumFilter, const int16_t **alpSrcx, uint8_t **dest, int dstW, int y) { - const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(c->dstFormat); + const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(c->opts.dst_format); int i; int hasAlpha = (desc->flags & AV_PIX_FMT_FLAG_ALPHA) && alpSrcx; uint32_t **dest32 = (uint32_t**)dest; @@ -2476,7 +2476,7 @@ yuv2gbrpf32_full_X_c(SwsInternal *c, const int16_t *lumFilter, if (hasAlpha) dest32[3][i] = av_float2int(float_mult * (float)(av_clip_uintp2(A, 30) >> 14)); } - if ((!isBE(c->dstFormat)) != (!HAVE_BIGENDIAN)) { + if ((!isBE(c->opts.dst_format)) != (!HAVE_BIGENDIAN)) { for (i = 0; i < dstW; i++) { dest32[0][i] = av_bswap32(dest32[0][i]); dest32[1][i] = av_bswap32(dest32[1][i]); @@ -3175,7 +3175,7 @@ av_cold void ff_sws_init_output_funcs(SwsInternal *c, yuv2packedX_fn *yuv2packedX, yuv2anyX_fn *yuv2anyX) { - enum AVPixelFormat dstFormat = c->dstFormat; + enum AVPixelFormat dstFormat = c->opts.dst_format; const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(dstFormat); if (isSemiPlanarYUV(dstFormat) && isDataInHighBits(dstFormat)) { @@ -3223,7 +3223,7 @@ av_cold void ff_sws_init_output_funcs(SwsInternal *c, *yuv2nv12cX = yuv2nv12cX_c; } - if(c->flags & SWS_FULL_CHR_H_INT) { + if(c->opts.flags & SWS_FULL_CHR_H_INT) { switch (dstFormat) { case AV_PIX_FMT_RGBA: #if CONFIG_SMALL diff --git a/libswscale/ppc/swscale_altivec.c b/libswscale/ppc/swscale_altivec.c index 836aaab1f8..c76c0b6d78 100644 --- a/libswscale/ppc/swscale_altivec.c +++ b/libswscale/ppc/swscale_altivec.c @@ -232,7 +232,7 @@ yuv2plane1_float(yuv2plane1_float_bswap_altivec, uint32_t, BE) av_cold void ff_sws_init_swscale_ppc(SwsInternal *c) { #if HAVE_ALTIVEC - enum AVPixelFormat dstFormat = c->dstFormat; + enum AVPixelFormat dstFormat = c->opts.dst_format; if (!(av_get_cpu_flags() & AV_CPU_FLAG_ALTIVEC)) return; @@ -256,8 +256,8 @@ av_cold void ff_sws_init_swscale_ppc(SwsInternal *c) /* The following list of supported dstFormat values should * match what's found in the body of ff_yuv2packedX_altivec() */ - if (!(c->flags & (SWS_BITEXACT | SWS_FULL_CHR_H_INT)) && !c->needAlpha) { - switch (c->dstFormat) { + if (!(c->opts.flags & (SWS_BITEXACT | SWS_FULL_CHR_H_INT)) && !c->needAlpha) { + switch (c->opts.dst_format) { case AV_PIX_FMT_ABGR: c->yuv2packedX = ff_yuv2abgr_X_altivec; break; diff --git a/libswscale/ppc/swscale_vsx.c b/libswscale/ppc/swscale_vsx.c index f83bb96ec9..5ea3407644 100644 --- a/libswscale/ppc/swscale_vsx.c +++ b/libswscale/ppc/swscale_vsx.c @@ -1862,7 +1862,7 @@ static void hScale16To19_vsx(SwsInternal *c, int16_t *_dst, int dstW, const uint8_t *_src, const int16_t *filter, const int32_t *filterPos, int filterSize) { - const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(c->srcFormat); + const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(c->opts.src_format); int i, j; int32_t *dst = (int32_t *) _dst; const uint16_t *src = (const uint16_t *) _src; @@ -1891,7 +1891,7 @@ static void hScale16To19_vsx(SwsInternal *c, int16_t *_dst, int dstW, }; const vec_u8 vunused = vunusedtab[filterSize % 8]; - if ((isAnyRGB(c->srcFormat) || c->srcFormat==AV_PIX_FMT_PAL8) && desc->comp[0].depth<16) { + if ((isAnyRGB(c->opts.src_format) || c->opts.src_format==AV_PIX_FMT_PAL8) && desc->comp[0].depth<16) { sh = 9; } else if (desc->flags & AV_PIX_FMT_FLAG_FLOAT) { /* float input are process like uint 16bpc */ sh = 16 - 1 - 4; @@ -1940,7 +1940,7 @@ static void hScale16To15_vsx(SwsInternal *c, int16_t *dst, int dstW, const uint8_t *_src, const int16_t *filter, const int32_t *filterPos, int filterSize) { - const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(c->srcFormat); + const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(c->opts.src_format); int i, j; const uint16_t *src = (const uint16_t *) _src; int sh = desc->comp[0].depth - 1; @@ -1968,7 +1968,7 @@ static void hScale16To15_vsx(SwsInternal *c, int16_t *dst, int dstW, const vec_u8 vunused = vunusedtab[filterSize % 8]; if (sh<15) { - sh = isAnyRGB(c->srcFormat) || c->srcFormat==AV_PIX_FMT_PAL8 ? 13 : (desc->comp[0].depth - 1); + sh = isAnyRGB(c->opts.src_format) || c->opts.src_format==AV_PIX_FMT_PAL8 ? 13 : (desc->comp[0].depth - 1); } else if (desc->flags & AV_PIX_FMT_FLAG_FLOAT) { /* float input are process like uint 16bpc */ sh = 16 - 1; } @@ -2019,7 +2019,7 @@ static void hScale16To15_vsx(SwsInternal *c, int16_t *dst, int dstW, av_cold void ff_sws_init_swscale_vsx(SwsInternal *c) { #if HAVE_VSX - enum AVPixelFormat dstFormat = c->dstFormat; + enum AVPixelFormat dstFormat = c->opts.dst_format; const int cpu_flags = av_get_cpu_flags(); const unsigned char power8 = HAVE_POWER8 && cpu_flags & AV_CPU_FLAG_POWER8; @@ -2030,7 +2030,7 @@ av_cold void ff_sws_init_swscale_vsx(SwsInternal *c) if (c->srcBpc == 8) { if (c->dstBpc <= 14) { c->hyScale = c->hcScale = hScale_real_vsx; - if (c->flags & SWS_FAST_BILINEAR && c->dstW >= c->srcW && c->chrDstW >= c->chrSrcW) { + if (c->opts.flags & SWS_FAST_BILINEAR && c->opts.dst_w >= c->opts.src_w && c->chrDstW >= c->chrSrcW) { c->hyscale_fast = hyscale_fast_vsx; c->hcscale_fast = hcscale_fast_vsx; } @@ -2048,7 +2048,7 @@ av_cold void ff_sws_init_swscale_vsx(SwsInternal *c) } #endif - if (!(c->flags & (SWS_BITEXACT | SWS_FULL_CHR_H_INT)) && !c->needAlpha) { + if (!(c->opts.flags & (SWS_BITEXACT | SWS_FULL_CHR_H_INT)) && !c->needAlpha) { switch (c->dstBpc) { case 8: c->yuv2plane1 = yuv2plane1_8_vsx; @@ -2082,11 +2082,11 @@ av_cold void ff_sws_init_swscale_vsx(SwsInternal *c) } } - if (c->flags & SWS_BITEXACT) + if (c->opts.flags & SWS_BITEXACT) return; #if !HAVE_BIGENDIAN - if (c->flags & SWS_FULL_CHR_H_INT) { + if (c->opts.flags & SWS_FULL_CHR_H_INT) { switch (dstFormat) { case AV_PIX_FMT_RGB24: if (power8) { diff --git a/libswscale/ppc/yuv2rgb_altivec.c b/libswscale/ppc/yuv2rgb_altivec.c index 9db305f43f..57574c4ab3 100644 --- a/libswscale/ppc/yuv2rgb_altivec.c +++ b/libswscale/ppc/yuv2rgb_altivec.c @@ -299,7 +299,7 @@ static int altivec_ ## name(SwsInternal *c, const unsigned char *const *in, \ const int *instrides, int srcSliceY, int srcSliceH, \ unsigned char *const *oplanes, const int *outstrides) \ { \ - int w = c->srcW; \ + int w = c->opts.src_w; \ int h = srcSliceH; \ int i, j; \ int instrides_scl[3]; \ @@ -475,7 +475,7 @@ static int altivec_uyvy_rgb32(SwsInternal *c, const unsigned char *const *in, const int *instrides, int srcSliceY, int srcSliceH, unsigned char *const *oplanes, const int *outstrides) { - int w = c->srcW; + int w = c->opts.src_w; int h = srcSliceH; int i, j; vector unsigned char uyvy; @@ -545,20 +545,20 @@ av_cold SwsFunc ff_yuv2rgb_init_ppc(SwsInternal *c) * boom with X11 bad match. * */ - if ((c->srcW & 0xf) != 0) + if ((c->opts.src_w & 0xf) != 0) return NULL; - switch (c->srcFormat) { + switch (c->opts.src_format) { case AV_PIX_FMT_YUV410P: case AV_PIX_FMT_YUV420P: /*case IMGFMT_CLPL: ??? */ case AV_PIX_FMT_GRAY8: case AV_PIX_FMT_NV12: case AV_PIX_FMT_NV21: - if ((c->srcH & 0x1) != 0) + if ((c->opts.src_h & 0x1) != 0) return NULL; - switch (c->dstFormat) { + switch (c->opts.dst_format) { case AV_PIX_FMT_RGB24: av_log(c, AV_LOG_WARNING, "ALTIVEC: Color Space RGB24\n"); return altivec_yuv2_rgb24; @@ -582,7 +582,7 @@ av_cold SwsFunc ff_yuv2rgb_init_ppc(SwsInternal *c) break; case AV_PIX_FMT_UYVY422: - switch (c->dstFormat) { + switch (c->opts.dst_format) { case AV_PIX_FMT_BGR32: av_log(c, AV_LOG_WARNING, "ALTIVEC: Color Space UYVY -> RGB32\n"); return altivec_uyvy_rgb32; @@ -742,7 +742,7 @@ static av_always_inline void yuv2packedX_altivec(SwsInternal *c, if (!printed_error_message) { av_log(c, AV_LOG_ERROR, "altivec_yuv2packedX doesn't support %s output\n", - av_get_pix_fmt_name(c->dstFormat)); + av_get_pix_fmt_name(c->opts.dst_format)); printed_error_message = 1; } return; @@ -830,7 +830,7 @@ static av_always_inline void yuv2packedX_altivec(SwsInternal *c, /* Unreachable, I think. */ av_log(c, AV_LOG_ERROR, "altivec_yuv2packedX doesn't support %s output\n", - av_get_pix_fmt_name(c->dstFormat)); + av_get_pix_fmt_name(c->opts.dst_format)); return; } diff --git a/libswscale/ppc/yuv2yuv_altivec.c b/libswscale/ppc/yuv2yuv_altivec.c index 0ae5223760..7884c38d69 100644 --- a/libswscale/ppc/yuv2yuv_altivec.c +++ b/libswscale/ppc/yuv2yuv_altivec.c @@ -37,12 +37,12 @@ static int yv12toyuy2_unscaled_altivec(SwsInternal *c, const uint8_t *const src[ const int dstStride_a[]) { uint8_t *dst = dstParam[0] + dstStride_a[0] * srcSliceY; - // yv12toyuy2(src[0], src[1], src[2], dst, c->srcW, srcSliceH, + // yv12toyuy2(src[0], src[1], src[2], dst, c->opts.src_w, srcSliceH, // srcStride[0], srcStride[1], dstStride[0]); const uint8_t *ysrc = src[0]; const uint8_t *usrc = src[1]; const uint8_t *vsrc = src[2]; - const int width = c->srcW; + const int width = c->opts.src_w; const int height = srcSliceH; const int lumStride = srcStride[0]; const int chromStride = srcStride[1]; @@ -113,12 +113,12 @@ static int yv12touyvy_unscaled_altivec(SwsInternal *c, const uint8_t *const src[ const int dstStride_a[]) { uint8_t *dst = dstParam[0] + dstStride_a[0] * srcSliceY; - // yv12toyuy2(src[0], src[1], src[2], dst, c->srcW, srcSliceH, + // yv12toyuy2(src[0], src[1], src[2], dst, c->opts.src_w, srcSliceH, // srcStride[0], srcStride[1], dstStride[0]); const uint8_t *ysrc = src[0]; const uint8_t *usrc = src[1]; const uint8_t *vsrc = src[2]; - const int width = c->srcW; + const int width = c->opts.src_w; const int height = srcSliceH; const int lumStride = srcStride[0]; const int chromStride = srcStride[1]; @@ -190,9 +190,9 @@ av_cold void ff_get_unscaled_swscale_ppc(SwsInternal *c) if (!(av_get_cpu_flags() & AV_CPU_FLAG_ALTIVEC)) return; - if (!(c->srcW & 15) && !(c->flags & SWS_BITEXACT) && - c->srcFormat == AV_PIX_FMT_YUV420P) { - enum AVPixelFormat dstFormat = c->dstFormat; + if (!(c->opts.src_w & 15) && !(c->opts.flags & SWS_BITEXACT) && + c->opts.src_format == AV_PIX_FMT_YUV420P) { + enum AVPixelFormat dstFormat = c->opts.dst_format; // unscaled YV12 -> packed YUV, we want speed if (dstFormat == AV_PIX_FMT_YUYV422) diff --git a/libswscale/riscv/swscale.c b/libswscale/riscv/swscale.c index 63539fa82e..3bdaf20af4 100644 --- a/libswscale/riscv/swscale.c +++ b/libswscale/riscv/swscale.c @@ -41,7 +41,7 @@ av_cold void ff_sws_init_range_convert_riscv(SwsInternal *c) if (c->dstBpc <= 14 && (flags & AV_CPU_FLAG_RVV_I32) && (flags & AV_CPU_FLAG_RVB)) { - bool from = c->srcRange != 0; + bool from = c->opts.src_range != 0; c->lumConvertRange = convs[from].lum; c->chrConvertRange = convs[from].chr; @@ -72,7 +72,7 @@ av_cold void ff_sws_init_swscale_riscv(SwsInternal *c) int flags = av_get_cpu_flags(); if ((flags & AV_CPU_FLAG_RVV_I32) && (flags & AV_CPU_FLAG_RVB)) { - switch (c->srcFormat) { + switch (c->opts.src_format) { case AV_PIX_FMT_ABGR: c->lumToYV12 = ff_abgr32ToY_rvv; if (c->chrSrcHSubSample) diff --git a/libswscale/slice.c b/libswscale/slice.c index f13a839f98..72e88be318 100644 --- a/libswscale/slice.c +++ b/libswscale/slice.c @@ -221,7 +221,7 @@ static void fill_ones(SwsSlice *s, int n, int bpc) static void get_min_buffer_size(SwsInternal *c, int *out_lum_size, int *out_chr_size) { int lumY; - int dstH = c->dstH; + int dstH = c->opts.dst_h; int chrDstH = c->chrDstH; int *lumFilterPos = c->vLumFilterPos; int *chrFilterPos = c->vChrFilterPos; @@ -253,14 +253,14 @@ int ff_init_filters(SwsInternal * c) int index; int num_ydesc; int num_cdesc; - int num_vdesc = isPlanarYUV(c->dstFormat) && !isGray(c->dstFormat) ? 2 : 1; + int num_vdesc = isPlanarYUV(c->opts.dst_format) && !isGray(c->opts.dst_format) ? 2 : 1; int need_lum_conv = c->lumToYV12 || c->readLumPlanar || c->alpToYV12 || c->readAlpPlanar; int need_chr_conv = c->chrToYV12 || c->readChrPlanar; int need_gamma = c->is_internal_gamma; int srcIdx, dstIdx; - int dst_stride = FFALIGN(c->dstW * sizeof(int16_t) + 66, 16); + int dst_stride = FFALIGN(c->opts.dst_w * sizeof(int16_t) + 66, 16); - uint32_t * pal = usePal(c->srcFormat) ? c->pal_yuv : (uint32_t*)c->input_rgb2yuv_table; + uint32_t * pal = usePal(c->opts.src_format) ? c->pal_yuv : (uint32_t*)c->input_rgb2yuv_table; int res = 0; int lumBufSize; @@ -284,7 +284,7 @@ int ff_init_filters(SwsInternal * c) c->descIndex[0] = num_ydesc + (need_gamma ? 1 : 0); c->descIndex[1] = num_ydesc + num_cdesc + (need_gamma ? 1 : 0); - if (isFloat16(c->srcFormat)) { + if (isFloat16(c->opts.src_format)) { c->h2f_tables = av_malloc(sizeof(*c->h2f_tables)); if (!c->h2f_tables) return AVERROR(ENOMEM); @@ -301,25 +301,25 @@ int ff_init_filters(SwsInternal * c) goto cleanup; } - res = alloc_slice(&c->slice[0], c->srcFormat, c->srcH, c->chrSrcH, c->chrSrcHSubSample, c->chrSrcVSubSample, 0); + res = alloc_slice(&c->slice[0], c->opts.src_format, c->opts.src_h, c->chrSrcH, c->chrSrcHSubSample, c->chrSrcVSubSample, 0); if (res < 0) goto cleanup; for (i = 1; i < c->numSlice-2; ++i) { - res = alloc_slice(&c->slice[i], c->srcFormat, lumBufSize, chrBufSize, c->chrSrcHSubSample, c->chrSrcVSubSample, 0); + res = alloc_slice(&c->slice[i], c->opts.src_format, lumBufSize, chrBufSize, c->chrSrcHSubSample, c->chrSrcVSubSample, 0); if (res < 0) goto cleanup; - res = alloc_lines(&c->slice[i], FFALIGN(c->srcW*2+78, 16), c->srcW); + res = alloc_lines(&c->slice[i], FFALIGN(c->opts.src_w*2+78, 16), c->opts.src_w); if (res < 0) goto cleanup; } // horizontal scaler output - res = alloc_slice(&c->slice[i], c->srcFormat, lumBufSize, chrBufSize, c->chrDstHSubSample, c->chrDstVSubSample, 1); + res = alloc_slice(&c->slice[i], c->opts.src_format, lumBufSize, chrBufSize, c->chrDstHSubSample, c->chrDstVSubSample, 1); if (res < 0) goto cleanup; - res = alloc_lines(&c->slice[i], dst_stride, c->dstW); + res = alloc_lines(&c->slice[i], dst_stride, c->opts.dst_w); if (res < 0) goto cleanup; fill_ones(&c->slice[i], dst_stride>>1, c->dstBpc); // vertical scaler output ++i; - res = alloc_slice(&c->slice[i], c->dstFormat, c->dstH, c->chrDstH, c->chrDstHSubSample, c->chrDstVSubSample, 0); + res = alloc_slice(&c->slice[i], c->opts.dst_format, c->opts.dst_h, c->chrDstH, c->chrDstHSubSample, c->chrDstVSubSample, 0); if (res < 0) goto cleanup; index = 0; diff --git a/libswscale/swscale.c b/libswscale/swscale.c index 4a139840b4..5b5a009f1b 100644 --- a/libswscale/swscale.c +++ b/libswscale/swscale.c @@ -66,14 +66,14 @@ static void hScale16To19_c(SwsInternal *c, int16_t *_dst, int dstW, const uint8_t *_src, const int16_t *filter, const int32_t *filterPos, int filterSize) { - const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(c->srcFormat); + const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(c->opts.src_format); int i; int32_t *dst = (int32_t *) _dst; const uint16_t *src = (const uint16_t *) _src; int bits = desc->comp[0].depth - 1; int sh = bits - 4; - if ((isAnyRGB(c->srcFormat) || c->srcFormat==AV_PIX_FMT_PAL8) && desc->comp[0].depth<16) { + if ((isAnyRGB(c->opts.src_format) || c->opts.src_format==AV_PIX_FMT_PAL8) && desc->comp[0].depth<16) { sh = 9; } else if (desc->flags & AV_PIX_FMT_FLAG_FLOAT) { /* float input are process like uint 16bpc */ sh = 16 - 1 - 4; @@ -96,13 +96,13 @@ static void hScale16To15_c(SwsInternal *c, int16_t *dst, int dstW, const uint8_t *_src, const int16_t *filter, const int32_t *filterPos, int filterSize) { - const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(c->srcFormat); + const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(c->opts.src_format); int i; const uint16_t *src = (const uint16_t *) _src; int sh = desc->comp[0].depth - 1; if (sh<15) { - sh = isAnyRGB(c->srcFormat) || c->srcFormat==AV_PIX_FMT_PAL8 ? 13 : (desc->comp[0].depth - 1); + sh = isAnyRGB(c->opts.src_format) || c->opts.src_format==AV_PIX_FMT_PAL8 ? 13 : (desc->comp[0].depth - 1); } else if (desc->flags & AV_PIX_FMT_FLAG_FLOAT) { /* float input are process like uint 16bpc */ sh = 16 - 1; } @@ -237,15 +237,15 @@ int ff_swscale(SwsInternal *c, const uint8_t *const src[], const int srcStride[] int srcSliceY, int srcSliceH, uint8_t *const dst[], const int dstStride[], int dstSliceY, int dstSliceH) { - const int scale_dst = dstSliceY > 0 || dstSliceH < c->dstH; + const int scale_dst = dstSliceY > 0 || dstSliceH < c->opts.dst_h; /* load a few things into local vars to make the code more readable? * and faster */ - const int dstW = c->dstW; - int dstH = c->dstH; + const int dstW = c->opts.dst_w; + int dstH = c->opts.dst_h; - const enum AVPixelFormat dstFormat = c->dstFormat; - const int flags = c->flags; + const enum AVPixelFormat dstFormat = c->opts.dst_format; + const int flags = c->opts.flags; int32_t *vLumFilterPos = c->vLumFilterPos; int32_t *vChrFilterPos = c->vChrFilterPos; @@ -261,8 +261,8 @@ int ff_swscale(SwsInternal *c, const uint8_t *const src[], const int srcStride[] yuv2anyX_fn yuv2anyX = c->yuv2anyX; const int chrSrcSliceY = srcSliceY >> c->chrSrcVSubSample; const int chrSrcSliceH = AV_CEIL_RSHIFT(srcSliceH, c->chrSrcVSubSample); - int should_dither = isNBPS(c->srcFormat) || - is16BPS(c->srcFormat); + int should_dither = isNBPS(c->opts.src_format) || + is16BPS(c->opts.src_format); int lastDstY; /* vars which will change and which we need to store back in the context */ @@ -289,7 +289,7 @@ int ff_swscale(SwsInternal *c, const uint8_t *const src[], const int srcStride[] const uint8_t *src2[4]; int srcStride2[4]; - if (isPacked(c->srcFormat)) { + if (isPacked(c->opts.src_format)) { src2[0] = src2[1] = src2[2] = @@ -364,10 +364,10 @@ int ff_swscale(SwsInternal *c, const uint8_t *const src[], const int srcStride[] ff_init_vscale_pfn(c, yuv2plane1, yuv2planeX, yuv2nv12cX, yuv2packed1, yuv2packed2, yuv2packedX, yuv2anyX, c->use_mmx_vfilter); - ff_init_slice_from_src(src_slice, (uint8_t**)src2, srcStride2, c->srcW, + ff_init_slice_from_src(src_slice, (uint8_t**)src2, srcStride2, c->opts.src_w, srcSliceY, srcSliceH, chrSrcSliceY, chrSrcSliceH, 1); - ff_init_slice_from_src(vout_slice, (uint8_t**)dst, dstStride, c->dstW, + ff_init_slice_from_src(vout_slice, (uint8_t**)dst, dstStride, c->opts.dst_w, dstY, dstSliceH, dstY >> c->chrDstVSubSample, AV_CEIL_RSHIFT(dstSliceH, c->chrDstVSubSample), scale_dst); if (srcSliceY == 0) { @@ -389,13 +389,13 @@ int ff_swscale(SwsInternal *c, const uint8_t *const src[], const int srcStride[] // First line needed as input const int firstLumSrcY = FFMAX(1 - vLumFilterSize, vLumFilterPos[dstY]); - const int firstLumSrcY2 = FFMAX(1 - vLumFilterSize, vLumFilterPos[FFMIN(dstY | ((1 << c->chrDstVSubSample) - 1), c->dstH - 1)]); + const int firstLumSrcY2 = FFMAX(1 - vLumFilterSize, vLumFilterPos[FFMIN(dstY | ((1 << c->chrDstVSubSample) - 1), c->opts.dst_h - 1)]); // First line needed as input const int firstChrSrcY = FFMAX(1 - vChrFilterSize, vChrFilterPos[chrDstY]); // Last line needed as input - int lastLumSrcY = FFMIN(c->srcH, firstLumSrcY + vLumFilterSize) - 1; - int lastLumSrcY2 = FFMIN(c->srcH, firstLumSrcY2 + vLumFilterSize) - 1; + int lastLumSrcY = FFMIN(c->opts.src_h, firstLumSrcY + vLumFilterSize) - 1; + int lastLumSrcY2 = FFMIN(c->opts.src_h, firstLumSrcY2 + vLumFilterSize) - 1; int lastChrSrcY = FFMIN(c->chrSrcH, firstChrSrcY + vChrFilterSize) - 1; int enough_lines; @@ -488,13 +488,13 @@ int ff_swscale(SwsInternal *c, const uint8_t *const src[], const int srcStride[] #if HAVE_MMX_INLINE ff_updateMMXDitherTables(c, dstY); - c->dstW_mmx = c->dstW; + c->dstW_mmx = c->opts.dst_w; #endif if (should_dither) { c->chrDither8 = ff_dither_8x8_128[chrDstY & 7]; c->lumDither8 = ff_dither_8x8_128[dstY & 7]; } - if (dstY >= c->dstH - 2) { + if (dstY >= c->opts.dst_h - 2) { /* hmm looks like we can't use MMX here without overwriting * this array's tail */ ff_sws_init_output_funcs(c, &yuv2plane1, &yuv2planeX, &yuv2nv12cX, @@ -544,9 +544,9 @@ av_cold void ff_sws_init_range_convert(SwsInternal *c) { c->lumConvertRange = NULL; c->chrConvertRange = NULL; - if (c->srcRange != c->dstRange && !isAnyRGB(c->dstFormat)) { + if (c->opts.src_range != c->opts.dst_range && !isAnyRGB(c->opts.dst_format)) { if (c->dstBpc <= 14) { - if (c->srcRange) { + if (c->opts.src_range) { c->lumConvertRange = lumRangeFromJpeg_c; c->chrConvertRange = chrRangeFromJpeg_c; } else { @@ -554,7 +554,7 @@ av_cold void ff_sws_init_range_convert(SwsInternal *c) c->chrConvertRange = chrRangeToJpeg_c; } } else { - if (c->srcRange) { + if (c->opts.src_range) { c->lumConvertRange = lumRangeFromJpeg16_c; c->chrConvertRange = chrRangeFromJpeg16_c; } else { @@ -577,7 +577,7 @@ av_cold void ff_sws_init_range_convert(SwsInternal *c) static av_cold void sws_init_swscale(SwsInternal *c) { - enum AVPixelFormat srcFormat = c->srcFormat; + enum AVPixelFormat srcFormat = c->opts.src_format; ff_sws_init_output_funcs(c, &c->yuv2plane1, &c->yuv2planeX, &c->yuv2nv12cX, &c->yuv2packed1, @@ -589,7 +589,7 @@ static av_cold void sws_init_swscale(SwsInternal *c) if (c->srcBpc == 8) { if (c->dstBpc <= 14) { c->hyScale = c->hcScale = hScale8To15_c; - if (c->flags & SWS_FAST_BILINEAR) { + if (c->opts.flags & SWS_FAST_BILINEAR) { c->hyscale_fast = ff_hyscale_fast_c; c->hcscale_fast = ff_hcscale_fast_c; } @@ -603,7 +603,7 @@ static av_cold void sws_init_swscale(SwsInternal *c) ff_sws_init_range_convert(c); - if (!(isGray(srcFormat) || isGray(c->dstFormat) || + if (!(isGray(srcFormat) || isGray(c->opts.dst_format) || srcFormat == AV_PIX_FMT_MONOBLACK || srcFormat == AV_PIX_FMT_MONOWHITE)) c->needs_hcscale = 1; } @@ -659,7 +659,7 @@ static int check_image_pointers(const uint8_t * const data[4], enum AVPixelForma void ff_xyz12Torgb48(const SwsInternal *c, uint8_t *dst, int dst_stride, const uint8_t *src, int src_stride, int w, int h) { - const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(c->srcFormat); + const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(c->opts.src_format); for (int yp = 0; yp < h; yp++) { const uint16_t *src16 = (const uint16_t *) src; @@ -718,7 +718,7 @@ void ff_xyz12Torgb48(const SwsInternal *c, uint8_t *dst, int dst_stride, void ff_rgb48Toxyz12(const SwsInternal *c, uint8_t *dst, int dst_stride, const uint8_t *src, int src_stride, int w, int h) { - const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(c->dstFormat); + const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(c->opts.dst_format); for (int yp = 0; yp < h; yp++) { uint16_t *src16 = (uint16_t *) src; @@ -778,28 +778,28 @@ void ff_update_palette(SwsInternal *c, const uint32_t *pal) { for (int i = 0; i < 256; i++) { int r, g, b, y, u, v, a = 0xff; - if (c->srcFormat == AV_PIX_FMT_PAL8) { + if (c->opts.src_format == AV_PIX_FMT_PAL8) { uint32_t p = pal[i]; a = (p >> 24) & 0xFF; r = (p >> 16) & 0xFF; g = (p >> 8) & 0xFF; b = p & 0xFF; - } else if (c->srcFormat == AV_PIX_FMT_RGB8) { + } else if (c->opts.src_format == AV_PIX_FMT_RGB8) { r = ( i >> 5 ) * 36; g = ((i >> 2) & 7) * 36; b = ( i & 3) * 85; - } else if (c->srcFormat == AV_PIX_FMT_BGR8) { + } else if (c->opts.src_format == AV_PIX_FMT_BGR8) { b = ( i >> 6 ) * 85; g = ((i >> 3) & 7) * 36; r = ( i & 7) * 36; - } else if (c->srcFormat == AV_PIX_FMT_RGB4_BYTE) { + } else if (c->opts.src_format == AV_PIX_FMT_RGB4_BYTE) { r = ( i >> 3 ) * 255; g = ((i >> 1) & 3) * 85; b = ( i & 1) * 255; - } else if (c->srcFormat == AV_PIX_FMT_GRAY8 || c->srcFormat == AV_PIX_FMT_GRAY8A) { + } else if (c->opts.src_format == AV_PIX_FMT_GRAY8 || c->opts.src_format == AV_PIX_FMT_GRAY8A) { r = g = b = i; } else { - av_assert1(c->srcFormat == AV_PIX_FMT_BGR4_BYTE); + av_assert1(c->opts.src_format == AV_PIX_FMT_BGR4_BYTE); b = ( i >> 3 ) * 255; g = ((i >> 1) & 3) * 85; r = ( i & 1) * 255; @@ -820,7 +820,7 @@ void ff_update_palette(SwsInternal *c, const uint32_t *pal) v = av_clip_uint8((RV * r + GV * g + BV * b + (257 << (RGB2YUV_SHIFT - 1))) >> RGB2YUV_SHIFT); c->pal_yuv[i]= y + (u<<8) + (v<<16) + ((unsigned)a<<24); - switch (c->dstFormat) { + switch (c->opts.dst_format) { case AV_PIX_FMT_BGR32: #if !HAVE_BIGENDIAN case AV_PIX_FMT_RGB24: @@ -863,7 +863,7 @@ static int scale_gamma(SwsInternal *c, { int ret = scale_internal(c->cascaded_context[0], srcSlice, srcStride, srcSliceY, srcSliceH, - c->cascaded_tmp[0], c->cascaded_tmpStride[0], 0, c->srcH); + c->cascaded_tmp[0], c->cascaded_tmpStride[0], 0, c->opts.src_h); if (ret < 0) return ret; @@ -871,7 +871,7 @@ static int scale_gamma(SwsInternal *c, if (c->cascaded_context[2]) ret = scale_internal(c->cascaded_context[1], (const uint8_t * const *)c->cascaded_tmp[0], c->cascaded_tmpStride[0], srcSliceY, srcSliceH, - c->cascaded_tmp[1], c->cascaded_tmpStride[1], 0, c->dstH); + c->cascaded_tmp[1], c->cascaded_tmpStride[1], 0, c->opts.dst_h); else ret = scale_internal(c->cascaded_context[1], (const uint8_t * const *)c->cascaded_tmp[0], c->cascaded_tmpStride[0], srcSliceY, srcSliceH, @@ -895,7 +895,7 @@ static int scale_cascaded(SwsInternal *c, uint8_t * const dstSlice[], const int dstStride[], int dstSliceY, int dstSliceH) { - const int dstH0 = sws_internal(c->cascaded_context[0])->dstH; + const int dstH0 = sws_internal(c->cascaded_context[0])->opts.dst_h; int ret = scale_internal(c->cascaded_context[0], srcSlice, srcStride, srcSliceY, srcSliceH, c->cascaded_tmp[0], c->cascaded_tmpStride[0], @@ -915,13 +915,13 @@ static int scale_internal(SwsContext *sws, int dstSliceY, int dstSliceH) { SwsInternal *c = sws_internal(sws); - const int scale_dst = dstSliceY > 0 || dstSliceH < c->dstH; + const int scale_dst = dstSliceY > 0 || dstSliceH < c->opts.dst_h; const int frame_start = scale_dst || !c->sliceDir; int i, ret; const uint8_t *src2[4]; uint8_t *dst2[4]; - int macro_height_src = isBayer(c->srcFormat) ? 2 : (1 << c->chrSrcVSubSample); - int macro_height_dst = isBayer(c->dstFormat) ? 2 : (1 << c->chrDstVSubSample); + int macro_height_src = isBayer(c->opts.src_format) ? 2 : (1 << c->chrSrcVSubSample); + int macro_height_dst = isBayer(c->opts.dst_format) ? 2 : (1 << c->chrDstVSubSample); // copy strides, so they can safely be modified int srcStride2[4]; int dstStride2[4]; @@ -933,25 +933,25 @@ static int scale_internal(SwsContext *sws, } if ((srcSliceY & (macro_height_src - 1)) || - ((srcSliceH & (macro_height_src - 1)) && srcSliceY + srcSliceH != c->srcH) || - srcSliceY + srcSliceH > c->srcH || - (isBayer(c->srcFormat) && srcSliceH <= 1)) { + ((srcSliceH & (macro_height_src - 1)) && srcSliceY + srcSliceH != c->opts.src_h) || + srcSliceY + srcSliceH > c->opts.src_h || + (isBayer(c->opts.src_format) && srcSliceH <= 1)) { av_log(c, AV_LOG_ERROR, "Slice parameters %d, %d are invalid\n", srcSliceY, srcSliceH); return AVERROR(EINVAL); } if ((dstSliceY & (macro_height_dst - 1)) || - ((dstSliceH & (macro_height_dst - 1)) && dstSliceY + dstSliceH != c->dstH) || - dstSliceY + dstSliceH > c->dstH) { + ((dstSliceH & (macro_height_dst - 1)) && dstSliceY + dstSliceH != c->opts.dst_h) || + dstSliceY + dstSliceH > c->opts.dst_h) { av_log(c, AV_LOG_ERROR, "Slice parameters %d, %d are invalid\n", dstSliceY, dstSliceH); return AVERROR(EINVAL); } - if (!check_image_pointers(srcSlice, c->srcFormat, srcStride)) { + if (!check_image_pointers(srcSlice, c->opts.src_format, srcStride)) { av_log(c, AV_LOG_ERROR, "bad src image pointers\n"); return AVERROR(EINVAL); } - if (!check_image_pointers((const uint8_t* const*)dstSlice, c->dstFormat, dstStride)) { + if (!check_image_pointers((const uint8_t* const*)dstSlice, c->opts.dst_format, dstStride)) { av_log(c, AV_LOG_ERROR, "bad dst image pointers\n"); return AVERROR(EINVAL); } @@ -960,22 +960,22 @@ static int scale_internal(SwsContext *sws, if (srcSliceH == 0) return 0; - if (c->gamma_flag && c->cascaded_context[0]) + if (c->opts.gamma_flag && c->cascaded_context[0]) return scale_gamma(c, srcSlice, srcStride, srcSliceY, srcSliceH, dstSlice, dstStride, dstSliceY, dstSliceH); if (c->cascaded_context[0] && srcSliceY == 0 && - srcSliceH == sws_internal(c->cascaded_context[0])->srcH) + srcSliceH == sws_internal(c->cascaded_context[0])->opts.src_h) { return scale_cascaded(c, srcSlice, srcStride, srcSliceY, srcSliceH, dstSlice, dstStride, dstSliceY, dstSliceH); } - if (!srcSliceY && (c->flags & SWS_BITEXACT) && c->dither == SWS_DITHER_ED && c->dither_error[0]) + if (!srcSliceY && (c->opts.flags & SWS_BITEXACT) && c->opts.dither == SWS_DITHER_ED && c->dither_error[0]) for (i = 0; i < 4; i++) - memset(c->dither_error[i], 0, sizeof(c->dither_error[0][0]) * (c->dstW+2)); + memset(c->dither_error[i], 0, sizeof(c->dither_error[0][0]) * (c->opts.dst_w+2)); - if (usePal(c->srcFormat)) + if (usePal(c->opts.src_format)) ff_update_palette(c, (const uint32_t *)srcSlice[1]); memcpy(src2, srcSlice, sizeof(src2)); @@ -984,7 +984,7 @@ static int scale_internal(SwsContext *sws, memcpy(dstStride2, dstStride, sizeof(dstStride2)); if (frame_start && !scale_dst) { - if (srcSliceY != 0 && srcSliceY + srcSliceH != c->srcH) { + if (srcSliceY != 0 && srcSliceY + srcSliceH != c->opts.src_h) { av_log(c, AV_LOG_ERROR, "Slices start in the middle!\n"); return AVERROR(EINVAL); } @@ -993,7 +993,7 @@ static int scale_internal(SwsContext *sws, } else if (scale_dst) c->sliceDir = 1; - if (c->src0Alpha && !c->dst0Alpha && isALPHA(c->dstFormat)) { + if (c->src0Alpha && !c->dst0Alpha && isALPHA(c->opts.dst_format)) { uint8_t *base; int x,y; @@ -1005,15 +1005,15 @@ static int scale_internal(SwsContext *sws, base = srcStride[0] < 0 ? c->rgb0_scratch - srcStride[0] * (srcSliceH-1) : c->rgb0_scratch; for (y=0; ysrcW); - for (x=c->src0Alpha-1; x<4*c->srcW; x+=4) { + memcpy(base + srcStride[0]*y, src2[0] + srcStride[0]*y, 4*c->opts.src_w); + for (x=c->src0Alpha-1; x<4*c->opts.src_w; x+=4) { base[ srcStride[0]*y + x] = 0xFF; } } src2[0] = base; } - if (c->srcXYZ && !(c->dstXYZ && c->srcW==c->dstW && c->srcH==c->dstH)) { + if (c->srcXYZ && !(c->dstXYZ && c->opts.src_w==c->opts.dst_w && c->opts.src_h==c->opts.dst_h)) { uint8_t *base; av_fast_malloc(&c->xyz_scratch, &c->xyz_scratch_allocated, @@ -1024,7 +1024,7 @@ static int scale_internal(SwsContext *sws, base = srcStride[0] < 0 ? c->xyz_scratch - srcStride[0] * (srcSliceH-1) : c->xyz_scratch; - ff_xyz12Torgb48(c, base, srcStride[0], src2[0], srcStride[0], c->srcW, srcSliceH); + ff_xyz12Torgb48(c, base, srcStride[0], src2[0], srcStride[0], c->opts.src_w, srcSliceH); src2[0] = base; } @@ -1036,19 +1036,19 @@ static int scale_internal(SwsContext *sws, } src2[0] += (srcSliceH - 1) * srcStride[0]; - if (!usePal(c->srcFormat)) + if (!usePal(c->opts.src_format)) src2[1] += ((srcSliceH >> c->chrSrcVSubSample) - 1) * srcStride[1]; src2[2] += ((srcSliceH >> c->chrSrcVSubSample) - 1) * srcStride[2]; src2[3] += (srcSliceH - 1) * srcStride[3]; - dst2[0] += ( c->dstH - 1) * dstStride[0]; - dst2[1] += ((c->dstH >> c->chrDstVSubSample) - 1) * dstStride[1]; - dst2[2] += ((c->dstH >> c->chrDstVSubSample) - 1) * dstStride[2]; - dst2[3] += ( c->dstH - 1) * dstStride[3]; + dst2[0] += ( c->opts.dst_h - 1) * dstStride[0]; + dst2[1] += ((c->opts.dst_h >> c->chrDstVSubSample) - 1) * dstStride[1]; + dst2[2] += ((c->opts.dst_h >> c->chrDstVSubSample) - 1) * dstStride[2]; + dst2[3] += ( c->opts.dst_h - 1) * dstStride[3]; - srcSliceY_internal = c->srcH-srcSliceY-srcSliceH; + srcSliceY_internal = c->opts.src_h-srcSliceY-srcSliceH; } - reset_ptr(src2, c->srcFormat); - reset_ptr((void*)dst2, c->dstFormat); + reset_ptr(src2, c->opts.src_format); + reset_ptr((void*)dst2, c->opts.dst_format); if (c->convert_unscaled) { int offset = srcSliceY_internal; @@ -1058,13 +1058,13 @@ static int scale_internal(SwsContext *sws, if (scale_dst) { av_assert0(offset == 0); for (i = 0; i < 4 && src2[i]; i++) { - if (!src2[i] || (i > 0 && usePal(c->srcFormat))) + if (!src2[i] || (i > 0 && usePal(c->opts.src_format))) break; src2[i] += (dstSliceY >> ((i == 1 || i == 2) ? c->chrSrcVSubSample : 0)) * srcStride2[i]; } for (i = 0; i < 4 && dst2[i]; i++) { - if (!dst2[i] || (i > 0 && usePal(c->dstFormat))) + if (!dst2[i] || (i > 0 && usePal(c->opts.dst_format))) break; dst2[i] -= (dstSliceY >> ((i == 1 || i == 2) ? c->chrDstVSubSample : 0)) * dstStride2[i]; } @@ -1081,7 +1081,7 @@ static int scale_internal(SwsContext *sws, dst2, dstStride2, dstSliceY, dstSliceH); } - if (c->dstXYZ && !(c->srcXYZ && c->srcW==c->dstW && c->srcH==c->dstH)) { + if (c->dstXYZ && !(c->srcXYZ && c->opts.src_w==c->opts.dst_w && c->opts.src_h==c->opts.dst_h)) { uint8_t *dst; if (scale_dst) { @@ -1091,16 +1091,16 @@ static int scale_internal(SwsContext *sws, av_assert0(dstY >= ret); av_assert0(ret >= 0); - av_assert0(c->dstH >= dstY); + av_assert0(c->opts.dst_h >= dstY); dst = dst2[0] + (dstY - ret) * dstStride2[0]; } /* replace on the same data */ - ff_rgb48Toxyz12(c, dst, dstStride2[0], dst, dstStride2[0], c->dstW, ret); + ff_rgb48Toxyz12(c, dst, dstStride2[0], dst, dstStride2[0], c->opts.dst_w, ret); } /* reset slice direction at end of frame */ - if ((srcSliceY_internal + srcSliceH == c->srcH) || scale_dst) + if ((srcSliceY_internal + srcSliceH == c->opts.src_h) || scale_dst) c->sliceDir = 0; return ret; @@ -1124,9 +1124,9 @@ int sws_frame_start(SwsContext *sws, AVFrame *dst, const AVFrame *src) return ret; if (!dst->buf[0]) { - dst->width = c->dstW; - dst->height = c->dstH; - dst->format = c->dstFormat; + dst->width = c->opts.dst_w; + dst->height = c->opts.dst_h; + dst->format = c->opts.dst_format; ret = av_frame_get_buffer(dst, 0); if (ret < 0) @@ -1177,10 +1177,10 @@ int sws_receive_slice(SwsContext *sws, unsigned int slice_start, /* wait until complete input has been received */ if (!(c->src_ranges.nb_ranges == 1 && c->src_ranges.ranges[0].start == 0 && - c->src_ranges.ranges[0].len == c->srcH)) + c->src_ranges.ranges[0].len == c->opts.src_h)) return AVERROR(EAGAIN); - if ((slice_start > 0 || slice_height < c->dstH) && + if ((slice_start > 0 || slice_height < c->opts.dst_h) && (slice_start % align || slice_height % align)) { av_log(c, AV_LOG_ERROR, "Incorrectly aligned output: %u/%u not multiples of %u\n", @@ -1192,7 +1192,7 @@ int sws_receive_slice(SwsContext *sws, unsigned int slice_start, int nb_jobs = c->nb_slice_ctx; int ret = 0; - if (sws_internal(c->slice_ctx[0])->dither == SWS_DITHER_ED) + if (sws_internal(c->slice_ctx[0])->opts.dither == SWS_DITHER_ED) nb_jobs = 1; c->dst_slice_start = slice_start; @@ -1218,7 +1218,7 @@ int sws_receive_slice(SwsContext *sws, unsigned int slice_start, } return scale_internal(sws, (const uint8_t * const *)c->frame_src->data, - c->frame_src->linesize, 0, c->srcH, + c->frame_src->linesize, 0, c->opts.src_h, dst, c->frame_dst->linesize, slice_start, slice_height); } @@ -1256,7 +1256,7 @@ int attribute_align_arg sws_scale(SwsContext *sws, } return scale_internal(sws, srcSlice, srcStride, srcSliceY, srcSliceH, - dst, dstStride, 0, c->dstH); + dst, dstStride, 0, c->opts.dst_h); } void ff_sws_slice_worker(void *priv, int jobnr, int threadnr, @@ -1284,7 +1284,7 @@ void ff_sws_slice_worker(void *priv, int jobnr, int threadnr, } err = scale_internal(sws, (const uint8_t * const *)parent->frame_src->data, - parent->frame_src->linesize, 0, c->srcH, + parent->frame_src->linesize, 0, c->opts.src_h, dst, parent->frame_dst->linesize, parent->dst_slice_start + slice_start, slice_end - slice_start); } diff --git a/libswscale/swscale_internal.h b/libswscale/swscale_internal.h index 0ab4e67270..643177d14d 100644 --- a/libswscale/swscale_internal.h +++ b/libswscale/swscale_internal.h @@ -329,10 +329,31 @@ struct SwsFilterDescriptor; /* This struct should be aligned on at least a 32-byte boundary. */ struct SwsInternal { - /** - * info on struct for av_log - */ - const AVClass *av_class; + /* Currently active user-facing options. */ + struct { + const AVClass *av_class; + + double scaler_params[2]; ///< Input parameters for scaling algorithms that need them. + int flags; ///< Flags passed by the user to select scaler algorithm, optimizations, subsampling, etc... + int threads; ///< Number of threads used for scaling + + int src_w; ///< Width of source luma/alpha planes. + int src_h; ///< Height of source luma/alpha planes. + int dst_w; ///< Width of destination luma/alpha planes. + int dst_h; ///< Height of destination luma/alpha planes. + enum AVPixelFormat src_format; ///< Source pixel format. + enum AVPixelFormat dst_format; ///< Destination pixel format. + int src_range; ///< 0 = MPG YUV range, 1 = JPG YUV range (source image). + int dst_range; ///< 0 = MPG YUV range, 1 = JPG YUV range (destination image). + int src_h_chr_pos; + int dst_h_chr_pos; + int src_v_chr_pos; + int dst_v_chr_pos; + int gamma_flag; + + SwsDither dither; + SwsAlphaBlend alpha_blend; + } opts; SwsContext *parent; @@ -350,18 +371,12 @@ struct SwsInternal { * sws_scale() wrapper so they can be freely modified here. */ SwsFunc convert_unscaled; - int srcW; ///< Width of source luma/alpha planes. - int srcH; ///< Height of source luma/alpha planes. - int dstW; ///< Width of destination luma/alpha planes. - int dstH; ///< Height of destination luma/alpha planes. int chrSrcW; ///< Width of source chroma planes. int chrSrcH; ///< Height of source chroma planes. int chrDstW; ///< Width of destination chroma planes. int chrDstH; ///< Height of destination chroma planes. int lumXInc, chrXInc; int lumYInc, chrYInc; - enum AVPixelFormat dstFormat; ///< Destination pixel format. - enum AVPixelFormat srcFormat; ///< Source pixel format. int dstFormatBpp; ///< Number of bits per pixel of the destination pixel format. int srcFormatBpp; ///< Number of bits per pixel of the source pixel format. int dstBpc, srcBpc; @@ -371,8 +386,6 @@ struct SwsInternal { int chrDstVSubSample; ///< Binary logarithm of vertical subsampling factor between luma/alpha and chroma planes in destination image. int vChrDrop; ///< Binary logarithm of extra vertical subsampling factor in source image chroma planes specified by user. int sliceDir; ///< Direction that slices are fed to the scaler (1 = top-to-bottom, -1 = bottom-to-top). - int nb_threads; ///< Number of threads used for scaling - double param[2]; ///< Input parameters for scaling algorithms that need them. AVFrame *frame_src; AVFrame *frame_dst; @@ -389,7 +402,6 @@ struct SwsInternal { int cascaded_mainindex; double gamma_value; - int gamma_flag; int is_internal_gamma; uint16_t *gamma; uint16_t *inv_gamma; @@ -459,7 +471,6 @@ struct SwsInternal { int warned_unuseable_bilinear; int dstY; ///< Last destination vertical line output from last slice. - int flags; ///< Flags passed by the user to select scaler algorithm, optimizations, subsampling, etc... void *yuvTable; // pointer to the yuv->rgb table start so it can be freed() // alignment ensures the offset can be added in a single // instruction on e.g. ARM @@ -485,16 +496,10 @@ struct SwsInternal { int contrast, brightness, saturation; // for sws_getColorspaceDetails int srcColorspaceTable[4]; int dstColorspaceTable[4]; - int srcRange; ///< 0 = MPG YUV range, 1 = JPG YUV range (source image). - int dstRange; ///< 0 = MPG YUV range, 1 = JPG YUV range (destination image). int src0Alpha; int dst0Alpha; int srcXYZ; int dstXYZ; - int src_h_chr_pos; - int dst_h_chr_pos; - int src_v_chr_pos; - int dst_v_chr_pos; int yuv2rgb_y_offset; int yuv2rgb_y_coeff; int yuv2rgb_v2r_coeff; @@ -682,10 +687,6 @@ struct SwsInternal { int needs_hcscale; ///< Set if there are chroma planes to be converted. - SwsDither dither; - - SwsAlphaBlend alphablend; - // scratch buffer for converting packed rgb0 sources // filled with a copy of the input frame + fully opaque alpha, // then passed as input to further conversion @@ -712,7 +713,7 @@ static_assert(offsetof(SwsInternal, redDither) + DITHER32_INT == offsetof(SwsInt #if ARCH_X86_64 /* x86 yuv2gbrp uses the SwsInternal for yuv coefficients if struct offsets change the asm needs to be updated too */ -static_assert(offsetof(SwsInternal, yuv2rgb_y_offset) == 40292, +static_assert(offsetof(SwsInternal, yuv2rgb_y_offset) == 40316, "yuv2rgb_y_offset must be updated in x86 asm"); #endif diff --git a/libswscale/swscale_unscaled.c b/libswscale/swscale_unscaled.c index 60c8d328a9..143c4c1002 100644 --- a/libswscale/swscale_unscaled.c +++ b/libswscale/swscale_unscaled.c @@ -146,10 +146,10 @@ static int planarToNv12Wrapper(SwsInternal *c, const uint8_t *const src[], { uint8_t *dst = dstParam[1] + dstStride[1] * srcSliceY / 2; - ff_copyPlane(src[0], srcStride[0], srcSliceY, srcSliceH, c->srcW, + ff_copyPlane(src[0], srcStride[0], srcSliceY, srcSliceH, c->opts.src_w, dstParam[0], dstStride[0]); - if (c->dstFormat == AV_PIX_FMT_NV12) + if (c->opts.dst_format == AV_PIX_FMT_NV12) interleaveBytes(src[1], src[2], dst, c->chrSrcW, (srcSliceH + 1) / 2, srcStride[1], srcStride[2], dstStride[1]); else @@ -167,10 +167,10 @@ static int nv12ToPlanarWrapper(SwsInternal *c, const uint8_t *const src[], uint8_t *dst1 = dstParam[1] + dstStride[1] * srcSliceY / 2; uint8_t *dst2 = dstParam[2] + dstStride[2] * srcSliceY / 2; - ff_copyPlane(src[0], srcStride[0], srcSliceY, srcSliceH, c->srcW, + ff_copyPlane(src[0], srcStride[0], srcSliceY, srcSliceH, c->opts.src_w, dstParam[0], dstStride[0]); - if (c->srcFormat == AV_PIX_FMT_NV12) + if (c->opts.src_format == AV_PIX_FMT_NV12) deinterleaveBytes(src[1], dst1, dst2, c->chrSrcW, (srcSliceH + 1) / 2, srcStride[1], dstStride[1], dstStride[2]); else @@ -187,10 +187,10 @@ static int planarToNv24Wrapper(SwsInternal *c, const uint8_t *const src[], { uint8_t *dst = dstParam[1] + dstStride[1] * srcSliceY; - ff_copyPlane(src[0], srcStride[0], srcSliceY, srcSliceH, c->srcW, + ff_copyPlane(src[0], srcStride[0], srcSliceY, srcSliceH, c->opts.src_w, dstParam[0], dstStride[0]); - if (c->dstFormat == AV_PIX_FMT_NV24) + if (c->opts.dst_format == AV_PIX_FMT_NV24) interleaveBytes(src[1], src[2], dst, c->chrSrcW, srcSliceH, srcStride[1], srcStride[2], dstStride[1]); else @@ -208,10 +208,10 @@ static int nv24ToPlanarWrapper(SwsInternal *c, const uint8_t *const src[], uint8_t *dst1 = dstParam[1] + dstStride[1] * srcSliceY; uint8_t *dst2 = dstParam[2] + dstStride[2] * srcSliceY; - ff_copyPlane(src[0], srcStride[0], srcSliceY, srcSliceH, c->srcW, + ff_copyPlane(src[0], srcStride[0], srcSliceY, srcSliceH, c->opts.src_w, dstParam[0], dstStride[0]); - if (c->srcFormat == AV_PIX_FMT_NV24) + if (c->opts.src_format == AV_PIX_FMT_NV24) deinterleaveBytes(src[1], dst1, dst2, c->chrSrcW, srcSliceH, srcStride[1], dstStride[1], dstStride[2]); else @@ -250,15 +250,15 @@ static int nv24ToYuv420Wrapper(SwsInternal *c, const uint8_t *const src[], uint8_t *dst1 = dstParam[1] + dstStride[1] * srcSliceY / 2; uint8_t *dst2 = dstParam[2] + dstStride[2] * srcSliceY / 2; - ff_copyPlane(src[0], srcStride[0], srcSliceY, srcSliceH, c->srcW, + ff_copyPlane(src[0], srcStride[0], srcSliceY, srcSliceH, c->opts.src_w, dstParam[0], dstStride[0]); - if (c->srcFormat == AV_PIX_FMT_NV24) + if (c->opts.src_format == AV_PIX_FMT_NV24) nv24_to_yuv420p_chroma(dst1, dstStride[1], dst2, dstStride[2], - src[1], srcStride[1], c->srcW / 2, srcSliceH); + src[1], srcStride[1], c->opts.src_w / 2, srcSliceH); else nv24_to_yuv420p_chroma(dst2, dstStride[2], dst1, dstStride[1], - src[1], srcStride[1], c->srcW / 2, srcSliceH); + src[1], srcStride[1], c->opts.src_w / 2, srcSliceH); return srcSliceH; } @@ -268,8 +268,8 @@ static int planarToP01xWrapper(SwsInternal *c, const uint8_t *const src8[], int srcSliceH, uint8_t *const dstParam8[], const int dstStride[]) { - const AVPixFmtDescriptor *src_format = av_pix_fmt_desc_get(c->srcFormat); - const AVPixFmtDescriptor *dst_format = av_pix_fmt_desc_get(c->dstFormat); + const AVPixFmtDescriptor *src_format = av_pix_fmt_desc_get(c->opts.src_format); + const AVPixFmtDescriptor *dst_format = av_pix_fmt_desc_get(c->opts.dst_format); const uint16_t **src = (const uint16_t**)src8; uint16_t *dstY = (uint16_t*)(dstParam8[0] + dstStride[0] * srcSliceY); uint16_t *dstUV = (uint16_t*)(dstParam8[1] + dstStride[1] * srcSliceY / 2); @@ -291,7 +291,7 @@ static int planarToP01xWrapper(SwsInternal *c, const uint8_t *const src8[], for (y = 0; y < srcSliceH; y++) { uint16_t *tdstY = dstY; const uint16_t *tsrc0 = src[0]; - for (x = c->srcW; x > 0; x--) { + for (x = c->opts.src_w; x > 0; x--) { *tdstY++ = *tsrc0++ << shift[0]; } src[0] += srcStride[0] / 2; @@ -301,7 +301,7 @@ static int planarToP01xWrapper(SwsInternal *c, const uint8_t *const src8[], uint16_t *tdstUV = dstUV; const uint16_t *tsrc1 = src[1]; const uint16_t *tsrc2 = src[2]; - for (x = c->srcW / 2; x > 0; x--) { + for (x = c->opts.src_w / 2; x > 0; x--) { *tdstUV++ = *tsrc1++ << shift[1]; *tdstUV++ = *tsrc2++ << shift[2]; } @@ -338,7 +338,7 @@ static int planar8ToP01xleWrapper(SwsInternal *c, const uint8_t *const src[], for (y = 0; y < srcSliceH; y++) { uint16_t *tdstY = dstY; const uint8_t *tsrc0 = src0; - for (x = c->srcW; x > 0; x--) { + for (x = c->opts.src_w; x > 0; x--) { t = *tsrc0++; output_pixel(tdstY++, t << 8); } @@ -349,7 +349,7 @@ static int planar8ToP01xleWrapper(SwsInternal *c, const uint8_t *const src[], uint16_t *tdstUV = dstUV; const uint8_t *tsrc1 = src1; const uint8_t *tsrc2 = src2; - for (x = c->srcW / 2; x > 0; x--) { + for (x = c->opts.src_w / 2; x > 0; x--) { t = *tsrc1++; output_pixel(tdstUV++, t << 8); t = *tsrc2++; @@ -372,7 +372,7 @@ static int planarToYuy2Wrapper(SwsInternal *c, const uint8_t *const src[], { uint8_t *dst = dstParam[0] + dstStride[0] * srcSliceY; - yv12toyuy2(src[0], src[1], src[2], dst, c->srcW, srcSliceH, srcStride[0], + yv12toyuy2(src[0], src[1], src[2], dst, c->opts.src_w, srcSliceH, srcStride[0], srcStride[1], dstStride[0]); return srcSliceH; @@ -384,7 +384,7 @@ static int planarToUyvyWrapper(SwsInternal *c, const uint8_t *const src[], { uint8_t *dst = dstParam[0] + dstStride[0] * srcSliceY; - yv12touyvy(src[0], src[1], src[2], dst, c->srcW, srcSliceH, srcStride[0], + yv12touyvy(src[0], src[1], src[2], dst, c->opts.src_w, srcSliceH, srcStride[0], srcStride[1], dstStride[0]); return srcSliceH; @@ -396,7 +396,7 @@ static int yuv422pToYuy2Wrapper(SwsInternal *c, const uint8_t *const src[], { uint8_t *dst = dstParam[0] + dstStride[0] * srcSliceY; - yuv422ptoyuy2(src[0], src[1], src[2], dst, c->srcW, srcSliceH, srcStride[0], + yuv422ptoyuy2(src[0], src[1], src[2], dst, c->opts.src_w, srcSliceH, srcStride[0], srcStride[1], dstStride[0]); return srcSliceH; @@ -408,7 +408,7 @@ static int yuv422pToUyvyWrapper(SwsInternal *c, const uint8_t *const src[], { uint8_t *dst = dstParam[0] + dstStride[0] * srcSliceY; - yuv422ptouyvy(src[0], src[1], src[2], dst, c->srcW, srcSliceH, srcStride[0], + yuv422ptouyvy(src[0], src[1], src[2], dst, c->opts.src_w, srcSliceH, srcStride[0], srcStride[1], dstStride[0]); return srcSliceH; @@ -422,11 +422,11 @@ static int yuyvToYuv420Wrapper(SwsInternal *c, const uint8_t *const src[], uint8_t *udst = dstParam[1] + dstStride[1] * srcSliceY / 2; uint8_t *vdst = dstParam[2] + dstStride[2] * srcSliceY / 2; - yuyvtoyuv420(ydst, udst, vdst, src[0], c->srcW, srcSliceH, dstStride[0], + yuyvtoyuv420(ydst, udst, vdst, src[0], c->opts.src_w, srcSliceH, dstStride[0], dstStride[1], srcStride[0]); if (dstParam[3]) - fillPlane(dstParam[3], dstStride[3], c->srcW, srcSliceH, srcSliceY, 255); + fillPlane(dstParam[3], dstStride[3], c->opts.src_w, srcSliceH, srcSliceY, 255); return srcSliceH; } @@ -439,7 +439,7 @@ static int yuyvToYuv422Wrapper(SwsInternal *c, const uint8_t *const src[], uint8_t *udst = dstParam[1] + dstStride[1] * srcSliceY; uint8_t *vdst = dstParam[2] + dstStride[2] * srcSliceY; - yuyvtoyuv422(ydst, udst, vdst, src[0], c->srcW, srcSliceH, dstStride[0], + yuyvtoyuv422(ydst, udst, vdst, src[0], c->opts.src_w, srcSliceH, dstStride[0], dstStride[1], srcStride[0]); return srcSliceH; @@ -453,11 +453,11 @@ static int uyvyToYuv420Wrapper(SwsInternal *c, const uint8_t *const src[], uint8_t *udst = dstParam[1] + dstStride[1] * srcSliceY / 2; uint8_t *vdst = dstParam[2] + dstStride[2] * srcSliceY / 2; - uyvytoyuv420(ydst, udst, vdst, src[0], c->srcW, srcSliceH, dstStride[0], + uyvytoyuv420(ydst, udst, vdst, src[0], c->opts.src_w, srcSliceH, dstStride[0], dstStride[1], srcStride[0]); if (dstParam[3]) - fillPlane(dstParam[3], dstStride[3], c->srcW, srcSliceH, srcSliceY, 255); + fillPlane(dstParam[3], dstStride[3], c->opts.src_w, srcSliceH, srcSliceY, 255); return srcSliceH; } @@ -470,7 +470,7 @@ static int uyvyToYuv422Wrapper(SwsInternal *c, const uint8_t *const src[], uint8_t *udst = dstParam[1] + dstStride[1] * srcSliceY; uint8_t *vdst = dstParam[2] + dstStride[2] * srcSliceY; - uyvytoyuv422(ydst, udst, vdst, src[0], c->srcW, srcSliceH, dstStride[0], + uyvytoyuv422(ydst, udst, vdst, src[0], c->opts.src_w, srcSliceH, dstStride[0], dstStride[1], srcStride[0]); return srcSliceH; @@ -566,8 +566,8 @@ static int palToRgbWrapper(SwsInternal *c, const uint8_t *const src[], const int int srcSliceY, int srcSliceH, uint8_t *const dst[], const int dstStride[]) { - const enum AVPixelFormat srcFormat = c->srcFormat; - const enum AVPixelFormat dstFormat = c->dstFormat; + const enum AVPixelFormat srcFormat = c->opts.src_format; + const enum AVPixelFormat dstFormat = c->opts.dst_format; void (*conv)(const uint8_t *src, uint8_t *dst, int num_pixels, const uint8_t *palette) = NULL; int i; @@ -599,7 +599,7 @@ static int palToRgbWrapper(SwsInternal *c, const uint8_t *const src[], const int av_get_pix_fmt_name(srcFormat), av_get_pix_fmt_name(dstFormat)); else { for (i = 0; i < srcSliceH; i++) { - conv(srcPtr, dstPtr, c->srcW, (uint8_t *) c->pal_rgb); + conv(srcPtr, dstPtr, c->opts.src_w, (uint8_t *) c->pal_rgb); srcPtr += srcStride[0]; dstPtr += dstStride[0]; } @@ -821,8 +821,8 @@ static int Rgb16ToPlanarRgb16Wrapper(SwsInternal *c, const uint8_t *const src[], uint16_t *dst1023[] = { (uint16_t *)dst[1], (uint16_t *)dst[0], (uint16_t *)dst[2], (uint16_t *)dst[3] }; int stride2013[] = { dstStride[2], dstStride[0], dstStride[1], dstStride[3] }; int stride1023[] = { dstStride[1], dstStride[0], dstStride[2], dstStride[3] }; - const AVPixFmtDescriptor *src_format = av_pix_fmt_desc_get(c->srcFormat); - const AVPixFmtDescriptor *dst_format = av_pix_fmt_desc_get(c->dstFormat); + const AVPixFmtDescriptor *src_format = av_pix_fmt_desc_get(c->opts.src_format); + const AVPixFmtDescriptor *dst_format = av_pix_fmt_desc_get(c->opts.dst_format); int bpc = dst_format->comp[0].depth; int alpha = src_format->flags & AV_PIX_FMT_FLAG_ALPHA; int swap = 0; @@ -847,20 +847,20 @@ static int Rgb16ToPlanarRgb16Wrapper(SwsInternal *c, const uint8_t *const src[], dst1023[i] += stride1023[i] * srcSliceY / 2; } - switch (c->srcFormat) { + switch (c->opts.src_format) { case AV_PIX_FMT_RGB48LE: case AV_PIX_FMT_RGB48BE: case AV_PIX_FMT_RGBA64LE: case AV_PIX_FMT_RGBA64BE: packed16togbra16(src[0], srcStride[0], dst2013, stride2013, srcSliceH, alpha, swap, - 16 - bpc, c->srcW); + 16 - bpc, c->opts.src_w); break; case AV_PIX_FMT_X2RGB10LE: av_assert0(bpc >= 10); packed30togbra10(src[0], srcStride[0], dst2013, stride2013, srcSliceH, swap, - bpc, c->srcW); + bpc, c->opts.src_w); break; case AV_PIX_FMT_BGR48LE: case AV_PIX_FMT_BGR48BE: @@ -868,13 +868,13 @@ static int Rgb16ToPlanarRgb16Wrapper(SwsInternal *c, const uint8_t *const src[], case AV_PIX_FMT_BGRA64BE: packed16togbra16(src[0], srcStride[0], dst1023, stride1023, srcSliceH, alpha, swap, - 16 - bpc, c->srcW); + 16 - bpc, c->opts.src_w); break; case AV_PIX_FMT_X2BGR10LE: av_assert0(bpc >= 10); packed30togbra10(src[0], srcStride[0], dst1023, stride1023, srcSliceH, swap, - bpc, c->srcW); + bpc, c->opts.src_w); break; default: av_log(c, AV_LOG_ERROR, @@ -1047,8 +1047,8 @@ static int planarRgb16ToRgb16Wrapper(SwsInternal *c, const uint8_t *const src[], const uint16_t *src201[] = { (uint16_t *)src[2], (uint16_t *)src[0], (uint16_t *)src[1], (uint16_t *)src[3] }; int stride102[] = { srcStride[1], srcStride[0], srcStride[2], srcStride[3] }; int stride201[] = { srcStride[2], srcStride[0], srcStride[1], srcStride[3] }; - const AVPixFmtDescriptor *src_format = av_pix_fmt_desc_get(c->srcFormat); - const AVPixFmtDescriptor *dst_format = av_pix_fmt_desc_get(c->dstFormat); + const AVPixFmtDescriptor *src_format = av_pix_fmt_desc_get(c->opts.src_format); + const AVPixFmtDescriptor *dst_format = av_pix_fmt_desc_get(c->opts.dst_format); int bits_per_sample = src_format->comp[0].depth; int swap = 0; if ( HAVE_BIGENDIAN && !(src_format->flags & AV_PIX_FMT_FLAG_BE) || @@ -1065,40 +1065,40 @@ static int planarRgb16ToRgb16Wrapper(SwsInternal *c, const uint8_t *const src[], src_format->name, dst_format->name); return srcSliceH; } - switch (c->dstFormat) { + switch (c->opts.dst_format) { case AV_PIX_FMT_BGR48LE: case AV_PIX_FMT_BGR48BE: gbr16ptopacked16(src102, stride102, dst[0] + srcSliceY * dstStride[0], dstStride[0], - srcSliceH, 0, swap, bits_per_sample, c->srcW); + srcSliceH, 0, swap, bits_per_sample, c->opts.src_w); break; case AV_PIX_FMT_RGB48LE: case AV_PIX_FMT_RGB48BE: gbr16ptopacked16(src201, stride201, dst[0] + srcSliceY * dstStride[0], dstStride[0], - srcSliceH, 0, swap, bits_per_sample, c->srcW); + srcSliceH, 0, swap, bits_per_sample, c->opts.src_w); break; case AV_PIX_FMT_RGBA64LE: case AV_PIX_FMT_RGBA64BE: gbr16ptopacked16(src201, stride201, dst[0] + srcSliceY * dstStride[0], dstStride[0], - srcSliceH, 1, swap, bits_per_sample, c->srcW); + srcSliceH, 1, swap, bits_per_sample, c->opts.src_w); break; case AV_PIX_FMT_BGRA64LE: case AV_PIX_FMT_BGRA64BE: gbr16ptopacked16(src102, stride102, dst[0] + srcSliceY * dstStride[0], dstStride[0], - srcSliceH, 1, swap, bits_per_sample, c->srcW); + srcSliceH, 1, swap, bits_per_sample, c->opts.src_w); break; case AV_PIX_FMT_X2RGB10LE: gbr16ptopacked30(src201, stride201, dst[0] + srcSliceY * dstStride[0], dstStride[0], - srcSliceH, swap, bits_per_sample, c->srcW); + srcSliceH, swap, bits_per_sample, c->opts.src_w); break; case AV_PIX_FMT_X2BGR10LE: gbr16ptopacked30(src102, stride102, dst[0] + srcSliceY * dstStride[0], dstStride[0], - srcSliceH, swap, bits_per_sample, c->srcW); + srcSliceH, swap, bits_per_sample, c->opts.src_w); break; default: av_log(c, AV_LOG_ERROR, @@ -1195,24 +1195,24 @@ static int planarRgbaToRgbWrapper(SwsInternal *c, const uint8_t *const src[], int stride102[] = { srcStride[1], srcStride[0], srcStride[2], srcStride[3] }; int stride201[] = { srcStride[2], srcStride[0], srcStride[1], srcStride[3] }; - if (c->srcFormat != AV_PIX_FMT_GBRAP) { + if (c->opts.src_format != AV_PIX_FMT_GBRAP) { av_log(c, AV_LOG_ERROR, "unsupported planar RGB conversion %s -> %s\n", - av_get_pix_fmt_name(c->srcFormat), - av_get_pix_fmt_name(c->dstFormat)); + av_get_pix_fmt_name(c->opts.src_format), + av_get_pix_fmt_name(c->opts.dst_format)); return srcSliceH; } - switch (c->dstFormat) { + switch (c->opts.dst_format) { case AV_PIX_FMT_BGR24: gbr24ptopacked24(src102, stride102, dst[0] + srcSliceY * dstStride[0], dstStride[0], - srcSliceH, c->srcW); + srcSliceH, c->opts.src_w); break; case AV_PIX_FMT_RGB24: gbr24ptopacked24(src201, stride201, dst[0] + srcSliceY * dstStride[0], dstStride[0], - srcSliceH, c->srcW); + srcSliceH, c->opts.src_w); break; case AV_PIX_FMT_ARGB: @@ -1220,7 +1220,7 @@ static int planarRgbaToRgbWrapper(SwsInternal *c, const uint8_t *const src[], case AV_PIX_FMT_RGBA: gbraptopacked32(src201, stride201, dst[0] + srcSliceY * dstStride[0], dstStride[0], - srcSliceH, alpha_first, c->srcW); + srcSliceH, alpha_first, c->opts.src_w); break; case AV_PIX_FMT_ABGR: @@ -1228,14 +1228,14 @@ static int planarRgbaToRgbWrapper(SwsInternal *c, const uint8_t *const src[], case AV_PIX_FMT_BGRA: gbraptopacked32(src102, stride102, dst[0] + srcSliceY * dstStride[0], dstStride[0], - srcSliceH, alpha_first, c->srcW); + srcSliceH, alpha_first, c->opts.src_w); break; default: av_log(c, AV_LOG_ERROR, "unsupported planar RGB conversion %s -> %s\n", - av_get_pix_fmt_name(c->srcFormat), - av_get_pix_fmt_name(c->dstFormat)); + av_get_pix_fmt_name(c->opts.src_format), + av_get_pix_fmt_name(c->opts.dst_format)); } return srcSliceH; @@ -1251,24 +1251,24 @@ static int planarRgbToRgbWrapper(SwsInternal *c, const uint8_t *const src[], int stride102[] = { srcStride[1], srcStride[0], srcStride[2] }; int stride201[] = { srcStride[2], srcStride[0], srcStride[1] }; - if (c->srcFormat != AV_PIX_FMT_GBRP) { + if (c->opts.src_format != AV_PIX_FMT_GBRP) { av_log(c, AV_LOG_ERROR, "unsupported planar RGB conversion %s -> %s\n", - av_get_pix_fmt_name(c->srcFormat), - av_get_pix_fmt_name(c->dstFormat)); + av_get_pix_fmt_name(c->opts.src_format), + av_get_pix_fmt_name(c->opts.dst_format)); return srcSliceH; } - switch (c->dstFormat) { + switch (c->opts.dst_format) { case AV_PIX_FMT_BGR24: gbr24ptopacked24(src102, stride102, dst[0] + srcSliceY * dstStride[0], dstStride[0], - srcSliceH, c->srcW); + srcSliceH, c->opts.src_w); break; case AV_PIX_FMT_RGB24: gbr24ptopacked24(src201, stride201, dst[0] + srcSliceY * dstStride[0], dstStride[0], - srcSliceH, c->srcW); + srcSliceH, c->opts.src_w); break; case AV_PIX_FMT_ARGB: @@ -1276,7 +1276,7 @@ static int planarRgbToRgbWrapper(SwsInternal *c, const uint8_t *const src[], case AV_PIX_FMT_RGBA: gbr24ptopacked32(src201, stride201, dst[0] + srcSliceY * dstStride[0], dstStride[0], - srcSliceH, alpha_first, c->srcW); + srcSliceH, alpha_first, c->opts.src_w); break; case AV_PIX_FMT_ABGR: @@ -1284,14 +1284,14 @@ static int planarRgbToRgbWrapper(SwsInternal *c, const uint8_t *const src[], case AV_PIX_FMT_BGRA: gbr24ptopacked32(src102, stride102, dst[0] + srcSliceY * dstStride[0], dstStride[0], - srcSliceH, alpha_first, c->srcW); + srcSliceH, alpha_first, c->opts.src_w); break; default: av_log(c, AV_LOG_ERROR, "unsupported planar RGB conversion %s -> %s\n", - av_get_pix_fmt_name(c->srcFormat), - av_get_pix_fmt_name(c->dstFormat)); + av_get_pix_fmt_name(c->opts.src_format), + av_get_pix_fmt_name(c->opts.dst_format)); } return srcSliceH; @@ -1302,14 +1302,14 @@ static int planarRgbToplanarRgbWrapper(SwsInternal *c, int srcSliceY, int srcSliceH, uint8_t *const dst[], const int dstStride[]) { - ff_copyPlane(src[0], srcStride[0], srcSliceY, srcSliceH, c->srcW, + ff_copyPlane(src[0], srcStride[0], srcSliceY, srcSliceH, c->opts.src_w, dst[0], dstStride[0]); - ff_copyPlane(src[1], srcStride[1], srcSliceY, srcSliceH, c->srcW, + ff_copyPlane(src[1], srcStride[1], srcSliceY, srcSliceH, c->opts.src_w, dst[1], dstStride[1]); - ff_copyPlane(src[2], srcStride[2], srcSliceY, srcSliceH, c->srcW, + ff_copyPlane(src[2], srcStride[2], srcSliceY, srcSliceH, c->opts.src_w, dst[2], dstStride[2]); if (dst[3]) - fillPlane(dst[3], dstStride[3], c->srcW, srcSliceH, srcSliceY, 255); + fillPlane(dst[3], dstStride[3], c->opts.src_w, srcSliceH, srcSliceY, 255); return srcSliceH; } @@ -1357,32 +1357,32 @@ static int rgbToPlanarRgbWrapper(SwsInternal *c, const uint8_t *const src[], dst[0] + srcSliceY * dstStride[0], dst[1] + srcSliceY * dstStride[1] }; - switch (c->srcFormat) { + switch (c->opts.src_format) { case AV_PIX_FMT_RGB24: packedtogbr24p((const uint8_t *) src[0], srcStride[0], dst201, - stride201, srcSliceH, alpha_first, 3, c->srcW); + stride201, srcSliceH, alpha_first, 3, c->opts.src_w); break; case AV_PIX_FMT_BGR24: packedtogbr24p((const uint8_t *) src[0], srcStride[0], dst102, - stride102, srcSliceH, alpha_first, 3, c->srcW); + stride102, srcSliceH, alpha_first, 3, c->opts.src_w); break; case AV_PIX_FMT_ARGB: alpha_first = 1; case AV_PIX_FMT_RGBA: packedtogbr24p((const uint8_t *) src[0], srcStride[0], dst201, - stride201, srcSliceH, alpha_first, 4, c->srcW); + stride201, srcSliceH, alpha_first, 4, c->opts.src_w); break; case AV_PIX_FMT_ABGR: alpha_first = 1; case AV_PIX_FMT_BGRA: packedtogbr24p((const uint8_t *) src[0], srcStride[0], dst102, - stride102, srcSliceH, alpha_first, 4, c->srcW); + stride102, srcSliceH, alpha_first, 4, c->opts.src_w); break; default: av_log(c, AV_LOG_ERROR, "unsupported planar RGB conversion %s -> %s\n", - av_get_pix_fmt_name(c->srcFormat), - av_get_pix_fmt_name(c->dstFormat)); + av_get_pix_fmt_name(c->opts.src_format), + av_get_pix_fmt_name(c->opts.dst_format)); } return srcSliceH; @@ -1467,32 +1467,32 @@ static int rgbToPlanarRgbaWrapper(SwsInternal *c, const uint8_t *const src[], dst[1] + srcSliceY * dstStride[1], dst[3] + srcSliceY * dstStride[3] }; - switch (c->srcFormat) { + switch (c->opts.src_format) { case AV_PIX_FMT_RGB24: packed24togbrap((const uint8_t *) src[0], srcStride[0], dst201, - stride201, srcSliceH, c->srcW); + stride201, srcSliceH, c->opts.src_w); break; case AV_PIX_FMT_BGR24: packed24togbrap((const uint8_t *) src[0], srcStride[0], dst102, - stride102, srcSliceH, c->srcW); + stride102, srcSliceH, c->opts.src_w); break; case AV_PIX_FMT_ARGB: alpha_first = 1; case AV_PIX_FMT_RGBA: packed32togbrap((const uint8_t *) src[0], srcStride[0], dst201, - stride201, srcSliceH, alpha_first, c->srcW); + stride201, srcSliceH, alpha_first, c->opts.src_w); break; case AV_PIX_FMT_ABGR: alpha_first = 1; case AV_PIX_FMT_BGRA: packed32togbrap((const uint8_t *) src[0], srcStride[0], dst102, - stride102, srcSliceH, alpha_first, c->srcW); + stride102, srcSliceH, alpha_first, c->opts.src_w); break; default: av_log(c, AV_LOG_ERROR, "unsupported planar RGB conversion %s -> %s\n", - av_get_pix_fmt_name(c->srcFormat), - av_get_pix_fmt_name(c->dstFormat)); + av_get_pix_fmt_name(c->opts.src_format), + av_get_pix_fmt_name(c->opts.dst_format)); } return srcSliceH; @@ -1568,7 +1568,7 @@ static int bayer_to_rgb24_wrapper(SwsInternal *c, const uint8_t *const src[], void (*copy) (const uint8_t *src, int src_stride, uint8_t *dst, int dst_stride, int width); void (*interpolate)(const uint8_t *src, int src_stride, uint8_t *dst, int dst_stride, int width); - switch(c->srcFormat) { + switch(c->opts.src_format) { #define CASE(pixfmt, prefix) \ case pixfmt: copy = bayer_##prefix##_to_rgb24_copy; \ interpolate = bayer_##prefix##_to_rgb24_interpolate; \ @@ -1591,20 +1591,20 @@ static int bayer_to_rgb24_wrapper(SwsInternal *c, const uint8_t *const src[], av_assert0(srcSliceH > 1); - copy(srcPtr, srcStride[0], dstPtr, dstStride[0], c->srcW); + copy(srcPtr, srcStride[0], dstPtr, dstStride[0], c->opts.src_w); srcPtr += 2 * srcStride[0]; dstPtr += 2 * dstStride[0]; for (i = 2; i < srcSliceH - 2; i += 2) { - interpolate(srcPtr, srcStride[0], dstPtr, dstStride[0], c->srcW); + interpolate(srcPtr, srcStride[0], dstPtr, dstStride[0], c->opts.src_w); srcPtr += 2 * srcStride[0]; dstPtr += 2 * dstStride[0]; } if (i + 1 == srcSliceH) { - copy(srcPtr, -srcStride[0], dstPtr, -dstStride[0], c->srcW); + copy(srcPtr, -srcStride[0], dstPtr, -dstStride[0], c->opts.src_w); } else if (i < srcSliceH) - copy(srcPtr, srcStride[0], dstPtr, dstStride[0], c->srcW); + copy(srcPtr, srcStride[0], dstPtr, dstStride[0], c->opts.src_w); return srcSliceH; } @@ -1618,7 +1618,7 @@ static int bayer_to_rgb48_wrapper(SwsInternal *c, const uint8_t *const src[], void (*copy) (const uint8_t *src, int src_stride, uint8_t *dst, int dst_stride, int width); void (*interpolate)(const uint8_t *src, int src_stride, uint8_t *dst, int dst_stride, int width); - switch(c->srcFormat) { + switch(c->opts.src_format) { #define CASE(pixfmt, prefix) \ case pixfmt: copy = bayer_##prefix##_to_rgb48_copy; \ interpolate = bayer_##prefix##_to_rgb48_interpolate; \ @@ -1641,20 +1641,20 @@ static int bayer_to_rgb48_wrapper(SwsInternal *c, const uint8_t *const src[], av_assert0(srcSliceH > 1); - copy(srcPtr, srcStride[0], dstPtr, dstStride[0], c->srcW); + copy(srcPtr, srcStride[0], dstPtr, dstStride[0], c->opts.src_w); srcPtr += 2 * srcStride[0]; dstPtr += 2 * dstStride[0]; for (i = 2; i < srcSliceH - 2; i += 2) { - interpolate(srcPtr, srcStride[0], dstPtr, dstStride[0], c->srcW); + interpolate(srcPtr, srcStride[0], dstPtr, dstStride[0], c->opts.src_w); srcPtr += 2 * srcStride[0]; dstPtr += 2 * dstStride[0]; } if (i + 1 == srcSliceH) { - copy(srcPtr, -srcStride[0], dstPtr, -dstStride[0], c->srcW); + copy(srcPtr, -srcStride[0], dstPtr, -dstStride[0], c->opts.src_w); } else if (i < srcSliceH) - copy(srcPtr, srcStride[0], dstPtr, dstStride[0], c->srcW); + copy(srcPtr, srcStride[0], dstPtr, dstStride[0], c->opts.src_w); return srcSliceH; } @@ -1670,7 +1670,7 @@ static int bayer_to_yv12_wrapper(SwsInternal *c, const uint8_t *const src[], void (*copy) (const uint8_t *src, int src_stride, uint8_t *dstY, uint8_t *dstU, uint8_t *dstV, int luma_stride, int width, const int32_t *rgb2yuv); void (*interpolate)(const uint8_t *src, int src_stride, uint8_t *dstY, uint8_t *dstU, uint8_t *dstV, int luma_stride, int width, const int32_t *rgb2yuv); - switch(c->srcFormat) { + switch(c->opts.src_format) { #define CASE(pixfmt, prefix) \ case pixfmt: copy = bayer_##prefix##_to_yv12_copy; \ interpolate = bayer_##prefix##_to_yv12_interpolate; \ @@ -1693,14 +1693,14 @@ static int bayer_to_yv12_wrapper(SwsInternal *c, const uint8_t *const src[], av_assert0(srcSliceH > 1); - copy(srcPtr, srcStride[0], dstY, dstU, dstV, dstStride[0], c->srcW, c->input_rgb2yuv_table); + copy(srcPtr, srcStride[0], dstY, dstU, dstV, dstStride[0], c->opts.src_w, c->input_rgb2yuv_table); srcPtr += 2 * srcStride[0]; dstY += 2 * dstStride[0]; dstU += dstStride[1]; dstV += dstStride[1]; for (i = 2; i < srcSliceH - 2; i += 2) { - interpolate(srcPtr, srcStride[0], dstY, dstU, dstV, dstStride[0], c->srcW, c->input_rgb2yuv_table); + interpolate(srcPtr, srcStride[0], dstY, dstU, dstV, dstStride[0], c->opts.src_w, c->input_rgb2yuv_table); srcPtr += 2 * srcStride[0]; dstY += 2 * dstStride[0]; dstU += dstStride[1]; @@ -1708,9 +1708,9 @@ static int bayer_to_yv12_wrapper(SwsInternal *c, const uint8_t *const src[], } if (i + 1 == srcSliceH) { - copy(srcPtr, -srcStride[0], dstY, dstU, dstV, -dstStride[0], c->srcW, c->input_rgb2yuv_table); + copy(srcPtr, -srcStride[0], dstY, dstU, dstV, -dstStride[0], c->opts.src_w, c->input_rgb2yuv_table); } else if (i < srcSliceH) - copy(srcPtr, srcStride[0], dstY, dstU, dstV, dstStride[0], c->srcW, c->input_rgb2yuv_table); + copy(srcPtr, srcStride[0], dstY, dstU, dstV, dstStride[0], c->opts.src_w, c->input_rgb2yuv_table); return srcSliceH; } @@ -1751,8 +1751,8 @@ static int bayer_to_yv12_wrapper(SwsInternal *c, const uint8_t *const src[], typedef void (* rgbConvFn) (const uint8_t *, uint8_t *, int); static rgbConvFn findRgbConvFn(SwsInternal *c) { - const enum AVPixelFormat srcFormat = c->srcFormat; - const enum AVPixelFormat dstFormat = c->dstFormat; + const enum AVPixelFormat srcFormat = c->opts.src_format; + const enum AVPixelFormat dstFormat = c->opts.dst_format; const int srcId = c->srcFormatBpp; const int dstId = c->dstFormatBpp; rgbConvFn conv = NULL; @@ -1899,7 +1899,7 @@ static rgbConvFn findRgbConvFn(SwsInternal *c) return NULL; // Maintain symmetry between endianness - if (c->flags & SWS_BITEXACT) + if (c->opts.flags & SWS_BITEXACT) if ((dstFormat == AV_PIX_FMT_RGB32 || dstFormat == AV_PIX_FMT_BGR32 ) && !isRGBA32(srcFormat) && ALT32_CORR>0) return NULL; @@ -1912,10 +1912,10 @@ static int rgbToRgbWrapper(SwsInternal *c, const uint8_t *const src[], const int const int dstStride[]) { - const enum AVPixelFormat srcFormat = c->srcFormat; - const enum AVPixelFormat dstFormat = c->dstFormat; - const AVPixFmtDescriptor *desc_src = av_pix_fmt_desc_get(c->srcFormat); - const AVPixFmtDescriptor *desc_dst = av_pix_fmt_desc_get(c->dstFormat); + const enum AVPixelFormat srcFormat = c->opts.src_format; + const enum AVPixelFormat dstFormat = c->opts.dst_format; + const AVPixFmtDescriptor *desc_src = av_pix_fmt_desc_get(c->opts.src_format); + const AVPixFmtDescriptor *desc_dst = av_pix_fmt_desc_get(c->opts.dst_format); const int srcBpp = (c->srcFormatBpp + 7) >> 3; const int dstBpp = (c->dstFormatBpp + 7) >> 3; rgbConvFn conv = findRgbConvFn(c); @@ -1945,20 +1945,20 @@ static int rgbToRgbWrapper(SwsInternal *c, const uint8_t *const src[], const int if (dstStride[0] * srcBpp == srcStride[0] * dstBpp && srcStride[0] > 0 && !(srcStride[0] % srcBpp) && !dst_bswap && !src_bswap) conv(srcPtr, dstPtr + dstStride[0] * srcSliceY, - (srcSliceH - 1) * srcStride[0] + c->srcW * srcBpp); + (srcSliceH - 1) * srcStride[0] + c->opts.src_w * srcBpp); else { int i, j; dstPtr += dstStride[0] * srcSliceY; for (i = 0; i < srcSliceH; i++) { if(src_bswap) { - for(j=0; jsrcW; j++) + for(j=0; jopts.src_w; j++) ((uint16_t*)c->formatConvBuffer)[j] = av_bswap16(((uint16_t*)srcPtr)[j]); - conv(c->formatConvBuffer, dstPtr, c->srcW * srcBpp); + conv(c->formatConvBuffer, dstPtr, c->opts.src_w * srcBpp); }else - conv(srcPtr, dstPtr, c->srcW * srcBpp); + conv(srcPtr, dstPtr, c->opts.src_w * srcBpp); if(dst_bswap) - for(j=0; jsrcW; j++) + for(j=0; jopts.src_w; j++) ((uint16_t*)dstPtr)[j] = av_bswap16(((uint16_t*)dstPtr)[j]); srcPtr += srcStride[0]; dstPtr += dstStride[0]; @@ -1977,11 +1977,11 @@ static int bgr24ToYv12Wrapper(SwsInternal *c, const uint8_t *const src[], dst[0] + srcSliceY * dstStride[0], dst[1] + (srcSliceY >> 1) * dstStride[1], dst[2] + (srcSliceY >> 1) * dstStride[2], - c->srcW, srcSliceH, + c->opts.src_w, srcSliceH, dstStride[0], dstStride[1], srcStride[0], c->input_rgb2yuv_table); if (dst[3]) - fillPlane(dst[3], dstStride[3], c->srcW, srcSliceH, srcSliceY, 255); + fillPlane(dst[3], dstStride[3], c->opts.src_w, srcSliceH, srcSliceY, 255); return srcSliceH; } @@ -1989,7 +1989,7 @@ static int yvu9ToYv12Wrapper(SwsInternal *c, const uint8_t *const src[], const int srcStride[], int srcSliceY, int srcSliceH, uint8_t *const dst[], const int dstStride[]) { - ff_copyPlane(src[0], srcStride[0], srcSliceY, srcSliceH, c->srcW, + ff_copyPlane(src[0], srcStride[0], srcSliceY, srcSliceH, c->opts.src_w, dst[0], dstStride[0]); planar2x(src[1], dst[1] + dstStride[1] * (srcSliceY >> 1), c->chrSrcW, @@ -1997,7 +1997,7 @@ static int yvu9ToYv12Wrapper(SwsInternal *c, const uint8_t *const src[], planar2x(src[2], dst[2] + dstStride[2] * (srcSliceY >> 1), c->chrSrcW, srcSliceH >> 2, srcStride[2], dstStride[2]); if (dst[3]) - fillPlane(dst[3], dstStride[3], c->srcW, srcSliceH, srcSliceY, 255); + fillPlane(dst[3], dstStride[3], c->opts.src_w, srcSliceH, srcSliceY, 255); return srcSliceH; } @@ -2011,7 +2011,7 @@ static int uint_y_to_float_y_wrapper(SwsInternal *c, const uint8_t *const src[], float *dstPtr = (float *)(dst[0] + dstStride[0] * srcSliceY); for (y = 0; y < srcSliceH; ++y){ - for (x = 0; x < c->srcW; ++x){ + for (x = 0; x < c->opts.src_w; ++x){ dstPtr[x] = c->uint2float_lut[srcPtr[x]]; } srcPtr += srcStride[0]; @@ -2033,7 +2033,7 @@ static int float_y_to_uint_y_wrapper(SwsInternal *c, uint8_t *dstPtr = dst[0] + dstStride[0] * srcSliceY; for (y = 0; y < srcSliceH; ++y){ - for (x = 0; x < c->srcW; ++x){ + for (x = 0; x < c->opts.src_w; ++x){ dstPtr[x] = av_clip_uint8(lrintf(255.0f * srcPtr[x])); } srcPtr += srcStrideFloat; @@ -2057,9 +2057,9 @@ static int packedCopyWrapper(SwsInternal *c, const uint8_t *const src[], int length = 0; /* universal length finder */ - while (length + c->srcW <= FFABS(dstStride[0]) && - length + c->srcW <= FFABS(srcStride[0])) - length += c->srcW; + while (length + c->opts.src_w <= FFABS(dstStride[0]) && + length + c->opts.src_w <= FFABS(srcStride[0])) + length += c->opts.src_w; av_assert1(length != 0); for (i = 0; i < srcSliceH; i++) { @@ -2073,7 +2073,7 @@ static int packedCopyWrapper(SwsInternal *c, const uint8_t *const src[], #define DITHER_COPY(dst, dstStride, src, srcStride, bswap, dbswap)\ unsigned shift= src_depth-dst_depth, tmp;\ - if (c->dither == SWS_DITHER_NONE) {\ + if (c->opts.dither == SWS_DITHER_NONE) {\ for (i = 0; i < height; i++) {\ for (j = 0; j < length-7; j+=8) {\ dst[j+0] = dbswap(bswap(src[j+0])>>shift);\ @@ -2135,31 +2135,31 @@ static int planarCopyWrapper(SwsInternal *c, const uint8_t *const src[], const int srcStride[], int srcSliceY, int srcSliceH, uint8_t *const dst[], const int dstStride[]) { - const AVPixFmtDescriptor *desc_src = av_pix_fmt_desc_get(c->srcFormat); - const AVPixFmtDescriptor *desc_dst = av_pix_fmt_desc_get(c->dstFormat); + const AVPixFmtDescriptor *desc_src = av_pix_fmt_desc_get(c->opts.src_format); + const AVPixFmtDescriptor *desc_dst = av_pix_fmt_desc_get(c->opts.dst_format); int plane, i, j; for (plane = 0; plane < 4 && dst[plane] != NULL; plane++) { - int length = (plane == 0 || plane == 3) ? c->srcW : AV_CEIL_RSHIFT(c->srcW, c->chrDstHSubSample); + int length = (plane == 0 || plane == 3) ? c->opts.src_w : AV_CEIL_RSHIFT(c->opts.src_w, c->chrDstHSubSample); int y = (plane == 0 || plane == 3) ? srcSliceY: AV_CEIL_RSHIFT(srcSliceY, c->chrDstVSubSample); int height = (plane == 0 || plane == 3) ? srcSliceH: AV_CEIL_RSHIFT(srcSliceH, c->chrDstVSubSample); const uint8_t *srcPtr = src[plane]; uint8_t *dstPtr = dst[plane] + dstStride[plane] * y; - int shiftonly = plane == 1 || plane == 2 || (!c->srcRange && plane == 0); + int shiftonly = plane == 1 || plane == 2 || (!c->opts.src_range && plane == 0); // ignore palette for GRAY8 if (plane == 1 && !dst[2]) continue; if (!src[plane] || (plane == 1 && !src[2])) { - if (is16BPS(c->dstFormat) || isNBPS(c->dstFormat)) { + if (is16BPS(c->opts.dst_format) || isNBPS(c->opts.dst_format)) { fillPlane16(dst[plane], dstStride[plane], length, height, y, plane == 3, desc_dst->comp[plane].depth, - isBE(c->dstFormat)); + isBE(c->opts.dst_format)); } else { fillPlane(dst[plane], dstStride[plane], length, height, y, (plane == 3) ? 255 : 128); } } else { - if(isNBPS(c->srcFormat) || isNBPS(c->dstFormat) - || (is16BPS(c->srcFormat) != is16BPS(c->dstFormat)) + if(isNBPS(c->opts.src_format) || isNBPS(c->opts.dst_format) + || (is16BPS(c->opts.src_format) != is16BPS(c->opts.dst_format)) ) { const int src_depth = desc_src->comp[plane].depth; const int dst_depth = desc_dst->comp[plane].depth; @@ -2167,7 +2167,7 @@ static int planarCopyWrapper(SwsInternal *c, const uint8_t *const src[], uint16_t *dstPtr2 = (uint16_t*)dstPtr; if (dst_depth == 8) { - if(isBE(c->srcFormat) == HAVE_BIGENDIAN){ + if(isBE(c->opts.src_format) == HAVE_BIGENDIAN){ DITHER_COPY(dstPtr, dstStride[plane], srcPtr2, srcStride[plane]/2, , ) } else { DITHER_COPY(dstPtr, dstStride[plane], srcPtr2, srcStride[plane]/2, av_bswap16, ) @@ -2183,7 +2183,7 @@ static int planarCopyWrapper(SwsInternal *c, const uint8_t *const src[], w(&dstPtr2[j], (srcPtr[j]<<(dst_depth-8)) |\ (srcPtr[j]>>(2*8-dst_depth)));\ } - if(isBE(c->dstFormat)){ + if(isBE(c->opts.dst_format)){ COPY816(AV_WB16) } else { COPY816(AV_WL16) @@ -2194,8 +2194,8 @@ static int planarCopyWrapper(SwsInternal *c, const uint8_t *const src[], } else if (src_depth <= dst_depth) { for (i = 0; i < height; i++) { j = 0; - if(isBE(c->srcFormat) == HAVE_BIGENDIAN && - isBE(c->dstFormat) == HAVE_BIGENDIAN && + if(isBE(c->opts.src_format) == HAVE_BIGENDIAN && + isBE(c->opts.dst_format) == HAVE_BIGENDIAN && shiftonly) { unsigned shift = dst_depth - src_depth; #if HAVE_FAST_64BIT @@ -2230,14 +2230,14 @@ static int planarCopyWrapper(SwsInternal *c, const uint8_t *const src[], (v>>(2*src_depth-dst_depth)));\ }\ } - if(isBE(c->srcFormat)){ - if(isBE(c->dstFormat)){ + if(isBE(c->opts.src_format)){ + if(isBE(c->opts.dst_format)){ COPY_UP(AV_RB16, AV_WB16) } else { COPY_UP(AV_RB16, AV_WL16) } } else { - if(isBE(c->dstFormat)){ + if(isBE(c->opts.dst_format)){ COPY_UP(AV_RL16, AV_WB16) } else { COPY_UP(AV_RL16, AV_WL16) @@ -2247,22 +2247,22 @@ static int planarCopyWrapper(SwsInternal *c, const uint8_t *const src[], srcPtr2 += srcStride[plane]/2; } } else { - if(isBE(c->srcFormat) == HAVE_BIGENDIAN){ - if(isBE(c->dstFormat) == HAVE_BIGENDIAN){ + if(isBE(c->opts.src_format) == HAVE_BIGENDIAN){ + if(isBE(c->opts.dst_format) == HAVE_BIGENDIAN){ DITHER_COPY(dstPtr2, dstStride[plane]/2, srcPtr2, srcStride[plane]/2, , ) } else { DITHER_COPY(dstPtr2, dstStride[plane]/2, srcPtr2, srcStride[plane]/2, , av_bswap16) } }else{ - if(isBE(c->dstFormat) == HAVE_BIGENDIAN){ + if(isBE(c->opts.dst_format) == HAVE_BIGENDIAN){ DITHER_COPY(dstPtr2, dstStride[plane]/2, srcPtr2, srcStride[plane]/2, av_bswap16, ) } else { DITHER_COPY(dstPtr2, dstStride[plane]/2, srcPtr2, srcStride[plane]/2, av_bswap16, av_bswap16) } } } - } else if (is16BPS(c->srcFormat) && is16BPS(c->dstFormat) && - isBE(c->srcFormat) != isBE(c->dstFormat)) { + } else if (is16BPS(c->opts.src_format) && is16BPS(c->opts.dst_format) && + isBE(c->opts.src_format) != isBE(c->opts.dst_format)) { for (i = 0; i < height; i++) { for (j = 0; j < length; j++) @@ -2270,8 +2270,8 @@ static int planarCopyWrapper(SwsInternal *c, const uint8_t *const src[], srcPtr += srcStride[plane]; dstPtr += dstStride[plane]; } - } else if (isFloat(c->srcFormat) && isFloat(c->dstFormat) && - isBE(c->srcFormat) != isBE(c->dstFormat)) { /* swap float plane */ + } else if (isFloat(c->opts.src_format) && isFloat(c->opts.dst_format) && + isBE(c->opts.src_format) != isBE(c->opts.dst_format)) { /* swap float plane */ for (i = 0; i < height; i++) { for (j = 0; j < length; j++) ((uint32_t *) dstPtr)[j] = av_bswap32(((const uint32_t *) srcPtr)[j]); @@ -2283,7 +2283,7 @@ static int planarCopyWrapper(SwsInternal *c, const uint8_t *const src[], memcpy(dst[plane] + dstStride[plane] * y, src[plane], height * dstStride[plane]); } else { - if (is16BPS(c->srcFormat) && is16BPS(c->dstFormat)) + if (is16BPS(c->opts.src_format) && is16BPS(c->opts.dst_format)) length *= 2; else if (desc_src->comp[0].depth == 1) length >>= 3; // monowhite/black @@ -2306,11 +2306,11 @@ static int planarCopyWrapper(SwsInternal *c, const uint8_t *const src[], void ff_get_unscaled_swscale(SwsInternal *c) { - const enum AVPixelFormat srcFormat = c->srcFormat; - const enum AVPixelFormat dstFormat = c->dstFormat; - const int flags = c->flags; - const int dstH = c->dstH; - const int dstW = c->dstW; + const enum AVPixelFormat srcFormat = c->opts.src_format; + const enum AVPixelFormat dstFormat = c->opts.dst_format; + const int flags = c->opts.flags; + const int dstH = c->opts.dst_h; + const int dstW = c->opts.dst_w; int needsDither; needsDither = isAnyRGB(dstFormat) && @@ -2340,7 +2340,7 @@ void ff_get_unscaled_swscale(SwsInternal *c) /* yuv2bgr */ if ((srcFormat == AV_PIX_FMT_YUV420P || srcFormat == AV_PIX_FMT_YUV422P || srcFormat == AV_PIX_FMT_YUVA420P) && isAnyRGB(dstFormat) && - !(flags & SWS_ACCURATE_RND) && (c->dither == SWS_DITHER_BAYER || c->dither == SWS_DITHER_AUTO) && !(dstH & 1)) { + !(flags & SWS_ACCURATE_RND) && (c->opts.dither == SWS_DITHER_BAYER || c->opts.dither == SWS_DITHER_AUTO) && !(dstH & 1)) { c->convert_unscaled = ff_yuv2rgb_get_func_ptr(c); c->dst_slice_align = 2; } @@ -2377,7 +2377,7 @@ void ff_get_unscaled_swscale(SwsInternal *c) /* RGB/BGR -> RGB/BGR (no dither needed forms) */ if (isAnyRGB(srcFormat) && isAnyRGB(dstFormat) && findRgbConvFn(c) - && (!needsDither || (c->flags&(SWS_FAST_BILINEAR|SWS_POINT)))) + && (!needsDither || (c->opts.flags&(SWS_FAST_BILINEAR|SWS_POINT)))) c->convert_unscaled = rgbToRgbWrapper; /* RGB to planar RGB */ @@ -2548,7 +2548,7 @@ void ff_get_unscaled_swscale(SwsInternal *c) } /* LQ converters if -sws 0 or -sws 4*/ - if (c->flags&(SWS_FAST_BILINEAR|SWS_POINT)) { + if (c->opts.flags&(SWS_FAST_BILINEAR|SWS_POINT)) { /* yv12_to_yuy2 */ if (srcFormat == AV_PIX_FMT_YUV420P || srcFormat == AV_PIX_FMT_YUVA420P) { if (dstFormat == AV_PIX_FMT_YUYV422) @@ -2584,7 +2584,7 @@ void ff_get_unscaled_swscale(SwsInternal *c) c->chrDstVSubSample == c->chrSrcVSubSample && !isSemiPlanarYUV(srcFormat) && !isSemiPlanarYUV(dstFormat)))) { - if (isPacked(c->srcFormat)) + if (isPacked(c->opts.src_format)) c->convert_unscaled = packedCopyWrapper; else /* Planar YUV or gray */ c->convert_unscaled = planarCopyWrapper; diff --git a/libswscale/utils.c b/libswscale/utils.c index f71c63c17f..465302a9fa 100644 --- a/libswscale/utils.c +++ b/libswscale/utils.c @@ -298,17 +298,17 @@ static SwsContext *alloc_set_opts(int srcW, int srcH, enum AVPixelFormat srcForm if (!c) return NULL; - c->flags = flags; - c->srcW = srcW; - c->srcH = srcH; - c->dstW = dstW; - c->dstH = dstH; - c->srcFormat = srcFormat; - c->dstFormat = dstFormat; + c->opts.flags = flags; + c->opts.src_w = srcW; + c->opts.src_h = srcH; + c->opts.dst_w = dstW; + c->opts.dst_h = dstH; + c->opts.src_format = srcFormat; + c->opts.dst_format = dstFormat; if (param) { - c->param[0] = param[0]; - c->param[1] = param[1]; + c->opts.scaler_params[0] = param[0]; + c->opts.scaler_params[1] = param[1]; } return sws; @@ -1030,10 +1030,10 @@ static int handle_xyz(enum AVPixelFormat *format) static void handle_formats(SwsInternal *c) { - c->src0Alpha |= handle_0alpha(&c->srcFormat); - c->dst0Alpha |= handle_0alpha(&c->dstFormat); - c->srcXYZ |= handle_xyz(&c->srcFormat); - c->dstXYZ |= handle_xyz(&c->dstFormat); + c->src0Alpha |= handle_0alpha(&c->opts.src_format); + c->dst0Alpha |= handle_0alpha(&c->opts.dst_format); + c->srcXYZ |= handle_xyz(&c->opts.src_format); + c->dstXYZ |= handle_xyz(&c->opts.dst_format); if (c->srcXYZ || c->dstXYZ) fill_xyztables(c); } @@ -1066,16 +1066,16 @@ int sws_setColorspaceDetails(SwsContext *sws, const int inv_table[4], } handle_formats(c); - desc_dst = av_pix_fmt_desc_get(c->dstFormat); - desc_src = av_pix_fmt_desc_get(c->srcFormat); + desc_dst = av_pix_fmt_desc_get(c->opts.dst_format); + desc_src = av_pix_fmt_desc_get(c->opts.src_format); - if(range_override_needed(c->dstFormat)) + if(range_override_needed(c->opts.dst_format)) dstRange = 0; - if(range_override_needed(c->srcFormat)) + if(range_override_needed(c->opts.src_format)) srcRange = 0; - if (c->srcRange != srcRange || - c->dstRange != dstRange || + if (c->opts.src_range != srcRange || + c->opts.dst_range != dstRange || c->brightness != brightness || c->contrast != contrast || c->saturation != saturation || @@ -1092,8 +1092,8 @@ int sws_setColorspaceDetails(SwsContext *sws, const int inv_table[4], c->brightness = brightness; c->contrast = contrast; c->saturation = saturation; - c->srcRange = srcRange; - c->dstRange = dstRange; + c->opts.src_range = srcRange; + c->opts.dst_range = dstRange; if (need_reinit) ff_sws_init_range_convert(c); @@ -1107,27 +1107,27 @@ int sws_setColorspaceDetails(SwsContext *sws, const int inv_table[4], if (!need_reinit) return 0; - if ((isYUV(c->dstFormat) || isGray(c->dstFormat)) && (isYUV(c->srcFormat) || isGray(c->srcFormat))) { + if ((isYUV(c->opts.dst_format) || isGray(c->opts.dst_format)) && (isYUV(c->opts.src_format) || isGray(c->opts.src_format))) { if (!c->cascaded_context[0] && memcmp(c->dstColorspaceTable, c->srcColorspaceTable, sizeof(int) * 4) && - c->srcW && c->srcH && c->dstW && c->dstH) { + c->opts.src_w && c->opts.src_h && c->opts.dst_w && c->opts.dst_h) { enum AVPixelFormat tmp_format; int tmp_width, tmp_height; - int srcW = c->srcW; - int srcH = c->srcH; - int dstW = c->dstW; - int dstH = c->dstH; + int srcW = c->opts.src_w; + int srcH = c->opts.src_h; + int dstW = c->opts.dst_w; + int dstH = c->opts.dst_h; int ret; av_log(c, AV_LOG_VERBOSE, "YUV color matrix differs for YUV->YUV, using intermediate RGB to convert\n"); - if (isNBPS(c->dstFormat) || is16BPS(c->dstFormat)) { - if (isALPHA(c->srcFormat) && isALPHA(c->dstFormat)) { + if (isNBPS(c->opts.dst_format) || is16BPS(c->opts.dst_format)) { + if (isALPHA(c->opts.src_format) && isALPHA(c->opts.dst_format)) { tmp_format = AV_PIX_FMT_BGRA64; } else { tmp_format = AV_PIX_FMT_BGR48; } } else { - if (isALPHA(c->srcFormat) && isALPHA(c->dstFormat)) { + if (isALPHA(c->opts.src_format) && isALPHA(c->opts.dst_format)) { tmp_format = AV_PIX_FMT_BGRA; } else { tmp_format = AV_PIX_FMT_BGR24; @@ -1147,13 +1147,14 @@ int sws_setColorspaceDetails(SwsContext *sws, const int inv_table[4], if (ret < 0) return ret; - c->cascaded_context[0] = alloc_set_opts(srcW, srcH, c->srcFormat, + c->cascaded_context[0] = alloc_set_opts(srcW, srcH, c->opts.src_format, tmp_width, tmp_height, tmp_format, - c->flags, c->param); + c->opts.flags, + c->opts.scaler_params); if (!c->cascaded_context[0]) return -1; - sws_internal(c->cascaded_context[0])->alphablend = c->alphablend; + sws_internal(c->cascaded_context[0])->opts.alpha_blend = c->opts.alpha_blend; ret = sws_init_context(c->cascaded_context[0], NULL , NULL); if (ret < 0) return ret; @@ -1163,12 +1164,13 @@ int sws_setColorspaceDetails(SwsContext *sws, const int inv_table[4], brightness, contrast, saturation); c->cascaded_context[1] = alloc_set_opts(tmp_width, tmp_height, tmp_format, - dstW, dstH, c->dstFormat, - c->flags, c->param); + dstW, dstH, c->opts.dst_format, + c->opts.flags, + c->opts.scaler_params); if (!c->cascaded_context[1]) return -1; - sws_internal(c->cascaded_context[1])->srcRange = srcRange; - sws_internal(c->cascaded_context[1])->dstRange = dstRange; + sws_internal(c->cascaded_context[1])->opts.src_range = srcRange; + sws_internal(c->cascaded_context[1])->opts.dst_range = dstRange; ret = sws_init_context(c->cascaded_context[1], NULL , NULL); if (ret < 0) return ret; @@ -1183,7 +1185,7 @@ int sws_setColorspaceDetails(SwsContext *sws, const int inv_table[4], return 0; } - if (!isYUV(c->dstFormat) && !isGray(c->dstFormat)) { + if (!isYUV(c->opts.dst_format) && !isGray(c->opts.dst_format)) { ff_yuv2rgb_c_init_tables(c, inv_table, srcRange, brightness, contrast, saturation); // FIXME factorize @@ -1215,8 +1217,8 @@ int sws_getColorspaceDetails(SwsContext *sws, int **inv_table, *inv_table = c->srcColorspaceTable; *table = c->dstColorspaceTable; - *srcRange = range_override_needed(c->srcFormat) ? 1 : c->srcRange; - *dstRange = range_override_needed(c->dstFormat) ? 1 : c->dstRange; + *srcRange = range_override_needed(c->opts.src_format) ? 1 : c->opts.src_range; + *dstRange = range_override_needed(c->opts.dst_format) ? 1 : c->opts.dst_range; *brightness = c->brightness; *contrast = c->contrast; *saturation = c->saturation; @@ -1229,7 +1231,7 @@ SwsContext *sws_alloc_context(void) SwsInternal *c = av_mallocz(sizeof(SwsInternal)); if (c) { - c->av_class = &ff_sws_context_class; + c->opts.av_class = &ff_sws_context_class; av_opt_set_defaults(c); atomic_init(&c->stride_unaligned_warned, 0); atomic_init(&c->data_unaligned_warned, 0); @@ -1321,10 +1323,10 @@ static av_cold int sws_init_single_context(SwsContext *sws, SwsFilter *srcFilter int unscaled; SwsInternal *c = sws_internal(sws); SwsFilter dummyFilter = { NULL, NULL, NULL, NULL }; - int srcW = c->srcW; - int srcH = c->srcH; - int dstW = c->dstW; - int dstH = c->dstH; + int srcW = c->opts.src_w; + int srcH = c->opts.src_h; + int dstW = c->opts.dst_w; + int dstH = c->opts.dst_h; int dst_stride = FFALIGN(dstW * sizeof(int16_t) + 66, 16); int flags, cpu_flags; enum AVPixelFormat srcFormat, dstFormat; @@ -1335,25 +1337,25 @@ static av_cold int sws_init_single_context(SwsContext *sws, SwsFilter *srcFilter static const float float_mult = 1.0f / 255.0f; cpu_flags = av_get_cpu_flags(); - flags = c->flags; + flags = c->opts.flags; emms_c(); unscaled = (srcW == dstW && srcH == dstH); if (!c->contrast && !c->saturation && !c->dstFormatBpp) - sws_setColorspaceDetails(sws, ff_yuv2rgb_coeffs[SWS_CS_DEFAULT], c->srcRange, + sws_setColorspaceDetails(sws, ff_yuv2rgb_coeffs[SWS_CS_DEFAULT], c->opts.src_range, ff_yuv2rgb_coeffs[SWS_CS_DEFAULT], - c->dstRange, 0, 1 << 16, 1 << 16); + c->opts.dst_range, 0, 1 << 16, 1 << 16); handle_formats(c); - srcFormat = c->srcFormat; - dstFormat = c->dstFormat; + srcFormat = c->opts.src_format; + dstFormat = c->opts.dst_format; desc_src = av_pix_fmt_desc_get(srcFormat); desc_dst = av_pix_fmt_desc_get(dstFormat); // If the source has no alpha then disable alpha blendaway if (c->src0Alpha) - c->alphablend = SWS_ALPHA_BLEND_NONE; + c->opts.alpha_blend = SWS_ALPHA_BLEND_NONE; if (!(unscaled && sws_isSupportedEndiannessConversion(srcFormat) && av_pix_fmt_swap_endianness(srcFormat) == dstFormat)) { @@ -1390,7 +1392,7 @@ static av_cold int sws_init_single_context(SwsContext *sws, SwsFilter *srcFilter flags |= SWS_BICUBIC; else flags |= SWS_BICUBIC; - c->flags = flags; + c->opts.flags = flags; } else if (i & (i - 1)) { av_log(c, AV_LOG_ERROR, "Exactly one scaler algorithm must be chosen, got %X\n", i); @@ -1407,7 +1409,7 @@ static av_cold int sws_init_single_context(SwsContext *sws, SwsFilter *srcFilter if (flags & SWS_FAST_BILINEAR) { if (srcW < 8 || dstW < 8) { flags ^= SWS_FAST_BILINEAR | SWS_BILINEAR; - c->flags = flags; + c->opts.flags = flags; } } @@ -1440,46 +1442,46 @@ static av_cold int sws_init_single_context(SwsContext *sws, SwsFilter *srcFilter if (dstW&1) { av_log(c, AV_LOG_DEBUG, "Forcing full internal H chroma due to odd output size\n"); flags |= SWS_FULL_CHR_H_INT; - c->flags = flags; + c->opts.flags = flags; } if ( c->chrSrcHSubSample == 0 && c->chrSrcVSubSample == 0 - && c->dither != SWS_DITHER_BAYER //SWS_FULL_CHR_H_INT is currently not supported with SWS_DITHER_BAYER - && !(c->flags & SWS_FAST_BILINEAR) + && c->opts.dither != SWS_DITHER_BAYER //SWS_FULL_CHR_H_INT is currently not supported with SWS_DITHER_BAYER + && !(c->opts.flags & SWS_FAST_BILINEAR) ) { av_log(c, AV_LOG_DEBUG, "Forcing full internal H chroma due to input having non subsampled chroma\n"); flags |= SWS_FULL_CHR_H_INT; - c->flags = flags; + c->opts.flags = flags; } } - if (c->dither == SWS_DITHER_AUTO) { + if (c->opts.dither == SWS_DITHER_AUTO) { if (flags & SWS_ERROR_DIFFUSION) - c->dither = SWS_DITHER_ED; + c->opts.dither = SWS_DITHER_ED; } if(dstFormat == AV_PIX_FMT_BGR4_BYTE || dstFormat == AV_PIX_FMT_RGB4_BYTE || dstFormat == AV_PIX_FMT_BGR8 || dstFormat == AV_PIX_FMT_RGB8) { - if (c->dither == SWS_DITHER_AUTO) - c->dither = (flags & SWS_FULL_CHR_H_INT) ? SWS_DITHER_ED : SWS_DITHER_BAYER; + if (c->opts.dither == SWS_DITHER_AUTO) + c->opts.dither = (flags & SWS_FULL_CHR_H_INT) ? SWS_DITHER_ED : SWS_DITHER_BAYER; if (!(flags & SWS_FULL_CHR_H_INT)) { - if (c->dither == SWS_DITHER_ED || c->dither == SWS_DITHER_A_DITHER || c->dither == SWS_DITHER_X_DITHER || c->dither == SWS_DITHER_NONE) { + if (c->opts.dither == SWS_DITHER_ED || c->opts.dither == SWS_DITHER_A_DITHER || c->opts.dither == SWS_DITHER_X_DITHER || c->opts.dither == SWS_DITHER_NONE) { av_log(c, AV_LOG_DEBUG, "Desired dithering only supported in full chroma interpolation for destination format '%s'\n", av_get_pix_fmt_name(dstFormat)); flags |= SWS_FULL_CHR_H_INT; - c->flags = flags; + c->opts.flags = flags; } } if (flags & SWS_FULL_CHR_H_INT) { - if (c->dither == SWS_DITHER_BAYER) { + if (c->opts.dither == SWS_DITHER_BAYER) { av_log(c, AV_LOG_DEBUG, "Ordered dither is not supported in full chroma interpolation for destination format '%s'\n", av_get_pix_fmt_name(dstFormat)); - c->dither = SWS_DITHER_ED; + c->opts.dither = SWS_DITHER_ED; } } } @@ -1489,7 +1491,7 @@ static av_cold int sws_init_single_context(SwsContext *sws, SwsFilter *srcFilter "%s output is not supported with half chroma resolution, switching to full\n", av_get_pix_fmt_name(dstFormat)); flags |= SWS_FULL_CHR_H_INT; - c->flags = flags; + c->opts.flags = flags; } } @@ -1523,7 +1525,7 @@ static av_cold int sws_init_single_context(SwsContext *sws, SwsFilter *srcFilter "full chroma interpolation for destination format '%s' not yet implemented\n", av_get_pix_fmt_name(dstFormat)); flags &= ~SWS_FULL_CHR_H_INT; - c->flags = flags; + c->opts.flags = flags; } if (isAnyRGB(dstFormat) && !(flags & SWS_FULL_CHR_H_INT)) c->chrDstHSubSample = 1; @@ -1585,7 +1587,7 @@ static av_cold int sws_init_single_context(SwsContext *sws, SwsFilter *srcFilter av_log(c, AV_LOG_INFO, "output width is not a multiple of 32 -> no MMXEXT scaler\n"); } - if (usesHFilter || isNBPS(c->srcFormat) || is16BPS(c->srcFormat) || isAnyRGB(c->srcFormat)) + if (usesHFilter || isNBPS(c->opts.src_format) || is16BPS(c->opts.src_format) || isAnyRGB(c->opts.src_format)) c->canMMXEXTBeUsed = 0; } else c->canMMXEXTBeUsed = 0; @@ -1617,7 +1619,7 @@ static av_cold int sws_init_single_context(SwsContext *sws, SwsFilter *srcFilter tmpFmt = AV_PIX_FMT_RGBA64LE; - if (!unscaled && c->gamma_flag && (srcFormat != tmpFmt || dstFormat != tmpFmt)) { + if (!unscaled && c->opts.gamma_flag && (srcFormat != tmpFmt || dstFormat != tmpFmt)) { SwsInternal *c2; c->cascaded_context[0] = NULL; @@ -1628,14 +1630,16 @@ static av_cold int sws_init_single_context(SwsContext *sws, SwsFilter *srcFilter c->cascaded_context[0] = sws_getContext(srcW, srcH, srcFormat, srcW, srcH, tmpFmt, - flags, NULL, NULL, c->param); + flags, NULL, NULL, + c->opts.scaler_params); if (!c->cascaded_context[0]) { return AVERROR(ENOMEM); } c->cascaded_context[1] = sws_getContext(srcW, srcH, tmpFmt, dstW, dstH, tmpFmt, - flags, srcFilter, dstFilter, c->param); + flags, srcFilter, dstFilter, + c->opts.scaler_params); if (!c->cascaded_context[1]) return AVERROR(ENOMEM); @@ -1665,8 +1669,9 @@ static av_cold int sws_init_single_context(SwsContext *sws, SwsFilter *srcFilter return ret; c->cascaded_context[2] = sws_getContext(dstW, dstH, tmpFmt, - dstW, dstH, dstFormat, - flags, NULL, NULL, c->param); + dstW, dstH, dstFormat, + flags, NULL, NULL, + c->opts.scaler_params); if (!c->cascaded_context[2]) return AVERROR(ENOMEM); } @@ -1686,13 +1691,15 @@ static av_cold int sws_init_single_context(SwsContext *sws, SwsFilter *srcFilter c->cascaded_context[0] = sws_getContext(srcW, srcH, srcFormat, srcW, srcH, tmpFormat, - flags, srcFilter, NULL, c->param); + flags, srcFilter, NULL, + c->opts.scaler_params); if (!c->cascaded_context[0]) return AVERROR(ENOMEM); c->cascaded_context[1] = sws_getContext(srcW, srcH, tmpFormat, dstW, dstH, dstFormat, - flags, NULL, dstFilter, c->param); + flags, NULL, dstFilter, + c->opts.scaler_params); if (!c->cascaded_context[1]) return AVERROR(ENOMEM); return 0; @@ -1715,11 +1722,11 @@ static av_cold int sws_init_single_context(SwsContext *sws, SwsFilter *srcFilter if (CONFIG_SWSCALE_ALPHA && isALPHA(srcFormat) && !isALPHA(dstFormat)) { enum AVPixelFormat tmpFormat = alphaless_fmt(srcFormat); - if (tmpFormat != AV_PIX_FMT_NONE && c->alphablend != SWS_ALPHA_BLEND_NONE) { + if (tmpFormat != AV_PIX_FMT_NONE && c->opts.alpha_blend != SWS_ALPHA_BLEND_NONE) { if (!unscaled || dstFormat != tmpFormat || usesHFilter || usesVFilter || - c->srcRange != c->dstRange + c->opts.src_range != c->opts.dst_range ) { c->cascaded_mainindex = 1; ret = av_image_alloc(c->cascaded_tmp[0], c->cascaded_tmpStride[0], @@ -1729,22 +1736,22 @@ static av_cold int sws_init_single_context(SwsContext *sws, SwsFilter *srcFilter c->cascaded_context[0] = alloc_set_opts(srcW, srcH, srcFormat, srcW, srcH, tmpFormat, - flags, c->param); + flags, c->opts.scaler_params); if (!c->cascaded_context[0]) return AVERROR(EINVAL); - sws_internal(c->cascaded_context[0])->alphablend = c->alphablend; + sws_internal(c->cascaded_context[0])->opts.alpha_blend = c->opts.alpha_blend; ret = sws_init_context(c->cascaded_context[0], NULL , NULL); if (ret < 0) return ret; c->cascaded_context[1] = alloc_set_opts(srcW, srcH, tmpFormat, dstW, dstH, dstFormat, - flags, c->param); + flags, c->opts.scaler_params); if (!c->cascaded_context[1]) return AVERROR(EINVAL); - sws_internal(c->cascaded_context[1])->srcRange = c->srcRange; - sws_internal(c->cascaded_context[1])->dstRange = c->dstRange; + sws_internal(c->cascaded_context[1])->opts.src_range = c->opts.src_range; + sws_internal(c->cascaded_context[1])->opts.dst_range = c->opts.dst_range; ret = sws_init_context(c->cascaded_context[1], srcFilter , dstFilter); if (ret < 0) return ret; @@ -1756,9 +1763,9 @@ static av_cold int sws_init_single_context(SwsContext *sws, SwsFilter *srcFilter /* alpha blend special case, note this has been split via cascaded contexts if its scaled */ if (unscaled && !usesHFilter && !usesVFilter && - c->alphablend != SWS_ALPHA_BLEND_NONE && + c->opts.alpha_blend != SWS_ALPHA_BLEND_NONE && isALPHA(srcFormat) && - (c->srcRange == c->dstRange || isAnyRGB(dstFormat)) && + (c->opts.src_range == c->opts.dst_range || isAnyRGB(dstFormat)) && alphaless_fmt(srcFormat) == dstFormat ) { c->convert_unscaled = ff_sws_alphablendaway; @@ -1772,7 +1779,7 @@ static av_cold int sws_init_single_context(SwsContext *sws, SwsFilter *srcFilter /* unscaled special cases */ if (unscaled && !usesHFilter && !usesVFilter && - (c->srcRange == c->dstRange || isAnyRGB(dstFormat) || + (c->opts.src_range == c->opts.dst_range || isAnyRGB(dstFormat) || isFloat(srcFormat) || isFloat(dstFormat) || isBayer(srcFormat))){ ff_get_unscaled_swscale(c); @@ -1868,7 +1875,7 @@ static av_cold int sws_init_single_context(SwsContext *sws, SwsFilter *srcFilter srcW, dstW, filterAlign, 1 << 14, (flags & SWS_BICUBLIN) ? (flags | SWS_BICUBIC) : flags, cpu_flags, srcFilter->lumH, dstFilter->lumH, - c->param, + c->opts.scaler_params, get_local_pos(c, 0, 0, 0), get_local_pos(c, 0, 0, 0))) < 0) goto fail; @@ -1879,9 +1886,9 @@ static av_cold int sws_init_single_context(SwsContext *sws, SwsFilter *srcFilter c->chrSrcW, c->chrDstW, filterAlign, 1 << 14, (flags & SWS_BICUBLIN) ? (flags | SWS_BILINEAR) : flags, cpu_flags, srcFilter->chrH, dstFilter->chrH, - c->param, - get_local_pos(c, c->chrSrcHSubSample, c->src_h_chr_pos, 0), - get_local_pos(c, c->chrDstHSubSample, c->dst_h_chr_pos, 0))) < 0) + c->opts.scaler_params, + get_local_pos(c, c->chrSrcHSubSample, c->opts.src_h_chr_pos, 0), + get_local_pos(c, c->chrDstHSubSample, c->opts.dst_h_chr_pos, 0))) < 0) goto fail; if (ff_shuffle_filter_coefficients(c, c->hChrFilterPos, c->hChrFilterSize, c->hChrFilter, c->chrDstW) < 0) goto nomem; @@ -1898,7 +1905,7 @@ static av_cold int sws_init_single_context(SwsContext *sws, SwsFilter *srcFilter c->lumYInc, srcH, dstH, filterAlign, (1 << 12), (flags & SWS_BICUBLIN) ? (flags | SWS_BICUBIC) : flags, cpu_flags, srcFilter->lumV, dstFilter->lumV, - c->param, + c->opts.scaler_params, get_local_pos(c, 0, 0, 1), get_local_pos(c, 0, 0, 1))) < 0) goto fail; @@ -1907,18 +1914,18 @@ static av_cold int sws_init_single_context(SwsContext *sws, SwsFilter *srcFilter filterAlign, (1 << 12), (flags & SWS_BICUBLIN) ? (flags | SWS_BILINEAR) : flags, cpu_flags, srcFilter->chrV, dstFilter->chrV, - c->param, - get_local_pos(c, c->chrSrcVSubSample, c->src_v_chr_pos, 1), - get_local_pos(c, c->chrDstVSubSample, c->dst_v_chr_pos, 1))) < 0) + c->opts.scaler_params, + get_local_pos(c, c->chrSrcVSubSample, c->opts.src_v_chr_pos, 1), + get_local_pos(c, c->chrDstVSubSample, c->opts.dst_v_chr_pos, 1))) < 0) goto fail; #if HAVE_ALTIVEC - if (!FF_ALLOC_TYPED_ARRAY(c->vYCoeffsBank, c->vLumFilterSize * c->dstH) || + if (!FF_ALLOC_TYPED_ARRAY(c->vYCoeffsBank, c->vLumFilterSize * c->opts.dst_h) || !FF_ALLOC_TYPED_ARRAY(c->vCCoeffsBank, c->vChrFilterSize * c->chrDstH)) goto nomem; - for (i = 0; i < c->vLumFilterSize * c->dstH; i++) { + for (i = 0; i < c->vLumFilterSize * c->opts.dst_h; i++) { int j; short *p = (short *)&c->vYCoeffsBank[i]; for (j = 0; j < 8; j++) @@ -1935,10 +1942,10 @@ static av_cold int sws_init_single_context(SwsContext *sws, SwsFilter *srcFilter } for (i = 0; i < 4; i++) - if (!FF_ALLOCZ_TYPED_ARRAY(c->dither_error[i], c->dstW + 3)) + if (!FF_ALLOCZ_TYPED_ARRAY(c->dither_error[i], c->opts.dst_w + 3)) goto nomem; - c->needAlpha = (CONFIG_SWSCALE_ALPHA && isALPHA(c->srcFormat) && isALPHA(c->dstFormat)) ? 1 : 0; + c->needAlpha = (CONFIG_SWSCALE_ALPHA && isALPHA(c->opts.src_format) && isALPHA(c->opts.dst_format)) ? 1 : 0; // 64 / c->scalingBpp is the same as 16 / sizeof(scaling_intermediate) c->uv_off = (dst_stride>>1) + 64 / (c->dstBpc &~ 7); @@ -1980,7 +1987,7 @@ static av_cold int sws_init_single_context(SwsContext *sws, SwsFilter *srcFilter av_log(c, AV_LOG_VERBOSE, "%dx%d -> %dx%d\n", srcW, srcH, dstW, dstH); av_log(c, AV_LOG_DEBUG, "lum srcW=%d srcH=%d dstW=%d dstH=%d xInc=%d yInc=%d\n", - c->srcW, c->srcH, c->dstW, c->dstH, c->lumXInc, c->lumYInc); + c->opts.src_w, c->opts.src_h, c->opts.dst_w, c->opts.dst_h, c->lumXInc, c->lumYInc); av_log(c, AV_LOG_DEBUG, "chr srcW=%d srcH=%d dstW=%d dstH=%d xInc=%d yInc=%d\n", c->chrSrcW, c->chrSrcH, c->chrDstW, c->chrDstH, @@ -2011,13 +2018,15 @@ fail: // FIXME replace things by appropriate error codes c->cascaded_context[0] = sws_getContext(srcW, srcH, srcFormat, tmpW, tmpH, tmpFormat, - flags, srcFilter, NULL, c->param); + flags, srcFilter, NULL, + c->opts.scaler_params); if (!c->cascaded_context[0]) return AVERROR(ENOMEM); c->cascaded_context[1] = sws_getContext(tmpW, tmpH, tmpFormat, dstW, dstH, dstFormat, - flags, NULL, dstFilter, c->param); + flags, NULL, dstFilter, + c->opts.scaler_params); if (!c->cascaded_context[1]) return AVERROR(ENOMEM); return 0; @@ -2032,21 +2041,21 @@ static int context_init_threaded(SwsContext *sws, int ret; ret = avpriv_slicethread_create(&c->slicethread, (void*) sws, - ff_sws_slice_worker, NULL, c->nb_threads); + ff_sws_slice_worker, NULL, c->opts.threads); if (ret == AVERROR(ENOSYS)) { - c->nb_threads = 1; + c->opts.threads = 1; return 0; } else if (ret < 0) return ret; - c->nb_threads = ret; + c->opts.threads = ret; - c->slice_ctx = av_calloc(c->nb_threads, sizeof(*c->slice_ctx)); - c->slice_err = av_calloc(c->nb_threads, sizeof(*c->slice_err)); + c->slice_ctx = av_calloc(c->opts.threads, sizeof(*c->slice_ctx)); + c->slice_err = av_calloc(c->opts.threads, sizeof(*c->slice_err)); if (!c->slice_ctx || !c->slice_err) return AVERROR(ENOMEM); - for (int i = 0; i < c->nb_threads; i++) { + for (int i = 0; i < c->opts.threads; i++) { SwsInternal *c2; c->slice_ctx[i] = sws_alloc_context(); if (!c->slice_ctx[i]) @@ -2060,13 +2069,13 @@ static int context_init_threaded(SwsContext *sws, if (ret < 0) return ret; - c2->nb_threads = 1; + c2->opts.threads = 1; ret = sws_init_single_context(c->slice_ctx[i], src_filter, dst_filter); if (ret < 0) return ret; - if (c2->dither == SWS_DITHER_ED) { + if (c2->opts.dither == SWS_DITHER_ED) { av_log(c, AV_LOG_VERBOSE, "Error-diffusion dither is in use, scaling will be single-threaded."); break; @@ -2092,17 +2101,17 @@ av_cold int sws_init_context(SwsContext *sws, SwsFilter *srcFilter, if (ff_thread_once(&rgb2rgb_once, ff_sws_rgb2rgb_init) != 0) return AVERROR_UNKNOWN; - src_format = c->srcFormat; - dst_format = c->dstFormat; - c->srcRange |= handle_jpeg(&c->srcFormat); - c->dstRange |= handle_jpeg(&c->dstFormat); + src_format = c->opts.src_format; + dst_format = c->opts.dst_format; + c->opts.src_range |= handle_jpeg(&c->opts.src_format); + c->opts.dst_range |= handle_jpeg(&c->opts.dst_format); - if (src_format != c->srcFormat || dst_format != c->dstFormat) + if (src_format != c->opts.src_format || dst_format != c->opts.dst_format) av_log(c, AV_LOG_WARNING, "deprecated pixel format used, make sure you did set range correctly\n"); - if (c->nb_threads != 1) { + if (c->opts.threads != 1) { ret = context_init_threaded(sws, srcFilter, dstFilter); - if (ret < 0 || c->nb_threads > 1) + if (ret < 0 || c->opts.threads > 1) return ret; // threading disabled in this build, init as single-threaded } @@ -2546,15 +2555,15 @@ SwsContext *sws_getCachedContext(SwsContext *sws, int srcW, param = default_param; if ((context = sws_internal(sws)) && - (context->srcW != srcW || - context->srcH != srcH || - context->srcFormat != srcFormat || - context->dstW != dstW || - context->dstH != dstH || - context->dstFormat != dstFormat || - context->flags != flags || - context->param[0] != param[0] || - context->param[1] != param[1])) { + (context->opts.src_w != srcW || + context->opts.src_h != srcH || + context->opts.src_format != srcFormat || + context->opts.dst_w != dstW || + context->opts.dst_h != dstH || + context->opts.dst_format != dstFormat || + context->opts.flags != flags || + context->opts.scaler_params[0] != param[0] || + context->opts.scaler_params[1] != param[1])) { av_opt_get_int(context, "src_h_chr_pos", 0, &src_h_chr_pos); av_opt_get_int(context, "src_v_chr_pos", 0, &src_v_chr_pos); @@ -2568,15 +2577,15 @@ SwsContext *sws_getCachedContext(SwsContext *sws, int srcW, if (!(sws = sws_alloc_context())) return NULL; context = sws_internal(sws); - context->srcW = srcW; - context->srcH = srcH; - context->srcFormat = srcFormat; - context->dstW = dstW; - context->dstH = dstH; - context->dstFormat = dstFormat; - context->flags = flags; - context->param[0] = param[0]; - context->param[1] = param[1]; + context->opts.src_w = srcW; + context->opts.src_h = srcH; + context->opts.src_format = srcFormat; + context->opts.dst_w = dstW; + context->opts.dst_h = dstH; + context->opts.dst_format = dstFormat; + context->opts.flags = flags; + context->opts.scaler_params[0] = param[0]; + context->opts.scaler_params[1] = param[1]; av_opt_set_int(context, "src_h_chr_pos", src_h_chr_pos, 0); av_opt_set_int(context, "src_v_chr_pos", src_v_chr_pos, 0); diff --git a/libswscale/vscale.c b/libswscale/vscale.c index 9b700ec58e..e972bd70e2 100644 --- a/libswscale/vscale.c +++ b/libswscale/vscale.c @@ -93,7 +93,7 @@ static int chr_planar_vscale(SwsInternal *c, SwsFilterDescriptor *desc, int slic uint16_t *filter = inst->filter[0] + (inst->isMMX ? 0 : chrSliceY * inst->filter_size); if (c->yuv2nv12cX) { - inst->pfn.yuv2interleavedX(c->dstFormat, c->chrDither8, filter, inst->filter_size, (const int16_t**)src1, (const int16_t**)src2, dst1[0], dstW); + inst->pfn.yuv2interleavedX(c->opts.dst_format, c->chrDither8, filter, inst->filter_size, (const int16_t**)src1, (const int16_t**)src2, dst1[0], dstW); } else if (inst->filter_size == 1) { inst->pfn.yuv2planar1((const int16_t*)src1[0], dst1[0], dstW, c->chrDither8, 0); inst->pfn.yuv2planar1((const int16_t*)src2[0], dst2[0], dstW, c->chrDither8, 3); @@ -216,7 +216,7 @@ int ff_init_vscale(SwsInternal *c, SwsFilterDescriptor *desc, SwsSlice *src, Sws VScalerContext *lumCtx = NULL; VScalerContext *chrCtx = NULL; - if (isPlanarYUV(c->dstFormat) || (isGray(c->dstFormat) && !isALPHA(c->dstFormat))) { + if (isPlanarYUV(c->opts.dst_format) || (isGray(c->opts.dst_format) && !isALPHA(c->opts.dst_format))) { lumCtx = av_mallocz(sizeof(VScalerContext)); if (!lumCtx) return AVERROR(ENOMEM); @@ -228,7 +228,7 @@ int ff_init_vscale(SwsInternal *c, SwsFilterDescriptor *desc, SwsSlice *src, Sws desc[0].dst = dst; desc[0].alpha = c->needAlpha; - if (!isGray(c->dstFormat)) { + if (!isGray(c->opts.dst_format)) { chrCtx = av_mallocz(sizeof(VScalerContext)); if (!chrCtx) return AVERROR(ENOMEM); @@ -268,8 +268,8 @@ void ff_init_vscale_pfn(SwsInternal *c, VScalerContext *chrCtx = NULL; int idx = c->numDesc - (c->is_internal_gamma ? 2 : 1); //FIXME avoid hardcoding indexes - if (isPlanarYUV(c->dstFormat) || (isGray(c->dstFormat) && !isALPHA(c->dstFormat))) { - if (!isGray(c->dstFormat)) { + if (isPlanarYUV(c->opts.dst_format) || (isGray(c->opts.dst_format) && !isALPHA(c->opts.dst_format))) { + if (!isGray(c->opts.dst_format)) { chrCtx = c->desc[idx].instance; chrCtx->filter[0] = use_mmx ? (int16_t*)c->chrMmxFilter : c->vChrFilter; diff --git a/libswscale/x86/output.asm b/libswscale/x86/output.asm index 0f854e521d..dec1d27f9a 100644 --- a/libswscale/x86/output.asm +++ b/libswscale/x86/output.asm @@ -582,7 +582,7 @@ yuv2nv12cX_fn yuv2nv21 %if ARCH_X86_64 struc SwsInternal - .padding: resb 40292 ; offsetof(SwsInternal, yuv2rgb_y_offset) + .padding: resb 40316 ; offsetof(SwsInternal, yuv2rgb_y_offset) .yuv2rgb_y_offset: resd 1 .yuv2rgb_y_coeff: resd 1 .yuv2rgb_v2r_coeff: resd 1 diff --git a/libswscale/x86/swscale.c b/libswscale/x86/swscale.c index 40bfe4a2f6..3e1f9f371f 100644 --- a/libswscale/x86/swscale.c +++ b/libswscale/x86/swscale.c @@ -63,8 +63,8 @@ DECLARE_ASM_ALIGNED(8, const uint64_t, ff_w1111) = 0x0001000100010001ULL; void ff_updateMMXDitherTables(SwsInternal *c, int dstY) { - const int dstH= c->dstH; - const int flags= c->flags; + const int dstH= c->opts.dst_h; + const int flags= c->opts.flags; SwsPlane *lumPlane = &c->slice[c->numSlice-2].plane[0]; SwsPlane *chrUPlane = &c->slice[c->numSlice-2].plane[1]; @@ -85,7 +85,7 @@ void ff_updateMMXDitherTables(SwsInternal *c, int dstY) const int firstChrSrcY= vChrFilterPos[chrDstY]; //First line needed as input c->blueDither= ff_dither8[dstY&1]; - if (c->dstFormat == AV_PIX_FMT_RGB555 || c->dstFormat == AV_PIX_FMT_BGR555) + if (c->opts.dst_format == AV_PIX_FMT_RGB555 || c->opts.dst_format == AV_PIX_FMT_BGR555) c->greenDither= ff_dither8[dstY&1]; else c->greenDither= ff_dither4[dstY&1]; @@ -96,10 +96,10 @@ void ff_updateMMXDitherTables(SwsInternal *c, int dstY) const int16_t **alpSrcPtr = (CONFIG_SWSCALE_ALPHA && hasAlpha) ? (const int16_t **)(void*) alpPlane->line + firstLumSrcY - alpPlane->sliceY : NULL; int i; - if (firstLumSrcY < 0 || firstLumSrcY + vLumFilterSize > c->srcH) { + if (firstLumSrcY < 0 || firstLumSrcY + vLumFilterSize > c->opts.src_h) { const int16_t **tmpY = (const int16_t **) lumPlane->tmp; - int neg = -firstLumSrcY, i, end = FFMIN(c->srcH - firstLumSrcY, vLumFilterSize); + int neg = -firstLumSrcY, i, end = FFMIN(c->opts.src_h - firstLumSrcY, vLumFilterSize); for (i = 0; i < neg; i++) tmpY[i] = lumSrcPtr[neg]; for ( ; i < end; i++) @@ -453,7 +453,7 @@ INPUT_PLANAR_RGB_A_ALL_DECL(avx2); #define RANGE_CONVERT_FUNCS(opt) do { \ if (c->dstBpc <= 14) { \ - if (c->srcRange) { \ + if (c->opts.src_range) { \ c->lumConvertRange = ff_lumRangeFromJpeg_ ##opt; \ c->chrConvertRange = ff_chrRangeFromJpeg_ ##opt; \ } else { \ @@ -490,7 +490,7 @@ av_cold void ff_sws_init_swscale_x86(SwsInternal *c) if (INLINE_MMXEXT(cpu_flags)) sws_init_swscale_mmxext(c); #endif - if(c->use_mmx_vfilter && !(c->flags & SWS_ACCURATE_RND)) { + if(c->use_mmx_vfilter && !(c->opts.flags & SWS_ACCURATE_RND)) { #if HAVE_MMXEXT_EXTERNAL if (EXTERNAL_MMXEXT(cpu_flags)) c->yuv2planeX = yuv2yuvX_mmxext; @@ -526,7 +526,7 @@ av_cold void ff_sws_init_swscale_x86(SwsInternal *c) } else if (c->srcBpc == 12) { \ hscalefn = c->dstBpc <= 14 ? ff_hscale12to15_ ## filtersize ## _ ## opt2 : \ ff_hscale12to19_ ## filtersize ## _ ## opt1; \ - } else if (c->srcBpc == 14 || ((c->srcFormat==AV_PIX_FMT_PAL8||isAnyRGB(c->srcFormat)) && av_pix_fmt_desc_get(c->srcFormat)->comp[0].depth<16)) { \ + } else if (c->srcBpc == 14 || ((c->opts.src_format==AV_PIX_FMT_PAL8||isAnyRGB(c->opts.src_format)) && av_pix_fmt_desc_get(c->opts.src_format)->comp[0].depth<16)) { \ hscalefn = c->dstBpc <= 14 ? ff_hscale14to15_ ## filtersize ## _ ## opt2 : \ ff_hscale14to19_ ## filtersize ## _ ## opt1; \ } else { /* c->srcBpc == 16 */ \ @@ -538,15 +538,15 @@ av_cold void ff_sws_init_swscale_x86(SwsInternal *c) #define ASSIGN_VSCALEX_FUNC(vscalefn, opt, do_16_case, condition_8bit) \ switch(c->dstBpc){ \ case 16: do_16_case; break; \ - case 10: if (!isBE(c->dstFormat) && !isSemiPlanarYUV(c->dstFormat)) vscalefn = ff_yuv2planeX_10_ ## opt; break; \ - case 9: if (!isBE(c->dstFormat)) vscalefn = ff_yuv2planeX_9_ ## opt; break; \ + case 10: if (!isBE(c->opts.dst_format) && !isSemiPlanarYUV(c->opts.dst_format)) vscalefn = ff_yuv2planeX_10_ ## opt; break; \ + case 9: if (!isBE(c->opts.dst_format)) vscalefn = ff_yuv2planeX_9_ ## opt; break; \ case 8: if ((condition_8bit) && !c->use_mmx_vfilter) vscalefn = ff_yuv2planeX_8_ ## opt; break; \ } #define ASSIGN_VSCALE_FUNC(vscalefn, opt) \ switch(c->dstBpc){ \ - case 16: if (!isBE(c->dstFormat)) vscalefn = ff_yuv2plane1_16_ ## opt; break; \ - case 10: if (!isBE(c->dstFormat) && !isSemiPlanarYUV(c->dstFormat)) vscalefn = ff_yuv2plane1_10_ ## opt; break; \ - case 9: if (!isBE(c->dstFormat)) vscalefn = ff_yuv2plane1_9_ ## opt; break; \ + case 16: if (!isBE(c->opts.dst_format)) vscalefn = ff_yuv2plane1_16_ ## opt; break; \ + case 10: if (!isBE(c->opts.dst_format) && !isSemiPlanarYUV(c->opts.dst_format)) vscalefn = ff_yuv2plane1_10_ ## opt; break; \ + case 9: if (!isBE(c->opts.dst_format)) vscalefn = ff_yuv2plane1_9_ ## opt; break; \ case 8: vscalefn = ff_yuv2plane1_8_ ## opt; break; \ default: av_assert0(c->dstBpc>8); \ } @@ -569,10 +569,10 @@ switch(c->dstBpc){ \ ASSIGN_SSE_SCALE_FUNC(c->hcScale, c->hChrFilterSize, sse2, sse2); ASSIGN_VSCALEX_FUNC(c->yuv2planeX, sse2, , HAVE_ALIGNED_STACK || ARCH_X86_64); - if (!(c->flags & SWS_ACCURATE_RND)) + if (!(c->opts.flags & SWS_ACCURATE_RND)) ASSIGN_VSCALE_FUNC(c->yuv2plane1, sse2); - switch (c->srcFormat) { + switch (c->opts.src_format) { case AV_PIX_FMT_YA8: c->lumToYV12 = ff_yuyvToY_sse2; if (c->needAlpha) @@ -605,7 +605,7 @@ switch(c->dstBpc){ \ if (EXTERNAL_SSSE3(cpu_flags)) { ASSIGN_SSE_SCALE_FUNC(c->hyScale, c->hLumFilterSize, ssse3, ssse3); ASSIGN_SSE_SCALE_FUNC(c->hcScale, c->hChrFilterSize, ssse3, ssse3); - switch (c->srcFormat) { + switch (c->opts.src_format) { case_rgb(rgb24, RGB24, ssse3); case_rgb(bgr24, BGR24, ssse3); default: @@ -617,19 +617,19 @@ switch(c->dstBpc){ \ ASSIGN_SSE_SCALE_FUNC(c->hyScale, c->hLumFilterSize, sse4, ssse3); ASSIGN_SSE_SCALE_FUNC(c->hcScale, c->hChrFilterSize, sse4, ssse3); ASSIGN_VSCALEX_FUNC(c->yuv2planeX, sse4, - if (!isBE(c->dstFormat)) c->yuv2planeX = ff_yuv2planeX_16_sse4, + if (!isBE(c->opts.dst_format)) c->yuv2planeX = ff_yuv2planeX_16_sse4, HAVE_ALIGNED_STACK || ARCH_X86_64); - if (c->dstBpc == 16 && !isBE(c->dstFormat) && !(c->flags & SWS_ACCURATE_RND)) + if (c->dstBpc == 16 && !isBE(c->opts.dst_format) && !(c->opts.flags & SWS_ACCURATE_RND)) c->yuv2plane1 = ff_yuv2plane1_16_sse4; } if (EXTERNAL_AVX(cpu_flags)) { ASSIGN_VSCALEX_FUNC(c->yuv2planeX, avx, , HAVE_ALIGNED_STACK || ARCH_X86_64); - if (!(c->flags & SWS_ACCURATE_RND)) + if (!(c->opts.flags & SWS_ACCURATE_RND)) ASSIGN_VSCALE_FUNC(c->yuv2plane1, avx); - switch (c->srcFormat) { + switch (c->opts.src_format) { case AV_PIX_FMT_YUYV422: c->chrToYV12 = ff_yuyvToUV_avx; break; @@ -670,7 +670,7 @@ switch(c->dstBpc){ \ if (EXTERNAL_AVX2_FAST(cpu_flags)) { if (ARCH_X86_64) - switch (c->srcFormat) { + switch (c->opts.src_format) { case_rgb(rgb24, RGB24, avx2); case_rgb(bgr24, BGR24, avx2); case_rgb(bgra, BGRA, avx2); @@ -678,8 +678,8 @@ switch(c->dstBpc){ \ case_rgb(abgr, ABGR, avx2); case_rgb(argb, ARGB, avx2); } - if (!(c->flags & SWS_ACCURATE_RND)) // FIXME - switch (c->dstFormat) { + if (!(c->opts.flags & SWS_ACCURATE_RND)) // FIXME + switch (c->opts.dst_format) { case AV_PIX_FMT_NV12: case AV_PIX_FMT_NV24: c->yuv2nv12cX = ff_yuv2nv12cX_avx2; @@ -752,7 +752,7 @@ switch(c->dstBpc){ \ if (EXTERNAL_SSE2(cpu_flags)) { - switch (c->srcFormat) { + switch (c->opts.src_format) { INPUT_PLANER_RGB_A_FUNC_CASE_NOBREAK(AV_PIX_FMT_GBRAP, rgb, sse2); INPUT_PLANER_RGB_UV_FUNC_CASE( AV_PIX_FMT_GBRP, rgb, sse2); INPUT_PLANER_RGBXX_UV_FUNC_CASE( AV_PIX_FMT_GBRP9, rgb9, sse2); @@ -767,7 +767,7 @@ switch(c->dstBpc){ \ } if (EXTERNAL_SSE4(cpu_flags)) { - switch (c->srcFormat) { + switch (c->opts.src_format) { case AV_PIX_FMT_GBRAP: INPUT_PLANER_RGB_YUV_FUNC_CASE( AV_PIX_FMT_GBRP, rgb, sse4); INPUT_PLANER_RGBXX_YUV_FUNC_CASE( AV_PIX_FMT_GBRP9, rgb9, sse4); @@ -782,14 +782,14 @@ switch(c->dstBpc){ \ } if (EXTERNAL_AVX2_FAST(cpu_flags)) { - switch (c->srcFormat) { + switch (c->opts.src_format) { INPUT_PLANER_RGB_YUVA_ALL_CASES(avx2) default: break; } } - if(c->flags & SWS_FULL_CHR_H_INT) { + if(c->opts.flags & SWS_FULL_CHR_H_INT) { #define YUV2ANYX_FUNC_CASE(fmt, name, opt) \ case fmt: \ @@ -821,7 +821,7 @@ switch(c->dstBpc){ \ YUV2ANYX_FUNC_CASE(AV_PIX_FMT_GBRAPF32BE, gbrapf32be, opt) if (EXTERNAL_SSE2(cpu_flags)) { - switch (c->dstFormat) { + switch (c->opts.dst_format) { YUV2ANYX_GBRAP_CASES(sse2) default: break; @@ -829,7 +829,7 @@ switch(c->dstBpc){ \ } if (EXTERNAL_SSE4(cpu_flags)) { - switch (c->dstFormat) { + switch (c->opts.dst_format) { YUV2ANYX_GBRAP_CASES(sse4) default: break; @@ -837,7 +837,7 @@ switch(c->dstBpc){ \ } if (EXTERNAL_AVX2_FAST(cpu_flags)) { - switch (c->dstFormat) { + switch (c->opts.dst_format) { YUV2ANYX_GBRAP_CASES(avx2) default: break; diff --git a/libswscale/x86/swscale_template.c b/libswscale/x86/swscale_template.c index cffafccb24..e09310ab91 100644 --- a/libswscale/x86/swscale_template.c +++ b/libswscale/x86/swscale_template.c @@ -1384,15 +1384,15 @@ static void RENAME(yuv2yuyv422_1)(SwsInternal *c, const int16_t *buf0, } static av_cold void RENAME(sws_init_swscale)(SwsInternal *c) { - enum AVPixelFormat dstFormat = c->dstFormat; + enum AVPixelFormat dstFormat = c->opts.dst_format; c->use_mmx_vfilter= 0; if (!is16BPS(dstFormat) && !isNBPS(dstFormat) && !isSemiPlanarYUV(dstFormat) && dstFormat != AV_PIX_FMT_GRAYF32BE && dstFormat != AV_PIX_FMT_GRAYF32LE - && !(c->flags & SWS_BITEXACT)) { - if (c->flags & SWS_ACCURATE_RND) { - if (!(c->flags & SWS_FULL_CHR_H_INT)) { - switch (c->dstFormat) { + && !(c->opts.flags & SWS_BITEXACT)) { + if (c->opts.flags & SWS_ACCURATE_RND) { + if (!(c->opts.flags & SWS_FULL_CHR_H_INT)) { + switch (c->opts.dst_format) { case AV_PIX_FMT_RGB32: c->yuv2packedX = RENAME(yuv2rgb32_X_ar); break; #if HAVE_6REGS case AV_PIX_FMT_BGR24: c->yuv2packedX = RENAME(yuv2bgr24_X_ar); break; @@ -1405,8 +1405,8 @@ static av_cold void RENAME(sws_init_swscale)(SwsInternal *c) } } else { c->use_mmx_vfilter= 1; - if (!(c->flags & SWS_FULL_CHR_H_INT)) { - switch (c->dstFormat) { + if (!(c->opts.flags & SWS_FULL_CHR_H_INT)) { + switch (c->opts.dst_format) { case AV_PIX_FMT_RGB32: c->yuv2packedX = RENAME(yuv2rgb32_X); break; case AV_PIX_FMT_BGR32: c->yuv2packedX = RENAME(yuv2bgr32_X); break; #if HAVE_6REGS @@ -1419,8 +1419,8 @@ static av_cold void RENAME(sws_init_swscale)(SwsInternal *c) } } } - if (!(c->flags & SWS_FULL_CHR_H_INT)) { - switch (c->dstFormat) { + if (!(c->opts.flags & SWS_FULL_CHR_H_INT)) { + switch (c->opts.dst_format) { case AV_PIX_FMT_RGB32: c->yuv2packed1 = RENAME(yuv2rgb32_1); c->yuv2packed2 = RENAME(yuv2rgb32_2); @@ -1449,7 +1449,7 @@ static av_cold void RENAME(sws_init_swscale)(SwsInternal *c) if (c->srcBpc == 8 && c->dstBpc <= 14) { // Use the new MMX scaler if the MMXEXT one can't be used (it is faster than the x86 ASM one). - if (c->flags & SWS_FAST_BILINEAR && c->canMMXEXTBeUsed) { + if (c->opts.flags & SWS_FAST_BILINEAR && c->canMMXEXTBeUsed) { c->hyscale_fast = ff_hyscale_fast_mmxext; c->hcscale_fast = ff_hcscale_fast_mmxext; } else { diff --git a/libswscale/x86/yuv2rgb.c b/libswscale/x86/yuv2rgb.c index 93a6b9a6e2..a1463867a2 100644 --- a/libswscale/x86/yuv2rgb.c +++ b/libswscale/x86/yuv2rgb.c @@ -41,11 +41,11 @@ #if HAVE_X86ASM #define YUV2RGB_LOOP(depth) \ - h_size = (c->dstW + 7) & ~7; \ + h_size = (c->opts.dst_w + 7) & ~7; \ if (h_size * depth > FFABS(dstStride[0])) \ h_size -= 8; \ \ - vshift = c->srcFormat != AV_PIX_FMT_YUV422P; \ + vshift = c->opts.src_format != AV_PIX_FMT_YUV422P; \ \ for (y = 0; y < srcSliceH; y++) { \ uint8_t *image = dst[0] + (y + srcSliceY) * dstStride[0]; \ @@ -215,11 +215,11 @@ static inline int yuv420_gbrp_ssse3(SwsInternal *c, const uint8_t *const src[], { int y, h_size, vshift; - h_size = (c->dstW + 7) & ~7; + h_size = (c->opts.dst_w + 7) & ~7; if (h_size * 3 > FFABS(dstStride[0])) h_size -= 8; - vshift = c->srcFormat != AV_PIX_FMT_YUV422P; + vshift = c->opts.src_format != AV_PIX_FMT_YUV422P; for (y = 0; y < srcSliceH; y++) { uint8_t *dst_g = dst[0] + (y + srcSliceY) * dstStride[0]; @@ -244,9 +244,9 @@ av_cold SwsFunc ff_yuv2rgb_init_x86(SwsInternal *c) int cpu_flags = av_get_cpu_flags(); if (EXTERNAL_SSSE3(cpu_flags)) { - switch (c->dstFormat) { + switch (c->opts.dst_format) { case AV_PIX_FMT_RGB32: - if (c->srcFormat == AV_PIX_FMT_YUVA420P) { + if (c->opts.src_format == AV_PIX_FMT_YUVA420P) { #if CONFIG_SWSCALE_ALPHA return yuva420_rgb32_ssse3; #endif @@ -254,7 +254,7 @@ av_cold SwsFunc ff_yuv2rgb_init_x86(SwsInternal *c) } else return yuv420_rgb32_ssse3; case AV_PIX_FMT_BGR32: - if (c->srcFormat == AV_PIX_FMT_YUVA420P) { + if (c->opts.src_format == AV_PIX_FMT_YUVA420P) { #if CONFIG_SWSCALE_ALPHA return yuva420_bgr32_ssse3; #endif diff --git a/libswscale/yuv2rgb.c b/libswscale/yuv2rgb.c index f4fa1c0549..ff8e013da4 100644 --- a/libswscale/yuv2rgb.c +++ b/libswscale/yuv2rgb.c @@ -155,7 +155,7 @@ const int *sws_getCoefficients(int colorspace) const uint8_t av_unused *pv_1 = src[2] + (y >> !yuv422) * srcStride[2]; \ const uint8_t av_unused *pu_2, *pv_2; \ const uint8_t av_unused *pa_1, *pa_2; \ - unsigned int h_size = c->dstW >> 3; \ + unsigned int h_size = c->opts.dst_w >> 3; \ if (nb_dst_planes > 1) { \ dst1_1 = (dst_type *)(dst[1] + (yd) * dstStride[1]); \ dst1_2 = (dst_type *)(dst[1] + (yd + 1) * dstStride[1]); \ @@ -195,7 +195,7 @@ const int *sws_getCoefficients(int colorspace) dst2_2 += dst_delta >> ss; \ } \ } \ - if (c->dstW & (4 >> ss)) { \ + if (c->opts.dst_w & (4 >> ss)) { \ int av_unused Y, U, V; \ #define ENDYUV2RGBFUNC() \ @@ -485,9 +485,9 @@ YUV2RGBFUNC(yuv2rgb_c_1_ordered_dither, uint8_t, 0, 0, 1) dst_1 += 1; dst_2 += 1; } - if (c->dstW & 7) { + if (c->opts.dst_w & 7) { int av_unused Y, U, V; - int pixels_left = c->dstW & 7; + int pixels_left = c->opts.dst_w & 7; const uint8_t *d128 = ff_dither_8x8_220[yd & 7]; char out_1 = 0, out_2 = 0; g = c->table_gU[128 + YUVRGB_TABLE_HEADROOM] + c->table_gV[128 + YUVRGB_TABLE_HEADROOM]; @@ -575,10 +575,10 @@ SwsFunc ff_yuv2rgb_get_func_ptr(SwsInternal *c) av_log(c, AV_LOG_WARNING, "No accelerated colorspace conversion found from %s to %s.\n", - av_get_pix_fmt_name(c->srcFormat), av_get_pix_fmt_name(c->dstFormat)); + av_get_pix_fmt_name(c->opts.src_format), av_get_pix_fmt_name(c->opts.dst_format)); - if (c->srcFormat == AV_PIX_FMT_YUV422P) { - switch (c->dstFormat) { + if (c->opts.src_format == AV_PIX_FMT_YUV422P) { + switch (c->opts.dst_format) { case AV_PIX_FMT_BGR48BE: case AV_PIX_FMT_BGR48LE: return yuv422p_bgr48_c; @@ -587,11 +587,11 @@ SwsFunc ff_yuv2rgb_get_func_ptr(SwsInternal *c) return yuv422p_rgb48_c; case AV_PIX_FMT_ARGB: case AV_PIX_FMT_ABGR: - if (CONFIG_SWSCALE_ALPHA && isALPHA(c->srcFormat)) + if (CONFIG_SWSCALE_ALPHA && isALPHA(c->opts.src_format)) return yuva422p_argb_c; case AV_PIX_FMT_RGBA: case AV_PIX_FMT_BGRA: - return (CONFIG_SWSCALE_ALPHA && isALPHA(c->srcFormat)) ? yuva422p_rgba_c : yuv422p_rgb32_c; + return (CONFIG_SWSCALE_ALPHA && isALPHA(c->opts.src_format)) ? yuva422p_rgba_c : yuv422p_rgb32_c; case AV_PIX_FMT_RGB24: return yuv422p_rgb24_c; case AV_PIX_FMT_BGR24: @@ -620,7 +620,7 @@ SwsFunc ff_yuv2rgb_get_func_ptr(SwsInternal *c) return yuv422p_gbrp_c; } } else { - switch (c->dstFormat) { + switch (c->opts.dst_format) { case AV_PIX_FMT_BGR48BE: case AV_PIX_FMT_BGR48LE: return yuv2rgb_c_bgr48; @@ -629,11 +629,11 @@ SwsFunc ff_yuv2rgb_get_func_ptr(SwsInternal *c) return yuv2rgb_c_48; case AV_PIX_FMT_ARGB: case AV_PIX_FMT_ABGR: - if (CONFIG_SWSCALE_ALPHA && isALPHA(c->srcFormat)) + if (CONFIG_SWSCALE_ALPHA && isALPHA(c->opts.src_format)) return yuva2argb_c; case AV_PIX_FMT_RGBA: case AV_PIX_FMT_BGRA: - return (CONFIG_SWSCALE_ALPHA && isALPHA(c->srcFormat)) ? yuva2rgba_c : yuv2rgb_c_32; + return (CONFIG_SWSCALE_ALPHA && isALPHA(c->opts.src_format)) ? yuva2rgba_c : yuv2rgb_c_32; case AV_PIX_FMT_RGB24: return yuv2rgb_c_24_rgb; case AV_PIX_FMT_BGR24: @@ -706,29 +706,29 @@ av_cold int ff_yuv2rgb_c_init_tables(SwsInternal *c, const int inv_table[4], int fullRange, int brightness, int contrast, int saturation) { - const int isRgb = c->dstFormat == AV_PIX_FMT_RGB32 || - c->dstFormat == AV_PIX_FMT_RGB32_1 || - c->dstFormat == AV_PIX_FMT_BGR24 || - c->dstFormat == AV_PIX_FMT_RGB565BE || - c->dstFormat == AV_PIX_FMT_RGB565LE || - c->dstFormat == AV_PIX_FMT_RGB555BE || - c->dstFormat == AV_PIX_FMT_RGB555LE || - c->dstFormat == AV_PIX_FMT_RGB444BE || - c->dstFormat == AV_PIX_FMT_RGB444LE || - c->dstFormat == AV_PIX_FMT_X2RGB10BE || - c->dstFormat == AV_PIX_FMT_X2RGB10LE || - c->dstFormat == AV_PIX_FMT_RGB8 || - c->dstFormat == AV_PIX_FMT_RGB4 || - c->dstFormat == AV_PIX_FMT_RGB4_BYTE || - c->dstFormat == AV_PIX_FMT_MONOBLACK; - const int isNotNe = c->dstFormat == AV_PIX_FMT_NE(RGB565LE, RGB565BE) || - c->dstFormat == AV_PIX_FMT_NE(RGB555LE, RGB555BE) || - c->dstFormat == AV_PIX_FMT_NE(RGB444LE, RGB444BE) || - c->dstFormat == AV_PIX_FMT_NE(BGR565LE, BGR565BE) || - c->dstFormat == AV_PIX_FMT_NE(BGR555LE, BGR555BE) || - c->dstFormat == AV_PIX_FMT_NE(BGR444LE, BGR444BE) || - c->dstFormat == AV_PIX_FMT_NE(X2RGB10LE, X2RGB10BE) || - c->dstFormat == AV_PIX_FMT_NE(X2BGR10LE, X2BGR10BE); + const int isRgb = c->opts.dst_format == AV_PIX_FMT_RGB32 || + c->opts.dst_format == AV_PIX_FMT_RGB32_1 || + c->opts.dst_format == AV_PIX_FMT_BGR24 || + c->opts.dst_format == AV_PIX_FMT_RGB565BE || + c->opts.dst_format == AV_PIX_FMT_RGB565LE || + c->opts.dst_format == AV_PIX_FMT_RGB555BE || + c->opts.dst_format == AV_PIX_FMT_RGB555LE || + c->opts.dst_format == AV_PIX_FMT_RGB444BE || + c->opts.dst_format == AV_PIX_FMT_RGB444LE || + c->opts.dst_format == AV_PIX_FMT_X2RGB10BE || + c->opts.dst_format == AV_PIX_FMT_X2RGB10LE || + c->opts.dst_format == AV_PIX_FMT_RGB8 || + c->opts.dst_format == AV_PIX_FMT_RGB4 || + c->opts.dst_format == AV_PIX_FMT_RGB4_BYTE || + c->opts.dst_format == AV_PIX_FMT_MONOBLACK; + const int isNotNe = c->opts.dst_format == AV_PIX_FMT_NE(RGB565LE, RGB565BE) || + c->opts.dst_format == AV_PIX_FMT_NE(RGB555LE, RGB555BE) || + c->opts.dst_format == AV_PIX_FMT_NE(RGB444LE, RGB444BE) || + c->opts.dst_format == AV_PIX_FMT_NE(BGR565LE, BGR565BE) || + c->opts.dst_format == AV_PIX_FMT_NE(BGR555LE, BGR555BE) || + c->opts.dst_format == AV_PIX_FMT_NE(BGR444LE, BGR444BE) || + c->opts.dst_format == AV_PIX_FMT_NE(X2RGB10LE, X2RGB10BE) || + c->opts.dst_format == AV_PIX_FMT_NE(X2BGR10LE, X2BGR10BE); const int bpp = c->dstFormatBpp; uint8_t *y_table; uint16_t *y_table16; @@ -904,7 +904,7 @@ av_cold int ff_yuv2rgb_c_init_tables(SwsInternal *c, const int inv_table[4], rbase = isRgb ? 20 : 0; gbase = 10; bbase = isRgb ? 0 : 20; - needAlpha = CONFIG_SWSCALE_ALPHA && isALPHA(c->srcFormat); + needAlpha = CONFIG_SWSCALE_ALPHA && isALPHA(c->opts.src_format); if (!needAlpha) abase = 30; ALLOC_YUV_TABLE(table_plane_size * 3 * 4); @@ -928,12 +928,12 @@ av_cold int ff_yuv2rgb_c_init_tables(SwsInternal *c, const int inv_table[4], break; case 32: case 64: - base = (c->dstFormat == AV_PIX_FMT_RGB32_1 || - c->dstFormat == AV_PIX_FMT_BGR32_1) ? 8 : 0; + base = (c->opts.dst_format == AV_PIX_FMT_RGB32_1 || + c->opts.dst_format == AV_PIX_FMT_BGR32_1) ? 8 : 0; rbase = base + (isRgb ? 16 : 0); gbase = base + 8; bbase = base + (isRgb ? 0 : 16); - needAlpha = CONFIG_SWSCALE_ALPHA && isALPHA(c->srcFormat); + needAlpha = CONFIG_SWSCALE_ALPHA && isALPHA(c->opts.src_format); if (!needAlpha) abase = (base + 24) & 31; ALLOC_YUV_TABLE(table_plane_size * 3 * 4); @@ -953,7 +953,7 @@ av_cold int ff_yuv2rgb_c_init_tables(SwsInternal *c, const int inv_table[4], fill_gv_table(c->table_gV, 4, cgv); break; default: - if(!isPlanar(c->dstFormat) || bpp <= 24) + if(!isPlanar(c->opts.dst_format) || bpp <= 24) av_log(c, AV_LOG_ERROR, "%ibpp not supported by yuv2rgb\n", bpp); return AVERROR(EINVAL); } diff --git a/tests/checkasm/sw_gbrp.c b/tests/checkasm/sw_gbrp.c index 23ac1dfb56..b8ac7fdd1c 100644 --- a/tests/checkasm/sw_gbrp.c +++ b/tests/checkasm/sw_gbrp.c @@ -135,13 +135,13 @@ static void check_output_yuv2gbrp(void) fail(); c = sws_internal(sws); - c->flags |= SWS_FULL_CHR_H_INT; + c->opts.flags |= SWS_FULL_CHR_H_INT; for (fmi = 0; fmi < FF_ARRAY_ELEMS(planar_fmts); fmi++) { for (fsi = 0; fsi < FILTER_SIZES; fsi++) { for (isi = 0; isi < FF_ARRAY_ELEMS(input_sizes); isi++ ) { desc = av_pix_fmt_desc_get(planar_fmts[fmi]); - c->dstFormat = planar_fmts[fmi]; + c->opts.dst_format = planar_fmts[fmi]; dstW = input_sizes[isi]; luma_filter_size = filter_sizes[fsi]; @@ -229,8 +229,8 @@ static void check_input_planar_rgb_to_y(void) for (fmi = 0; fmi < FF_ARRAY_ELEMS(planar_fmts); fmi++) { for (isi = 0; isi < FF_ARRAY_ELEMS(input_sizes); isi++ ) { desc = av_pix_fmt_desc_get(planar_fmts[fmi]); - c->srcFormat = planar_fmts[fmi]; - c->dstFormat = AV_PIX_FMT_YUVA444P16; + c->opts.src_format = planar_fmts[fmi]; + c->opts.dst_format = AV_PIX_FMT_YUVA444P16; byte_size = 2; dstW = input_sizes[isi]; @@ -300,8 +300,8 @@ static void check_input_planar_rgb_to_uv(void) for (fmi = 0; fmi < FF_ARRAY_ELEMS(planar_fmts); fmi++) { for (isi = 0; isi < FF_ARRAY_ELEMS(input_sizes); isi++ ) { desc = av_pix_fmt_desc_get(planar_fmts[fmi]); - c->srcFormat = planar_fmts[fmi]; - c->dstFormat = AV_PIX_FMT_YUVA444P16; + c->opts.src_format = planar_fmts[fmi]; + c->opts.dst_format = AV_PIX_FMT_YUVA444P16; byte_size = 2; dstW = input_sizes[isi]; @@ -373,8 +373,8 @@ static void check_input_planar_rgb_to_a(void) if (!(desc->flags & AV_PIX_FMT_FLAG_ALPHA)) continue; - c->srcFormat = planar_fmts[fmi]; - c->dstFormat = AV_PIX_FMT_YUVA444P16; + c->opts.src_format = planar_fmts[fmi]; + c->opts.dst_format = AV_PIX_FMT_YUVA444P16; byte_size = 2; dstW = input_sizes[isi]; diff --git a/tests/checkasm/sw_range_convert.c b/tests/checkasm/sw_range_convert.c index f8167a411e..f17050f524 100644 --- a/tests/checkasm/sw_range_convert.c +++ b/tests/checkasm/sw_range_convert.c @@ -73,16 +73,16 @@ static void check_lumConvertRange(int from) fail(); c = sws_internal(sws); - c->srcRange = from; - c->dstRange = !from; + c->opts.src_range = from; + c->opts.dst_range = !from; for (int pfi = 0; pfi < FF_ARRAY_ELEMS(pixel_formats); pfi++) { enum AVPixelFormat pix_fmt = pixel_formats[pfi]; const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(pix_fmt); int bit_depth = desc->comp[0].depth; int sample_size = bit_depth == 16 ? sizeof(int32_t) : sizeof(int16_t); - c->srcFormat = pix_fmt; - c->dstFormat = pix_fmt; + c->opts.src_format = pix_fmt; + c->opts.dst_format = pix_fmt; c->dstBpc = bit_depth; ff_sws_init_scale(c); for (int dstWi = 0; dstWi < FF_ARRAY_ELEMS(input_sizes); dstWi++) { @@ -123,16 +123,16 @@ static void check_chrConvertRange(int from) fail(); c = sws_internal(sws); - c->srcRange = from; - c->dstRange = !from; + c->opts.src_range = from; + c->opts.dst_range = !from; for (int pfi = 0; pfi < FF_ARRAY_ELEMS(pixel_formats); pfi++) { enum AVPixelFormat pix_fmt = pixel_formats[pfi]; const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(pix_fmt); int bit_depth = desc->comp[0].depth; int sample_size = bit_depth == 16 ? sizeof(int32_t) : sizeof(int16_t); - c->srcFormat = pix_fmt; - c->dstFormat = pix_fmt; + c->opts.src_format = pix_fmt; + c->opts.dst_format = pix_fmt; c->dstBpc = bit_depth; ff_sws_init_scale(c); for (int dstWi = 0; dstWi < FF_ARRAY_ELEMS(input_sizes); dstWi++) { diff --git a/tests/checkasm/sw_rgb.c b/tests/checkasm/sw_rgb.c index 7af82f0fc7..65f8404d3f 100644 --- a/tests/checkasm/sw_rgb.c +++ b/tests/checkasm/sw_rgb.c @@ -370,7 +370,7 @@ static void check_rgb_to_y(SwsInternal *ctx) for (int i = 0; i < FF_ARRAY_ELEMS(rgb_formats); i++) { const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(rgb_formats[i]); - ctx->srcFormat = rgb_formats[i]; + ctx->opts.src_format = rgb_formats[i]; ff_sws_init_scale(ctx); for (int j = 0; j < FF_ARRAY_ELEMS(input_sizes); j++) { @@ -389,7 +389,7 @@ static void check_rgb_to_y(SwsInternal *ctx) if (desc->nb_components == 3 || // only bench native endian formats - (ctx->srcFormat == AV_PIX_FMT_RGB32 || ctx->srcFormat == AV_PIX_FMT_RGB32_1)) + (ctx->opts.src_format == AV_PIX_FMT_RGB32 || ctx->opts.src_format == AV_PIX_FMT_RGB32_1)) bench_new(dst1_y, src, NULL, NULL, w, ctx->input_rgb2yuv_table, NULL); } } @@ -417,8 +417,8 @@ static void check_rgb_to_uv(SwsInternal *ctx) const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(src_fmt); ctx->chrSrcHSubSample = (i % 2) ? 0 : 1; - ctx->srcFormat = src_fmt; - ctx->dstFormat = ctx->chrSrcHSubSample ? AV_PIX_FMT_YUV420P : AV_PIX_FMT_YUV444P; + ctx->opts.src_format = src_fmt; + ctx->opts.dst_format = ctx->chrSrcHSubSample ? AV_PIX_FMT_YUV420P : AV_PIX_FMT_YUV444P; ff_sws_init_scale(ctx); for (int j = 0; j < FF_ARRAY_ELEMS(input_sizes); j++) { @@ -441,7 +441,7 @@ static void check_rgb_to_uv(SwsInternal *ctx) if (desc->nb_components == 3 || // only bench native endian formats - (ctx->srcFormat == AV_PIX_FMT_RGB32 || ctx->srcFormat == AV_PIX_FMT_RGB32_1)) + (ctx->opts.src_format == AV_PIX_FMT_RGB32 || ctx->opts.src_format == AV_PIX_FMT_RGB32_1)) bench_new(dst1_u, dst1_v, NULL, src, src, w, ctx->input_rgb2yuv_table, NULL); } } diff --git a/tests/checkasm/sw_scale.c b/tests/checkasm/sw_scale.c index 7580c8b56c..82e2b1d5ce 100644 --- a/tests/checkasm/sw_scale.c +++ b/tests/checkasm/sw_scale.c @@ -125,7 +125,7 @@ static void check_yuv2yuv1(int accurate) sws = sws_alloc_context(); c = sws_internal(sws); if (accurate) - c->flags |= SWS_ACCURATE_RND; + c->opts.flags |= SWS_ACCURATE_RND; if (sws_init_context(sws, NULL, NULL) < 0) fail(); @@ -192,7 +192,7 @@ static void check_yuv2yuvX(int accurate) sws = sws_alloc_context(); c = sws_internal(sws); if (accurate) - c->flags |= SWS_ACCURATE_RND; + c->opts.flags |= SWS_ACCURATE_RND; if (sws_init_context(sws, NULL, NULL) < 0) fail(); @@ -341,20 +341,20 @@ static void check_hscale(void) filter[SRC_PIXELS * width + i] = rnd(); } - c->dstW = c->chrDstW = input_sizes[dstWi]; + c->opts.dst_w = c->chrDstW = input_sizes[dstWi]; ff_sws_init_scale(c); memcpy(filterAvx2, filter, sizeof(uint16_t) * (SRC_PIXELS * MAX_FILTER_WIDTH + MAX_FILTER_WIDTH)); - ff_shuffle_filter_coefficients(c, filterPosAvx, width, filterAvx2, c->dstW); + ff_shuffle_filter_coefficients(c, filterPosAvx, width, filterAvx2, c->opts.dst_w); - if (check_func(c->hcScale, "hscale_%d_to_%d__fs_%d_dstW_%d", c->srcBpc, c->dstBpc + 1, width, c->dstW)) { + if (check_func(c->hcScale, "hscale_%d_to_%d__fs_%d_dstW_%d", c->srcBpc, c->dstBpc + 1, width, c->opts.dst_w)) { memset(dst0, 0, SRC_PIXELS * sizeof(dst0[0])); memset(dst1, 0, SRC_PIXELS * sizeof(dst1[0])); - call_ref(NULL, dst0, c->dstW, src, filter, filterPos, width); - call_new(NULL, dst1, c->dstW, src, filterAvx2, filterPosAvx, width); - if (memcmp(dst0, dst1, c->dstW * sizeof(dst0[0]))) + call_ref(NULL, dst0, c->opts.dst_w, src, filter, filterPos, width); + call_new(NULL, dst1, c->opts.dst_w, src, filterAvx2, filterPosAvx, width); + if (memcmp(dst0, dst1, c->opts.dst_w * sizeof(dst0[0]))) fail(); - bench_new(NULL, dst0, c->dstW, src, filter, filterPosAvx, width); + bench_new(NULL, dst0, c->opts.dst_w, src, filter, filterPosAvx, width); } } } From patchwork Tue Nov 12 09:50:38 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Niklas Haas X-Patchwork-Id: 52695 Delivered-To: ffmpegpatchwork2@gmail.com Received: by 2002:a05:612c:6704:20b0:4a6:637d:5226 with SMTP id mp4-n2csp140296vqb; Tue, 12 Nov 2024 01:53:00 -0800 (PST) X-Forwarded-Encrypted: i=2; AJvYcCXfAr0edrvs7mGJjUxO0Ml2wCiE+SBVVnMOc66Ob9EcGGyOUGVRp9LhU8L8WrLOzSM4uYmC3MT2f1QNK30+NC4k@gmail.com X-Google-Smtp-Source: AGHT+IFdnugwB8dVVE9hQo9elw/RNEWEGGJUt4s2I2BGN65fkqmCqp51mtuyeB90I560DRTmPvMT X-Received: by 2002:a05:6402:d05:b0:5ce:d028:e11 with SMTP id 4fb4d7f45d1cf-5cf0a32a404mr10487747a12.17.1731405180302; Tue, 12 Nov 2024 01:53:00 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1731405180; cv=none; d=google.com; s=arc-20240605; b=jp6NZoLZlgt4J0gMgVZ0POMrOzC7R2Ms5Uj/Akv5q7L9zOeyB/GPZEL1zF10hU1Nj3 VFMDOtKjOi7VoUktWJQ1z1pJVukG460KH0q9pyy3pFJpv+PGEDYSI7s+UDL+95RaUp79 CuhlLOZ0LmbaRvBvFaFwNYamb/WwJpnjmCMBoS14V/NEZoVcJiuNaITUF/OzlE9pyfYs C/EVSPSGPEfmYiw4EgVNtK908cWb8fnl2Xkv+ed4gQHP+LIyjtXQGLfnJBc8tOJNWf1+ nbHjhV7ekJR20Eq7jzKNUif3dc0tiLeIvK6V+PbzHbNrb586dHWroWOESIApLQsjP1lp EzuQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20240605; h=sender:errors-to:content-transfer-encoding:cc:reply-to :list-subscribe:list-help:list-post:list-archive:list-unsubscribe :list-id:precedence:subject:mime-version:references:in-reply-to :message-id:date:to:from:delivered-to; bh=JLiHg+6mTyZ3gjL0i0pnRTJxiCArEQFs5yb+csDeRkg=; fh=xmAeKtysnShNOmkhiJmYkS30uw4Fu2hvBJ7qlIwukxQ=; b=BCtKZm8vQmgL3L3GqfD/ABkIL4yT49stxl3S3vote1F1myOHXRpQLI4eoSWmTHENQC ddyLHadAzEXSc2zWMrIf8GqPDJVQ+SVlmmqz3QNJsf8FpSrpMoqMH9p2mHTZbsVgtnbM LoTFsPs/YJm1I1aDVcKFIl6cY0KuJMar8N2rDuissZ2bV61E00GUkVDnQSvidjKEwZ8/ z4ovAB9mkuNgCLDCXq2V3I+CJEBjvXW6JkTgisCItsDpJuilVoQdJGTnC4gSC4zftraw W6Awmku8vktU/cYiRe9J/UUbhKzIS63MrxVd+lqtjzgSEDCA2+Z5wcd2Fe7xu0so4YuH +vyw==; dara=google.com ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org Return-Path: Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org. [79.124.17.100]) by mx.google.com with ESMTPS id 4fb4d7f45d1cf-5cf03b7dc63si7900489a12.10.2024.11.12.01.53.00 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 12 Nov 2024 01:53:00 -0800 (PST) Received-SPF: pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) client-ip=79.124.17.100; Authentication-Results: mx.google.com; spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 7E20C68DEA4; Tue, 12 Nov 2024 11:52:09 +0200 (EET) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from haasn.dev (haasn.dev [78.46.187.166]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id D02B268DE23 for ; Tue, 12 Nov 2024 11:51:57 +0200 (EET) Received: from haasn.dev (unknown [10.30.1.1]) by haasn.dev (Postfix) with ESMTP id 96F0F41C5E; Tue, 12 Nov 2024 10:51:57 +0100 (CET) From: Niklas Haas To: ffmpeg-devel@ffmpeg.org Date: Tue, 12 Nov 2024 10:50:38 +0100 Message-ID: <20241112095154.483778-5-ffmpeg@haasn.xyz> X-Mailer: git-send-email 2.47.0 In-Reply-To: <20241112095154.483778-1-ffmpeg@haasn.xyz> References: <20241112095154.483778-1-ffmpeg@haasn.xyz> MIME-Version: 1.0 Subject: [FFmpeg-devel] [PATCH v6 04/12] swscale: expose SwsContext publicly X-BeenThere: ffmpeg-devel@ffmpeg.org X-Mailman-Version: 2.1.29 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: Niklas Haas Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" X-TUID: 8MvUbBMXaKh0 From: Niklas Haas Following in the footsteps of the work in the previous commit, it's now relatively straightforward to expose the options struct publicly as SwsContext. This is a step towards making this more user friendly, as well as following API conventions established elsewhere. Sponsored-by: Sovereign Tech Fund Signed-off-by: Niklas Haas --- libswscale/swscale.h | 93 +++++++++++++++++++++++-- libswscale/swscale_internal.h | 45 +------------ libswscale/utils.c | 123 +++++++++++++++------------------- 3 files changed, 144 insertions(+), 117 deletions(-) diff --git a/libswscale/swscale.h b/libswscale/swscale.h index 50c705ae06..4baef532b6 100644 --- a/libswscale/swscale.h +++ b/libswscale/swscale.h @@ -42,8 +42,6 @@ #include "version.h" #endif -typedef struct SwsContext SwsContext; - /** * @defgroup libsws libswscale * Color conversion and scaling library. @@ -65,17 +63,98 @@ const char *swscale_configuration(void); const char *swscale_license(void); /** - * Get the AVClass for swsContext. It can be used in combination with + * Get the AVClass for SwsContext. It can be used in combination with * AV_OPT_SEARCH_FAKE_OBJ for examining options. * * @see av_opt_find(). */ const AVClass *sws_get_class(void); -/** - * Allocate an empty SwsContext. This must be filled and passed to - * sws_init_context(). For filling see AVOptions, options.c and - * sws_setColorspaceDetails(). +/****************************** + * Flags and quality settings * + ******************************/ + +typedef enum SwsDither { + SWS_DITHER_NONE = 0, /* disable dithering */ + SWS_DITHER_AUTO, /* auto-select from preset */ + SWS_DITHER_BAYER, /* ordered dither matrix */ + SWS_DITHER_ED, /* error diffusion */ + SWS_DITHER_A_DITHER, /* arithmetic addition */ + SWS_DITHER_X_DITHER, /* arithmetic xor */ + SWS_DITHER_NB, /* not part of the ABI */ +} SwsDither; + +typedef enum SwsAlphaBlend { + SWS_ALPHA_BLEND_NONE = 0, + SWS_ALPHA_BLEND_UNIFORM, + SWS_ALPHA_BLEND_CHECKERBOARD, + SWS_ALPHA_BLEND_NB, /* not part of the ABI */ +} SwsAlphaBlend; + +/*********************************** + * Context creation and management * + ***********************************/ + +/** + * Main external API structure. New fields can be added to the end with + * minor version bumps. Removal, reordering and changes to existing fields + * require a major version bump. sizeof(SwsContext) is not part of the ABI. + */ +typedef struct SwsContext { + const AVClass *av_class; + + /** + * Private data of the user, can be used to carry app specific stuff. + */ + void *opaque; + + /** + * Bitmask of SWS_*. + */ + unsigned flags; + + /** + * Extra parameters for fine-tuning certain scalers. + */ + double scaler_params[2]; + + /** + * How many threads to use for processing, or 0 for automatic selection. + */ + int threads; + + /** + * Dither mode. + */ + SwsDither dither; + + /** + * Alpha blending mode. See `SwsAlphaBlend` for details. + */ + SwsAlphaBlend alpha_blend; + + /** + * Use gamma correct scaling. + */ + int gamma_flag; + + /** + * Frame property overrides. + */ + int src_w, src_h; ///< Width and height of the source frame + int dst_w, dst_h; ///< Width and height of the destination frame + int src_format; ///< Source pixel format + int dst_format; ///< Destination pixel format + int src_range; ///< Source is full range + int dst_range; ///< Destination is full range + int src_v_chr_pos; ///< Source vertical chroma position in luma grid / 256 + int src_h_chr_pos; ///< Source horizontal chroma position + int dst_v_chr_pos; ///< Destination vertical chroma position + int dst_h_chr_pos; ///< Destination horizontal chroma position +} SwsContext; + +/** + * Allocate an empty SwsContext and set its fields to default values. */ SwsContext *sws_alloc_context(void); diff --git a/libswscale/swscale_internal.h b/libswscale/swscale_internal.h index 643177d14d..5218ab0921 100644 --- a/libswscale/swscale_internal.h +++ b/libswscale/swscale_internal.h @@ -73,23 +73,6 @@ static inline SwsInternal *sws_internal(const SwsContext *sws) return (SwsInternal *) sws; } -typedef enum SwsDither { - SWS_DITHER_NONE = 0, - SWS_DITHER_AUTO, - SWS_DITHER_BAYER, - SWS_DITHER_ED, - SWS_DITHER_A_DITHER, - SWS_DITHER_X_DITHER, - SWS_DITHER_NB, -} SwsDither; - -typedef enum SwsAlphaBlend { - SWS_ALPHA_BLEND_NONE = 0, - SWS_ALPHA_BLEND_UNIFORM, - SWS_ALPHA_BLEND_CHECKERBOARD, - SWS_ALPHA_BLEND_NB, -} SwsAlphaBlend; - typedef struct Range { unsigned int start; unsigned int len; @@ -329,32 +312,10 @@ struct SwsFilterDescriptor; /* This struct should be aligned on at least a 32-byte boundary. */ struct SwsInternal { - /* Currently active user-facing options. */ - struct { - const AVClass *av_class; - - double scaler_params[2]; ///< Input parameters for scaling algorithms that need them. - int flags; ///< Flags passed by the user to select scaler algorithm, optimizations, subsampling, etc... - int threads; ///< Number of threads used for scaling - - int src_w; ///< Width of source luma/alpha planes. - int src_h; ///< Height of source luma/alpha planes. - int dst_w; ///< Width of destination luma/alpha planes. - int dst_h; ///< Height of destination luma/alpha planes. - enum AVPixelFormat src_format; ///< Source pixel format. - enum AVPixelFormat dst_format; ///< Destination pixel format. - int src_range; ///< 0 = MPG YUV range, 1 = JPG YUV range (source image). - int dst_range; ///< 0 = MPG YUV range, 1 = JPG YUV range (destination image). - int src_h_chr_pos; - int dst_h_chr_pos; - int src_v_chr_pos; - int dst_v_chr_pos; - int gamma_flag; - - SwsDither dither; - SwsAlphaBlend alpha_blend; - } opts; + /* Currently active user-facing options. Also contains AVClass */ + SwsContext opts; + /* Parent context (for slice contexts) */ SwsContext *parent; AVSliceThread *slicethread; diff --git a/libswscale/utils.c b/libswscale/utils.c index 465302a9fa..ce9807d401 100644 --- a/libswscale/utils.c +++ b/libswscale/utils.c @@ -293,22 +293,20 @@ static SwsContext *alloc_set_opts(int srcW, int srcH, enum AVPixelFormat srcForm int flags, const double *param) { SwsContext *sws = sws_alloc_context(); - SwsInternal *c = sws_internal(sws); - - if (!c) + if (!sws) return NULL; - c->opts.flags = flags; - c->opts.src_w = srcW; - c->opts.src_h = srcH; - c->opts.dst_w = dstW; - c->opts.dst_h = dstH; - c->opts.src_format = srcFormat; - c->opts.dst_format = dstFormat; + sws->flags = flags; + sws->src_w = srcW; + sws->src_h = srcH; + sws->dst_w = dstW; + sws->dst_h = dstH; + sws->src_format = srcFormat; + sws->dst_format = dstFormat; if (param) { - c->opts.scaler_params[0] = param[0]; - c->opts.scaler_params[1] = param[1]; + sws->scaler_params[0] = param[0]; + sws->scaler_params[1] = param[1]; } return sws; @@ -1228,16 +1226,16 @@ int sws_getColorspaceDetails(SwsContext *sws, int **inv_table, SwsContext *sws_alloc_context(void) { - SwsInternal *c = av_mallocz(sizeof(SwsInternal)); + SwsInternal *c = (SwsInternal *) av_mallocz(sizeof(SwsInternal)); + if (!c) + return NULL; - if (c) { - c->opts.av_class = &ff_sws_context_class; - av_opt_set_defaults(c); - atomic_init(&c->stride_unaligned_warned, 0); - atomic_init(&c->data_unaligned_warned, 0); - } + c->opts.av_class = &ff_sws_context_class; + av_opt_set_defaults(c); + atomic_init(&c->stride_unaligned_warned, 0); + atomic_init(&c->data_unaligned_warned, 0); - return (SwsContext *) c; + return &c->opts; } static uint16_t * alloc_gamma_tbl(double e) @@ -2523,7 +2521,7 @@ void sws_freeContext(SwsContext *sws) ff_free_filters(c); - av_free(sws); + av_free(c); } void sws_free_context(SwsContext **pctx) @@ -2536,7 +2534,7 @@ void sws_free_context(SwsContext **pctx) *pctx = NULL; } -SwsContext *sws_getCachedContext(SwsContext *sws, int srcW, +SwsContext *sws_getCachedContext(SwsContext *prev, int srcW, int srcH, enum AVPixelFormat srcFormat, int dstW, int dstH, enum AVPixelFormat dstFormat, int flags, @@ -2544,59 +2542,48 @@ SwsContext *sws_getCachedContext(SwsContext *sws, int srcW, SwsFilter *dstFilter, const double *param) { - SwsInternal *context; - + SwsContext *sws; static const double default_param[2] = { SWS_PARAM_DEFAULT, SWS_PARAM_DEFAULT }; - int64_t src_h_chr_pos = -513, dst_h_chr_pos = -513, - src_v_chr_pos = -513, dst_v_chr_pos = -513; if (!param) param = default_param; - if ((context = sws_internal(sws)) && - (context->opts.src_w != srcW || - context->opts.src_h != srcH || - context->opts.src_format != srcFormat || - context->opts.dst_w != dstW || - context->opts.dst_h != dstH || - context->opts.dst_format != dstFormat || - context->opts.flags != flags || - context->opts.scaler_params[0] != param[0] || - context->opts.scaler_params[1] != param[1])) { - - av_opt_get_int(context, "src_h_chr_pos", 0, &src_h_chr_pos); - av_opt_get_int(context, "src_v_chr_pos", 0, &src_v_chr_pos); - av_opt_get_int(context, "dst_h_chr_pos", 0, &dst_h_chr_pos); - av_opt_get_int(context, "dst_v_chr_pos", 0, &dst_v_chr_pos); - sws_freeContext(sws); - sws = NULL; - } - - if (!sws) { - if (!(sws = sws_alloc_context())) - return NULL; - context = sws_internal(sws); - context->opts.src_w = srcW; - context->opts.src_h = srcH; - context->opts.src_format = srcFormat; - context->opts.dst_w = dstW; - context->opts.dst_h = dstH; - context->opts.dst_format = dstFormat; - context->opts.flags = flags; - context->opts.scaler_params[0] = param[0]; - context->opts.scaler_params[1] = param[1]; - - av_opt_set_int(context, "src_h_chr_pos", src_h_chr_pos, 0); - av_opt_set_int(context, "src_v_chr_pos", src_v_chr_pos, 0); - av_opt_set_int(context, "dst_h_chr_pos", dst_h_chr_pos, 0); - av_opt_set_int(context, "dst_v_chr_pos", dst_v_chr_pos, 0); - - if (sws_init_context(sws, srcFilter, dstFilter) < 0) { - sws_freeContext(sws); - return NULL; - } + if (prev && (prev->src_w == srcW || + prev->src_h == srcH || + prev->src_format == srcFormat || + prev->dst_w == dstW || + prev->dst_h == dstH || + prev->dst_format == dstFormat || + prev->flags == flags || + prev->scaler_params[0] == param[0] || + prev->scaler_params[1] == param[1])) { + return prev; } + + if (!(sws = sws_alloc_context())) { + sws_free_context(&prev); + return NULL; + } + + if (prev) { + av_opt_copy(sws, prev); + sws_free_context(&prev); + } + + sws->src_w = srcW; + sws->src_h = srcH; + sws->src_format = srcFormat; + sws->dst_w = dstW; + sws->dst_h = dstH; + sws->dst_format = dstFormat; + sws->flags = flags; + sws->scaler_params[0] = param[0]; + sws->scaler_params[1] = param[1]; + + if (sws_init_context(sws, srcFilter, dstFilter) < 0) + sws_free_context(&sws); + return sws; } From patchwork Tue Nov 12 09:50:39 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Niklas Haas X-Patchwork-Id: 52696 Delivered-To: ffmpegpatchwork2@gmail.com Received: by 2002:a05:612c:6704:20b0:4a6:637d:5226 with SMTP id mp4-n2csp140573vqb; Tue, 12 Nov 2024 01:53:38 -0800 (PST) X-Forwarded-Encrypted: i=2; AJvYcCXYF8lMhW/f1L9rXzIAWstiOM5+fxVX5YPa7azrurI/tXEgABtzVfVfo/D3pA+PovKbA5a8nzlVBUJcD4YJ98no@gmail.com X-Google-Smtp-Source: AGHT+IHqFisfCb9TKI9l4/vQysk5P5gKXCu2MqEoyD5d0KVAYuiaTI0OaivVAuPtFBgqm/1PJFpr X-Received: by 2002:a05:6512:3f12:b0:539:9867:eed7 with SMTP id 2adb3069b0e04-53d862d40e4mr7390847e87.24.1731405218663; Tue, 12 Nov 2024 01:53:38 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1731405218; cv=none; d=google.com; s=arc-20240605; b=RyRQWSwG4d3myRDFt9mP/dTWUkZFjhEnP/0RHuGIa9igpAZNOY05pJUznhZ79qzM7T QMkfAiiTc+FZik+RpiIyC0knbie/tme46/IlcK2jCWrD1L4hrRQHfgZ3By/5EkD5gfTG 6l0jVodpQtBN31rDF0bbAnOuYmpp2rrzzlCGi3KjExD360hwROGcpiGtJJlVvf3h1dHq DgZNArhyv+ZGOe/JhsxUDQpe26MeNkEIkuPWrw8UUwBqFZaHMK6u6SDXzkRCpXsodka0 7rIE3Chs2ygLsmlxfp4FpkN/Rcyomq/37VlwbPogIJJiR7e4aGPZoVPPeZYLMbT6YvJM xDnA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20240605; h=sender:errors-to:content-transfer-encoding:cc:reply-to :list-subscribe:list-help:list-post:list-archive:list-unsubscribe :list-id:precedence:subject:mime-version:references:in-reply-to :message-id:date:to:from:delivered-to; bh=hG0deE2oVD6KyKReZu4i1z2d8UDIbGAPZ9P+SLQB5uY=; fh=xmAeKtysnShNOmkhiJmYkS30uw4Fu2hvBJ7qlIwukxQ=; b=T30d0isgNA7eDQzFd+gNE6c/wZFY7cMNpkagQWm67M+ws+Boc2iFmzTjltertmmXL/ LhsxcDHUqiT+YNEE+Pf3WH/QqostySb9fpnkli0p9VWuyd9ovePVan0xdIbNsrZ5aE01 1UYyHTpgYvIaCzks1+duMqLPm/oOWoZVXjRE9SelyLr+oZ9//8/bjglziOp5sVKU9rbv 5tPgMrZSMVKUJIpzkQJa7VnIB61kVl3Yksppa0I2T59y8DcpLBJy/9NNtz2GQ7n2Bl6g RDG7EXrfQdsgiPZ3ljAMdpSzbOTX2nhxh3Hu2pl+RjsTwRGO/pPt0wwf1pDO+zJoctO6 j3FA==; dara=google.com ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org Return-Path: Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org. [79.124.17.100]) by mx.google.com with ESMTPS id 2adb3069b0e04-53d826b5da1si4310455e87.571.2024.11.12.01.53.38 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 12 Nov 2024 01:53:38 -0800 (PST) Received-SPF: pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) client-ip=79.124.17.100; Authentication-Results: mx.google.com; spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 8D25568DEB5; Tue, 12 Nov 2024 11:52:13 +0200 (EET) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from haasn.dev (haasn.dev [78.46.187.166]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 6FE9168DE80 for ; Tue, 12 Nov 2024 11:52:02 +0200 (EET) Received: from haasn.dev (unknown [10.30.1.1]) by haasn.dev (Postfix) with ESMTP id CF20F42957; Tue, 12 Nov 2024 10:51:57 +0100 (CET) From: Niklas Haas To: ffmpeg-devel@ffmpeg.org Date: Tue, 12 Nov 2024 10:50:39 +0100 Message-ID: <20241112095154.483778-6-ffmpeg@haasn.xyz> X-Mailer: git-send-email 2.47.0 In-Reply-To: <20241112095154.483778-1-ffmpeg@haasn.xyz> References: <20241112095154.483778-1-ffmpeg@haasn.xyz> MIME-Version: 1.0 Subject: [FFmpeg-devel] [PATCH v6 05/12] swscale: eliminate redundant SwsInternal accesses X-BeenThere: ffmpeg-devel@ffmpeg.org X-Mailman-Version: 2.1.29 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: Niklas Haas Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" X-TUID: 7iVL2xkpBeK8 From: Niklas Haas This is a purely cosmetic commit aimed at replacing accesses to SwsInternal.opts by direct access to SwsContext wherever convenient. Sponsored-by: Sovereign Tech Fund Signed-off-by: Niklas Haas --- libswscale/options.c | 2 +- libswscale/swscale.c | 93 ++++++------ libswscale/utils.c | 233 +++++++++++++++--------------- tests/checkasm/sw_gbrp.c | 16 +- tests/checkasm/sw_range_convert.c | 16 +- tests/checkasm/sw_rgb.c | 29 ++-- tests/checkasm/sw_scale.c | 22 +-- 7 files changed, 203 insertions(+), 208 deletions(-) diff --git a/libswscale/options.c b/libswscale/options.c index 6248e5f4b5..5eef26de06 100644 --- a/libswscale/options.c +++ b/libswscale/options.c @@ -27,7 +27,7 @@ static const char *sws_context_to_name(void *ptr) return "swscaler"; } -#define OFFSET(x) offsetof(SwsInternal, opts.x) +#define OFFSET(x) offsetof(SwsContext, x) #define DEFAULT 0 #define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM diff --git a/libswscale/swscale.c b/libswscale/swscale.c index 5b5a009f1b..45172dcea4 100644 --- a/libswscale/swscale.c +++ b/libswscale/swscale.c @@ -895,7 +895,7 @@ static int scale_cascaded(SwsInternal *c, uint8_t * const dstSlice[], const int dstStride[], int dstSliceY, int dstSliceH) { - const int dstH0 = sws_internal(c->cascaded_context[0])->opts.dst_h; + const int dstH0 = c->cascaded_context[0]->dst_h; int ret = scale_internal(c->cascaded_context[0], srcSlice, srcStride, srcSliceY, srcSliceH, c->cascaded_tmp[0], c->cascaded_tmpStride[0], @@ -915,13 +915,13 @@ static int scale_internal(SwsContext *sws, int dstSliceY, int dstSliceH) { SwsInternal *c = sws_internal(sws); - const int scale_dst = dstSliceY > 0 || dstSliceH < c->opts.dst_h; + const int scale_dst = dstSliceY > 0 || dstSliceH < sws->dst_h; const int frame_start = scale_dst || !c->sliceDir; int i, ret; const uint8_t *src2[4]; uint8_t *dst2[4]; - int macro_height_src = isBayer(c->opts.src_format) ? 2 : (1 << c->chrSrcVSubSample); - int macro_height_dst = isBayer(c->opts.dst_format) ? 2 : (1 << c->chrDstVSubSample); + int macro_height_src = isBayer(sws->src_format) ? 2 : (1 << c->chrSrcVSubSample); + int macro_height_dst = isBayer(sws->dst_format) ? 2 : (1 << c->chrDstVSubSample); // copy strides, so they can safely be modified int srcStride2[4]; int dstStride2[4]; @@ -933,25 +933,25 @@ static int scale_internal(SwsContext *sws, } if ((srcSliceY & (macro_height_src - 1)) || - ((srcSliceH & (macro_height_src - 1)) && srcSliceY + srcSliceH != c->opts.src_h) || - srcSliceY + srcSliceH > c->opts.src_h || - (isBayer(c->opts.src_format) && srcSliceH <= 1)) { + ((srcSliceH & (macro_height_src - 1)) && srcSliceY + srcSliceH != sws->src_h) || + srcSliceY + srcSliceH > sws->src_h || + (isBayer(sws->src_format) && srcSliceH <= 1)) { av_log(c, AV_LOG_ERROR, "Slice parameters %d, %d are invalid\n", srcSliceY, srcSliceH); return AVERROR(EINVAL); } if ((dstSliceY & (macro_height_dst - 1)) || - ((dstSliceH & (macro_height_dst - 1)) && dstSliceY + dstSliceH != c->opts.dst_h) || - dstSliceY + dstSliceH > c->opts.dst_h) { + ((dstSliceH & (macro_height_dst - 1)) && dstSliceY + dstSliceH != sws->dst_h) || + dstSliceY + dstSliceH > sws->dst_h) { av_log(c, AV_LOG_ERROR, "Slice parameters %d, %d are invalid\n", dstSliceY, dstSliceH); return AVERROR(EINVAL); } - if (!check_image_pointers(srcSlice, c->opts.src_format, srcStride)) { + if (!check_image_pointers(srcSlice, sws->src_format, srcStride)) { av_log(c, AV_LOG_ERROR, "bad src image pointers\n"); return AVERROR(EINVAL); } - if (!check_image_pointers((const uint8_t* const*)dstSlice, c->opts.dst_format, dstStride)) { + if (!check_image_pointers((const uint8_t* const*)dstSlice, sws->dst_format, dstStride)) { av_log(c, AV_LOG_ERROR, "bad dst image pointers\n"); return AVERROR(EINVAL); } @@ -960,22 +960,19 @@ static int scale_internal(SwsContext *sws, if (srcSliceH == 0) return 0; - if (c->opts.gamma_flag && c->cascaded_context[0]) + if (sws->gamma_flag && c->cascaded_context[0]) return scale_gamma(c, srcSlice, srcStride, srcSliceY, srcSliceH, dstSlice, dstStride, dstSliceY, dstSliceH); - if (c->cascaded_context[0] && srcSliceY == 0 && - srcSliceH == sws_internal(c->cascaded_context[0])->opts.src_h) - { + if (c->cascaded_context[0] && srcSliceY == 0 && srcSliceH == c->cascaded_context[0]->src_h) return scale_cascaded(c, srcSlice, srcStride, srcSliceY, srcSliceH, dstSlice, dstStride, dstSliceY, dstSliceH); - } - if (!srcSliceY && (c->opts.flags & SWS_BITEXACT) && c->opts.dither == SWS_DITHER_ED && c->dither_error[0]) + if (!srcSliceY && (sws->flags & SWS_BITEXACT) && sws->dither == SWS_DITHER_ED && c->dither_error[0]) for (i = 0; i < 4; i++) - memset(c->dither_error[i], 0, sizeof(c->dither_error[0][0]) * (c->opts.dst_w+2)); + memset(c->dither_error[i], 0, sizeof(c->dither_error[0][0]) * (sws->dst_w+2)); - if (usePal(c->opts.src_format)) + if (usePal(sws->src_format)) ff_update_palette(c, (const uint32_t *)srcSlice[1]); memcpy(src2, srcSlice, sizeof(src2)); @@ -984,7 +981,7 @@ static int scale_internal(SwsContext *sws, memcpy(dstStride2, dstStride, sizeof(dstStride2)); if (frame_start && !scale_dst) { - if (srcSliceY != 0 && srcSliceY + srcSliceH != c->opts.src_h) { + if (srcSliceY != 0 && srcSliceY + srcSliceH != sws->src_h) { av_log(c, AV_LOG_ERROR, "Slices start in the middle!\n"); return AVERROR(EINVAL); } @@ -993,7 +990,7 @@ static int scale_internal(SwsContext *sws, } else if (scale_dst) c->sliceDir = 1; - if (c->src0Alpha && !c->dst0Alpha && isALPHA(c->opts.dst_format)) { + if (c->src0Alpha && !c->dst0Alpha && isALPHA(sws->dst_format)) { uint8_t *base; int x,y; @@ -1005,15 +1002,15 @@ static int scale_internal(SwsContext *sws, base = srcStride[0] < 0 ? c->rgb0_scratch - srcStride[0] * (srcSliceH-1) : c->rgb0_scratch; for (y=0; yopts.src_w); - for (x=c->src0Alpha-1; x<4*c->opts.src_w; x+=4) { + memcpy(base + srcStride[0]*y, src2[0] + srcStride[0]*y, 4*sws->src_w); + for (x=c->src0Alpha-1; x<4*sws->src_w; x+=4) { base[ srcStride[0]*y + x] = 0xFF; } } src2[0] = base; } - if (c->srcXYZ && !(c->dstXYZ && c->opts.src_w==c->opts.dst_w && c->opts.src_h==c->opts.dst_h)) { + if (c->srcXYZ && !(c->dstXYZ && sws->src_w==sws->dst_w && sws->src_h==sws->dst_h)) { uint8_t *base; av_fast_malloc(&c->xyz_scratch, &c->xyz_scratch_allocated, @@ -1024,7 +1021,7 @@ static int scale_internal(SwsContext *sws, base = srcStride[0] < 0 ? c->xyz_scratch - srcStride[0] * (srcSliceH-1) : c->xyz_scratch; - ff_xyz12Torgb48(c, base, srcStride[0], src2[0], srcStride[0], c->opts.src_w, srcSliceH); + ff_xyz12Torgb48(c, base, srcStride[0], src2[0], srcStride[0], sws->src_w, srcSliceH); src2[0] = base; } @@ -1036,19 +1033,19 @@ static int scale_internal(SwsContext *sws, } src2[0] += (srcSliceH - 1) * srcStride[0]; - if (!usePal(c->opts.src_format)) + if (!usePal(sws->src_format)) src2[1] += ((srcSliceH >> c->chrSrcVSubSample) - 1) * srcStride[1]; src2[2] += ((srcSliceH >> c->chrSrcVSubSample) - 1) * srcStride[2]; src2[3] += (srcSliceH - 1) * srcStride[3]; - dst2[0] += ( c->opts.dst_h - 1) * dstStride[0]; - dst2[1] += ((c->opts.dst_h >> c->chrDstVSubSample) - 1) * dstStride[1]; - dst2[2] += ((c->opts.dst_h >> c->chrDstVSubSample) - 1) * dstStride[2]; - dst2[3] += ( c->opts.dst_h - 1) * dstStride[3]; + dst2[0] += ( sws->dst_h - 1) * dstStride[0]; + dst2[1] += ((sws->dst_h >> c->chrDstVSubSample) - 1) * dstStride[1]; + dst2[2] += ((sws->dst_h >> c->chrDstVSubSample) - 1) * dstStride[2]; + dst2[3] += ( sws->dst_h - 1) * dstStride[3]; - srcSliceY_internal = c->opts.src_h-srcSliceY-srcSliceH; + srcSliceY_internal = sws->src_h-srcSliceY-srcSliceH; } - reset_ptr(src2, c->opts.src_format); - reset_ptr((void*)dst2, c->opts.dst_format); + reset_ptr(src2, sws->src_format); + reset_ptr((void*)dst2, sws->dst_format); if (c->convert_unscaled) { int offset = srcSliceY_internal; @@ -1058,13 +1055,13 @@ static int scale_internal(SwsContext *sws, if (scale_dst) { av_assert0(offset == 0); for (i = 0; i < 4 && src2[i]; i++) { - if (!src2[i] || (i > 0 && usePal(c->opts.src_format))) + if (!src2[i] || (i > 0 && usePal(sws->src_format))) break; src2[i] += (dstSliceY >> ((i == 1 || i == 2) ? c->chrSrcVSubSample : 0)) * srcStride2[i]; } for (i = 0; i < 4 && dst2[i]; i++) { - if (!dst2[i] || (i > 0 && usePal(c->opts.dst_format))) + if (!dst2[i] || (i > 0 && usePal(sws->dst_format))) break; dst2[i] -= (dstSliceY >> ((i == 1 || i == 2) ? c->chrDstVSubSample : 0)) * dstStride2[i]; } @@ -1081,7 +1078,7 @@ static int scale_internal(SwsContext *sws, dst2, dstStride2, dstSliceY, dstSliceH); } - if (c->dstXYZ && !(c->srcXYZ && c->opts.src_w==c->opts.dst_w && c->opts.src_h==c->opts.dst_h)) { + if (c->dstXYZ && !(c->srcXYZ && sws->src_w==sws->dst_w && sws->src_h==sws->dst_h)) { uint8_t *dst; if (scale_dst) { @@ -1091,16 +1088,16 @@ static int scale_internal(SwsContext *sws, av_assert0(dstY >= ret); av_assert0(ret >= 0); - av_assert0(c->opts.dst_h >= dstY); + av_assert0(sws->dst_h >= dstY); dst = dst2[0] + (dstY - ret) * dstStride2[0]; } /* replace on the same data */ - ff_rgb48Toxyz12(c, dst, dstStride2[0], dst, dstStride2[0], c->opts.dst_w, ret); + ff_rgb48Toxyz12(c, dst, dstStride2[0], dst, dstStride2[0], sws->dst_w, ret); } /* reset slice direction at end of frame */ - if ((srcSliceY_internal + srcSliceH == c->opts.src_h) || scale_dst) + if ((srcSliceY_internal + srcSliceH == sws->src_h) || scale_dst) c->sliceDir = 0; return ret; @@ -1124,9 +1121,9 @@ int sws_frame_start(SwsContext *sws, AVFrame *dst, const AVFrame *src) return ret; if (!dst->buf[0]) { - dst->width = c->opts.dst_w; - dst->height = c->opts.dst_h; - dst->format = c->opts.dst_format; + dst->width = sws->dst_w; + dst->height = sws->dst_h; + dst->format = sws->dst_format; ret = av_frame_get_buffer(dst, 0); if (ret < 0) @@ -1177,10 +1174,10 @@ int sws_receive_slice(SwsContext *sws, unsigned int slice_start, /* wait until complete input has been received */ if (!(c->src_ranges.nb_ranges == 1 && c->src_ranges.ranges[0].start == 0 && - c->src_ranges.ranges[0].len == c->opts.src_h)) + c->src_ranges.ranges[0].len == sws->src_h)) return AVERROR(EAGAIN); - if ((slice_start > 0 || slice_height < c->opts.dst_h) && + if ((slice_start > 0 || slice_height < sws->dst_h) && (slice_start % align || slice_height % align)) { av_log(c, AV_LOG_ERROR, "Incorrectly aligned output: %u/%u not multiples of %u\n", @@ -1192,7 +1189,7 @@ int sws_receive_slice(SwsContext *sws, unsigned int slice_start, int nb_jobs = c->nb_slice_ctx; int ret = 0; - if (sws_internal(c->slice_ctx[0])->opts.dither == SWS_DITHER_ED) + if (c->slice_ctx[0]->dither == SWS_DITHER_ED) nb_jobs = 1; c->dst_slice_start = slice_start; @@ -1218,7 +1215,7 @@ int sws_receive_slice(SwsContext *sws, unsigned int slice_start, } return scale_internal(sws, (const uint8_t * const *)c->frame_src->data, - c->frame_src->linesize, 0, c->opts.src_h, + c->frame_src->linesize, 0, sws->src_h, dst, c->frame_dst->linesize, slice_start, slice_height); } @@ -1256,7 +1253,7 @@ int attribute_align_arg sws_scale(SwsContext *sws, } return scale_internal(sws, srcSlice, srcStride, srcSliceY, srcSliceH, - dst, dstStride, 0, c->opts.dst_h); + dst, dstStride, 0, sws->dst_h); } void ff_sws_slice_worker(void *priv, int jobnr, int threadnr, @@ -1284,7 +1281,7 @@ void ff_sws_slice_worker(void *priv, int jobnr, int threadnr, } err = scale_internal(sws, (const uint8_t * const *)parent->frame_src->data, - parent->frame_src->linesize, 0, c->opts.src_h, + parent->frame_src->linesize, 0, sws->src_h, dst, parent->frame_dst->linesize, parent->dst_slice_start + slice_start, slice_end - slice_start); } diff --git a/libswscale/utils.c b/libswscale/utils.c index ce9807d401..a01138d11b 100644 --- a/libswscale/utils.c +++ b/libswscale/utils.c @@ -1026,12 +1026,13 @@ static int handle_xyz(enum AVPixelFormat *format) } } -static void handle_formats(SwsInternal *c) +static void handle_formats(SwsContext *sws) { - c->src0Alpha |= handle_0alpha(&c->opts.src_format); - c->dst0Alpha |= handle_0alpha(&c->opts.dst_format); - c->srcXYZ |= handle_xyz(&c->opts.src_format); - c->dstXYZ |= handle_xyz(&c->opts.dst_format); + SwsInternal *c = sws_internal(sws); + c->src0Alpha |= handle_0alpha(&sws->src_format); + c->dst0Alpha |= handle_0alpha(&sws->dst_format); + c->srcXYZ |= handle_xyz(&sws->src_format); + c->dstXYZ |= handle_xyz(&sws->dst_format); if (c->srcXYZ || c->dstXYZ) fill_xyztables(c); } @@ -1063,17 +1064,17 @@ int sws_setColorspaceDetails(SwsContext *sws, const int inv_table[4], return parent_ret; } - handle_formats(c); - desc_dst = av_pix_fmt_desc_get(c->opts.dst_format); - desc_src = av_pix_fmt_desc_get(c->opts.src_format); + handle_formats(sws); + desc_dst = av_pix_fmt_desc_get(sws->dst_format); + desc_src = av_pix_fmt_desc_get(sws->src_format); - if(range_override_needed(c->opts.dst_format)) + if(range_override_needed(sws->dst_format)) dstRange = 0; - if(range_override_needed(c->opts.src_format)) + if(range_override_needed(sws->src_format)) srcRange = 0; - if (c->opts.src_range != srcRange || - c->opts.dst_range != dstRange || + if (sws->src_range != srcRange || + sws->dst_range != dstRange || c->brightness != brightness || c->contrast != contrast || c->saturation != saturation || @@ -1090,8 +1091,8 @@ int sws_setColorspaceDetails(SwsContext *sws, const int inv_table[4], c->brightness = brightness; c->contrast = contrast; c->saturation = saturation; - c->opts.src_range = srcRange; - c->opts.dst_range = dstRange; + sws->src_range = srcRange; + sws->dst_range = dstRange; if (need_reinit) ff_sws_init_range_convert(c); @@ -1105,27 +1106,27 @@ int sws_setColorspaceDetails(SwsContext *sws, const int inv_table[4], if (!need_reinit) return 0; - if ((isYUV(c->opts.dst_format) || isGray(c->opts.dst_format)) && (isYUV(c->opts.src_format) || isGray(c->opts.src_format))) { + if ((isYUV(sws->dst_format) || isGray(sws->dst_format)) && (isYUV(sws->src_format) || isGray(sws->src_format))) { if (!c->cascaded_context[0] && memcmp(c->dstColorspaceTable, c->srcColorspaceTable, sizeof(int) * 4) && - c->opts.src_w && c->opts.src_h && c->opts.dst_w && c->opts.dst_h) { + sws->src_w && sws->src_h && sws->dst_w && sws->dst_h) { enum AVPixelFormat tmp_format; int tmp_width, tmp_height; - int srcW = c->opts.src_w; - int srcH = c->opts.src_h; - int dstW = c->opts.dst_w; - int dstH = c->opts.dst_h; + int srcW = sws->src_w; + int srcH = sws->src_h; + int dstW = sws->dst_w; + int dstH = sws->dst_h; int ret; av_log(c, AV_LOG_VERBOSE, "YUV color matrix differs for YUV->YUV, using intermediate RGB to convert\n"); - if (isNBPS(c->opts.dst_format) || is16BPS(c->opts.dst_format)) { - if (isALPHA(c->opts.src_format) && isALPHA(c->opts.dst_format)) { + if (isNBPS(sws->dst_format) || is16BPS(sws->dst_format)) { + if (isALPHA(sws->src_format) && isALPHA(sws->dst_format)) { tmp_format = AV_PIX_FMT_BGRA64; } else { tmp_format = AV_PIX_FMT_BGR48; } } else { - if (isALPHA(c->opts.src_format) && isALPHA(c->opts.dst_format)) { + if (isALPHA(sws->src_format) && isALPHA(sws->dst_format)) { tmp_format = AV_PIX_FMT_BGRA; } else { tmp_format = AV_PIX_FMT_BGR24; @@ -1145,14 +1146,13 @@ int sws_setColorspaceDetails(SwsContext *sws, const int inv_table[4], if (ret < 0) return ret; - c->cascaded_context[0] = alloc_set_opts(srcW, srcH, c->opts.src_format, + c->cascaded_context[0] = alloc_set_opts(srcW, srcH, sws->src_format, tmp_width, tmp_height, tmp_format, - c->opts.flags, - c->opts.scaler_params); + sws->flags, sws->scaler_params); if (!c->cascaded_context[0]) return -1; - sws_internal(c->cascaded_context[0])->opts.alpha_blend = c->opts.alpha_blend; + c->cascaded_context[0]->alpha_blend = sws->alpha_blend; ret = sws_init_context(c->cascaded_context[0], NULL , NULL); if (ret < 0) return ret; @@ -1162,13 +1162,12 @@ int sws_setColorspaceDetails(SwsContext *sws, const int inv_table[4], brightness, contrast, saturation); c->cascaded_context[1] = alloc_set_opts(tmp_width, tmp_height, tmp_format, - dstW, dstH, c->opts.dst_format, - c->opts.flags, - c->opts.scaler_params); + dstW, dstH, sws->dst_format, + sws->flags, sws->scaler_params); if (!c->cascaded_context[1]) return -1; - sws_internal(c->cascaded_context[1])->opts.src_range = srcRange; - sws_internal(c->cascaded_context[1])->opts.dst_range = dstRange; + c->cascaded_context[1]->src_range = srcRange; + c->cascaded_context[1]->dst_range = dstRange; ret = sws_init_context(c->cascaded_context[1], NULL , NULL); if (ret < 0) return ret; @@ -1183,7 +1182,7 @@ int sws_setColorspaceDetails(SwsContext *sws, const int inv_table[4], return 0; } - if (!isYUV(c->opts.dst_format) && !isGray(c->opts.dst_format)) { + if (!isYUV(sws->dst_format) && !isGray(sws->dst_format)) { ff_yuv2rgb_c_init_tables(c, inv_table, srcRange, brightness, contrast, saturation); // FIXME factorize @@ -1215,8 +1214,8 @@ int sws_getColorspaceDetails(SwsContext *sws, int **inv_table, *inv_table = c->srcColorspaceTable; *table = c->dstColorspaceTable; - *srcRange = range_override_needed(c->opts.src_format) ? 1 : c->opts.src_range; - *dstRange = range_override_needed(c->opts.dst_format) ? 1 : c->opts.dst_range; + *srcRange = range_override_needed(sws->src_format) ? 1 : sws->src_range; + *dstRange = range_override_needed(sws->dst_format) ? 1 : sws->dst_range; *brightness = c->brightness; *contrast = c->contrast; *saturation = c->saturation; @@ -1321,10 +1320,10 @@ static av_cold int sws_init_single_context(SwsContext *sws, SwsFilter *srcFilter int unscaled; SwsInternal *c = sws_internal(sws); SwsFilter dummyFilter = { NULL, NULL, NULL, NULL }; - int srcW = c->opts.src_w; - int srcH = c->opts.src_h; - int dstW = c->opts.dst_w; - int dstH = c->opts.dst_h; + int srcW = sws->src_w; + int srcH = sws->src_h; + int dstW = sws->dst_w; + int dstH = sws->dst_h; int dst_stride = FFALIGN(dstW * sizeof(int16_t) + 66, 16); int flags, cpu_flags; enum AVPixelFormat srcFormat, dstFormat; @@ -1335,25 +1334,25 @@ static av_cold int sws_init_single_context(SwsContext *sws, SwsFilter *srcFilter static const float float_mult = 1.0f / 255.0f; cpu_flags = av_get_cpu_flags(); - flags = c->opts.flags; + flags = sws->flags; emms_c(); unscaled = (srcW == dstW && srcH == dstH); if (!c->contrast && !c->saturation && !c->dstFormatBpp) - sws_setColorspaceDetails(sws, ff_yuv2rgb_coeffs[SWS_CS_DEFAULT], c->opts.src_range, + sws_setColorspaceDetails(sws, ff_yuv2rgb_coeffs[SWS_CS_DEFAULT], sws->src_range, ff_yuv2rgb_coeffs[SWS_CS_DEFAULT], - c->opts.dst_range, 0, 1 << 16, 1 << 16); + sws->dst_range, 0, 1 << 16, 1 << 16); - handle_formats(c); - srcFormat = c->opts.src_format; - dstFormat = c->opts.dst_format; + handle_formats(sws); + srcFormat = sws->src_format; + dstFormat = sws->dst_format; desc_src = av_pix_fmt_desc_get(srcFormat); desc_dst = av_pix_fmt_desc_get(dstFormat); // If the source has no alpha then disable alpha blendaway if (c->src0Alpha) - c->opts.alpha_blend = SWS_ALPHA_BLEND_NONE; + sws->alpha_blend = SWS_ALPHA_BLEND_NONE; if (!(unscaled && sws_isSupportedEndiannessConversion(srcFormat) && av_pix_fmt_swap_endianness(srcFormat) == dstFormat)) { @@ -1390,7 +1389,7 @@ static av_cold int sws_init_single_context(SwsContext *sws, SwsFilter *srcFilter flags |= SWS_BICUBIC; else flags |= SWS_BICUBIC; - c->opts.flags = flags; + sws->flags = flags; } else if (i & (i - 1)) { av_log(c, AV_LOG_ERROR, "Exactly one scaler algorithm must be chosen, got %X\n", i); @@ -1407,7 +1406,7 @@ static av_cold int sws_init_single_context(SwsContext *sws, SwsFilter *srcFilter if (flags & SWS_FAST_BILINEAR) { if (srcW < 8 || dstW < 8) { flags ^= SWS_FAST_BILINEAR | SWS_BILINEAR; - c->opts.flags = flags; + sws->flags = flags; } } @@ -1440,46 +1439,46 @@ static av_cold int sws_init_single_context(SwsContext *sws, SwsFilter *srcFilter if (dstW&1) { av_log(c, AV_LOG_DEBUG, "Forcing full internal H chroma due to odd output size\n"); flags |= SWS_FULL_CHR_H_INT; - c->opts.flags = flags; + sws->flags = flags; } if ( c->chrSrcHSubSample == 0 && c->chrSrcVSubSample == 0 - && c->opts.dither != SWS_DITHER_BAYER //SWS_FULL_CHR_H_INT is currently not supported with SWS_DITHER_BAYER - && !(c->opts.flags & SWS_FAST_BILINEAR) + && sws->dither != SWS_DITHER_BAYER //SWS_FULL_CHR_H_INT is currently not supported with SWS_DITHER_BAYER + && !(sws->flags & SWS_FAST_BILINEAR) ) { av_log(c, AV_LOG_DEBUG, "Forcing full internal H chroma due to input having non subsampled chroma\n"); flags |= SWS_FULL_CHR_H_INT; - c->opts.flags = flags; + sws->flags = flags; } } - if (c->opts.dither == SWS_DITHER_AUTO) { + if (sws->dither == SWS_DITHER_AUTO) { if (flags & SWS_ERROR_DIFFUSION) - c->opts.dither = SWS_DITHER_ED; + sws->dither = SWS_DITHER_ED; } if(dstFormat == AV_PIX_FMT_BGR4_BYTE || dstFormat == AV_PIX_FMT_RGB4_BYTE || dstFormat == AV_PIX_FMT_BGR8 || dstFormat == AV_PIX_FMT_RGB8) { - if (c->opts.dither == SWS_DITHER_AUTO) - c->opts.dither = (flags & SWS_FULL_CHR_H_INT) ? SWS_DITHER_ED : SWS_DITHER_BAYER; + if (sws->dither == SWS_DITHER_AUTO) + sws->dither = (flags & SWS_FULL_CHR_H_INT) ? SWS_DITHER_ED : SWS_DITHER_BAYER; if (!(flags & SWS_FULL_CHR_H_INT)) { - if (c->opts.dither == SWS_DITHER_ED || c->opts.dither == SWS_DITHER_A_DITHER || c->opts.dither == SWS_DITHER_X_DITHER || c->opts.dither == SWS_DITHER_NONE) { + if (sws->dither == SWS_DITHER_ED || sws->dither == SWS_DITHER_A_DITHER || sws->dither == SWS_DITHER_X_DITHER || sws->dither == SWS_DITHER_NONE) { av_log(c, AV_LOG_DEBUG, "Desired dithering only supported in full chroma interpolation for destination format '%s'\n", av_get_pix_fmt_name(dstFormat)); flags |= SWS_FULL_CHR_H_INT; - c->opts.flags = flags; + sws->flags = flags; } } if (flags & SWS_FULL_CHR_H_INT) { - if (c->opts.dither == SWS_DITHER_BAYER) { + if (sws->dither == SWS_DITHER_BAYER) { av_log(c, AV_LOG_DEBUG, "Ordered dither is not supported in full chroma interpolation for destination format '%s'\n", av_get_pix_fmt_name(dstFormat)); - c->opts.dither = SWS_DITHER_ED; + sws->dither = SWS_DITHER_ED; } } } @@ -1489,7 +1488,7 @@ static av_cold int sws_init_single_context(SwsContext *sws, SwsFilter *srcFilter "%s output is not supported with half chroma resolution, switching to full\n", av_get_pix_fmt_name(dstFormat)); flags |= SWS_FULL_CHR_H_INT; - c->opts.flags = flags; + sws->flags = flags; } } @@ -1523,7 +1522,7 @@ static av_cold int sws_init_single_context(SwsContext *sws, SwsFilter *srcFilter "full chroma interpolation for destination format '%s' not yet implemented\n", av_get_pix_fmt_name(dstFormat)); flags &= ~SWS_FULL_CHR_H_INT; - c->opts.flags = flags; + sws->flags = flags; } if (isAnyRGB(dstFormat) && !(flags & SWS_FULL_CHR_H_INT)) c->chrDstHSubSample = 1; @@ -1585,7 +1584,7 @@ static av_cold int sws_init_single_context(SwsContext *sws, SwsFilter *srcFilter av_log(c, AV_LOG_INFO, "output width is not a multiple of 32 -> no MMXEXT scaler\n"); } - if (usesHFilter || isNBPS(c->opts.src_format) || is16BPS(c->opts.src_format) || isAnyRGB(c->opts.src_format)) + if (usesHFilter || isNBPS(sws->src_format) || is16BPS(sws->src_format) || isAnyRGB(sws->src_format)) c->canMMXEXTBeUsed = 0; } else c->canMMXEXTBeUsed = 0; @@ -1616,8 +1615,7 @@ static av_cold int sws_init_single_context(SwsContext *sws, SwsFilter *srcFilter c->gamma_value = 2.2; tmpFmt = AV_PIX_FMT_RGBA64LE; - - if (!unscaled && c->opts.gamma_flag && (srcFormat != tmpFmt || dstFormat != tmpFmt)) { + if (!unscaled && sws->gamma_flag && (srcFormat != tmpFmt || dstFormat != tmpFmt)) { SwsInternal *c2; c->cascaded_context[0] = NULL; @@ -1629,7 +1627,7 @@ static av_cold int sws_init_single_context(SwsContext *sws, SwsFilter *srcFilter c->cascaded_context[0] = sws_getContext(srcW, srcH, srcFormat, srcW, srcH, tmpFmt, flags, NULL, NULL, - c->opts.scaler_params); + sws->scaler_params); if (!c->cascaded_context[0]) { return AVERROR(ENOMEM); } @@ -1637,7 +1635,7 @@ static av_cold int sws_init_single_context(SwsContext *sws, SwsFilter *srcFilter c->cascaded_context[1] = sws_getContext(srcW, srcH, tmpFmt, dstW, dstH, tmpFmt, flags, srcFilter, dstFilter, - c->opts.scaler_params); + sws->scaler_params); if (!c->cascaded_context[1]) return AVERROR(ENOMEM); @@ -1669,7 +1667,7 @@ static av_cold int sws_init_single_context(SwsContext *sws, SwsFilter *srcFilter c->cascaded_context[2] = sws_getContext(dstW, dstH, tmpFmt, dstW, dstH, dstFormat, flags, NULL, NULL, - c->opts.scaler_params); + sws->scaler_params); if (!c->cascaded_context[2]) return AVERROR(ENOMEM); } @@ -1690,14 +1688,14 @@ static av_cold int sws_init_single_context(SwsContext *sws, SwsFilter *srcFilter c->cascaded_context[0] = sws_getContext(srcW, srcH, srcFormat, srcW, srcH, tmpFormat, flags, srcFilter, NULL, - c->opts.scaler_params); + sws->scaler_params); if (!c->cascaded_context[0]) return AVERROR(ENOMEM); c->cascaded_context[1] = sws_getContext(srcW, srcH, tmpFormat, dstW, dstH, dstFormat, flags, NULL, dstFilter, - c->opts.scaler_params); + sws->scaler_params); if (!c->cascaded_context[1]) return AVERROR(ENOMEM); return 0; @@ -1720,11 +1718,11 @@ static av_cold int sws_init_single_context(SwsContext *sws, SwsFilter *srcFilter if (CONFIG_SWSCALE_ALPHA && isALPHA(srcFormat) && !isALPHA(dstFormat)) { enum AVPixelFormat tmpFormat = alphaless_fmt(srcFormat); - if (tmpFormat != AV_PIX_FMT_NONE && c->opts.alpha_blend != SWS_ALPHA_BLEND_NONE) { + if (tmpFormat != AV_PIX_FMT_NONE && sws->alpha_blend != SWS_ALPHA_BLEND_NONE) { if (!unscaled || dstFormat != tmpFormat || usesHFilter || usesVFilter || - c->opts.src_range != c->opts.dst_range + sws->src_range != sws->dst_range ) { c->cascaded_mainindex = 1; ret = av_image_alloc(c->cascaded_tmp[0], c->cascaded_tmpStride[0], @@ -1734,22 +1732,22 @@ static av_cold int sws_init_single_context(SwsContext *sws, SwsFilter *srcFilter c->cascaded_context[0] = alloc_set_opts(srcW, srcH, srcFormat, srcW, srcH, tmpFormat, - flags, c->opts.scaler_params); + flags, sws->scaler_params); if (!c->cascaded_context[0]) return AVERROR(EINVAL); - sws_internal(c->cascaded_context[0])->opts.alpha_blend = c->opts.alpha_blend; + c->cascaded_context[0]->alpha_blend = sws->alpha_blend; ret = sws_init_context(c->cascaded_context[0], NULL , NULL); if (ret < 0) return ret; c->cascaded_context[1] = alloc_set_opts(srcW, srcH, tmpFormat, dstW, dstH, dstFormat, - flags, c->opts.scaler_params); + flags, sws->scaler_params); if (!c->cascaded_context[1]) return AVERROR(EINVAL); - sws_internal(c->cascaded_context[1])->opts.src_range = c->opts.src_range; - sws_internal(c->cascaded_context[1])->opts.dst_range = c->opts.dst_range; + c->cascaded_context[1]->src_range = sws->src_range; + c->cascaded_context[1]->dst_range = sws->dst_range; ret = sws_init_context(c->cascaded_context[1], srcFilter , dstFilter); if (ret < 0) return ret; @@ -1761,9 +1759,9 @@ static av_cold int sws_init_single_context(SwsContext *sws, SwsFilter *srcFilter /* alpha blend special case, note this has been split via cascaded contexts if its scaled */ if (unscaled && !usesHFilter && !usesVFilter && - c->opts.alpha_blend != SWS_ALPHA_BLEND_NONE && + sws->alpha_blend != SWS_ALPHA_BLEND_NONE && isALPHA(srcFormat) && - (c->opts.src_range == c->opts.dst_range || isAnyRGB(dstFormat)) && + (sws->src_range == sws->dst_range || isAnyRGB(dstFormat)) && alphaless_fmt(srcFormat) == dstFormat ) { c->convert_unscaled = ff_sws_alphablendaway; @@ -1777,7 +1775,7 @@ static av_cold int sws_init_single_context(SwsContext *sws, SwsFilter *srcFilter /* unscaled special cases */ if (unscaled && !usesHFilter && !usesVFilter && - (c->opts.src_range == c->opts.dst_range || isAnyRGB(dstFormat) || + (sws->src_range == sws->dst_range || isAnyRGB(dstFormat) || isFloat(srcFormat) || isFloat(dstFormat) || isBayer(srcFormat))){ ff_get_unscaled_swscale(c); @@ -1873,7 +1871,7 @@ static av_cold int sws_init_single_context(SwsContext *sws, SwsFilter *srcFilter srcW, dstW, filterAlign, 1 << 14, (flags & SWS_BICUBLIN) ? (flags | SWS_BICUBIC) : flags, cpu_flags, srcFilter->lumH, dstFilter->lumH, - c->opts.scaler_params, + sws->scaler_params, get_local_pos(c, 0, 0, 0), get_local_pos(c, 0, 0, 0))) < 0) goto fail; @@ -1884,9 +1882,9 @@ static av_cold int sws_init_single_context(SwsContext *sws, SwsFilter *srcFilter c->chrSrcW, c->chrDstW, filterAlign, 1 << 14, (flags & SWS_BICUBLIN) ? (flags | SWS_BILINEAR) : flags, cpu_flags, srcFilter->chrH, dstFilter->chrH, - c->opts.scaler_params, - get_local_pos(c, c->chrSrcHSubSample, c->opts.src_h_chr_pos, 0), - get_local_pos(c, c->chrDstHSubSample, c->opts.dst_h_chr_pos, 0))) < 0) + sws->scaler_params, + get_local_pos(c, c->chrSrcHSubSample, sws->src_h_chr_pos, 0), + get_local_pos(c, c->chrDstHSubSample, sws->dst_h_chr_pos, 0))) < 0) goto fail; if (ff_shuffle_filter_coefficients(c, c->hChrFilterPos, c->hChrFilterSize, c->hChrFilter, c->chrDstW) < 0) goto nomem; @@ -1903,7 +1901,7 @@ static av_cold int sws_init_single_context(SwsContext *sws, SwsFilter *srcFilter c->lumYInc, srcH, dstH, filterAlign, (1 << 12), (flags & SWS_BICUBLIN) ? (flags | SWS_BICUBIC) : flags, cpu_flags, srcFilter->lumV, dstFilter->lumV, - c->opts.scaler_params, + sws->scaler_params, get_local_pos(c, 0, 0, 1), get_local_pos(c, 0, 0, 1))) < 0) goto fail; @@ -1912,18 +1910,18 @@ static av_cold int sws_init_single_context(SwsContext *sws, SwsFilter *srcFilter filterAlign, (1 << 12), (flags & SWS_BICUBLIN) ? (flags | SWS_BILINEAR) : flags, cpu_flags, srcFilter->chrV, dstFilter->chrV, - c->opts.scaler_params, - get_local_pos(c, c->chrSrcVSubSample, c->opts.src_v_chr_pos, 1), - get_local_pos(c, c->chrDstVSubSample, c->opts.dst_v_chr_pos, 1))) < 0) + sws->scaler_params, + get_local_pos(c, c->chrSrcVSubSample, sws->src_v_chr_pos, 1), + get_local_pos(c, c->chrDstVSubSample, sws->dst_v_chr_pos, 1))) < 0) goto fail; #if HAVE_ALTIVEC - if (!FF_ALLOC_TYPED_ARRAY(c->vYCoeffsBank, c->vLumFilterSize * c->opts.dst_h) || + if (!FF_ALLOC_TYPED_ARRAY(c->vYCoeffsBank, c->vLumFilterSize * sws->dst_h) || !FF_ALLOC_TYPED_ARRAY(c->vCCoeffsBank, c->vChrFilterSize * c->chrDstH)) goto nomem; - for (i = 0; i < c->vLumFilterSize * c->opts.dst_h; i++) { + for (i = 0; i < c->vLumFilterSize * sws->dst_h; i++) { int j; short *p = (short *)&c->vYCoeffsBank[i]; for (j = 0; j < 8; j++) @@ -1940,10 +1938,10 @@ static av_cold int sws_init_single_context(SwsContext *sws, SwsFilter *srcFilter } for (i = 0; i < 4; i++) - if (!FF_ALLOCZ_TYPED_ARRAY(c->dither_error[i], c->opts.dst_w + 3)) + if (!FF_ALLOCZ_TYPED_ARRAY(c->dither_error[i], sws->dst_w + 3)) goto nomem; - c->needAlpha = (CONFIG_SWSCALE_ALPHA && isALPHA(c->opts.src_format) && isALPHA(c->opts.dst_format)) ? 1 : 0; + c->needAlpha = (CONFIG_SWSCALE_ALPHA && isALPHA(sws->src_format) && isALPHA(sws->dst_format)) ? 1 : 0; // 64 / c->scalingBpp is the same as 16 / sizeof(scaling_intermediate) c->uv_off = (dst_stride>>1) + 64 / (c->dstBpc &~ 7); @@ -1985,7 +1983,7 @@ static av_cold int sws_init_single_context(SwsContext *sws, SwsFilter *srcFilter av_log(c, AV_LOG_VERBOSE, "%dx%d -> %dx%d\n", srcW, srcH, dstW, dstH); av_log(c, AV_LOG_DEBUG, "lum srcW=%d srcH=%d dstW=%d dstH=%d xInc=%d yInc=%d\n", - c->opts.src_w, c->opts.src_h, c->opts.dst_w, c->opts.dst_h, c->lumXInc, c->lumYInc); + sws->src_w, sws->src_h, sws->dst_w, sws->dst_h, c->lumXInc, c->lumYInc); av_log(c, AV_LOG_DEBUG, "chr srcW=%d srcH=%d dstW=%d dstH=%d xInc=%d yInc=%d\n", c->chrSrcW, c->chrSrcH, c->chrDstW, c->chrDstH, @@ -2017,14 +2015,14 @@ fail: // FIXME replace things by appropriate error codes c->cascaded_context[0] = sws_getContext(srcW, srcH, srcFormat, tmpW, tmpH, tmpFormat, flags, srcFilter, NULL, - c->opts.scaler_params); + sws->scaler_params); if (!c->cascaded_context[0]) return AVERROR(ENOMEM); c->cascaded_context[1] = sws_getContext(tmpW, tmpH, tmpFormat, dstW, dstH, dstFormat, flags, NULL, dstFilter, - c->opts.scaler_params); + sws->scaler_params); if (!c->cascaded_context[1]) return AVERROR(ENOMEM); return 0; @@ -2039,41 +2037,38 @@ static int context_init_threaded(SwsContext *sws, int ret; ret = avpriv_slicethread_create(&c->slicethread, (void*) sws, - ff_sws_slice_worker, NULL, c->opts.threads); + ff_sws_slice_worker, NULL, sws->threads); if (ret == AVERROR(ENOSYS)) { - c->opts.threads = 1; + sws->threads = 1; return 0; } else if (ret < 0) return ret; - c->opts.threads = ret; + sws->threads = ret; - c->slice_ctx = av_calloc(c->opts.threads, sizeof(*c->slice_ctx)); - c->slice_err = av_calloc(c->opts.threads, sizeof(*c->slice_err)); + c->slice_ctx = av_calloc(sws->threads, sizeof(*c->slice_ctx)); + c->slice_err = av_calloc(sws->threads, sizeof(*c->slice_err)); if (!c->slice_ctx || !c->slice_err) return AVERROR(ENOMEM); - for (int i = 0; i < c->opts.threads; i++) { - SwsInternal *c2; - c->slice_ctx[i] = sws_alloc_context(); - if (!c->slice_ctx[i]) + for (int i = 0; i < sws->threads; i++) { + SwsContext *slice; + slice = c->slice_ctx[i] = sws_alloc_context(); + if (!slice) return AVERROR(ENOMEM); - c2 = sws_internal(c->slice_ctx[i]); - + sws_internal(slice)->parent = sws; c->nb_slice_ctx++; - c2->parent = sws; - ret = av_opt_copy((void*)c->slice_ctx[i], (void*)c); + ret = av_opt_copy(slice, sws); if (ret < 0) return ret; + slice->threads = 1; - c2->opts.threads = 1; - - ret = sws_init_single_context(c->slice_ctx[i], src_filter, dst_filter); + ret = sws_init_single_context(slice, src_filter, dst_filter); if (ret < 0) return ret; - if (c2->opts.dither == SWS_DITHER_ED) { + if (slice->dither == SWS_DITHER_ED) { av_log(c, AV_LOG_VERBOSE, "Error-diffusion dither is in use, scaling will be single-threaded."); break; @@ -2099,17 +2094,17 @@ av_cold int sws_init_context(SwsContext *sws, SwsFilter *srcFilter, if (ff_thread_once(&rgb2rgb_once, ff_sws_rgb2rgb_init) != 0) return AVERROR_UNKNOWN; - src_format = c->opts.src_format; - dst_format = c->opts.dst_format; - c->opts.src_range |= handle_jpeg(&c->opts.src_format); - c->opts.dst_range |= handle_jpeg(&c->opts.dst_format); + src_format = sws->src_format; + dst_format = sws->dst_format; + sws->src_range |= handle_jpeg(&sws->src_format); + sws->dst_range |= handle_jpeg(&sws->dst_format); - if (src_format != c->opts.src_format || dst_format != c->opts.dst_format) + if (src_format != sws->src_format || dst_format != sws->dst_format) av_log(c, AV_LOG_WARNING, "deprecated pixel format used, make sure you did set range correctly\n"); - if (c->opts.threads != 1) { + if (sws->threads != 1) { ret = context_init_threaded(sws, srcFilter, dstFilter); - if (ret < 0 || c->opts.threads > 1) + if (ret < 0 || sws->threads > 1) return ret; // threading disabled in this build, init as single-threaded } diff --git a/tests/checkasm/sw_gbrp.c b/tests/checkasm/sw_gbrp.c index b8ac7fdd1c..4fcb87cd5f 100644 --- a/tests/checkasm/sw_gbrp.c +++ b/tests/checkasm/sw_gbrp.c @@ -135,13 +135,13 @@ static void check_output_yuv2gbrp(void) fail(); c = sws_internal(sws); - c->opts.flags |= SWS_FULL_CHR_H_INT; + sws->flags |= SWS_FULL_CHR_H_INT; for (fmi = 0; fmi < FF_ARRAY_ELEMS(planar_fmts); fmi++) { for (fsi = 0; fsi < FILTER_SIZES; fsi++) { for (isi = 0; isi < FF_ARRAY_ELEMS(input_sizes); isi++ ) { desc = av_pix_fmt_desc_get(planar_fmts[fmi]); - c->opts.dst_format = planar_fmts[fmi]; + sws->dst_format = planar_fmts[fmi]; dstW = input_sizes[isi]; luma_filter_size = filter_sizes[fsi]; @@ -229,8 +229,8 @@ static void check_input_planar_rgb_to_y(void) for (fmi = 0; fmi < FF_ARRAY_ELEMS(planar_fmts); fmi++) { for (isi = 0; isi < FF_ARRAY_ELEMS(input_sizes); isi++ ) { desc = av_pix_fmt_desc_get(planar_fmts[fmi]); - c->opts.src_format = planar_fmts[fmi]; - c->opts.dst_format = AV_PIX_FMT_YUVA444P16; + sws->src_format = planar_fmts[fmi]; + sws->dst_format = AV_PIX_FMT_YUVA444P16; byte_size = 2; dstW = input_sizes[isi]; @@ -300,8 +300,8 @@ static void check_input_planar_rgb_to_uv(void) for (fmi = 0; fmi < FF_ARRAY_ELEMS(planar_fmts); fmi++) { for (isi = 0; isi < FF_ARRAY_ELEMS(input_sizes); isi++ ) { desc = av_pix_fmt_desc_get(planar_fmts[fmi]); - c->opts.src_format = planar_fmts[fmi]; - c->opts.dst_format = AV_PIX_FMT_YUVA444P16; + sws->src_format = planar_fmts[fmi]; + sws->dst_format = AV_PIX_FMT_YUVA444P16; byte_size = 2; dstW = input_sizes[isi]; @@ -373,8 +373,8 @@ static void check_input_planar_rgb_to_a(void) if (!(desc->flags & AV_PIX_FMT_FLAG_ALPHA)) continue; - c->opts.src_format = planar_fmts[fmi]; - c->opts.dst_format = AV_PIX_FMT_YUVA444P16; + sws->src_format = planar_fmts[fmi]; + sws->dst_format = AV_PIX_FMT_YUVA444P16; byte_size = 2; dstW = input_sizes[isi]; diff --git a/tests/checkasm/sw_range_convert.c b/tests/checkasm/sw_range_convert.c index f17050f524..bf14209987 100644 --- a/tests/checkasm/sw_range_convert.c +++ b/tests/checkasm/sw_range_convert.c @@ -73,16 +73,16 @@ static void check_lumConvertRange(int from) fail(); c = sws_internal(sws); - c->opts.src_range = from; - c->opts.dst_range = !from; + sws->src_range = from; + sws->dst_range = !from; for (int pfi = 0; pfi < FF_ARRAY_ELEMS(pixel_formats); pfi++) { enum AVPixelFormat pix_fmt = pixel_formats[pfi]; const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(pix_fmt); int bit_depth = desc->comp[0].depth; int sample_size = bit_depth == 16 ? sizeof(int32_t) : sizeof(int16_t); - c->opts.src_format = pix_fmt; - c->opts.dst_format = pix_fmt; + sws->src_format = pix_fmt; + sws->dst_format = pix_fmt; c->dstBpc = bit_depth; ff_sws_init_scale(c); for (int dstWi = 0; dstWi < FF_ARRAY_ELEMS(input_sizes); dstWi++) { @@ -123,16 +123,16 @@ static void check_chrConvertRange(int from) fail(); c = sws_internal(sws); - c->opts.src_range = from; - c->opts.dst_range = !from; + sws->src_range = from; + sws->dst_range = !from; for (int pfi = 0; pfi < FF_ARRAY_ELEMS(pixel_formats); pfi++) { enum AVPixelFormat pix_fmt = pixel_formats[pfi]; const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(pix_fmt); int bit_depth = desc->comp[0].depth; int sample_size = bit_depth == 16 ? sizeof(int32_t) : sizeof(int16_t); - c->opts.src_format = pix_fmt; - c->opts.dst_format = pix_fmt; + sws->src_format = pix_fmt; + sws->dst_format = pix_fmt; c->dstBpc = bit_depth; ff_sws_init_scale(c); for (int dstWi = 0; dstWi < FF_ARRAY_ELEMS(input_sizes); dstWi++) { diff --git a/tests/checkasm/sw_rgb.c b/tests/checkasm/sw_rgb.c index 65f8404d3f..05370c1e41 100644 --- a/tests/checkasm/sw_rgb.c +++ b/tests/checkasm/sw_rgb.c @@ -127,9 +127,10 @@ static int cmp_off_by_n(const uint8_t *ref, const uint8_t *test, size_t n, int a return 0; } -static void check_rgb24toyv12(SwsInternal *ctx) +static void check_rgb24toyv12(SwsContext *sws) { static const int input_sizes[] = {16, 128, 512, MAX_LINE_SIZE, -MAX_LINE_SIZE}; + SwsInternal *ctx = sws_internal(sws); LOCAL_ALIGNED_32(uint8_t, src, [BUFSIZE * 3]); LOCAL_ALIGNED_32(uint8_t, buf_y_0, [BUFSIZE]); @@ -353,8 +354,10 @@ static const enum AVPixelFormat rgb_formats[] = { AV_PIX_FMT_ARGB, }; -static void check_rgb_to_y(SwsInternal *ctx) +static void check_rgb_to_y(SwsContext *sws) { + SwsInternal *ctx = sws_internal(sws); + LOCAL_ALIGNED_16(uint8_t, src24, [MAX_LINE_SIZE * 3]); LOCAL_ALIGNED_16(uint8_t, src32, [MAX_LINE_SIZE * 4]); LOCAL_ALIGNED_32(uint8_t, dst0_y, [MAX_LINE_SIZE * 2]); @@ -370,7 +373,7 @@ static void check_rgb_to_y(SwsInternal *ctx) for (int i = 0; i < FF_ARRAY_ELEMS(rgb_formats); i++) { const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(rgb_formats[i]); - ctx->opts.src_format = rgb_formats[i]; + sws->src_format = rgb_formats[i]; ff_sws_init_scale(ctx); for (int j = 0; j < FF_ARRAY_ELEMS(input_sizes); j++) { @@ -389,15 +392,17 @@ static void check_rgb_to_y(SwsInternal *ctx) if (desc->nb_components == 3 || // only bench native endian formats - (ctx->opts.src_format == AV_PIX_FMT_RGB32 || ctx->opts.src_format == AV_PIX_FMT_RGB32_1)) + (sws->src_format == AV_PIX_FMT_RGB32 || sws->src_format == AV_PIX_FMT_RGB32_1)) bench_new(dst1_y, src, NULL, NULL, w, ctx->input_rgb2yuv_table, NULL); } } } } -static void check_rgb_to_uv(SwsInternal *ctx) +static void check_rgb_to_uv(SwsContext *sws) { + SwsInternal *ctx = sws_internal(sws); + LOCAL_ALIGNED_16(uint8_t, src24, [MAX_LINE_SIZE * 3]); LOCAL_ALIGNED_16(uint8_t, src32, [MAX_LINE_SIZE * 4]); LOCAL_ALIGNED_16(uint8_t, dst0_u, [MAX_LINE_SIZE * 2]); @@ -417,8 +422,8 @@ static void check_rgb_to_uv(SwsInternal *ctx) const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(src_fmt); ctx->chrSrcHSubSample = (i % 2) ? 0 : 1; - ctx->opts.src_format = src_fmt; - ctx->opts.dst_format = ctx->chrSrcHSubSample ? AV_PIX_FMT_YUV420P : AV_PIX_FMT_YUV444P; + sws->src_format = src_fmt; + sws->dst_format = ctx->chrSrcHSubSample ? AV_PIX_FMT_YUV420P : AV_PIX_FMT_YUV444P; ff_sws_init_scale(ctx); for (int j = 0; j < FF_ARRAY_ELEMS(input_sizes); j++) { @@ -441,7 +446,7 @@ static void check_rgb_to_uv(SwsInternal *ctx) if (desc->nb_components == 3 || // only bench native endian formats - (ctx->opts.src_format == AV_PIX_FMT_RGB32 || ctx->opts.src_format == AV_PIX_FMT_RGB32_1)) + (sws->src_format == AV_PIX_FMT_RGB32 || sws->src_format == AV_PIX_FMT_RGB32_1)) bench_new(dst1_u, dst1_v, NULL, src, src, w, ctx->input_rgb2yuv_table, NULL); } } @@ -451,7 +456,6 @@ static void check_rgb_to_uv(SwsInternal *ctx) void checkasm_check_sw_rgb(void) { SwsContext *sws; - SwsInternal *c; ff_sws_rgb2rgb_init(); @@ -485,14 +489,13 @@ void checkasm_check_sw_rgb(void) if (!sws) fail(); - c = sws_internal(sws); - check_rgb_to_y(c); + check_rgb_to_y(sws); report("rgb_to_y"); - check_rgb_to_uv(c); + check_rgb_to_uv(sws); report("rgb_to_uv"); - check_rgb24toyv12(c); + check_rgb24toyv12(sws); report("rgb24toyv12"); sws_freeContext(sws); diff --git a/tests/checkasm/sw_scale.c b/tests/checkasm/sw_scale.c index 82e2b1d5ce..350f2b73d4 100644 --- a/tests/checkasm/sw_scale.c +++ b/tests/checkasm/sw_scale.c @@ -123,12 +123,12 @@ static void check_yuv2yuv1(int accurate) randomize_buffers((uint8_t*)dither, 8); randomize_buffers((uint8_t*)src_pixels, LARGEST_INPUT_SIZE * sizeof(int16_t)); sws = sws_alloc_context(); - c = sws_internal(sws); if (accurate) - c->opts.flags |= SWS_ACCURATE_RND; + sws->flags |= SWS_ACCURATE_RND; if (sws_init_context(sws, NULL, NULL) < 0) fail(); + c = sws_internal(sws); ff_sws_init_scale(c); for (isi = 0; isi < FF_ARRAY_ELEMS(input_sizes); ++isi) { dstW = input_sizes[isi]; @@ -190,12 +190,12 @@ static void check_yuv2yuvX(int accurate) memset(dither, d_val, LARGEST_INPUT_SIZE); randomize_buffers((uint8_t*)src_pixels, LARGEST_FILTER * LARGEST_INPUT_SIZE * sizeof(int16_t)); sws = sws_alloc_context(); - c = sws_internal(sws); if (accurate) - c->opts.flags |= SWS_ACCURATE_RND; + sws->flags |= SWS_ACCURATE_RND; if (sws_init_context(sws, NULL, NULL) < 0) fail(); + c = sws_internal(sws); ff_sws_init_scale(c); for(isi = 0; isi < FF_ARRAY_ELEMS(input_sizes); ++isi){ dstW = input_sizes[isi]; @@ -341,20 +341,20 @@ static void check_hscale(void) filter[SRC_PIXELS * width + i] = rnd(); } - c->opts.dst_w = c->chrDstW = input_sizes[dstWi]; + sws->dst_w = c->chrDstW = input_sizes[dstWi]; ff_sws_init_scale(c); memcpy(filterAvx2, filter, sizeof(uint16_t) * (SRC_PIXELS * MAX_FILTER_WIDTH + MAX_FILTER_WIDTH)); - ff_shuffle_filter_coefficients(c, filterPosAvx, width, filterAvx2, c->opts.dst_w); + ff_shuffle_filter_coefficients(c, filterPosAvx, width, filterAvx2, sws->dst_w); - if (check_func(c->hcScale, "hscale_%d_to_%d__fs_%d_dstW_%d", c->srcBpc, c->dstBpc + 1, width, c->opts.dst_w)) { + if (check_func(c->hcScale, "hscale_%d_to_%d__fs_%d_dstW_%d", c->srcBpc, c->dstBpc + 1, width, sws->dst_w)) { memset(dst0, 0, SRC_PIXELS * sizeof(dst0[0])); memset(dst1, 0, SRC_PIXELS * sizeof(dst1[0])); - call_ref(NULL, dst0, c->opts.dst_w, src, filter, filterPos, width); - call_new(NULL, dst1, c->opts.dst_w, src, filterAvx2, filterPosAvx, width); - if (memcmp(dst0, dst1, c->opts.dst_w * sizeof(dst0[0]))) + call_ref(NULL, dst0, sws->dst_w, src, filter, filterPos, width); + call_new(NULL, dst1, sws->dst_w, src, filterAvx2, filterPosAvx, width); + if (memcmp(dst0, dst1, sws->dst_w * sizeof(dst0[0]))) fail(); - bench_new(NULL, dst0, c->opts.dst_w, src, filter, filterPosAvx, width); + bench_new(NULL, dst0, sws->dst_w, src, filter, filterPosAvx, width); } } } From patchwork Tue Nov 12 09:50:40 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Niklas Haas X-Patchwork-Id: 52697 Delivered-To: ffmpegpatchwork2@gmail.com Received: by 2002:a05:612c:6704:20b0:4a6:637d:5226 with SMTP id mp4-n2csp140675vqb; Tue, 12 Nov 2024 01:53:50 -0800 (PST) X-Forwarded-Encrypted: i=2; AJvYcCXoF4cQqKPUtQvW0hQYAUbUQQvjWSjmGfqc5O5WuDWZtn0XxAkkZTcgiIfz/zta/bEJUQrSx+tHQ8TYRhblat6e@gmail.com X-Google-Smtp-Source: AGHT+IFXBAhkzYY1+quo1indAF+2POxy/cV529IWH5BXMVJzcF//b9VlMy5Hjtmju5CZpTOkHSiw X-Received: by 2002:a17:907:6e8e:b0:a9a:5b78:cee5 with SMTP id a640c23a62f3a-a9eeffcefbbmr609062766b.9.1731405230306; Tue, 12 Nov 2024 01:53:50 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1731405230; cv=none; d=google.com; s=arc-20240605; b=TTVMcnOxiQdX18oocbUcoF7Q6cyya1hHZu9ESA9pyQo96I/D0vmuh41eu10RO1B1Lo TWQBxh6je6STfdb3E2ZauxGa7Dsk4W8Y4zEjYRiqsqLAlfTv/kvPL8ugOmpDRAyQ4rmp zzD+jDsntrFIARjckVIh+L3cViOufxyg2RdsVKLK044KWSTZJn7jn4I2XRrDgmexV9yo Bkk3ayrLSxbS7HiIYq8voJqmZq1Zz4H1URBLpeN1Cscae1TUMZsheRogJK6lJzvz2IZ9 gUKXDrRoKqeA6EHqXnJ9iDuyPpHEPStItsxNwwFHT1pUFWzn3Mi5t4whADsNz8f7ltWe QyFg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20240605; h=sender:errors-to:content-transfer-encoding:cc:reply-to :list-subscribe:list-help:list-post:list-archive:list-unsubscribe :list-id:precedence:subject:mime-version:references:in-reply-to :message-id:date:to:from:delivered-to; bh=TnBrD1F2bApNc/Wikv9nAKZ+eNoOLcDqs/iE3vZNmtA=; fh=xmAeKtysnShNOmkhiJmYkS30uw4Fu2hvBJ7qlIwukxQ=; b=Isfmt++9fchn0IyfTI25uDDE9+SHYRrCFfCPqpkZIFdWhwy+izGcDsPrtN78SAvwJh +GOggeHxt60hrHwKr4ZvvhLvNe+AyKMwXfjE8flf1WVFxmEPdkwcB7YXHhr3XEV/pDiL Sja+5X46Jsvgdiy6ZAqW8fFvlOvyG/jZwn3H7gg82uA2LQ8ZUa1zawlKJ9RFPChPLY1a 6KxHvqUOu7+azVdrgvb506gzZDnihJaTDO6b/c9Q4fk2ZeVGJaKZT/CalGVtIAwjoSm7 dsKQoicAtku8R0mJItGsABFDiGp5cvNGvB9weRcNcXIbUx6FCgy1pOtZLiR9clrH7CXK D/rQ==; dara=google.com ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org Return-Path: Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org. [79.124.17.100]) by mx.google.com with ESMTPS id a640c23a62f3a-a9ee0deeeddsi911731366b.605.2024.11.12.01.53.50 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 12 Nov 2024 01:53:50 -0800 (PST) Received-SPF: pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) client-ip=79.124.17.100; Authentication-Results: mx.google.com; spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id B2D7868DEBE; Tue, 12 Nov 2024 11:52:14 +0200 (EET) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from haasn.dev (haasn.dev [78.46.187.166]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 8B7CF68DE82 for ; Tue, 12 Nov 2024 11:52:02 +0200 (EET) Received: from haasn.dev (unknown [10.30.1.1]) by haasn.dev (Postfix) with ESMTP id 186C143F06; Tue, 12 Nov 2024 10:51:58 +0100 (CET) From: Niklas Haas To: ffmpeg-devel@ffmpeg.org Date: Tue, 12 Nov 2024 10:50:40 +0100 Message-ID: <20241112095154.483778-7-ffmpeg@haasn.xyz> X-Mailer: git-send-email 2.47.0 In-Reply-To: <20241112095154.483778-1-ffmpeg@haasn.xyz> References: <20241112095154.483778-1-ffmpeg@haasn.xyz> MIME-Version: 1.0 Subject: [FFmpeg-devel] [PATCH v6 06/12] swscale: organize and better document flags X-BeenThere: ffmpeg-devel@ffmpeg.org X-Mailman-Version: 2.1.29 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: Niklas Haas Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" X-TUID: n1aroIRHOyJ2 From: Niklas Haas Group them into an enum rather than random #defines, and document their behavior a bit more obviously. Of particular note, I discovered that SWS_DIRECT_BGR is not referenced anywhere else in the code base. As such, I have moved it to the deprecated section, alongside SWS_ERROR_DIFFUSION. Sponsored-by: Sovereign Tech Fund Signed-off-by: Niklas Haas --- libswscale/swscale.h | 116 ++++++++++++++++++++++++------------------- 1 file changed, 66 insertions(+), 50 deletions(-) diff --git a/libswscale/swscale.h b/libswscale/swscale.h index 4baef532b6..3996411dc8 100644 --- a/libswscale/swscale.h +++ b/libswscale/swscale.h @@ -91,6 +91,71 @@ typedef enum SwsAlphaBlend { SWS_ALPHA_BLEND_NB, /* not part of the ABI */ } SwsAlphaBlend; +typedef enum SwsFlags { + /** + * Scaler selection options. Only one may be active at a time. + */ + SWS_FAST_BILINEAR = 1 << 0, ///< fast bilinear filtering + SWS_BILINEAR = 1 << 1, ///< bilinear filtering + SWS_BICUBIC = 1 << 2, ///< 2-tap cubic B-spline + SWS_X = 1 << 3, ///< experimental + SWS_POINT = 1 << 4, ///< nearest neighbor + SWS_AREA = 1 << 5, ///< area averaging + SWS_BICUBLIN = 1 << 6, ///< bicubic luma, bilinear chroma + SWS_GAUSS = 1 << 7, ///< gaussian approximation + SWS_SINC = 1 << 8, ///< unwindowed sinc + SWS_LANCZOS = 1 << 9, ///< 3-tap sinc/sinc + SWS_SPLINE = 1 << 10, ///< cubic Keys spline + + /** + * Emit verbose log of scaling parameters. + */ + SWS_PRINT_INFO = 1 << 12, + + /** + * Perform full chroma upsampling when upscaling to RGB. + * + * For example, when converting 50x50 yuv420p to 100x100 rgba, setting this flag + * will scale the chroma plane from 25x25 to 100x100 (4:4:4), and then convert + * the 100x100 yuv444p image to rgba in the final output step. + * + * Without this flag, the chroma plane is instead scaled to 50x100 (4:2:2), + * with a single chroma sample being re-used for both of the horizontally + * adjacent RGBA output pixels. + */ + SWS_FULL_CHR_H_INT = 1 << 13, + + /** + * Perform full chroma interpolation when downscaling RGB sources. + * + * For example, when converting a 100x100 rgba source to 50x50 yuv444p, setting + * this flag will generate a 100x100 (4:4:4) chroma plane, which is then + * downscaled to the required 50x50. + * + * Without this flag, the chroma plane is instead generated at 50x100 (dropping + * every other pixel), before then being downscaled to the required 50x50 + * resolution. + */ + SWS_FULL_CHR_H_INP = 1 << 14, + + /** + * Force bit-exact output. This will prevent the use of platform-specific + * optimizations that may lead to slight difference in rounding, in favor + * of always maintaining exact bit output compatibility with the reference + * C code. + * + * Note: It is recommended to set both of these flags simultaneously. + */ + SWS_ACCURATE_RND = 1 << 18, + SWS_BITEXACT = 1 << 19, + + /** + * Deprecated flags. + */ + SWS_DIRECT_BGR = 1 << 15, ///< This flag has no effect + SWS_ERROR_DIFFUSION = 1 << 23, ///< Set `SwsContext.dither` instead +} SwsFlags; + /*********************************** * Context creation and management * ***********************************/ @@ -109,7 +174,7 @@ typedef struct SwsContext { void *opaque; /** - * Bitmask of SWS_*. + * Bitmask of SWS_*. See `SwsFlags` for details. */ unsigned flags; @@ -225,60 +290,11 @@ int sws_test_frame(const AVFrame *frame, int output); */ int sws_is_noop(const AVFrame *dst, const AVFrame *src); -/* values for the flags, the stuff on the command line is different */ -#define SWS_FAST_BILINEAR 1 -#define SWS_BILINEAR 2 -#define SWS_BICUBIC 4 -#define SWS_X 8 -#define SWS_POINT 0x10 -#define SWS_AREA 0x20 -#define SWS_BICUBLIN 0x40 -#define SWS_GAUSS 0x80 -#define SWS_SINC 0x100 -#define SWS_LANCZOS 0x200 -#define SWS_SPLINE 0x400 - #define SWS_SRC_V_CHR_DROP_MASK 0x30000 #define SWS_SRC_V_CHR_DROP_SHIFT 16 #define SWS_PARAM_DEFAULT 123456 -#define SWS_PRINT_INFO 0x1000 - -//the following 3 flags are not completely implemented - -/** - * Perform full chroma upsampling when upscaling to RGB. - * - * For example, when converting 50x50 yuv420p to 100x100 rgba, setting this flag - * will scale the chroma plane from 25x25 to 100x100 (4:4:4), and then convert - * the 100x100 yuv444p image to rgba in the final output step. - * - * Without this flag, the chroma plane is instead scaled to 50x100 (4:2:2), - * with a single chroma sample being re-used for both of the horizontally - * adjacent RGBA output pixels. - */ -#define SWS_FULL_CHR_H_INT 0x2000 - -/** - * Perform full chroma interpolation when downscaling RGB sources. - * - * For example, when converting a 100x100 rgba source to 50x50 yuv444p, setting - * this flag will generate a 100x100 (4:4:4) chroma plane, which is then - * downscaled to the required 50x50. - * - * Without this flag, the chroma plane is instead generated at 50x100 (dropping - * every other pixel), before then being downscaled to the required 50x50 - * resolution. - */ -#define SWS_FULL_CHR_H_INP 0x4000 - -#define SWS_DIRECT_BGR 0x8000 - -#define SWS_ACCURATE_RND 0x40000 -#define SWS_BITEXACT 0x80000 -#define SWS_ERROR_DIFFUSION 0x800000 - #define SWS_MAX_REDUCE_CUTOFF 0.002 #define SWS_CS_ITU709 1 From patchwork Tue Nov 12 09:50:41 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Niklas Haas X-Patchwork-Id: 52699 Delivered-To: ffmpegpatchwork2@gmail.com Received: by 2002:a05:612c:6704:20b0:4a6:637d:5226 with SMTP id mp4-n2csp144327vqb; Tue, 12 Nov 2024 02:01:15 -0800 (PST) X-Forwarded-Encrypted: i=2; AJvYcCWlYgH4VJz900YeQal/VR0EiabwPqDTvQYtm/z27ugmRlKrQkNzhM7kwJ6CpYJhZftaA1gR+X2KvbQvxv+OL3oZ@gmail.com X-Google-Smtp-Source: AGHT+IFJprzs0SMU2omd+ZTL0ZWjh3bjFj6FiBdH0wzb2S4lIrllgHe1lEci/QRerXjkEIALXqkl X-Received: by 2002:a17:907:9615:b0:a99:4b56:cf76 with SMTP id a640c23a62f3a-a9eefff1878mr1674170566b.47.1731405675342; Tue, 12 Nov 2024 02:01:15 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1731405675; cv=none; d=google.com; s=arc-20240605; b=ErainPLmL/QWXKd7vv2JOeQMN6YmCAZcLIo5W9L0mjnEeVg9d76gtOJzXA8uyJIwEf C5x5tYnNzw5X2sgHRgT4HcvnN8/TAlyXugGVzw36NrvpceQITy7WnkyaOz/WMx+eayR1 5qNiCvYzq8xxUxuUKF3V542DWaONFTQ8V/Jl1bY5TSteVxrdn9nutDCkyp/5yxwe0NY1 ARBI5HiXUfJhN4jvpBR1mmRGVbpmt1NEnZD7pVBORIcGJguS9I/+wAUoQMqnMSyXsLC1 c95cKdn39TkXnRRJwsHUqeTEigEu+O+Tb60VpqHHjEIpxGhoTSmc3wWgZUUVXIPs1YC3 1oZg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20240605; h=sender:errors-to:content-transfer-encoding:cc:reply-to :list-subscribe:list-help:list-post:list-archive:list-unsubscribe :list-id:precedence:subject:mime-version:references:in-reply-to :message-id:date:to:from:delivered-to; bh=iHLvSpAsyUee8cBkvEuF64jntk1EKY7GH0GFUGetjlY=; fh=xmAeKtysnShNOmkhiJmYkS30uw4Fu2hvBJ7qlIwukxQ=; b=QejIBVenLbqJoeTdUsHy2rjYa01p9j+ovWWZjab3PeMGVox5V2uPm4/S6xepJ6WEOr 321WSZT3o2JUqjEoPoh9MwxUUBnT/aWLuScYxQym9wj/VzlDUpXswwWTfgNyW+D2RLQY ZkRYUoRdu8MRirU7js2274DZIA0yO/gs54oxGACuwc+r5rulxb/c7TVzGHIPeFF+sjq2 62yDAnictemnyRYbKWa0vedHXf6oce1nlKHe1Rj7lU1tuyH28JLAAnBuV2AICMk5hJei oEVHVWr7XPIzl5tFlExq2rajR/LdN0fMO1VopW3ogcHhmmhPtLJ94pmCic0eLB3MThFO jGOQ==; dara=google.com ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org Return-Path: Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org. [79.124.17.100]) by mx.google.com with ESMTPS id 4fb4d7f45d1cf-5cf03c7c9e9si7908535a12.224.2024.11.12.02.01.15 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 12 Nov 2024 02:01:15 -0800 (PST) Received-SPF: pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) client-ip=79.124.17.100; Authentication-Results: mx.google.com; spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id DCDBB68DEBF; Tue, 12 Nov 2024 11:52:15 +0200 (EET) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from haasn.dev (haasn.dev [78.46.187.166]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 90D5668DE8B for ; Tue, 12 Nov 2024 11:52:02 +0200 (EET) Received: from haasn.dev (unknown [10.30.1.1]) by haasn.dev (Postfix) with ESMTP id 4D36047EC6; Tue, 12 Nov 2024 10:51:58 +0100 (CET) From: Niklas Haas To: ffmpeg-devel@ffmpeg.org Date: Tue, 12 Nov 2024 10:50:41 +0100 Message-ID: <20241112095154.483778-8-ffmpeg@haasn.xyz> X-Mailer: git-send-email 2.47.0 In-Reply-To: <20241112095154.483778-1-ffmpeg@haasn.xyz> References: <20241112095154.483778-1-ffmpeg@haasn.xyz> MIME-Version: 1.0 Subject: [FFmpeg-devel] [PATCH v6 07/12] swscale/internal: expose sws_init_single_context() internally X-BeenThere: ffmpeg-devel@ffmpeg.org X-Mailman-Version: 2.1.29 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: Niklas Haas Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" X-TUID: 6swrzb4K94Hn From: Niklas Haas Used by the graph API swscale wrapper, for now. Sponsored-by: Sovereign Tech Fund Signed-off-by: Niklas Haas --- libswscale/swscale_internal.h | 3 +++ libswscale/utils.c | 4 ++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/libswscale/swscale_internal.h b/libswscale/swscale_internal.h index 5218ab0921..7c9517975b 100644 --- a/libswscale/swscale_internal.h +++ b/libswscale/swscale_internal.h @@ -958,6 +958,9 @@ extern const int32_t ff_yuv2rgb_coeffs[11][4]; extern const AVClass ff_sws_context_class; +int sws_init_single_context(SwsContext *sws, SwsFilter *srcFilter, + SwsFilter *dstFilter); + /** * Set c->convert_unscaled to an unscaled converter if one exists for the * specific source and destination formats, bit depths, flags, etc. diff --git a/libswscale/utils.c b/libswscale/utils.c index a01138d11b..1b6f54fc30 100644 --- a/libswscale/utils.c +++ b/libswscale/utils.c @@ -1312,8 +1312,8 @@ static enum AVPixelFormat alphaless_fmt(enum AVPixelFormat fmt) } } -static av_cold int sws_init_single_context(SwsContext *sws, SwsFilter *srcFilter, - SwsFilter *dstFilter) +av_cold int sws_init_single_context(SwsContext *sws, SwsFilter *srcFilter, + SwsFilter *dstFilter) { int i; int usesVFilter, usesHFilter; From patchwork Tue Nov 12 09:50:42 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Niklas Haas X-Patchwork-Id: 52703 Delivered-To: ffmpegpatchwork2@gmail.com Received: by 2002:a05:612c:6704:20b0:4a6:637d:5226 with SMTP id mp4-n2csp145048vqb; Tue, 12 Nov 2024 02:02:51 -0800 (PST) X-Forwarded-Encrypted: i=2; AJvYcCW33EsL46ixhA8I44pkZi77Cy3X+PC6FBo+11AJVQmVc5hdFrjs7xRYHEmHonbvBfwyuOBHEqVPsBqM3NcuZym6@gmail.com X-Google-Smtp-Source: AGHT+IHFhFkuT+rpmQVhZBsyfAfDpb3qHwgDDnxH9A90J+s0lAbO3mNo5YwZb8B61ezTQW382c1g X-Received: by 2002:a17:907:3ea4:b0:a99:f0f4:463d with SMTP id a640c23a62f3a-aa1b10a1e74mr209689566b.26.1731405677258; Tue, 12 Nov 2024 02:01:17 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1731405677; cv=none; d=google.com; s=arc-20240605; b=lfPdyJOGLq8dLEwaxgtfpW0vEmdSmEdIZNrfAUDIl160RImDN2Cev44nNbsVytvTns nwUfDLT+NQAPVM/9zXPQ4zSL++YJeICw43WjZ3ySvbHBVXxFgpvsK4Ie6Heog2pO9NeV Xd2O15w6p2t/PRaAke27VmrV/AofdpD7bRjSUBIIuNpqDVpOJy9snqAvQwbSRbYYmzhN 8MS4J9dJCPGvpcGPDIPexW0GSBHafONEyRxLXhJH4g8gqjt2oOSKBXRqtuMCkIYQ1QLu BJDMBQq/hKJYGNPupGNJkzFZm3mJZ/U2XWJUyGxR3zimUEThZUW8KJxAQ+sRl0RszdyF z7fw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20240605; h=sender:errors-to:content-transfer-encoding:cc:reply-to :list-subscribe:list-help:list-post:list-archive:list-unsubscribe :list-id:precedence:subject:mime-version:references:in-reply-to :message-id:date:to:from:delivered-to; bh=Vxm6mr/oEAE2CLqNueWnfvoNNqh9L9Uy7ReuSp6A55o=; fh=xmAeKtysnShNOmkhiJmYkS30uw4Fu2hvBJ7qlIwukxQ=; b=SiNDggkF2jwPtEVNXu1tYQtRb8RYyMkLx2w/AXWX8VL50YAlaY1J3Q0kDt24C00Z82 ygH5q9REZybQ32Luns+v5J6/eY/mrU6yFyMGLikfANioP09VZMZ8HOOzMKMN4L5fnv/0 OKreRUilmr1UsGOeC/6QQqvk1/f3d4wKVyFeygb2Fcp3Xqp7aBo7E0lNMsIh6GZfaoTX G/gr2CH9pdUPrX9af5t62LEZ1AVr/rlPcSw85H34kZ1euWjVnbRBBARhqw7fRGgTHBhu XR8n3V7AKVzn1phUZusR1B4OI/Cy3AJbfH9PVUhcPYR4NPvkrRasw9duhse2ZKrrnj8v 4hww==; dara=google.com ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org Return-Path: Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org. [79.124.17.100]) by mx.google.com with ESMTPS id a640c23a62f3a-a9ee0dc17casi782114166b.432.2024.11.12.02.01.16 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 12 Nov 2024 02:01:17 -0800 (PST) Received-SPF: pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) client-ip=79.124.17.100; Authentication-Results: mx.google.com; spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id CC65768DE2A; Tue, 12 Nov 2024 11:52:17 +0200 (EET) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from haasn.dev (haasn.dev [78.46.187.166]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 8C28168DE8A for ; Tue, 12 Nov 2024 11:52:02 +0200 (EET) Received: from haasn.dev (unknown [10.30.1.1]) by haasn.dev (Postfix) with ESMTP id 8AE1A482D5; Tue, 12 Nov 2024 10:51:58 +0100 (CET) From: Niklas Haas To: ffmpeg-devel@ffmpeg.org Date: Tue, 12 Nov 2024 10:50:42 +0100 Message-ID: <20241112095154.483778-9-ffmpeg@haasn.xyz> X-Mailer: git-send-email 2.47.0 In-Reply-To: <20241112095154.483778-1-ffmpeg@haasn.xyz> References: <20241112095154.483778-1-ffmpeg@haasn.xyz> MIME-Version: 1.0 Subject: [FFmpeg-devel] [PATCH v6 08/12] swscale/graph: add new high-level scaler dispatch mechanism X-BeenThere: ffmpeg-devel@ffmpeg.org X-Mailman-Version: 2.1.29 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: Niklas Haas Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" X-TUID: 84IrzQzcgPt5 From: Niklas Haas This interface has been designed from the ground up to serve as a new framework for dispatching various scaling operations at a high level. This will eventually replace the old ad-hoc system of using cascaded contexts, as well as allowing us to plug in more dynamic scaling passes requiring intermediate steps, such as colorspace conversions, etc. The starter implementation merely piggybacks off the existing sws_init() and sws_scale(), functions, though it does bring the immediate improvement of splitting up cascaded functions and pre/post conversion functions into separate filter passes, which allows them to e.g. be executed in parallel even when the main scaler is required to be single threaded. Additionally, a dedicated (multi-threaded) noop memcpy pass substantially improves throughput of that fast path. Follow-up commits will eventually expand this to move all of the scaling decision logic into the graph init function, and also eliminate some of the current special cases. Sponsored-by: Sovereign Tech Fund Signed-off-by: Niklas Haas --- libswscale/Makefile | 1 + libswscale/graph.c | 597 ++++++++++++++++++++++++++++++++++++++++++++ libswscale/graph.h | 122 +++++++++ 3 files changed, 720 insertions(+) create mode 100644 libswscale/graph.c create mode 100644 libswscale/graph.h diff --git a/libswscale/Makefile b/libswscale/Makefile index 757997b401..81f32f4dd7 100644 --- a/libswscale/Makefile +++ b/libswscale/Makefile @@ -9,6 +9,7 @@ OBJS = alphablend.o \ hscale.o \ hscale_fast_bilinear.o \ gamma.o \ + graph.o \ half2float.o \ input.o \ options.o \ diff --git a/libswscale/graph.c b/libswscale/graph.c new file mode 100644 index 0000000000..e0388bac61 --- /dev/null +++ b/libswscale/graph.c @@ -0,0 +1,597 @@ +/* + * Copyright (C) 2024 Niklas Haas + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavutil/avassert.h" +#include "libavutil/error.h" +#include "libavutil/macros.h" +#include "libavutil/mem.h" +#include "libavutil/opt.h" +#include "libavutil/pixdesc.h" +#include "libavutil/slicethread.h" + +#include "libswscale/swscale.h" +#include "libswscale/utils.h" + +#include "swscale_internal.h" +#include "graph.h" + +/* slice_align should be a power of two, or 0 to disable slice threading */ +static SwsPass *pass_add(SwsGraph *graph, void *priv, int w, int h, + sws_filter_run_t run, SwsImg in, SwsImg out, + int slice_align) +{ + SwsPass *pass = av_mallocz(sizeof(*pass)); + int ret; + + pass->graph = graph; + pass->run = run; + pass->input = in; + pass->output = out; + pass->priv = priv; + pass->width = w; + pass->height = h; + + if (!slice_align) { + pass->slice_h = pass->height; + pass->num_slices = 1; + } else { + pass->slice_h = (pass->height + graph->num_threads - 1) / graph->num_threads; + pass->slice_h = FFALIGN(pass->slice_h, slice_align); + pass->num_slices = (pass->height + pass->slice_h - 1) / pass->slice_h; + } + + ret = av_dynarray_add_nofree(&graph->passes, &graph->num_passes, pass); + if (ret < 0) + av_freep(&pass); + return pass; +} + +/* Set output linesize before calling this */ +static int pass_alloc_output(SwsPass *pass) +{ + const int aligned_h = pass->num_slices * pass->slice_h; + const int *linesize = pass->output.linesize; + + size_t offset[4]; + size_t total_size = 0; + for (int i = 0; i < 4; i++) { + const size_t size = FFABS(linesize[i]) * aligned_h; + offset[i] = total_size; + total_size = FFALIGN(total_size + size, 16); + } + + av_assert0(!pass->buf); + pass->buf = av_malloc(total_size); + if (!pass->buf) + return AVERROR(ENOMEM); + + for (int i = 0; i < 4; i++) { + uint8_t *base = pass->buf + offset[i]; + if (linesize[i] < 0) + base -= linesize[i] * (aligned_h - 1); + pass->output.data[i] = linesize[i] ? base : NULL; + } + + return 0; +} + +static int vshift(enum AVPixelFormat fmt, int plane) +{ + const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(fmt); + const int is_pal = usePal(fmt); + const int is_chroma = (plane == 1 || plane == 2) && !is_pal; + return is_chroma ? desc->log2_chroma_h : 0; +} + +/* Shift an image vertically by y lines */ +static SwsImg shift_img(const SwsImg *img_base, int y) +{ + SwsImg img = *img_base; + for (int i = 0; i < 4 && img.data[i]; i++) + img.data[i] += (y >> vshift(img.fmt, i)) * img.linesize[i]; + return img; +} + +static void setup_swscale(const SwsImg *out, const SwsImg *in, + const SwsPass *pass) +{ + SwsContext *sws = pass->priv; + SwsInternal *c = sws_internal(sws); + if (sws->flags & SWS_BITEXACT && sws->dither == SWS_DITHER_ED && c->dither_error[0]) { + for (int i = 0; i < 4; i++) + memset(c->dither_error[i], 0, sizeof(c->dither_error[0][0]) * (sws->dst_w + 2)); + } + + if (usePal(sws->src_format)) + ff_update_palette(c, (const uint32_t *) in->data[1]); +} + +static void run_copy(const SwsImg *out_base, const SwsImg *in_base, + int y, int h, const SwsPass *pass) +{ + SwsImg in = shift_img(in_base, y); + SwsImg out = shift_img(out_base, y); + + for (int i = 0; i < FF_ARRAY_ELEMS(in.data) && in.data[i]; i++) { + const int lines = h >> vshift(in.fmt, i); + if (in.linesize[i] == out.linesize[i]) { + memcpy(out.data[i], in.data[i], lines * out.linesize[i]); + } else { + const int linesize = FFMIN(out.linesize[i], in.linesize[i]); + for (int j = 0; j < lines; j++) { + memcpy(out.data[i], in.data[i], linesize); + in.data[i] += in.linesize[i]; + out.data[i] += out.linesize[i]; + } + } + } +} + +static void run_rgb0(const SwsImg *out, const SwsImg *in, int y, int h, + const SwsPass *pass) +{ + SwsInternal *c = pass->priv; + const int x0 = c->src0Alpha - 1; + const int w4 = 4 * pass->width; + const int src_stride = in->linesize[0]; + const int dst_stride = out->linesize[0]; + const uint8_t *src = in->data[0] + y * src_stride; + uint8_t *dst = out->data[0] + y * dst_stride; + + for (int y = 0; y < h; y++) { + memcpy(dst, src, w4 * sizeof(*dst)); + for (int x = x0; x < w4; x += 4) + dst[x] = 0xFF; + + src += src_stride; + dst += dst_stride; + } +} + +static void run_xyz2rgb(const SwsImg *out, const SwsImg *in, int y, int h, + const SwsPass *pass) +{ + ff_xyz12Torgb48(pass->priv, out->data[0] + y * out->linesize[0], out->linesize[0], + in->data[0] + y * in->linesize[0], in->linesize[0], + pass->width, h); +} + +static void run_rgb2xyz(const SwsImg *out, const SwsImg *in, int y, int h, + const SwsPass *pass) +{ + ff_rgb48Toxyz12(pass->priv, out->data[0] + y * out->linesize[0], out->linesize[0], + in->data[0] + y * in->linesize[0], in->linesize[0], + pass->width, h); +} + +static inline SwsContext *slice_ctx(const SwsPass *pass, int y) +{ + SwsContext *sws = pass->priv; + SwsInternal *parent = sws_internal(sws); + if (pass->num_slices == 1) + return sws; + + av_assert1(parent->nb_slice_ctx == pass->num_slices); + sws = parent->slice_ctx[y / pass->slice_h]; + + if (usePal(sws->src_format)) { + SwsInternal *sub = sws_internal(sws); + memcpy(sub->pal_yuv, parent->pal_yuv, sizeof(sub->pal_yuv)); + memcpy(sub->pal_rgb, parent->pal_rgb, sizeof(sub->pal_rgb)); + } + + return sws; +} + +static void run_unscaled(const SwsImg *out, const SwsImg *in_base, + int y, int h, const SwsPass *pass) +{ + SwsContext *sws = slice_ctx(pass, y); + SwsInternal *c = sws_internal(sws); + const SwsImg in = shift_img(in_base, y); + + c->convert_unscaled(c, (const uint8_t *const *) in.data, in.linesize, y, h, + out->data, out->linesize); +} + +static void run_swscale(const SwsImg *out_base, const SwsImg *in, + int y, int h, const SwsPass *pass) +{ + SwsContext *sws = slice_ctx(pass, y); + SwsInternal *c = sws_internal(sws); + const SwsImg out = shift_img(out_base, y); + + ff_swscale(c, (const uint8_t *const *) in->data, in->linesize, 0, + sws->src_h, out.data, out.linesize, y, h); +} + +static void get_chroma_pos(SwsGraph *graph, int *h_chr_pos, int *v_chr_pos, + const SwsFormat *fmt) +{ + enum AVChromaLocation chroma_loc = fmt->loc; + const int sub_x = fmt->desc->log2_chroma_w; + const int sub_y = fmt->desc->log2_chroma_h; + int x_pos, y_pos; + + /* Explicitly default to center siting for compatibility with swscale */ + if (chroma_loc == AVCHROMA_LOC_UNSPECIFIED) { + chroma_loc = AVCHROMA_LOC_CENTER; + graph->incomplete |= sub_x || sub_y; + } + + /* av_chroma_location_enum_to_pos() always gives us values in the range from + * 0 to 256, but we need to adjust this to the true value range of the + * subsampling grid, which may be larger for h/v_sub > 1 */ + av_chroma_location_enum_to_pos(&x_pos, &y_pos, chroma_loc); + x_pos *= (1 << sub_x) - 1; + y_pos *= (1 << sub_y) - 1; + + /* Fix vertical chroma position for interlaced frames */ + if (sub_y && fmt->interlaced) { + /* When vertically subsampling, chroma samples are effectively only + * placed next to even rows. To access them from the odd field, we need + * to account for this shift by offsetting the distance of one luma row. + * + * For 4x vertical subsampling (v_sub == 2), they are only placed + * next to every *other* even row, so we need to shift by three luma + * rows to get to the chroma sample. */ + if (graph->field == FIELD_BOTTOM) + y_pos += (256 << sub_y) - 256; + + /* Luma row distance is doubled for fields, so halve offsets */ + y_pos >>= 1; + } + + /* Explicitly strip chroma offsets when not subsampling, because it + * interferes with the operation of flags like SWS_FULL_CHR_H_INP */ + *h_chr_pos = sub_x ? x_pos : -513; + *v_chr_pos = sub_y ? y_pos : -513; +} + +static int init_pass(SwsGraph *graph, SwsContext *sws, + SwsImg input, SwsImg output) +{ + SwsInternal *c = sws_internal(sws); + const int src_w = sws->src_w, src_h = sws->src_h; + const int dst_w = sws->dst_w, dst_h = sws->dst_h; + const int unscaled = src_w == dst_w && src_h == dst_h; + int align = c->dst_slice_align; + SwsPass *pass; + int ret; + + if (c->cascaded_context[0]) { + const int num_cascaded = c->cascaded_context[2] ? 3 : 2; + for (int i = 0; i < num_cascaded; i++) { + SwsContext *sub = c->cascaded_context[i]; + + if (i + 1 == num_cascaded) { + ret = init_pass(graph, sub, input, output); + } else { + /* Steal the intermediate buffers that were already allocated */ + SwsImg tmp = { .fmt = sub->dst_format }; + av_assert1(i < FF_ARRAY_ELEMS(c->cascaded_tmp)); + memcpy(tmp.data, c->cascaded_tmp[i], sizeof(tmp.data)); + memcpy(tmp.linesize, c->cascaded_tmpStride[i], sizeof(tmp.linesize)); + + ret = init_pass(graph, sub, input, tmp); + input = tmp; + } + + if (ret < 0) + return ret; + } + + return 0; + } + + if (sws->dither == SWS_DITHER_ED && !c->convert_unscaled) + align = 0; /* disable slice threading */ + + if (c->src0Alpha && !c->dst0Alpha && isALPHA(sws->dst_format)) { + SwsImg tmp = { + .linesize = { FFALIGN(src_w * sizeof(uint8_t[4]), 16) }, + .fmt = sws->dst_format, + }; + + SwsPass *sub = pass_add(graph, c, src_w, src_h, run_rgb0, input, tmp, 1); + if (!sub || pass_alloc_output(sub) < 0) + return AVERROR(ENOMEM); + input = sub->output; + } + + if (c->srcXYZ && !(c->dstXYZ && unscaled)) { + SwsImg tmp = { + .linesize = { FFALIGN(src_w * sizeof(uint16_t[3]), 16) }, + .fmt = sws->dst_format, + }; + + SwsPass *sub = pass_add(graph, c, src_w, src_h, run_xyz2rgb, input, tmp, 1); + if (!sub || pass_alloc_output(sub) < 0) + return AVERROR(ENOMEM); + input = sub->output; + } + + pass = pass_add(graph, sws, dst_w, dst_h, + c->convert_unscaled ? run_unscaled : run_swscale, + input, output, align); + if (!pass) + return AVERROR(ENOMEM); + pass->setup = setup_swscale; + + /** + * For slice threading, we need to create sub contexts, similar to how + * swscale normally handles it internally. The most important difference + * is that we handle cascaded contexts before threaded contexts; whereas + * context_init_threaded() does it the other way around. + */ + + if (pass->num_slices > 1) { + c->slice_ctx = av_calloc(pass->num_slices, sizeof(*c->slice_ctx)); + if (!c->slice_ctx) + return AVERROR(ENOMEM); + + for (int i = 0; i < pass->num_slices; i++) { + SwsContext *slice; + SwsInternal *c2; + slice = c->slice_ctx[i] = sws_alloc_context(); + if (!slice) + return AVERROR(ENOMEM); + c->nb_slice_ctx++; + + c2 = sws_internal(slice); + c2->parent = sws; + + ret = av_opt_copy(slice, sws); + if (ret < 0) + return ret; + + ret = sws_init_single_context(slice, NULL, NULL); + if (ret < 0) + return ret; + + sws_setColorspaceDetails(slice, c->srcColorspaceTable, + slice->src_range, c->dstColorspaceTable, + slice->dst_range, c->brightness, c->contrast, + c->saturation); + + for (int i = 0; i < FF_ARRAY_ELEMS(c->srcColorspaceTable); i++) { + c2->srcColorspaceTable[i] = c->srcColorspaceTable[i]; + c2->dstColorspaceTable[i] = c->dstColorspaceTable[i]; + } + } + } + + if (c->dstXYZ && !(c->srcXYZ && unscaled)) { + SwsPass *sub = pass_add(graph, c, dst_w, dst_h, run_rgb2xyz, output, output, 1); + if (!sub) + return AVERROR(ENOMEM); + } + + return 0; +} + +/** + * Sentinel values to refer to the overall image input / output during + * filter graph construction, as the true values are not known. + */ +static uint8_t sws_input_sentinel, sws_output_sentinel; + +static const SwsImg *resolve_img(SwsGraph *graph, const SwsImg *img) +{ + if (img->data[0] == &sws_input_sentinel) + return &graph->exec.input; + else if (img->data[0] == &sws_output_sentinel) + return &graph->exec.output; + else + return img; +} + +static int init_passes(SwsGraph *graph) +{ + SwsContext *const ctx = graph->ctx; + const SwsFormat *const src = &graph->src; + const SwsFormat *const dst = &graph->dst; + const SwsDither dither = ctx->dither; + SwsContext *sws; + int ret; + + const SwsImg input = { .data = { &sws_input_sentinel }, .fmt = src->format }; + const SwsImg output = { .data = { &sws_output_sentinel }, .fmt = dst->format }; + + graph->noop = ff_fmt_equal(dst, src); + if (graph->noop) { + /* Threaded memcpy pass */ + SwsPass *copy = pass_add(graph, NULL, dst->width, dst->height, + run_copy, input, output, 1); + if (!copy) + return AVERROR(ENOMEM); + return 0; + } + + graph->incomplete |= src->range == AVCOL_RANGE_UNSPECIFIED; + graph->incomplete |= dst->range == AVCOL_RANGE_UNSPECIFIED; + + sws = graph->sws = sws_alloc_context(); + if (!sws) + return AVERROR(ENOMEM); + + sws->flags = ctx->flags; + sws->dither = dither; + sws->src_w = src->width; + sws->src_h = src->height; + sws->src_format = src->format; + sws->src_range = src->range == AVCOL_RANGE_JPEG; + + sws->dst_w = dst->width; + sws->dst_h = dst->height; + sws->dst_format = dst->format; + sws->dst_range = dst->range == AVCOL_RANGE_JPEG; + get_chroma_pos(graph, &sws->src_h_chr_pos, &sws->src_v_chr_pos, src); + get_chroma_pos(graph, &sws->dst_h_chr_pos, &sws->dst_v_chr_pos, dst); + + ret = sws_init_context(sws, NULL, NULL); + if (ret < 0) + return ret; + + /* Set correct color matrices */ + { + int in_full, out_full, brightness, contrast, saturation; + const int *inv_table, *table; + sws_getColorspaceDetails(sws, (int **)&inv_table, &in_full, + (int **)&table, &out_full, + &brightness, &contrast, &saturation); + + inv_table = sws_getCoefficients(src->csp); + table = sws_getCoefficients(dst->csp); + + graph->incomplete |= src->csp != dst->csp && + (src->csp == AVCOL_SPC_UNSPECIFIED || + dst->csp == AVCOL_SPC_UNSPECIFIED); + + sws_setColorspaceDetails(sws, inv_table, in_full, table, out_full, + brightness, contrast, saturation); + } + + ret = init_pass(graph, sws, input, output); + if (ret < 0) + return ret; + + return 0; +} + +static void sws_graph_worker(void *priv, int jobnr, int threadnr, int nb_jobs, + int nb_threads) +{ + SwsGraph *graph = priv; + const SwsPass *pass = graph->exec.pass; + const SwsImg *input = resolve_img(graph, &pass->input); + const SwsImg *output = resolve_img(graph, &pass->output); + const int slice_y = jobnr * pass->slice_h; + const int slice_h = FFMIN(pass->slice_h, pass->height - slice_y); + + pass->run(output, input, slice_y, slice_h, pass); +} + +int sws_graph_create(SwsContext *ctx, const SwsFormat *dst, const SwsFormat *src, + int field, SwsGraph **out_graph) +{ + int ret; + SwsGraph *graph = av_mallocz(sizeof(*graph)); + if (!graph) + return AVERROR(ENOMEM); + + graph->ctx = ctx; + graph->src = *src; + graph->dst = *dst; + graph->field = field; + graph->opts = *ctx; + + graph->exec.input.fmt = src->format; + graph->exec.output.fmt = dst->format; + + ret = avpriv_slicethread_create(&graph->slicethread, (void *) graph, + sws_graph_worker, NULL, ctx->threads); + if (ret == AVERROR(ENOSYS)) + graph->num_threads = 1; + else if (ret < 0) + goto error; + else + graph->num_threads = ret; + + ret = init_passes(graph); + if (ret < 0) + goto error; + + *out_graph = graph; + return 0; + +error: + sws_graph_free(&graph); + return ret; +} + +void sws_graph_free(SwsGraph **pgraph) +{ + SwsGraph *graph = *pgraph; + if (!graph) + return; + + avpriv_slicethread_free(&graph->slicethread); + + for (int i = 0; i < graph->num_passes; i++) { + SwsPass *pass = graph->passes[i]; + if (pass->uninit) + pass->uninit(pass); + av_free(pass->buf); + av_free(pass); + } + av_free(graph->passes); + + sws_freeContext(graph->sws); + av_free(graph); + *pgraph = NULL; +} + +/* Tests only options relevant to SwsGraph */ +static int opts_equal(const SwsContext *c1, const SwsContext *c2) +{ + return c1->flags == c2->flags && + c1->threads == c2->threads && + c1->dither == c2->dither && + c1->alpha_blend == c2->alpha_blend && + c1->gamma_flag == c2->gamma_flag && + !memcmp(c1->scaler_params, c2->scaler_params, sizeof(c1->scaler_params)); + +} + +int sws_graph_reinit(SwsContext *ctx, const SwsFormat *dst, const SwsFormat *src, + int field, SwsGraph **out_graph) +{ + const SwsGraph *graph = *out_graph; + if (graph && ff_fmt_equal(&graph->src, src) && + ff_fmt_equal(&graph->dst, dst) && + opts_equal(ctx, &graph->opts)) + return 0; + + sws_graph_free(out_graph); + return sws_graph_create(ctx, dst, src, field, out_graph); +} + + +void sws_graph_run(SwsGraph *graph, uint8_t *const out_data[4], + const int out_linesize[4], + const uint8_t *const in_data[4], + const int in_linesize[4]) +{ + SwsImg *out = &graph->exec.output; + SwsImg *in = &graph->exec.input; + memcpy(out->data, out_data, sizeof(out->data)); + memcpy(out->linesize, out_linesize, sizeof(out->linesize)); + memcpy(in->data, in_data, sizeof(in->data)); + memcpy(in->linesize, in_linesize, sizeof(in->linesize)); + + for (int i = 0; i < graph->num_passes; i++) { + const SwsPass *pass = graph->passes[i]; + graph->exec.pass = pass; + if (pass->setup) + pass->setup(out, in, pass); + avpriv_slicethread_execute(graph->slicethread, pass->num_slices, 0); + } +} diff --git a/libswscale/graph.h b/libswscale/graph.h new file mode 100644 index 0000000000..8b4544973e --- /dev/null +++ b/libswscale/graph.h @@ -0,0 +1,122 @@ +/* + * Copyright (C) 2024 Niklas Haas + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef SWSCALE_GRAPH_H +#define SWSCALE_GRAPH_H + +#include "libavutil/slicethread.h" +#include "swscale.h" +#include "utils.h" + +/* Represents a view into a single field of frame data */ +typedef struct SwsImg { + enum AVPixelFormat fmt; + uint8_t *data[4]; /* points to y=0 */ + int linesize[4]; +} SwsImg; + +typedef struct SwsPass SwsPass; +typedef struct SwsGraph SwsGraph; + +/** + * Output `h` lines of filtered data. `out` and `in` point to the + * start of the image buffer for this pass. + */ +typedef void (*sws_filter_run_t)(const SwsImg *out, const SwsImg *in, + int y, int h, const SwsPass *pass); + +struct SwsPass { + const SwsGraph *graph; + uint8_t *buf; /* temporary buffer for this pass, freed automatically */ + + sws_filter_run_t run; + int width, height; /* new output size */ + int pixel_bytes; /* bytes per pixel */ + int slice_h; /* filter granularity */ + int num_slices; + + /* Filter input/output. */ + SwsImg input; + SwsImg output; + + /** + * Called once from the main thread before running the filter. Optional. + * `out` and `in` always point to the main image input/output, regardless + * of `input` and `output` fields. + */ + void (*setup)(const SwsImg *out, const SwsImg *in, const SwsPass *pass); + + void (*uninit)(const SwsPass *pass); /* optional */ + void *priv; +}; + +/* Filter graph, which represents a 'baked' pixel format conversion */ +typedef struct SwsGraph { + SwsContext *ctx; + AVSliceThread *slicethread; + int num_threads; /* resolved at init() time */ + int incomplete; /* set during init() if formats had to be inferred */ + SwsContext *sws; /* wrapped legacy context */ + + /* Sorted sequence of filter passes to apply */ + SwsPass **passes; + int num_passes; + + /* Overall image parameters and flags */ + SwsContext opts; + SwsFormat src, dst; + int field; + int noop; /* true if the graph is a no-op */ + + /* Temporary execution state inside sws_graph_run */ + struct { + const SwsPass *pass; /* current filter pass */ + SwsImg input; + SwsImg output; + } exec; +} SwsGraph; + +/** + * Allocate and initialize the filter graph. Returns 0 or a negative error. + */ +int sws_graph_create(SwsContext *ctx, const SwsFormat *dst, const SwsFormat *src, + int field, SwsGraph **out_graph); + +/** + * Uninitialize any state associate with this filter graph and free it. + */ +void sws_graph_free(SwsGraph **graph); + +/** + * Wrapper around sws_graph_create that does nothing if the format is + * unchanged. + */ +int sws_graph_reinit(SwsContext *ctx, const SwsFormat *dst, const SwsFormat *src, + int field, SwsGraph **graph); + +/** + * Dispatch the filter graph on a single field. Internally threaded. + */ +void sws_graph_run(SwsGraph *graph, uint8_t *const out_data[4], + const int out_linesize[4], + const uint8_t *const in_data[4], + const int in_linesize[4]); + +#endif /* SWSCALE_GRAPH_H */ From patchwork Tue Nov 12 09:50:43 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Niklas Haas X-Patchwork-Id: 52702 Delivered-To: ffmpegpatchwork2@gmail.com Received: by 2002:a05:612c:6704:20b0:4a6:637d:5226 with SMTP id mp4-n2csp144331vqb; Tue, 12 Nov 2024 02:01:16 -0800 (PST) X-Forwarded-Encrypted: i=2; AJvYcCXVGLnSR2JVf3d20RltAo3UYfXCir2cV2zxfA7KcR5rAs8oKhwrhF6nnu3hcvXHVw5yfEPZZv75glaasjLuHZUi@gmail.com X-Google-Smtp-Source: AGHT+IGg2S3d0JueVW7ef4dz+EH0lk1cmIQIPV34ZPyAXYXqYaVwCsCIj0pAEiWnIZ17tiMwH4q/ X-Received: by 2002:a05:6402:2690:b0:5c9:39d8:58b3 with SMTP id 4fb4d7f45d1cf-5cf0a447552mr12762619a12.23.1731405675913; Tue, 12 Nov 2024 02:01:15 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1731405675; cv=none; d=google.com; s=arc-20240605; b=PNtyR8VHY0Y//m+7ODjpVJ25WTV938e+n5JDCBK4JWJRBXS9GWGzDZZa0KtVEQ0fTi CU0Kk12d5fbIu8I7RA9kN7IgrNeXTBDr2npr3RzRkaHyahyDexfTs4lFLKoRPhFmuCk0 KrsqswFPUzq8mIyZnEo/rGMlmSd5whRPTx/diSmNGFE6jQfHCPz4/wEY3IL8Q4uYXpQQ Tzd9NZq5FQY7bvSQ8s6Xf2I7wtMPYgdmNYz9mHyfT4dg2UIyxaLLShiwYcIL8wj9hDRx TLcueOhqRJ63vFUIDyGDJ4uiZ4cn3IQ+imHfUOrQLAVcVdVJgPIKKQBRCuo3DKqEBbqQ acwA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20240605; h=sender:errors-to:content-transfer-encoding:cc:reply-to :list-subscribe:list-help:list-post:list-archive:list-unsubscribe :list-id:precedence:subject:mime-version:references:in-reply-to :message-id:date:to:from:delivered-to; bh=tKsoEtHsD37bqgL3WR6Yhx+xFAV/qIysIZ93Q3A3X14=; fh=xmAeKtysnShNOmkhiJmYkS30uw4Fu2hvBJ7qlIwukxQ=; b=c6kVNY58xCJ6DoM86vtNiJneOoDf1oujz1cFOxos2ipODYa/WTMWmt2pEzdzuGvzs4 /9XNfgF1j2EyK5kagAfZuLiyAW6M/x4wlt/sSYH8tFL4d20Y1HZ05jqeunMrs17LSYKb g0jsiBB/t7lvyc1ryZ88D8lHhRRoFu4VmSXF5WjabEDPJSQq+fP4pVdYqC+yUVTDJ4Xq Xd9OrQK9YGc840+0eae+soD7S+z0XpBsQxTmjvRUd3vuqpmeODMNC9VMLk+UFtk19zvn O8/lE1uXkpqWyUQqLRPQWPDQo1sjiPx6FWQC9RHCtxwFoPhKRf6UkUcR80CxYlg2S6Fg 2juA==; dara=google.com ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org Return-Path: Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org. [79.124.17.100]) by mx.google.com with ESMTPS id 4fb4d7f45d1cf-5cf03cbba18si8052496a12.477.2024.11.12.02.01.15 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 12 Nov 2024 02:01:15 -0800 (PST) Received-SPF: pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) client-ip=79.124.17.100; Authentication-Results: mx.google.com; spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 0BB9A68DED3; Tue, 12 Nov 2024 11:52:19 +0200 (EET) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from haasn.dev (haasn.dev [78.46.187.166]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 8BCA168DE86 for ; Tue, 12 Nov 2024 11:52:02 +0200 (EET) Received: from haasn.dev (unknown [10.30.1.1]) by haasn.dev (Postfix) with ESMTP id C1339483CA; Tue, 12 Nov 2024 10:51:58 +0100 (CET) From: Niklas Haas To: ffmpeg-devel@ffmpeg.org Date: Tue, 12 Nov 2024 10:50:43 +0100 Message-ID: <20241112095154.483778-10-ffmpeg@haasn.xyz> X-Mailer: git-send-email 2.47.0 In-Reply-To: <20241112095154.483778-1-ffmpeg@haasn.xyz> References: <20241112095154.483778-1-ffmpeg@haasn.xyz> MIME-Version: 1.0 Subject: [FFmpeg-devel] [PATCH v6 09/12] swscale: introduce new, dynamic scaling API X-BeenThere: ffmpeg-devel@ffmpeg.org X-Mailman-Version: 2.1.29 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: Niklas Haas Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" X-TUID: +thAOl7Dx+88 From: Niklas Haas As part of a larger, ongoing effort to modernize and partially rewrite libswscale, it was decided and generally agreed upon to introduce a new public API for libswscale. This API is designed to be less stateful, more explicitly defined, and considerably easier to use than the existing one. Most of the API work has been already accomplished in the previous commits, this commit merely introduces the ability to use sws_scale_frame() dynamically, without prior sws_init_context() calls. Instead, the new API takes frame properties from the frames themselves, and the implementation is based on the new SwsGraph API, which we simply reinitialize as needed. This high-level wrapper also recreates the logic that used to live inside vf_scale for scaling interlaced frames, enabling it to be reused more easily by end users. Finally, this function is designed to simply copy refs directly when nothing needs to be done, substantially improving throughput of the noop fast path. Sponsored-by: Sovereign Tech Fund Signed-off-by: Niklas Haas --- libswscale/swscale.c | 196 ++++++++++++++++++++++++++++++++-- libswscale/swscale.h | 89 +++++++++++---- libswscale/swscale_internal.h | 7 +- libswscale/utils.c | 4 + libswscale/x86/output.asm | 2 +- 5 files changed, 269 insertions(+), 29 deletions(-) diff --git a/libswscale/swscale.c b/libswscale/swscale.c index 45172dcea4..d3dac44d04 100644 --- a/libswscale/swscale.c +++ b/libswscale/swscale.c @@ -1219,21 +1219,205 @@ int sws_receive_slice(SwsContext *sws, unsigned int slice_start, dst, c->frame_dst->linesize, slice_start, slice_height); } +static void get_frame_pointers(const AVFrame *frame, uint8_t *data[4], + int linesize[4], int field) +{ + for (int i = 0; i < 4; i++) { + data[i] = frame->data[i]; + linesize[i] = frame->linesize[i]; + } + + if (!(frame->flags & AV_FRAME_FLAG_INTERLACED)) { + av_assert1(!field); + return; + } + + if (field == FIELD_BOTTOM) { + /* Odd rows, offset by one line */ + const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(frame->format); + for (int i = 0; i < 4; i++) { + data[i] += linesize[i]; + if (desc->flags & AV_PIX_FMT_FLAG_PAL) + break; + } + } + + /* Take only every second line */ + for (int i = 0; i < 4; i++) + linesize[i] <<= 1; +} + +/* Subset of av_frame_ref() that only references (video) data buffers */ +static int frame_ref(AVFrame *dst, const AVFrame *src) +{ + /* ref the buffers */ + for (int i = 0; i < FF_ARRAY_ELEMS(src->buf); i++) { + if (!src->buf[i]) + continue; + dst->buf[i] = av_buffer_ref(src->buf[i]); + if (!dst->buf[i]) + return AVERROR(ENOMEM); + } + + memcpy(dst->data, src->data, sizeof(src->data)); + memcpy(dst->linesize, src->linesize, sizeof(src->linesize)); + return 0; +} + int sws_scale_frame(SwsContext *sws, AVFrame *dst, const AVFrame *src) { int ret; + SwsInternal *c = sws_internal(sws); + if (!src || !dst) + return AVERROR(EINVAL); + + if (c->frame_src) { + /* Context has been initialized with explicit values, fall back to + * legacy API */ + ret = sws_frame_start(sws, dst, src); + if (ret < 0) + return ret; + + ret = sws_send_slice(sws, 0, src->height); + if (ret >= 0) + ret = sws_receive_slice(sws, 0, dst->height); - ret = sws_frame_start(sws, dst, src); + sws_frame_end(sws); + + return ret; + } + + ret = sws_frame_setup(sws, dst, src); if (ret < 0) return ret; - ret = sws_send_slice(sws, 0, src->height); - if (ret >= 0) - ret = sws_receive_slice(sws, 0, dst->height); + if (!src->data[0]) + return 0; - sws_frame_end(sws); + if (c->graph[FIELD_TOP]->noop && + (!c->graph[FIELD_BOTTOM] || c->graph[FIELD_BOTTOM]->noop) && + src->buf[0] && !dst->buf[0] && !dst->data[0]) + { + /* Lightweight refcopy */ + ret = frame_ref(dst, src); + if (ret < 0) + return ret; + } else { + if (!dst->data[0]) { + ret = av_frame_get_buffer(dst, 0); + if (ret < 0) + return ret; + } - return ret; + for (int field = 0; field < 2; field++) { + SwsGraph *graph = c->graph[field]; + uint8_t *dst_data[4], *src_data[4]; + int dst_linesize[4], src_linesize[4]; + get_frame_pointers(dst, dst_data, dst_linesize, field); + get_frame_pointers(src, src_data, src_linesize, field); + sws_graph_run(graph, dst_data, dst_linesize, + (const uint8_t **) src_data, src_linesize); + if (!graph->dst.interlaced) + break; + } + } + + return 0; +} + +static int validate_params(SwsContext *ctx) +{ +#define VALIDATE(field, min, max) \ + if (ctx->field < min || ctx->field > max) { \ + av_log(ctx, AV_LOG_ERROR, "'%s' (%d) out of range [%d, %d]\n", \ + #field, (int) ctx->field, min, max); \ + return AVERROR(EINVAL); \ + } + + VALIDATE(threads, 0, 8192); + VALIDATE(dither, 0, SWS_DITHER_NB - 1) + VALIDATE(alpha_blend, 0, SWS_ALPHA_BLEND_NB - 1) + return 0; +} + +int sws_frame_setup(SwsContext *ctx, const AVFrame *dst, const AVFrame *src) +{ + SwsInternal *s = sws_internal(ctx); + const char *err_msg; + int ret; + + if (!src || !dst) + return AVERROR(EINVAL); + if ((ret = validate_params(ctx)) < 0) + return ret; + + for (int field = 0; field < 2; field++) { + SwsFormat src_fmt = ff_fmt_from_frame(src, field); + SwsFormat dst_fmt = ff_fmt_from_frame(dst, field); + + if ((src->flags ^ dst->flags) & AV_FRAME_FLAG_INTERLACED) { + err_msg = "Cannot convert interlaced to progressive frames or vice versa.\n"; + ret = AVERROR(EINVAL); + goto fail; + } + + /* TODO: remove once implemented */ + if ((dst_fmt.prim != src_fmt.prim || dst_fmt.trc != src_fmt.trc) && + !s->color_conversion_warned) + { + av_log(ctx, AV_LOG_WARNING, "Conversions between different primaries / " + "transfer functions are not currently implemented, expect " + "wrong results.\n"); + s->color_conversion_warned = 1; + } + + if (!ff_test_fmt(&src_fmt, 0)) { + err_msg = "Unsupported input"; + ret = AVERROR(ENOTSUP); + goto fail; + } + + if (!ff_test_fmt(&dst_fmt, 1)) { + err_msg = "Unsupported output"; + ret = AVERROR(ENOTSUP); + goto fail; + } + + ret = sws_graph_reinit(ctx, &dst_fmt, &src_fmt, field, &s->graph[field]); + if (ret < 0) { + err_msg = "Failed initializing scaling graph"; + goto fail; + } + + if (s->graph[field]->incomplete && ctx->flags & SWS_STRICT) { + err_msg = "Incomplete scaling graph"; + ret = AVERROR(EINVAL); + goto fail; + } + + if (!src_fmt.interlaced) { + sws_graph_free(&s->graph[FIELD_BOTTOM]); + break; + } + + continue; + + fail: + av_log(ctx, AV_LOG_ERROR, "%s (%s): fmt:%s csp:%s prim:%s trc:%s ->" + " fmt:%s csp:%s prim:%s trc:%s\n", + err_msg, av_err2str(ret), + av_get_pix_fmt_name(src_fmt.format), av_color_space_name(src_fmt.csp), + av_color_primaries_name(src_fmt.prim), av_color_transfer_name(src_fmt.trc), + av_get_pix_fmt_name(dst_fmt.format), av_color_space_name(dst_fmt.csp), + av_color_primaries_name(dst_fmt.prim), av_color_transfer_name(dst_fmt.trc)); + + for (int i = 0; i < FF_ARRAY_ELEMS(s->graph); i++) + sws_graph_free(&s->graph[i]); + + return ret; + } + + return 0; } /** diff --git a/libswscale/swscale.h b/libswscale/swscale.h index 3996411dc8..fa3a0f01ab 100644 --- a/libswscale/swscale.h +++ b/libswscale/swscale.h @@ -107,6 +107,12 @@ typedef enum SwsFlags { SWS_LANCZOS = 1 << 9, ///< 3-tap sinc/sinc SWS_SPLINE = 1 << 10, ///< cubic Keys spline + /** + * Return an error on underspecified conversions. Without this flag, + * unspecified fields are defaulted to sensible values. + */ + SWS_STRICT = 1 << 11, + /** * Emit verbose log of scaling parameters. */ @@ -204,7 +210,10 @@ typedef struct SwsContext { int gamma_flag; /** - * Frame property overrides. + * Deprecated frame property overrides, for the legacy API only. + * + * Ignored by sws_scale_frame() when used in dynamic mode, in which + * case all properties are instead taken from the frame directly. */ int src_w, src_h; ///< Width and height of the source frame int dst_w, dst_h; ///< Width and height of the destination frame @@ -216,6 +225,8 @@ typedef struct SwsContext { int src_h_chr_pos; ///< Source horizontal chroma position int dst_v_chr_pos; ///< Destination vertical chroma position int dst_h_chr_pos; ///< Destination horizontal chroma position + + /* Remember to add new fields to graph.c:opts_equal() */ } SwsContext; /** @@ -284,12 +295,57 @@ int sws_test_transfer(enum AVColorTransferCharacteristic trc, int output); */ int sws_test_frame(const AVFrame *frame, int output); +/** + * Like `sws_scale_frame`, but without actually scaling. It will instead + * merely initialize internal state that *would* be required to perform the + * operation, as well as returning the correct error code for unsupported + * frame combinations. + * + * @param ctx The scaling context. + * @param dst The destination frame to consider. + * @param src The source frame to consider. + * @return 0 on success, a negative AVERROR code on failure. + */ +int sws_frame_setup(SwsContext *ctx, const AVFrame *dst, const AVFrame *src); + +/******************** + * Main scaling API * + ********************/ + /** * Check if a given conversion is a noop. Returns a positive integer if * no operation needs to be performed, 0 otherwise. */ int sws_is_noop(const AVFrame *dst, const AVFrame *src); +/** + * Scale source data from `src` and write the output to `dst`. + * + * This function can be used directly on an allocated context, without setting + * up any frame properties or calling `sws_init_context()`. Such usage is fully + * dynamic and does not require reallocation if the frame properties change. + * + * Alternatively, this function can be called on a context that has been + * explicitly initialized. However, this is provided only for backwards + * compatibility. In this usage mode, all frame properties must be correctly + * set at init time, and may no longer change after initialization. + * + * @param ctx The scaling context. + * @param dst The destination frame. The data buffers may either be already + * allocated by the caller or left clear, in which case they will + * be allocated by the scaler. The latter may have performance + * advantages - e.g. in certain cases some (or all) output planes + * may be references to input planes, rather than copies. + * @param src The source frame. If the data buffers are set to NULL, then + * this function behaves identically to `sws_frame_setup`. + * @return 0 on success, a negative AVERROR code on failure. + */ +int sws_scale_frame(SwsContext *c, AVFrame *dst, const AVFrame *src); + +/************************* + * Legacy (stateful) API * + *************************/ + #define SWS_SRC_V_CHR_DROP_MASK 0x30000 #define SWS_SRC_V_CHR_DROP_SHIFT 16 @@ -352,6 +408,11 @@ int sws_isSupportedEndiannessConversion(enum AVPixelFormat pix_fmt); /** * Initialize the swscaler context sws_context. * + * This function is considered deprecated, and provided only for backwards + * compatibility with sws_scale() and sws_start_frame(). The preferred way to + * use libswscale is to set all frame properties correctly and call + * sws_scale_frame() directly, without explicitly initializing the context. + * * @return zero or positive value on success, a negative value on * error */ @@ -393,7 +454,8 @@ SwsContext *sws_getContext(int srcW, int srcH, enum AVPixelFormat srcFormat, /** * Scale the image slice in srcSlice and put the resulting scaled * slice in the image in dst. A slice is a sequence of consecutive - * rows in an image. + * rows in an image. Requires a context that has been previously + * been initialized with sws_init_context(). * * Slices have to be provided in sequential order, either in * top-bottom or bottom-top order. If slices are provided in @@ -420,27 +482,11 @@ int sws_scale(SwsContext *c, const uint8_t *const srcSlice[], const int srcStride[], int srcSliceY, int srcSliceH, uint8_t *const dst[], const int dstStride[]); -/** - * Scale source data from src and write the output to dst. - * - * This is merely a convenience wrapper around - * - sws_frame_start() - * - sws_send_slice(0, src->height) - * - sws_receive_slice(0, dst->height) - * - sws_frame_end() - * - * @param c The scaling context - * @param dst The destination frame. See documentation for sws_frame_start() for - * more details. - * @param src The source frame. - * - * @return 0 on success, a negative AVERROR code on failure - */ -int sws_scale_frame(SwsContext *c, AVFrame *dst, const AVFrame *src); - /** * Initialize the scaling process for a given pair of source/destination frames. * Must be called before any calls to sws_send_slice() and sws_receive_slice(). + * Requires a context that has been previously been initialized with + * sws_init_context(). * * This function will retain references to src and dst, so they must both use * refcounted buffers (if allocated by the caller, in case of dst). @@ -511,7 +557,8 @@ int sws_receive_slice(SwsContext *c, unsigned int slice_start, unsigned int slice_height); /** - * Get the alignment required for slices + * Get the alignment required for slices. Requires a context that has been + * previously been initialized with sws_init_context(). * * @param c The scaling context * @return alignment required for output slices requested with sws_receive_slice(). diff --git a/libswscale/swscale_internal.h b/libswscale/swscale_internal.h index 7c9517975b..80487e5275 100644 --- a/libswscale/swscale_internal.h +++ b/libswscale/swscale_internal.h @@ -26,6 +26,7 @@ #include "config.h" #include "swscale.h" +#include "graph.h" #include "libavutil/avassert.h" #include "libavutil/common.h" @@ -323,6 +324,9 @@ struct SwsInternal { int *slice_err; int nb_slice_ctx; + /* Scaling graph, reinitialized dynamically as needed. */ + SwsGraph *graph[2]; /* top, bottom fields */ + // values passed to current sws_receive_slice() call int dst_slice_start; int dst_slice_height; @@ -663,6 +667,7 @@ struct SwsInternal { unsigned int dst_slice_align; atomic_int stride_unaligned_warned; atomic_int data_unaligned_warned; + int color_conversion_warned; Half2FloatTables *h2f_tables; }; @@ -674,7 +679,7 @@ static_assert(offsetof(SwsInternal, redDither) + DITHER32_INT == offsetof(SwsInt #if ARCH_X86_64 /* x86 yuv2gbrp uses the SwsInternal for yuv coefficients if struct offsets change the asm needs to be updated too */ -static_assert(offsetof(SwsInternal, yuv2rgb_y_offset) == 40316, +static_assert(offsetof(SwsInternal, yuv2rgb_y_offset) == 40332, "yuv2rgb_y_offset must be updated in x86 asm"); #endif diff --git a/libswscale/utils.c b/libswscale/utils.c index 1b6f54fc30..628a3f1091 100644 --- a/libswscale/utils.c +++ b/libswscale/utils.c @@ -61,6 +61,7 @@ #include "swscale.h" #include "swscale_internal.h" #include "utils.h" +#include "graph.h" typedef struct FormatEntry { uint8_t is_supported_in :1; @@ -2450,6 +2451,9 @@ void sws_freeContext(SwsContext *sws) if (!c) return; + for (i = 0; i < FF_ARRAY_ELEMS(c->graph); i++) + sws_graph_free(&c->graph[i]); + for (i = 0; i < c->nb_slice_ctx; i++) sws_freeContext(c->slice_ctx[i]); av_freep(&c->slice_ctx); diff --git a/libswscale/x86/output.asm b/libswscale/x86/output.asm index dec1d27f9a..7a1e5d9bc1 100644 --- a/libswscale/x86/output.asm +++ b/libswscale/x86/output.asm @@ -582,7 +582,7 @@ yuv2nv12cX_fn yuv2nv21 %if ARCH_X86_64 struc SwsInternal - .padding: resb 40316 ; offsetof(SwsInternal, yuv2rgb_y_offset) + .padding: resb 40332 ; offsetof(SwsInternal, yuv2rgb_y_offset) .yuv2rgb_y_offset: resd 1 .yuv2rgb_y_coeff: resd 1 .yuv2rgb_v2r_coeff: resd 1 From patchwork Tue Nov 12 09:50:44 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Niklas Haas X-Patchwork-Id: 52701 Delivered-To: ffmpegpatchwork2@gmail.com Received: by 2002:a05:612c:6704:20b0:4a6:637d:5226 with SMTP id mp4-n2csp144324vqb; Tue, 12 Nov 2024 02:01:15 -0800 (PST) X-Forwarded-Encrypted: i=2; AJvYcCXDvTgqPBwZL2xmo0EBkxITtdZc0SfkgPoVRcna3grjPu4Ic8p4CcMJ1KOiyGKPwfMZP/d84Hp/P93hJtxJLGau@gmail.com X-Google-Smtp-Source: AGHT+IE+6Oa3rfbB7p8BVCmYTi1sSxvPbcpZtTZeOg9j7suN+8pEmUf3xv44ySgfz1lwijN2hteF X-Received: by 2002:a05:6402:3593:b0:5cf:98a:ccb5 with SMTP id 4fb4d7f45d1cf-5cf0a471b1amr4183434a12.10.1731405675070; Tue, 12 Nov 2024 02:01:15 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1731405675; cv=none; d=google.com; s=arc-20240605; b=cUTA6TkZYFXQ8u/QIl9QbgutHXJ1OR0yGcXDxcMd3FI0LnA8SJOZxNsUcZM0l47pQn AUPNXkZpwxMhvEG4Ksk0JEkxxiRkwfC8N3SB4saDhqqRdZDkq6dOdGooPSK3myoA+BxG cMyQPCzOqLeUSS+8nzZp3a60irs2acRo43GGgIPynu8FNi2fOSwDL+Ya9E8hI9XFBomV D+AxeWi0GmfLWLPyFGLxIDeGmfe8iuH3w3zggbQBXuhBOmWY4wElUMh2t/fqjH+S8gO2 4aKwSxGiqzc+kpw1cTjSwbIJqQWNWQtWf8Fq74Ja8WJ2mN1ewr5rkBBIzROci745pZX5 yF7Q== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20240605; h=sender:errors-to:content-transfer-encoding:cc:reply-to :list-subscribe:list-help:list-post:list-archive:list-unsubscribe :list-id:precedence:subject:mime-version:references:in-reply-to :message-id:date:to:from:delivered-to; bh=1f5skIpHmIjS4VmqyYycWPHfWfZ6t/6VSxlwgnGDY7M=; fh=xmAeKtysnShNOmkhiJmYkS30uw4Fu2hvBJ7qlIwukxQ=; b=iarBcdcyvFWvMOLvd91JbTFUKgdpIJV8pywQ4nQ9+g9XB6kdOX/b0TAsyU7iIk72JK 4EF0tfL1Si+9BXovUK2iRC9DmfqOYWhqUkazBLUmeAqbQsa43onlnfF+5TcoIfyHeeft DX74Zs3N458aa1cfvyL0qMxxCO+oeuEyOH6gvIZqLBlFSXc+7U0bxJ4941CgqK4efCMr NRHkBtlpP5t4XHsU/zz05DW5KgzQVOqI1/8s3pO/h4RCXQ0W/e9Can6QLn/9aVxWXgfe Ir4DD9w56ppB/n6LMWYXs2TI+P47qinq9Oewi/Y6lLxu4DWBHrMQo6FWtlgqv0PYMTgx 607g==; dara=google.com ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org Return-Path: Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org. [79.124.17.100]) by mx.google.com with ESMTPS id 4fb4d7f45d1cf-5cf03ccd65asi8235531a12.565.2024.11.12.02.01.14 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 12 Nov 2024 02:01:15 -0800 (PST) Received-SPF: pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) client-ip=79.124.17.100; Authentication-Results: mx.google.com; spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id DF69B68DEC9; Tue, 12 Nov 2024 11:52:16 +0200 (EET) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from haasn.dev (haasn.dev [78.46.187.166]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 8BBBE68DE84 for ; Tue, 12 Nov 2024 11:52:02 +0200 (EET) Received: from haasn.dev (unknown [10.30.1.1]) by haasn.dev (Postfix) with ESMTP id 03E8948707; Tue, 12 Nov 2024 10:51:58 +0100 (CET) From: Niklas Haas To: ffmpeg-devel@ffmpeg.org Date: Tue, 12 Nov 2024 10:50:44 +0100 Message-ID: <20241112095154.483778-11-ffmpeg@haasn.xyz> X-Mailer: git-send-email 2.47.0 In-Reply-To: <20241112095154.483778-1-ffmpeg@haasn.xyz> References: <20241112095154.483778-1-ffmpeg@haasn.xyz> MIME-Version: 1.0 Subject: [FFmpeg-devel] [PATCH v6 10/12] tests/swscale: rewrite on top of new API X-BeenThere: ffmpeg-devel@ffmpeg.org X-Mailman-Version: 2.1.29 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: Niklas Haas Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" X-TUID: Ra6/A5IEOm0+ From: Niklas Haas This rewrite cleans up the code to use AVFrames and the new swscale API. The log format has also been simplified and expanded to account for the new options. (Not yet implemented) The self testing code path has also been expanded to test the new swscale implementation against the old one, to serve as an unchanging reference. This does not accomplish much yet, but serves as a framework for future work. Sponsored-by: Sovereign Tech Fund Signed-off-by: Niklas Haas --- libswscale/tests/swscale.c | 665 ++++++++++++++++--------------------- 1 file changed, 284 insertions(+), 381 deletions(-) diff --git a/libswscale/tests/swscale.c b/libswscale/tests/swscale.c index af8069f728..c11a46024e 100644 --- a/libswscale/tests/swscale.c +++ b/libswscale/tests/swscale.c @@ -1,4 +1,5 @@ /* + * Copyright (C) 2024 Nikles Haas * Copyright (C) 2003-2011 Michael Niedermayer * * This file is part of FFmpeg. @@ -26,424 +27,307 @@ #undef HAVE_AV_CONFIG_H #include "libavutil/cpu.h" -#include "libavutil/imgutils.h" -#include "libavutil/mem.h" -#include "libavutil/avutil.h" -#include "libavutil/crc.h" -#include "libavutil/opt.h" #include "libavutil/pixdesc.h" #include "libavutil/lfg.h" #include "libavutil/sfc64.h" +#include "libavutil/frame.h" +#include "libavutil/pixfmt.h" +#include "libavutil/avassert.h" +#include "libavutil/macros.h" #include "libswscale/swscale.h" -/* HACK Duplicated from swscale_internal.h. - * Should be removed when a cleaner pixel format system exists. */ -#define isGray(x) \ - ((x) == AV_PIX_FMT_GRAY8 || \ - (x) == AV_PIX_FMT_YA8 || \ - (x) == AV_PIX_FMT_GRAY16BE || \ - (x) == AV_PIX_FMT_GRAY16LE || \ - (x) == AV_PIX_FMT_YA16BE || \ - (x) == AV_PIX_FMT_YA16LE) -#define hasChroma(x) \ - (!(isGray(x) || \ - (x) == AV_PIX_FMT_MONOBLACK || \ - (x) == AV_PIX_FMT_MONOWHITE)) - -static av_always_inline int isALPHA(enum AVPixelFormat pix_fmt) -{ - const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(pix_fmt); - return desc->flags & AV_PIX_FMT_FLAG_ALPHA; -} +enum { + WIDTH = 96, + HEIGHT = 96, +}; -static double prob = 1; -FFSFC64 prng_state; +struct options { + enum AVPixelFormat src_fmt; + enum AVPixelFormat dst_fmt; + double prob; +}; -static uint64_t getSSD(const uint8_t *src1, const uint8_t *src2, - int stride1, int stride2, int w, int h) -{ - int x, y; - uint64_t ssd = 0; +struct mode { + SwsFlags flags; + SwsDither dither; +}; - for (y = 0; y < h; y++) { - for (x = 0; x < w; x++) { - int d = src1[x + y * stride1] - src2[x + y * stride2]; - ssd += d * d; - } - } - return ssd; -} +const int dst_w[] = { WIDTH, WIDTH - WIDTH / 3, WIDTH + WIDTH / 3 }; +const int dst_h[] = { HEIGHT, HEIGHT - HEIGHT / 3, HEIGHT + HEIGHT / 3 }; + +const struct mode modes[] = { + { SWS_FAST_BILINEAR }, + { SWS_BILINEAR }, + { SWS_BICUBIC }, + { SWS_X | SWS_BITEXACT }, + { SWS_POINT }, + { SWS_AREA | SWS_ACCURATE_RND }, + { SWS_BICUBIC | SWS_FULL_CHR_H_INT | SWS_FULL_CHR_H_INP }, + {0}, // test defaults +}; -static uint64_t getSSD0(int ref, const uint8_t *src1, int stride1, - int w, int h) -{ - int x, y; - uint64_t ssd = 0; +static FFSFC64 prng_state; +static SwsContext *sws[3]; /* reused between tests for efficiency */ - for (y = 0; y < h; y++) { - for (x = 0; x < w; x++) { - int d = src1[x + y * stride1] - ref; - ssd += d * d; - } - } - return ssd; +static int fmt_comps(enum AVPixelFormat fmt) +{ + const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(fmt); + int comps = desc->nb_components >= 3 ? 0b111 : 0b1; + if (desc->flags & AV_PIX_FMT_FLAG_ALPHA) + comps |= 0b1000; + return comps; } -struct Results { - uint64_t ssdY; - uint64_t ssdU; - uint64_t ssdV; - uint64_t ssdA; - uint32_t crc; -}; - -// test by ref -> src -> dst -> out & compare out against ref -// ref & out are YV12 -static int doTest(const uint8_t * const ref[4], int refStride[4], int w, int h, - enum AVPixelFormat srcFormat, enum AVPixelFormat dstFormat, - int srcW, int srcH, int dstW, int dstH, int flags, - struct Results *r) +static void get_mse(int mse[4], const AVFrame *a, const AVFrame *b, int comps) { - const AVPixFmtDescriptor *desc_yuva420p = av_pix_fmt_desc_get(AV_PIX_FMT_YUVA420P); - const AVPixFmtDescriptor *desc_src = av_pix_fmt_desc_get(srcFormat); - const AVPixFmtDescriptor *desc_dst = av_pix_fmt_desc_get(dstFormat); - static enum AVPixelFormat cur_srcFormat; - static int cur_srcW, cur_srcH; - static const uint8_t *src[4]; - static int srcStride[4]; - uint8_t *dst[4] = { 0 }; - uint8_t *out[4] = { 0 }; - int dstStride[4] = {0}; - int i; - uint64_t ssdY, ssdU = 0, ssdV = 0, ssdA = 0; - SwsContext *dstContext = NULL, *outContext = NULL; - uint32_t crc = 0; - int res = 0; - - if (ff_sfc64_get(&prng_state) > UINT64_MAX * prob) - return 0; - - if (cur_srcFormat != srcFormat || cur_srcW != srcW || cur_srcH != srcH) { - SwsContext *srcContext = NULL; - int p; - - for (p = 0; p < 4; p++) - av_freep(&src[p]); - - res = av_image_fill_linesizes(srcStride, srcFormat, srcW); - if (res < 0) { - fprintf(stderr, "av_image_fill_linesizes failed\n"); - goto end; - } - for (p = 0; p < 4; p++) { - srcStride[p] = FFALIGN(srcStride[p], 16); - if (srcStride[p]) - src[p] = av_mallocz(srcStride[p] * srcH + 16); - if (srcStride[p] && !src[p]) { - perror("Malloc"); - res = -1; - goto end; + av_assert1(a->format == AV_PIX_FMT_YUVA420P); + av_assert1(b->format == a->format); + av_assert1(b->width == a->width && b->height == a->height); + + for (int p = 0; p < 4; p++) { + const int is_chroma = p == 1 || p == 2; + const int stride_a = a->linesize[p]; + const int stride_b = b->linesize[p]; + const int w = (a->width + is_chroma) >> is_chroma; + const int h = (a->height + is_chroma) >> is_chroma; + uint64_t sum = 0; + + if (comps & (1 << p)) { + for (int y = 0; y < h; y++) { + for (int x = 0; x < w; x++) { + int d = a->data[p][y * stride_a + x] - b->data[p][y * stride_b + x]; + sum += d * d; + } + } + } else { + const int ref = is_chroma ? 128 : 0xFF; + for (int y = 0; y < h; y++) { + for (int x = 0; x < w; x++) { + int d = a->data[p][y * stride_a + x] - ref; + sum += d * d; + } } } - srcContext = sws_getContext(w, h, AV_PIX_FMT_YUVA420P, srcW, srcH, - srcFormat, SWS_BILINEAR, NULL, NULL, NULL); - if (!srcContext) { - fprintf(stderr, "Failed to get %s ---> %s\n", - desc_yuva420p->name, - desc_src->name); - res = -1; - goto end; - } - sws_scale(srcContext, ref, refStride, 0, h, - (uint8_t * const *) src, srcStride); - sws_freeContext(srcContext); - cur_srcFormat = srcFormat; - cur_srcW = srcW; - cur_srcH = srcH; + mse[p] = sum / (w * h); } +} - res = av_image_fill_linesizes(dstStride, dstFormat, dstW); - if (res < 0) { - fprintf(stderr, "av_image_fill_linesizes failed\n"); - goto end; - } +static int scale_legacy(AVFrame *dst, const AVFrame *src, struct mode mode) +{ + SwsContext *sws_legacy; + int ret; - for (i = 0; i < 4; i++) { - /* Image buffers passed into libswscale can be allocated any way you - * prefer, as long as they're aligned enough for the architecture, and - * they're freed appropriately (such as using av_free for buffers - * allocated with av_malloc). */ - /* An extra 16 bytes is being allocated because some scalers may write - * out of bounds. */ - dstStride[i] = FFALIGN(dstStride[i], 16); - if (dstStride[i]) - dst[i] = av_mallocz(dstStride[i] * dstH + 16); - if (dstStride[i] && !dst[i]) { - perror("Malloc"); - res = -1; - - goto end; - } - } + sws_legacy = sws_alloc_context(); + if (!sws_legacy) + return -1; + + sws_legacy->src_w = src->width; + sws_legacy->src_h = src->height; + sws_legacy->src_format = src->format; + sws_legacy->dst_w = dst->width; + sws_legacy->dst_h = dst->height; + sws_legacy->dst_format = dst->format; + sws_legacy->flags = mode.flags; + sws_legacy->dither = mode.dither; + + ret = sws_init_context(sws_legacy, NULL, NULL); + if (!ret) + ret = sws_scale_frame(sws_legacy, dst, src); + + sws_freeContext(sws_legacy); + return ret; +} + +/* Runs a series of ref -> src -> dst -> out, and compares out vs ref */ +static int run_test(enum AVPixelFormat src_fmt, enum AVPixelFormat dst_fmt, + int dst_w, int dst_h, struct mode mode, const AVFrame *ref, + const int mse_ref[4]) +{ + AVFrame *src = NULL, *dst = NULL, *out = NULL; + int mse[4], mse_sws[4], ret = -1; + const int comps = fmt_comps(src_fmt) & fmt_comps(dst_fmt); + + src = av_frame_alloc(); + dst = av_frame_alloc(); + out = av_frame_alloc(); + if (!src || !dst || !out) + goto error; - dstContext = sws_alloc_context(); - if (!dstContext) { - fprintf(stderr, "Failed to alloc %s ---> %s\n", - desc_src->name, desc_dst->name); - res = -1; - goto end; + av_frame_copy_props(src, ref); + av_frame_copy_props(dst, ref); + av_frame_copy_props(out, ref); + src->width = out->width = ref->width; + src->height = out->height = ref->height; + out->format = ref->format; + src->format = src_fmt; + dst->format = dst_fmt; + dst->width = dst_w; + dst->height = dst_h; + + if (sws_scale_frame(sws[0], src, ref) < 0) { + fprintf(stderr, "Failed %s ---> %s\n", av_get_pix_fmt_name(ref->format), + av_get_pix_fmt_name(src->format)); + goto error; } - av_opt_set_int(dstContext, "sws_flags", flags, 0); - av_opt_set_int(dstContext, "srcw", srcW, 0); - av_opt_set_int(dstContext, "srch", srcH, 0); - av_opt_set_int(dstContext, "dstw", dstW, 0); - av_opt_set_int(dstContext, "dsth", dstH, 0); - av_opt_set_int(dstContext, "src_format", srcFormat, 0); - av_opt_set_int(dstContext, "dst_format", dstFormat, 0); - av_opt_set(dstContext, "alphablend", "none", 0); - - if (sws_init_context(dstContext, NULL, NULL) < 0) { - sws_freeContext(dstContext); - fprintf(stderr, "Failed to init %s ---> %s\n", - desc_src->name, desc_dst->name); - res = -1; - goto end; + sws[1]->flags = mode.flags; + sws[1]->dither = mode.dither; + if (sws_scale_frame(sws[1], dst, src) < 0) { + fprintf(stderr, "Failed %s ---> %s\n", av_get_pix_fmt_name(src->format), + av_get_pix_fmt_name(dst->format)); + goto error; } - printf(" %s %dx%d -> %s %3dx%3d flags=%2d", - desc_src->name, srcW, srcH, - desc_dst->name, dstW, dstH, - flags); - fflush(stdout); + if (sws_scale_frame(sws[2], out, dst) < 0) { + fprintf(stderr, "Failed %s ---> %s\n", av_get_pix_fmt_name(dst->format), + av_get_pix_fmt_name(out->format)); + goto error; + } - sws_scale(dstContext, (const uint8_t * const*)src, srcStride, 0, srcH, dst, dstStride); - - for (i = 0; i < 4 && dstStride[i]; i++) - crc = av_crc(av_crc_get_table(AV_CRC_32_IEEE), crc, dst[i], - dstStride[i] * dstH); - - if (r && crc == r->crc) { - ssdY = r->ssdY; - ssdU = r->ssdU; - ssdV = r->ssdV; - ssdA = r->ssdA; - } else { - for (i = 0; i < 4; i++) { - refStride[i] = FFALIGN(refStride[i], 16); - if (refStride[i]) - out[i] = av_mallocz(refStride[i] * h); - if (refStride[i] && !out[i]) { - perror("Malloc"); - res = -1; - goto end; - } - } - outContext = sws_getContext(dstW, dstH, dstFormat, w, h, - AV_PIX_FMT_YUVA420P, SWS_BILINEAR, - NULL, NULL, NULL); - if (!outContext) { - fprintf(stderr, "Failed to get %s ---> %s\n", - desc_dst->name, - desc_yuva420p->name); - res = -1; - goto end; - } - sws_scale(outContext, (const uint8_t * const *) dst, dstStride, 0, dstH, - out, refStride); - - ssdY = getSSD(ref[0], out[0], refStride[0], refStride[0], w, h); - if (hasChroma(srcFormat) && hasChroma(dstFormat)) { - //FIXME check that output is really gray - ssdU = getSSD(ref[1], out[1], refStride[1], refStride[1], - (w + 1) >> 1, (h + 1) >> 1); - ssdV = getSSD(ref[2], out[2], refStride[2], refStride[2], - (w + 1) >> 1, (h + 1) >> 1); - } else { - ssdU = getSSD0(128, out[1], refStride[1], - (w + 1) >> 1, (h + 1) >> 1); - ssdV = getSSD0(128, out[2], refStride[2], - (w + 1) >> 1, (h + 1) >> 1); - } - if (isALPHA(srcFormat) && isALPHA(dstFormat)) { - ssdA = getSSD(ref[3], out[3], refStride[3], refStride[3], w, h); - } else { - ssdA = getSSD0(0xFF, out[3], refStride[3], w, h); + get_mse(mse, out, ref, comps); + printf("%s %dx%d -> %s %3dx%3d, flags=%u dither=%u, " + "MSE={%5d %5d %5d %5d}\n", + av_get_pix_fmt_name(src->format), src->width, src->height, + av_get_pix_fmt_name(dst->format), dst->width, dst->height, + mode.flags, mode.dither, + mse[0], mse[1], mse[2], mse[3]); + + if (!mse_ref) { + /* Compare against the legacy swscale API as a reference */ + if (scale_legacy(dst, src, mode) < 0) { + fprintf(stderr, "Failed ref %s ---> %s\n", av_get_pix_fmt_name(src->format), + av_get_pix_fmt_name(dst->format)); + goto error; } - ssdY /= w * h; - ssdU /= w * h / 4; - ssdV /= w * h / 4; - ssdA /= w * h; - - sws_freeContext(outContext); + if (sws_scale_frame(sws[2], out, dst) < 0) + goto error; - for (i = 0; i < 4; i++) - if (refStride[i]) - av_free(out[i]); + get_mse(mse_sws, out, ref, comps); + mse_ref = mse_sws; } - if(r){ - if(ssdY>r->ssdY*1.02+1 || ssdU>r->ssdU*1.02+1 || ssdV>r->ssdV*1.02+1|| ssdA>r->ssdA*1.02+1) - printf("WORSE SSD=%5"PRId64",%5"PRId64",%5"PRId64",%5"PRId64"", - r->ssdY, r->ssdU, r->ssdV, r->ssdA); - else if(ssdY>r->ssdY || ssdU>r->ssdU || ssdV>r->ssdV|| ssdA>r->ssdA) - printf("worse SSD=%5"PRId64",%5"PRId64",%5"PRId64",%5"PRId64"", - r->ssdY, r->ssdU, r->ssdV, r->ssdA); + for (int i = 0; i < 4; i++) { + if (mse[i] > mse_ref[i]) { + int bad = mse[i] > mse_ref[i] * 1.02 + 1; + printf("\033[1;31m %s, ref MSE={%5d %5d %5d %5d}\033[0m\n", + bad ? "WORSE" : "worse", + mse_ref[0], mse_ref[1], mse_ref[2], mse_ref[3]); + if (bad) + goto error; + break; + } } - printf(" CRC=%08x SSD=%5"PRId64 ",%5"PRId64 ",%5"PRId64 ",%5"PRId64 "\n", - crc, ssdY, ssdU, ssdV, ssdA); - -end: - sws_freeContext(dstContext); - - for (i = 0; i < 4; i++) - if (dstStride[i]) - av_free(dst[i]); - - return !!res; + fflush(stdout); + ret = 0; /* fall through */ + error: + av_frame_free(&src); + av_frame_free(&dst); + av_frame_free(&out); + return ret; } -static void selfTest(const uint8_t * const ref[4], int refStride[4], - int w, int h, - enum AVPixelFormat srcFormat_in, - enum AVPixelFormat dstFormat_in) +static int run_self_tests(const AVFrame *ref, struct options opts) { - const int flags[] = { SWS_FAST_BILINEAR, - SWS_BILINEAR, SWS_BICUBIC, - SWS_X|SWS_BITEXACT , SWS_POINT , SWS_AREA|SWS_ACCURATE_RND, - SWS_BICUBIC|SWS_FULL_CHR_H_INT|SWS_FULL_CHR_H_INP, 0}; - const int srcW = w; - const int srcH = h; - const int dstW[] = { srcW - srcW / 3, srcW, srcW + srcW / 3, 0 }; - const int dstH[] = { srcH - srcH / 3, srcH, srcH + srcH / 3, 0 }; - enum AVPixelFormat srcFormat, dstFormat; - const AVPixFmtDescriptor *desc_src, *desc_dst; - - for (srcFormat = srcFormat_in != AV_PIX_FMT_NONE ? srcFormat_in : 0; - srcFormat < AV_PIX_FMT_NB; srcFormat++) { - if (!sws_isSupportedInput(srcFormat) || - !sws_isSupportedOutput(srcFormat)) + enum AVPixelFormat src_fmt, dst_fmt, + src_fmt_min = 0, + dst_fmt_min = 0, + src_fmt_max = AV_PIX_FMT_NB - 1, + dst_fmt_max = AV_PIX_FMT_NB - 1; + + if (opts.src_fmt != AV_PIX_FMT_NONE) + src_fmt_min = src_fmt_max = opts.src_fmt; + if (opts.dst_fmt != AV_PIX_FMT_NONE) + dst_fmt_min = dst_fmt_max = opts.dst_fmt; + + for (src_fmt = src_fmt_min; src_fmt <= src_fmt_max; src_fmt++) { + if (!sws_test_format(src_fmt, 0) || !sws_test_format(src_fmt, 1)) continue; - - desc_src = av_pix_fmt_desc_get(srcFormat); - - for (dstFormat = dstFormat_in != AV_PIX_FMT_NONE ? dstFormat_in : 0; - dstFormat < AV_PIX_FMT_NB; dstFormat++) { - int i, j, k; - int res = 0; - - if (!sws_isSupportedInput(dstFormat) || - !sws_isSupportedOutput(dstFormat)) + for (dst_fmt = dst_fmt_min; dst_fmt <= dst_fmt_max; dst_fmt++) { + if (!sws_test_format(dst_fmt, 0) || !sws_test_format(dst_fmt, 1)) continue; - - desc_dst = av_pix_fmt_desc_get(dstFormat); - - printf("%s -> %s\n", desc_src->name, desc_dst->name); - fflush(stdout); - - for (k = 0; flags[k] && !res; k++) - for (i = 0; dstW[i] && !res; i++) - for (j = 0; dstH[j] && !res; j++) - res = doTest(ref, refStride, w, h, - srcFormat, dstFormat, - srcW, srcH, dstW[i], dstH[j], flags[k], - NULL); - if (dstFormat_in != AV_PIX_FMT_NONE) - break; + for (int h = 0; h < FF_ARRAY_ELEMS(dst_h); h++) + for (int w = 0; w < FF_ARRAY_ELEMS(dst_w); w++) + for (int m = 0; m < FF_ARRAY_ELEMS(modes); m++) { + if (ff_sfc64_get(&prng_state) > UINT64_MAX * opts.prob) + continue; + if (run_test(src_fmt, dst_fmt, dst_w[w], dst_h[h], + modes[m], ref, NULL) < 0) + return -1; + } } - if (srcFormat_in != AV_PIX_FMT_NONE) - break; } + + return 0; } -static int fileTest(const uint8_t * const ref[4], int refStride[4], - int w, int h, FILE *fp, - enum AVPixelFormat srcFormat_in, - enum AVPixelFormat dstFormat_in) +static int run_file_tests(const AVFrame *ref, FILE *fp, struct options opts) { char buf[256]; + int ret; while (fgets(buf, sizeof(buf), fp)) { - struct Results r; - enum AVPixelFormat srcFormat; - char srcStr[21]; - int srcW = 0, srcH = 0; - enum AVPixelFormat dstFormat; - char dstStr[21]; - int dstW = 0, dstH = 0; - int flags; - int ret; + char src_fmt_str[20], dst_fmt_str[20]; + enum AVPixelFormat src_fmt; + enum AVPixelFormat dst_fmt; + int sw, sh, dw, dh, mse[4]; + struct mode mode; ret = sscanf(buf, - " %20s %dx%d -> %20s %dx%d flags=%d CRC=%x" - " SSD=%"SCNu64 ", %"SCNu64 ", %"SCNu64 ", %"SCNu64 "\n", - srcStr, &srcW, &srcH, dstStr, &dstW, &dstH, - &flags, &r.crc, &r.ssdY, &r.ssdU, &r.ssdV, &r.ssdA); - if (ret != 12) { - srcStr[0] = dstStr[0] = 0; - ret = sscanf(buf, "%20s -> %20s\n", srcStr, dstStr); + " %20s %dx%d -> %20s %dx%d, flags=%u dither=%u, " + "MSE={%d %d %d %d}\n", + src_fmt_str, &sw, &sh, dst_fmt_str, &dw, &dh, + &mode.flags, &mode.dither, + &mse[0], &mse[1], &mse[2], &mse[3]); + if (ret != 13) { + printf("%s", buf); + continue; } - srcFormat = av_get_pix_fmt(srcStr); - dstFormat = av_get_pix_fmt(dstStr); - - if (srcFormat == AV_PIX_FMT_NONE || dstFormat == AV_PIX_FMT_NONE || - srcW > 8192U || srcH > 8192U || dstW > 8192U || dstH > 8192U) { + src_fmt = av_get_pix_fmt(src_fmt_str); + dst_fmt = av_get_pix_fmt(dst_fmt_str); + if (src_fmt == AV_PIX_FMT_NONE || dst_fmt == AV_PIX_FMT_NONE || + sw != ref->width || sh != ref->height || dw > 8192 || dh > 8192 || + mode.dither >= SWS_DITHER_NB) { fprintf(stderr, "malformed input file\n"); return -1; } - if ((srcFormat_in != AV_PIX_FMT_NONE && srcFormat_in != srcFormat) || - (dstFormat_in != AV_PIX_FMT_NONE && dstFormat_in != dstFormat)) - continue; - if (ret != 12) { - printf("%s", buf); + + if (opts.src_fmt != AV_PIX_FMT_NONE && src_fmt != opts.src_fmt || + opts.dst_fmt != AV_PIX_FMT_NONE && dst_fmt != opts.dst_fmt) continue; - } - doTest(ref, refStride, w, h, - srcFormat, dstFormat, - srcW, srcH, dstW, dstH, flags, - &r); + if (run_test(src_fmt, dst_fmt, dw, dh, mode, ref, mse) < 0) + return -1; } return 0; } -#define W 96 -#define H 96 - int main(int argc, char **argv) { - enum AVPixelFormat srcFormat = AV_PIX_FMT_NONE; - enum AVPixelFormat dstFormat = AV_PIX_FMT_NONE; - uint8_t *rgb_data = av_malloc(W * H * 4); - const uint8_t * const rgb_src[4] = { rgb_data, NULL, NULL, NULL }; - int rgb_stride[4] = { 4 * W, 0, 0, 0 }; - uint8_t *data = av_malloc(4 * W * H); - const uint8_t * const src[4] = { data, data + W * H, data + W * H * 2, data + W * H * 3 }; - int stride[4] = { W, W, W, W }; - int x, y; - SwsContext *sws; - AVLFG rand; - int res = -1; - int i; - FILE *fp = NULL; + struct options opts = { + .src_fmt = AV_PIX_FMT_NONE, + .dst_fmt = AV_PIX_FMT_NONE, + .prob = 1.0, + }; - if (!rgb_data || !data) - return -1; + AVFrame *rgb = NULL, *ref = NULL; + FILE *fp = NULL; + AVLFG rand; + int ret = -1; - for (i = 1; i < argc; i += 2) { + for (int i = 1; i < argc; i += 2) { if (!strcmp(argv[i], "-help") || !strcmp(argv[i], "--help")) { fprintf(stderr, "swscale [options...]\n" " -help\n" " This text\n" " -ref \n" - " Uses file as reference to compae tests againsts. Tests that have become worse will contain the string worse or WORSE\n" + " Uses file as reference to compare tests againsts. Tests that have become worse will contain the string worse or WORSE\n" " -p \n" " The percentage of tests or comparisons to perform. Doing all tests will take long and generate over a hundred MB text output\n" " It is often convenient to perform a random subset\n" @@ -454,7 +338,7 @@ int main(int argc, char **argv) " -cpuflags \n" " Uses the specified cpuflags in the tests\n" ); - goto error; + return 0; } if (argv[i][0] != '-' || i + 1 == argc) goto bad_option; @@ -466,26 +350,26 @@ int main(int argc, char **argv) } } else if (!strcmp(argv[i], "-cpuflags")) { unsigned flags = av_get_cpu_flags(); - int ret = av_parse_cpu_caps(&flags, argv[i + 1]); - if (ret < 0) { + int res = av_parse_cpu_caps(&flags, argv[i + 1]); + if (res < 0) { fprintf(stderr, "invalid cpu flags %s\n", argv[i + 1]); - return ret; + goto error; } av_force_cpu_flags(flags); } else if (!strcmp(argv[i], "-src")) { - srcFormat = av_get_pix_fmt(argv[i + 1]); - if (srcFormat == AV_PIX_FMT_NONE) { + opts.src_fmt = av_get_pix_fmt(argv[i + 1]); + if (opts.src_fmt == AV_PIX_FMT_NONE) { fprintf(stderr, "invalid pixel format %s\n", argv[i + 1]); - return -1; + goto error; } } else if (!strcmp(argv[i], "-dst")) { - dstFormat = av_get_pix_fmt(argv[i + 1]); - if (dstFormat == AV_PIX_FMT_NONE) { + opts.dst_fmt = av_get_pix_fmt(argv[i + 1]); + if (opts.dst_fmt == AV_PIX_FMT_NONE) { fprintf(stderr, "invalid pixel format %s\n", argv[i + 1]); - return -1; + goto error; } } else if (!strcmp(argv[i], "-p")) { - prob = atof(argv[i + 1]); + opts.prob = atof(argv[i + 1]); } else { bad_option: fprintf(stderr, "bad option or argument missing (%s) see -help\n", argv[i]); @@ -494,32 +378,51 @@ bad_option: } ff_sfc64_init(&prng_state, 0, 0, 0, 12); - - sws = sws_getContext(W / 12, H / 12, AV_PIX_FMT_RGB32, W, H, - AV_PIX_FMT_YUVA420P, SWS_BILINEAR, NULL, NULL, NULL); - av_lfg_init(&rand, 1); - for (y = 0; y < H; y++) - for (x = 0; x < W * 4; x++) - rgb_data[ x + y * 4 * W] = av_lfg_get(&rand); - res = sws_scale(sws, rgb_src, rgb_stride, 0, H / 12, (uint8_t * const *) src, stride); - if (res < 0 || res != H) { - res = -1; - goto error; + for (int i = 0; i < 3; i++) { + sws[i] = sws_alloc_context(); + if (!sws[i]) + goto error; + sws[i]->flags = SWS_BILINEAR; } - sws_freeContext(sws); - av_free(rgb_data); - if(fp) { - res = fileTest(src, stride, W, H, fp, srcFormat, dstFormat); - fclose(fp); - } else { - selfTest(src, stride, W, H, srcFormat, dstFormat); - res = 0; + rgb = av_frame_alloc(); + if (!rgb) + goto error; + rgb->width = WIDTH / 12; + rgb->height = HEIGHT / 12; + rgb->format = AV_PIX_FMT_RGBA; + if (av_frame_get_buffer(rgb, 32) < 0) + goto error; + + for (int y = 0; y < rgb->height; y++) { + for (int x = 0; x < rgb->width; x++) { + for (int c = 0; c < 4; c++) + rgb->data[0][y * rgb->linesize[0] + x * 4 + c] = av_lfg_get(&rand); + } } -error: - av_free(data); - return res; + ref = av_frame_alloc(); + if (!ref) + goto error; + ref->width = WIDTH; + ref->height = HEIGHT; + ref->format = AV_PIX_FMT_YUVA420P; + + if (sws_scale_frame(sws[0], ref, rgb) < 0) + goto error; + + ret = fp ? run_file_tests(ref, fp, opts) + : run_self_tests(ref, opts); + + /* fall through */ +error: + for (int i = 0; i < 3; i++) + sws_free_context(&sws[i]); + av_frame_free(&rgb); + av_frame_free(&ref); + if (fp) + fclose(fp); + return ret; } From patchwork Tue Nov 12 09:50:45 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Niklas Haas X-Patchwork-Id: 52698 Delivered-To: ffmpegpatchwork2@gmail.com Received: by 2002:a05:612c:6704:20b0:4a6:637d:5226 with SMTP id mp4-n2csp144293vqb; Tue, 12 Nov 2024 02:01:13 -0800 (PST) X-Forwarded-Encrypted: i=2; AJvYcCXcnOsih54xXFYO9udx8QqT2prOENkZvQsR8BP3n+BaUflVtKNo+zms2Q0ziETcURPgbsJSmh02XP08NuB2yD9/@gmail.com X-Google-Smtp-Source: AGHT+IFqDBhlmXBYtd2Dw40fwMNhqktiH+KY1S9MOBtg1wnWuxhPACBHzNdFpxRxOTjYY/FjYirx X-Received: by 2002:a17:906:fe0e:b0:a9a:7f84:9408 with SMTP id a640c23a62f3a-a9eefe9282amr604325566b.3.1731405673118; Tue, 12 Nov 2024 02:01:13 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1731405673; cv=none; d=google.com; s=arc-20240605; b=VQngT/9nLDB+Mg7y27FGWhW3RytAwn7IgPjo2HZW4tedEWmxOJtEhVSGz0JRE4GNWO Pqo6hoVIf67jIpQWAhBfx56LINRkktWaWLijbYawV5bHcTldyRNbhWuWwiZBAqnZuE5R IlFyWuI8lMeItL7AKFiyPIIvrEl2a0n5OFUFutrw2AuckSTow5yya5sPjl8A6LVEwYNK bf8xs4iNrrBexvxIHW4Fc1Fu1cuZFn/WB6VeeFquQKuU5GoC8cEGjaCnE0XhHufUKa7x G6qM9dROWflG2cFR5WcXzZkv83rA0A3lHqx21lAfNEK5PfBpxJx+/nZ+yp4GinqWl9Wt bMtQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20240605; h=sender:errors-to:content-transfer-encoding:cc:reply-to :list-subscribe:list-help:list-post:list-archive:list-unsubscribe :list-id:precedence:subject:mime-version:references:in-reply-to :message-id:date:to:from:delivered-to; bh=i2PXxek6yRgkynJG6SOithvzaQjFMVDPPZrVTlqXuS8=; fh=xmAeKtysnShNOmkhiJmYkS30uw4Fu2hvBJ7qlIwukxQ=; b=OfKPBhPMpb6mnnB9MQus0uhHwDREi/F/pkS21gIRbtQ8Y1KjJ9tq5mgsb0/lV2b0LH owQiJPv5bll7ssnJPyq6OQWK+xD1zo/oq6Dlacz25qWKIabVyPzZP2CSV4YaTMtetx3Q Vfuh8DLT/eI2K1s3FdzIapCEsAf8vRKRl1T6TzFv41S3XXkXCMbPnURSU4RtQdKEvWog ELUOOA7DcPi3avVIoWZ/rrMy374QLCwaMQOBJEtcZTjcrayHPfrzuRKKFrko0xW9Kp6l MPBI7EMLbumXz/CrzGSbKHrA51DPAlJrUyWYnk8XDdH141PalbdEF5ICHlwNfOBl4aPe RN8g==; dara=google.com ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org Return-Path: Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org. [79.124.17.100]) by mx.google.com with ESMTPS id a640c23a62f3a-a9ee0a0c0b6si782279166b.166.2024.11.12.02.01.12 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 12 Nov 2024 02:01:13 -0800 (PST) Received-SPF: pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) client-ip=79.124.17.100; Authentication-Results: mx.google.com; spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 3C81168DE27; Tue, 12 Nov 2024 11:52:11 +0200 (EET) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from haasn.dev (haasn.dev [78.46.187.166]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 16F4B68D933 for ; Tue, 12 Nov 2024 11:52:03 +0200 (EET) Received: from haasn.dev (unknown [10.30.1.1]) by haasn.dev (Postfix) with ESMTP id 3BFC54B2A9; Tue, 12 Nov 2024 10:51:59 +0100 (CET) From: Niklas Haas To: ffmpeg-devel@ffmpeg.org Date: Tue, 12 Nov 2024 10:50:45 +0100 Message-ID: <20241112095154.483778-12-ffmpeg@haasn.xyz> X-Mailer: git-send-email 2.47.0 In-Reply-To: <20241112095154.483778-1-ffmpeg@haasn.xyz> References: <20241112095154.483778-1-ffmpeg@haasn.xyz> MIME-Version: 1.0 Subject: [FFmpeg-devel] [PATCH v6 11/12] tests/swscale: add a benchmarking mode X-BeenThere: ffmpeg-devel@ffmpeg.org X-Mailman-Version: 2.1.29 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: Niklas Haas Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" X-TUID: GWl2noYHQgkU From: Niklas Haas With the ability to set the thread count as well. This benchmark includes the constant overhead of context initialization. Sponsored-by: Sovereign Tech Fund Signed-off-by: Niklas Haas --- libswscale/tests/swscale.c | 93 ++++++++++++++++++++++++++++---------- 1 file changed, 68 insertions(+), 25 deletions(-) diff --git a/libswscale/tests/swscale.c b/libswscale/tests/swscale.c index c11a46024e..f5ad4b3132 100644 --- a/libswscale/tests/swscale.c +++ b/libswscale/tests/swscale.c @@ -31,21 +31,22 @@ #include "libavutil/lfg.h" #include "libavutil/sfc64.h" #include "libavutil/frame.h" +#include "libavutil/opt.h" +#include "libavutil/time.h" #include "libavutil/pixfmt.h" #include "libavutil/avassert.h" #include "libavutil/macros.h" #include "libswscale/swscale.h" -enum { - WIDTH = 96, - HEIGHT = 96, -}; - struct options { enum AVPixelFormat src_fmt; enum AVPixelFormat dst_fmt; double prob; + int w, h; + int threads; + int iters; + int bench; }; struct mode { @@ -53,9 +54,6 @@ struct mode { SwsDither dither; }; -const int dst_w[] = { WIDTH, WIDTH - WIDTH / 3, WIDTH + WIDTH / 3 }; -const int dst_h[] = { HEIGHT, HEIGHT - HEIGHT / 3, HEIGHT + HEIGHT / 3 }; - const struct mode modes[] = { { SWS_FAST_BILINEAR }, { SWS_BILINEAR }, @@ -114,7 +112,8 @@ static void get_mse(int mse[4], const AVFrame *a, const AVFrame *b, int comps) } } -static int scale_legacy(AVFrame *dst, const AVFrame *src, struct mode mode) +static int scale_legacy(AVFrame *dst, const AVFrame *src, struct mode mode, + struct options opts) { SwsContext *sws_legacy; int ret; @@ -131,23 +130,28 @@ static int scale_legacy(AVFrame *dst, const AVFrame *src, struct mode mode) sws_legacy->dst_format = dst->format; sws_legacy->flags = mode.flags; sws_legacy->dither = mode.dither; + sws_legacy->threads = opts.threads; + + if ((ret = sws_init_context(sws_legacy, NULL, NULL)) < 0) + goto error; - ret = sws_init_context(sws_legacy, NULL, NULL); - if (!ret) + for (int i = 0; i < opts.iters; i++) ret = sws_scale_frame(sws_legacy, dst, src); +error: sws_freeContext(sws_legacy); return ret; } /* Runs a series of ref -> src -> dst -> out, and compares out vs ref */ static int run_test(enum AVPixelFormat src_fmt, enum AVPixelFormat dst_fmt, - int dst_w, int dst_h, struct mode mode, const AVFrame *ref, - const int mse_ref[4]) + int dst_w, int dst_h, struct mode mode, struct options opts, + const AVFrame *ref, const int mse_ref[4]) { AVFrame *src = NULL, *dst = NULL, *out = NULL; int mse[4], mse_sws[4], ret = -1; const int comps = fmt_comps(src_fmt) & fmt_comps(dst_fmt); + int64_t time, time_ref = 0; src = av_frame_alloc(); dst = av_frame_alloc(); @@ -174,12 +178,20 @@ static int run_test(enum AVPixelFormat src_fmt, enum AVPixelFormat dst_fmt, sws[1]->flags = mode.flags; sws[1]->dither = mode.dither; - if (sws_scale_frame(sws[1], dst, src) < 0) { - fprintf(stderr, "Failed %s ---> %s\n", av_get_pix_fmt_name(src->format), - av_get_pix_fmt_name(dst->format)); - goto error; + sws[1]->threads = opts.threads; + + time = av_gettime_relative(); + + for (int i = 0; i < opts.iters; i++) { + if (sws_scale_frame(sws[1], dst, src) < 0) { + fprintf(stderr, "Failed %s ---> %s\n", av_get_pix_fmt_name(src->format), + av_get_pix_fmt_name(dst->format)); + goto error; + } } + time = av_gettime_relative() - time; + if (sws_scale_frame(sws[2], out, dst) < 0) { fprintf(stderr, "Failed %s ---> %s\n", av_get_pix_fmt_name(dst->format), av_get_pix_fmt_name(out->format)); @@ -196,11 +208,13 @@ static int run_test(enum AVPixelFormat src_fmt, enum AVPixelFormat dst_fmt, if (!mse_ref) { /* Compare against the legacy swscale API as a reference */ - if (scale_legacy(dst, src, mode) < 0) { + time_ref = av_gettime_relative(); + if (scale_legacy(dst, src, mode, opts) < 0) { fprintf(stderr, "Failed ref %s ---> %s\n", av_get_pix_fmt_name(src->format), av_get_pix_fmt_name(dst->format)); goto error; } + time_ref = av_gettime_relative() - time_ref; if (sws_scale_frame(sws[2], out, dst) < 0) goto error; @@ -221,6 +235,15 @@ static int run_test(enum AVPixelFormat src_fmt, enum AVPixelFormat dst_fmt, } } + if (opts.bench && time_ref) { + printf(" time=%"PRId64" us, ref=%"PRId64" us, speedup=%.3fx %s\n", + time / opts.iters, time_ref / opts.iters, + (double) time_ref / time, + time <= time_ref ? "faster" : "\033[1;33mslower\033[0m"); + } else if (opts.bench) { + printf(" time=%"PRId64" us\n", time / opts.iters); + } + fflush(stdout); ret = 0; /* fall through */ error: @@ -232,6 +255,9 @@ static int run_test(enum AVPixelFormat src_fmt, enum AVPixelFormat dst_fmt, static int run_self_tests(const AVFrame *ref, struct options opts) { + const int dst_w[] = { opts.w, opts.w - opts.w / 3, opts.w + opts.w / 3 }; + const int dst_h[] = { opts.h, opts.h - opts.h / 3, opts.h + opts.h / 3 }; + enum AVPixelFormat src_fmt, dst_fmt, src_fmt_min = 0, dst_fmt_min = 0, @@ -254,8 +280,9 @@ static int run_self_tests(const AVFrame *ref, struct options opts) for (int m = 0; m < FF_ARRAY_ELEMS(modes); m++) { if (ff_sfc64_get(&prng_state) > UINT64_MAX * opts.prob) continue; + if (run_test(src_fmt, dst_fmt, dst_w[w], dst_h[h], - modes[m], ref, NULL) < 0) + modes[m], opts, ref, NULL) < 0) return -1; } } @@ -300,7 +327,7 @@ static int run_file_tests(const AVFrame *ref, FILE *fp, struct options opts) opts.dst_fmt != AV_PIX_FMT_NONE && dst_fmt != opts.dst_fmt) continue; - if (run_test(src_fmt, dst_fmt, dw, dh, mode, ref, mse) < 0) + if (run_test(src_fmt, dst_fmt, dw, dh, mode, opts, ref, mse) < 0) return -1; } @@ -312,7 +339,11 @@ int main(int argc, char **argv) struct options opts = { .src_fmt = AV_PIX_FMT_NONE, .dst_fmt = AV_PIX_FMT_NONE, - .prob = 1.0, + .w = 96, + .h = 96, + .threads = 1, + .iters = 1, + .prob = 1.0, }; AVFrame *rgb = NULL, *ref = NULL; @@ -335,6 +366,10 @@ int main(int argc, char **argv) " Only test the specified destination pixel format\n" " -src \n" " Only test the specified source pixel format\n" + " -bench \n" + " Run benchmarks with the specified number of iterations. This mode also increases the size of the test images\n" + " -threads \n" + " Use the specified number of threads\n" " -cpuflags \n" " Uses the specified cpuflags in the tests\n" ); @@ -368,6 +403,14 @@ int main(int argc, char **argv) fprintf(stderr, "invalid pixel format %s\n", argv[i + 1]); goto error; } + } else if (!strcmp(argv[i], "-bench")) { + opts.bench = 1; + opts.iters = atoi(argv[i + 1]); + opts.iters = FFMAX(opts.iters, 1); + opts.w = 1920; + opts.h = 1080; + } else if (!strcmp(argv[i], "-threads")) { + opts.threads = atoi(argv[i + 1]); } else if (!strcmp(argv[i], "-p")) { opts.prob = atof(argv[i + 1]); } else { @@ -390,8 +433,8 @@ bad_option: rgb = av_frame_alloc(); if (!rgb) goto error; - rgb->width = WIDTH / 12; - rgb->height = HEIGHT / 12; + rgb->width = opts.w / 12; + rgb->height = opts.h / 12; rgb->format = AV_PIX_FMT_RGBA; if (av_frame_get_buffer(rgb, 32) < 0) goto error; @@ -406,8 +449,8 @@ bad_option: ref = av_frame_alloc(); if (!ref) goto error; - ref->width = WIDTH; - ref->height = HEIGHT; + ref->width = opts.w; + ref->height = opts.h; ref->format = AV_PIX_FMT_YUVA420P; if (sws_scale_frame(sws[0], ref, rgb) < 0) From patchwork Tue Nov 12 09:50:46 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Niklas Haas X-Patchwork-Id: 52700 Delivered-To: ffmpegpatchwork2@gmail.com Received: by 2002:a05:612c:6704:20b0:4a6:637d:5226 with SMTP id mp4-n2csp144323vqb; Tue, 12 Nov 2024 02:01:15 -0800 (PST) X-Forwarded-Encrypted: i=2; AJvYcCVRMHkI6pDeFH6024Bu4lJqxXshKBCeyaKqq34bxemjWJzmOp1ZwgD3l1EWT3piRZ23gjjRySzrRBpqPzjoJFbR@gmail.com X-Google-Smtp-Source: AGHT+IFWDmQ9U+Alk+E9ZcKBp/3rINXzhWunJqPH94Iv0xpvcpAxDyT6SycVfQYHX3Z6hHYdYE07 X-Received: by 2002:a17:907:7205:b0:a99:60c8:f2c4 with SMTP id a640c23a62f3a-a9eeff0d8d4mr1564392966b.15.1731405674867; Tue, 12 Nov 2024 02:01:14 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1731405674; cv=none; d=google.com; s=arc-20240605; b=jTBvOtGli3pjBWAMtun8LQIoT1RltRJ7Kt3Wv34h9jZrSBk/ACAMYJeIniFLIup0wR hXllCgmmdq72y77ZhvvARRTo5sFkG0+qcH0a1FAN/Yw9OSxOBlRvvlXj7biSLhr1B4GR WY0eg0Y4Y5ZVeIecOvNCHkQdhVHBDN9md3gItIJ8PhvzVeBEDp+XsqcsAXImAISCWkkV C0SeUg6eyqTgUSu9ouHTnT+JwK/ZW6PIzFCeSd7Wb3K0K+iquHNa4sFZcbAljSIEuyaw AiHreFHDOKvjwMJUxS59/m/3ze2lLQnrAdzz1xUpB0dw3EFcH5tfCRM23See0PpHMdWL 3OQg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20240605; h=sender:errors-to:content-transfer-encoding:cc:reply-to :list-subscribe:list-help:list-post:list-archive:list-unsubscribe :list-id:precedence:subject:mime-version:references:in-reply-to :message-id:date:to:from:delivered-to; bh=BtuamjL5swUQCgYAOkrdhIpllQxfKkbfr9uL4H/ccvQ=; fh=xmAeKtysnShNOmkhiJmYkS30uw4Fu2hvBJ7qlIwukxQ=; b=PS/hTJAN9OxlTVydkmkVqJnDuwUFzAaRaQzDRS/xK8Z8dXHuExT2O+2H5i3Jx9LGlo mX45eU55ltsduXPwmJQ4KFvdCd9HjWzBWGmN+s8yAtRxl4UtzGxmLcMT7NdLaBC9HJOu 85iyLfvLdCZGpmfG585WQmAKh93WNdAHyd1ycQ92wo1Zr1QUkA1xoaipQvjtHl+bLI2i /rl0cPTPLKnyVF9vrnlVq+tiLLrBgeFAMMDNLBH6GYevF6s9MeRxE/adSyhbG0Il1NN8 GPIxfmArQn4zFsrrPeFpBkmP0jEi4t6H47pui/dpmYMoBQtgVyyYI3bgwmVEC38wWpsI 5+gQ==; dara=google.com ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org Return-Path: Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org. [79.124.17.100]) by mx.google.com with ESMTPS id a640c23a62f3a-a9ee0dc2336si740987966b.301.2024.11.12.02.01.14 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 12 Nov 2024 02:01:14 -0800 (PST) Received-SPF: pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) client-ip=79.124.17.100; Authentication-Results: mx.google.com; spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 6CAF768DEAA; Tue, 12 Nov 2024 11:52:12 +0200 (EET) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from haasn.dev (haasn.dev [78.46.187.166]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 1718F68DE2F for ; Tue, 12 Nov 2024 11:52:03 +0200 (EET) Received: from haasn.dev (unknown [10.30.1.1]) by haasn.dev (Postfix) with ESMTP id 738E34B9C6; Tue, 12 Nov 2024 10:51:59 +0100 (CET) From: Niklas Haas To: ffmpeg-devel@ffmpeg.org Date: Tue, 12 Nov 2024 10:50:46 +0100 Message-ID: <20241112095154.483778-13-ffmpeg@haasn.xyz> X-Mailer: git-send-email 2.47.0 In-Reply-To: <20241112095154.483778-1-ffmpeg@haasn.xyz> References: <20241112095154.483778-1-ffmpeg@haasn.xyz> MIME-Version: 1.0 Subject: [FFmpeg-devel] [PATCH v6 12/12] avfilter/vf_scale: switch to new swscale API X-BeenThere: ffmpeg-devel@ffmpeg.org X-Mailman-Version: 2.1.29 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: Niklas Haas Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" X-TUID: 4ob+AOBTVdbA From: Niklas Haas Most logic from this filter has been co-opted into swscale itself, allowing the resulting filter to be substantially simpler as it no longer has to worry about context initialization, interlacing, etc. Sponsored-by: Sovereign Tech Fund Signed-off-by: Niklas Haas --- libavfilter/vf_scale.c | 354 +++++++++-------------------------------- 1 file changed, 72 insertions(+), 282 deletions(-) diff --git a/libavfilter/vf_scale.c b/libavfilter/vf_scale.c index a89ebe8c47..4afad8d958 100644 --- a/libavfilter/vf_scale.c +++ b/libavfilter/vf_scale.c @@ -31,6 +31,7 @@ #include "filters.h" #include "formats.h" #include "framesync.h" +#include "libavutil/pixfmt.h" #include "scale_eval.h" #include "video.h" #include "libavutil/eval.h" @@ -131,10 +132,7 @@ enum EvalMode { typedef struct ScaleContext { const AVClass *class; - struct SwsContext *sws; ///< software scaler context - struct SwsContext *isws[2]; ///< software scaler context for interlaced material - // context used for forwarding options to sws - struct SwsContext *sws_opts; + SwsContext *sws; FFFrameSync fs; /** @@ -149,8 +147,6 @@ typedef struct ScaleContext { int hsub, vsub; ///< chroma subsampling int slice_y; ///< top of current output slice - int input_is_pal; ///< set to 1 if the input format is paletted - int output_is_pal; ///< set to 1 if the output format is paletted int interlaced; int uses_ref; @@ -170,10 +166,6 @@ typedef struct ScaleContext { int in_chroma_loc; int out_chroma_loc; - int out_h_chr_pos; - int out_v_chr_pos; - int in_h_chr_pos; - int in_v_chr_pos; int force_original_aspect_ratio; int force_divisible_by; @@ -334,40 +326,24 @@ revert: static av_cold int preinit(AVFilterContext *ctx) { ScaleContext *scale = ctx->priv; - int ret; - scale->sws_opts = sws_alloc_context(); - if (!scale->sws_opts) + scale->sws = sws_alloc_context(); + if (!scale->sws) return AVERROR(ENOMEM); // set threads=0, so we can later check whether the user modified it - ret = av_opt_set_int(scale->sws_opts, "threads", 0, 0); - if (ret < 0) - return ret; + scale->sws->threads = 0; ff_framesync_preinit(&scale->fs); return 0; } -static const int sws_colorspaces[] = { - AVCOL_SPC_UNSPECIFIED, - AVCOL_SPC_RGB, - AVCOL_SPC_BT709, - AVCOL_SPC_BT470BG, - AVCOL_SPC_SMPTE170M, - AVCOL_SPC_FCC, - AVCOL_SPC_SMPTE240M, - AVCOL_SPC_BT2020_NCL, - -1 -}; - static int do_scale(FFFrameSync *fs); static av_cold int init(AVFilterContext *ctx) { ScaleContext *scale = ctx->priv; - int64_t threads; int ret; if (ctx->filter == &ff_vf_scale2ref) @@ -407,14 +383,13 @@ static av_cold int init(AVFilterContext *ctx) if (ret < 0) return ret; - if (scale->in_color_matrix != -1 && - !ff_fmt_is_in(scale->in_color_matrix, sws_colorspaces)) { + if (scale->in_color_matrix != -1 && !sws_test_colorspace(scale->in_color_matrix, 0)) { av_log(ctx, AV_LOG_ERROR, "Unsupported input color matrix '%s'\n", av_color_space_name(scale->in_color_matrix)); return AVERROR(EINVAL); } - if (!ff_fmt_is_in(scale->out_color_matrix, sws_colorspaces)) { + if (scale->out_color_matrix != -1 && !sws_test_colorspace(scale->out_color_matrix, 1)) { av_log(ctx, AV_LOG_ERROR, "Unsupported output color matrix '%s'\n", av_color_space_name(scale->out_color_matrix)); return AVERROR(EINVAL); @@ -424,25 +399,18 @@ static av_cold int init(AVFilterContext *ctx) scale->w_expr, scale->h_expr, (char *)av_x_if_null(scale->flags_str, ""), scale->interlaced); if (scale->flags_str && *scale->flags_str) { - ret = av_opt_set(scale->sws_opts, "sws_flags", scale->flags_str, 0); + ret = av_opt_set(scale->sws, "sws_flags", scale->flags_str, 0); if (ret < 0) return ret; } for (int i = 0; i < FF_ARRAY_ELEMS(scale->param); i++) - if (scale->param[i] != DBL_MAX) { - ret = av_opt_set_double(scale->sws_opts, i ? "param1" : "param0", - scale->param[i], 0); - if (ret < 0) - return ret; - } + if (scale->param[i] != DBL_MAX) + scale->sws->scaler_params[i] = scale->param[i]; // use generic thread-count if the user did not set it explicitly - ret = av_opt_get_int(scale->sws_opts, "threads", 0, &threads); - if (ret < 0) - return ret; - if (!threads) - av_opt_set_int(scale->sws_opts, "threads", ff_filter_get_nb_threads(ctx), 0); + if (!scale->sws->threads) + scale->sws->threads = ff_filter_get_nb_threads(ctx); if (ctx->filter != &ff_vf_scale2ref && scale->uses_ref) { AVFilterPad pad = { @@ -464,11 +432,7 @@ static av_cold void uninit(AVFilterContext *ctx) av_expr_free(scale->h_pexpr); scale->w_pexpr = scale->h_pexpr = NULL; ff_framesync_uninit(&scale->fs); - sws_freeContext(scale->sws_opts); - sws_freeContext(scale->sws); - sws_freeContext(scale->isws[0]); - sws_freeContext(scale->isws[1]); - scale->sws = NULL; + sws_free_context(&scale->sws); } static int query_formats(const AVFilterContext *ctx, @@ -485,10 +449,9 @@ static int query_formats(const AVFilterContext *ctx, formats = NULL; while ((desc = av_pix_fmt_desc_next(desc))) { pix_fmt = av_pix_fmt_desc_get_id(desc); - if ((sws_isSupportedInput(pix_fmt) || - sws_isSupportedEndiannessConversion(pix_fmt)) - && (ret = ff_add_format(&formats, pix_fmt)) < 0) { - return ret; + if (sws_test_format(pix_fmt, 0)) { + if ((ret = ff_add_format(&formats, pix_fmt)) < 0) + return ret; } } if ((ret = ff_formats_ref(formats, &cfg_in[0]->formats)) < 0) @@ -498,18 +461,24 @@ static int query_formats(const AVFilterContext *ctx, formats = NULL; while ((desc = av_pix_fmt_desc_next(desc))) { pix_fmt = av_pix_fmt_desc_get_id(desc); - if ((sws_isSupportedOutput(pix_fmt) || pix_fmt == AV_PIX_FMT_PAL8 || - sws_isSupportedEndiannessConversion(pix_fmt)) - && (ret = ff_add_format(&formats, pix_fmt)) < 0) { - return ret; + if (sws_test_format(pix_fmt, 1) || pix_fmt == AV_PIX_FMT_PAL8) { + if ((ret = ff_add_format(&formats, pix_fmt)) < 0) + return ret; } } if ((ret = ff_formats_ref(formats, &cfg_out[0]->formats)) < 0) return ret; /* accept all supported inputs, even if user overrides their properties */ - if ((ret = ff_formats_ref(ff_make_format_list(sws_colorspaces), - &cfg_in[0]->color_spaces)) < 0) + formats = ff_all_color_spaces(); + for (int i = 0; i < formats->nb_formats; i++) { + if (!sws_test_colorspace(formats->formats[i], 0)) { + for (int j = i--; j < formats->nb_formats; j++) + formats->formats[j] = formats->formats[j + 1]; + formats->nb_formats--; + } + } + if ((ret = ff_formats_ref(formats, &cfg_in[0]->color_spaces)) < 0) return ret; if ((ret = ff_formats_ref(ff_all_color_ranges(), @@ -517,9 +486,18 @@ static int query_formats(const AVFilterContext *ctx, return ret; /* propagate output properties if overridden */ - formats = scale->out_color_matrix != AVCOL_SPC_UNSPECIFIED - ? ff_make_formats_list_singleton(scale->out_color_matrix) - : ff_make_format_list(sws_colorspaces); + if (scale->out_color_matrix != AVCOL_SPC_UNSPECIFIED) { + formats = ff_make_formats_list_singleton(scale->out_color_matrix); + } else { + formats = ff_all_color_spaces(); + for (int i = 0; i < formats->nb_formats; i++) { + if (!sws_test_colorspace(formats->formats[i], 1)) { + for (int j = i--; j < formats->nb_formats; j++) + formats->formats[j] = formats->formats[j + 1]; + formats->nb_formats--; + } + } + } if ((ret = ff_formats_ref(formats, &cfg_out[0]->color_spaces)) < 0) return ret; @@ -621,50 +599,6 @@ fail: return ret; } -static void calc_chroma_pos(int *h_pos_out, int *v_pos_out, int chroma_loc, - int h_pos_override, int v_pos_override, - int h_sub, int v_sub, int index) -{ - int h_pos, v_pos; - - /* Explicitly default to center siting for compatibility with swscale */ - if (chroma_loc == AVCHROMA_LOC_UNSPECIFIED) - chroma_loc = AVCHROMA_LOC_CENTER; - - /* av_chroma_location_enum_to_pos() always gives us values in the range from - * 0 to 256, but we need to adjust this to the true value range of the - * subsampling grid, which may be larger for h/v_sub > 1 */ - av_chroma_location_enum_to_pos(&h_pos, &v_pos, chroma_loc); - h_pos *= (1 << h_sub) - 1; - v_pos *= (1 << v_sub) - 1; - - if (h_pos_override != -513) - h_pos = h_pos_override; - if (v_pos_override != -513) - v_pos = v_pos_override; - - /* Fix vertical chroma position for interlaced frames */ - if (v_sub && index > 0) { - /* When vertically subsampling, chroma samples are effectively only - * placed next to even rows. To access them from the odd field, we need - * to account for this shift by offsetting the distance of one luma row. - * - * For 4x vertical subsampling (v_sub == 2), they are only placed - * next to every *other* even row, so we need to shift by three luma - * rows to get to the chroma sample. */ - if (index == 2) - v_pos += (256 << v_sub) - 256; - - /* Luma row distance is doubled for fields, so halve offsets */ - v_pos >>= 1; - } - - /* Explicitly strip chroma offsets when not subsampling, because it - * interferes with the operation of flags like SWS_FULL_CHR_H_INP */ - *h_pos_out = h_sub ? h_pos : -513; - *v_pos_out = v_sub ? v_pos : -513; -} - static int config_props(AVFilterLink *outlink) { AVFilterContext *ctx = outlink->src; @@ -672,12 +606,8 @@ static int config_props(AVFilterLink *outlink) AVFilterLink *inlink = ctx->filter == &ff_vf_scale2ref ? outlink->src->inputs[1] : outlink->src->inputs[0]; - enum AVPixelFormat outfmt = outlink->format; - const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(inlink->format); - const AVPixFmtDescriptor *outdesc = av_pix_fmt_desc_get(outfmt); ScaleContext *scale = ctx->priv; uint8_t *flags_val = NULL; - int in_range, in_colorspace; int ret; if ((ret = scale_eval_dimensions(ctx)) < 0) @@ -701,107 +631,12 @@ static int config_props(AVFilterLink *outlink) /* TODO: make algorithm configurable */ - scale->input_is_pal = desc->flags & AV_PIX_FMT_FLAG_PAL; - if (outfmt == AV_PIX_FMT_PAL8) outfmt = AV_PIX_FMT_BGR8; - scale->output_is_pal = av_pix_fmt_desc_get(outfmt)->flags & AV_PIX_FMT_FLAG_PAL; - - in_range = scale->in_range; - if (in_range == AVCOL_RANGE_UNSPECIFIED) - in_range = inlink0->color_range; - - in_colorspace = scale->in_color_matrix; - if (in_colorspace == -1 /* auto */) - in_colorspace = inlink0->colorspace; - - if (scale->sws) - sws_freeContext(scale->sws); - if (scale->isws[0]) - sws_freeContext(scale->isws[0]); - if (scale->isws[1]) - sws_freeContext(scale->isws[1]); - scale->isws[0] = scale->isws[1] = scale->sws = NULL; - if (inlink0->w == outlink->w && - inlink0->h == outlink->h && - in_range == outlink->color_range && - in_colorspace == outlink->colorspace && - inlink0->format == outlink->format && - scale->in_chroma_loc == scale->out_chroma_loc) - ; - else { - struct SwsContext **swscs[3] = {&scale->sws, &scale->isws[0], &scale->isws[1]}; - int i; - - for (i = 0; i < 3; i++) { - int in_full, out_full, brightness, contrast, saturation; - int h_chr_pos, v_chr_pos; - const int *inv_table, *table; - struct SwsContext *const s = sws_alloc_context(); - if (!s) - return AVERROR(ENOMEM); - *swscs[i] = s; - - ret = av_opt_copy(s, scale->sws_opts); - if (ret < 0) - return ret; - - av_opt_set_int(s, "srcw", inlink0 ->w, 0); - av_opt_set_int(s, "srch", inlink0 ->h >> !!i, 0); - av_opt_set_int(s, "src_format", inlink0->format, 0); - av_opt_set_int(s, "dstw", outlink->w, 0); - av_opt_set_int(s, "dsth", outlink->h >> !!i, 0); - av_opt_set_int(s, "dst_format", outfmt, 0); - if (in_range != AVCOL_RANGE_UNSPECIFIED) - av_opt_set_int(s, "src_range", - in_range == AVCOL_RANGE_JPEG, 0); - if (outlink->color_range != AVCOL_RANGE_UNSPECIFIED) - av_opt_set_int(s, "dst_range", - outlink->color_range == AVCOL_RANGE_JPEG, 0); - - calc_chroma_pos(&h_chr_pos, &v_chr_pos, scale->in_chroma_loc, - scale->in_h_chr_pos, scale->in_v_chr_pos, - desc->log2_chroma_w, desc->log2_chroma_h, i); - av_opt_set_int(s, "src_h_chr_pos", h_chr_pos, 0); - av_opt_set_int(s, "src_v_chr_pos", v_chr_pos, 0); - - calc_chroma_pos(&h_chr_pos, &v_chr_pos, scale->out_chroma_loc, - scale->out_h_chr_pos, scale->out_v_chr_pos, - outdesc->log2_chroma_w, outdesc->log2_chroma_h, i); - av_opt_set_int(s, "dst_h_chr_pos", h_chr_pos, 0); - av_opt_set_int(s, "dst_v_chr_pos", v_chr_pos, 0); - - if ((ret = sws_init_context(s, NULL, NULL)) < 0) - return ret; - - sws_getColorspaceDetails(s, (int **)&inv_table, &in_full, - (int **)&table, &out_full, - &brightness, &contrast, &saturation); - - if (scale->in_color_matrix == -1 /* auto */) - inv_table = sws_getCoefficients(inlink0->colorspace); - else if (scale->in_color_matrix != AVCOL_SPC_UNSPECIFIED) - inv_table = sws_getCoefficients(scale->in_color_matrix); - if (outlink->colorspace != AVCOL_SPC_UNSPECIFIED) - table = sws_getCoefficients(outlink->colorspace); - else if (scale->in_color_matrix != AVCOL_SPC_UNSPECIFIED) - table = inv_table; - - sws_setColorspaceDetails(s, inv_table, in_full, - table, out_full, - brightness, contrast, saturation); - - if (!scale->interlaced) - break; - } - } - if (inlink0->sample_aspect_ratio.num){ outlink->sample_aspect_ratio = av_mul_q((AVRational){outlink->h * inlink0->w, outlink->w * inlink0->h}, inlink0->sample_aspect_ratio); } else outlink->sample_aspect_ratio = inlink0->sample_aspect_ratio; - if (scale->sws) - av_opt_get(scale->sws, "sws_flags", 0, &flags_val); - + av_opt_get(scale->sws, "sws_flags", 0, &flags_val); av_log(ctx, AV_LOG_VERBOSE, "w:%d h:%d fmt:%s csp:%s range:%s sar:%d/%d -> w:%d h:%d fmt:%s csp:%s range:%s sar:%d/%d flags:%s\n", inlink ->w, inlink ->h, av_get_pix_fmt_name( inlink->format), av_color_space_name(inlink->colorspace), av_color_range_name(inlink->color_range), @@ -868,56 +703,6 @@ static int request_frame_ref(AVFilterLink *outlink) return ff_request_frame(outlink->src->inputs[1]); } -static void frame_offset(AVFrame *frame, int dir, int is_pal) -{ - for (int i = 0; i < 4 && frame->data[i]; i++) { - if (i == 1 && is_pal) - break; - frame->data[i] += frame->linesize[i] * dir; - } -} - -static int scale_field(ScaleContext *scale, AVFrame *dst, AVFrame *src, - int field) -{ - int orig_h_src = src->height; - int orig_h_dst = dst->height; - int ret; - - // offset the data pointers for the bottom field - if (field) { - frame_offset(src, 1, scale->input_is_pal); - frame_offset(dst, 1, scale->output_is_pal); - } - - // take every second line - for (int i = 0; i < 4; i++) { - src->linesize[i] *= 2; - dst->linesize[i] *= 2; - } - src->height /= 2; - dst->height /= 2; - - ret = sws_scale_frame(scale->isws[field], dst, src); - if (ret < 0) - return ret; - - // undo the changes we made above - for (int i = 0; i < 4; i++) { - src->linesize[i] /= 2; - dst->linesize[i] /= 2; - } - src->height = orig_h_src; - dst->height = orig_h_dst; - - if (field) { - frame_offset(src, -1, scale->input_is_pal); - frame_offset(dst, -1, scale->output_is_pal); - } - - return 0; -} - /* Takes over ownership of *frame_in, passes ownership of *frame_out to caller */ static int scale_frame(AVFilterLink *link, AVFrame **frame_in, AVFrame **frame_out) @@ -929,12 +714,9 @@ static int scale_frame(AVFilterLink *link, AVFrame **frame_in, AVFrame *out, *in = *frame_in; const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(link->format); char buf[32]; - int ret; - int frame_changed; + int ret, flags_orig, frame_changed; *frame_in = NULL; - if (in->colorspace == AVCOL_SPC_YCGCO) - av_log(link->dst, AV_LOG_WARNING, "Detected unsupported YCgCo colorspace.\n"); frame_changed = in->width != link->w || in->height != link->h || @@ -1013,11 +795,6 @@ FF_ENABLE_DEPRECATION_WARNINGS } scale: - if (!scale->sws) { - *frame_out = in; - return 0; - } - scale->hsub = desc->log2_chroma_w; scale->vsub = desc->log2_chroma_h; @@ -1027,6 +804,18 @@ scale: goto err; } + if (scale->in_color_matrix != -1) + in->colorspace = scale->in_color_matrix; + if (scale->in_range != AVCOL_RANGE_UNSPECIFIED) + in->color_range = scale->in_range; + in->chroma_location = scale->in_chroma_loc; + + flags_orig = in->flags; + if (scale->interlaced > 0) + in->flags |= AV_FRAME_FLAG_INTERLACED; + else if (!scale->interlaced) + in->flags &= ~AV_FRAME_FLAG_INTERLACED; + av_frame_copy_props(out, in); out->width = outlink->w; out->height = outlink->h; @@ -1035,26 +824,31 @@ scale: if (scale->out_chroma_loc != AVCHROMA_LOC_UNSPECIFIED) out->chroma_location = scale->out_chroma_loc; - if (scale->output_is_pal) - avpriv_set_systematic_pal2((uint32_t*)out->data[1], outlink->format == AV_PIX_FMT_PAL8 ? AV_PIX_FMT_BGR8 : outlink->format); - av_reduce(&out->sample_aspect_ratio.num, &out->sample_aspect_ratio.den, (int64_t)in->sample_aspect_ratio.num * outlink->h * link->w, (int64_t)in->sample_aspect_ratio.den * outlink->w * link->h, INT_MAX); - if (scale->interlaced>0 || (scale->interlaced<0 && - (in->flags & AV_FRAME_FLAG_INTERLACED))) { - ret = scale_field(scale, out, in, 0); - if (ret >= 0) - ret = scale_field(scale, out, in, 1); - } else { - ret = sws_scale_frame(scale->sws, out, in); + if (sws_is_noop(out, in)) { + av_frame_free(&out); + in->flags = flags_orig; + *frame_out = in; + return 0; } + if (out->format == AV_PIX_FMT_PAL8) { + out->format = AV_PIX_FMT_BGR8; + avpriv_set_systematic_pal2((uint32_t*) out->data[1], out->format); + } + + ret = sws_scale_frame(scale->sws, out, in); + av_frame_free(&in); + out->flags = flags_orig; + out->format = outlink->format; /* undo PAL8 handling */ if (ret < 0) av_frame_free(&out); *frame_out = out; + return ret; err: av_frame_free(&in); @@ -1232,8 +1026,8 @@ static void *child_next(void *obj, void *prev) { ScaleContext *s = obj; if (!prev) - return s->sws_opts; - if (prev == s->sws_opts) + return s->sws; + if (prev == s->sws) return &s->fs; return NULL; } @@ -1281,10 +1075,6 @@ static const AVOption scale_options[] = { {"top", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCHROMA_LOC_TOP}, 0, 0, FLAGS, .unit = "chroma_loc"}, {"bottomleft", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCHROMA_LOC_BOTTOMLEFT}, 0, 0, FLAGS, .unit = "chroma_loc"}, {"bottom", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCHROMA_LOC_BOTTOM}, 0, 0, FLAGS, .unit = "chroma_loc"}, - { "in_v_chr_pos", "input vertical chroma position in luma grid/256" , OFFSET(in_v_chr_pos), AV_OPT_TYPE_INT, { .i64 = -513}, -513, 512, FLAGS }, - { "in_h_chr_pos", "input horizontal chroma position in luma grid/256", OFFSET(in_h_chr_pos), AV_OPT_TYPE_INT, { .i64 = -513}, -513, 512, FLAGS }, - { "out_v_chr_pos", "output vertical chroma position in luma grid/256" , OFFSET(out_v_chr_pos), AV_OPT_TYPE_INT, { .i64 = -513}, -513, 512, FLAGS }, - { "out_h_chr_pos", "output horizontal chroma position in luma grid/256", OFFSET(out_h_chr_pos), AV_OPT_TYPE_INT, { .i64 = -513}, -513, 512, FLAGS }, { "force_original_aspect_ratio", "decrease or increase w/h if necessary to keep the original AR", OFFSET(force_original_aspect_ratio), AV_OPT_TYPE_INT, { .i64 = 0}, 0, 2, FLAGS, .unit = "force_oar" }, { "disable", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = 0 }, 0, 0, FLAGS, .unit = "force_oar" }, { "decrease", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = 1 }, 0, 0, FLAGS, .unit = "force_oar" }, @@ -1350,7 +1140,7 @@ static void *scale2ref_child_next(void *obj, void *prev) { ScaleContext *s = obj; if (!prev) - return s->sws_opts; + return s->sws; return NULL; }