OLD | NEW |
1 /* | 1 /* |
2 * Copyright (c) 2004 The WebRTC project authors. All Rights Reserved. | 2 * Copyright (c) 2004 The WebRTC project authors. All Rights Reserved. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license | 4 * Use of this source code is governed by a BSD-style license |
5 * that can be found in the LICENSE file in the root of the source | 5 * that can be found in the LICENSE file in the root of the source |
6 * tree. An additional intellectual property rights grant can be found | 6 * tree. An additional intellectual property rights grant can be found |
7 * in the file PATENTS. All contributing project authors may | 7 * in the file PATENTS. All contributing project authors may |
8 * be found in the AUTHORS file in the root of the source tree. | 8 * be found in the AUTHORS file in the root of the source tree. |
9 */ | 9 */ |
10 | 10 |
11 #ifndef WEBRTC_MEDIA_BASE_VIDEOFRAME_UNITTEST_H_ | 11 #ifndef WEBRTC_MEDIA_BASE_VIDEOFRAME_UNITTEST_H_ |
12 #define WEBRTC_MEDIA_BASE_VIDEOFRAME_UNITTEST_H_ | 12 #define WEBRTC_MEDIA_BASE_VIDEOFRAME_UNITTEST_H_ |
13 | 13 |
14 #include <algorithm> | 14 #include <algorithm> |
15 #include <memory> | 15 #include <memory> |
16 #include <string> | 16 #include <string> |
17 | 17 |
18 #include "libyuv/convert.h" | 18 #include "libyuv/convert.h" |
19 #include "libyuv/convert_from.h" | 19 #include "libyuv/convert_from.h" |
20 #include "libyuv/planar_functions.h" | 20 #include "libyuv/planar_functions.h" |
21 #include "libyuv/rotate.h" | 21 #include "libyuv/rotate.h" |
22 #include "webrtc/base/gunit.h" | 22 #include "webrtc/base/gunit.h" |
23 #include "webrtc/base/pathutils.h" | 23 #include "webrtc/base/pathutils.h" |
24 #include "webrtc/base/stream.h" | 24 #include "webrtc/base/stream.h" |
25 #include "webrtc/base/stringutils.h" | 25 #include "webrtc/base/stringutils.h" |
26 #include "webrtc/common_video/rotation.h" | 26 #include "webrtc/common_video/rotation.h" |
27 #include "webrtc/media/base/testutils.h" | 27 #include "webrtc/media/base/testutils.h" |
28 #include "webrtc/media/base/videocommon.h" | 28 #include "webrtc/media/base/videocommon.h" |
29 #include "webrtc/media/base/videoframe.h" | 29 #include "webrtc/media/base/videoframe.h" |
| 30 #include "webrtc/test/testsupport/fileutils.h" |
30 | 31 |
31 #if defined(_MSC_VER) | 32 #if defined(_MSC_VER) |
32 #define ALIGN16(var) __declspec(align(16)) var | 33 #define ALIGN16(var) __declspec(align(16)) var |
33 #else | 34 #else |
34 #define ALIGN16(var) var __attribute__((aligned(16))) | 35 #define ALIGN16(var) var __attribute__((aligned(16))) |
35 #endif | 36 #endif |
36 | 37 |
37 #define kImageFilename "faces.1280x720_P420.yuv" | 38 #define kImageFilename "media/faces.1280x720_P420" |
38 #define kJpeg420Filename "faces_I420.jpg" | 39 #define kYuvExtension "yuv" |
39 #define kJpeg422Filename "faces_I422.jpg" | 40 #define kJpeg420Filename "media/faces_I420" |
40 #define kJpeg444Filename "faces_I444.jpg" | 41 #define kJpeg422Filename "media/faces_I422" |
41 #define kJpeg411Filename "faces_I411.jpg" | 42 #define kJpeg444Filename "media/faces_I444" |
42 #define kJpeg400Filename "faces_I400.jpg" | 43 #define kJpeg411Filename "media/faces_I411" |
| 44 #define kJpeg400Filename "media/faces_I400" |
| 45 #define kJpegExtension "jpg" |
43 | 46 |
44 // Generic test class for testing various video frame implementations. | 47 // Generic test class for testing various video frame implementations. |
45 template <class T> | 48 template <class T> |
46 class VideoFrameTest : public testing::Test { | 49 class VideoFrameTest : public testing::Test { |
47 public: | 50 public: |
48 VideoFrameTest() : repeat_(1) {} | 51 VideoFrameTest() : repeat_(1) {} |
49 | 52 |
50 protected: | 53 protected: |
51 static const int kWidth = 1280; | 54 static const int kWidth = 1280; |
52 static const int kHeight = 720; | 55 static const int kHeight = 720; |
53 static const int kAlignment = 16; | 56 static const int kAlignment = 16; |
54 static const int kMinWidthAll = 1; // Constants for ConstructYUY2AllSizes. | 57 static const int kMinWidthAll = 1; // Constants for ConstructYUY2AllSizes. |
55 static const int kMinHeightAll = 1; | 58 static const int kMinHeightAll = 1; |
56 static const int kMaxWidthAll = 17; | 59 static const int kMaxWidthAll = 17; |
57 static const int kMaxHeightAll = 23; | 60 static const int kMaxHeightAll = 23; |
58 | 61 |
59 // Load a video frame from disk. | 62 // Load a video frame from disk. |
60 bool LoadFrameNoRepeat(T* frame) { | 63 bool LoadFrameNoRepeat(T* frame) { |
61 int save_repeat = repeat_; // This LoadFrame disables repeat. | 64 int save_repeat = repeat_; // This LoadFrame disables repeat. |
62 repeat_ = 1; | 65 repeat_ = 1; |
63 bool success = LoadFrame(kImageFilename, cricket::FOURCC_I420, | 66 bool success = LoadFrame(LoadSample(kImageFilename, kYuvExtension).get(), |
64 kWidth, kHeight, frame); | 67 cricket::FOURCC_I420, |
| 68 kWidth, kHeight, frame); |
65 repeat_ = save_repeat; | 69 repeat_ = save_repeat; |
66 return success; | 70 return success; |
67 } | 71 } |
68 | 72 |
69 bool LoadFrame(const std::string& filename, | 73 bool LoadFrame(const std::string& filename, |
70 uint32_t format, | 74 uint32_t format, |
71 int32_t width, | 75 int32_t width, |
72 int32_t height, | 76 int32_t height, |
73 T* frame) { | 77 T* frame) { |
74 return LoadFrame(filename, format, width, height, width, abs(height), | 78 return LoadFrame(filename, format, width, height, width, abs(height), |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
134 webrtc::VideoRotation rotation, | 138 webrtc::VideoRotation rotation, |
135 T* frame) { | 139 T* frame) { |
136 bool ret = false; | 140 bool ret = false; |
137 for (int i = 0; i < repeat_; ++i) { | 141 for (int i = 0; i < repeat_; ++i) { |
138 ret = frame->Init(format, width, height, dw, dh, | 142 ret = frame->Init(format, width, height, dw, dh, |
139 sample, sample_size, 0, rotation); | 143 sample, sample_size, 0, rotation); |
140 } | 144 } |
141 return ret; | 145 return ret; |
142 } | 146 } |
143 | 147 |
144 rtc::MemoryStream* LoadSample(const std::string& filename) { | 148 std::unique_ptr<rtc::MemoryStream> LoadSample(const std::string& filename, |
145 rtc::Pathname path(cricket::GetTestFilePath(filename)); | 149 const std::string& extension) { |
| 150 rtc::Pathname path(webrtc::test::ResourcePath(filename, extension)); |
146 std::unique_ptr<rtc::FileStream> fs( | 151 std::unique_ptr<rtc::FileStream> fs( |
147 rtc::Filesystem::OpenFile(path, "rb")); | 152 rtc::Filesystem::OpenFile(path, "rb")); |
148 if (!fs.get()) { | 153 if (!fs.get()) { |
149 LOG(LS_ERROR) << "Could not open test file path: " << path.pathname() | 154 LOG(LS_ERROR) << "Could not open test file path: " << path.pathname() |
150 << " from current dir " | 155 << " from current dir " |
151 << rtc::Filesystem::GetCurrentDirectory().pathname(); | 156 << rtc::Filesystem::GetCurrentDirectory().pathname(); |
152 return NULL; | 157 return NULL; |
153 } | 158 } |
154 | 159 |
155 char buf[4096]; | 160 char buf[4096]; |
156 std::unique_ptr<rtc::MemoryStream> ms( | 161 std::unique_ptr<rtc::MemoryStream> ms( |
157 new rtc::MemoryStream()); | 162 new rtc::MemoryStream()); |
158 rtc::StreamResult res = Flow(fs.get(), buf, sizeof(buf), ms.get()); | 163 rtc::StreamResult res = Flow(fs.get(), buf, sizeof(buf), ms.get()); |
159 if (res != rtc::SR_SUCCESS) { | 164 if (res != rtc::SR_SUCCESS) { |
160 LOG(LS_ERROR) << "Could not load test file path: " << path.pathname(); | 165 LOG(LS_ERROR) << "Could not load test file path: " << path.pathname(); |
161 return NULL; | 166 return NULL; |
162 } | 167 } |
163 | 168 |
164 return ms.release(); | 169 return ms; |
165 } | 170 } |
166 | 171 |
167 bool DumpSample(const std::string& filename, const void* buffer, int size) { | 172 bool DumpSample(const std::string& filename, const void* buffer, int size) { |
168 rtc::Pathname path(filename); | 173 rtc::Pathname path(filename); |
169 std::unique_ptr<rtc::FileStream> fs( | 174 std::unique_ptr<rtc::FileStream> fs( |
170 rtc::Filesystem::OpenFile(path, "wb")); | 175 rtc::Filesystem::OpenFile(path, "wb")); |
171 if (!fs.get()) { | 176 if (!fs.get()) { |
172 return false; | 177 return false; |
173 } | 178 } |
174 | 179 |
175 return (fs->Write(buffer, size, NULL, NULL) == rtc::SR_SUCCESS); | 180 return (fs->Write(buffer, size, NULL, NULL) == rtc::SR_SUCCESS); |
176 } | 181 } |
177 | 182 |
178 // Create a test image in the desired color space. | 183 // Create a test image in the desired color space. |
179 // The image is a checkerboard pattern with 63x63 squares, which allows | 184 // The image is a checkerboard pattern with 63x63 squares, which allows |
180 // I420 chroma artifacts to easily be seen on the square boundaries. | 185 // I420 chroma artifacts to easily be seen on the square boundaries. |
181 // The pattern is { { green, orange }, { blue, purple } } | 186 // The pattern is { { green, orange }, { blue, purple } } |
182 // There is also a gradient within each square to ensure that the luma | 187 // There is also a gradient within each square to ensure that the luma |
183 // values are handled properly. | 188 // values are handled properly. |
184 rtc::MemoryStream* CreateYuv422Sample(uint32_t fourcc, | 189 std::unique_ptr<rtc::MemoryStream> CreateYuv422Sample(uint32_t fourcc, |
185 uint32_t width, | 190 uint32_t width, |
186 uint32_t height) { | 191 uint32_t height) { |
187 int y1_pos, y2_pos, u_pos, v_pos; | 192 int y1_pos, y2_pos, u_pos, v_pos; |
188 if (!GetYuv422Packing(fourcc, &y1_pos, &y2_pos, &u_pos, &v_pos)) { | 193 if (!GetYuv422Packing(fourcc, &y1_pos, &y2_pos, &u_pos, &v_pos)) { |
189 return NULL; | 194 return NULL; |
190 } | 195 } |
191 | 196 |
192 std::unique_ptr<rtc::MemoryStream> ms( | 197 std::unique_ptr<rtc::MemoryStream> ms( |
193 new rtc::MemoryStream); | 198 new rtc::MemoryStream); |
194 int awidth = (width + 1) & ~1; | 199 int awidth = (width + 1) & ~1; |
195 int size = awidth * 2 * height; | 200 int size = awidth * 2 * height; |
196 if (!ms->ReserveSize(size)) { | 201 if (!ms->ReserveSize(size)) { |
197 return NULL; | 202 return NULL; |
198 } | 203 } |
199 for (uint32_t y = 0; y < height; ++y) { | 204 for (uint32_t y = 0; y < height; ++y) { |
200 for (int x = 0; x < awidth; x += 2) { | 205 for (int x = 0; x < awidth; x += 2) { |
201 uint8_t quad[4]; | 206 uint8_t quad[4]; |
202 quad[y1_pos] = (x % 63 + y % 63) + 64; | 207 quad[y1_pos] = (x % 63 + y % 63) + 64; |
203 quad[y2_pos] = ((x + 1) % 63 + y % 63) + 64; | 208 quad[y2_pos] = ((x + 1) % 63 + y % 63) + 64; |
204 quad[u_pos] = ((x / 63) & 1) ? 192 : 64; | 209 quad[u_pos] = ((x / 63) & 1) ? 192 : 64; |
205 quad[v_pos] = ((y / 63) & 1) ? 192 : 64; | 210 quad[v_pos] = ((y / 63) & 1) ? 192 : 64; |
206 ms->Write(quad, sizeof(quad), NULL, NULL); | 211 ms->Write(quad, sizeof(quad), NULL, NULL); |
207 } | 212 } |
208 } | 213 } |
209 return ms.release(); | 214 return ms; |
210 } | 215 } |
211 | 216 |
212 // Create a test image for YUV 420 formats with 12 bits per pixel. | 217 // Create a test image for YUV 420 formats with 12 bits per pixel. |
213 rtc::MemoryStream* CreateYuvSample(uint32_t width, | 218 std::unique_ptr<rtc::MemoryStream> CreateYuvSample(uint32_t width, |
214 uint32_t height, | 219 uint32_t height, |
215 uint32_t bpp) { | 220 uint32_t bpp) { |
216 std::unique_ptr<rtc::MemoryStream> ms( | 221 std::unique_ptr<rtc::MemoryStream> ms( |
217 new rtc::MemoryStream); | 222 new rtc::MemoryStream); |
218 if (!ms->ReserveSize(width * height * bpp / 8)) { | 223 if (!ms->ReserveSize(width * height * bpp / 8)) { |
219 return NULL; | 224 return NULL; |
220 } | 225 } |
221 | 226 |
222 for (uint32_t i = 0; i < width * height * bpp / 8; ++i) { | 227 for (uint32_t i = 0; i < width * height * bpp / 8; ++i) { |
223 uint8_t value = ((i / 63) & 1) ? 192 : 64; | 228 uint8_t value = ((i / 63) & 1) ? 192 : 64; |
224 ms->Write(&value, sizeof(value), NULL, NULL); | 229 ms->Write(&value, sizeof(value), NULL, NULL); |
225 } | 230 } |
226 return ms.release(); | 231 return ms; |
227 } | 232 } |
228 | 233 |
229 rtc::MemoryStream* CreateRgbSample(uint32_t fourcc, | 234 std::unique_ptr<rtc::MemoryStream> CreateRgbSample(uint32_t fourcc, |
230 uint32_t width, | 235 uint32_t width, |
231 uint32_t height) { | 236 uint32_t height) { |
232 int r_pos, g_pos, b_pos, bytes; | 237 int r_pos, g_pos, b_pos, bytes; |
233 if (!GetRgbPacking(fourcc, &r_pos, &g_pos, &b_pos, &bytes)) { | 238 if (!GetRgbPacking(fourcc, &r_pos, &g_pos, &b_pos, &bytes)) { |
234 return NULL; | 239 return NULL; |
235 } | 240 } |
236 | 241 |
237 std::unique_ptr<rtc::MemoryStream> ms( | 242 std::unique_ptr<rtc::MemoryStream> ms( |
238 new rtc::MemoryStream); | 243 new rtc::MemoryStream); |
239 if (!ms->ReserveSize(width * height * bytes)) { | 244 if (!ms->ReserveSize(width * height * bytes)) { |
240 return NULL; | 245 return NULL; |
241 } | 246 } |
242 | 247 |
243 for (uint32_t y = 0; y < height; ++y) { | 248 for (uint32_t y = 0; y < height; ++y) { |
244 for (uint32_t x = 0; x < width; ++x) { | 249 for (uint32_t x = 0; x < width; ++x) { |
245 uint8_t rgb[4] = {255, 255, 255, 255}; | 250 uint8_t rgb[4] = {255, 255, 255, 255}; |
246 rgb[r_pos] = ((x / 63) & 1) ? 224 : 32; | 251 rgb[r_pos] = ((x / 63) & 1) ? 224 : 32; |
247 rgb[g_pos] = (x % 63 + y % 63) + 96; | 252 rgb[g_pos] = (x % 63 + y % 63) + 96; |
248 rgb[b_pos] = ((y / 63) & 1) ? 224 : 32; | 253 rgb[b_pos] = ((y / 63) & 1) ? 224 : 32; |
249 ms->Write(rgb, bytes, NULL, NULL); | 254 ms->Write(rgb, bytes, NULL, NULL); |
250 } | 255 } |
251 } | 256 } |
252 return ms.release(); | 257 return ms; |
253 } | 258 } |
254 | 259 |
255 // Simple conversion routines to verify the optimized VideoFrame routines. | 260 // Simple conversion routines to verify the optimized VideoFrame routines. |
256 // Converts from the specified colorspace to I420. | 261 // Converts from the specified colorspace to I420. |
257 std::unique_ptr<T> ConvertYuv422(const rtc::MemoryStream* ms, | 262 std::unique_ptr<T> ConvertYuv422(const rtc::MemoryStream* ms, |
258 uint32_t fourcc, | 263 uint32_t fourcc, |
259 uint32_t width, | 264 uint32_t width, |
260 uint32_t height) { | 265 uint32_t height) { |
261 int y1_pos, y2_pos, u_pos, v_pos; | 266 int y1_pos, y2_pos, u_pos, v_pos; |
262 if (!GetYuv422Packing(fourcc, &y1_pos, &y2_pos, &u_pos, &v_pos)) { | 267 if (!GetYuv422Packing(fourcc, &y1_pos, &y2_pos, &u_pos, &v_pos)) { |
(...skipping 800 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1063 out_size)); // stride. | 1068 out_size)); // stride. |
1064 EXPECT_TRUE(IsPlaneEqual("argb", pixel, out_size, | 1069 EXPECT_TRUE(IsPlaneEqual("argb", pixel, out_size, |
1065 out, out_size, | 1070 out, out_size, |
1066 out_size, 1, 2)); | 1071 out_size, 1, 2)); |
1067 } | 1072 } |
1068 | 1073 |
1069 // Test constructing an image from an I420 buffer with horizontal cropping. | 1074 // Test constructing an image from an I420 buffer with horizontal cropping. |
1070 void ConstructI420CropHorizontal() { | 1075 void ConstructI420CropHorizontal() { |
1071 T frame1, frame2; | 1076 T frame1, frame2; |
1072 ASSERT_TRUE(LoadFrameNoRepeat(&frame1)); | 1077 ASSERT_TRUE(LoadFrameNoRepeat(&frame1)); |
1073 ASSERT_TRUE(LoadFrame(kImageFilename, cricket::FOURCC_I420, kWidth, kHeight, | 1078 ASSERT_TRUE(LoadFrame(kImageFilename, kYuvExtension, |
| 1079 cricket::FOURCC_I420, kWidth, kHeight, |
1074 kWidth * 3 / 4, kHeight, webrtc::kVideoRotation_0, | 1080 kWidth * 3 / 4, kHeight, webrtc::kVideoRotation_0, |
1075 &frame2)); | 1081 &frame2)); |
1076 EXPECT_TRUE(IsEqualWithCrop(frame2, frame1, kWidth / 8, 0, 0)); | 1082 EXPECT_TRUE(IsEqualWithCrop(frame2, frame1, kWidth / 8, 0, 0)); |
1077 } | 1083 } |
1078 | 1084 |
1079 // Test constructing an image from a YUY2 buffer with horizontal cropping. | 1085 // Test constructing an image from a YUY2 buffer with horizontal cropping. |
1080 void ConstructYuy2CropHorizontal() { | 1086 void ConstructYuy2CropHorizontal() { |
1081 T frame1, frame2; | 1087 T frame1, frame2; |
1082 std::unique_ptr<rtc::MemoryStream> ms( | 1088 std::unique_ptr<rtc::MemoryStream> ms( |
1083 CreateYuv422Sample(cricket::FOURCC_YUY2, kWidth, kHeight)); | 1089 CreateYuv422Sample(cricket::FOURCC_YUY2, kWidth, kHeight)); |
(...skipping 18 matching lines...) Expand all Loading... |
1102 EXPECT_TRUE(LoadFrame(ms.get(), cricket::FOURCC_ARGB, kWidth, kHeight, | 1108 EXPECT_TRUE(LoadFrame(ms.get(), cricket::FOURCC_ARGB, kWidth, kHeight, |
1103 kWidth * 3 / 4, kHeight, webrtc::kVideoRotation_0, | 1109 kWidth * 3 / 4, kHeight, webrtc::kVideoRotation_0, |
1104 &frame2)); | 1110 &frame2)); |
1105 EXPECT_TRUE(IsEqualWithCrop(frame2, *frame1, kWidth / 8, 0, 2)); | 1111 EXPECT_TRUE(IsEqualWithCrop(frame2, *frame1, kWidth / 8, 0, 2)); |
1106 } | 1112 } |
1107 | 1113 |
1108 // Test constructing an image from an I420 buffer, cropping top and bottom. | 1114 // Test constructing an image from an I420 buffer, cropping top and bottom. |
1109 void ConstructI420CropVertical() { | 1115 void ConstructI420CropVertical() { |
1110 T frame1, frame2; | 1116 T frame1, frame2; |
1111 ASSERT_TRUE(LoadFrameNoRepeat(&frame1)); | 1117 ASSERT_TRUE(LoadFrameNoRepeat(&frame1)); |
1112 ASSERT_TRUE(LoadFrame(kImageFilename, cricket::FOURCC_I420, kWidth, kHeight, | 1118 ASSERT_TRUE(LoadFrame(LoadSample(kImageFilename, kYuvExtension).get(), |
| 1119 cricket::FOURCC_I420, kWidth, kHeight, |
1113 kWidth, kHeight * 3 / 4, webrtc::kVideoRotation_0, | 1120 kWidth, kHeight * 3 / 4, webrtc::kVideoRotation_0, |
1114 &frame2)); | 1121 &frame2)); |
1115 EXPECT_TRUE(IsEqualWithCrop(frame2, frame1, 0, kHeight / 8, 0)); | 1122 EXPECT_TRUE(IsEqualWithCrop(frame2, frame1, 0, kHeight / 8, 0)); |
1116 } | 1123 } |
1117 | 1124 |
1118 // Test constructing an image from I420 synonymous formats. | 1125 // Test constructing an image from I420 synonymous formats. |
1119 void ConstructI420Aliases() { | 1126 void ConstructI420Aliases() { |
1120 T frame1, frame2, frame3; | 1127 T frame1, frame2, frame3; |
1121 ASSERT_TRUE(LoadFrame(kImageFilename, cricket::FOURCC_I420, kWidth, kHeight, | 1128 ASSERT_TRUE(LoadFrame(LoadSample(kImageFilename, kYuvExtension), |
| 1129 cricket::FOURCC_I420, kWidth, kHeight, |
1122 &frame1)); | 1130 &frame1)); |
1123 ASSERT_TRUE(LoadFrame(kImageFilename, cricket::FOURCC_IYUV, kWidth, kHeight, | 1131 ASSERT_TRUE(LoadFrame(kImageFilename, kYuvExtension, |
| 1132 cricket::FOURCC_IYUV, kWidth, kHeight, |
1124 &frame2)); | 1133 &frame2)); |
1125 ASSERT_TRUE(LoadFrame(kImageFilename, cricket::FOURCC_YU12, kWidth, kHeight, | 1134 ASSERT_TRUE(LoadFrame(kImageFilename, kYuvExtension, |
| 1135 cricket::FOURCC_YU12, kWidth, kHeight, |
1126 &frame3)); | 1136 &frame3)); |
1127 EXPECT_TRUE(IsEqual(frame1, frame2, 0)); | 1137 EXPECT_TRUE(IsEqual(frame1, frame2, 0)); |
1128 EXPECT_TRUE(IsEqual(frame1, frame3, 0)); | 1138 EXPECT_TRUE(IsEqual(frame1, frame3, 0)); |
1129 } | 1139 } |
1130 | 1140 |
1131 // Test constructing an image from an I420 MJPG buffer. | 1141 // Test constructing an image from an I420 MJPG buffer. |
1132 void ConstructMjpgI420() { | 1142 void ConstructMjpgI420() { |
1133 T frame1, frame2; | 1143 T frame1, frame2; |
1134 ASSERT_TRUE(LoadFrameNoRepeat(&frame1)); | 1144 ASSERT_TRUE(LoadFrameNoRepeat(&frame1)); |
1135 ASSERT_TRUE(LoadFrame(kJpeg420Filename, | 1145 ASSERT_TRUE(LoadFrame(kJpeg420Filename, kJpegExtension, |
1136 cricket::FOURCC_MJPG, kWidth, kHeight, &frame2)); | 1146 cricket::FOURCC_MJPG, kWidth, kHeight, &frame2)); |
1137 EXPECT_TRUE(IsEqual(frame1, frame2, 32)); | 1147 EXPECT_TRUE(IsEqual(frame1, frame2, 32)); |
1138 } | 1148 } |
1139 | 1149 |
1140 // Test constructing an image from an I422 MJPG buffer. | 1150 // Test constructing an image from an I422 MJPG buffer. |
1141 void ConstructMjpgI422() { | 1151 void ConstructMjpgI422() { |
1142 T frame1, frame2; | 1152 T frame1, frame2; |
1143 ASSERT_TRUE(LoadFrameNoRepeat(&frame1)); | 1153 ASSERT_TRUE(LoadFrameNoRepeat(&frame1)); |
1144 ASSERT_TRUE(LoadFrame(kJpeg422Filename, | 1154 ASSERT_TRUE(LoadFrame(LoadSample(kJpeg422Filename, kJpegExtension).get(), |
1145 cricket::FOURCC_MJPG, kWidth, kHeight, &frame2)); | 1155 cricket::FOURCC_MJPG, kWidth, kHeight, &frame2)); |
1146 EXPECT_TRUE(IsEqual(frame1, frame2, 32)); | 1156 EXPECT_TRUE(IsEqual(frame1, frame2, 32)); |
1147 } | 1157 } |
1148 | 1158 |
1149 // Test constructing an image from an I444 MJPG buffer. | 1159 // Test constructing an image from an I444 MJPG buffer. |
1150 void ConstructMjpgI444() { | 1160 void ConstructMjpgI444() { |
1151 T frame1, frame2; | 1161 T frame1, frame2; |
1152 ASSERT_TRUE(LoadFrameNoRepeat(&frame1)); | 1162 ASSERT_TRUE(LoadFrameNoRepeat(&frame1)); |
1153 ASSERT_TRUE(LoadFrame(kJpeg444Filename, | 1163 ASSERT_TRUE(LoadFrame(LoadSample(kJpeg444Filename, kJpegExtension), |
1154 cricket::FOURCC_MJPG, kWidth, kHeight, &frame2)); | 1164 cricket::FOURCC_MJPG, kWidth, kHeight, &frame2)); |
1155 EXPECT_TRUE(IsEqual(frame1, frame2, 32)); | 1165 EXPECT_TRUE(IsEqual(frame1, frame2, 32)); |
1156 } | 1166 } |
1157 | 1167 |
1158 // Test constructing an image from an I444 MJPG buffer. | 1168 // Test constructing an image from an I444 MJPG buffer. |
1159 void ConstructMjpgI411() { | 1169 void ConstructMjpgI411() { |
1160 T frame1, frame2; | 1170 T frame1, frame2; |
1161 ASSERT_TRUE(LoadFrameNoRepeat(&frame1)); | 1171 ASSERT_TRUE(LoadFrameNoRepeat(&frame1)); |
1162 ASSERT_TRUE(LoadFrame(kJpeg411Filename, | 1172 ASSERT_TRUE(LoadFrame(kJpeg411Filename, kJpegExtension, |
1163 cricket::FOURCC_MJPG, kWidth, kHeight, &frame2)); | 1173 cricket::FOURCC_MJPG, kWidth, kHeight, &frame2)); |
1164 EXPECT_TRUE(IsEqual(frame1, frame2, 32)); | 1174 EXPECT_TRUE(IsEqual(frame1, frame2, 32)); |
1165 } | 1175 } |
1166 | 1176 |
1167 // Test constructing an image from an I400 MJPG buffer. | 1177 // Test constructing an image from an I400 MJPG buffer. |
1168 // TODO(fbarchard): Stronger compare on chroma. Compare agaisnt a grey image. | 1178 // TODO(fbarchard): Stronger compare on chroma. Compare agaisnt a grey image. |
1169 void ConstructMjpgI400() { | 1179 void ConstructMjpgI400() { |
1170 T frame1, frame2; | 1180 T frame1, frame2; |
1171 ASSERT_TRUE(LoadFrameNoRepeat(&frame1)); | 1181 ASSERT_TRUE(LoadFrameNoRepeat(&frame1)); |
1172 ASSERT_TRUE(LoadFrame(kJpeg400Filename, | 1182 ASSERT_TRUE(LoadFrame(kJpeg400Filename, kJpegExtension, |
1173 cricket::FOURCC_MJPG, kWidth, kHeight, &frame2)); | 1183 cricket::FOURCC_MJPG, kWidth, kHeight, &frame2)); |
1174 EXPECT_TRUE(IsPlaneEqual("y", frame1.video_frame_buffer()->DataY(), | 1184 EXPECT_TRUE(IsPlaneEqual("y", frame1.video_frame_buffer()->DataY(), |
1175 frame1.video_frame_buffer()->StrideY(), | 1185 frame1.video_frame_buffer()->StrideY(), |
1176 frame2.video_frame_buffer()->DataY(), | 1186 frame2.video_frame_buffer()->DataY(), |
1177 frame2.video_frame_buffer()->StrideY(), | 1187 frame2.video_frame_buffer()->StrideY(), |
1178 kWidth, kHeight, 32)); | 1188 kWidth, kHeight, 32)); |
1179 EXPECT_TRUE(IsEqual(frame1, frame2, 128)); | 1189 EXPECT_TRUE(IsEqual(frame1, frame2, 128)); |
1180 } | 1190 } |
1181 | 1191 |
1182 // Test constructing an image from an I420 MJPG buffer. | 1192 // Test constructing an image from an I420 MJPG buffer. |
1183 void ValidateFrame(const char* name, | 1193 void ValidateFrame(const char* name, |
| 1194 const char* extension, |
1184 uint32_t fourcc, | 1195 uint32_t fourcc, |
1185 int data_adjust, | 1196 int data_adjust, |
1186 int size_adjust, | 1197 int size_adjust, |
1187 bool expected_result) { | 1198 bool expected_result) { |
1188 T frame; | 1199 T frame; |
1189 std::unique_ptr<rtc::MemoryStream> ms(LoadSample(name)); | 1200 std::unique_ptr<rtc::MemoryStream> ms(LoadSample(name, extension)); |
1190 ASSERT_TRUE(ms.get() != NULL); | 1201 ASSERT_TRUE(ms.get() != NULL); |
1191 const uint8_t* sample = | 1202 const uint8_t* sample = |
1192 reinterpret_cast<const uint8_t*>(ms.get()->GetBuffer()); | 1203 reinterpret_cast<const uint8_t*>(ms.get()->GetBuffer()); |
1193 size_t sample_size; | 1204 size_t sample_size; |
1194 ms->GetSize(&sample_size); | 1205 ms->GetSize(&sample_size); |
1195 // Optional adjust size to test invalid size. | 1206 // Optional adjust size to test invalid size. |
1196 size_t data_size = sample_size + data_adjust; | 1207 size_t data_size = sample_size + data_adjust; |
1197 | 1208 |
1198 // Allocate a buffer with end page aligned. | 1209 // Allocate a buffer with end page aligned. |
1199 const int kPadToHeapSized = 16 * 1024 * 1024; | 1210 const int kPadToHeapSized = 16 * 1024 * 1024; |
1200 std::unique_ptr<uint8_t[]> page_buffer( | 1211 std::unique_ptr<uint8_t[]> page_buffer( |
1201 new uint8_t[((data_size + kPadToHeapSized + 4095) & ~4095)]); | 1212 new uint8_t[((data_size + kPadToHeapSized + 4095) & ~4095)]); |
1202 uint8_t* data_ptr = page_buffer.get(); | 1213 uint8_t* data_ptr = page_buffer.get(); |
1203 if (!data_ptr) { | 1214 if (!data_ptr) { |
1204 LOG(LS_WARNING) << "Failed to allocate memory for ValidateFrame test."; | 1215 LOG(LS_WARNING) << "Failed to allocate memory for ValidateFrame test."; |
1205 EXPECT_FALSE(expected_result); // NULL is okay if failure was expected. | 1216 EXPECT_FALSE(expected_result); // NULL is okay if failure was expected. |
1206 return; | 1217 return; |
1207 } | 1218 } |
1208 data_ptr += kPadToHeapSized + (-(static_cast<int>(data_size)) & 4095); | 1219 data_ptr += kPadToHeapSized + (-(static_cast<int>(data_size)) & 4095); |
1209 memcpy(data_ptr, sample, std::min(data_size, sample_size)); | 1220 memcpy(data_ptr, sample, std::min(data_size, sample_size)); |
1210 for (int i = 0; i < repeat_; ++i) { | 1221 for (int i = 0; i < repeat_; ++i) { |
1211 EXPECT_EQ(expected_result, frame.Validate(fourcc, kWidth, kHeight, | 1222 EXPECT_EQ(expected_result, frame.Validate(fourcc, kWidth, kHeight, |
1212 data_ptr, | 1223 data_ptr, |
1213 sample_size + size_adjust)); | 1224 sample_size + size_adjust)); |
1214 } | 1225 } |
1215 } | 1226 } |
1216 | 1227 |
1217 // Test validate for I420 MJPG buffer. | 1228 // Test validate for I420 MJPG buffer. |
1218 void ValidateMjpgI420() { | 1229 void ValidateMjpgI420() { |
1219 ValidateFrame(kJpeg420Filename, cricket::FOURCC_MJPG, 0, 0, true); | 1230 ValidateFrame(kJpeg420Filename, kJpegExtension, |
| 1231 cricket::FOURCC_MJPG, 0, 0, true); |
1220 } | 1232 } |
1221 | 1233 |
1222 // Test validate for I422 MJPG buffer. | 1234 // Test validate for I422 MJPG buffer. |
1223 void ValidateMjpgI422() { | 1235 void ValidateMjpgI422() { |
1224 ValidateFrame(kJpeg422Filename, cricket::FOURCC_MJPG, 0, 0, true); | 1236 ValidateFrame(kJpeg422Filename, kJpegExtension, |
| 1237 cricket::FOURCC_MJPG, 0, 0, true); |
1225 } | 1238 } |
1226 | 1239 |
1227 // Test validate for I444 MJPG buffer. | 1240 // Test validate for I444 MJPG buffer. |
1228 void ValidateMjpgI444() { | 1241 void ValidateMjpgI444() { |
1229 ValidateFrame(kJpeg444Filename, cricket::FOURCC_MJPG, 0, 0, true); | 1242 ValidateFrame(kJpeg444Filename, kJpegExtension, |
| 1243 cricket::FOURCC_MJPG, 0, 0, true); |
1230 } | 1244 } |
1231 | 1245 |
1232 // Test validate for I411 MJPG buffer. | 1246 // Test validate for I411 MJPG buffer. |
1233 void ValidateMjpgI411() { | 1247 void ValidateMjpgI411() { |
1234 ValidateFrame(kJpeg411Filename, cricket::FOURCC_MJPG, 0, 0, true); | 1248 ValidateFrame(kJpeg411Filename, kJpegExtension, |
| 1249 cricket::FOURCC_MJPG, 0, 0, true); |
1235 } | 1250 } |
1236 | 1251 |
1237 // Test validate for I400 MJPG buffer. | 1252 // Test validate for I400 MJPG buffer. |
1238 void ValidateMjpgI400() { | 1253 void ValidateMjpgI400() { |
1239 ValidateFrame(kJpeg400Filename, cricket::FOURCC_MJPG, 0, 0, true); | 1254 ValidateFrame(kJpeg400Filename, kJpegExtension, |
| 1255 cricket::FOURCC_MJPG, 0, 0, true); |
1240 } | 1256 } |
1241 | 1257 |
1242 // Test validate for I420 buffer. | 1258 // Test validate for I420 buffer. |
1243 void ValidateI420() { | 1259 void ValidateI420() { |
1244 ValidateFrame(kImageFilename, cricket::FOURCC_I420, 0, 0, true); | 1260 ValidateFrame(kImageFilename, kYuvExtension, |
| 1261 cricket::FOURCC_I420, 0, 0, true); |
1245 } | 1262 } |
1246 | 1263 |
1247 // Test validate for I420 buffer where size is too small | 1264 // Test validate for I420 buffer where size is too small |
1248 void ValidateI420SmallSize() { | 1265 void ValidateI420SmallSize() { |
1249 ValidateFrame(kImageFilename, cricket::FOURCC_I420, 0, -16384, false); | 1266 ValidateFrame(kImageFilename, kYuvExtension, |
| 1267 cricket::FOURCC_I420, 0, -16384, false); |
1250 } | 1268 } |
1251 | 1269 |
1252 // Test validate for I420 buffer where size is too large (16 MB) | 1270 // Test validate for I420 buffer where size is too large (16 MB) |
1253 // Will produce warning but pass. | 1271 // Will produce warning but pass. |
1254 void ValidateI420LargeSize() { | 1272 void ValidateI420LargeSize() { |
1255 ValidateFrame(kImageFilename, cricket::FOURCC_I420, 16000000, 16000000, | 1273 ValidateFrame(kImageFilename, kYuvExtension, |
| 1274 cricket::FOURCC_I420, 16000000, 16000000, |
1256 true); | 1275 true); |
1257 } | 1276 } |
1258 | 1277 |
1259 // Test validate for I420 buffer where size is 1 GB (not reasonable). | 1278 // Test validate for I420 buffer where size is 1 GB (not reasonable). |
1260 void ValidateI420HugeSize() { | 1279 void ValidateI420HugeSize() { |
1261 #ifndef WIN32 // TODO(fbarchard): Reenable when fixing bug 9603762. | 1280 #ifndef WIN32 // TODO(fbarchard): Reenable when fixing bug 9603762. |
1262 ValidateFrame(kImageFilename, cricket::FOURCC_I420, 1000000000u, | 1281 ValidateFrame(kImageFilename, kYuvExtension, |
| 1282 cricket::FOURCC_I420, 1000000000u, |
1263 1000000000u, false); | 1283 1000000000u, false); |
1264 #endif | 1284 #endif |
1265 } | 1285 } |
1266 | 1286 |
1267 // The following test that Validate crashes if the size is greater than the | 1287 // The following test that Validate crashes if the size is greater than the |
1268 // actual buffer size. | 1288 // actual buffer size. |
1269 // TODO(fbarchard): Consider moving a filter into the capturer/plugin. | 1289 // TODO(fbarchard): Consider moving a filter into the capturer/plugin. |
1270 #if defined(_MSC_VER) && !defined(NDEBUG) | 1290 #if defined(_MSC_VER) && !defined(NDEBUG) |
1271 int ExceptionFilter(unsigned int code, struct _EXCEPTION_POINTERS *ep) { | 1291 int ExceptionFilter(unsigned int code, struct _EXCEPTION_POINTERS *ep) { |
1272 if (code == EXCEPTION_ACCESS_VIOLATION) { | 1292 if (code == EXCEPTION_ACCESS_VIOLATION) { |
1273 LOG(LS_INFO) << "Caught EXCEPTION_ACCESS_VIOLATION as expected."; | 1293 LOG(LS_INFO) << "Caught EXCEPTION_ACCESS_VIOLATION as expected."; |
1274 return EXCEPTION_EXECUTE_HANDLER; | 1294 return EXCEPTION_EXECUTE_HANDLER; |
1275 } else { | 1295 } else { |
1276 LOG(LS_INFO) << "Did not catch EXCEPTION_ACCESS_VIOLATION. Unexpected."; | 1296 LOG(LS_INFO) << "Did not catch EXCEPTION_ACCESS_VIOLATION. Unexpected."; |
1277 return EXCEPTION_CONTINUE_SEARCH; | 1297 return EXCEPTION_CONTINUE_SEARCH; |
1278 } | 1298 } |
1279 } | 1299 } |
1280 | 1300 |
1281 // Test validate fails for truncated MJPG data buffer. If ValidateFrame | 1301 // Test validate fails for truncated MJPG data buffer. If ValidateFrame |
1282 // crashes the exception handler will return and unittest passes with OK. | 1302 // crashes the exception handler will return and unittest passes with OK. |
1283 void ValidateMjpgI420InvalidSize() { | 1303 void ValidateMjpgI420InvalidSize() { |
1284 __try { | 1304 __try { |
1285 ValidateFrame(kJpeg420Filename, cricket::FOURCC_MJPG, -16384, 0, false); | 1305 ValidateFrame(kJpeg420Filename, kJpegExtension, |
| 1306 cricket::FOURCC_MJPG, -16384, 0, false); |
1286 FAIL() << "Validate was expected to cause EXCEPTION_ACCESS_VIOLATION."; | 1307 FAIL() << "Validate was expected to cause EXCEPTION_ACCESS_VIOLATION."; |
1287 } __except(ExceptionFilter(GetExceptionCode(), GetExceptionInformation())) { | 1308 } __except(ExceptionFilter(GetExceptionCode(), GetExceptionInformation())) { |
1288 return; // Successfully crashed in ValidateFrame. | 1309 return; // Successfully crashed in ValidateFrame. |
1289 } | 1310 } |
1290 } | 1311 } |
1291 | 1312 |
1292 // Test validate fails for truncated I420 buffer. | 1313 // Test validate fails for truncated I420 buffer. |
1293 void ValidateI420InvalidSize() { | 1314 void ValidateI420InvalidSize() { |
1294 __try { | 1315 __try { |
1295 ValidateFrame(kImageFilename, cricket::FOURCC_I420, -16384, 0, false); | 1316 ValidateFrame(kImageFilename, kYuvExtension, |
| 1317 cricket::FOURCC_I420, -16384, 0, false); |
1296 FAIL() << "Validate was expected to cause EXCEPTION_ACCESS_VIOLATION."; | 1318 FAIL() << "Validate was expected to cause EXCEPTION_ACCESS_VIOLATION."; |
1297 } __except(ExceptionFilter(GetExceptionCode(), GetExceptionInformation())) { | 1319 } __except(ExceptionFilter(GetExceptionCode(), GetExceptionInformation())) { |
1298 return; // Successfully crashed in ValidateFrame. | 1320 return; // Successfully crashed in ValidateFrame. |
1299 } | 1321 } |
1300 } | 1322 } |
1301 #endif | 1323 #endif |
1302 | 1324 |
1303 // Test constructing an image from a YUY2 buffer (and synonymous formats). | 1325 // Test constructing an image from a YUY2 buffer (and synonymous formats). |
1304 void ConstructYuy2Aliases() { | 1326 void ConstructYuy2Aliases() { |
1305 T frame1, frame2, frame3, frame4; | 1327 T frame1, frame2, frame3, frame4; |
(...skipping 502 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1808 target.reset(source->Copy()); | 1830 target.reset(source->Copy()); |
1809 EXPECT_TRUE(IsEqual(*source, *target, 0)); | 1831 EXPECT_TRUE(IsEqual(*source, *target, 0)); |
1810 const T* const_source = source.get(); | 1832 const T* const_source = source.get(); |
1811 EXPECT_EQ(const_source->video_frame_buffer(), target->video_frame_buffer()); | 1833 EXPECT_EQ(const_source->video_frame_buffer(), target->video_frame_buffer()); |
1812 } | 1834 } |
1813 | 1835 |
1814 int repeat_; | 1836 int repeat_; |
1815 }; | 1837 }; |
1816 | 1838 |
1817 #endif // WEBRTC_MEDIA_BASE_VIDEOFRAME_UNITTEST_H_ | 1839 #endif // WEBRTC_MEDIA_BASE_VIDEOFRAME_UNITTEST_H_ |
OLD | NEW |