Opened 3 years ago

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

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.

Input image:
Original black image

Output image (IBM Power9):
Black image converted on a IBM Power9 processor

Output image (AMD Ryzen 5 1600X processor):
Black image converted on a AMD processor

Output image (IBM Power9, --disable-altivec):
Black image converted with --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)

black.png (173 bytes ) - added by gciaparrone 3 years ago.
Original black image
reblack.png (112 bytes ) - added by gciaparrone 3 years ago.
Black image converted with --disable-altivec
reblack_bad.png (173 bytes ) - added by gciaparrone 3 years ago.
Black image converted on a IBM Power9 processor
reblack_amd.png (112 bytes ) - added by gciaparrone 3 years ago.
Black image converted on a AMD processor
reblack1.png (172 bytes ) - added by gciaparrone 3 years ago.
Black image converted on IBM Power9 with TV color range setting
black.yuv (6.0 KB ) - added by gciaparrone 3 years ago.
YUV file output on IBM Power9

Download all attachments as: .zip

Change History (14)

by gciaparrone, 3 years ago

Attachment: black.png added

Original black image

by gciaparrone, 3 years ago

Attachment: reblack.png added

Black image converted with --disable-altivec

by gciaparrone, 3 years ago

Attachment: reblack_bad.png added

Black image converted on a IBM Power9 processor

by gciaparrone, 3 years ago

Attachment: reblack_amd.png added

Black image converted on a AMD processor

comment:1 by gciaparrone, 3 years ago

Description: modified (diff)

comment:2 by Balling, 3 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 gciaparrone, 3 years ago

Attachment: reblack1.png added

Black image converted on IBM Power9 with TV color range setting

in reply to:  2 comment:3 by gciaparrone, 3 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?

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

by gciaparrone, 3 years ago

Attachment: black.yuv added

YUV file output on IBM Power9

comment:4 by gciaparrone, 3 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.

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

in reply to:  5 comment:6 by gciaparrone, 3 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 also true of the original reblack.png image I posted. So something weird is going on.

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.

Version 0, edited 3 years ago by gciaparrone (next)

comment:7 by gciaparrone, 3 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
Last edited 3 years ago by gciaparrone (previous) (diff)

comment:8 by Carl Eugen Hoyos, 2 years ago

Keywords: altivec added
Note: See TracTickets for help on using tickets.