Opened 10 years ago
Last modified 3 years ago
#3801 open defect
SWSCALE: Incorrect Values (+-1) in Full Range Conversion RGB to YCbCr
Reported by: | troy_s | Owned by: | |
---|---|---|---|
Priority: | normal | Component: | undetermined |
Version: | unspecified | Keywords: | range |
Cc: | Blocked By: | ||
Blocking: | Reproduced by developer: | no | |
Analyzed by developer: | no |
Description
Summary of the bug:
FFMPEG is potentially delivering values that deviate from theoretical results in RGB to YCbCr conversions. This case applies to RGB to full range YCbCr conversion, using REC.709 coefficients on the input.
./ffmpeg -i ~/Documents/FFMPEG\ Color\ Research/ARIB_STD-B28.png -pix_fmt yuv444p -vcodec rawvideo -f rawvideo -vf scale="in_range=full:in_color_matrix=bt709:out_range=full:out_color_matrix=bt709" test-full.yuv ffmpeg version N-64958-gce8e27e Copyright (c) 2000-2014 the FFmpeg developers built on Jul 24 2014 10:54:07 with gcc 4.7 (Ubuntu/Linaro 4.7.3-12ubuntu1) configuration: --enable-gpl --enable-libx264 --enable-shared --disable-static --enable-pic WARNING: library configuration mismatch avutil configuration: --enable-gpl --enable-libx264 --disable-asm --enable-shared --disable-static --enable-pic avcodec configuration: --enable-gpl --enable-libx264 --disable-asm --enable-shared --disable-static --enable-pic avformat configuration: --enable-gpl --enable-libx264 --disable-asm --enable-shared --disable-static --enable-pic avdevice configuration: --enable-gpl --enable-libx264 --disable-asm --enable-shared --disable-static --enable-pic avfilter configuration: --enable-gpl --enable-libx264 --disable-asm --enable-shared --disable-static --enable-pic swscale configuration: --enable-gpl --enable-libx264 --disable-asm --enable-shared --disable-static --enable-pic swresample configuration: --enable-gpl --enable-libx264 --disable-asm --enable-shared --disable-static --enable-pic postproc configuration: --enable-gpl --enable-libx264 --disable-asm --enable-shared --disable-static --enable-pic libavutil 52. 92.101 / 52. 92.101 libavcodec 55. 69.100 / 55. 69.100 libavformat 55. 49.100 / 55. 49.100 libavdevice 55. 13.102 / 55. 13.102 libavfilter 4. 11.102 / 4. 11.102 libswscale 2. 6.100 / 2. 6.100 libswresample 0. 19.100 / 0. 19.100 libpostproc 52. 3.100 / 52. 3.100 Input #0, image2, from '/home/aphorism/Documents/FFMPEG Color Research/ARIB_STD-B28.png': Duration: 00:00:00.04, start: 0.000000, bitrate: N/A Stream #0:0: Video: png, rgb24, 1920x1080 [SAR 2835:2835 DAR 16:9], 25 tbr, 25 tbn, 25 tbc Output #0, rawvideo, to 'test-full.yuv': Metadata: encoder : Lavf55.49.100 Stream #0:0: Video: rawvideo (444P / 0x50343434), yuv444p, 1920x1080 [SAR 1:1 DAR 16:9], q=2-31, 200 kb/s, 25 fps, 25 tbn, 25 tbc Metadata: encoder : Lavc55.69.100 rawvideo Stream mapping: Stream #0:0 -> #0:0 (png (native) -> rawvideo (native)) Press [q] to stop, [?] for help frame= 1 fps=0.0 q=0.0 Lsize= 6075kB time=00:00:00.04 bitrate=1244160.0kbits/s video:6075kB audio:0kB subtitle:0kB other streams:0kB global headers:0kB muxing overhead: 0.000000%
The above command delivers the attachment test-full-444-out.png, with Y, Cb, and Cr a pure dump of the results into the R, G, and B channels of the image. No color transformations have been applied.
The file ARIB_STD-B28.png is an 8 bit representation of a SMPTE test pattern, based off of a 32 bit float version.
The file ARIB_STD-B28_YCbCr_full.png is a theoretically correct transformation of the ARIB_STD-B28.png test pattern into YCbCr using REC.709 coefficients. It is based off of a 32 bit EXR input.
The file test-full-diff.png is a heat-map difference, with red areas indicating deviations between the theoretical results and the actual.
The SMPTE test pattern black set test stripes at the very bottom contain one stripe that sources at -2%, and as such, will always be incorrect unless float values are provided for input. As such, it is the single bar that can be ignored.
Potentially Related Issues:
https://trac.ffmpeg.org/ticket/3794
Attachments (6)
Change History (18)
by , 10 years ago
Attachment: | ARIB_STD-B28_YCbCr_full.png added |
---|
by , 10 years ago
Attachment: | test-full-444-out.png added |
---|
Output of FFMPEG, with the raw YCbCr values packed into the RGB channels of a PNG with no color transformations applied.
by , 10 years ago
Attachment: | test-full-diff.png added |
---|
A visual difference between the 8 bit SMPTE input versus theoretical and FFMPEG YCbCr output.
comment:1 by , 10 years ago
Keywords: | range added |
---|
comment:2 by , 10 years ago
Resolution: | → invalid |
---|---|
Status: | new → closed |
The 2 png images are nearly identical, i see some +-1 differences from different rounding, which is clearly not what was meant in this bug, though if our rounding is suboptimal then such suboptmal rounding of course would be a bug that iam interrested in.
The big vissible color difference is a fault in how the file was created, one of the pngs has a gamma of 1.0 the other does not. firefox displays them quite differently, other software shows them nearly identical, ignoring gamma i assume
xview, displays this difference:
ARIB_STD-B28_YCbCr_full.png is 1920x1080 PNG image, color type RGB, 8 bit
test-full-444-out.png is 1920x1080 PNG image, color type RGB, 8 bit, file gamma 1.0000
Also the difference png shows massive differences in areas that are bit exactly identical
comment:3 by , 10 years ago
The rounding is the issue, and I can assure you that all of the values per channel were encoded 1:1.
The reason a gamma of 1.0 was assigned is likely due to that being required to prevent the PNG color mangling.
I could provide raw files, but that is vastly less easy to diagnose.
comment:4 by , 10 years ago
Resolution: | invalid |
---|---|
Status: | closed → reopened |
Summary: | SWSCALE: Incorrect Values in Full Range Conversion RGB to YCbCr → SWSCALE: Incorrect Values (+-1) in Full Range Conversion RGB to YCbCr |
by , 10 years ago
Attachment: | ARIB_STD-B28_YCbCr_full.yuv.bz2 added |
---|
rawvideo YCbCr reference based on png
comment:5 by , 10 years ago
ffmpeg output vs. the reference:
stddev: 0.39 PSNR: 56.28 MAXDIFF: 1 bytes: 6220800/ 6220800
comment:6 by , 4 years ago
Well, you know what. First of all, you must have specified that the file should be opened with ffplay -video_size 1920x1080 -pixel_format yuvj444p -f rawvideo -i ARIB_STD-B28_YCbCr_full.yuv -vf scale=in_color_matrix=bt709
Second of all, it uses range full YCbCr values, as can be checked using
ffplay -video_size 1920x1080 -pixel_format yuv444p -f rawvideo -i ARIB_STD-B28_YCbCr_full.yuv -vf extractplanes=y (see black that is 0 in Y).
Here it does not matter yuvj444p or yuv444p we are using, BTW!
That is why "contain one stripe that sources at -2%" will be just not included for full range.
But ARIB B28 never specified full range YCbCr format... Just like SMPTE RP 219. Also looks like the 100 red and blue are not actually 100% or it is just a bug somewhere... They are RGB 254, not 255.
comment:7 by , 4 years ago
Right, so test-full-444-out.png has 1.0 gAMA png chunk. How beautiful. You know that Photoshop, Paint (and GIMP until my fixes) and FFmpeg do not support gAMA or cHRM chunks? While Chrome, Mozilla and Windows photo viewer do support it? Let me guess, considering your ramp from 0 to 255 uses 186 as Cb=Cr with applying gAMA, gAMA of 1.0 is actually NOT CORRECT, because without applying it (and falling back to sRGB) it will be 128 for Cb=Cr??? WTF. Are you serious right now? Okay, whatever. P.S. test-full-diff.png also has 1.0 gAMA.
That means you do not understand PNG spec or gAMA/EOTF too. Wow, just wow.
exiftool test-full-444-out.png
Color Type : RGB
Compression : Deflate/Inflate
Filter : Adaptive
Interlace : Noninterlaced
Gamma : 1
Background Color : 255 255 255
Pixels Per Unit X : 72
Pixels Per Unit Y : 72
Pixel Units : Unknown
So I need to remove gAMA with pngcrush -m 3 -rem gAMA:
by , 4 years ago
Attachment: | test-full-444-out-no-gAMA.png added |
---|
comment:8 by , 4 years ago
Status: | reopened → open |
---|
And here are first results. ffplay -video_size 1920x1080 -pixel_format yuv444p -f rawvideo -i ARIB_STD-B28_YCbCr_full.yuv -vf extractplanes=y
shows that 75% Cyan is 151, 149, 32 while it should be (at least according to you) as in png 150, 150, 32, NICE! Next, 75% blue is supposed to be 14, 224, 119 but it is 14, 223, 119 (DAH). Next: 75 % magenta is supposed to be 54, 202, 215 but actually it is 54, 201, 214.
Next 100% Red is supposed to be 54, 99, 255 but it is actually 54, 98, 255 (which causes that 254 issue).
100% yellow is supposed to be 237, 0, 140 but is actually 237, 0, 139 (again, 254 issue).
And finally 75% yellow is supposed to be 177, 32, 137 but it is actually 177, 32, 136.
comment:9 by , 4 years ago
These are all good on modern ffmpeg even without any magic whatsover. I would say that
a) mpv says there is out-of-gamut stuff even though there should be none (maybe your png is wrong and then ffmpeg encoder is wrong too, or there is another bug in --gamut-warning of mpv, not the first time)
b) decoder in ffmpeg is pretty bad (not that can be fixed, since not only 75% R'G'B' colors can be encoded as such), but encoder is perfect, all issues in comment above this are fixed
ffmpeg -y -t 4 -loop 1 -i ARIB_STD-B28.png -vf scale=out_color_matrix=bt709:out_range=pc -color_range 2 -color_primaries bt709 -color_trc iec61966_2_1 -colorspace bt709 8.mp4
comment:10 by , 3 years ago
Apparently all that SMPTE pattern stuff is popular, see #7249.
Does anybody has ideas on the decoder and whether it should be hardcoded for those values? mpv should be fixed too.
comment:11 by , 3 years ago
See bug in mpv: https://github.com/mpv-player/mpv/issues/9757
As for b) I believe that there is at least a problem that one should use most saturated colors when decoding. Indeed, otherwise that would be that 255, 255, 0 is not achievable, which is just hilarious. And it looks like a bug in ffmpeg.
comment:12 by , 3 years ago
Actually, now that I think about it, you can still get the 255, 255, 0 color by doing some out-of-gamut magic. So I suppose all is correct here. It is also very cool to note that 8 bit YCbCr RP 219 pattern is not more often correct. For example on this video. https://youtu.be/k5tcHp1kBmQ (0:21 time.)
A full range theoretical transformed version of the SMPTE test chart.