Opened 10 years ago

Last modified 2 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)

ARIB_STD-B28_YCbCr_full.png (30.9 KB ) - added by troy_s 10 years ago.
A full range theoretical transformed version of the SMPTE test chart.
ARIB_STD-B28.png (30.7 KB ) - added by troy_s 10 years ago.
An 8 bit input SMPTE test chart.
test-full-444-out.png (8.8 KB ) - added by troy_s 10 years ago.
Output of FFMPEG, with the raw YCbCr values packed into the RGB channels of a PNG with no color transformations applied.
test-full-diff.png (14.4 KB ) - added by troy_s 10 years ago.
A visual difference between the 8 bit SMPTE input versus theoretical and FFMPEG YCbCr output.
ARIB_STD-B28_YCbCr_full.yuv.bz2 (2.5 KB ) - added by Michael Niedermayer 10 years ago.
rawvideo YCbCr reference based on png
test-full-444-out-no-gAMA.png (8.7 KB ) - added by Balling 3 years ago.

Download all attachments as: .zip

Change History (18)

by troy_s, 10 years ago

Attachment: ARIB_STD-B28_YCbCr_full.png added

A full range theoretical transformed version of the SMPTE test chart.

by troy_s, 10 years ago

Attachment: ARIB_STD-B28.png added

An 8 bit input SMPTE test chart.

by troy_s, 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 troy_s, 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 Carl Eugen Hoyos, 10 years ago

Keywords: range added

comment:2 by Michael Niedermayer, 10 years ago

Resolution: invalid
Status: newclosed

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 troy_s, 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 Michael Niedermayer, 10 years ago

Resolution: invalid
Status: closedreopened
Summary: SWSCALE: Incorrect Values in Full Range Conversion RGB to YCbCrSWSCALE: Incorrect Values (+-1) in Full Range Conversion RGB to YCbCr

by Michael Niedermayer, 10 years ago

rawvideo YCbCr reference based on png

comment:5 by Michael Niedermayer, 10 years ago

ffmpeg output vs. the reference:
stddev: 0.39 PSNR: 56.28 MAXDIFF: 1 bytes: 6220800/ 6220800

comment:6 by Balling, 3 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.

Last edited 3 years ago by Balling (previous) (diff)

comment:7 by Balling, 3 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:

Last edited 2 years ago by Balling (previous) (diff)

by Balling, 3 years ago

comment:8 by Balling, 3 years ago

Status: reopenedopen

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 Balling, 3 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

Last edited 3 years ago by Balling (previous) (diff)

comment:10 by Balling, 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 Balling, 2 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 Balling, 2 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, no bug. It is also very cool to note that 8 bit YCbCr RP 219 pattern is now more often correct. For example on this video. https://youtu.be/k5tcHp1kBmQ (0:21 time.)

Last edited 2 years ago by Balling (previous) (diff)
Note: See TracTickets for help on using tickets.