Commit 66305588 authored by Frank Barchard's avatar Frank Barchard Committed by Commit Bot

10 bit YUV to 10 bit BGR

BGR variation of 10 bit conversion using swapped U and V
and mirrored matrix to produce AB30 format instead of AR30.

Bug: libyuv:777
Test: LibYUVConvertTest.H010ToAB30_Opt
Change-Id: I96d115a5d1e12138f40cb548871e03aa3ab210eb
Reviewed-on: https://chromium-review.googlesource.com/922284
Commit-Queue: Frank Barchard <fbarchard@chromium.org>
Reviewed-by: 's avatarMiguel Casas <mcasas@chromium.org>
parent 439fc3ce
Name: libyuv
URL: http://code.google.com/p/libyuv/
Version: 1697
Version: 1698
License: BSD
License File: LICENSE
......
......@@ -50,11 +50,12 @@ The following is extracted from video_common.h as a complete list of formats sup
// 1 Secondary YUV format: row biplanar.
FOURCC_M420 = FOURCC('M', '4', '2', '0'),
// 10 Primary RGB formats: 4 32 bpp, 2 24 bpp, 3 16 bpp, 1 10 bpc
// 11 Primary RGB formats: 4 32 bpp, 2 24 bpp, 3 16 bpp, 1 10 bpc
FOURCC_ARGB = FOURCC('A', 'R', 'G', 'B'),
FOURCC_BGRA = FOURCC('B', 'G', 'R', 'A'),
FOURCC_ABGR = FOURCC('A', 'B', 'G', 'R'),
FOURCC_AR30 = FOURCC('A', 'R', '3', '0'), // 10 bit per channel. 2101010.
FOURCC_AB30 = FOURCC('A', 'B', '3', '0'), // ABGR version of 10 bit
FOURCC_24BG = FOURCC('2', '4', 'B', 'G'),
FOURCC_RAW = FOURCC('r', 'a', 'w', ' '),
FOURCC_RGBA = FOURCC('R', 'G', 'B', 'A'),
......
......@@ -446,6 +446,32 @@ int H010ToAR30(const uint16_t* src_y,
int width,
int height);
// Convert I010 to AB30.
LIBYUV_API
int I010ToAB30(const uint16_t* src_y,
int src_stride_y,
const uint16_t* src_u,
int src_stride_u,
const uint16_t* src_v,
int src_stride_v,
uint8_t* dst_ab30,
int dst_stride_ab30,
int width,
int height);
// Convert H010 to AB30.
LIBYUV_API
int H010ToAB30(const uint16_t* src_y,
int src_stride_y,
const uint16_t* src_u,
int src_stride_u,
const uint16_t* src_v,
int src_stride_v,
uint8_t* dst_ab30,
int dst_stride_ab30,
int width,
int height);
// BGRA little endian (argb in memory) to ARGB.
LIBYUV_API
int BGRAToARGB(const uint8_t* src_bgra,
......@@ -530,6 +556,8 @@ int AR30ToARGB(const uint8_t* src_ar30,
int width,
int height);
#define AB30ToABGR
// Convert AR30 To ABGR.
LIBYUV_API
int AR30ToABGR(const uint8_t* src_ar30,
......
......@@ -1631,14 +1631,14 @@ void ARGB1555ToARGBRow_Any_SSE2(const uint8_t* src_ptr,
void ARGB4444ToARGBRow_Any_SSE2(const uint8_t* src_ptr,
uint8_t* dst_ptr,
int width);
void RGB565ToARGBRow_Any_AVX2(const uint8_t* src_rgb565,
uint8_t* dst_argb,
void RGB565ToARGBRow_Any_AVX2(const uint8_t* src_ptr,
uint8_t* dst_ptr,
int width);
void ARGB1555ToARGBRow_Any_AVX2(const uint8_t* src_argb1555,
uint8_t* dst_argb,
void ARGB1555ToARGBRow_Any_AVX2(const uint8_t* src_ptr,
uint8_t* dst_ptr,
int width);
void ARGB4444ToARGBRow_Any_AVX2(const uint8_t* src_argb4444,
uint8_t* dst_argb,
void ARGB4444ToARGBRow_Any_AVX2(const uint8_t* src_ptr,
uint8_t* dst_ptr,
int width);
void RGB24ToARGBRow_Any_NEON(const uint8_t* src_ptr,
......@@ -1752,7 +1752,9 @@ void J400ToARGBRow_C(const uint8_t* src_y, uint8_t* dst_argb, int width);
void J400ToARGBRow_Any_SSE2(const uint8_t* src_ptr,
uint8_t* dst_ptr,
int width);
void J400ToARGBRow_Any_AVX2(const uint8_t* src_y, uint8_t* dst_argb, int width);
void J400ToARGBRow_Any_AVX2(const uint8_t* src_ptr,
uint8_t* dst_ptr,
int width);
void J400ToARGBRow_Any_NEON(const uint8_t* src_ptr,
uint8_t* dst_ptr,
int width);
......@@ -2430,14 +2432,14 @@ void ARGBToRGB565DitherRow_Any_AVX2(const uint8_t* src_ptr,
const uint32_t param,
int width);
void ARGBToRGB565Row_Any_AVX2(const uint8_t* src_argb,
uint8_t* dst_rgb,
void ARGBToRGB565Row_Any_AVX2(const uint8_t* src_ptr,
uint8_t* dst_ptr,
int width);
void ARGBToARGB1555Row_Any_AVX2(const uint8_t* src_argb,
uint8_t* dst_rgb,
void ARGBToARGB1555Row_Any_AVX2(const uint8_t* src_ptr,
uint8_t* dst_ptr,
int width);
void ARGBToARGB4444Row_Any_AVX2(const uint8_t* src_argb,
uint8_t* dst_rgb,
void ARGBToARGB4444Row_Any_AVX2(const uint8_t* src_ptr,
uint8_t* dst_ptr,
int width);
void ABGRToAR30Row_Any_AVX2(const uint8_t* src_ptr,
uint8_t* dst_ptr,
......
......@@ -63,11 +63,12 @@ enum FourCC {
// 1 Secondary YUV format: row biplanar.
FOURCC_M420 = FOURCC('M', '4', '2', '0'),
// 10 Primary RGB formats: 4 32 bpp, 2 24 bpp, 3 16 bpp, 1 10 bpc
// 11 Primary RGB formats: 4 32 bpp, 2 24 bpp, 3 16 bpp, 1 10 bpc
FOURCC_ARGB = FOURCC('A', 'R', 'G', 'B'),
FOURCC_BGRA = FOURCC('B', 'G', 'R', 'A'),
FOURCC_ABGR = FOURCC('A', 'B', 'G', 'R'),
FOURCC_AR30 = FOURCC('A', 'R', '3', '0'), // 10 bit per channel. 2101010.
FOURCC_AB30 = FOURCC('A', 'B', '3', '0'), // ABGR version of 10 bit
FOURCC_24BG = FOURCC('2', '4', 'B', 'G'),
FOURCC_RAW = FOURCC('r', 'a', 'w', ' '),
FOURCC_RGBA = FOURCC('R', 'G', 'B', 'A'),
......@@ -137,6 +138,7 @@ enum FourCCBpp {
FOURCC_BPP_ABGR = 32,
FOURCC_BPP_RGBA = 32,
FOURCC_BPP_AR30 = 32,
FOURCC_BPP_AB30 = 32,
FOURCC_BPP_24BG = 24,
FOURCC_BPP_RAW = 24,
FOURCC_BPP_RGBP = 16,
......
......@@ -1716,8 +1716,8 @@ int Android420ToI420(const uint8_t* src_y,
halfwidth, halfheight);
return 0;
// Split UV planes - NV12
} else if (src_pixel_stride_uv == 2 && vu_off == 1 &&
src_stride_u == src_stride_v) {
}
if (src_pixel_stride_uv == 2 && vu_off == 1 && src_stride_u == src_stride_v) {
SplitUVPlane(src_u, src_stride_u, dst_u, dst_stride_u, dst_v, dst_stride_v,
halfwidth, halfheight);
return 0;
......
......@@ -500,6 +500,40 @@ int H010ToAR30(const uint16_t* src_y,
&kYuvH709Constants, width, height);
}
// Convert I010 to AB30.
LIBYUV_API
int I010ToAB30(const uint16_t* src_y,
int src_stride_y,
const uint16_t* src_u,
int src_stride_u,
const uint16_t* src_v,
int src_stride_v,
uint8_t* dst_ab30,
int dst_stride_ab30,
int width,
int height) {
return I010ToAR30Matrix(src_y, src_stride_y, src_v,
src_stride_v, src_u, src_stride_u, dst_ab30, dst_stride_ab30,
&kYvuI601Constants, width, height);
}
// Convert H010 to AB30.
LIBYUV_API
int H010ToAB30(const uint16_t* src_y,
int src_stride_y,
const uint16_t* src_u,
int src_stride_u,
const uint16_t* src_v,
int src_stride_v,
uint8_t* dst_ab30,
int dst_stride_ab30,
int width,
int height) {
return I010ToAR30Matrix(src_y, src_stride_y, src_v,
src_stride_v, src_u, src_stride_u, dst_ab30, dst_stride_ab30,
&kYvuH709Constants, width, height);
}
// Convert 10 bit YUV to ARGB with matrix
static int I010ToARGBMatrix(const uint16_t* src_y,
int src_stride_y,
......@@ -1950,8 +1984,8 @@ int Android420ToARGBMatrix(const uint8_t* src_y,
return NV21ToARGBMatrix(src_y, src_stride_y, src_v, src_stride_v, dst_argb,
dst_stride_argb, yuvconstants, width, height);
// NV12
} else if (src_pixel_stride_uv == 2 && vu_off == 1 &&
src_stride_u == src_stride_v) {
}
if (src_pixel_stride_uv == 2 && vu_off == 1 && src_stride_u == src_stride_v) {
return NV12ToARGBMatrix(src_y, src_stride_y, src_u, src_stride_u, dst_argb,
dst_stride_argb, yuvconstants, width, height);
}
......
......@@ -556,9 +556,9 @@ JpegSubsamplingType MJpegDecoder::JpegSubsamplingTypeHelper(
if (subsample_x[0] == 1 && subsample_y[0] == 1 && subsample_x[1] == 2 &&
subsample_y[1] == 1 && subsample_x[2] == 2 && subsample_y[2] == 1) {
return kJpegYuv422;
} else if (subsample_x[0] == 1 && subsample_y[0] == 1 &&
subsample_x[1] == 1 && subsample_y[1] == 1 &&
subsample_x[2] == 1 && subsample_y[2] == 1) {
}
if (subsample_x[0] == 1 && subsample_y[0] == 1 && subsample_x[1] == 1 &&
subsample_y[1] == 1 && subsample_x[2] == 1 && subsample_y[2] == 1) {
return kJpegYuv444;
}
} else if (number_of_components == 1) { // Grey-scale images.
......
......@@ -2122,9 +2122,11 @@ TEST_F(LibYUVConvertTest, ABGRToAR30Row_Opt) {
TESTPLANAR16TOB(I010, 2, 2, ARGB, 4, 4, 1, 2)
TESTPLANAR16TOB(I010, 2, 2, ABGR, 4, 4, 1, 2)
TESTPLANAR16TOB(I010, 2, 2, AR30, 4, 4, 1, 2)
TESTPLANAR16TOB(I010, 2, 2, AB30, 4, 4, 1, 2)
TESTPLANAR16TOB(H010, 2, 2, ARGB, 4, 4, 1, 2)
TESTPLANAR16TOB(H010, 2, 2, ABGR, 4, 4, 1, 2)
TESTPLANAR16TOB(H010, 2, 2, AR30, 4, 4, 1, 2)
TESTPLANAR16TOB(H010, 2, 2, AB30, 4, 4, 1, 2)
static int Clamp(int y) {
if (y < 0) {
......@@ -2331,6 +2333,69 @@ TEST_F(LibYUVConvertTest, TestH010ToAR30) {
free_aligned_buffer_page_end(ar30_pixels);
}
// Test 10 bit YUV to 10 bit RGB
// Caveat: Result is near due to float rounding in expected result.
TEST_F(LibYUVConvertTest, TestH010ToAB30) {
const int kSize = 1024;
int histogram_b[1024];
int histogram_g[1024];
int histogram_r[1024];
memset(histogram_b, 0, sizeof(histogram_b));
memset(histogram_g, 0, sizeof(histogram_g));
memset(histogram_r, 0, sizeof(histogram_r));
align_buffer_page_end(orig_yuv, kSize * 2 + kSize / 2 * 2 * 2);
align_buffer_page_end(ab30_pixels, kSize * 4);
uint16_t* orig_y = reinterpret_cast<uint16_t*>(orig_yuv);
uint16_t* orig_u = orig_y + kSize;
uint16_t* orig_v = orig_u + kSize / 2;
// Test grey scale
for (int i = 0; i < kSize; ++i) {
orig_y[i] = i;
}
for (int i = 0; i < kSize / 2; ++i) {
orig_u[i] = 512; // 512 is 0.
orig_v[i] = 512;
}
H010ToAB30(orig_y, 0, orig_u, 0, orig_v, 0, ab30_pixels, 0, kSize, 1);
for (int i = 0; i < kSize; ++i) {
int r10 = reinterpret_cast<uint32_t*>(ab30_pixels)[i] & 1023;
int g10 = (reinterpret_cast<uint32_t*>(ab30_pixels)[i] >> 10) & 1023;
int b10 = (reinterpret_cast<uint32_t*>(ab30_pixels)[i] >> 20) & 1023;
int a2 = (reinterpret_cast<uint32_t*>(ab30_pixels)[i] >> 30) & 3;
++histogram_b[b10];
++histogram_g[g10];
++histogram_r[r10];
int expected_y = Clamp10(static_cast<int>((i - 64) * 1.164f));
EXPECT_NEAR(b10, expected_y, 4);
EXPECT_NEAR(g10, expected_y, 4);
EXPECT_NEAR(r10, expected_y, 4);
EXPECT_EQ(a2, 3);
}
int count_b = 0;
int count_g = 0;
int count_r = 0;
for (int i = 0; i < kSize; ++i) {
if (histogram_b[i]) {
++count_b;
}
if (histogram_g[i]) {
++count_g;
}
if (histogram_r[i]) {
++count_r;
}
}
printf("uniques: B %d, G, %d, R %d\n", count_b, count_g, count_r);
free_aligned_buffer_page_end(orig_yuv);
free_aligned_buffer_page_end(ab30_pixels);
}
// Test 8 bit YUV to 10 bit RGB
TEST_F(LibYUVConvertTest, TestH420ToAR30) {
const int kSize = 256;
......
......@@ -71,6 +71,7 @@ TEST_F(LibYUVBaseTest, TestFourCC) {
EXPECT_TRUE(TestValidFourCC(FOURCC_BGRA, FOURCC_BPP_BGRA));
EXPECT_TRUE(TestValidFourCC(FOURCC_ABGR, FOURCC_BPP_ABGR));
EXPECT_TRUE(TestValidFourCC(FOURCC_AR30, FOURCC_BPP_AR30));
EXPECT_TRUE(TestValidFourCC(FOURCC_AB30, FOURCC_BPP_AB30));
EXPECT_TRUE(TestValidFourCC(FOURCC_24BG, FOURCC_BPP_24BG));
EXPECT_TRUE(TestValidFourCC(FOURCC_RAW, FOURCC_BPP_RAW));
EXPECT_TRUE(TestValidFourCC(FOURCC_RGBA, FOURCC_BPP_RGBA));
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment