15c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu// Copyright 2014 The Chromium Authors. All rights reserved. 25c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu// Use of this source code is governed by a BSD-style license that can be 35c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu// found in the LICENSE file. 45c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 55c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "base/base_paths.h" 65c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "base/cpu.h" 71320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "base/files/file_util.h" 85c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "base/logging.h" 95c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "base/path_service.h" 105c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "base/time/time.h" 115c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "media/base/simd/convert_yuv_to_rgb.h" 125c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "media/base/yuv_convert.h" 135c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "testing/gtest/include/gtest/gtest.h" 145c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "testing/perf/perf_test.h" 155c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 165c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liunamespace media { 175c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#if !defined(ARCH_CPU_ARM_FAMILY) && !defined(ARCH_CPU_MIPS_FAMILY) 185c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu// Size of raw image. 195c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liustatic const int kSourceWidth = 640; 205c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liustatic const int kSourceHeight = 360; 215c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liustatic const int kSourceYSize = kSourceWidth * kSourceHeight; 225c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liustatic const int kSourceUOffset = kSourceYSize; 235c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liustatic const int kSourceVOffset = kSourceYSize * 5 / 4; 245c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liustatic const int kBpp = 4; 255c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 265c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu// Width of the row to convert. Odd so that we exercise the ending 275c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu// one-pixel-leftover case. 285c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liustatic const int kWidth = 639; 295c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 305c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu// Surface sizes for various test files. 315c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liustatic const int kYUV12Size = kSourceYSize * 12 / 8; 325c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liustatic const int kRGBSize = kSourceYSize * kBpp; 335c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 345c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liustatic const int kPerfTestIterations = 2000; 355c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 365c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liuclass YUVConvertPerfTest : public testing::Test { 375c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu public: 385c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu YUVConvertPerfTest() 395c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu : yuv_bytes_(new uint8[kYUV12Size]), 405c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu rgb_bytes_converted_(new uint8[kRGBSize]) { 415c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu base::FilePath path; 425c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu CHECK(PathService::Get(base::DIR_SOURCE_ROOT, &path)); 435c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu path = path.Append(FILE_PATH_LITERAL("media")) 445c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu .Append(FILE_PATH_LITERAL("test")) 455c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu .Append(FILE_PATH_LITERAL("data")) 465c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu .Append(FILE_PATH_LITERAL("bali_640x360_P420.yuv")); 475c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 485c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu // Verify file size is correct. 495c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu int64 actual_size = 0; 505c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu base::GetFileSize(path, &actual_size); 515c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu CHECK_EQ(actual_size, kYUV12Size); 525c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 535c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu // Verify bytes read are correct. 545c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu int bytes_read = base::ReadFile( 555c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu path, reinterpret_cast<char*>(yuv_bytes_.get()), kYUV12Size); 565c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 575c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu CHECK_EQ(bytes_read, kYUV12Size); 585c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu } 595c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 605c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu scoped_ptr<uint8[]> yuv_bytes_; 615c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu scoped_ptr<uint8[]> rgb_bytes_converted_; 625c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 635c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu private: 645c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu DISALLOW_COPY_AND_ASSIGN(YUVConvertPerfTest); 655c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu}; 665c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 675c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo LiuTEST_F(YUVConvertPerfTest, ConvertYUVToRGB32Row_SSE) { 685c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu ASSERT_TRUE(base::CPU().has_sse()); 695c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 705c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu base::TimeTicks start = base::TimeTicks::HighResNow(); 715c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu for (int i = 0; i < kPerfTestIterations; ++i) { 725c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu for (int row = 0; row < kSourceHeight; ++row) { 735c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu int chroma_row = row / 2; 745c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu ConvertYUVToRGB32Row_SSE( 755c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu yuv_bytes_.get() + row * kSourceWidth, 765c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu yuv_bytes_.get() + kSourceUOffset + (chroma_row * kSourceWidth / 2), 775c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu yuv_bytes_.get() + kSourceVOffset + (chroma_row * kSourceWidth / 2), 785c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu rgb_bytes_converted_.get(), 79010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) kWidth, 80010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) GetLookupTable(YV12)); 815c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu } 825c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu } 835c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu double total_time_seconds = 845c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu (base::TimeTicks::HighResNow() - start).InSecondsF(); 855c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu perf_test::PrintResult( 865c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu "yuv_convert_perftest", "", "ConvertYUVToRGB32Row_SSE", 875c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu kPerfTestIterations / total_time_seconds, "runs/s", true); 885c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu media::EmptyRegisterState(); 895c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu} 905c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 911320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// 64-bit release + component builds on Windows are too smart and optimizes 921320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// away the function being tested. 931320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#if defined(OS_WIN) && (defined(ARCH_CPU_X86) || !defined(COMPONENT_BUILD)) 945c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo LiuTEST_F(YUVConvertPerfTest, ScaleYUVToRGB32Row_SSE) { 955c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu ASSERT_TRUE(base::CPU().has_sse()); 965c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 975c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu const int kSourceDx = 80000; // This value means a scale down. 985c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 995c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu base::TimeTicks start = base::TimeTicks::HighResNow(); 1005c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu for (int i = 0; i < kPerfTestIterations; ++i) { 1015c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu for (int row = 0; row < kSourceHeight; ++row) { 1025c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu int chroma_row = row / 2; 1035c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu ScaleYUVToRGB32Row_SSE( 1045c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu yuv_bytes_.get() + row * kSourceWidth, 1055c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu yuv_bytes_.get() + kSourceUOffset + (chroma_row * kSourceWidth / 2), 1065c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu yuv_bytes_.get() + kSourceVOffset + (chroma_row * kSourceWidth / 2), 1075c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu rgb_bytes_converted_.get(), 1085c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu kWidth, 109010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) kSourceDx, 110010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) GetLookupTable(YV12)); 1115c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu } 1125c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu } 1135c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu double total_time_seconds = 1145c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu (base::TimeTicks::HighResNow() - start).InSecondsF(); 1155c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu perf_test::PrintResult( 1165c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu "yuv_convert_perftest", "", "ScaleYUVToRGB32Row_SSE", 1175c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu kPerfTestIterations / total_time_seconds, "runs/s", true); 1185c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu media::EmptyRegisterState(); 1195c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu} 1205c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 1215c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo LiuTEST_F(YUVConvertPerfTest, LinearScaleYUVToRGB32Row_SSE) { 1225c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu ASSERT_TRUE(base::CPU().has_sse()); 1235c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 1245c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu const int kSourceDx = 80000; // This value means a scale down. 1255c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 1265c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu base::TimeTicks start = base::TimeTicks::HighResNow(); 1275c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu for (int i = 0; i < kPerfTestIterations; ++i) { 1285c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu for (int row = 0; row < kSourceHeight; ++row) { 1295c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu int chroma_row = row / 2; 1305c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu LinearScaleYUVToRGB32Row_SSE( 1315c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu yuv_bytes_.get() + row * kSourceWidth, 1325c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu yuv_bytes_.get() + kSourceUOffset + (chroma_row * kSourceWidth / 2), 1335c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu yuv_bytes_.get() + kSourceVOffset + (chroma_row * kSourceWidth / 2), 1345c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu rgb_bytes_converted_.get(), 1355c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu kWidth, 136010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) kSourceDx, 137010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) GetLookupTable(YV12)); 1385c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu } 1395c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu } 1405c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu double total_time_seconds = 1415c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu (base::TimeTicks::HighResNow() - start).InSecondsF(); 1425c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu perf_test::PrintResult( 1435c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu "yuv_convert_perftest", "", "LinearScaleYUVToRGB32Row_SSE", 1445c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu kPerfTestIterations / total_time_seconds, "runs/s", true); 1455c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu media::EmptyRegisterState(); 1465c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu} 1471320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#endif // defined(OS_WIN) && (ARCH_CPU_X86 || COMPONENT_BUILD) 1485c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 1495c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#endif // !defined(ARCH_CPU_ARM_FAMILY) && !defined(ARCH_CPU_MIPS_FAMILY) 1505c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 1515c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu} // namespace media 152