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.
Unified · Split
| @@ -14,6 +14,10 @@ libavutil: 2021-04-27 · 13 unmodified lines | |||
| 14 | 14 | ||
| 15 | API changes, most recent first: | 15 | API changes, most recent first: |
| 16 | 16 | ||
| 17 | 2023-02-xx - xxxxxxxxxx - lavu 58.0.100 - csp.h | ||
| 18 | Add av_csp_approximate_trc_gamma() and av_csp_trc_func_from_id(). | ||
| 19 | Add av_csp_trc_function. | ||
| 20 | |||
| 17 | 2023-02-xx - xxxxxxxxxx - lavc 60.0.100 - avcodec.h | 21 | 2023-02-xx - xxxxxxxxxx - lavc 60.0.100 - avcodec.h |
| 18 | avcodec_decode_subtitle2() now accepts const AVPacket*. | 22 | avcodec_decode_subtitle2() now accepts const AVPacket*. |
| 19 | 23 | ||
| @@ -36,11 +36,11 @@ · 35 unmodified lines | |||
| 36 | 36 | ||
| 37 | #include "libavutil/avassert.h" | 37 | #include "libavutil/avassert.h" |
| 38 | #include "libavutil/common.h" | 38 | #include "libavutil/common.h" |
| 39 | #include "libavutil/csp.h" | ||
| 39 | #include "libavutil/imgutils.h" | 40 | #include "libavutil/imgutils.h" |
| 40 | #include "libavutil/intfloat.h" | 41 | #include "libavutil/intfloat.h" |
| 41 | #include "libavutil/avstring.h" | 42 | #include "libavutil/avstring.h" |
| 42 | #include "libavutil/opt.h" | 43 | #include "libavutil/opt.h" |
| 43 | #include "libavutil/color_utils.h" | ||
| 44 | #include "libavutil/half2float.h" | 44 | #include "libavutil/half2float.h" |
| 45 | 45 | ||
| 46 | #include "avcodec.h" | 46 | #include "avcodec.h" |
| @@ -1189,7 +1189,7 @@ static int decode_block(AVCodecContext *avctx, void *tdata, · 1142 unmodified lines | |||
| 1189 | int i, x, buf_size = s->buf_size; | 1189 | int i, x, buf_size = s->buf_size; |
| 1190 | int c, rgb_channel_count; | 1190 | int c, rgb_channel_count; |
| 1191 | float one_gamma = 1.0f / s->gamma; | 1191 | float one_gamma = 1.0f / s->gamma; |
| 1192 | avpriv_trc_function trc_func = avpriv_get_trc_function_from_trc(s->apply_trc_type); | 1192 | av_csp_trc_function trc_func = av_csp_trc_func_from_id(s->apply_trc_type); |
| 1193 | int ret; | 1193 | int ret; |
| 1194 | 1194 | ||
| 1195 | line_offset = AV_RL64(s->gb.buffer + jobnr * 8); | 1195 | line_offset = AV_RL64(s->gb.buffer + jobnr * 8); |
| @@ -2215,7 +2215,7 @@ static av_cold int decode_init(AVCodecContext *avctx) · 1019 unmodified lines | |||
| 2215 | uint32_t i; | 2215 | uint32_t i; |
| 2216 | union av_intfloat32 t; | 2216 | union av_intfloat32 t; |
| 2217 | float one_gamma = 1.0f / s->gamma; | 2217 | float one_gamma = 1.0f / s->gamma; |
| 2218 | avpriv_trc_function trc_func = NULL; | 2218 | av_csp_trc_function trc_func = NULL; |
| 2219 | 2219 | ||
| 2220 | ff_init_half2float_tables(&s->h2f_tables); | 2220 | ff_init_half2float_tables(&s->h2f_tables); |
| 2221 | 2221 | ||
| @@ -2227,7 +2227,7 @@ static av_cold int decode_init(AVCodecContext *avctx) · 5 unmodified lines | |||
| 2227 | ff_bswapdsp_init(&s->bbdsp); | 2227 | ff_bswapdsp_init(&s->bbdsp); |
| 2228 | #endif | 2228 | #endif |
| 2229 | 2229 | ||
| 2230 | trc_func = avpriv_get_trc_function_from_trc(s->apply_trc_type); | 2230 | trc_func = av_csp_trc_func_from_id(s->apply_trc_type); |
| 2231 | if (trc_func) { | 2231 | if (trc_func) { |
| 2232 | for (i = 0; i < 65536; ++i) { | 2232 | for (i = 0; i < 65536; ++i) { |
| 2233 | t.i = half2float(i, &s->h2f_tables); | 2233 | t.i = half2float(i, &s->h2f_tables); |
| @@ -17,7 +17,6 @@ · 16 unmodified lines | |||
| 17 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | 17 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
| 18 | */ | 18 | */ |
| 19 | 19 | ||
| 20 | #include "libavutil/color_utils.h" | ||
| 21 | #include "libavutil/csp.h" | 20 | #include "libavutil/csp.h" |
| 22 | 21 | ||
| 23 | #include "fflcms2.h" | 22 | #include "fflcms2.h" |
| @@ -29,7 +29,6 @@ · 28 unmodified lines | |||
| 29 | #include "zlib_wrapper.h" | 29 | #include "zlib_wrapper.h" |
| 30 | 30 | ||
| 31 | #include "libavutil/avassert.h" | 31 | #include "libavutil/avassert.h" |
| 32 | #include "libavutil/color_utils.h" | ||
| 33 | #include "libavutil/crc.h" | 32 | #include "libavutil/crc.h" |
| 34 | #include "libavutil/csp.h" | 33 | #include "libavutil/csp.h" |
| 35 | #include "libavutil/libm.h" | 34 | #include "libavutil/libm.h" |
| @@ -317,7 +316,7 @@ static int png_get_chrm(enum AVColorPrimaries prim, uint8_t *buf) · 281 unmodified lines | |||
| 317 | 316 | ||
| 318 | static int png_get_gama(enum AVColorTransferCharacteristic trc, uint8_t *buf) | 317 | static int png_get_gama(enum AVColorTransferCharacteristic trc, uint8_t *buf) |
| 319 | { | 318 | { |
| 320 | double gamma = avpriv_get_gamma_from_trc(trc); | 319 | double gamma = av_csp_approximate_trc_gamma(trc); |
| 321 | if (gamma <= 1e-6) | 320 | if (gamma <= 1e-6) |
| 322 | return 0; | 321 | return 0; |
| 323 | 322 | ||
| @@ -47,6 +47,7 @@ · 46 unmodified lines | |||
| 47 | #include "internal.h" | 47 | #include "internal.h" |
| 48 | #include "libavutil/avstring.h" | 48 | #include "libavutil/avstring.h" |
| 49 | #include "libavutil/channel_layout.h" | 49 | #include "libavutil/channel_layout.h" |
| 50 | #include "libavutil/csp.h" | ||
| 50 | #include "libavutil/intfloat.h" | 51 | #include "libavutil/intfloat.h" |
| 51 | #include "libavutil/mathematics.h" | 52 | #include "libavutil/mathematics.h" |
| 52 | #include "libavutil/libm.h" | 53 | #include "libavutil/libm.h" |
| @@ -56,7 +57,6 @@ · 3 unmodified lines | |||
| 56 | #include "libavutil/stereo3d.h" | 57 | #include "libavutil/stereo3d.h" |
| 57 | #include "libavutil/timecode.h" | 58 | #include "libavutil/timecode.h" |
| 58 | #include "libavutil/dovi_meta.h" | 59 | #include "libavutil/dovi_meta.h" |
| 59 | #include "libavutil/color_utils.h" | ||
| 60 | #include "libavutil/uuid.h" | 60 | #include "libavutil/uuid.h" |
| 61 | #include "hevc.h" | 61 | #include "hevc.h" |
| 62 | #include "rtpenc.h" | 62 | #include "rtpenc.h" |
| @@ -2011,9 +2011,8 @@ static int mov_write_pasp_tag(AVIOContext *pb, MOVTrack *track) · 1948 unmodified lines | |||
| 2011 | static int mov_write_gama_tag(AVFormatContext *s, AVIOContext *pb, MOVTrack *track, double gamma) | 2011 | static int mov_write_gama_tag(AVFormatContext *s, AVIOContext *pb, MOVTrack *track, double gamma) |
| 2012 | { | 2012 | { |
| 2013 | uint32_t gama = 0; | 2013 | uint32_t gama = 0; |
| 2014 | if (gamma <= 0.0) { | 2014 | if (gamma <= 0.0) |
| 2015 | gamma = avpriv_get_gamma_from_trc(track->par->color_trc); | 2015 | gamma = av_csp_approximate_trc_gamma(track->par->color_trc); |
| 2016 | } | ||
| 2017 | av_log(s, AV_LOG_DEBUG, "gamma value %g\n", gamma); | 2016 | av_log(s, AV_LOG_DEBUG, "gamma value %g\n", gamma); |
| 2018 | 2017 | ||
| 2019 | if (gamma > 1e-6) { | 2018 | if (gamma > 1e-6) { |
| @@ -114,7 +114,6 @@ OBJS = adler32.o \ · 113 unmodified lines | |||
| 114 | cast5.o \ | 114 | cast5.o \ |
| 115 | camellia.o \ | 115 | camellia.o \ |
| 116 | channel_layout.o \ | 116 | channel_layout.o \ |
| 117 | color_utils.o \ | ||
| 118 | cpu.o \ | 117 | cpu.o \ |
| 119 | crc.o \ | 118 | crc.o \ |
| 120 | csp.o \ | 119 | csp.o \ |
| @@ -1,234 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (c) 2015 Kevin Wheatley <kevin.j.wheatley@gmail.com> | ||
| 3 | * | ||
| 4 | * This file is part of FFmpeg. | ||
| 5 | * | ||
| 6 | * FFmpeg is free software; you can redistribute it and/or | ||
| 7 | * modify it under the terms of the GNU Lesser General Public | ||
| 8 | * License as published by the Free Software Foundation; either | ||
| 9 | * version 2.1 of the License, or (at your option) any later version. | ||
| 10 | * | ||
| 11 | * FFmpeg is distributed in the hope that it will be useful, | ||
| 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
| 14 | * Lesser General Public License for more details. | ||
| 15 | * | ||
| 16 | * You should have received a copy of the GNU Lesser General Public | ||
| 17 | * License along with FFmpeg; if not, write to the Free Software | ||
| 18 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | ||
| 19 | */ | ||
| 20 | |||
| 21 | #include <stddef.h> | ||
| 22 | #include <math.h> | ||
| 23 | |||
| 24 | #include "libavutil/color_utils.h" | ||
| 25 | #include "libavutil/pixfmt.h" | ||
| 26 | |||
| 27 | double avpriv_get_gamma_from_trc(enum AVColorTransferCharacteristic trc) | ||
| 28 | { | ||
| 29 | double gamma; | ||
| 30 | switch (trc) { | ||
| 31 | case AVCOL_TRC_BT709: | ||
| 32 | case AVCOL_TRC_SMPTE170M: | ||
| 33 | case AVCOL_TRC_SMPTE240M: | ||
| 34 | case AVCOL_TRC_BT1361_ECG: | ||
| 35 | case AVCOL_TRC_BT2020_10: | ||
| 36 | case AVCOL_TRC_BT2020_12: | ||
| 37 | /* these share a segmented TRC, but gamma 1.961 is a close | ||
| 38 | approximation, and also more correct for decoding content */ | ||
| 39 | gamma = 1.961; | ||
| 40 | break; | ||
| 41 | case AVCOL_TRC_GAMMA22: | ||
| 42 | case AVCOL_TRC_IEC61966_2_1: | ||
| 43 | gamma = 2.2; | ||
| 44 | break; | ||
| 45 | case AVCOL_TRC_GAMMA28: | ||
| 46 | gamma = 2.8; | ||
| 47 | break; | ||
| 48 | case AVCOL_TRC_LINEAR: | ||
| 49 | gamma = 1.0; | ||
| 50 | break; | ||
| 51 | default: | ||
| 52 | gamma = 0.0; // Unknown value representation | ||
| 53 | } | ||
| 54 | return gamma; | ||
| 55 | } | ||
| 56 | |||
| 57 | #define BT709_alpha 1.099296826809442 | ||
| 58 | #define BT709_beta 0.018053968510807 | ||
| 59 | |||
| 60 | static double avpriv_trc_bt709(double Lc) | ||
| 61 | { | ||
| 62 | const double a = BT709_alpha; | ||
| 63 | const double b = BT709_beta; | ||
| 64 | |||
| 65 | return (0.0 > Lc) ? 0.0 | ||
| 66 | : ( b > Lc) ? 4.500 * Lc | ||
| 67 | : a * pow(Lc, 0.45) - (a - 1.0); | ||
| 68 | } | ||
| 69 | |||
| 70 | static double avpriv_trc_gamma22(double Lc) | ||
| 71 | { | ||
| 72 | return (0.0 > Lc) ? 0.0 : pow(Lc, 1.0/ 2.2); | ||
| 73 | } | ||
| 74 | |||
| 75 | static double avpriv_trc_gamma28(double Lc) | ||
| 76 | { | ||
| 77 | return (0.0 > Lc) ? 0.0 : pow(Lc, 1.0/ 2.8); | ||
| 78 | } | ||
| 79 | |||
| 80 | static double avpriv_trc_smpte240M(double Lc) | ||
| 81 | { | ||
| 82 | const double a = 1.1115; | ||
| 83 | const double b = 0.0228; | ||
| 84 | |||
| 85 | return (0.0 > Lc) ? 0.0 | ||
| 86 | : ( b > Lc) ? 4.000 * Lc | ||
| 87 | : a * pow(Lc, 0.45) - (a - 1.0); | ||
| 88 | } | ||
| 89 | |||
| 90 | static double avpriv_trc_linear(double Lc) | ||
| 91 | { | ||
| 92 | return Lc; | ||
| 93 | } | ||
| 94 | |||
| 95 | static double avpriv_trc_log(double Lc) | ||
| 96 | { | ||
| 97 | return (0.01 > Lc) ? 0.0 : 1.0 + log10(Lc) / 2.0; | ||
| 98 | } | ||
| 99 | |||
| 100 | static double avpriv_trc_log_sqrt(double Lc) | ||
| 101 | { | ||
| 102 | // sqrt(10) / 1000 | ||
| 103 | return (0.00316227766 > Lc) ? 0.0 : 1.0 + log10(Lc) / 2.5; | ||
| 104 | } | ||
| 105 | |||
| 106 | static double avpriv_trc_iec61966_2_4(double Lc) | ||
| 107 | { | ||
| 108 | const double a = BT709_alpha; | ||
| 109 | const double b = BT709_beta; | ||
| 110 | |||
| 111 | return (-b >= Lc) ? -a * pow(-Lc, 0.45) + (a - 1.0) | ||
| 112 | : ( b > Lc) ? 4.500 * Lc | ||
| 113 | : a * pow( Lc, 0.45) - (a - 1.0); | ||
| 114 | } | ||
| 115 | |||
| 116 | static double avpriv_trc_bt1361(double Lc) | ||
| 117 | { | ||
| 118 | const double a = BT709_alpha; | ||
| 119 | const double b = BT709_beta; | ||
| 120 | |||
| 121 | return (-0.0045 >= Lc) ? -(a * pow(-4.0 * Lc, 0.45) + (a - 1.0)) / 4.0 | ||
| 122 | : ( b > Lc) ? 4.500 * Lc | ||
| 123 | : a * pow( Lc, 0.45) - (a - 1.0); | ||
| 124 | } | ||
| 125 | |||
| 126 | static double avpriv_trc_iec61966_2_1(double Lc) | ||
| 127 | { | ||
| 128 | const double a = 1.055; | ||
| 129 | const double b = 0.0031308; | ||
| 130 | |||
| 131 | return (0.0 > Lc) ? 0.0 | ||
| 132 | : ( b > Lc) ? 12.92 * Lc | ||
| 133 | : a * pow(Lc, 1.0 / 2.4) - (a - 1.0); | ||
| 134 | } | ||
| 135 | |||
| 136 | static double avpriv_trc_smpte_st2084(double Lc) | ||
| 137 | { | ||
| 138 | const double c1 = 3424.0 / 4096.0; // c3-c2 + 1 | ||
| 139 | const double c2 = 32.0 * 2413.0 / 4096.0; | ||
| 140 | const double c3 = 32.0 * 2392.0 / 4096.0; | ||
| 141 | const double m = 128.0 * 2523.0 / 4096.0; | ||
| 142 | const double n = 0.25 * 2610.0 / 4096.0; | ||
| 143 | const double L = Lc / 10000.0; | ||
| 144 | const double Ln = pow(L, n); | ||
| 145 | |||
| 146 | return (0.0 > Lc) ? 0.0 | ||
| 147 | : pow((c1 + c2 * Ln) / (1.0 + c3 * Ln), m); | ||
| 148 | |||
| 149 | } | ||
| 150 | |||
| 151 | static double avpriv_trc_smpte_st428_1(double Lc) | ||
| 152 | { | ||
| 153 | return (0.0 > Lc) ? 0.0 | ||
| 154 | : pow(48.0 * Lc / 52.37, 1.0 / 2.6); | ||
| 155 | } | ||
| 156 | |||
| 157 | |||
| 158 | static double avpriv_trc_arib_std_b67(double Lc) { | ||
| 159 | // The function uses the definition from HEVC, which assumes that the peak | ||
| 160 | // white is input level = 1. (this is equivalent to scaling E = Lc * 12 and | ||
| 161 | // using the definition from the ARIB STD-B67 spec) | ||
| 162 | const double a = 0.17883277; | ||
| 163 | const double b = 0.28466892; | ||
| 164 | const double c = 0.55991073; | ||
| 165 | return (0.0 > Lc) ? 0.0 : | ||
| 166 | (Lc <= 1.0 / 12.0 ? sqrt(3.0 * Lc) : a * log(12.0 * Lc - b) + c); | ||
| 167 | } | ||
| 168 | |||
| 169 | avpriv_trc_function avpriv_get_trc_function_from_trc(enum AVColorTransferCharacteristic trc) | ||
| 170 | { | ||
| 171 | avpriv_trc_function func = NULL; | ||
| 172 | switch (trc) { | ||
| 173 | case AVCOL_TRC_BT709: | ||
| 174 | case AVCOL_TRC_SMPTE170M: | ||
| 175 | case AVCOL_TRC_BT2020_10: | ||
| 176 | case AVCOL_TRC_BT2020_12: | ||
| 177 | func = avpriv_trc_bt709; | ||
| 178 | break; | ||
| 179 | |||
| 180 | case AVCOL_TRC_GAMMA22: | ||
| 181 | func = avpriv_trc_gamma22; | ||
| 182 | break; | ||
| 183 | case AVCOL_TRC_GAMMA28: | ||
| 184 | func = avpriv_trc_gamma28; | ||
| 185 | break; | ||
| 186 | |||
| 187 | case AVCOL_TRC_SMPTE240M: | ||
| 188 | func = avpriv_trc_smpte240M; | ||
| 189 | break; | ||
| 190 | |||
| 191 | case AVCOL_TRC_LINEAR: | ||
| 192 | func = avpriv_trc_linear; | ||
| 193 | break; | ||
| 194 | |||
| 195 | case AVCOL_TRC_LOG: | ||
| 196 | func = avpriv_trc_log; | ||
| 197 | break; | ||
| 198 | |||
| 199 | case AVCOL_TRC_LOG_SQRT: | ||
| 200 | func = avpriv_trc_log_sqrt; | ||
| 201 | break; | ||
| 202 | |||
| 203 | case AVCOL_TRC_IEC61966_2_4: | ||
| 204 | func = avpriv_trc_iec61966_2_4; | ||
| 205 | break; | ||
| 206 | |||
| 207 | case AVCOL_TRC_BT1361_ECG: | ||
| 208 | func = avpriv_trc_bt1361; | ||
| 209 | break; | ||
| 210 | |||
| 211 | case AVCOL_TRC_IEC61966_2_1: | ||
| 212 | func = avpriv_trc_iec61966_2_1; | ||
| 213 | break; | ||
| 214 | |||
| 215 | case AVCOL_TRC_SMPTEST2084: | ||
| 216 | func = avpriv_trc_smpte_st2084; | ||
| 217 | break; | ||
| 218 | |||
| 219 | case AVCOL_TRC_SMPTEST428_1: | ||
| 220 | func = avpriv_trc_smpte_st428_1; | ||
| 221 | break; | ||
| 222 | |||
| 223 | case AVCOL_TRC_ARIB_STD_B67: | ||
| 224 | func = avpriv_trc_arib_std_b67; | ||
| 225 | break; | ||
| 226 | |||
| 227 | case AVCOL_TRC_RESERVED0: | ||
| 228 | case AVCOL_TRC_UNSPECIFIED: | ||
| 229 | case AVCOL_TRC_RESERVED: | ||
| 230 | default: | ||
| 231 | break; | ||
| 232 | } | ||
| 233 | return func; | ||
| 234 | } | ||
| @@ -1,56 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (c) 2015 Kevin Wheatley <kevin.j.wheatley@gmail.com> | ||
| 3 | * | ||
| 4 | * This file is part of FFmpeg. | ||
| 5 | * | ||
| 6 | * FFmpeg is free software; you can redistribute it and/or | ||
| 7 | * modify it under the terms of the GNU Lesser General Public | ||
| 8 | * License as published by the Free Software Foundation; either | ||
| 9 | * version 2.1 of the License, or (at your option) any later version. | ||
| 10 | * | ||
| 11 | * FFmpeg is distributed in the hope that it will be useful, | ||
| 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
| 14 | * Lesser General Public License for more details. | ||
| 15 | * | ||
| 16 | * You should have received a copy of the GNU Lesser General Public | ||
| 17 | * License along with FFmpeg; if not, write to the Free Software | ||
| 18 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | ||
| 19 | */ | ||
| 20 | |||
| 21 | #ifndef AVUTIL_COLOR_UTILS_H | ||
| 22 | #define AVUTIL_COLOR_UTILS_H | ||
| 23 | |||
| 24 | |||
| 25 | #include "libavutil/pixfmt.h" | ||
| 26 | |||
| 27 | /** | ||
| 28 | * Determine a suitable 'gamma' value to match the supplied | ||
| 29 | * AVColorTransferCharacteristic. | ||
| 30 | * | ||
| 31 | * See Apple Technical Note TN2257 (https://developer.apple.com/library/mac/technotes/tn2257/_index.html) | ||
| 32 | * | ||
| 33 | * @return Will return an approximation to the simple gamma function matching | ||
| 34 | * the supplied Transfer Characteristic, Will return 0.0 for any | ||
| 35 | * we cannot reasonably match against. | ||
| 36 | */ | ||
| 37 | double avpriv_get_gamma_from_trc(enum AVColorTransferCharacteristic trc); | ||
| 38 | |||
| 39 | |||
| 40 | typedef double (*avpriv_trc_function)(double); | ||
| 41 | |||
| 42 | /** | ||
| 43 | * Determine the function needed to apply the given | ||
| 44 | * AVColorTransferCharacteristic to linear input. | ||
| 45 | * | ||
| 46 | * The function returned should expect a nominal domain and range of [0.0-1.0] | ||
| 47 | * values outside of this range maybe valid depending on the chosen | ||
| 48 | * characteristic function. | ||
| 49 | * | ||
| 50 | * @return Will return pointer to the function matching the | ||
| 51 | * supplied Transfer Characteristic. If unspecified will | ||
| 52 | * return NULL: | ||
| 53 | */ | ||
| 54 | avpriv_trc_function avpriv_get_trc_function_from_trc(enum AVColorTransferCharacteristic trc); | ||
| 55 | |||
| 56 | #endif | ||
| @@ -1,5 +1,8 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * Copyright (c) 2015 Kevin Wheatley <kevin.j.wheatley@gmail.com> | ||
| 2 | * Copyright (c) 2016 Ronald S. Bultje <rsbultje@gmail.com> | 3 | * Copyright (c) 2016 Ronald S. Bultje <rsbultje@gmail.com> |
| 4 | * Copyright (c) 2023 Leo Izen <leo.izen@gmail.com> | ||
| 5 | * | ||
| 3 | * This file is part of FFmpeg. | 6 | * This file is part of FFmpeg. |
| 4 | * | 7 | * |
| 5 | * FFmpeg is free software; you can redistribute it and/or | 8 | * FFmpeg is free software; you can redistribute it and/or |
| @@ -21,9 +24,11 @@ · 15 unmodified lines | |||
| 21 | * @file Colorspace functions for libavutil | 24 | * @file Colorspace functions for libavutil |
| 22 | * @author Ronald S. Bultje <rsbultje@gmail.com> | 25 | * @author Ronald S. Bultje <rsbultje@gmail.com> |
| 23 | * @author Leo Izen <leo.izen@gmail.com> | 26 | * @author Leo Izen <leo.izen@gmail.com> |
| 27 | * @author Kevin Wheatley <kevin.j.wheatley@gmail.com> | ||
| 24 | */ | 28 | */ |
| 25 | 29 | ||
| 26 | #include <stdlib.h> | 30 | #include <stdlib.h> |
| 31 | #include <math.h> | ||
| 27 | 32 | ||
| 28 | #include "attributes.h" | 33 | #include "attributes.h" |
| 29 | #include "csp.h" | 34 | #include "csp.h" |
| @@ -126,3 +131,170 @@ enum AVColorPrimaries av_csp_primaries_id_from_desc(const AVColorPrimariesDesc * · 96 unmodified lines | |||
| 126 | 131 | ||
| 127 | return AVCOL_PRI_UNSPECIFIED; | 132 | return AVCOL_PRI_UNSPECIFIED; |
| 128 | } | 133 | } |
| 134 | |||
| 135 | static const double approximate_gamma[AVCOL_TRC_NB] = { | ||
| 136 | [AVCOL_TRC_BT709] = 1.961, | ||
| 137 | [AVCOL_TRC_SMPTE170M] = 1.961, | ||
| 138 | [AVCOL_TRC_SMPTE240M] = 1.961, | ||
| 139 | [AVCOL_TRC_BT1361_ECG] = 1.961, | ||
| 140 | [AVCOL_TRC_BT2020_10] = 1.961, | ||
| 141 | [AVCOL_TRC_BT2020_12] = 1.961, | ||
| 142 | [AVCOL_TRC_GAMMA22] = 2.2, | ||
| 143 | [AVCOL_TRC_IEC61966_2_1] = 2.2, | ||
| 144 | [AVCOL_TRC_GAMMA28] = 2.8, | ||
| 145 | [AVCOL_TRC_LINEAR] = 1.0, | ||
| 146 | [AVCOL_TRC_SMPTE428] = 2.6, | ||
| 147 | }; | ||
| 148 | |||
| 149 | double av_csp_approximate_trc_gamma(enum AVColorTransferCharacteristic trc) | ||
| 150 | { | ||
| 151 | double gamma; | ||
| 152 | if (trc >= AVCOL_TRC_NB) | ||
| 153 | return 0.0; | ||
| 154 | gamma = approximate_gamma[trc]; | ||
| 155 | if (gamma > 0) | ||
| 156 | return gamma; | ||
| 157 | return 0.0; | ||
| 158 | } | ||
| 159 | |||
| 160 | #define BT709_alpha 1.099296826809442 | ||
| 161 | #define BT709_beta 0.018053968510807 | ||
| 162 | |||
| 163 | static double trc_bt709(double Lc) | ||
| 164 | { | ||
| 165 | const double a = BT709_alpha; | ||
| 166 | const double b = BT709_beta; | ||
| 167 | |||
| 168 | return (0.0 > Lc) ? 0.0 | ||
| 169 | : ( b > Lc) ? 4.500 * Lc | ||
| 170 | : a * pow(Lc, 0.45) - (a - 1.0); | ||
| 171 | } | ||
| 172 | |||
| 173 | static double trc_gamma22(double Lc) | ||
| 174 | { | ||
| 175 | return (0.0 > Lc) ? 0.0 : pow(Lc, 1.0/ 2.2); | ||
| 176 | } | ||
| 177 | |||
| 178 | static double trc_gamma28(double Lc) | ||
| 179 | { | ||
| 180 | return (0.0 > Lc) ? 0.0 : pow(Lc, 1.0/ 2.8); | ||
| 181 | } | ||
| 182 | |||
| 183 | static double trc_smpte240M(double Lc) | ||
| 184 | { | ||
| 185 | const double a = 1.1115; | ||
| 186 | const double b = 0.0228; | ||
| 187 | |||
| 188 | return (0.0 > Lc) ? 0.0 | ||
| 189 | : ( b > Lc) ? 4.000 * Lc | ||
| 190 | : a * pow(Lc, 0.45) - (a - 1.0); | ||
| 191 | } | ||
| 192 | |||
| 193 | static double trc_linear(double Lc) | ||
| 194 | { | ||
| 195 | return Lc; | ||
| 196 | } | ||
| 197 | |||
| 198 | static double trc_log(double Lc) | ||
| 199 | { | ||
| 200 | return (0.01 > Lc) ? 0.0 : 1.0 + log10(Lc) / 2.0; | ||
| 201 | } | ||
| 202 | |||
| 203 | static double trc_log_sqrt(double Lc) | ||
| 204 | { | ||
| 205 | // sqrt(10) / 1000 | ||
| 206 | return (0.00316227766 > Lc) ? 0.0 : 1.0 + log10(Lc) / 2.5; | ||
| 207 | } | ||
| 208 | |||
| 209 | static double trc_iec61966_2_4(double Lc) | ||
| 210 | { | ||
| 211 | const double a = BT709_alpha; | ||
| 212 | const double b = BT709_beta; | ||
| 213 | |||
| 214 | return (-b >= Lc) ? -a * pow(-Lc, 0.45) + (a - 1.0) | ||
| 215 | : ( b > Lc) ? 4.500 * Lc | ||
| 216 | : a * pow( Lc, 0.45) - (a - 1.0); | ||
| 217 | } | ||
| 218 | |||
| 219 | static double trc_bt1361(double Lc) | ||
| 220 | { | ||
| 221 | const double a = BT709_alpha; | ||
| 222 | const double b = BT709_beta; | ||
| 223 | |||
| 224 | return (-0.0045 >= Lc) ? -(a * pow(-4.0 * Lc, 0.45) + (a - 1.0)) / 4.0 | ||
| 225 | : ( b > Lc) ? 4.500 * Lc | ||
| 226 | : a * pow( Lc, 0.45) - (a - 1.0); | ||
| 227 | } | ||
| 228 | |||
| 229 | static double trc_iec61966_2_1(double Lc) | ||
| 230 | { | ||
| 231 | const double a = 1.055; | ||
| 232 | const double b = 0.0031308; | ||
| 233 | |||
| 234 | return (0.0 > Lc) ? 0.0 | ||
| 235 | : ( b > Lc) ? 12.92 * Lc | ||
| 236 | : a * pow(Lc, 1.0 / 2.4) - (a - 1.0); | ||
| 237 | } | ||
| 238 | |||
| 239 | static double trc_smpte_st2084(double Lc) | ||
| 240 | { | ||
| 241 | const double c1 = 3424.0 / 4096.0; // c3-c2 + 1 | ||
| 242 | const double c2 = 32.0 * 2413.0 / 4096.0; | ||
| 243 | const double c3 = 32.0 * 2392.0 / 4096.0; | ||
| 244 | const double m = 128.0 * 2523.0 / 4096.0; | ||
| 245 | const double n = 0.25 * 2610.0 / 4096.0; | ||
| 246 | const double L = Lc / 10000.0; | ||
| 247 | const double Ln = pow(L, n); | ||
| 248 | |||
| 249 | return (0.0 > Lc) ? 0.0 | ||
| 250 | : pow((c1 + c2 * Ln) / (1.0 + c3 * Ln), m); | ||
| 251 | |||
| 252 | } | ||
| 253 | |||
| 254 | static double trc_smpte_st428_1(double Lc) | ||
| 255 | { | ||
| 256 | return (0.0 > Lc) ? 0.0 | ||
| 257 | : pow(48.0 * Lc / 52.37, 1.0 / 2.6); | ||
| 258 | } | ||
| 259 | |||
| 260 | |||
| 261 | static double trc_arib_std_b67(double Lc) { | ||
| 262 | // The function uses the definition from HEVC, which assumes that the peak | ||
| 263 | // white is input level = 1. (this is equivalent to scaling E = Lc * 12 and | ||
| 264 | // using the definition from the ARIB STD-B67 spec) | ||
| 265 | const double a = 0.17883277; | ||
| 266 | const double b = 0.28466892; | ||
| 267 | const double c = 0.55991073; | ||
| 268 | return (0.0 > Lc) ? 0.0 : | ||
| 269 | (Lc <= 1.0 / 12.0 ? sqrt(3.0 * Lc) : a * log(12.0 * Lc - b) + c); | ||
| 270 | } | ||
| 271 | |||
| 272 | static const av_csp_trc_function trc_funcs[AVCOL_TRC_NB] = { | ||
| 273 | [AVCOL_TRC_BT709] = trc_bt709, | ||
| 274 | [AVCOL_TRC_GAMMA22] = trc_gamma22, | ||
| 275 | [AVCOL_TRC_GAMMA28] = trc_gamma28, | ||
| 276 | [AVCOL_TRC_SMPTE170M] = trc_bt709, | ||
| 277 | [AVCOL_TRC_SMPTE240M] = trc_smpte240M, | ||
| 278 | [AVCOL_TRC_LINEAR] = trc_linear, | ||
| 279 | [AVCOL_TRC_LOG] = trc_log, | ||
| 280 | [AVCOL_TRC_LOG_SQRT] = trc_log_sqrt, | ||
| 281 | [AVCOL_TRC_IEC61966_2_4] = trc_iec61966_2_4, | ||
| 282 | [AVCOL_TRC_BT1361_ECG] = trc_bt1361, | ||
| 283 | [AVCOL_TRC_IEC61966_2_1] = trc_iec61966_2_1, | ||
| 284 | [AVCOL_TRC_BT2020_10] = trc_bt709, | ||
| 285 | [AVCOL_TRC_BT2020_12] = trc_bt709, | ||
| 286 | [AVCOL_TRC_SMPTE2084] = trc_smpte_st2084, | ||
| 287 | [AVCOL_TRC_SMPTE428] = trc_smpte_st428_1, | ||
| 288 | [AVCOL_TRC_ARIB_STD_B67] = trc_arib_std_b67, | ||
| 289 | }; | ||
| 290 | |||
| 291 | av_csp_trc_function av_csp_trc_func_from_id(enum AVColorTransferCharacteristic trc) | ||
| 292 | { | ||
| 293 | av_csp_trc_function func; | ||
| 294 | if (trc >= AVCOL_TRC_NB) | ||
| 295 | return NULL; | ||
| 296 | func = trc_funcs[trc]; | ||
| 297 | if (!func) | ||
| 298 | return NULL; | ||
| 299 | return func; | ||
| 300 | } | ||
| @@ -1,5 +1,8 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * Copyright (c) 2015 Kevin Wheatley <kevin.j.wheatley@gmail.com> | ||
| 2 | * Copyright (c) 2016 Ronald S. Bultje <rsbultje@gmail.com> | 3 | * Copyright (c) 2016 Ronald S. Bultje <rsbultje@gmail.com> |
| 4 | * Copyright (c) 2023 Leo Izen <leo.izen@gmail.com> | ||
| 5 | * | ||
| 3 | * This file is part of FFmpeg. | 6 | * This file is part of FFmpeg. |
| 4 | * | 7 | * |
| 5 | * FFmpeg is free software; you can redistribute it and/or | 8 | * FFmpeg is free software; you can redistribute it and/or |
| @@ -29,6 +32,7 @@ · 23 unmodified lines | |||
| 29 | * @ingroup lavu_math_csp | 32 | * @ingroup lavu_math_csp |
| 30 | * @author Ronald S. Bultje <rsbultje@gmail.com> | 33 | * @author Ronald S. Bultje <rsbultje@gmail.com> |
| 31 | * @author Leo Izen <leo.izen@gmail.com> | 34 | * @author Leo Izen <leo.izen@gmail.com> |
| 35 | * @author Kevin Wheatley <kevin.j.wheatley@gmail.com> | ||
| 32 | */ | 36 | */ |
| 33 | 37 | ||
| 34 | /** | 38 | /** |
| @@ -76,6 +80,12 @@ typedef struct AVColorPrimariesDesc { · 41 unmodified lines | |||
| 76 | AVPrimaryCoefficients prim; | 80 | AVPrimaryCoefficients prim; |
| 77 | } AVColorPrimariesDesc; | 81 | } AVColorPrimariesDesc; |
| 78 | 82 | ||
| 83 | /** | ||
| 84 | * Function pointer representing a double -> double transfer function that performs | ||
| 85 | * an EOTF transfer inversion. This function outputs linear light. | ||
| 86 | */ | ||
| 87 | typedef double (*av_csp_trc_function)(double); | ||
| 88 | |||
| 79 | /** | 89 | /** |
| 80 | * Retrieves the Luma coefficients necessary to construct a conversion matrix | 90 | * Retrieves the Luma coefficients necessary to construct a conversion matrix |
| 81 | * from an enum constant describing the colorspace. | 91 | * from an enum constant describing the colorspace. |
| @@ -104,6 +114,35 @@ const AVColorPrimariesDesc *av_csp_primaries_desc_from_id(enum AVColorPrimaries · 22 unmodified lines | |||
| 104 | */ | 114 | */ |
| 105 | enum AVColorPrimaries av_csp_primaries_id_from_desc(const AVColorPrimariesDesc *prm); | 115 | enum AVColorPrimaries av_csp_primaries_id_from_desc(const AVColorPrimariesDesc *prm); |
| 106 | 116 | ||
| 117 | /** | ||
| 118 | * Determine a suitable 'gamma' value to match the supplied | ||
| 119 | * AVColorTransferCharacteristic. | ||
| 120 | * | ||
| 121 | * See Apple Technical Note TN2257 (https://developer.apple.com/library/mac/technotes/tn2257/_index.html) | ||
| 122 | * | ||
| 123 | * This function returns the gamma exponent for the OETF. For example, sRGB is approximated | ||
| 124 | * by gamma 2.2, not by gamma 0.45455. | ||
| 125 | * | ||
| 126 | * @return Will return an approximation to the simple gamma function matching | ||
| 127 | * the supplied Transfer Characteristic, Will return 0.0 for any | ||
| 128 | * we cannot reasonably match against. | ||
| 129 | */ | ||
| 130 | double av_csp_approximate_trc_gamma(enum AVColorTransferCharacteristic trc); | ||
| 131 | |||
| 132 | /** | ||
| 133 | * Determine the function needed to apply the given | ||
| 134 | * AVColorTransferCharacteristic to linear input. | ||
| 135 | * | ||
| 136 | * The function returned should expect a nominal domain and range of [0.0-1.0] | ||
| 137 | * values outside of this range maybe valid depending on the chosen | ||
| 138 | * characteristic function. | ||
| 139 | * | ||
| 140 | * @return Will return pointer to the function matching the | ||
| 141 | * supplied Transfer Characteristic. If unspecified will | ||
| 142 | * return NULL: | ||
| 143 | */ | ||
| 144 | av_csp_trc_function av_csp_trc_func_from_id(enum AVColorTransferCharacteristic trc); | ||
| 145 | |||
| 107 | /** | 146 | /** |
| 108 | * @} | 147 | * @} |
| 109 | */ | 148 | */ |
| @@ -19,7 +19,7 @@ · 18 unmodified lines | |||
| 19 | */ | 19 | */ |
| 20 | 20 | ||
| 21 | #include <stdio.h> | 21 | #include <stdio.h> |
| 22 | #include "libavutil/color_utils.c" | 22 | #include "libavutil/csp.h" |
| 23 | #include "libavutil/macros.h" | 23 | #include "libavutil/macros.h" |
| 24 | 24 | ||
| 25 | int main(int argc, char *argv[]) | 25 | int main(int argc, char *argv[]) |
| @@ -32,7 +32,7 @@ int main(int argc, char *argv[]) · 6 unmodified lines | |||
| 32 | }; | 32 | }; |
| 33 | 33 | ||
| 34 | for(i = 0; i < AVCOL_TRC_NB; i++) { | 34 | for(i = 0; i < AVCOL_TRC_NB; i++) { |
| 35 | avpriv_trc_function func = avpriv_get_trc_function_from_trc(i); | 35 | av_csp_trc_function func = av_csp_trc_func_from_id(i); |
| 36 | for(j = 0; j < FF_ARRAY_ELEMS(test_data); j++) { | 36 | for(j = 0; j < FF_ARRAY_ELEMS(test_data); j++) { |
| 37 | if(func != NULL) { | 37 | if(func != NULL) { |
| 38 | double result = func(test_data[j]); | 38 | double result = func(test_data[j]); |