PR #25340 opened by Daniel Brodie (danielbrodie) URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/25340 Patch URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/25340.patch
# Summary of changes `(x << 4) | (x & 0xF)` repeats the low nibble when widening the 8-bit chroma endpoints to 12 bits. `(x << 4) | (x >> 4)` replicates the high bits, as #23791 does for alpha. Measured against the 16-bit source each file was encoded from (exported by Notch's After Effects plugin, 1280x720, every 5th of 300 frames), converted to RGB with swscale's default conversion: | file | before R/G/B (dB) | after R/G/B (dB) | TouchDesigner R/G/B (dB) | |---|---|---|---| | flat color, Best, no alpha (with the #25281 fix so it decodes) | 52.9 / 58.1 / 51.5 | 57.6 / 63.4 / 55.5 | 57.7 / 63.5 / 55.4 | | gradient with alpha matte, Optimal | 50.5 / 55.6 / 48.7 | 51.9 / 57.2 / 50.2 | 52.3 / 58.1 / 52.4 | On the first file this closes the gap to TouchDesigner. On the second a gap of 0.4 / 1.0 / 2.2 dB remains; I don't know its cause. make fate (Windows, MSYS2 MINGW64, full fate-suite): the 15 failures also fail on unpatched master. This conflicts with #23791 in context lines only; I can rebase on whichever lands first. AI disclosure: AI was used for investigation and development of this patch. >From 8e895910e109b56276a9a7706dbdc3a92a51ceb5 Mon Sep 17 00:00:00 2001 From: Daniel Brodie <[email protected]> Date: Wed, 21 Oct 2026 14:43:03 -0400 Subject: [PATCH] avcodec/notchlc: replicate the high bits when widening chroma endpoints (x << 4) | (x & 0xF) repeats the low nibble, so 8-bit chroma endpoints land up to 15 codes off on the 12-bit scale. (x << 4) | (x >> 4) is bit replication and maps 0..255 exactly onto 0..4095, matching the alpha expansion. Signed-off-by: Daniel Brodie <[email protected]> --- libavcodec/notchlc.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/libavcodec/notchlc.c b/libavcodec/notchlc.c index 396089254e6..3a7c700cc3c 100644 --- a/libavcodec/notchlc.c +++ b/libavcodec/notchlc.c @@ -376,10 +376,10 @@ static int decode_blocks(AVCodecContext *avctx, AVFrame *p, u1 = bytestream2_get_byte(&dgb); v1 = bytestream2_get_byte(&dgb); loc = bytestream2_get_le32(&dgb); - u0 = (u0 << 4) | (u0 & 0xF); - v0 = (v0 << 4) | (v0 & 0xF); - u1 = (u1 << 4) | (u1 & 0xF); - v1 = (v1 << 4) | (v1 & 0xF); + u0 = (u0 << 4) | (u0 >> 4); + v0 = (v0 << 4) | (v0 >> 4); + u1 = (u1 << 4) | (u1 >> 4); + v1 = (v1 << 4) | (v1 >> 4); udif = u1 - u0; vdif = v1 - v0; @@ -404,10 +404,10 @@ static int decode_blocks(AVCodecContext *avctx, AVFrame *p, u1 = bytestream2_get_byte(&dgb); v1 = bytestream2_get_byte(&dgb); loc = bytestream2_get_le32(&dgb); - u0 = (u0 << 4) | (u0 & 0xF); - v0 = (v0 << 4) | (v0 & 0xF); - u1 = (u1 << 4) | (u1 & 0xF); - v1 = (v1 << 4) | (v1 & 0xF); + u0 = (u0 << 4) | (u0 >> 4); + v0 = (v0 << 4) | (v0 >> 4); + u1 = (u1 << 4) | (u1 >> 4); + v1 = (v1 << 4) | (v1 >> 4); udif = u1 - u0; vdif = v1 - v0; @@ -431,10 +431,10 @@ static int decode_blocks(AVCodecContext *avctx, AVFrame *p, u1 = bytestream2_get_byte(&dgb); v1 = bytestream2_get_byte(&dgb); loc = bytestream2_get_le32(&dgb); - u0 = (u0 << 4) | (u0 & 0xF); - v0 = (v0 << 4) | (v0 & 0xF); - u1 = (u1 << 4) | (u1 & 0xF); - v1 = (v1 << 4) | (v1 & 0xF); + u0 = (u0 << 4) | (u0 >> 4); + v0 = (v0 << 4) | (v0 >> 4); + u1 = (u1 << 4) | (u1 >> 4); + v1 = (v1 << 4) | (v1 >> 4); udif = u1 - u0; vdif = v1 - v0; -- 2.54.0 _______________________________________________ ffmpeg-devel mailing list -- [email protected] To unsubscribe send an email to [email protected]
