Opened 2 years ago
Last modified 22 months ago
#9751 new defect
Incorrect YUV->RGB24 conversion results on IBM Power9
Reported by: | gciaparrone | Owned by: | |
---|---|---|---|
Priority: | normal | Component: | swscale |
Version: | git-master | Keywords: | altivec |
Cc: | gciaparrone | Blocked By: | |
Blocking: | Reproduced by developer: | no | |
Analyzed by developer: | no |
Description (last modified by )
Converting a YUV frame into an RGB24 image seems to produce incorrect results on an IBM Power9 processor. Compiling ffmpeg with --disable-altivec solves the issue. The problem might be related to this old issue pointed out by Hong Bo Peng here: https://trac.ffmpeg.org/ticket/7124#comment:7
This can be more easily seen by converting a completely black image from RGB to YUV and then back to RGB on an IBM Power9 (or possibly on any Little Endian processor with ALTIVEC support?). The output image has all pixels set to [16, 16, 16] instead of [0, 0, 0]. The issue spans multiple versions of ffmpeg, including the current git master version. Using --disable-altivec or running the command on a non-ALTIVEC processor outputs the correct image with all [0, 0, 0] pixels.
Output image (AMD Ryzen 5 1600X processor):
Output image (IBM Power9, --disable-altivec):
How to reproduce:
# convert RGB image to YUV420p $ ffmpeg -i black.png -pix_fmt yuv420p black.yuv # convert it back to RGB $ ffmpeg -s:v 64x64 -pix_fmt yuv420p -i black.yuv -frames:v 1 -pix_fmt rgb24 reblack.png
Attachments (6)
Change History (14)
by , 2 years ago
comment:1 by , 2 years ago
Description: | modified (diff) |
---|
follow-up: 3 comment:2 by , 2 years ago
When you convert ffmpeg -i black.png -pix_fmt yuv420p black.yuv you get limited range data with Y set to 16 and Cb, Cb achromatic (128 for 8 bit, 12 bit per pixel yuv420p). Please attach that yuv file for IBM Power9.
When you convert back you are IMHO supposed to set input range and because it is somehow gbr use accurate_rnd.
ffmpeg -s:v 64x64 -pix_fmt yuv420p -i black.yuv -frames:v 1 -vf scale=in_range=tv:flags=accurate_rnd,format=rgb24 reblack1.png
Please test.
by , 2 years ago
Attachment: | reblack1.png added |
---|
Black image converted on IBM Power9 with TV color range setting
comment:3 by , 2 years ago
Replying to Balling:
When you convert ffmpeg -i black.png -pix_fmt yuv420p black.yuv you get limited range data with Y set to 16 and Cb, Cb achromatic (128 for 8 bit, 12 bit per pixel yuv420p). Please attach that yuv file for IBM Power9.
When you convert back you are IMHO supposed to set input range and because it is somehow gbr use accurate_rnd.
ffmpeg -s:v 64x64 -pix_fmt yuv420p -i black.yuv -frames:v 1 -vf scale=in_range=tv:flags=accurate_rnd,format=rgb24 reblack1.png
Please test.
Hi, even with the settings you provided I got the wrong pixels on IBM Power9. Please see the picture attached. Anyway, shouldn't running the exact same command on two different CPUs produce approximately the same result?
comment:4 by , 2 years ago
I attached the black.yuv file produced on the IBM Power9. It has indeed a limited range on Y. Converting that file to RGB using the standard Altivec-optimized version of ffmpeg produces a "limited range" RGB image, while running the exact command on the Power9 with an ffmpeg version compiled with --disable-altivec produces the correct black image.
So there is at least a mismatch in default settings for the two versions, or maybe the Altivec optimized version ignores the color range setting.
follow-up: 6 comment:5 by , 2 years ago
Try
ffmpeg -s:v 64x64 -pix_fmt yuv420p -i black.yuv -frames:v 1 -vf scale=in_range=tv:out_range=pc:flags=accurate_rnd,format=rgb24 reblack1.png
Also try
ffmpeg -s:v 64x64 -pix_fmt yuv420p -i black.yuv -frames:v 1 -vf zscale reblack1.png
For last command zimg should be compiled in.
Limited range RGB was prohibited in ffmpeg back in 2021, PNG does not support it anyway.
comment:6 by , 2 years ago
Replying to Balling:
Try
ffmpeg -s:v 64x64 -pix_fmt yuv420p -i black.yuv -frames:v 1 -vf scale=in_range=tv:out_range=pc:flags=accurate_rnd,format=rgb24 reblack1.png
This command keeps outputting the wrong image. But I have noticed something weird: the image is not entirely made of [16, 16, 16] pixels. There is a thin band on the bottom of the image with the correct pixels ([0, 0, 0]). This is the same as the reblack1.png I posted a few comments earlier.
Also try
ffmpeg -s:v 64x64 -pix_fmt yuv420p -i black.yuv -frames:v 1 -vf zscale reblack1.png
For last command zimg should be compiled in.
Limited range RGB was prohibited in ffmpeg back in 2021, PNG does not support it anyway.
I will try to recompile ffmpeg as soon as I can and test this out.
comment:7 by , 2 years ago
Using the command
ffmpeg -s:v 64x64 -pix_fmt yuv420p -i black.yuv -frames:v 1 -vf zscale reblack1.png
outputs an image identical to reblack_bad.png, so the problem persists. I think ffmpeg still re-routes the conversion to the swscale ALTIVEC-optimized code, since the command repeatedly prints
[swscaler @ 0x405049d0] [swscaler @ 0x40cae530] ALTIVEC: Color Space RGB24
comment:8 by , 22 months ago
Keywords: | altivec added |
---|
Original black image