Fix RGB565ToARGB_SSE2. Expose rgb conversions. Low levels were already there for i420 to rgb, but rgb to rgb functions were not exposed. Added unittests.

BUG=none
TEST=planar unittests
Review URL: https://webrtc-codereview.appspot.com/632004

git-svn-id: http://libyuv.googlecode.com/svn/trunk@276 16f28f9a-4ce2-e073-06de-1de4eb20be90
This commit is contained in:
fbarchard@google.com 2012-06-04 15:29:15 +00:00
parent 85869c87f3
commit 6d6b7709f7
9 changed files with 283 additions and 66 deletions

View File

@ -1,6 +1,6 @@
Name: libyuv Name: libyuv
URL: http://code.google.com/p/libyuv/ URL: http://code.google.com/p/libyuv/
Version: 275 Version: 276
License: BSD License: BSD
License File: LICENSE License File: LICENSE

View File

@ -22,6 +22,9 @@ namespace libyuv {
extern "C" { extern "C" {
#endif #endif
// Alias
#define I420ToI420 I420Copy
// Copy I420 to I420. // Copy I420 to I420.
int I420Copy(const uint8* src_y, int src_stride_y, int I420Copy(const uint8* src_y, int src_stride_y,
const uint8* src_u, int src_stride_u, const uint8* src_u, int src_stride_u,

View File

@ -104,9 +104,10 @@ int ABGRToARGB(const uint8* src_abgr, int src_stride_abgr,
uint8* dst_argb, int dst_stride_argb, uint8* dst_argb, int dst_stride_argb,
int width, int height); int width, int height);
// Palindromes. // Aliases.
#define ARGBToBGRA BGRAToARGB #define ARGBToBGRA BGRAToARGB
#define ARGBToABGR ABGRToARGB #define ARGBToABGR ABGRToARGB
#define ARGBToARGB ARGBCopy
// Convert BGRA to ARGB. Also used for ARGB to BGRA. // Convert BGRA to ARGB. Also used for ARGB to BGRA.
int BGRAToARGB(const uint8* src_bgra, int src_stride_bgra, int BGRAToARGB(const uint8* src_bgra, int src_stride_bgra,
@ -128,6 +129,31 @@ int ARGBToRGB565(const uint8* src_argb, int src_stride_argb,
uint8* dst_rgb565, int dst_stride_rgb565, uint8* dst_rgb565, int dst_stride_rgb565,
int width, int height); int width, int height);
// Convert ARGB To ARGB1555.
int ARGBToARGB1555(const uint8* src_argb, int src_stride_argb,
uint8* dst_argb1555, int dst_stride_argb1555,
int width, int height);
// Convert ARGB To ARGB4444.
int ARGBToARGB4444(const uint8* src_argb, int src_stride_argb,
uint8* dst_argb4444, int dst_stride_argb4444,
int width, int height);
// Convert RGB565 To ARGB.
int RGB565ToARGB(const uint8* src_rgb565, int src_stride_rgb565,
uint8* dst_argb, int dst_stride_argb,
int width, int height);
// Convert ARGB1555 To ARGB.
int ARGB1555ToARGB(const uint8* src_argb1555, int src_stride_argb1555,
uint8* dst_argb, int dst_stride_argb,
int width, int height);
// Convert ARGB4444 To ARGB.
int ARGB4444ToARGB(const uint8* src_argb4444, int src_stride_argb4444,
uint8* dst_argb, int dst_stride_argb,
int width, int height);
// Convert ARGB to I400. // Convert ARGB to I400.
int ARGBToI400(const uint8* src_argb, int src_stride_argb, int ARGBToI400(const uint8* src_argb, int src_stride_argb,
uint8* dst_y, int dst_stride_y, uint8* dst_y, int dst_stride_y,

View File

@ -11,7 +11,7 @@
#ifndef INCLUDE_LIBYUV_VERSION_H_ #ifndef INCLUDE_LIBYUV_VERSION_H_
#define INCLUDE_LIBYUV_VERSION_H_ #define INCLUDE_LIBYUV_VERSION_H_
#define LIBYUV_VERSION 275 #define LIBYUV_VERSION 276
#endif // INCLUDE_LIBYUV_VERSION_H_ #endif // INCLUDE_LIBYUV_VERSION_H_

View File

@ -338,6 +338,34 @@ int I400ToARGB(const uint8* src_y, int src_stride_y,
return 0; return 0;
} }
// Convert ARGB to I400.
int ARGBToI400(const uint8* src_argb, int src_stride_argb,
uint8* dst_y, int dst_stride_y,
int width, int height) {
if (height < 0) {
height = -height;
src_argb = src_argb + (height - 1) * src_stride_argb;
src_stride_argb = -src_stride_argb;
}
void (*ARGBToYRow)(const uint8* src_argb, uint8* dst_y, int pix) =
ARGBToYRow_C;
#if defined(HAS_ARGBTOYROW_SSSE3)
if (TestCpuFlag(kCpuHasSSSE3) &&
IS_ALIGNED(width, 4) &&
IS_ALIGNED(src_argb, 16) && IS_ALIGNED(src_stride_argb, 16) &&
IS_ALIGNED(dst_y, 16) && IS_ALIGNED(dst_stride_y, 16)) {
ARGBToYRow = ARGBToYRow_SSSE3;
}
#endif
for (int y = 0; y < height; ++y) {
ARGBToYRow(src_argb, dst_y, width);
src_argb += src_stride_argb;
dst_y += dst_stride_y;
}
return 0;
}
int ABGRToARGB(const uint8* src_abgr, int src_stride_abgr, int ABGRToARGB(const uint8* src_abgr, int src_stride_abgr,
uint8* dst_argb, int dst_stride_argb, uint8* dst_argb, int dst_stride_argb,
int width, int height) { int width, int height) {
@ -393,34 +421,6 @@ int BGRAToARGB(const uint8* src_bgra, int src_stride_bgra,
return 0; return 0;
} }
// Convert ARGB to I400.
int ARGBToI400(const uint8* src_argb, int src_stride_argb,
uint8* dst_y, int dst_stride_y,
int width, int height) {
if (height < 0) {
height = -height;
src_argb = src_argb + (height - 1) * src_stride_argb;
src_stride_argb = -src_stride_argb;
}
void (*ARGBToYRow)(const uint8* src_argb, uint8* dst_y, int pix) =
ARGBToYRow_C;
#if defined(HAS_ARGBTOYROW_SSSE3)
if (TestCpuFlag(kCpuHasSSSE3) &&
IS_ALIGNED(width, 4) &&
IS_ALIGNED(src_argb, 16) && IS_ALIGNED(src_stride_argb, 16) &&
IS_ALIGNED(dst_y, 16) && IS_ALIGNED(dst_stride_y, 16)) {
ARGBToYRow = ARGBToYRow_SSSE3;
}
#endif
for (int y = 0; y < height; ++y) {
ARGBToYRow(src_argb, dst_y, width);
src_argb += src_stride_argb;
dst_y += dst_stride_y;
}
return 0;
}
// Convert RAW to ARGB. // Convert RAW to ARGB.
int RAWToARGB(const uint8* src_raw, int src_stride_raw, int RAWToARGB(const uint8* src_raw, int src_stride_raw,
uint8* dst_argb, int dst_stride_argb, uint8* dst_argb, int dst_stride_argb,
@ -475,6 +475,87 @@ int RGB24ToARGB(const uint8* src_rgb24, int src_stride_rgb24,
return 0; return 0;
} }
// Convert RGB565 to ARGB.
int RGB565ToARGB(const uint8* src_rgb565, int src_stride_rgb565,
uint8* dst_argb, int dst_stride_argb,
int width, int height) {
if (height < 0) {
height = -height;
src_rgb565 = src_rgb565 + (height - 1) * src_stride_rgb565;
src_stride_rgb565 = -src_stride_rgb565;
}
void (*RGB565ToARGBRow)(const uint8* src_rgb565, uint8* dst_argb, int pix) =
RGB565ToARGBRow_C;
#if defined(HAS_RGB565TOARGBROW_SSE2)
if (TestCpuFlag(kCpuHasSSE2) &&
IS_ALIGNED(width, 8) &&
IS_ALIGNED(dst_argb, 16) && IS_ALIGNED(dst_stride_argb, 16)) {
RGB565ToARGBRow = RGB565ToARGBRow_SSE2;
}
#endif
for (int y = 0; y < height; ++y) {
RGB565ToARGBRow(src_rgb565, dst_argb, width);
src_rgb565 += src_stride_rgb565;
dst_argb += dst_stride_argb;
}
return 0;
}
// Convert ARGB1555 to ARGB.
int ARGB1555ToARGB(const uint8* src_argb1555, int src_stride_argb1555,
uint8* dst_argb, int dst_stride_argb,
int width, int height) {
if (height < 0) {
height = -height;
src_argb1555 = src_argb1555 + (height - 1) * src_stride_argb1555;
src_stride_argb1555 = -src_stride_argb1555;
}
void (*ARGB1555ToARGBRow)(const uint8* src_argb1555, uint8* dst_argb, int pix) =
ARGB1555ToARGBRow_C;
#if defined(HAS_ARGB1555TOARGBROW_SSE2)
if (TestCpuFlag(kCpuHasSSE2) &&
IS_ALIGNED(width, 8) &&
IS_ALIGNED(dst_argb, 16) && IS_ALIGNED(dst_stride_argb, 16)) {
ARGB1555ToARGBRow = ARGB1555ToARGBRow_SSE2;
}
#endif
for (int y = 0; y < height; ++y) {
ARGB1555ToARGBRow(src_argb1555, dst_argb, width);
src_argb1555 += src_stride_argb1555;
dst_argb += dst_stride_argb;
}
return 0;
}
// Convert ARGB4444 to ARGB.
int ARGB4444ToARGB(const uint8* src_argb4444, int src_stride_argb4444,
uint8* dst_argb, int dst_stride_argb,
int width, int height) {
if (height < 0) {
height = -height;
src_argb4444 = src_argb4444 + (height - 1) * src_stride_argb4444;
src_stride_argb4444 = -src_stride_argb4444;
}
void (*ARGB4444ToARGBRow)(const uint8* src_argb4444, uint8* dst_argb, int pix) =
ARGB4444ToARGBRow_C;
#if defined(HAS_ARGB4444TOARGBROW_SSE2)
if (TestCpuFlag(kCpuHasSSE2) &&
IS_ALIGNED(width, 8) &&
IS_ALIGNED(dst_argb, 16) && IS_ALIGNED(dst_stride_argb, 16)) {
ARGB4444ToARGBRow = ARGB4444ToARGBRow_SSE2;
}
#endif
for (int y = 0; y < height; ++y) {
ARGB4444ToARGBRow(src_argb4444, dst_argb, width);
src_argb4444 += src_stride_argb4444;
dst_argb += dst_stride_argb;
}
return 0;
}
// Convert ARGB To RGB24. // Convert ARGB To RGB24.
int ARGBToRGB24(const uint8* src_argb, int src_stride_argb, int ARGBToRGB24(const uint8* src_argb, int src_stride_argb,
uint8* dst_rgb24, int dst_stride_rgb24, uint8* dst_rgb24, int dst_stride_rgb24,
@ -550,15 +631,14 @@ int ARGBToRGB565(const uint8* src_argb, int src_stride_argb,
} }
void (*ARGBToRGB565Row)(const uint8* src_argb, uint8* dst_rgb, int pix) = void (*ARGBToRGB565Row)(const uint8* src_argb, uint8* dst_rgb, int pix) =
ARGBToRGB565Row_C; ARGBToRGB565Row_C;
#if defined(HAS_ARGBTORGB565ROW_SSSE3) #if defined(HAS_ARGBTORGB565ROW_SSE2)
if (TestCpuFlag(kCpuHasSSSE3) && if (TestCpuFlag(kCpuHasSSE2) &&
IS_ALIGNED(src_argb, 16) && IS_ALIGNED(src_stride_argb, 16)) { IS_ALIGNED(src_argb, 16) && IS_ALIGNED(src_stride_argb, 16)) {
if (width * 3 <= kMaxStride) { if (width * 2 <= kMaxStride) {
ARGBToRGB565Row = ARGBToRGB565Row_Any_SSSE3; ARGBToRGB565Row = ARGBToRGB565Row_Any_SSE2;
} }
if (IS_ALIGNED(width, 16) && if (IS_ALIGNED(width, 4)) {
IS_ALIGNED(dst_rgb565, 16) && IS_ALIGNED(dst_stride_rgb565, 16)) { ARGBToRGB565Row = ARGBToRGB565Row_SSE2;
ARGBToRGB565Row = ARGBToRGB565Row_SSSE3;
} }
} }
#endif #endif
@ -571,6 +651,68 @@ int ARGBToRGB565(const uint8* src_argb, int src_stride_argb,
return 0; return 0;
} }
// Convert ARGB To ARGB1555.
int ARGBToARGB1555(const uint8* src_argb, int src_stride_argb,
uint8* dst_argb1555, int dst_stride_argb1555,
int width, int height) {
if (height < 0) {
height = -height;
src_argb = src_argb + (height - 1) * src_stride_argb;
src_stride_argb = -src_stride_argb;
}
void (*ARGBToARGB1555Row)(const uint8* src_argb, uint8* dst_rgb, int pix) =
ARGBToARGB1555Row_C;
#if defined(HAS_ARGBTOARGB1555ROW_SSE2)
if (TestCpuFlag(kCpuHasSSE2) &&
IS_ALIGNED(src_argb, 16) && IS_ALIGNED(src_stride_argb, 16)) {
if (width * 2 <= kMaxStride) {
ARGBToARGB1555Row = ARGBToARGB1555Row_Any_SSE2;
}
if (IS_ALIGNED(width, 4)) {
ARGBToARGB1555Row = ARGBToARGB1555Row_SSE2;
}
}
#endif
for (int y = 0; y < height; ++y) {
ARGBToARGB1555Row(src_argb, dst_argb1555, width);
src_argb += src_stride_argb;
dst_argb1555 += dst_stride_argb1555;
}
return 0;
}
// Convert ARGB To ARGB4444.
int ARGBToARGB4444(const uint8* src_argb, int src_stride_argb,
uint8* dst_argb4444, int dst_stride_argb4444,
int width, int height) {
if (height < 0) {
height = -height;
src_argb = src_argb + (height - 1) * src_stride_argb;
src_stride_argb = -src_stride_argb;
}
void (*ARGBToARGB4444Row)(const uint8* src_argb, uint8* dst_rgb, int pix) =
ARGBToARGB4444Row_C;
#if defined(HAS_ARGBTOARGB4444ROW_SSE2)
if (TestCpuFlag(kCpuHasSSE2) &&
IS_ALIGNED(src_argb, 16) && IS_ALIGNED(src_stride_argb, 16)) {
if (width * 2 <= kMaxStride) {
ARGBToARGB4444Row = ARGBToARGB4444Row_Any_SSE2;
}
if (IS_ALIGNED(width, 4)) {
ARGBToARGB4444Row = ARGBToARGB4444Row_SSE2;
}
}
#endif
for (int y = 0; y < height; ++y) {
ARGBToARGB4444Row(src_argb, dst_argb4444, width);
src_argb += src_stride_argb;
dst_argb4444 += dst_stride_argb4444;
}
return 0;
}
// Convert NV12 to ARGB. // Convert NV12 to ARGB.
int NV12ToARGB(const uint8* src_y, int src_stride_y, int NV12ToARGB(const uint8* src_y, int src_stride_y,
const uint8* src_uv, int src_stride_uv, const uint8* src_uv, int src_stride_uv,

View File

@ -151,37 +151,75 @@ void ARGBToRAWRow_C(const uint8* src_argb, uint8* dst_rgb, int width) {
// TODO(fbarchard): support big endian CPU // TODO(fbarchard): support big endian CPU
void ARGBToRGB565Row_C(const uint8* src_argb, uint8* dst_rgb, int width) { void ARGBToRGB565Row_C(const uint8* src_argb, uint8* dst_rgb, int width) {
for (int x = 0; x < width; ++x) { for (int x = 0; x < width - 1; x += 2) {
uint8 b = src_argb[0] >> 3; uint8 b0 = src_argb[0] >> 3;
uint8 g = src_argb[1] >> 2; uint8 g0 = src_argb[1] >> 2;
uint8 r = src_argb[2] >> 3; uint8 r0 = src_argb[2] >> 3;
*reinterpret_cast<uint16*>(dst_rgb) = (r << 11) | (g << 5) | b; uint8 b1 = src_argb[4] >> 3;
dst_rgb += 2; uint8 g1 = src_argb[5] >> 2;
src_argb += 4; uint8 r1 = src_argb[6] >> 3;
*reinterpret_cast<uint32*>(dst_rgb) = b0 | (g0 << 5) | (r0 << 11) |
(b1 << 16) | (g1 << 21) | (r1 << 27);
dst_rgb += 4;
src_argb += 8;
}
if (width & 1) {
uint8 b0 = src_argb[0] >> 3;
uint8 g0 = src_argb[1] >> 2;
uint8 r0 = src_argb[2] >> 3;
*reinterpret_cast<uint16*>(dst_rgb) = b0 | (g0 << 5) | (r0 << 11);
} }
} }
void ARGBToARGB1555Row_C(const uint8* src_argb, uint8* dst_rgb, int width) { void ARGBToARGB1555Row_C(const uint8* src_argb, uint8* dst_rgb, int width) {
for (int x = 0; x < width; ++x) { for (int x = 0; x < width - 1; x += 2) {
uint8 b = src_argb[0] >> 3; uint8 b0 = src_argb[0] >> 3;
uint8 g = src_argb[1] >> 3; uint8 g0 = src_argb[1] >> 3;
uint8 r = src_argb[2] >> 3; uint8 r0 = src_argb[2] >> 3;
uint8 a = src_argb[3] >> 7; uint8 a0 = src_argb[3] >> 7;
*reinterpret_cast<uint16*>(dst_rgb) = (a << 15) | (r << 10) | (g << 5) | b; uint8 b1 = src_argb[4] >> 3;
dst_rgb += 2; uint8 g1 = src_argb[5] >> 3;
src_argb += 4; uint8 r1 = src_argb[6] >> 3;
uint8 a1 = src_argb[7] >> 7;
*reinterpret_cast<uint32*>(dst_rgb) =
b0 | (g0 << 5) | (r0 << 10) | (a0 << 15) |
(b1 << 16) | (g1 << 21) | (r1 << 26) | (a1 << 31);
dst_rgb += 4;
src_argb += 8;
}
if (width & 1) {
uint8 b0 = src_argb[0] >> 3;
uint8 g0 = src_argb[1] >> 3;
uint8 r0 = src_argb[2] >> 3;
uint8 a0 = src_argb[3] >> 7;
*reinterpret_cast<uint16*>(dst_rgb) =
b0 | (g0 << 5) | (r0 << 10) | (a0 << 15);
} }
} }
void ARGBToARGB4444Row_C(const uint8* src_argb, uint8* dst_rgb, int width) { void ARGBToARGB4444Row_C(const uint8* src_argb, uint8* dst_rgb, int width) {
for (int x = 0; x < width; ++x) { for (int x = 0; x < width - 1; x += 2) {
uint8 b = src_argb[0] >> 4; uint8 b0 = src_argb[0] >> 4;
uint8 g = src_argb[1] >> 4; uint8 g0 = src_argb[1] >> 4;
uint8 r = src_argb[2] >> 4; uint8 r0 = src_argb[2] >> 4;
uint8 a = src_argb[3] >> 4; uint8 a0 = src_argb[3] >> 4;
*reinterpret_cast<uint16*>(dst_rgb) = (a << 12) | (r << 8) | (g << 4) | b; uint8 b1 = src_argb[4] >> 4;
dst_rgb += 2; uint8 g1 = src_argb[5] >> 4;
src_argb += 4; uint8 r1 = src_argb[6] >> 4;
uint8 a1 = src_argb[7] >> 4;
*reinterpret_cast<uint32*>(dst_rgb) =
b0 | (g0 << 4) | (r0 << 8) | (a0 << 12) |
(b1 << 16) | (g1 << 20) | (r1 << 24) | (a1 << 28);
dst_rgb += 4;
src_argb += 8;
}
if (width & 1) {
uint8 b0 = src_argb[0] >> 4;
uint8 g0 = src_argb[1] >> 4;
uint8 r0 = src_argb[2] >> 4;
uint8 a0 = src_argb[3] >> 4;
*reinterpret_cast<uint16*>(dst_rgb) =
b0 | (g0 << 4) | (r0 << 8) | (a0 << 12);
} }
} }

View File

@ -272,7 +272,7 @@ void RGB565ToARGBRow_SSE2(const uint8* src, uint8* dst, int pix) {
"mov $0x1080108,%%eax \n" "mov $0x1080108,%%eax \n"
"movd %%eax,%%xmm5 \n" "movd %%eax,%%xmm5 \n"
"pshufd $0x0,%%xmm5,%%xmm5 \n" "pshufd $0x0,%%xmm5,%%xmm5 \n"
"mov $0x20082008,%%eax \n" "mov $0x20802080,%%eax \n"
"movd %%eax,%%xmm6 \n" "movd %%eax,%%xmm6 \n"
"pshufd $0x0,%%xmm6,%%xmm6 \n" "pshufd $0x0,%%xmm6,%%xmm6 \n"
"pcmpeqb %%xmm3,%%xmm3 \n" "pcmpeqb %%xmm3,%%xmm3 \n"

View File

@ -261,7 +261,7 @@ __asm {
mov eax, 0x01080108 // generate multiplier to repeat 5 bits mov eax, 0x01080108 // generate multiplier to repeat 5 bits
movd xmm5, eax movd xmm5, eax
pshufd xmm5, xmm5, 0 pshufd xmm5, xmm5, 0
mov eax, 0x20082008 // multiplier shift by 5 and then repeat 6 bits mov eax, 0x20802080 // multiplier shift by 5 and then repeat 6 bits
movd xmm6, eax movd xmm6, eax
pshufd xmm6, xmm6, 0 pshufd xmm6, xmm6, 0
pcmpeqb xmm3, xmm3 // generate mask 0xf800f800 for Red pcmpeqb xmm3, xmm3 // generate mask 0xf800f800 for Red

View File

@ -165,14 +165,22 @@ TEST_F(libyuvTest, ##FMT_A##To##FMT_B##_CvsOPT) { \
free_aligned_buffer_16(dst_rgb_opt) \ free_aligned_buffer_16(dst_rgb_opt) \
} }
// TODO(fbarchard): Expose more ARGBToRGB functions and test. TESTATOB(ARGB, 4, ARGB, 4)
TESTATOB(ARGB, 4, BGRA, 4) TESTATOB(ARGB, 4, BGRA, 4)
TESTATOB(ARGB, 4, ABGR, 4) TESTATOB(ARGB, 4, ABGR, 4)
TESTATOB(ARGB, 4, RAW, 3) TESTATOB(ARGB, 4, RAW, 3)
TESTATOB(ARGB, 4, RGB24, 3) TESTATOB(ARGB, 4, RGB24, 3)
TESTATOB(ARGB, 4, RGB565, 2) TESTATOB(ARGB, 4, RGB565, 2)
//TESTATOB(ARGB, 4, ARGB1555, 2) TESTATOB(ARGB, 4, ARGB1555, 2)
//TESTATOB(ARGB, 4, ARGB4444, 2) TESTATOB(ARGB, 4, ARGB4444, 2)
TESTATOB(BGRA, 4, ARGB, 4)
TESTATOB(ABGR, 4, ARGB, 4)
TESTATOB(RAW, 3, ARGB, 4)
TESTATOB(RGB24, 3, ARGB, 4)
TESTATOB(RGB565, 2, ARGB, 4)
TESTATOB(ARGB1555, 2, ARGB, 4)
TESTATOB(ARGB4444, 2, ARGB, 4)
TESTATOB(YUY2, 2, ARGB, 4) TESTATOB(YUY2, 2, ARGB, 4)
TESTATOB(UYVY, 2, ARGB, 4) TESTATOB(UYVY, 2, ARGB, 4)