Message ID | 20230130165010.3156-1-leo.izen@gmail.com |
---|---|
State | New |
Headers | show |
Series | [FFmpeg-devel,v2] avutil/{color_utils, csp}: merge color_utils into csp and expose API | expand |
Context | Check | Description |
---|---|---|
yinshiyou/make_loongarch64 | success | Make finished |
yinshiyou/make_fate_loongarch64 | success | Make fate finished |
andriy/make_x86 | success | Make finished |
andriy/make_fate_x86 | success | Make fate finished |
> -----Original Message----- > From: ffmpeg-devel <ffmpeg-devel-bounces@ffmpeg.org> On Behalf Of Leo Izen > Sent: 2023年1月31日 0:50 > To: ffmpeg-devel@ffmpeg.org > Cc: Leo Izen <leo.izen@gmail.com> > Subject: [FFmpeg-devel] [PATCH v2] avutil/{color_utils, csp}: merge color_utils into csp and expose API > > libavutil/color_utils contains some avpriv_ symbols that map > enum AVTransferCharacteristic values to gamma-curve approximations and > to the actual transfer functions to invert them (i.e. -> linear). > > There's two issues with this: > (1) avpriv is evil and should be avoided whenever possible > (2) libavutil/csp.h exposes a public API for handling color that > already handles primaries and matricies > > I don't see any reason this API has to be private, so this commit takes > the functionality from avutil/color_utils and merges it into avutil/csp > with an exposed av_ API rather than the previous avpriv_ API. > > Every reference to the previous API has been updated to point to the > new one. color_utils.h has been deleted as well. This should not break > any applications as it only contained avpriv_ symbols in the first > place, so nothing in that header could be referenced by other > applications. Isn't it break old libavcodec which linked to the new libavutil? > > Signed-off-by: Leo Izen <leo.izen@gmail.com> > --- > doc/APIchanges | 4 + > libavcodec/exr.c | 8 +- > libavcodec/fflcms2.c | 1 - > libavcodec/pngenc.c | 3 +- > libavformat/movenc.c | 7 +- > libavutil/Makefile | 1 - > libavutil/color_utils.c | 234 ---------------------------------- > libavutil/color_utils.h | 56 -------- > libavutil/csp.c | 172 +++++++++++++++++++++++++ > libavutil/csp.h | 39 ++++++ > libavutil/tests/color_utils.c | 4 +- > 11 files changed, 225 insertions(+), 304 deletions(-) > delete mode 100644 libavutil/color_utils.c > delete mode 100644 libavutil/color_utils.h > > diff --git a/doc/APIchanges b/doc/APIchanges > index bc52a07964..f28eb59ed3 100644 > --- a/doc/APIchanges > +++ b/doc/APIchanges > @@ -14,6 +14,10 @@ libavutil: 2021-04-27 > > API changes, most recent first: > > +2023-01-30 - xxxxxxxxxx - lavu 57.44.100 - csp.h > + Add av_csp_approximate_trc_gamma() and av_csp_trc_func_from_id(). > + Add av_csp_trc_function. > + > 2023-01-29 - xxxxxxxxxx - lavc 59.59.100 - avcodec.h > Add AV_CODEC_FLAG_COPY_OPAQUE and AV_CODEC_FLAG_FRAME_DURATION. > > diff --git a/libavcodec/exr.c b/libavcodec/exr.c > index 6a0af96ce4..2f1766c17b 100644 > --- a/libavcodec/exr.c > +++ b/libavcodec/exr.c > @@ -36,11 +36,11 @@ > > #include "libavutil/avassert.h" > #include "libavutil/common.h" > +#include "libavutil/csp.h" > #include "libavutil/imgutils.h" > #include "libavutil/intfloat.h" > #include "libavutil/avstring.h" > #include "libavutil/opt.h" > -#include "libavutil/color_utils.h" > #include "libavutil/half2float.h" > > #include "avcodec.h" > @@ -1189,7 +1189,7 @@ static int decode_block(AVCodecContext *avctx, void *tdata, > int i, x, buf_size = s->buf_size; > int c, rgb_channel_count; > float one_gamma = 1.0f / s->gamma; > - avpriv_trc_function trc_func = avpriv_get_trc_function_from_trc(s->apply_trc_type); > + av_csp_trc_function trc_func = av_csp_trc_func_from_id(s->apply_trc_type); > int ret; > > line_offset = AV_RL64(s->gb.buffer + jobnr * 8); > @@ -2215,7 +2215,7 @@ static av_cold int decode_init(AVCodecContext *avctx) > uint32_t i; > union av_intfloat32 t; > float one_gamma = 1.0f / s->gamma; > - avpriv_trc_function trc_func = NULL; > + av_csp_trc_function trc_func = NULL; > > ff_init_half2float_tables(&s->h2f_tables); > > @@ -2227,7 +2227,7 @@ static av_cold int decode_init(AVCodecContext *avctx) > ff_bswapdsp_init(&s->bbdsp); > #endif > > - trc_func = avpriv_get_trc_function_from_trc(s->apply_trc_type); > + trc_func = av_csp_trc_func_from_id(s->apply_trc_type); > if (trc_func) { > for (i = 0; i < 65536; ++i) { > t.i = half2float(i, &s->h2f_tables); > diff --git a/libavcodec/fflcms2.c b/libavcodec/fflcms2.c > index fd370fb310..5443f178bc 100644 > --- a/libavcodec/fflcms2.c > +++ b/libavcodec/fflcms2.c > @@ -17,7 +17,6 @@ > * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA > */ > > -#include "libavutil/color_utils.h" > #include "libavutil/csp.h" > > #include "fflcms2.h" > diff --git a/libavcodec/pngenc.c b/libavcodec/pngenc.c > index 2393161c3b..ac27eebf3a 100644 > --- a/libavcodec/pngenc.c > +++ b/libavcodec/pngenc.c > @@ -29,7 +29,6 @@ > #include "zlib_wrapper.h" > > #include "libavutil/avassert.h" > -#include "libavutil/color_utils.h" > #include "libavutil/crc.h" > #include "libavutil/csp.h" > #include "libavutil/libm.h" > @@ -317,7 +316,7 @@ static int png_get_chrm(enum AVColorPrimaries prim, uint8_t *buf) > > static int png_get_gama(enum AVColorTransferCharacteristic trc, uint8_t *buf) > { > - double gamma = avpriv_get_gamma_from_trc(trc); > + double gamma = av_csp_approximate_trc_gamma(trc); > if (gamma <= 1e-6) > return 0; > > diff --git a/libavformat/movenc.c b/libavformat/movenc.c > index 8d31317838..6182dc7f58 100644 > --- a/libavformat/movenc.c > +++ b/libavformat/movenc.c > @@ -47,6 +47,7 @@ > #include "internal.h" > #include "libavutil/avstring.h" > #include "libavutil/channel_layout.h" > +#include "libavutil/csp.h" > #include "libavutil/intfloat.h" > #include "libavutil/mathematics.h" > #include "libavutil/libm.h" > @@ -56,7 +57,6 @@ > #include "libavutil/stereo3d.h" > #include "libavutil/timecode.h" > #include "libavutil/dovi_meta.h" > -#include "libavutil/color_utils.h" > #include "libavutil/uuid.h" > #include "hevc.h" > #include "rtpenc.h" > @@ -2011,9 +2011,8 @@ static int mov_write_pasp_tag(AVIOContext *pb, MOVTrack *track) > static int mov_write_gama_tag(AVFormatContext *s, AVIOContext *pb, MOVTrack *track, double gamma) > { > uint32_t gama = 0; > - if (gamma <= 0.0) { > - gamma = avpriv_get_gamma_from_trc(track->par->color_trc); > - } > + if (gamma <= 0.0) > + gamma = av_csp_approximate_trc_gamma(track->par->color_trc); > av_log(s, AV_LOG_DEBUG, "gamma value %g\n", gamma); > > if (gamma > 1e-6) { > diff --git a/libavutil/Makefile b/libavutil/Makefile > index 29b06665f5..dc9012f9a8 100644 > --- a/libavutil/Makefile > +++ b/libavutil/Makefile > @@ -114,7 +114,6 @@ OBJS = adler32.o \ > cast5.o \ > camellia.o \ > channel_layout.o \ > - color_utils.o \ > cpu.o \ > crc.o \ > csp.o \ > diff --git a/libavutil/color_utils.c b/libavutil/color_utils.c > deleted file mode 100644 > index 5e221fb798..0000000000 > --- a/libavutil/color_utils.c > +++ /dev/null > @@ -1,234 +0,0 @@ > -/* > - * Copyright (c) 2015 Kevin Wheatley <kevin.j.wheatley@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 <stddef.h> > -#include <math.h> > - > -#include "libavutil/color_utils.h" > -#include "libavutil/pixfmt.h" > - > -double avpriv_get_gamma_from_trc(enum AVColorTransferCharacteristic trc) > -{ > - double gamma; > - switch (trc) { > - case AVCOL_TRC_BT709: > - case AVCOL_TRC_SMPTE170M: > - case AVCOL_TRC_SMPTE240M: > - case AVCOL_TRC_BT1361_ECG: > - case AVCOL_TRC_BT2020_10: > - case AVCOL_TRC_BT2020_12: > - /* these share a segmented TRC, but gamma 1.961 is a close > - approximation, and also more correct for decoding content */ > - gamma = 1.961; > - break; > - case AVCOL_TRC_GAMMA22: > - case AVCOL_TRC_IEC61966_2_1: > - gamma = 2.2; > - break; > - case AVCOL_TRC_GAMMA28: > - gamma = 2.8; > - break; > - case AVCOL_TRC_LINEAR: > - gamma = 1.0; > - break; > - default: > - gamma = 0.0; // Unknown value representation > - } > - return gamma; > -} > - > -#define BT709_alpha 1.099296826809442 > -#define BT709_beta 0.018053968510807 > - > -static double avpriv_trc_bt709(double Lc) > -{ > - const double a = BT709_alpha; > - const double b = BT709_beta; > - > - return (0.0 > Lc) ? 0.0 > - : ( b > Lc) ? 4.500 * Lc > - : a * pow(Lc, 0.45) - (a - 1.0); > -} > - > -static double avpriv_trc_gamma22(double Lc) > -{ > - return (0.0 > Lc) ? 0.0 : pow(Lc, 1.0/ 2.2); > -} > - > -static double avpriv_trc_gamma28(double Lc) > -{ > - return (0.0 > Lc) ? 0.0 : pow(Lc, 1.0/ 2.8); > -} > - > -static double avpriv_trc_smpte240M(double Lc) > -{ > - const double a = 1.1115; > - const double b = 0.0228; > - > - return (0.0 > Lc) ? 0.0 > - : ( b > Lc) ? 4.000 * Lc > - : a * pow(Lc, 0.45) - (a - 1.0); > -} > - > -static double avpriv_trc_linear(double Lc) > -{ > - return Lc; > -} > - > -static double avpriv_trc_log(double Lc) > -{ > - return (0.01 > Lc) ? 0.0 : 1.0 + log10(Lc) / 2.0; > -} > - > -static double avpriv_trc_log_sqrt(double Lc) > -{ > - // sqrt(10) / 1000 > - return (0.00316227766 > Lc) ? 0.0 : 1.0 + log10(Lc) / 2.5; > -} > - > -static double avpriv_trc_iec61966_2_4(double Lc) > -{ > - const double a = BT709_alpha; > - const double b = BT709_beta; > - > - return (-b >= Lc) ? -a * pow(-Lc, 0.45) + (a - 1.0) > - : ( b > Lc) ? 4.500 * Lc > - : a * pow( Lc, 0.45) - (a - 1.0); > -} > - > -static double avpriv_trc_bt1361(double Lc) > -{ > - const double a = BT709_alpha; > - const double b = BT709_beta; > - > - return (-0.0045 >= Lc) ? -(a * pow(-4.0 * Lc, 0.45) + (a - 1.0)) / 4.0 > - : ( b > Lc) ? 4.500 * Lc > - : a * pow( Lc, 0.45) - (a - 1.0); > -} > - > -static double avpriv_trc_iec61966_2_1(double Lc) > -{ > - const double a = 1.055; > - const double b = 0.0031308; > - > - return (0.0 > Lc) ? 0.0 > - : ( b > Lc) ? 12.92 * Lc > - : a * pow(Lc, 1.0 / 2.4) - (a - 1.0); > -} > - > -static double avpriv_trc_smpte_st2084(double Lc) > -{ > - const double c1 = 3424.0 / 4096.0; // c3-c2 + 1 > - const double c2 = 32.0 * 2413.0 / 4096.0; > - const double c3 = 32.0 * 2392.0 / 4096.0; > - const double m = 128.0 * 2523.0 / 4096.0; > - const double n = 0.25 * 2610.0 / 4096.0; > - const double L = Lc / 10000.0; > - const double Ln = pow(L, n); > - > - return (0.0 > Lc) ? 0.0 > - : pow((c1 + c2 * Ln) / (1.0 + c3 * Ln), m); > - > -} > - > -static double avpriv_trc_smpte_st428_1(double Lc) > -{ > - return (0.0 > Lc) ? 0.0 > - : pow(48.0 * Lc / 52.37, 1.0 / 2.6); > -} > - > - > -static double avpriv_trc_arib_std_b67(double Lc) { > - // The function uses the definition from HEVC, which assumes that the peak > - // white is input level = 1. (this is equivalent to scaling E = Lc * 12 and > - // using the definition from the ARIB STD-B67 spec) > - const double a = 0.17883277; > - const double b = 0.28466892; > - const double c = 0.55991073; > - return (0.0 > Lc) ? 0.0 : > - (Lc <= 1.0 / 12.0 ? sqrt(3.0 * Lc) : a * log(12.0 * Lc - b) + c); > -} > - > -avpriv_trc_function avpriv_get_trc_function_from_trc(enum AVColorTransferCharacteristic trc) > -{ > - avpriv_trc_function func = NULL; > - switch (trc) { > - case AVCOL_TRC_BT709: > - case AVCOL_TRC_SMPTE170M: > - case AVCOL_TRC_BT2020_10: > - case AVCOL_TRC_BT2020_12: > - func = avpriv_trc_bt709; > - break; > - > - case AVCOL_TRC_GAMMA22: > - func = avpriv_trc_gamma22; > - break; > - case AVCOL_TRC_GAMMA28: > - func = avpriv_trc_gamma28; > - break; > - > - case AVCOL_TRC_SMPTE240M: > - func = avpriv_trc_smpte240M; > - break; > - > - case AVCOL_TRC_LINEAR: > - func = avpriv_trc_linear; > - break; > - > - case AVCOL_TRC_LOG: > - func = avpriv_trc_log; > - break; > - > - case AVCOL_TRC_LOG_SQRT: > - func = avpriv_trc_log_sqrt; > - break; > - > - case AVCOL_TRC_IEC61966_2_4: > - func = avpriv_trc_iec61966_2_4; > - break; > - > - case AVCOL_TRC_BT1361_ECG: > - func = avpriv_trc_bt1361; > - break; > - > - case AVCOL_TRC_IEC61966_2_1: > - func = avpriv_trc_iec61966_2_1; > - break; > - > - case AVCOL_TRC_SMPTEST2084: > - func = avpriv_trc_smpte_st2084; > - break; > - > - case AVCOL_TRC_SMPTEST428_1: > - func = avpriv_trc_smpte_st428_1; > - break; > - > - case AVCOL_TRC_ARIB_STD_B67: > - func = avpriv_trc_arib_std_b67; > - break; > - > - case AVCOL_TRC_RESERVED0: > - case AVCOL_TRC_UNSPECIFIED: > - case AVCOL_TRC_RESERVED: > - default: > - break; > - } > - return func; > -} > diff --git a/libavutil/color_utils.h b/libavutil/color_utils.h > deleted file mode 100644 > index 9529006452..0000000000 > --- a/libavutil/color_utils.h > +++ /dev/null > @@ -1,56 +0,0 @@ > -/* > - * Copyright (c) 2015 Kevin Wheatley <kevin.j.wheatley@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_COLOR_UTILS_H > -#define AVUTIL_COLOR_UTILS_H > - > - > -#include "libavutil/pixfmt.h" > - > -/** > - * Determine a suitable 'gamma' value to match the supplied > - * AVColorTransferCharacteristic. > - * > - * See Apple Technical Note TN2257 (https://developer.apple.com/library/mac/technotes/tn2257/_index.html) > - * > - * @return Will return an approximation to the simple gamma function matching > - * the supplied Transfer Characteristic, Will return 0.0 for any > - * we cannot reasonably match against. > - */ > -double avpriv_get_gamma_from_trc(enum AVColorTransferCharacteristic trc); > - > - > -typedef double (*avpriv_trc_function)(double); > - > -/** > - * Determine the function needed to apply the given > - * AVColorTransferCharacteristic to linear input. > - * > - * The function returned should expect a nominal domain and range of [0.0-1.0] > - * values outside of this range maybe valid depending on the chosen > - * characteristic function. > - * > - * @return Will return pointer to the function matching the > - * supplied Transfer Characteristic. If unspecified will > - * return NULL: > - */ > -avpriv_trc_function avpriv_get_trc_function_from_trc(enum AVColorTransferCharacteristic trc); > - > -#endif > diff --git a/libavutil/csp.c b/libavutil/csp.c > index 98fc83c1da..7ef822c60b 100644 > --- a/libavutil/csp.c > +++ b/libavutil/csp.c > @@ -1,5 +1,8 @@ > /* > + * Copyright (c) 2015 Kevin Wheatley <kevin.j.wheatley@gmail.com> > * Copyright (c) 2016 Ronald S. Bultje <rsbultje@gmail.com> > + * Copyright (c) 2023 Leo Izen <leo.izen@gmail.com> > + * > * This file is part of FFmpeg. > * > * FFmpeg is free software; you can redistribute it and/or > @@ -21,9 +24,11 @@ > * @file Colorspace functions for libavutil > * @author Ronald S. Bultje <rsbultje@gmail.com> > * @author Leo Izen <leo.izen@gmail.com> > + * @author Kevin Wheatley <kevin.j.wheatley@gmail.com> > */ > > #include <stdlib.h> > +#include <math.h> > > #include "attributes.h" > #include "csp.h" > @@ -126,3 +131,170 @@ enum AVColorPrimaries av_csp_primaries_id_from_desc(const AVColorPrimariesDesc * > > return AVCOL_PRI_UNSPECIFIED; > } > + > +static const double approximate_gamma[AVCOL_TRC_NB] = { > + [AVCOL_TRC_BT709] = 1.961, > + [AVCOL_TRC_SMPTE170M] = 1.961, > + [AVCOL_TRC_SMPTE240M] = 1.961, > + [AVCOL_TRC_BT1361_ECG] = 1.961, > + [AVCOL_TRC_BT2020_10] = 1.961, > + [AVCOL_TRC_BT2020_12] = 1.961, > + [AVCOL_TRC_GAMMA22] = 2.2, > + [AVCOL_TRC_IEC61966_2_1] = 2.2, > + [AVCOL_TRC_GAMMA28] = 2.8, > + [AVCOL_TRC_LINEAR] = 1.0, > + [AVCOL_TRC_SMPTE428] = 2.6, > +}; > + > +double av_csp_approximate_trc_gamma(enum AVColorTransferCharacteristic trc) > +{ > + double gamma; > + if (trc >= AVCOL_TRC_NB) > + return 0.0; > + gamma = approximate_gamma[trc]; > + if (gamma > 0) > + return gamma; > + return 0.0; > +} > + > +#define BT709_alpha 1.099296826809442 > +#define BT709_beta 0.018053968510807 > + > +static double trc_bt709(double Lc) > +{ > + const double a = BT709_alpha; > + const double b = BT709_beta; > + > + return (0.0 > Lc) ? 0.0 > + : ( b > Lc) ? 4.500 * Lc > + : a * pow(Lc, 0.45) - (a - 1.0); > +} > + > +static double trc_gamma22(double Lc) > +{ > + return (0.0 > Lc) ? 0.0 : pow(Lc, 1.0/ 2.2); > +} > + > +static double trc_gamma28(double Lc) > +{ > + return (0.0 > Lc) ? 0.0 : pow(Lc, 1.0/ 2.8); > +} > + > +static double trc_smpte240M(double Lc) > +{ > + const double a = 1.1115; > + const double b = 0.0228; > + > + return (0.0 > Lc) ? 0.0 > + : ( b > Lc) ? 4.000 * Lc > + : a * pow(Lc, 0.45) - (a - 1.0); > +} > + > +static double trc_linear(double Lc) > +{ > + return Lc; > +} > + > +static double trc_log(double Lc) > +{ > + return (0.01 > Lc) ? 0.0 : 1.0 + log10(Lc) / 2.0; > +} > + > +static double trc_log_sqrt(double Lc) > +{ > + // sqrt(10) / 1000 > + return (0.00316227766 > Lc) ? 0.0 : 1.0 + log10(Lc) / 2.5; > +} > + > +static double trc_iec61966_2_4(double Lc) > +{ > + const double a = BT709_alpha; > + const double b = BT709_beta; > + > + return (-b >= Lc) ? -a * pow(-Lc, 0.45) + (a - 1.0) > + : ( b > Lc) ? 4.500 * Lc > + : a * pow( Lc, 0.45) - (a - 1.0); > +} > + > +static double trc_bt1361(double Lc) > +{ > + const double a = BT709_alpha; > + const double b = BT709_beta; > + > + return (-0.0045 >= Lc) ? -(a * pow(-4.0 * Lc, 0.45) + (a - 1.0)) / 4.0 > + : ( b > Lc) ? 4.500 * Lc > + : a * pow( Lc, 0.45) - (a - 1.0); > +} > + > +static double trc_iec61966_2_1(double Lc) > +{ > + const double a = 1.055; > + const double b = 0.0031308; > + > + return (0.0 > Lc) ? 0.0 > + : ( b > Lc) ? 12.92 * Lc > + : a * pow(Lc, 1.0 / 2.4) - (a - 1.0); > +} > + > +static double trc_smpte_st2084(double Lc) > +{ > + const double c1 = 3424.0 / 4096.0; // c3-c2 + 1 > + const double c2 = 32.0 * 2413.0 / 4096.0; > + const double c3 = 32.0 * 2392.0 / 4096.0; > + const double m = 128.0 * 2523.0 / 4096.0; > + const double n = 0.25 * 2610.0 / 4096.0; > + const double L = Lc / 10000.0; > + const double Ln = pow(L, n); > + > + return (0.0 > Lc) ? 0.0 > + : pow((c1 + c2 * Ln) / (1.0 + c3 * Ln), m); > + > +} > + > +static double trc_smpte_st428_1(double Lc) > +{ > + return (0.0 > Lc) ? 0.0 > + : pow(48.0 * Lc / 52.37, 1.0 / 2.6); > +} > + > + > +static double trc_arib_std_b67(double Lc) { > + // The function uses the definition from HEVC, which assumes that the peak > + // white is input level = 1. (this is equivalent to scaling E = Lc * 12 and > + // using the definition from the ARIB STD-B67 spec) > + const double a = 0.17883277; > + const double b = 0.28466892; > + const double c = 0.55991073; > + return (0.0 > Lc) ? 0.0 : > + (Lc <= 1.0 / 12.0 ? sqrt(3.0 * Lc) : a * log(12.0 * Lc - b) + c); > +} > + > +static const av_csp_trc_function trc_funcs[AVCOL_TRC_NB] = { > + [AVCOL_TRC_BT709] = trc_bt709, > + [AVCOL_TRC_GAMMA22] = trc_gamma22, > + [AVCOL_TRC_GAMMA28] = trc_gamma28, > + [AVCOL_TRC_SMPTE170M] = trc_bt709, > + [AVCOL_TRC_SMPTE240M] = trc_smpte240M, > + [AVCOL_TRC_LINEAR] = trc_linear, > + [AVCOL_TRC_LOG] = trc_log, > + [AVCOL_TRC_LOG_SQRT] = trc_log_sqrt, > + [AVCOL_TRC_IEC61966_2_4] = trc_iec61966_2_4, > + [AVCOL_TRC_BT1361_ECG] = trc_bt1361, > + [AVCOL_TRC_IEC61966_2_1] = trc_iec61966_2_1, > + [AVCOL_TRC_BT2020_10] = trc_bt709, > + [AVCOL_TRC_BT2020_12] = trc_bt709, > + [AVCOL_TRC_SMPTE2084] = trc_smpte_st2084, > + [AVCOL_TRC_SMPTE428] = trc_smpte_st428_1, > + [AVCOL_TRC_ARIB_STD_B67] = trc_arib_std_b67, > +}; > + > +av_csp_trc_function av_csp_trc_func_from_id(enum AVColorTransferCharacteristic trc) > +{ > + av_csp_trc_function func; > + if (trc >= AVCOL_TRC_NB) > + return NULL; > + func = trc_funcs[trc]; > + if (!func) > + return NULL; > + return func; > +} > diff --git a/libavutil/csp.h b/libavutil/csp.h > index 18ef208adf..73bce52bc0 100644 > --- a/libavutil/csp.h > +++ b/libavutil/csp.h > @@ -1,5 +1,8 @@ > /* > + * Copyright (c) 2015 Kevin Wheatley <kevin.j.wheatley@gmail.com> > * Copyright (c) 2016 Ronald S. Bultje <rsbultje@gmail.com> > + * Copyright (c) 2023 Leo Izen <leo.izen@gmail.com> > + * > * This file is part of FFmpeg. > * > * FFmpeg is free software; you can redistribute it and/or > @@ -29,6 +32,7 @@ > * @ingroup lavu_math_csp > * @author Ronald S. Bultje <rsbultje@gmail.com> > * @author Leo Izen <leo.izen@gmail.com> > + * @author Kevin Wheatley <kevin.j.wheatley@gmail.com> > */ > > /** > @@ -76,6 +80,12 @@ typedef struct AVColorPrimariesDesc { > AVPrimaryCoefficients prim; > } AVColorPrimariesDesc; > > +/** > + * Function pointer representing a double -> double transfer function that performs > + * an EOTF transfer inversion. This function outputs linear light. > + */ > +typedef double (*av_csp_trc_function)(double); > + > /** > * Retrieves the Luma coefficients necessary to construct a conversion matrix > * from an enum constant describing the colorspace. > @@ -104,6 +114,35 @@ const AVColorPrimariesDesc *av_csp_primaries_desc_from_id(enum AVColorPrimaries > */ > enum AVColorPrimaries av_csp_primaries_id_from_desc(const AVColorPrimariesDesc *prm); > > +/** > + * Determine a suitable 'gamma' value to match the supplied > + * AVColorTransferCharacteristic. > + * > + * See Apple Technical Note TN2257 (https://developer.apple.com/library/mac/technotes/tn2257/_index.html) > + * > + * This function returns the gamma exponent for the OETF. For example, sRGB is approximated > + * by gamma 2.2, not by gamma 0.45455. > + * > + * @return Will return an approximation to the simple gamma function matching > + * the supplied Transfer Characteristic, Will return 0.0 for any > + * we cannot reasonably match against. > + */ > +double av_csp_approximate_trc_gamma(enum AVColorTransferCharacteristic trc); > + > +/** > + * Determine the function needed to apply the given > + * AVColorTransferCharacteristic to linear input. > + * > + * The function returned should expect a nominal domain and range of [0.0-1.0] > + * values outside of this range maybe valid depending on the chosen > + * characteristic function. > + * > + * @return Will return pointer to the function matching the > + * supplied Transfer Characteristic. If unspecified will > + * return NULL: > + */ > +av_csp_trc_function av_csp_trc_func_from_id(enum AVColorTransferCharacteristic trc); > + > /** > * @} > */ > diff --git a/libavutil/tests/color_utils.c b/libavutil/tests/color_utils.c > index 4bdc550330..95fb3c1d56 100644 > --- a/libavutil/tests/color_utils.c > +++ b/libavutil/tests/color_utils.c > @@ -19,7 +19,7 @@ > */ > > #include <stdio.h> > -#include "libavutil/color_utils.c" > +#include "libavutil/csp.h" > #include "libavutil/macros.h" > > int main(int argc, char *argv[]) > @@ -32,7 +32,7 @@ int main(int argc, char *argv[]) > }; > > for(i = 0; i < AVCOL_TRC_NB; i++) { > - avpriv_trc_function func = avpriv_get_trc_function_from_trc(i); > + av_csp_trc_function func = av_csp_trc_func_from_id(i); > for(j = 0; j < FF_ARRAY_ELEMS(test_data); j++) { > if(func != NULL) { > double result = func(test_data[j]); > -- > 2.39.1 > > _______________________________________________ > 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".
On 1/30/23, Zhao Zhili <quinkblack@foxmail.com> wrote: > > >> -----Original Message----- >> From: ffmpeg-devel <ffmpeg-devel-bounces@ffmpeg.org> On Behalf Of Leo Izen >> Sent: 2023年1月31日 0:50 >> To: ffmpeg-devel@ffmpeg.org >> Cc: Leo Izen <leo.izen@gmail.com> >> Subject: [FFmpeg-devel] [PATCH v2] avutil/{color_utils, csp}: merge >> color_utils into csp and expose API >> >> libavutil/color_utils contains some avpriv_ symbols that map >> enum AVTransferCharacteristic values to gamma-curve approximations and >> to the actual transfer functions to invert them (i.e. -> linear). >> >> There's two issues with this: >> (1) avpriv is evil and should be avoided whenever possible >> (2) libavutil/csp.h exposes a public API for handling color that >> already handles primaries and matricies >> >> I don't see any reason this API has to be private, so this commit takes >> the functionality from avutil/color_utils and merges it into avutil/csp >> with an exposed av_ API rather than the previous avpriv_ API. >> >> Every reference to the previous API has been updated to point to the >> new one. color_utils.h has been deleted as well. This should not break >> any applications as it only contained avpriv_ symbols in the first >> place, so nothing in that header could be referenced by other >> applications. > > Isn't it break old libavcodec which linked to the new libavutil? Yes it is, thats why according to Anton it can not be pushed as is. > >> >> Signed-off-by: Leo Izen <leo.izen@gmail.com> >> --- >> doc/APIchanges | 4 + >> libavcodec/exr.c | 8 +- >> libavcodec/fflcms2.c | 1 - >> libavcodec/pngenc.c | 3 +- >> libavformat/movenc.c | 7 +- >> libavutil/Makefile | 1 - >> libavutil/color_utils.c | 234 ---------------------------------- >> libavutil/color_utils.h | 56 -------- >> libavutil/csp.c | 172 +++++++++++++++++++++++++ >> libavutil/csp.h | 39 ++++++ >> libavutil/tests/color_utils.c | 4 +- >> 11 files changed, 225 insertions(+), 304 deletions(-) >> delete mode 100644 libavutil/color_utils.c >> delete mode 100644 libavutil/color_utils.h >> >> diff --git a/doc/APIchanges b/doc/APIchanges >> index bc52a07964..f28eb59ed3 100644 >> --- a/doc/APIchanges >> +++ b/doc/APIchanges >> @@ -14,6 +14,10 @@ libavutil: 2021-04-27 >> >> API changes, most recent first: >> >> +2023-01-30 - xxxxxxxxxx - lavu 57.44.100 - csp.h >> + Add av_csp_approximate_trc_gamma() and av_csp_trc_func_from_id(). >> + Add av_csp_trc_function. >> + >> 2023-01-29 - xxxxxxxxxx - lavc 59.59.100 - avcodec.h >> Add AV_CODEC_FLAG_COPY_OPAQUE and AV_CODEC_FLAG_FRAME_DURATION. >> >> diff --git a/libavcodec/exr.c b/libavcodec/exr.c >> index 6a0af96ce4..2f1766c17b 100644 >> --- a/libavcodec/exr.c >> +++ b/libavcodec/exr.c >> @@ -36,11 +36,11 @@ >> >> #include "libavutil/avassert.h" >> #include "libavutil/common.h" >> +#include "libavutil/csp.h" >> #include "libavutil/imgutils.h" >> #include "libavutil/intfloat.h" >> #include "libavutil/avstring.h" >> #include "libavutil/opt.h" >> -#include "libavutil/color_utils.h" >> #include "libavutil/half2float.h" >> >> #include "avcodec.h" >> @@ -1189,7 +1189,7 @@ static int decode_block(AVCodecContext *avctx, void >> *tdata, >> int i, x, buf_size = s->buf_size; >> int c, rgb_channel_count; >> float one_gamma = 1.0f / s->gamma; >> - avpriv_trc_function trc_func = >> avpriv_get_trc_function_from_trc(s->apply_trc_type); >> + av_csp_trc_function trc_func = >> av_csp_trc_func_from_id(s->apply_trc_type); >> int ret; >> >> line_offset = AV_RL64(s->gb.buffer + jobnr * 8); >> @@ -2215,7 +2215,7 @@ static av_cold int decode_init(AVCodecContext >> *avctx) >> uint32_t i; >> union av_intfloat32 t; >> float one_gamma = 1.0f / s->gamma; >> - avpriv_trc_function trc_func = NULL; >> + av_csp_trc_function trc_func = NULL; >> >> ff_init_half2float_tables(&s->h2f_tables); >> >> @@ -2227,7 +2227,7 @@ static av_cold int decode_init(AVCodecContext >> *avctx) >> ff_bswapdsp_init(&s->bbdsp); >> #endif >> >> - trc_func = avpriv_get_trc_function_from_trc(s->apply_trc_type); >> + trc_func = av_csp_trc_func_from_id(s->apply_trc_type); >> if (trc_func) { >> for (i = 0; i < 65536; ++i) { >> t.i = half2float(i, &s->h2f_tables); >> diff --git a/libavcodec/fflcms2.c b/libavcodec/fflcms2.c >> index fd370fb310..5443f178bc 100644 >> --- a/libavcodec/fflcms2.c >> +++ b/libavcodec/fflcms2.c >> @@ -17,7 +17,6 @@ >> * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA >> 02110-1301 USA >> */ >> >> -#include "libavutil/color_utils.h" >> #include "libavutil/csp.h" >> >> #include "fflcms2.h" >> diff --git a/libavcodec/pngenc.c b/libavcodec/pngenc.c >> index 2393161c3b..ac27eebf3a 100644 >> --- a/libavcodec/pngenc.c >> +++ b/libavcodec/pngenc.c >> @@ -29,7 +29,6 @@ >> #include "zlib_wrapper.h" >> >> #include "libavutil/avassert.h" >> -#include "libavutil/color_utils.h" >> #include "libavutil/crc.h" >> #include "libavutil/csp.h" >> #include "libavutil/libm.h" >> @@ -317,7 +316,7 @@ static int png_get_chrm(enum AVColorPrimaries prim, >> uint8_t *buf) >> >> static int png_get_gama(enum AVColorTransferCharacteristic trc, uint8_t >> *buf) >> { >> - double gamma = avpriv_get_gamma_from_trc(trc); >> + double gamma = av_csp_approximate_trc_gamma(trc); >> if (gamma <= 1e-6) >> return 0; >> >> diff --git a/libavformat/movenc.c b/libavformat/movenc.c >> index 8d31317838..6182dc7f58 100644 >> --- a/libavformat/movenc.c >> +++ b/libavformat/movenc.c >> @@ -47,6 +47,7 @@ >> #include "internal.h" >> #include "libavutil/avstring.h" >> #include "libavutil/channel_layout.h" >> +#include "libavutil/csp.h" >> #include "libavutil/intfloat.h" >> #include "libavutil/mathematics.h" >> #include "libavutil/libm.h" >> @@ -56,7 +57,6 @@ >> #include "libavutil/stereo3d.h" >> #include "libavutil/timecode.h" >> #include "libavutil/dovi_meta.h" >> -#include "libavutil/color_utils.h" >> #include "libavutil/uuid.h" >> #include "hevc.h" >> #include "rtpenc.h" >> @@ -2011,9 +2011,8 @@ static int mov_write_pasp_tag(AVIOContext *pb, >> MOVTrack *track) >> static int mov_write_gama_tag(AVFormatContext *s, AVIOContext *pb, >> MOVTrack *track, double gamma) >> { >> uint32_t gama = 0; >> - if (gamma <= 0.0) { >> - gamma = avpriv_get_gamma_from_trc(track->par->color_trc); >> - } >> + if (gamma <= 0.0) >> + gamma = av_csp_approximate_trc_gamma(track->par->color_trc); >> av_log(s, AV_LOG_DEBUG, "gamma value %g\n", gamma); >> >> if (gamma > 1e-6) { >> diff --git a/libavutil/Makefile b/libavutil/Makefile >> index 29b06665f5..dc9012f9a8 100644 >> --- a/libavutil/Makefile >> +++ b/libavutil/Makefile >> @@ -114,7 +114,6 @@ OBJS = adler32.o >> \ >> cast5.o \ >> camellia.o \ >> channel_layout.o \ >> - color_utils.o \ >> cpu.o \ >> crc.o \ >> csp.o \ >> diff --git a/libavutil/color_utils.c b/libavutil/color_utils.c >> deleted file mode 100644 >> index 5e221fb798..0000000000 >> --- a/libavutil/color_utils.c >> +++ /dev/null >> @@ -1,234 +0,0 @@ >> -/* >> - * Copyright (c) 2015 Kevin Wheatley <kevin.j.wheatley@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 <stddef.h> >> -#include <math.h> >> - >> -#include "libavutil/color_utils.h" >> -#include "libavutil/pixfmt.h" >> - >> -double avpriv_get_gamma_from_trc(enum AVColorTransferCharacteristic trc) >> -{ >> - double gamma; >> - switch (trc) { >> - case AVCOL_TRC_BT709: >> - case AVCOL_TRC_SMPTE170M: >> - case AVCOL_TRC_SMPTE240M: >> - case AVCOL_TRC_BT1361_ECG: >> - case AVCOL_TRC_BT2020_10: >> - case AVCOL_TRC_BT2020_12: >> - /* these share a segmented TRC, but gamma 1.961 is a close >> - approximation, and also more correct for decoding content >> */ >> - gamma = 1.961; >> - break; >> - case AVCOL_TRC_GAMMA22: >> - case AVCOL_TRC_IEC61966_2_1: >> - gamma = 2.2; >> - break; >> - case AVCOL_TRC_GAMMA28: >> - gamma = 2.8; >> - break; >> - case AVCOL_TRC_LINEAR: >> - gamma = 1.0; >> - break; >> - default: >> - gamma = 0.0; // Unknown value representation >> - } >> - return gamma; >> -} >> - >> -#define BT709_alpha 1.099296826809442 >> -#define BT709_beta 0.018053968510807 >> - >> -static double avpriv_trc_bt709(double Lc) >> -{ >> - const double a = BT709_alpha; >> - const double b = BT709_beta; >> - >> - return (0.0 > Lc) ? 0.0 >> - : ( b > Lc) ? 4.500 * Lc >> - : a * pow(Lc, 0.45) - (a - 1.0); >> -} >> - >> -static double avpriv_trc_gamma22(double Lc) >> -{ >> - return (0.0 > Lc) ? 0.0 : pow(Lc, 1.0/ 2.2); >> -} >> - >> -static double avpriv_trc_gamma28(double Lc) >> -{ >> - return (0.0 > Lc) ? 0.0 : pow(Lc, 1.0/ 2.8); >> -} >> - >> -static double avpriv_trc_smpte240M(double Lc) >> -{ >> - const double a = 1.1115; >> - const double b = 0.0228; >> - >> - return (0.0 > Lc) ? 0.0 >> - : ( b > Lc) ? 4.000 * Lc >> - : a * pow(Lc, 0.45) - (a - 1.0); >> -} >> - >> -static double avpriv_trc_linear(double Lc) >> -{ >> - return Lc; >> -} >> - >> -static double avpriv_trc_log(double Lc) >> -{ >> - return (0.01 > Lc) ? 0.0 : 1.0 + log10(Lc) / 2.0; >> -} >> - >> -static double avpriv_trc_log_sqrt(double Lc) >> -{ >> - // sqrt(10) / 1000 >> - return (0.00316227766 > Lc) ? 0.0 : 1.0 + log10(Lc) / 2.5; >> -} >> - >> -static double avpriv_trc_iec61966_2_4(double Lc) >> -{ >> - const double a = BT709_alpha; >> - const double b = BT709_beta; >> - >> - return (-b >= Lc) ? -a * pow(-Lc, 0.45) + (a - 1.0) >> - : ( b > Lc) ? 4.500 * Lc >> - : a * pow( Lc, 0.45) - (a - 1.0); >> -} >> - >> -static double avpriv_trc_bt1361(double Lc) >> -{ >> - const double a = BT709_alpha; >> - const double b = BT709_beta; >> - >> - return (-0.0045 >= Lc) ? -(a * pow(-4.0 * Lc, 0.45) + (a - 1.0)) / >> 4.0 >> - : ( b > Lc) ? 4.500 * Lc >> - : a * pow( Lc, 0.45) - (a - 1.0); >> -} >> - >> -static double avpriv_trc_iec61966_2_1(double Lc) >> -{ >> - const double a = 1.055; >> - const double b = 0.0031308; >> - >> - return (0.0 > Lc) ? 0.0 >> - : ( b > Lc) ? 12.92 * Lc >> - : a * pow(Lc, 1.0 / 2.4) - (a - 1.0); >> -} >> - >> -static double avpriv_trc_smpte_st2084(double Lc) >> -{ >> - const double c1 = 3424.0 / 4096.0; // c3-c2 + 1 >> - const double c2 = 32.0 * 2413.0 / 4096.0; >> - const double c3 = 32.0 * 2392.0 / 4096.0; >> - const double m = 128.0 * 2523.0 / 4096.0; >> - const double n = 0.25 * 2610.0 / 4096.0; >> - const double L = Lc / 10000.0; >> - const double Ln = pow(L, n); >> - >> - return (0.0 > Lc) ? 0.0 >> - : pow((c1 + c2 * Ln) / (1.0 + c3 * Ln), m); >> - >> -} >> - >> -static double avpriv_trc_smpte_st428_1(double Lc) >> -{ >> - return (0.0 > Lc) ? 0.0 >> - : pow(48.0 * Lc / 52.37, 1.0 / 2.6); >> -} >> - >> - >> -static double avpriv_trc_arib_std_b67(double Lc) { >> - // The function uses the definition from HEVC, which assumes that the >> peak >> - // white is input level = 1. (this is equivalent to scaling E = Lc * >> 12 and >> - // using the definition from the ARIB STD-B67 spec) >> - const double a = 0.17883277; >> - const double b = 0.28466892; >> - const double c = 0.55991073; >> - return (0.0 > Lc) ? 0.0 : >> - (Lc <= 1.0 / 12.0 ? sqrt(3.0 * Lc) : a * log(12.0 * Lc - b) + c); >> -} >> - >> -avpriv_trc_function avpriv_get_trc_function_from_trc(enum >> AVColorTransferCharacteristic trc) >> -{ >> - avpriv_trc_function func = NULL; >> - switch (trc) { >> - case AVCOL_TRC_BT709: >> - case AVCOL_TRC_SMPTE170M: >> - case AVCOL_TRC_BT2020_10: >> - case AVCOL_TRC_BT2020_12: >> - func = avpriv_trc_bt709; >> - break; >> - >> - case AVCOL_TRC_GAMMA22: >> - func = avpriv_trc_gamma22; >> - break; >> - case AVCOL_TRC_GAMMA28: >> - func = avpriv_trc_gamma28; >> - break; >> - >> - case AVCOL_TRC_SMPTE240M: >> - func = avpriv_trc_smpte240M; >> - break; >> - >> - case AVCOL_TRC_LINEAR: >> - func = avpriv_trc_linear; >> - break; >> - >> - case AVCOL_TRC_LOG: >> - func = avpriv_trc_log; >> - break; >> - >> - case AVCOL_TRC_LOG_SQRT: >> - func = avpriv_trc_log_sqrt; >> - break; >> - >> - case AVCOL_TRC_IEC61966_2_4: >> - func = avpriv_trc_iec61966_2_4; >> - break; >> - >> - case AVCOL_TRC_BT1361_ECG: >> - func = avpriv_trc_bt1361; >> - break; >> - >> - case AVCOL_TRC_IEC61966_2_1: >> - func = avpriv_trc_iec61966_2_1; >> - break; >> - >> - case AVCOL_TRC_SMPTEST2084: >> - func = avpriv_trc_smpte_st2084; >> - break; >> - >> - case AVCOL_TRC_SMPTEST428_1: >> - func = avpriv_trc_smpte_st428_1; >> - break; >> - >> - case AVCOL_TRC_ARIB_STD_B67: >> - func = avpriv_trc_arib_std_b67; >> - break; >> - >> - case AVCOL_TRC_RESERVED0: >> - case AVCOL_TRC_UNSPECIFIED: >> - case AVCOL_TRC_RESERVED: >> - default: >> - break; >> - } >> - return func; >> -} >> diff --git a/libavutil/color_utils.h b/libavutil/color_utils.h >> deleted file mode 100644 >> index 9529006452..0000000000 >> --- a/libavutil/color_utils.h >> +++ /dev/null >> @@ -1,56 +0,0 @@ >> -/* >> - * Copyright (c) 2015 Kevin Wheatley <kevin.j.wheatley@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_COLOR_UTILS_H >> -#define AVUTIL_COLOR_UTILS_H >> - >> - >> -#include "libavutil/pixfmt.h" >> - >> -/** >> - * Determine a suitable 'gamma' value to match the supplied >> - * AVColorTransferCharacteristic. >> - * >> - * See Apple Technical Note TN2257 >> (https://developer.apple.com/library/mac/technotes/tn2257/_index.html) >> - * >> - * @return Will return an approximation to the simple gamma function >> matching >> - * the supplied Transfer Characteristic, Will return 0.0 for any >> - * we cannot reasonably match against. >> - */ >> -double avpriv_get_gamma_from_trc(enum AVColorTransferCharacteristic trc); >> - >> - >> -typedef double (*avpriv_trc_function)(double); >> - >> -/** >> - * Determine the function needed to apply the given >> - * AVColorTransferCharacteristic to linear input. >> - * >> - * The function returned should expect a nominal domain and range of >> [0.0-1.0] >> - * values outside of this range maybe valid depending on the chosen >> - * characteristic function. >> - * >> - * @return Will return pointer to the function matching the >> - * supplied Transfer Characteristic. If unspecified will >> - * return NULL: >> - */ >> -avpriv_trc_function avpriv_get_trc_function_from_trc(enum >> AVColorTransferCharacteristic trc); >> - >> -#endif >> diff --git a/libavutil/csp.c b/libavutil/csp.c >> index 98fc83c1da..7ef822c60b 100644 >> --- a/libavutil/csp.c >> +++ b/libavutil/csp.c >> @@ -1,5 +1,8 @@ >> /* >> + * Copyright (c) 2015 Kevin Wheatley <kevin.j.wheatley@gmail.com> >> * Copyright (c) 2016 Ronald S. Bultje <rsbultje@gmail.com> >> + * Copyright (c) 2023 Leo Izen <leo.izen@gmail.com> >> + * >> * This file is part of FFmpeg. >> * >> * FFmpeg is free software; you can redistribute it and/or >> @@ -21,9 +24,11 @@ >> * @file Colorspace functions for libavutil >> * @author Ronald S. Bultje <rsbultje@gmail.com> >> * @author Leo Izen <leo.izen@gmail.com> >> + * @author Kevin Wheatley <kevin.j.wheatley@gmail.com> >> */ >> >> #include <stdlib.h> >> +#include <math.h> >> >> #include "attributes.h" >> #include "csp.h" >> @@ -126,3 +131,170 @@ enum AVColorPrimaries >> av_csp_primaries_id_from_desc(const AVColorPrimariesDesc * >> >> return AVCOL_PRI_UNSPECIFIED; >> } >> + >> +static const double approximate_gamma[AVCOL_TRC_NB] = { >> + [AVCOL_TRC_BT709] = 1.961, >> + [AVCOL_TRC_SMPTE170M] = 1.961, >> + [AVCOL_TRC_SMPTE240M] = 1.961, >> + [AVCOL_TRC_BT1361_ECG] = 1.961, >> + [AVCOL_TRC_BT2020_10] = 1.961, >> + [AVCOL_TRC_BT2020_12] = 1.961, >> + [AVCOL_TRC_GAMMA22] = 2.2, >> + [AVCOL_TRC_IEC61966_2_1] = 2.2, >> + [AVCOL_TRC_GAMMA28] = 2.8, >> + [AVCOL_TRC_LINEAR] = 1.0, >> + [AVCOL_TRC_SMPTE428] = 2.6, >> +}; >> + >> +double av_csp_approximate_trc_gamma(enum AVColorTransferCharacteristic >> trc) >> +{ >> + double gamma; >> + if (trc >= AVCOL_TRC_NB) >> + return 0.0; >> + gamma = approximate_gamma[trc]; >> + if (gamma > 0) >> + return gamma; >> + return 0.0; >> +} >> + >> +#define BT709_alpha 1.099296826809442 >> +#define BT709_beta 0.018053968510807 >> + >> +static double trc_bt709(double Lc) >> +{ >> + const double a = BT709_alpha; >> + const double b = BT709_beta; >> + >> + return (0.0 > Lc) ? 0.0 >> + : ( b > Lc) ? 4.500 * Lc >> + : a * pow(Lc, 0.45) - (a - 1.0); >> +} >> + >> +static double trc_gamma22(double Lc) >> +{ >> + return (0.0 > Lc) ? 0.0 : pow(Lc, 1.0/ 2.2); >> +} >> + >> +static double trc_gamma28(double Lc) >> +{ >> + return (0.0 > Lc) ? 0.0 : pow(Lc, 1.0/ 2.8); >> +} >> + >> +static double trc_smpte240M(double Lc) >> +{ >> + const double a = 1.1115; >> + const double b = 0.0228; >> + >> + return (0.0 > Lc) ? 0.0 >> + : ( b > Lc) ? 4.000 * Lc >> + : a * pow(Lc, 0.45) - (a - 1.0); >> +} >> + >> +static double trc_linear(double Lc) >> +{ >> + return Lc; >> +} >> + >> +static double trc_log(double Lc) >> +{ >> + return (0.01 > Lc) ? 0.0 : 1.0 + log10(Lc) / 2.0; >> +} >> + >> +static double trc_log_sqrt(double Lc) >> +{ >> + // sqrt(10) / 1000 >> + return (0.00316227766 > Lc) ? 0.0 : 1.0 + log10(Lc) / 2.5; >> +} >> + >> +static double trc_iec61966_2_4(double Lc) >> +{ >> + const double a = BT709_alpha; >> + const double b = BT709_beta; >> + >> + return (-b >= Lc) ? -a * pow(-Lc, 0.45) + (a - 1.0) >> + : ( b > Lc) ? 4.500 * Lc >> + : a * pow( Lc, 0.45) - (a - 1.0); >> +} >> + >> +static double trc_bt1361(double Lc) >> +{ >> + const double a = BT709_alpha; >> + const double b = BT709_beta; >> + >> + return (-0.0045 >= Lc) ? -(a * pow(-4.0 * Lc, 0.45) + (a - 1.0)) / >> 4.0 >> + : ( b > Lc) ? 4.500 * Lc >> + : a * pow( Lc, 0.45) - (a - 1.0); >> +} >> + >> +static double trc_iec61966_2_1(double Lc) >> +{ >> + const double a = 1.055; >> + const double b = 0.0031308; >> + >> + return (0.0 > Lc) ? 0.0 >> + : ( b > Lc) ? 12.92 * Lc >> + : a * pow(Lc, 1.0 / 2.4) - (a - 1.0); >> +} >> + >> +static double trc_smpte_st2084(double Lc) >> +{ >> + const double c1 = 3424.0 / 4096.0; // c3-c2 + 1 >> + const double c2 = 32.0 * 2413.0 / 4096.0; >> + const double c3 = 32.0 * 2392.0 / 4096.0; >> + const double m = 128.0 * 2523.0 / 4096.0; >> + const double n = 0.25 * 2610.0 / 4096.0; >> + const double L = Lc / 10000.0; >> + const double Ln = pow(L, n); >> + >> + return (0.0 > Lc) ? 0.0 >> + : pow((c1 + c2 * Ln) / (1.0 + c3 * Ln), m); >> + >> +} >> + >> +static double trc_smpte_st428_1(double Lc) >> +{ >> + return (0.0 > Lc) ? 0.0 >> + : pow(48.0 * Lc / 52.37, 1.0 / 2.6); >> +} >> + >> + >> +static double trc_arib_std_b67(double Lc) { >> + // The function uses the definition from HEVC, which assumes that the >> peak >> + // white is input level = 1. (this is equivalent to scaling E = Lc * >> 12 and >> + // using the definition from the ARIB STD-B67 spec) >> + const double a = 0.17883277; >> + const double b = 0.28466892; >> + const double c = 0.55991073; >> + return (0.0 > Lc) ? 0.0 : >> + (Lc <= 1.0 / 12.0 ? sqrt(3.0 * Lc) : a * log(12.0 * Lc - b) + c); >> +} >> + >> +static const av_csp_trc_function trc_funcs[AVCOL_TRC_NB] = { >> + [AVCOL_TRC_BT709] = trc_bt709, >> + [AVCOL_TRC_GAMMA22] = trc_gamma22, >> + [AVCOL_TRC_GAMMA28] = trc_gamma28, >> + [AVCOL_TRC_SMPTE170M] = trc_bt709, >> + [AVCOL_TRC_SMPTE240M] = trc_smpte240M, >> + [AVCOL_TRC_LINEAR] = trc_linear, >> + [AVCOL_TRC_LOG] = trc_log, >> + [AVCOL_TRC_LOG_SQRT] = trc_log_sqrt, >> + [AVCOL_TRC_IEC61966_2_4] = trc_iec61966_2_4, >> + [AVCOL_TRC_BT1361_ECG] = trc_bt1361, >> + [AVCOL_TRC_IEC61966_2_1] = trc_iec61966_2_1, >> + [AVCOL_TRC_BT2020_10] = trc_bt709, >> + [AVCOL_TRC_BT2020_12] = trc_bt709, >> + [AVCOL_TRC_SMPTE2084] = trc_smpte_st2084, >> + [AVCOL_TRC_SMPTE428] = trc_smpte_st428_1, >> + [AVCOL_TRC_ARIB_STD_B67] = trc_arib_std_b67, >> +}; >> + >> +av_csp_trc_function av_csp_trc_func_from_id(enum >> AVColorTransferCharacteristic trc) >> +{ >> + av_csp_trc_function func; >> + if (trc >= AVCOL_TRC_NB) >> + return NULL; >> + func = trc_funcs[trc]; >> + if (!func) >> + return NULL; >> + return func; >> +} >> diff --git a/libavutil/csp.h b/libavutil/csp.h >> index 18ef208adf..73bce52bc0 100644 >> --- a/libavutil/csp.h >> +++ b/libavutil/csp.h >> @@ -1,5 +1,8 @@ >> /* >> + * Copyright (c) 2015 Kevin Wheatley <kevin.j.wheatley@gmail.com> >> * Copyright (c) 2016 Ronald S. Bultje <rsbultje@gmail.com> >> + * Copyright (c) 2023 Leo Izen <leo.izen@gmail.com> >> + * >> * This file is part of FFmpeg. >> * >> * FFmpeg is free software; you can redistribute it and/or >> @@ -29,6 +32,7 @@ >> * @ingroup lavu_math_csp >> * @author Ronald S. Bultje <rsbultje@gmail.com> >> * @author Leo Izen <leo.izen@gmail.com> >> + * @author Kevin Wheatley <kevin.j.wheatley@gmail.com> >> */ >> >> /** >> @@ -76,6 +80,12 @@ typedef struct AVColorPrimariesDesc { >> AVPrimaryCoefficients prim; >> } AVColorPrimariesDesc; >> >> +/** >> + * Function pointer representing a double -> double transfer function >> that performs >> + * an EOTF transfer inversion. This function outputs linear light. >> + */ >> +typedef double (*av_csp_trc_function)(double); >> + >> /** >> * Retrieves the Luma coefficients necessary to construct a conversion >> matrix >> * from an enum constant describing the colorspace. >> @@ -104,6 +114,35 @@ const AVColorPrimariesDesc >> *av_csp_primaries_desc_from_id(enum AVColorPrimaries >> */ >> enum AVColorPrimaries av_csp_primaries_id_from_desc(const >> AVColorPrimariesDesc *prm); >> >> +/** >> + * Determine a suitable 'gamma' value to match the supplied >> + * AVColorTransferCharacteristic. >> + * >> + * See Apple Technical Note TN2257 >> (https://developer.apple.com/library/mac/technotes/tn2257/_index.html) >> + * >> + * This function returns the gamma exponent for the OETF. For example, >> sRGB is approximated >> + * by gamma 2.2, not by gamma 0.45455. >> + * >> + * @return Will return an approximation to the simple gamma function >> matching >> + * the supplied Transfer Characteristic, Will return 0.0 for any >> + * we cannot reasonably match against. >> + */ >> +double av_csp_approximate_trc_gamma(enum AVColorTransferCharacteristic >> trc); >> + >> +/** >> + * Determine the function needed to apply the given >> + * AVColorTransferCharacteristic to linear input. >> + * >> + * The function returned should expect a nominal domain and range of >> [0.0-1.0] >> + * values outside of this range maybe valid depending on the chosen >> + * characteristic function. >> + * >> + * @return Will return pointer to the function matching the >> + * supplied Transfer Characteristic. If unspecified will >> + * return NULL: >> + */ >> +av_csp_trc_function av_csp_trc_func_from_id(enum >> AVColorTransferCharacteristic trc); >> + >> /** >> * @} >> */ >> diff --git a/libavutil/tests/color_utils.c b/libavutil/tests/color_utils.c >> index 4bdc550330..95fb3c1d56 100644 >> --- a/libavutil/tests/color_utils.c >> +++ b/libavutil/tests/color_utils.c >> @@ -19,7 +19,7 @@ >> */ >> >> #include <stdio.h> >> -#include "libavutil/color_utils.c" >> +#include "libavutil/csp.h" >> #include "libavutil/macros.h" >> >> int main(int argc, char *argv[]) >> @@ -32,7 +32,7 @@ int main(int argc, char *argv[]) >> }; >> >> for(i = 0; i < AVCOL_TRC_NB; i++) { >> - avpriv_trc_function func = avpriv_get_trc_function_from_trc(i); >> + av_csp_trc_function func = av_csp_trc_func_from_id(i); >> for(j = 0; j < FF_ARRAY_ELEMS(test_data); j++) { >> if(func != NULL) { >> double result = func(test_data[j]); >> -- >> 2.39.1 >> >> _______________________________________________ >> 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". > > _______________________________________________ > 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". >
On 1/30/23 12:08, Zhao Zhili wrote: > > >> -----Original Message----- >> From: ffmpeg-devel <ffmpeg-devel-bounces@ffmpeg.org> On Behalf Of Leo Izen >> Sent: 2023年1月31日 0:50 >> To: ffmpeg-devel@ffmpeg.org >> Cc: Leo Izen <leo.izen@gmail.com> >> Subject: [FFmpeg-devel] [PATCH v2] avutil/{color_utils, csp}: merge color_utils into csp and expose API >> >> libavutil/color_utils contains some avpriv_ symbols that map >> enum AVTransferCharacteristic values to gamma-curve approximations and >> to the actual transfer functions to invert them (i.e. -> linear). >> >> There's two issues with this: >> (1) avpriv is evil and should be avoided whenever possible >> (2) libavutil/csp.h exposes a public API for handling color that >> already handles primaries and matricies >> >> I don't see any reason this API has to be private, so this commit takes >> the functionality from avutil/color_utils and merges it into avutil/csp >> with an exposed av_ API rather than the previous avpriv_ API. >> >> Every reference to the previous API has been updated to point to the >> new one. color_utils.h has been deleted as well. This should not break >> any applications as it only contained avpriv_ symbols in the first >> place, so nothing in that header could be referenced by other >> applications. > > Isn't it break old libavcodec which linked to the new libavutil? > That's why it's in the major version bump thread. - Leo Izen (thebombzen)
> On Jan 31, 2023, at 02:22, Leo Izen <leo.izen@gmail.com> wrote: > > On 1/30/23 12:08, Zhao Zhili wrote: >>> -----Original Message----- >>> From: ffmpeg-devel <ffmpeg-devel-bounces@ffmpeg.org> On Behalf Of Leo Izen >>> Sent: 2023年1月31日 0:50 >>> To: ffmpeg-devel@ffmpeg.org >>> Cc: Leo Izen <leo.izen@gmail.com> >>> Subject: [FFmpeg-devel] [PATCH v2] avutil/{color_utils, csp}: merge color_utils into csp and expose API >>> >>> libavutil/color_utils contains some avpriv_ symbols that map >>> enum AVTransferCharacteristic values to gamma-curve approximations and >>> to the actual transfer functions to invert them (i.e. -> linear). >>> >>> There's two issues with this: >>> (1) avpriv is evil and should be avoided whenever possible >>> (2) libavutil/csp.h exposes a public API for handling color that >>> already handles primaries and matricies >>> >>> I don't see any reason this API has to be private, so this commit takes >>> the functionality from avutil/color_utils and merges it into avutil/csp >>> with an exposed av_ API rather than the previous avpriv_ API. >>> >>> Every reference to the previous API has been updated to point to the >>> new one. color_utils.h has been deleted as well. This should not break >>> any applications as it only contained avpriv_ symbols in the first >>> place, so nothing in that header could be referenced by other >>> applications. >> Isn't it break old libavcodec which linked to the new libavutil? > > That's why it's in the major version bump thread. OK then. Didn’t notice that because email client didn’t show thread correctly. > > - 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".
diff --git a/doc/APIchanges b/doc/APIchanges index bc52a07964..f28eb59ed3 100644 --- a/doc/APIchanges +++ b/doc/APIchanges @@ -14,6 +14,10 @@ libavutil: 2021-04-27 API changes, most recent first: +2023-01-30 - xxxxxxxxxx - lavu 57.44.100 - csp.h + Add av_csp_approximate_trc_gamma() and av_csp_trc_func_from_id(). + Add av_csp_trc_function. + 2023-01-29 - xxxxxxxxxx - lavc 59.59.100 - avcodec.h Add AV_CODEC_FLAG_COPY_OPAQUE and AV_CODEC_FLAG_FRAME_DURATION. diff --git a/libavcodec/exr.c b/libavcodec/exr.c index 6a0af96ce4..2f1766c17b 100644 --- a/libavcodec/exr.c +++ b/libavcodec/exr.c @@ -36,11 +36,11 @@ #include "libavutil/avassert.h" #include "libavutil/common.h" +#include "libavutil/csp.h" #include "libavutil/imgutils.h" #include "libavutil/intfloat.h" #include "libavutil/avstring.h" #include "libavutil/opt.h" -#include "libavutil/color_utils.h" #include "libavutil/half2float.h" #include "avcodec.h" @@ -1189,7 +1189,7 @@ static int decode_block(AVCodecContext *avctx, void *tdata, int i, x, buf_size = s->buf_size; int c, rgb_channel_count; float one_gamma = 1.0f / s->gamma; - avpriv_trc_function trc_func = avpriv_get_trc_function_from_trc(s->apply_trc_type); + av_csp_trc_function trc_func = av_csp_trc_func_from_id(s->apply_trc_type); int ret; line_offset = AV_RL64(s->gb.buffer + jobnr * 8); @@ -2215,7 +2215,7 @@ static av_cold int decode_init(AVCodecContext *avctx) uint32_t i; union av_intfloat32 t; float one_gamma = 1.0f / s->gamma; - avpriv_trc_function trc_func = NULL; + av_csp_trc_function trc_func = NULL; ff_init_half2float_tables(&s->h2f_tables); @@ -2227,7 +2227,7 @@ static av_cold int decode_init(AVCodecContext *avctx) ff_bswapdsp_init(&s->bbdsp); #endif - trc_func = avpriv_get_trc_function_from_trc(s->apply_trc_type); + trc_func = av_csp_trc_func_from_id(s->apply_trc_type); if (trc_func) { for (i = 0; i < 65536; ++i) { t.i = half2float(i, &s->h2f_tables); diff --git a/libavcodec/fflcms2.c b/libavcodec/fflcms2.c index fd370fb310..5443f178bc 100644 --- a/libavcodec/fflcms2.c +++ b/libavcodec/fflcms2.c @@ -17,7 +17,6 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "libavutil/color_utils.h" #include "libavutil/csp.h" #include "fflcms2.h" diff --git a/libavcodec/pngenc.c b/libavcodec/pngenc.c index 2393161c3b..ac27eebf3a 100644 --- a/libavcodec/pngenc.c +++ b/libavcodec/pngenc.c @@ -29,7 +29,6 @@ #include "zlib_wrapper.h" #include "libavutil/avassert.h" -#include "libavutil/color_utils.h" #include "libavutil/crc.h" #include "libavutil/csp.h" #include "libavutil/libm.h" @@ -317,7 +316,7 @@ static int png_get_chrm(enum AVColorPrimaries prim, uint8_t *buf) static int png_get_gama(enum AVColorTransferCharacteristic trc, uint8_t *buf) { - double gamma = avpriv_get_gamma_from_trc(trc); + double gamma = av_csp_approximate_trc_gamma(trc); if (gamma <= 1e-6) return 0; diff --git a/libavformat/movenc.c b/libavformat/movenc.c index 8d31317838..6182dc7f58 100644 --- a/libavformat/movenc.c +++ b/libavformat/movenc.c @@ -47,6 +47,7 @@ #include "internal.h" #include "libavutil/avstring.h" #include "libavutil/channel_layout.h" +#include "libavutil/csp.h" #include "libavutil/intfloat.h" #include "libavutil/mathematics.h" #include "libavutil/libm.h" @@ -56,7 +57,6 @@ #include "libavutil/stereo3d.h" #include "libavutil/timecode.h" #include "libavutil/dovi_meta.h" -#include "libavutil/color_utils.h" #include "libavutil/uuid.h" #include "hevc.h" #include "rtpenc.h" @@ -2011,9 +2011,8 @@ static int mov_write_pasp_tag(AVIOContext *pb, MOVTrack *track) static int mov_write_gama_tag(AVFormatContext *s, AVIOContext *pb, MOVTrack *track, double gamma) { uint32_t gama = 0; - if (gamma <= 0.0) { - gamma = avpriv_get_gamma_from_trc(track->par->color_trc); - } + if (gamma <= 0.0) + gamma = av_csp_approximate_trc_gamma(track->par->color_trc); av_log(s, AV_LOG_DEBUG, "gamma value %g\n", gamma); if (gamma > 1e-6) { diff --git a/libavutil/Makefile b/libavutil/Makefile index 29b06665f5..dc9012f9a8 100644 --- a/libavutil/Makefile +++ b/libavutil/Makefile @@ -114,7 +114,6 @@ OBJS = adler32.o \ cast5.o \ camellia.o \ channel_layout.o \ - color_utils.o \ cpu.o \ crc.o \ csp.o \ diff --git a/libavutil/color_utils.c b/libavutil/color_utils.c deleted file mode 100644 index 5e221fb798..0000000000 --- a/libavutil/color_utils.c +++ /dev/null @@ -1,234 +0,0 @@ -/* - * Copyright (c) 2015 Kevin Wheatley <kevin.j.wheatley@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 <stddef.h> -#include <math.h> - -#include "libavutil/color_utils.h" -#include "libavutil/pixfmt.h" - -double avpriv_get_gamma_from_trc(enum AVColorTransferCharacteristic trc) -{ - double gamma; - switch (trc) { - case AVCOL_TRC_BT709: - case AVCOL_TRC_SMPTE170M: - case AVCOL_TRC_SMPTE240M: - case AVCOL_TRC_BT1361_ECG: - case AVCOL_TRC_BT2020_10: - case AVCOL_TRC_BT2020_12: - /* these share a segmented TRC, but gamma 1.961 is a close - approximation, and also more correct for decoding content */ - gamma = 1.961; - break; - case AVCOL_TRC_GAMMA22: - case AVCOL_TRC_IEC61966_2_1: - gamma = 2.2; - break; - case AVCOL_TRC_GAMMA28: - gamma = 2.8; - break; - case AVCOL_TRC_LINEAR: - gamma = 1.0; - break; - default: - gamma = 0.0; // Unknown value representation - } - return gamma; -} - -#define BT709_alpha 1.099296826809442 -#define BT709_beta 0.018053968510807 - -static double avpriv_trc_bt709(double Lc) -{ - const double a = BT709_alpha; - const double b = BT709_beta; - - return (0.0 > Lc) ? 0.0 - : ( b > Lc) ? 4.500 * Lc - : a * pow(Lc, 0.45) - (a - 1.0); -} - -static double avpriv_trc_gamma22(double Lc) -{ - return (0.0 > Lc) ? 0.0 : pow(Lc, 1.0/ 2.2); -} - -static double avpriv_trc_gamma28(double Lc) -{ - return (0.0 > Lc) ? 0.0 : pow(Lc, 1.0/ 2.8); -} - -static double avpriv_trc_smpte240M(double Lc) -{ - const double a = 1.1115; - const double b = 0.0228; - - return (0.0 > Lc) ? 0.0 - : ( b > Lc) ? 4.000 * Lc - : a * pow(Lc, 0.45) - (a - 1.0); -} - -static double avpriv_trc_linear(double Lc) -{ - return Lc; -} - -static double avpriv_trc_log(double Lc) -{ - return (0.01 > Lc) ? 0.0 : 1.0 + log10(Lc) / 2.0; -} - -static double avpriv_trc_log_sqrt(double Lc) -{ - // sqrt(10) / 1000 - return (0.00316227766 > Lc) ? 0.0 : 1.0 + log10(Lc) / 2.5; -} - -static double avpriv_trc_iec61966_2_4(double Lc) -{ - const double a = BT709_alpha; - const double b = BT709_beta; - - return (-b >= Lc) ? -a * pow(-Lc, 0.45) + (a - 1.0) - : ( b > Lc) ? 4.500 * Lc - : a * pow( Lc, 0.45) - (a - 1.0); -} - -static double avpriv_trc_bt1361(double Lc) -{ - const double a = BT709_alpha; - const double b = BT709_beta; - - return (-0.0045 >= Lc) ? -(a * pow(-4.0 * Lc, 0.45) + (a - 1.0)) / 4.0 - : ( b > Lc) ? 4.500 * Lc - : a * pow( Lc, 0.45) - (a - 1.0); -} - -static double avpriv_trc_iec61966_2_1(double Lc) -{ - const double a = 1.055; - const double b = 0.0031308; - - return (0.0 > Lc) ? 0.0 - : ( b > Lc) ? 12.92 * Lc - : a * pow(Lc, 1.0 / 2.4) - (a - 1.0); -} - -static double avpriv_trc_smpte_st2084(double Lc) -{ - const double c1 = 3424.0 / 4096.0; // c3-c2 + 1 - const double c2 = 32.0 * 2413.0 / 4096.0; - const double c3 = 32.0 * 2392.0 / 4096.0; - const double m = 128.0 * 2523.0 / 4096.0; - const double n = 0.25 * 2610.0 / 4096.0; - const double L = Lc / 10000.0; - const double Ln = pow(L, n); - - return (0.0 > Lc) ? 0.0 - : pow((c1 + c2 * Ln) / (1.0 + c3 * Ln), m); - -} - -static double avpriv_trc_smpte_st428_1(double Lc) -{ - return (0.0 > Lc) ? 0.0 - : pow(48.0 * Lc / 52.37, 1.0 / 2.6); -} - - -static double avpriv_trc_arib_std_b67(double Lc) { - // The function uses the definition from HEVC, which assumes that the peak - // white is input level = 1. (this is equivalent to scaling E = Lc * 12 and - // using the definition from the ARIB STD-B67 spec) - const double a = 0.17883277; - const double b = 0.28466892; - const double c = 0.55991073; - return (0.0 > Lc) ? 0.0 : - (Lc <= 1.0 / 12.0 ? sqrt(3.0 * Lc) : a * log(12.0 * Lc - b) + c); -} - -avpriv_trc_function avpriv_get_trc_function_from_trc(enum AVColorTransferCharacteristic trc) -{ - avpriv_trc_function func = NULL; - switch (trc) { - case AVCOL_TRC_BT709: - case AVCOL_TRC_SMPTE170M: - case AVCOL_TRC_BT2020_10: - case AVCOL_TRC_BT2020_12: - func = avpriv_trc_bt709; - break; - - case AVCOL_TRC_GAMMA22: - func = avpriv_trc_gamma22; - break; - case AVCOL_TRC_GAMMA28: - func = avpriv_trc_gamma28; - break; - - case AVCOL_TRC_SMPTE240M: - func = avpriv_trc_smpte240M; - break; - - case AVCOL_TRC_LINEAR: - func = avpriv_trc_linear; - break; - - case AVCOL_TRC_LOG: - func = avpriv_trc_log; - break; - - case AVCOL_TRC_LOG_SQRT: - func = avpriv_trc_log_sqrt; - break; - - case AVCOL_TRC_IEC61966_2_4: - func = avpriv_trc_iec61966_2_4; - break; - - case AVCOL_TRC_BT1361_ECG: - func = avpriv_trc_bt1361; - break; - - case AVCOL_TRC_IEC61966_2_1: - func = avpriv_trc_iec61966_2_1; - break; - - case AVCOL_TRC_SMPTEST2084: - func = avpriv_trc_smpte_st2084; - break; - - case AVCOL_TRC_SMPTEST428_1: - func = avpriv_trc_smpte_st428_1; - break; - - case AVCOL_TRC_ARIB_STD_B67: - func = avpriv_trc_arib_std_b67; - break; - - case AVCOL_TRC_RESERVED0: - case AVCOL_TRC_UNSPECIFIED: - case AVCOL_TRC_RESERVED: - default: - break; - } - return func; -} diff --git a/libavutil/color_utils.h b/libavutil/color_utils.h deleted file mode 100644 index 9529006452..0000000000 --- a/libavutil/color_utils.h +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright (c) 2015 Kevin Wheatley <kevin.j.wheatley@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_COLOR_UTILS_H -#define AVUTIL_COLOR_UTILS_H - - -#include "libavutil/pixfmt.h" - -/** - * Determine a suitable 'gamma' value to match the supplied - * AVColorTransferCharacteristic. - * - * See Apple Technical Note TN2257 (https://developer.apple.com/library/mac/technotes/tn2257/_index.html) - * - * @return Will return an approximation to the simple gamma function matching - * the supplied Transfer Characteristic, Will return 0.0 for any - * we cannot reasonably match against. - */ -double avpriv_get_gamma_from_trc(enum AVColorTransferCharacteristic trc); - - -typedef double (*avpriv_trc_function)(double); - -/** - * Determine the function needed to apply the given - * AVColorTransferCharacteristic to linear input. - * - * The function returned should expect a nominal domain and range of [0.0-1.0] - * values outside of this range maybe valid depending on the chosen - * characteristic function. - * - * @return Will return pointer to the function matching the - * supplied Transfer Characteristic. If unspecified will - * return NULL: - */ -avpriv_trc_function avpriv_get_trc_function_from_trc(enum AVColorTransferCharacteristic trc); - -#endif diff --git a/libavutil/csp.c b/libavutil/csp.c index 98fc83c1da..7ef822c60b 100644 --- a/libavutil/csp.c +++ b/libavutil/csp.c @@ -1,5 +1,8 @@ /* + * Copyright (c) 2015 Kevin Wheatley <kevin.j.wheatley@gmail.com> * Copyright (c) 2016 Ronald S. Bultje <rsbultje@gmail.com> + * Copyright (c) 2023 Leo Izen <leo.izen@gmail.com> + * * This file is part of FFmpeg. * * FFmpeg is free software; you can redistribute it and/or @@ -21,9 +24,11 @@ * @file Colorspace functions for libavutil * @author Ronald S. Bultje <rsbultje@gmail.com> * @author Leo Izen <leo.izen@gmail.com> + * @author Kevin Wheatley <kevin.j.wheatley@gmail.com> */ #include <stdlib.h> +#include <math.h> #include "attributes.h" #include "csp.h" @@ -126,3 +131,170 @@ enum AVColorPrimaries av_csp_primaries_id_from_desc(const AVColorPrimariesDesc * return AVCOL_PRI_UNSPECIFIED; } + +static const double approximate_gamma[AVCOL_TRC_NB] = { + [AVCOL_TRC_BT709] = 1.961, + [AVCOL_TRC_SMPTE170M] = 1.961, + [AVCOL_TRC_SMPTE240M] = 1.961, + [AVCOL_TRC_BT1361_ECG] = 1.961, + [AVCOL_TRC_BT2020_10] = 1.961, + [AVCOL_TRC_BT2020_12] = 1.961, + [AVCOL_TRC_GAMMA22] = 2.2, + [AVCOL_TRC_IEC61966_2_1] = 2.2, + [AVCOL_TRC_GAMMA28] = 2.8, + [AVCOL_TRC_LINEAR] = 1.0, + [AVCOL_TRC_SMPTE428] = 2.6, +}; + +double av_csp_approximate_trc_gamma(enum AVColorTransferCharacteristic trc) +{ + double gamma; + if (trc >= AVCOL_TRC_NB) + return 0.0; + gamma = approximate_gamma[trc]; + if (gamma > 0) + return gamma; + return 0.0; +} + +#define BT709_alpha 1.099296826809442 +#define BT709_beta 0.018053968510807 + +static double trc_bt709(double Lc) +{ + const double a = BT709_alpha; + const double b = BT709_beta; + + return (0.0 > Lc) ? 0.0 + : ( b > Lc) ? 4.500 * Lc + : a * pow(Lc, 0.45) - (a - 1.0); +} + +static double trc_gamma22(double Lc) +{ + return (0.0 > Lc) ? 0.0 : pow(Lc, 1.0/ 2.2); +} + +static double trc_gamma28(double Lc) +{ + return (0.0 > Lc) ? 0.0 : pow(Lc, 1.0/ 2.8); +} + +static double trc_smpte240M(double Lc) +{ + const double a = 1.1115; + const double b = 0.0228; + + return (0.0 > Lc) ? 0.0 + : ( b > Lc) ? 4.000 * Lc + : a * pow(Lc, 0.45) - (a - 1.0); +} + +static double trc_linear(double Lc) +{ + return Lc; +} + +static double trc_log(double Lc) +{ + return (0.01 > Lc) ? 0.0 : 1.0 + log10(Lc) / 2.0; +} + +static double trc_log_sqrt(double Lc) +{ + // sqrt(10) / 1000 + return (0.00316227766 > Lc) ? 0.0 : 1.0 + log10(Lc) / 2.5; +} + +static double trc_iec61966_2_4(double Lc) +{ + const double a = BT709_alpha; + const double b = BT709_beta; + + return (-b >= Lc) ? -a * pow(-Lc, 0.45) + (a - 1.0) + : ( b > Lc) ? 4.500 * Lc + : a * pow( Lc, 0.45) - (a - 1.0); +} + +static double trc_bt1361(double Lc) +{ + const double a = BT709_alpha; + const double b = BT709_beta; + + return (-0.0045 >= Lc) ? -(a * pow(-4.0 * Lc, 0.45) + (a - 1.0)) / 4.0 + : ( b > Lc) ? 4.500 * Lc + : a * pow( Lc, 0.45) - (a - 1.0); +} + +static double trc_iec61966_2_1(double Lc) +{ + const double a = 1.055; + const double b = 0.0031308; + + return (0.0 > Lc) ? 0.0 + : ( b > Lc) ? 12.92 * Lc + : a * pow(Lc, 1.0 / 2.4) - (a - 1.0); +} + +static double trc_smpte_st2084(double Lc) +{ + const double c1 = 3424.0 / 4096.0; // c3-c2 + 1 + const double c2 = 32.0 * 2413.0 / 4096.0; + const double c3 = 32.0 * 2392.0 / 4096.0; + const double m = 128.0 * 2523.0 / 4096.0; + const double n = 0.25 * 2610.0 / 4096.0; + const double L = Lc / 10000.0; + const double Ln = pow(L, n); + + return (0.0 > Lc) ? 0.0 + : pow((c1 + c2 * Ln) / (1.0 + c3 * Ln), m); + +} + +static double trc_smpte_st428_1(double Lc) +{ + return (0.0 > Lc) ? 0.0 + : pow(48.0 * Lc / 52.37, 1.0 / 2.6); +} + + +static double trc_arib_std_b67(double Lc) { + // The function uses the definition from HEVC, which assumes that the peak + // white is input level = 1. (this is equivalent to scaling E = Lc * 12 and + // using the definition from the ARIB STD-B67 spec) + const double a = 0.17883277; + const double b = 0.28466892; + const double c = 0.55991073; + return (0.0 > Lc) ? 0.0 : + (Lc <= 1.0 / 12.0 ? sqrt(3.0 * Lc) : a * log(12.0 * Lc - b) + c); +} + +static const av_csp_trc_function trc_funcs[AVCOL_TRC_NB] = { + [AVCOL_TRC_BT709] = trc_bt709, + [AVCOL_TRC_GAMMA22] = trc_gamma22, + [AVCOL_TRC_GAMMA28] = trc_gamma28, + [AVCOL_TRC_SMPTE170M] = trc_bt709, + [AVCOL_TRC_SMPTE240M] = trc_smpte240M, + [AVCOL_TRC_LINEAR] = trc_linear, + [AVCOL_TRC_LOG] = trc_log, + [AVCOL_TRC_LOG_SQRT] = trc_log_sqrt, + [AVCOL_TRC_IEC61966_2_4] = trc_iec61966_2_4, + [AVCOL_TRC_BT1361_ECG] = trc_bt1361, + [AVCOL_TRC_IEC61966_2_1] = trc_iec61966_2_1, + [AVCOL_TRC_BT2020_10] = trc_bt709, + [AVCOL_TRC_BT2020_12] = trc_bt709, + [AVCOL_TRC_SMPTE2084] = trc_smpte_st2084, + [AVCOL_TRC_SMPTE428] = trc_smpte_st428_1, + [AVCOL_TRC_ARIB_STD_B67] = trc_arib_std_b67, +}; + +av_csp_trc_function av_csp_trc_func_from_id(enum AVColorTransferCharacteristic trc) +{ + av_csp_trc_function func; + if (trc >= AVCOL_TRC_NB) + return NULL; + func = trc_funcs[trc]; + if (!func) + return NULL; + return func; +} diff --git a/libavutil/csp.h b/libavutil/csp.h index 18ef208adf..73bce52bc0 100644 --- a/libavutil/csp.h +++ b/libavutil/csp.h @@ -1,5 +1,8 @@ /* + * Copyright (c) 2015 Kevin Wheatley <kevin.j.wheatley@gmail.com> * Copyright (c) 2016 Ronald S. Bultje <rsbultje@gmail.com> + * Copyright (c) 2023 Leo Izen <leo.izen@gmail.com> + * * This file is part of FFmpeg. * * FFmpeg is free software; you can redistribute it and/or @@ -29,6 +32,7 @@ * @ingroup lavu_math_csp * @author Ronald S. Bultje <rsbultje@gmail.com> * @author Leo Izen <leo.izen@gmail.com> + * @author Kevin Wheatley <kevin.j.wheatley@gmail.com> */ /** @@ -76,6 +80,12 @@ typedef struct AVColorPrimariesDesc { AVPrimaryCoefficients prim; } AVColorPrimariesDesc; +/** + * Function pointer representing a double -> double transfer function that performs + * an EOTF transfer inversion. This function outputs linear light. + */ +typedef double (*av_csp_trc_function)(double); + /** * Retrieves the Luma coefficients necessary to construct a conversion matrix * from an enum constant describing the colorspace. @@ -104,6 +114,35 @@ const AVColorPrimariesDesc *av_csp_primaries_desc_from_id(enum AVColorPrimaries */ enum AVColorPrimaries av_csp_primaries_id_from_desc(const AVColorPrimariesDesc *prm); +/** + * Determine a suitable 'gamma' value to match the supplied + * AVColorTransferCharacteristic. + * + * See Apple Technical Note TN2257 (https://developer.apple.com/library/mac/technotes/tn2257/_index.html) + * + * This function returns the gamma exponent for the OETF. For example, sRGB is approximated + * by gamma 2.2, not by gamma 0.45455. + * + * @return Will return an approximation to the simple gamma function matching + * the supplied Transfer Characteristic, Will return 0.0 for any + * we cannot reasonably match against. + */ +double av_csp_approximate_trc_gamma(enum AVColorTransferCharacteristic trc); + +/** + * Determine the function needed to apply the given + * AVColorTransferCharacteristic to linear input. + * + * The function returned should expect a nominal domain and range of [0.0-1.0] + * values outside of this range maybe valid depending on the chosen + * characteristic function. + * + * @return Will return pointer to the function matching the + * supplied Transfer Characteristic. If unspecified will + * return NULL: + */ +av_csp_trc_function av_csp_trc_func_from_id(enum AVColorTransferCharacteristic trc); + /** * @} */ diff --git a/libavutil/tests/color_utils.c b/libavutil/tests/color_utils.c index 4bdc550330..95fb3c1d56 100644 --- a/libavutil/tests/color_utils.c +++ b/libavutil/tests/color_utils.c @@ -19,7 +19,7 @@ */ #include <stdio.h> -#include "libavutil/color_utils.c" +#include "libavutil/csp.h" #include "libavutil/macros.h" int main(int argc, char *argv[]) @@ -32,7 +32,7 @@ int main(int argc, char *argv[]) }; for(i = 0; i < AVCOL_TRC_NB; i++) { - avpriv_trc_function func = avpriv_get_trc_function_from_trc(i); + av_csp_trc_function func = av_csp_trc_func_from_id(i); for(j = 0; j < FF_ARRAY_ELEMS(test_data); j++) { if(func != NULL) { double result = func(test_data[j]);
libavutil/color_utils contains some avpriv_ symbols that map enum AVTransferCharacteristic values to gamma-curve approximations and to the actual transfer functions to invert them (i.e. -> linear). There's two issues with this: (1) avpriv is evil and should be avoided whenever possible (2) libavutil/csp.h exposes a public API for handling color that already handles primaries and matricies I don't see any reason this API has to be private, so this commit takes the functionality from avutil/color_utils and merges it into avutil/csp with an exposed av_ API rather than the previous avpriv_ API. Every reference to the previous API has been updated to point to the new one. color_utils.h has been deleted as well. This should not break any applications as it only contained avpriv_ symbols in the first place, so nothing in that header could be referenced by other applications. Signed-off-by: Leo Izen <leo.izen@gmail.com> --- doc/APIchanges | 4 + libavcodec/exr.c | 8 +- libavcodec/fflcms2.c | 1 - libavcodec/pngenc.c | 3 +- libavformat/movenc.c | 7 +- libavutil/Makefile | 1 - libavutil/color_utils.c | 234 ---------------------------------- libavutil/color_utils.h | 56 -------- libavutil/csp.c | 172 +++++++++++++++++++++++++ libavutil/csp.h | 39 ++++++ libavutil/tests/color_utils.c | 4 +- 11 files changed, 225 insertions(+), 304 deletions(-) delete mode 100644 libavutil/color_utils.c delete mode 100644 libavutil/color_utils.h