Opened 5 years ago

Closed 5 years ago

Last modified 5 years ago

#8056 closed defect (duplicate)

Convert BMP/JPG to YUV420p video color shift, but not PNG

Reported by: fireattack Owned by:
Priority: normal Component: undetermined
Version: unspecified Keywords:
Cc: rwijnsma@xs4all.nl Blocked By:
Blocking: Reproduced by developer: no
Analyzed by developer: no

Description

Summary of the bug:

The color become slightly yellow when converting 24-bit BMP to limited range video (YUV420p).

255,255,255 will become 252,254,252 or similar.

Not reproducible with pixel-exact png file (also attached).
Not reproducible with yuvj420p

How to reproduce:

F:\sync\Personal research\!视频\ffmpeg color bug>ffmpeg -loop 1 -i bmp.bmp -vf scale=out_color_matrix=bt709 -color_primaries 1 -co
lor_trc 1 -colorspace 1 -t 30 -pix_fmt yuv420p -y -report bmp.mp4
ffmpeg started on 2019-08-03 at 04:33:18
Report written to "ffmpeg-20190803-043318.log"
ffmpeg version N-94433-gf60b1211b2 Copyright (c) 2000-2019 the FFmpeg developers
  built with gcc 9.1.1 (GCC) 20190716
  configuration: --enable-gpl --enable-version3 --enable-sdl2 --enable-fontconfig --enable-gnutls --enable-iconv --enable-libass -
-enable-libdav1d --enable-libbluray --enable-libfreetype --enable-libmp3lame --enable-libopencore-amrnb --enable-libopencore-amrwb
 --enable-libopenjpeg --enable-libopus --enable-libshine --enable-libsnappy --enable-libsoxr --enable-libtheora --enable-libtwolam
e --enable-libvpx --enable-libwavpack --enable-libwebp --enable-libx264 --enable-libx265 --enable-libxml2 --enable-libzimg --enabl
e-lzma --enable-zlib --enable-gmp --enable-libvidstab --enable-libvorbis --enable-libvo-amrwbenc --enable-libmysofa --enable-libsp
eex --enable-libxvid --enable-libaom --enable-libmfx --enable-amf --enable-ffnvcodec --enable-cuvid --enable-d3d11va --enable-nven
c --enable-nvdec --enable-dxva2 --enable-avisynth --enable-libopenmpt
  libavutil      56. 32.100 / 56. 32.100
  libavcodec     58. 55.100 / 58. 55.100
  libavformat    58. 30.100 / 58. 30.100
  libavdevice    58.  9.100 / 58.  9.100
  libavfilter     7. 58.100 /  7. 58.100
  libswscale      5.  6.100 /  5.  6.100
  libswresample   3.  6.100 /  3.  6.100
  libpostproc    55.  6.100 / 55.  6.100
[bmp_pipe @ 0000000000383100] Stream #0: not enough frames to estimate rate; consider increasing probesize
Input #0, bmp_pipe, from 'bmp.bmp':
  Duration: N/A, bitrate: N/A
    Stream #0:0: Video: bmp, bgr24, 1920x1080, 25 tbr, 25 tbn, 25 tbc
Stream mapping:
  Stream #0:0 -> #0:0 (bmp (native) -> h264 (libx264))
Press [q] to stop, [?] for help
[libx264 @ 0000000000386c40] using cpu capabilities: MMX2 SSE2Fast SSSE3 SSE4.2 AVX FMA3 BMI2 AVX2
[libx264 @ 0000000000386c40] profile High, level 4.0, 4:2:0, 8-bit
[libx264 @ 0000000000386c40] 264 - core 158 r2984 3759fcb - H.264/MPEG-4 AVC codec - Copyleft 2003-2019 - http://www.videolan.org/
x264.html - options: cabac=1 ref=3 deblock=1:0:0 analyse=0x3:0x113 me=hex subme=7 psy=1 psy_rd=1.00:0.00 mixed_ref=1 me_range=16 c
hroma_me=1 trellis=1 8x8dct=1 cqm=0 deadzone=21,11 fast_pskip=1 chroma_qp_offset=-2 threads=6 lookahead_threads=1 sliced_threads=0
 nr=0 decimate=1 interlaced=0 bluray_compat=0 constrained_intra=0 bframes=3 b_pyramid=2 b_adapt=1 b_bias=0 direct=1 weightb=1 open
_gop=0 weightp=2 keyint=250 keyint_min=25 scenecut=40 intra_refresh=0 rc_lookahead=40 rc=crf mbtree=1 crf=23.0 qcomp=0.60 qpmin=0
qpmax=69 qpstep=4 ip_ratio=1.40 aq=1:1.00
Output #0, mp4, to 'bmp.mp4':
  Metadata:
    encoder         : Lavf58.30.100
    Stream #0:0: Video: h264 (libx264) (avc1 / 0x31637661), yuv420p(bt709), 1920x1080, q=-1--1, 25 fps, 12800 tbn, 25 tbc
    Metadata:
      encoder         : Lavc58.55.100 libx264
    Side data:
      cpb: bitrate max/min/avg: 0/0/0 buffer size: 0 vbv_delay: -1
frame=  750 fps= 75 q=-1.0 Lsize=      64kB time=00:00:29.88 bitrate=  17.5kbits/s speed=2.98x
video:54kB audio:0kB subtitle:0kB other streams:0kB global headers:0kB muxing overhead: 17.723938%
[libx264 @ 0000000000386c40] frame I:3     Avg QP:12.00  size:   670
[libx264 @ 0000000000386c40] frame P:189   Avg QP:14.11  size:    77
[libx264 @ 0000000000386c40] frame B:558   Avg QP:18.33  size:    68
[libx264 @ 0000000000386c40] consecutive B-frames:  0.8%  0.0%  0.0% 99.2%
[libx264 @ 0000000000386c40] mb I  I16..4:  2.0% 98.0%  0.0%
[libx264 @ 0000000000386c40] mb P  I16..4:  0.0%  0.0%  0.0%  P16..4:  0.0%  0.0%  0.0%  0.0%  0.0%    skip:100.0%
[libx264 @ 0000000000386c40] mb B  I16..4:  0.0%  0.0%  0.0%  B16..8:  0.0%  0.0%  0.0%  direct: 0.0%  skip:100.0%  L0: 0.0% L1:10
0.0% BI: 0.0%
[libx264 @ 0000000000386c40] 8x8 transform intra:97.8%
[libx264 @ 0000000000386c40] coded y,uvDC,uvAC intra: 0.0% 0.0% 0.0% inter: 0.0% 0.0% 0.0%
[libx264 @ 0000000000386c40] i16 v,h,dc,p:  0% 78% 22%  0%
[libx264 @ 0000000000386c40] i8 v,h,dc,ddl,ddr,vr,hd,vl,hu:  0% 67% 33%  0%  0%  0%  0%  0%  0%
[libx264 @ 0000000000386c40] i4 v,h,dc,ddl,ddr,vr,hd,vl,hu:  0% 72% 28%  0%  0%  0%  0%  0%  0%
[libx264 @ 0000000000386c40] i8c dc,h,v,p: 98%  1%  0%  0%
[libx264 @ 0000000000386c40] Weighted P-Frames: Y:0.0% UV:0.0%
[libx264 @ 0000000000386c40] kb/s:14.61

Patches should be submitted to the ffmpeg-devel mailing list and not this bug tracker.

Attachments (3)

png.png (22.5 KB ) - added by fireattack 5 years ago.
png image (no issue)
bmp.bmp.7z (1.1 KB ) - added by fireattack 5 years ago.
bmp sample file (compressed)
colortest_hd.7z (23.5 KB ) - added by fireattack 5 years ago.
To test the color range and bt601/709 conversion

Download all attachments as: .zip

Change History (10)

by fireattack, 5 years ago

Attachment: png.png added

png image (no issue)

by fireattack, 5 years ago

Attachment: bmp.bmp.7z added

bmp sample file (compressed)

comment:1 by fireattack, 5 years ago

Summary: Convert BMP to YUV420p video color shift, but not PNGConvert BMP/JPG to YUV420p video color shift, but not PNG

This bug also happens to JPG.

And the video encoding method doesn't seem to matter, tried HEVC, same result.

comment:2 by CoRoNe, 5 years ago

Cc: rwijnsma@xs4all.nl added

I'm not an expert in this field of work, but I can confirm the "yellowness" (if it's really a bug).

While 'png.png' is marked as rgb24(pc) (full range), 'bmp.bmp' is marked as just bgr24 (no range set). So apparently you have to convert to full range yourself.

https://ffmpeg.org/ffmpeg-all.html#Codec-Options:

color_range integer (decoding/encoding,video)
If used as input parameter, it serves as a hint to the decoder, which color_range the input has.

ffmpeg -loop 1 -color_range pc -i bmp.bmp -t 10 -pix_fmt yuv420p -preset ultrafast bmp.mp4

With -color_range pc 'bmp.bmp' is now marked as bgr24(pc), but the "bmp decoder" seems to be ignorant of this hint, because 'bmp.mp4' is still 252,255,252 (#FCFFFC).

What does work which I found out:

ffmpeg -loop 1 -i bmp.bmp -t 10 -vf scale=out_range=pc -pix_fmt yuv420p -preset ultrafast bmp.mp4
ffmpeg -loop 1 -i bmp.bmp -t 10 -vf colorspace=iall=bt709:all=bt709:format=yuv420p -preset ultrafast bmp.mp4

(I noticed the first command to be twice as fast than the second)

Btw, there's no need for intermediate files. You can use FFplay:

ffplay -f lavfi color=white:s=1280x720,format=bgr24,format=yuv420p                      # 252,255,252 (#FCFFFC)
ffplay -f lavfi color=white:s=1280x720,format=rgb24,format=yuv420p                      # 255,255,255 (#FFFFFF)
ffplay -f lavfi color=white:s=1280x720,format=bgr24,scale=out_range=pc,format=yuv420p   # 255,255,255 (#FFFFFF)

comment:3 by Carl Eugen Hoyos, 5 years ago

Resolution: duplicate
Status: newclosed

Looks like a duplicate of ticket #979.

by fireattack, 5 years ago

Attachment: colortest_hd.7z added

To test the color range and bt601/709 conversion

comment:4 by fireattack, 5 years ago

CoRoNe, thank you very much for your help!
But your commands don't work well.

The first one,

ffmpeg -loop 1 -i bmp.bmp -t 10 -vf scale=out_range=pc -pix_fmt yuv420p -preset ultrafast bmp.mp4

Will clip the color range (instead of properly convert it), means colors between 236-255 will all become white.

The second one,

ffmpeg -loop 1 -i bmp.bmp -t 10 -vf colorspace=iall=bt709:all=bt709:format=yuv420p -preset ultrafast bmp.mp4

does NOT use/convert to BT.709 properly, means pure red (255,0,0) will become 255,24,0.

Please use the newly attached test image to test.

I tried to improve it, but I can't seem to make it work with only colorspace filter.

Version 2, edited 5 years ago by fireattack (previous) (next) (diff)

comment:5 by CoRoNe, 5 years ago

Will clip the color range (instead of properly convert it), means colors between 236-255 will all crush to pure white.

I only tested the samples you provided, the color white. I haven't looked at other colors.

I suppose it is because we moved rgb->yuv conversion to colorspace filter from the problematic swscale

Who's we? Are you a FFmpeg developer?

Is this issue really 8 years old already? In all those years not a single FFmpeg coder was able to fix this?!

comment:6 by pdr0, 5 years ago

It's been "fixed" a long time ago with the proper flags. It's just not well documented

The popular way to do it these days is zscale . Format comes last in the filter chain, the earlier flags get passed to it

ffmpeg -i colortest_hd.bmp -vf zscale=matrix=709,format=yuv420p -c:v libx264 -crf 18 -x264opts colormatrix=bt709 zscale709.mp4

It's a good practice to flag the colormatrix as 709 (doesn't affect the actual conversion, just metadata)

Acceptable rounding error for 8bit conversions should be +/-3 for YUV<=>RGB conversions

If using swscale, you need -sws_flags full_chroma_int+accurate_rnd to reduce the rounding errors (accurate_rnd is the important one)

ffmpeg -i colortest_hd.bmp -vf scale=out_color_matrix=bt709:flags=full_chroma_int+accurate_rnd,format=yuv420p -c:v libx264 -crf 18 -x264opts colormatrix=bt709 swscale709accurate_rnd.mp4

ffmpeg -i colortest_hd.bmp -vf scale=out_color_matrix=bt709,format=yuv420p -c:v libx264 -crf 18 -x264opts colormatrix=bt709 swscale709.mp4

As you see, "white" is 255,255,255 with the sws accurate_rnd flag, but discolored (252,255, 252) without.

Last edited 5 years ago by pdr0 (previous) (diff)

comment:7 by fireattack, 5 years ago

Thank you for your informative reply. These commands are definitely handy in future.

I think that swscale's bug (without flag) (#979) still should be fixed as it only happens to bgr24 but not rgb24, which means it isn't just an accuracy problem.

Note: See TracTickets for help on using tickets.