1 /*
2 * Copyright (c) 2018 The WebRTC project authors. All Rights Reserved.
3 *
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
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
11 #include "rtc_tools/frame_analyzer/video_geometry_aligner.h"
12
13 #include <vector>
14
15 #include "api/video/i420_buffer.h"
16 #include "rtc_tools/frame_analyzer/video_quality_analysis.h"
17 #include "rtc_tools/video_file_reader.h"
18 #include "test/gtest.h"
19 #include "test/testsupport/file_utils.h"
20
21 namespace webrtc {
22 namespace test {
23
24 class VideoGeometryAlignerTest : public ::testing::Test {
25 protected:
SetUp()26 void SetUp() {
27 reference_video_ =
28 OpenYuvFile(ResourcePath("foreman_128x96", "yuv"), 128, 96);
29 ASSERT_TRUE(reference_video_);
30
31 // Very simple 4x4 frame used for verying CropAndZoom.
32 const uint8_t data_y[] = {0, 1, 2, 3, 4, 5, 6, 7,
33 8, 9, 10, 11, 12, 13, 14, 15};
34 const uint8_t data_u[] = {0, 1, 2, 3};
35 const uint8_t data_v[] = {0, 1, 2, 3};
36 test_frame_ = I420Buffer::Copy(
37 /* width= */ 4, /* height= */ 4, data_y, /* stride_y= */ 4, data_u,
38 /* stride_u= */ 2, data_v, /* stride_v= */ 2);
39 }
40
41 rtc::scoped_refptr<Video> reference_video_;
42 rtc::scoped_refptr<I420BufferInterface> test_frame_;
43 };
44
45 // Teach gtest how to compare CropRegions.
operator ==(const CropRegion & a,const CropRegion & b)46 bool operator==(const CropRegion& a, const CropRegion& b) {
47 return a.left == b.left && a.top == b.top && a.right == b.right &&
48 a.bottom == b.bottom;
49 }
50
TEST_F(VideoGeometryAlignerTest,CropAndZoomIdentity)51 TEST_F(VideoGeometryAlignerTest, CropAndZoomIdentity) {
52 const rtc::scoped_refptr<I420BufferInterface> frame =
53 reference_video_->GetFrame(0);
54
55 // Assume perfect match, i.e. SSIM == 1.
56 CropRegion identity_region;
57 EXPECT_EQ(1.0, Ssim(frame, CropAndZoom(identity_region, frame)));
58 }
59
TEST_F(VideoGeometryAlignerTest,CropAndZoomLeft)60 TEST_F(VideoGeometryAlignerTest, CropAndZoomLeft) {
61 CropRegion region;
62 region.left = 2;
63 const rtc::scoped_refptr<I420BufferInterface> cropped_frame =
64 CropAndZoom(region, test_frame_);
65 EXPECT_EQ(std::vector<uint8_t>(
66 {2, 2, 3, 3, 6, 6, 7, 7, 10, 10, 11, 11, 14, 14, 15, 15}),
67 std::vector<uint8_t>(cropped_frame->DataY(),
68 cropped_frame->DataY() + 16));
69 EXPECT_EQ(
70 std::vector<uint8_t>({1, 1, 3, 3}),
71 std::vector<uint8_t>(cropped_frame->DataU(), cropped_frame->DataU() + 4));
72 EXPECT_EQ(
73 std::vector<uint8_t>({1, 1, 3, 3}),
74 std::vector<uint8_t>(cropped_frame->DataV(), cropped_frame->DataV() + 4));
75 }
76
TEST_F(VideoGeometryAlignerTest,CropAndZoomTop)77 TEST_F(VideoGeometryAlignerTest, CropAndZoomTop) {
78 CropRegion region;
79 region.top = 2;
80 const rtc::scoped_refptr<I420BufferInterface> cropped_frame =
81 CropAndZoom(region, test_frame_);
82 EXPECT_EQ(std::vector<uint8_t>(
83 {8, 9, 10, 11, 10, 11, 12, 13, 12, 13, 14, 15, 12, 13, 14, 15}),
84 std::vector<uint8_t>(cropped_frame->DataY(),
85 cropped_frame->DataY() + 16));
86 EXPECT_EQ(
87 std::vector<uint8_t>({2, 3, 2, 3}),
88 std::vector<uint8_t>(cropped_frame->DataU(), cropped_frame->DataU() + 4));
89 EXPECT_EQ(
90 std::vector<uint8_t>({2, 3, 2, 3}),
91 std::vector<uint8_t>(cropped_frame->DataV(), cropped_frame->DataV() + 4));
92 }
93
TEST_F(VideoGeometryAlignerTest,CropAndZoomRight)94 TEST_F(VideoGeometryAlignerTest, CropAndZoomRight) {
95 CropRegion region;
96 region.right = 2;
97 const rtc::scoped_refptr<I420BufferInterface> cropped_frame =
98 CropAndZoom(region, test_frame_);
99 EXPECT_EQ(std::vector<uint8_t>(
100 {0, 0, 1, 1, 4, 4, 5, 5, 8, 8, 9, 9, 12, 12, 13, 13}),
101 std::vector<uint8_t>(cropped_frame->DataY(),
102 cropped_frame->DataY() + 16));
103 EXPECT_EQ(
104 std::vector<uint8_t>({0, 0, 2, 2}),
105 std::vector<uint8_t>(cropped_frame->DataU(), cropped_frame->DataU() + 4));
106 EXPECT_EQ(
107 std::vector<uint8_t>({0, 0, 2, 2}),
108 std::vector<uint8_t>(cropped_frame->DataV(), cropped_frame->DataV() + 4));
109 }
110
TEST_F(VideoGeometryAlignerTest,CropAndZoomBottom)111 TEST_F(VideoGeometryAlignerTest, CropAndZoomBottom) {
112 CropRegion region;
113 region.bottom = 2;
114 const rtc::scoped_refptr<I420BufferInterface> cropped_frame =
115 CropAndZoom(region, test_frame_);
116 EXPECT_EQ(
117 std::vector<uint8_t>({0, 1, 2, 3, 2, 3, 4, 5, 4, 5, 6, 7, 4, 5, 6, 7}),
118 std::vector<uint8_t>(cropped_frame->DataY(),
119 cropped_frame->DataY() + 16));
120 EXPECT_EQ(
121 std::vector<uint8_t>({0, 1, 0, 1}),
122 std::vector<uint8_t>(cropped_frame->DataU(), cropped_frame->DataU() + 4));
123 EXPECT_EQ(
124 std::vector<uint8_t>({0, 1, 0, 1}),
125 std::vector<uint8_t>(cropped_frame->DataV(), cropped_frame->DataV() + 4));
126 }
127
TEST_F(VideoGeometryAlignerTest,CalculateCropRegionIdentity)128 TEST_F(VideoGeometryAlignerTest, CalculateCropRegionIdentity) {
129 const rtc::scoped_refptr<I420BufferInterface> frame =
130 reference_video_->GetFrame(0);
131 CropRegion identity_region;
132 EXPECT_EQ(identity_region, CalculateCropRegion(frame, frame));
133 }
134
TEST_F(VideoGeometryAlignerTest,CalculateCropRegionArbitrary)135 TEST_F(VideoGeometryAlignerTest, CalculateCropRegionArbitrary) {
136 // Arbitrary crop region.
137 CropRegion crop_region;
138 crop_region.left = 2;
139 crop_region.top = 4;
140 crop_region.right = 5;
141 crop_region.bottom = 3;
142
143 const rtc::scoped_refptr<I420BufferInterface> frame =
144 reference_video_->GetFrame(0);
145
146 EXPECT_EQ(crop_region,
147 CalculateCropRegion(frame, CropAndZoom(crop_region, frame)));
148 }
149
150 } // namespace test
151 } // namespace webrtc
152