diff --git a/include/libyuv/compare.h b/include/libyuv/compare.h index 5dfac7c86..08b2bb2ec 100644 --- a/include/libyuv/compare.h +++ b/include/libyuv/compare.h @@ -22,6 +22,11 @@ extern "C" { LIBYUV_API uint32 HashDjb2(const uint8* src, uint64 count, uint32 seed); +// Scan an opaque argb image and return fourcc based on alpha offset. +// Returns FOURCC_ARGB, FOURCC_BGRA, or 0 if unknown. +LIBYUV_API +uint32 ARGBDetect(const uint8* argb, int stride_argb, int width, int height); + // Sum Square Error - used to compute Mean Square Error or PSNR. LIBYUV_API uint64 ComputeSumSquareError(const uint8* src_a, diff --git a/source/compare.cc b/source/compare.cc index 255e77276..759223a87 100644 --- a/source/compare.cc +++ b/source/compare.cc @@ -19,6 +19,7 @@ #include "libyuv/basic_types.h" #include "libyuv/cpu_id.h" #include "libyuv/row.h" +#include "libyuv/video_common.h" #ifdef __cplusplus namespace libyuv { @@ -78,6 +79,40 @@ uint32 HashDjb2(const uint8* src, uint64 count, uint32 seed) { return seed; } +static uint32 ARGBDetectRow_C(const uint8* argb, int width) { + int x; + for (x = 0; x < width; ++x) { + if (argb[0] != 255) { // First byte is not Alpha of 255, so not ARGB. + return FOURCC_BGRA; + } + if (argb[3] != 255) { // 4th byte is not Alpha of 255, so not BGRA. + return FOURCC_ARGB; + } + argb += 4; + } + return 0; +} + +// Scan an opaque argb image and return fourcc based on alpha offset. +// Returns FOURCC_ARGB, FOURCC_BGRA, or 0 if unknown. +LIBYUV_API +uint32 ARGBDetect(const uint8* argb, int stride_argb, int width, int height) { + uint32 fourcc = 0; + int h; + + // Coalesce rows. + if (stride_argb == width * 4) { + width *= height; + height = 1; + stride_argb = 0; + } + for (h = 0; h < height && fourcc == 0; ++h) { + fourcc = ARGBDetectRow_C(argb, width); + argb += stride_argb; + } + return fourcc; +} + uint32 SumSquareError_C(const uint8* src_a, const uint8* src_b, int count); #if !defined(LIBYUV_DISABLE_NEON) && \ (defined(__ARM_NEON__) || defined(LIBYUV_NEON) || defined(__aarch64__)) diff --git a/unit_test/compare_test.cc b/unit_test/compare_test.cc index 464e2559e..15215fe7c 100644 --- a/unit_test/compare_test.cc +++ b/unit_test/compare_test.cc @@ -17,6 +17,7 @@ #include "libyuv/compare.h" #include "libyuv/cpu_id.h" #include "libyuv/row.h" +#include "libyuv/video_common.h" namespace libyuv { @@ -146,6 +147,34 @@ TEST_F(libyuvTest, BenchmarkDjb2_Unaligned) { free_aligned_buffer_64(src_a); } +TEST_F(libyuvTest, BenchmarkARGBDetect_Opt) { + uint32 fourcc; + const int kMaxTest = benchmark_width_ * benchmark_height_ * 4; + align_buffer_64(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(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(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(0, fourcc); + + free_aligned_buffer_64(src_a); +} + TEST_F(libyuvTest, BenchmarkSumSquareError_Opt) { const int kMaxWidth = 4096 * 3; align_buffer_64(src_a, kMaxWidth);