15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/base_paths.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/cpu.h"
71320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "base/files/file_util.h"
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h"
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/path_service.h"
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "media/base/djb2.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "media/base/simd/convert_rgb_to_yuv.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "media/base/simd/convert_yuv_to_rgb.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "media/base/simd/filter_yuv.h"
14010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#include "media/base/simd/yuv_to_rgb_table.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "media/base/yuv_convert.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "testing/gtest/include/gtest/gtest.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gfx/rect.h"
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Size of raw image.
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const int kSourceWidth = 640;
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const int kSourceHeight = 360;
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const int kSourceYSize = kSourceWidth * kSourceHeight;
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const int kSourceUOffset = kSourceYSize;
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const int kSourceVOffset = kSourceYSize * 5 / 4;
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const int kScaledWidth = 1024;
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const int kScaledHeight = 768;
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const int kDownScaledWidth = 512;
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const int kDownScaledHeight = 320;
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const int kBpp = 4;
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Surface sizes for various test files.
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const int kYUV12Size = kSourceYSize * 12 / 8;
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const int kYUV16Size = kSourceYSize * 16 / 8;
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const int kYUY2Size =  kSourceYSize * 16 / 8;
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const int kRGBSize = kSourceYSize * kBpp;
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const int kRGBSizeScaled = kScaledWidth * kScaledHeight * kBpp;
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const int kRGB24Size = kSourceYSize * 3;
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const int kRGBSizeConverted = kSourceYSize * kBpp;
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
400de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)#if !defined(ARCH_CPU_ARM_FAMILY) && !defined(ARCH_CPU_MIPS_FAMILY)
410de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)static const int kSourceAOffset = kSourceYSize * 12 / 8;
420de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)static const int kYUVA12Size = kSourceYSize * 20 / 8;
430de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)#endif
440de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)
45c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Helper for reading test data into a scoped_ptr<uint8[]>.
462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)static void ReadData(const base::FilePath::CharType* filename,
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     int expected_size,
48c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                     scoped_ptr<uint8[]>* data) {
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  data->reset(new uint8[expected_size]);
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::FilePath path;
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CHECK(PathService::Get(base::DIR_SOURCE_ROOT, &path));
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  path = path.Append(FILE_PATH_LITERAL("media"))
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             .Append(FILE_PATH_LITERAL("test"))
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             .Append(FILE_PATH_LITERAL("data"))
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             .Append(filename);
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Verify file size is correct.
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int64 actual_size = 0;
60a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  base::GetFileSize(path, &actual_size);
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CHECK_EQ(actual_size, expected_size);
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Verify bytes read are correct.
64a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  int bytes_read = base::ReadFile(
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      path, reinterpret_cast<char*>(data->get()), expected_size);
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CHECK_EQ(bytes_read, expected_size);
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
69c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)static void ReadYV12Data(scoped_ptr<uint8[]>* data) {
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ReadData(FILE_PATH_LITERAL("bali_640x360_P420.yuv"), kYUV12Size, data);
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
73c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)static void ReadYV16Data(scoped_ptr<uint8[]>* data) {
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ReadData(FILE_PATH_LITERAL("bali_640x360_P422.yuv"), kYUV16Size, data);
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
770de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)#if !defined(ARCH_CPU_ARM_FAMILY) && !defined(ARCH_CPU_MIPS_FAMILY)
780de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)static void ReadYV12AData(scoped_ptr<uint8[]>* data) {
790de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)  ReadData(FILE_PATH_LITERAL("bali_640x360_P420_alpha.yuv"), kYUVA12Size, data);
800de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)}
810de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)#endif
820de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)
83c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)static void ReadRGB24Data(scoped_ptr<uint8[]>* data) {
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ReadData(FILE_PATH_LITERAL("bali_640x360_RGB24.rgb"), kRGB24Size, data);
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
87c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)static void ReadYUY2Data(scoped_ptr<uint8[]>* data) {
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ReadData(FILE_PATH_LITERAL("bali_640x360_YUY2.yuv"), kYUY2Size, data);
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
91eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#if defined(OS_ANDROID)
92eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// Helper for swapping red and blue channels of RGBA or BGRA.
93eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochstatic void SwapRedAndBlueChannels(unsigned char* pixels, size_t buffer_size) {
94eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  for (size_t i = 0; i < buffer_size; i += 4) {
95eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    std::swap(pixels[i], pixels[i + 2]);
96eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
97eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
98eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#endif
99eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
10090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)namespace media {
10190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(YUVConvertTest, YV12) {
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Allocate all surfaces.
104c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scoped_ptr<uint8[]> yuv_bytes;
105c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scoped_ptr<uint8[]> rgb_bytes(new uint8[kRGBSize]);
106c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scoped_ptr<uint8[]> rgb_converted_bytes(new uint8[kRGBSizeConverted]);
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Read YUV reference data from file.
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ReadYV12Data(&yuv_bytes);
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Convert a frame of YUV to 32 bit ARGB.
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  media::ConvertYUVToRGB32(yuv_bytes.get(),
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           yuv_bytes.get() + kSourceUOffset,
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           yuv_bytes.get() + kSourceVOffset,
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           rgb_converted_bytes.get(),            // RGB output
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           kSourceWidth, kSourceHeight,          // Dimensions
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           kSourceWidth,                         // YStride
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           kSourceWidth / 2,                     // UVStride
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           kSourceWidth * kBpp,                  // RGBStride
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           media::YV12);
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
122eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#if defined(OS_ANDROID)
123eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  SwapRedAndBlueChannels(rgb_converted_bytes.get(), kRGBSizeConverted);
124eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#endif
125eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  uint32 rgb_hash = DJB2Hash(rgb_converted_bytes.get(), kRGBSizeConverted,
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             kDJB2HashSeed);
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(2413171226u, rgb_hash);
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(YUVConvertTest, YV16) {
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Allocate all surfaces.
133c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scoped_ptr<uint8[]> yuv_bytes;
134c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scoped_ptr<uint8[]> rgb_bytes(new uint8[kRGBSize]);
135c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scoped_ptr<uint8[]> rgb_converted_bytes(new uint8[kRGBSizeConverted]);
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Read YUV reference data from file.
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ReadYV16Data(&yuv_bytes);
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Convert a frame of YUV to 32 bit ARGB.
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  media::ConvertYUVToRGB32(yuv_bytes.get(),                        // Y
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           yuv_bytes.get() + kSourceUOffset,       // U
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           yuv_bytes.get() + kSourceYSize * 3 / 2, // V
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           rgb_converted_bytes.get(),              // RGB output
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           kSourceWidth, kSourceHeight,            // Dimensions
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           kSourceWidth,                           // YStride
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           kSourceWidth / 2,                       // UVStride
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           kSourceWidth * kBpp,                    // RGBStride
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           media::YV16);
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
151eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#if defined(OS_ANDROID)
152eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  SwapRedAndBlueChannels(rgb_converted_bytes.get(), kRGBSizeConverted);
153eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#endif
154eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  uint32 rgb_hash = DJB2Hash(rgb_converted_bytes.get(), kRGBSizeConverted,
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             kDJB2HashSeed);
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(4222342047u, rgb_hash);
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct YUVScaleTestData {
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  YUVScaleTestData(media::YUVType y, media::ScaleFilter s, uint32 r)
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : yuv_type(y),
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        scale_filter(s),
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        rgb_hash(r) {
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  media::YUVType yuv_type;
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  media::ScaleFilter scale_filter;
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  uint32 rgb_hash;
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class YUVScaleTest : public ::testing::TestWithParam<YUVScaleTestData> {
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  YUVScaleTest() {
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    switch (GetParam().yuv_type) {
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case media::YV12:
177010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      case media::YV12J:
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        ReadYV12Data(&yuv_bytes_);
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case media::YV16:
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        ReadYV16Data(&yuv_bytes_);
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    rgb_bytes_.reset(new uint8[kRGBSizeScaled]);
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Helpers for getting the proper Y, U and V plane offsets.
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  uint8* y_plane() { return yuv_bytes_.get(); }
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  uint8* u_plane() { return yuv_bytes_.get() + kSourceYSize; }
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  uint8* v_plane() {
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    switch (GetParam().yuv_type) {
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case media::YV12:
194010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      case media::YV12J:
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return yuv_bytes_.get() + kSourceVOffset;
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case media::YV16:
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return yuv_bytes_.get() + kSourceYSize * 3 / 2;
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return NULL;
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
202c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scoped_ptr<uint8[]> yuv_bytes_;
203c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scoped_ptr<uint8[]> rgb_bytes_;
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_P(YUVScaleTest, NoScale) {
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  media::ScaleYUVToRGB32(y_plane(),                    // Y
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         u_plane(),                    // U
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         v_plane(),                    // V
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         rgb_bytes_.get(),             // RGB output
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         kSourceWidth, kSourceHeight,  // Dimensions
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         kSourceWidth, kSourceHeight,  // Dimensions
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         kSourceWidth,                 // YStride
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         kSourceWidth / 2,             // UvStride
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         kSourceWidth * kBpp,          // RgbStride
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         GetParam().yuv_type,
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         media::ROTATE_0,
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         GetParam().scale_filter);
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  uint32 yuv_hash = DJB2Hash(rgb_bytes_.get(), kRGBSize, kDJB2HashSeed);
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  media::ConvertYUVToRGB32(y_plane(),                    // Y
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           u_plane(),                    // U
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           v_plane(),                    // V
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           rgb_bytes_.get(),             // RGB output
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           kSourceWidth, kSourceHeight,  // Dimensions
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           kSourceWidth,                 // YStride
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           kSourceWidth / 2,             // UVStride
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           kSourceWidth * kBpp,          // RGBStride
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           GetParam().yuv_type);
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  uint32 rgb_hash = DJB2Hash(rgb_bytes_.get(), kRGBSize, kDJB2HashSeed);
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(yuv_hash, rgb_hash);
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_P(YUVScaleTest, Normal) {
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  media::ScaleYUVToRGB32(y_plane(),                    // Y
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         u_plane(),                    // U
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         v_plane(),                    // V
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         rgb_bytes_.get(),             // RGB output
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         kSourceWidth, kSourceHeight,  // Dimensions
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         kScaledWidth, kScaledHeight,  // Dimensions
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         kSourceWidth,                 // YStride
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         kSourceWidth / 2,             // UvStride
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         kScaledWidth * kBpp,          // RgbStride
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         GetParam().yuv_type,
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         media::ROTATE_0,
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         GetParam().scale_filter);
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
251eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#if defined(OS_ANDROID)
252eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  SwapRedAndBlueChannels(rgb_bytes_.get(), kRGBSizeScaled);
253eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#endif
254eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  uint32 rgb_hash = DJB2Hash(rgb_bytes_.get(), kRGBSizeScaled, kDJB2HashSeed);
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(GetParam().rgb_hash, rgb_hash);
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_P(YUVScaleTest, ZeroSourceSize) {
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  media::ScaleYUVToRGB32(y_plane(),                    // Y
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         u_plane(),                    // U
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         v_plane(),                    // V
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         rgb_bytes_.get(),             // RGB output
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         0, 0,                         // Dimensions
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         kScaledWidth, kScaledHeight,  // Dimensions
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         kSourceWidth,                 // YStride
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         kSourceWidth / 2,             // UvStride
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         kScaledWidth * kBpp,          // RgbStride
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         GetParam().yuv_type,
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         media::ROTATE_0,
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         GetParam().scale_filter);
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Testing for out-of-bound read/writes with AddressSanitizer.
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_P(YUVScaleTest, ZeroDestinationSize) {
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  media::ScaleYUVToRGB32(y_plane(),                    // Y
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         u_plane(),                    // U
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         v_plane(),                    // V
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         rgb_bytes_.get(),             // RGB output
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         kSourceWidth, kSourceHeight,  // Dimensions
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         0, 0,                         // Dimensions
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         kSourceWidth,                 // YStride
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         kSourceWidth / 2,             // UvStride
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         kScaledWidth * kBpp,          // RgbStride
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         GetParam().yuv_type,
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         media::ROTATE_0,
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         GetParam().scale_filter);
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Testing for out-of-bound read/writes with AddressSanitizer.
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_P(YUVScaleTest, OddWidthAndHeightNotCrash) {
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  media::ScaleYUVToRGB32(y_plane(),                    // Y
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         u_plane(),                    // U
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         v_plane(),                    // V
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         rgb_bytes_.get(),             // RGB output
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         kSourceWidth, kSourceHeight,  // Dimensions
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         3, 3,                         // Dimensions
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         kSourceWidth,                 // YStride
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         kSourceWidth / 2,             // UvStride
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         kScaledWidth * kBpp,          // RgbStride
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         GetParam().yuv_type,
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         media::ROTATE_0,
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         GetParam().scale_filter);
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)INSTANTIATE_TEST_CASE_P(
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    YUVScaleFormats, YUVScaleTest,
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ::testing::Values(
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        YUVScaleTestData(media::YV12, media::FILTER_NONE, 4136904952u),
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        YUVScaleTestData(media::YV16, media::FILTER_NONE, 1501777547u),
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        YUVScaleTestData(media::YV12, media::FILTER_BILINEAR, 3164274689u),
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        YUVScaleTestData(media::YV16, media::FILTER_BILINEAR, 3095878046u)));
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This tests a known worst case YUV value, and for overflow.
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(YUVConvertTest, Clamp) {
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Allocate all surfaces.
319c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scoped_ptr<uint8[]> yuv_bytes(new uint8[1]);
320c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scoped_ptr<uint8[]> rgb_bytes(new uint8[1]);
321c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scoped_ptr<uint8[]> rgb_converted_bytes(new uint8[1]);
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Values that failed previously in bug report.
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unsigned char y = 255u;
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unsigned char u = 255u;
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unsigned char v = 19u;
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Prefill extra large destination buffer to test for overflow.
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unsigned char rgb[8] = { 0, 1, 2, 3, 4, 5, 6, 7 };
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unsigned char expected[8] = { 255, 255, 104, 255, 4, 5, 6, 7 };
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Convert a frame of YUV to 32 bit ARGB.
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  media::ConvertYUVToRGB32(&y,       // Y
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           &u,       // U
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           &v,       // V
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           &rgb[0],  // RGB output
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           1, 1,     // Dimensions
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           0,        // YStride
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           0,        // UVStride
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           0,        // RGBStride
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           media::YV12);
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
342eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#if defined(OS_ANDROID)
343eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  SwapRedAndBlueChannels(rgb, kBpp);
344eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#endif
345eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int expected_test = memcmp(rgb, expected, sizeof(expected));
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(0, expected_test);
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(YUVConvertTest, RGB24ToYUV) {
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Allocate all surfaces.
352c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scoped_ptr<uint8[]> rgb_bytes;
353c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scoped_ptr<uint8[]> yuv_converted_bytes(new uint8[kYUV12Size]);
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Read RGB24 reference data from file.
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ReadRGB24Data(&rgb_bytes);
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Convert to I420.
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  media::ConvertRGB24ToYUV(rgb_bytes.get(),
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           yuv_converted_bytes.get(),
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           yuv_converted_bytes.get() + kSourceUOffset,
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           yuv_converted_bytes.get() + kSourceVOffset,
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           kSourceWidth, kSourceHeight,        // Dimensions
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           kSourceWidth * 3,                   // RGBStride
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           kSourceWidth,                       // YStride
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           kSourceWidth / 2);                  // UVStride
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  uint32 rgb_hash = DJB2Hash(yuv_converted_bytes.get(), kYUV12Size,
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             kDJB2HashSeed);
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(320824432u, rgb_hash);
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(YUVConvertTest, RGB32ToYUV) {
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Allocate all surfaces.
375c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scoped_ptr<uint8[]> yuv_bytes(new uint8[kYUV12Size]);
376c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scoped_ptr<uint8[]> rgb_bytes(new uint8[kRGBSize]);
377c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scoped_ptr<uint8[]> yuv_converted_bytes(new uint8[kYUV12Size]);
378c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scoped_ptr<uint8[]> rgb_converted_bytes(new uint8[kRGBSize]);
3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Read YUV reference data from file.
3812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::FilePath yuv_url;
3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(PathService::Get(base::DIR_SOURCE_ROOT, &yuv_url));
3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  yuv_url = yuv_url.Append(FILE_PATH_LITERAL("media"))
3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   .Append(FILE_PATH_LITERAL("test"))
3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   .Append(FILE_PATH_LITERAL("data"))
3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   .Append(FILE_PATH_LITERAL("bali_640x360_P420.yuv"));
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(static_cast<int>(kYUV12Size),
388a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)            base::ReadFile(yuv_url,
389a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                           reinterpret_cast<char*>(yuv_bytes.get()),
390a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                           static_cast<int>(kYUV12Size)));
3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Convert a frame of YUV to 32 bit ARGB.
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  media::ConvertYUVToRGB32(yuv_bytes.get(),
3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           yuv_bytes.get() + kSourceUOffset,
3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           yuv_bytes.get() + kSourceVOffset,
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           rgb_bytes.get(),            // RGB output
3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           kSourceWidth, kSourceHeight,          // Dimensions
3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           kSourceWidth,                         // YStride
3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           kSourceWidth / 2,                     // UVStride
4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           kSourceWidth * kBpp,                  // RGBStride
4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           media::YV12);
4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Convert RGB32 to YV12.
4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  media::ConvertRGB32ToYUV(rgb_bytes.get(),
4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           yuv_converted_bytes.get(),
4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           yuv_converted_bytes.get() + kSourceUOffset,
4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           yuv_converted_bytes.get() + kSourceVOffset,
4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           kSourceWidth, kSourceHeight,        // Dimensions
4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           kSourceWidth * 4,                   // RGBStride
4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           kSourceWidth,                       // YStride
4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           kSourceWidth / 2);                  // UVStride
4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Convert YV12 back to RGB32.
4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  media::ConvertYUVToRGB32(yuv_converted_bytes.get(),
4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           yuv_converted_bytes.get() + kSourceUOffset,
4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           yuv_converted_bytes.get() + kSourceVOffset,
4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           rgb_converted_bytes.get(),            // RGB output
4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           kSourceWidth, kSourceHeight,          // Dimensions
4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           kSourceWidth,                         // YStride
4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           kSourceWidth / 2,                     // UVStride
4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           kSourceWidth * kBpp,                  // RGBStride
4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           media::YV12);
4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int error = 0;
4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < kRGBSize; ++i) {
4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int diff = rgb_converted_bytes[i] - rgb_bytes[i];
4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (diff < 0)
4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      diff = -diff;
4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    error += diff;
4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Make sure error is within bound.
4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DVLOG(1) << "Average error per channel: " << error / kRGBSize;
4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_GT(5, error / kRGBSize);
4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(YUVConvertTest, YUY2ToYUV) {
4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Allocate all surfaces.
439c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scoped_ptr<uint8[]> yuy_bytes;
440c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scoped_ptr<uint8[]> yuv_converted_bytes(new uint8[kYUV12Size]);
4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Read YUY reference data from file.
4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ReadYUY2Data(&yuy_bytes);
4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Convert to I420.
4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  media::ConvertYUY2ToYUV(yuy_bytes.get(),
4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                          yuv_converted_bytes.get(),
4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                          yuv_converted_bytes.get() + kSourceUOffset,
4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                          yuv_converted_bytes.get() + kSourceVOffset,
4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                          kSourceWidth, kSourceHeight);
4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  uint32 yuy_hash = DJB2Hash(yuv_converted_bytes.get(), kYUV12Size,
4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             kDJB2HashSeed);
4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(666823187u, yuy_hash);
4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(YUVConvertTest, DownScaleYUVToRGB32WithRect) {
4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Read YUV reference data from file.
4592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::FilePath yuv_url;
4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(PathService::Get(base::DIR_SOURCE_ROOT, &yuv_url));
4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  yuv_url = yuv_url.Append(FILE_PATH_LITERAL("media"))
4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   .Append(FILE_PATH_LITERAL("test"))
4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   .Append(FILE_PATH_LITERAL("data"))
4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   .Append(FILE_PATH_LITERAL("bali_640x360_P420.yuv"));
4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const size_t size_of_yuv = kSourceYSize * 12 / 8;  // 12 bpp.
466c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scoped_ptr<uint8[]> yuv_bytes(new uint8[size_of_yuv]);
4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(static_cast<int>(size_of_yuv),
468a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)            base::ReadFile(yuv_url,
469a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                           reinterpret_cast<char*>(yuv_bytes.get()),
470a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                           static_cast<int>(size_of_yuv)));
4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Scale the full frame of YUV to 32 bit ARGB.
4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The API currently only supports down-scaling, so we don't test up-scaling.
4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const size_t size_of_rgb_scaled = kDownScaledWidth * kDownScaledHeight * kBpp;
475c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scoped_ptr<uint8[]> rgb_scaled_bytes(new uint8[size_of_rgb_scaled]);
4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gfx::Rect sub_rect(0, 0, kDownScaledWidth, kDownScaledHeight);
4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We can't compare with the full-frame scaler because it uses slightly
4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // different sampling coordinates.
4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  media::ScaleYUVToRGB32WithRect(
4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      yuv_bytes.get(),                          // Y
4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      yuv_bytes.get() + kSourceUOffset,         // U
4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      yuv_bytes.get() + kSourceVOffset,         // V
4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      rgb_scaled_bytes.get(),                   // Rgb output
4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      kSourceWidth, kSourceHeight,              // Dimensions
4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      kDownScaledWidth, kDownScaledHeight,      // Dimensions
4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      sub_rect.x(), sub_rect.y(),               // Dest rect
4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      sub_rect.right(), sub_rect.bottom(),      // Dest rect
4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      kSourceWidth,                             // YStride
4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      kSourceWidth / 2,                         // UvStride
4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      kDownScaledWidth * kBpp);                 // RgbStride
4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  uint32 rgb_hash_full_rect = DJB2Hash(rgb_scaled_bytes.get(),
4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                       size_of_rgb_scaled,
4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                       kDJB2HashSeed);
4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Re-scale sub-rectangles and verify the results are the same.
4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int next_sub_rect = 0;
4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  while (!sub_rect.IsEmpty()) {
5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Scale a partial rectangle.
5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    media::ScaleYUVToRGB32WithRect(
5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        yuv_bytes.get(),                          // Y
5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        yuv_bytes.get() + kSourceUOffset,         // U
5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        yuv_bytes.get() + kSourceVOffset,         // V
5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        rgb_scaled_bytes.get(),                   // Rgb output
5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        kSourceWidth, kSourceHeight,              // Dimensions
5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        kDownScaledWidth, kDownScaledHeight,      // Dimensions
5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        sub_rect.x(), sub_rect.y(),               // Dest rect
5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        sub_rect.right(), sub_rect.bottom(),      // Dest rect
5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        kSourceWidth,                             // YStride
5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        kSourceWidth / 2,                         // UvStride
5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        kDownScaledWidth * kBpp);                 // RgbStride
5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    uint32 rgb_hash_sub_rect = DJB2Hash(rgb_scaled_bytes.get(),
5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                        size_of_rgb_scaled,
5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                        kDJB2HashSeed);
5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(rgb_hash_full_rect, rgb_hash_sub_rect);
5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Now pick choose a quarter rect of this sub-rect.
5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (next_sub_rect & 1)
5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      sub_rect.set_x(sub_rect.x() + sub_rect.width() / 2);
5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (next_sub_rect & 2)
5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      sub_rect.set_y(sub_rect.y() + sub_rect.height() / 2);
5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    sub_rect.set_width(sub_rect.width() / 2);
5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    sub_rect.set_height(sub_rect.height() / 2);
5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    next_sub_rect++;
5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
530c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#if !defined(ARCH_CPU_ARM_FAMILY) && !defined(ARCH_CPU_MIPS_FAMILY)
5310de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)TEST(YUVConvertTest, YUVAtoARGB_MMX_MatchReference) {
5320de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)  // Allocate all surfaces.
5330de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)  scoped_ptr<uint8[]> yuv_bytes;
5340de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)  scoped_ptr<uint8[]> rgb_bytes(new uint8[kRGBSize]);
5350de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)  scoped_ptr<uint8[]> rgb_converted_bytes(new uint8[kRGBSizeConverted]);
5360de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)  scoped_ptr<uint8[]> rgb_converted_bytes_ref(new uint8[kRGBSizeConverted]);
5370de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)
5380de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)  // Read YUV reference data from file.
5390de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)  ReadYV12AData(&yuv_bytes);
5400de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)
5410de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)  // Convert a frame of YUV to 32 bit ARGB using both C and MMX versions.
5420de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)  media::ConvertYUVAToARGB_C(yuv_bytes.get(),
5430de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)                             yuv_bytes.get() + kSourceUOffset,
5440de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)                             yuv_bytes.get() + kSourceVOffset,
5450de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)                             yuv_bytes.get() + kSourceAOffset,
5460de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)                             rgb_converted_bytes_ref.get(),
5470de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)                             kSourceWidth,
5480de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)                             kSourceHeight,
5490de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)                             kSourceWidth,
5500de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)                             kSourceWidth / 2,
5510de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)                             kSourceWidth,
5520de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)                             kSourceWidth * kBpp,
5530de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)                             media::YV12);
5540de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)  media::ConvertYUVAToARGB_MMX(yuv_bytes.get(),
5550de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)                               yuv_bytes.get() + kSourceUOffset,
5560de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)                               yuv_bytes.get() + kSourceVOffset,
5570de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)                               yuv_bytes.get() + kSourceAOffset,
5580de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)                               rgb_converted_bytes.get(),
5590de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)                               kSourceWidth,
5600de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)                               kSourceHeight,
5610de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)                               kSourceWidth,
5620de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)                               kSourceWidth / 2,
5630de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)                               kSourceWidth,
5640de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)                               kSourceWidth * kBpp,
5650de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)                               media::YV12);
5660de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)
5670de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)  EXPECT_EQ(0,
5680de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)            memcmp(rgb_converted_bytes.get(),
5690de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)                   rgb_converted_bytes_ref.get(),
5700de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)                   kRGBSizeConverted));
5710de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)}
5720de6073388f4e2780db8536178b129cd8f6ab386Torne (Richard Coles)
5735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(YUVConvertTest, RGB32ToYUV_SSE2_MatchReference) {
5745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::CPU cpu;
5755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!cpu.has_sse2()) {
5765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(WARNING) << "System doesn't support SSE2, test not executed.";
5775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
5785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Allocate all surfaces.
581c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scoped_ptr<uint8[]> yuv_bytes(new uint8[kYUV12Size]);
582c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scoped_ptr<uint8[]> rgb_bytes(new uint8[kRGBSize]);
583c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scoped_ptr<uint8[]> yuv_converted_bytes(new uint8[kYUV12Size]);
584c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scoped_ptr<uint8[]> yuv_reference_bytes(new uint8[kYUV12Size]);
5855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ReadYV12Data(&yuv_bytes);
5875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Convert a frame of YUV to 32 bit ARGB.
5895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  media::ConvertYUVToRGB32(
5905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      yuv_bytes.get(),
5915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      yuv_bytes.get() + kSourceUOffset,
5925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      yuv_bytes.get() + kSourceVOffset,
5935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      rgb_bytes.get(),            // RGB output
5945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      kSourceWidth, kSourceHeight,          // Dimensions
5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      kSourceWidth,                         // YStride
5965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      kSourceWidth / 2,                     // UVStride
5975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      kSourceWidth * kBpp,                  // RGBStride
5985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      media::YV12);
5995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Convert RGB32 to YV12 with SSE2 version.
6015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  media::ConvertRGB32ToYUV_SSE2(
6025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      rgb_bytes.get(),
6035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      yuv_converted_bytes.get(),
6045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      yuv_converted_bytes.get() + kSourceUOffset,
6055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      yuv_converted_bytes.get() + kSourceVOffset,
6065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      kSourceWidth, kSourceHeight,        // Dimensions
6075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      kSourceWidth * 4,                   // RGBStride
6085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      kSourceWidth,                       // YStride
6095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      kSourceWidth / 2);                  // UVStride
6105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Convert RGB32 to YV12 with reference version.
6125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  media::ConvertRGB32ToYUV_SSE2_Reference(
6135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      rgb_bytes.get(),
6145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      yuv_reference_bytes.get(),
6155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      yuv_reference_bytes.get() + kSourceUOffset,
6165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      yuv_reference_bytes.get() + kSourceVOffset,
6175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      kSourceWidth, kSourceHeight,        // Dimensions
6185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      kSourceWidth * 4,                   // RGBStride
6195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      kSourceWidth,                       // YStride
6205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      kSourceWidth / 2);                  // UVStride
6215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Now convert a odd width and height, this overrides part of the buffer
6235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // generated above but that is fine because the point of this test is to
6245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // match the result with the reference code.
6255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Convert RGB32 to YV12 with SSE2 version.
6275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  media::ConvertRGB32ToYUV_SSE2(
6285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      rgb_bytes.get(),
6295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      yuv_converted_bytes.get(),
6305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      yuv_converted_bytes.get() + kSourceUOffset,
6315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      yuv_converted_bytes.get() + kSourceVOffset,
6325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      7, 7,                               // Dimensions
6335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      kSourceWidth * 4,                   // RGBStride
6345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      kSourceWidth,                       // YStride
6355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      kSourceWidth / 2);                  // UVStride
6365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Convert RGB32 to YV12 with reference version.
6385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  media::ConvertRGB32ToYUV_SSE2_Reference(
6395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      rgb_bytes.get(),
6405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      yuv_reference_bytes.get(),
6415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      yuv_reference_bytes.get() + kSourceUOffset,
6425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      yuv_reference_bytes.get() + kSourceVOffset,
6435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      7, 7,                               // Dimensions
6445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      kSourceWidth * 4,                   // RGBStride
6455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      kSourceWidth,                       // YStride
6465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      kSourceWidth / 2);                  // UVStride
6475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int error = 0;
6495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < kYUV12Size; ++i) {
6505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int diff = yuv_reference_bytes[i] - yuv_converted_bytes[i];
6515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (diff < 0)
6525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      diff = -diff;
6535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    error += diff;
6545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Make sure there's no difference from the reference.
6575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(0, error);
6585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(YUVConvertTest, ConvertYUVToRGB32Row_SSE) {
6615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::CPU cpu;
6625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!cpu.has_sse()) {
6635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(WARNING) << "System not supported. Test skipped.";
6645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
6655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
667c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scoped_ptr<uint8[]> yuv_bytes(new uint8[kYUV12Size]);
668c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scoped_ptr<uint8[]> rgb_bytes_reference(new uint8[kRGBSize]);
669c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scoped_ptr<uint8[]> rgb_bytes_converted(new uint8[kRGBSize]);
6705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ReadYV12Data(&yuv_bytes);
6715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const int kWidth = 167;
6735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ConvertYUVToRGB32Row_C(yuv_bytes.get(),
6745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         yuv_bytes.get() + kSourceUOffset,
6755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         yuv_bytes.get() + kSourceVOffset,
6765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         rgb_bytes_reference.get(),
677010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                         kWidth,
678010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                         GetLookupTable(YV12));
6795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ConvertYUVToRGB32Row_SSE(yuv_bytes.get(),
6805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           yuv_bytes.get() + kSourceUOffset,
6815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           yuv_bytes.get() + kSourceVOffset,
6825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           rgb_bytes_converted.get(),
683010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                           kWidth,
684010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                           GetLookupTable(YV12));
6855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  media::EmptyRegisterState();
6865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(0, memcmp(rgb_bytes_reference.get(),
6875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      rgb_bytes_converted.get(),
6885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      kWidth * kBpp));
6895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6911320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// 64-bit release + component builds on Windows are too smart and optimizes
6921320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// away the function being tested.
6931320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#if defined(OS_WIN) && (defined(ARCH_CPU_X86) || !defined(COMPONENT_BUILD))
6945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(YUVConvertTest, ScaleYUVToRGB32Row_SSE) {
6955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::CPU cpu;
6965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!cpu.has_sse()) {
6975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(WARNING) << "System not supported. Test skipped.";
6985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
6995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
701c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scoped_ptr<uint8[]> yuv_bytes(new uint8[kYUV12Size]);
702c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scoped_ptr<uint8[]> rgb_bytes_reference(new uint8[kRGBSize]);
703c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scoped_ptr<uint8[]> rgb_bytes_converted(new uint8[kRGBSize]);
7045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ReadYV12Data(&yuv_bytes);
7055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const int kWidth = 167;
7075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const int kSourceDx = 80000;  // This value means a scale down.
7085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ScaleYUVToRGB32Row_C(yuv_bytes.get(),
7095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       yuv_bytes.get() + kSourceUOffset,
7105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       yuv_bytes.get() + kSourceVOffset,
7115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       rgb_bytes_reference.get(),
7125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       kWidth,
713010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                       kSourceDx,
714010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                       GetLookupTable(YV12));
7155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ScaleYUVToRGB32Row_SSE(yuv_bytes.get(),
7165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         yuv_bytes.get() + kSourceUOffset,
7175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         yuv_bytes.get() + kSourceVOffset,
7185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         rgb_bytes_converted.get(),
7195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         kWidth,
720010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                         kSourceDx,
721010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                         GetLookupTable(YV12));
7225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  media::EmptyRegisterState();
7235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(0, memcmp(rgb_bytes_reference.get(),
7245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      rgb_bytes_converted.get(),
7255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      kWidth * kBpp));
7265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(YUVConvertTest, LinearScaleYUVToRGB32Row_SSE) {
7295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::CPU cpu;
7305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!cpu.has_sse()) {
7315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(WARNING) << "System not supported. Test skipped.";
7325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
7335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
735c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scoped_ptr<uint8[]> yuv_bytes(new uint8[kYUV12Size]);
736c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scoped_ptr<uint8[]> rgb_bytes_reference(new uint8[kRGBSize]);
737c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scoped_ptr<uint8[]> rgb_bytes_converted(new uint8[kRGBSize]);
7385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ReadYV12Data(&yuv_bytes);
7395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const int kWidth = 167;
7415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const int kSourceDx = 80000;  // This value means a scale down.
7425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LinearScaleYUVToRGB32Row_C(yuv_bytes.get(),
7435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             yuv_bytes.get() + kSourceUOffset,
7445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             yuv_bytes.get() + kSourceVOffset,
7455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             rgb_bytes_reference.get(),
7465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             kWidth,
747010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                             kSourceDx,
748010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                             GetLookupTable(YV12));
7495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LinearScaleYUVToRGB32Row_SSE(yuv_bytes.get(),
7505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               yuv_bytes.get() + kSourceUOffset,
7515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               yuv_bytes.get() + kSourceVOffset,
7525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               rgb_bytes_converted.get(),
7535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               kWidth,
754010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                               kSourceDx,
755010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                               GetLookupTable(YV12));
7565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  media::EmptyRegisterState();
7575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(0, memcmp(rgb_bytes_reference.get(),
7585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      rgb_bytes_converted.get(),
7595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      kWidth * kBpp));
7605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7611320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#endif  // defined(OS_WIN) && (ARCH_CPU_X86 || COMPONENT_BUILD)
7625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(YUVConvertTest, FilterYUVRows_C_OutOfBounds) {
764c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scoped_ptr<uint8[]> src(new uint8[16]);
765c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scoped_ptr<uint8[]> dst(new uint8[16]);
7665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memset(src.get(), 0xff, 16);
7685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memset(dst.get(), 0, 16);
7695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  media::FilterYUVRows_C(dst.get(), src.get(), src.get(), 1, 255);
7715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(255u, dst[0]);
7735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 1; i < 16; ++i) {
7745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(0u, dst[i]) << " not equal at " << i;
7755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(YUVConvertTest, FilterYUVRows_SSE2_OutOfBounds) {
7795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::CPU cpu;
7805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!cpu.has_sse2()) {
7815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(WARNING) << "System not supported. Test skipped.";
7825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
7835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
785c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scoped_ptr<uint8[]> src(new uint8[16]);
786c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scoped_ptr<uint8[]> dst(new uint8[16]);
7875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memset(src.get(), 0xff, 16);
7895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memset(dst.get(), 0, 16);
7905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  media::FilterYUVRows_SSE2(dst.get(), src.get(), src.get(), 1, 255);
7925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(255u, dst[0]);
7945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 1; i < 16; ++i) {
7955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(0u, dst[i]);
7965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(YUVConvertTest, FilterYUVRows_SSE2_UnalignedDestination) {
8005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::CPU cpu;
8015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!cpu.has_sse2()) {
8025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(WARNING) << "System not supported. Test skipped.";
8035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
8045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const int kSize = 64;
807c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scoped_ptr<uint8[]> src(new uint8[kSize]);
808c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scoped_ptr<uint8[]> dst_sample(new uint8[kSize]);
809c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scoped_ptr<uint8[]> dst(new uint8[kSize]);
8105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memset(dst_sample.get(), 0, kSize);
8125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memset(dst.get(), 0, kSize);
8135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < kSize; ++i)
8145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    src[i] = 100 + i;
8155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  media::FilterYUVRows_C(dst_sample.get(),
8175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         src.get(), src.get(), 37, 128);
8185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Generate an unaligned output address.
8205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  uint8* dst_ptr =
8215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      reinterpret_cast<uint8*>(
8225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          (reinterpret_cast<uintptr_t>(dst.get() + 16) & ~15) + 1);
8235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  media::FilterYUVRows_SSE2(dst_ptr, src.get(), src.get(), 37, 128);
8245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  media::EmptyRegisterState();
8255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(0, memcmp(dst_sample.get(), dst_ptr, 37));
8275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(ARCH_CPU_X86_64)
8305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(YUVConvertTest, ScaleYUVToRGB32Row_SSE2_X64) {
832c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scoped_ptr<uint8[]> yuv_bytes(new uint8[kYUV12Size]);
833c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scoped_ptr<uint8[]> rgb_bytes_reference(new uint8[kRGBSize]);
834c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scoped_ptr<uint8[]> rgb_bytes_converted(new uint8[kRGBSize]);
8355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ReadYV12Data(&yuv_bytes);
8365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const int kWidth = 167;
8385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const int kSourceDx = 80000;  // This value means a scale down.
8395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ScaleYUVToRGB32Row_C(yuv_bytes.get(),
8405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       yuv_bytes.get() + kSourceUOffset,
8415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       yuv_bytes.get() + kSourceVOffset,
8425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       rgb_bytes_reference.get(),
8435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       kWidth,
844010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                       kSourceDx,
845010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                       GetLookupTable(YV12));
8465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ScaleYUVToRGB32Row_SSE2_X64(yuv_bytes.get(),
8475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              yuv_bytes.get() + kSourceUOffset,
8485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              yuv_bytes.get() + kSourceVOffset,
8495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              rgb_bytes_converted.get(),
8505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              kWidth,
851010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                              kSourceDx,
852010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                              GetLookupTable(YV12));
8535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  media::EmptyRegisterState();
8545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(0, memcmp(rgb_bytes_reference.get(),
8555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      rgb_bytes_converted.get(),
8565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      kWidth * kBpp));
8575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(YUVConvertTest, LinearScaleYUVToRGB32Row_MMX_X64) {
860c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scoped_ptr<uint8[]> yuv_bytes(new uint8[kYUV12Size]);
861c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scoped_ptr<uint8[]> rgb_bytes_reference(new uint8[kRGBSize]);
862c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scoped_ptr<uint8[]> rgb_bytes_converted(new uint8[kRGBSize]);
8635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ReadYV12Data(&yuv_bytes);
8645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const int kWidth = 167;
8665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const int kSourceDx = 80000;  // This value means a scale down.
8675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LinearScaleYUVToRGB32Row_C(yuv_bytes.get(),
8685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             yuv_bytes.get() + kSourceUOffset,
8695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             yuv_bytes.get() + kSourceVOffset,
8705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             rgb_bytes_reference.get(),
8715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             kWidth,
872010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                             kSourceDx,
873010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                             GetLookupTable(YV12));
8745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LinearScaleYUVToRGB32Row_MMX_X64(yuv_bytes.get(),
8755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   yuv_bytes.get() + kSourceUOffset,
8765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   yuv_bytes.get() + kSourceVOffset,
8775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   rgb_bytes_converted.get(),
8785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   kWidth,
879010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                                   kSourceDx,
880010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                                   GetLookupTable(YV12));
8815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  media::EmptyRegisterState();
8825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(0, memcmp(rgb_bytes_reference.get(),
8835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      rgb_bytes_converted.get(),
8845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      kWidth * kBpp));
8855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif  // defined(ARCH_CPU_X86_64)
8885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif  // defined(ARCH_CPU_X86_FAMILY)
89090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
89190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}  // namespace media
892