Commit 790054ff authored by Frank Barchard's avatar Frank Barchard Committed by Commit Bot

Add AR30ToARGB function

Initial AR30ToARGB function to allow converion
from AR30 to other formats if necessary and/or
for testing.
Not optimized at this point.

Bug: libyuv:751
Test: LibYUVConvertTest.AR30ToARGB_Opt
Change-Id: I38ef192315240f3caa7aee0218b38d5e88a2849f
Reviewed-on: https://chromium-review.googlesource.com/833025
Commit-Queue: Frank Barchard <fbarchard@chromium.org>
Reviewed-by: 's avatarrichard winterton <rrwinterton@gmail.com>
parent 5336217f
Name: libyuv Name: libyuv
URL: http://code.google.com/p/libyuv/ URL: http://code.google.com/p/libyuv/
Version: 1683 Version: 1684
License: BSD License: BSD
License File: LICENSE License File: LICENSE
......
...@@ -443,6 +443,15 @@ int ARGB4444ToARGB(const uint8* src_frame, ...@@ -443,6 +443,15 @@ int ARGB4444ToARGB(const uint8* src_frame,
int width, int width,
int height); int height);
// Convert AR30 To ARGB.
LIBYUV_API
int AR30ToARGB(const uint8* src_ar30,
int src_stride_ar30,
uint8* dst_argb,
int dst_stride_argb,
int width,
int height);
#ifdef HAVE_JPEG #ifdef HAVE_JPEG
// src_width/height provided by capture // src_width/height provided by capture
// dst_width/height for clipping determine final size. // dst_width/height for clipping determine final size.
......
...@@ -1601,6 +1601,7 @@ void RAWToRGB24Row_C(const uint8* src_raw, uint8* dst_rgb24, int width); ...@@ -1601,6 +1601,7 @@ void RAWToRGB24Row_C(const uint8* src_raw, uint8* dst_rgb24, int width);
void RGB565ToARGBRow_C(const uint8* src_rgb, uint8* dst_argb, int width); void RGB565ToARGBRow_C(const uint8* src_rgb, uint8* dst_argb, int width);
void ARGB1555ToARGBRow_C(const uint8* src_argb, uint8* dst_argb, int width); void ARGB1555ToARGBRow_C(const uint8* src_argb, uint8* dst_argb, int width);
void ARGB4444ToARGBRow_C(const uint8* src_argb, uint8* dst_argb, int width); void ARGB4444ToARGBRow_C(const uint8* src_argb, uint8* dst_argb, int width);
void AR30ToARGBRow_C(const uint8* src_ar30, uint8* dst_argb, int width);
void RGB24ToARGBRow_Any_SSSE3(const uint8* src_rgb24, void RGB24ToARGBRow_Any_SSSE3(const uint8* src_rgb24,
uint8* dst_argb, uint8* dst_argb,
int width); int width);
......
...@@ -11,6 +11,6 @@ ...@@ -11,6 +11,6 @@
#ifndef INCLUDE_LIBYUV_VERSION_H_ #ifndef INCLUDE_LIBYUV_VERSION_H_
#define INCLUDE_LIBYUV_VERSION_H_ #define INCLUDE_LIBYUV_VERSION_H_
#define LIBYUV_VERSION 1683 #define LIBYUV_VERSION 1684
#endif // INCLUDE_LIBYUV_VERSION_H_ #endif // INCLUDE_LIBYUV_VERSION_H_
...@@ -1504,6 +1504,40 @@ int ARGB4444ToARGB(const uint8* src_argb4444, ...@@ -1504,6 +1504,40 @@ int ARGB4444ToARGB(const uint8* src_argb4444,
return 0; return 0;
} }
// Convert AR30 to ARGB.
LIBYUV_API
int AR30ToARGB(const uint8* src_ar30,
int src_stride_ar30,
uint8* dst_argb,
int dst_stride_argb,
int width,
int height) {
int y;
void (*AR30ToARGBRow)(const uint8* src_ar30, uint8* dst_argb, int width) =
AR30ToARGBRow_C;
if (!src_ar30 || !dst_argb || width <= 0 || height == 0) {
return -1;
}
// Negative height means invert the image.
if (height < 0) {
height = -height;
src_ar30 = src_ar30 + (height - 1) * src_stride_ar30;
src_stride_ar30 = -src_stride_ar30;
}
// Coalesce rows.
if (src_stride_ar30 == width * 2 && dst_stride_argb == width * 4) {
width *= height;
height = 1;
src_stride_ar30 = dst_stride_argb = 0;
}
for (y = 0; y < height; ++y) {
AR30ToARGBRow(src_ar30, dst_argb, width);
src_ar30 += src_stride_ar30;
dst_argb += dst_stride_argb;
}
return 0;
}
// Convert NV12 to ARGB with matrix // Convert NV12 to ARGB with matrix
static int NV12ToARGBMatrix(const uint8* src_y, static int NV12ToARGBMatrix(const uint8* src_y,
int src_stride_y, int src_stride_y,
......
...@@ -165,6 +165,23 @@ void ARGB4444ToARGBRow_C(const uint8* src_argb4444, ...@@ -165,6 +165,23 @@ void ARGB4444ToARGBRow_C(const uint8* src_argb4444,
} }
} }
void AR30ToARGBRow_C(const uint8* src_ar30, uint8* dst_argb, int width) {
int x;
for (x = 0; x < width; ++x) {
uint32 ar30 = *(uint32*)src_ar30;
uint32 b = ar30 & 0x3ff;
uint32 g = (ar30 >> 10) & 0x3ff;
uint32 r = (ar30 >> 20) & 0x3ff;
uint32 a = (ar30 >> 30) & 0x3;
dst_argb[0] = b >> 2;
dst_argb[1] = g >> 2;
dst_argb[2] = r >> 2;
dst_argb[3] = a * 0x55;
dst_argb += 4;
src_ar30 += 4;
}
}
void ARGBToRGB24Row_C(const uint8* src_argb, uint8* dst_rgb, int width) { void ARGBToRGB24Row_C(const uint8* src_argb, uint8* dst_rgb, int width) {
int x; int x;
for (x = 0; x < width; ++x) { for (x = 0; x < width; ++x) {
...@@ -304,9 +321,9 @@ void ARGBToARGB4444Row_C(const uint8* src_argb, uint8* dst_rgb, int width) { ...@@ -304,9 +321,9 @@ void ARGBToARGB4444Row_C(const uint8* src_argb, uint8* dst_rgb, int width) {
void ARGBToAR30Row_C(const uint8* src_argb, uint8* dst_rgb, int width) { void ARGBToAR30Row_C(const uint8* src_argb, uint8* dst_rgb, int width) {
int x; int x;
for (x = 0; x < width; ++x) { for (x = 0; x < width; ++x) {
uint32 b0 = (src_argb[0] >> 6) | (src_argb[0] << 2); uint32 b0 = (src_argb[0] >> 6) | ((uint32)(src_argb[0]) << 2);
uint32 g0 = (src_argb[1] >> 6) | (src_argb[1] << 2); uint32 g0 = (src_argb[1] >> 6) | ((uint32)(src_argb[1]) << 2);
uint32 r0 = (src_argb[2] >> 6) | (src_argb[2] << 2); uint32 r0 = (src_argb[2] >> 6) | ((uint32)(src_argb[2]) << 2);
uint32 a0 = (src_argb[3] >> 6); uint32 a0 = (src_argb[3] >> 6);
*(uint32*)(dst_rgb) = b0 | (g0 << 10) | (r0 << 20) | (a0 << 30); *(uint32*)(dst_rgb) = b0 | (g0 << 10) | (r0 << 20) | (a0 << 30);
dst_rgb += 4; dst_rgb += 4;
......
...@@ -1072,6 +1072,7 @@ TESTATOB(RGB24, 3, 3, 1, ARGB, 4, 4, 1, 0) ...@@ -1072,6 +1072,7 @@ TESTATOB(RGB24, 3, 3, 1, ARGB, 4, 4, 1, 0)
TESTATOB(RGB565, 2, 2, 1, ARGB, 4, 4, 1, 0) TESTATOB(RGB565, 2, 2, 1, ARGB, 4, 4, 1, 0)
TESTATOB(ARGB1555, 2, 2, 1, ARGB, 4, 4, 1, 0) TESTATOB(ARGB1555, 2, 2, 1, ARGB, 4, 4, 1, 0)
TESTATOB(ARGB4444, 2, 2, 1, ARGB, 4, 4, 1, 0) TESTATOB(ARGB4444, 2, 2, 1, ARGB, 4, 4, 1, 0)
TESTATOB(AR30, 4, 4, 1, ARGB, 4, 4, 1, 0)
TESTATOB(YUY2, 2, 4, 1, ARGB, 4, 4, 1, 4) TESTATOB(YUY2, 2, 4, 1, ARGB, 4, 4, 1, 4)
TESTATOB(UYVY, 2, 4, 1, ARGB, 4, 4, 1, 4) TESTATOB(UYVY, 2, 4, 1, ARGB, 4, 4, 1, 4)
TESTATOB(YUY2, 2, 4, 1, Y, 1, 1, 1, 0) TESTATOB(YUY2, 2, 4, 1, Y, 1, 1, 1, 0)
...@@ -1718,6 +1719,8 @@ TESTPLANARTOBD(I420, 2, 2, RGB565, 2, 2, 1, 9, ARGB, 4) ...@@ -1718,6 +1719,8 @@ TESTPLANARTOBD(I420, 2, 2, RGB565, 2, 2, 1, 9, ARGB, 4)
TESTPTOB(TestYUY2ToNV12, YUY2ToI420, YUY2ToNV12) TESTPTOB(TestYUY2ToNV12, YUY2ToI420, YUY2ToNV12)
TESTPTOB(TestUYVYToNV12, UYVYToI420, UYVYToNV12) TESTPTOB(TestUYVYToNV12, UYVYToI420, UYVYToNV12)
// Transitive tests. A to B to C is same as A to C.
#define TESTPLANARTOEI(FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y, FMT_B, SUB_B, BPP_B, \ #define TESTPLANARTOEI(FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y, FMT_B, SUB_B, BPP_B, \
W1280, N, NEG, OFF, FMT_C, BPP_C) \ W1280, N, NEG, OFF, FMT_C, BPP_C) \
TEST_F(LibYUVConvertTest, FMT_PLANAR##To##FMT_B##_##FMT_C##N) { \ TEST_F(LibYUVConvertTest, FMT_PLANAR##To##FMT_B##_##FMT_C##N) { \
...@@ -1883,6 +1886,59 @@ TESTPLANARTOE(I422, 2, 1, UYVY, 2, 4, ARGB, 4) ...@@ -1883,6 +1886,59 @@ TESTPLANARTOE(I422, 2, 1, UYVY, 2, 4, ARGB, 4)
TESTQPLANARTOE(I420Alpha, 2, 2, ARGB, 1, 4, ABGR, 4) TESTQPLANARTOE(I420Alpha, 2, 2, ARGB, 1, 4, ABGR, 4)
TESTQPLANARTOE(I420Alpha, 2, 2, ABGR, 1, 4, ARGB, 4) TESTQPLANARTOE(I420Alpha, 2, 2, ABGR, 1, 4, ARGB, 4)
#define TESTPLANETOEI(FMT_A, SUB_A, BPP_A, FMT_B, SUB_B, BPP_B, W1280, N, NEG, \
OFF, FMT_C, BPP_C) \
TEST_F(LibYUVConvertTest, FMT_A##To##FMT_B##_##FMT_C##N) { \
const int kWidth = ((W1280) > 0) ? (W1280) : 1; \
const int kHeight = benchmark_height_; \
const int kStrideA = SUBSAMPLE(kWidth, SUB_A) * BPP_A; \
const int kStrideB = SUBSAMPLE(kWidth, SUB_B) * BPP_B; \
align_buffer_page_end(src_argb_a, kStrideA* kHeight + OFF); \
align_buffer_page_end(dst_argb_b, kStrideB* kHeight + OFF); \
MemRandomize(src_argb_a + OFF, kStrideA * kHeight); \
memset(dst_argb_b + OFF, 1, kStrideB * kHeight); \
for (int i = 0; i < benchmark_iterations_; ++i) { \
FMT_A##To##FMT_B(src_argb_a + OFF, kStrideA, dst_argb_b + OFF, kStrideB, \
kWidth, NEG kHeight); \
} \
/* Convert to a 3rd format in 1 step and 2 steps and compare */ \
const int kStrideC = kWidth * BPP_C; \
align_buffer_page_end(dst_argb_c, kStrideC* kHeight + OFF); \
align_buffer_page_end(dst_argb_bc, kStrideC* kHeight + OFF); \
memset(dst_argb_c + OFF, 2, kStrideC * kHeight); \
memset(dst_argb_bc + OFF, 3, kStrideC * kHeight); \
FMT_A##To##FMT_C(src_argb_a + OFF, kStrideA, dst_argb_c + OFF, kStrideC, \
kWidth, NEG kHeight); \
/* Convert B to C */ \
FMT_B##To##FMT_C(dst_argb_b + OFF, kStrideB, dst_argb_bc + OFF, kStrideC, \
kWidth, kHeight); \
for (int i = 0; i < kStrideC * kHeight; i += 4) { \
EXPECT_EQ(dst_argb_c[i + OFF + 0], dst_argb_bc[i + OFF + 0]); \
EXPECT_EQ(dst_argb_c[i + OFF + 1], dst_argb_bc[i + OFF + 1]); \
EXPECT_EQ(dst_argb_c[i + OFF + 2], dst_argb_bc[i + OFF + 2]); \
EXPECT_NEAR(dst_argb_c[i + OFF + 3], dst_argb_bc[i + OFF + 3], 64); \
} \
free_aligned_buffer_page_end(src_argb_a); \
free_aligned_buffer_page_end(dst_argb_b); \
free_aligned_buffer_page_end(dst_argb_c); \
free_aligned_buffer_page_end(dst_argb_bc); \
}
#define TESTPLANETOE(FMT_A, SUB_A, BPP_A, FMT_B, SUB_B, BPP_B, FMT_C, BPP_C) \
TESTPLANETOEI(FMT_A, SUB_A, BPP_A, FMT_B, SUB_B, BPP_B, \
benchmark_width_ - 4, _Any, +, 0, FMT_C, BPP_C) \
TESTPLANETOEI(FMT_A, SUB_A, BPP_A, FMT_B, SUB_B, BPP_B, benchmark_width_, \
_Unaligned, +, 1, FMT_C, BPP_C) \
TESTPLANETOEI(FMT_A, SUB_A, BPP_A, FMT_B, SUB_B, BPP_B, benchmark_width_, \
_Invert, -, 0, FMT_C, BPP_C) \
TESTPLANETOEI(FMT_A, SUB_A, BPP_A, FMT_B, SUB_B, BPP_B, benchmark_width_, \
_Opt, +, 0, FMT_C, BPP_C)
// Caveat: Destination needs to be 4 bytes
TESTPLANETOE(ARGB, 1, 4, AR30, 1, 4, ARGB, 4)
// TESTPLANETOE(ARGB, 1, 4, BGRA, 1, 4, ARGB, 4)
TEST_F(LibYUVConvertTest, RotateWithARGBSource) { TEST_F(LibYUVConvertTest, RotateWithARGBSource) {
// 2x2 frames // 2x2 frames
uint32_t src[4]; uint32_t src[4];
......
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