| 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 |