Home | History | Annotate | Download | only in base
      1 // Copyright 2014 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "base/base_paths.h"
      6 #include "base/cpu.h"
      7 #include "base/files/file_util.h"
      8 #include "base/logging.h"
      9 #include "base/path_service.h"
     10 #include "base/time/time.h"
     11 #include "media/base/simd/convert_yuv_to_rgb.h"
     12 #include "media/base/yuv_convert.h"
     13 #include "testing/gtest/include/gtest/gtest.h"
     14 #include "testing/perf/perf_test.h"
     15 
     16 namespace media {
     17 #if !defined(ARCH_CPU_ARM_FAMILY) && !defined(ARCH_CPU_MIPS_FAMILY)
     18 // Size of raw image.
     19 static const int kSourceWidth = 640;
     20 static const int kSourceHeight = 360;
     21 static const int kSourceYSize = kSourceWidth * kSourceHeight;
     22 static const int kSourceUOffset = kSourceYSize;
     23 static const int kSourceVOffset = kSourceYSize * 5 / 4;
     24 static const int kBpp = 4;
     25 
     26 // Width of the row to convert. Odd so that we exercise the ending
     27 // one-pixel-leftover case.
     28 static const int kWidth = 639;
     29 
     30 // Surface sizes for various test files.
     31 static const int kYUV12Size = kSourceYSize * 12 / 8;
     32 static const int kRGBSize = kSourceYSize * kBpp;
     33 
     34 static const int kPerfTestIterations = 2000;
     35 
     36 class YUVConvertPerfTest : public testing::Test {
     37  public:
     38   YUVConvertPerfTest()
     39       : yuv_bytes_(new uint8[kYUV12Size]),
     40         rgb_bytes_converted_(new uint8[kRGBSize]) {
     41     base::FilePath path;
     42     CHECK(PathService::Get(base::DIR_SOURCE_ROOT, &path));
     43     path = path.Append(FILE_PATH_LITERAL("media"))
     44                .Append(FILE_PATH_LITERAL("test"))
     45                .Append(FILE_PATH_LITERAL("data"))
     46                .Append(FILE_PATH_LITERAL("bali_640x360_P420.yuv"));
     47 
     48     // Verify file size is correct.
     49     int64 actual_size = 0;
     50     base::GetFileSize(path, &actual_size);
     51     CHECK_EQ(actual_size, kYUV12Size);
     52 
     53     // Verify bytes read are correct.
     54     int bytes_read = base::ReadFile(
     55         path, reinterpret_cast<char*>(yuv_bytes_.get()), kYUV12Size);
     56 
     57     CHECK_EQ(bytes_read, kYUV12Size);
     58   }
     59 
     60   scoped_ptr<uint8[]> yuv_bytes_;
     61   scoped_ptr<uint8[]> rgb_bytes_converted_;
     62 
     63  private:
     64   DISALLOW_COPY_AND_ASSIGN(YUVConvertPerfTest);
     65 };
     66 
     67 TEST_F(YUVConvertPerfTest, ConvertYUVToRGB32Row_SSE) {
     68   ASSERT_TRUE(base::CPU().has_sse());
     69 
     70   base::TimeTicks start = base::TimeTicks::HighResNow();
     71   for (int i = 0; i < kPerfTestIterations; ++i) {
     72     for (int row = 0; row < kSourceHeight; ++row) {
     73       int chroma_row = row / 2;
     74       ConvertYUVToRGB32Row_SSE(
     75           yuv_bytes_.get() + row * kSourceWidth,
     76           yuv_bytes_.get() + kSourceUOffset + (chroma_row * kSourceWidth / 2),
     77           yuv_bytes_.get() + kSourceVOffset + (chroma_row * kSourceWidth / 2),
     78           rgb_bytes_converted_.get(),
     79           kWidth,
     80           GetLookupTable(YV12));
     81     }
     82   }
     83   double total_time_seconds =
     84       (base::TimeTicks::HighResNow() - start).InSecondsF();
     85   perf_test::PrintResult(
     86       "yuv_convert_perftest", "", "ConvertYUVToRGB32Row_SSE",
     87       kPerfTestIterations / total_time_seconds, "runs/s", true);
     88   media::EmptyRegisterState();
     89 }
     90 
     91 // 64-bit release + component builds on Windows are too smart and optimizes
     92 // away the function being tested.
     93 #if defined(OS_WIN) && (defined(ARCH_CPU_X86) || !defined(COMPONENT_BUILD))
     94 TEST_F(YUVConvertPerfTest, ScaleYUVToRGB32Row_SSE) {
     95   ASSERT_TRUE(base::CPU().has_sse());
     96 
     97   const int kSourceDx = 80000;  // This value means a scale down.
     98 
     99   base::TimeTicks start = base::TimeTicks::HighResNow();
    100   for (int i = 0; i < kPerfTestIterations; ++i) {
    101     for (int row = 0; row < kSourceHeight; ++row) {
    102       int chroma_row = row / 2;
    103       ScaleYUVToRGB32Row_SSE(
    104           yuv_bytes_.get() + row * kSourceWidth,
    105           yuv_bytes_.get() + kSourceUOffset + (chroma_row * kSourceWidth / 2),
    106           yuv_bytes_.get() + kSourceVOffset + (chroma_row * kSourceWidth / 2),
    107           rgb_bytes_converted_.get(),
    108           kWidth,
    109           kSourceDx,
    110           GetLookupTable(YV12));
    111     }
    112   }
    113   double total_time_seconds =
    114       (base::TimeTicks::HighResNow() - start).InSecondsF();
    115   perf_test::PrintResult(
    116       "yuv_convert_perftest", "", "ScaleYUVToRGB32Row_SSE",
    117       kPerfTestIterations / total_time_seconds, "runs/s", true);
    118   media::EmptyRegisterState();
    119 }
    120 
    121 TEST_F(YUVConvertPerfTest, LinearScaleYUVToRGB32Row_SSE) {
    122   ASSERT_TRUE(base::CPU().has_sse());
    123 
    124   const int kSourceDx = 80000;  // This value means a scale down.
    125 
    126   base::TimeTicks start = base::TimeTicks::HighResNow();
    127   for (int i = 0; i < kPerfTestIterations; ++i) {
    128     for (int row = 0; row < kSourceHeight; ++row) {
    129       int chroma_row = row / 2;
    130       LinearScaleYUVToRGB32Row_SSE(
    131           yuv_bytes_.get() + row * kSourceWidth,
    132           yuv_bytes_.get() + kSourceUOffset + (chroma_row * kSourceWidth / 2),
    133           yuv_bytes_.get() + kSourceVOffset + (chroma_row * kSourceWidth / 2),
    134           rgb_bytes_converted_.get(),
    135           kWidth,
    136           kSourceDx,
    137           GetLookupTable(YV12));
    138     }
    139   }
    140   double total_time_seconds =
    141       (base::TimeTicks::HighResNow() - start).InSecondsF();
    142   perf_test::PrintResult(
    143       "yuv_convert_perftest", "", "LinearScaleYUVToRGB32Row_SSE",
    144       kPerfTestIterations / total_time_seconds, "runs/s", true);
    145   media::EmptyRegisterState();
    146 }
    147 #endif  // defined(OS_WIN) && (ARCH_CPU_X86 || COMPONENT_BUILD)
    148 
    149 #endif  // !defined(ARCH_CPU_ARM_FAMILY) && !defined(ARCH_CPU_MIPS_FAMILY)
    150 
    151 }  // namespace media
    152