Implement dynamic software fallback in PPB_VideoDecoder API.
[chromium-blink-merge.git] / media / base / video_util_unittest.cc
bloba62f0cbaf0b1e7650b809bc004846d6283b4ba4d
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "base/memory/scoped_ptr.h"
6 #include "media/base/video_frame.h"
7 #include "media/base/video_util.h"
8 #include "testing/gtest/include/gtest/gtest.h"
10 namespace media {
12 class VideoUtilTest : public testing::Test {
13 public:
14 VideoUtilTest()
15 : height_(0),
16 y_stride_(0),
17 u_stride_(0),
18 v_stride_(0) {
21 ~VideoUtilTest() override {}
23 void CreateSourceFrame(int width, int height,
24 int y_stride, int u_stride, int v_stride) {
25 EXPECT_GE(y_stride, width);
26 EXPECT_GE(u_stride, width / 2);
27 EXPECT_GE(v_stride, width / 2);
29 height_ = height;
30 y_stride_ = y_stride;
31 u_stride_ = u_stride;
32 v_stride_ = v_stride;
34 y_plane_.reset(new uint8[y_stride * height]);
35 u_plane_.reset(new uint8[u_stride * height / 2]);
36 v_plane_.reset(new uint8[v_stride * height / 2]);
39 void CreateDestinationFrame(int width, int height) {
40 gfx::Size size(width, height);
41 destination_frame_ = VideoFrame::CreateFrame(
42 PIXEL_FORMAT_YV12, size, gfx::Rect(size), size, base::TimeDelta());
45 void CopyPlanes() {
46 CopyYPlane(y_plane_.get(), y_stride_, height_, destination_frame_.get());
47 CopyUPlane(
48 u_plane_.get(), u_stride_, height_ / 2, destination_frame_.get());
49 CopyVPlane(
50 v_plane_.get(), v_stride_, height_ / 2, destination_frame_.get());
53 private:
54 scoped_ptr<uint8[]> y_plane_;
55 scoped_ptr<uint8[]> u_plane_;
56 scoped_ptr<uint8[]> v_plane_;
58 int height_;
59 int y_stride_;
60 int u_stride_;
61 int v_stride_;
63 scoped_refptr<VideoFrame> destination_frame_;
65 DISALLOW_COPY_AND_ASSIGN(VideoUtilTest);
68 TEST_F(VideoUtilTest, GetNaturalSize) {
69 gfx::Size visible_size(320, 240);
71 // Test 0 sizes.
72 EXPECT_EQ(gfx::Size(0, 0), GetNaturalSize(gfx::Size(0, 0), 1, 1));
73 EXPECT_EQ(gfx::Size(0, 1), GetNaturalSize(gfx::Size(0, 1), 1, 1));
74 EXPECT_EQ(gfx::Size(1, 0), GetNaturalSize(gfx::Size(1, 0), 1, 1));
76 // Test abnormal ratios.
77 EXPECT_EQ(gfx::Size(0, 0), GetNaturalSize(visible_size, 0, 0));
78 EXPECT_EQ(gfx::Size(0, 0), GetNaturalSize(visible_size, 1, 0));
79 EXPECT_EQ(gfx::Size(0, 0), GetNaturalSize(visible_size, 1, -1));
80 EXPECT_EQ(gfx::Size(0, 0), GetNaturalSize(visible_size, -1, 1));
82 // Test normal sizes and ratios.
83 EXPECT_EQ(gfx::Size(0, 240), GetNaturalSize(visible_size, 0, 1));
84 EXPECT_EQ(gfx::Size(320, 240), GetNaturalSize(visible_size, 1, 1));
85 EXPECT_EQ(gfx::Size(640, 240), GetNaturalSize(visible_size, 2, 1));
86 EXPECT_EQ(gfx::Size(160, 240), GetNaturalSize(visible_size, 1, 2));
87 EXPECT_EQ(gfx::Size(427, 240), GetNaturalSize(visible_size, 4, 3));
88 EXPECT_EQ(gfx::Size(240, 240), GetNaturalSize(visible_size, 3, 4));
89 EXPECT_EQ(gfx::Size(569, 240), GetNaturalSize(visible_size, 16, 9));
90 EXPECT_EQ(gfx::Size(180, 240), GetNaturalSize(visible_size, 9, 16));
92 // Test some random ratios.
93 EXPECT_EQ(gfx::Size(495, 240), GetNaturalSize(visible_size, 17, 11));
94 EXPECT_EQ(gfx::Size(207, 240), GetNaturalSize(visible_size, 11, 17));
97 TEST_F(VideoUtilTest, CopyPlane_Exact) {
98 CreateSourceFrame(16, 16, 16, 8, 8);
99 CreateDestinationFrame(16, 16);
100 CopyPlanes();
103 TEST_F(VideoUtilTest, CopyPlane_SmallerSource) {
104 CreateSourceFrame(8, 8, 8, 4, 4);
105 CreateDestinationFrame(16, 16);
106 CopyPlanes();
109 TEST_F(VideoUtilTest, CopyPlane_SmallerDestination) {
110 CreateSourceFrame(16, 16, 16, 8, 8);
111 CreateDestinationFrame(8, 8);
112 CopyPlanes();
115 namespace {
117 uint8 src6x4[] = {
118 0, 1, 2, 3, 4, 5,
119 6, 7, 8, 9, 10, 11,
120 12, 13, 14, 15, 16, 17,
121 18, 19, 20, 21, 22, 23
124 // Target images, name pattern target_rotation_flipV_flipH.
125 uint8* target6x4_0_n_n = src6x4;
127 uint8 target6x4_0_n_y[] = {
128 5, 4, 3, 2, 1, 0,
129 11, 10, 9, 8, 7, 6,
130 17, 16, 15, 14, 13, 12,
131 23, 22, 21, 20, 19, 18
134 uint8 target6x4_0_y_n[] = {
135 18, 19, 20, 21, 22, 23,
136 12, 13, 14, 15, 16, 17,
137 6, 7, 8, 9, 10, 11,
138 0, 1, 2, 3, 4, 5
141 uint8 target6x4_0_y_y[] = {
142 23, 22, 21, 20, 19, 18,
143 17, 16, 15, 14, 13, 12,
144 11, 10, 9, 8, 7, 6,
145 5, 4, 3, 2, 1, 0
148 uint8 target6x4_90_n_n[] = {
149 255, 19, 13, 7, 1, 255,
150 255, 20, 14, 8, 2, 255,
151 255, 21, 15, 9, 3, 255,
152 255, 22, 16, 10, 4, 255
155 uint8 target6x4_90_n_y[] = {
156 255, 1, 7, 13, 19, 255,
157 255, 2, 8, 14, 20, 255,
158 255, 3, 9, 15, 21, 255,
159 255, 4, 10, 16, 22, 255
162 uint8 target6x4_90_y_n[] = {
163 255, 22, 16, 10, 4, 255,
164 255, 21, 15, 9, 3, 255,
165 255, 20, 14, 8, 2, 255,
166 255, 19, 13, 7, 1, 255
169 uint8 target6x4_90_y_y[] = {
170 255, 4, 10, 16, 22, 255,
171 255, 3, 9, 15, 21, 255,
172 255, 2, 8, 14, 20, 255,
173 255, 1, 7, 13, 19, 255
176 uint8* target6x4_180_n_n = target6x4_0_y_y;
177 uint8* target6x4_180_n_y = target6x4_0_y_n;
178 uint8* target6x4_180_y_n = target6x4_0_n_y;
179 uint8* target6x4_180_y_y = target6x4_0_n_n;
181 uint8* target6x4_270_n_n = target6x4_90_y_y;
182 uint8* target6x4_270_n_y = target6x4_90_y_n;
183 uint8* target6x4_270_y_n = target6x4_90_n_y;
184 uint8* target6x4_270_y_y = target6x4_90_n_n;
186 uint8 src4x6[] = {
187 0, 1, 2, 3,
188 4, 5, 6, 7,
189 8, 9, 10, 11,
190 12, 13, 14, 15,
191 16, 17, 18, 19,
192 20, 21, 22, 23
195 uint8* target4x6_0_n_n = src4x6;
197 uint8 target4x6_0_n_y[] = {
198 3, 2, 1, 0,
199 7, 6, 5, 4,
200 11, 10, 9, 8,
201 15, 14, 13, 12,
202 19, 18, 17, 16,
203 23, 22, 21, 20
206 uint8 target4x6_0_y_n[] = {
207 20, 21, 22, 23,
208 16, 17, 18, 19,
209 12, 13, 14, 15,
210 8, 9, 10, 11,
211 4, 5, 6, 7,
212 0, 1, 2, 3
215 uint8 target4x6_0_y_y[] = {
216 23, 22, 21, 20,
217 19, 18, 17, 16,
218 15, 14, 13, 12,
219 11, 10, 9, 8,
220 7, 6, 5, 4,
221 3, 2, 1, 0
224 uint8 target4x6_90_n_n[] = {
225 255, 255, 255, 255,
226 16, 12, 8, 4,
227 17, 13, 9, 5,
228 18, 14, 10, 6,
229 19, 15, 11, 7,
230 255, 255, 255, 255
233 uint8 target4x6_90_n_y[] = {
234 255, 255, 255, 255,
235 4, 8, 12, 16,
236 5, 9, 13, 17,
237 6, 10, 14, 18,
238 7, 11, 15, 19,
239 255, 255, 255, 255
242 uint8 target4x6_90_y_n[] = {
243 255, 255, 255, 255,
244 19, 15, 11, 7,
245 18, 14, 10, 6,
246 17, 13, 9, 5,
247 16, 12, 8, 4,
248 255, 255, 255, 255
251 uint8 target4x6_90_y_y[] = {
252 255, 255, 255, 255,
253 7, 11, 15, 19,
254 6, 10, 14, 18,
255 5, 9, 13, 17,
256 4, 8, 12, 16,
257 255, 255, 255, 255
260 uint8* target4x6_180_n_n = target4x6_0_y_y;
261 uint8* target4x6_180_n_y = target4x6_0_y_n;
262 uint8* target4x6_180_y_n = target4x6_0_n_y;
263 uint8* target4x6_180_y_y = target4x6_0_n_n;
265 uint8* target4x6_270_n_n = target4x6_90_y_y;
266 uint8* target4x6_270_n_y = target4x6_90_y_n;
267 uint8* target4x6_270_y_n = target4x6_90_n_y;
268 uint8* target4x6_270_y_y = target4x6_90_n_n;
270 struct VideoRotationTestData {
271 uint8* src;
272 uint8* target;
273 int width;
274 int height;
275 int rotation;
276 bool flip_vert;
277 bool flip_horiz;
280 const VideoRotationTestData kVideoRotationTestData[] = {
281 { src6x4, target6x4_0_n_n, 6, 4, 0, false, false },
282 { src6x4, target6x4_0_n_y, 6, 4, 0, false, true },
283 { src6x4, target6x4_0_y_n, 6, 4, 0, true, false },
284 { src6x4, target6x4_0_y_y, 6, 4, 0, true, true },
286 { src6x4, target6x4_90_n_n, 6, 4, 90, false, false },
287 { src6x4, target6x4_90_n_y, 6, 4, 90, false, true },
288 { src6x4, target6x4_90_y_n, 6, 4, 90, true, false },
289 { src6x4, target6x4_90_y_y, 6, 4, 90, true, true },
291 { src6x4, target6x4_180_n_n, 6, 4, 180, false, false },
292 { src6x4, target6x4_180_n_y, 6, 4, 180, false, true },
293 { src6x4, target6x4_180_y_n, 6, 4, 180, true, false },
294 { src6x4, target6x4_180_y_y, 6, 4, 180, true, true },
296 { src6x4, target6x4_270_n_n, 6, 4, 270, false, false },
297 { src6x4, target6x4_270_n_y, 6, 4, 270, false, true },
298 { src6x4, target6x4_270_y_n, 6, 4, 270, true, false },
299 { src6x4, target6x4_270_y_y, 6, 4, 270, true, true },
301 { src4x6, target4x6_0_n_n, 4, 6, 0, false, false },
302 { src4x6, target4x6_0_n_y, 4, 6, 0, false, true },
303 { src4x6, target4x6_0_y_n, 4, 6, 0, true, false },
304 { src4x6, target4x6_0_y_y, 4, 6, 0, true, true },
306 { src4x6, target4x6_90_n_n, 4, 6, 90, false, false },
307 { src4x6, target4x6_90_n_y, 4, 6, 90, false, true },
308 { src4x6, target4x6_90_y_n, 4, 6, 90, true, false },
309 { src4x6, target4x6_90_y_y, 4, 6, 90, true, true },
311 { src4x6, target4x6_180_n_n, 4, 6, 180, false, false },
312 { src4x6, target4x6_180_n_y, 4, 6, 180, false, true },
313 { src4x6, target4x6_180_y_n, 4, 6, 180, true, false },
314 { src4x6, target4x6_180_y_y, 4, 6, 180, true, true },
316 { src4x6, target4x6_270_n_n, 4, 6, 270, false, false },
317 { src4x6, target4x6_270_n_y, 4, 6, 270, false, true },
318 { src4x6, target4x6_270_y_n, 4, 6, 270, true, false },
319 { src4x6, target4x6_270_y_y, 4, 6, 270, true, true }
322 } // namespace
324 class VideoUtilRotationTest
325 : public testing::TestWithParam<VideoRotationTestData> {
326 public:
327 VideoUtilRotationTest() {
328 dest_.reset(new uint8[GetParam().width * GetParam().height]);
331 virtual ~VideoUtilRotationTest() {}
333 uint8* dest_plane() { return dest_.get(); }
335 private:
336 scoped_ptr<uint8[]> dest_;
338 DISALLOW_COPY_AND_ASSIGN(VideoUtilRotationTest);
341 TEST_P(VideoUtilRotationTest, Rotate) {
342 int rotation = GetParam().rotation;
343 EXPECT_TRUE((rotation >= 0) && (rotation < 360) && (rotation % 90 == 0));
345 int size = GetParam().width * GetParam().height;
346 uint8* dest = dest_plane();
347 memset(dest, 255, size);
349 RotatePlaneByPixels(GetParam().src, dest, GetParam().width,
350 GetParam().height, rotation,
351 GetParam().flip_vert, GetParam().flip_horiz);
353 EXPECT_EQ(memcmp(dest, GetParam().target, size), 0);
356 INSTANTIATE_TEST_CASE_P(, VideoUtilRotationTest,
357 testing::ValuesIn(kVideoRotationTestData));
359 // Tests the ComputeLetterboxRegion function. Also, because of shared code
360 // internally, this also tests ScaleSizeToFitWithinTarget().
361 TEST_F(VideoUtilTest, ComputeLetterboxRegion) {
362 EXPECT_EQ(gfx::Rect(166, 0, 667, 500),
363 ComputeLetterboxRegion(gfx::Rect(0, 0, 1000, 500),
364 gfx::Size(640, 480)));
365 EXPECT_EQ(gfx::Rect(0, 312, 500, 375),
366 ComputeLetterboxRegion(gfx::Rect(0, 0, 500, 1000),
367 gfx::Size(640, 480)));
368 EXPECT_EQ(gfx::Rect(55, 0, 889, 500),
369 ComputeLetterboxRegion(gfx::Rect(0, 0, 1000, 500),
370 gfx::Size(1920, 1080)));
371 EXPECT_EQ(gfx::Rect(0, 12, 100, 75),
372 ComputeLetterboxRegion(gfx::Rect(0, 0, 100, 100),
373 gfx::Size(400, 300)));
374 EXPECT_EQ(gfx::Rect(0, 250000000, 2000000000, 1500000000),
375 ComputeLetterboxRegion(gfx::Rect(0, 0, 2000000000, 2000000000),
376 gfx::Size(40000, 30000)));
377 EXPECT_TRUE(ComputeLetterboxRegion(gfx::Rect(0, 0, 2000000000, 2000000000),
378 gfx::Size(0, 0)).IsEmpty());
381 TEST_F(VideoUtilTest, ScaleSizeToEncompassTarget) {
382 EXPECT_EQ(gfx::Size(1000, 750),
383 ScaleSizeToEncompassTarget(gfx::Size(640, 480),
384 gfx::Size(1000, 500)));
385 EXPECT_EQ(gfx::Size(1333, 1000),
386 ScaleSizeToEncompassTarget(gfx::Size(640, 480),
387 gfx::Size(500, 1000)));
388 EXPECT_EQ(gfx::Size(1000, 563),
389 ScaleSizeToEncompassTarget(gfx::Size(1920, 1080),
390 gfx::Size(1000, 500)));
391 EXPECT_EQ(gfx::Size(133, 100),
392 ScaleSizeToEncompassTarget(gfx::Size(400, 300),
393 gfx::Size(100, 100)));
394 EXPECT_EQ(gfx::Size(266666667, 200000000),
395 ScaleSizeToEncompassTarget(gfx::Size(40000, 30000),
396 gfx::Size(200000000, 200000000)));
397 EXPECT_TRUE(ScaleSizeToEncompassTarget(
398 gfx::Size(0, 0), gfx::Size(2000000000, 2000000000)).IsEmpty());
401 TEST_F(VideoUtilTest, PadToMatchAspectRatio) {
402 EXPECT_EQ(gfx::Size(640, 480),
403 PadToMatchAspectRatio(gfx::Size(640, 480), gfx::Size(640, 480)));
404 EXPECT_EQ(gfx::Size(640, 480),
405 PadToMatchAspectRatio(gfx::Size(640, 480), gfx::Size(4, 3)));
406 EXPECT_EQ(gfx::Size(960, 480),
407 PadToMatchAspectRatio(gfx::Size(640, 480), gfx::Size(1000, 500)));
408 EXPECT_EQ(gfx::Size(640, 1280),
409 PadToMatchAspectRatio(gfx::Size(640, 480), gfx::Size(500, 1000)));
410 EXPECT_EQ(gfx::Size(2160, 1080),
411 PadToMatchAspectRatio(gfx::Size(1920, 1080), gfx::Size(1000, 500)));
412 EXPECT_EQ(gfx::Size(400, 400),
413 PadToMatchAspectRatio(gfx::Size(400, 300), gfx::Size(100, 100)));
414 EXPECT_EQ(gfx::Size(400, 400),
415 PadToMatchAspectRatio(gfx::Size(300, 400), gfx::Size(100, 100)));
416 EXPECT_EQ(gfx::Size(40000, 40000),
417 PadToMatchAspectRatio(gfx::Size(40000, 30000),
418 gfx::Size(2000000000, 2000000000)));
419 EXPECT_TRUE(PadToMatchAspectRatio(
420 gfx::Size(40000, 30000), gfx::Size(0, 0)).IsEmpty());
423 TEST_F(VideoUtilTest, LetterboxYUV) {
424 int width = 40;
425 int height = 30;
426 gfx::Size size(width, height);
427 scoped_refptr<VideoFrame> frame(VideoFrame::CreateFrame(
428 PIXEL_FORMAT_YV12, size, gfx::Rect(size), size, base::TimeDelta()));
430 for (int left_margin = 0; left_margin <= 10; left_margin += 10) {
431 for (int right_margin = 0; right_margin <= 10; right_margin += 10) {
432 for (int top_margin = 0; top_margin <= 10; top_margin += 10) {
433 for (int bottom_margin = 0; bottom_margin <= 10; bottom_margin += 10) {
434 gfx::Rect view_area(left_margin, top_margin,
435 width - left_margin - right_margin,
436 height - top_margin - bottom_margin);
437 FillYUV(frame.get(), 0x1, 0x2, 0x3);
438 LetterboxYUV(frame.get(), view_area);
439 for (int x = 0; x < width; x++) {
440 for (int y = 0; y < height; y++) {
441 bool inside = x >= view_area.x() &&
442 x < view_area.x() + view_area.width() &&
443 y >= view_area.y() &&
444 y < view_area.y() + view_area.height();
445 EXPECT_EQ(frame->data(VideoFrame::kYPlane)[
446 y * frame->stride(VideoFrame::kYPlane) + x],
447 inside ? 0x01 : 0x00);
448 EXPECT_EQ(frame->data(VideoFrame::kUPlane)[
449 (y / 2) * frame->stride(VideoFrame::kUPlane) + (x / 2)],
450 inside ? 0x02 : 0x80);
451 EXPECT_EQ(frame->data(VideoFrame::kVPlane)[
452 (y / 2) * frame->stride(VideoFrame::kVPlane) + (x / 2)],
453 inside ? 0x03 : 0x80);
462 } // namespace media