First Commit
This commit is contained in:
43
externals/libyuv/unit_test/basictypes_test.cc
vendored
Normal file
43
externals/libyuv/unit_test/basictypes_test.cc
vendored
Normal file
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Copyright 2012 The LibYuv Project Authors. All rights reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#include "../unit_test/unit_test.h"
|
||||
#include "libyuv/basic_types.h"
|
||||
|
||||
namespace libyuv {
|
||||
|
||||
TEST_F(LibYUVBaseTest, SizeOfTypes) {
|
||||
int8_t i8 = -1;
|
||||
uint8_t u8 = 1u;
|
||||
int16_t i16 = -1;
|
||||
uint16_t u16 = 1u;
|
||||
int32_t i32 = -1;
|
||||
uint32_t u32 = 1u;
|
||||
int64_t i64 = -1;
|
||||
uint64_t u64 = 1u;
|
||||
EXPECT_EQ(1u, sizeof(i8));
|
||||
EXPECT_EQ(1u, sizeof(u8));
|
||||
EXPECT_EQ(2u, sizeof(i16));
|
||||
EXPECT_EQ(2u, sizeof(u16));
|
||||
EXPECT_EQ(4u, sizeof(i32));
|
||||
EXPECT_EQ(4u, sizeof(u32));
|
||||
EXPECT_EQ(8u, sizeof(i64));
|
||||
EXPECT_EQ(8u, sizeof(u64));
|
||||
EXPECT_GT(0, i8);
|
||||
EXPECT_LT(0u, u8);
|
||||
EXPECT_GT(0, i16);
|
||||
EXPECT_LT(0u, u16);
|
||||
EXPECT_GT(0, i32);
|
||||
EXPECT_LT(0u, u32);
|
||||
EXPECT_GT(0, i64);
|
||||
EXPECT_LT(0u, u64);
|
||||
}
|
||||
|
||||
} // namespace libyuv
|
||||
848
externals/libyuv/unit_test/color_test.cc
vendored
Normal file
848
externals/libyuv/unit_test/color_test.cc
vendored
Normal file
@@ -0,0 +1,848 @@
|
||||
/*
|
||||
* Copyright 2015 The LibYuv Project Authors. All rights reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "../unit_test/unit_test.h"
|
||||
#include "libyuv/basic_types.h"
|
||||
#include "libyuv/convert.h"
|
||||
#include "libyuv/convert_argb.h"
|
||||
#include "libyuv/convert_from.h"
|
||||
#include "libyuv/convert_from_argb.h"
|
||||
#include "libyuv/cpu_id.h"
|
||||
|
||||
namespace libyuv {
|
||||
|
||||
// TODO(fbarchard): clang x86 has a higher accuracy YUV to RGB.
|
||||
// Port to Visual C and other CPUs
|
||||
#if !defined(LIBYUV_BIT_EXACT) && !defined(LIBYUV_DISABLE_X86) && \
|
||||
(defined(__x86_64__) || defined(__i386__))
|
||||
#define ERROR_FULL 5
|
||||
#define ERROR_J420 4
|
||||
#else
|
||||
#define ERROR_FULL 6
|
||||
#define ERROR_J420 6
|
||||
#endif
|
||||
#define ERROR_R 1
|
||||
#define ERROR_G 1
|
||||
#ifdef LIBYUV_UNLIMITED_DATA
|
||||
#define ERROR_B 1
|
||||
#else
|
||||
#define ERROR_B 18
|
||||
#endif
|
||||
|
||||
#define TESTCS(TESTNAME, YUVTOARGB, ARGBTOYUV, HS1, HS, HN, DIFF) \
|
||||
TEST_F(LibYUVColorTest, TESTNAME) { \
|
||||
const int kPixels = benchmark_width_ * benchmark_height_; \
|
||||
const int kHalfPixels = \
|
||||
((benchmark_width_ + 1) / 2) * ((benchmark_height_ + HS1) / HS); \
|
||||
align_buffer_page_end(orig_y, kPixels); \
|
||||
align_buffer_page_end(orig_u, kHalfPixels); \
|
||||
align_buffer_page_end(orig_v, kHalfPixels); \
|
||||
align_buffer_page_end(orig_pixels, kPixels * 4); \
|
||||
align_buffer_page_end(temp_y, kPixels); \
|
||||
align_buffer_page_end(temp_u, kHalfPixels); \
|
||||
align_buffer_page_end(temp_v, kHalfPixels); \
|
||||
align_buffer_page_end(dst_pixels_opt, kPixels * 4); \
|
||||
align_buffer_page_end(dst_pixels_c, kPixels * 4); \
|
||||
\
|
||||
MemRandomize(orig_pixels, kPixels * 4); \
|
||||
MemRandomize(orig_y, kPixels); \
|
||||
MemRandomize(orig_u, kHalfPixels); \
|
||||
MemRandomize(orig_v, kHalfPixels); \
|
||||
MemRandomize(temp_y, kPixels); \
|
||||
MemRandomize(temp_u, kHalfPixels); \
|
||||
MemRandomize(temp_v, kHalfPixels); \
|
||||
MemRandomize(dst_pixels_opt, kPixels * 4); \
|
||||
MemRandomize(dst_pixels_c, kPixels * 4); \
|
||||
\
|
||||
/* The test is overall for color conversion matrix being reversible, so */ \
|
||||
/* this initializes the pixel with 2x2 blocks to eliminate subsampling. */ \
|
||||
uint8_t* p = orig_y; \
|
||||
for (int y = 0; y < benchmark_height_ - HS1; y += HS) { \
|
||||
for (int x = 0; x < benchmark_width_ - 1; x += 2) { \
|
||||
uint8_t r = static_cast<uint8_t>(fastrand()); \
|
||||
p[0] = r; \
|
||||
p[1] = r; \
|
||||
p[HN] = r; \
|
||||
p[HN + 1] = r; \
|
||||
p += 2; \
|
||||
} \
|
||||
if (benchmark_width_ & 1) { \
|
||||
uint8_t r = static_cast<uint8_t>(fastrand()); \
|
||||
p[0] = r; \
|
||||
p[HN] = r; \
|
||||
p += 1; \
|
||||
} \
|
||||
p += HN; \
|
||||
} \
|
||||
if ((benchmark_height_ & 1) && HS == 2) { \
|
||||
for (int x = 0; x < benchmark_width_ - 1; x += 2) { \
|
||||
uint8_t r = static_cast<uint8_t>(fastrand()); \
|
||||
p[0] = r; \
|
||||
p[1] = r; \
|
||||
p += 2; \
|
||||
} \
|
||||
if (benchmark_width_ & 1) { \
|
||||
uint8_t r = static_cast<uint8_t>(fastrand()); \
|
||||
p[0] = r; \
|
||||
p += 1; \
|
||||
} \
|
||||
} \
|
||||
/* Start with YUV converted to ARGB. */ \
|
||||
YUVTOARGB(orig_y, benchmark_width_, orig_u, (benchmark_width_ + 1) / 2, \
|
||||
orig_v, (benchmark_width_ + 1) / 2, orig_pixels, \
|
||||
benchmark_width_ * 4, benchmark_width_, benchmark_height_); \
|
||||
\
|
||||
ARGBTOYUV(orig_pixels, benchmark_width_ * 4, temp_y, benchmark_width_, \
|
||||
temp_u, (benchmark_width_ + 1) / 2, temp_v, \
|
||||
(benchmark_width_ + 1) / 2, benchmark_width_, \
|
||||
benchmark_height_); \
|
||||
\
|
||||
MaskCpuFlags(disable_cpu_flags_); \
|
||||
YUVTOARGB(temp_y, benchmark_width_, temp_u, (benchmark_width_ + 1) / 2, \
|
||||
temp_v, (benchmark_width_ + 1) / 2, dst_pixels_c, \
|
||||
benchmark_width_ * 4, benchmark_width_, benchmark_height_); \
|
||||
MaskCpuFlags(benchmark_cpu_info_); \
|
||||
\
|
||||
for (int i = 0; i < benchmark_iterations_; ++i) { \
|
||||
YUVTOARGB(temp_y, benchmark_width_, temp_u, (benchmark_width_ + 1) / 2, \
|
||||
temp_v, (benchmark_width_ + 1) / 2, dst_pixels_opt, \
|
||||
benchmark_width_ * 4, benchmark_width_, benchmark_height_); \
|
||||
} \
|
||||
/* Test C and SIMD match. */ \
|
||||
for (int i = 0; i < kPixels * 4; ++i) { \
|
||||
EXPECT_EQ(dst_pixels_c[i], dst_pixels_opt[i]); \
|
||||
} \
|
||||
/* Test SIMD is close to original. */ \
|
||||
for (int i = 0; i < kPixels * 4; ++i) { \
|
||||
EXPECT_NEAR(static_cast<int>(orig_pixels[i]), \
|
||||
static_cast<int>(dst_pixels_opt[i]), DIFF); \
|
||||
} \
|
||||
\
|
||||
free_aligned_buffer_page_end(orig_pixels); \
|
||||
free_aligned_buffer_page_end(orig_y); \
|
||||
free_aligned_buffer_page_end(orig_u); \
|
||||
free_aligned_buffer_page_end(orig_v); \
|
||||
free_aligned_buffer_page_end(temp_y); \
|
||||
free_aligned_buffer_page_end(temp_u); \
|
||||
free_aligned_buffer_page_end(temp_v); \
|
||||
free_aligned_buffer_page_end(dst_pixels_opt); \
|
||||
free_aligned_buffer_page_end(dst_pixels_c); \
|
||||
}
|
||||
|
||||
TESTCS(TestI420, I420ToARGB, ARGBToI420, 1, 2, benchmark_width_, ERROR_FULL)
|
||||
TESTCS(TestI422, I422ToARGB, ARGBToI422, 0, 1, 0, ERROR_FULL)
|
||||
TESTCS(TestJ420, J420ToARGB, ARGBToJ420, 1, 2, benchmark_width_, ERROR_J420)
|
||||
TESTCS(TestJ422, J422ToARGB, ARGBToJ422, 0, 1, 0, ERROR_J420)
|
||||
|
||||
static void YUVToRGB(int y, int u, int v, int* r, int* g, int* b) {
|
||||
const int kWidth = 16;
|
||||
const int kHeight = 1;
|
||||
const int kPixels = kWidth * kHeight;
|
||||
const int kHalfPixels = ((kWidth + 1) / 2) * ((kHeight + 1) / 2);
|
||||
|
||||
SIMD_ALIGNED(uint8_t orig_y[16]);
|
||||
SIMD_ALIGNED(uint8_t orig_u[8]);
|
||||
SIMD_ALIGNED(uint8_t orig_v[8]);
|
||||
SIMD_ALIGNED(uint8_t orig_pixels[16 * 4]);
|
||||
memset(orig_y, y, kPixels);
|
||||
memset(orig_u, u, kHalfPixels);
|
||||
memset(orig_v, v, kHalfPixels);
|
||||
|
||||
/* YUV converted to ARGB. */
|
||||
I422ToARGB(orig_y, kWidth, orig_u, (kWidth + 1) / 2, orig_v, (kWidth + 1) / 2,
|
||||
orig_pixels, kWidth * 4, kWidth, kHeight);
|
||||
|
||||
*b = orig_pixels[0];
|
||||
*g = orig_pixels[1];
|
||||
*r = orig_pixels[2];
|
||||
}
|
||||
|
||||
static void YUVJToRGB(int y, int u, int v, int* r, int* g, int* b) {
|
||||
const int kWidth = 16;
|
||||
const int kHeight = 1;
|
||||
const int kPixels = kWidth * kHeight;
|
||||
const int kHalfPixels = ((kWidth + 1) / 2) * ((kHeight + 1) / 2);
|
||||
|
||||
SIMD_ALIGNED(uint8_t orig_y[16]);
|
||||
SIMD_ALIGNED(uint8_t orig_u[8]);
|
||||
SIMD_ALIGNED(uint8_t orig_v[8]);
|
||||
SIMD_ALIGNED(uint8_t orig_pixels[16 * 4]);
|
||||
memset(orig_y, y, kPixels);
|
||||
memset(orig_u, u, kHalfPixels);
|
||||
memset(orig_v, v, kHalfPixels);
|
||||
|
||||
/* YUV converted to ARGB. */
|
||||
J422ToARGB(orig_y, kWidth, orig_u, (kWidth + 1) / 2, orig_v, (kWidth + 1) / 2,
|
||||
orig_pixels, kWidth * 4, kWidth, kHeight);
|
||||
|
||||
*b = orig_pixels[0];
|
||||
*g = orig_pixels[1];
|
||||
*r = orig_pixels[2];
|
||||
}
|
||||
|
||||
static void YUVHToRGB(int y, int u, int v, int* r, int* g, int* b) {
|
||||
const int kWidth = 16;
|
||||
const int kHeight = 1;
|
||||
const int kPixels = kWidth * kHeight;
|
||||
const int kHalfPixels = ((kWidth + 1) / 2) * ((kHeight + 1) / 2);
|
||||
|
||||
SIMD_ALIGNED(uint8_t orig_y[16]);
|
||||
SIMD_ALIGNED(uint8_t orig_u[8]);
|
||||
SIMD_ALIGNED(uint8_t orig_v[8]);
|
||||
SIMD_ALIGNED(uint8_t orig_pixels[16 * 4]);
|
||||
memset(orig_y, y, kPixels);
|
||||
memset(orig_u, u, kHalfPixels);
|
||||
memset(orig_v, v, kHalfPixels);
|
||||
|
||||
/* YUV converted to ARGB. */
|
||||
H422ToARGB(orig_y, kWidth, orig_u, (kWidth + 1) / 2, orig_v, (kWidth + 1) / 2,
|
||||
orig_pixels, kWidth * 4, kWidth, kHeight);
|
||||
|
||||
*b = orig_pixels[0];
|
||||
*g = orig_pixels[1];
|
||||
*r = orig_pixels[2];
|
||||
}
|
||||
|
||||
#define F422ToARGB(a, b, c, d, e, f, g, h, i, j) \
|
||||
I422ToARGBMatrix(a, b, c, d, e, f, g, h, &kYuvF709Constants, i, j)
|
||||
|
||||
static void YUVFToRGB(int y, int u, int v, int* r, int* g, int* b) {
|
||||
const int kWidth = 16;
|
||||
const int kHeight = 1;
|
||||
const int kPixels = kWidth * kHeight;
|
||||
const int kHalfPixels = ((kWidth + 1) / 2) * ((kHeight + 1) / 2);
|
||||
|
||||
SIMD_ALIGNED(uint8_t orig_y[16]);
|
||||
SIMD_ALIGNED(uint8_t orig_u[8]);
|
||||
SIMD_ALIGNED(uint8_t orig_v[8]);
|
||||
SIMD_ALIGNED(uint8_t orig_pixels[16 * 4]);
|
||||
memset(orig_y, y, kPixels);
|
||||
memset(orig_u, u, kHalfPixels);
|
||||
memset(orig_v, v, kHalfPixels);
|
||||
|
||||
/* YUV converted to ARGB. */
|
||||
F422ToARGB(orig_y, kWidth, orig_u, (kWidth + 1) / 2, orig_v, (kWidth + 1) / 2,
|
||||
orig_pixels, kWidth * 4, kWidth, kHeight);
|
||||
|
||||
*b = orig_pixels[0];
|
||||
*g = orig_pixels[1];
|
||||
*r = orig_pixels[2];
|
||||
}
|
||||
|
||||
static void YUVUToRGB(int y, int u, int v, int* r, int* g, int* b) {
|
||||
const int kWidth = 16;
|
||||
const int kHeight = 1;
|
||||
const int kPixels = kWidth * kHeight;
|
||||
const int kHalfPixels = ((kWidth + 1) / 2) * ((kHeight + 1) / 2);
|
||||
|
||||
SIMD_ALIGNED(uint8_t orig_y[16]);
|
||||
SIMD_ALIGNED(uint8_t orig_u[8]);
|
||||
SIMD_ALIGNED(uint8_t orig_v[8]);
|
||||
SIMD_ALIGNED(uint8_t orig_pixels[16 * 4]);
|
||||
memset(orig_y, y, kPixels);
|
||||
memset(orig_u, u, kHalfPixels);
|
||||
memset(orig_v, v, kHalfPixels);
|
||||
|
||||
/* YUV converted to ARGB. */
|
||||
U422ToARGB(orig_y, kWidth, orig_u, (kWidth + 1) / 2, orig_v, (kWidth + 1) / 2,
|
||||
orig_pixels, kWidth * 4, kWidth, kHeight);
|
||||
|
||||
*b = orig_pixels[0];
|
||||
*g = orig_pixels[1];
|
||||
*r = orig_pixels[2];
|
||||
}
|
||||
|
||||
#define V422ToARGB(a, b, c, d, e, f, g, h, i, j) \
|
||||
I422ToARGBMatrix(a, b, c, d, e, f, g, h, &kYuvV2020Constants, i, j)
|
||||
|
||||
static void YUVVToRGB(int y, int u, int v, int* r, int* g, int* b) {
|
||||
const int kWidth = 16;
|
||||
const int kHeight = 1;
|
||||
const int kPixels = kWidth * kHeight;
|
||||
const int kHalfPixels = ((kWidth + 1) / 2) * ((kHeight + 1) / 2);
|
||||
|
||||
SIMD_ALIGNED(uint8_t orig_y[16]);
|
||||
SIMD_ALIGNED(uint8_t orig_u[8]);
|
||||
SIMD_ALIGNED(uint8_t orig_v[8]);
|
||||
SIMD_ALIGNED(uint8_t orig_pixels[16 * 4]);
|
||||
memset(orig_y, y, kPixels);
|
||||
memset(orig_u, u, kHalfPixels);
|
||||
memset(orig_v, v, kHalfPixels);
|
||||
|
||||
/* YUV converted to ARGB. */
|
||||
V422ToARGB(orig_y, kWidth, orig_u, (kWidth + 1) / 2, orig_v, (kWidth + 1) / 2,
|
||||
orig_pixels, kWidth * 4, kWidth, kHeight);
|
||||
|
||||
*b = orig_pixels[0];
|
||||
*g = orig_pixels[1];
|
||||
*r = orig_pixels[2];
|
||||
}
|
||||
|
||||
static void YToRGB(int y, int* r, int* g, int* b) {
|
||||
const int kWidth = 16;
|
||||
const int kHeight = 1;
|
||||
const int kPixels = kWidth * kHeight;
|
||||
|
||||
SIMD_ALIGNED(uint8_t orig_y[16]);
|
||||
SIMD_ALIGNED(uint8_t orig_pixels[16 * 4]);
|
||||
memset(orig_y, y, kPixels);
|
||||
|
||||
/* YUV converted to ARGB. */
|
||||
I400ToARGB(orig_y, kWidth, orig_pixels, kWidth * 4, kWidth, kHeight);
|
||||
|
||||
*b = orig_pixels[0];
|
||||
*g = orig_pixels[1];
|
||||
*r = orig_pixels[2];
|
||||
}
|
||||
|
||||
static void YJToRGB(int y, int* r, int* g, int* b) {
|
||||
const int kWidth = 16;
|
||||
const int kHeight = 1;
|
||||
const int kPixels = kWidth * kHeight;
|
||||
|
||||
SIMD_ALIGNED(uint8_t orig_y[16]);
|
||||
SIMD_ALIGNED(uint8_t orig_pixels[16 * 4]);
|
||||
memset(orig_y, y, kPixels);
|
||||
|
||||
/* YUV converted to ARGB. */
|
||||
J400ToARGB(orig_y, kWidth, orig_pixels, kWidth * 4, kWidth, kHeight);
|
||||
|
||||
*b = orig_pixels[0];
|
||||
*g = orig_pixels[1];
|
||||
*r = orig_pixels[2];
|
||||
}
|
||||
|
||||
// Pick a method for clamping.
|
||||
// #define CLAMPMETHOD_IF 1
|
||||
// #define CLAMPMETHOD_TABLE 1
|
||||
#define CLAMPMETHOD_TERNARY 1
|
||||
// #define CLAMPMETHOD_MASK 1
|
||||
|
||||
// Pick a method for rounding.
|
||||
#define ROUND(f) static_cast<int>(f + 0.5f)
|
||||
// #define ROUND(f) lrintf(f)
|
||||
// #define ROUND(f) static_cast<int>(round(f))
|
||||
// #define ROUND(f) _mm_cvt_ss2si(_mm_load_ss(&f))
|
||||
|
||||
#if defined(CLAMPMETHOD_IF)
|
||||
static int RoundToByte(float f) {
|
||||
int i = ROUND(f);
|
||||
if (i < 0) {
|
||||
i = 0;
|
||||
}
|
||||
if (i > 255) {
|
||||
i = 255;
|
||||
}
|
||||
return i;
|
||||
}
|
||||
#elif defined(CLAMPMETHOD_TABLE)
|
||||
static const unsigned char clamptable[811] = {
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8,
|
||||
9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23,
|
||||
24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38,
|
||||
39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53,
|
||||
54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68,
|
||||
69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83,
|
||||
84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98,
|
||||
99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113,
|
||||
114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128,
|
||||
129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143,
|
||||
144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158,
|
||||
159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173,
|
||||
174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188,
|
||||
189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203,
|
||||
204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218,
|
||||
219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233,
|
||||
234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248,
|
||||
249, 250, 251, 252, 253, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255,
|
||||
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
|
||||
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
|
||||
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
|
||||
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
|
||||
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
|
||||
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
|
||||
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
|
||||
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
|
||||
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
|
||||
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
|
||||
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
|
||||
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
|
||||
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
|
||||
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
|
||||
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
|
||||
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
|
||||
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
|
||||
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
|
||||
255};
|
||||
|
||||
static int RoundToByte(float f) {
|
||||
return clamptable[ROUND(f) + 276];
|
||||
}
|
||||
#elif defined(CLAMPMETHOD_TERNARY)
|
||||
static int RoundToByte(float f) {
|
||||
int i = ROUND(f);
|
||||
return (i < 0) ? 0 : ((i > 255) ? 255 : i);
|
||||
}
|
||||
#elif defined(CLAMPMETHOD_MASK)
|
||||
static int RoundToByte(float f) {
|
||||
int i = ROUND(f);
|
||||
i = ((-(i) >> 31) & (i)); // clamp to 0.
|
||||
return (((255 - (i)) >> 31) | (i)) & 255; // clamp to 255.
|
||||
}
|
||||
#endif
|
||||
|
||||
#define RANDOM256(s) ((s & 1) ? ((s >> 1) ^ 0xb8) : (s >> 1))
|
||||
|
||||
TEST_F(LibYUVColorTest, TestRoundToByte) {
|
||||
int allb = 0;
|
||||
int count = benchmark_width_ * benchmark_height_;
|
||||
for (int i = 0; i < benchmark_iterations_; ++i) {
|
||||
float f = (fastrand() & 255) * 3.14f - 260.f;
|
||||
for (int j = 0; j < count; ++j) {
|
||||
int b = RoundToByte(f);
|
||||
f += 0.91f;
|
||||
allb |= b;
|
||||
}
|
||||
}
|
||||
EXPECT_GE(allb, 0);
|
||||
EXPECT_LE(allb, 255);
|
||||
}
|
||||
|
||||
// BT.601 limited range YUV to RGB reference
|
||||
static void YUVToRGBReference(int y, int u, int v, int* r, int* g, int* b) {
|
||||
*r = RoundToByte((y - 16) * 1.164 - (v - 128) * -1.596);
|
||||
*g = RoundToByte((y - 16) * 1.164 - (u - 128) * 0.391 - (v - 128) * 0.813);
|
||||
*b = RoundToByte((y - 16) * 1.164 - (u - 128) * -2.018);
|
||||
}
|
||||
|
||||
// BT.601 full range YUV to RGB reference (aka JPEG)
|
||||
static void YUVJToRGBReference(int y, int u, int v, int* r, int* g, int* b) {
|
||||
*r = RoundToByte(y - (v - 128) * -1.40200);
|
||||
*g = RoundToByte(y - (u - 128) * 0.34414 - (v - 128) * 0.71414);
|
||||
*b = RoundToByte(y - (u - 128) * -1.77200);
|
||||
}
|
||||
|
||||
// BT.709 limited range YUV to RGB reference
|
||||
// See also http://www.equasys.de/colorconversion.html
|
||||
static void YUVHToRGBReference(int y, int u, int v, int* r, int* g, int* b) {
|
||||
*r = RoundToByte((y - 16) * 1.164 - (v - 128) * -1.793);
|
||||
*g = RoundToByte((y - 16) * 1.164 - (u - 128) * 0.213 - (v - 128) * 0.533);
|
||||
*b = RoundToByte((y - 16) * 1.164 - (u - 128) * -2.112);
|
||||
}
|
||||
|
||||
// BT.709 full range YUV to RGB reference
|
||||
static void YUVFToRGBReference(int y, int u, int v, int* r, int* g, int* b) {
|
||||
*r = RoundToByte(y - (v - 128) * -1.5748);
|
||||
*g = RoundToByte(y - (u - 128) * 0.18732 - (v - 128) * 0.46812);
|
||||
*b = RoundToByte(y - (u - 128) * -1.8556);
|
||||
}
|
||||
|
||||
// BT.2020 limited range YUV to RGB reference
|
||||
static void YUVUToRGBReference(int y, int u, int v, int* r, int* g, int* b) {
|
||||
*r = RoundToByte((y - 16) * 1.164384 - (v - 128) * -1.67867);
|
||||
*g = RoundToByte((y - 16) * 1.164384 - (u - 128) * 0.187326 -
|
||||
(v - 128) * 0.65042);
|
||||
*b = RoundToByte((y - 16) * 1.164384 - (u - 128) * -2.14177);
|
||||
}
|
||||
|
||||
// BT.2020 full range YUV to RGB reference
|
||||
static void YUVVToRGBReference(int y, int u, int v, int* r, int* g, int* b) {
|
||||
*r = RoundToByte(y + (v - 128) * 1.474600);
|
||||
*g = RoundToByte(y - (u - 128) * 0.164553 - (v - 128) * 0.571353);
|
||||
*b = RoundToByte(y + (u - 128) * 1.881400);
|
||||
}
|
||||
|
||||
TEST_F(LibYUVColorTest, TestYUV) {
|
||||
int r0, g0, b0, r1, g1, b1;
|
||||
|
||||
// cyan (less red)
|
||||
YUVToRGBReference(240, 255, 0, &r0, &g0, &b0);
|
||||
EXPECT_EQ(56, r0);
|
||||
EXPECT_EQ(255, g0);
|
||||
EXPECT_EQ(255, b0);
|
||||
|
||||
YUVToRGB(240, 255, 0, &r1, &g1, &b1);
|
||||
EXPECT_EQ(57, r1);
|
||||
EXPECT_EQ(255, g1);
|
||||
EXPECT_EQ(255, b1);
|
||||
|
||||
// green (less red and blue)
|
||||
YUVToRGBReference(240, 0, 0, &r0, &g0, &b0);
|
||||
EXPECT_EQ(56, r0);
|
||||
EXPECT_EQ(255, g0);
|
||||
EXPECT_EQ(2, b0);
|
||||
|
||||
YUVToRGB(240, 0, 0, &r1, &g1, &b1);
|
||||
EXPECT_EQ(57, r1);
|
||||
EXPECT_EQ(255, g1);
|
||||
#ifdef LIBYUV_UNLIMITED_DATA
|
||||
EXPECT_EQ(3, b1);
|
||||
#else
|
||||
EXPECT_EQ(5, b1);
|
||||
#endif
|
||||
|
||||
for (int i = 0; i < 256; ++i) {
|
||||
YUVToRGBReference(i, 128, 128, &r0, &g0, &b0);
|
||||
YUVToRGB(i, 128, 128, &r1, &g1, &b1);
|
||||
EXPECT_NEAR(r0, r1, ERROR_R);
|
||||
EXPECT_NEAR(g0, g1, ERROR_G);
|
||||
EXPECT_NEAR(b0, b1, ERROR_B);
|
||||
|
||||
YUVToRGBReference(i, 0, 0, &r0, &g0, &b0);
|
||||
YUVToRGB(i, 0, 0, &r1, &g1, &b1);
|
||||
EXPECT_NEAR(r0, r1, ERROR_R);
|
||||
EXPECT_NEAR(g0, g1, ERROR_G);
|
||||
EXPECT_NEAR(b0, b1, ERROR_B);
|
||||
|
||||
YUVToRGBReference(i, 0, 255, &r0, &g0, &b0);
|
||||
YUVToRGB(i, 0, 255, &r1, &g1, &b1);
|
||||
EXPECT_NEAR(r0, r1, ERROR_R);
|
||||
EXPECT_NEAR(g0, g1, ERROR_G);
|
||||
EXPECT_NEAR(b0, b1, ERROR_B);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(LibYUVColorTest, TestGreyYUV) {
|
||||
int r0, g0, b0, r1, g1, b1, r2, g2, b2;
|
||||
|
||||
// black
|
||||
YUVToRGBReference(16, 128, 128, &r0, &g0, &b0);
|
||||
EXPECT_EQ(0, r0);
|
||||
EXPECT_EQ(0, g0);
|
||||
EXPECT_EQ(0, b0);
|
||||
|
||||
YUVToRGB(16, 128, 128, &r1, &g1, &b1);
|
||||
EXPECT_EQ(0, r1);
|
||||
EXPECT_EQ(0, g1);
|
||||
EXPECT_EQ(0, b1);
|
||||
|
||||
// white
|
||||
YUVToRGBReference(240, 128, 128, &r0, &g0, &b0);
|
||||
EXPECT_EQ(255, r0);
|
||||
EXPECT_EQ(255, g0);
|
||||
EXPECT_EQ(255, b0);
|
||||
|
||||
YUVToRGB(240, 128, 128, &r1, &g1, &b1);
|
||||
EXPECT_EQ(255, r1);
|
||||
EXPECT_EQ(255, g1);
|
||||
EXPECT_EQ(255, b1);
|
||||
|
||||
// grey
|
||||
YUVToRGBReference(128, 128, 128, &r0, &g0, &b0);
|
||||
EXPECT_EQ(130, r0);
|
||||
EXPECT_EQ(130, g0);
|
||||
EXPECT_EQ(130, b0);
|
||||
|
||||
YUVToRGB(128, 128, 128, &r1, &g1, &b1);
|
||||
EXPECT_EQ(130, r1);
|
||||
EXPECT_EQ(130, g1);
|
||||
EXPECT_EQ(130, b1);
|
||||
|
||||
for (int y = 0; y < 256; ++y) {
|
||||
YUVToRGBReference(y, 128, 128, &r0, &g0, &b0);
|
||||
YUVToRGB(y, 128, 128, &r1, &g1, &b1);
|
||||
YToRGB(y, &r2, &g2, &b2);
|
||||
EXPECT_EQ(r0, r1);
|
||||
EXPECT_EQ(g0, g1);
|
||||
EXPECT_EQ(b0, b1);
|
||||
EXPECT_EQ(r0, r2);
|
||||
EXPECT_EQ(g0, g2);
|
||||
EXPECT_EQ(b0, b2);
|
||||
}
|
||||
}
|
||||
|
||||
static void PrintHistogram(int rh[256], int gh[256], int bh[256]) {
|
||||
int i;
|
||||
printf("hist ");
|
||||
for (i = 0; i < 256; ++i) {
|
||||
if (rh[i] || gh[i] || bh[i]) {
|
||||
printf(" %8d", i - 128);
|
||||
}
|
||||
}
|
||||
printf("\nred ");
|
||||
for (i = 0; i < 256; ++i) {
|
||||
if (rh[i] || gh[i] || bh[i]) {
|
||||
printf(" %8d", rh[i]);
|
||||
}
|
||||
}
|
||||
printf("\ngreen");
|
||||
for (i = 0; i < 256; ++i) {
|
||||
if (rh[i] || gh[i] || bh[i]) {
|
||||
printf(" %8d", gh[i]);
|
||||
}
|
||||
}
|
||||
printf("\nblue ");
|
||||
for (i = 0; i < 256; ++i) {
|
||||
if (rh[i] || gh[i] || bh[i]) {
|
||||
printf(" %8d", bh[i]);
|
||||
}
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
// Step by 5 on inner loop goes from 0 to 255 inclusive.
|
||||
// Set to 1 for better converage. 3, 5 or 17 for faster testing.
|
||||
#ifdef DISABLE_SLOW_TESTS
|
||||
#define FASTSTEP 5
|
||||
#else
|
||||
#define FASTSTEP 1
|
||||
#endif
|
||||
|
||||
// BT.601 limited range.
|
||||
TEST_F(LibYUVColorTest, TestFullYUV) {
|
||||
int rh[256] = {
|
||||
0,
|
||||
};
|
||||
int gh[256] = {
|
||||
0,
|
||||
};
|
||||
int bh[256] = {
|
||||
0,
|
||||
};
|
||||
for (int u = 0; u < 256; ++u) {
|
||||
for (int v = 0; v < 256; ++v) {
|
||||
for (int y2 = 0; y2 < 256; y2 += FASTSTEP) {
|
||||
int r0, g0, b0, r1, g1, b1;
|
||||
int y = RANDOM256(y2);
|
||||
YUVToRGBReference(y, u, v, &r0, &g0, &b0);
|
||||
YUVToRGB(y, u, v, &r1, &g1, &b1);
|
||||
EXPECT_NEAR(r0, r1, ERROR_R);
|
||||
EXPECT_NEAR(g0, g1, ERROR_G);
|
||||
EXPECT_NEAR(b0, b1, ERROR_B);
|
||||
++rh[r1 - r0 + 128];
|
||||
++gh[g1 - g0 + 128];
|
||||
++bh[b1 - b0 + 128];
|
||||
}
|
||||
}
|
||||
}
|
||||
PrintHistogram(rh, gh, bh);
|
||||
}
|
||||
|
||||
// BT.601 full range.
|
||||
TEST_F(LibYUVColorTest, TestFullYUVJ) {
|
||||
int rh[256] = {
|
||||
0,
|
||||
};
|
||||
int gh[256] = {
|
||||
0,
|
||||
};
|
||||
int bh[256] = {
|
||||
0,
|
||||
};
|
||||
for (int u = 0; u < 256; ++u) {
|
||||
for (int v = 0; v < 256; ++v) {
|
||||
for (int y2 = 0; y2 < 256; y2 += FASTSTEP) {
|
||||
int r0, g0, b0, r1, g1, b1;
|
||||
int y = RANDOM256(y2);
|
||||
YUVJToRGBReference(y, u, v, &r0, &g0, &b0);
|
||||
YUVJToRGB(y, u, v, &r1, &g1, &b1);
|
||||
EXPECT_NEAR(r0, r1, ERROR_R);
|
||||
EXPECT_NEAR(g0, g1, ERROR_G);
|
||||
EXPECT_NEAR(b0, b1, ERROR_B);
|
||||
++rh[r1 - r0 + 128];
|
||||
++gh[g1 - g0 + 128];
|
||||
++bh[b1 - b0 + 128];
|
||||
}
|
||||
}
|
||||
}
|
||||
PrintHistogram(rh, gh, bh);
|
||||
}
|
||||
|
||||
// BT.709 limited range.
|
||||
TEST_F(LibYUVColorTest, TestFullYUVH) {
|
||||
int rh[256] = {
|
||||
0,
|
||||
};
|
||||
int gh[256] = {
|
||||
0,
|
||||
};
|
||||
int bh[256] = {
|
||||
0,
|
||||
};
|
||||
for (int u = 0; u < 256; ++u) {
|
||||
for (int v = 0; v < 256; ++v) {
|
||||
for (int y2 = 0; y2 < 256; y2 += FASTSTEP) {
|
||||
int r0, g0, b0, r1, g1, b1;
|
||||
int y = RANDOM256(y2);
|
||||
YUVHToRGBReference(y, u, v, &r0, &g0, &b0);
|
||||
YUVHToRGB(y, u, v, &r1, &g1, &b1);
|
||||
EXPECT_NEAR(r0, r1, ERROR_R);
|
||||
EXPECT_NEAR(g0, g1, ERROR_G);
|
||||
EXPECT_NEAR(b0, b1, ERROR_B);
|
||||
++rh[r1 - r0 + 128];
|
||||
++gh[g1 - g0 + 128];
|
||||
++bh[b1 - b0 + 128];
|
||||
}
|
||||
}
|
||||
}
|
||||
PrintHistogram(rh, gh, bh);
|
||||
}
|
||||
|
||||
// BT.709 full range.
|
||||
TEST_F(LibYUVColorTest, TestFullYUVF) {
|
||||
int rh[256] = {
|
||||
0,
|
||||
};
|
||||
int gh[256] = {
|
||||
0,
|
||||
};
|
||||
int bh[256] = {
|
||||
0,
|
||||
};
|
||||
for (int u = 0; u < 256; ++u) {
|
||||
for (int v = 0; v < 256; ++v) {
|
||||
for (int y2 = 0; y2 < 256; y2 += FASTSTEP) {
|
||||
int r0, g0, b0, r1, g1, b1;
|
||||
int y = RANDOM256(y2);
|
||||
YUVFToRGBReference(y, u, v, &r0, &g0, &b0);
|
||||
YUVFToRGB(y, u, v, &r1, &g1, &b1);
|
||||
EXPECT_NEAR(r0, r1, ERROR_R);
|
||||
EXPECT_NEAR(g0, g1, ERROR_G);
|
||||
EXPECT_NEAR(b0, b1, ERROR_B);
|
||||
++rh[r1 - r0 + 128];
|
||||
++gh[g1 - g0 + 128];
|
||||
++bh[b1 - b0 + 128];
|
||||
}
|
||||
}
|
||||
}
|
||||
PrintHistogram(rh, gh, bh);
|
||||
}
|
||||
|
||||
// BT.2020 limited range.
|
||||
TEST_F(LibYUVColorTest, TestFullYUVU) {
|
||||
int rh[256] = {
|
||||
0,
|
||||
};
|
||||
int gh[256] = {
|
||||
0,
|
||||
};
|
||||
int bh[256] = {
|
||||
0,
|
||||
};
|
||||
for (int u = 0; u < 256; ++u) {
|
||||
for (int v = 0; v < 256; ++v) {
|
||||
for (int y2 = 0; y2 < 256; y2 += FASTSTEP) {
|
||||
int r0, g0, b0, r1, g1, b1;
|
||||
int y = RANDOM256(y2);
|
||||
YUVUToRGBReference(y, u, v, &r0, &g0, &b0);
|
||||
YUVUToRGB(y, u, v, &r1, &g1, &b1);
|
||||
EXPECT_NEAR(r0, r1, ERROR_R);
|
||||
EXPECT_NEAR(g0, g1, ERROR_G);
|
||||
EXPECT_NEAR(b0, b1, ERROR_B);
|
||||
++rh[r1 - r0 + 128];
|
||||
++gh[g1 - g0 + 128];
|
||||
++bh[b1 - b0 + 128];
|
||||
}
|
||||
}
|
||||
}
|
||||
PrintHistogram(rh, gh, bh);
|
||||
}
|
||||
|
||||
// BT.2020 full range.
|
||||
TEST_F(LibYUVColorTest, TestFullYUVV) {
|
||||
int rh[256] = {
|
||||
0,
|
||||
};
|
||||
int gh[256] = {
|
||||
0,
|
||||
};
|
||||
int bh[256] = {
|
||||
0,
|
||||
};
|
||||
for (int u = 0; u < 256; ++u) {
|
||||
for (int v = 0; v < 256; ++v) {
|
||||
for (int y2 = 0; y2 < 256; y2 += FASTSTEP) {
|
||||
int r0, g0, b0, r1, g1, b1;
|
||||
int y = RANDOM256(y2);
|
||||
YUVVToRGBReference(y, u, v, &r0, &g0, &b0);
|
||||
YUVVToRGB(y, u, v, &r1, &g1, &b1);
|
||||
EXPECT_NEAR(r0, r1, ERROR_R);
|
||||
EXPECT_NEAR(g0, g1, 2);
|
||||
EXPECT_NEAR(b0, b1, ERROR_B);
|
||||
++rh[r1 - r0 + 128];
|
||||
++gh[g1 - g0 + 128];
|
||||
++bh[b1 - b0 + 128];
|
||||
}
|
||||
}
|
||||
}
|
||||
PrintHistogram(rh, gh, bh);
|
||||
}
|
||||
#undef FASTSTEP
|
||||
|
||||
TEST_F(LibYUVColorTest, TestGreyYUVJ) {
|
||||
int r0, g0, b0, r1, g1, b1, r2, g2, b2;
|
||||
|
||||
// black
|
||||
YUVJToRGBReference(0, 128, 128, &r0, &g0, &b0);
|
||||
EXPECT_EQ(0, r0);
|
||||
EXPECT_EQ(0, g0);
|
||||
EXPECT_EQ(0, b0);
|
||||
|
||||
YUVJToRGB(0, 128, 128, &r1, &g1, &b1);
|
||||
EXPECT_EQ(0, r1);
|
||||
EXPECT_EQ(0, g1);
|
||||
EXPECT_EQ(0, b1);
|
||||
|
||||
// white
|
||||
YUVJToRGBReference(255, 128, 128, &r0, &g0, &b0);
|
||||
EXPECT_EQ(255, r0);
|
||||
EXPECT_EQ(255, g0);
|
||||
EXPECT_EQ(255, b0);
|
||||
|
||||
YUVJToRGB(255, 128, 128, &r1, &g1, &b1);
|
||||
EXPECT_EQ(255, r1);
|
||||
EXPECT_EQ(255, g1);
|
||||
EXPECT_EQ(255, b1);
|
||||
|
||||
// grey
|
||||
YUVJToRGBReference(128, 128, 128, &r0, &g0, &b0);
|
||||
EXPECT_EQ(128, r0);
|
||||
EXPECT_EQ(128, g0);
|
||||
EXPECT_EQ(128, b0);
|
||||
|
||||
YUVJToRGB(128, 128, 128, &r1, &g1, &b1);
|
||||
EXPECT_EQ(128, r1);
|
||||
EXPECT_EQ(128, g1);
|
||||
EXPECT_EQ(128, b1);
|
||||
|
||||
for (int y = 0; y < 256; ++y) {
|
||||
YUVJToRGBReference(y, 128, 128, &r0, &g0, &b0);
|
||||
YUVJToRGB(y, 128, 128, &r1, &g1, &b1);
|
||||
YJToRGB(y, &r2, &g2, &b2);
|
||||
EXPECT_EQ(r0, r1);
|
||||
EXPECT_EQ(g0, g1);
|
||||
EXPECT_EQ(b0, b1);
|
||||
EXPECT_EQ(r0, r2);
|
||||
EXPECT_EQ(g0, g2);
|
||||
EXPECT_EQ(b0, b2);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace libyuv
|
||||
739
externals/libyuv/unit_test/compare_test.cc
vendored
Normal file
739
externals/libyuv/unit_test/compare_test.cc
vendored
Normal file
@@ -0,0 +1,739 @@
|
||||
/*
|
||||
* Copyright 2011 The LibYuv Project Authors. All rights reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
|
||||
#include "../unit_test/unit_test.h"
|
||||
#include "libyuv/basic_types.h"
|
||||
#include "libyuv/compare.h"
|
||||
#include "libyuv/cpu_id.h"
|
||||
#include "libyuv/video_common.h"
|
||||
|
||||
#ifdef ENABLE_ROW_TESTS
|
||||
#include "libyuv/compare_row.h" /* For HammingDistance_C */
|
||||
#endif
|
||||
|
||||
namespace libyuv {
|
||||
|
||||
// hash seed of 5381 recommended.
|
||||
static uint32_t ReferenceHashDjb2(const uint8_t* src,
|
||||
uint64_t count,
|
||||
uint32_t seed) {
|
||||
uint32_t hash = seed;
|
||||
if (count > 0) {
|
||||
do {
|
||||
hash = hash * 33 + *src++;
|
||||
} while (--count);
|
||||
}
|
||||
return hash;
|
||||
}
|
||||
|
||||
TEST_F(LibYUVCompareTest, Djb2_Test) {
|
||||
const int kMaxTest = benchmark_width_ * benchmark_height_;
|
||||
align_buffer_page_end(src_a, kMaxTest);
|
||||
align_buffer_page_end(src_b, kMaxTest);
|
||||
|
||||
const char* fox =
|
||||
"The quick brown fox jumps over the lazy dog"
|
||||
" and feels as if he were in the seventh heaven of typography"
|
||||
" together with Hermann Zapf";
|
||||
uint32_t foxhash = HashDjb2(reinterpret_cast<const uint8_t*>(fox), 131, 5381);
|
||||
const uint32_t kExpectedFoxHash = 2611006483u;
|
||||
EXPECT_EQ(kExpectedFoxHash, foxhash);
|
||||
|
||||
for (int i = 0; i < kMaxTest; ++i) {
|
||||
src_a[i] = (fastrand() & 0xff);
|
||||
src_b[i] = (fastrand() & 0xff);
|
||||
}
|
||||
// Compare different buffers. Expect hash is different.
|
||||
uint32_t h1 = HashDjb2(src_a, kMaxTest, 5381);
|
||||
uint32_t h2 = HashDjb2(src_b, kMaxTest, 5381);
|
||||
EXPECT_NE(h1, h2);
|
||||
|
||||
// Make last half same. Expect hash is different.
|
||||
memcpy(src_a + kMaxTest / 2, src_b + kMaxTest / 2, kMaxTest / 2);
|
||||
h1 = HashDjb2(src_a, kMaxTest, 5381);
|
||||
h2 = HashDjb2(src_b, kMaxTest, 5381);
|
||||
EXPECT_NE(h1, h2);
|
||||
|
||||
// Make first half same. Expect hash is different.
|
||||
memcpy(src_a + kMaxTest / 2, src_a, kMaxTest / 2);
|
||||
memcpy(src_b + kMaxTest / 2, src_b, kMaxTest / 2);
|
||||
memcpy(src_a, src_b, kMaxTest / 2);
|
||||
h1 = HashDjb2(src_a, kMaxTest, 5381);
|
||||
h2 = HashDjb2(src_b, kMaxTest, 5381);
|
||||
EXPECT_NE(h1, h2);
|
||||
|
||||
// Make same. Expect hash is same.
|
||||
memcpy(src_a, src_b, kMaxTest);
|
||||
h1 = HashDjb2(src_a, kMaxTest, 5381);
|
||||
h2 = HashDjb2(src_b, kMaxTest, 5381);
|
||||
EXPECT_EQ(h1, h2);
|
||||
|
||||
// Mask seed different. Expect hash is different.
|
||||
memcpy(src_a, src_b, kMaxTest);
|
||||
h1 = HashDjb2(src_a, kMaxTest, 5381);
|
||||
h2 = HashDjb2(src_b, kMaxTest, 1234);
|
||||
EXPECT_NE(h1, h2);
|
||||
|
||||
// Make one byte different in middle. Expect hash is different.
|
||||
memcpy(src_a, src_b, kMaxTest);
|
||||
++src_b[kMaxTest / 2];
|
||||
h1 = HashDjb2(src_a, kMaxTest, 5381);
|
||||
h2 = HashDjb2(src_b, kMaxTest, 5381);
|
||||
EXPECT_NE(h1, h2);
|
||||
|
||||
// Make first byte different. Expect hash is different.
|
||||
memcpy(src_a, src_b, kMaxTest);
|
||||
++src_b[0];
|
||||
h1 = HashDjb2(src_a, kMaxTest, 5381);
|
||||
h2 = HashDjb2(src_b, kMaxTest, 5381);
|
||||
EXPECT_NE(h1, h2);
|
||||
|
||||
// Make last byte different. Expect hash is different.
|
||||
memcpy(src_a, src_b, kMaxTest);
|
||||
++src_b[kMaxTest - 1];
|
||||
h1 = HashDjb2(src_a, kMaxTest, 5381);
|
||||
h2 = HashDjb2(src_b, kMaxTest, 5381);
|
||||
EXPECT_NE(h1, h2);
|
||||
|
||||
// Make a zeros. Test different lengths. Expect hash is different.
|
||||
memset(src_a, 0, kMaxTest);
|
||||
h1 = HashDjb2(src_a, kMaxTest, 5381);
|
||||
h2 = HashDjb2(src_a, kMaxTest / 2, 5381);
|
||||
EXPECT_NE(h1, h2);
|
||||
|
||||
// Make a zeros and seed of zero. Test different lengths. Expect hash is same.
|
||||
memset(src_a, 0, kMaxTest);
|
||||
h1 = HashDjb2(src_a, kMaxTest, 0);
|
||||
h2 = HashDjb2(src_a, kMaxTest / 2, 0);
|
||||
EXPECT_EQ(h1, h2);
|
||||
|
||||
free_aligned_buffer_page_end(src_a);
|
||||
free_aligned_buffer_page_end(src_b);
|
||||
}
|
||||
|
||||
TEST_F(LibYUVCompareTest, BenchmarkDjb2_Opt) {
|
||||
const int kMaxTest = benchmark_width_ * benchmark_height_;
|
||||
align_buffer_page_end(src_a, kMaxTest);
|
||||
|
||||
for (int i = 0; i < kMaxTest; ++i) {
|
||||
src_a[i] = i;
|
||||
}
|
||||
uint32_t h2 = ReferenceHashDjb2(src_a, kMaxTest, 5381);
|
||||
uint32_t h1;
|
||||
for (int i = 0; i < benchmark_iterations_; ++i) {
|
||||
h1 = HashDjb2(src_a, kMaxTest, 5381);
|
||||
}
|
||||
EXPECT_EQ(h1, h2);
|
||||
free_aligned_buffer_page_end(src_a);
|
||||
}
|
||||
|
||||
TEST_F(LibYUVCompareTest, BenchmarkDjb2_Unaligned) {
|
||||
const int kMaxTest = benchmark_width_ * benchmark_height_;
|
||||
align_buffer_page_end(src_a, kMaxTest + 1);
|
||||
for (int i = 0; i < kMaxTest; ++i) {
|
||||
src_a[i + 1] = i;
|
||||
}
|
||||
uint32_t h2 = ReferenceHashDjb2(src_a + 1, kMaxTest, 5381);
|
||||
uint32_t h1;
|
||||
for (int i = 0; i < benchmark_iterations_; ++i) {
|
||||
h1 = HashDjb2(src_a + 1, kMaxTest, 5381);
|
||||
}
|
||||
EXPECT_EQ(h1, h2);
|
||||
free_aligned_buffer_page_end(src_a);
|
||||
}
|
||||
|
||||
TEST_F(LibYUVCompareTest, BenchmarkARGBDetect_Opt) {
|
||||
uint32_t fourcc;
|
||||
const int kMaxTest = benchmark_width_ * benchmark_height_ * 4;
|
||||
align_buffer_page_end(src_a, kMaxTest);
|
||||
for (int i = 0; i < kMaxTest; ++i) {
|
||||
src_a[i] = 255;
|
||||
}
|
||||
|
||||
src_a[0] = 0;
|
||||
fourcc = ARGBDetect(src_a, benchmark_width_ * 4, benchmark_width_,
|
||||
benchmark_height_);
|
||||
EXPECT_EQ(static_cast<uint32_t>(libyuv::FOURCC_BGRA), fourcc);
|
||||
src_a[0] = 255;
|
||||
src_a[3] = 0;
|
||||
fourcc = ARGBDetect(src_a, benchmark_width_ * 4, benchmark_width_,
|
||||
benchmark_height_);
|
||||
EXPECT_EQ(static_cast<uint32_t>(libyuv::FOURCC_ARGB), fourcc);
|
||||
src_a[3] = 255;
|
||||
|
||||
for (int i = 0; i < benchmark_iterations_; ++i) {
|
||||
fourcc = ARGBDetect(src_a, benchmark_width_ * 4, benchmark_width_,
|
||||
benchmark_height_);
|
||||
}
|
||||
EXPECT_EQ(0u, fourcc);
|
||||
|
||||
free_aligned_buffer_page_end(src_a);
|
||||
}
|
||||
|
||||
TEST_F(LibYUVCompareTest, BenchmarkARGBDetect_Unaligned) {
|
||||
uint32_t fourcc;
|
||||
const int kMaxTest = benchmark_width_ * benchmark_height_ * 4 + 1;
|
||||
align_buffer_page_end(src_a, kMaxTest);
|
||||
for (int i = 1; i < kMaxTest; ++i) {
|
||||
src_a[i] = 255;
|
||||
}
|
||||
|
||||
src_a[0 + 1] = 0;
|
||||
fourcc = ARGBDetect(src_a + 1, benchmark_width_ * 4, benchmark_width_,
|
||||
benchmark_height_);
|
||||
EXPECT_EQ(static_cast<uint32_t>(libyuv::FOURCC_BGRA), fourcc);
|
||||
src_a[0 + 1] = 255;
|
||||
src_a[3 + 1] = 0;
|
||||
fourcc = ARGBDetect(src_a + 1, benchmark_width_ * 4, benchmark_width_,
|
||||
benchmark_height_);
|
||||
EXPECT_EQ(static_cast<uint32_t>(libyuv::FOURCC_ARGB), fourcc);
|
||||
src_a[3 + 1] = 255;
|
||||
|
||||
for (int i = 0; i < benchmark_iterations_; ++i) {
|
||||
fourcc = ARGBDetect(src_a + 1, benchmark_width_ * 4, benchmark_width_,
|
||||
benchmark_height_);
|
||||
}
|
||||
EXPECT_EQ(0u, fourcc);
|
||||
|
||||
free_aligned_buffer_page_end(src_a);
|
||||
}
|
||||
|
||||
#ifdef ENABLE_ROW_TESTS
|
||||
TEST_F(LibYUVCompareTest, BenchmarkHammingDistance_Opt) {
|
||||
const int kMaxWidth = 4096 * 3;
|
||||
align_buffer_page_end(src_a, kMaxWidth);
|
||||
align_buffer_page_end(src_b, kMaxWidth);
|
||||
memset(src_a, 0, kMaxWidth);
|
||||
memset(src_b, 0, kMaxWidth);
|
||||
|
||||
// Test known value
|
||||
memcpy(src_a, "test0123test4567", 16);
|
||||
memcpy(src_b, "tick0123tock4567", 16);
|
||||
uint32_t h1 = HammingDistance_C(src_a, src_b, 16);
|
||||
EXPECT_EQ(16u, h1);
|
||||
|
||||
// Test C vs OPT on random buffer
|
||||
MemRandomize(src_a, kMaxWidth);
|
||||
MemRandomize(src_b, kMaxWidth);
|
||||
|
||||
uint32_t h0 = HammingDistance_C(src_a, src_b, kMaxWidth);
|
||||
|
||||
int count =
|
||||
benchmark_iterations_ *
|
||||
((benchmark_width_ * benchmark_height_ + kMaxWidth - 1) / kMaxWidth);
|
||||
for (int i = 0; i < count; ++i) {
|
||||
#if defined(HAS_HAMMINGDISTANCE_NEON)
|
||||
h1 = HammingDistance_NEON(src_a, src_b, kMaxWidth);
|
||||
#elif defined(HAS_HAMMINGDISTANCE_AVX2)
|
||||
int has_avx2 = TestCpuFlag(kCpuHasAVX2);
|
||||
if (has_avx2) {
|
||||
h1 = HammingDistance_AVX2(src_a, src_b, kMaxWidth);
|
||||
} else {
|
||||
int has_sse42 = TestCpuFlag(kCpuHasSSE42);
|
||||
if (has_sse42) {
|
||||
h1 = HammingDistance_SSE42(src_a, src_b, kMaxWidth);
|
||||
} else {
|
||||
int has_ssse3 = TestCpuFlag(kCpuHasSSSE3);
|
||||
if (has_ssse3) {
|
||||
h1 = HammingDistance_SSSE3(src_a, src_b, kMaxWidth);
|
||||
} else {
|
||||
h1 = HammingDistance_C(src_a, src_b, kMaxWidth);
|
||||
}
|
||||
}
|
||||
}
|
||||
#elif defined(HAS_HAMMINGDISTANCE_SSE42)
|
||||
int has_sse42 = TestCpuFlag(kCpuHasSSE42);
|
||||
if (has_sse42) {
|
||||
h1 = HammingDistance_SSE42(src_a, src_b, kMaxWidth);
|
||||
} else {
|
||||
h1 = HammingDistance_C(src_a, src_b, kMaxWidth);
|
||||
}
|
||||
#else
|
||||
h1 = HammingDistance_C(src_a, src_b, kMaxWidth);
|
||||
#endif
|
||||
}
|
||||
EXPECT_EQ(h0, h1);
|
||||
|
||||
free_aligned_buffer_page_end(src_a);
|
||||
free_aligned_buffer_page_end(src_b);
|
||||
}
|
||||
|
||||
TEST_F(LibYUVCompareTest, BenchmarkHammingDistance_C) {
|
||||
const int kMaxWidth = 4096 * 3;
|
||||
align_buffer_page_end(src_a, kMaxWidth);
|
||||
align_buffer_page_end(src_b, kMaxWidth);
|
||||
memset(src_a, 0, kMaxWidth);
|
||||
memset(src_b, 0, kMaxWidth);
|
||||
|
||||
// Test known value
|
||||
memcpy(src_a, "test0123test4567", 16);
|
||||
memcpy(src_b, "tick0123tock4567", 16);
|
||||
uint32_t h1 = HammingDistance_C(src_a, src_b, 16);
|
||||
EXPECT_EQ(16u, h1);
|
||||
|
||||
// Test C vs OPT on random buffer
|
||||
MemRandomize(src_a, kMaxWidth);
|
||||
MemRandomize(src_b, kMaxWidth);
|
||||
|
||||
uint32_t h0 = HammingDistance_C(src_a, src_b, kMaxWidth);
|
||||
|
||||
int count =
|
||||
benchmark_iterations_ *
|
||||
((benchmark_width_ * benchmark_height_ + kMaxWidth - 1) / kMaxWidth);
|
||||
for (int i = 0; i < count; ++i) {
|
||||
h1 = HammingDistance_C(src_a, src_b, kMaxWidth);
|
||||
}
|
||||
|
||||
EXPECT_EQ(h0, h1);
|
||||
|
||||
free_aligned_buffer_page_end(src_a);
|
||||
free_aligned_buffer_page_end(src_b);
|
||||
}
|
||||
|
||||
TEST_F(LibYUVCompareTest, BenchmarkHammingDistance) {
|
||||
const int kMaxWidth = 4096 * 3;
|
||||
align_buffer_page_end(src_a, kMaxWidth);
|
||||
align_buffer_page_end(src_b, kMaxWidth);
|
||||
memset(src_a, 0, kMaxWidth);
|
||||
memset(src_b, 0, kMaxWidth);
|
||||
|
||||
memcpy(src_a, "test0123test4567", 16);
|
||||
memcpy(src_b, "tick0123tock4567", 16);
|
||||
uint64_t h1 = ComputeHammingDistance(src_a, src_b, 16);
|
||||
EXPECT_EQ(16u, h1);
|
||||
|
||||
// Test C vs OPT on random buffer
|
||||
MemRandomize(src_a, kMaxWidth);
|
||||
MemRandomize(src_b, kMaxWidth);
|
||||
|
||||
uint32_t h0 = HammingDistance_C(src_a, src_b, kMaxWidth);
|
||||
|
||||
int count =
|
||||
benchmark_iterations_ *
|
||||
((benchmark_width_ * benchmark_height_ + kMaxWidth - 1) / kMaxWidth);
|
||||
for (int i = 0; i < count; ++i) {
|
||||
h1 = ComputeHammingDistance(src_a, src_b, kMaxWidth);
|
||||
}
|
||||
|
||||
EXPECT_EQ(h0, h1);
|
||||
|
||||
free_aligned_buffer_page_end(src_a);
|
||||
free_aligned_buffer_page_end(src_b);
|
||||
}
|
||||
|
||||
// Tests low levels match reference C for specified size.
|
||||
// The opt implementations have size limitations
|
||||
// For NEON the counters are 16 bit so the shorts overflow after 65536 bytes.
|
||||
// So doing one less iteration of the loop is the maximum.
|
||||
#if defined(HAS_HAMMINGDISTANCE_NEON)
|
||||
static const int kMaxOptCount = 65536 - 32; // 65504
|
||||
#else
|
||||
static const int kMaxOptCount = (1 << (32 - 3)) - 64; // 536870848
|
||||
#endif
|
||||
|
||||
TEST_F(LibYUVCompareTest, TestHammingDistance_Opt) {
|
||||
uint32_t h1 = 0;
|
||||
const int kMaxWidth = (benchmark_width_ * benchmark_height_ + 63) & ~63;
|
||||
align_buffer_page_end(src_a, kMaxWidth);
|
||||
align_buffer_page_end(src_b, kMaxWidth);
|
||||
memset(src_a, 255u, kMaxWidth);
|
||||
memset(src_b, 0u, kMaxWidth);
|
||||
|
||||
uint64_t h0 = ComputeHammingDistance(src_a, src_b, kMaxWidth);
|
||||
EXPECT_EQ(kMaxWidth * 8ULL, h0);
|
||||
|
||||
for (int i = 0; i < benchmark_iterations_; ++i) {
|
||||
#if defined(HAS_HAMMINGDISTANCE_NEON)
|
||||
h1 = HammingDistance_NEON(src_a, src_b, kMaxWidth);
|
||||
#elif defined(HAS_HAMMINGDISTANCE_AVX2)
|
||||
int has_avx2 = TestCpuFlag(kCpuHasAVX2);
|
||||
if (has_avx2) {
|
||||
h1 = HammingDistance_AVX2(src_a, src_b, kMaxWidth);
|
||||
} else {
|
||||
int has_sse42 = TestCpuFlag(kCpuHasSSE42);
|
||||
if (has_sse42) {
|
||||
h1 = HammingDistance_SSE42(src_a, src_b, kMaxWidth);
|
||||
} else {
|
||||
int has_ssse3 = TestCpuFlag(kCpuHasSSSE3);
|
||||
if (has_ssse3) {
|
||||
h1 = HammingDistance_SSSE3(src_a, src_b, kMaxWidth);
|
||||
} else {
|
||||
h1 = HammingDistance_C(src_a, src_b, kMaxWidth);
|
||||
}
|
||||
}
|
||||
}
|
||||
#elif defined(HAS_HAMMINGDISTANCE_SSE42)
|
||||
int has_sse42 = TestCpuFlag(kCpuHasSSE42);
|
||||
if (has_sse42) {
|
||||
h1 = HammingDistance_SSE42(src_a, src_b, kMaxWidth);
|
||||
} else {
|
||||
h1 = HammingDistance_C(src_a, src_b, kMaxWidth);
|
||||
}
|
||||
#else
|
||||
h1 = HammingDistance_C(src_a, src_b, kMaxWidth);
|
||||
#endif
|
||||
}
|
||||
|
||||
// A large count will cause the low level to potentially overflow so the
|
||||
// result can not be expected to be correct.
|
||||
// TODO(fbarchard): Consider expecting the low 16 bits to match.
|
||||
if (kMaxWidth <= kMaxOptCount) {
|
||||
EXPECT_EQ(kMaxWidth * 8U, h1);
|
||||
} else {
|
||||
if (kMaxWidth * 8ULL != static_cast<uint64_t>(h1)) {
|
||||
printf(
|
||||
"warning - HammingDistance_Opt %u does not match %llu "
|
||||
"but length of %u is longer than guaranteed.\n",
|
||||
h1, kMaxWidth * 8ULL, kMaxWidth);
|
||||
} else {
|
||||
printf(
|
||||
"warning - HammingDistance_Opt %u matches but length of %u "
|
||||
"is longer than guaranteed.\n",
|
||||
h1, kMaxWidth);
|
||||
}
|
||||
}
|
||||
|
||||
free_aligned_buffer_page_end(src_a);
|
||||
free_aligned_buffer_page_end(src_b);
|
||||
}
|
||||
#endif // ENABLE_ROW_TESTS
|
||||
|
||||
TEST_F(LibYUVCompareTest, TestHammingDistance) {
|
||||
align_buffer_page_end(src_a, benchmark_width_ * benchmark_height_);
|
||||
align_buffer_page_end(src_b, benchmark_width_ * benchmark_height_);
|
||||
memset(src_a, 255u, benchmark_width_ * benchmark_height_);
|
||||
memset(src_b, 0, benchmark_width_ * benchmark_height_);
|
||||
|
||||
uint64_t h1 = 0;
|
||||
for (int i = 0; i < benchmark_iterations_; ++i) {
|
||||
h1 = ComputeHammingDistance(src_a, src_b,
|
||||
benchmark_width_ * benchmark_height_);
|
||||
}
|
||||
EXPECT_EQ(benchmark_width_ * benchmark_height_ * 8ULL, h1);
|
||||
|
||||
free_aligned_buffer_page_end(src_a);
|
||||
free_aligned_buffer_page_end(src_b);
|
||||
}
|
||||
|
||||
TEST_F(LibYUVCompareTest, BenchmarkSumSquareError_Opt) {
|
||||
const int kMaxWidth = 4096 * 3;
|
||||
align_buffer_page_end(src_a, kMaxWidth);
|
||||
align_buffer_page_end(src_b, kMaxWidth);
|
||||
memset(src_a, 0, kMaxWidth);
|
||||
memset(src_b, 0, kMaxWidth);
|
||||
|
||||
memcpy(src_a, "test0123test4567", 16);
|
||||
memcpy(src_b, "tick0123tock4567", 16);
|
||||
uint64_t h1 = ComputeSumSquareError(src_a, src_b, 16);
|
||||
EXPECT_EQ(790u, h1);
|
||||
|
||||
for (int i = 0; i < kMaxWidth; ++i) {
|
||||
src_a[i] = i;
|
||||
src_b[i] = i;
|
||||
}
|
||||
memset(src_a, 0, kMaxWidth);
|
||||
memset(src_b, 0, kMaxWidth);
|
||||
|
||||
int count =
|
||||
benchmark_iterations_ *
|
||||
((benchmark_width_ * benchmark_height_ + kMaxWidth - 1) / kMaxWidth);
|
||||
for (int i = 0; i < count; ++i) {
|
||||
h1 = ComputeSumSquareError(src_a, src_b, kMaxWidth);
|
||||
}
|
||||
|
||||
EXPECT_EQ(0u, h1);
|
||||
|
||||
free_aligned_buffer_page_end(src_a);
|
||||
free_aligned_buffer_page_end(src_b);
|
||||
}
|
||||
|
||||
TEST_F(LibYUVCompareTest, SumSquareError) {
|
||||
const int kMaxWidth = 4096 * 3;
|
||||
align_buffer_page_end(src_a, kMaxWidth);
|
||||
align_buffer_page_end(src_b, kMaxWidth);
|
||||
memset(src_a, 0, kMaxWidth);
|
||||
memset(src_b, 0, kMaxWidth);
|
||||
|
||||
uint64_t err;
|
||||
err = ComputeSumSquareError(src_a, src_b, kMaxWidth);
|
||||
|
||||
EXPECT_EQ(0u, err);
|
||||
|
||||
memset(src_a, 1, kMaxWidth);
|
||||
err = ComputeSumSquareError(src_a, src_b, kMaxWidth);
|
||||
|
||||
EXPECT_EQ(static_cast<int>(err), kMaxWidth);
|
||||
|
||||
memset(src_a, 190, kMaxWidth);
|
||||
memset(src_b, 193, kMaxWidth);
|
||||
err = ComputeSumSquareError(src_a, src_b, kMaxWidth);
|
||||
|
||||
EXPECT_EQ(static_cast<int>(err), kMaxWidth * 3 * 3);
|
||||
|
||||
for (int i = 0; i < kMaxWidth; ++i) {
|
||||
src_a[i] = (fastrand() & 0xff);
|
||||
src_b[i] = (fastrand() & 0xff);
|
||||
}
|
||||
|
||||
MaskCpuFlags(disable_cpu_flags_);
|
||||
uint64_t c_err = ComputeSumSquareError(src_a, src_b, kMaxWidth);
|
||||
|
||||
MaskCpuFlags(benchmark_cpu_info_);
|
||||
uint64_t opt_err = ComputeSumSquareError(src_a, src_b, kMaxWidth);
|
||||
|
||||
EXPECT_EQ(c_err, opt_err);
|
||||
|
||||
free_aligned_buffer_page_end(src_a);
|
||||
free_aligned_buffer_page_end(src_b);
|
||||
}
|
||||
|
||||
TEST_F(LibYUVCompareTest, BenchmarkPsnr_Opt) {
|
||||
align_buffer_page_end(src_a, benchmark_width_ * benchmark_height_);
|
||||
align_buffer_page_end(src_b, benchmark_width_ * benchmark_height_);
|
||||
for (int i = 0; i < benchmark_width_ * benchmark_height_; ++i) {
|
||||
src_a[i] = i;
|
||||
src_b[i] = i;
|
||||
}
|
||||
|
||||
MaskCpuFlags(benchmark_cpu_info_);
|
||||
|
||||
double opt_time = get_time();
|
||||
for (int i = 0; i < benchmark_iterations_; ++i) {
|
||||
CalcFramePsnr(src_a, benchmark_width_, src_b, benchmark_width_,
|
||||
benchmark_width_, benchmark_height_);
|
||||
}
|
||||
|
||||
opt_time = (get_time() - opt_time) / benchmark_iterations_;
|
||||
printf("BenchmarkPsnr_Opt - %8.2f us opt\n", opt_time * 1e6);
|
||||
|
||||
EXPECT_EQ(0, 0);
|
||||
|
||||
free_aligned_buffer_page_end(src_a);
|
||||
free_aligned_buffer_page_end(src_b);
|
||||
}
|
||||
|
||||
TEST_F(LibYUVCompareTest, BenchmarkPsnr_Unaligned) {
|
||||
align_buffer_page_end(src_a, benchmark_width_ * benchmark_height_ + 1);
|
||||
align_buffer_page_end(src_b, benchmark_width_ * benchmark_height_);
|
||||
for (int i = 0; i < benchmark_width_ * benchmark_height_; ++i) {
|
||||
src_a[i + 1] = i;
|
||||
src_b[i] = i;
|
||||
}
|
||||
|
||||
MaskCpuFlags(benchmark_cpu_info_);
|
||||
|
||||
double opt_time = get_time();
|
||||
for (int i = 0; i < benchmark_iterations_; ++i) {
|
||||
CalcFramePsnr(src_a + 1, benchmark_width_, src_b, benchmark_width_,
|
||||
benchmark_width_, benchmark_height_);
|
||||
}
|
||||
|
||||
opt_time = (get_time() - opt_time) / benchmark_iterations_;
|
||||
printf("BenchmarkPsnr_Opt - %8.2f us opt\n", opt_time * 1e6);
|
||||
|
||||
EXPECT_EQ(0, 0);
|
||||
|
||||
free_aligned_buffer_page_end(src_a);
|
||||
free_aligned_buffer_page_end(src_b);
|
||||
}
|
||||
|
||||
TEST_F(LibYUVCompareTest, Psnr) {
|
||||
const int kSrcWidth = benchmark_width_;
|
||||
const int kSrcHeight = benchmark_height_;
|
||||
const int b = 128;
|
||||
const int kSrcPlaneSize = (kSrcWidth + b * 2) * (kSrcHeight + b * 2);
|
||||
const int kSrcStride = 2 * b + kSrcWidth;
|
||||
align_buffer_page_end(src_a, kSrcPlaneSize);
|
||||
align_buffer_page_end(src_b, kSrcPlaneSize);
|
||||
memset(src_a, 0, kSrcPlaneSize);
|
||||
memset(src_b, 0, kSrcPlaneSize);
|
||||
|
||||
double err;
|
||||
err = CalcFramePsnr(src_a + kSrcStride * b + b, kSrcStride,
|
||||
src_b + kSrcStride * b + b, kSrcStride, kSrcWidth,
|
||||
kSrcHeight);
|
||||
|
||||
EXPECT_EQ(err, kMaxPsnr);
|
||||
|
||||
memset(src_a, 255, kSrcPlaneSize);
|
||||
|
||||
err = CalcFramePsnr(src_a + kSrcStride * b + b, kSrcStride,
|
||||
src_b + kSrcStride * b + b, kSrcStride, kSrcWidth,
|
||||
kSrcHeight);
|
||||
|
||||
EXPECT_EQ(err, 0.0);
|
||||
|
||||
memset(src_a, 1, kSrcPlaneSize);
|
||||
|
||||
err = CalcFramePsnr(src_a + kSrcStride * b + b, kSrcStride,
|
||||
src_b + kSrcStride * b + b, kSrcStride, kSrcWidth,
|
||||
kSrcHeight);
|
||||
|
||||
EXPECT_GT(err, 48.0);
|
||||
EXPECT_LT(err, 49.0);
|
||||
|
||||
for (int i = 0; i < kSrcPlaneSize; ++i) {
|
||||
src_a[i] = i;
|
||||
}
|
||||
|
||||
err = CalcFramePsnr(src_a + kSrcStride * b + b, kSrcStride,
|
||||
src_b + kSrcStride * b + b, kSrcStride, kSrcWidth,
|
||||
kSrcHeight);
|
||||
|
||||
EXPECT_GT(err, 2.0);
|
||||
if (kSrcWidth * kSrcHeight >= 256) {
|
||||
EXPECT_LT(err, 6.0);
|
||||
}
|
||||
|
||||
memset(src_a, 0, kSrcPlaneSize);
|
||||
memset(src_b, 0, kSrcPlaneSize);
|
||||
|
||||
for (int i = b; i < (kSrcHeight + b); ++i) {
|
||||
for (int j = b; j < (kSrcWidth + b); ++j) {
|
||||
src_a[(i * kSrcStride) + j] = (fastrand() & 0xff);
|
||||
src_b[(i * kSrcStride) + j] = (fastrand() & 0xff);
|
||||
}
|
||||
}
|
||||
|
||||
MaskCpuFlags(disable_cpu_flags_);
|
||||
double c_err, opt_err;
|
||||
|
||||
c_err = CalcFramePsnr(src_a + kSrcStride * b + b, kSrcStride,
|
||||
src_b + kSrcStride * b + b, kSrcStride, kSrcWidth,
|
||||
kSrcHeight);
|
||||
|
||||
MaskCpuFlags(benchmark_cpu_info_);
|
||||
|
||||
opt_err = CalcFramePsnr(src_a + kSrcStride * b + b, kSrcStride,
|
||||
src_b + kSrcStride * b + b, kSrcStride, kSrcWidth,
|
||||
kSrcHeight);
|
||||
|
||||
EXPECT_EQ(opt_err, c_err);
|
||||
|
||||
free_aligned_buffer_page_end(src_a);
|
||||
free_aligned_buffer_page_end(src_b);
|
||||
}
|
||||
|
||||
TEST_F(LibYUVCompareTest, DISABLED_BenchmarkSsim_Opt) {
|
||||
align_buffer_page_end(src_a, benchmark_width_ * benchmark_height_);
|
||||
align_buffer_page_end(src_b, benchmark_width_ * benchmark_height_);
|
||||
for (int i = 0; i < benchmark_width_ * benchmark_height_; ++i) {
|
||||
src_a[i] = i;
|
||||
src_b[i] = i;
|
||||
}
|
||||
|
||||
MaskCpuFlags(benchmark_cpu_info_);
|
||||
|
||||
double opt_time = get_time();
|
||||
for (int i = 0; i < benchmark_iterations_; ++i) {
|
||||
CalcFrameSsim(src_a, benchmark_width_, src_b, benchmark_width_,
|
||||
benchmark_width_, benchmark_height_);
|
||||
}
|
||||
|
||||
opt_time = (get_time() - opt_time) / benchmark_iterations_;
|
||||
printf("BenchmarkSsim_Opt - %8.2f us opt\n", opt_time * 1e6);
|
||||
|
||||
EXPECT_EQ(0, 0); // Pass if we get this far.
|
||||
|
||||
free_aligned_buffer_page_end(src_a);
|
||||
free_aligned_buffer_page_end(src_b);
|
||||
}
|
||||
|
||||
TEST_F(LibYUVCompareTest, Ssim) {
|
||||
const int kSrcWidth = benchmark_width_;
|
||||
const int kSrcHeight = benchmark_height_;
|
||||
const int b = 128;
|
||||
const int kSrcPlaneSize = (kSrcWidth + b * 2) * (kSrcHeight + b * 2);
|
||||
const int kSrcStride = 2 * b + kSrcWidth;
|
||||
align_buffer_page_end(src_a, kSrcPlaneSize);
|
||||
align_buffer_page_end(src_b, kSrcPlaneSize);
|
||||
memset(src_a, 0, kSrcPlaneSize);
|
||||
memset(src_b, 0, kSrcPlaneSize);
|
||||
|
||||
if (kSrcWidth <= 8 || kSrcHeight <= 8) {
|
||||
printf("warning - Ssim size too small. Testing function executes.\n");
|
||||
}
|
||||
|
||||
double err;
|
||||
err = CalcFrameSsim(src_a + kSrcStride * b + b, kSrcStride,
|
||||
src_b + kSrcStride * b + b, kSrcStride, kSrcWidth,
|
||||
kSrcHeight);
|
||||
|
||||
if (kSrcWidth > 8 && kSrcHeight > 8) {
|
||||
EXPECT_EQ(err, 1.0);
|
||||
}
|
||||
|
||||
memset(src_a, 255, kSrcPlaneSize);
|
||||
|
||||
err = CalcFrameSsim(src_a + kSrcStride * b + b, kSrcStride,
|
||||
src_b + kSrcStride * b + b, kSrcStride, kSrcWidth,
|
||||
kSrcHeight);
|
||||
|
||||
if (kSrcWidth > 8 && kSrcHeight > 8) {
|
||||
EXPECT_LT(err, 0.0001);
|
||||
}
|
||||
|
||||
memset(src_a, 1, kSrcPlaneSize);
|
||||
|
||||
err = CalcFrameSsim(src_a + kSrcStride * b + b, kSrcStride,
|
||||
src_b + kSrcStride * b + b, kSrcStride, kSrcWidth,
|
||||
kSrcHeight);
|
||||
|
||||
if (kSrcWidth > 8 && kSrcHeight > 8) {
|
||||
EXPECT_GT(err, 0.0001);
|
||||
EXPECT_LT(err, 0.9);
|
||||
}
|
||||
|
||||
for (int i = 0; i < kSrcPlaneSize; ++i) {
|
||||
src_a[i] = i;
|
||||
}
|
||||
|
||||
err = CalcFrameSsim(src_a + kSrcStride * b + b, kSrcStride,
|
||||
src_b + kSrcStride * b + b, kSrcStride, kSrcWidth,
|
||||
kSrcHeight);
|
||||
|
||||
if (kSrcWidth > 8 && kSrcHeight > 8) {
|
||||
EXPECT_GT(err, 0.0);
|
||||
EXPECT_LT(err, 0.01);
|
||||
}
|
||||
|
||||
for (int i = b; i < (kSrcHeight + b); ++i) {
|
||||
for (int j = b; j < (kSrcWidth + b); ++j) {
|
||||
src_a[(i * kSrcStride) + j] = (fastrand() & 0xff);
|
||||
src_b[(i * kSrcStride) + j] = (fastrand() & 0xff);
|
||||
}
|
||||
}
|
||||
|
||||
MaskCpuFlags(disable_cpu_flags_);
|
||||
double c_err, opt_err;
|
||||
|
||||
c_err = CalcFrameSsim(src_a + kSrcStride * b + b, kSrcStride,
|
||||
src_b + kSrcStride * b + b, kSrcStride, kSrcWidth,
|
||||
kSrcHeight);
|
||||
|
||||
MaskCpuFlags(benchmark_cpu_info_);
|
||||
|
||||
opt_err = CalcFrameSsim(src_a + kSrcStride * b + b, kSrcStride,
|
||||
src_b + kSrcStride * b + b, kSrcStride, kSrcWidth,
|
||||
kSrcHeight);
|
||||
|
||||
if (kSrcWidth > 8 && kSrcHeight > 8) {
|
||||
EXPECT_EQ(opt_err, c_err);
|
||||
}
|
||||
|
||||
free_aligned_buffer_page_end(src_a);
|
||||
free_aligned_buffer_page_end(src_b);
|
||||
}
|
||||
|
||||
} // namespace libyuv
|
||||
4341
externals/libyuv/unit_test/convert_test.cc
vendored
Normal file
4341
externals/libyuv/unit_test/convert_test.cc
vendored
Normal file
File diff suppressed because it is too large
Load Diff
295
externals/libyuv/unit_test/cpu_test.cc
vendored
Normal file
295
externals/libyuv/unit_test/cpu_test.cc
vendored
Normal file
@@ -0,0 +1,295 @@
|
||||
/*
|
||||
* Copyright 2012 The LibYuv Project Authors. All rights reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "../unit_test/unit_test.h"
|
||||
#include "libyuv/basic_types.h"
|
||||
#include "libyuv/cpu_id.h"
|
||||
#include "libyuv/version.h"
|
||||
|
||||
namespace libyuv {
|
||||
|
||||
TEST_F(LibYUVBaseTest, TestCpuHas) {
|
||||
int cpu_flags = TestCpuFlag(-1);
|
||||
printf("Cpu Flags %d\n", cpu_flags);
|
||||
#if defined(__arm__) || defined(__aarch64__)
|
||||
int has_arm = TestCpuFlag(kCpuHasARM);
|
||||
printf("Has ARM %d\n", has_arm);
|
||||
int has_neon = TestCpuFlag(kCpuHasNEON);
|
||||
printf("Has NEON %d\n", has_neon);
|
||||
#endif
|
||||
int has_x86 = TestCpuFlag(kCpuHasX86);
|
||||
int has_sse2 = TestCpuFlag(kCpuHasSSE2);
|
||||
int has_ssse3 = TestCpuFlag(kCpuHasSSSE3);
|
||||
int has_sse41 = TestCpuFlag(kCpuHasSSE41);
|
||||
int has_sse42 = TestCpuFlag(kCpuHasSSE42);
|
||||
int has_avx = TestCpuFlag(kCpuHasAVX);
|
||||
int has_avx2 = TestCpuFlag(kCpuHasAVX2);
|
||||
int has_erms = TestCpuFlag(kCpuHasERMS);
|
||||
int has_fma3 = TestCpuFlag(kCpuHasFMA3);
|
||||
int has_f16c = TestCpuFlag(kCpuHasF16C);
|
||||
int has_gfni = TestCpuFlag(kCpuHasGFNI);
|
||||
int has_avx512bw = TestCpuFlag(kCpuHasAVX512BW);
|
||||
int has_avx512vl = TestCpuFlag(kCpuHasAVX512VL);
|
||||
int has_avx512vnni = TestCpuFlag(kCpuHasAVX512VNNI);
|
||||
int has_avx512vbmi = TestCpuFlag(kCpuHasAVX512VBMI);
|
||||
int has_avx512vbmi2 = TestCpuFlag(kCpuHasAVX512VBMI2);
|
||||
int has_avx512vbitalg = TestCpuFlag(kCpuHasAVX512VBITALG);
|
||||
int has_avx512vpopcntdq = TestCpuFlag(kCpuHasAVX512VPOPCNTDQ);
|
||||
printf("Has X86 %d\n", has_x86);
|
||||
printf("Has SSE2 %d\n", has_sse2);
|
||||
printf("Has SSSE3 %d\n", has_ssse3);
|
||||
printf("Has SSE41 %d\n", has_sse41);
|
||||
printf("Has SSE42 %d\n", has_sse42);
|
||||
printf("Has AVX %d\n", has_avx);
|
||||
printf("Has AVX2 %d\n", has_avx2);
|
||||
printf("Has ERMS %d\n", has_erms);
|
||||
printf("Has FMA3 %d\n", has_fma3);
|
||||
printf("Has F16C %d\n", has_f16c);
|
||||
printf("Has GFNI %d\n", has_gfni);
|
||||
printf("Has AVX512BW %d\n", has_avx512bw);
|
||||
printf("Has AVX512VL %d\n", has_avx512vl);
|
||||
printf("Has AVX512VNNI %d\n", has_avx512vnni);
|
||||
printf("Has AVX512VBMI %d\n", has_avx512vbmi);
|
||||
printf("Has AVX512VBMI2 %d\n", has_avx512vbmi2);
|
||||
printf("Has AVX512VBITALG %d\n", has_avx512vbitalg);
|
||||
printf("Has AVX512VPOPCNTDQ %d\n", has_avx512vpopcntdq);
|
||||
|
||||
#if defined(__mips__)
|
||||
int has_mips = TestCpuFlag(kCpuHasMIPS);
|
||||
printf("Has MIPS %d\n", has_mips);
|
||||
int has_msa = TestCpuFlag(kCpuHasMSA);
|
||||
printf("Has MSA %d\n", has_msa);
|
||||
#endif
|
||||
|
||||
#if defined(__loongarch__)
|
||||
int has_loongarch = TestCpuFlag(kCpuHasLOONGARCH);
|
||||
printf("Has LOONGARCH %d\n", has_loongarch);
|
||||
int has_lsx = TestCpuFlag(kCpuHasLSX);
|
||||
printf("Has LSX %d\n", has_lsx);
|
||||
int has_lasx = TestCpuFlag(kCpuHasLASX);
|
||||
printf("Has LASX %d\n", has_lasx);
|
||||
#endif
|
||||
}
|
||||
|
||||
TEST_F(LibYUVBaseTest, TestCompilerMacros) {
|
||||
// Tests all macros used in public headers.
|
||||
#ifdef __ATOMIC_RELAXED
|
||||
printf("__ATOMIC_RELAXED %d\n", __ATOMIC_RELAXED);
|
||||
#endif
|
||||
#ifdef __cplusplus
|
||||
printf("__cplusplus %ld\n", __cplusplus);
|
||||
#endif
|
||||
#ifdef __clang_major__
|
||||
printf("__clang_major__ %d\n", __clang_major__);
|
||||
#endif
|
||||
#ifdef __clang_minor__
|
||||
printf("__clang_minor__ %d\n", __clang_minor__);
|
||||
#endif
|
||||
#ifdef __GNUC__
|
||||
printf("__GNUC__ %d\n", __GNUC__);
|
||||
#endif
|
||||
#ifdef __GNUC_MINOR__
|
||||
printf("__GNUC_MINOR__ %d\n", __GNUC_MINOR__);
|
||||
#endif
|
||||
#ifdef __i386__
|
||||
printf("__i386__ %d\n", __i386__);
|
||||
#endif
|
||||
#ifdef __mips
|
||||
printf("__mips %d\n", __mips);
|
||||
#endif
|
||||
#ifdef __mips_isa_rev
|
||||
printf("__mips_isa_rev %d\n", __mips_isa_rev);
|
||||
#endif
|
||||
#ifdef __x86_64__
|
||||
printf("__x86_64__ %d\n", __x86_64__);
|
||||
#endif
|
||||
#ifdef _MSC_VER
|
||||
printf("_MSC_VER %d\n", _MSC_VER);
|
||||
#endif
|
||||
#ifdef __aarch64__
|
||||
printf("__aarch64__ %d\n", __aarch64__);
|
||||
#endif
|
||||
#ifdef __APPLE__
|
||||
printf("__APPLE__ %d\n", __APPLE__);
|
||||
#endif
|
||||
#ifdef __arm__
|
||||
printf("__arm__ %d\n", __arm__);
|
||||
#endif
|
||||
#ifdef __clang__
|
||||
printf("__clang__ %d\n", __clang__);
|
||||
#endif
|
||||
#ifdef __CLR_VER
|
||||
printf("__CLR_VER %d\n", __CLR_VER);
|
||||
#endif
|
||||
#ifdef __CYGWIN__
|
||||
printf("__CYGWIN__ %d\n", __CYGWIN__);
|
||||
#endif
|
||||
#ifdef __llvm__
|
||||
printf("__llvm__ %d\n", __llvm__);
|
||||
#endif
|
||||
#ifdef __mips_msa
|
||||
printf("__mips_msa %d\n", __mips_msa);
|
||||
#endif
|
||||
#ifdef __native_client__
|
||||
printf("__native_client__ %d\n", __native_client__);
|
||||
#endif
|
||||
#ifdef __pic__
|
||||
printf("__pic__ %d\n", __pic__);
|
||||
#endif
|
||||
#ifdef __pnacl__
|
||||
printf("__pnacl__ %d\n", __pnacl__);
|
||||
#endif
|
||||
#ifdef _M_IX86
|
||||
printf("_M_IX86 %d\n", _M_IX86);
|
||||
#endif
|
||||
#ifdef _M_X64
|
||||
printf("_M_X64 %d\n", _M_X64);
|
||||
#endif
|
||||
#ifdef _MIPS_ARCH_LOONGSON3A
|
||||
printf("_MIPS_ARCH_LOONGSON3A %d\n", _MIPS_ARCH_LOONGSON3A);
|
||||
#endif
|
||||
#ifdef __loongarch__
|
||||
printf("__loongarch__ %d\n", __loongarch__);
|
||||
#endif
|
||||
#ifdef _WIN32
|
||||
printf("_WIN32 %d\n", _WIN32);
|
||||
#endif
|
||||
#ifdef GG_LONGLONG
|
||||
printf("GG_LONGLONG %d\n", GG_LONGLONG);
|
||||
#endif
|
||||
#ifdef INT_TYPES_DEFINED
|
||||
printf("INT_TYPES_DEFINED\n");
|
||||
#endif
|
||||
#ifdef __has_feature
|
||||
printf("__has_feature\n");
|
||||
#if __has_feature(memory_sanitizer)
|
||||
printf("__has_feature(memory_sanitizer) %d\n",
|
||||
__has_feature(memory_sanitizer));
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
#if defined(__i386__) || defined(__x86_64__) || defined(_M_IX86) || \
|
||||
defined(_M_X64)
|
||||
TEST_F(LibYUVBaseTest, TestCpuId) {
|
||||
int has_x86 = TestCpuFlag(kCpuHasX86);
|
||||
if (has_x86) {
|
||||
int cpu_info[4];
|
||||
// Vendor ID:
|
||||
// AuthenticAMD AMD processor
|
||||
// CentaurHauls Centaur processor
|
||||
// CyrixInstead Cyrix processor
|
||||
// GenuineIntel Intel processor
|
||||
// GenuineTMx86 Transmeta processor
|
||||
// Geode by NSC National Semiconductor processor
|
||||
// NexGenDriven NexGen processor
|
||||
// RiseRiseRise Rise Technology processor
|
||||
// SiS SiS SiS SiS processor
|
||||
// UMC UMC UMC UMC processor
|
||||
CpuId(0, 0, cpu_info);
|
||||
cpu_info[0] = cpu_info[1]; // Reorder output
|
||||
cpu_info[1] = cpu_info[3];
|
||||
cpu_info[3] = 0;
|
||||
printf("Cpu Vendor: %s %x %x %x\n", reinterpret_cast<char*>(&cpu_info[0]),
|
||||
cpu_info[0], cpu_info[1], cpu_info[2]);
|
||||
EXPECT_EQ(12u, strlen(reinterpret_cast<char*>(&cpu_info[0])));
|
||||
|
||||
// CPU Family and Model
|
||||
// 3:0 - Stepping
|
||||
// 7:4 - Model
|
||||
// 11:8 - Family
|
||||
// 13:12 - Processor Type
|
||||
// 19:16 - Extended Model
|
||||
// 27:20 - Extended Family
|
||||
CpuId(1, 0, cpu_info);
|
||||
int family = ((cpu_info[0] >> 8) & 0x0f) | ((cpu_info[0] >> 16) & 0xff0);
|
||||
int model = ((cpu_info[0] >> 4) & 0x0f) | ((cpu_info[0] >> 12) & 0xf0);
|
||||
printf("Cpu Family %d (0x%x), Model %d (0x%x)\n", family, family, model,
|
||||
model);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
static int FileExists(const char* file_name) {
|
||||
FILE* f = fopen(file_name, "r");
|
||||
if (!f) {
|
||||
return 0;
|
||||
}
|
||||
fclose(f);
|
||||
return 1;
|
||||
}
|
||||
|
||||
TEST_F(LibYUVBaseTest, TestLinuxNeon) {
|
||||
if (FileExists("../../unit_test/testdata/arm_v7.txt")) {
|
||||
printf("Note: testing to load \"../../unit_test/testdata/arm_v7.txt\"\n");
|
||||
|
||||
EXPECT_EQ(0, ArmCpuCaps("../../unit_test/testdata/arm_v7.txt"));
|
||||
EXPECT_EQ(kCpuHasNEON, ArmCpuCaps("../../unit_test/testdata/tegra3.txt"));
|
||||
EXPECT_EQ(kCpuHasNEON, ArmCpuCaps("../../unit_test/testdata/juno.txt"));
|
||||
} else {
|
||||
printf("WARNING: unable to load \"../../unit_test/testdata/arm_v7.txt\"\n");
|
||||
}
|
||||
#if defined(__linux__) && defined(__ARM_NEON__)
|
||||
if (FileExists("/proc/cpuinfo")) {
|
||||
if (kCpuHasNEON != ArmCpuCaps("/proc/cpuinfo")) {
|
||||
// This can happen on ARM emulator but /proc/cpuinfo is from host.
|
||||
printf("WARNING: Neon build enabled but CPU does not have NEON\n");
|
||||
}
|
||||
} else {
|
||||
printf("WARNING: unable to load \"/proc/cpuinfo\"\n");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
TEST_F(LibYUVBaseTest, TestLinuxMipsMsa) {
|
||||
if (FileExists("../../unit_test/testdata/mips.txt")) {
|
||||
printf("Note: testing to load \"../../unit_test/testdata/mips.txt\"\n");
|
||||
|
||||
EXPECT_EQ(0, MipsCpuCaps("../../unit_test/testdata/mips.txt"));
|
||||
EXPECT_EQ(kCpuHasMSA, MipsCpuCaps("../../unit_test/testdata/mips_msa.txt"));
|
||||
EXPECT_EQ(kCpuHasMSA,
|
||||
MipsCpuCaps("../../unit_test/testdata/mips_loongson2k.txt"));
|
||||
} else {
|
||||
printf("WARNING: unable to load \"../../unit_test/testdata/mips.txt\"\n");
|
||||
}
|
||||
}
|
||||
|
||||
// TODO(fbarchard): Fix clangcl test of cpuflags.
|
||||
#ifdef _MSC_VER
|
||||
TEST_F(LibYUVBaseTest, DISABLED_TestSetCpuFlags) {
|
||||
#else
|
||||
TEST_F(LibYUVBaseTest, TestSetCpuFlags) {
|
||||
#endif
|
||||
// Reset any masked flags that may have been set so auto init is enabled.
|
||||
MaskCpuFlags(0);
|
||||
|
||||
int original_cpu_flags = TestCpuFlag(-1);
|
||||
|
||||
// Test setting different CPU configurations.
|
||||
int cpu_flags = kCpuHasARM | kCpuHasNEON | kCpuInitialized;
|
||||
SetCpuFlags(cpu_flags);
|
||||
EXPECT_EQ(cpu_flags, TestCpuFlag(-1));
|
||||
|
||||
cpu_flags = kCpuHasX86 | kCpuInitialized;
|
||||
SetCpuFlags(cpu_flags);
|
||||
EXPECT_EQ(cpu_flags, TestCpuFlag(-1));
|
||||
|
||||
// Test that setting 0 turns auto-init back on.
|
||||
SetCpuFlags(0);
|
||||
EXPECT_EQ(original_cpu_flags, TestCpuFlag(-1));
|
||||
|
||||
// Restore the CPU flag mask.
|
||||
MaskCpuFlags(benchmark_cpu_info_);
|
||||
}
|
||||
|
||||
} // namespace libyuv
|
||||
63
externals/libyuv/unit_test/cpu_thread_test.cc
vendored
Normal file
63
externals/libyuv/unit_test/cpu_thread_test.cc
vendored
Normal file
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* Copyright 2017 The LibYuv Project Authors. All rights reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include "libyuv/cpu_id.h"
|
||||
|
||||
#if defined(__clang__) && !defined(__wasm__)
|
||||
#if __has_include(<pthread.h>)
|
||||
#define LIBYUV_HAVE_PTHREAD 1
|
||||
#endif
|
||||
#elif defined(__linux__)
|
||||
#define LIBYUV_HAVE_PTHREAD 1
|
||||
#endif
|
||||
|
||||
#ifdef LIBYUV_HAVE_PTHREAD
|
||||
#include <pthread.h>
|
||||
#endif
|
||||
|
||||
namespace libyuv {
|
||||
|
||||
#ifdef LIBYUV_HAVE_PTHREAD
|
||||
void* ThreadMain(void* arg) {
|
||||
int* flags = static_cast<int*>(arg);
|
||||
|
||||
*flags = TestCpuFlag(kCpuInitialized);
|
||||
return nullptr;
|
||||
}
|
||||
#endif // LIBYUV_HAVE_PTHREAD
|
||||
|
||||
// Call TestCpuFlag() from two threads. ThreadSanitizer should not report any
|
||||
// data race.
|
||||
TEST(LibYUVCpuThreadTest, TestCpuFlagMultipleThreads) {
|
||||
#ifdef LIBYUV_HAVE_PTHREAD
|
||||
int cpu_flags1;
|
||||
int cpu_flags2;
|
||||
int ret;
|
||||
pthread_t thread1;
|
||||
pthread_t thread2;
|
||||
|
||||
MaskCpuFlags(0); // Reset to 0 to allow auto detect.
|
||||
ret = pthread_create(&thread1, nullptr, ThreadMain, &cpu_flags1);
|
||||
ASSERT_EQ(ret, 0);
|
||||
ret = pthread_create(&thread2, nullptr, ThreadMain, &cpu_flags2);
|
||||
ASSERT_EQ(ret, 0);
|
||||
ret = pthread_join(thread1, nullptr);
|
||||
EXPECT_EQ(ret, 0);
|
||||
ret = pthread_join(thread2, nullptr);
|
||||
EXPECT_EQ(ret, 0);
|
||||
EXPECT_EQ(cpu_flags1, cpu_flags2);
|
||||
#else
|
||||
printf("pthread unavailable; Test skipped.");
|
||||
#endif // LIBYUV_HAVE_PTHREAD
|
||||
}
|
||||
|
||||
} // namespace libyuv
|
||||
160
externals/libyuv/unit_test/math_test.cc
vendored
Normal file
160
externals/libyuv/unit_test/math_test.cc
vendored
Normal file
@@ -0,0 +1,160 @@
|
||||
/*
|
||||
* Copyright 2013 The LibYuv Project Authors. All rights reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
|
||||
#include "../unit_test/unit_test.h"
|
||||
#include "libyuv/basic_types.h"
|
||||
#include "libyuv/cpu_id.h"
|
||||
#include "libyuv/scale.h"
|
||||
|
||||
#ifdef ENABLE_ROW_TESTS
|
||||
#include "libyuv/scale_row.h"
|
||||
#endif
|
||||
|
||||
namespace libyuv {
|
||||
|
||||
#ifdef ENABLE_ROW_TESTS
|
||||
TEST_F(LibYUVBaseTest, TestFixedDiv) {
|
||||
int num[1280];
|
||||
int div[1280];
|
||||
int result_opt[1280];
|
||||
int result_c[1280];
|
||||
|
||||
EXPECT_EQ(0x10000, libyuv::FixedDiv(1, 1));
|
||||
EXPECT_EQ(0x7fff0000, libyuv::FixedDiv(0x7fff, 1));
|
||||
// TODO(fbarchard): Avoid the following that throw exceptions.
|
||||
// EXPECT_EQ(0x100000000, libyuv::FixedDiv(0x10000, 1));
|
||||
// EXPECT_EQ(0x80000000, libyuv::FixedDiv(0x8000, 1));
|
||||
|
||||
EXPECT_EQ(0x20000, libyuv::FixedDiv(640 * 2, 640));
|
||||
EXPECT_EQ(0x30000, libyuv::FixedDiv(640 * 3, 640));
|
||||
EXPECT_EQ(0x40000, libyuv::FixedDiv(640 * 4, 640));
|
||||
EXPECT_EQ(0x50000, libyuv::FixedDiv(640 * 5, 640));
|
||||
EXPECT_EQ(0x60000, libyuv::FixedDiv(640 * 6, 640));
|
||||
EXPECT_EQ(0x70000, libyuv::FixedDiv(640 * 7, 640));
|
||||
EXPECT_EQ(0x80000, libyuv::FixedDiv(640 * 8, 640));
|
||||
EXPECT_EQ(0xa0000, libyuv::FixedDiv(640 * 10, 640));
|
||||
EXPECT_EQ(0x20000, libyuv::FixedDiv(960 * 2, 960));
|
||||
EXPECT_EQ(0x08000, libyuv::FixedDiv(640 / 2, 640));
|
||||
EXPECT_EQ(0x04000, libyuv::FixedDiv(640 / 4, 640));
|
||||
EXPECT_EQ(0x20000, libyuv::FixedDiv(1080 * 2, 1080));
|
||||
EXPECT_EQ(0x20000, libyuv::FixedDiv(200000, 100000));
|
||||
EXPECT_EQ(0x18000, libyuv::FixedDiv(150000, 100000));
|
||||
EXPECT_EQ(0x20000, libyuv::FixedDiv(40000, 20000));
|
||||
EXPECT_EQ(0x20000, libyuv::FixedDiv(-40000, -20000));
|
||||
EXPECT_EQ(-0x20000, libyuv::FixedDiv(40000, -20000));
|
||||
EXPECT_EQ(-0x20000, libyuv::FixedDiv(-40000, 20000));
|
||||
EXPECT_EQ(0x10000, libyuv::FixedDiv(4095, 4095));
|
||||
EXPECT_EQ(0x10000, libyuv::FixedDiv(4096, 4096));
|
||||
EXPECT_EQ(0x10000, libyuv::FixedDiv(4097, 4097));
|
||||
EXPECT_EQ(123 * 65536, libyuv::FixedDiv(123, 1));
|
||||
|
||||
for (int i = 1; i < 4100; ++i) {
|
||||
EXPECT_EQ(0x10000, libyuv::FixedDiv(i, i));
|
||||
EXPECT_EQ(0x20000, libyuv::FixedDiv(i * 2, i));
|
||||
EXPECT_EQ(0x30000, libyuv::FixedDiv(i * 3, i));
|
||||
EXPECT_EQ(0x40000, libyuv::FixedDiv(i * 4, i));
|
||||
EXPECT_EQ(0x08000, libyuv::FixedDiv(i, i * 2));
|
||||
EXPECT_NEAR(16384 * 65536 / i, libyuv::FixedDiv(16384, i), 1);
|
||||
}
|
||||
EXPECT_EQ(123 * 65536, libyuv::FixedDiv(123, 1));
|
||||
|
||||
MemRandomize(reinterpret_cast<uint8_t*>(&num[0]), sizeof(num));
|
||||
MemRandomize(reinterpret_cast<uint8_t*>(&div[0]), sizeof(div));
|
||||
for (int j = 0; j < 1280; ++j) {
|
||||
if (div[j] == 0) {
|
||||
div[j] = 1280;
|
||||
}
|
||||
num[j] &= 0xffff; // Clamp to avoid divide overflow.
|
||||
}
|
||||
for (int i = 0; i < benchmark_pixels_div1280_; ++i) {
|
||||
for (int j = 0; j < 1280; ++j) {
|
||||
result_opt[j] = libyuv::FixedDiv(num[j], div[j]);
|
||||
}
|
||||
}
|
||||
for (int j = 0; j < 1280; ++j) {
|
||||
result_c[j] = libyuv::FixedDiv_C(num[j], div[j]);
|
||||
EXPECT_NEAR(result_c[j], result_opt[j], 1);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(LibYUVBaseTest, TestFixedDiv_Opt) {
|
||||
int num[1280];
|
||||
int div[1280];
|
||||
int result_opt[1280];
|
||||
int result_c[1280];
|
||||
|
||||
MemRandomize(reinterpret_cast<uint8_t*>(&num[0]), sizeof(num));
|
||||
MemRandomize(reinterpret_cast<uint8_t*>(&div[0]), sizeof(div));
|
||||
for (int j = 0; j < 1280; ++j) {
|
||||
num[j] &= 4095; // Make numerator smaller.
|
||||
div[j] &= 4095; // Make divisor smaller.
|
||||
if (div[j] == 0) {
|
||||
div[j] = 1280;
|
||||
}
|
||||
}
|
||||
|
||||
int has_x86 = TestCpuFlag(kCpuHasX86);
|
||||
for (int i = 0; i < benchmark_pixels_div1280_; ++i) {
|
||||
if (has_x86) {
|
||||
for (int j = 0; j < 1280; ++j) {
|
||||
result_opt[j] = libyuv::FixedDiv(num[j], div[j]);
|
||||
}
|
||||
} else {
|
||||
for (int j = 0; j < 1280; ++j) {
|
||||
result_opt[j] = libyuv::FixedDiv_C(num[j], div[j]);
|
||||
}
|
||||
}
|
||||
}
|
||||
for (int j = 0; j < 1280; ++j) {
|
||||
result_c[j] = libyuv::FixedDiv_C(num[j], div[j]);
|
||||
EXPECT_NEAR(result_c[j], result_opt[j], 1);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(LibYUVBaseTest, TestFixedDiv1_Opt) {
|
||||
int num[1280];
|
||||
int div[1280];
|
||||
int result_opt[1280];
|
||||
int result_c[1280];
|
||||
|
||||
MemRandomize(reinterpret_cast<uint8_t*>(&num[0]), sizeof(num));
|
||||
MemRandomize(reinterpret_cast<uint8_t*>(&div[0]), sizeof(div));
|
||||
for (int j = 0; j < 1280; ++j) {
|
||||
num[j] &= 4095; // Make numerator smaller.
|
||||
div[j] &= 4095; // Make divisor smaller.
|
||||
if (div[j] <= 1) {
|
||||
div[j] = 1280;
|
||||
}
|
||||
}
|
||||
|
||||
int has_x86 = TestCpuFlag(kCpuHasX86);
|
||||
for (int i = 0; i < benchmark_pixels_div1280_; ++i) {
|
||||
if (has_x86) {
|
||||
for (int j = 0; j < 1280; ++j) {
|
||||
result_opt[j] = libyuv::FixedDiv1(num[j], div[j]);
|
||||
}
|
||||
} else {
|
||||
for (int j = 0; j < 1280; ++j) {
|
||||
result_opt[j] = libyuv::FixedDiv1_C(num[j], div[j]);
|
||||
}
|
||||
}
|
||||
}
|
||||
for (int j = 0; j < 1280; ++j) {
|
||||
result_c[j] = libyuv::FixedDiv1_C(num[j], div[j]);
|
||||
EXPECT_NEAR(result_c[j], result_opt[j], 1);
|
||||
}
|
||||
}
|
||||
#endif // ENABLE_ROW_TESTS
|
||||
|
||||
} // namespace libyuv
|
||||
4436
externals/libyuv/unit_test/planar_test.cc
vendored
Normal file
4436
externals/libyuv/unit_test/planar_test.cc
vendored
Normal file
File diff suppressed because it is too large
Load Diff
228
externals/libyuv/unit_test/rotate_argb_test.cc
vendored
Normal file
228
externals/libyuv/unit_test/rotate_argb_test.cc
vendored
Normal file
@@ -0,0 +1,228 @@
|
||||
/*
|
||||
* Copyright 2012 The LibYuv Project Authors. All rights reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "../unit_test/unit_test.h"
|
||||
#include "libyuv/cpu_id.h"
|
||||
#include "libyuv/rotate_argb.h"
|
||||
|
||||
namespace libyuv {
|
||||
|
||||
void TestRotateBpp(int src_width,
|
||||
int src_height,
|
||||
int dst_width,
|
||||
int dst_height,
|
||||
libyuv::RotationMode mode,
|
||||
int benchmark_iterations,
|
||||
int disable_cpu_flags,
|
||||
int benchmark_cpu_info,
|
||||
const int kBpp) {
|
||||
if (src_width < 1) {
|
||||
src_width = 1;
|
||||
}
|
||||
if (src_height < 1) {
|
||||
src_height = 1;
|
||||
}
|
||||
if (dst_width < 1) {
|
||||
dst_width = 1;
|
||||
}
|
||||
if (dst_height < 1) {
|
||||
dst_height = 1;
|
||||
}
|
||||
int src_stride_argb = src_width * kBpp;
|
||||
int src_argb_plane_size = src_stride_argb * abs(src_height);
|
||||
align_buffer_page_end(src_argb, src_argb_plane_size);
|
||||
for (int i = 0; i < src_argb_plane_size; ++i) {
|
||||
src_argb[i] = fastrand() & 0xff;
|
||||
}
|
||||
|
||||
int dst_stride_argb = dst_width * kBpp;
|
||||
int dst_argb_plane_size = dst_stride_argb * dst_height;
|
||||
align_buffer_page_end(dst_argb_c, dst_argb_plane_size);
|
||||
align_buffer_page_end(dst_argb_opt, dst_argb_plane_size);
|
||||
memset(dst_argb_c, 2, dst_argb_plane_size);
|
||||
memset(dst_argb_opt, 3, dst_argb_plane_size);
|
||||
|
||||
if (kBpp == 1) {
|
||||
MaskCpuFlags(disable_cpu_flags); // Disable all CPU optimization.
|
||||
RotatePlane(src_argb, src_stride_argb, dst_argb_c, dst_stride_argb,
|
||||
src_width, src_height, mode);
|
||||
|
||||
MaskCpuFlags(benchmark_cpu_info); // Enable all CPU optimization.
|
||||
for (int i = 0; i < benchmark_iterations; ++i) {
|
||||
RotatePlane(src_argb, src_stride_argb, dst_argb_opt, dst_stride_argb,
|
||||
src_width, src_height, mode);
|
||||
}
|
||||
} else if (kBpp == 4) {
|
||||
MaskCpuFlags(disable_cpu_flags); // Disable all CPU optimization.
|
||||
ARGBRotate(src_argb, src_stride_argb, dst_argb_c, dst_stride_argb,
|
||||
src_width, src_height, mode);
|
||||
|
||||
MaskCpuFlags(benchmark_cpu_info); // Enable all CPU optimization.
|
||||
for (int i = 0; i < benchmark_iterations; ++i) {
|
||||
ARGBRotate(src_argb, src_stride_argb, dst_argb_opt, dst_stride_argb,
|
||||
src_width, src_height, mode);
|
||||
}
|
||||
}
|
||||
|
||||
// Rotation should be exact.
|
||||
for (int i = 0; i < dst_argb_plane_size; ++i) {
|
||||
EXPECT_EQ(dst_argb_c[i], dst_argb_opt[i]);
|
||||
}
|
||||
|
||||
free_aligned_buffer_page_end(dst_argb_c);
|
||||
free_aligned_buffer_page_end(dst_argb_opt);
|
||||
free_aligned_buffer_page_end(src_argb);
|
||||
}
|
||||
|
||||
static void ARGBTestRotate(int src_width,
|
||||
int src_height,
|
||||
int dst_width,
|
||||
int dst_height,
|
||||
libyuv::RotationMode mode,
|
||||
int benchmark_iterations,
|
||||
int disable_cpu_flags,
|
||||
int benchmark_cpu_info) {
|
||||
TestRotateBpp(src_width, src_height, dst_width, dst_height, mode,
|
||||
benchmark_iterations, disable_cpu_flags, benchmark_cpu_info, 4);
|
||||
}
|
||||
|
||||
TEST_F(LibYUVRotateTest, ARGBRotate0_Opt) {
|
||||
ARGBTestRotate(benchmark_width_, benchmark_height_, benchmark_width_,
|
||||
benchmark_height_, kRotate0, benchmark_iterations_,
|
||||
disable_cpu_flags_, benchmark_cpu_info_);
|
||||
}
|
||||
|
||||
TEST_F(LibYUVRotateTest, ARGBRotate90_Opt) {
|
||||
ARGBTestRotate(benchmark_width_, benchmark_height_, benchmark_height_,
|
||||
benchmark_width_, kRotate90, benchmark_iterations_,
|
||||
disable_cpu_flags_, benchmark_cpu_info_);
|
||||
}
|
||||
|
||||
TEST_F(LibYUVRotateTest, ARGBRotate180_Opt) {
|
||||
ARGBTestRotate(benchmark_width_, benchmark_height_, benchmark_width_,
|
||||
benchmark_height_, kRotate180, benchmark_iterations_,
|
||||
disable_cpu_flags_, benchmark_cpu_info_);
|
||||
}
|
||||
|
||||
TEST_F(LibYUVRotateTest, ARGBRotate270_Opt) {
|
||||
ARGBTestRotate(benchmark_width_, benchmark_height_, benchmark_height_,
|
||||
benchmark_width_, kRotate270, benchmark_iterations_,
|
||||
disable_cpu_flags_, benchmark_cpu_info_);
|
||||
}
|
||||
|
||||
static void TestRotatePlane(int src_width,
|
||||
int src_height,
|
||||
int dst_width,
|
||||
int dst_height,
|
||||
libyuv::RotationMode mode,
|
||||
int benchmark_iterations,
|
||||
int disable_cpu_flags,
|
||||
int benchmark_cpu_info) {
|
||||
TestRotateBpp(src_width, src_height, dst_width, dst_height, mode,
|
||||
benchmark_iterations, disable_cpu_flags, benchmark_cpu_info, 1);
|
||||
}
|
||||
|
||||
TEST_F(LibYUVRotateTest, RotatePlane0_Opt) {
|
||||
TestRotatePlane(benchmark_width_, benchmark_height_, benchmark_width_,
|
||||
benchmark_height_, kRotate0, benchmark_iterations_,
|
||||
disable_cpu_flags_, benchmark_cpu_info_);
|
||||
}
|
||||
|
||||
TEST_F(LibYUVRotateTest, RotatePlane90_Opt) {
|
||||
TestRotatePlane(benchmark_width_, benchmark_height_, benchmark_height_,
|
||||
benchmark_width_, kRotate90, benchmark_iterations_,
|
||||
disable_cpu_flags_, benchmark_cpu_info_);
|
||||
}
|
||||
|
||||
TEST_F(LibYUVRotateTest, RotatePlane180_Opt) {
|
||||
TestRotatePlane(benchmark_width_, benchmark_height_, benchmark_width_,
|
||||
benchmark_height_, kRotate180, benchmark_iterations_,
|
||||
disable_cpu_flags_, benchmark_cpu_info_);
|
||||
}
|
||||
|
||||
TEST_F(LibYUVRotateTest, RotatePlane270_Opt) {
|
||||
TestRotatePlane(benchmark_width_, benchmark_height_, benchmark_height_,
|
||||
benchmark_width_, kRotate270, benchmark_iterations_,
|
||||
disable_cpu_flags_, benchmark_cpu_info_);
|
||||
}
|
||||
|
||||
TEST_F(LibYUVRotateTest, DISABLED_RotatePlane0_Odd) {
|
||||
TestRotatePlane(benchmark_width_ + 1, benchmark_height_ + 1,
|
||||
benchmark_width_ + 1, benchmark_height_ + 1, kRotate0,
|
||||
benchmark_iterations_, disable_cpu_flags_,
|
||||
benchmark_cpu_info_);
|
||||
}
|
||||
|
||||
TEST_F(LibYUVRotateTest, DISABLED_RotatePlane90_Odd) {
|
||||
TestRotatePlane(benchmark_width_ + 1, benchmark_height_ + 1,
|
||||
benchmark_height_ + 1, benchmark_width_ + 1, kRotate90,
|
||||
benchmark_iterations_, disable_cpu_flags_,
|
||||
benchmark_cpu_info_);
|
||||
}
|
||||
|
||||
TEST_F(LibYUVRotateTest, DISABLED_RotatePlane180_Odd) {
|
||||
TestRotatePlane(benchmark_width_ + 1, benchmark_height_ + 1,
|
||||
benchmark_width_ + 1, benchmark_height_ + 1, kRotate180,
|
||||
benchmark_iterations_, disable_cpu_flags_,
|
||||
benchmark_cpu_info_);
|
||||
}
|
||||
|
||||
TEST_F(LibYUVRotateTest, DISABLED_RotatePlane270_Odd) {
|
||||
TestRotatePlane(benchmark_width_ + 1, benchmark_height_ + 1,
|
||||
benchmark_height_ + 1, benchmark_width_ + 1, kRotate270,
|
||||
benchmark_iterations_, disable_cpu_flags_,
|
||||
benchmark_cpu_info_);
|
||||
}
|
||||
|
||||
TEST_F(LibYUVRotateTest, RotatePlane90_TestStride) {
|
||||
int argb_plane_size = benchmark_width_ * 4 * abs(benchmark_height_);
|
||||
|
||||
align_buffer_page_end(src_argb, argb_plane_size);
|
||||
align_buffer_page_end(dst_argb, argb_plane_size);
|
||||
|
||||
EXPECT_EQ(0, ARGBRotate(src_argb, benchmark_width_ * 4, dst_argb,
|
||||
benchmark_width_ * 4, benchmark_width_,
|
||||
benchmark_height_, kRotate0));
|
||||
|
||||
EXPECT_EQ(0, ARGBRotate(src_argb, benchmark_width_ * 4 - 1, dst_argb,
|
||||
benchmark_width_ * 4 - 1, benchmark_width_ - 1,
|
||||
benchmark_height_, kRotate0));
|
||||
|
||||
EXPECT_EQ(0, ARGBRotate(src_argb, benchmark_width_ * 4, dst_argb,
|
||||
benchmark_width_ * 4, benchmark_width_,
|
||||
benchmark_height_, kRotate180));
|
||||
|
||||
EXPECT_EQ(0, ARGBRotate(src_argb, benchmark_width_ * 4 - 1, dst_argb,
|
||||
benchmark_width_ * 4 - 1, benchmark_width_ - 1,
|
||||
benchmark_height_, kRotate180));
|
||||
|
||||
EXPECT_EQ(0, ARGBRotate(src_argb, benchmark_width_ * 4, dst_argb,
|
||||
abs(benchmark_height_) * 4, benchmark_width_,
|
||||
benchmark_height_, kRotate90));
|
||||
|
||||
EXPECT_EQ(-1, ARGBRotate(src_argb, benchmark_width_ * 4 - 1, dst_argb,
|
||||
abs(benchmark_height_) * 4, benchmark_width_ - 1,
|
||||
benchmark_height_, kRotate90));
|
||||
|
||||
EXPECT_EQ(0, ARGBRotate(src_argb, benchmark_width_ * 4, dst_argb,
|
||||
abs(benchmark_height_) * 4, benchmark_width_,
|
||||
benchmark_height_, kRotate270));
|
||||
|
||||
EXPECT_EQ(-1, ARGBRotate(src_argb, benchmark_width_ * 4 - 1, dst_argb,
|
||||
abs(benchmark_height_) * 4, benchmark_width_ - 1,
|
||||
benchmark_height_, kRotate270));
|
||||
|
||||
free_aligned_buffer_page_end(dst_argb);
|
||||
free_aligned_buffer_page_end(src_argb);
|
||||
}
|
||||
|
||||
} // namespace libyuv
|
||||
599
externals/libyuv/unit_test/rotate_test.cc
vendored
Normal file
599
externals/libyuv/unit_test/rotate_test.cc
vendored
Normal file
@@ -0,0 +1,599 @@
|
||||
/*
|
||||
* Copyright 2012 The LibYuv Project Authors. All rights reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "../unit_test/unit_test.h"
|
||||
#include "libyuv/cpu_id.h"
|
||||
#include "libyuv/rotate.h"
|
||||
|
||||
namespace libyuv {
|
||||
|
||||
#define SUBSAMPLE(v, a) ((((v) + (a)-1)) / (a))
|
||||
|
||||
static void I420TestRotate(int src_width,
|
||||
int src_height,
|
||||
int dst_width,
|
||||
int dst_height,
|
||||
libyuv::RotationMode mode,
|
||||
int benchmark_iterations,
|
||||
int disable_cpu_flags,
|
||||
int benchmark_cpu_info) {
|
||||
if (src_width < 1) {
|
||||
src_width = 1;
|
||||
}
|
||||
if (src_height == 0) {
|
||||
src_height = 1;
|
||||
}
|
||||
if (dst_width < 1) {
|
||||
dst_width = 1;
|
||||
}
|
||||
if (dst_height < 1) {
|
||||
dst_height = 1;
|
||||
}
|
||||
int src_i420_y_size = src_width * Abs(src_height);
|
||||
int src_i420_uv_size = ((src_width + 1) / 2) * ((Abs(src_height) + 1) / 2);
|
||||
int src_i420_size = src_i420_y_size + src_i420_uv_size * 2;
|
||||
align_buffer_page_end(src_i420, src_i420_size);
|
||||
for (int i = 0; i < src_i420_size; ++i) {
|
||||
src_i420[i] = fastrand() & 0xff;
|
||||
}
|
||||
|
||||
int dst_i420_y_size = dst_width * dst_height;
|
||||
int dst_i420_uv_size = ((dst_width + 1) / 2) * ((dst_height + 1) / 2);
|
||||
int dst_i420_size = dst_i420_y_size + dst_i420_uv_size * 2;
|
||||
align_buffer_page_end(dst_i420_c, dst_i420_size);
|
||||
align_buffer_page_end(dst_i420_opt, dst_i420_size);
|
||||
memset(dst_i420_c, 2, dst_i420_size);
|
||||
memset(dst_i420_opt, 3, dst_i420_size);
|
||||
|
||||
MaskCpuFlags(disable_cpu_flags); // Disable all CPU optimization.
|
||||
I420Rotate(src_i420, src_width, src_i420 + src_i420_y_size,
|
||||
(src_width + 1) / 2, src_i420 + src_i420_y_size + src_i420_uv_size,
|
||||
(src_width + 1) / 2, dst_i420_c, dst_width,
|
||||
dst_i420_c + dst_i420_y_size, (dst_width + 1) / 2,
|
||||
dst_i420_c + dst_i420_y_size + dst_i420_uv_size,
|
||||
(dst_width + 1) / 2, src_width, src_height, mode);
|
||||
|
||||
MaskCpuFlags(benchmark_cpu_info); // Enable all CPU optimization.
|
||||
for (int i = 0; i < benchmark_iterations; ++i) {
|
||||
I420Rotate(
|
||||
src_i420, src_width, src_i420 + src_i420_y_size, (src_width + 1) / 2,
|
||||
src_i420 + src_i420_y_size + src_i420_uv_size, (src_width + 1) / 2,
|
||||
dst_i420_opt, dst_width, dst_i420_opt + dst_i420_y_size,
|
||||
(dst_width + 1) / 2, dst_i420_opt + dst_i420_y_size + dst_i420_uv_size,
|
||||
(dst_width + 1) / 2, src_width, src_height, mode);
|
||||
}
|
||||
|
||||
// Rotation should be exact.
|
||||
for (int i = 0; i < dst_i420_size; ++i) {
|
||||
EXPECT_EQ(dst_i420_c[i], dst_i420_opt[i]);
|
||||
}
|
||||
|
||||
free_aligned_buffer_page_end(dst_i420_c);
|
||||
free_aligned_buffer_page_end(dst_i420_opt);
|
||||
free_aligned_buffer_page_end(src_i420);
|
||||
}
|
||||
|
||||
TEST_F(LibYUVRotateTest, I420Rotate0_Opt) {
|
||||
I420TestRotate(benchmark_width_, benchmark_height_, benchmark_width_,
|
||||
benchmark_height_, kRotate0, benchmark_iterations_,
|
||||
disable_cpu_flags_, benchmark_cpu_info_);
|
||||
}
|
||||
|
||||
TEST_F(LibYUVRotateTest, I420Rotate90_Opt) {
|
||||
I420TestRotate(benchmark_width_, benchmark_height_, benchmark_height_,
|
||||
benchmark_width_, kRotate90, benchmark_iterations_,
|
||||
disable_cpu_flags_, benchmark_cpu_info_);
|
||||
}
|
||||
|
||||
TEST_F(LibYUVRotateTest, I420Rotate180_Opt) {
|
||||
I420TestRotate(benchmark_width_, benchmark_height_, benchmark_width_,
|
||||
benchmark_height_, kRotate180, benchmark_iterations_,
|
||||
disable_cpu_flags_, benchmark_cpu_info_);
|
||||
}
|
||||
|
||||
TEST_F(LibYUVRotateTest, I420Rotate270_Opt) {
|
||||
I420TestRotate(benchmark_width_, benchmark_height_, benchmark_height_,
|
||||
benchmark_width_, kRotate270, benchmark_iterations_,
|
||||
disable_cpu_flags_, benchmark_cpu_info_);
|
||||
}
|
||||
|
||||
// TODO(fbarchard): Remove odd width tests.
|
||||
// Odd width tests work but disabled because they use C code and can be
|
||||
// tested by passing an odd width command line or environment variable.
|
||||
TEST_F(LibYUVRotateTest, DISABLED_I420Rotate0_Odd) {
|
||||
I420TestRotate(benchmark_width_ + 1, benchmark_height_ + 1,
|
||||
benchmark_width_ + 1, benchmark_height_ + 1, kRotate0,
|
||||
benchmark_iterations_, disable_cpu_flags_,
|
||||
benchmark_cpu_info_);
|
||||
}
|
||||
|
||||
TEST_F(LibYUVRotateTest, DISABLED_I420Rotate90_Odd) {
|
||||
I420TestRotate(benchmark_width_ + 1, benchmark_height_ + 1,
|
||||
benchmark_height_ + 1, benchmark_width_ + 1, kRotate90,
|
||||
benchmark_iterations_, disable_cpu_flags_,
|
||||
benchmark_cpu_info_);
|
||||
}
|
||||
|
||||
TEST_F(LibYUVRotateTest, DISABLED_I420Rotate180_Odd) {
|
||||
I420TestRotate(benchmark_width_ + 1, benchmark_height_ + 1,
|
||||
benchmark_width_ + 1, benchmark_height_ + 1, kRotate180,
|
||||
benchmark_iterations_, disable_cpu_flags_,
|
||||
benchmark_cpu_info_);
|
||||
}
|
||||
|
||||
TEST_F(LibYUVRotateTest, DISABLED_I420Rotate270_Odd) {
|
||||
I420TestRotate(benchmark_width_ + 1, benchmark_height_ + 1,
|
||||
benchmark_height_ + 1, benchmark_width_ + 1, kRotate270,
|
||||
benchmark_iterations_, disable_cpu_flags_,
|
||||
benchmark_cpu_info_);
|
||||
}
|
||||
|
||||
static void I422TestRotate(int src_width,
|
||||
int src_height,
|
||||
int dst_width,
|
||||
int dst_height,
|
||||
libyuv::RotationMode mode,
|
||||
int benchmark_iterations,
|
||||
int disable_cpu_flags,
|
||||
int benchmark_cpu_info) {
|
||||
if (src_width < 1) {
|
||||
src_width = 1;
|
||||
}
|
||||
if (src_height == 0) {
|
||||
src_height = 1;
|
||||
}
|
||||
if (dst_width < 1) {
|
||||
dst_width = 1;
|
||||
}
|
||||
if (dst_height < 1) {
|
||||
dst_height = 1;
|
||||
}
|
||||
int src_i422_y_size = src_width * Abs(src_height);
|
||||
int src_i422_uv_size = ((src_width + 1) / 2) * Abs(src_height);
|
||||
int src_i422_size = src_i422_y_size + src_i422_uv_size * 2;
|
||||
align_buffer_page_end(src_i422, src_i422_size);
|
||||
for (int i = 0; i < src_i422_size; ++i) {
|
||||
src_i422[i] = fastrand() & 0xff;
|
||||
}
|
||||
|
||||
int dst_i422_y_size = dst_width * dst_height;
|
||||
int dst_i422_uv_size = ((dst_width + 1) / 2) * dst_height;
|
||||
int dst_i422_size = dst_i422_y_size + dst_i422_uv_size * 2;
|
||||
align_buffer_page_end(dst_i422_c, dst_i422_size);
|
||||
align_buffer_page_end(dst_i422_opt, dst_i422_size);
|
||||
memset(dst_i422_c, 2, dst_i422_size);
|
||||
memset(dst_i422_opt, 3, dst_i422_size);
|
||||
|
||||
MaskCpuFlags(disable_cpu_flags); // Disable all CPU optimization.
|
||||
I422Rotate(src_i422, src_width, src_i422 + src_i422_y_size,
|
||||
(src_width + 1) / 2, src_i422 + src_i422_y_size + src_i422_uv_size,
|
||||
(src_width + 1) / 2, dst_i422_c, dst_width,
|
||||
dst_i422_c + dst_i422_y_size, (dst_width + 1) / 2,
|
||||
dst_i422_c + dst_i422_y_size + dst_i422_uv_size,
|
||||
(dst_width + 1) / 2, src_width, src_height, mode);
|
||||
|
||||
MaskCpuFlags(benchmark_cpu_info); // Enable all CPU optimization.
|
||||
for (int i = 0; i < benchmark_iterations; ++i) {
|
||||
I422Rotate(
|
||||
src_i422, src_width, src_i422 + src_i422_y_size, (src_width + 1) / 2,
|
||||
src_i422 + src_i422_y_size + src_i422_uv_size, (src_width + 1) / 2,
|
||||
dst_i422_opt, dst_width, dst_i422_opt + dst_i422_y_size,
|
||||
(dst_width + 1) / 2, dst_i422_opt + dst_i422_y_size + dst_i422_uv_size,
|
||||
(dst_width + 1) / 2, src_width, src_height, mode);
|
||||
}
|
||||
|
||||
// Rotation should be exact.
|
||||
for (int i = 0; i < dst_i422_size; ++i) {
|
||||
EXPECT_EQ(dst_i422_c[i], dst_i422_opt[i]);
|
||||
}
|
||||
|
||||
free_aligned_buffer_page_end(dst_i422_c);
|
||||
free_aligned_buffer_page_end(dst_i422_opt);
|
||||
free_aligned_buffer_page_end(src_i422);
|
||||
}
|
||||
|
||||
TEST_F(LibYUVRotateTest, I422Rotate0_Opt) {
|
||||
I422TestRotate(benchmark_width_, benchmark_height_, benchmark_width_,
|
||||
benchmark_height_, kRotate0, benchmark_iterations_,
|
||||
disable_cpu_flags_, benchmark_cpu_info_);
|
||||
}
|
||||
|
||||
TEST_F(LibYUVRotateTest, I422Rotate90_Opt) {
|
||||
I422TestRotate(benchmark_width_, benchmark_height_, benchmark_height_,
|
||||
benchmark_width_, kRotate90, benchmark_iterations_,
|
||||
disable_cpu_flags_, benchmark_cpu_info_);
|
||||
}
|
||||
|
||||
TEST_F(LibYUVRotateTest, I422Rotate180_Opt) {
|
||||
I422TestRotate(benchmark_width_, benchmark_height_, benchmark_width_,
|
||||
benchmark_height_, kRotate180, benchmark_iterations_,
|
||||
disable_cpu_flags_, benchmark_cpu_info_);
|
||||
}
|
||||
|
||||
TEST_F(LibYUVRotateTest, I422Rotate270_Opt) {
|
||||
I422TestRotate(benchmark_width_, benchmark_height_, benchmark_height_,
|
||||
benchmark_width_, kRotate270, benchmark_iterations_,
|
||||
disable_cpu_flags_, benchmark_cpu_info_);
|
||||
}
|
||||
|
||||
static void I444TestRotate(int src_width,
|
||||
int src_height,
|
||||
int dst_width,
|
||||
int dst_height,
|
||||
libyuv::RotationMode mode,
|
||||
int benchmark_iterations,
|
||||
int disable_cpu_flags,
|
||||
int benchmark_cpu_info) {
|
||||
if (src_width < 1) {
|
||||
src_width = 1;
|
||||
}
|
||||
if (src_height == 0) {
|
||||
src_height = 1;
|
||||
}
|
||||
if (dst_width < 1) {
|
||||
dst_width = 1;
|
||||
}
|
||||
if (dst_height < 1) {
|
||||
dst_height = 1;
|
||||
}
|
||||
int src_i444_y_size = src_width * Abs(src_height);
|
||||
int src_i444_uv_size = src_width * Abs(src_height);
|
||||
int src_i444_size = src_i444_y_size + src_i444_uv_size * 2;
|
||||
align_buffer_page_end(src_i444, src_i444_size);
|
||||
for (int i = 0; i < src_i444_size; ++i) {
|
||||
src_i444[i] = fastrand() & 0xff;
|
||||
}
|
||||
|
||||
int dst_i444_y_size = dst_width * dst_height;
|
||||
int dst_i444_uv_size = dst_width * dst_height;
|
||||
int dst_i444_size = dst_i444_y_size + dst_i444_uv_size * 2;
|
||||
align_buffer_page_end(dst_i444_c, dst_i444_size);
|
||||
align_buffer_page_end(dst_i444_opt, dst_i444_size);
|
||||
memset(dst_i444_c, 2, dst_i444_size);
|
||||
memset(dst_i444_opt, 3, dst_i444_size);
|
||||
|
||||
MaskCpuFlags(disable_cpu_flags); // Disable all CPU optimization.
|
||||
I444Rotate(src_i444, src_width, src_i444 + src_i444_y_size, src_width,
|
||||
src_i444 + src_i444_y_size + src_i444_uv_size, src_width,
|
||||
dst_i444_c, dst_width, dst_i444_c + dst_i444_y_size, dst_width,
|
||||
dst_i444_c + dst_i444_y_size + dst_i444_uv_size, dst_width,
|
||||
src_width, src_height, mode);
|
||||
|
||||
MaskCpuFlags(benchmark_cpu_info); // Enable all CPU optimization.
|
||||
for (int i = 0; i < benchmark_iterations; ++i) {
|
||||
I444Rotate(src_i444, src_width, src_i444 + src_i444_y_size, src_width,
|
||||
src_i444 + src_i444_y_size + src_i444_uv_size, src_width,
|
||||
dst_i444_opt, dst_width, dst_i444_opt + dst_i444_y_size,
|
||||
dst_width, dst_i444_opt + dst_i444_y_size + dst_i444_uv_size,
|
||||
dst_width, src_width, src_height, mode);
|
||||
}
|
||||
|
||||
// Rotation should be exact.
|
||||
for (int i = 0; i < dst_i444_size; ++i) {
|
||||
EXPECT_EQ(dst_i444_c[i], dst_i444_opt[i]);
|
||||
}
|
||||
|
||||
free_aligned_buffer_page_end(dst_i444_c);
|
||||
free_aligned_buffer_page_end(dst_i444_opt);
|
||||
free_aligned_buffer_page_end(src_i444);
|
||||
}
|
||||
|
||||
TEST_F(LibYUVRotateTest, I444Rotate0_Opt) {
|
||||
I444TestRotate(benchmark_width_, benchmark_height_, benchmark_width_,
|
||||
benchmark_height_, kRotate0, benchmark_iterations_,
|
||||
disable_cpu_flags_, benchmark_cpu_info_);
|
||||
}
|
||||
|
||||
TEST_F(LibYUVRotateTest, I444Rotate90_Opt) {
|
||||
I444TestRotate(benchmark_width_, benchmark_height_, benchmark_height_,
|
||||
benchmark_width_, kRotate90, benchmark_iterations_,
|
||||
disable_cpu_flags_, benchmark_cpu_info_);
|
||||
}
|
||||
|
||||
TEST_F(LibYUVRotateTest, I444Rotate180_Opt) {
|
||||
I444TestRotate(benchmark_width_, benchmark_height_, benchmark_width_,
|
||||
benchmark_height_, kRotate180, benchmark_iterations_,
|
||||
disable_cpu_flags_, benchmark_cpu_info_);
|
||||
}
|
||||
|
||||
TEST_F(LibYUVRotateTest, I444Rotate270_Opt) {
|
||||
I444TestRotate(benchmark_width_, benchmark_height_, benchmark_height_,
|
||||
benchmark_width_, kRotate270, benchmark_iterations_,
|
||||
disable_cpu_flags_, benchmark_cpu_info_);
|
||||
}
|
||||
|
||||
// TODO(fbarchard): Remove odd width tests.
|
||||
// Odd width tests work but disabled because they use C code and can be
|
||||
// tested by passing an odd width command line or environment variable.
|
||||
TEST_F(LibYUVRotateTest, DISABLED_I444Rotate0_Odd) {
|
||||
I444TestRotate(benchmark_width_ + 1, benchmark_height_ + 1,
|
||||
benchmark_width_ + 1, benchmark_height_ + 1, kRotate0,
|
||||
benchmark_iterations_, disable_cpu_flags_,
|
||||
benchmark_cpu_info_);
|
||||
}
|
||||
|
||||
TEST_F(LibYUVRotateTest, DISABLED_I444Rotate90_Odd) {
|
||||
I444TestRotate(benchmark_width_ + 1, benchmark_height_ + 1,
|
||||
benchmark_height_ + 1, benchmark_width_ + 1, kRotate90,
|
||||
benchmark_iterations_, disable_cpu_flags_,
|
||||
benchmark_cpu_info_);
|
||||
}
|
||||
|
||||
TEST_F(LibYUVRotateTest, DISABLED_I444Rotate180_Odd) {
|
||||
I444TestRotate(benchmark_width_ + 1, benchmark_height_ + 1,
|
||||
benchmark_width_ + 1, benchmark_height_ + 1, kRotate180,
|
||||
benchmark_iterations_, disable_cpu_flags_,
|
||||
benchmark_cpu_info_);
|
||||
}
|
||||
|
||||
TEST_F(LibYUVRotateTest, DISABLED_I444Rotate270_Odd) {
|
||||
I444TestRotate(benchmark_width_ + 1, benchmark_height_ + 1,
|
||||
benchmark_height_ + 1, benchmark_width_ + 1, kRotate270,
|
||||
benchmark_iterations_, disable_cpu_flags_,
|
||||
benchmark_cpu_info_);
|
||||
}
|
||||
|
||||
static void NV12TestRotate(int src_width,
|
||||
int src_height,
|
||||
int dst_width,
|
||||
int dst_height,
|
||||
libyuv::RotationMode mode,
|
||||
int benchmark_iterations,
|
||||
int disable_cpu_flags,
|
||||
int benchmark_cpu_info) {
|
||||
if (src_width < 1) {
|
||||
src_width = 1;
|
||||
}
|
||||
if (src_height == 0) { // allow negative for inversion test.
|
||||
src_height = 1;
|
||||
}
|
||||
if (dst_width < 1) {
|
||||
dst_width = 1;
|
||||
}
|
||||
if (dst_height < 1) {
|
||||
dst_height = 1;
|
||||
}
|
||||
int src_nv12_y_size = src_width * Abs(src_height);
|
||||
int src_nv12_uv_size =
|
||||
((src_width + 1) / 2) * ((Abs(src_height) + 1) / 2) * 2;
|
||||
int src_nv12_size = src_nv12_y_size + src_nv12_uv_size;
|
||||
align_buffer_page_end(src_nv12, src_nv12_size);
|
||||
for (int i = 0; i < src_nv12_size; ++i) {
|
||||
src_nv12[i] = fastrand() & 0xff;
|
||||
}
|
||||
|
||||
int dst_i420_y_size = dst_width * dst_height;
|
||||
int dst_i420_uv_size = ((dst_width + 1) / 2) * ((dst_height + 1) / 2);
|
||||
int dst_i420_size = dst_i420_y_size + dst_i420_uv_size * 2;
|
||||
align_buffer_page_end(dst_i420_c, dst_i420_size);
|
||||
align_buffer_page_end(dst_i420_opt, dst_i420_size);
|
||||
memset(dst_i420_c, 2, dst_i420_size);
|
||||
memset(dst_i420_opt, 3, dst_i420_size);
|
||||
|
||||
MaskCpuFlags(disable_cpu_flags); // Disable all CPU optimization.
|
||||
NV12ToI420Rotate(src_nv12, src_width, src_nv12 + src_nv12_y_size,
|
||||
(src_width + 1) & ~1, dst_i420_c, dst_width,
|
||||
dst_i420_c + dst_i420_y_size, (dst_width + 1) / 2,
|
||||
dst_i420_c + dst_i420_y_size + dst_i420_uv_size,
|
||||
(dst_width + 1) / 2, src_width, src_height, mode);
|
||||
|
||||
MaskCpuFlags(benchmark_cpu_info); // Enable all CPU optimization.
|
||||
for (int i = 0; i < benchmark_iterations; ++i) {
|
||||
NV12ToI420Rotate(src_nv12, src_width, src_nv12 + src_nv12_y_size,
|
||||
(src_width + 1) & ~1, dst_i420_opt, dst_width,
|
||||
dst_i420_opt + dst_i420_y_size, (dst_width + 1) / 2,
|
||||
dst_i420_opt + dst_i420_y_size + dst_i420_uv_size,
|
||||
(dst_width + 1) / 2, src_width, src_height, mode);
|
||||
}
|
||||
|
||||
// Rotation should be exact.
|
||||
for (int i = 0; i < dst_i420_size; ++i) {
|
||||
EXPECT_EQ(dst_i420_c[i], dst_i420_opt[i]);
|
||||
}
|
||||
|
||||
free_aligned_buffer_page_end(dst_i420_c);
|
||||
free_aligned_buffer_page_end(dst_i420_opt);
|
||||
free_aligned_buffer_page_end(src_nv12);
|
||||
}
|
||||
|
||||
TEST_F(LibYUVRotateTest, NV12Rotate0_Opt) {
|
||||
NV12TestRotate(benchmark_width_, benchmark_height_, benchmark_width_,
|
||||
benchmark_height_, kRotate0, benchmark_iterations_,
|
||||
disable_cpu_flags_, benchmark_cpu_info_);
|
||||
}
|
||||
|
||||
TEST_F(LibYUVRotateTest, NV12Rotate90_Opt) {
|
||||
NV12TestRotate(benchmark_width_, benchmark_height_, benchmark_height_,
|
||||
benchmark_width_, kRotate90, benchmark_iterations_,
|
||||
disable_cpu_flags_, benchmark_cpu_info_);
|
||||
}
|
||||
|
||||
TEST_F(LibYUVRotateTest, NV12Rotate180_Opt) {
|
||||
NV12TestRotate(benchmark_width_, benchmark_height_, benchmark_width_,
|
||||
benchmark_height_, kRotate180, benchmark_iterations_,
|
||||
disable_cpu_flags_, benchmark_cpu_info_);
|
||||
}
|
||||
|
||||
TEST_F(LibYUVRotateTest, NV12Rotate270_Opt) {
|
||||
NV12TestRotate(benchmark_width_, benchmark_height_, benchmark_height_,
|
||||
benchmark_width_, kRotate270, benchmark_iterations_,
|
||||
disable_cpu_flags_, benchmark_cpu_info_);
|
||||
}
|
||||
|
||||
TEST_F(LibYUVRotateTest, DISABLED_NV12Rotate0_Odd) {
|
||||
NV12TestRotate(benchmark_width_ + 1, benchmark_height_ + 1,
|
||||
benchmark_width_ + 1, benchmark_height_ + 1, kRotate0,
|
||||
benchmark_iterations_, disable_cpu_flags_,
|
||||
benchmark_cpu_info_);
|
||||
}
|
||||
|
||||
TEST_F(LibYUVRotateTest, DISABLED_NV12Rotate90_Odd) {
|
||||
NV12TestRotate(benchmark_width_ + 1, benchmark_height_ + 1,
|
||||
benchmark_height_ + 1, benchmark_width_ + 1, kRotate90,
|
||||
benchmark_iterations_, disable_cpu_flags_,
|
||||
benchmark_cpu_info_);
|
||||
}
|
||||
|
||||
TEST_F(LibYUVRotateTest, DISABLED_NV12Rotate180_Odd) {
|
||||
NV12TestRotate(benchmark_width_ + 1, benchmark_height_ + 1,
|
||||
benchmark_width_ + 1, benchmark_height_ + 1, kRotate180,
|
||||
benchmark_iterations_, disable_cpu_flags_,
|
||||
benchmark_cpu_info_);
|
||||
}
|
||||
|
||||
TEST_F(LibYUVRotateTest, DISABLED_NV12Rotate270_Odd) {
|
||||
NV12TestRotate(benchmark_width_ + 1, benchmark_height_ + 1,
|
||||
benchmark_height_ + 1, benchmark_width_ + 1, kRotate270,
|
||||
benchmark_iterations_, disable_cpu_flags_,
|
||||
benchmark_cpu_info_);
|
||||
}
|
||||
|
||||
TEST_F(LibYUVRotateTest, NV12Rotate0_Invert) {
|
||||
NV12TestRotate(benchmark_width_, -benchmark_height_, benchmark_width_,
|
||||
benchmark_height_, kRotate0, benchmark_iterations_,
|
||||
disable_cpu_flags_, benchmark_cpu_info_);
|
||||
}
|
||||
|
||||
TEST_F(LibYUVRotateTest, NV12Rotate90_Invert) {
|
||||
NV12TestRotate(benchmark_width_, -benchmark_height_, benchmark_height_,
|
||||
benchmark_width_, kRotate90, benchmark_iterations_,
|
||||
disable_cpu_flags_, benchmark_cpu_info_);
|
||||
}
|
||||
|
||||
TEST_F(LibYUVRotateTest, NV12Rotate180_Invert) {
|
||||
NV12TestRotate(benchmark_width_, -benchmark_height_, benchmark_width_,
|
||||
benchmark_height_, kRotate180, benchmark_iterations_,
|
||||
disable_cpu_flags_, benchmark_cpu_info_);
|
||||
}
|
||||
|
||||
TEST_F(LibYUVRotateTest, NV12Rotate270_Invert) {
|
||||
NV12TestRotate(benchmark_width_, -benchmark_height_, benchmark_height_,
|
||||
benchmark_width_, kRotate270, benchmark_iterations_,
|
||||
disable_cpu_flags_, benchmark_cpu_info_);
|
||||
}
|
||||
|
||||
// Test Android 420 to I420 Rotate
|
||||
#define TESTAPLANARTOPI(SRC_FMT_PLANAR, PIXEL_STRIDE, SRC_SUBSAMP_X, \
|
||||
SRC_SUBSAMP_Y, FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y, \
|
||||
W1280, N, NEG, OFF, PN, OFF_U, OFF_V, ROT) \
|
||||
TEST_F(LibYUVRotateTest, \
|
||||
SRC_FMT_PLANAR##To##FMT_PLANAR##Rotate##ROT##To##PN##N) { \
|
||||
const int kWidth = W1280; \
|
||||
const int kHeight = benchmark_height_; \
|
||||
const int kSizeUV = \
|
||||
SUBSAMPLE(kWidth, SRC_SUBSAMP_X) * SUBSAMPLE(kHeight, SRC_SUBSAMP_Y); \
|
||||
align_buffer_page_end(src_y, kWidth* kHeight + OFF); \
|
||||
align_buffer_page_end(src_uv, \
|
||||
kSizeUV*((PIXEL_STRIDE == 3) ? 3 : 2) + OFF); \
|
||||
align_buffer_page_end(dst_y_c, kWidth* kHeight); \
|
||||
align_buffer_page_end(dst_u_c, SUBSAMPLE(kWidth, SUBSAMP_X) * \
|
||||
SUBSAMPLE(kHeight, SUBSAMP_Y)); \
|
||||
align_buffer_page_end(dst_v_c, SUBSAMPLE(kWidth, SUBSAMP_X) * \
|
||||
SUBSAMPLE(kHeight, SUBSAMP_Y)); \
|
||||
align_buffer_page_end(dst_y_opt, kWidth* kHeight); \
|
||||
align_buffer_page_end(dst_u_opt, SUBSAMPLE(kWidth, SUBSAMP_X) * \
|
||||
SUBSAMPLE(kHeight, SUBSAMP_Y)); \
|
||||
align_buffer_page_end(dst_v_opt, SUBSAMPLE(kWidth, SUBSAMP_X) * \
|
||||
SUBSAMPLE(kHeight, SUBSAMP_Y)); \
|
||||
uint8_t* src_u = src_uv + OFF_U; \
|
||||
uint8_t* src_v = src_uv + (PIXEL_STRIDE == 1 ? kSizeUV : OFF_V); \
|
||||
int src_stride_uv = SUBSAMPLE(kWidth, SUBSAMP_X) * PIXEL_STRIDE; \
|
||||
for (int i = 0; i < kHeight; ++i) \
|
||||
for (int j = 0; j < kWidth; ++j) \
|
||||
src_y[i * kWidth + j + OFF] = (fastrand() & 0xff); \
|
||||
for (int i = 0; i < SUBSAMPLE(kHeight, SRC_SUBSAMP_Y); ++i) { \
|
||||
for (int j = 0; j < SUBSAMPLE(kWidth, SRC_SUBSAMP_X); ++j) { \
|
||||
src_u[(i * src_stride_uv) + j * PIXEL_STRIDE + OFF] = \
|
||||
(fastrand() & 0xff); \
|
||||
src_v[(i * src_stride_uv) + j * PIXEL_STRIDE + OFF] = \
|
||||
(fastrand() & 0xff); \
|
||||
} \
|
||||
} \
|
||||
memset(dst_y_c, 1, kWidth* kHeight); \
|
||||
memset(dst_u_c, 2, \
|
||||
SUBSAMPLE(kWidth, SUBSAMP_X) * SUBSAMPLE(kHeight, SUBSAMP_Y)); \
|
||||
memset(dst_v_c, 3, \
|
||||
SUBSAMPLE(kWidth, SUBSAMP_X) * SUBSAMPLE(kHeight, SUBSAMP_Y)); \
|
||||
memset(dst_y_opt, 101, kWidth* kHeight); \
|
||||
memset(dst_u_opt, 102, \
|
||||
SUBSAMPLE(kWidth, SUBSAMP_X) * SUBSAMPLE(kHeight, SUBSAMP_Y)); \
|
||||
memset(dst_v_opt, 103, \
|
||||
SUBSAMPLE(kWidth, SUBSAMP_X) * SUBSAMPLE(kHeight, SUBSAMP_Y)); \
|
||||
MaskCpuFlags(disable_cpu_flags_); \
|
||||
SRC_FMT_PLANAR##To##FMT_PLANAR##Rotate( \
|
||||
src_y + OFF, kWidth, src_u + OFF, SUBSAMPLE(kWidth, SRC_SUBSAMP_X), \
|
||||
src_v + OFF, SUBSAMPLE(kWidth, SRC_SUBSAMP_X), PIXEL_STRIDE, dst_y_c, \
|
||||
kWidth, dst_u_c, SUBSAMPLE(kWidth, SUBSAMP_X), dst_v_c, \
|
||||
SUBSAMPLE(kWidth, SUBSAMP_X), kWidth, NEG kHeight, \
|
||||
(libyuv::RotationMode)ROT); \
|
||||
MaskCpuFlags(benchmark_cpu_info_); \
|
||||
for (int i = 0; i < benchmark_iterations_; ++i) { \
|
||||
SRC_FMT_PLANAR##To##FMT_PLANAR##Rotate( \
|
||||
src_y + OFF, kWidth, src_u + OFF, SUBSAMPLE(kWidth, SRC_SUBSAMP_X), \
|
||||
src_v + OFF, SUBSAMPLE(kWidth, SRC_SUBSAMP_X), PIXEL_STRIDE, \
|
||||
dst_y_opt, kWidth, dst_u_opt, SUBSAMPLE(kWidth, SUBSAMP_X), \
|
||||
dst_v_opt, SUBSAMPLE(kWidth, SUBSAMP_X), kWidth, NEG kHeight, \
|
||||
(libyuv::RotationMode)ROT); \
|
||||
} \
|
||||
for (int i = 0; i < kHeight; ++i) { \
|
||||
for (int j = 0; j < kWidth; ++j) { \
|
||||
EXPECT_EQ(dst_y_c[i * kWidth + j], dst_y_opt[i * kWidth + j]); \
|
||||
} \
|
||||
} \
|
||||
for (int i = 0; i < SUBSAMPLE(kHeight, SUBSAMP_Y); ++i) { \
|
||||
for (int j = 0; j < SUBSAMPLE(kWidth, SUBSAMP_X); ++j) { \
|
||||
EXPECT_EQ(dst_u_c[i * SUBSAMPLE(kWidth, SUBSAMP_X) + j], \
|
||||
dst_u_opt[i * SUBSAMPLE(kWidth, SUBSAMP_X) + j]); \
|
||||
} \
|
||||
} \
|
||||
for (int i = 0; i < SUBSAMPLE(kHeight, SUBSAMP_Y); ++i) { \
|
||||
for (int j = 0; j < SUBSAMPLE(kWidth, SUBSAMP_X); ++j) { \
|
||||
EXPECT_EQ(dst_v_c[i * SUBSAMPLE(kWidth, SUBSAMP_X) + j], \
|
||||
dst_v_opt[i * SUBSAMPLE(kWidth, SUBSAMP_X) + j]); \
|
||||
} \
|
||||
} \
|
||||
free_aligned_buffer_page_end(dst_y_c); \
|
||||
free_aligned_buffer_page_end(dst_u_c); \
|
||||
free_aligned_buffer_page_end(dst_v_c); \
|
||||
free_aligned_buffer_page_end(dst_y_opt); \
|
||||
free_aligned_buffer_page_end(dst_u_opt); \
|
||||
free_aligned_buffer_page_end(dst_v_opt); \
|
||||
free_aligned_buffer_page_end(src_y); \
|
||||
free_aligned_buffer_page_end(src_uv); \
|
||||
}
|
||||
|
||||
#define TESTAPLANARTOP(SRC_FMT_PLANAR, PN, PIXEL_STRIDE, OFF_U, OFF_V, \
|
||||
SRC_SUBSAMP_X, SRC_SUBSAMP_Y, FMT_PLANAR, SUBSAMP_X, \
|
||||
SUBSAMP_Y) \
|
||||
TESTAPLANARTOPI(SRC_FMT_PLANAR, PIXEL_STRIDE, SRC_SUBSAMP_X, SRC_SUBSAMP_Y, \
|
||||
FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y, benchmark_width_ + 1, \
|
||||
_Any, +, 0, PN, OFF_U, OFF_V, 0) \
|
||||
TESTAPLANARTOPI(SRC_FMT_PLANAR, PIXEL_STRIDE, SRC_SUBSAMP_X, SRC_SUBSAMP_Y, \
|
||||
FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y, benchmark_width_, \
|
||||
_Unaligned, +, 2, PN, OFF_U, OFF_V, 0) \
|
||||
TESTAPLANARTOPI(SRC_FMT_PLANAR, PIXEL_STRIDE, SRC_SUBSAMP_X, SRC_SUBSAMP_Y, \
|
||||
FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y, benchmark_width_, _Invert, \
|
||||
-, 0, PN, OFF_U, OFF_V, 0) \
|
||||
TESTAPLANARTOPI(SRC_FMT_PLANAR, PIXEL_STRIDE, SRC_SUBSAMP_X, SRC_SUBSAMP_Y, \
|
||||
FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y, benchmark_width_, _Opt, +, \
|
||||
0, PN, OFF_U, OFF_V, 0) \
|
||||
TESTAPLANARTOPI(SRC_FMT_PLANAR, PIXEL_STRIDE, SRC_SUBSAMP_X, SRC_SUBSAMP_Y, \
|
||||
FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y, benchmark_width_, _Opt, +, \
|
||||
0, PN, OFF_U, OFF_V, 180)
|
||||
|
||||
TESTAPLANARTOP(Android420, I420, 1, 0, 0, 2, 2, I420, 2, 2)
|
||||
TESTAPLANARTOP(Android420, NV12, 2, 0, 1, 2, 2, I420, 2, 2)
|
||||
TESTAPLANARTOP(Android420, NV21, 2, 1, 0, 2, 2, I420, 2, 2)
|
||||
#undef TESTAPLANARTOP
|
||||
#undef TESTAPLANARTOPI
|
||||
|
||||
} // namespace libyuv
|
||||
588
externals/libyuv/unit_test/scale_argb_test.cc
vendored
Normal file
588
externals/libyuv/unit_test/scale_argb_test.cc
vendored
Normal file
@@ -0,0 +1,588 @@
|
||||
/*
|
||||
* Copyright 2011 The LibYuv Project Authors. All rights reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
|
||||
#include "../unit_test/unit_test.h"
|
||||
#include "libyuv/convert_argb.h"
|
||||
#include "libyuv/cpu_id.h"
|
||||
#include "libyuv/scale_argb.h"
|
||||
#include "libyuv/video_common.h"
|
||||
|
||||
namespace libyuv {
|
||||
|
||||
#define STRINGIZE(line) #line
|
||||
#define FILELINESTR(file, line) file ":" STRINGIZE(line)
|
||||
|
||||
#if !defined(DISABLE_SLOW_TESTS) || defined(__x86_64__) || defined(__i386__)
|
||||
// SLOW TESTS are those that are unoptimized C code.
|
||||
// FULL TESTS are optimized but test many variations of the same code.
|
||||
#define ENABLE_FULL_TESTS
|
||||
#endif
|
||||
|
||||
// Test scaling with C vs Opt and return maximum pixel difference. 0 = exact.
|
||||
static int ARGBTestFilter(int src_width,
|
||||
int src_height,
|
||||
int dst_width,
|
||||
int dst_height,
|
||||
FilterMode f,
|
||||
int benchmark_iterations,
|
||||
int disable_cpu_flags,
|
||||
int benchmark_cpu_info) {
|
||||
if (!SizeValid(src_width, src_height, dst_width, dst_height)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int i, j;
|
||||
const int b = 0; // 128 to test for padding/stride.
|
||||
int64_t src_argb_plane_size =
|
||||
(Abs(src_width) + b * 2) * (Abs(src_height) + b * 2) * 4LL;
|
||||
int src_stride_argb = (b * 2 + Abs(src_width)) * 4;
|
||||
|
||||
align_buffer_page_end(src_argb, src_argb_plane_size);
|
||||
if (!src_argb) {
|
||||
printf("Skipped. Alloc failed " FILELINESTR(__FILE__, __LINE__) "\n");
|
||||
return 0;
|
||||
}
|
||||
MemRandomize(src_argb, src_argb_plane_size);
|
||||
|
||||
int64_t dst_argb_plane_size =
|
||||
(dst_width + b * 2) * (dst_height + b * 2) * 4LL;
|
||||
int dst_stride_argb = (b * 2 + dst_width) * 4;
|
||||
|
||||
align_buffer_page_end(dst_argb_c, dst_argb_plane_size);
|
||||
align_buffer_page_end(dst_argb_opt, dst_argb_plane_size);
|
||||
if (!dst_argb_c || !dst_argb_opt) {
|
||||
printf("Skipped. Alloc failed " FILELINESTR(__FILE__, __LINE__) "\n");
|
||||
return 0;
|
||||
}
|
||||
memset(dst_argb_c, 2, dst_argb_plane_size);
|
||||
memset(dst_argb_opt, 3, dst_argb_plane_size);
|
||||
|
||||
// Warm up both versions for consistent benchmarks.
|
||||
MaskCpuFlags(disable_cpu_flags); // Disable all CPU optimization.
|
||||
ARGBScale(src_argb + (src_stride_argb * b) + b * 4, src_stride_argb,
|
||||
src_width, src_height, dst_argb_c + (dst_stride_argb * b) + b * 4,
|
||||
dst_stride_argb, dst_width, dst_height, f);
|
||||
MaskCpuFlags(benchmark_cpu_info); // Enable all CPU optimization.
|
||||
ARGBScale(src_argb + (src_stride_argb * b) + b * 4, src_stride_argb,
|
||||
src_width, src_height, dst_argb_opt + (dst_stride_argb * b) + b * 4,
|
||||
dst_stride_argb, dst_width, dst_height, f);
|
||||
|
||||
MaskCpuFlags(disable_cpu_flags); // Disable all CPU optimization.
|
||||
double c_time = get_time();
|
||||
ARGBScale(src_argb + (src_stride_argb * b) + b * 4, src_stride_argb,
|
||||
src_width, src_height, dst_argb_c + (dst_stride_argb * b) + b * 4,
|
||||
dst_stride_argb, dst_width, dst_height, f);
|
||||
|
||||
c_time = (get_time() - c_time);
|
||||
|
||||
MaskCpuFlags(benchmark_cpu_info); // Enable all CPU optimization.
|
||||
double opt_time = get_time();
|
||||
for (i = 0; i < benchmark_iterations; ++i) {
|
||||
ARGBScale(src_argb + (src_stride_argb * b) + b * 4, src_stride_argb,
|
||||
src_width, src_height,
|
||||
dst_argb_opt + (dst_stride_argb * b) + b * 4, dst_stride_argb,
|
||||
dst_width, dst_height, f);
|
||||
}
|
||||
opt_time = (get_time() - opt_time) / benchmark_iterations;
|
||||
|
||||
// Report performance of C vs OPT
|
||||
printf("filter %d - %8d us C - %8d us OPT\n", f,
|
||||
static_cast<int>(c_time * 1e6), static_cast<int>(opt_time * 1e6));
|
||||
|
||||
// C version may be a little off from the optimized. Order of
|
||||
// operations may introduce rounding somewhere. So do a difference
|
||||
// of the buffers and look to see that the max difference isn't
|
||||
// over 2.
|
||||
int max_diff = 0;
|
||||
for (i = b; i < (dst_height + b); ++i) {
|
||||
for (j = b * 4; j < (dst_width + b) * 4; ++j) {
|
||||
int abs_diff = Abs(dst_argb_c[(i * dst_stride_argb) + j] -
|
||||
dst_argb_opt[(i * dst_stride_argb) + j]);
|
||||
if (abs_diff > max_diff) {
|
||||
max_diff = abs_diff;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
free_aligned_buffer_page_end(dst_argb_c);
|
||||
free_aligned_buffer_page_end(dst_argb_opt);
|
||||
free_aligned_buffer_page_end(src_argb);
|
||||
return max_diff;
|
||||
}
|
||||
|
||||
static const int kTileX = 64;
|
||||
static const int kTileY = 64;
|
||||
|
||||
static int TileARGBScale(const uint8_t* src_argb,
|
||||
int src_stride_argb,
|
||||
int src_width,
|
||||
int src_height,
|
||||
uint8_t* dst_argb,
|
||||
int dst_stride_argb,
|
||||
int dst_width,
|
||||
int dst_height,
|
||||
FilterMode filtering) {
|
||||
for (int y = 0; y < dst_height; y += kTileY) {
|
||||
for (int x = 0; x < dst_width; x += kTileX) {
|
||||
int clip_width = kTileX;
|
||||
if (x + clip_width > dst_width) {
|
||||
clip_width = dst_width - x;
|
||||
}
|
||||
int clip_height = kTileY;
|
||||
if (y + clip_height > dst_height) {
|
||||
clip_height = dst_height - y;
|
||||
}
|
||||
int r = ARGBScaleClip(src_argb, src_stride_argb, src_width, src_height,
|
||||
dst_argb, dst_stride_argb, dst_width, dst_height, x,
|
||||
y, clip_width, clip_height, filtering);
|
||||
if (r) {
|
||||
return r;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ARGBClipTestFilter(int src_width,
|
||||
int src_height,
|
||||
int dst_width,
|
||||
int dst_height,
|
||||
FilterMode f,
|
||||
int benchmark_iterations) {
|
||||
if (!SizeValid(src_width, src_height, dst_width, dst_height)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
const int b = 128;
|
||||
int64_t src_argb_plane_size =
|
||||
(Abs(src_width) + b * 2) * (Abs(src_height) + b * 2) * 4;
|
||||
int src_stride_argb = (b * 2 + Abs(src_width)) * 4;
|
||||
|
||||
align_buffer_page_end(src_argb, src_argb_plane_size);
|
||||
if (!src_argb) {
|
||||
printf("Skipped. Alloc failed " FILELINESTR(__FILE__, __LINE__) "\n");
|
||||
return 0;
|
||||
}
|
||||
memset(src_argb, 1, src_argb_plane_size);
|
||||
|
||||
int64_t dst_argb_plane_size = (dst_width + b * 2) * (dst_height + b * 2) * 4;
|
||||
int dst_stride_argb = (b * 2 + dst_width) * 4;
|
||||
|
||||
int i, j;
|
||||
for (i = b; i < (Abs(src_height) + b); ++i) {
|
||||
for (j = b; j < (Abs(src_width) + b) * 4; ++j) {
|
||||
src_argb[(i * src_stride_argb) + j] = (fastrand() & 0xff);
|
||||
}
|
||||
}
|
||||
|
||||
align_buffer_page_end(dst_argb_c, dst_argb_plane_size);
|
||||
align_buffer_page_end(dst_argb_opt, dst_argb_plane_size);
|
||||
if (!dst_argb_c || !dst_argb_opt) {
|
||||
printf("Skipped. Alloc failed " FILELINESTR(__FILE__, __LINE__) "\n");
|
||||
return 0;
|
||||
}
|
||||
memset(dst_argb_c, 2, dst_argb_plane_size);
|
||||
memset(dst_argb_opt, 3, dst_argb_plane_size);
|
||||
|
||||
// Do full image, no clipping.
|
||||
double c_time = get_time();
|
||||
ARGBScale(src_argb + (src_stride_argb * b) + b * 4, src_stride_argb,
|
||||
src_width, src_height, dst_argb_c + (dst_stride_argb * b) + b * 4,
|
||||
dst_stride_argb, dst_width, dst_height, f);
|
||||
c_time = (get_time() - c_time);
|
||||
|
||||
// Do tiled image, clipping scale to a tile at a time.
|
||||
double opt_time = get_time();
|
||||
for (i = 0; i < benchmark_iterations; ++i) {
|
||||
TileARGBScale(src_argb + (src_stride_argb * b) + b * 4, src_stride_argb,
|
||||
src_width, src_height,
|
||||
dst_argb_opt + (dst_stride_argb * b) + b * 4, dst_stride_argb,
|
||||
dst_width, dst_height, f);
|
||||
}
|
||||
opt_time = (get_time() - opt_time) / benchmark_iterations;
|
||||
|
||||
// Report performance of Full vs Tiled.
|
||||
printf("filter %d - %8d us Full - %8d us Tiled\n", f,
|
||||
static_cast<int>(c_time * 1e6), static_cast<int>(opt_time * 1e6));
|
||||
|
||||
// Compare full scaled image vs tiled image.
|
||||
int max_diff = 0;
|
||||
for (i = b; i < (dst_height + b); ++i) {
|
||||
for (j = b * 4; j < (dst_width + b) * 4; ++j) {
|
||||
int abs_diff = Abs(dst_argb_c[(i * dst_stride_argb) + j] -
|
||||
dst_argb_opt[(i * dst_stride_argb) + j]);
|
||||
if (abs_diff > max_diff) {
|
||||
max_diff = abs_diff;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
free_aligned_buffer_page_end(dst_argb_c);
|
||||
free_aligned_buffer_page_end(dst_argb_opt);
|
||||
free_aligned_buffer_page_end(src_argb);
|
||||
return max_diff;
|
||||
}
|
||||
|
||||
// The following adjustments in dimensions ensure the scale factor will be
|
||||
// exactly achieved.
|
||||
#define DX(x, nom, denom) static_cast<int>((Abs(x) / nom) * nom)
|
||||
#define SX(x, nom, denom) static_cast<int>((x / nom) * denom)
|
||||
|
||||
#define TEST_FACTOR1(DISABLED_, name, filter, nom, denom, max_diff) \
|
||||
TEST_F(LibYUVScaleTest, ARGBScaleDownBy##name##_##filter) { \
|
||||
int diff = ARGBTestFilter( \
|
||||
SX(benchmark_width_, nom, denom), SX(benchmark_height_, nom, denom), \
|
||||
DX(benchmark_width_, nom, denom), DX(benchmark_height_, nom, denom), \
|
||||
kFilter##filter, benchmark_iterations_, disable_cpu_flags_, \
|
||||
benchmark_cpu_info_); \
|
||||
EXPECT_LE(diff, max_diff); \
|
||||
} \
|
||||
TEST_F(LibYUVScaleTest, DISABLED_##ARGBScaleDownClipBy##name##_##filter) { \
|
||||
int diff = ARGBClipTestFilter( \
|
||||
SX(benchmark_width_, nom, denom), SX(benchmark_height_, nom, denom), \
|
||||
DX(benchmark_width_, nom, denom), DX(benchmark_height_, nom, denom), \
|
||||
kFilter##filter, benchmark_iterations_); \
|
||||
EXPECT_LE(diff, max_diff); \
|
||||
}
|
||||
|
||||
// Test a scale factor with all 4 filters. Expect unfiltered to be exact, but
|
||||
// filtering is different fixed point implementations for SSSE3, Neon and C.
|
||||
#ifndef DISABLE_SLOW_TESTS
|
||||
#define TEST_FACTOR(name, nom, denom) \
|
||||
TEST_FACTOR1(, name, None, nom, denom, 0) \
|
||||
TEST_FACTOR1(, name, Linear, nom, denom, 3) \
|
||||
TEST_FACTOR1(, name, Bilinear, nom, denom, 3) \
|
||||
TEST_FACTOR1(, name, Box, nom, denom, 3)
|
||||
#else
|
||||
#if defined(ENABLE_FULL_TESTS)
|
||||
#define TEST_FACTOR(name, nom, denom) \
|
||||
TEST_FACTOR1(DISABLED_, name, None, nom, denom, 0) \
|
||||
TEST_FACTOR1(DISABLED_, name, Linear, nom, denom, 3) \
|
||||
TEST_FACTOR1(DISABLED_, name, Bilinear, nom, denom, 3) \
|
||||
TEST_FACTOR1(DISABLED_, name, Box, nom, denom, 3)
|
||||
#else
|
||||
#define TEST_FACTOR(name, nom, denom) \
|
||||
TEST_FACTOR1(DISABLED_, name, Bilinear, nom, denom, 3)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
TEST_FACTOR(2, 1, 2)
|
||||
TEST_FACTOR(4, 1, 4)
|
||||
#ifndef DISABLE_SLOW_TESTS
|
||||
TEST_FACTOR(8, 1, 8)
|
||||
#endif
|
||||
TEST_FACTOR(3by4, 3, 4)
|
||||
TEST_FACTOR(3by8, 3, 8)
|
||||
TEST_FACTOR(3, 1, 3)
|
||||
#undef TEST_FACTOR1
|
||||
#undef TEST_FACTOR
|
||||
#undef SX
|
||||
#undef DX
|
||||
|
||||
#define TEST_SCALETO1(DISABLED_, name, width, height, filter, max_diff) \
|
||||
TEST_F(LibYUVScaleTest, name##To##width##x##height##_##filter) { \
|
||||
int diff = ARGBTestFilter(benchmark_width_, benchmark_height_, width, \
|
||||
height, kFilter##filter, benchmark_iterations_, \
|
||||
disable_cpu_flags_, benchmark_cpu_info_); \
|
||||
EXPECT_LE(diff, max_diff); \
|
||||
} \
|
||||
TEST_F(LibYUVScaleTest, name##From##width##x##height##_##filter) { \
|
||||
int diff = ARGBTestFilter(width, height, Abs(benchmark_width_), \
|
||||
Abs(benchmark_height_), kFilter##filter, \
|
||||
benchmark_iterations_, disable_cpu_flags_, \
|
||||
benchmark_cpu_info_); \
|
||||
EXPECT_LE(diff, max_diff); \
|
||||
} \
|
||||
TEST_F(LibYUVScaleTest, \
|
||||
DISABLED_##name##ClipTo##width##x##height##_##filter) { \
|
||||
int diff = \
|
||||
ARGBClipTestFilter(benchmark_width_, benchmark_height_, width, height, \
|
||||
kFilter##filter, benchmark_iterations_); \
|
||||
EXPECT_LE(diff, max_diff); \
|
||||
} \
|
||||
TEST_F(LibYUVScaleTest, \
|
||||
DISABLED_##name##ClipFrom##width##x##height##_##filter) { \
|
||||
int diff = ARGBClipTestFilter(width, height, Abs(benchmark_width_), \
|
||||
Abs(benchmark_height_), kFilter##filter, \
|
||||
benchmark_iterations_); \
|
||||
EXPECT_LE(diff, max_diff); \
|
||||
}
|
||||
|
||||
#ifndef DISABLE_SLOW_TESTS
|
||||
// Test scale to a specified size with all 4 filters.
|
||||
#define TEST_SCALETO(name, width, height) \
|
||||
TEST_SCALETO1(, name, width, height, None, 0) \
|
||||
TEST_SCALETO1(, name, width, height, Linear, 3) \
|
||||
TEST_SCALETO1(, name, width, height, Bilinear, 3)
|
||||
#else
|
||||
#if defined(ENABLE_FULL_TESTS)
|
||||
#define TEST_SCALETO(name, width, height) \
|
||||
TEST_SCALETO1(DISABLED_, name, width, height, None, 0) \
|
||||
TEST_SCALETO1(DISABLED_, name, width, height, Linear, 3) \
|
||||
TEST_SCALETO1(DISABLED_, name, width, height, Bilinear, 3)
|
||||
#else
|
||||
#define TEST_SCALETO(name, width, height) \
|
||||
TEST_SCALETO1(DISABLED_, name, width, height, Bilinear, 3)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
TEST_SCALETO(ARGBScale, 1, 1)
|
||||
// TEST_SCALETO(ARGBScale, 256, 144) /* 128x72 * 2 */
|
||||
TEST_SCALETO(ARGBScale, 320, 240)
|
||||
TEST_SCALETO(ARGBScale, 569, 480)
|
||||
TEST_SCALETO(ARGBScale, 640, 360)
|
||||
#ifndef DISABLE_SLOW_TESTS
|
||||
TEST_SCALETO(ARGBScale, 1280, 720)
|
||||
TEST_SCALETO(ARGBScale, 1920, 1080)
|
||||
#endif // DISABLE_SLOW_TESTS
|
||||
#undef TEST_SCALETO1
|
||||
#undef TEST_SCALETO
|
||||
|
||||
#define TEST_SCALESWAPXY1(name, filter, max_diff) \
|
||||
TEST_F(LibYUVScaleTest, name##SwapXY_##filter) { \
|
||||
int diff = ARGBTestFilter(benchmark_width_, benchmark_height_, \
|
||||
benchmark_height_, benchmark_width_, \
|
||||
kFilter##filter, benchmark_iterations_, \
|
||||
disable_cpu_flags_, benchmark_cpu_info_); \
|
||||
EXPECT_LE(diff, max_diff); \
|
||||
}
|
||||
|
||||
#if defined(ENABLE_FULL_TESTS)
|
||||
// Test scale with swapped width and height with all 3 filters.
|
||||
TEST_SCALESWAPXY1(ARGBScale, None, 0)
|
||||
TEST_SCALESWAPXY1(ARGBScale, Linear, 0)
|
||||
TEST_SCALESWAPXY1(ARGBScale, Bilinear, 0)
|
||||
#else
|
||||
TEST_SCALESWAPXY1(ARGBScale, Bilinear, 0)
|
||||
#endif
|
||||
#undef TEST_SCALESWAPXY1
|
||||
|
||||
// Scale with YUV conversion to ARGB and clipping.
|
||||
// TODO(fbarchard): Add fourcc support. All 4 ARGB formats is easy to support.
|
||||
LIBYUV_API
|
||||
int YUVToARGBScaleReference2(const uint8_t* src_y,
|
||||
int src_stride_y,
|
||||
const uint8_t* src_u,
|
||||
int src_stride_u,
|
||||
const uint8_t* src_v,
|
||||
int src_stride_v,
|
||||
uint32_t /* src_fourcc */,
|
||||
int src_width,
|
||||
int src_height,
|
||||
uint8_t* dst_argb,
|
||||
int dst_stride_argb,
|
||||
uint32_t /* dst_fourcc */,
|
||||
int dst_width,
|
||||
int dst_height,
|
||||
int clip_x,
|
||||
int clip_y,
|
||||
int clip_width,
|
||||
int clip_height,
|
||||
enum FilterMode filtering) {
|
||||
uint8_t* argb_buffer =
|
||||
static_cast<uint8_t*>(malloc(src_width * src_height * 4));
|
||||
int r;
|
||||
I420ToARGB(src_y, src_stride_y, src_u, src_stride_u, src_v, src_stride_v,
|
||||
argb_buffer, src_width * 4, src_width, src_height);
|
||||
|
||||
r = ARGBScaleClip(argb_buffer, src_width * 4, src_width, src_height, dst_argb,
|
||||
dst_stride_argb, dst_width, dst_height, clip_x, clip_y,
|
||||
clip_width, clip_height, filtering);
|
||||
free(argb_buffer);
|
||||
return r;
|
||||
}
|
||||
|
||||
static void FillRamp(uint8_t* buf,
|
||||
int width,
|
||||
int height,
|
||||
int v,
|
||||
int dx,
|
||||
int dy) {
|
||||
int rv = v;
|
||||
for (int y = 0; y < height; ++y) {
|
||||
for (int x = 0; x < width; ++x) {
|
||||
*buf++ = v;
|
||||
v += dx;
|
||||
if (v < 0 || v > 255) {
|
||||
dx = -dx;
|
||||
v += dx;
|
||||
}
|
||||
}
|
||||
v = rv + dy;
|
||||
if (v < 0 || v > 255) {
|
||||
dy = -dy;
|
||||
v += dy;
|
||||
}
|
||||
rv = v;
|
||||
}
|
||||
}
|
||||
|
||||
// Test scaling with C vs Opt and return maximum pixel difference. 0 = exact.
|
||||
static int YUVToARGBTestFilter(int src_width,
|
||||
int src_height,
|
||||
int dst_width,
|
||||
int dst_height,
|
||||
FilterMode f,
|
||||
int benchmark_iterations) {
|
||||
int64_t src_y_plane_size = Abs(src_width) * Abs(src_height);
|
||||
int64_t src_uv_plane_size =
|
||||
((Abs(src_width) + 1) / 2) * ((Abs(src_height) + 1) / 2);
|
||||
int src_stride_y = Abs(src_width);
|
||||
int src_stride_uv = (Abs(src_width) + 1) / 2;
|
||||
|
||||
align_buffer_page_end(src_y, src_y_plane_size);
|
||||
align_buffer_page_end(src_u, src_uv_plane_size);
|
||||
align_buffer_page_end(src_v, src_uv_plane_size);
|
||||
|
||||
int64_t dst_argb_plane_size = (dst_width) * (dst_height)*4LL;
|
||||
int dst_stride_argb = (dst_width)*4;
|
||||
align_buffer_page_end(dst_argb_c, dst_argb_plane_size);
|
||||
align_buffer_page_end(dst_argb_opt, dst_argb_plane_size);
|
||||
if (!dst_argb_c || !dst_argb_opt || !src_y || !src_u || !src_v) {
|
||||
printf("Skipped. Alloc failed " FILELINESTR(__FILE__, __LINE__) "\n");
|
||||
return 0;
|
||||
}
|
||||
// Fill YUV image with continuous ramp, which is less sensitive to
|
||||
// subsampling and filtering differences for test purposes.
|
||||
FillRamp(src_y, Abs(src_width), Abs(src_height), 128, 1, 1);
|
||||
FillRamp(src_u, (Abs(src_width) + 1) / 2, (Abs(src_height) + 1) / 2, 3, 1, 1);
|
||||
FillRamp(src_v, (Abs(src_width) + 1) / 2, (Abs(src_height) + 1) / 2, 4, 1, 1);
|
||||
memset(dst_argb_c, 2, dst_argb_plane_size);
|
||||
memset(dst_argb_opt, 3, dst_argb_plane_size);
|
||||
|
||||
YUVToARGBScaleReference2(src_y, src_stride_y, src_u, src_stride_uv, src_v,
|
||||
src_stride_uv, libyuv::FOURCC_I420, src_width,
|
||||
src_height, dst_argb_c, dst_stride_argb,
|
||||
libyuv::FOURCC_I420, dst_width, dst_height, 0, 0,
|
||||
dst_width, dst_height, f);
|
||||
|
||||
for (int i = 0; i < benchmark_iterations; ++i) {
|
||||
YUVToARGBScaleClip(src_y, src_stride_y, src_u, src_stride_uv, src_v,
|
||||
src_stride_uv, libyuv::FOURCC_I420, src_width,
|
||||
src_height, dst_argb_opt, dst_stride_argb,
|
||||
libyuv::FOURCC_I420, dst_width, dst_height, 0, 0,
|
||||
dst_width, dst_height, f);
|
||||
}
|
||||
int max_diff = 0;
|
||||
for (int i = 0; i < dst_height; ++i) {
|
||||
for (int j = 0; j < dst_width * 4; ++j) {
|
||||
int abs_diff = Abs(dst_argb_c[(i * dst_stride_argb) + j] -
|
||||
dst_argb_opt[(i * dst_stride_argb) + j]);
|
||||
if (abs_diff > max_diff) {
|
||||
printf("error %d at %d,%d c %d opt %d", abs_diff, j, i,
|
||||
dst_argb_c[(i * dst_stride_argb) + j],
|
||||
dst_argb_opt[(i * dst_stride_argb) + j]);
|
||||
EXPECT_LE(abs_diff, 40);
|
||||
max_diff = abs_diff;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
free_aligned_buffer_page_end(dst_argb_c);
|
||||
free_aligned_buffer_page_end(dst_argb_opt);
|
||||
free_aligned_buffer_page_end(src_y);
|
||||
free_aligned_buffer_page_end(src_u);
|
||||
free_aligned_buffer_page_end(src_v);
|
||||
return max_diff;
|
||||
}
|
||||
|
||||
TEST_F(LibYUVScaleTest, YUVToRGBScaleUp) {
|
||||
int diff =
|
||||
YUVToARGBTestFilter(benchmark_width_, benchmark_height_,
|
||||
benchmark_width_ * 3 / 2, benchmark_height_ * 3 / 2,
|
||||
libyuv::kFilterBilinear, benchmark_iterations_);
|
||||
EXPECT_LE(diff, 10);
|
||||
}
|
||||
|
||||
TEST_F(LibYUVScaleTest, YUVToRGBScaleDown) {
|
||||
int diff = YUVToARGBTestFilter(
|
||||
benchmark_width_ * 3 / 2, benchmark_height_ * 3 / 2, benchmark_width_,
|
||||
benchmark_height_, libyuv::kFilterBilinear, benchmark_iterations_);
|
||||
EXPECT_LE(diff, 10);
|
||||
}
|
||||
|
||||
TEST_F(LibYUVScaleTest, ARGBTest3x) {
|
||||
const int kSrcStride = 480 * 4;
|
||||
const int kDstStride = 160 * 4;
|
||||
const int kSize = kSrcStride * 3;
|
||||
align_buffer_page_end(orig_pixels, kSize);
|
||||
for (int i = 0; i < 480 * 3; ++i) {
|
||||
orig_pixels[i * 4 + 0] = i;
|
||||
orig_pixels[i * 4 + 1] = 255 - i;
|
||||
orig_pixels[i * 4 + 2] = i + 1;
|
||||
orig_pixels[i * 4 + 3] = i + 10;
|
||||
}
|
||||
align_buffer_page_end(dest_pixels, kDstStride);
|
||||
|
||||
int iterations160 = (benchmark_width_ * benchmark_height_ + (160 - 1)) / 160 *
|
||||
benchmark_iterations_;
|
||||
for (int i = 0; i < iterations160; ++i) {
|
||||
ARGBScale(orig_pixels, kSrcStride, 480, 3, dest_pixels, kDstStride, 160, 1,
|
||||
kFilterBilinear);
|
||||
}
|
||||
|
||||
EXPECT_EQ(225, dest_pixels[0]);
|
||||
EXPECT_EQ(255 - 225, dest_pixels[1]);
|
||||
EXPECT_EQ(226, dest_pixels[2]);
|
||||
EXPECT_EQ(235, dest_pixels[3]);
|
||||
|
||||
ARGBScale(orig_pixels, kSrcStride, 480, 3, dest_pixels, kDstStride, 160, 1,
|
||||
kFilterNone);
|
||||
|
||||
EXPECT_EQ(225, dest_pixels[0]);
|
||||
EXPECT_EQ(255 - 225, dest_pixels[1]);
|
||||
EXPECT_EQ(226, dest_pixels[2]);
|
||||
EXPECT_EQ(235, dest_pixels[3]);
|
||||
|
||||
free_aligned_buffer_page_end(dest_pixels);
|
||||
free_aligned_buffer_page_end(orig_pixels);
|
||||
}
|
||||
|
||||
TEST_F(LibYUVScaleTest, ARGBTest4x) {
|
||||
const int kSrcStride = 640 * 4;
|
||||
const int kDstStride = 160 * 4;
|
||||
const int kSize = kSrcStride * 4;
|
||||
align_buffer_page_end(orig_pixels, kSize);
|
||||
for (int i = 0; i < 640 * 4; ++i) {
|
||||
orig_pixels[i * 4 + 0] = i;
|
||||
orig_pixels[i * 4 + 1] = 255 - i;
|
||||
orig_pixels[i * 4 + 2] = i + 1;
|
||||
orig_pixels[i * 4 + 3] = i + 10;
|
||||
}
|
||||
align_buffer_page_end(dest_pixels, kDstStride);
|
||||
|
||||
int iterations160 = (benchmark_width_ * benchmark_height_ + (160 - 1)) / 160 *
|
||||
benchmark_iterations_;
|
||||
for (int i = 0; i < iterations160; ++i) {
|
||||
ARGBScale(orig_pixels, kSrcStride, 640, 4, dest_pixels, kDstStride, 160, 1,
|
||||
kFilterBilinear);
|
||||
}
|
||||
|
||||
EXPECT_NEAR(66, dest_pixels[0], 4);
|
||||
EXPECT_NEAR(255 - 66, dest_pixels[1], 4);
|
||||
EXPECT_NEAR(67, dest_pixels[2], 4);
|
||||
EXPECT_NEAR(76, dest_pixels[3], 4);
|
||||
|
||||
ARGBScale(orig_pixels, kSrcStride, 640, 4, dest_pixels, kDstStride, 160, 1,
|
||||
kFilterNone);
|
||||
|
||||
EXPECT_EQ(2, dest_pixels[0]);
|
||||
EXPECT_EQ(255 - 2, dest_pixels[1]);
|
||||
EXPECT_EQ(3, dest_pixels[2]);
|
||||
EXPECT_EQ(12, dest_pixels[3]);
|
||||
|
||||
free_aligned_buffer_page_end(dest_pixels);
|
||||
free_aligned_buffer_page_end(orig_pixels);
|
||||
}
|
||||
|
||||
} // namespace libyuv
|
||||
282
externals/libyuv/unit_test/scale_rgb_test.cc
vendored
Normal file
282
externals/libyuv/unit_test/scale_rgb_test.cc
vendored
Normal file
@@ -0,0 +1,282 @@
|
||||
/*
|
||||
* Copyright 2022 The LibYuv Project Authors. All rights reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
|
||||
#include "../unit_test/unit_test.h"
|
||||
#include "libyuv/cpu_id.h"
|
||||
#include "libyuv/scale_rgb.h"
|
||||
|
||||
namespace libyuv {
|
||||
|
||||
#define STRINGIZE(line) #line
|
||||
#define FILELINESTR(file, line) file ":" STRINGIZE(line)
|
||||
|
||||
#if !defined(DISABLE_SLOW_TESTS) || defined(__x86_64__) || defined(__i386__)
|
||||
// SLOW TESTS are those that are unoptimized C code.
|
||||
// FULL TESTS are optimized but test many variations of the same code.
|
||||
#define ENABLE_FULL_TESTS
|
||||
#endif
|
||||
|
||||
// Test scaling with C vs Opt and return maximum pixel difference. 0 = exact.
|
||||
static int RGBTestFilter(int src_width,
|
||||
int src_height,
|
||||
int dst_width,
|
||||
int dst_height,
|
||||
FilterMode f,
|
||||
int benchmark_iterations,
|
||||
int disable_cpu_flags,
|
||||
int benchmark_cpu_info) {
|
||||
if (!SizeValid(src_width, src_height, dst_width, dst_height)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int i, j;
|
||||
const int b = 0; // 128 to test for padding/stride.
|
||||
int64_t src_rgb_plane_size =
|
||||
(Abs(src_width) + b * 3) * (Abs(src_height) + b * 3) * 3LL;
|
||||
int src_stride_rgb = (b * 3 + Abs(src_width)) * 3;
|
||||
|
||||
align_buffer_page_end(src_rgb, src_rgb_plane_size);
|
||||
if (!src_rgb) {
|
||||
printf("Skipped. Alloc failed " FILELINESTR(__FILE__, __LINE__) "\n");
|
||||
return 0;
|
||||
}
|
||||
MemRandomize(src_rgb, src_rgb_plane_size);
|
||||
|
||||
int64_t dst_rgb_plane_size = (dst_width + b * 3) * (dst_height + b * 3) * 3LL;
|
||||
int dst_stride_rgb = (b * 3 + dst_width) * 3;
|
||||
|
||||
align_buffer_page_end(dst_rgb_c, dst_rgb_plane_size);
|
||||
align_buffer_page_end(dst_rgb_opt, dst_rgb_plane_size);
|
||||
if (!dst_rgb_c || !dst_rgb_opt) {
|
||||
printf("Skipped. Alloc failed " FILELINESTR(__FILE__, __LINE__) "\n");
|
||||
return 0;
|
||||
}
|
||||
memset(dst_rgb_c, 2, dst_rgb_plane_size);
|
||||
memset(dst_rgb_opt, 3, dst_rgb_plane_size);
|
||||
|
||||
// Warm up both versions for consistent benchmarks.
|
||||
MaskCpuFlags(disable_cpu_flags); // Disable all CPU optimization.
|
||||
RGBScale(src_rgb + (src_stride_rgb * b) + b * 3, src_stride_rgb, src_width,
|
||||
src_height, dst_rgb_c + (dst_stride_rgb * b) + b * 3, dst_stride_rgb,
|
||||
dst_width, dst_height, f);
|
||||
MaskCpuFlags(benchmark_cpu_info); // Enable all CPU optimization.
|
||||
RGBScale(src_rgb + (src_stride_rgb * b) + b * 3, src_stride_rgb, src_width,
|
||||
src_height, dst_rgb_opt + (dst_stride_rgb * b) + b * 3,
|
||||
dst_stride_rgb, dst_width, dst_height, f);
|
||||
|
||||
MaskCpuFlags(disable_cpu_flags); // Disable all CPU optimization.
|
||||
double c_time = get_time();
|
||||
RGBScale(src_rgb + (src_stride_rgb * b) + b * 3, src_stride_rgb, src_width,
|
||||
src_height, dst_rgb_c + (dst_stride_rgb * b) + b * 3, dst_stride_rgb,
|
||||
dst_width, dst_height, f);
|
||||
|
||||
c_time = (get_time() - c_time);
|
||||
|
||||
MaskCpuFlags(benchmark_cpu_info); // Enable all CPU optimization.
|
||||
double opt_time = get_time();
|
||||
for (i = 0; i < benchmark_iterations; ++i) {
|
||||
RGBScale(src_rgb + (src_stride_rgb * b) + b * 3, src_stride_rgb, src_width,
|
||||
src_height, dst_rgb_opt + (dst_stride_rgb * b) + b * 3,
|
||||
dst_stride_rgb, dst_width, dst_height, f);
|
||||
}
|
||||
opt_time = (get_time() - opt_time) / benchmark_iterations;
|
||||
|
||||
// Report performance of C vs OPT
|
||||
printf("filter %d - %8d us C - %8d us OPT\n", f,
|
||||
static_cast<int>(c_time * 1e6), static_cast<int>(opt_time * 1e6));
|
||||
|
||||
// C version may be a little off from the optimized. Order of
|
||||
// operations may introduce rounding somewhere. So do a difference
|
||||
// of the buffers and look to see that the max difference isn't
|
||||
// over 2.
|
||||
int max_diff = 0;
|
||||
for (i = b; i < (dst_height + b); ++i) {
|
||||
for (j = b * 3; j < (dst_width + b) * 3; ++j) {
|
||||
int abs_diff = Abs(dst_rgb_c[(i * dst_stride_rgb) + j] -
|
||||
dst_rgb_opt[(i * dst_stride_rgb) + j]);
|
||||
if (abs_diff > max_diff) {
|
||||
max_diff = abs_diff;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
free_aligned_buffer_page_end(dst_rgb_c);
|
||||
free_aligned_buffer_page_end(dst_rgb_opt);
|
||||
free_aligned_buffer_page_end(src_rgb);
|
||||
return max_diff;
|
||||
}
|
||||
|
||||
// The following adjustments in dimensions ensure the scale factor will be
|
||||
// exactly achieved.
|
||||
#define DX(x, nom, denom) static_cast<int>((Abs(x) / nom) * nom)
|
||||
#define SX(x, nom, denom) static_cast<int>((x / nom) * denom)
|
||||
|
||||
#define TEST_FACTOR1(name, filter, nom, denom, max_diff) \
|
||||
TEST_F(LibYUVScaleTest, RGBScaleDownBy##name##_##filter) { \
|
||||
int diff = RGBTestFilter( \
|
||||
SX(benchmark_width_, nom, denom), SX(benchmark_height_, nom, denom), \
|
||||
DX(benchmark_width_, nom, denom), DX(benchmark_height_, nom, denom), \
|
||||
kFilter##filter, benchmark_iterations_, disable_cpu_flags_, \
|
||||
benchmark_cpu_info_); \
|
||||
EXPECT_LE(diff, max_diff); \
|
||||
}
|
||||
|
||||
#if defined(ENABLE_FULL_TESTS)
|
||||
// Test a scale factor with all 4 filters. Expect unfiltered to be exact, but
|
||||
// filtering is different fixed point implementations for SSSE3, Neon and C.
|
||||
#define TEST_FACTOR(name, nom, denom) \
|
||||
TEST_FACTOR1(name, None, nom, denom, 0) \
|
||||
TEST_FACTOR1(name, Linear, nom, denom, 3) \
|
||||
TEST_FACTOR1(name, Bilinear, nom, denom, 3) \
|
||||
TEST_FACTOR1(name, Box, nom, denom, 3)
|
||||
#else
|
||||
// Test a scale factor with Bilinear.
|
||||
#define TEST_FACTOR(name, nom, denom) \
|
||||
TEST_FACTOR1(name, Bilinear, nom, denom, 3)
|
||||
#endif
|
||||
|
||||
TEST_FACTOR(2, 1, 2)
|
||||
#ifndef DISABLE_SLOW_TESTS
|
||||
TEST_FACTOR(4, 1, 4)
|
||||
// TEST_FACTOR(8, 1, 8) Disable for benchmark performance.
|
||||
TEST_FACTOR(3by4, 3, 4)
|
||||
TEST_FACTOR(3by8, 3, 8)
|
||||
TEST_FACTOR(3, 1, 3)
|
||||
#endif
|
||||
#undef TEST_FACTOR1
|
||||
#undef TEST_FACTOR
|
||||
#undef SX
|
||||
#undef DX
|
||||
|
||||
#define TEST_SCALETO1(name, width, height, filter, max_diff) \
|
||||
TEST_F(LibYUVScaleTest, name##To##width##x##height##_##filter) { \
|
||||
int diff = RGBTestFilter(benchmark_width_, benchmark_height_, width, \
|
||||
height, kFilter##filter, benchmark_iterations_, \
|
||||
disable_cpu_flags_, benchmark_cpu_info_); \
|
||||
EXPECT_LE(diff, max_diff); \
|
||||
} \
|
||||
TEST_F(LibYUVScaleTest, name##From##width##x##height##_##filter) { \
|
||||
int diff = RGBTestFilter(width, height, Abs(benchmark_width_), \
|
||||
Abs(benchmark_height_), kFilter##filter, \
|
||||
benchmark_iterations_, disable_cpu_flags_, \
|
||||
benchmark_cpu_info_); \
|
||||
EXPECT_LE(diff, max_diff); \
|
||||
}
|
||||
|
||||
#if defined(ENABLE_FULL_TESTS)
|
||||
/// Test scale to a specified size with all 4 filters.
|
||||
#define TEST_SCALETO(name, width, height) \
|
||||
TEST_SCALETO1(name, width, height, None, 0) \
|
||||
TEST_SCALETO1(name, width, height, Linear, 3) \
|
||||
TEST_SCALETO1(name, width, height, Bilinear, 3)
|
||||
#else
|
||||
#define TEST_SCALETO(name, width, height) \
|
||||
TEST_SCALETO1(name, width, height, Bilinear, 3)
|
||||
#endif
|
||||
|
||||
#ifndef DISABLE_SLOW_TESTS
|
||||
TEST_SCALETO(RGBScale, 1, 1)
|
||||
#endif
|
||||
// TEST_SCALETO(RGBScale, 256, 144) /* 128x72 * 3 */
|
||||
TEST_SCALETO(RGBScale, 320, 240)
|
||||
#ifndef DISABLE_SLOW_TESTS
|
||||
TEST_SCALETO(RGBScale, 569, 480)
|
||||
TEST_SCALETO(RGBScale, 640, 360)
|
||||
TEST_SCALETO(RGBScale, 1280, 720)
|
||||
TEST_SCALETO(RGBScale, 1920, 1080)
|
||||
#endif // DISABLE_SLOW_TESTS
|
||||
#undef TEST_SCALETO1
|
||||
#undef TEST_SCALETO
|
||||
|
||||
#define TEST_SCALESWAPXY1(name, filter, max_diff) \
|
||||
TEST_F(LibYUVScaleTest, name##SwapXY_##filter) { \
|
||||
int diff = RGBTestFilter(benchmark_width_, benchmark_height_, \
|
||||
benchmark_height_, benchmark_width_, \
|
||||
kFilter##filter, benchmark_iterations_, \
|
||||
disable_cpu_flags_, benchmark_cpu_info_); \
|
||||
EXPECT_LE(diff, max_diff); \
|
||||
}
|
||||
|
||||
#if defined(ENABLE_FULL_TESTS)
|
||||
// Test scale with swapped width and height with all 3 filters.
|
||||
TEST_SCALESWAPXY1(RGBScale, None, 0)
|
||||
TEST_SCALESWAPXY1(RGBScale, Linear, 0)
|
||||
TEST_SCALESWAPXY1(RGBScale, Bilinear, 0)
|
||||
#else
|
||||
TEST_SCALESWAPXY1(RGBScale, Bilinear, 0)
|
||||
#endif
|
||||
#undef TEST_SCALESWAPXY1
|
||||
|
||||
TEST_F(LibYUVScaleTest, RGBTest3x) {
|
||||
const int kSrcStride = 480 * 3;
|
||||
const int kDstStride = 160 * 3;
|
||||
const int kSize = kSrcStride * 3;
|
||||
align_buffer_page_end(orig_pixels, kSize);
|
||||
for (int i = 0; i < 480 * 3; ++i) {
|
||||
orig_pixels[i * 3 + 0] = i;
|
||||
orig_pixels[i * 3 + 1] = 255 - i;
|
||||
}
|
||||
align_buffer_page_end(dest_pixels, kDstStride);
|
||||
|
||||
int iterations160 = (benchmark_width_ * benchmark_height_ + (160 - 1)) / 160 *
|
||||
benchmark_iterations_;
|
||||
for (int i = 0; i < iterations160; ++i) {
|
||||
RGBScale(orig_pixels, kSrcStride, 480, 3, dest_pixels, kDstStride, 160, 1,
|
||||
kFilterBilinear);
|
||||
}
|
||||
|
||||
EXPECT_EQ(225, dest_pixels[0]);
|
||||
EXPECT_EQ(255 - 225, dest_pixels[1]);
|
||||
|
||||
RGBScale(orig_pixels, kSrcStride, 480, 3, dest_pixels, kDstStride, 160, 1,
|
||||
kFilterNone);
|
||||
|
||||
EXPECT_EQ(225, dest_pixels[0]);
|
||||
EXPECT_EQ(255 - 225, dest_pixels[1]);
|
||||
|
||||
free_aligned_buffer_page_end(dest_pixels);
|
||||
free_aligned_buffer_page_end(orig_pixels);
|
||||
}
|
||||
|
||||
TEST_F(LibYUVScaleTest, RGBTest4x) {
|
||||
const int kSrcStride = 640 * 3;
|
||||
const int kDstStride = 160 * 3;
|
||||
const int kSize = kSrcStride * 4;
|
||||
align_buffer_page_end(orig_pixels, kSize);
|
||||
for (int i = 0; i < 640 * 4; ++i) {
|
||||
orig_pixels[i * 3 + 0] = i;
|
||||
orig_pixels[i * 3 + 1] = 255 - i;
|
||||
}
|
||||
align_buffer_page_end(dest_pixels, kDstStride);
|
||||
|
||||
int iterations160 = (benchmark_width_ * benchmark_height_ + (160 - 1)) / 160 *
|
||||
benchmark_iterations_;
|
||||
for (int i = 0; i < iterations160; ++i) {
|
||||
RGBScale(orig_pixels, kSrcStride, 640, 4, dest_pixels, kDstStride, 160, 1,
|
||||
kFilterBilinear);
|
||||
}
|
||||
|
||||
EXPECT_EQ(66, dest_pixels[0]);
|
||||
EXPECT_EQ(190, dest_pixels[1]);
|
||||
|
||||
RGBScale(orig_pixels, kSrcStride, 64, 4, dest_pixels, kDstStride, 16, 1,
|
||||
kFilterNone);
|
||||
|
||||
EXPECT_EQ(2, dest_pixels[0]); // expect the 3rd pixel of the 3rd row
|
||||
EXPECT_EQ(255 - 2, dest_pixels[1]);
|
||||
|
||||
free_aligned_buffer_page_end(dest_pixels);
|
||||
free_aligned_buffer_page_end(orig_pixels);
|
||||
}
|
||||
|
||||
} // namespace libyuv
|
||||
1601
externals/libyuv/unit_test/scale_test.cc
vendored
Normal file
1601
externals/libyuv/unit_test/scale_test.cc
vendored
Normal file
File diff suppressed because it is too large
Load Diff
278
externals/libyuv/unit_test/scale_uv_test.cc
vendored
Normal file
278
externals/libyuv/unit_test/scale_uv_test.cc
vendored
Normal file
@@ -0,0 +1,278 @@
|
||||
/*
|
||||
* Copyright 2011 The LibYuv Project Authors. All rights reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
|
||||
#include "../unit_test/unit_test.h"
|
||||
#include "libyuv/cpu_id.h"
|
||||
#include "libyuv/scale_uv.h"
|
||||
|
||||
namespace libyuv {
|
||||
|
||||
#define STRINGIZE(line) #line
|
||||
#define FILELINESTR(file, line) file ":" STRINGIZE(line)
|
||||
|
||||
#if !defined(DISABLE_SLOW_TESTS) || defined(__x86_64__) || defined(__i386__)
|
||||
// SLOW TESTS are those that are unoptimized C code.
|
||||
// FULL TESTS are optimized but test many variations of the same code.
|
||||
#define ENABLE_FULL_TESTS
|
||||
#endif
|
||||
|
||||
// Test scaling with C vs Opt and return maximum pixel difference. 0 = exact.
|
||||
static int UVTestFilter(int src_width,
|
||||
int src_height,
|
||||
int dst_width,
|
||||
int dst_height,
|
||||
FilterMode f,
|
||||
int benchmark_iterations,
|
||||
int disable_cpu_flags,
|
||||
int benchmark_cpu_info) {
|
||||
if (!SizeValid(src_width, src_height, dst_width, dst_height)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int i, j;
|
||||
const int b = 0; // 128 to test for padding/stride.
|
||||
int64_t src_uv_plane_size =
|
||||
(Abs(src_width) + b * 2) * (Abs(src_height) + b * 2) * 2LL;
|
||||
int src_stride_uv = (b * 2 + Abs(src_width)) * 2;
|
||||
|
||||
align_buffer_page_end(src_uv, src_uv_plane_size);
|
||||
if (!src_uv) {
|
||||
printf("Skipped. Alloc failed " FILELINESTR(__FILE__, __LINE__) "\n");
|
||||
return 0;
|
||||
}
|
||||
MemRandomize(src_uv, src_uv_plane_size);
|
||||
|
||||
int64_t dst_uv_plane_size = (dst_width + b * 2) * (dst_height + b * 2) * 2LL;
|
||||
int dst_stride_uv = (b * 2 + dst_width) * 2;
|
||||
|
||||
align_buffer_page_end(dst_uv_c, dst_uv_plane_size);
|
||||
align_buffer_page_end(dst_uv_opt, dst_uv_plane_size);
|
||||
if (!dst_uv_c || !dst_uv_opt) {
|
||||
printf("Skipped. Alloc failed " FILELINESTR(__FILE__, __LINE__) "\n");
|
||||
return 0;
|
||||
}
|
||||
memset(dst_uv_c, 2, dst_uv_plane_size);
|
||||
memset(dst_uv_opt, 3, dst_uv_plane_size);
|
||||
|
||||
// Warm up both versions for consistent benchmarks.
|
||||
MaskCpuFlags(disable_cpu_flags); // Disable all CPU optimization.
|
||||
UVScale(src_uv + (src_stride_uv * b) + b * 2, src_stride_uv, src_width,
|
||||
src_height, dst_uv_c + (dst_stride_uv * b) + b * 2, dst_stride_uv,
|
||||
dst_width, dst_height, f);
|
||||
MaskCpuFlags(benchmark_cpu_info); // Enable all CPU optimization.
|
||||
UVScale(src_uv + (src_stride_uv * b) + b * 2, src_stride_uv, src_width,
|
||||
src_height, dst_uv_opt + (dst_stride_uv * b) + b * 2, dst_stride_uv,
|
||||
dst_width, dst_height, f);
|
||||
|
||||
MaskCpuFlags(disable_cpu_flags); // Disable all CPU optimization.
|
||||
double c_time = get_time();
|
||||
UVScale(src_uv + (src_stride_uv * b) + b * 2, src_stride_uv, src_width,
|
||||
src_height, dst_uv_c + (dst_stride_uv * b) + b * 2, dst_stride_uv,
|
||||
dst_width, dst_height, f);
|
||||
|
||||
c_time = (get_time() - c_time);
|
||||
|
||||
MaskCpuFlags(benchmark_cpu_info); // Enable all CPU optimization.
|
||||
double opt_time = get_time();
|
||||
for (i = 0; i < benchmark_iterations; ++i) {
|
||||
UVScale(src_uv + (src_stride_uv * b) + b * 2, src_stride_uv, src_width,
|
||||
src_height, dst_uv_opt + (dst_stride_uv * b) + b * 2, dst_stride_uv,
|
||||
dst_width, dst_height, f);
|
||||
}
|
||||
opt_time = (get_time() - opt_time) / benchmark_iterations;
|
||||
|
||||
// Report performance of C vs OPT
|
||||
printf("filter %d - %8d us C - %8d us OPT\n", f,
|
||||
static_cast<int>(c_time * 1e6), static_cast<int>(opt_time * 1e6));
|
||||
|
||||
// C version may be a little off from the optimized. Order of
|
||||
// operations may introduce rounding somewhere. So do a difference
|
||||
// of the buffers and look to see that the max difference isn't
|
||||
// over 2.
|
||||
int max_diff = 0;
|
||||
for (i = b; i < (dst_height + b); ++i) {
|
||||
for (j = b * 2; j < (dst_width + b) * 2; ++j) {
|
||||
int abs_diff = Abs(dst_uv_c[(i * dst_stride_uv) + j] -
|
||||
dst_uv_opt[(i * dst_stride_uv) + j]);
|
||||
if (abs_diff > max_diff) {
|
||||
max_diff = abs_diff;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
free_aligned_buffer_page_end(dst_uv_c);
|
||||
free_aligned_buffer_page_end(dst_uv_opt);
|
||||
free_aligned_buffer_page_end(src_uv);
|
||||
return max_diff;
|
||||
}
|
||||
|
||||
// The following adjustments in dimensions ensure the scale factor will be
|
||||
// exactly achieved.
|
||||
#define DX(x, nom, denom) static_cast<int>((Abs(x) / nom) * nom)
|
||||
#define SX(x, nom, denom) static_cast<int>((x / nom) * denom)
|
||||
|
||||
#define TEST_FACTOR1(name, filter, nom, denom, max_diff) \
|
||||
TEST_F(LibYUVScaleTest, UVScaleDownBy##name##_##filter) { \
|
||||
int diff = UVTestFilter( \
|
||||
SX(benchmark_width_, nom, denom), SX(benchmark_height_, nom, denom), \
|
||||
DX(benchmark_width_, nom, denom), DX(benchmark_height_, nom, denom), \
|
||||
kFilter##filter, benchmark_iterations_, disable_cpu_flags_, \
|
||||
benchmark_cpu_info_); \
|
||||
EXPECT_LE(diff, max_diff); \
|
||||
}
|
||||
|
||||
#if defined(ENABLE_FULL_TESTS)
|
||||
// Test a scale factor with all 4 filters. Expect unfiltered to be exact, but
|
||||
// filtering is different fixed point implementations for SSSE3, Neon and C.
|
||||
#define TEST_FACTOR(name, nom, denom) \
|
||||
TEST_FACTOR1(name, None, nom, denom, 0) \
|
||||
TEST_FACTOR1(name, Linear, nom, denom, 3) \
|
||||
TEST_FACTOR1(name, Bilinear, nom, denom, 3) \
|
||||
TEST_FACTOR1(name, Box, nom, denom, 3)
|
||||
#else
|
||||
// Test a scale factor with Bilinear.
|
||||
#define TEST_FACTOR(name, nom, denom) \
|
||||
TEST_FACTOR1(name, Bilinear, nom, denom, 3)
|
||||
#endif
|
||||
|
||||
TEST_FACTOR(2, 1, 2)
|
||||
TEST_FACTOR(4, 1, 4)
|
||||
// TEST_FACTOR(8, 1, 8) Disable for benchmark performance.
|
||||
TEST_FACTOR(3by4, 3, 4)
|
||||
TEST_FACTOR(3by8, 3, 8)
|
||||
TEST_FACTOR(3, 1, 3)
|
||||
#undef TEST_FACTOR1
|
||||
#undef TEST_FACTOR
|
||||
#undef SX
|
||||
#undef DX
|
||||
|
||||
#define TEST_SCALETO1(name, width, height, filter, max_diff) \
|
||||
TEST_F(LibYUVScaleTest, name##To##width##x##height##_##filter) { \
|
||||
int diff = UVTestFilter(benchmark_width_, benchmark_height_, width, \
|
||||
height, kFilter##filter, benchmark_iterations_, \
|
||||
disable_cpu_flags_, benchmark_cpu_info_); \
|
||||
EXPECT_LE(diff, max_diff); \
|
||||
} \
|
||||
TEST_F(LibYUVScaleTest, name##From##width##x##height##_##filter) { \
|
||||
int diff = UVTestFilter(width, height, Abs(benchmark_width_), \
|
||||
Abs(benchmark_height_), kFilter##filter, \
|
||||
benchmark_iterations_, disable_cpu_flags_, \
|
||||
benchmark_cpu_info_); \
|
||||
EXPECT_LE(diff, max_diff); \
|
||||
}
|
||||
|
||||
#if defined(ENABLE_FULL_TESTS)
|
||||
/// Test scale to a specified size with all 4 filters.
|
||||
#define TEST_SCALETO(name, width, height) \
|
||||
TEST_SCALETO1(name, width, height, None, 0) \
|
||||
TEST_SCALETO1(name, width, height, Linear, 3) \
|
||||
TEST_SCALETO1(name, width, height, Bilinear, 3)
|
||||
#else
|
||||
#define TEST_SCALETO(name, width, height) \
|
||||
TEST_SCALETO1(name, width, height, Bilinear, 3)
|
||||
#endif
|
||||
|
||||
TEST_SCALETO(UVScale, 1, 1)
|
||||
// TEST_SCALETO(UVScale, 256, 144) /* 128x72 * 2 */
|
||||
TEST_SCALETO(UVScale, 320, 240)
|
||||
TEST_SCALETO(UVScale, 569, 480)
|
||||
TEST_SCALETO(UVScale, 640, 360)
|
||||
#ifndef DISABLE_SLOW_TESTS
|
||||
TEST_SCALETO(UVScale, 1280, 720)
|
||||
TEST_SCALETO(UVScale, 1920, 1080)
|
||||
#endif // DISABLE_SLOW_TESTS
|
||||
#undef TEST_SCALETO1
|
||||
#undef TEST_SCALETO
|
||||
|
||||
#define TEST_SCALESWAPXY1(name, filter, max_diff) \
|
||||
TEST_F(LibYUVScaleTest, name##SwapXY_##filter) { \
|
||||
int diff = \
|
||||
UVTestFilter(benchmark_width_, benchmark_height_, benchmark_height_, \
|
||||
benchmark_width_, kFilter##filter, benchmark_iterations_, \
|
||||
disable_cpu_flags_, benchmark_cpu_info_); \
|
||||
EXPECT_LE(diff, max_diff); \
|
||||
}
|
||||
|
||||
#if defined(ENABLE_FULL_TESTS)
|
||||
// Test scale with swapped width and height with all 3 filters.
|
||||
TEST_SCALESWAPXY1(UVScale, None, 0)
|
||||
TEST_SCALESWAPXY1(UVScale, Linear, 0)
|
||||
TEST_SCALESWAPXY1(UVScale, Bilinear, 0)
|
||||
#else
|
||||
TEST_SCALESWAPXY1(UVScale, Bilinear, 0)
|
||||
#endif
|
||||
#undef TEST_SCALESWAPXY1
|
||||
|
||||
TEST_F(LibYUVScaleTest, UVTest3x) {
|
||||
const int kSrcStride = 480 * 2;
|
||||
const int kDstStride = 160 * 2;
|
||||
const int kSize = kSrcStride * 3;
|
||||
align_buffer_page_end(orig_pixels, kSize);
|
||||
for (int i = 0; i < 480 * 3; ++i) {
|
||||
orig_pixels[i * 2 + 0] = i;
|
||||
orig_pixels[i * 2 + 1] = 255 - i;
|
||||
}
|
||||
align_buffer_page_end(dest_pixels, kDstStride);
|
||||
|
||||
int iterations160 = (benchmark_width_ * benchmark_height_ + (160 - 1)) / 160 *
|
||||
benchmark_iterations_;
|
||||
for (int i = 0; i < iterations160; ++i) {
|
||||
UVScale(orig_pixels, kSrcStride, 480, 3, dest_pixels, kDstStride, 160, 1,
|
||||
kFilterBilinear);
|
||||
}
|
||||
|
||||
EXPECT_EQ(225, dest_pixels[0]);
|
||||
EXPECT_EQ(255 - 225, dest_pixels[1]);
|
||||
|
||||
UVScale(orig_pixels, kSrcStride, 480, 3, dest_pixels, kDstStride, 160, 1,
|
||||
kFilterNone);
|
||||
|
||||
EXPECT_EQ(225, dest_pixels[0]);
|
||||
EXPECT_EQ(255 - 225, dest_pixels[1]);
|
||||
|
||||
free_aligned_buffer_page_end(dest_pixels);
|
||||
free_aligned_buffer_page_end(orig_pixels);
|
||||
}
|
||||
|
||||
TEST_F(LibYUVScaleTest, UVTest4x) {
|
||||
const int kSrcStride = 640 * 2;
|
||||
const int kDstStride = 160 * 2;
|
||||
const int kSize = kSrcStride * 4;
|
||||
align_buffer_page_end(orig_pixels, kSize);
|
||||
for (int i = 0; i < 640 * 4; ++i) {
|
||||
orig_pixels[i * 2 + 0] = i;
|
||||
orig_pixels[i * 2 + 1] = 255 - i;
|
||||
}
|
||||
align_buffer_page_end(dest_pixels, kDstStride);
|
||||
|
||||
int iterations160 = (benchmark_width_ * benchmark_height_ + (160 - 1)) / 160 *
|
||||
benchmark_iterations_;
|
||||
for (int i = 0; i < iterations160; ++i) {
|
||||
UVScale(orig_pixels, kSrcStride, 640, 4, dest_pixels, kDstStride, 160, 1,
|
||||
kFilterBilinear);
|
||||
}
|
||||
|
||||
EXPECT_EQ(66, dest_pixels[0]);
|
||||
EXPECT_EQ(190, dest_pixels[1]);
|
||||
|
||||
UVScale(orig_pixels, kSrcStride, 64, 4, dest_pixels, kDstStride, 16, 1,
|
||||
kFilterNone);
|
||||
|
||||
EXPECT_EQ(2, dest_pixels[0]); // expect the 3rd pixel of the 3rd row
|
||||
EXPECT_EQ(255 - 2, dest_pixels[1]);
|
||||
|
||||
free_aligned_buffer_page_end(dest_pixels);
|
||||
free_aligned_buffer_page_end(orig_pixels);
|
||||
}
|
||||
|
||||
} // namespace libyuv
|
||||
12
externals/libyuv/unit_test/testdata/arm_v7.txt
vendored
Normal file
12
externals/libyuv/unit_test/testdata/arm_v7.txt
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
Processor : ARMv7 Processor rev 5 (v7l)
|
||||
BogoMIPS : 795.44
|
||||
Features : swp half thumb fastmult vfp edsp iwmmxt thumbee vfpv3 vfpv3d16
|
||||
CPU implementer : 0x56
|
||||
CPU architecture: 7
|
||||
CPU variant : 0x0
|
||||
CPU part : 0x581
|
||||
CPU revision : 5
|
||||
|
||||
Hardware : OLPC XO-1.75
|
||||
Revision : 0000
|
||||
Serial : 0000000000000000
|
||||
15
externals/libyuv/unit_test/testdata/juno.txt
vendored
Normal file
15
externals/libyuv/unit_test/testdata/juno.txt
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
Processor : AArch64 Processor rev 0 (aarch64)
|
||||
processor : 0
|
||||
processor : 1
|
||||
processor : 2
|
||||
processor : 3
|
||||
processor : 4
|
||||
processor : 5
|
||||
Features : fp asimd evtstrm aes pmull sha1 sha2 crc32
|
||||
CPU implementer : 0x41
|
||||
CPU architecture: AArch64
|
||||
CPU variant : 0x0
|
||||
CPU part : 0xd07
|
||||
CPU revision : 0
|
||||
|
||||
Hardware : Juno
|
||||
7
externals/libyuv/unit_test/testdata/mips.txt
vendored
Normal file
7
externals/libyuv/unit_test/testdata/mips.txt
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
system type : generic-loongson-machine
|
||||
machine : loongson,generic
|
||||
processor : 0
|
||||
|
||||
isa : mips1 mips2 mips3 mips4 mips5 mips32r1 mips32r2 mips64r1 mips64r2
|
||||
ASEs implemented : vz
|
||||
shadow register sets : 1
|
||||
5
externals/libyuv/unit_test/testdata/mips_loongson2k.txt
vendored
Normal file
5
externals/libyuv/unit_test/testdata/mips_loongson2k.txt
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
system type : Loongson2K-SBC
|
||||
machine : loongson,LS2k1000-EVP
|
||||
processor : 0
|
||||
cpu model : Loongson-2K V0.3 FPU V0.1
|
||||
BogoMIPS : 1980.41
|
||||
10
externals/libyuv/unit_test/testdata/mips_loongson3.txt
vendored
Normal file
10
externals/libyuv/unit_test/testdata/mips_loongson3.txt
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
system type : generic-loongson-machine
|
||||
machine : Unknown
|
||||
processor : 0
|
||||
cpu model : ICT Loongson-3 V0.9 FPU V0.1
|
||||
model name : ICT Loongson-3A R3 (Loongson-3A3000) @ 1500MHz
|
||||
BogoMIPS : 2990.15
|
||||
|
||||
isa : mips1 mips2 mips3 mips4 mips5 mips32r1 mips32r2 mips64r1 mips64r2
|
||||
ASEs implemented : dsp dsp2 vz
|
||||
shadow register sets : 1
|
||||
7
externals/libyuv/unit_test/testdata/mips_loongson_mmi.txt
vendored
Normal file
7
externals/libyuv/unit_test/testdata/mips_loongson_mmi.txt
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
system type : generic-loongson-machine
|
||||
machine : loongson,generic
|
||||
processor : 0
|
||||
|
||||
isa : mips1 mips2 mips3 mips4 mips5 mips32r1 mips32r2 mips64r1 mips64r2
|
||||
ASEs implemented : vz loongson-mmi loongson-ext
|
||||
shadow register sets : 1
|
||||
7
externals/libyuv/unit_test/testdata/mips_msa.txt
vendored
Normal file
7
externals/libyuv/unit_test/testdata/mips_msa.txt
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
system type : generic-loongson-machine
|
||||
machine : loongson,generic
|
||||
processor : 0
|
||||
|
||||
isa : mips1 mips2 mips3 mips4 mips5 mips32r1 mips32r2 mips64r1 mips64r2
|
||||
ASEs implemented : vz msa
|
||||
shadow register sets : 1
|
||||
23
externals/libyuv/unit_test/testdata/tegra3.txt
vendored
Normal file
23
externals/libyuv/unit_test/testdata/tegra3.txt
vendored
Normal file
@@ -0,0 +1,23 @@
|
||||
Processor : ARMv7 Processor rev 9 (v7l)
|
||||
processor : 0
|
||||
BogoMIPS : 1992.29
|
||||
|
||||
processor : 1
|
||||
BogoMIPS : 1992.29
|
||||
|
||||
processor : 2
|
||||
BogoMIPS : 1992.29
|
||||
|
||||
processor : 3
|
||||
BogoMIPS : 1992.29
|
||||
|
||||
Features : swp half thumb fastmult vfp edsp neon vfpv3
|
||||
CPU implementer : 0×41
|
||||
CPU architecture: 7
|
||||
CPU variant : 0×2
|
||||
CPU part : 0xc09
|
||||
CPU revision : 9
|
||||
|
||||
Hardware : cardhu
|
||||
Revision : 0000
|
||||
|
||||
BIN
externals/libyuv/unit_test/testdata/test0.jpg
vendored
Normal file
BIN
externals/libyuv/unit_test/testdata/test0.jpg
vendored
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 421 B |
BIN
externals/libyuv/unit_test/testdata/test1.jpg
vendored
Normal file
BIN
externals/libyuv/unit_test/testdata/test1.jpg
vendored
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 735 B |
BIN
externals/libyuv/unit_test/testdata/test2.jpg
vendored
Normal file
BIN
externals/libyuv/unit_test/testdata/test2.jpg
vendored
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 685 B |
BIN
externals/libyuv/unit_test/testdata/test3.jpg
vendored
Normal file
BIN
externals/libyuv/unit_test/testdata/test3.jpg
vendored
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 704 B |
BIN
externals/libyuv/unit_test/testdata/test4.jpg
vendored
Normal file
BIN
externals/libyuv/unit_test/testdata/test4.jpg
vendored
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 701 B |
557
externals/libyuv/unit_test/unit_test.cc
vendored
Normal file
557
externals/libyuv/unit_test/unit_test.cc
vendored
Normal file
@@ -0,0 +1,557 @@
|
||||
/*
|
||||
* Copyright 2011 The LibYuv Project Authors. All rights reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#include "../unit_test/unit_test.h"
|
||||
|
||||
#include <stdlib.h> // For getenv()
|
||||
|
||||
#include <cstring>
|
||||
|
||||
#ifdef LIBYUV_USE_ABSL_FLAGS
|
||||
#include "absl/flags/flag.h"
|
||||
#include "absl/flags/parse.h"
|
||||
#endif
|
||||
#include "libyuv/cpu_id.h"
|
||||
|
||||
unsigned int fastrand_seed = 0xfb;
|
||||
|
||||
#ifdef LIBYUV_USE_ABSL_FLAGS
|
||||
ABSL_FLAG(int32_t, libyuv_width, 0, "width of test image.");
|
||||
ABSL_FLAG(int32_t, libyuv_height, 0, "height of test image.");
|
||||
ABSL_FLAG(int32_t, libyuv_repeat, 0, "number of times to repeat test.");
|
||||
ABSL_FLAG(int32_t,
|
||||
libyuv_flags,
|
||||
0,
|
||||
"cpu flags for reference code. 1 = C, -1 = SIMD");
|
||||
ABSL_FLAG(int32_t,
|
||||
libyuv_cpu_info,
|
||||
0,
|
||||
"cpu flags for benchmark code. 1 = C, -1 = SIMD");
|
||||
#else
|
||||
// Disable command line parameters if absl/flags disabled.
|
||||
static const int32_t FLAGS_libyuv_width = 0;
|
||||
static const int32_t FLAGS_libyuv_height = 0;
|
||||
static const int32_t FLAGS_libyuv_repeat = 0;
|
||||
static const int32_t FLAGS_libyuv_flags = 0;
|
||||
static const int32_t FLAGS_libyuv_cpu_info = 0;
|
||||
#endif
|
||||
|
||||
#ifdef LIBYUV_USE_ABSL_FLAGS
|
||||
#define LIBYUV_GET_FLAG(f) absl::GetFlag(f)
|
||||
#else
|
||||
#define LIBYUV_GET_FLAG(f) f
|
||||
#endif
|
||||
|
||||
// Test environment variable for disabling CPU features. Any non-zero value
|
||||
// to disable. Zero ignored to make it easy to set the variable on/off.
|
||||
#if !defined(__native_client__) && !defined(_M_ARM)
|
||||
static LIBYUV_BOOL TestEnv(const char* name) {
|
||||
const char* var = getenv(name);
|
||||
if (var) {
|
||||
if (var[0] != '0') {
|
||||
return LIBYUV_TRUE;
|
||||
}
|
||||
}
|
||||
return LIBYUV_FALSE;
|
||||
}
|
||||
#else // nacl does not support getenv().
|
||||
static LIBYUV_BOOL TestEnv(const char*) {
|
||||
return LIBYUV_FALSE;
|
||||
}
|
||||
#endif
|
||||
|
||||
int TestCpuEnv(int cpu_info) {
|
||||
#if defined(__arm__) || defined(__aarch64__)
|
||||
if (TestEnv("LIBYUV_DISABLE_NEON")) {
|
||||
cpu_info &= ~libyuv::kCpuHasNEON;
|
||||
}
|
||||
#endif
|
||||
#if defined(__mips__) && defined(__linux__)
|
||||
if (TestEnv("LIBYUV_DISABLE_MSA")) {
|
||||
cpu_info &= ~libyuv::kCpuHasMSA;
|
||||
}
|
||||
#endif
|
||||
#if defined(__longarch__) && defined(__linux__)
|
||||
if (TestEnv("LIBYUV_DISABLE_LSX")) {
|
||||
cpu_info &= ~libyuv::kCpuHasLSX;
|
||||
}
|
||||
#endif
|
||||
#if defined(__longarch__) && defined(__linux__)
|
||||
if (TestEnv("LIBYUV_DISABLE_LASX")) {
|
||||
cpu_info &= ~libyuv::kCpuHasLASX;
|
||||
}
|
||||
#endif
|
||||
#if !defined(__pnacl__) && !defined(__CLR_VER) && \
|
||||
(defined(__x86_64__) || defined(_M_X64) || defined(__i386__) || \
|
||||
defined(_M_IX86))
|
||||
if (TestEnv("LIBYUV_DISABLE_X86")) {
|
||||
cpu_info &= ~libyuv::kCpuHasX86;
|
||||
}
|
||||
if (TestEnv("LIBYUV_DISABLE_SSE2")) {
|
||||
cpu_info &= ~libyuv::kCpuHasSSE2;
|
||||
}
|
||||
if (TestEnv("LIBYUV_DISABLE_SSSE3")) {
|
||||
cpu_info &= ~libyuv::kCpuHasSSSE3;
|
||||
}
|
||||
if (TestEnv("LIBYUV_DISABLE_SSE41")) {
|
||||
cpu_info &= ~libyuv::kCpuHasSSE41;
|
||||
}
|
||||
if (TestEnv("LIBYUV_DISABLE_SSE42")) {
|
||||
cpu_info &= ~libyuv::kCpuHasSSE42;
|
||||
}
|
||||
if (TestEnv("LIBYUV_DISABLE_AVX")) {
|
||||
cpu_info &= ~libyuv::kCpuHasAVX;
|
||||
}
|
||||
if (TestEnv("LIBYUV_DISABLE_AVX2")) {
|
||||
cpu_info &= ~libyuv::kCpuHasAVX2;
|
||||
}
|
||||
if (TestEnv("LIBYUV_DISABLE_ERMS")) {
|
||||
cpu_info &= ~libyuv::kCpuHasERMS;
|
||||
}
|
||||
if (TestEnv("LIBYUV_DISABLE_FMA3")) {
|
||||
cpu_info &= ~libyuv::kCpuHasFMA3;
|
||||
}
|
||||
if (TestEnv("LIBYUV_DISABLE_F16C")) {
|
||||
cpu_info &= ~libyuv::kCpuHasF16C;
|
||||
}
|
||||
if (TestEnv("LIBYUV_DISABLE_AVX512BW")) {
|
||||
cpu_info &= ~libyuv::kCpuHasAVX512BW;
|
||||
}
|
||||
if (TestEnv("LIBYUV_DISABLE_AVX512VL")) {
|
||||
cpu_info &= ~libyuv::kCpuHasAVX512VL;
|
||||
}
|
||||
if (TestEnv("LIBYUV_DISABLE_AVX512VNNI")) {
|
||||
cpu_info &= ~libyuv::kCpuHasAVX512VNNI;
|
||||
}
|
||||
if (TestEnv("LIBYUV_DISABLE_AVX512VBMI")) {
|
||||
cpu_info &= ~libyuv::kCpuHasAVX512VBMI;
|
||||
}
|
||||
if (TestEnv("LIBYUV_DISABLE_AVX512VBMI2")) {
|
||||
cpu_info &= ~libyuv::kCpuHasAVX512VBMI2;
|
||||
}
|
||||
if (TestEnv("LIBYUV_DISABLE_AVX512VBITALG")) {
|
||||
cpu_info &= ~libyuv::kCpuHasAVX512VBITALG;
|
||||
}
|
||||
if (TestEnv("LIBYUV_DISABLE_AVX512VPOPCNTDQ")) {
|
||||
cpu_info &= ~libyuv::kCpuHasAVX512VPOPCNTDQ;
|
||||
}
|
||||
if (TestEnv("LIBYUV_DISABLE_GFNI")) {
|
||||
cpu_info &= ~libyuv::kCpuHasGFNI;
|
||||
}
|
||||
#endif
|
||||
if (TestEnv("LIBYUV_DISABLE_ASM")) {
|
||||
cpu_info = libyuv::kCpuInitialized;
|
||||
}
|
||||
return cpu_info;
|
||||
}
|
||||
|
||||
// For quicker unittests, default is 128 x 72. But when benchmarking,
|
||||
// default to 720p. Allow size to specify.
|
||||
// Set flags to -1 for benchmarking to avoid slower C code.
|
||||
|
||||
LibYUVConvertTest::LibYUVConvertTest()
|
||||
: benchmark_iterations_(1),
|
||||
benchmark_width_(128),
|
||||
benchmark_height_(72),
|
||||
disable_cpu_flags_(1),
|
||||
benchmark_cpu_info_(-1) {
|
||||
const char* repeat = getenv("LIBYUV_REPEAT");
|
||||
if (repeat) {
|
||||
benchmark_iterations_ = atoi(repeat); // NOLINT
|
||||
}
|
||||
if (LIBYUV_GET_FLAG(FLAGS_libyuv_repeat)) {
|
||||
benchmark_iterations_ = LIBYUV_GET_FLAG(FLAGS_libyuv_repeat);
|
||||
}
|
||||
if (benchmark_iterations_ > 1) {
|
||||
benchmark_width_ = 1280;
|
||||
benchmark_height_ = 720;
|
||||
}
|
||||
const char* width = getenv("LIBYUV_WIDTH");
|
||||
if (width) {
|
||||
benchmark_width_ = atoi(width); // NOLINT
|
||||
}
|
||||
if (LIBYUV_GET_FLAG(FLAGS_libyuv_width)) {
|
||||
benchmark_width_ = LIBYUV_GET_FLAG(FLAGS_libyuv_width);
|
||||
}
|
||||
const char* height = getenv("LIBYUV_HEIGHT");
|
||||
if (height) {
|
||||
benchmark_height_ = atoi(height); // NOLINT
|
||||
}
|
||||
if (LIBYUV_GET_FLAG(FLAGS_libyuv_height)) {
|
||||
benchmark_height_ = LIBYUV_GET_FLAG(FLAGS_libyuv_height);
|
||||
}
|
||||
const char* cpu_flags = getenv("LIBYUV_FLAGS");
|
||||
if (cpu_flags) {
|
||||
disable_cpu_flags_ = atoi(cpu_flags); // NOLINT
|
||||
}
|
||||
if (LIBYUV_GET_FLAG(FLAGS_libyuv_flags)) {
|
||||
disable_cpu_flags_ = LIBYUV_GET_FLAG(FLAGS_libyuv_flags);
|
||||
}
|
||||
const char* cpu_info = getenv("LIBYUV_CPU_INFO");
|
||||
if (cpu_info) {
|
||||
benchmark_cpu_info_ = atoi(cpu_flags); // NOLINT
|
||||
}
|
||||
if (LIBYUV_GET_FLAG(FLAGS_libyuv_cpu_info)) {
|
||||
benchmark_cpu_info_ = LIBYUV_GET_FLAG(FLAGS_libyuv_cpu_info);
|
||||
}
|
||||
disable_cpu_flags_ = TestCpuEnv(disable_cpu_flags_);
|
||||
benchmark_cpu_info_ = TestCpuEnv(benchmark_cpu_info_);
|
||||
libyuv::MaskCpuFlags(benchmark_cpu_info_);
|
||||
benchmark_pixels_div1280_ =
|
||||
static_cast<int>((static_cast<double>(Abs(benchmark_width_)) *
|
||||
static_cast<double>(Abs(benchmark_height_)) *
|
||||
static_cast<double>(benchmark_iterations_) +
|
||||
1279.0) /
|
||||
1280.0);
|
||||
}
|
||||
|
||||
LibYUVColorTest::LibYUVColorTest()
|
||||
: benchmark_iterations_(1),
|
||||
benchmark_width_(128),
|
||||
benchmark_height_(72),
|
||||
disable_cpu_flags_(1),
|
||||
benchmark_cpu_info_(-1) {
|
||||
const char* repeat = getenv("LIBYUV_REPEAT");
|
||||
if (repeat) {
|
||||
benchmark_iterations_ = atoi(repeat); // NOLINT
|
||||
}
|
||||
if (LIBYUV_GET_FLAG(FLAGS_libyuv_repeat)) {
|
||||
benchmark_iterations_ = LIBYUV_GET_FLAG(FLAGS_libyuv_repeat);
|
||||
}
|
||||
if (benchmark_iterations_ > 1) {
|
||||
benchmark_width_ = 1280;
|
||||
benchmark_height_ = 720;
|
||||
}
|
||||
const char* width = getenv("LIBYUV_WIDTH");
|
||||
if (width) {
|
||||
benchmark_width_ = atoi(width); // NOLINT
|
||||
}
|
||||
if (LIBYUV_GET_FLAG(FLAGS_libyuv_width)) {
|
||||
benchmark_width_ = LIBYUV_GET_FLAG(FLAGS_libyuv_width);
|
||||
}
|
||||
const char* height = getenv("LIBYUV_HEIGHT");
|
||||
if (height) {
|
||||
benchmark_height_ = atoi(height); // NOLINT
|
||||
}
|
||||
if (LIBYUV_GET_FLAG(FLAGS_libyuv_height)) {
|
||||
benchmark_height_ = LIBYUV_GET_FLAG(FLAGS_libyuv_height);
|
||||
}
|
||||
const char* cpu_flags = getenv("LIBYUV_FLAGS");
|
||||
if (cpu_flags) {
|
||||
disable_cpu_flags_ = atoi(cpu_flags); // NOLINT
|
||||
}
|
||||
if (LIBYUV_GET_FLAG(FLAGS_libyuv_flags)) {
|
||||
disable_cpu_flags_ = LIBYUV_GET_FLAG(FLAGS_libyuv_flags);
|
||||
}
|
||||
const char* cpu_info = getenv("LIBYUV_CPU_INFO");
|
||||
if (cpu_info) {
|
||||
benchmark_cpu_info_ = atoi(cpu_flags); // NOLINT
|
||||
}
|
||||
if (LIBYUV_GET_FLAG(FLAGS_libyuv_cpu_info)) {
|
||||
benchmark_cpu_info_ = LIBYUV_GET_FLAG(FLAGS_libyuv_cpu_info);
|
||||
}
|
||||
disable_cpu_flags_ = TestCpuEnv(disable_cpu_flags_);
|
||||
benchmark_cpu_info_ = TestCpuEnv(benchmark_cpu_info_);
|
||||
libyuv::MaskCpuFlags(benchmark_cpu_info_);
|
||||
benchmark_pixels_div1280_ =
|
||||
static_cast<int>((static_cast<double>(Abs(benchmark_width_)) *
|
||||
static_cast<double>(Abs(benchmark_height_)) *
|
||||
static_cast<double>(benchmark_iterations_) +
|
||||
1279.0) /
|
||||
1280.0);
|
||||
}
|
||||
|
||||
LibYUVScaleTest::LibYUVScaleTest()
|
||||
: benchmark_iterations_(1),
|
||||
benchmark_width_(128),
|
||||
benchmark_height_(72),
|
||||
disable_cpu_flags_(1),
|
||||
benchmark_cpu_info_(-1) {
|
||||
const char* repeat = getenv("LIBYUV_REPEAT");
|
||||
if (repeat) {
|
||||
benchmark_iterations_ = atoi(repeat); // NOLINT
|
||||
}
|
||||
if (LIBYUV_GET_FLAG(FLAGS_libyuv_repeat)) {
|
||||
benchmark_iterations_ = LIBYUV_GET_FLAG(FLAGS_libyuv_repeat);
|
||||
}
|
||||
if (benchmark_iterations_ > 1) {
|
||||
benchmark_width_ = 1280;
|
||||
benchmark_height_ = 720;
|
||||
}
|
||||
const char* width = getenv("LIBYUV_WIDTH");
|
||||
if (width) {
|
||||
benchmark_width_ = atoi(width); // NOLINT
|
||||
}
|
||||
if (LIBYUV_GET_FLAG(FLAGS_libyuv_width)) {
|
||||
benchmark_width_ = LIBYUV_GET_FLAG(FLAGS_libyuv_width);
|
||||
}
|
||||
const char* height = getenv("LIBYUV_HEIGHT");
|
||||
if (height) {
|
||||
benchmark_height_ = atoi(height); // NOLINT
|
||||
}
|
||||
if (LIBYUV_GET_FLAG(FLAGS_libyuv_height)) {
|
||||
benchmark_height_ = LIBYUV_GET_FLAG(FLAGS_libyuv_height);
|
||||
}
|
||||
const char* cpu_flags = getenv("LIBYUV_FLAGS");
|
||||
if (cpu_flags) {
|
||||
disable_cpu_flags_ = atoi(cpu_flags); // NOLINT
|
||||
}
|
||||
if (LIBYUV_GET_FLAG(FLAGS_libyuv_flags)) {
|
||||
disable_cpu_flags_ = LIBYUV_GET_FLAG(FLAGS_libyuv_flags);
|
||||
}
|
||||
const char* cpu_info = getenv("LIBYUV_CPU_INFO");
|
||||
if (cpu_info) {
|
||||
benchmark_cpu_info_ = atoi(cpu_flags); // NOLINT
|
||||
}
|
||||
if (LIBYUV_GET_FLAG(FLAGS_libyuv_cpu_info)) {
|
||||
benchmark_cpu_info_ = LIBYUV_GET_FLAG(FLAGS_libyuv_cpu_info);
|
||||
}
|
||||
disable_cpu_flags_ = TestCpuEnv(disable_cpu_flags_);
|
||||
benchmark_cpu_info_ = TestCpuEnv(benchmark_cpu_info_);
|
||||
libyuv::MaskCpuFlags(benchmark_cpu_info_);
|
||||
benchmark_pixels_div1280_ =
|
||||
static_cast<int>((static_cast<double>(Abs(benchmark_width_)) *
|
||||
static_cast<double>(Abs(benchmark_height_)) *
|
||||
static_cast<double>(benchmark_iterations_) +
|
||||
1279.0) /
|
||||
1280.0);
|
||||
}
|
||||
|
||||
LibYUVRotateTest::LibYUVRotateTest()
|
||||
: benchmark_iterations_(1),
|
||||
benchmark_width_(128),
|
||||
benchmark_height_(72),
|
||||
disable_cpu_flags_(1),
|
||||
benchmark_cpu_info_(-1) {
|
||||
const char* repeat = getenv("LIBYUV_REPEAT");
|
||||
if (repeat) {
|
||||
benchmark_iterations_ = atoi(repeat); // NOLINT
|
||||
}
|
||||
if (LIBYUV_GET_FLAG(FLAGS_libyuv_repeat)) {
|
||||
benchmark_iterations_ = LIBYUV_GET_FLAG(FLAGS_libyuv_repeat);
|
||||
}
|
||||
if (benchmark_iterations_ > 1) {
|
||||
benchmark_width_ = 1280;
|
||||
benchmark_height_ = 720;
|
||||
}
|
||||
const char* width = getenv("LIBYUV_WIDTH");
|
||||
if (width) {
|
||||
benchmark_width_ = atoi(width); // NOLINT
|
||||
}
|
||||
if (LIBYUV_GET_FLAG(FLAGS_libyuv_width)) {
|
||||
benchmark_width_ = LIBYUV_GET_FLAG(FLAGS_libyuv_width);
|
||||
}
|
||||
const char* height = getenv("LIBYUV_HEIGHT");
|
||||
if (height) {
|
||||
benchmark_height_ = atoi(height); // NOLINT
|
||||
}
|
||||
if (LIBYUV_GET_FLAG(FLAGS_libyuv_height)) {
|
||||
benchmark_height_ = LIBYUV_GET_FLAG(FLAGS_libyuv_height);
|
||||
}
|
||||
const char* cpu_flags = getenv("LIBYUV_FLAGS");
|
||||
if (cpu_flags) {
|
||||
disable_cpu_flags_ = atoi(cpu_flags); // NOLINT
|
||||
}
|
||||
if (LIBYUV_GET_FLAG(FLAGS_libyuv_flags)) {
|
||||
disable_cpu_flags_ = LIBYUV_GET_FLAG(FLAGS_libyuv_flags);
|
||||
}
|
||||
const char* cpu_info = getenv("LIBYUV_CPU_INFO");
|
||||
if (cpu_info) {
|
||||
benchmark_cpu_info_ = atoi(cpu_flags); // NOLINT
|
||||
}
|
||||
if (LIBYUV_GET_FLAG(FLAGS_libyuv_cpu_info)) {
|
||||
benchmark_cpu_info_ = LIBYUV_GET_FLAG(FLAGS_libyuv_cpu_info);
|
||||
}
|
||||
disable_cpu_flags_ = TestCpuEnv(disable_cpu_flags_);
|
||||
benchmark_cpu_info_ = TestCpuEnv(benchmark_cpu_info_);
|
||||
libyuv::MaskCpuFlags(benchmark_cpu_info_);
|
||||
benchmark_pixels_div1280_ =
|
||||
static_cast<int>((static_cast<double>(Abs(benchmark_width_)) *
|
||||
static_cast<double>(Abs(benchmark_height_)) *
|
||||
static_cast<double>(benchmark_iterations_) +
|
||||
1279.0) /
|
||||
1280.0);
|
||||
}
|
||||
|
||||
LibYUVPlanarTest::LibYUVPlanarTest()
|
||||
: benchmark_iterations_(1),
|
||||
benchmark_width_(128),
|
||||
benchmark_height_(72),
|
||||
disable_cpu_flags_(1),
|
||||
benchmark_cpu_info_(-1) {
|
||||
const char* repeat = getenv("LIBYUV_REPEAT");
|
||||
if (repeat) {
|
||||
benchmark_iterations_ = atoi(repeat); // NOLINT
|
||||
}
|
||||
if (LIBYUV_GET_FLAG(FLAGS_libyuv_repeat)) {
|
||||
benchmark_iterations_ = LIBYUV_GET_FLAG(FLAGS_libyuv_repeat);
|
||||
}
|
||||
if (benchmark_iterations_ > 1) {
|
||||
benchmark_width_ = 1280;
|
||||
benchmark_height_ = 720;
|
||||
}
|
||||
const char* width = getenv("LIBYUV_WIDTH");
|
||||
if (width) {
|
||||
benchmark_width_ = atoi(width); // NOLINT
|
||||
}
|
||||
if (LIBYUV_GET_FLAG(FLAGS_libyuv_width)) {
|
||||
benchmark_width_ = LIBYUV_GET_FLAG(FLAGS_libyuv_width);
|
||||
}
|
||||
const char* height = getenv("LIBYUV_HEIGHT");
|
||||
if (height) {
|
||||
benchmark_height_ = atoi(height); // NOLINT
|
||||
}
|
||||
if (LIBYUV_GET_FLAG(FLAGS_libyuv_height)) {
|
||||
benchmark_height_ = LIBYUV_GET_FLAG(FLAGS_libyuv_height);
|
||||
}
|
||||
const char* cpu_flags = getenv("LIBYUV_FLAGS");
|
||||
if (cpu_flags) {
|
||||
disable_cpu_flags_ = atoi(cpu_flags); // NOLINT
|
||||
}
|
||||
if (LIBYUV_GET_FLAG(FLAGS_libyuv_flags)) {
|
||||
disable_cpu_flags_ = LIBYUV_GET_FLAG(FLAGS_libyuv_flags);
|
||||
}
|
||||
const char* cpu_info = getenv("LIBYUV_CPU_INFO");
|
||||
if (cpu_info) {
|
||||
benchmark_cpu_info_ = atoi(cpu_flags); // NOLINT
|
||||
}
|
||||
if (LIBYUV_GET_FLAG(FLAGS_libyuv_cpu_info)) {
|
||||
benchmark_cpu_info_ = LIBYUV_GET_FLAG(FLAGS_libyuv_cpu_info);
|
||||
}
|
||||
disable_cpu_flags_ = TestCpuEnv(disable_cpu_flags_);
|
||||
benchmark_cpu_info_ = TestCpuEnv(benchmark_cpu_info_);
|
||||
libyuv::MaskCpuFlags(benchmark_cpu_info_);
|
||||
benchmark_pixels_div1280_ =
|
||||
static_cast<int>((static_cast<double>(Abs(benchmark_width_)) *
|
||||
static_cast<double>(Abs(benchmark_height_)) *
|
||||
static_cast<double>(benchmark_iterations_) +
|
||||
1279.0) /
|
||||
1280.0);
|
||||
}
|
||||
|
||||
LibYUVBaseTest::LibYUVBaseTest()
|
||||
: benchmark_iterations_(1),
|
||||
benchmark_width_(128),
|
||||
benchmark_height_(72),
|
||||
disable_cpu_flags_(1),
|
||||
benchmark_cpu_info_(-1) {
|
||||
const char* repeat = getenv("LIBYUV_REPEAT");
|
||||
if (repeat) {
|
||||
benchmark_iterations_ = atoi(repeat); // NOLINT
|
||||
}
|
||||
if (LIBYUV_GET_FLAG(FLAGS_libyuv_repeat)) {
|
||||
benchmark_iterations_ = LIBYUV_GET_FLAG(FLAGS_libyuv_repeat);
|
||||
}
|
||||
if (benchmark_iterations_ > 1) {
|
||||
benchmark_width_ = 1280;
|
||||
benchmark_height_ = 720;
|
||||
}
|
||||
const char* width = getenv("LIBYUV_WIDTH");
|
||||
if (width) {
|
||||
benchmark_width_ = atoi(width); // NOLINT
|
||||
}
|
||||
if (LIBYUV_GET_FLAG(FLAGS_libyuv_width)) {
|
||||
benchmark_width_ = LIBYUV_GET_FLAG(FLAGS_libyuv_width);
|
||||
}
|
||||
const char* height = getenv("LIBYUV_HEIGHT");
|
||||
if (height) {
|
||||
benchmark_height_ = atoi(height); // NOLINT
|
||||
}
|
||||
if (LIBYUV_GET_FLAG(FLAGS_libyuv_height)) {
|
||||
benchmark_height_ = LIBYUV_GET_FLAG(FLAGS_libyuv_height);
|
||||
}
|
||||
const char* cpu_flags = getenv("LIBYUV_FLAGS");
|
||||
if (cpu_flags) {
|
||||
disable_cpu_flags_ = atoi(cpu_flags); // NOLINT
|
||||
}
|
||||
if (LIBYUV_GET_FLAG(FLAGS_libyuv_flags)) {
|
||||
disable_cpu_flags_ = LIBYUV_GET_FLAG(FLAGS_libyuv_flags);
|
||||
}
|
||||
const char* cpu_info = getenv("LIBYUV_CPU_INFO");
|
||||
if (cpu_info) {
|
||||
benchmark_cpu_info_ = atoi(cpu_flags); // NOLINT
|
||||
}
|
||||
if (LIBYUV_GET_FLAG(FLAGS_libyuv_cpu_info)) {
|
||||
benchmark_cpu_info_ = LIBYUV_GET_FLAG(FLAGS_libyuv_cpu_info);
|
||||
}
|
||||
disable_cpu_flags_ = TestCpuEnv(disable_cpu_flags_);
|
||||
benchmark_cpu_info_ = TestCpuEnv(benchmark_cpu_info_);
|
||||
libyuv::MaskCpuFlags(benchmark_cpu_info_);
|
||||
benchmark_pixels_div1280_ =
|
||||
static_cast<int>((static_cast<double>(Abs(benchmark_width_)) *
|
||||
static_cast<double>(Abs(benchmark_height_)) *
|
||||
static_cast<double>(benchmark_iterations_) +
|
||||
1279.0) /
|
||||
1280.0);
|
||||
}
|
||||
|
||||
LibYUVCompareTest::LibYUVCompareTest()
|
||||
: benchmark_iterations_(1),
|
||||
benchmark_width_(128),
|
||||
benchmark_height_(72),
|
||||
disable_cpu_flags_(1),
|
||||
benchmark_cpu_info_(-1) {
|
||||
const char* repeat = getenv("LIBYUV_REPEAT");
|
||||
if (repeat) {
|
||||
benchmark_iterations_ = atoi(repeat); // NOLINT
|
||||
}
|
||||
if (LIBYUV_GET_FLAG(FLAGS_libyuv_repeat)) {
|
||||
benchmark_iterations_ = LIBYUV_GET_FLAG(FLAGS_libyuv_repeat);
|
||||
}
|
||||
if (benchmark_iterations_ > 1) {
|
||||
benchmark_width_ = 1280;
|
||||
benchmark_height_ = 720;
|
||||
}
|
||||
const char* width = getenv("LIBYUV_WIDTH");
|
||||
if (width) {
|
||||
benchmark_width_ = atoi(width); // NOLINT
|
||||
}
|
||||
if (LIBYUV_GET_FLAG(FLAGS_libyuv_width)) {
|
||||
benchmark_width_ = LIBYUV_GET_FLAG(FLAGS_libyuv_width);
|
||||
}
|
||||
const char* height = getenv("LIBYUV_HEIGHT");
|
||||
if (height) {
|
||||
benchmark_height_ = atoi(height); // NOLINT
|
||||
}
|
||||
if (LIBYUV_GET_FLAG(FLAGS_libyuv_height)) {
|
||||
benchmark_height_ = LIBYUV_GET_FLAG(FLAGS_libyuv_height);
|
||||
}
|
||||
const char* cpu_flags = getenv("LIBYUV_FLAGS");
|
||||
if (cpu_flags) {
|
||||
disable_cpu_flags_ = atoi(cpu_flags); // NOLINT
|
||||
}
|
||||
if (LIBYUV_GET_FLAG(FLAGS_libyuv_flags)) {
|
||||
disable_cpu_flags_ = LIBYUV_GET_FLAG(FLAGS_libyuv_flags);
|
||||
}
|
||||
const char* cpu_info = getenv("LIBYUV_CPU_INFO");
|
||||
if (cpu_info) {
|
||||
benchmark_cpu_info_ = atoi(cpu_flags); // NOLINT
|
||||
}
|
||||
if (LIBYUV_GET_FLAG(FLAGS_libyuv_cpu_info)) {
|
||||
benchmark_cpu_info_ = LIBYUV_GET_FLAG(FLAGS_libyuv_cpu_info);
|
||||
}
|
||||
disable_cpu_flags_ = TestCpuEnv(disable_cpu_flags_);
|
||||
benchmark_cpu_info_ = TestCpuEnv(benchmark_cpu_info_);
|
||||
libyuv::MaskCpuFlags(benchmark_cpu_info_);
|
||||
benchmark_pixels_div1280_ =
|
||||
static_cast<int>((static_cast<double>(Abs(benchmark_width_)) *
|
||||
static_cast<double>(Abs(benchmark_height_)) *
|
||||
static_cast<double>(benchmark_iterations_) +
|
||||
1279.0) /
|
||||
1280.0);
|
||||
}
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
::testing::InitGoogleTest(&argc, argv);
|
||||
#ifdef LIBYUV_USE_ABSL_FLAGS
|
||||
absl::ParseCommandLine(argc, argv);
|
||||
#endif
|
||||
return RUN_ALL_TESTS();
|
||||
}
|
||||
212
externals/libyuv/unit_test/unit_test.h
vendored
Normal file
212
externals/libyuv/unit_test/unit_test.h
vendored
Normal file
@@ -0,0 +1,212 @@
|
||||
/*
|
||||
* Copyright 2011 The LibYuv Project Authors. All rights reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#ifndef UNIT_TEST_UNIT_TEST_H_ // NOLINT
|
||||
#define UNIT_TEST_UNIT_TEST_H_
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <windows.h>
|
||||
#else
|
||||
#include <sys/resource.h>
|
||||
#include <sys/time.h>
|
||||
#endif
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include "libyuv/basic_types.h"
|
||||
|
||||
#ifndef SIMD_ALIGNED
|
||||
#if defined(_MSC_VER) && !defined(__CLR_VER)
|
||||
#define SIMD_ALIGNED(var) __declspec(align(16)) var
|
||||
#elif defined(__GNUC__) && !defined(__pnacl__)
|
||||
#define SIMD_ALIGNED(var) var __attribute__((aligned(16)))
|
||||
#else
|
||||
#define SIMD_ALIGNED(var) var
|
||||
#endif
|
||||
#endif
|
||||
|
||||
static __inline int Abs(int v) {
|
||||
return v >= 0 ? v : -v;
|
||||
}
|
||||
|
||||
static __inline float FAbs(float v) {
|
||||
return v >= 0 ? v : -v;
|
||||
}
|
||||
#define OFFBY 0
|
||||
|
||||
// Scaling uses 16.16 fixed point to step thru the source image, so a
|
||||
// maximum size of 32767.999 can be expressed. 32768 is valid because
|
||||
// the step is 1 beyond the image but not used.
|
||||
// Destination size is mainly constrained by valid scale step not the
|
||||
// absolute size, so it may be possible to relax the destination size
|
||||
// constraint.
|
||||
// Source size is unconstrained for most specialized scalers. e.g.
|
||||
// An image of 65536 scaled to half size would be valid. The test
|
||||
// could be relaxed for special scale factors.
|
||||
// If this test is removed, the scaling function should gracefully
|
||||
// fail with a return code. The test could be changed to know that
|
||||
// libyuv failed in a controlled way.
|
||||
|
||||
static const int kMaxWidth = 32768;
|
||||
static const int kMaxHeight = 32768;
|
||||
|
||||
static inline bool SizeValid(int src_width,
|
||||
int src_height,
|
||||
int dst_width,
|
||||
int dst_height) {
|
||||
if (src_width > kMaxWidth || src_height > kMaxHeight ||
|
||||
dst_width > kMaxWidth || dst_height > kMaxHeight) {
|
||||
printf("Warning - size too large to test. Skipping\n");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
#define align_buffer_page_end(var, size) \
|
||||
uint8_t* var##_mem = \
|
||||
reinterpret_cast<uint8_t*>(malloc(((size) + 4095 + 63) & ~4095)); \
|
||||
uint8_t* var = reinterpret_cast<uint8_t*>( \
|
||||
(intptr_t)(var##_mem + (((size) + 4095 + 63) & ~4095) - (size)) & ~63)
|
||||
|
||||
#define free_aligned_buffer_page_end(var) \
|
||||
free(var##_mem); \
|
||||
var = 0
|
||||
|
||||
#ifdef WIN32
|
||||
static inline double get_time() {
|
||||
LARGE_INTEGER t, f;
|
||||
QueryPerformanceCounter(&t);
|
||||
QueryPerformanceFrequency(&f);
|
||||
return static_cast<double>(t.QuadPart) / static_cast<double>(f.QuadPart);
|
||||
}
|
||||
#else
|
||||
static inline double get_time() {
|
||||
struct timeval t;
|
||||
struct timezone tzp;
|
||||
gettimeofday(&t, &tzp);
|
||||
return t.tv_sec + t.tv_usec * 1e-6;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef SIMD_ALIGNED
|
||||
#if defined(_MSC_VER) && !defined(__CLR_VER)
|
||||
#define SIMD_ALIGNED(var) __declspec(align(16)) var
|
||||
#elif defined(__GNUC__) && !defined(__pnacl__)
|
||||
#define SIMD_ALIGNED(var) var __attribute__((aligned(16)))
|
||||
#else
|
||||
#define SIMD_ALIGNED(var) var
|
||||
#endif
|
||||
#endif
|
||||
|
||||
extern unsigned int fastrand_seed;
|
||||
inline int fastrand() {
|
||||
fastrand_seed = fastrand_seed * 214013u + 2531011u;
|
||||
return static_cast<int>((fastrand_seed >> 16) & 0xffff);
|
||||
}
|
||||
|
||||
// ubsan fails if dst is unaligned unless we use uint8
|
||||
static inline void MemRandomize(uint8_t* dst, int64_t len) {
|
||||
int64_t i;
|
||||
for (i = 0; i < len - 1; i += 2) {
|
||||
int r = fastrand();
|
||||
dst[0] = static_cast<uint8_t>(r);
|
||||
dst[1] = static_cast<uint8_t>(r >> 8);
|
||||
dst += 2;
|
||||
}
|
||||
for (; i < len; ++i) {
|
||||
*dst++ = fastrand();
|
||||
}
|
||||
}
|
||||
|
||||
class LibYUVColorTest : public ::testing::Test {
|
||||
protected:
|
||||
LibYUVColorTest();
|
||||
|
||||
int benchmark_iterations_; // Default 1. Use 1000 for benchmarking.
|
||||
int benchmark_width_; // Default 1280. Use 640 for benchmarking VGA.
|
||||
int benchmark_height_; // Default 720. Use 360 for benchmarking VGA.
|
||||
int benchmark_pixels_div1280_; // Total pixels to benchmark / 1280.
|
||||
int disable_cpu_flags_; // Default 1. Use -1 for benchmarking.
|
||||
int benchmark_cpu_info_; // Default -1. Use 1 to disable SIMD.
|
||||
};
|
||||
|
||||
class LibYUVConvertTest : public ::testing::Test {
|
||||
protected:
|
||||
LibYUVConvertTest();
|
||||
|
||||
int benchmark_iterations_; // Default 1. Use 1000 for benchmarking.
|
||||
int benchmark_width_; // Default 1280. Use 640 for benchmarking VGA.
|
||||
int benchmark_height_; // Default 720. Use 360 for benchmarking VGA.
|
||||
int benchmark_pixels_div1280_; // Total pixels to benchmark / 1280.
|
||||
int disable_cpu_flags_; // Default 1. Use -1 for benchmarking.
|
||||
int benchmark_cpu_info_; // Default -1. Use 1 to disable SIMD.
|
||||
};
|
||||
|
||||
class LibYUVScaleTest : public ::testing::Test {
|
||||
protected:
|
||||
LibYUVScaleTest();
|
||||
|
||||
int benchmark_iterations_; // Default 1. Use 1000 for benchmarking.
|
||||
int benchmark_width_; // Default 1280. Use 640 for benchmarking VGA.
|
||||
int benchmark_height_; // Default 720. Use 360 for benchmarking VGA.
|
||||
int benchmark_pixels_div1280_; // Total pixels to benchmark / 1280.
|
||||
int disable_cpu_flags_; // Default 1. Use -1 for benchmarking.
|
||||
int benchmark_cpu_info_; // Default -1. Use 1 to disable SIMD.
|
||||
};
|
||||
|
||||
class LibYUVRotateTest : public ::testing::Test {
|
||||
protected:
|
||||
LibYUVRotateTest();
|
||||
|
||||
int benchmark_iterations_; // Default 1. Use 1000 for benchmarking.
|
||||
int benchmark_width_; // Default 1280. Use 640 for benchmarking VGA.
|
||||
int benchmark_height_; // Default 720. Use 360 for benchmarking VGA.
|
||||
int benchmark_pixels_div1280_; // Total pixels to benchmark / 1280.
|
||||
int disable_cpu_flags_; // Default 1. Use -1 for benchmarking.
|
||||
int benchmark_cpu_info_; // Default -1. Use 1 to disable SIMD.
|
||||
};
|
||||
|
||||
class LibYUVPlanarTest : public ::testing::Test {
|
||||
protected:
|
||||
LibYUVPlanarTest();
|
||||
|
||||
int benchmark_iterations_; // Default 1. Use 1000 for benchmarking.
|
||||
int benchmark_width_; // Default 1280. Use 640 for benchmarking VGA.
|
||||
int benchmark_height_; // Default 720. Use 360 for benchmarking VGA.
|
||||
int benchmark_pixels_div1280_; // Total pixels to benchmark / 1280.
|
||||
int disable_cpu_flags_; // Default 1. Use -1 for benchmarking.
|
||||
int benchmark_cpu_info_; // Default -1. Use 1 to disable SIMD.
|
||||
};
|
||||
|
||||
class LibYUVBaseTest : public ::testing::Test {
|
||||
protected:
|
||||
LibYUVBaseTest();
|
||||
|
||||
int benchmark_iterations_; // Default 1. Use 1000 for benchmarking.
|
||||
int benchmark_width_; // Default 1280. Use 640 for benchmarking VGA.
|
||||
int benchmark_height_; // Default 720. Use 360 for benchmarking VGA.
|
||||
int benchmark_pixels_div1280_; // Total pixels to benchmark / 1280.
|
||||
int disable_cpu_flags_; // Default 1. Use -1 for benchmarking.
|
||||
int benchmark_cpu_info_; // Default -1. Use 1 to disable SIMD.
|
||||
};
|
||||
|
||||
class LibYUVCompareTest : public ::testing::Test {
|
||||
protected:
|
||||
LibYUVCompareTest();
|
||||
|
||||
int benchmark_iterations_; // Default 1. Use 1000 for benchmarking.
|
||||
int benchmark_width_; // Default 1280. Use 640 for benchmarking VGA.
|
||||
int benchmark_height_; // Default 720. Use 360 for benchmarking VGA.
|
||||
int benchmark_pixels_div1280_; // Total pixels to benchmark / 1280.
|
||||
int disable_cpu_flags_; // Default 1. Use -1 for benchmarking.
|
||||
int benchmark_cpu_info_; // Default -1. Use 1 to disable SIMD.
|
||||
};
|
||||
|
||||
#endif // UNIT_TEST_UNIT_TEST_H_ NOLINT
|
||||
112
externals/libyuv/unit_test/video_common_test.cc
vendored
Normal file
112
externals/libyuv/unit_test/video_common_test.cc
vendored
Normal file
@@ -0,0 +1,112 @@
|
||||
/*
|
||||
* Copyright 2012 The LibYuv Project Authors. All rights reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "../unit_test/unit_test.h"
|
||||
#include "libyuv/video_common.h"
|
||||
|
||||
namespace libyuv {
|
||||
|
||||
// Tests FourCC codes in video common, which are used for ConvertToI420().
|
||||
|
||||
static bool TestValidChar(uint32_t onecc) {
|
||||
return (onecc >= '0' && onecc <= '9') || (onecc >= 'A' && onecc <= 'Z') ||
|
||||
(onecc >= 'a' && onecc <= 'z') || (onecc == ' ') || (onecc == 0xff);
|
||||
}
|
||||
|
||||
static bool TestValidFourCC(uint32_t fourcc, int bpp) {
|
||||
if (!TestValidChar(fourcc & 0xff) || !TestValidChar((fourcc >> 8) & 0xff) ||
|
||||
!TestValidChar((fourcc >> 16) & 0xff) ||
|
||||
!TestValidChar((fourcc >> 24) & 0xff)) {
|
||||
return false;
|
||||
}
|
||||
if (bpp < 0 || bpp > 64) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
TEST_F(LibYUVBaseTest, TestCanonicalFourCC) {
|
||||
EXPECT_EQ(static_cast<uint32_t>(FOURCC_I420), CanonicalFourCC(FOURCC_IYUV));
|
||||
EXPECT_EQ(static_cast<uint32_t>(FOURCC_I420), CanonicalFourCC(FOURCC_YU12));
|
||||
EXPECT_EQ(static_cast<uint32_t>(FOURCC_I422), CanonicalFourCC(FOURCC_YU16));
|
||||
EXPECT_EQ(static_cast<uint32_t>(FOURCC_I444), CanonicalFourCC(FOURCC_YU24));
|
||||
EXPECT_EQ(static_cast<uint32_t>(FOURCC_YUY2), CanonicalFourCC(FOURCC_YUYV));
|
||||
EXPECT_EQ(static_cast<uint32_t>(FOURCC_YUY2), CanonicalFourCC(FOURCC_YUVS));
|
||||
EXPECT_EQ(static_cast<uint32_t>(FOURCC_UYVY), CanonicalFourCC(FOURCC_HDYC));
|
||||
EXPECT_EQ(static_cast<uint32_t>(FOURCC_UYVY), CanonicalFourCC(FOURCC_2VUY));
|
||||
EXPECT_EQ(static_cast<uint32_t>(FOURCC_MJPG), CanonicalFourCC(FOURCC_JPEG));
|
||||
EXPECT_EQ(static_cast<uint32_t>(FOURCC_MJPG), CanonicalFourCC(FOURCC_DMB1));
|
||||
EXPECT_EQ(static_cast<uint32_t>(FOURCC_RAW), CanonicalFourCC(FOURCC_RGB3));
|
||||
EXPECT_EQ(static_cast<uint32_t>(FOURCC_24BG), CanonicalFourCC(FOURCC_BGR3));
|
||||
EXPECT_EQ(static_cast<uint32_t>(FOURCC_BGRA), CanonicalFourCC(FOURCC_CM32));
|
||||
EXPECT_EQ(static_cast<uint32_t>(FOURCC_RAW), CanonicalFourCC(FOURCC_CM24));
|
||||
EXPECT_EQ(static_cast<uint32_t>(FOURCC_RGBO), CanonicalFourCC(FOURCC_L555));
|
||||
EXPECT_EQ(static_cast<uint32_t>(FOURCC_RGBP), CanonicalFourCC(FOURCC_L565));
|
||||
EXPECT_EQ(static_cast<uint32_t>(FOURCC_RGBO), CanonicalFourCC(FOURCC_5551));
|
||||
}
|
||||
|
||||
TEST_F(LibYUVBaseTest, TestFourCC) {
|
||||
EXPECT_TRUE(TestValidFourCC(FOURCC_I420, FOURCC_BPP_I420));
|
||||
EXPECT_TRUE(TestValidFourCC(FOURCC_I420, FOURCC_BPP_I420));
|
||||
EXPECT_TRUE(TestValidFourCC(FOURCC_I422, FOURCC_BPP_I422));
|
||||
EXPECT_TRUE(TestValidFourCC(FOURCC_I444, FOURCC_BPP_I444));
|
||||
EXPECT_TRUE(TestValidFourCC(FOURCC_I400, FOURCC_BPP_I400));
|
||||
EXPECT_TRUE(TestValidFourCC(FOURCC_NV21, FOURCC_BPP_NV21));
|
||||
EXPECT_TRUE(TestValidFourCC(FOURCC_NV12, FOURCC_BPP_NV12));
|
||||
EXPECT_TRUE(TestValidFourCC(FOURCC_YUY2, FOURCC_BPP_YUY2));
|
||||
EXPECT_TRUE(TestValidFourCC(FOURCC_UYVY, FOURCC_BPP_UYVY));
|
||||
EXPECT_TRUE(TestValidFourCC(FOURCC_M420, FOURCC_BPP_M420)); // deprecated.
|
||||
EXPECT_TRUE(TestValidFourCC(FOURCC_Q420, FOURCC_BPP_Q420)); // deprecated.
|
||||
EXPECT_TRUE(TestValidFourCC(FOURCC_ARGB, FOURCC_BPP_ARGB));
|
||||
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_AR64, FOURCC_BPP_AR64));
|
||||
EXPECT_TRUE(TestValidFourCC(FOURCC_AB64, FOURCC_BPP_AB64));
|
||||
EXPECT_TRUE(TestValidFourCC(FOURCC_24BG, FOURCC_BPP_24BG));
|
||||
EXPECT_TRUE(TestValidFourCC(FOURCC_RAW, FOURCC_BPP_RAW));
|
||||
EXPECT_TRUE(TestValidFourCC(FOURCC_RGBA, FOURCC_BPP_RGBA));
|
||||
EXPECT_TRUE(TestValidFourCC(FOURCC_RGBP, FOURCC_BPP_RGBP));
|
||||
EXPECT_TRUE(TestValidFourCC(FOURCC_RGBO, FOURCC_BPP_RGBO));
|
||||
EXPECT_TRUE(TestValidFourCC(FOURCC_R444, FOURCC_BPP_R444));
|
||||
EXPECT_TRUE(TestValidFourCC(FOURCC_H420, FOURCC_BPP_H420));
|
||||
EXPECT_TRUE(TestValidFourCC(FOURCC_H422, FOURCC_BPP_H422));
|
||||
EXPECT_TRUE(TestValidFourCC(FOURCC_H010, FOURCC_BPP_H010));
|
||||
EXPECT_TRUE(TestValidFourCC(FOURCC_H210, FOURCC_BPP_H210));
|
||||
EXPECT_TRUE(TestValidFourCC(FOURCC_I010, FOURCC_BPP_I010));
|
||||
EXPECT_TRUE(TestValidFourCC(FOURCC_I210, FOURCC_BPP_I210));
|
||||
EXPECT_TRUE(TestValidFourCC(FOURCC_P010, FOURCC_BPP_P010));
|
||||
EXPECT_TRUE(TestValidFourCC(FOURCC_P210, FOURCC_BPP_P210));
|
||||
EXPECT_TRUE(TestValidFourCC(FOURCC_MJPG, FOURCC_BPP_MJPG));
|
||||
EXPECT_TRUE(TestValidFourCC(FOURCC_YV12, FOURCC_BPP_YV12));
|
||||
EXPECT_TRUE(TestValidFourCC(FOURCC_YV16, FOURCC_BPP_YV16));
|
||||
EXPECT_TRUE(TestValidFourCC(FOURCC_YV24, FOURCC_BPP_YV24));
|
||||
EXPECT_TRUE(TestValidFourCC(FOURCC_YU12, FOURCC_BPP_YU12));
|
||||
EXPECT_TRUE(TestValidFourCC(FOURCC_IYUV, FOURCC_BPP_IYUV));
|
||||
EXPECT_TRUE(TestValidFourCC(FOURCC_YU16, FOURCC_BPP_YU16));
|
||||
EXPECT_TRUE(TestValidFourCC(FOURCC_YU24, FOURCC_BPP_YU24));
|
||||
EXPECT_TRUE(TestValidFourCC(FOURCC_YUYV, FOURCC_BPP_YUYV));
|
||||
EXPECT_TRUE(TestValidFourCC(FOURCC_YUVS, FOURCC_BPP_YUVS));
|
||||
EXPECT_TRUE(TestValidFourCC(FOURCC_HDYC, FOURCC_BPP_HDYC));
|
||||
EXPECT_TRUE(TestValidFourCC(FOURCC_2VUY, FOURCC_BPP_2VUY));
|
||||
EXPECT_TRUE(TestValidFourCC(FOURCC_JPEG, FOURCC_BPP_JPEG));
|
||||
EXPECT_TRUE(TestValidFourCC(FOURCC_DMB1, FOURCC_BPP_DMB1));
|
||||
EXPECT_TRUE(TestValidFourCC(FOURCC_BA81, FOURCC_BPP_BA81));
|
||||
EXPECT_TRUE(TestValidFourCC(FOURCC_RGB3, FOURCC_BPP_RGB3));
|
||||
EXPECT_TRUE(TestValidFourCC(FOURCC_BGR3, FOURCC_BPP_BGR3));
|
||||
EXPECT_TRUE(TestValidFourCC(FOURCC_H264, FOURCC_BPP_H264));
|
||||
EXPECT_TRUE(TestValidFourCC(FOURCC_ANY, FOURCC_BPP_ANY));
|
||||
}
|
||||
|
||||
} // namespace libyuv
|
||||
Reference in New Issue
Block a user