This is an automated email from the git hooks/post-receive script. Git pushed a commit to branch master in repository ffmpeg.
commit 89ca1261d063f38e981de392ebd28c4e360f2467 Author: Kacper Michajłow <[email protected]> AuthorDate: Sat Oct 24 19:53:15 2026 +0200 Commit: Kacper Michajłow <[email protected]> CommitDate: Wed Oct 28 19:22:28 2026 +0000 avutil/csp: apply only the transfer in the ST 428-1 EOTF The EOTF scaled X and Z by the X/Y and Z/Y of the DCI white, the reference projector of RP 431-2, which ST 428-1 does not define: it fixes the transfer alone, 52.37/48 above the 48 cd/m2 white. Treat the three channels alike, L = (Lw - Lb) * 52.37/48 * V^2.6 + Lb, through the wrappers of the other SDR curves. Equal in each channel, the black is neutral in RGB only. The black of X'Y'Z' has the white of its content, which only the RGB it is decoded into knows, so the documentation asks for Lb = 0 on X'Y'Z' samples and their black after that conversion. A gray of the reference projector came out at the chromaticity (0.298, 0.366) instead of its own. Broken since 06f084468e. Signed-off-by: Kacper Michajłow <[email protected]> --- libavutil/csp.c | 30 ++---------------------------- libavutil/csp.h | 5 +++-- tests/ref/fate/color_utils | 20 ++++++++++---------- 3 files changed, 15 insertions(+), 40 deletions(-) diff --git a/libavutil/csp.c b/libavutil/csp.c index 7ebbcc5856..5f37984429 100644 --- a/libavutil/csp.c +++ b/libavutil/csp.c @@ -537,6 +537,7 @@ static void oetf_##name##_inv(double E[3]) \ WRAP_SDR_OETF(gamma22) WRAP_SDR_OETF(gamma28) WRAP_SDR_OETF(iec61966_2_1) +WRAP_SDR_OETF(smpte_st428_1) #define WRAP_SDR_EOTF(name) \ static void eotf_##name(double Lw, double Lb, double E[3]) \ @@ -554,6 +555,7 @@ static void eotf_##name##_inv(double Lw, double Lb, double L[3]) \ WRAP_SDR_EOTF(gamma22) WRAP_SDR_EOTF(gamma28) WRAP_SDR_EOTF(iec61966_2_1) +WRAP_SDR_EOTF(smpte_st428_1) static void eotf_bt1886(const double Lw, const double Lb, double E[3]) { @@ -589,34 +591,6 @@ static void eotf_smpte_st2084_inv(const double Lw, const double Lb, double L[3]) L[i] = trc_smpte_st2084(L[i]); } -/* This implementation assumes an SMPTE RP 431-2 reference projector (DCI) */ -#define DCI_L 48.00 -#define DCI_P 52.37 -#define DCI_X (42.94 / DCI_L) -#define DCI_Z (45.82 / DCI_L) - -static void eotf_smpte_st428_1(const double Lw_Y, const double Lb_Y, double E[3]) -{ - const double Lw[3] = { DCI_X * Lw_Y, Lw_Y, DCI_Z * Lw_Y }; - const double Lb[3] = { DCI_X * Lb_Y, Lb_Y, DCI_Z * Lb_Y }; - - for (int i = 0; i < 3; i++) { - E[i] = (0.0 > E[i]) ? 0.0 : pow(E[i], 2.6) * DCI_P / DCI_L; - E[i] = E[i] * (Lw[i] - Lb[i]) + Lb[i]; - } -} - -static void eotf_smpte_st428_1_inv(const double Lw_Y, const double Lb_Y, double L[3]) -{ - const double Lw[3] = { DCI_X * Lw_Y, Lw_Y, DCI_Z * Lw_Y }; - const double Lb[3] = { DCI_X * Lb_Y, Lb_Y, DCI_Z * Lb_Y }; - - for (int i = 0; i < 3; i++) { - L[i] = (L[i] - Lb[i]) / (Lw[i] - Lb[i]); - L[i] = (0.0 > L[i]) ? 0.0 : pow(L[i] * DCI_L / DCI_P, 1.0 / 2.6); - } -} - static void eotf_arib_std_b67(const double Lw, const double Lb, double E[3]) { const double gamma = fmax(1.2 + 0.42 * log10(Lw / 1000.0), 1.0); diff --git a/libavutil/csp.h b/libavutil/csp.h index 9d75ccbb64..8c035b4686 100644 --- a/libavutil/csp.h +++ b/libavutil/csp.h @@ -180,8 +180,9 @@ typedef void (*av_csp_eotf_function)(double Lw, double Lb, double c[3]); /** * Returns the ITU EOTF corresponding to a given TRC. This converts from the * signal level [0,1] to the raw output display luminance in nits (cd/m^2). - * This is done per channel in RGB space, except for AVCOL_TRC_SMPTE428, which - * assumes CIE XYZ in- and output. + * This is done per channel in RGB space. For X'Y'Z' with AVCOL_TRC_SMPTE428, + * pass Lb = 0 and apply the black level after the conversion to RGB for correct + * white point scaling. * * @return A pointer to the function implementing the given TRC, or NULL if no * such function is defined. diff --git a/tests/ref/fate/color_utils b/tests/ref/fate/color_utils index e681ef7310..237c9ac40f 100644 --- a/tests/ref/fate/color_utils +++ b/tests/ref/fate/color_utils @@ -2741,16 +2741,16 @@ trc=bt2020-12 EOTF(10000, 1.5, {0.7}) = {4360.83} trc=bt2020-12 EOTF(10000, 1.5, {0.8}) = {5943.5} trc=bt2020-12 EOTF(10000, 1.5, {0.9}) = {7818.66} trc=bt2020-12 EOTF(10000, 1.5, {1}) = {10000} -trc=smpte428 EOTF(48.024, 0.024012, {0.0925519, 0.0967033, 0.0949939}) = {0.11771, 0.144579 0.132798}, expected Y=0.140000 -trc=smpte428 EOTF(48.024, 0.024012, {0.185348, 0.193407, 0.189988}) = {0.606907, 0.754996 0.689089}, expected Y=0.750000 -trc=smpte428 EOTF(48.024, 0.024012, {0.2779, 0.29011, 0.284982}) = {1.69956, 2.12172 1.93462}, expected Y=2.120000 -trc=smpte428 EOTF(48.024, 0.024012, {0.370696, 0.386813, 0.379976}) = {3.57084, 4.45587 4.0618}, expected Y=4.450000 -trc=smpte428 EOTF(48.024, 0.024012, {0.463248, 0.483516, 0.474969}) = {6.35753, 7.94085 7.23777}, expected Y=7.940000 -trc=smpte428 EOTF(48.024, 0.024012, {0.5558, 0.58022, 0.569963}) = {10.1955, 12.7421 11.6133}, expected Y=12.740000 -trc=smpte428 EOTF(48.024, 0.024012, {0.648596, 0.676923, 0.664957}) = {15.2212, 19.0123 17.3275}, expected Y=19.010000 -trc=smpte428 EOTF(48.024, 0.024012, {0.741148, 0.773626, 0.759951}) = {21.5223, 26.8938 24.5101}, expected Y=26.890000 -trc=smpte428 EOTF(48.024, 0.024012, {0.833944, 0.87033, 0.854945}) = {29.2401, 36.5213 33.284}, expected Y=36.520000 -trc=smpte428 EOTF(48.024, 0.024012, {0.926496, 0.967033, 0.949939}) = {38.4361, 48.0228 43.7656}, expected Y=48.020000 +trc=smpte428 EOTF(48.024, 0.024012, {0.0925519, 0.0967033, 0.0949939}) = {0.13158, 0.144579 0.139116}, expected Y=0.140000 +trc=smpte428 EOTF(48.024, 0.024012, {0.185348, 0.193407, 0.189988}) = {0.678424, 0.754996 0.721874}, expected Y=0.750000 +trc=smpte428 EOTF(48.024, 0.024012, {0.2779, 0.29011, 0.284982}) = {1.89984, 2.12172 2.02667}, expected Y=2.120000 +trc=smpte428 EOTF(48.024, 0.024012, {0.370696, 0.386813, 0.379976}) = {3.99162, 4.45587 4.25505}, expected Y=4.450000 +trc=smpte428 EOTF(48.024, 0.024012, {0.463248, 0.483516, 0.474969}) = {7.10669, 7.94085 7.58213}, expected Y=7.940000 +trc=smpte428 EOTF(48.024, 0.024012, {0.5558, 0.58022, 0.569963}) = {11.3969, 12.7421 12.1659}, expected Y=12.740000 +trc=smpte428 EOTF(48.024, 0.024012, {0.648596, 0.676923, 0.664957}) = {17.0149, 19.0123 18.1519}, expected Y=19.010000 +trc=smpte428 EOTF(48.024, 0.024012, {0.741148, 0.773626, 0.759951}) = {24.0585, 26.8938 25.6763}, expected Y=26.890000 +trc=smpte428 EOTF(48.024, 0.024012, {0.833944, 0.87033, 0.854945}) = {32.6857, 36.5213 34.8675}, expected Y=36.520000 +trc=smpte428 EOTF(48.024, 0.024012, {0.926496, 0.967033, 0.949939}) = {42.9653, 48.0228 45.8478}, expected Y=48.020000 trc=arib-std-b67 EOTF(50, 0, {0}) = {0} trc=arib-std-b67 EOTF(50, 0, {0.1}) = {0.166667} trc=arib-std-b67 EOTF(50, 0, {0.2}) = {0.666667} -- To stop receiving notification emails like this one, please contact [email protected]. _______________________________________________ ffmpeg-cvslog mailing list -- [email protected] To unsubscribe send an email to [email protected]
