[FFmpeg-devel] [PATCH v2 1/5] lavfi: generalize colorspace coefficent helpers

Niklas Haas ffmpeg at haasn.xyz
Tue Apr 19 15:46:53 EEST 2022


From: Niklas Haas <git at haasn.dev>

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 <git at haasn.dev>
---
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 {
-- 
2.35.1



More information about the ffmpeg-devel mailing list