mirror of
https://github.com/fluxerapp/fluxer
synced 2026-10-07 19:22:14 +09:00
fix(media-proxy): stop lifting bt709 video thumbnails (#2443)
This commit is contained in:
@@ -58,6 +58,42 @@ fn video_thumbnail_accepts_bt470bg_pal_primaries() {
|
||||
assert_eq!(png_dimensions(&thumb.bytes), Some((320, 240)));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn a_bt709_thumbnail_keeps_the_source_shadow_luminance() {
|
||||
let Some(video) = ffmpeg_gen_media(
|
||||
"shadow.mkv",
|
||||
&[
|
||||
"-f",
|
||||
"lavfi",
|
||||
"-i",
|
||||
"color=c=0x181818:size=320x240:rate=10:duration=1",
|
||||
"-vf",
|
||||
"setparams=color_primaries=bt709:color_trc=bt709:colorspace=bt709:range=tv",
|
||||
"-pix_fmt",
|
||||
"yuv420p",
|
||||
"-c:v",
|
||||
"mpeg4",
|
||||
"-f",
|
||||
"matroska",
|
||||
],
|
||||
) else {
|
||||
eprintln!("skipping: ffmpeg CLI not available");
|
||||
return;
|
||||
};
|
||||
let thumb = extract_video_thumbnail(&video, OutputFormat::PNG, &test_media_limits())
|
||||
.expect("bt709 shadow video should thumbnail");
|
||||
let (_, _, pixels) = decode_rgba(&thumb.bytes);
|
||||
let luma: Vec<f64> = pixels
|
||||
.chunks_exact(4)
|
||||
.map(|p| 0.2126 * f64::from(p[0]) + 0.7152 * f64::from(p[1]) + 0.0722 * f64::from(p[2]))
|
||||
.collect();
|
||||
let mean = luma.iter().sum::<f64>() / luma.len() as f64;
|
||||
assert!(
|
||||
(mean - 24.0).abs() <= 8.0,
|
||||
"a bt709 source must not be lifted by a transfer conversion: mean luminance {mean}"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn video_thumbnail_accepts_every_widened_sdr_transfer() {
|
||||
let transfers = ["smpte240m", "linear", "iec61966-2-1", "bt470m", "bt470bg"];
|
||||
|
||||
@@ -4,11 +4,9 @@
|
||||
|
||||
enum ff_sdr_transfer {
|
||||
FF_SDR_TRANSFER_SRGB = 0,
|
||||
FF_SDR_TRANSFER_BT709 = 1,
|
||||
FF_SDR_TRANSFER_LINEAR = 2,
|
||||
FF_SDR_TRANSFER_LINEAR = 1,
|
||||
};
|
||||
|
||||
static uint8_t ff_bt709_to_srgb_lut[256];
|
||||
static uint8_t ff_linear_to_srgb_lut[256];
|
||||
static pthread_once_t ff_transfer_lut_once = PTHREAD_ONCE_INIT;
|
||||
|
||||
@@ -25,18 +23,12 @@ static uint8_t ff_encode_srgb_byte(double linear) {
|
||||
static void ff_initialize_transfer_luts(void) {
|
||||
for (int index = 0; index < 256; index++) {
|
||||
double encoded = (double)index / 255.0;
|
||||
double linear = encoded < 0.081
|
||||
? encoded / 4.5
|
||||
: pow((encoded + 0.099) / 1.099, 1.0 / 0.45);
|
||||
ff_bt709_to_srgb_lut[index] = ff_encode_srgb_byte(linear);
|
||||
ff_linear_to_srgb_lut[index] = ff_encode_srgb_byte(encoded);
|
||||
}
|
||||
}
|
||||
|
||||
static const uint8_t *ff_transfer_to_srgb_lut(enum ff_sdr_transfer transfer) {
|
||||
switch (transfer) {
|
||||
case FF_SDR_TRANSFER_BT709:
|
||||
return ff_bt709_to_srgb_lut;
|
||||
case FF_SDR_TRANSFER_LINEAR:
|
||||
return ff_linear_to_srgb_lut;
|
||||
default:
|
||||
@@ -89,7 +81,7 @@ static int ff_frame_sdr_transfer(
|
||||
case AVCOL_TRC_BT709:
|
||||
case AVCOL_TRC_SMPTE170M:
|
||||
case AVCOL_TRC_SMPTE240M:
|
||||
*out_transfer = FF_SDR_TRANSFER_BT709;
|
||||
*out_transfer = FF_SDR_TRANSFER_SRGB;
|
||||
return 0;
|
||||
case AVCOL_TRC_LINEAR:
|
||||
*out_transfer = FF_SDR_TRANSFER_LINEAR;
|
||||
|
||||
Reference in New Issue
Block a user