| OLD | NEW |
| 1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "base/base_paths.h" | 5 #include "base/base_paths.h" |
| 6 #include "base/file_util.h" | 6 #include "base/file_util.h" |
| 7 #include "media/base/yuv_convert.h" | 7 #include "media/base/yuv_convert.h" |
| 8 #include "media/base/yuv_row.h" | 8 #include "media/base/yuv_row.h" |
| 9 #include "testing/gtest/include/gtest/gtest.h" | 9 #include "testing/gtest/include/gtest/gtest.h" |
| 10 | 10 |
| 11 // Reference images were created with the following steps | 11 // Reference images were created with the following steps |
| 12 // ffmpeg -vframes 25 -i bali.mov -vcodec rawvideo -pix_fmt yuv420p -an | 12 // ffmpeg -vframes 25 -i bali.mov -vcodec rawvideo -pix_fmt yuv420p -an |
| 13 // bali.yv12.1280_720.yuv | 13 // bali.yv12.1280_720.yuv |
| 14 // yuvhalf -yv12 -skip 24 bali.yv12.1280_720.yuv bali.yv12.640_360.yuv | 14 // yuvhalf -yv12 -skip 24 bali.yv12.1280_720.yuv bali.yv12.640_360.yuv |
| 15 | 15 |
| 16 // ffmpeg -vframes 25 -i bali.mov -vcodec rawvideo -pix_fmt yuv422p -an | 16 // ffmpeg -vframes 25 -i bali.mov -vcodec rawvideo -pix_fmt yuv422p -an |
| 17 // bali.yv16.1280_720.yuv | 17 // bali.yv16.1280_720.yuv |
| 18 // yuvhalf -yv16 -skip 24 bali.yv16.1280_720.yuv bali.yv16.640_360.yuv | 18 // yuvhalf -yv16 -skip 24 bali.yv16.1280_720.yuv bali.yv16.640_360.yuv |
| 19 // Size of raw image. | 19 // Size of raw image. |
| 20 | 20 |
| 21 // Size of raw image. |
| 21 static const int kWidth = 640; | 22 static const int kWidth = 640; |
| 22 static const int kHeight = 360; | 23 static const int kHeight = 360; |
| 24 static const int kScaledWidth = 1024; |
| 25 static const int kScaledHeight = 768; |
| 23 static const int kBpp = 4; | 26 static const int kBpp = 4; |
| 24 | 27 |
| 25 // Surface sizes. | 28 // Surface sizes. |
| 26 static const size_t kYUV12Size = kWidth * kHeight * 12 / 8; | 29 static const size_t kYUV12Size = kWidth * kHeight * 12 / 8; |
| 27 static const size_t kYUV16Size = kWidth * kHeight * 16 / 8; | 30 static const size_t kYUV16Size = kWidth * kHeight * 16 / 8; |
| 28 static const size_t kRGBSize = kWidth * kHeight * kBpp; | 31 static const size_t kRGBSize = kWidth * kHeight * kBpp; |
| 29 static const size_t kRGBSizeConverted = kWidth * kHeight * kBpp; | 32 static const size_t kRGBSizeConverted = kWidth * kHeight * kBpp; |
| 30 | 33 |
| 34 namespace { |
| 35 // DJB2 hash |
| 36 unsigned int hash(unsigned char *s, size_t len, unsigned int hash = 5381) { |
| 37 while (len--) |
| 38 hash = hash * 33 + *s++; |
| 39 return hash; |
| 40 } |
| 41 } |
| 42 |
| 31 TEST(YUVConvertTest, YV12) { | 43 TEST(YUVConvertTest, YV12) { |
| 32 // Allocate all surfaces. | 44 // Allocate all surfaces. |
| 33 scoped_array<uint8> yuv_bytes(new uint8[kYUV12Size]); | 45 scoped_array<uint8> yuv_bytes(new uint8[kYUV12Size]); |
| 34 scoped_array<uint8> rgb_bytes(new uint8[kRGBSize]); | 46 scoped_array<uint8> rgb_bytes(new uint8[kRGBSize]); |
| 35 scoped_array<uint8> rgb_converted_bytes(new uint8[kRGBSizeConverted]); | 47 scoped_array<uint8> rgb_converted_bytes(new uint8[kRGBSizeConverted]); |
| 36 | 48 |
| 37 // Read YUV reference data from file. | 49 // Read YUV reference data from file. |
| 38 FilePath yuv_url; | 50 FilePath yuv_url; |
| 39 EXPECT_TRUE(PathService::Get(base::DIR_SOURCE_ROOT, &yuv_url)); | 51 EXPECT_TRUE(PathService::Get(base::DIR_SOURCE_ROOT, &yuv_url)); |
| 40 yuv_url = yuv_url.Append(FILE_PATH_LITERAL("media")) | 52 yuv_url = yuv_url.Append(FILE_PATH_LITERAL("media")) |
| 41 .Append(FILE_PATH_LITERAL("test")) | 53 .Append(FILE_PATH_LITERAL("test")) |
| 42 .Append(FILE_PATH_LITERAL("data")) | 54 .Append(FILE_PATH_LITERAL("data")) |
| 43 .Append(FILE_PATH_LITERAL("bali.yv12.640_360.yuv")); | 55 .Append(FILE_PATH_LITERAL("bali.yv12.640_360.yuv")); |
| 44 EXPECT_EQ(static_cast<int>(kYUV12Size), | 56 EXPECT_EQ(static_cast<int>(kYUV12Size), |
| 45 file_util::ReadFile(yuv_url, | 57 file_util::ReadFile(yuv_url, |
| 46 reinterpret_cast<char*>(yuv_bytes.get()), | 58 reinterpret_cast<char*>(yuv_bytes.get()), |
| 47 static_cast<int>(kYUV12Size))); | 59 static_cast<int>(kYUV12Size))); |
| 48 | 60 |
| 49 // Read RGB reference data from file. | 61 // Convert a frame of YUV to 32 bit ARGB. |
| 50 FilePath rgb_url; | 62 media::ConvertYUVToRGB32(yuv_bytes.get(), // Y |
| 51 EXPECT_TRUE(PathService::Get(base::DIR_SOURCE_ROOT, &rgb_url)); | 63 yuv_bytes.get() + kWidth * kHeight, // U |
| 52 rgb_url = rgb_url.Append(FILE_PATH_LITERAL("media")) | 64 yuv_bytes.get() + kWidth * kHeight * 5 / 4, // V |
| 53 .Append(FILE_PATH_LITERAL("test")) | 65 rgb_converted_bytes.get(), // RGB output |
| 54 .Append(FILE_PATH_LITERAL("data")) | 66 kWidth, kHeight, // Dimensions |
| 55 .Append(FILE_PATH_LITERAL("bali.yv12.640_360.rgb")); | 67 kWidth, // YStride |
| 56 EXPECT_EQ(static_cast<int>(kRGBSize), | 68 kWidth / 2, // UVStride |
| 57 file_util::ReadFile(rgb_url, | 69 kWidth * kBpp, // RGBStride |
| 58 reinterpret_cast<char*>(rgb_bytes.get()), | 70 media::YV12); |
| 59 static_cast<int>(kRGBSize))); | |
| 60 | 71 |
| 61 // Convert a frame of YUV to 32 bit ARGB. | 72 unsigned int rgb_hash = hash(rgb_converted_bytes.get(), kRGBSizeConverted); |
| 62 media::ConvertYV12ToRGB32(yuv_bytes.get(), // Y | |
| 63 yuv_bytes.get() + kWidth * kHeight, // U | |
| 64 yuv_bytes.get() + kWidth * kHeight * 5 / 4, // V | |
| 65 rgb_converted_bytes.get(), // RGB output | |
| 66 kWidth, kHeight, // Dimensions | |
| 67 kWidth, // YStride | |
| 68 kWidth / 2, // UVStride | |
| 69 kWidth * kBpp); // RGBStride | |
| 70 | 73 |
| 71 // TODO(fbarchard): The reference image was converted with MMX. | 74 // To get this hash value, run once and examine the following EXPECT_EQ. |
| 72 // Non-MMX implementations do not match exactly. In the future, | 75 // Then plug new hash value into EXPECT_EQ statements. |
| 73 // Mac and Linux will use MMX as well and the unittest will be | 76 |
| 74 // activated automatically. | 77 // TODO(fbarchard): Make reference code mimic MMX exactly |
| 75 #if USE_MMX | 78 #if USE_MMX |
| 76 // Compare converted YUV to reference conversion file. | 79 EXPECT_EQ(2413171226u, rgb_hash); |
| 77 int rgb_diff = memcmp(rgb_converted_bytes.get(), rgb_bytes.get(), kRGBSize); | 80 #else |
| 78 | 81 EXPECT_EQ(2936300063u, rgb_hash); |
| 79 EXPECT_EQ(0, rgb_diff); | |
| 80 #endif | 82 #endif |
| 81 return; // This is here to allow you to put a break point on this line | 83 return; // This is here to allow you to put a break point on this line |
| 82 } | 84 } |
| 83 | 85 |
| 84 TEST(YUVConvertTest, YV16) { | 86 TEST(YUVConvertTest, YV16) { |
| 85 // Allocate all surfaces. | 87 // Allocate all surfaces. |
| 86 scoped_array<uint8> yuv_bytes(new uint8[kYUV16Size]); | 88 scoped_array<uint8> yuv_bytes(new uint8[kYUV16Size]); |
| 87 scoped_array<uint8> rgb_bytes(new uint8[kRGBSize]); | 89 scoped_array<uint8> rgb_bytes(new uint8[kRGBSize]); |
| 88 scoped_array<uint8> rgb_converted_bytes(new uint8[kRGBSizeConverted]); | 90 scoped_array<uint8> rgb_converted_bytes(new uint8[kRGBSizeConverted]); |
| 89 | 91 |
| 90 // Read YV16 reference data from file. | 92 // Read YV16 reference data from file. |
| 91 FilePath yuv_url; | 93 FilePath yuv_url; |
| 92 EXPECT_TRUE(PathService::Get(base::DIR_SOURCE_ROOT, &yuv_url)); | 94 EXPECT_TRUE(PathService::Get(base::DIR_SOURCE_ROOT, &yuv_url)); |
| 93 yuv_url = yuv_url.Append(FILE_PATH_LITERAL("media")) | 95 yuv_url = yuv_url.Append(FILE_PATH_LITERAL("media")) |
| 94 .Append(FILE_PATH_LITERAL("test")) | 96 .Append(FILE_PATH_LITERAL("test")) |
| 95 .Append(FILE_PATH_LITERAL("data")) | 97 .Append(FILE_PATH_LITERAL("data")) |
| 96 .Append(FILE_PATH_LITERAL("bali.yv16.640_360.yuv")); | 98 .Append(FILE_PATH_LITERAL("bali.yv16.640_360.yuv")); |
| 97 EXPECT_EQ(static_cast<int>(kYUV16Size), | 99 EXPECT_EQ(static_cast<int>(kYUV16Size), |
| 98 file_util::ReadFile(yuv_url, | 100 file_util::ReadFile(yuv_url, |
| 99 reinterpret_cast<char*>(yuv_bytes.get()), | 101 reinterpret_cast<char*>(yuv_bytes.get()), |
| 100 static_cast<int>(kYUV16Size))); | 102 static_cast<int>(kYUV16Size))); |
| 101 | 103 |
| 102 // Read RGB reference data from file. | 104 // Convert a frame of YUV to 32 bit ARGB. |
| 103 FilePath rgb_url; | 105 media::ConvertYUVToRGB32(yuv_bytes.get(), // Y |
| 104 EXPECT_TRUE(PathService::Get(base::DIR_SOURCE_ROOT, &rgb_url)); | 106 yuv_bytes.get() + kWidth * kHeight, // U |
| 105 rgb_url = rgb_url.Append(FILE_PATH_LITERAL("media")) | 107 yuv_bytes.get() + kWidth * kHeight * 3 / 2, // V |
| 108 rgb_converted_bytes.get(), // RGB output |
| 109 kWidth, kHeight, // Dimensions |
| 110 kWidth, // YStride |
| 111 kWidth / 2, // UVStride |
| 112 kWidth * kBpp, // RGBStride |
| 113 media::YV16); |
| 114 |
| 115 unsigned int rgb_hash = hash(rgb_converted_bytes.get(), kRGBSizeConverted); |
| 116 |
| 117 // To get this hash value, run once and examine the following EXPECT_EQ. |
| 118 // Then plug new hash value into EXPECT_EQ statements. |
| 119 |
| 120 // TODO(fbarchard): Make reference code mimic MMX exactly |
| 121 #if USE_MMX |
| 122 EXPECT_EQ(4222342047u, rgb_hash); |
| 123 #else |
| 124 EXPECT_EQ(106869773u, rgb_hash); |
| 125 #endif |
| 126 return; // This is here to allow you to put a break point on this line |
| 127 } |
| 128 |
| 129 TEST(YuvScaleTest, Basic) { |
| 130 // Read YUV reference data from file. |
| 131 FilePath yuv_url; |
| 132 EXPECT_TRUE(PathService::Get(base::DIR_SOURCE_ROOT, &yuv_url)); |
| 133 yuv_url = yuv_url.Append(FILE_PATH_LITERAL("media")) |
| 106 .Append(FILE_PATH_LITERAL("test")) | 134 .Append(FILE_PATH_LITERAL("test")) |
| 107 .Append(FILE_PATH_LITERAL("data")) | 135 .Append(FILE_PATH_LITERAL("data")) |
| 108 .Append(FILE_PATH_LITERAL("bali.yv16.640_360.rgb")); | 136 .Append(FILE_PATH_LITERAL("bali.yv12.640_360.yuv")); |
| 109 EXPECT_EQ(static_cast<int>(kRGBSize), | 137 const size_t size_of_yuv = kWidth * kHeight * 12 / 8; // 12 bpp. |
| 110 file_util::ReadFile(rgb_url, | 138 uint8* yuv_bytes = new uint8[size_of_yuv]; |
| 111 reinterpret_cast<char*>(rgb_bytes.get()), | 139 EXPECT_EQ(static_cast<int>(size_of_yuv), |
| 112 static_cast<int>(kRGBSize))); | 140 file_util::ReadFile(yuv_url, |
| 141 reinterpret_cast<char*>(yuv_bytes), |
| 142 static_cast<int>(size_of_yuv))); |
| 113 | 143 |
| 114 // Convert a frame of YUV to 32 bit ARGB. | 144 // Scale a frame of YUV to 32 bit ARGB. |
| 115 media::ConvertYV16ToRGB32(yuv_bytes.get(), // Y | 145 const size_t size_of_rgb_scaled = kScaledWidth * kScaledHeight * kBpp; |
| 116 yuv_bytes.get() + kWidth * kHeight, // U | 146 uint8* rgb_scaled_bytes = new uint8[size_of_rgb_scaled]; |
| 117 yuv_bytes.get() + kWidth * kHeight * 3 / 2, // V | |
| 118 rgb_converted_bytes.get(), // RGB output | |
| 119 kWidth, kHeight, // Dimensions | |
| 120 kWidth, // YStride | |
| 121 kWidth / 2, // UVStride | |
| 122 kWidth * kBpp); // RGBStride | |
| 123 | 147 |
| 124 // TODO(fbarchard): The reference image was converted with MMX. | 148 media::ScaleYUVToRGB32(yuv_bytes, // Y plane |
| 125 // Non-MMX implementations do not match exactly. In the future, | 149 yuv_bytes + kWidth * kHeight, // U plane |
| 126 // Mac and Linux will use MMX as well and the unittest will be | 150 yuv_bytes + kWidth * kHeight * 5 / 4, // V plane |
| 127 // activated automatically. | 151 rgb_scaled_bytes, // Rgb output |
| 152 kWidth, kHeight, // Dimensions |
| 153 kScaledWidth, kScaledHeight, // Dimensions |
| 154 kWidth, // YStride |
| 155 kWidth / 2, // UvStride |
| 156 kScaledWidth * kBpp, // RgbStride |
| 157 media::YV12, |
| 158 media::ROTATE_0); |
| 159 |
| 160 unsigned int rgb_hash = hash(rgb_scaled_bytes, size_of_rgb_scaled); |
| 161 |
| 162 // To get this hash value, run once and examine the following EXPECT_EQ. |
| 163 // Then plug new hash value into EXPECT_EQ statements. |
| 164 |
| 165 // TODO(fbarchard): Make reference code mimic MMX exactly |
| 128 #if USE_MMX | 166 #if USE_MMX |
| 129 // Compare converted YUV to reference conversion file. | 167 EXPECT_EQ(4259656254u, rgb_hash); |
| 130 int rgb_diff = memcmp(rgb_converted_bytes.get(), rgb_bytes.get(), kRGBSize); | 168 #else |
| 169 EXPECT_EQ(197274901u, rgb_hash); |
| 170 #endif |
| 171 return; // This is here to allow you to put a break point on this line |
| 172 } |
| 131 | 173 |
| 132 EXPECT_EQ(0, rgb_diff); | 174 TEST(YV16ScaleTest, Basic) { |
| 175 // Read YV16 reference data from file. |
| 176 FilePath yuv_url; |
| 177 EXPECT_TRUE(PathService::Get(base::DIR_SOURCE_ROOT, &yuv_url)); |
| 178 yuv_url = yuv_url.Append(FILE_PATH_LITERAL("media")) |
| 179 .Append(FILE_PATH_LITERAL("test")) |
| 180 .Append(FILE_PATH_LITERAL("data")) |
| 181 .Append(FILE_PATH_LITERAL("bali.yv16.640_360.yuv")); |
| 182 const size_t size_of_yuv = kWidth * kHeight * 16 / 8; // 16 bpp. |
| 183 uint8* yuv_bytes = new uint8[size_of_yuv]; |
| 184 EXPECT_EQ(static_cast<int>(size_of_yuv), |
| 185 file_util::ReadFile(yuv_url, |
| 186 reinterpret_cast<char*>(yuv_bytes), |
| 187 static_cast<int>(size_of_yuv))); |
| 188 |
| 189 // Scale a frame of YUV to 32 bit ARGB. |
| 190 const size_t size_of_rgb_scaled = kScaledWidth * kScaledHeight * kBpp; |
| 191 uint8* rgb_scaled_bytes = new uint8[size_of_rgb_scaled]; |
| 192 |
| 193 media::ScaleYUVToRGB32(yuv_bytes, // Y plane |
| 194 yuv_bytes + kWidth * kHeight, // U plane |
| 195 yuv_bytes + kWidth * kHeight * 3 / 2, // V plane |
| 196 rgb_scaled_bytes, // Rgb output |
| 197 kWidth, kHeight, // Dimensions |
| 198 kScaledWidth, kScaledHeight, // Dimensions |
| 199 kWidth, // YStride |
| 200 kWidth / 2, // UvStride |
| 201 kScaledWidth * kBpp, // RgbStride |
| 202 media::YV16, |
| 203 media::ROTATE_0); |
| 204 |
| 205 unsigned int rgb_hash = hash(rgb_scaled_bytes, size_of_rgb_scaled); |
| 206 |
| 207 // To get this hash value, run once and examine the following EXPECT_EQ. |
| 208 // Then plug new hash value into EXPECT_EQ statements. |
| 209 |
| 210 // TODO(fbarchard): Make reference code mimic MMX exactly |
| 211 #if USE_MMX |
| 212 EXPECT_EQ(974965419u, rgb_hash); |
| 213 #else |
| 214 EXPECT_EQ(2946450771u, rgb_hash); |
| 133 #endif | 215 #endif |
| 134 return; | 216 return; |
| 135 } | 217 } |
| 136 | 218 |
| OLD | NEW |