RGB24Mirror function

Bug: b/151960427
Change-Id: I413db0011a4ed87eefc0dd166bb8e076b5aa4b1d
Reviewed-on: https://chromium-review.googlesource.com/c/libyuv/libyuv/+/2116639
Commit-Queue: Frank Barchard <fbarchard@chromium.org>
Reviewed-by: richard winterton <rrwinterton@gmail.com>
This commit is contained in:
Frank Barchard 2020-03-24 12:07:52 -07:00 committed by Commit Bot
parent 7f00d67d7c
commit aabcc477bd
16 changed files with 1614 additions and 1529 deletions

View File

@ -313,6 +313,18 @@ int ARGBMirror(const uint8_t* src_argb,
int width, int width,
int height); int height);
// Alias
#define RGB24ToRGB24Mirror RGB24Mirror
// RGB24 mirror.
LIBYUV_API
int RGB24Mirror(const uint8_t* src_rgb24,
int src_stride_rgb24,
uint8_t* dst_rgb24,
int dst_stride_rgb24,
int width,
int height);
// Mirror a plane of data. // Mirror a plane of data.
LIBYUV_API LIBYUV_API
void MirrorPlane(const uint8_t* src_y, void MirrorPlane(const uint8_t* src_y,

View File

@ -83,6 +83,20 @@ int NV12ToI420Rotate(const uint8_t* src_y,
int height, int height,
enum RotationMode mode); enum RotationMode mode);
// Rotate NV12 input and store in NV12.
LIBYUV_API
int NV12Rotate(const uint8_t* src_y,
int src_stride_y,
const uint8_t* src_uv,
int src_stride_uv,
uint8_t* dst_y,
int dst_stride_y,
uint8_t* dst_uv,
int dst_stride_uv,
int width,
int height,
enum RotationMode mode);
// Rotate a plane by 0, 90, 180, or 270. // Rotate a plane by 0, 90, 180, or 270.
LIBYUV_API LIBYUV_API
int RotatePlane(const uint8_t* src, int RotatePlane(const uint8_t* src,

View File

@ -279,6 +279,7 @@ extern "C" {
#define HAS_I422TOAR30ROW_SSSE3 #define HAS_I422TOAR30ROW_SSSE3
#define HAS_MERGERGBROW_SSSE3 #define HAS_MERGERGBROW_SSSE3
#define HAS_RAWTORGBAROW_SSSE3 #define HAS_RAWTORGBAROW_SSSE3
#define HAS_RGB24MIRRORROW_SSSE3
#define HAS_RGBATOYJROW_SSSE3 #define HAS_RGBATOYJROW_SSSE3
#define HAS_SPLITRGBROW_SSSE3 #define HAS_SPLITRGBROW_SSSE3
#define HAS_SWAPUVROW_SSSE3 #define HAS_SWAPUVROW_SSSE3
@ -408,6 +409,7 @@ extern "C" {
#define HAS_ARGBCOLORMATRIXROW_NEON #define HAS_ARGBCOLORMATRIXROW_NEON
#define HAS_ARGBGRAYROW_NEON #define HAS_ARGBGRAYROW_NEON
#define HAS_ARGBMIRRORROW_NEON #define HAS_ARGBMIRRORROW_NEON
#define HAS_RGB24MIRRORROW_NEON
#define HAS_ARGBMULTIPLYROW_NEON #define HAS_ARGBMULTIPLYROW_NEON
#define HAS_ARGBQUANTIZEROW_NEON #define HAS_ARGBQUANTIZEROW_NEON
#define HAS_ARGBSEPIAROW_NEON #define HAS_ARGBSEPIAROW_NEON
@ -1196,7 +1198,9 @@ void BGRAToYRow_Any_SSSE3(const uint8_t* src_ptr, uint8_t* dst_ptr, int width);
void ABGRToYRow_Any_SSSE3(const uint8_t* src_ptr, uint8_t* dst_ptr, int width); void ABGRToYRow_Any_SSSE3(const uint8_t* src_ptr, uint8_t* dst_ptr, int width);
void RGBAToYRow_Any_SSSE3(const uint8_t* src_ptr, uint8_t* dst_ptr, int width); void RGBAToYRow_Any_SSSE3(const uint8_t* src_ptr, uint8_t* dst_ptr, int width);
void RGB24ToYRow_Any_SSSE3(const uint8_t* src_ptr, uint8_t* dst_ptr, int width); void RGB24ToYRow_Any_SSSE3(const uint8_t* src_ptr, uint8_t* dst_ptr, int width);
void RGB24ToYJRow_Any_SSSE3(const uint8_t* src_ptr, uint8_t* dst_ptr, int width); void RGB24ToYJRow_Any_SSSE3(const uint8_t* src_ptr,
uint8_t* dst_ptr,
int width);
void RAWToYRow_Any_SSSE3(const uint8_t* src_ptr, uint8_t* dst_ptr, int width); void RAWToYRow_Any_SSSE3(const uint8_t* src_ptr, uint8_t* dst_ptr, int width);
void RAWToYJRow_Any_SSSE3(const uint8_t* src_ptr, uint8_t* dst_ptr, int width); void RAWToYJRow_Any_SSSE3(const uint8_t* src_ptr, uint8_t* dst_ptr, int width);
void RGB24ToYJRow_Any_AVX2(const uint8_t* src_ptr, uint8_t* dst_ptr, int width); void RGB24ToYJRow_Any_AVX2(const uint8_t* src_ptr, uint8_t* dst_ptr, int width);
@ -1608,6 +1612,16 @@ void ARGBMirrorRow_Any_NEON(const uint8_t* src_ptr,
void ARGBMirrorRow_Any_MSA(const uint8_t* src_ptr, uint8_t* dst_ptr, int width); void ARGBMirrorRow_Any_MSA(const uint8_t* src_ptr, uint8_t* dst_ptr, int width);
void ARGBMirrorRow_Any_MMI(const uint8_t* src_ptr, uint8_t* dst_ptr, int width); void ARGBMirrorRow_Any_MMI(const uint8_t* src_ptr, uint8_t* dst_ptr, int width);
void RGB24MirrorRow_SSSE3(const uint8_t* src, uint8_t* dst, int width);
void RGB24MirrorRow_NEON(const uint8_t* src, uint8_t* dst, int width);
void RGB24MirrorRow_C(const uint8_t* src, uint8_t* dst, int width);
void RGB24MirrorRow_Any_SSSE3(const uint8_t* src_ptr,
uint8_t* dst_ptr,
int width);
void RGB24MirrorRow_Any_NEON(const uint8_t* src_ptr,
uint8_t* dst_ptr,
int width);
void SplitUVRow_C(const uint8_t* src_uv, void SplitUVRow_C(const uint8_t* src_uv,
uint8_t* dst_u, uint8_t* dst_u,
uint8_t* dst_v, uint8_t* dst_v,

View File

@ -86,10 +86,14 @@ enum FourCC {
FOURCC_YV16 = FOURCC('Y', 'V', '1', '6'), FOURCC_YV16 = FOURCC('Y', 'V', '1', '6'),
FOURCC_YV24 = FOURCC('Y', 'V', '2', '4'), FOURCC_YV24 = FOURCC('Y', 'V', '2', '4'),
FOURCC_YU12 = FOURCC('Y', 'U', '1', '2'), // Linux version of I420. FOURCC_YU12 = FOURCC('Y', 'U', '1', '2'), // Linux version of I420.
FOURCC_J420 = FOURCC('J', '4', '2', '0'), // jpeg (bt.601 full), unofficial fourcc FOURCC_J420 =
FOURCC_J422 = FOURCC('J', '4', '2', '2'), // jpeg (bt.601 full), unofficial fourcc FOURCC('J', '4', '2', '0'), // jpeg (bt.601 full), unofficial fourcc
FOURCC_J444 = FOURCC('J', '4', '4', '4'), // jpeg (bt.601 full), unofficial fourcc FOURCC_J422 =
FOURCC_J400 = FOURCC('J', '4', '0', '0'), // jpeg (bt.601 full), unofficial fourcc FOURCC('J', '4', '2', '2'), // jpeg (bt.601 full), unofficial fourcc
FOURCC_J444 =
FOURCC('J', '4', '4', '4'), // jpeg (bt.601 full), unofficial fourcc
FOURCC_J400 =
FOURCC('J', '4', '0', '0'), // jpeg (bt.601 full), unofficial fourcc
FOURCC_H420 = FOURCC('H', '4', '2', '0'), // bt.709, unofficial fourcc FOURCC_H420 = FOURCC('H', '4', '2', '0'), // bt.709, unofficial fourcc
FOURCC_H422 = FOURCC('H', '4', '2', '2'), // bt.709, unofficial fourcc FOURCC_H422 = FOURCC('H', '4', '2', '2'), // bt.709, unofficial fourcc
FOURCC_H444 = FOURCC('H', '4', '4', '4'), // bt.709, unofficial fourcc FOURCC_H444 = FOURCC('H', '4', '4', '4'), // bt.709, unofficial fourcc

View File

@ -1599,8 +1599,7 @@ int RGB24ToJ420(const uint8_t* src_rgb24,
int height) { int height) {
int y; int y;
#if (defined(HAS_RGB24TOYJROW_NEON) && defined(HAS_RGB24TOUVJROW_NEON)) || \ #if (defined(HAS_RGB24TOYJROW_NEON) && defined(HAS_RGB24TOUVJROW_NEON)) || \
defined(HAS_RGB24TOYJROW_MSA) || \ defined(HAS_RGB24TOYJROW_MSA) || defined(HAS_RGB24TOYJROW_MMI)
defined(HAS_RGB24TOYJROW_MMI)
void (*RGB24ToUVJRow)(const uint8_t* src_rgb24, int src_stride_rgb24, void (*RGB24ToUVJRow)(const uint8_t* src_rgb24, int src_stride_rgb24,
uint8_t* dst_u, uint8_t* dst_v, int width) = uint8_t* dst_u, uint8_t* dst_v, int width) =
RGB24ToUVJRow_C; RGB24ToUVJRow_C;
@ -1748,8 +1747,7 @@ int RAWToI420(const uint8_t* src_raw,
int height) { int height) {
int y; int y;
#if (defined(HAS_RAWTOYROW_NEON) && defined(HAS_RAWTOUVROW_NEON)) || \ #if (defined(HAS_RAWTOYROW_NEON) && defined(HAS_RAWTOUVROW_NEON)) || \
defined(HAS_RAWTOYROW_MSA) || \ defined(HAS_RAWTOYROW_MSA) || defined(HAS_RAWTOYROW_MMI)
defined(HAS_RAWTOYROW_MMI)
void (*RAWToUVRow)(const uint8_t* src_raw, int src_stride_raw, uint8_t* dst_u, void (*RAWToUVRow)(const uint8_t* src_raw, int src_stride_raw, uint8_t* dst_u,
uint8_t* dst_v, int width) = RAWToUVRow_C; uint8_t* dst_v, int width) = RAWToUVRow_C;
void (*RAWToYRow)(const uint8_t* src_raw, uint8_t* dst_y, int width) = void (*RAWToYRow)(const uint8_t* src_raw, uint8_t* dst_y, int width) =

View File

@ -1270,9 +1270,6 @@ static int I210ToARGBMatrix(const uint16_t* src_y,
return 0; return 0;
} }
// Convert I210 to ARGB. // Convert I210 to ARGB.
LIBYUV_API LIBYUV_API
int I210ToARGB(const uint16_t* src_y, int I210ToARGB(const uint16_t* src_y,

View File

@ -1132,7 +1132,7 @@ int ARGBMirror(const uint8_t* src_argb,
#if defined(HAS_ARGBMIRRORROW_NEON) #if defined(HAS_ARGBMIRRORROW_NEON)
if (TestCpuFlag(kCpuHasNEON)) { if (TestCpuFlag(kCpuHasNEON)) {
ARGBMirrorRow = ARGBMirrorRow_Any_NEON; ARGBMirrorRow = ARGBMirrorRow_Any_NEON;
if (IS_ALIGNED(width, 4)) { if (IS_ALIGNED(width, 16)) {
ARGBMirrorRow = ARGBMirrorRow_NEON; ARGBMirrorRow = ARGBMirrorRow_NEON;
} }
} }
@ -1179,6 +1179,52 @@ int ARGBMirror(const uint8_t* src_argb,
return 0; return 0;
} }
// RGB24 mirror.
LIBYUV_API
int RGB24Mirror(const uint8_t* src_rgb24,
int src_stride_rgb24,
uint8_t* dst_rgb24,
int dst_stride_rgb24,
int width,
int height) {
int y;
void (*RGB24MirrorRow)(const uint8_t* src, uint8_t* dst, int width) =
RGB24MirrorRow_C;
if (!src_rgb24 || !dst_rgb24 || width <= 0 || height == 0) {
return -1;
}
// Negative height means invert the image.
if (height < 0) {
height = -height;
src_rgb24 = src_rgb24 + (height - 1) * src_stride_rgb24;
src_stride_rgb24 = -src_stride_rgb24;
}
#if defined(HAS_RGB24MIRRORROW_NEON)
if (TestCpuFlag(kCpuHasNEON)) {
RGB24MirrorRow = RGB24MirrorRow_Any_NEON;
if (IS_ALIGNED(width, 16)) {
RGB24MirrorRow = RGB24MirrorRow_NEON;
}
}
#endif
#if defined(HAS_RGB24MIRRORROW_SSSE3)
if (TestCpuFlag(kCpuHasSSSE3)) {
RGB24MirrorRow = RGB24MirrorRow_Any_SSSE3;
if (IS_ALIGNED(width, 16)) {
RGB24MirrorRow = RGB24MirrorRow_SSSE3;
}
}
#endif
// Mirror plane
for (y = 0; y < height; ++y) {
RGB24MirrorRow(src_rgb24, dst_rgb24, width);
src_rgb24 += src_stride_rgb24;
dst_rgb24 += dst_stride_rgb24;
}
return 0;
}
// Get a blender that optimized for the CPU and pixel count. // Get a blender that optimized for the CPU and pixel count.
// As there are 6 blenders to choose from, the caller should try to use // As there are 6 blenders to choose from, the caller should try to use
// the same blend function for all pixels if possible. // the same blend function for all pixels if possible.

View File

@ -126,7 +126,7 @@ static int ARGBRotate180(const uint8_t* src_argb,
#if defined(HAS_ARGBMIRRORROW_NEON) #if defined(HAS_ARGBMIRRORROW_NEON)
if (TestCpuFlag(kCpuHasNEON)) { if (TestCpuFlag(kCpuHasNEON)) {
ARGBMirrorRow = ARGBMirrorRow_Any_NEON; ARGBMirrorRow = ARGBMirrorRow_Any_NEON;
if (IS_ALIGNED(width, 4)) { if (IS_ALIGNED(width, 16)) {
ARGBMirrorRow = ARGBMirrorRow_NEON; ARGBMirrorRow = ARGBMirrorRow_NEON;
} }
} }

View File

@ -1189,7 +1189,7 @@ ANY11M(ARGBMirrorRow_Any_AVX2, ARGBMirrorRow_AVX2, 4, 7)
ANY11M(ARGBMirrorRow_Any_SSE2, ARGBMirrorRow_SSE2, 4, 3) ANY11M(ARGBMirrorRow_Any_SSE2, ARGBMirrorRow_SSE2, 4, 3)
#endif #endif
#ifdef HAS_ARGBMIRRORROW_NEON #ifdef HAS_ARGBMIRRORROW_NEON
ANY11M(ARGBMirrorRow_Any_NEON, ARGBMirrorRow_NEON, 4, 3) ANY11M(ARGBMirrorRow_Any_NEON, ARGBMirrorRow_NEON, 4, 15)
#endif #endif
#ifdef HAS_ARGBMIRRORROW_MSA #ifdef HAS_ARGBMIRRORROW_MSA
ANY11M(ARGBMirrorRow_Any_MSA, ARGBMirrorRow_MSA, 4, 15) ANY11M(ARGBMirrorRow_Any_MSA, ARGBMirrorRow_MSA, 4, 15)
@ -1197,6 +1197,12 @@ ANY11M(ARGBMirrorRow_Any_MSA, ARGBMirrorRow_MSA, 4, 15)
#ifdef HAS_ARGBMIRRORROW_MMI #ifdef HAS_ARGBMIRRORROW_MMI
ANY11M(ARGBMirrorRow_Any_MMI, ARGBMirrorRow_MMI, 4, 1) ANY11M(ARGBMirrorRow_Any_MMI, ARGBMirrorRow_MMI, 4, 1)
#endif #endif
#ifdef HAS_RGB24MIRRORROW_SSSE3
ANY11M(RGB24MirrorRow_Any_SSSE3, RGB24MirrorRow_SSSE3, 3, 15)
#endif
#ifdef HAS_RGB24MIRRORROW_NEON
ANY11M(RGB24MirrorRow_Any_NEON, RGB24MirrorRow_NEON, 3, 15)
#endif
#undef ANY11M #undef ANY11M
// Any 1 plane. (memset) // Any 1 plane. (memset)

View File

@ -2201,6 +2201,22 @@ void ARGBMirrorRow_C(const uint8_t* src, uint8_t* dst, int width) {
} }
} }
void RGB24MirrorRow_C(const uint8_t* src_rgb24, uint8_t* dst_rgb24,
int width) {
int x;
src_rgb24 += width * 3 - 3;
for (x = 0; x < width; ++x) {
uint8_t b = src_rgb24[0];
uint8_t g = src_rgb24[1];
uint8_t r = src_rgb24[2];
dst_rgb24[0] = b;
dst_rgb24[1] = g;
dst_rgb24[2] = r;
src_rgb24 -= 3;
dst_rgb24 += 3;
}
}
void SplitUVRow_C(const uint8_t* src_uv, void SplitUVRow_C(const uint8_t* src_uv,
uint8_t* dst_u, uint8_t* dst_u,
uint8_t* dst_v, uint8_t* dst_v,
@ -3321,7 +3337,7 @@ void RGB24ToYJRow_AVX2(const uint8_t* src_rgb24, uint8_t* dst_yj, int width) {
width -= twidth; width -= twidth;
} }
} }
#endif //HAS_RGB24TOYJROW_AVX2 #endif // HAS_RGB24TOYJROW_AVX2
#ifdef HAS_RAWTOYJROW_AVX2 #ifdef HAS_RAWTOYJROW_AVX2
// Convert 16 RAW pixels (64 bytes) to 16 YJ values. // Convert 16 RAW pixels (64 bytes) to 16 YJ values.
@ -3337,7 +3353,7 @@ void RAWToYJRow_AVX2(const uint8_t* src_raw, uint8_t* dst_yj, int width) {
width -= twidth; width -= twidth;
} }
} }
#endif //HAS_RAWTOYJROW_AVX2 #endif // HAS_RAWTOYJROW_AVX2
#ifdef HAS_RGB24TOYJROW_SSSE3 #ifdef HAS_RGB24TOYJROW_SSSE3
// Convert 16 RGB24 pixels (64 bytes) to 16 YJ values. // Convert 16 RGB24 pixels (64 bytes) to 16 YJ values.
@ -3353,7 +3369,7 @@ void RGB24ToYJRow_SSSE3(const uint8_t* src_rgb24, uint8_t* dst_yj, int width) {
width -= twidth; width -= twidth;
} }
} }
#endif //HAS_RGB24TOYJROW_SSSE3 #endif // HAS_RGB24TOYJROW_SSSE3
#ifdef HAS_RAWTOYJROW_SSSE3 #ifdef HAS_RAWTOYJROW_SSSE3
// Convert 16 RAW pixels (64 bytes) to 16 YJ values. // Convert 16 RAW pixels (64 bytes) to 16 YJ values.
@ -3369,7 +3385,7 @@ void RAWToYJRow_SSSE3(const uint8_t* src_raw, uint8_t* dst_yj, int width) {
width -= twidth; width -= twidth;
} }
} }
#endif //HAS_RAWTOYJROW_SSSE3 #endif // HAS_RAWTOYJROW_SSSE3
float ScaleSumSamples_C(const float* src, float* dst, float scale, int width) { float ScaleSumSamples_C(const float* src, float* dst, float scale, int width) {
float fsum = 0.f; float fsum = 0.f;
@ -3427,8 +3443,8 @@ void GaussCol_C(const uint16_t* src0,
void GaussRow_F32_C(const float* src, float* dst, int width) { void GaussRow_F32_C(const float* src, float* dst, int width) {
int i; int i;
for (i = 0; i < width; ++i) { for (i = 0; i < width; ++i) {
*dst++ = *dst++ = (src[0] + src[1] * 4 + src[2] * 6 + src[3] * 4 + src[4]) *
(src[0] + src[1] * 4 + src[2] * 6 + src[3] * 4 + src[4]) * (1.0f / 256.0f); (1.0f / 256.0f);
++src; ++src;
} }
} }

View File

@ -3262,6 +3262,52 @@ void MirrorUVRow_SSSE3(const uint8_t* src,
} }
#endif // HAS_MIRRORUVROW_SSSE3 #endif // HAS_MIRRORUVROW_SSSE3
#ifdef HAS_RGB24MIRRORROW_SSSE3
// Shuffle first 5 pixels to last 5 mirrored. first byte zero
static const uvec8 kShuffleMirrorRGB0 = {128u, 12u, 13u, 14u, 9u, 10u, 11u, 6u,
7u, 8u, 3u, 4u, 5u, 0u, 1u, 2u};
// Shuffle last 5 pixels to first 5 mirrored. last byte zero
static const uvec8 kShuffleMirrorRGB1 = {13u, 14u, 15u, 10u, 11u, 12u, 7u,
8u, 9u, 4u, 5u, 6u, 1u, 2u, 3u, 128u};
// Shuffle 5 pixels at a time (15 bytes)
void RGB24MirrorRow_SSSE3(const uint8_t* src_rgb24, uint8_t* dst_rgb24,
int width) {
intptr_t temp_width = (intptr_t)(width);
src_rgb24 += width * 3 - 48;
asm volatile(
"movdqa %3,%%xmm4 \n"
"movdqa %4,%%xmm5 \n"
LABELALIGN
"1: \n"
"movdqu (%0),%%xmm0 \n" // first 5
"movdqu 15(%0),%%xmm1 \n" // next 5
"movdqu 30(%0),%%xmm2 \n" // next 5
"movdqu 32(%0),%%xmm3 \n" // last 1 special
"pshufb %%xmm4,%%xmm0 \n"
"pshufb %%xmm4,%%xmm1 \n"
"pshufb %%xmm4,%%xmm2 \n"
"pshufb %%xmm5,%%xmm3 \n"
"lea -0x30(%0),%0 \n"
"movdqu %%xmm0,32(%1) \n" // last 5
"movdqu %%xmm1,17(%1) \n" // next 5
"movdqu %%xmm2,2(%1) \n" // next 5
"movlpd %%xmm3,0(%1) \n" // first 1
"lea 0x30(%1),%1 \n"
"sub $0x10,%2 \n"
"jg 1b \n"
: "+r"(src_rgb24), // %0
"+r"(dst_rgb24), // %1
"+r"(temp_width) // %2
: "m"(kShuffleMirrorRGB0), // %3
"m"(kShuffleMirrorRGB1) // %4
: "memory", "cc", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5");
}
#endif // HAS_RGB24MIRRORROW_SSSE3
#ifdef HAS_ARGBMIRRORROW_SSE2 #ifdef HAS_ARGBMIRRORROW_SSE2
void ARGBMirrorRow_SSE2(const uint8_t* src, uint8_t* dst, int width) { void ARGBMirrorRow_SSE2(const uint8_t* src, uint8_t* dst, int width) {

File diff suppressed because it is too large Load Diff

View File

@ -727,14 +727,10 @@ void MirrorUVRow_NEON(const uint8_t* src_uv,
} }
void ARGBMirrorRow_NEON(const uint8_t* src, uint8_t* dst, int width) { void ARGBMirrorRow_NEON(const uint8_t* src, uint8_t* dst, int width) {
src += width * 4 - 16;
asm volatile( asm volatile(
// Start at end of source row.
"mov r3, #-16 \n"
"add %0, %0, %2, lsl #2 \n"
"sub %0, #16 \n"
"1: \n" "1: \n"
"vld1.8 {q0}, [%0], r3 \n" // src -= 16 "vld1.8 {q0}, [%0], %3 \n" // src -= 16
"subs %2, #4 \n" // 4 pixels per loop. "subs %2, #4 \n" // 4 pixels per loop.
"vrev64.32 q0, q0 \n" "vrev64.32 q0, q0 \n"
"vst1.8 {d1}, [%1]! \n" // dst += 16 "vst1.8 {d1}, [%1]! \n" // dst += 16
@ -743,12 +739,30 @@ void ARGBMirrorRow_NEON(const uint8_t* src, uint8_t* dst, int width) {
: "+r"(src), // %0 : "+r"(src), // %0
"+r"(dst), // %1 "+r"(dst), // %1
"+r"(width) // %2 "+r"(width) // %2
: : "r"(-16) // %3
: "cc", "memory", "r3", "q0"); : "cc", "memory", "q0");
} }
void RGB24ToARGBRow_NEON(const uint8_t* src_rgb24, void RGB24MirrorRow_NEON(const uint8_t* src_rgb24, uint8_t* dst_rgb24,
uint8_t* dst_argb, int width) {
src_rgb24 += width * 3 - 24;
asm volatile(
"1: \n"
"vld3.8 {d0, d1, d2}, [%0], %3 \n" // src -= 24
"subs %2, #8 \n" // 8 pixels per loop.
"vrev64.8 d0, d0 \n"
"vrev64.8 d1, d1 \n"
"vrev64.8 d2, d2 \n"
"vst3.8 {d0, d1, d2}, [%1]! \n" // dst += 24
"bgt 1b \n"
: "+r"(src_rgb24), // %0
"+r"(dst_rgb24), // %1
"+r"(width) // %2
: "r"(-24) // %3
: "cc", "memory", "d0", "d1", "d2");
}
void RGB24ToARGBRow_NEON(const uint8_t* src_rgb24, uint8_t* dst_argb,
int width) { int width) {
asm volatile( asm volatile(
"vmov.u8 d4, #255 \n" // Alpha "vmov.u8 d4, #255 \n" // Alpha
@ -2065,7 +2079,6 @@ void RAWToYRow_NEON(const uint8_t* src_raw, uint8_t* dst_y, int width) {
: "cc", "memory", "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", "q8"); : "cc", "memory", "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", "q8");
} }
void RGB24ToYJRow_NEON(const uint8_t* src_rgb24, uint8_t* dst_yj, int width) { void RGB24ToYJRow_NEON(const uint8_t* src_rgb24, uint8_t* dst_yj, int width) {
asm volatile( asm volatile(
"vmov.u8 d4, #29 \n" // B * 0.1140 coefficient "vmov.u8 d4, #29 \n" // B * 0.1140 coefficient

View File

@ -278,7 +278,8 @@ void I422ToRGB565Row_NEON(const uint8_t* src_y,
v20) "subs %w4, %w4, #8 \n" ARGBTORGB565 v20) "subs %w4, %w4, #8 \n" ARGBTORGB565
"st1 {v0.8h}, [%3], #16 \n" // store 8 pixels "st1 {v0.8h}, [%3], #16 \n" // store 8 pixels
// RGB565. // RGB565.
"prfm pldl1keep, [%0, 448] \n" // prefetch 7 lines ahead "prfm pldl1keep, [%0, 448] \n" // prefetch 7
// lines ahead
"b.gt 1b \n" "b.gt 1b \n"
: "+r"(src_y), // %0 : "+r"(src_y), // %0
"+r"(src_u), // %1 "+r"(src_u), // %1
@ -316,7 +317,8 @@ void I422ToARGB1555Row_NEON(const uint8_t* src_y,
v20) "subs %w4, %w4, #8 \n" ARGBTOARGB1555 v20) "subs %w4, %w4, #8 \n" ARGBTOARGB1555
"st1 {v0.8h}, [%3], #16 \n" // store 8 pixels "st1 {v0.8h}, [%3], #16 \n" // store 8 pixels
// RGB565. // RGB565.
"prfm pldl1keep, [%0, 448] \n" // prefetch 7 lines ahead "prfm pldl1keep, [%0, 448] \n" // prefetch 7
// lines ahead
"b.gt 1b \n" "b.gt 1b \n"
: "+r"(src_y), // %0 : "+r"(src_y), // %0
"+r"(src_u), // %1 "+r"(src_u), // %1
@ -530,7 +532,8 @@ void NV12ToRGB565Row_NEON(const uint8_t* src_y,
v20) "subs %w3, %w3, #8 \n" ARGBTORGB565 v20) "subs %w3, %w3, #8 \n" ARGBTORGB565
"st1 {v0.8h}, [%2], 16 \n" // store 8 pixels "st1 {v0.8h}, [%2], 16 \n" // store 8 pixels
// RGB565. // RGB565.
"prfm pldl1keep, [%0, 448] \n" // prefetch 7 lines ahead "prfm pldl1keep, [%0, 448] \n" // prefetch 7
// lines ahead
"b.gt 1b \n" "b.gt 1b \n"
: "+r"(src_y), // %0 : "+r"(src_y), // %0
"+r"(src_uv), // %1 "+r"(src_uv), // %1
@ -750,7 +753,6 @@ void MirrorRow_NEON(const uint8_t* src, uint8_t* dst, int width) {
"tbl v1.16b, {v1.16b}, v3.16b \n" "tbl v1.16b, {v1.16b}, v3.16b \n"
"tbl v0.16b, {v2.16b}, v3.16b \n" "tbl v0.16b, {v2.16b}, v3.16b \n"
"st1 {v0.16b, v1.16b}, [%1], #32 \n" // store 32 pixels "st1 {v0.16b, v1.16b}, [%1], #32 \n" // store 32 pixels
"prfm pldl1keep, [%0, 448] \n" // prefetch 7 lines ahead
"b.gt 1b \n" "b.gt 1b \n"
: "+r"(src), // %0 : "+r"(src), // %0
"+r"(dst), // %1 "+r"(dst), // %1
@ -775,7 +777,6 @@ void MirrorUVRow_NEON(const uint8_t* src_uv,
"rev64 v1.8b, v1.8b \n" "rev64 v1.8b, v1.8b \n"
"st1 {v0.8b}, [%1], #8 \n" // dst += 8 "st1 {v0.8b}, [%1], #8 \n" // dst += 8
"st1 {v1.8b}, [%2], #8 \n" "st1 {v1.8b}, [%2], #8 \n"
"prfm pldl1keep, [%0, 448] \n" // prefetch 7 lines ahead
"b.gt 1b \n" "b.gt 1b \n"
: "+r"(src_uv), // %0 : "+r"(src_uv), // %0
"+r"(dst_u), // %1 "+r"(dst_u), // %1
@ -785,24 +786,49 @@ void MirrorUVRow_NEON(const uint8_t* src_uv,
: "cc", "memory", "v0", "v1"); : "cc", "memory", "v0", "v1");
} }
void ARGBMirrorRow_NEON(const uint8_t* src, uint8_t* dst, int width) { void ARGBMirrorRow_NEON(const uint8_t* src_argb, uint8_t* dst_argb,
int width) {
asm volatile( asm volatile(
// Start at end of source row. "ld1 {v4.16b}, [%4] \n" // shuffler
"add %0, %0, %w2, sxtw #2 \n" "add %0, %0, %w2, sxtw #2 \n" // Start at end of row.
"sub %0, %0, #16 \n" "sub %0, %0, #64 \n"
"1: \n" "1: \n"
"ld1 {v0.16b}, [%0], %3 \n" // src -= 16 "ld4 {v0.16b, v1.16b, v2.16b, v3.16b}, [%0], %3\n" // src -= 64
"subs %w2, %w2, #4 \n" // 4 pixels per loop. "subs %w2, %w2, #16 \n" // 16 pixels per loop.
"rev64 v0.4s, v0.4s \n" "tbl v0.16b, {v0.16b}, v4.16b \n"
"st1 {v0.D}[1], [%1], #8 \n" // dst += 16 "tbl v1.16b, {v1.16b}, v4.16b \n"
"st1 {v0.D}[0], [%1], #8 \n" "tbl v2.16b, {v2.16b}, v4.16b \n"
"prfm pldl1keep, [%0, 448] \n" // prefetch 7 lines ahead "tbl v3.16b, {v3.16b}, v4.16b \n"
"st4 {v0.16b, v1.16b, v2.16b, v3.16b}, [%1], #64 \n" // dst += 64
"b.gt 1b \n" "b.gt 1b \n"
: "+r"(src), // %0 : "+r"(src_argb), // %0
"+r"(dst), // %1 "+r"(dst_argb), // %1
"+r"(width) // %2 "+r"(width) // %2
: "r"((ptrdiff_t)-16) // %3 : "r"((ptrdiff_t)-64), // %3
: "cc", "memory", "v0"); "r"(&kShuffleMirror) // %4
: "cc", "memory", "v0", "v1", "v2", "v3", "v4");
}
void RGB24MirrorRow_NEON(const uint8_t* src_rgb24, uint8_t* dst_rgb24,
int width) {
src_rgb24 += width * 3 - 48;
asm volatile(
"ld1 {v3.16b}, [%4] \n" // shuffler
"1: \n"
"ld3 {v0.16b, v1.16b, v2.16b}, [%0], %3\n" // src -= 48
"subs %w2, %w2, #16 \n" // 16 pixels per loop.
"tbl v0.16b, {v0.16b}, v3.16b \n"
"tbl v1.16b, {v1.16b}, v3.16b \n"
"tbl v2.16b, {v2.16b}, v3.16b \n"
"st3 {v0.16b, v1.16b, v2.16b}, [%1], #48 \n" // dst += 48
"b.gt 1b \n"
: "+r"(src_rgb24), // %0
"+r"(dst_rgb24), // %1
"+r"(width) // %2
: "r"((ptrdiff_t)-48), // %3
"r"(&kShuffleMirror) // %4
: "cc", "memory", "v0", "v1", "v2", "v3");
} }
void RGB24ToARGBRow_NEON(const uint8_t* src_rgb24, void RGB24ToARGBRow_NEON(const uint8_t* src_rgb24,
@ -2185,7 +2211,8 @@ void RAWToYJRow_NEON(const uint8_t* src_raw, uint8_t* dst_yj, int width) {
"umull v0.8h, v0.8b, v4.8b \n" // B "umull v0.8h, v0.8b, v4.8b \n" // B
"umlal v0.8h, v1.8b, v5.8b \n" // G "umlal v0.8h, v1.8b, v5.8b \n" // G
"umlal v0.8h, v2.8b, v6.8b \n" // R "umlal v0.8h, v2.8b, v6.8b \n" // R
"prfm pldl1keep, [%0, 448] \n" // prefetch 7 cache lines ahead "prfm pldl1keep, [%0, 448] \n" // prefetch 7 cache lines
// ahead
"uqrshrn v0.8b, v0.8h, #8 \n" // 16 bit to 8 bit Y "uqrshrn v0.8b, v0.8h, #8 \n" // 16 bit to 8 bit Y
"st1 {v0.8b}, [%1], #8 \n" // store 8 pixels Y. "st1 {v0.8b}, [%1], #8 \n" // store 8 pixels Y.
"prfm pldl1keep, [%0, 448] \n" // prefetch 7 lines ahead "prfm pldl1keep, [%0, 448] \n" // prefetch 7 lines ahead
@ -3089,9 +3116,7 @@ void GaussCol_F32_NEON(const float* src0,
} }
// filter 5 rows with 1, 4, 6, 4, 1 coefficients to produce 1 row. // filter 5 rows with 1, 4, 6, 4, 1 coefficients to produce 1 row.
void GaussRow_F32_NEON(const float* src, void GaussRow_F32_NEON(const float* src, float* dst, int width) {
float* dst,
int width) {
asm volatile( asm volatile(
"ld3r {v6.4s, v7.4s, v8.4s}, [%3] \n" // constants 4, 6, 1/256 "ld3r {v6.4s, v7.4s, v8.4s}, [%3] \n" // constants 4, 6, 1/256

View File

@ -1245,6 +1245,7 @@ TESTATOB(RAW, 3, 3, 1, RGBA, 4, 4, 1, 0)
TESTATOB(RAW, 3, 3, 1, RGB24, 3, 3, 1, 0) TESTATOB(RAW, 3, 3, 1, RGB24, 3, 3, 1, 0)
TESTATOB(RGB24, 3, 3, 1, ARGB, 4, 4, 1, 0) TESTATOB(RGB24, 3, 3, 1, ARGB, 4, 4, 1, 0)
TESTATOB(RGB24, 3, 3, 1, J400, 1, 1, 1, 0) TESTATOB(RGB24, 3, 3, 1, J400, 1, 1, 1, 0)
TESTATOB(RGB24, 3, 3, 1, RGB24Mirror, 3, 3, 1, 0)
TESTATOB(RAW, 3, 3, 1, J400, 1, 1, 1, 0) TESTATOB(RAW, 3, 3, 1, J400, 1, 1, 1, 0)
#ifdef INTEL_TEST #ifdef INTEL_TEST
TESTATOB(RGB565, 2, 2, 1, ARGB, 4, 4, 1, 0) TESTATOB(RGB565, 2, 2, 1, ARGB, 4, 4, 1, 0)

View File

@ -574,13 +574,15 @@ TEST_FACTOR(3, 1, 3, 0)
disable_cpu_flags_, benchmark_cpu_info_); \ disable_cpu_flags_, benchmark_cpu_info_); \
EXPECT_LE(diff, max_diff); \ EXPECT_LE(diff, max_diff); \
} \ } \
TEST_F(LibYUVScaleTest, DISABLED_##I420##name##To##width##x##height##_##filter##_16) { \ TEST_F(LibYUVScaleTest, \
DISABLED_##I420##name##To##width##x##height##_##filter##_16) { \
int diff = I420TestFilter_16( \ int diff = I420TestFilter_16( \
benchmark_width_, benchmark_height_, width, height, kFilter##filter, \ benchmark_width_, benchmark_height_, width, height, kFilter##filter, \
benchmark_iterations_, disable_cpu_flags_, benchmark_cpu_info_); \ benchmark_iterations_, disable_cpu_flags_, benchmark_cpu_info_); \
EXPECT_LE(diff, max_diff); \ EXPECT_LE(diff, max_diff); \
} \ } \
TEST_F(LibYUVScaleTest, DISABLED_##I444##name##To##width##x##height##_##filter##_16) { \ TEST_F(LibYUVScaleTest, \
DISABLED_##I444##name##To##width##x##height##_##filter##_16) { \
int diff = I444TestFilter_16( \ int diff = I444TestFilter_16( \
benchmark_width_, benchmark_height_, width, height, kFilter##filter, \ benchmark_width_, benchmark_height_, width, height, kFilter##filter, \
benchmark_iterations_, disable_cpu_flags_, benchmark_cpu_info_); \ benchmark_iterations_, disable_cpu_flags_, benchmark_cpu_info_); \
@ -625,7 +627,7 @@ TEST_FACTOR(3, 1, 3, 0)
TEST_SCALETO1(, name, width, height, Bilinear, 3) \ TEST_SCALETO1(, name, width, height, Bilinear, 3) \
TEST_SCALETO1(, name, width, height, Box, 3) TEST_SCALETO1(, name, width, height, Box, 3)
#else #else
// Test scale to a specified size with all 4 filters. // Test scale to a specified size with all 4 filters.
#define TEST_SCALETO(name, width, height) \ #define TEST_SCALETO(name, width, height) \
TEST_SCALETO1(DISABLED_, name, width, height, None, 0) \ TEST_SCALETO1(DISABLED_, name, width, height, None, 0) \
TEST_SCALETO1(DISABLED_, name, width, height, Linear, 3) \ TEST_SCALETO1(DISABLED_, name, width, height, Linear, 3) \
@ -898,7 +900,7 @@ static int TestPlaneFilter_16(int src_width,
#define SX(x, nom, denom) static_cast<int>(((x / nom + 1) / 2) * denom * 2) #define SX(x, nom, denom) static_cast<int>(((x / nom + 1) / 2) * denom * 2)
#define TEST_FACTOR1(name, filter, nom, denom, max_diff) \ #define TEST_FACTOR1(name, filter, nom, denom, max_diff) \
TEST_F(LibYUVScaleTest, DISABLED_##ScalePlaneDownBy##name##_##filter##_16) {\ TEST_F(LibYUVScaleTest, DISABLED_##ScalePlaneDownBy##name##_##filter##_16) { \
int diff = TestPlaneFilter_16( \ int diff = TestPlaneFilter_16( \
SX(benchmark_width_, nom, denom), SX(benchmark_height_, nom, denom), \ SX(benchmark_width_, nom, denom), SX(benchmark_height_, nom, denom), \
DX(benchmark_width_, nom, denom), DX(benchmark_height_, nom, denom), \ DX(benchmark_width_, nom, denom), DX(benchmark_height_, nom, denom), \