#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)
Change History (10)
by , 5 years ago
comment:1 by , 5 years ago
Summary: | Convert BMP to YUV420p video color shift, but not PNG → Convert 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 , 5 years ago
Cc: | 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 , 5 years ago
Resolution: | → duplicate |
---|---|
Status: | new → closed |
Looks like a duplicate of ticket #979.
by , 5 years ago
Attachment: | colortest_hd.7z added |
---|
To test the color range and bt601/709 conversion
comment:4 by , 5 years ago
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 have no idea what is the syntax of "colorspace=iall=bt709:all=bt709:format=yuv420p" part.
comment:5 by , 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 , 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.
comment:7 by , 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.
png image (no issue)