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"
12 class VideoUtilTest
: public testing::Test
{
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);
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());
46 CopyYPlane(y_plane_
.get(), y_stride_
, height_
, destination_frame_
.get());
48 u_plane_
.get(), u_stride_
, height_
/ 2, destination_frame_
.get());
50 v_plane_
.get(), v_stride_
, height_
/ 2, destination_frame_
.get());
54 scoped_ptr
<uint8
[]> y_plane_
;
55 scoped_ptr
<uint8
[]> u_plane_
;
56 scoped_ptr
<uint8
[]> v_plane_
;
63 scoped_refptr
<VideoFrame
> destination_frame_
;
65 DISALLOW_COPY_AND_ASSIGN(VideoUtilTest
);
68 TEST_F(VideoUtilTest
, CopyPlane_Exact
) {
69 CreateSourceFrame(16, 16, 16, 8, 8);
70 CreateDestinationFrame(16, 16);
74 TEST_F(VideoUtilTest
, CopyPlane_SmallerSource
) {
75 CreateSourceFrame(8, 8, 8, 4, 4);
76 CreateDestinationFrame(16, 16);
80 TEST_F(VideoUtilTest
, CopyPlane_SmallerDestination
) {
81 CreateSourceFrame(16, 16, 16, 8, 8);
82 CreateDestinationFrame(8, 8);
91 12, 13, 14, 15, 16, 17,
92 18, 19, 20, 21, 22, 23
95 // Target images, name pattern target_rotation_flipV_flipH.
96 uint8
* target6x4_0_n_n
= src6x4
;
98 uint8 target6x4_0_n_y
[] = {
101 17, 16, 15, 14, 13, 12,
102 23, 22, 21, 20, 19, 18
105 uint8 target6x4_0_y_n
[] = {
106 18, 19, 20, 21, 22, 23,
107 12, 13, 14, 15, 16, 17,
112 uint8 target6x4_0_y_y
[] = {
113 23, 22, 21, 20, 19, 18,
114 17, 16, 15, 14, 13, 12,
119 uint8 target6x4_90_n_n
[] = {
120 255, 19, 13, 7, 1, 255,
121 255, 20, 14, 8, 2, 255,
122 255, 21, 15, 9, 3, 255,
123 255, 22, 16, 10, 4, 255
126 uint8 target6x4_90_n_y
[] = {
127 255, 1, 7, 13, 19, 255,
128 255, 2, 8, 14, 20, 255,
129 255, 3, 9, 15, 21, 255,
130 255, 4, 10, 16, 22, 255
133 uint8 target6x4_90_y_n
[] = {
134 255, 22, 16, 10, 4, 255,
135 255, 21, 15, 9, 3, 255,
136 255, 20, 14, 8, 2, 255,
137 255, 19, 13, 7, 1, 255
140 uint8 target6x4_90_y_y
[] = {
141 255, 4, 10, 16, 22, 255,
142 255, 3, 9, 15, 21, 255,
143 255, 2, 8, 14, 20, 255,
144 255, 1, 7, 13, 19, 255
147 uint8
* target6x4_180_n_n
= target6x4_0_y_y
;
148 uint8
* target6x4_180_n_y
= target6x4_0_y_n
;
149 uint8
* target6x4_180_y_n
= target6x4_0_n_y
;
150 uint8
* target6x4_180_y_y
= target6x4_0_n_n
;
152 uint8
* target6x4_270_n_n
= target6x4_90_y_y
;
153 uint8
* target6x4_270_n_y
= target6x4_90_y_n
;
154 uint8
* target6x4_270_y_n
= target6x4_90_n_y
;
155 uint8
* target6x4_270_y_y
= target6x4_90_n_n
;
166 uint8
* target4x6_0_n_n
= src4x6
;
168 uint8 target4x6_0_n_y
[] = {
177 uint8 target4x6_0_y_n
[] = {
186 uint8 target4x6_0_y_y
[] = {
195 uint8 target4x6_90_n_n
[] = {
204 uint8 target4x6_90_n_y
[] = {
213 uint8 target4x6_90_y_n
[] = {
222 uint8 target4x6_90_y_y
[] = {
231 uint8
* target4x6_180_n_n
= target4x6_0_y_y
;
232 uint8
* target4x6_180_n_y
= target4x6_0_y_n
;
233 uint8
* target4x6_180_y_n
= target4x6_0_n_y
;
234 uint8
* target4x6_180_y_y
= target4x6_0_n_n
;
236 uint8
* target4x6_270_n_n
= target4x6_90_y_y
;
237 uint8
* target4x6_270_n_y
= target4x6_90_y_n
;
238 uint8
* target4x6_270_y_n
= target4x6_90_n_y
;
239 uint8
* target4x6_270_y_y
= target4x6_90_n_n
;
241 struct VideoRotationTestData
{
251 const VideoRotationTestData kVideoRotationTestData
[] = {
252 { src6x4
, target6x4_0_n_n
, 6, 4, 0, false, false },
253 { src6x4
, target6x4_0_n_y
, 6, 4, 0, false, true },
254 { src6x4
, target6x4_0_y_n
, 6, 4, 0, true, false },
255 { src6x4
, target6x4_0_y_y
, 6, 4, 0, true, true },
257 { src6x4
, target6x4_90_n_n
, 6, 4, 90, false, false },
258 { src6x4
, target6x4_90_n_y
, 6, 4, 90, false, true },
259 { src6x4
, target6x4_90_y_n
, 6, 4, 90, true, false },
260 { src6x4
, target6x4_90_y_y
, 6, 4, 90, true, true },
262 { src6x4
, target6x4_180_n_n
, 6, 4, 180, false, false },
263 { src6x4
, target6x4_180_n_y
, 6, 4, 180, false, true },
264 { src6x4
, target6x4_180_y_n
, 6, 4, 180, true, false },
265 { src6x4
, target6x4_180_y_y
, 6, 4, 180, true, true },
267 { src6x4
, target6x4_270_n_n
, 6, 4, 270, false, false },
268 { src6x4
, target6x4_270_n_y
, 6, 4, 270, false, true },
269 { src6x4
, target6x4_270_y_n
, 6, 4, 270, true, false },
270 { src6x4
, target6x4_270_y_y
, 6, 4, 270, true, true },
272 { src4x6
, target4x6_0_n_n
, 4, 6, 0, false, false },
273 { src4x6
, target4x6_0_n_y
, 4, 6, 0, false, true },
274 { src4x6
, target4x6_0_y_n
, 4, 6, 0, true, false },
275 { src4x6
, target4x6_0_y_y
, 4, 6, 0, true, true },
277 { src4x6
, target4x6_90_n_n
, 4, 6, 90, false, false },
278 { src4x6
, target4x6_90_n_y
, 4, 6, 90, false, true },
279 { src4x6
, target4x6_90_y_n
, 4, 6, 90, true, false },
280 { src4x6
, target4x6_90_y_y
, 4, 6, 90, true, true },
282 { src4x6
, target4x6_180_n_n
, 4, 6, 180, false, false },
283 { src4x6
, target4x6_180_n_y
, 4, 6, 180, false, true },
284 { src4x6
, target4x6_180_y_n
, 4, 6, 180, true, false },
285 { src4x6
, target4x6_180_y_y
, 4, 6, 180, true, true },
287 { src4x6
, target4x6_270_n_n
, 4, 6, 270, false, false },
288 { src4x6
, target4x6_270_n_y
, 4, 6, 270, false, true },
289 { src4x6
, target4x6_270_y_n
, 4, 6, 270, true, false },
290 { src4x6
, target4x6_270_y_y
, 4, 6, 270, true, true }
295 class VideoUtilRotationTest
296 : public testing::TestWithParam
<VideoRotationTestData
> {
298 VideoUtilRotationTest() {
299 dest_
.reset(new uint8
[GetParam().width
* GetParam().height
]);
302 virtual ~VideoUtilRotationTest() {}
304 uint8
* dest_plane() { return dest_
.get(); }
307 scoped_ptr
<uint8
[]> dest_
;
309 DISALLOW_COPY_AND_ASSIGN(VideoUtilRotationTest
);
312 TEST_P(VideoUtilRotationTest
, Rotate
) {
313 int rotation
= GetParam().rotation
;
314 EXPECT_TRUE((rotation
>= 0) && (rotation
< 360) && (rotation
% 90 == 0));
316 int size
= GetParam().width
* GetParam().height
;
317 uint8
* dest
= dest_plane();
318 memset(dest
, 255, size
);
320 RotatePlaneByPixels(GetParam().src
, dest
, GetParam().width
,
321 GetParam().height
, rotation
,
322 GetParam().flip_vert
, GetParam().flip_horiz
);
324 EXPECT_EQ(memcmp(dest
, GetParam().target
, size
), 0);
327 INSTANTIATE_TEST_CASE_P(, VideoUtilRotationTest
,
328 testing::ValuesIn(kVideoRotationTestData
));
330 // Tests the ComputeLetterboxRegion function. Also, because of shared code
331 // internally, this also tests ScaleSizeToFitWithinTarget().
332 TEST_F(VideoUtilTest
, ComputeLetterboxRegion
) {
333 EXPECT_EQ(gfx::Rect(166, 0, 667, 500),
334 ComputeLetterboxRegion(gfx::Rect(0, 0, 1000, 500),
335 gfx::Size(640, 480)));
336 EXPECT_EQ(gfx::Rect(0, 312, 500, 375),
337 ComputeLetterboxRegion(gfx::Rect(0, 0, 500, 1000),
338 gfx::Size(640, 480)));
339 EXPECT_EQ(gfx::Rect(55, 0, 889, 500),
340 ComputeLetterboxRegion(gfx::Rect(0, 0, 1000, 500),
341 gfx::Size(1920, 1080)));
342 EXPECT_EQ(gfx::Rect(0, 12, 100, 75),
343 ComputeLetterboxRegion(gfx::Rect(0, 0, 100, 100),
344 gfx::Size(400, 300)));
345 EXPECT_EQ(gfx::Rect(0, 250000000, 2000000000, 1500000000),
346 ComputeLetterboxRegion(gfx::Rect(0, 0, 2000000000, 2000000000),
347 gfx::Size(40000, 30000)));
348 EXPECT_TRUE(ComputeLetterboxRegion(gfx::Rect(0, 0, 2000000000, 2000000000),
349 gfx::Size(0, 0)).IsEmpty());
352 TEST_F(VideoUtilTest
, ScaleSizeToEncompassTarget
) {
353 EXPECT_EQ(gfx::Size(1000, 750),
354 ScaleSizeToEncompassTarget(gfx::Size(640, 480),
355 gfx::Size(1000, 500)));
356 EXPECT_EQ(gfx::Size(1333, 1000),
357 ScaleSizeToEncompassTarget(gfx::Size(640, 480),
358 gfx::Size(500, 1000)));
359 EXPECT_EQ(gfx::Size(1000, 563),
360 ScaleSizeToEncompassTarget(gfx::Size(1920, 1080),
361 gfx::Size(1000, 500)));
362 EXPECT_EQ(gfx::Size(133, 100),
363 ScaleSizeToEncompassTarget(gfx::Size(400, 300),
364 gfx::Size(100, 100)));
365 EXPECT_EQ(gfx::Size(266666667, 200000000),
366 ScaleSizeToEncompassTarget(gfx::Size(40000, 30000),
367 gfx::Size(200000000, 200000000)));
368 EXPECT_TRUE(ScaleSizeToEncompassTarget(
369 gfx::Size(0, 0), gfx::Size(2000000000, 2000000000)).IsEmpty());
372 TEST_F(VideoUtilTest
, PadToMatchAspectRatio
) {
373 EXPECT_EQ(gfx::Size(640, 480),
374 PadToMatchAspectRatio(gfx::Size(640, 480), gfx::Size(640, 480)));
375 EXPECT_EQ(gfx::Size(640, 480),
376 PadToMatchAspectRatio(gfx::Size(640, 480), gfx::Size(4, 3)));
377 EXPECT_EQ(gfx::Size(960, 480),
378 PadToMatchAspectRatio(gfx::Size(640, 480), gfx::Size(1000, 500)));
379 EXPECT_EQ(gfx::Size(640, 1280),
380 PadToMatchAspectRatio(gfx::Size(640, 480), gfx::Size(500, 1000)));
381 EXPECT_EQ(gfx::Size(2160, 1080),
382 PadToMatchAspectRatio(gfx::Size(1920, 1080), gfx::Size(1000, 500)));
383 EXPECT_EQ(gfx::Size(400, 400),
384 PadToMatchAspectRatio(gfx::Size(400, 300), gfx::Size(100, 100)));
385 EXPECT_EQ(gfx::Size(400, 400),
386 PadToMatchAspectRatio(gfx::Size(300, 400), gfx::Size(100, 100)));
387 EXPECT_EQ(gfx::Size(40000, 40000),
388 PadToMatchAspectRatio(gfx::Size(40000, 30000),
389 gfx::Size(2000000000, 2000000000)));
390 EXPECT_TRUE(PadToMatchAspectRatio(
391 gfx::Size(40000, 30000), gfx::Size(0, 0)).IsEmpty());
394 TEST_F(VideoUtilTest
, LetterboxYUV
) {
397 gfx::Size
size(width
, height
);
398 scoped_refptr
<VideoFrame
> frame(VideoFrame::CreateFrame(
399 PIXEL_FORMAT_YV12
, size
, gfx::Rect(size
), size
, base::TimeDelta()));
401 for (int left_margin
= 0; left_margin
<= 10; left_margin
+= 10) {
402 for (int right_margin
= 0; right_margin
<= 10; right_margin
+= 10) {
403 for (int top_margin
= 0; top_margin
<= 10; top_margin
+= 10) {
404 for (int bottom_margin
= 0; bottom_margin
<= 10; bottom_margin
+= 10) {
405 gfx::Rect
view_area(left_margin
, top_margin
,
406 width
- left_margin
- right_margin
,
407 height
- top_margin
- bottom_margin
);
408 FillYUV(frame
.get(), 0x1, 0x2, 0x3);
409 LetterboxYUV(frame
.get(), view_area
);
410 for (int x
= 0; x
< width
; x
++) {
411 for (int y
= 0; y
< height
; y
++) {
412 bool inside
= x
>= view_area
.x() &&
413 x
< view_area
.x() + view_area
.width() &&
414 y
>= view_area
.y() &&
415 y
< view_area
.y() + view_area
.height();
416 EXPECT_EQ(frame
->data(VideoFrame::kYPlane
)[
417 y
* frame
->stride(VideoFrame::kYPlane
) + x
],
418 inside
? 0x01 : 0x00);
419 EXPECT_EQ(frame
->data(VideoFrame::kUPlane
)[
420 (y
/ 2) * frame
->stride(VideoFrame::kUPlane
) + (x
/ 2)],
421 inside
? 0x02 : 0x80);
422 EXPECT_EQ(frame
->data(VideoFrame::kVPlane
)[
423 (y
/ 2) * frame
->stride(VideoFrame::kVPlane
) + (x
/ 2)],
424 inside
? 0x03 : 0x80);