Bug 1960639 - Fix YU12/YV12 confusion in V4L2 decode r=stransky,media-playback-reviewers,aosmond

The V4L2 code in FFmpegDescToVA erroneously stored YUV420 as
VA_FOURCC_YV12, but actually it should be VA_FOURCC_I420 (YV12 is for
YVU420, not YUV420).  This didn't make any difference when the format
conversion was done by the GPU in Firefox's compositor, but now we're
exporting YUV dmabufs (webrender-compositor and hdr mode), this causes
colors to appear incorrect.

Also, DmaBufSurface.mFOURCCFormat is stored as a VA_FOURCC_* enum, but
the format passed to zwp_linux_buffer_params_v1::create_immed needs to
be a DRM_FORMAT_* enum, so add a conversion in CreateWlBuffer().

Differential Revision: https://phabricator.services.mozilla.com/D245574
This commit is contained in:
David Turner
2025-05-06 15:14:13 +00:00
committed by david.turner@raspberrypi.com
parent 186b5eaa63
commit b315f24a48
3 changed files with 22 additions and 4 deletions

View File

@@ -346,7 +346,7 @@ static Maybe<VADRMPRIMESurfaceDescriptor> FFmpegDescToVA(
unsigned int offset = aDesc.layers[0].planes[0].offset;
if (aDesc.layers[0].format == DRM_FORMAT_YUV420) {
vaDesc.fourcc = VA_FOURCC_YV12;
vaDesc.fourcc = VA_FOURCC_I420;
// V4L2 expresses YUV420 as a single contiguous buffer containing
// all three planes. DMABufSurfaceYUV expects the three planes

View File

@@ -34,6 +34,13 @@
#endif
#include <sys/ioctl.h>
// DMABufLibWrapper defines its own version of this which collides with the
// official version in drm_fourcc.h
#ifdef DRM_FORMAT_MOD_INVALID
# undef DRM_FORMAT_MOD_INVALID
#endif
#include <libdrm/drm_fourcc.h>
#include "mozilla/widget/va_drmcommon.h"
#include "mozilla/gfx/2D.h"
#include "mozilla/gfx/FileHandleWrapper.h"
@@ -2028,9 +2035,10 @@ gfx::SurfaceFormat DMABufSurfaceYUV::GetFormat() {
case VA_FOURCC_NV12:
return gfx::SurfaceFormat::NV12;
case VA_FOURCC_YV12:
case VA_FOURCC_I420:
return gfx::SurfaceFormat::YUV420;
default:
gfxCriticalNoteOnce << "DMABufSurfaceYUV::GetFormat() unknow format: "
gfxCriticalNoteOnce << "DMABufSurfaceYUV::GetFormat() unknown format: "
<< mFOURCCFormat;
return gfx::SurfaceFormat::UNKNOWN;
}
@@ -2153,11 +2161,18 @@ wl_buffer* DMABufSurfaceYUV::CreateWlBuffer() {
mBufferModifiers[i] >> 32, mBufferModifiers[i] & 0xffffffff);
}
// The format passed to wayland needs to be a DRM_FORMAT_* enum. These are
// largely the same as VA_FOURCC_* values except for I420/YUV420
uint32_t format = GetFOURCCFormat();
if (format == VA_FOURCC_I420) {
format = DRM_FORMAT_YUV420;
}
LOGDMABUF(
" zwp_linux_buffer_params_v1_create_immed() [%d x %d], fourcc [%x]",
GetWidth(), GetHeight(), GetFOURCCFormat());
GetWidth(), GetHeight(), format);
wl_buffer* buffer = zwp_linux_buffer_params_v1_create_immed(
params, GetWidth(), GetHeight(), GetFOURCCFormat(), 0);
params, GetWidth(), GetHeight(), format, 0);
if (!buffer) {
LOGDMABUF(
" zwp_linux_buffer_params_v1_create_immed(): failed to create "

View File

@@ -30,6 +30,9 @@ typedef void* EGLSyncKHR;
#ifndef VA_FOURCC_NV12
# define VA_FOURCC_NV12 0x3231564E
#endif
#ifndef VA_FOURCC_I420
# define VA_FOURCC_I420 0x30323449
#endif
#ifndef VA_FOURCC_YV12
# define VA_FOURCC_YV12 0x32315659
#endif