diff options
author | Leo Izen <leo.izen@gmail.com> | 2022-05-28 09:30:36 -0400 |
---|---|---|
committer | Ronald S. Bultje <rsbultje@gmail.com> | 2022-06-01 13:52:38 -0400 |
commit | d42b410e05ad1c4d6e74aa981b4a4423103291fb (patch) | |
tree | ef3a78871469fd303caa770e888d78779998d030 /libavfilter/colorspace.c | |
parent | 77b529fbd228fe30a870e3157f051885b436ad92 (diff) | |
download | ffmpeg-d42b410e05ad1c4d6e74aa981b4a4423103291fb.tar.gz |
avutil/csp: create public API for colorspace structs
This commit moves some of the functionality from avfilter/colorspace
into avutil/csp and exposes it as a public API so it can be used by
libavcodec and/or libavformat. It also converts those structs from
double values to AVRational to make regression testing easier and
more consistent.
Signed-off-by: Ronald S. Bultje <rsbultje@gmail.com>
Diffstat (limited to 'libavfilter/colorspace.c')
-rw-r--r-- | libavfilter/colorspace.c | 143 |
1 files changed, 30 insertions, 113 deletions
diff --git a/libavfilter/colorspace.c b/libavfilter/colorspace.c index 8d7b882375..7f74fe5113 100644 --- a/libavfilter/colorspace.c +++ b/libavfilter/colorspace.c @@ -65,24 +65,28 @@ void ff_matrix_mul_3x3(double dst[3][3], /* * see e.g. http://www.brucelindbloom.com/index.html?Eqn_RGB_XYZ_Matrix.html */ -void ff_fill_rgb2xyz_table(const struct PrimaryCoefficients *coeffs, - const struct WhitepointCoefficients *wp, +void ff_fill_rgb2xyz_table(const AVPrimaryCoefficients *coeffs, + const AVWhitepointCoefficients *wp, double rgb2xyz[3][3]) { double i[3][3], sr, sg, sb, zw; - - rgb2xyz[0][0] = coeffs->xr / coeffs->yr; - rgb2xyz[0][1] = coeffs->xg / coeffs->yg; - rgb2xyz[0][2] = coeffs->xb / coeffs->yb; + double xr = av_q2d(coeffs->r.x), yr = av_q2d(coeffs->r.y); + double xg = av_q2d(coeffs->g.x), yg = av_q2d(coeffs->g.y); + double xb = av_q2d(coeffs->b.x), yb = av_q2d(coeffs->b.y); + double xw = av_q2d(wp->x), yw = av_q2d(wp->y); + + rgb2xyz[0][0] = xr / yr; + rgb2xyz[0][1] = xg / yg; + rgb2xyz[0][2] = xb / yb; rgb2xyz[1][0] = rgb2xyz[1][1] = rgb2xyz[1][2] = 1.0; - rgb2xyz[2][0] = (1.0 - coeffs->xr - coeffs->yr) / coeffs->yr; - rgb2xyz[2][1] = (1.0 - coeffs->xg - coeffs->yg) / coeffs->yg; - rgb2xyz[2][2] = (1.0 - coeffs->xb - coeffs->yb) / coeffs->yb; + rgb2xyz[2][0] = (1.0 - xr - yr) / yr; + rgb2xyz[2][1] = (1.0 - xg - yg) / yg; + rgb2xyz[2][2] = (1.0 - xb - yb) / yb; ff_matrix_invert_3x3(rgb2xyz, i); - zw = 1.0 - wp->xw - wp->yw; - sr = i[0][0] * wp->xw + i[0][1] * wp->yw + i[0][2] * zw; - sg = i[1][0] * wp->xw + i[1][1] * wp->yw + i[1][2] * zw; - sb = i[2][0] * wp->xw + i[2][1] * wp->yw + i[2][2] * zw; + zw = 1.0 - xw - yw; + sr = i[0][0] * xw + i[0][1] * yw + i[0][2] * zw; + sg = i[1][0] * xw + i[1][1] * yw + i[1][2] * zw; + sb = i[2][0] * xw + i[2][1] * yw + i[2][2] * zw; rgb2xyz[0][0] *= sr; rgb2xyz[0][1] *= sg; rgb2xyz[0][2] *= sb; @@ -107,119 +111,32 @@ static const double gbr_matrix[3][3] = { 0.5, -0.5, 0 }, }; -/* - * All constants explained in e.g. https://linuxtv.org/downloads/v4l-dvb-apis/ch02s06.html - * The older ones (bt470bg/m) are also explained in their respective ITU docs - * (e.g. https://www.itu.int/dms_pubrec/itu-r/rec/bt/R-REC-BT.470-5-199802-S!!PDF-E.pdf) - * whereas the newer ones can typically be copied directly from wikipedia :) - */ -static const struct LumaCoefficients luma_coefficients[AVCOL_SPC_NB] = { - [AVCOL_SPC_FCC] = { 0.30, 0.59, 0.11 }, - [AVCOL_SPC_BT470BG] = { 0.299, 0.587, 0.114 }, - [AVCOL_SPC_SMPTE170M] = { 0.299, 0.587, 0.114 }, - [AVCOL_SPC_BT709] = { 0.2126, 0.7152, 0.0722 }, - [AVCOL_SPC_SMPTE240M] = { 0.212, 0.701, 0.087 }, - [AVCOL_SPC_YCOCG] = { 0.25, 0.5, 0.25 }, - [AVCOL_SPC_RGB] = { 1, 1, 1 }, - [AVCOL_SPC_BT2020_NCL] = { 0.2627, 0.6780, 0.0593 }, - [AVCOL_SPC_BT2020_CL] = { 0.2627, 0.6780, 0.0593 }, -}; - -const struct LumaCoefficients *ff_get_luma_coefficients(enum AVColorSpace csp) -{ - const struct LumaCoefficients *coeffs; - - if (csp >= AVCOL_SPC_NB) - return NULL; - coeffs = &luma_coefficients[csp]; - if (!coeffs->cr) - return NULL; - - 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; -} - -enum AVColorPrimaries ff_detect_color_primaries(const struct ColorPrimaries *prm) -{ - double delta; - - for (enum AVColorPrimaries p = 0; p < AVCOL_PRI_NB; p++) { - const struct ColorPrimaries *ref = &color_primaries[p]; - if (!ref->prim.xr) - continue; - - delta = fabs(prm->prim.xr - ref->prim.xr) + - fabs(prm->prim.yr - ref->prim.yr) + - fabs(prm->prim.yg - ref->prim.yg) + - fabs(prm->prim.yg - ref->prim.yg) + - fabs(prm->prim.yb - ref->prim.yb) + - fabs(prm->prim.yb - ref->prim.yb) + - fabs(prm->wp.xw - ref->wp.xw) + - fabs(prm->wp.yw - ref->wp.yw); - - if (delta < 0.001) - return p; - } - - return AVCOL_PRI_UNSPECIFIED; -} - -void ff_fill_rgb2yuv_table(const struct LumaCoefficients *coeffs, +void ff_fill_rgb2yuv_table(const AVLumaCoefficients *coeffs, double rgb2yuv[3][3]) { double bscale, rscale; + double cr = av_q2d(coeffs->cr), cg = av_q2d(coeffs->cg), cb = av_q2d(coeffs->cb); // special ycgco matrix - if (coeffs->cr == 0.25 && coeffs->cg == 0.5 && coeffs->cb == 0.25) { + if (cr == 0.25 && cg == 0.5 && cb == 0.25) { memcpy(rgb2yuv, ycgco_matrix, sizeof(double) * 9); return; - } else if (coeffs->cr == 1 && coeffs->cg == 1 && coeffs->cb == 1) { + } else if (cr == 1 && cg == 1 && cb == 1) { memcpy(rgb2yuv, gbr_matrix, sizeof(double) * 9); return; } - rgb2yuv[0][0] = coeffs->cr; - rgb2yuv[0][1] = coeffs->cg; - rgb2yuv[0][2] = coeffs->cb; - bscale = 0.5 / (coeffs->cb - 1.0); - rscale = 0.5 / (coeffs->cr - 1.0); - rgb2yuv[1][0] = bscale * coeffs->cr; - rgb2yuv[1][1] = bscale * coeffs->cg; + rgb2yuv[0][0] = cr; + rgb2yuv[0][1] = cg; + rgb2yuv[0][2] = cb; + bscale = 0.5 / (cb - 1.0); + rscale = 0.5 / (cr - 1.0); + rgb2yuv[1][0] = bscale * cr; + rgb2yuv[1][1] = bscale * cg; rgb2yuv[1][2] = 0.5; rgb2yuv[2][0] = 0.5; - rgb2yuv[2][1] = rscale * coeffs->cg; - rgb2yuv[2][2] = rscale * coeffs->cb; + rgb2yuv[2][1] = rscale * cg; + rgb2yuv[2][2] = rscale * cb; } double ff_determine_signal_peak(AVFrame *in) |