Message ID | 20220513154208.17941-1-leo.izen@gmail.com |
---|---|
State | New |
Headers | show |
Series | [FFmpeg-devel] avutil/csp: create public API for colorspace structs | expand |
Context | Check | Description |
---|---|---|
andriy/make_x86 | success | Make finished |
andriy/make_fate_x86 | success | Make fate finished |
Hi, On Fri, May 13, 2022 at 11:42 AM Leo Izen <leo.izen@gmail.com> wrote: > 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. > --- > libavfilter/colorspace.c | 88 ---------------------------- > libavfilter/colorspace.h | 25 +------- > libavfilter/fflcms2.c | 3 +- > libavfilter/fflcms2.h | 2 +- > libavfilter/vf_colorspace.c | 9 +-- > libavfilter/vf_iccdetect.c | 3 +- > libavutil/Makefile | 2 + > libavutil/csp.c | 111 ++++++++++++++++++++++++++++++++++++ > libavutil/csp.h | 49 ++++++++++++++++ > 9 files changed, 173 insertions(+), 119 deletions(-) > create mode 100644 libavutil/csp.c > create mode 100644 libavutil/csp.h > I don't have objections. Ronald
On 5/13/2022 12:42 PM, Leo Izen wrote: > 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. If it's of no use for library users, then make them avpriv_ and not installed. > --- > libavfilter/colorspace.c | 88 ---------------------------- > libavfilter/colorspace.h | 25 +------- > libavfilter/fflcms2.c | 3 +- > libavfilter/fflcms2.h | 2 +- > libavfilter/vf_colorspace.c | 9 +-- > libavfilter/vf_iccdetect.c | 3 +- > libavutil/Makefile | 2 + > libavutil/csp.c | 111 ++++++++++++++++++++++++++++++++++++ > libavutil/csp.h | 49 ++++++++++++++++ > 9 files changed, 173 insertions(+), 119 deletions(-) > create mode 100644 libavutil/csp.c > create mode 100644 libavutil/csp.h > > diff --git a/libavfilter/colorspace.c b/libavfilter/colorspace.c > index 8d7b882375..f22e7002e1 100644 > --- a/libavfilter/colorspace.c > +++ b/libavfilter/colorspace.c > @@ -107,94 +107,6 @@ 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, > double rgb2yuv[3][3]) > { > diff --git a/libavfilter/colorspace.h b/libavfilter/colorspace.h > index 6959133a49..c5f39baca8 100644 > --- a/libavfilter/colorspace.h > +++ b/libavfilter/colorspace.h > @@ -20,43 +20,20 @@ > #ifndef AVFILTER_COLORSPACE_H > #define AVFILTER_COLORSPACE_H > > +#include "libavutil/csp.h" > #include "libavutil/frame.h" > #include "libavutil/pixfmt.h" > > #define REFERENCE_WHITE 100.0f > > -struct LumaCoefficients { > - double cr, cg, cb; > -}; > - > -struct PrimaryCoefficients { > - double xr, yr, xg, yg, xb, yb; > -}; > - > -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]); > void ff_fill_rgb2xyz_table(const struct PrimaryCoefficients *coeffs, > const struct WhitepointCoefficients *wp, > double rgb2xyz[3][3]); > - > -/* Returns AVCOL_PRI_UNSPECIFIED if no clear match can be identified */ > -enum AVColorPrimaries ff_detect_color_primaries(const struct ColorPrimaries *prm); > - > -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]); > - > double ff_determine_signal_peak(AVFrame *in); > void ff_update_hdr_metadata(AVFrame *in, double peak); > > diff --git a/libavfilter/fflcms2.c b/libavfilter/fflcms2.c > index efc7cb5189..b1a0429010 100644 > --- a/libavfilter/fflcms2.c > +++ b/libavfilter/fflcms2.c > @@ -18,6 +18,7 @@ > */ > > #include "libavutil/color_utils.h" > +#include "libavutil/csp.h" > > #include "fflcms2.h" > > @@ -151,7 +152,7 @@ int ff_icc_profile_generate(FFIccContext *s, > const struct ColorPrimaries *prim; > int ret; > > - if (!(prim = ff_get_color_primaries(color_prim))) > + if (!(prim = av_get_color_primaries(color_prim))) > return AVERROR_INVALIDDATA; > if ((ret = get_curve(s, color_trc, &tonecurve)) < 0) > return ret; > diff --git a/libavfilter/fflcms2.h b/libavfilter/fflcms2.h > index ad6c8c47cf..628598a41c 100644 > --- a/libavfilter/fflcms2.h > +++ b/libavfilter/fflcms2.h > @@ -25,9 +25,9 @@ > #ifndef AVFILTER_FFLCMS2_H > #define AVFILTER_FFLCMS2_H > > +#include "libavutil/csp.h" > #include "libavutil/frame.h" > #include "libavutil/pixfmt.h" > -#include "colorspace.h" > > #include <lcms2.h> > > diff --git a/libavfilter/vf_colorspace.c b/libavfilter/vf_colorspace.c > index 3c8b3b20eb..e5b1a06c54 100644 > --- a/libavfilter/vf_colorspace.c > +++ b/libavfilter/vf_colorspace.c > @@ -24,6 +24,7 @@ > */ > > #include "libavutil/avassert.h" > +#include "libavutil/csp.h" > #include "libavutil/mem_internal.h" > #include "libavutil/opt.h" > #include "libavutil/pixdesc.h" > @@ -438,7 +439,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 = ff_get_color_primaries(s->in_prm); > + s->in_primaries = av_get_color_primaries(s->in_prm); > if (!s->in_primaries) { > av_log(ctx, AV_LOG_ERROR, > "Unsupported input primaries %d (%s)\n", > @@ -446,7 +447,7 @@ static int create_filtergraph(AVFilterContext *ctx, > return AVERROR(EINVAL); > } > s->out_prm = out->color_primaries; > - s->out_primaries = ff_get_color_primaries(s->out_prm); > + s->out_primaries = av_get_color_primaries(s->out_prm); > if (!s->out_primaries) { > if (s->out_prm == AVCOL_PRI_UNSPECIFIED) { > if (s->user_all == CS_UNSPECIFIED) { > @@ -551,7 +552,7 @@ static int create_filtergraph(AVFilterContext *ctx, > s->in_rng = in->color_range; > if (s->user_irng != AVCOL_RANGE_UNSPECIFIED) > s->in_rng = s->user_irng; > - s->in_lumacoef = ff_get_luma_coefficients(s->in_csp); > + s->in_lumacoef = av_get_luma_coefficients(s->in_csp); > if (!s->in_lumacoef) { > av_log(ctx, AV_LOG_ERROR, > "Unsupported input colorspace %d (%s)\n", > @@ -564,7 +565,7 @@ static int create_filtergraph(AVFilterContext *ctx, > if (!s->out_lumacoef) { > s->out_csp = out->colorspace; > s->out_rng = out->color_range; > - s->out_lumacoef = ff_get_luma_coefficients(s->out_csp); > + s->out_lumacoef = av_get_luma_coefficients(s->out_csp); > if (!s->out_lumacoef) { > if (s->out_csp == AVCOL_SPC_UNSPECIFIED) { > if (s->user_all == CS_UNSPECIFIED) { > diff --git a/libavfilter/vf_iccdetect.c b/libavfilter/vf_iccdetect.c > index fb7871f035..d2b0e5569f 100644 > --- a/libavfilter/vf_iccdetect.c > +++ b/libavfilter/vf_iccdetect.c > @@ -24,6 +24,7 @@ > > #include <lcms2.h> > > +#include "libavutil/csp.h" > #include "libavutil/opt.h" > #include "libavutil/pixdesc.h" > > @@ -98,7 +99,7 @@ static int iccdetect_filter_frame(AVFilterLink *inlink, AVFrame *frame) > if (ret < 0) > return ret; > > - s->profile_prim = ff_detect_color_primaries(&coeffs); > + s->profile_prim = av_detect_color_primaries(&coeffs); > > done: > if (s->profile_prim != AVCOL_PRI_UNSPECIFIED) { > diff --git a/libavutil/Makefile b/libavutil/Makefile > index 234de62a4b..74d21a8103 100644 > --- a/libavutil/Makefile > +++ b/libavutil/Makefile > @@ -20,6 +20,7 @@ HEADERS = adler32.h \ > common.h \ > cpu.h \ > crc.h \ > + csp.h \ > des.h \ > detection_bbox.h \ > dict.h \ > @@ -113,6 +114,7 @@ OBJS = adler32.o \ > color_utils.o \ > cpu.o \ > crc.o \ > + csp.o \ > des.o \ > detection_bbox.o \ > dict.o \ > diff --git a/libavutil/csp.c b/libavutil/csp.c > new file mode 100644 > index 0000000000..cd755c1795 > --- /dev/null > +++ b/libavutil/csp.c > @@ -0,0 +1,111 @@ > +/* > + * Copyright (c) 2016 Ronald S. Bultje <rsbultje@gmail.com> > + * 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 "csp.h" > +#include "frame.h" > +#include "mastering_display_metadata.h" > +#include "pixfmt.h" > + > +/* > + * 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 *av_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 *av_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 av_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; > +} > diff --git a/libavutil/csp.h b/libavutil/csp.h > new file mode 100644 > index 0000000000..1bcde7ddd3 > --- /dev/null > +++ b/libavutil/csp.h > @@ -0,0 +1,49 @@ > +/* > + * Copyright (c) 2016 Ronald S. Bultje <rsbultje@gmail.com> > + * 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 AVUTIL_CSP_H > +#define AVUTIL_CSP_H > + > +#include "libavutil/frame.h" > +#include "libavutil/pixfmt.h" > + > +struct LumaCoefficients { > + double cr, cg, cb; > +}; > + > +struct PrimaryCoefficients { > + double xr, yr, xg, yg, xb, yb; > +}; > + > +struct WhitepointCoefficients { > + double xw, yw; > +}; > + > +struct ColorPrimaries { > + struct WhitepointCoefficients wp; > + struct PrimaryCoefficients prim; > +}; > + > +/* Returns AVCOL_PRI_UNSPECIFIED if no clear match can be identified */ > +enum AVColorPrimaries av_detect_color_primaries(const struct ColorPrimaries *prm); > + > +const struct ColorPrimaries *av_get_color_primaries(enum AVColorPrimaries prm); > +const struct LumaCoefficients *av_get_luma_coefficients(enum AVColorSpace csp); > + > +#endif /* AVUTIL_CSP_H */
On Fri, May 13, 2022 at 11:42:08AM -0400, Leo Izen wrote: > 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. [...] > diff --git a/libavutil/csp.h b/libavutil/csp.h > new file mode 100644 > index 0000000000..1bcde7ddd3 > --- /dev/null > +++ b/libavutil/csp.h > @@ -0,0 +1,49 @@ > +/* > + * Copyright (c) 2016 Ronald S. Bultje <rsbultje@gmail.com> > + * 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 AVUTIL_CSP_H > +#define AVUTIL_CSP_H > + > +#include "libavutil/frame.h" > +#include "libavutil/pixfmt.h" > + > +struct LumaCoefficients { > + double cr, cg, cb; > +}; > + > +struct PrimaryCoefficients { > + double xr, yr, xg, yg, xb, yb; > +}; > + > +struct WhitepointCoefficients { > + double xw, yw; > +}; I think we should avoid floating point so as to ensure reproduceable results and simplify regerssion testing thx [...]
On 5/13/22 17:22, Michael Niedermayer wrote: > On Fri, May 13, 2022 at 11:42:08AM -0400, Leo Izen wrote: >> + >> +struct WhitepointCoefficients { >> + double xw, yw; >> +}; > I think we should avoid floating point so as to ensure reproduceable > results and simplify regerssion testing > > thx This code already exists in master right now in libavfilter/colorspace, so changing these from floats to AVRational would require a bit more work than just a movement. - Leo Izen (thebombzen)
On 5/13/22 15:18, James Almer wrote: > On 5/13/2022 12:42 PM, Leo Izen wrote: >> 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. > > If it's of no use for library users, then make them avpriv_ and not > installed. I was told a public API would be useful for this. I recall haasn and Lynne voicing support on IRC, but maybe I misinterpreted what they meant. - Leo Izen (thebombzen)
Hi, If you push the code somewhere I can take a stab at porting it to AVRational. On Fri, 13 May 2022 22:41:15 -0400 Leo Izen <leo.izen@gmail.com> wrote: > On 5/13/22 17:22, Michael Niedermayer wrote: > > On Fri, May 13, 2022 at 11:42:08AM -0400, Leo Izen wrote: > >> + > >> +struct WhitepointCoefficients { > >> + double xw, yw; > >> +}; > > I think we should avoid floating point so as to ensure reproduceable > > results and simplify regerssion testing > > > > thx > This code already exists in master right now in libavfilter/colorspace, > so changing these from floats to AVRational would require a bit more > work than just a movement. > > - Leo Izen (thebombzen) > > _______________________________________________ > ffmpeg-devel mailing list > ffmpeg-devel@ffmpeg.org > https://ffmpeg.org/mailman/listinfo/ffmpeg-devel > > To unsubscribe, visit link above, or email > ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
Leo Izen: > 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. > --- > libavfilter/colorspace.c | 88 ---------------------------- > libavfilter/colorspace.h | 25 +------- > libavfilter/fflcms2.c | 3 +- > libavfilter/fflcms2.h | 2 +- > libavfilter/vf_colorspace.c | 9 +-- > libavfilter/vf_iccdetect.c | 3 +- > libavutil/Makefile | 2 + > libavutil/csp.c | 111 ++++++++++++++++++++++++++++++++++++ > libavutil/csp.h | 49 ++++++++++++++++ > 9 files changed, 173 insertions(+), 119 deletions(-) > create mode 100644 libavutil/csp.c > create mode 100644 libavutil/csp.h > > diff --git a/libavfilter/colorspace.c b/libavfilter/colorspace.c > index 8d7b882375..f22e7002e1 100644 > --- a/libavfilter/colorspace.c > +++ b/libavfilter/colorspace.c > @@ -107,94 +107,6 @@ 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, > double rgb2yuv[3][3]) > { > diff --git a/libavfilter/colorspace.h b/libavfilter/colorspace.h > index 6959133a49..c5f39baca8 100644 > --- a/libavfilter/colorspace.h > +++ b/libavfilter/colorspace.h > @@ -20,43 +20,20 @@ > #ifndef AVFILTER_COLORSPACE_H > #define AVFILTER_COLORSPACE_H > > +#include "libavutil/csp.h" > #include "libavutil/frame.h" > #include "libavutil/pixfmt.h" > > #define REFERENCE_WHITE 100.0f > > -struct LumaCoefficients { > - double cr, cg, cb; > -}; > - > -struct PrimaryCoefficients { > - double xr, yr, xg, yg, xb, yb; > -}; > - > -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]); > void ff_fill_rgb2xyz_table(const struct PrimaryCoefficients *coeffs, > const struct WhitepointCoefficients *wp, > double rgb2xyz[3][3]); > - > -/* Returns AVCOL_PRI_UNSPECIFIED if no clear match can be identified */ > -enum AVColorPrimaries ff_detect_color_primaries(const struct ColorPrimaries *prm); > - > -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]); > - > double ff_determine_signal_peak(AVFrame *in); > void ff_update_hdr_metadata(AVFrame *in, double peak); > > diff --git a/libavfilter/fflcms2.c b/libavfilter/fflcms2.c > index efc7cb5189..b1a0429010 100644 > --- a/libavfilter/fflcms2.c > +++ b/libavfilter/fflcms2.c > @@ -18,6 +18,7 @@ > */ > > #include "libavutil/color_utils.h" > +#include "libavutil/csp.h" > > #include "fflcms2.h" > > @@ -151,7 +152,7 @@ int ff_icc_profile_generate(FFIccContext *s, > const struct ColorPrimaries *prim; > int ret; > > - if (!(prim = ff_get_color_primaries(color_prim))) > + if (!(prim = av_get_color_primaries(color_prim))) > return AVERROR_INVALIDDATA; > if ((ret = get_curve(s, color_trc, &tonecurve)) < 0) > return ret; > diff --git a/libavfilter/fflcms2.h b/libavfilter/fflcms2.h > index ad6c8c47cf..628598a41c 100644 > --- a/libavfilter/fflcms2.h > +++ b/libavfilter/fflcms2.h > @@ -25,9 +25,9 @@ > #ifndef AVFILTER_FFLCMS2_H > #define AVFILTER_FFLCMS2_H > > +#include "libavutil/csp.h" > #include "libavutil/frame.h" > #include "libavutil/pixfmt.h" > -#include "colorspace.h" > > #include <lcms2.h> > > diff --git a/libavfilter/vf_colorspace.c b/libavfilter/vf_colorspace.c > index 3c8b3b20eb..e5b1a06c54 100644 > --- a/libavfilter/vf_colorspace.c > +++ b/libavfilter/vf_colorspace.c > @@ -24,6 +24,7 @@ > */ > > #include "libavutil/avassert.h" > +#include "libavutil/csp.h" > #include "libavutil/mem_internal.h" > #include "libavutil/opt.h" > #include "libavutil/pixdesc.h" > @@ -438,7 +439,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 = ff_get_color_primaries(s->in_prm); > + s->in_primaries = av_get_color_primaries(s->in_prm); > if (!s->in_primaries) { > av_log(ctx, AV_LOG_ERROR, > "Unsupported input primaries %d (%s)\n", > @@ -446,7 +447,7 @@ static int create_filtergraph(AVFilterContext *ctx, > return AVERROR(EINVAL); > } > s->out_prm = out->color_primaries; > - s->out_primaries = ff_get_color_primaries(s->out_prm); > + s->out_primaries = av_get_color_primaries(s->out_prm); > if (!s->out_primaries) { > if (s->out_prm == AVCOL_PRI_UNSPECIFIED) { > if (s->user_all == CS_UNSPECIFIED) { > @@ -551,7 +552,7 @@ static int create_filtergraph(AVFilterContext *ctx, > s->in_rng = in->color_range; > if (s->user_irng != AVCOL_RANGE_UNSPECIFIED) > s->in_rng = s->user_irng; > - s->in_lumacoef = ff_get_luma_coefficients(s->in_csp); > + s->in_lumacoef = av_get_luma_coefficients(s->in_csp); > if (!s->in_lumacoef) { > av_log(ctx, AV_LOG_ERROR, > "Unsupported input colorspace %d (%s)\n", > @@ -564,7 +565,7 @@ static int create_filtergraph(AVFilterContext *ctx, > if (!s->out_lumacoef) { > s->out_csp = out->colorspace; > s->out_rng = out->color_range; > - s->out_lumacoef = ff_get_luma_coefficients(s->out_csp); > + s->out_lumacoef = av_get_luma_coefficients(s->out_csp); > if (!s->out_lumacoef) { > if (s->out_csp == AVCOL_SPC_UNSPECIFIED) { > if (s->user_all == CS_UNSPECIFIED) { > diff --git a/libavfilter/vf_iccdetect.c b/libavfilter/vf_iccdetect.c > index fb7871f035..d2b0e5569f 100644 > --- a/libavfilter/vf_iccdetect.c > +++ b/libavfilter/vf_iccdetect.c > @@ -24,6 +24,7 @@ > > #include <lcms2.h> > > +#include "libavutil/csp.h" > #include "libavutil/opt.h" > #include "libavutil/pixdesc.h" > > @@ -98,7 +99,7 @@ static int iccdetect_filter_frame(AVFilterLink *inlink, AVFrame *frame) > if (ret < 0) > return ret; > > - s->profile_prim = ff_detect_color_primaries(&coeffs); > + s->profile_prim = av_detect_color_primaries(&coeffs); > > done: > if (s->profile_prim != AVCOL_PRI_UNSPECIFIED) { > diff --git a/libavutil/Makefile b/libavutil/Makefile > index 234de62a4b..74d21a8103 100644 > --- a/libavutil/Makefile > +++ b/libavutil/Makefile > @@ -20,6 +20,7 @@ HEADERS = adler32.h \ > common.h \ > cpu.h \ > crc.h \ > + csp.h \ > des.h \ > detection_bbox.h \ > dict.h \ > @@ -113,6 +114,7 @@ OBJS = adler32.o \ > color_utils.o \ > cpu.o \ > crc.o \ > + csp.o \ > des.o \ > detection_bbox.o \ > dict.o \ > diff --git a/libavutil/csp.c b/libavutil/csp.c > new file mode 100644 > index 0000000000..cd755c1795 > --- /dev/null > +++ b/libavutil/csp.c > @@ -0,0 +1,111 @@ > +/* > + * Copyright (c) 2016 Ronald S. Bultje <rsbultje@gmail.com> > + * 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 "csp.h" > +#include "frame.h" > +#include "mastering_display_metadata.h" > +#include "pixfmt.h" > + > +/* > + * 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 *av_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 *av_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 av_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; > +} > diff --git a/libavutil/csp.h b/libavutil/csp.h > new file mode 100644 > index 0000000000..1bcde7ddd3 > --- /dev/null > +++ b/libavutil/csp.h > @@ -0,0 +1,49 @@ > +/* > + * Copyright (c) 2016 Ronald S. Bultje <rsbultje@gmail.com> > + * 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 AVUTIL_CSP_H > +#define AVUTIL_CSP_H > + > +#include "libavutil/frame.h" ? > +#include "libavutil/pixfmt.h" > + > +struct LumaCoefficients { > + double cr, cg, cb; > +}; > + > +struct PrimaryCoefficients { > + double xr, yr, xg, yg, xb, yb; > +}; > + > +struct WhitepointCoefficients { > + double xw, yw; > +}; > + > +struct ColorPrimaries { > + struct WhitepointCoefficients wp; > + struct PrimaryCoefficients prim; > +}; > + > +/* Returns AVCOL_PRI_UNSPECIFIED if no clear match can be identified */ > +enum AVColorPrimaries av_detect_color_primaries(const struct ColorPrimaries *prm); > + > +const struct ColorPrimaries *av_get_color_primaries(enum AVColorPrimaries prm); > +const struct LumaCoefficients *av_get_luma_coefficients(enum AVColorSpace csp); > + > +#endif /* AVUTIL_CSP_H */ Is there any scenario in which these structs might need to be extended? This is something that we could no longer easily do if these structs were public. - Andreas
Hi, On Fri, May 13, 2022 at 5:22 PM Michael Niedermayer <michael@niedermayer.cc> wrote: > On Fri, May 13, 2022 at 11:42:08AM -0400, Leo Izen wrote: > > 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. > [...] > > diff --git a/libavutil/csp.h b/libavutil/csp.h > > new file mode 100644 > > index 0000000000..1bcde7ddd3 > > --- /dev/null > > +++ b/libavutil/csp.h > > @@ -0,0 +1,49 @@ > > +/* > > + * Copyright (c) 2016 Ronald S. Bultje <rsbultje@gmail.com> > > + * 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 AVUTIL_CSP_H > > +#define AVUTIL_CSP_H > > + > > +#include "libavutil/frame.h" > > +#include "libavutil/pixfmt.h" > > + > > +struct LumaCoefficients { > > + double cr, cg, cb; > > +}; > > + > > +struct PrimaryCoefficients { > > + double xr, yr, xg, yg, xb, yb; > > +}; > > + > > +struct WhitepointCoefficients { > > + double xw, yw; > > +}; > > I think we should avoid floating point so as to ensure reproduceable > results and simplify regerssion testing > To explain: when I designed this stuff, I chose to keep them in float so that we can use the literal values from the specs, which are themselves in floating point. That would not be possible anymore, and would therefore make it slightly harder to read for a casual observer. (Otherwise no opinion, I'm typically used to fixed-point rather than floating-point myself also.) Ronald
On Sun, 15 May 2022 12:49:51 -0400 "Ronald S. Bultje" <rsbultje@gmail.com> wrote: > To explain: when I designed this stuff, I chose to keep them in float so > that we can use the literal values from the specs, which are themselves in > floating point. That would not be possible anymore, and would therefore > make it slightly harder to read for a casual observer. > > (Otherwise no opinion, I'm typically used to fixed-point rather than > floating-point myself also.) > > Ronald Can you elaborate on this? Aren't almost all of these constants represented in some notation rounded to 3-4 decimal places, in which case a fixed point notation with denominator 10^N makes perfect sense?
On Sun, May 15, 2022 at 12:49:51PM -0400, Ronald S. Bultje wrote: > Hi, > > On Fri, May 13, 2022 at 5:22 PM Michael Niedermayer <michael@niedermayer.cc> > wrote: > > > On Fri, May 13, 2022 at 11:42:08AM -0400, Leo Izen wrote: > > > 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. > > [...] > > > diff --git a/libavutil/csp.h b/libavutil/csp.h > > > new file mode 100644 > > > index 0000000000..1bcde7ddd3 > > > --- /dev/null > > > +++ b/libavutil/csp.h > > > @@ -0,0 +1,49 @@ > > > +/* > > > + * Copyright (c) 2016 Ronald S. Bultje <rsbultje@gmail.com> > > > + * 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 AVUTIL_CSP_H > > > +#define AVUTIL_CSP_H > > > + > > > +#include "libavutil/frame.h" > > > +#include "libavutil/pixfmt.h" > > > + > > > +struct LumaCoefficients { > > > + double cr, cg, cb; > > > +}; > > > + > > > +struct PrimaryCoefficients { > > > + double xr, yr, xg, yg, xb, yb; > > > +}; > > > + > > > +struct WhitepointCoefficients { > > > + double xw, yw; > > > +}; > > > > I think we should avoid floating point so as to ensure reproduceable > > results and simplify regerssion testing > > > > To explain: when I designed this stuff, I chose to keep them in float so > that we can use the literal values from the specs, which are themselves in > floating point. That would not be possible anymore, and would therefore > make it slightly harder to read for a casual observer. > > (Otherwise no opinion, I'm typically used to fixed-point rather than > floating-point myself also.) I looked at Rec. ITU-T H.264 (02/2016) (was the first thing laying around, i assume but did not check that this matches the specs these numbers came from) (randomly picking "whitepoints") the whitepoints for "10" contain some 1/3 values but if i just look at "1" the values are 0.3127, 0.3290 i dont think these can be represented as m*2^E either 3127/10000 = m*2^E 3127 * 2^-E = m * 10000 both sides would be all integers the right side contains 5 as factor, the left doesnt of course i may be missing something thx [...]
On Sun, May 15, 2022 at 08:55:49PM +0200, Michael Niedermayer wrote: > On Sun, May 15, 2022 at 12:49:51PM -0400, Ronald S. Bultje wrote: > > Hi, > > > > On Fri, May 13, 2022 at 5:22 PM Michael Niedermayer <michael@niedermayer.cc> > > wrote: > > > > > On Fri, May 13, 2022 at 11:42:08AM -0400, Leo Izen wrote: > > > > 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. > > > [...] > > > > diff --git a/libavutil/csp.h b/libavutil/csp.h > > > > new file mode 100644 > > > > index 0000000000..1bcde7ddd3 > > > > --- /dev/null > > > > +++ b/libavutil/csp.h > > > > @@ -0,0 +1,49 @@ > > > > +/* > > > > + * Copyright (c) 2016 Ronald S. Bultje <rsbultje@gmail.com> > > > > + * 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 AVUTIL_CSP_H > > > > +#define AVUTIL_CSP_H > > > > + > > > > +#include "libavutil/frame.h" > > > > +#include "libavutil/pixfmt.h" > > > > + > > > > +struct LumaCoefficients { > > > > + double cr, cg, cb; > > > > +}; > > > > + > > > > +struct PrimaryCoefficients { > > > > + double xr, yr, xg, yg, xb, yb; > > > > +}; > > > > + > > > > +struct WhitepointCoefficients { > > > > + double xw, yw; > > > > +}; > > > > > > I think we should avoid floating point so as to ensure reproduceable > > > results and simplify regerssion testing > > > > > > > To explain: when I designed this stuff, I chose to keep them in float so > > that we can use the literal values from the specs, which are themselves in > > floating point. That would not be possible anymore, and would therefore > > make it slightly harder to read for a casual observer. > > > > (Otherwise no opinion, I'm typically used to fixed-point rather than > > floating-point myself also.) > > I looked at Rec. ITU-T H.264 (02/2016) (was the first thing laying around, > i assume but did not check that this matches the specs these numbers came from) > > (randomly picking "whitepoints") > the whitepoints for "10" contain some 1/3 values > but if i just look at "1" the values are > 0.3127, 0.3290 > i dont think these can be represented as m*2^E either > 3127/10000 = m*2^E > 3127 * 2^-E = m * 10000 > both sides would be all integers > the right side contains 5 as factor, the left doesnt > > of course i may be missing something Also for extra entertainment try this: #include <stdio.h> #include <stdlib.h> int main(int argc, char **argv) { float exact_tenth = 0.1; double done = 1.0; float fone = 1.0; int i; for(i= 0; i<100000000; i++) { done *= exact_tenth * 10.0; fone *= exact_tenth * 10.0; } printf("float one is %f double one is %f\n", fone, done); return 0; } [...]
On 5/15/22 12:32, Andreas Rheinhardt wrote: > Leo Izen: >> +/* Returns AVCOL_PRI_UNSPECIFIED if no clear match can be identified */ >> +enum AVColorPrimaries av_detect_color_primaries(const struct ColorPrimaries *prm); >> + >> +const struct ColorPrimaries *av_get_color_primaries(enum AVColorPrimaries prm); >> +const struct LumaCoefficients *av_get_luma_coefficients(enum AVColorSpace csp); >> + >> +#endif /* AVUTIL_CSP_H */ > > Is there any scenario in which these structs might need to be extended? > This is something that we could no longer easily do if these structs > were public. > I don't believe these will need to be extended since they're somewhat simple structs that are meant to contain a very specific set of data, not general data about a more abstract object. - Leo Izen (thebombzen)
On Sun, 15 May 2022 18:32:36 +0200 Andreas Rheinhardt <andreas.rheinhardt@outlook.com> wrote: > Is there any scenario in which these structs might need to be extended? > This is something that we could no longer easily do if these structs > were public. This struct has existed in essentially this exact form for decades (before FFmpeg) and is derived from fundamentals of the human visual system. I could not begin to dream of a reason it would need to be suddenly extended - even if we add support for, say, CMYK color spaces and libavprinter, it would be a new struct.
On Wed, 18 May 2022 14:21:41 +0200 Niklas Haas <ffmpeg@haasn.xyz> wrote: > On Sun, 15 May 2022 18:32:36 +0200 Andreas Rheinhardt <andreas.rheinhardt@outlook.com> wrote: > > Is there any scenario in which these structs might need to be extended? > > This is something that we could no longer easily do if these structs > > were public. > > This struct has existed in essentially this exact form for decades > (before FFmpeg) and is derived from fundamentals of the human visual > system. I could not begin to dream of a reason it would need to be > suddenly extended - even if we add support for, say, CMYK color spaces > and libavprinter, it would be a new struct. That said, I think that it might make more sense, for reasons of polish, to group the x/y coordinates into their own struct CIExy or something along those lines. Then you can also have helper functions accepting individual CIExy struct elements. But YMMV.
diff --git a/libavfilter/colorspace.c b/libavfilter/colorspace.c index 8d7b882375..f22e7002e1 100644 --- a/libavfilter/colorspace.c +++ b/libavfilter/colorspace.c @@ -107,94 +107,6 @@ 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, double rgb2yuv[3][3]) { diff --git a/libavfilter/colorspace.h b/libavfilter/colorspace.h index 6959133a49..c5f39baca8 100644 --- a/libavfilter/colorspace.h +++ b/libavfilter/colorspace.h @@ -20,43 +20,20 @@ #ifndef AVFILTER_COLORSPACE_H #define AVFILTER_COLORSPACE_H +#include "libavutil/csp.h" #include "libavutil/frame.h" #include "libavutil/pixfmt.h" #define REFERENCE_WHITE 100.0f -struct LumaCoefficients { - double cr, cg, cb; -}; - -struct PrimaryCoefficients { - double xr, yr, xg, yg, xb, yb; -}; - -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]); void ff_fill_rgb2xyz_table(const struct PrimaryCoefficients *coeffs, const struct WhitepointCoefficients *wp, double rgb2xyz[3][3]); - -/* Returns AVCOL_PRI_UNSPECIFIED if no clear match can be identified */ -enum AVColorPrimaries ff_detect_color_primaries(const struct ColorPrimaries *prm); - -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]); - double ff_determine_signal_peak(AVFrame *in); void ff_update_hdr_metadata(AVFrame *in, double peak); diff --git a/libavfilter/fflcms2.c b/libavfilter/fflcms2.c index efc7cb5189..b1a0429010 100644 --- a/libavfilter/fflcms2.c +++ b/libavfilter/fflcms2.c @@ -18,6 +18,7 @@ */ #include "libavutil/color_utils.h" +#include "libavutil/csp.h" #include "fflcms2.h" @@ -151,7 +152,7 @@ int ff_icc_profile_generate(FFIccContext *s, const struct ColorPrimaries *prim; int ret; - if (!(prim = ff_get_color_primaries(color_prim))) + if (!(prim = av_get_color_primaries(color_prim))) return AVERROR_INVALIDDATA; if ((ret = get_curve(s, color_trc, &tonecurve)) < 0) return ret; diff --git a/libavfilter/fflcms2.h b/libavfilter/fflcms2.h index ad6c8c47cf..628598a41c 100644 --- a/libavfilter/fflcms2.h +++ b/libavfilter/fflcms2.h @@ -25,9 +25,9 @@ #ifndef AVFILTER_FFLCMS2_H #define AVFILTER_FFLCMS2_H +#include "libavutil/csp.h" #include "libavutil/frame.h" #include "libavutil/pixfmt.h" -#include "colorspace.h" #include <lcms2.h> diff --git a/libavfilter/vf_colorspace.c b/libavfilter/vf_colorspace.c index 3c8b3b20eb..e5b1a06c54 100644 --- a/libavfilter/vf_colorspace.c +++ b/libavfilter/vf_colorspace.c @@ -24,6 +24,7 @@ */ #include "libavutil/avassert.h" +#include "libavutil/csp.h" #include "libavutil/mem_internal.h" #include "libavutil/opt.h" #include "libavutil/pixdesc.h" @@ -438,7 +439,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 = ff_get_color_primaries(s->in_prm); + s->in_primaries = av_get_color_primaries(s->in_prm); if (!s->in_primaries) { av_log(ctx, AV_LOG_ERROR, "Unsupported input primaries %d (%s)\n", @@ -446,7 +447,7 @@ static int create_filtergraph(AVFilterContext *ctx, return AVERROR(EINVAL); } s->out_prm = out->color_primaries; - s->out_primaries = ff_get_color_primaries(s->out_prm); + s->out_primaries = av_get_color_primaries(s->out_prm); if (!s->out_primaries) { if (s->out_prm == AVCOL_PRI_UNSPECIFIED) { if (s->user_all == CS_UNSPECIFIED) { @@ -551,7 +552,7 @@ static int create_filtergraph(AVFilterContext *ctx, s->in_rng = in->color_range; if (s->user_irng != AVCOL_RANGE_UNSPECIFIED) s->in_rng = s->user_irng; - s->in_lumacoef = ff_get_luma_coefficients(s->in_csp); + s->in_lumacoef = av_get_luma_coefficients(s->in_csp); if (!s->in_lumacoef) { av_log(ctx, AV_LOG_ERROR, "Unsupported input colorspace %d (%s)\n", @@ -564,7 +565,7 @@ static int create_filtergraph(AVFilterContext *ctx, if (!s->out_lumacoef) { s->out_csp = out->colorspace; s->out_rng = out->color_range; - s->out_lumacoef = ff_get_luma_coefficients(s->out_csp); + s->out_lumacoef = av_get_luma_coefficients(s->out_csp); if (!s->out_lumacoef) { if (s->out_csp == AVCOL_SPC_UNSPECIFIED) { if (s->user_all == CS_UNSPECIFIED) { diff --git a/libavfilter/vf_iccdetect.c b/libavfilter/vf_iccdetect.c index fb7871f035..d2b0e5569f 100644 --- a/libavfilter/vf_iccdetect.c +++ b/libavfilter/vf_iccdetect.c @@ -24,6 +24,7 @@ #include <lcms2.h> +#include "libavutil/csp.h" #include "libavutil/opt.h" #include "libavutil/pixdesc.h" @@ -98,7 +99,7 @@ static int iccdetect_filter_frame(AVFilterLink *inlink, AVFrame *frame) if (ret < 0) return ret; - s->profile_prim = ff_detect_color_primaries(&coeffs); + s->profile_prim = av_detect_color_primaries(&coeffs); done: if (s->profile_prim != AVCOL_PRI_UNSPECIFIED) { diff --git a/libavutil/Makefile b/libavutil/Makefile index 234de62a4b..74d21a8103 100644 --- a/libavutil/Makefile +++ b/libavutil/Makefile @@ -20,6 +20,7 @@ HEADERS = adler32.h \ common.h \ cpu.h \ crc.h \ + csp.h \ des.h \ detection_bbox.h \ dict.h \ @@ -113,6 +114,7 @@ OBJS = adler32.o \ color_utils.o \ cpu.o \ crc.o \ + csp.o \ des.o \ detection_bbox.o \ dict.o \ diff --git a/libavutil/csp.c b/libavutil/csp.c new file mode 100644 index 0000000000..cd755c1795 --- /dev/null +++ b/libavutil/csp.c @@ -0,0 +1,111 @@ +/* + * Copyright (c) 2016 Ronald S. Bultje <rsbultje@gmail.com> + * 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 "csp.h" +#include "frame.h" +#include "mastering_display_metadata.h" +#include "pixfmt.h" + +/* + * 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 *av_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 *av_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 av_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; +} diff --git a/libavutil/csp.h b/libavutil/csp.h new file mode 100644 index 0000000000..1bcde7ddd3 --- /dev/null +++ b/libavutil/csp.h @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2016 Ronald S. Bultje <rsbultje@gmail.com> + * 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 AVUTIL_CSP_H +#define AVUTIL_CSP_H + +#include "libavutil/frame.h" +#include "libavutil/pixfmt.h" + +struct LumaCoefficients { + double cr, cg, cb; +}; + +struct PrimaryCoefficients { + double xr, yr, xg, yg, xb, yb; +}; + +struct WhitepointCoefficients { + double xw, yw; +}; + +struct ColorPrimaries { + struct WhitepointCoefficients wp; + struct PrimaryCoefficients prim; +}; + +/* Returns AVCOL_PRI_UNSPECIFIED if no clear match can be identified */ +enum AVColorPrimaries av_detect_color_primaries(const struct ColorPrimaries *prm); + +const struct ColorPrimaries *av_get_color_primaries(enum AVColorPrimaries prm); +const struct LumaCoefficients *av_get_luma_coefficients(enum AVColorSpace csp); + +#endif /* AVUTIL_CSP_H */