From patchwork Tue Apr 19 12:46:53 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Niklas Haas X-Patchwork-Id: 35345 Delivered-To: ffmpegpatchwork2@gmail.com Received: by 2002:a05:6a20:3b9e:b0:7d:cfb5:dc7c with SMTP id b30csp328270pzh; Tue, 19 Apr 2022 05:47:44 -0700 (PDT) X-Google-Smtp-Source: ABdhPJyo248bzBKwZxGXKxMWX1sL/fJn//Mm1/df1rXi8HZED/MqOGVNSu0r3s0ZETckPhQrnwRl X-Received: by 2002:a05:6402:3509:b0:423:f906:8e2d with SMTP id b9-20020a056402350900b00423f9068e2dmr5110521edd.333.1650372464464; Tue, 19 Apr 2022 05:47:44 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1650372464; cv=none; d=google.com; s=arc-20160816; b=QHiO/MuILMHvvB6YxJEL3ZRi30jRJJVdXMSlb7pPf8yk096tw2WXKpeleAODUOXI9h /yRKkKBi/N3u0jczl4A9sgcwa+4O7KJ5RSiSIFJNAQvNC536RMqW5zMLBrty1PFaU3zF BMNch0c+1zIl3RyE6guGmOXPyqWonhC3/db0WGWoLAcq/6QBhRRjMnxBavJGcxfHG1bK 0BFB9wlGX8TFRDYXTtg24JTdlr4Tj/g3CJV9T8MohSmBjphNngcWGDwTcEd+aNNCSKa7 zUUZB+vad4vXBpnuiskk1k5oaaK9S55Cpg8AP9l27D5vIYHolkUqW5MVHL8s7CISFbi2 ShwA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; 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:message-id:date:to:from :dkim-signature:delivered-to; bh=iMY2I3F0vpvA1FfKTD0t7WErmk1hq5D1AaaTqS0wgYY=; b=pUbD96cbDv8wqkSsjoTLjblWUS2TDs0183TCKmK09q6wuz8SxAlmzi0+d5rYSxYani H0Su24SISHYnX4x+D577bLGh6nr5+2j4Leg0/V0rVcw4qcRuRn71SikEdzvE+pBORUkd BIq8C6XDCo0ivg2smVI+rpyjwWrLIPzKVIV7iljZzcGJuz0kMnEZJFbwlspNk0aKTk+X kmcDQ8ljlYjGb2npcy0nxE9zNA41NM9l/oKH9819gKlQTZiVdrhD22r2WbeUxYyLf1RD C9J7LFS0Qc6qW5ZPv1nkFESy9+1pFbHuD96bBDcZXO/8ky1l6pV9JjrsH6m05uId5UFO HznA== ARC-Authentication-Results: i=1; mx.google.com; dkim=neutral (body hash did not verify) header.i=@haasn.xyz header.s=mail header.b=Dj0NURo9; 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 ESMTP id h1-20020a1709066d8100b006e860384033si7588190ejt.106.2022.04.19.05.47.43; Tue, 19 Apr 2022 05:47:44 -0700 (PDT) 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; dkim=neutral (body hash did not verify) header.i=@haasn.xyz header.s=mail header.b=Dj0NURo9; 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 3FE7568A8CD; Tue, 19 Apr 2022 15:47:39 +0300 (EEST) 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 4091E68B34E for ; Tue, 19 Apr 2022 15:47:32 +0300 (EEST) Received: from haasn.dev (unknown [10.30.0.2]) by haasn.dev (Postfix) with ESMTP id 7FDC449CBD; Tue, 19 Apr 2022 14:47:31 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=haasn.xyz; s=mail; t=1650372451; bh=n8a2Gh51x2O3szqihYW9TL8Yrjt2gKROXnQbd5qSu+U=; h=From:To:Cc:Subject:Date:From; b=Dj0NURo9TSm1n6kGHEbfKK1njXgFLg4+b6RWqogJBNZRif3rauIAjdm+ArkIoIUjh tljbKUA4kf/On/1rEYU/rbI6qeNk2+FCv7Fgk2fbUz1OVIt/uuPV4YA38c1ZDjOkmC 459RK3L0JdsG7yv+vdbjY6QwgOwRJeccXpxOlqlw= From: Niklas Haas To: ffmpeg-devel@ffmpeg.org Date: Tue, 19 Apr 2022 14:46:53 +0200 Message-Id: <20220419124656.121638-1-ffmpeg@haasn.xyz> X-Mailer: git-send-email 2.35.1 MIME-Version: 1.0 Subject: [FFmpeg-devel] [PATCH v2 1/5] lavfi: generalize colorspace coefficent helpers 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: KA1L5A4t2LTW From: Niklas Haas These are needed beyond just vf_colorspace, so give them a new home in colorspace.h. In addition to moving code around, also merge the white point and primary coefficients into a single struct to slightly increase the convenience and shrink the size of the new API by avoiding the need to introduce an extra function just to look up the white point as well. The only place the distinction matters is in a single enum comparison, which can just as well be a single memcpy - the difference is negligible. Signed-off-by: Niklas Haas --- Changes to v1 of this series: - minor cleanup here and there --- libavfilter/colorspace.c | 32 +++++++++++++++++ libavfilter/colorspace.h | 6 ++++ libavfilter/vf_colorspace.c | 70 ++++++------------------------------- 3 files changed, 49 insertions(+), 59 deletions(-) diff --git a/libavfilter/colorspace.c b/libavfilter/colorspace.c index 19616e4f12..25e99f4759 100644 --- a/libavfilter/colorspace.c +++ b/libavfilter/colorspace.c @@ -138,6 +138,38 @@ const struct LumaCoefficients *ff_get_luma_coefficients(enum AVColorSpace csp) return coeffs; } +#define WP_D65 { 0.3127, 0.3290 } +#define WP_C { 0.3100, 0.3160 } +#define WP_DCI { 0.3140, 0.3510 } +#define WP_E { 1/3.0f, 1/3.0f } + +static const struct ColorPrimaries color_primaries[AVCOL_PRI_NB] = { + [AVCOL_PRI_BT709] = { WP_D65, { 0.640, 0.330, 0.300, 0.600, 0.150, 0.060 } }, + [AVCOL_PRI_BT470M] = { WP_C, { 0.670, 0.330, 0.210, 0.710, 0.140, 0.080 } }, + [AVCOL_PRI_BT470BG] = { WP_D65, { 0.640, 0.330, 0.290, 0.600, 0.150, 0.060 } }, + [AVCOL_PRI_SMPTE170M] = { WP_D65, { 0.630, 0.340, 0.310, 0.595, 0.155, 0.070 } }, + [AVCOL_PRI_SMPTE240M] = { WP_D65, { 0.630, 0.340, 0.310, 0.595, 0.155, 0.070 } }, + [AVCOL_PRI_SMPTE428] = { WP_E, { 0.735, 0.265, 0.274, 0.718, 0.167, 0.009 } }, + [AVCOL_PRI_SMPTE431] = { WP_DCI, { 0.680, 0.320, 0.265, 0.690, 0.150, 0.060 } }, + [AVCOL_PRI_SMPTE432] = { WP_D65, { 0.680, 0.320, 0.265, 0.690, 0.150, 0.060 } }, + [AVCOL_PRI_FILM] = { WP_C, { 0.681, 0.319, 0.243, 0.692, 0.145, 0.049 } }, + [AVCOL_PRI_BT2020] = { WP_D65, { 0.708, 0.292, 0.170, 0.797, 0.131, 0.046 } }, + [AVCOL_PRI_JEDEC_P22] = { WP_D65, { 0.630, 0.340, 0.295, 0.605, 0.155, 0.077 } }, +}; + +const struct ColorPrimaries *ff_get_color_primaries(enum AVColorPrimaries prm) +{ + const struct ColorPrimaries *p; + + if (prm >= AVCOL_PRI_NB) + return NULL; + p = &color_primaries[prm]; + if (!p->prim.xr) + return NULL; + + return p; +} + void ff_fill_rgb2yuv_table(const struct LumaCoefficients *coeffs, double rgb2yuv[3][3]) { diff --git a/libavfilter/colorspace.h b/libavfilter/colorspace.h index a4c5078d5f..fc415fed05 100644 --- a/libavfilter/colorspace.h +++ b/libavfilter/colorspace.h @@ -37,6 +37,11 @@ struct WhitepointCoefficients { double xw, yw; }; +struct ColorPrimaries { + struct WhitepointCoefficients wp; + struct PrimaryCoefficients prim; +}; + void ff_matrix_invert_3x3(const double in[3][3], double out[3][3]); void ff_matrix_mul_3x3(double dst[3][3], const double src1[3][3], const double src2[3][3]); @@ -44,6 +49,7 @@ void ff_fill_rgb2xyz_table(const struct PrimaryCoefficients *coeffs, const struct WhitepointCoefficients *wp, double rgb2xyz[3][3]); +const struct ColorPrimaries *ff_get_color_primaries(enum AVColorPrimaries prm); const struct LumaCoefficients *ff_get_luma_coefficients(enum AVColorSpace csp); void ff_fill_rgb2yuv_table(const struct LumaCoefficients *coeffs, double rgb2yuv[3][3]); diff --git a/libavfilter/vf_colorspace.c b/libavfilter/vf_colorspace.c index 0bd8e2b0cf..3c8b3b20eb 100644 --- a/libavfilter/vf_colorspace.c +++ b/libavfilter/vf_colorspace.c @@ -55,14 +55,6 @@ enum Colorspace { CS_NB, }; -enum Whitepoint { - WP_D65, - WP_C, - WP_DCI, - WP_E, - WP_NB, -}; - enum WhitepointAdaptation { WP_ADAPT_BRADFORD, WP_ADAPT_VON_KRIES, @@ -110,11 +102,6 @@ static const enum AVColorSpace default_csp[CS_NB + 1] = { [CS_NB] = AVCOL_SPC_UNSPECIFIED, }; -struct ColorPrimaries { - enum Whitepoint wp; - struct PrimaryCoefficients coeff; -}; - struct TransferCharacteristics { double alpha, beta, gamma, delta; }; @@ -201,40 +188,6 @@ static const struct TransferCharacteristics * return coeffs; } -static const struct WhitepointCoefficients whitepoint_coefficients[WP_NB] = { - [WP_D65] = { 0.3127, 0.3290 }, - [WP_C] = { 0.3100, 0.3160 }, - [WP_DCI] = { 0.3140, 0.3510 }, - [WP_E] = { 1/3.0f, 1/3.0f }, -}; - -static const struct ColorPrimaries color_primaries[AVCOL_PRI_NB] = { - [AVCOL_PRI_BT709] = { WP_D65, { 0.640, 0.330, 0.300, 0.600, 0.150, 0.060 } }, - [AVCOL_PRI_BT470M] = { WP_C, { 0.670, 0.330, 0.210, 0.710, 0.140, 0.080 } }, - [AVCOL_PRI_BT470BG] = { WP_D65, { 0.640, 0.330, 0.290, 0.600, 0.150, 0.060 } }, - [AVCOL_PRI_SMPTE170M] = { WP_D65, { 0.630, 0.340, 0.310, 0.595, 0.155, 0.070 } }, - [AVCOL_PRI_SMPTE240M] = { WP_D65, { 0.630, 0.340, 0.310, 0.595, 0.155, 0.070 } }, - [AVCOL_PRI_SMPTE428] = { WP_E, { 0.735, 0.265, 0.274, 0.718, 0.167, 0.009 } }, - [AVCOL_PRI_SMPTE431] = { WP_DCI, { 0.680, 0.320, 0.265, 0.690, 0.150, 0.060 } }, - [AVCOL_PRI_SMPTE432] = { WP_D65, { 0.680, 0.320, 0.265, 0.690, 0.150, 0.060 } }, - [AVCOL_PRI_FILM] = { WP_C, { 0.681, 0.319, 0.243, 0.692, 0.145, 0.049 } }, - [AVCOL_PRI_BT2020] = { WP_D65, { 0.708, 0.292, 0.170, 0.797, 0.131, 0.046 } }, - [AVCOL_PRI_JEDEC_P22] = { WP_D65, { 0.630, 0.340, 0.295, 0.605, 0.155, 0.077 } }, -}; - -static const struct ColorPrimaries *get_color_primaries(enum AVColorPrimaries prm) -{ - const struct ColorPrimaries *p; - - if (prm >= AVCOL_PRI_NB) - return NULL; - p = &color_primaries[prm]; - if (!p->coeff.xr) - return NULL; - - return p; -} - static int fill_gamma_table(ColorSpaceContext *s) { int n; @@ -280,7 +233,8 @@ static int fill_gamma_table(ColorSpaceContext *s) * This function uses the Bradford mechanism. */ static void fill_whitepoint_conv_table(double out[3][3], enum WhitepointAdaptation wp_adapt, - enum Whitepoint src, enum Whitepoint dst) + const struct WhitepointCoefficients *wp_src, + const struct WhitepointCoefficients *wp_dst) { static const double ma_tbl[NB_WP_ADAPT_NON_IDENTITY][3][3] = { [WP_ADAPT_BRADFORD] = { @@ -294,9 +248,7 @@ static void fill_whitepoint_conv_table(double out[3][3], enum WhitepointAdaptati }, }; const double (*ma)[3] = ma_tbl[wp_adapt]; - const struct WhitepointCoefficients *wp_src = &whitepoint_coefficients[src]; double zw_src = 1.0 - wp_src->xw - wp_src->yw; - const struct WhitepointCoefficients *wp_dst = &whitepoint_coefficients[dst]; double zw_dst = 1.0 - wp_dst->xw - wp_dst->yw; double mai[3][3], fac[3][3], tmp[3][3]; double rs, gs, bs, rd, gd, bd; @@ -486,7 +438,7 @@ static int create_filtergraph(AVFilterContext *ctx, s->in_prm = default_prm[FFMIN(s->user_iall, CS_NB)]; if (s->user_iprm != AVCOL_PRI_UNSPECIFIED) s->in_prm = s->user_iprm; - s->in_primaries = get_color_primaries(s->in_prm); + s->in_primaries = ff_get_color_primaries(s->in_prm); if (!s->in_primaries) { av_log(ctx, AV_LOG_ERROR, "Unsupported input primaries %d (%s)\n", @@ -494,7 +446,7 @@ static int create_filtergraph(AVFilterContext *ctx, return AVERROR(EINVAL); } s->out_prm = out->color_primaries; - s->out_primaries = get_color_primaries(s->out_prm); + s->out_primaries = ff_get_color_primaries(s->out_prm); if (!s->out_primaries) { if (s->out_prm == AVCOL_PRI_UNSPECIFIED) { if (s->user_all == CS_UNSPECIFIED) { @@ -516,17 +468,17 @@ static int create_filtergraph(AVFilterContext *ctx, double rgb2xyz[3][3], xyz2rgb[3][3], rgb2rgb[3][3]; const struct WhitepointCoefficients *wp_out, *wp_in; - wp_out = &whitepoint_coefficients[s->out_primaries->wp]; - wp_in = &whitepoint_coefficients[s->in_primaries->wp]; - ff_fill_rgb2xyz_table(&s->out_primaries->coeff, wp_out, rgb2xyz); + wp_out = &s->out_primaries->wp; + wp_in = &s->in_primaries->wp; + ff_fill_rgb2xyz_table(&s->out_primaries->prim, wp_out, rgb2xyz); ff_matrix_invert_3x3(rgb2xyz, xyz2rgb); - ff_fill_rgb2xyz_table(&s->in_primaries->coeff, wp_in, rgb2xyz); - if (s->out_primaries->wp != s->in_primaries->wp && + ff_fill_rgb2xyz_table(&s->in_primaries->prim, wp_in, rgb2xyz); + if (memcmp(wp_in, wp_out, sizeof(*wp_in)) != 0 && s->wp_adapt != WP_ADAPT_IDENTITY) { double wpconv[3][3], tmp[3][3]; - fill_whitepoint_conv_table(wpconv, s->wp_adapt, s->in_primaries->wp, - s->out_primaries->wp); + fill_whitepoint_conv_table(wpconv, s->wp_adapt, &s->in_primaries->wp, + &s->out_primaries->wp); ff_matrix_mul_3x3(tmp, rgb2xyz, wpconv); ff_matrix_mul_3x3(rgb2rgb, tmp, xyz2rgb); } else {