diff --git a/webrtc/base/BUILD.gn b/webrtc/base/BUILD.gn index 583cf68813..1c8997ef55 100644 --- a/webrtc/base/BUILD.gn +++ b/webrtc/base/BUILD.gn @@ -670,6 +670,7 @@ if (rtc_include_tests) { deps = [ ":rtc_base", "../test:field_trial", + "../test:test_support", ] public_deps = [ "//testing/gtest", diff --git a/webrtc/base/base_tests.gyp b/webrtc/base/base_tests.gyp index 003a1dbf87..e1d5bc0496 100644 --- a/webrtc/base/base_tests.gyp +++ b/webrtc/base/base_tests.gyp @@ -33,6 +33,7 @@ 'base.gyp:rtc_base', '<(DEPTH)/testing/gtest.gyp:gtest', '<(webrtc_root)/test/test.gyp:field_trial', + '<(webrtc_root)/test/test.gyp:test_support', ], 'direct_dependent_settings': { 'defines': [ diff --git a/webrtc/base/testutils.h b/webrtc/base/testutils.h index c9d5a317e2..34b760618e 100644 --- a/webrtc/base/testutils.h +++ b/webrtc/base/testutils.h @@ -419,49 +419,6 @@ class SocketTestServer : public sigslot::has_slots<> { std::vector clients_; }; -/////////////////////////////////////////////////////////////////////////////// -// Generic Utilities -/////////////////////////////////////////////////////////////////////////////// - -inline bool ReadFile(const char* filename, std::string* contents) { - FILE* fp = fopen(filename, "rb"); - if (!fp) - return false; - char buffer[1024*64]; - size_t read; - contents->clear(); - while ((read = fread(buffer, 1, sizeof(buffer), fp))) { - contents->append(buffer, read); - } - bool success = (0 != feof(fp)); - fclose(fp); - return success; -} - -// Look in parent dir for parallel directory. -inline rtc::Pathname GetSiblingDirectory( - const std::string& parallel_dir) { - rtc::Pathname path = rtc::Filesystem::GetCurrentDirectory(); - while (!path.empty()) { - rtc::Pathname potential_parallel_dir = path; - potential_parallel_dir.AppendFolder(parallel_dir); - if (rtc::Filesystem::IsFolder(potential_parallel_dir)) { - return potential_parallel_dir; - } - - path.SetFolder(path.parent_folder()); - } - return path; -} - -inline rtc::Pathname GetGoogle3Directory() { - return GetSiblingDirectory("google3"); -} - -inline rtc::Pathname GetTalkDirectory() { - return GetSiblingDirectory("talk"); -} - /////////////////////////////////////////////////////////////////////////////// // Unittest predicates which are similar to STREQ, but for raw memory /////////////////////////////////////////////////////////////////////////////// @@ -504,25 +461,6 @@ inline AssertionResult CmpHelperMemEq(const char* expected_expression, return AssertionFailure(msg); } -inline AssertionResult CmpHelperFileEq(const char* expected_expression, - const char* expected_length_expression, - const char* actual_filename, - const void* expected, - size_t expected_length, - const char* filename) -{ - std::string contents; - if (!ReadFile(filename, &contents)) { - Message msg; - msg << "File '" << filename << "' could not be read."; - return AssertionFailure(msg); - } - return CmpHelperMemEq(expected_expression, expected_length_expression, - actual_filename, "", - expected, expected_length, - contents.c_str(), contents.size()); -} - #define EXPECT_MEMEQ(expected, expected_length, actual, actual_length) \ EXPECT_PRED_FORMAT4(::testing::CmpHelperMemEq, expected, expected_length, \ actual, actual_length) @@ -531,14 +469,6 @@ inline AssertionResult CmpHelperFileEq(const char* expected_expression, ASSERT_PRED_FORMAT4(::testing::CmpHelperMemEq, expected, expected_length, \ actual, actual_length) -#define EXPECT_FILEEQ(expected, expected_length, filename) \ - EXPECT_PRED_FORMAT3(::testing::CmpHelperFileEq, expected, expected_length, \ - filename) - -#define ASSERT_FILEEQ(expected, expected_length, filename) \ - ASSERT_PRED_FORMAT3(::testing::CmpHelperFileEq, expected, expected_length, \ - filename) - /////////////////////////////////////////////////////////////////////////////// // Helpers for initializing constant memory with integers in a particular byte // order diff --git a/webrtc/base/unittest_main.cc b/webrtc/base/unittest_main.cc index 167570d449..66a9a73309 100644 --- a/webrtc/base/unittest_main.cc +++ b/webrtc/base/unittest_main.cc @@ -20,6 +20,7 @@ #include "webrtc/base/logging.h" #include "webrtc/base/ssladapter.h" #include "webrtc/test/field_trial.h" +#include "webrtc/test/testsupport/fileutils.h" DEFINE_bool(help, false, "prints this message"); DEFINE_string(log, "", "logging options to use"); @@ -68,6 +69,7 @@ int main(int argc, char** argv) { return 0; } + webrtc::test::SetExecutablePath(argv[0]); webrtc::test::InitFieldTrialsFromString(FLAG_force_fieldtrials); #if defined(WEBRTC_WIN) diff --git a/webrtc/media/base/executablehelpers.h b/webrtc/media/base/executablehelpers.h deleted file mode 100644 index 25ce41bcc6..0000000000 --- a/webrtc/media/base/executablehelpers.h +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright (c) 2014 The WebRTC 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 WEBRTC_MEDIA_BASE_EXECUTABLEHELPERS_H_ -#define WEBRTC_MEDIA_BASE_EXECUTABLEHELPERS_H_ - -#if defined(WEBRTC_MAC) && !defined(WEBRTC_IOS) -#include -#endif - -#include - -#include "webrtc/base/logging.h" -#include "webrtc/base/pathutils.h" - -namespace rtc { - -// Returns the path to the running executable or an empty path. -// TODO(thorcarpenter): Consolidate with FluteClient::get_executable_dir. -inline Pathname GetExecutablePath() { - const int32_t kMaxExePathSize = 255; -#ifdef WIN32 - TCHAR exe_path_buffer[kMaxExePathSize]; - DWORD copied_length = GetModuleFileName(NULL, // NULL = Current process - exe_path_buffer, kMaxExePathSize); - if (0 == copied_length) { - LOG(LS_ERROR) << "Copied length is zero"; - return rtc::Pathname(); - } - if (kMaxExePathSize == copied_length) { - LOG(LS_ERROR) << "Buffer too small"; - return rtc::Pathname(); - } -#ifdef UNICODE - std::wstring wdir(exe_path_buffer); - std::string dir_tmp(wdir.begin(), wdir.end()); - rtc::Pathname path(dir_tmp); -#else // UNICODE - rtc::Pathname path(exe_path_buffer); -#endif // UNICODE -#elif (defined(WEBRTC_MAC) && !defined(WEBRTC_IOS)) || defined(WEBRTC_LINUX) - char exe_path_buffer[kMaxExePathSize]; -#if defined(WEBRTC_MAC) && !defined(WEBRTC_IOS) - uint32_t copied_length = kMaxExePathSize - 1; - if (_NSGetExecutablePath(exe_path_buffer, &copied_length) == -1) { - LOG(LS_ERROR) << "Buffer too small"; - return rtc::Pathname(); - } -#elif defined WEBRTC_LINUX - int32_t copied_length = kMaxExePathSize - 1; - const char* kProcExeFmt = "/proc/%d/exe"; - char proc_exe_link[40]; - snprintf(proc_exe_link, sizeof(proc_exe_link), kProcExeFmt, getpid()); - copied_length = readlink(proc_exe_link, exe_path_buffer, copied_length); - if (copied_length == -1) { - LOG_ERR(LS_ERROR) << "Error reading link " << proc_exe_link; - return rtc::Pathname(); - } - if (copied_length == kMaxExePathSize - 1) { - LOG(LS_ERROR) << "Probably truncated result when reading link " - << proc_exe_link; - return rtc::Pathname(); - } - exe_path_buffer[copied_length] = '\0'; -#endif // WEBRTC_LINUX - rtc::Pathname path(exe_path_buffer); -#else // Android || iOS - rtc::Pathname path; -#endif // Mac || Linux - return path; -} - -} // namespace rtc - -#endif // WEBRTC_MEDIA_BASE_EXECUTABLEHELPERS_H_ - diff --git a/webrtc/media/base/testutils.cc b/webrtc/media/base/testutils.cc index cbc1ac2df6..9e2d174f61 100644 --- a/webrtc/media/base/testutils.cc +++ b/webrtc/media/base/testutils.cc @@ -21,7 +21,6 @@ #include "webrtc/base/stream.h" #include "webrtc/base/stringutils.h" #include "webrtc/base/testutils.h" -#include "webrtc/media/base/executablehelpers.h" #include "webrtc/media/base/rtpdump.h" #include "webrtc/media/base/videocapturer.h" #include "webrtc/media/base/videoframe.h" @@ -242,70 +241,6 @@ void VideoCapturerListener::OnFrameCaptured(VideoCapturer* capturer, } } -// Returns the absolute path to a file in the resources/ directory. -std::string GetTestFilePath(const std::string& filename) { - // Locate test data directory. -#ifdef ENABLE_WEBRTC - rtc::Pathname path = rtc::GetExecutablePath(); - EXPECT_FALSE(path.empty()); - path.AppendPathname("../../resources/"); -#else - rtc::Pathname path = testing::GetTalkDirectory(); - EXPECT_FALSE(path.empty()); // must be run from inside "talk" -#endif - path.AppendFolder("media/"); - path.SetFilename(filename); - return path.pathname(); -} - -// Loads the image with the specified prefix and size into |out|. -bool LoadPlanarYuvTestImage(const std::string& prefix, - int width, - int height, - uint8_t* out) { - std::stringstream ss; - ss << prefix << "." << width << "x" << height << "_P420.yuv"; - - std::unique_ptr stream( - rtc::Filesystem::OpenFile(rtc::Pathname( - GetTestFilePath(ss.str())), "rb")); - if (!stream) { - return false; - } - - rtc::StreamResult res = - stream->ReadAll(out, I420_SIZE(width, height), NULL, NULL); - return (res == rtc::SR_SUCCESS); -} - -// Dumps the YUV image out to a file, for visual inspection. -// PYUV tool can be used to view dump files. -void DumpPlanarYuvTestImage(const std::string& prefix, - const uint8_t* img, - int w, - int h) { - rtc::FileStream fs; - char filename[256]; - rtc::sprintfn(filename, sizeof(filename), "%s.%dx%d_P420.yuv", - prefix.c_str(), w, h); - fs.Open(filename, "wb", NULL); - fs.Write(img, I420_SIZE(w, h), NULL, NULL); -} - -// Dumps the ARGB image out to a file, for visual inspection. -// ffplay tool can be used to view dump files. -void DumpPlanarArgbTestImage(const std::string& prefix, - const uint8_t* img, - int w, - int h) { - rtc::FileStream fs; - char filename[256]; - rtc::sprintfn(filename, sizeof(filename), "%s.%dx%d_ARGB.raw", - prefix.c_str(), w, h); - fs.Open(filename, "wb", NULL); - fs.Write(img, ARGB_SIZE(w, h), NULL, NULL); -} - cricket::StreamParams CreateSimStreamParams( const std::string& cname, const std::vector& ssrcs) { diff --git a/webrtc/media/base/testutils.h b/webrtc/media/base/testutils.h index b73d8f67f8..2e338d95ae 100644 --- a/webrtc/media/base/testutils.h +++ b/webrtc/media/base/testutils.h @@ -167,42 +167,6 @@ class VideoMediaErrorCatcher : public sigslot::has_slots<> { VideoMediaChannel::Error error_; }; -// Returns the absolute path to a file in the testdata/ directory. -std::string GetTestFilePath(const std::string& filename); - -// PSNR formula: psnr = 10 * log10 (Peak Signal^2 / mse) -// sse is set to a small number for identical frames or sse == 0 -static inline double ComputePSNR(double sse, double count) { - return libyuv::SumSquareErrorToPsnr(static_cast(sse), - static_cast(count)); -} - -static inline double ComputeSumSquareError(const uint8_t* org, - const uint8_t* rec, - int size) { - return static_cast(libyuv::ComputeSumSquareError(org, rec, size)); -} - -// Loads the image with the specified prefix and size into |out|. -bool LoadPlanarYuvTestImage(const std::string& prefix, - int width, - int height, - uint8_t* out); - -// Dumps the YUV image out to a file, for visual inspection. -// PYUV tool can be used to view dump files. -void DumpPlanarYuvTestImage(const std::string& prefix, - const uint8_t* img, - int w, - int h); - -// Dumps the ARGB image out to a file, for visual inspection. -// ffplay tool can be used to view dump files. -void DumpPlanarArgbTestImage(const std::string& prefix, - const uint8_t* img, - int w, - int h); - // Checks whether |codecs| contains |codec|; checks using Codec::Matches(). template bool ContainsMatchingCodec(const std::vector& codecs, const C& codec) { diff --git a/webrtc/media/base/videoframe_unittest.h b/webrtc/media/base/videoframe_unittest.h index a79492d106..39985617c5 100644 --- a/webrtc/media/base/videoframe_unittest.h +++ b/webrtc/media/base/videoframe_unittest.h @@ -27,6 +27,7 @@ #include "webrtc/media/base/testutils.h" #include "webrtc/media/base/videocommon.h" #include "webrtc/media/base/videoframe.h" +#include "webrtc/test/testsupport/fileutils.h" #if defined(_MSC_VER) #define ALIGN16(var) __declspec(align(16)) var @@ -34,12 +35,14 @@ #define ALIGN16(var) var __attribute__((aligned(16))) #endif -#define kImageFilename "faces.1280x720_P420.yuv" -#define kJpeg420Filename "faces_I420.jpg" -#define kJpeg422Filename "faces_I422.jpg" -#define kJpeg444Filename "faces_I444.jpg" -#define kJpeg411Filename "faces_I411.jpg" -#define kJpeg400Filename "faces_I400.jpg" +#define kImageFilename "media/faces.1280x720_P420" +#define kYuvExtension "yuv" +#define kJpeg420Filename "media/faces_I420" +#define kJpeg422Filename "media/faces_I422" +#define kJpeg444Filename "media/faces_I444" +#define kJpeg411Filename "media/faces_I411" +#define kJpeg400Filename "media/faces_I400" +#define kJpegExtension "jpg" // Generic test class for testing various video frame implementations. template @@ -60,8 +63,9 @@ class VideoFrameTest : public testing::Test { bool LoadFrameNoRepeat(T* frame) { int save_repeat = repeat_; // This LoadFrame disables repeat. repeat_ = 1; - bool success = LoadFrame(kImageFilename, cricket::FOURCC_I420, - kWidth, kHeight, frame); + bool success = LoadFrame(LoadSample(kImageFilename, kYuvExtension).get(), + cricket::FOURCC_I420, + kWidth, kHeight, frame); repeat_ = save_repeat; return success; } @@ -141,8 +145,9 @@ class VideoFrameTest : public testing::Test { return ret; } - rtc::MemoryStream* LoadSample(const std::string& filename) { - rtc::Pathname path(cricket::GetTestFilePath(filename)); + std::unique_ptr LoadSample(const std::string& filename, + const std::string& extension) { + rtc::Pathname path(webrtc::test::ResourcePath(filename, extension)); std::unique_ptr fs( rtc::Filesystem::OpenFile(path, "rb")); if (!fs.get()) { @@ -161,7 +166,7 @@ class VideoFrameTest : public testing::Test { return NULL; } - return ms.release(); + return ms; } bool DumpSample(const std::string& filename, const void* buffer, int size) { @@ -181,9 +186,9 @@ class VideoFrameTest : public testing::Test { // The pattern is { { green, orange }, { blue, purple } } // There is also a gradient within each square to ensure that the luma // values are handled properly. - rtc::MemoryStream* CreateYuv422Sample(uint32_t fourcc, - uint32_t width, - uint32_t height) { + std::unique_ptr CreateYuv422Sample(uint32_t fourcc, + uint32_t width, + uint32_t height) { int y1_pos, y2_pos, u_pos, v_pos; if (!GetYuv422Packing(fourcc, &y1_pos, &y2_pos, &u_pos, &v_pos)) { return NULL; @@ -206,13 +211,13 @@ class VideoFrameTest : public testing::Test { ms->Write(quad, sizeof(quad), NULL, NULL); } } - return ms.release(); + return ms; } // Create a test image for YUV 420 formats with 12 bits per pixel. - rtc::MemoryStream* CreateYuvSample(uint32_t width, - uint32_t height, - uint32_t bpp) { + std::unique_ptr CreateYuvSample(uint32_t width, + uint32_t height, + uint32_t bpp) { std::unique_ptr ms( new rtc::MemoryStream); if (!ms->ReserveSize(width * height * bpp / 8)) { @@ -223,12 +228,12 @@ class VideoFrameTest : public testing::Test { uint8_t value = ((i / 63) & 1) ? 192 : 64; ms->Write(&value, sizeof(value), NULL, NULL); } - return ms.release(); + return ms; } - rtc::MemoryStream* CreateRgbSample(uint32_t fourcc, - uint32_t width, - uint32_t height) { + std::unique_ptr CreateRgbSample(uint32_t fourcc, + uint32_t width, + uint32_t height) { int r_pos, g_pos, b_pos, bytes; if (!GetRgbPacking(fourcc, &r_pos, &g_pos, &b_pos, &bytes)) { return NULL; @@ -249,7 +254,7 @@ class VideoFrameTest : public testing::Test { ms->Write(rgb, bytes, NULL, NULL); } } - return ms.release(); + return ms; } // Simple conversion routines to verify the optimized VideoFrame routines. @@ -1070,7 +1075,8 @@ class VideoFrameTest : public testing::Test { void ConstructI420CropHorizontal() { T frame1, frame2; ASSERT_TRUE(LoadFrameNoRepeat(&frame1)); - ASSERT_TRUE(LoadFrame(kImageFilename, cricket::FOURCC_I420, kWidth, kHeight, + ASSERT_TRUE(LoadFrame(kImageFilename, kYuvExtension, + cricket::FOURCC_I420, kWidth, kHeight, kWidth * 3 / 4, kHeight, webrtc::kVideoRotation_0, &frame2)); EXPECT_TRUE(IsEqualWithCrop(frame2, frame1, kWidth / 8, 0, 0)); @@ -1109,7 +1115,8 @@ class VideoFrameTest : public testing::Test { void ConstructI420CropVertical() { T frame1, frame2; ASSERT_TRUE(LoadFrameNoRepeat(&frame1)); - ASSERT_TRUE(LoadFrame(kImageFilename, cricket::FOURCC_I420, kWidth, kHeight, + ASSERT_TRUE(LoadFrame(LoadSample(kImageFilename, kYuvExtension).get(), + cricket::FOURCC_I420, kWidth, kHeight, kWidth, kHeight * 3 / 4, webrtc::kVideoRotation_0, &frame2)); EXPECT_TRUE(IsEqualWithCrop(frame2, frame1, 0, kHeight / 8, 0)); @@ -1118,11 +1125,14 @@ class VideoFrameTest : public testing::Test { // Test constructing an image from I420 synonymous formats. void ConstructI420Aliases() { T frame1, frame2, frame3; - ASSERT_TRUE(LoadFrame(kImageFilename, cricket::FOURCC_I420, kWidth, kHeight, + ASSERT_TRUE(LoadFrame(LoadSample(kImageFilename, kYuvExtension), + cricket::FOURCC_I420, kWidth, kHeight, &frame1)); - ASSERT_TRUE(LoadFrame(kImageFilename, cricket::FOURCC_IYUV, kWidth, kHeight, + ASSERT_TRUE(LoadFrame(kImageFilename, kYuvExtension, + cricket::FOURCC_IYUV, kWidth, kHeight, &frame2)); - ASSERT_TRUE(LoadFrame(kImageFilename, cricket::FOURCC_YU12, kWidth, kHeight, + ASSERT_TRUE(LoadFrame(kImageFilename, kYuvExtension, + cricket::FOURCC_YU12, kWidth, kHeight, &frame3)); EXPECT_TRUE(IsEqual(frame1, frame2, 0)); EXPECT_TRUE(IsEqual(frame1, frame3, 0)); @@ -1132,7 +1142,7 @@ class VideoFrameTest : public testing::Test { void ConstructMjpgI420() { T frame1, frame2; ASSERT_TRUE(LoadFrameNoRepeat(&frame1)); - ASSERT_TRUE(LoadFrame(kJpeg420Filename, + ASSERT_TRUE(LoadFrame(kJpeg420Filename, kJpegExtension, cricket::FOURCC_MJPG, kWidth, kHeight, &frame2)); EXPECT_TRUE(IsEqual(frame1, frame2, 32)); } @@ -1141,7 +1151,7 @@ class VideoFrameTest : public testing::Test { void ConstructMjpgI422() { T frame1, frame2; ASSERT_TRUE(LoadFrameNoRepeat(&frame1)); - ASSERT_TRUE(LoadFrame(kJpeg422Filename, + ASSERT_TRUE(LoadFrame(LoadSample(kJpeg422Filename, kJpegExtension).get(), cricket::FOURCC_MJPG, kWidth, kHeight, &frame2)); EXPECT_TRUE(IsEqual(frame1, frame2, 32)); } @@ -1150,7 +1160,7 @@ class VideoFrameTest : public testing::Test { void ConstructMjpgI444() { T frame1, frame2; ASSERT_TRUE(LoadFrameNoRepeat(&frame1)); - ASSERT_TRUE(LoadFrame(kJpeg444Filename, + ASSERT_TRUE(LoadFrame(LoadSample(kJpeg444Filename, kJpegExtension), cricket::FOURCC_MJPG, kWidth, kHeight, &frame2)); EXPECT_TRUE(IsEqual(frame1, frame2, 32)); } @@ -1159,7 +1169,7 @@ class VideoFrameTest : public testing::Test { void ConstructMjpgI411() { T frame1, frame2; ASSERT_TRUE(LoadFrameNoRepeat(&frame1)); - ASSERT_TRUE(LoadFrame(kJpeg411Filename, + ASSERT_TRUE(LoadFrame(kJpeg411Filename, kJpegExtension, cricket::FOURCC_MJPG, kWidth, kHeight, &frame2)); EXPECT_TRUE(IsEqual(frame1, frame2, 32)); } @@ -1169,7 +1179,7 @@ class VideoFrameTest : public testing::Test { void ConstructMjpgI400() { T frame1, frame2; ASSERT_TRUE(LoadFrameNoRepeat(&frame1)); - ASSERT_TRUE(LoadFrame(kJpeg400Filename, + ASSERT_TRUE(LoadFrame(kJpeg400Filename, kJpegExtension, cricket::FOURCC_MJPG, kWidth, kHeight, &frame2)); EXPECT_TRUE(IsPlaneEqual("y", frame1.video_frame_buffer()->DataY(), frame1.video_frame_buffer()->StrideY(), @@ -1181,12 +1191,13 @@ class VideoFrameTest : public testing::Test { // Test constructing an image from an I420 MJPG buffer. void ValidateFrame(const char* name, + const char* extension, uint32_t fourcc, int data_adjust, int size_adjust, bool expected_result) { T frame; - std::unique_ptr ms(LoadSample(name)); + std::unique_ptr ms(LoadSample(name, extension)); ASSERT_TRUE(ms.get() != NULL); const uint8_t* sample = reinterpret_cast(ms.get()->GetBuffer()); @@ -1216,50 +1227,59 @@ class VideoFrameTest : public testing::Test { // Test validate for I420 MJPG buffer. void ValidateMjpgI420() { - ValidateFrame(kJpeg420Filename, cricket::FOURCC_MJPG, 0, 0, true); + ValidateFrame(kJpeg420Filename, kJpegExtension, + cricket::FOURCC_MJPG, 0, 0, true); } // Test validate for I422 MJPG buffer. void ValidateMjpgI422() { - ValidateFrame(kJpeg422Filename, cricket::FOURCC_MJPG, 0, 0, true); + ValidateFrame(kJpeg422Filename, kJpegExtension, + cricket::FOURCC_MJPG, 0, 0, true); } // Test validate for I444 MJPG buffer. void ValidateMjpgI444() { - ValidateFrame(kJpeg444Filename, cricket::FOURCC_MJPG, 0, 0, true); + ValidateFrame(kJpeg444Filename, kJpegExtension, + cricket::FOURCC_MJPG, 0, 0, true); } // Test validate for I411 MJPG buffer. void ValidateMjpgI411() { - ValidateFrame(kJpeg411Filename, cricket::FOURCC_MJPG, 0, 0, true); + ValidateFrame(kJpeg411Filename, kJpegExtension, + cricket::FOURCC_MJPG, 0, 0, true); } // Test validate for I400 MJPG buffer. void ValidateMjpgI400() { - ValidateFrame(kJpeg400Filename, cricket::FOURCC_MJPG, 0, 0, true); + ValidateFrame(kJpeg400Filename, kJpegExtension, + cricket::FOURCC_MJPG, 0, 0, true); } // Test validate for I420 buffer. void ValidateI420() { - ValidateFrame(kImageFilename, cricket::FOURCC_I420, 0, 0, true); + ValidateFrame(kImageFilename, kYuvExtension, + cricket::FOURCC_I420, 0, 0, true); } // Test validate for I420 buffer where size is too small void ValidateI420SmallSize() { - ValidateFrame(kImageFilename, cricket::FOURCC_I420, 0, -16384, false); + ValidateFrame(kImageFilename, kYuvExtension, + cricket::FOURCC_I420, 0, -16384, false); } // Test validate for I420 buffer where size is too large (16 MB) // Will produce warning but pass. void ValidateI420LargeSize() { - ValidateFrame(kImageFilename, cricket::FOURCC_I420, 16000000, 16000000, + ValidateFrame(kImageFilename, kYuvExtension, + cricket::FOURCC_I420, 16000000, 16000000, true); } // Test validate for I420 buffer where size is 1 GB (not reasonable). void ValidateI420HugeSize() { #ifndef WIN32 // TODO(fbarchard): Reenable when fixing bug 9603762. - ValidateFrame(kImageFilename, cricket::FOURCC_I420, 1000000000u, + ValidateFrame(kImageFilename, kYuvExtension, + cricket::FOURCC_I420, 1000000000u, 1000000000u, false); #endif } @@ -1282,7 +1302,8 @@ class VideoFrameTest : public testing::Test { // crashes the exception handler will return and unittest passes with OK. void ValidateMjpgI420InvalidSize() { __try { - ValidateFrame(kJpeg420Filename, cricket::FOURCC_MJPG, -16384, 0, false); + ValidateFrame(kJpeg420Filename, kJpegExtension, + cricket::FOURCC_MJPG, -16384, 0, false); FAIL() << "Validate was expected to cause EXCEPTION_ACCESS_VIOLATION."; } __except(ExceptionFilter(GetExceptionCode(), GetExceptionInformation())) { return; // Successfully crashed in ValidateFrame. @@ -1292,7 +1313,8 @@ class VideoFrameTest : public testing::Test { // Test validate fails for truncated I420 buffer. void ValidateI420InvalidSize() { __try { - ValidateFrame(kImageFilename, cricket::FOURCC_I420, -16384, 0, false); + ValidateFrame(kImageFilename, kYuvExtension, + cricket::FOURCC_I420, -16384, 0, false); FAIL() << "Validate was expected to cause EXCEPTION_ACCESS_VIOLATION."; } __except(ExceptionFilter(GetExceptionCode(), GetExceptionInformation())) { return; // Successfully crashed in ValidateFrame. diff --git a/webrtc/media/engine/webrtcvideoframe_unittest.cc b/webrtc/media/engine/webrtcvideoframe_unittest.cc index 2c6f56cb25..abfd0aea3c 100644 --- a/webrtc/media/engine/webrtcvideoframe_unittest.cc +++ b/webrtc/media/engine/webrtcvideoframe_unittest.cc @@ -313,9 +313,8 @@ TEST_F(WebRtcVideoFrameTest, CopyTextureFrame) { TEST_F(WebRtcVideoFrameTest, ApplyRotationToFrame) { WebRtcVideoTestFrame applied0; EXPECT_TRUE(IsNull(applied0)); - std::unique_ptr ms(CreateYuvSample(kWidth, kHeight, 12)); - EXPECT_TRUE( - LoadFrame(ms.get(), cricket::FOURCC_I420, kWidth, kHeight, &applied0)); + EXPECT_TRUE(LoadFrame(CreateYuvSample(kWidth, kHeight, 12).get(), + cricket::FOURCC_I420, kWidth, kHeight, &applied0)); // Claim that this frame needs to be rotated for 90 degree. applied0.set_rotation(webrtc::kVideoRotation_90); diff --git a/webrtc/media/media.gyp b/webrtc/media/media.gyp index 691bb1e0c5..1e19a84936 100644 --- a/webrtc/media/media.gyp +++ b/webrtc/media/media.gyp @@ -250,6 +250,7 @@ '<(webrtc_root)/base/base_tests.gyp:rtc_base_tests_utils', '<(webrtc_root)/media/media.gyp:rtc_media', '<(webrtc_root)/system_wrappers/system_wrappers.gyp:metrics_default', + '<(webrtc_root)/test/test.gyp:test_support', 'rtc_unittest_main', ], 'sources': [ diff --git a/webrtc/pc/planarfunctions_unittest.cc b/webrtc/pc/planarfunctions_unittest.cc deleted file mode 100644 index af7e628cde..0000000000 --- a/webrtc/pc/planarfunctions_unittest.cc +++ /dev/null @@ -1,925 +0,0 @@ -/* - * Copyright 2014 The WebRTC 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 -#include - -#include "libyuv/convert.h" -#include "libyuv/convert_from.h" -#include "libyuv/convert_from_argb.h" -#include "libyuv/mjpeg_decoder.h" -#include "libyuv/planar_functions.h" -#include "webrtc/base/flags.h" -#include "webrtc/base/gunit.h" -#include "webrtc/media/base/testutils.h" -#include "webrtc/media/base/videocommon.h" - -// Undefine macros for the windows build. -#undef max -#undef min - -using cricket::DumpPlanarYuvTestImage; - -DEFINE_bool(planarfunctions_dump, false, - "whether to write out scaled images for inspection"); -DEFINE_int(planarfunctions_repeat, 1, - "how many times to perform each scaling operation (for perf testing)"); - -namespace cricket { - -// Number of testing colors in each color channel. -static const int kTestingColorChannelResolution = 6; - -// The total number of testing colors -// kTestingColorNum = kTestingColorChannelResolution^3; -static const int kTestingColorNum = kTestingColorChannelResolution * - kTestingColorChannelResolution * kTestingColorChannelResolution; - -static const int kWidth = 1280; -static const int kHeight = 720; -static const int kAlignment = 16; - -class PlanarFunctionsTest : public testing::TestWithParam { - protected: - PlanarFunctionsTest() : dump_(false), repeat_(1) { - InitializeColorBand(); - } - - virtual void SetUp() { - dump_ = FLAG_planarfunctions_dump; - repeat_ = FLAG_planarfunctions_repeat; - } - - // Initialize the color band for testing. - void InitializeColorBand() { - testing_color_y_.reset(new uint8_t[kTestingColorNum]); - testing_color_u_.reset(new uint8_t[kTestingColorNum]); - testing_color_v_.reset(new uint8_t[kTestingColorNum]); - testing_color_r_.reset(new uint8_t[kTestingColorNum]); - testing_color_g_.reset(new uint8_t[kTestingColorNum]); - testing_color_b_.reset(new uint8_t[kTestingColorNum]); - int color_counter = 0; - for (int i = 0; i < kTestingColorChannelResolution; ++i) { - uint8_t color_r = - static_cast(i * 255 / (kTestingColorChannelResolution - 1)); - for (int j = 0; j < kTestingColorChannelResolution; ++j) { - uint8_t color_g = static_cast( - j * 255 / (kTestingColorChannelResolution - 1)); - for (int k = 0; k < kTestingColorChannelResolution; ++k) { - uint8_t color_b = static_cast( - k * 255 / (kTestingColorChannelResolution - 1)); - testing_color_r_[color_counter] = color_r; - testing_color_g_[color_counter] = color_g; - testing_color_b_[color_counter] = color_b; - // Converting the testing RGB colors to YUV colors. - ConvertRgbPixel(color_r, color_g, color_b, - &(testing_color_y_[color_counter]), - &(testing_color_u_[color_counter]), - &(testing_color_v_[color_counter])); - ++color_counter; - } - } - } - } - // Simple and slow RGB->YUV conversion. From NTSC standard, c/o Wikipedia. - // (from lmivideoframe_unittest.cc) - void ConvertRgbPixel(uint8_t r, - uint8_t g, - uint8_t b, - uint8_t* y, - uint8_t* u, - uint8_t* v) { - *y = ClampUint8(.257 * r + .504 * g + .098 * b + 16); - *u = ClampUint8(-.148 * r - .291 * g + .439 * b + 128); - *v = ClampUint8(.439 * r - .368 * g - .071 * b + 128); - } - - uint8_t ClampUint8(double value) { - value = std::max(0., std::min(255., value)); - uint8_t uint8_value = static_cast(value); - return uint8_value; - } - - // Generate a Red-Green-Blue inter-weaving chessboard-like - // YUV testing image (I420/I422/I444). - // The pattern looks like c0 c1 c2 c3 ... - // c1 c2 c3 c4 ... - // c2 c3 c4 c5 ... - // ............... - // The size of each chrome block is (block_size) x (block_size). - uint8_t* CreateFakeYuvTestingImage(int height, - int width, - int block_size, - libyuv::JpegSubsamplingType subsample_type, - uint8_t*& y_pointer, - uint8_t*& u_pointer, - uint8_t*& v_pointer) { - if (height <= 0 || width <= 0 || block_size <= 0) { return NULL; } - int y_size = height * width; - int u_size, v_size; - int vertical_sample_ratio = 1, horizontal_sample_ratio = 1; - switch (subsample_type) { - case libyuv::kJpegYuv420: - u_size = ((height + 1) >> 1) * ((width + 1) >> 1); - v_size = u_size; - vertical_sample_ratio = 2, horizontal_sample_ratio = 2; - break; - case libyuv::kJpegYuv422: - u_size = height * ((width + 1) >> 1); - v_size = u_size; - vertical_sample_ratio = 1, horizontal_sample_ratio = 2; - break; - case libyuv::kJpegYuv444: - v_size = u_size = y_size; - vertical_sample_ratio = 1, horizontal_sample_ratio = 1; - break; - case libyuv::kJpegUnknown: - default: - return NULL; - break; - } - uint8_t* image_pointer = new uint8_t[y_size + u_size + v_size + kAlignment]; - y_pointer = ALIGNP(image_pointer, kAlignment); - u_pointer = ALIGNP(&image_pointer[y_size], kAlignment); - v_pointer = ALIGNP(&image_pointer[y_size + u_size], kAlignment); - uint8_t* current_y_pointer = y_pointer; - uint8_t* current_u_pointer = u_pointer; - uint8_t* current_v_pointer = v_pointer; - for (int j = 0; j < height; ++j) { - for (int i = 0; i < width; ++i) { - int color = ((i / block_size) + (j / block_size)) % kTestingColorNum; - *(current_y_pointer++) = testing_color_y_[color]; - if (i % horizontal_sample_ratio == 0 && - j % vertical_sample_ratio == 0) { - *(current_u_pointer++) = testing_color_u_[color]; - *(current_v_pointer++) = testing_color_v_[color]; - } - } - } - return image_pointer; - } - - // Generate a Red-Green-Blue inter-weaving chessboard-like - // YUY2/UYVY testing image. - // The pattern looks like c0 c1 c2 c3 ... - // c1 c2 c3 c4 ... - // c2 c3 c4 c5 ... - // ............... - // The size of each chrome block is (block_size) x (block_size). - uint8_t* CreateFakeInterleaveYuvTestingImage(int height, - int width, - int block_size, - uint8_t*& yuv_pointer, - FourCC fourcc_type) { - if (height <= 0 || width <= 0 || block_size <= 0) { return NULL; } - if (fourcc_type != FOURCC_YUY2 && fourcc_type != FOURCC_UYVY) { - LOG(LS_ERROR) << "Format " << static_cast(fourcc_type) - << " is not supported."; - return NULL; - } - // Regularize the width of the output to be even. - int awidth = (width + 1) & ~1; - - uint8_t* image_pointer = new uint8_t[2 * height * awidth + kAlignment]; - yuv_pointer = ALIGNP(image_pointer, kAlignment); - uint8_t* current_yuv_pointer = yuv_pointer; - switch (fourcc_type) { - case FOURCC_YUY2: { - for (int j = 0; j < height; ++j) { - for (int i = 0; i < awidth; i += 2, current_yuv_pointer += 4) { - int color1 = ((i / block_size) + (j / block_size)) % - kTestingColorNum; - int color2 = (((i + 1) / block_size) + (j / block_size)) % - kTestingColorNum; - current_yuv_pointer[0] = testing_color_y_[color1]; - if (i < width) { - current_yuv_pointer[1] = static_cast( - (static_cast(testing_color_u_[color1]) + - static_cast(testing_color_u_[color2])) / - 2); - current_yuv_pointer[2] = testing_color_y_[color2]; - current_yuv_pointer[3] = static_cast( - (static_cast(testing_color_v_[color1]) + - static_cast(testing_color_v_[color2])) / - 2); - } else { - current_yuv_pointer[1] = testing_color_u_[color1]; - current_yuv_pointer[2] = 0; - current_yuv_pointer[3] = testing_color_v_[color1]; - } - } - } - break; - } - case FOURCC_UYVY: { - for (int j = 0; j < height; ++j) { - for (int i = 0; i < awidth; i += 2, current_yuv_pointer += 4) { - int color1 = ((i / block_size) + (j / block_size)) % - kTestingColorNum; - int color2 = (((i + 1) / block_size) + (j / block_size)) % - kTestingColorNum; - if (i < width) { - current_yuv_pointer[0] = static_cast( - (static_cast(testing_color_u_[color1]) + - static_cast(testing_color_u_[color2])) / - 2); - current_yuv_pointer[1] = testing_color_y_[color1]; - current_yuv_pointer[2] = static_cast( - (static_cast(testing_color_v_[color1]) + - static_cast(testing_color_v_[color2])) / - 2); - current_yuv_pointer[3] = testing_color_y_[color2]; - } else { - current_yuv_pointer[0] = testing_color_u_[color1]; - current_yuv_pointer[1] = testing_color_y_[color1]; - current_yuv_pointer[2] = testing_color_v_[color1]; - current_yuv_pointer[3] = 0; - } - } - } - break; - } - } - return image_pointer; - } - - // Generate a Red-Green-Blue inter-weaving chessboard-like - // NV12 testing image. - // (Note: No interpolation is used.) - // The pattern looks like c0 c1 c2 c3 ... - // c1 c2 c3 c4 ... - // c2 c3 c4 c5 ... - // ............... - // The size of each chrome block is (block_size) x (block_size). - uint8_t* CreateFakeNV12TestingImage(int height, - int width, - int block_size, - uint8_t*& y_pointer, - uint8_t*& uv_pointer) { - if (height <= 0 || width <= 0 || block_size <= 0) { return NULL; } - - uint8_t* image_pointer = - new uint8_t[height * width + - ((height + 1) / 2) * ((width + 1) / 2) * 2 + kAlignment]; - y_pointer = ALIGNP(image_pointer, kAlignment); - uv_pointer = y_pointer + height * width; - uint8_t* current_uv_pointer = uv_pointer; - uint8_t* current_y_pointer = y_pointer; - for (int j = 0; j < height; ++j) { - for (int i = 0; i < width; ++i) { - int color = ((i / block_size) + (j / block_size)) % - kTestingColorNum; - *(current_y_pointer++) = testing_color_y_[color]; - } - if (j % 2 == 0) { - for (int i = 0; i < width; i += 2, current_uv_pointer += 2) { - int color = ((i / block_size) + (j / block_size)) % - kTestingColorNum; - current_uv_pointer[0] = testing_color_u_[color]; - current_uv_pointer[1] = testing_color_v_[color]; - } - } - } - return image_pointer; - } - - // Generate a Red-Green-Blue inter-weaving chessboard-like - // M420 testing image. - // (Note: No interpolation is used.) - // The pattern looks like c0 c1 c2 c3 ... - // c1 c2 c3 c4 ... - // c2 c3 c4 c5 ... - // ............... - // The size of each chrome block is (block_size) x (block_size). - uint8_t* CreateFakeM420TestingImage(int height, - int width, - int block_size, - uint8_t*& m420_pointer) { - if (height <= 0 || width <= 0 || block_size <= 0) { return NULL; } - - uint8_t* image_pointer = - new uint8_t[height * width + - ((height + 1) / 2) * ((width + 1) / 2) * 2 + kAlignment]; - m420_pointer = ALIGNP(image_pointer, kAlignment); - uint8_t* current_m420_pointer = m420_pointer; - for (int j = 0; j < height; ++j) { - for (int i = 0; i < width; ++i) { - int color = ((i / block_size) + (j / block_size)) % - kTestingColorNum; - *(current_m420_pointer++) = testing_color_y_[color]; - } - if (j % 2 == 1) { - for (int i = 0; i < width; i += 2, current_m420_pointer += 2) { - int color = ((i / block_size) + ((j - 1) / block_size)) % - kTestingColorNum; - current_m420_pointer[0] = testing_color_u_[color]; - current_m420_pointer[1] = testing_color_v_[color]; - } - } - } - return image_pointer; - } - - // Generate a Red-Green-Blue inter-weaving chessboard-like - // ARGB/ABGR/RAW/BG24 testing image. - // The pattern looks like c0 c1 c2 c3 ... - // c1 c2 c3 c4 ... - // c2 c3 c4 c5 ... - // ............... - // The size of each chrome block is (block_size) x (block_size). - uint8_t* CreateFakeArgbTestingImage(int height, - int width, - int block_size, - uint8_t*& argb_pointer, - FourCC fourcc_type) { - if (height <= 0 || width <= 0 || block_size <= 0) { return NULL; } - uint8_t* image_pointer = NULL; - if (fourcc_type == FOURCC_ABGR || fourcc_type == FOURCC_BGRA || - fourcc_type == FOURCC_ARGB) { - image_pointer = new uint8_t[height * width * 4 + kAlignment]; - } else if (fourcc_type == FOURCC_RAW || fourcc_type == FOURCC_24BG) { - image_pointer = new uint8_t[height * width * 3 + kAlignment]; - } else { - LOG(LS_ERROR) << "Format " << static_cast(fourcc_type) - << " is not supported."; - return NULL; - } - argb_pointer = ALIGNP(image_pointer, kAlignment); - uint8_t* current_pointer = argb_pointer; - switch (fourcc_type) { - case FOURCC_ARGB: { - for (int j = 0; j < height; ++j) { - for (int i = 0; i < width; ++i) { - int color = ((i / block_size) + (j / block_size)) % - kTestingColorNum; - *(current_pointer++) = testing_color_b_[color]; - *(current_pointer++) = testing_color_g_[color]; - *(current_pointer++) = testing_color_r_[color]; - *(current_pointer++) = 255; - } - } - break; - } - case FOURCC_ABGR: { - for (int j = 0; j < height; ++j) { - for (int i = 0; i < width; ++i) { - int color = ((i / block_size) + (j / block_size)) % - kTestingColorNum; - *(current_pointer++) = testing_color_r_[color]; - *(current_pointer++) = testing_color_g_[color]; - *(current_pointer++) = testing_color_b_[color]; - *(current_pointer++) = 255; - } - } - break; - } - case FOURCC_BGRA: { - for (int j = 0; j < height; ++j) { - for (int i = 0; i < width; ++i) { - int color = ((i / block_size) + (j / block_size)) % - kTestingColorNum; - *(current_pointer++) = 255; - *(current_pointer++) = testing_color_r_[color]; - *(current_pointer++) = testing_color_g_[color]; - *(current_pointer++) = testing_color_b_[color]; - } - } - break; - } - case FOURCC_24BG: { - for (int j = 0; j < height; ++j) { - for (int i = 0; i < width; ++i) { - int color = ((i / block_size) + (j / block_size)) % - kTestingColorNum; - *(current_pointer++) = testing_color_b_[color]; - *(current_pointer++) = testing_color_g_[color]; - *(current_pointer++) = testing_color_r_[color]; - } - } - break; - } - case FOURCC_RAW: { - for (int j = 0; j < height; ++j) { - for (int i = 0; i < width; ++i) { - int color = ((i / block_size) + (j / block_size)) % - kTestingColorNum; - *(current_pointer++) = testing_color_r_[color]; - *(current_pointer++) = testing_color_g_[color]; - *(current_pointer++) = testing_color_b_[color]; - } - } - break; - } - default: { - LOG(LS_ERROR) << "Format " << static_cast(fourcc_type) - << " is not supported."; - } - } - return image_pointer; - } - - // Check if two memory chunks are equal. - // (tolerate MSE errors within a threshold). - static bool IsMemoryEqual(const uint8_t* ibuf, - const uint8_t* obuf, - int osize, - double average_error) { - double sse = cricket::ComputeSumSquareError(ibuf, obuf, osize); - double error = sse / osize; // Mean Squared Error. - double PSNR = cricket::ComputePSNR(sse, osize); - LOG(LS_INFO) << "Image MSE: " << error << " Image PSNR: " << PSNR - << " First Diff Byte: " << FindDiff(ibuf, obuf, osize); - return (error < average_error); - } - - // Returns the index of the first differing byte. Easier to debug than memcmp. - static int FindDiff(const uint8_t* buf1, const uint8_t* buf2, int len) { - int i = 0; - while (i < len && buf1[i] == buf2[i]) { - i++; - } - return (i < len) ? i : -1; - } - - // Dump the result image (ARGB format). - void DumpArgbImage(const uint8_t* obuf, int width, int height) { - DumpPlanarArgbTestImage(GetTestName(), obuf, width, height); - } - - // Dump the result image (YUV420 format). - void DumpYuvImage(const uint8_t* obuf, int width, int height) { - DumpPlanarYuvTestImage(GetTestName(), obuf, width, height); - } - - std::string GetTestName() { - const testing::TestInfo* const test_info = - testing::UnitTest::GetInstance()->current_test_info(); - std::string test_name(test_info->name()); - return test_name; - } - - bool dump_; - int repeat_; - - // Y, U, V and R, G, B channels of testing colors. - std::unique_ptr testing_color_y_; - std::unique_ptr testing_color_u_; - std::unique_ptr testing_color_v_; - std::unique_ptr testing_color_r_; - std::unique_ptr testing_color_g_; - std::unique_ptr testing_color_b_; -}; - -TEST_F(PlanarFunctionsTest, I420Copy) { - uint8_t* y_pointer = nullptr; - uint8_t* u_pointer = nullptr; - uint8_t* v_pointer = nullptr; - int y_pitch = kWidth; - int u_pitch = (kWidth + 1) >> 1; - int v_pitch = (kWidth + 1) >> 1; - int y_size = kHeight * kWidth; - int uv_size = ((kHeight + 1) >> 1) * ((kWidth + 1) >> 1); - int block_size = 3; - // Generate a fake input image. - std::unique_ptr yuv_input(CreateFakeYuvTestingImage( - kHeight, kWidth, block_size, libyuv::kJpegYuv420, y_pointer, u_pointer, - v_pointer)); - // Allocate space for the output image. - std::unique_ptr yuv_output( - new uint8_t[I420_SIZE(kHeight, kWidth) + kAlignment]); - uint8_t* y_output_pointer = ALIGNP(yuv_output.get(), kAlignment); - uint8_t* u_output_pointer = y_output_pointer + y_size; - uint8_t* v_output_pointer = u_output_pointer + uv_size; - - for (int i = 0; i < repeat_; ++i) { - libyuv::I420Copy(y_pointer, y_pitch, - u_pointer, u_pitch, - v_pointer, v_pitch, - y_output_pointer, y_pitch, - u_output_pointer, u_pitch, - v_output_pointer, v_pitch, - kWidth, kHeight); - } - - // Expect the copied frame to be exactly the same. - EXPECT_TRUE(IsMemoryEqual(y_output_pointer, y_pointer, - I420_SIZE(kHeight, kWidth), 1.e-6)); - - if (dump_) { DumpYuvImage(y_output_pointer, kWidth, kHeight); } -} - -TEST_F(PlanarFunctionsTest, I422ToI420) { - uint8_t* y_pointer = nullptr; - uint8_t* u_pointer = nullptr; - uint8_t* v_pointer = nullptr; - int y_pitch = kWidth; - int u_pitch = (kWidth + 1) >> 1; - int v_pitch = (kWidth + 1) >> 1; - int y_size = kHeight * kWidth; - int uv_size = ((kHeight + 1) >> 1) * ((kWidth + 1) >> 1); - int block_size = 2; - // Generate a fake input image. - std::unique_ptr yuv_input(CreateFakeYuvTestingImage( - kHeight, kWidth, block_size, libyuv::kJpegYuv422, y_pointer, u_pointer, - v_pointer)); - // Allocate space for the output image. - std::unique_ptr yuv_output( - new uint8_t[I420_SIZE(kHeight, kWidth) + kAlignment]); - uint8_t* y_output_pointer = ALIGNP(yuv_output.get(), kAlignment); - uint8_t* u_output_pointer = y_output_pointer + y_size; - uint8_t* v_output_pointer = u_output_pointer + uv_size; - // Generate the expected output. - uint8_t* y_expected_pointer = nullptr; - uint8_t* u_expected_pointer = nullptr; - uint8_t* v_expected_pointer = nullptr; - std::unique_ptr yuv_output_expected(CreateFakeYuvTestingImage( - kHeight, kWidth, block_size, libyuv::kJpegYuv420, y_expected_pointer, - u_expected_pointer, v_expected_pointer)); - - for (int i = 0; i < repeat_; ++i) { - libyuv::I422ToI420(y_pointer, y_pitch, - u_pointer, u_pitch, - v_pointer, v_pitch, - y_output_pointer, y_pitch, - u_output_pointer, u_pitch, - v_output_pointer, v_pitch, - kWidth, kHeight); - } - - // Compare the output frame with what is expected; expect exactly the same. - // Note: MSE should be set to a larger threshold if an odd block width - // is used, since the conversion will be lossy. - EXPECT_TRUE(IsMemoryEqual(y_output_pointer, y_expected_pointer, - I420_SIZE(kHeight, kWidth), 1.e-6)); - - if (dump_) { DumpYuvImage(y_output_pointer, kWidth, kHeight); } -} - -TEST_P(PlanarFunctionsTest, M420ToI420) { - // Get the unalignment offset - int unalignment = GetParam(); - uint8_t* m420_pointer = NULL; - int y_pitch = kWidth; - int m420_pitch = kWidth; - int u_pitch = (kWidth + 1) >> 1; - int v_pitch = (kWidth + 1) >> 1; - int y_size = kHeight * kWidth; - int uv_size = ((kHeight + 1) >> 1) * ((kWidth + 1) >> 1); - int block_size = 2; - // Generate a fake input image. - std::unique_ptr yuv_input( - CreateFakeM420TestingImage(kHeight, kWidth, block_size, m420_pointer)); - // Allocate space for the output image. - std::unique_ptr yuv_output( - new uint8_t[I420_SIZE(kHeight, kWidth) + kAlignment + unalignment]); - uint8_t* y_output_pointer = - ALIGNP(yuv_output.get(), kAlignment) + unalignment; - uint8_t* u_output_pointer = y_output_pointer + y_size; - uint8_t* v_output_pointer = u_output_pointer + uv_size; - // Generate the expected output. - uint8_t* y_expected_pointer = nullptr; - uint8_t* u_expected_pointer = nullptr; - uint8_t* v_expected_pointer = nullptr; - std::unique_ptr yuv_output_expected(CreateFakeYuvTestingImage( - kHeight, kWidth, block_size, libyuv::kJpegYuv420, y_expected_pointer, - u_expected_pointer, v_expected_pointer)); - - for (int i = 0; i < repeat_; ++i) { - libyuv::M420ToI420(m420_pointer, m420_pitch, - y_output_pointer, y_pitch, - u_output_pointer, u_pitch, - v_output_pointer, v_pitch, - kWidth, kHeight); - } - // Compare the output frame with what is expected; expect exactly the same. - // Note: MSE should be set to a larger threshold if an odd block width - // is used, since the conversion will be lossy. - EXPECT_TRUE(IsMemoryEqual(y_output_pointer, y_expected_pointer, - I420_SIZE(kHeight, kWidth), 1.e-6)); - - if (dump_) { DumpYuvImage(y_output_pointer, kWidth, kHeight); } -} - -TEST_P(PlanarFunctionsTest, NV12ToI420) { - // Get the unalignment offset - int unalignment = GetParam(); - uint8_t* y_pointer = nullptr; - uint8_t* uv_pointer = nullptr; - int y_pitch = kWidth; - int uv_pitch = 2 * ((kWidth + 1) >> 1); - int u_pitch = (kWidth + 1) >> 1; - int v_pitch = (kWidth + 1) >> 1; - int y_size = kHeight * kWidth; - int uv_size = ((kHeight + 1) >> 1) * ((kWidth + 1) >> 1); - int block_size = 2; - // Generate a fake input image. - std::unique_ptr yuv_input(CreateFakeNV12TestingImage( - kHeight, kWidth, block_size, y_pointer, uv_pointer)); - // Allocate space for the output image. - std::unique_ptr yuv_output( - new uint8_t[I420_SIZE(kHeight, kWidth) + kAlignment + unalignment]); - uint8_t* y_output_pointer = - ALIGNP(yuv_output.get(), kAlignment) + unalignment; - uint8_t* u_output_pointer = y_output_pointer + y_size; - uint8_t* v_output_pointer = u_output_pointer + uv_size; - // Generate the expected output. - uint8_t* y_expected_pointer = nullptr; - uint8_t* u_expected_pointer = nullptr; - uint8_t* v_expected_pointer = nullptr; - std::unique_ptr yuv_output_expected(CreateFakeYuvTestingImage( - kHeight, kWidth, block_size, libyuv::kJpegYuv420, y_expected_pointer, - u_expected_pointer, v_expected_pointer)); - - for (int i = 0; i < repeat_; ++i) { - libyuv::NV12ToI420(y_pointer, y_pitch, - uv_pointer, uv_pitch, - y_output_pointer, y_pitch, - u_output_pointer, u_pitch, - v_output_pointer, v_pitch, - kWidth, kHeight); - } - // Compare the output frame with what is expected; expect exactly the same. - // Note: MSE should be set to a larger threshold if an odd block width - // is used, since the conversion will be lossy. - EXPECT_TRUE(IsMemoryEqual(y_output_pointer, y_expected_pointer, - I420_SIZE(kHeight, kWidth), 1.e-6)); - - if (dump_) { DumpYuvImage(y_output_pointer, kWidth, kHeight); } -} - -// A common macro for testing converting YUY2/UYVY to I420. -#define TEST_YUVTOI420(SRC_NAME, MSE, BLOCK_SIZE) \ - TEST_P(PlanarFunctionsTest, SRC_NAME##ToI420) { \ - /* Get the unalignment offset.*/ \ - int unalignment = GetParam(); \ - uint8_t* yuv_pointer = nullptr; \ - int yuv_pitch = 2 * ((kWidth + 1) & ~1); \ - int y_pitch = kWidth; \ - int u_pitch = (kWidth + 1) >> 1; \ - int v_pitch = (kWidth + 1) >> 1; \ - int y_size = kHeight * kWidth; \ - int uv_size = ((kHeight + 1) >> 1) * ((kWidth + 1) >> 1); \ - int block_size = 2; \ - /* Generate a fake input image.*/ \ - std::unique_ptr yuv_input(CreateFakeInterleaveYuvTestingImage( \ - kHeight, kWidth, BLOCK_SIZE, yuv_pointer, FOURCC_##SRC_NAME)); \ - /* Allocate space for the output image.*/ \ - std::unique_ptr yuv_output( \ - new uint8_t[I420_SIZE(kHeight, kWidth) + kAlignment + unalignment]); \ - uint8_t* y_output_pointer = \ - ALIGNP(yuv_output.get(), kAlignment) + unalignment; \ - uint8_t* u_output_pointer = y_output_pointer + y_size; \ - uint8_t* v_output_pointer = u_output_pointer + uv_size; \ - /* Generate the expected output.*/ \ - uint8_t* y_expected_pointer = nullptr; \ - uint8_t* u_expected_pointer = nullptr; \ - uint8_t* v_expected_pointer = nullptr; \ - std::unique_ptr yuv_output_expected(CreateFakeYuvTestingImage( \ - kHeight, kWidth, block_size, libyuv::kJpegYuv420, y_expected_pointer, \ - u_expected_pointer, v_expected_pointer)); \ - for (int i = 0; i < repeat_; ++i) { \ - libyuv::SRC_NAME##ToI420(yuv_pointer, yuv_pitch, y_output_pointer, \ - y_pitch, u_output_pointer, u_pitch, \ - v_output_pointer, v_pitch, kWidth, kHeight); \ - } \ - /* Compare the output frame with what is expected.*/ \ - /* Note: MSE should be set to a larger threshold if an odd block width*/ \ - /* is used, since the conversion will be lossy.*/ \ - EXPECT_TRUE(IsMemoryEqual(y_output_pointer, y_expected_pointer, \ - I420_SIZE(kHeight, kWidth), MSE)); \ - if (dump_) { \ - DumpYuvImage(y_output_pointer, kWidth, kHeight); \ - } \ - } - -// TEST_P(PlanarFunctionsTest, YUV2ToI420) -TEST_YUVTOI420(YUY2, 1.e-6, 2); -// TEST_P(PlanarFunctionsTest, UYVYToI420) -TEST_YUVTOI420(UYVY, 1.e-6, 2); - -// A common macro for testing converting I420 to ARGB, BGRA and ABGR. -#define TEST_YUVTORGB(SRC_NAME, DST_NAME, JPG_TYPE, MSE, BLOCK_SIZE) \ - TEST_F(PlanarFunctionsTest, SRC_NAME##To##DST_NAME) { \ - uint8_t* y_pointer = nullptr; \ - uint8_t* u_pointer = nullptr; \ - uint8_t* v_pointer = nullptr; \ - uint8_t* argb_expected_pointer = NULL; \ - int y_pitch = kWidth; \ - int u_pitch = (kWidth + 1) >> 1; \ - int v_pitch = (kWidth + 1) >> 1; \ - /* Generate a fake input image.*/ \ - std::unique_ptr yuv_input( \ - CreateFakeYuvTestingImage(kHeight, kWidth, BLOCK_SIZE, JPG_TYPE, \ - y_pointer, u_pointer, v_pointer)); \ - /* Generate the expected output.*/ \ - std::unique_ptr argb_expected( \ - CreateFakeArgbTestingImage(kHeight, kWidth, BLOCK_SIZE, \ - argb_expected_pointer, FOURCC_##DST_NAME)); \ - /* Allocate space for the output.*/ \ - std::unique_ptr argb_output( \ - new uint8_t[kHeight * kWidth * 4 + kAlignment]); \ - uint8_t* argb_pointer = ALIGNP(argb_expected.get(), kAlignment); \ - for (int i = 0; i < repeat_; ++i) { \ - libyuv::SRC_NAME##To##DST_NAME(y_pointer, y_pitch, u_pointer, u_pitch, \ - v_pointer, v_pitch, argb_pointer, \ - kWidth * 4, kWidth, kHeight); \ - } \ - EXPECT_TRUE(IsMemoryEqual(argb_expected_pointer, argb_pointer, \ - kHeight* kWidth * 4, MSE)); \ - if (dump_) { \ - DumpArgbImage(argb_pointer, kWidth, kHeight); \ - } \ - } - -// TEST_F(PlanarFunctionsTest, I420ToARGB) -TEST_YUVTORGB(I420, ARGB, libyuv::kJpegYuv420, 3., 2); -// TEST_F(PlanarFunctionsTest, I420ToABGR) -TEST_YUVTORGB(I420, ABGR, libyuv::kJpegYuv420, 3., 2); -// TEST_F(PlanarFunctionsTest, I420ToBGRA) -TEST_YUVTORGB(I420, BGRA, libyuv::kJpegYuv420, 3., 2); -// TEST_F(PlanarFunctionsTest, I422ToARGB) -TEST_YUVTORGB(I422, ARGB, libyuv::kJpegYuv422, 3., 2); -// TEST_F(PlanarFunctionsTest, I444ToARGB) -TEST_YUVTORGB(I444, ARGB, libyuv::kJpegYuv444, 3., 3); -// Note: an empirical MSE tolerance 3.0 is used here for the probable -// error from float-to-uint8_t type conversion. - -TEST_F(PlanarFunctionsTest, I400ToARGB_Reference) { - uint8_t* y_pointer = nullptr; - uint8_t* u_pointer = nullptr; - uint8_t* v_pointer = nullptr; - int y_pitch = kWidth; - int u_pitch = (kWidth + 1) >> 1; - int v_pitch = (kWidth + 1) >> 1; - int block_size = 3; - // Generate a fake input image. - std::unique_ptr yuv_input(CreateFakeYuvTestingImage( - kHeight, kWidth, block_size, libyuv::kJpegYuv420, y_pointer, u_pointer, - v_pointer)); - // As the comparison standard, we convert a grayscale image (by setting both - // U and V channels to be 128) using an I420 converter. - int uv_size = ((kHeight + 1) >> 1) * ((kWidth + 1) >> 1); - - std::unique_ptr uv(new uint8_t[uv_size + kAlignment]); - u_pointer = v_pointer = ALIGNP(uv.get(), kAlignment); - memset(u_pointer, 128, uv_size); - - // Allocate space for the output image and generate the expected output. - std::unique_ptr argb_expected( - new uint8_t[kHeight * kWidth * 4 + kAlignment]); - std::unique_ptr argb_output( - new uint8_t[kHeight * kWidth * 4 + kAlignment]); - uint8_t* argb_expected_pointer = ALIGNP(argb_expected.get(), kAlignment); - uint8_t* argb_pointer = ALIGNP(argb_output.get(), kAlignment); - - libyuv::I420ToARGB(y_pointer, y_pitch, - u_pointer, u_pitch, - v_pointer, v_pitch, - argb_expected_pointer, kWidth * 4, - kWidth, kHeight); - for (int i = 0; i < repeat_; ++i) { - libyuv::I400ToARGB_Reference(y_pointer, y_pitch, - argb_pointer, kWidth * 4, - kWidth, kHeight); - } - - // Note: I420ToARGB and I400ToARGB_Reference should produce identical results. - EXPECT_TRUE(IsMemoryEqual(argb_expected_pointer, argb_pointer, - kHeight * kWidth * 4, 2.)); - if (dump_) { DumpArgbImage(argb_pointer, kWidth, kHeight); } -} - -TEST_P(PlanarFunctionsTest, I400ToARGB) { - // Get the unalignment offset - int unalignment = GetParam(); - uint8_t* y_pointer = nullptr; - uint8_t* u_pointer = nullptr; - uint8_t* v_pointer = nullptr; - int y_pitch = kWidth; - int u_pitch = (kWidth + 1) >> 1; - int v_pitch = (kWidth + 1) >> 1; - int block_size = 3; - // Generate a fake input image. - std::unique_ptr yuv_input(CreateFakeYuvTestingImage( - kHeight, kWidth, block_size, libyuv::kJpegYuv420, y_pointer, u_pointer, - v_pointer)); - // As the comparison standard, we convert a grayscale image (by setting both - // U and V channels to be 128) using an I420 converter. - int uv_size = ((kHeight + 1) >> 1) * ((kWidth + 1) >> 1); - - // 1 byte extra if in the unaligned mode. - std::unique_ptr uv(new uint8_t[uv_size * 2 + kAlignment]); - u_pointer = ALIGNP(uv.get(), kAlignment); - v_pointer = u_pointer + uv_size; - memset(u_pointer, 128, uv_size); - memset(v_pointer, 128, uv_size); - - // Allocate space for the output image and generate the expected output. - std::unique_ptr argb_expected( - new uint8_t[kHeight * kWidth * 4 + kAlignment]); - // 1 byte extra if in the misalinged mode. - std::unique_ptr argb_output( - new uint8_t[kHeight * kWidth * 4 + kAlignment + unalignment]); - uint8_t* argb_expected_pointer = ALIGNP(argb_expected.get(), kAlignment); - uint8_t* argb_pointer = ALIGNP(argb_output.get(), kAlignment) + unalignment; - - libyuv::I420ToARGB(y_pointer, y_pitch, - u_pointer, u_pitch, - v_pointer, v_pitch, - argb_expected_pointer, kWidth * 4, - kWidth, kHeight); - for (int i = 0; i < repeat_; ++i) { - libyuv::I400ToARGB(y_pointer, y_pitch, - argb_pointer, kWidth * 4, - kWidth, kHeight); - } - - // Note: current I400ToARGB uses an approximate method, - // so the error tolerance is larger here. - EXPECT_TRUE(IsMemoryEqual(argb_expected_pointer, argb_pointer, - kHeight * kWidth * 4, 64.0)); - if (dump_) { DumpArgbImage(argb_pointer, kWidth, kHeight); } -} - -TEST_P(PlanarFunctionsTest, ARGBToI400) { - // Get the unalignment offset - int unalignment = GetParam(); - // Create a fake ARGB input image. - uint8_t* y_pointer = NULL, * u_pointer = NULL, * v_pointer = NULL; - uint8_t* argb_pointer = NULL; - int block_size = 3; - // Generate a fake input image. - std::unique_ptr argb_input(CreateFakeArgbTestingImage( - kHeight, kWidth, block_size, argb_pointer, FOURCC_ARGB)); - // Generate the expected output. Only Y channel is used - std::unique_ptr yuv_expected(CreateFakeYuvTestingImage( - kHeight, kWidth, block_size, libyuv::kJpegYuv420, y_pointer, u_pointer, - v_pointer)); - // Allocate space for the Y output. - std::unique_ptr y_output( - new uint8_t[kHeight * kWidth + kAlignment + unalignment]); - uint8_t* y_output_pointer = ALIGNP(y_output.get(), kAlignment) + unalignment; - - for (int i = 0; i < repeat_; ++i) { - libyuv::ARGBToI400(argb_pointer, kWidth * 4, y_output_pointer, kWidth, - kWidth, kHeight); - } - // Check if the output matches the input Y channel. - // Note: an empirical MSE tolerance 2.0 is used here for the probable - // error from float-to-uint8_t type conversion. - EXPECT_TRUE(IsMemoryEqual(y_output_pointer, y_pointer, - kHeight * kWidth, 2.)); - if (dump_) { DumpArgbImage(argb_pointer, kWidth, kHeight); } -} - -// A common macro for testing converting RAW, BG24, BGRA, and ABGR -// to ARGB. -#define TEST_ARGB(SRC_NAME, FC_ID, BPP, BLOCK_SIZE) \ - TEST_P(PlanarFunctionsTest, SRC_NAME##ToARGB) { \ - int unalignment = GetParam(); /* Get the unalignment offset.*/ \ - uint8_t *argb_expected_pointer = NULL, *src_pointer = NULL; \ - /* Generate a fake input image.*/ \ - std::unique_ptr src_input(CreateFakeArgbTestingImage( \ - kHeight, kWidth, BLOCK_SIZE, src_pointer, FOURCC_##FC_ID)); \ - /* Generate the expected output.*/ \ - std::unique_ptr argb_expected(CreateFakeArgbTestingImage( \ - kHeight, kWidth, BLOCK_SIZE, argb_expected_pointer, FOURCC_ARGB)); \ - /* Allocate space for the output; 1 byte extra if in the unaligned mode.*/ \ - std::unique_ptr argb_output( \ - new uint8_t[kHeight * kWidth * 4 + kAlignment + unalignment]); \ - uint8_t* argb_pointer = \ - ALIGNP(argb_output.get(), kAlignment) + unalignment; \ - for (int i = 0; i < repeat_; ++i) { \ - libyuv::SRC_NAME##ToARGB(src_pointer, kWidth*(BPP), argb_pointer, \ - kWidth * 4, kWidth, kHeight); \ - } \ - /* Compare the result; expect identical.*/ \ - EXPECT_TRUE(IsMemoryEqual(argb_expected_pointer, argb_pointer, \ - kHeight* kWidth * 4, 1.e-6)); \ - if (dump_) { \ - DumpArgbImage(argb_pointer, kWidth, kHeight); \ - } \ - } - -TEST_ARGB(RAW, RAW, 3, 3); // TEST_P(PlanarFunctionsTest, RAWToARGB) -TEST_ARGB(BG24, 24BG, 3, 3); // TEST_P(PlanarFunctionsTest, BG24ToARGB) -TEST_ARGB(ABGR, ABGR, 4, 3); // TEST_P(PlanarFunctionsTest, ABGRToARGB) -TEST_ARGB(BGRA, BGRA, 4, 3); // TEST_P(PlanarFunctionsTest, BGRAToARGB) - -// Parameter Test: The parameter is the unalignment offset. -// Aligned data for testing assembly versions. -INSTANTIATE_TEST_CASE_P(PlanarFunctionsAligned, PlanarFunctionsTest, - ::testing::Values(0)); - -// Purposely unalign the output argb pointer to test slow path (C version). -INSTANTIATE_TEST_CASE_P(PlanarFunctionsMisaligned, PlanarFunctionsTest, - ::testing::Values(1)); - -} // namespace cricket diff --git a/webrtc/pc/yuvscaler_unittest.cc b/webrtc/pc/yuvscaler_unittest.cc deleted file mode 100644 index a33d49523d..0000000000 --- a/webrtc/pc/yuvscaler_unittest.cc +++ /dev/null @@ -1,602 +0,0 @@ -/* - * Copyright 2010 The WebRTC 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 -#include - -#include "libyuv/cpu_id.h" -#include "libyuv/scale.h" -#include "webrtc/base/basictypes.h" -#include "webrtc/base/flags.h" -#include "webrtc/base/gunit.h" -#include "webrtc/media/base/testutils.h" - -#if defined(_MSC_VER) -#define ALIGN16(var) __declspec(align(16)) var -#else -#define ALIGN16(var) var __attribute__((aligned(16))) -#endif - -using cricket::LoadPlanarYuvTestImage; -using cricket::DumpPlanarYuvTestImage; - -DEFINE_bool(yuvscaler_dump, false, - "whether to write out scaled images for inspection"); -DEFINE_int(yuvscaler_repeat, 1, - "how many times to perform each scaling operation (for perf testing)"); - -static const int kAlignment = 16; - -// TEST_UNCACHED flushes cache to test real memory performance. -// TEST_RSTSC uses cpu cycles for more accurate benchmark of the scale function. -#ifndef __arm__ -// #define TEST_UNCACHED 1 -// #define TEST_RSTSC 1 -#endif - -#if defined(TEST_UNCACHED) || defined(TEST_RSTSC) -#ifdef _MSC_VER -#include // NOLINT -#endif - -#if defined(__GNUC__) && defined(__i386__) -static inline uint64_t __rdtsc(void) { - uint32_t a, d; - __asm__ volatile("rdtsc" : "=a" (a), "=d" (d)); - return (reinterpret_cast(d) << 32) + a; -} - -static inline void _mm_clflush(volatile void *__p) { - asm volatile("clflush %0" : "+m" (*(volatile char *)__p)); -} -#endif - -static void FlushCache(uint8_t* dst, int count) { - while (count >= 32) { - _mm_clflush(dst); - dst += 32; - count -= 32; - } -} -#endif - -class YuvScalerTest : public testing::Test { - protected: - virtual void SetUp() { - dump_ = *rtc::FlagList::Lookup("yuvscaler_dump")->bool_variable(); - repeat_ = *rtc::FlagList::Lookup("yuvscaler_repeat")->int_variable(); - } - - // Scale an image and compare against a Lanczos-filtered test image. - // Lanczos is considered to be the "ideal" image resampling method, so we try - // to get as close to that as possible, while being as fast as possible. - bool TestScale(int iw, int ih, int ow, int oh, int offset, bool usefile, - bool optimize, int cpuflags, bool interpolate, - int memoffset, double* error) { - *error = 0.; - size_t isize = I420_SIZE(iw, ih); - size_t osize = I420_SIZE(ow, oh); - std::unique_ptr ibuffer( - new uint8_t[isize + kAlignment + memoffset]()); - std::unique_ptr obuffer( - new uint8_t[osize + kAlignment + memoffset]()); - std::unique_ptr xbuffer( - new uint8_t[osize + kAlignment + memoffset]()); - - uint8_t* ibuf = ALIGNP(ibuffer.get(), kAlignment) + memoffset; - uint8_t* obuf = ALIGNP(obuffer.get(), kAlignment) + memoffset; - uint8_t* xbuf = ALIGNP(xbuffer.get(), kAlignment) + memoffset; - - if (usefile) { - if (!LoadPlanarYuvTestImage("faces", iw, ih, ibuf) || - !LoadPlanarYuvTestImage("faces", ow, oh, xbuf)) { - LOG(LS_ERROR) << "Failed to load image"; - return false; - } - } else { - // These are used to test huge images. - memset(ibuf, 213, isize); // Input is constant color. - memset(obuf, 100, osize); // Output set to something wrong for now. - memset(xbuf, 213, osize); // Expected result. - } - -#ifdef TEST_UNCACHED - FlushCache(ibuf, isize); - FlushCache(obuf, osize); - FlushCache(xbuf, osize); -#endif - - // Scale down. - // If cpu true, disable cpu optimizations. Else allow auto detect - // TODO(fbarchard): set flags for libyuv - libyuv::MaskCpuFlags(cpuflags); -#ifdef TEST_RSTSC - uint64_t t = 0; -#endif - for (int i = 0; i < repeat_; ++i) { -#ifdef TEST_UNCACHED - FlushCache(ibuf, isize); - FlushCache(obuf, osize); -#endif -#ifdef TEST_RSTSC - uint64_t t1 = __rdtsc(); -#endif - EXPECT_EQ(0, libyuv::ScaleOffset(ibuf, iw, ih, obuf, ow, oh, - offset, interpolate)); -#ifdef TEST_RSTSC - uint64_t t2 = __rdtsc(); - t += t2 - t1; -#endif - } - -#ifdef TEST_RSTSC - LOG(LS_INFO) << "Time: " << std::setw(9) << t; -#endif - - if (dump_) { - const testing::TestInfo* const test_info = - testing::UnitTest::GetInstance()->current_test_info(); - std::string test_name(test_info->name()); - DumpPlanarYuvTestImage(test_name, obuf, ow, oh); - } - - double sse = cricket::ComputeSumSquareError(obuf, xbuf, osize); - *error = sse / osize; // Mean Squared Error. - double PSNR = cricket::ComputePSNR(sse, osize); - LOG(LS_INFO) << "Image MSE: " << - std::setw(6) << std::setprecision(4) << *error << - " Image PSNR: " << PSNR; - return true; - } - - // Returns the index of the first differing byte. Easier to debug than memcmp. - static int FindDiff(const uint8_t* buf1, const uint8_t* buf2, int len) { - int i = 0; - while (i < len && buf1[i] == buf2[i]) { - i++; - } - return (i < len) ? i : -1; - } - - protected: - bool dump_; - int repeat_; -}; - -// Tests straight copy of data. -TEST_F(YuvScalerTest, TestCopy) { - const int iw = 640, ih = 360; - const int ow = 640, oh = 360; - ALIGN16(uint8_t ibuf[I420_SIZE(iw, ih)]); - ALIGN16(uint8_t obuf[I420_SIZE(ow, oh)]); - - // Load the frame, scale it, check it. - ASSERT_TRUE(LoadPlanarYuvTestImage("faces", iw, ih, ibuf)); - for (int i = 0; i < repeat_; ++i) { - libyuv::ScaleOffset(ibuf, iw, ih, obuf, ow, oh, 0, false); - } - if (dump_) DumpPlanarYuvTestImage("TestCopy", obuf, ow, oh); - EXPECT_EQ(-1, FindDiff(obuf, ibuf, sizeof(ibuf))); -} - -// Tests copy from 4:3 to 16:9. -TEST_F(YuvScalerTest, TestOffset16_10Copy) { - const int iw = 640, ih = 360; - const int ow = 640, oh = 480; - const int offset = (480 - 360) / 2; - std::unique_ptr ibuffer( - new uint8_t[I420_SIZE(iw, ih) + kAlignment]); - std::unique_ptr obuffer( - new uint8_t[I420_SIZE(ow, oh) + kAlignment]); - - uint8_t* ibuf = ALIGNP(ibuffer.get(), kAlignment); - uint8_t* obuf = ALIGNP(obuffer.get(), kAlignment); - - // Load the frame, scale it, check it. - ASSERT_TRUE(LoadPlanarYuvTestImage("faces", iw, ih, ibuf)); - - // Clear to black, which is Y = 0 and U and V = 128 - memset(obuf, 0, ow * oh); - memset(obuf + ow * oh, 128, ow * oh / 2); - for (int i = 0; i < repeat_; ++i) { - libyuv::ScaleOffset(ibuf, iw, ih, obuf, ow, oh, offset, false); - } - if (dump_) DumpPlanarYuvTestImage("TestOffsetCopy16_9", obuf, ow, oh); - EXPECT_EQ(-1, FindDiff(obuf + ow * offset, - ibuf, - iw * ih)); - EXPECT_EQ(-1, FindDiff(obuf + ow * oh + ow * offset / 4, - ibuf + iw * ih, - iw * ih / 4)); - EXPECT_EQ(-1, FindDiff(obuf + ow * oh * 5 / 4 + ow * offset / 4, - ibuf + iw * ih * 5 / 4, - iw * ih / 4)); -} - -// The following are 'cpu' flag values: -// Allow all SIMD optimizations -#define ALLFLAGS -1 -// Disable SSSE3 but allow other forms of SIMD (SSE2) -#define NOSSSE3 ~libyuv::kCpuHasSSSE3 -// Disable SSE2 and SSSE3 -#define NOSSE ~libyuv::kCpuHasSSE2 & ~libyuv::kCpuHasSSSE3 - -// TEST_M scale factor with variations of opt, align, int -#define TEST_M(name, iwidth, iheight, owidth, oheight, mse) \ -TEST_F(YuvScalerTest, name##Ref) { \ - double error; \ - EXPECT_TRUE(TestScale(iwidth, iheight, owidth, oheight, \ - 0, true, false, ALLFLAGS, false, 0, &error)); \ - EXPECT_LE(error, mse); \ -} \ -TEST_F(YuvScalerTest, name##OptAligned) { \ - double error; \ - EXPECT_TRUE(TestScale(iwidth, iheight, owidth, oheight, \ - 0, true, true, ALLFLAGS, false, 0, &error)); \ - EXPECT_LE(error, mse); \ -} \ -TEST_F(YuvScalerTest, name##OptUnaligned) { \ - double error; \ - EXPECT_TRUE(TestScale(iwidth, iheight, owidth, oheight, \ - 0, true, true, ALLFLAGS, false, 1, &error)); \ - EXPECT_LE(error, mse); \ -} \ -TEST_F(YuvScalerTest, name##OptSSE2) { \ - double error; \ - EXPECT_TRUE(TestScale(iwidth, iheight, owidth, oheight, \ - 0, true, true, NOSSSE3, false, 0, &error)); \ - EXPECT_LE(error, mse); \ -} \ -TEST_F(YuvScalerTest, name##OptC) { \ - double error; \ - EXPECT_TRUE(TestScale(iwidth, iheight, owidth, oheight, \ - 0, true, true, NOSSE, false, 0, &error)); \ - EXPECT_LE(error, mse); \ -} \ -TEST_F(YuvScalerTest, name##IntRef) { \ - double error; \ - EXPECT_TRUE(TestScale(iwidth, iheight, owidth, oheight, \ - 0, true, false, ALLFLAGS, true, 0, &error)); \ - EXPECT_LE(error, mse); \ -} \ -TEST_F(YuvScalerTest, name##IntOptAligned) { \ - double error; \ - EXPECT_TRUE(TestScale(iwidth, iheight, owidth, oheight, \ - 0, true, true, ALLFLAGS, true, 0, &error)); \ - EXPECT_LE(error, mse); \ -} \ -TEST_F(YuvScalerTest, name##IntOptUnaligned) { \ - double error; \ - EXPECT_TRUE(TestScale(iwidth, iheight, owidth, oheight, \ - 0, true, true, ALLFLAGS, true, 1, &error)); \ - EXPECT_LE(error, mse); \ -} \ -TEST_F(YuvScalerTest, name##IntOptSSE2) { \ - double error; \ - EXPECT_TRUE(TestScale(iwidth, iheight, owidth, oheight, \ - 0, true, true, NOSSSE3, true, 0, &error)); \ - EXPECT_LE(error, mse); \ -} \ -TEST_F(YuvScalerTest, name##IntOptC) { \ - double error; \ - EXPECT_TRUE(TestScale(iwidth, iheight, owidth, oheight, \ - 0, true, true, NOSSE, true, 0, &error)); \ - EXPECT_LE(error, mse); \ -} - -#define TEST_H(name, iwidth, iheight, owidth, oheight, opt, cpu, intr, mse) \ -TEST_F(YuvScalerTest, name) { \ - double error; \ - EXPECT_TRUE(TestScale(iwidth, iheight, owidth, oheight, \ - 0, false, opt, cpu, intr, 0, &error)); \ - EXPECT_LE(error, mse); \ -} - -// Test 4x3 aspect ratio scaling - -// Tests 1/1x scale down. -TEST_M(TestScale4by3Down11, 640, 480, 640, 480, 0) - -// Tests 3/4x scale down. -TEST_M(TestScale4by3Down34, 640, 480, 480, 360, 60) - -// Tests 1/2x scale down. -TEST_M(TestScale4by3Down12, 640, 480, 320, 240, 60) - -// Tests 3/8x scale down. -TEST_M(TestScale4by3Down38, 640, 480, 240, 180, 60) - -// Tests 1/4x scale down.. -TEST_M(TestScale4by3Down14, 640, 480, 160, 120, 60) - -// Tests 3/16x scale down. -TEST_M(TestScale4by3Down316, 640, 480, 120, 90, 120) - -// Tests 1/8x scale down. -TEST_M(TestScale4by3Down18, 640, 480, 80, 60, 150) - -// Tests 2/3x scale down. -TEST_M(TestScale4by3Down23, 480, 360, 320, 240, 60) - -// Tests 4/3x scale up. -TEST_M(TestScale4by3Up43, 480, 360, 640, 480, 60) - -// Tests 2/1x scale up. -TEST_M(TestScale4by3Up21, 320, 240, 640, 480, 60) - -// Tests 4/1x scale up. -TEST_M(TestScale4by3Up41, 160, 120, 640, 480, 80) - -// Test 16x10 aspect ratio scaling - -// Tests 1/1x scale down. -TEST_M(TestScale16by10Down11, 640, 400, 640, 400, 0) - -// Tests 3/4x scale down. -TEST_M(TestScale16by10Down34, 640, 400, 480, 300, 60) - -// Tests 1/2x scale down. -TEST_M(TestScale16by10Down12, 640, 400, 320, 200, 60) - -// Tests 3/8x scale down. -TEST_M(TestScale16by10Down38, 640, 400, 240, 150, 60) - -// Tests 1/4x scale down.. -TEST_M(TestScale16by10Down14, 640, 400, 160, 100, 60) - -// Tests 3/16x scale down. -TEST_M(TestScale16by10Down316, 640, 400, 120, 75, 120) - -// Tests 1/8x scale down. -TEST_M(TestScale16by10Down18, 640, 400, 80, 50, 150) - -// Tests 2/3x scale down. -TEST_M(TestScale16by10Down23, 480, 300, 320, 200, 60) - -// Tests 4/3x scale up. -TEST_M(TestScale16by10Up43, 480, 300, 640, 400, 60) - -// Tests 2/1x scale up. -TEST_M(TestScale16by10Up21, 320, 200, 640, 400, 60) - -// Tests 4/1x scale up. -TEST_M(TestScale16by10Up41, 160, 100, 640, 400, 80) - -// Test 16x9 aspect ratio scaling - -// Tests 1/1x scale down. -TEST_M(TestScaleDown11, 640, 360, 640, 360, 0) - -// Tests 3/4x scale down. -TEST_M(TestScaleDown34, 640, 360, 480, 270, 60) - -// Tests 1/2x scale down. -TEST_M(TestScaleDown12, 640, 360, 320, 180, 60) - -// Tests 3/8x scale down. -TEST_M(TestScaleDown38, 640, 360, 240, 135, 60) - -// Tests 1/4x scale down.. -TEST_M(TestScaleDown14, 640, 360, 160, 90, 60) - -// Tests 3/16x scale down. -TEST_M(TestScaleDown316, 640, 360, 120, 68, 120) - -// Tests 1/8x scale down. -TEST_M(TestScaleDown18, 640, 360, 80, 45, 150) - -// Tests 2/3x scale down. -TEST_M(TestScaleDown23, 480, 270, 320, 180, 60) - -// Tests 4/3x scale up. -TEST_M(TestScaleUp43, 480, 270, 640, 360, 60) - -// Tests 2/1x scale up. -TEST_M(TestScaleUp21, 320, 180, 640, 360, 60) - -// Tests 4/1x scale up. -TEST_M(TestScaleUp41, 160, 90, 640, 360, 80) - -// Test HD 4x3 aspect ratio scaling - -// Tests 1/1x scale down. -TEST_M(TestScaleHD4x3Down11, 1280, 960, 1280, 960, 0) - -// Tests 3/4x scale down. -TEST_M(TestScaleHD4x3Down34, 1280, 960, 960, 720, 60) - -// Tests 1/2x scale down. -TEST_M(TestScaleHD4x3Down12, 1280, 960, 640, 480, 60) - -// Tests 3/8x scale down. -TEST_M(TestScaleHD4x3Down38, 1280, 960, 480, 360, 60) - -// Tests 1/4x scale down.. -TEST_M(TestScaleHD4x3Down14, 1280, 960, 320, 240, 60) - -// Tests 3/16x scale down. -TEST_M(TestScaleHD4x3Down316, 1280, 960, 240, 180, 120) - -// Tests 1/8x scale down. -TEST_M(TestScaleHD4x3Down18, 1280, 960, 160, 120, 150) - -// Tests 2/3x scale down. -TEST_M(TestScaleHD4x3Down23, 960, 720, 640, 480, 60) - -// Tests 4/3x scale up. -TEST_M(TestScaleHD4x3Up43, 960, 720, 1280, 960, 60) - -// Tests 2/1x scale up. -TEST_M(TestScaleHD4x3Up21, 640, 480, 1280, 960, 60) - -// Tests 4/1x scale up. -TEST_M(TestScaleHD4x3Up41, 320, 240, 1280, 960, 80) - -// Test HD 16x10 aspect ratio scaling - -// Tests 1/1x scale down. -TEST_M(TestScaleHD16x10Down11, 1280, 800, 1280, 800, 0) - -// Tests 3/4x scale down. -TEST_M(TestScaleHD16x10Down34, 1280, 800, 960, 600, 60) - -// Tests 1/2x scale down. -TEST_M(TestScaleHD16x10Down12, 1280, 800, 640, 400, 60) - -// Tests 3/8x scale down. -TEST_M(TestScaleHD16x10Down38, 1280, 800, 480, 300, 60) - -// Tests 1/4x scale down.. -TEST_M(TestScaleHD16x10Down14, 1280, 800, 320, 200, 60) - -// Tests 3/16x scale down. -TEST_M(TestScaleHD16x10Down316, 1280, 800, 240, 150, 120) - -// Tests 1/8x scale down. -TEST_M(TestScaleHD16x10Down18, 1280, 800, 160, 100, 150) - -// Tests 2/3x scale down. -TEST_M(TestScaleHD16x10Down23, 960, 600, 640, 400, 60) - -// Tests 4/3x scale up. -TEST_M(TestScaleHD16x10Up43, 960, 600, 1280, 800, 60) - -// Tests 2/1x scale up. -TEST_M(TestScaleHD16x10Up21, 640, 400, 1280, 800, 60) - -// Tests 4/1x scale up. -TEST_M(TestScaleHD16x10Up41, 320, 200, 1280, 800, 80) - -// Test HD 16x9 aspect ratio scaling - -// Tests 1/1x scale down. -TEST_M(TestScaleHDDown11, 1280, 720, 1280, 720, 0) - -// Tests 3/4x scale down. -TEST_M(TestScaleHDDown34, 1280, 720, 960, 540, 60) - -// Tests 1/2x scale down. -TEST_M(TestScaleHDDown12, 1280, 720, 640, 360, 60) - -// Tests 3/8x scale down. -TEST_M(TestScaleHDDown38, 1280, 720, 480, 270, 60) - -// Tests 1/4x scale down.. -TEST_M(TestScaleHDDown14, 1280, 720, 320, 180, 60) - -// Tests 3/16x scale down. -TEST_M(TestScaleHDDown316, 1280, 720, 240, 135, 120) - -// Tests 1/8x scale down. -TEST_M(TestScaleHDDown18, 1280, 720, 160, 90, 150) - -// Tests 2/3x scale down. -TEST_M(TestScaleHDDown23, 960, 540, 640, 360, 60) - -// Tests 4/3x scale up. -TEST_M(TestScaleHDUp43, 960, 540, 1280, 720, 60) - -// Tests 2/1x scale up. -TEST_M(TestScaleHDUp21, 640, 360, 1280, 720, 60) - -// Tests 4/1x scale up. -TEST_M(TestScaleHDUp41, 320, 180, 1280, 720, 80) - -// Tests 1366x768 resolution for comparison to chromium scaler_bench -TEST_M(TestScaleHDUp1366, 1280, 720, 1366, 768, 10) - -// Tests odd source/dest sizes. 3 less to make chroma odd as well. -TEST_M(TestScaleHDUp1363, 1277, 717, 1363, 765, 10) - -// Tests 1/2x scale down, using optimized algorithm. -TEST_M(TestScaleOddDown12, 180, 100, 90, 50, 50) - -// Tests bilinear scale down -TEST_M(TestScaleOddDownBilin, 160, 100, 90, 50, 120) - -// Test huge buffer scales that are expected to use a different code path -// that avoids stack overflow but still work using point sampling. -// Max output size is 640 wide. - -// Tests interpolated 1/8x scale down, using optimized algorithm. -TEST_H(TestScaleDown18HDOptInt, 6144, 48, 768, 6, true, ALLFLAGS, true, 1) - -// Tests interpolated 1/8x scale down, using c_only optimized algorithm. -TEST_H(TestScaleDown18HDCOnlyOptInt, 6144, 48, 768, 6, true, NOSSE, true, 1) - -// Tests interpolated 3/8x scale down, using optimized algorithm. -TEST_H(TestScaleDown38HDOptInt, 2048, 16, 768, 6, true, ALLFLAGS, true, 1) - -// Tests interpolated 3/8x scale down, using no SSSE3 optimized algorithm. -TEST_H(TestScaleDown38HDNoSSSE3OptInt, 2048, 16, 768, 6, true, NOSSSE3, true, 1) - -// Tests interpolated 3/8x scale down, using c_only optimized algorithm. -TEST_H(TestScaleDown38HDCOnlyOptInt, 2048, 16, 768, 6, true, NOSSE, true, 1) - -// Tests interpolated 3/16x scale down, using optimized algorithm. -TEST_H(TestScaleDown316HDOptInt, 4096, 32, 768, 6, true, ALLFLAGS, true, 1) - -// Tests interpolated 3/16x scale down, using no SSSE3 optimized algorithm. -TEST_H(TestScaleDown316HDNoSSSE3OptInt, 4096, 32, 768, 6, true, NOSSSE3, true, - 1) - -// Tests interpolated 3/16x scale down, using c_only optimized algorithm. -TEST_H(TestScaleDown316HDCOnlyOptInt, 4096, 32, 768, 6, true, NOSSE, true, 1) - -// Test special sizes dont crash -// Tests scaling down to 1 pixel width -TEST_H(TestScaleDown1x6OptInt, 3, 24, 1, 6, true, ALLFLAGS, true, 4) - -// Tests scaling down to 1 pixel height -TEST_H(TestScaleDown6x1OptInt, 24, 3, 6, 1, true, ALLFLAGS, true, 4) - -// Tests scaling up from 1 pixel width -TEST_H(TestScaleUp1x6OptInt, 1, 6, 3, 24, true, ALLFLAGS, true, 4) - -// Tests scaling up from 1 pixel height -TEST_H(TestScaleUp6x1OptInt, 6, 1, 24, 3, true, ALLFLAGS, true, 4) - -// Test performance of a range of box filter scale sizes - -// Tests interpolated 1/2x scale down, using optimized algorithm. -TEST_H(TestScaleDown2xHDOptInt, 1280, 720, 1280 / 2, 720 / 2, true, ALLFLAGS, - true, 1) - -// Tests interpolated 1/3x scale down, using optimized algorithm. -TEST_H(TestScaleDown3xHDOptInt, 1280, 720, 1280 / 3, 720 / 3, true, ALLFLAGS, - true, 1) - -// Tests interpolated 1/4x scale down, using optimized algorithm. -TEST_H(TestScaleDown4xHDOptInt, 1280, 720, 1280 / 4, 720 / 4, true, ALLFLAGS, - true, 1) - -// Tests interpolated 1/5x scale down, using optimized algorithm. -TEST_H(TestScaleDown5xHDOptInt, 1280, 720, 1280 / 5, 720 / 5, true, ALLFLAGS, - true, 1) - -// Tests interpolated 1/6x scale down, using optimized algorithm. -TEST_H(TestScaleDown6xHDOptInt, 1280, 720, 1280 / 6, 720 / 6, true, ALLFLAGS, - true, 1) - -// Tests interpolated 1/7x scale down, using optimized algorithm. -TEST_H(TestScaleDown7xHDOptInt, 1280, 720, 1280 / 7, 720 / 7, true, ALLFLAGS, - true, 1) - -// Tests interpolated 1/8x scale down, using optimized algorithm. -TEST_H(TestScaleDown8xHDOptInt, 1280, 720, 1280 / 8, 720 / 8, true, ALLFLAGS, - true, 1) - -// Tests interpolated 1/8x scale down, using optimized algorithm. -TEST_H(TestScaleDown9xHDOptInt, 1280, 720, 1280 / 9, 720 / 9, true, ALLFLAGS, - true, 1) - -// Tests interpolated 1/8x scale down, using optimized algorithm. -TEST_H(TestScaleDown10xHDOptInt, 1280, 720, 1280 / 10, 720 / 10, true, ALLFLAGS, - true, 1)