#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
CoRoNe, thank you very much for your help!
As marked by cehoyos, the reason seems to be input rgb24 vs. bgr24, so color range is not an issue (the range conversion is already done with "-pix_fmt yuv420p").
Actually, your first command:
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 crush to pure white. I think it may not actually fix the yellowish issue.
The second one
ffmpeg -loop 1 -i bmp.bmp -t 10 -vf colorspace=iall=bt709:all=bt709:format=yuv420p -preset ultrafast bmp.mp4
does fix the color shift issue, I suppose it is because we moved rgb->yuv conversion to colorspace filter from the problematic swscale
I suppose?
But it does NOT convert from bgr24 to BT.709 properly, means pure red (255,0,0) in original will become 255,24,0 now. I tried to fix this, but I can't seem to make it work with colorspace filter.
I think you can fix it by changing to -vf colorspace=iall=bt601-6-625:all=bt709:format=yuv420p
If you want to do any further testing, please use the newly attached test image (I should use this sample image to begin with, but I want to highlight the yellow-ish issue with a pure white image).
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)