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
);
42 VideoFrame::CreateFrame(VideoFrame::YV12
, size
, gfx::Rect(size
), size
,
47 CopyYPlane(y_plane_
.get(), y_stride_
, height_
, destination_frame_
.get());
49 u_plane_
.get(), u_stride_
, height_
/ 2, destination_frame_
.get());
51 v_plane_
.get(), v_stride_
, height_
/ 2, destination_frame_
.get());
55 scoped_ptr
<uint8
[]> y_plane_
;
56 scoped_ptr
<uint8
[]> u_plane_
;
57 scoped_ptr
<uint8
[]> v_plane_
;
64 scoped_refptr
<VideoFrame
> destination_frame_
;
66 DISALLOW_COPY_AND_ASSIGN(VideoUtilTest
);
69 TEST_F(VideoUtilTest
, CopyPlane_Exact
) {
70 CreateSourceFrame(16, 16, 16, 8, 8);
71 CreateDestinationFrame(16, 16);
75 TEST_F(VideoUtilTest
, CopyPlane_SmallerSource
) {
76 CreateSourceFrame(8, 8, 8, 4, 4);
77 CreateDestinationFrame(16, 16);
81 TEST_F(VideoUtilTest
, CopyPlane_SmallerDestination
) {
82 CreateSourceFrame(16, 16, 16, 8, 8);
83 CreateDestinationFrame(8, 8);
92 12, 13, 14, 15, 16, 17,
93 18, 19, 20, 21, 22, 23
96 // Target images, name pattern target_rotation_flipV_flipH.
97 uint8
* target6x4_0_n_n
= src6x4
;
99 uint8 target6x4_0_n_y
[] = {
102 17, 16, 15, 14, 13, 12,
103 23, 22, 21, 20, 19, 18
106 uint8 target6x4_0_y_n
[] = {
107 18, 19, 20, 21, 22, 23,
108 12, 13, 14, 15, 16, 17,
113 uint8 target6x4_0_y_y
[] = {
114 23, 22, 21, 20, 19, 18,
115 17, 16, 15, 14, 13, 12,
120 uint8 target6x4_90_n_n
[] = {
121 255, 19, 13, 7, 1, 255,
122 255, 20, 14, 8, 2, 255,
123 255, 21, 15, 9, 3, 255,
124 255, 22, 16, 10, 4, 255
127 uint8 target6x4_90_n_y
[] = {
128 255, 1, 7, 13, 19, 255,
129 255, 2, 8, 14, 20, 255,
130 255, 3, 9, 15, 21, 255,
131 255, 4, 10, 16, 22, 255
134 uint8 target6x4_90_y_n
[] = {
135 255, 22, 16, 10, 4, 255,
136 255, 21, 15, 9, 3, 255,
137 255, 20, 14, 8, 2, 255,
138 255, 19, 13, 7, 1, 255
141 uint8 target6x4_90_y_y
[] = {
142 255, 4, 10, 16, 22, 255,
143 255, 3, 9, 15, 21, 255,
144 255, 2, 8, 14, 20, 255,
145 255, 1, 7, 13, 19, 255
148 uint8
* target6x4_180_n_n
= target6x4_0_y_y
;
149 uint8
* target6x4_180_n_y
= target6x4_0_y_n
;
150 uint8
* target6x4_180_y_n
= target6x4_0_n_y
;
151 uint8
* target6x4_180_y_y
= target6x4_0_n_n
;
153 uint8
* target6x4_270_n_n
= target6x4_90_y_y
;
154 uint8
* target6x4_270_n_y
= target6x4_90_y_n
;
155 uint8
* target6x4_270_y_n
= target6x4_90_n_y
;
156 uint8
* target6x4_270_y_y
= target6x4_90_n_n
;
167 uint8
* target4x6_0_n_n
= src4x6
;
169 uint8 target4x6_0_n_y
[] = {
178 uint8 target4x6_0_y_n
[] = {
187 uint8 target4x6_0_y_y
[] = {
196 uint8 target4x6_90_n_n
[] = {
205 uint8 target4x6_90_n_y
[] = {
214 uint8 target4x6_90_y_n
[] = {
223 uint8 target4x6_90_y_y
[] = {
232 uint8
* target4x6_180_n_n
= target4x6_0_y_y
;
233 uint8
* target4x6_180_n_y
= target4x6_0_y_n
;
234 uint8
* target4x6_180_y_n
= target4x6_0_n_y
;
235 uint8
* target4x6_180_y_y
= target4x6_0_n_n
;
237 uint8
* target4x6_270_n_n
= target4x6_90_y_y
;
238 uint8
* target4x6_270_n_y
= target4x6_90_y_n
;
239 uint8
* target4x6_270_y_n
= target4x6_90_n_y
;
240 uint8
* target4x6_270_y_y
= target4x6_90_n_n
;
242 struct VideoRotationTestData
{
252 const VideoRotationTestData kVideoRotationTestData
[] = {
253 { src6x4
, target6x4_0_n_n
, 6, 4, 0, false, false },
254 { src6x4
, target6x4_0_n_y
, 6, 4, 0, false, true },
255 { src6x4
, target6x4_0_y_n
, 6, 4, 0, true, false },
256 { src6x4
, target6x4_0_y_y
, 6, 4, 0, true, true },
258 { src6x4
, target6x4_90_n_n
, 6, 4, 90, false, false },
259 { src6x4
, target6x4_90_n_y
, 6, 4, 90, false, true },
260 { src6x4
, target6x4_90_y_n
, 6, 4, 90, true, false },
261 { src6x4
, target6x4_90_y_y
, 6, 4, 90, true, true },
263 { src6x4
, target6x4_180_n_n
, 6, 4, 180, false, false },
264 { src6x4
, target6x4_180_n_y
, 6, 4, 180, false, true },
265 { src6x4
, target6x4_180_y_n
, 6, 4, 180, true, false },
266 { src6x4
, target6x4_180_y_y
, 6, 4, 180, true, true },
268 { src6x4
, target6x4_270_n_n
, 6, 4, 270, false, false },
269 { src6x4
, target6x4_270_n_y
, 6, 4, 270, false, true },
270 { src6x4
, target6x4_270_y_n
, 6, 4, 270, true, false },
271 { src6x4
, target6x4_270_y_y
, 6, 4, 270, true, true },
273 { src4x6
, target4x6_0_n_n
, 4, 6, 0, false, false },
274 { src4x6
, target4x6_0_n_y
, 4, 6, 0, false, true },
275 { src4x6
, target4x6_0_y_n
, 4, 6, 0, true, false },
276 { src4x6
, target4x6_0_y_y
, 4, 6, 0, true, true },
278 { src4x6
, target4x6_90_n_n
, 4, 6, 90, false, false },
279 { src4x6
, target4x6_90_n_y
, 4, 6, 90, false, true },
280 { src4x6
, target4x6_90_y_n
, 4, 6, 90, true, false },
281 { src4x6
, target4x6_90_y_y
, 4, 6, 90, true, true },
283 { src4x6
, target4x6_180_n_n
, 4, 6, 180, false, false },
284 { src4x6
, target4x6_180_n_y
, 4, 6, 180, false, true },
285 { src4x6
, target4x6_180_y_n
, 4, 6, 180, true, false },
286 { src4x6
, target4x6_180_y_y
, 4, 6, 180, true, true },
288 { src4x6
, target4x6_270_n_n
, 4, 6, 270, false, false },
289 { src4x6
, target4x6_270_n_y
, 4, 6, 270, false, true },
290 { src4x6
, target4x6_270_y_n
, 4, 6, 270, true, false },
291 { src4x6
, target4x6_270_y_y
, 4, 6, 270, true, true }
296 class VideoUtilRotationTest
297 : public testing::TestWithParam
<VideoRotationTestData
> {
299 VideoUtilRotationTest() {
300 dest_
.reset(new uint8
[GetParam().width
* GetParam().height
]);
303 virtual ~VideoUtilRotationTest() {}
305 uint8
* dest_plane() { return dest_
.get(); }
308 scoped_ptr
<uint8
[]> dest_
;
310 DISALLOW_COPY_AND_ASSIGN(VideoUtilRotationTest
);
313 TEST_P(VideoUtilRotationTest
, Rotate
) {
314 int rotation
= GetParam().rotation
;
315 EXPECT_TRUE((rotation
>= 0) && (rotation
< 360) && (rotation
% 90 == 0));
317 int size
= GetParam().width
* GetParam().height
;
318 uint8
* dest
= dest_plane();
319 memset(dest
, 255, size
);
321 RotatePlaneByPixels(GetParam().src
, dest
, GetParam().width
,
322 GetParam().height
, rotation
,
323 GetParam().flip_vert
, GetParam().flip_horiz
);
325 EXPECT_EQ(memcmp(dest
, GetParam().target
, size
), 0);
328 INSTANTIATE_TEST_CASE_P(, VideoUtilRotationTest
,
329 testing::ValuesIn(kVideoRotationTestData
));
331 // Tests the ComputeLetterboxRegion function. Also, because of shared code
332 // internally, this also tests ScaleSizeToFitWithinTarget().
333 TEST_F(VideoUtilTest
, ComputeLetterboxRegion
) {
334 EXPECT_EQ(gfx::Rect(167, 0, 666, 500),
335 ComputeLetterboxRegion(gfx::Rect(0, 0, 1000, 500),
336 gfx::Size(640, 480)));
337 EXPECT_EQ(gfx::Rect(0, 312, 500, 375),
338 ComputeLetterboxRegion(gfx::Rect(0, 0, 500, 1000),
339 gfx::Size(640, 480)));
340 EXPECT_EQ(gfx::Rect(56, 0, 888, 500),
341 ComputeLetterboxRegion(gfx::Rect(0, 0, 1000, 500),
342 gfx::Size(1920, 1080)));
343 EXPECT_EQ(gfx::Rect(0, 12, 100, 75),
344 ComputeLetterboxRegion(gfx::Rect(0, 0, 100, 100),
345 gfx::Size(400, 300)));
346 EXPECT_EQ(gfx::Rect(0, 250000000, 2000000000, 1500000000),
347 ComputeLetterboxRegion(gfx::Rect(0, 0, 2000000000, 2000000000),
348 gfx::Size(40000, 30000)));
349 EXPECT_TRUE(ComputeLetterboxRegion(gfx::Rect(0, 0, 2000000000, 2000000000),
350 gfx::Size(0, 0)).IsEmpty());
353 TEST_F(VideoUtilTest
, ScaleSizeToEncompassTarget
) {
354 EXPECT_EQ(gfx::Size(1000, 750),
355 ScaleSizeToEncompassTarget(gfx::Size(640, 480),
356 gfx::Size(1000, 500)));
357 EXPECT_EQ(gfx::Size(1333, 1000),
358 ScaleSizeToEncompassTarget(gfx::Size(640, 480),
359 gfx::Size(500, 1000)));
360 EXPECT_EQ(gfx::Size(1000, 562),
361 ScaleSizeToEncompassTarget(gfx::Size(1920, 1080),
362 gfx::Size(1000, 500)));
363 EXPECT_EQ(gfx::Size(133, 100),
364 ScaleSizeToEncompassTarget(gfx::Size(400, 300),
365 gfx::Size(100, 100)));
366 EXPECT_EQ(gfx::Size(2666666666, 2000000000),
367 ScaleSizeToEncompassTarget(gfx::Size(40000, 30000),
368 gfx::Size(2000000000, 2000000000)));
369 EXPECT_TRUE(ScaleSizeToEncompassTarget(
370 gfx::Size(0, 0), gfx::Size(2000000000, 2000000000)).IsEmpty());
373 TEST_F(VideoUtilTest
, PadToMatchAspectRatio
) {
374 EXPECT_EQ(gfx::Size(640, 480),
375 PadToMatchAspectRatio(gfx::Size(640, 480), gfx::Size(640, 480)));
376 EXPECT_EQ(gfx::Size(640, 480),
377 PadToMatchAspectRatio(gfx::Size(640, 480), gfx::Size(4, 3)));
378 EXPECT_EQ(gfx::Size(960, 480),
379 PadToMatchAspectRatio(gfx::Size(640, 480), gfx::Size(1000, 500)));
380 EXPECT_EQ(gfx::Size(640, 1280),
381 PadToMatchAspectRatio(gfx::Size(640, 480), gfx::Size(500, 1000)));
382 EXPECT_EQ(gfx::Size(2160, 1080),
383 PadToMatchAspectRatio(gfx::Size(1920, 1080), gfx::Size(1000, 500)));
384 EXPECT_EQ(gfx::Size(400, 400),
385 PadToMatchAspectRatio(gfx::Size(400, 300), gfx::Size(100, 100)));
386 EXPECT_EQ(gfx::Size(400, 400),
387 PadToMatchAspectRatio(gfx::Size(300, 400), gfx::Size(100, 100)));
388 EXPECT_EQ(gfx::Size(40000, 40000),
389 PadToMatchAspectRatio(gfx::Size(40000, 30000),
390 gfx::Size(2000000000, 2000000000)));
391 EXPECT_TRUE(PadToMatchAspectRatio(
392 gfx::Size(40000, 30000), gfx::Size(0, 0)).IsEmpty());
395 TEST_F(VideoUtilTest
, LetterboxYUV
) {
398 gfx::Size
size(width
, height
);
399 scoped_refptr
<VideoFrame
> frame(
400 VideoFrame::CreateFrame(VideoFrame::YV12
, size
, gfx::Rect(size
), size
,
403 for (int left_margin
= 0; left_margin
<= 10; left_margin
+= 10) {
404 for (int right_margin
= 0; right_margin
<= 10; right_margin
+= 10) {
405 for (int top_margin
= 0; top_margin
<= 10; top_margin
+= 10) {
406 for (int bottom_margin
= 0; bottom_margin
<= 10; bottom_margin
+= 10) {
407 gfx::Rect
view_area(left_margin
, top_margin
,
408 width
- left_margin
- right_margin
,
409 height
- top_margin
- bottom_margin
);
410 FillYUV(frame
.get(), 0x1, 0x2, 0x3);
411 LetterboxYUV(frame
.get(), view_area
);
412 for (int x
= 0; x
< width
; x
++) {
413 for (int y
= 0; y
< height
; y
++) {
414 bool inside
= x
>= view_area
.x() &&
415 x
< view_area
.x() + view_area
.width() &&
416 y
>= view_area
.y() &&
417 y
< view_area
.y() + view_area
.height();
418 EXPECT_EQ(frame
->data(VideoFrame::kYPlane
)[
419 y
* frame
->stride(VideoFrame::kYPlane
) + x
],
420 inside
? 0x01 : 0x00);
421 EXPECT_EQ(frame
->data(VideoFrame::kUPlane
)[
422 (y
/ 2) * frame
->stride(VideoFrame::kUPlane
) + (x
/ 2)],
423 inside
? 0x02 : 0x80);
424 EXPECT_EQ(frame
->data(VideoFrame::kVPlane
)[
425 (y
/ 2) * frame
->stride(VideoFrame::kVPlane
) + (x
/ 2)],
426 inside
? 0x03 : 0x80);