[libyuv] Fix color matrix constants in RAWToI420

RAW format in libyuv is Red-first ([R, G, B] in memory), whereas RGB24
is Blue-first ([B, G, R] in memory).

RGBToYMatrixRow and RGBToUVMatrixRow internally expand 3-byte input
into 4-byte [byte0, byte1, byte2, 255]. For RAW, this buffer becomes
[R, G, B, 255] (matching ABGR byte order). RAWToI420 previously passed
&kArgbI601Constants (which expects [B, G, R, 255]) instead of
&kAbgrI601Constants, causing Red and Blue channels to be swapped.

Pass &kAbgrI601Constants in RAWToI420, fix parameter names in
source/convert.cc, and add a unit test.

Test: libyuv_unittest --gtest_filter=*RAWToI420*
Bug: None

TAG=agy
CONV=2c54c4b5-f515-421b-80b3-079caa9f948b

Change-Id: Ic72470813eaf15e80046c2c01cf804cb827039ab
This commit is contained in:
Frank Barchard 2026-07-21 18:14:59 -07:00
parent 666b4ee514
commit 44da5ae9ca
2 changed files with 53 additions and 13 deletions

View File

@ -2862,8 +2862,8 @@ int RGB24ToJ420(const uint8_t* src_rgb24,
// Convert RAW to I420.
LIBYUV_API
int RAWToI420(const uint8_t* src_rgb24,
int src_stride_rgb24,
int RAWToI420(const uint8_t* src_raw,
int src_stride_raw,
uint8_t* dst_y,
int dst_stride_y,
uint8_t* dst_u,
@ -2925,31 +2925,31 @@ int RAWToI420(const uint8_t* src_rgb24,
}
#endif
if (!src_rgb24 || !dst_y || !dst_u || !dst_v || width <= 0 || height == 0 ||
if (!src_raw || !dst_y || !dst_u || !dst_v || width <= 0 || height == 0 ||
height == INT_MIN) {
return -1;
}
// Negative height means invert the image.
if (height < 0) {
height = -height;
src_rgb24 = src_rgb24 + (ptrdiff_t)(height - 1) * src_stride_rgb24;
src_stride_rgb24 = -src_stride_rgb24;
src_raw = src_raw + (ptrdiff_t)(height - 1) * src_stride_raw;
src_stride_raw = -src_stride_raw;
}
for (y = 0; y < height - 1; y += 2) {
RGBToUVMatrixRow(src_rgb24, src_stride_rgb24, dst_u, dst_v, width,
&kArgbI601Constants);
RGBToYMatrixRow(src_rgb24, dst_y, width, &kArgbI601Constants);
RGBToYMatrixRow(src_rgb24 + src_stride_rgb24, dst_y + dst_stride_y, width,
&kArgbI601Constants);
src_rgb24 += src_stride_rgb24 * 2;
RGBToUVMatrixRow(src_raw, src_stride_raw, dst_u, dst_v, width,
&kAbgrI601Constants);
RGBToYMatrixRow(src_raw, dst_y, width, &kAbgrI601Constants);
RGBToYMatrixRow(src_raw + src_stride_raw, dst_y + dst_stride_y, width,
&kAbgrI601Constants);
src_raw += src_stride_raw * 2;
dst_y += dst_stride_y * 2;
dst_u += dst_stride_u;
dst_v += dst_stride_v;
}
if (height & 1) {
RGBToYMatrixRow(src_rgb24, dst_y, width, &kArgbI601Constants);
RGBToUVMatrixRow(src_rgb24, 0, dst_u, dst_v, width, &kArgbI601Constants);
RGBToYMatrixRow(src_raw, dst_y, width, &kAbgrI601Constants);
RGBToUVMatrixRow(src_raw, 0, dst_u, dst_v, width, &kAbgrI601Constants);
}
return 0;
}

View File

@ -2176,6 +2176,46 @@ TEST_F(LibYUVConvertTest, TestABGRToI420Matrix) {
free_aligned_buffer_page_end(ref_v);
}
TEST_F(LibYUVConvertTest, TestRAWToI420) {
const int kWidth = 16;
const int kHeight = 16;
align_buffer_page_end(src_raw, kWidth * kHeight * 3);
align_buffer_page_end(dst_y, kWidth * kHeight);
align_buffer_page_end(dst_u, kWidth / 2 * kHeight / 2);
align_buffer_page_end(dst_v, kWidth / 2 * kHeight / 2);
align_buffer_page_end(src_argb, kWidth * kHeight * 4);
align_buffer_page_end(ref_y, kWidth * kHeight);
align_buffer_page_end(ref_u, kWidth / 2 * kHeight / 2);
align_buffer_page_end(ref_v, kWidth / 2 * kHeight / 2);
MemRandomize(src_raw, kWidth * kHeight * 3);
RAWToI420(src_raw, kWidth * 3, dst_y, kWidth, dst_u, kWidth / 2, dst_v,
kWidth / 2, kWidth, kHeight);
// Verify against RAWToARGB + ARGBToI420
RAWToARGB(src_raw, kWidth * 3, src_argb, kWidth * 4, kWidth, kHeight);
ARGBToI420(src_argb, kWidth * 4, ref_y, kWidth, ref_u, kWidth / 2, ref_v,
kWidth / 2, kWidth, kHeight);
for (int i = 0; i < kWidth * kHeight; ++i) {
ASSERT_EQ(dst_y[i], ref_y[i]);
}
for (int i = 0; i < kWidth / 2 * kHeight / 2; ++i) {
ASSERT_EQ(dst_u[i], ref_u[i]);
ASSERT_EQ(dst_v[i], ref_v[i]);
}
free_aligned_buffer_page_end(src_raw);
free_aligned_buffer_page_end(dst_y);
free_aligned_buffer_page_end(dst_u);
free_aligned_buffer_page_end(dst_v);
free_aligned_buffer_page_end(src_argb);
free_aligned_buffer_page_end(ref_y);
free_aligned_buffer_page_end(ref_u);
free_aligned_buffer_page_end(ref_v);
}
TEST_F(LibYUVConvertTest, TestARGBToNV12Matrix) {
const int kWidth = 16;
const int kHeight = 16;