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