1*d9f75844SAndroid Build Coastguard Worker /*
2*d9f75844SAndroid Build Coastguard Worker * Copyright (c) 2018 The WebRTC project authors. All Rights Reserved.
3*d9f75844SAndroid Build Coastguard Worker *
4*d9f75844SAndroid Build Coastguard Worker * Use of this source code is governed by a BSD-style license
5*d9f75844SAndroid Build Coastguard Worker * that can be found in the LICENSE file in the root of the source
6*d9f75844SAndroid Build Coastguard Worker * tree. An additional intellectual property rights grant can be found
7*d9f75844SAndroid Build Coastguard Worker * in the file PATENTS. All contributing project authors may
8*d9f75844SAndroid Build Coastguard Worker * be found in the AUTHORS file in the root of the source tree.
9*d9f75844SAndroid Build Coastguard Worker */
10*d9f75844SAndroid Build Coastguard Worker
11*d9f75844SAndroid Build Coastguard Worker #include "api/video/video_frame.h"
12*d9f75844SAndroid Build Coastguard Worker
13*d9f75844SAndroid Build Coastguard Worker #include <math.h>
14*d9f75844SAndroid Build Coastguard Worker #include <string.h>
15*d9f75844SAndroid Build Coastguard Worker
16*d9f75844SAndroid Build Coastguard Worker #include "api/video/i010_buffer.h"
17*d9f75844SAndroid Build Coastguard Worker #include "api/video/i210_buffer.h"
18*d9f75844SAndroid Build Coastguard Worker #include "api/video/i420_buffer.h"
19*d9f75844SAndroid Build Coastguard Worker #include "api/video/i422_buffer.h"
20*d9f75844SAndroid Build Coastguard Worker #include "api/video/i444_buffer.h"
21*d9f75844SAndroid Build Coastguard Worker #include "api/video/nv12_buffer.h"
22*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/time_utils.h"
23*d9f75844SAndroid Build Coastguard Worker #include "test/fake_texture_frame.h"
24*d9f75844SAndroid Build Coastguard Worker #include "test/frame_utils.h"
25*d9f75844SAndroid Build Coastguard Worker #include "test/gtest.h"
26*d9f75844SAndroid Build Coastguard Worker
27*d9f75844SAndroid Build Coastguard Worker namespace webrtc {
28*d9f75844SAndroid Build Coastguard Worker
29*d9f75844SAndroid Build Coastguard Worker namespace {
30*d9f75844SAndroid Build Coastguard Worker
31*d9f75844SAndroid Build Coastguard Worker struct SubSampling {
32*d9f75844SAndroid Build Coastguard Worker int x;
33*d9f75844SAndroid Build Coastguard Worker int y;
34*d9f75844SAndroid Build Coastguard Worker };
35*d9f75844SAndroid Build Coastguard Worker
SubSamplingForType(VideoFrameBuffer::Type type)36*d9f75844SAndroid Build Coastguard Worker SubSampling SubSamplingForType(VideoFrameBuffer::Type type) {
37*d9f75844SAndroid Build Coastguard Worker switch (type) {
38*d9f75844SAndroid Build Coastguard Worker case VideoFrameBuffer::Type::kI420:
39*d9f75844SAndroid Build Coastguard Worker return {.x = 2, .y = 2};
40*d9f75844SAndroid Build Coastguard Worker case VideoFrameBuffer::Type::kI420A:
41*d9f75844SAndroid Build Coastguard Worker return {.x = 2, .y = 2};
42*d9f75844SAndroid Build Coastguard Worker case VideoFrameBuffer::Type::kI422:
43*d9f75844SAndroid Build Coastguard Worker return {.x = 2, .y = 1};
44*d9f75844SAndroid Build Coastguard Worker case VideoFrameBuffer::Type::kI444:
45*d9f75844SAndroid Build Coastguard Worker return {.x = 1, .y = 1};
46*d9f75844SAndroid Build Coastguard Worker case VideoFrameBuffer::Type::kI010:
47*d9f75844SAndroid Build Coastguard Worker return {.x = 2, .y = 2};
48*d9f75844SAndroid Build Coastguard Worker case VideoFrameBuffer::Type::kI210:
49*d9f75844SAndroid Build Coastguard Worker return {.x = 2, .y = 1};
50*d9f75844SAndroid Build Coastguard Worker default:
51*d9f75844SAndroid Build Coastguard Worker return {};
52*d9f75844SAndroid Build Coastguard Worker }
53*d9f75844SAndroid Build Coastguard Worker }
54*d9f75844SAndroid Build Coastguard Worker
55*d9f75844SAndroid Build Coastguard Worker // Helper function to create a buffer and fill it with a gradient for
56*d9f75844SAndroid Build Coastguard Worker // PlanarYuvBuffer based buffers.
57*d9f75844SAndroid Build Coastguard Worker template <class T>
CreateGradient(int width,int height)58*d9f75844SAndroid Build Coastguard Worker rtc::scoped_refptr<T> CreateGradient(int width, int height) {
59*d9f75844SAndroid Build Coastguard Worker rtc::scoped_refptr<T> buffer(T::Create(width, height));
60*d9f75844SAndroid Build Coastguard Worker // Initialize with gradient, Y = 128(x/w + y/h), U = 256 x/w, V = 256 y/h
61*d9f75844SAndroid Build Coastguard Worker for (int x = 0; x < width; x++) {
62*d9f75844SAndroid Build Coastguard Worker for (int y = 0; y < height; y++) {
63*d9f75844SAndroid Build Coastguard Worker buffer->MutableDataY()[x + y * width] =
64*d9f75844SAndroid Build Coastguard Worker 128 * (x * height + y * width) / (width * height);
65*d9f75844SAndroid Build Coastguard Worker }
66*d9f75844SAndroid Build Coastguard Worker }
67*d9f75844SAndroid Build Coastguard Worker int chroma_width = buffer->ChromaWidth();
68*d9f75844SAndroid Build Coastguard Worker int chroma_height = buffer->ChromaHeight();
69*d9f75844SAndroid Build Coastguard Worker for (int x = 0; x < chroma_width; x++) {
70*d9f75844SAndroid Build Coastguard Worker for (int y = 0; y < chroma_height; y++) {
71*d9f75844SAndroid Build Coastguard Worker buffer->MutableDataU()[x + y * chroma_width] =
72*d9f75844SAndroid Build Coastguard Worker 255 * x / (chroma_width - 1);
73*d9f75844SAndroid Build Coastguard Worker buffer->MutableDataV()[x + y * chroma_width] =
74*d9f75844SAndroid Build Coastguard Worker 255 * y / (chroma_height - 1);
75*d9f75844SAndroid Build Coastguard Worker }
76*d9f75844SAndroid Build Coastguard Worker }
77*d9f75844SAndroid Build Coastguard Worker return buffer;
78*d9f75844SAndroid Build Coastguard Worker }
79*d9f75844SAndroid Build Coastguard Worker
80*d9f75844SAndroid Build Coastguard Worker // Helper function to create a buffer and fill it with a gradient.
CreateNV12Gradient(int width,int height)81*d9f75844SAndroid Build Coastguard Worker rtc::scoped_refptr<NV12BufferInterface> CreateNV12Gradient(int width,
82*d9f75844SAndroid Build Coastguard Worker int height) {
83*d9f75844SAndroid Build Coastguard Worker rtc::scoped_refptr<NV12Buffer> buffer(NV12Buffer::Create(width, height));
84*d9f75844SAndroid Build Coastguard Worker // Initialize with gradient, Y = 128(x/w + y/h), U = 256 x/w, V = 256 y/h
85*d9f75844SAndroid Build Coastguard Worker for (int x = 0; x < width; x++) {
86*d9f75844SAndroid Build Coastguard Worker for (int y = 0; y < height; y++) {
87*d9f75844SAndroid Build Coastguard Worker buffer->MutableDataY()[x + y * width] =
88*d9f75844SAndroid Build Coastguard Worker 128 * (x * height + y * width) / (width * height);
89*d9f75844SAndroid Build Coastguard Worker }
90*d9f75844SAndroid Build Coastguard Worker }
91*d9f75844SAndroid Build Coastguard Worker int chroma_width = buffer->ChromaWidth();
92*d9f75844SAndroid Build Coastguard Worker int chroma_height = buffer->ChromaHeight();
93*d9f75844SAndroid Build Coastguard Worker for (int x = 0; x < chroma_width; x++) {
94*d9f75844SAndroid Build Coastguard Worker for (int y = 0; y < chroma_height; y++) {
95*d9f75844SAndroid Build Coastguard Worker buffer->MutableDataUV()[x * 2 + y * buffer->StrideUV()] =
96*d9f75844SAndroid Build Coastguard Worker 255 * x / (chroma_width - 1);
97*d9f75844SAndroid Build Coastguard Worker buffer->MutableDataUV()[x * 2 + 1 + y * buffer->StrideUV()] =
98*d9f75844SAndroid Build Coastguard Worker 255 * y / (chroma_height - 1);
99*d9f75844SAndroid Build Coastguard Worker }
100*d9f75844SAndroid Build Coastguard Worker }
101*d9f75844SAndroid Build Coastguard Worker return buffer;
102*d9f75844SAndroid Build Coastguard Worker }
103*d9f75844SAndroid Build Coastguard Worker
104*d9f75844SAndroid Build Coastguard Worker // The offsets and sizes describe the rectangle extracted from the
105*d9f75844SAndroid Build Coastguard Worker // original (gradient) frame, in relative coordinates where the
106*d9f75844SAndroid Build Coastguard Worker // original frame correspond to the unit square, 0.0 <= x, y < 1.0.
107*d9f75844SAndroid Build Coastguard Worker template <class T>
CheckCrop(const T & frame,double offset_x,double offset_y,double rel_width,double rel_height)108*d9f75844SAndroid Build Coastguard Worker void CheckCrop(const T& frame,
109*d9f75844SAndroid Build Coastguard Worker double offset_x,
110*d9f75844SAndroid Build Coastguard Worker double offset_y,
111*d9f75844SAndroid Build Coastguard Worker double rel_width,
112*d9f75844SAndroid Build Coastguard Worker double rel_height) {
113*d9f75844SAndroid Build Coastguard Worker int width = frame.width();
114*d9f75844SAndroid Build Coastguard Worker int height = frame.height();
115*d9f75844SAndroid Build Coastguard Worker
116*d9f75844SAndroid Build Coastguard Worker SubSampling plane_divider = SubSamplingForType(frame.type());
117*d9f75844SAndroid Build Coastguard Worker
118*d9f75844SAndroid Build Coastguard Worker // Check that pixel values in the corners match the gradient used
119*d9f75844SAndroid Build Coastguard Worker // for initialization.
120*d9f75844SAndroid Build Coastguard Worker for (int i = 0; i < 2; i++) {
121*d9f75844SAndroid Build Coastguard Worker for (int j = 0; j < 2; j++) {
122*d9f75844SAndroid Build Coastguard Worker // Pixel coordinates of the corner.
123*d9f75844SAndroid Build Coastguard Worker int x = i * (width - 1);
124*d9f75844SAndroid Build Coastguard Worker int y = j * (height - 1);
125*d9f75844SAndroid Build Coastguard Worker // Relative coordinates, range 0.0 - 1.0 correspond to the
126*d9f75844SAndroid Build Coastguard Worker // size of the uncropped input frame.
127*d9f75844SAndroid Build Coastguard Worker double orig_x = offset_x + i * rel_width;
128*d9f75844SAndroid Build Coastguard Worker double orig_y = offset_y + j * rel_height;
129*d9f75844SAndroid Build Coastguard Worker
130*d9f75844SAndroid Build Coastguard Worker EXPECT_NEAR(frame.DataY()[x + y * frame.StrideY()] / 256.0,
131*d9f75844SAndroid Build Coastguard Worker (orig_x + orig_y) / 2, 0.02);
132*d9f75844SAndroid Build Coastguard Worker EXPECT_NEAR(frame.DataU()[x / plane_divider.x +
133*d9f75844SAndroid Build Coastguard Worker (y / plane_divider.y) * frame.StrideU()] /
134*d9f75844SAndroid Build Coastguard Worker 256.0,
135*d9f75844SAndroid Build Coastguard Worker orig_x, 0.02);
136*d9f75844SAndroid Build Coastguard Worker EXPECT_NEAR(frame.DataV()[x / plane_divider.x +
137*d9f75844SAndroid Build Coastguard Worker (y / plane_divider.y) * frame.StrideV()] /
138*d9f75844SAndroid Build Coastguard Worker 256.0,
139*d9f75844SAndroid Build Coastguard Worker orig_y, 0.02);
140*d9f75844SAndroid Build Coastguard Worker }
141*d9f75844SAndroid Build Coastguard Worker }
142*d9f75844SAndroid Build Coastguard Worker }
143*d9f75844SAndroid Build Coastguard Worker
144*d9f75844SAndroid Build Coastguard Worker template <class T>
CheckRotate(int width,int height,webrtc::VideoRotation rotation,const T & rotated)145*d9f75844SAndroid Build Coastguard Worker void CheckRotate(int width,
146*d9f75844SAndroid Build Coastguard Worker int height,
147*d9f75844SAndroid Build Coastguard Worker webrtc::VideoRotation rotation,
148*d9f75844SAndroid Build Coastguard Worker const T& rotated) {
149*d9f75844SAndroid Build Coastguard Worker int rotated_width = width;
150*d9f75844SAndroid Build Coastguard Worker int rotated_height = height;
151*d9f75844SAndroid Build Coastguard Worker
152*d9f75844SAndroid Build Coastguard Worker if (rotation == kVideoRotation_90 || rotation == kVideoRotation_270) {
153*d9f75844SAndroid Build Coastguard Worker std::swap(rotated_width, rotated_height);
154*d9f75844SAndroid Build Coastguard Worker }
155*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(rotated_width, rotated.width());
156*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(rotated_height, rotated.height());
157*d9f75844SAndroid Build Coastguard Worker
158*d9f75844SAndroid Build Coastguard Worker // Clock-wise order (with 0,0 at top-left)
159*d9f75844SAndroid Build Coastguard Worker const struct {
160*d9f75844SAndroid Build Coastguard Worker int x;
161*d9f75844SAndroid Build Coastguard Worker int y;
162*d9f75844SAndroid Build Coastguard Worker } corners[] = {{0, 0}, {1, 0}, {1, 1}, {0, 1}};
163*d9f75844SAndroid Build Coastguard Worker // Corresponding corner colors of the frame produced by CreateGradient.
164*d9f75844SAndroid Build Coastguard Worker const struct {
165*d9f75844SAndroid Build Coastguard Worker int y;
166*d9f75844SAndroid Build Coastguard Worker int u;
167*d9f75844SAndroid Build Coastguard Worker int v;
168*d9f75844SAndroid Build Coastguard Worker } colors[] = {{0, 0, 0}, {127, 255, 0}, {255, 255, 255}, {127, 0, 255}};
169*d9f75844SAndroid Build Coastguard Worker int corner_offset = static_cast<int>(rotation) / 90;
170*d9f75844SAndroid Build Coastguard Worker
171*d9f75844SAndroid Build Coastguard Worker SubSampling plane_divider = SubSamplingForType(rotated.type());
172*d9f75844SAndroid Build Coastguard Worker
173*d9f75844SAndroid Build Coastguard Worker for (int i = 0; i < 4; i++) {
174*d9f75844SAndroid Build Coastguard Worker int j = (i + corner_offset) % 4;
175*d9f75844SAndroid Build Coastguard Worker int x = corners[j].x * (rotated_width - 1);
176*d9f75844SAndroid Build Coastguard Worker int y = corners[j].y * (rotated_height - 1);
177*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(colors[i].y, rotated.DataY()[x + y * rotated.StrideY()]);
178*d9f75844SAndroid Build Coastguard Worker if (rotated.type() == VideoFrameBuffer::Type::kI422 ||
179*d9f75844SAndroid Build Coastguard Worker rotated.type() == VideoFrameBuffer::Type::kI210) {
180*d9f75844SAndroid Build Coastguard Worker EXPECT_NEAR(colors[i].u,
181*d9f75844SAndroid Build Coastguard Worker rotated.DataU()[(x / plane_divider.x) +
182*d9f75844SAndroid Build Coastguard Worker (y / plane_divider.y) * rotated.StrideU()],
183*d9f75844SAndroid Build Coastguard Worker 1);
184*d9f75844SAndroid Build Coastguard Worker EXPECT_NEAR(colors[i].v,
185*d9f75844SAndroid Build Coastguard Worker rotated.DataV()[(x / plane_divider.x) +
186*d9f75844SAndroid Build Coastguard Worker (y / plane_divider.y) * rotated.StrideV()],
187*d9f75844SAndroid Build Coastguard Worker 1);
188*d9f75844SAndroid Build Coastguard Worker } else {
189*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(colors[i].u,
190*d9f75844SAndroid Build Coastguard Worker rotated.DataU()[(x / plane_divider.x) +
191*d9f75844SAndroid Build Coastguard Worker (y / plane_divider.y) * rotated.StrideU()]);
192*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(colors[i].v,
193*d9f75844SAndroid Build Coastguard Worker rotated.DataV()[(x / plane_divider.x) +
194*d9f75844SAndroid Build Coastguard Worker (y / plane_divider.y) * rotated.StrideV()]);
195*d9f75844SAndroid Build Coastguard Worker }
196*d9f75844SAndroid Build Coastguard Worker }
197*d9f75844SAndroid Build Coastguard Worker }
198*d9f75844SAndroid Build Coastguard Worker
199*d9f75844SAndroid Build Coastguard Worker } // namespace
200*d9f75844SAndroid Build Coastguard Worker
TEST(TestVideoFrame,WidthHeightValues)201*d9f75844SAndroid Build Coastguard Worker TEST(TestVideoFrame, WidthHeightValues) {
202*d9f75844SAndroid Build Coastguard Worker VideoFrame frame =
203*d9f75844SAndroid Build Coastguard Worker VideoFrame::Builder()
204*d9f75844SAndroid Build Coastguard Worker .set_video_frame_buffer(I420Buffer::Create(10, 10, 10, 14, 90))
205*d9f75844SAndroid Build Coastguard Worker .set_rotation(webrtc::kVideoRotation_0)
206*d9f75844SAndroid Build Coastguard Worker .set_timestamp_ms(789)
207*d9f75844SAndroid Build Coastguard Worker .build();
208*d9f75844SAndroid Build Coastguard Worker const int valid_value = 10;
209*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(valid_value, frame.width());
210*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(valid_value, frame.height());
211*d9f75844SAndroid Build Coastguard Worker frame.set_timestamp(123u);
212*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(123u, frame.timestamp());
213*d9f75844SAndroid Build Coastguard Worker frame.set_ntp_time_ms(456);
214*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(456, frame.ntp_time_ms());
215*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(789, frame.render_time_ms());
216*d9f75844SAndroid Build Coastguard Worker }
217*d9f75844SAndroid Build Coastguard Worker
TEST(TestVideoFrame,ShallowCopy)218*d9f75844SAndroid Build Coastguard Worker TEST(TestVideoFrame, ShallowCopy) {
219*d9f75844SAndroid Build Coastguard Worker uint32_t timestamp = 1;
220*d9f75844SAndroid Build Coastguard Worker int64_t ntp_time_ms = 2;
221*d9f75844SAndroid Build Coastguard Worker int64_t timestamp_us = 3;
222*d9f75844SAndroid Build Coastguard Worker int stride_y = 15;
223*d9f75844SAndroid Build Coastguard Worker int stride_u = 10;
224*d9f75844SAndroid Build Coastguard Worker int stride_v = 10;
225*d9f75844SAndroid Build Coastguard Worker int width = 15;
226*d9f75844SAndroid Build Coastguard Worker int height = 15;
227*d9f75844SAndroid Build Coastguard Worker
228*d9f75844SAndroid Build Coastguard Worker const int kSizeY = 400;
229*d9f75844SAndroid Build Coastguard Worker const int kSizeU = 100;
230*d9f75844SAndroid Build Coastguard Worker const int kSizeV = 100;
231*d9f75844SAndroid Build Coastguard Worker const VideoRotation kRotation = kVideoRotation_270;
232*d9f75844SAndroid Build Coastguard Worker uint8_t buffer_y[kSizeY];
233*d9f75844SAndroid Build Coastguard Worker uint8_t buffer_u[kSizeU];
234*d9f75844SAndroid Build Coastguard Worker uint8_t buffer_v[kSizeV];
235*d9f75844SAndroid Build Coastguard Worker memset(buffer_y, 16, kSizeY);
236*d9f75844SAndroid Build Coastguard Worker memset(buffer_u, 8, kSizeU);
237*d9f75844SAndroid Build Coastguard Worker memset(buffer_v, 4, kSizeV);
238*d9f75844SAndroid Build Coastguard Worker
239*d9f75844SAndroid Build Coastguard Worker VideoFrame frame1 = VideoFrame::Builder()
240*d9f75844SAndroid Build Coastguard Worker .set_video_frame_buffer(I420Buffer::Copy(
241*d9f75844SAndroid Build Coastguard Worker width, height, buffer_y, stride_y, buffer_u,
242*d9f75844SAndroid Build Coastguard Worker stride_u, buffer_v, stride_v))
243*d9f75844SAndroid Build Coastguard Worker .set_rotation(kRotation)
244*d9f75844SAndroid Build Coastguard Worker .set_timestamp_us(0)
245*d9f75844SAndroid Build Coastguard Worker .build();
246*d9f75844SAndroid Build Coastguard Worker frame1.set_timestamp(timestamp);
247*d9f75844SAndroid Build Coastguard Worker frame1.set_ntp_time_ms(ntp_time_ms);
248*d9f75844SAndroid Build Coastguard Worker frame1.set_timestamp_us(timestamp_us);
249*d9f75844SAndroid Build Coastguard Worker VideoFrame frame2(frame1);
250*d9f75844SAndroid Build Coastguard Worker
251*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(frame1.video_frame_buffer(), frame2.video_frame_buffer());
252*d9f75844SAndroid Build Coastguard Worker const webrtc::I420BufferInterface* yuv1 =
253*d9f75844SAndroid Build Coastguard Worker frame1.video_frame_buffer()->GetI420();
254*d9f75844SAndroid Build Coastguard Worker const webrtc::I420BufferInterface* yuv2 =
255*d9f75844SAndroid Build Coastguard Worker frame2.video_frame_buffer()->GetI420();
256*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(yuv1->DataY(), yuv2->DataY());
257*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(yuv1->DataU(), yuv2->DataU());
258*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(yuv1->DataV(), yuv2->DataV());
259*d9f75844SAndroid Build Coastguard Worker
260*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(frame2.timestamp(), frame1.timestamp());
261*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(frame2.ntp_time_ms(), frame1.ntp_time_ms());
262*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(frame2.timestamp_us(), frame1.timestamp_us());
263*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(frame2.rotation(), frame1.rotation());
264*d9f75844SAndroid Build Coastguard Worker
265*d9f75844SAndroid Build Coastguard Worker frame2.set_timestamp(timestamp + 1);
266*d9f75844SAndroid Build Coastguard Worker frame2.set_ntp_time_ms(ntp_time_ms + 1);
267*d9f75844SAndroid Build Coastguard Worker frame2.set_timestamp_us(timestamp_us + 1);
268*d9f75844SAndroid Build Coastguard Worker frame2.set_rotation(kVideoRotation_90);
269*d9f75844SAndroid Build Coastguard Worker
270*d9f75844SAndroid Build Coastguard Worker EXPECT_NE(frame2.timestamp(), frame1.timestamp());
271*d9f75844SAndroid Build Coastguard Worker EXPECT_NE(frame2.ntp_time_ms(), frame1.ntp_time_ms());
272*d9f75844SAndroid Build Coastguard Worker EXPECT_NE(frame2.timestamp_us(), frame1.timestamp_us());
273*d9f75844SAndroid Build Coastguard Worker EXPECT_NE(frame2.rotation(), frame1.rotation());
274*d9f75844SAndroid Build Coastguard Worker }
275*d9f75844SAndroid Build Coastguard Worker
TEST(TestVideoFrame,TextureInitialValues)276*d9f75844SAndroid Build Coastguard Worker TEST(TestVideoFrame, TextureInitialValues) {
277*d9f75844SAndroid Build Coastguard Worker VideoFrame frame = test::FakeNativeBuffer::CreateFrame(
278*d9f75844SAndroid Build Coastguard Worker 640, 480, 100, 10, webrtc::kVideoRotation_0);
279*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(640, frame.width());
280*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(480, frame.height());
281*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(100u, frame.timestamp());
282*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(10, frame.render_time_ms());
283*d9f75844SAndroid Build Coastguard Worker ASSERT_TRUE(frame.video_frame_buffer() != nullptr);
284*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE(frame.video_frame_buffer()->type() ==
285*d9f75844SAndroid Build Coastguard Worker VideoFrameBuffer::Type::kNative);
286*d9f75844SAndroid Build Coastguard Worker
287*d9f75844SAndroid Build Coastguard Worker frame.set_timestamp(200);
288*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(200u, frame.timestamp());
289*d9f75844SAndroid Build Coastguard Worker frame.set_timestamp_us(20);
290*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(20, frame.timestamp_us());
291*d9f75844SAndroid Build Coastguard Worker }
292*d9f75844SAndroid Build Coastguard Worker
293*d9f75844SAndroid Build Coastguard Worker template <typename T>
294*d9f75844SAndroid Build Coastguard Worker class TestPlanarYuvBuffer : public ::testing::Test {};
295*d9f75844SAndroid Build Coastguard Worker TYPED_TEST_SUITE_P(TestPlanarYuvBuffer);
296*d9f75844SAndroid Build Coastguard Worker
297*d9f75844SAndroid Build Coastguard Worker template <class T>
CreateAndFillBuffer()298*d9f75844SAndroid Build Coastguard Worker rtc::scoped_refptr<T> CreateAndFillBuffer() {
299*d9f75844SAndroid Build Coastguard Worker auto buf = T::Create(20, 10);
300*d9f75844SAndroid Build Coastguard Worker memset(buf->MutableDataY(), 1, 200);
301*d9f75844SAndroid Build Coastguard Worker
302*d9f75844SAndroid Build Coastguard Worker if (buf->type() == VideoFrameBuffer::Type::kI444) {
303*d9f75844SAndroid Build Coastguard Worker memset(buf->MutableDataU(), 2, 200);
304*d9f75844SAndroid Build Coastguard Worker memset(buf->MutableDataV(), 3, 200);
305*d9f75844SAndroid Build Coastguard Worker } else if (buf->type() == VideoFrameBuffer::Type::kI422 ||
306*d9f75844SAndroid Build Coastguard Worker buf->type() == VideoFrameBuffer::Type::kI210) {
307*d9f75844SAndroid Build Coastguard Worker memset(buf->MutableDataU(), 2, 100);
308*d9f75844SAndroid Build Coastguard Worker memset(buf->MutableDataV(), 3, 100);
309*d9f75844SAndroid Build Coastguard Worker } else {
310*d9f75844SAndroid Build Coastguard Worker memset(buf->MutableDataU(), 2, 50);
311*d9f75844SAndroid Build Coastguard Worker memset(buf->MutableDataV(), 3, 50);
312*d9f75844SAndroid Build Coastguard Worker }
313*d9f75844SAndroid Build Coastguard Worker
314*d9f75844SAndroid Build Coastguard Worker return buf;
315*d9f75844SAndroid Build Coastguard Worker }
316*d9f75844SAndroid Build Coastguard Worker
TYPED_TEST_P(TestPlanarYuvBuffer,Copy)317*d9f75844SAndroid Build Coastguard Worker TYPED_TEST_P(TestPlanarYuvBuffer, Copy) {
318*d9f75844SAndroid Build Coastguard Worker rtc::scoped_refptr<TypeParam> buf1 = CreateAndFillBuffer<TypeParam>();
319*d9f75844SAndroid Build Coastguard Worker rtc::scoped_refptr<TypeParam> buf2 = TypeParam::Copy(*buf1);
320*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE(test::FrameBufsEqual(buf1, buf2));
321*d9f75844SAndroid Build Coastguard Worker }
322*d9f75844SAndroid Build Coastguard Worker
TYPED_TEST_P(TestPlanarYuvBuffer,CropXCenter)323*d9f75844SAndroid Build Coastguard Worker TYPED_TEST_P(TestPlanarYuvBuffer, CropXCenter) {
324*d9f75844SAndroid Build Coastguard Worker rtc::scoped_refptr<TypeParam> buf = CreateGradient<TypeParam>(200, 100);
325*d9f75844SAndroid Build Coastguard Worker
326*d9f75844SAndroid Build Coastguard Worker // Pure center cropping, no scaling.
327*d9f75844SAndroid Build Coastguard Worker rtc::scoped_refptr<TypeParam> scaled_buffer = TypeParam::Create(100, 100);
328*d9f75844SAndroid Build Coastguard Worker scaled_buffer->CropAndScaleFrom(*buf, 50, 0, 100, 100);
329*d9f75844SAndroid Build Coastguard Worker CheckCrop<TypeParam>(*scaled_buffer, 0.25, 0.0, 0.5, 1.0);
330*d9f75844SAndroid Build Coastguard Worker }
331*d9f75844SAndroid Build Coastguard Worker
TYPED_TEST_P(TestPlanarYuvBuffer,CropXNotCenter)332*d9f75844SAndroid Build Coastguard Worker TYPED_TEST_P(TestPlanarYuvBuffer, CropXNotCenter) {
333*d9f75844SAndroid Build Coastguard Worker rtc::scoped_refptr<TypeParam> buf = CreateGradient<TypeParam>(200, 100);
334*d9f75844SAndroid Build Coastguard Worker
335*d9f75844SAndroid Build Coastguard Worker // Non-center cropping, no scaling.
336*d9f75844SAndroid Build Coastguard Worker rtc::scoped_refptr<TypeParam> scaled_buffer = TypeParam::Create(100, 100);
337*d9f75844SAndroid Build Coastguard Worker scaled_buffer->CropAndScaleFrom(*buf, 25, 0, 100, 100);
338*d9f75844SAndroid Build Coastguard Worker CheckCrop<TypeParam>(*scaled_buffer, 0.125, 0.0, 0.5, 1.0);
339*d9f75844SAndroid Build Coastguard Worker }
340*d9f75844SAndroid Build Coastguard Worker
TYPED_TEST_P(TestPlanarYuvBuffer,CropYCenter)341*d9f75844SAndroid Build Coastguard Worker TYPED_TEST_P(TestPlanarYuvBuffer, CropYCenter) {
342*d9f75844SAndroid Build Coastguard Worker rtc::scoped_refptr<TypeParam> buf = CreateGradient<TypeParam>(100, 200);
343*d9f75844SAndroid Build Coastguard Worker
344*d9f75844SAndroid Build Coastguard Worker // Pure center cropping, no scaling.
345*d9f75844SAndroid Build Coastguard Worker rtc::scoped_refptr<TypeParam> scaled_buffer = TypeParam::Create(100, 100);
346*d9f75844SAndroid Build Coastguard Worker scaled_buffer->CropAndScaleFrom(*buf, 0, 50, 100, 100);
347*d9f75844SAndroid Build Coastguard Worker CheckCrop<TypeParam>(*scaled_buffer, 0.0, 0.25, 1.0, 0.5);
348*d9f75844SAndroid Build Coastguard Worker }
349*d9f75844SAndroid Build Coastguard Worker
TYPED_TEST_P(TestPlanarYuvBuffer,CropYNotCenter)350*d9f75844SAndroid Build Coastguard Worker TYPED_TEST_P(TestPlanarYuvBuffer, CropYNotCenter) {
351*d9f75844SAndroid Build Coastguard Worker rtc::scoped_refptr<TypeParam> buf = CreateGradient<TypeParam>(100, 200);
352*d9f75844SAndroid Build Coastguard Worker
353*d9f75844SAndroid Build Coastguard Worker // Pure center cropping, no scaling.
354*d9f75844SAndroid Build Coastguard Worker rtc::scoped_refptr<TypeParam> scaled_buffer = TypeParam::Create(100, 100);
355*d9f75844SAndroid Build Coastguard Worker scaled_buffer->CropAndScaleFrom(*buf, 0, 25, 100, 100);
356*d9f75844SAndroid Build Coastguard Worker CheckCrop<TypeParam>(*scaled_buffer, 0.0, 0.125, 1.0, 0.5);
357*d9f75844SAndroid Build Coastguard Worker }
358*d9f75844SAndroid Build Coastguard Worker
TYPED_TEST_P(TestPlanarYuvBuffer,CropAndScale16x9)359*d9f75844SAndroid Build Coastguard Worker TYPED_TEST_P(TestPlanarYuvBuffer, CropAndScale16x9) {
360*d9f75844SAndroid Build Coastguard Worker const int buffer_width = 640;
361*d9f75844SAndroid Build Coastguard Worker const int buffer_height = 480;
362*d9f75844SAndroid Build Coastguard Worker const int crop_width = 320;
363*d9f75844SAndroid Build Coastguard Worker const int crop_height = 180;
364*d9f75844SAndroid Build Coastguard Worker rtc::scoped_refptr<TypeParam> buf = CreateGradient<TypeParam>(640, 480);
365*d9f75844SAndroid Build Coastguard Worker
366*d9f75844SAndroid Build Coastguard Worker // Pure center cropping, no scaling.
367*d9f75844SAndroid Build Coastguard Worker const int out_width =
368*d9f75844SAndroid Build Coastguard Worker std::min(buffer_width, crop_width * buffer_height / crop_height);
369*d9f75844SAndroid Build Coastguard Worker const int out_height =
370*d9f75844SAndroid Build Coastguard Worker std::min(buffer_height, crop_height * buffer_width / crop_width);
371*d9f75844SAndroid Build Coastguard Worker rtc::scoped_refptr<TypeParam> scaled_buffer =
372*d9f75844SAndroid Build Coastguard Worker TypeParam::Create(out_width, out_height);
373*d9f75844SAndroid Build Coastguard Worker scaled_buffer->CropAndScaleFrom(*buf, (buffer_width - out_width) / 2,
374*d9f75844SAndroid Build Coastguard Worker (buffer_height - out_height) / 2, out_width,
375*d9f75844SAndroid Build Coastguard Worker out_height);
376*d9f75844SAndroid Build Coastguard Worker CheckCrop<TypeParam>(*scaled_buffer, 0.0, 0.125, 1.0, 0.75);
377*d9f75844SAndroid Build Coastguard Worker }
378*d9f75844SAndroid Build Coastguard Worker
379*d9f75844SAndroid Build Coastguard Worker REGISTER_TYPED_TEST_SUITE_P(TestPlanarYuvBuffer,
380*d9f75844SAndroid Build Coastguard Worker Copy,
381*d9f75844SAndroid Build Coastguard Worker CropXCenter,
382*d9f75844SAndroid Build Coastguard Worker CropXNotCenter,
383*d9f75844SAndroid Build Coastguard Worker CropYCenter,
384*d9f75844SAndroid Build Coastguard Worker CropYNotCenter,
385*d9f75844SAndroid Build Coastguard Worker CropAndScale16x9);
386*d9f75844SAndroid Build Coastguard Worker
387*d9f75844SAndroid Build Coastguard Worker using TestTypesAll = ::testing::
388*d9f75844SAndroid Build Coastguard Worker Types<I420Buffer, I010Buffer, I444Buffer, I422Buffer, I210Buffer>;
389*d9f75844SAndroid Build Coastguard Worker INSTANTIATE_TYPED_TEST_SUITE_P(All, TestPlanarYuvBuffer, TestTypesAll);
390*d9f75844SAndroid Build Coastguard Worker
391*d9f75844SAndroid Build Coastguard Worker template <class T>
392*d9f75844SAndroid Build Coastguard Worker class TestPlanarYuvBufferScale : public ::testing::Test {};
393*d9f75844SAndroid Build Coastguard Worker TYPED_TEST_SUITE_P(TestPlanarYuvBufferScale);
394*d9f75844SAndroid Build Coastguard Worker
TYPED_TEST_P(TestPlanarYuvBufferScale,Scale)395*d9f75844SAndroid Build Coastguard Worker TYPED_TEST_P(TestPlanarYuvBufferScale, Scale) {
396*d9f75844SAndroid Build Coastguard Worker rtc::scoped_refptr<TypeParam> buf = CreateGradient<TypeParam>(200, 100);
397*d9f75844SAndroid Build Coastguard Worker
398*d9f75844SAndroid Build Coastguard Worker // Pure scaling, no cropping.
399*d9f75844SAndroid Build Coastguard Worker rtc::scoped_refptr<TypeParam> scaled_buffer = TypeParam::Create(150, 75);
400*d9f75844SAndroid Build Coastguard Worker scaled_buffer->ScaleFrom(*buf);
401*d9f75844SAndroid Build Coastguard Worker CheckCrop<TypeParam>(*scaled_buffer, 0.0, 0.0, 1.0, 1.0);
402*d9f75844SAndroid Build Coastguard Worker }
403*d9f75844SAndroid Build Coastguard Worker
404*d9f75844SAndroid Build Coastguard Worker REGISTER_TYPED_TEST_SUITE_P(TestPlanarYuvBufferScale, Scale);
405*d9f75844SAndroid Build Coastguard Worker
406*d9f75844SAndroid Build Coastguard Worker using TestTypesScale = ::testing::Types<I420Buffer, I010Buffer, I210Buffer>;
407*d9f75844SAndroid Build Coastguard Worker INSTANTIATE_TYPED_TEST_SUITE_P(All, TestPlanarYuvBufferScale, TestTypesScale);
408*d9f75844SAndroid Build Coastguard Worker
409*d9f75844SAndroid Build Coastguard Worker template <class T>
410*d9f75844SAndroid Build Coastguard Worker class TestPlanarYuvBufferRotate : public ::testing::Test {
411*d9f75844SAndroid Build Coastguard Worker public:
412*d9f75844SAndroid Build Coastguard Worker std::vector<webrtc::VideoRotation> RotationParams = {
413*d9f75844SAndroid Build Coastguard Worker kVideoRotation_0, kVideoRotation_90, kVideoRotation_180,
414*d9f75844SAndroid Build Coastguard Worker kVideoRotation_270};
415*d9f75844SAndroid Build Coastguard Worker };
416*d9f75844SAndroid Build Coastguard Worker
417*d9f75844SAndroid Build Coastguard Worker TYPED_TEST_SUITE_P(TestPlanarYuvBufferRotate);
418*d9f75844SAndroid Build Coastguard Worker
TYPED_TEST_P(TestPlanarYuvBufferRotate,Rotates)419*d9f75844SAndroid Build Coastguard Worker TYPED_TEST_P(TestPlanarYuvBufferRotate, Rotates) {
420*d9f75844SAndroid Build Coastguard Worker for (const webrtc::VideoRotation& rotation : this->RotationParams) {
421*d9f75844SAndroid Build Coastguard Worker rtc::scoped_refptr<TypeParam> buffer = CreateGradient<TypeParam>(640, 480);
422*d9f75844SAndroid Build Coastguard Worker rtc::scoped_refptr<TypeParam> rotated_buffer =
423*d9f75844SAndroid Build Coastguard Worker TypeParam::Rotate(*buffer, rotation);
424*d9f75844SAndroid Build Coastguard Worker CheckRotate(640, 480, rotation, *rotated_buffer);
425*d9f75844SAndroid Build Coastguard Worker }
426*d9f75844SAndroid Build Coastguard Worker }
427*d9f75844SAndroid Build Coastguard Worker
428*d9f75844SAndroid Build Coastguard Worker REGISTER_TYPED_TEST_SUITE_P(TestPlanarYuvBufferRotate, Rotates);
429*d9f75844SAndroid Build Coastguard Worker
430*d9f75844SAndroid Build Coastguard Worker using TestTypesRotate = ::testing::
431*d9f75844SAndroid Build Coastguard Worker Types<I420Buffer, I010Buffer, I444Buffer, I422Buffer, I210Buffer>;
432*d9f75844SAndroid Build Coastguard Worker INSTANTIATE_TYPED_TEST_SUITE_P(Rotate,
433*d9f75844SAndroid Build Coastguard Worker TestPlanarYuvBufferRotate,
434*d9f75844SAndroid Build Coastguard Worker TestTypesRotate);
435*d9f75844SAndroid Build Coastguard Worker
TEST(TestNV12Buffer,CropAndScale)436*d9f75844SAndroid Build Coastguard Worker TEST(TestNV12Buffer, CropAndScale) {
437*d9f75844SAndroid Build Coastguard Worker const int kSourceWidth = 640;
438*d9f75844SAndroid Build Coastguard Worker const int kSourceHeight = 480;
439*d9f75844SAndroid Build Coastguard Worker const int kScaledWidth = 320;
440*d9f75844SAndroid Build Coastguard Worker const int kScaledHeight = 240;
441*d9f75844SAndroid Build Coastguard Worker const int kCropLeft = 40;
442*d9f75844SAndroid Build Coastguard Worker const int kCropTop = 30;
443*d9f75844SAndroid Build Coastguard Worker const int kCropRight = 0;
444*d9f75844SAndroid Build Coastguard Worker const int kCropBottom = 30;
445*d9f75844SAndroid Build Coastguard Worker
446*d9f75844SAndroid Build Coastguard Worker rtc::scoped_refptr<VideoFrameBuffer> buf =
447*d9f75844SAndroid Build Coastguard Worker CreateNV12Gradient(kSourceWidth, kSourceHeight);
448*d9f75844SAndroid Build Coastguard Worker
449*d9f75844SAndroid Build Coastguard Worker rtc::scoped_refptr<VideoFrameBuffer> scaled_buffer = buf->CropAndScale(
450*d9f75844SAndroid Build Coastguard Worker kCropLeft, kCropTop, kSourceWidth - kCropLeft - kCropRight,
451*d9f75844SAndroid Build Coastguard Worker kSourceHeight - kCropTop - kCropBottom, kScaledWidth, kScaledHeight);
452*d9f75844SAndroid Build Coastguard Worker
453*d9f75844SAndroid Build Coastguard Worker // Parameters to CheckCrop indicate what part of the source frame is in the
454*d9f75844SAndroid Build Coastguard Worker // scaled frame.
455*d9f75844SAndroid Build Coastguard Worker const float kOffsetX = (kCropLeft + 0.0) / kSourceWidth;
456*d9f75844SAndroid Build Coastguard Worker const float kOffsetY = (kCropTop + 0.0) / kSourceHeight;
457*d9f75844SAndroid Build Coastguard Worker const float kRelativeWidth =
458*d9f75844SAndroid Build Coastguard Worker (kSourceWidth - kCropLeft - kCropRight + 0.0) / kSourceWidth;
459*d9f75844SAndroid Build Coastguard Worker const float kRelativeHeight =
460*d9f75844SAndroid Build Coastguard Worker (kSourceHeight - kCropTop - kCropBottom + 0.0) / kSourceHeight;
461*d9f75844SAndroid Build Coastguard Worker CheckCrop(*scaled_buffer->ToI420(), kOffsetX, kOffsetY, kRelativeWidth,
462*d9f75844SAndroid Build Coastguard Worker kRelativeHeight);
463*d9f75844SAndroid Build Coastguard Worker }
464*d9f75844SAndroid Build Coastguard Worker
TEST(TestUpdateRect,CanCompare)465*d9f75844SAndroid Build Coastguard Worker TEST(TestUpdateRect, CanCompare) {
466*d9f75844SAndroid Build Coastguard Worker VideoFrame::UpdateRect a = {0, 0, 100, 200};
467*d9f75844SAndroid Build Coastguard Worker VideoFrame::UpdateRect b = {0, 0, 100, 200};
468*d9f75844SAndroid Build Coastguard Worker VideoFrame::UpdateRect c = {1, 0, 100, 200};
469*d9f75844SAndroid Build Coastguard Worker VideoFrame::UpdateRect d = {0, 1, 100, 200};
470*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE(a == b);
471*d9f75844SAndroid Build Coastguard Worker EXPECT_FALSE(a == c);
472*d9f75844SAndroid Build Coastguard Worker EXPECT_FALSE(a == d);
473*d9f75844SAndroid Build Coastguard Worker }
474*d9f75844SAndroid Build Coastguard Worker
TEST(TestUpdateRect,ComputesIsEmpty)475*d9f75844SAndroid Build Coastguard Worker TEST(TestUpdateRect, ComputesIsEmpty) {
476*d9f75844SAndroid Build Coastguard Worker VideoFrame::UpdateRect a = {0, 0, 0, 0};
477*d9f75844SAndroid Build Coastguard Worker VideoFrame::UpdateRect b = {0, 0, 100, 200};
478*d9f75844SAndroid Build Coastguard Worker VideoFrame::UpdateRect c = {1, 100, 0, 0};
479*d9f75844SAndroid Build Coastguard Worker VideoFrame::UpdateRect d = {1, 100, 100, 200};
480*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE(a.IsEmpty());
481*d9f75844SAndroid Build Coastguard Worker EXPECT_FALSE(b.IsEmpty());
482*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE(c.IsEmpty());
483*d9f75844SAndroid Build Coastguard Worker EXPECT_FALSE(d.IsEmpty());
484*d9f75844SAndroid Build Coastguard Worker }
485*d9f75844SAndroid Build Coastguard Worker
TEST(TestUpdateRectUnion,NonIntersecting)486*d9f75844SAndroid Build Coastguard Worker TEST(TestUpdateRectUnion, NonIntersecting) {
487*d9f75844SAndroid Build Coastguard Worker VideoFrame::UpdateRect a = {0, 0, 10, 20};
488*d9f75844SAndroid Build Coastguard Worker VideoFrame::UpdateRect b = {100, 200, 10, 20};
489*d9f75844SAndroid Build Coastguard Worker a.Union(b);
490*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(a, VideoFrame::UpdateRect({0, 0, 110, 220}));
491*d9f75844SAndroid Build Coastguard Worker }
492*d9f75844SAndroid Build Coastguard Worker
TEST(TestUpdateRectUnion,Intersecting)493*d9f75844SAndroid Build Coastguard Worker TEST(TestUpdateRectUnion, Intersecting) {
494*d9f75844SAndroid Build Coastguard Worker VideoFrame::UpdateRect a = {0, 0, 10, 10};
495*d9f75844SAndroid Build Coastguard Worker VideoFrame::UpdateRect b = {5, 5, 30, 20};
496*d9f75844SAndroid Build Coastguard Worker a.Union(b);
497*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(a, VideoFrame::UpdateRect({0, 0, 35, 25}));
498*d9f75844SAndroid Build Coastguard Worker }
499*d9f75844SAndroid Build Coastguard Worker
TEST(TestUpdateRectUnion,OneInsideAnother)500*d9f75844SAndroid Build Coastguard Worker TEST(TestUpdateRectUnion, OneInsideAnother) {
501*d9f75844SAndroid Build Coastguard Worker VideoFrame::UpdateRect a = {0, 0, 100, 100};
502*d9f75844SAndroid Build Coastguard Worker VideoFrame::UpdateRect b = {5, 5, 30, 20};
503*d9f75844SAndroid Build Coastguard Worker a.Union(b);
504*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(a, VideoFrame::UpdateRect({0, 0, 100, 100}));
505*d9f75844SAndroid Build Coastguard Worker }
506*d9f75844SAndroid Build Coastguard Worker
TEST(TestUpdateRectIntersect,NonIntersecting)507*d9f75844SAndroid Build Coastguard Worker TEST(TestUpdateRectIntersect, NonIntersecting) {
508*d9f75844SAndroid Build Coastguard Worker VideoFrame::UpdateRect a = {0, 0, 10, 20};
509*d9f75844SAndroid Build Coastguard Worker VideoFrame::UpdateRect b = {100, 200, 10, 20};
510*d9f75844SAndroid Build Coastguard Worker a.Intersect(b);
511*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(a, VideoFrame::UpdateRect({0, 0, 0, 0}));
512*d9f75844SAndroid Build Coastguard Worker }
513*d9f75844SAndroid Build Coastguard Worker
TEST(TestUpdateRectIntersect,Intersecting)514*d9f75844SAndroid Build Coastguard Worker TEST(TestUpdateRectIntersect, Intersecting) {
515*d9f75844SAndroid Build Coastguard Worker VideoFrame::UpdateRect a = {0, 0, 10, 10};
516*d9f75844SAndroid Build Coastguard Worker VideoFrame::UpdateRect b = {5, 5, 30, 20};
517*d9f75844SAndroid Build Coastguard Worker a.Intersect(b);
518*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(a, VideoFrame::UpdateRect({5, 5, 5, 5}));
519*d9f75844SAndroid Build Coastguard Worker }
520*d9f75844SAndroid Build Coastguard Worker
TEST(TestUpdateRectIntersect,OneInsideAnother)521*d9f75844SAndroid Build Coastguard Worker TEST(TestUpdateRectIntersect, OneInsideAnother) {
522*d9f75844SAndroid Build Coastguard Worker VideoFrame::UpdateRect a = {0, 0, 100, 100};
523*d9f75844SAndroid Build Coastguard Worker VideoFrame::UpdateRect b = {5, 5, 30, 20};
524*d9f75844SAndroid Build Coastguard Worker a.Intersect(b);
525*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(a, VideoFrame::UpdateRect({5, 5, 30, 20}));
526*d9f75844SAndroid Build Coastguard Worker }
527*d9f75844SAndroid Build Coastguard Worker
TEST(TestUpdateRectScale,NoScale)528*d9f75844SAndroid Build Coastguard Worker TEST(TestUpdateRectScale, NoScale) {
529*d9f75844SAndroid Build Coastguard Worker const int width = 640;
530*d9f75844SAndroid Build Coastguard Worker const int height = 480;
531*d9f75844SAndroid Build Coastguard Worker VideoFrame::UpdateRect a = {100, 50, 100, 200};
532*d9f75844SAndroid Build Coastguard Worker VideoFrame::UpdateRect scaled =
533*d9f75844SAndroid Build Coastguard Worker a.ScaleWithFrame(width, height, 0, 0, width, height, width, height);
534*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(scaled, VideoFrame::UpdateRect({100, 50, 100, 200}));
535*d9f75844SAndroid Build Coastguard Worker }
536*d9f75844SAndroid Build Coastguard Worker
TEST(TestUpdateRectScale,CropOnly)537*d9f75844SAndroid Build Coastguard Worker TEST(TestUpdateRectScale, CropOnly) {
538*d9f75844SAndroid Build Coastguard Worker const int width = 640;
539*d9f75844SAndroid Build Coastguard Worker const int height = 480;
540*d9f75844SAndroid Build Coastguard Worker VideoFrame::UpdateRect a = {100, 50, 100, 200};
541*d9f75844SAndroid Build Coastguard Worker VideoFrame::UpdateRect scaled = a.ScaleWithFrame(
542*d9f75844SAndroid Build Coastguard Worker width, height, 10, 10, width - 20, height - 20, width - 20, height - 20);
543*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(scaled, VideoFrame::UpdateRect({90, 40, 100, 200}));
544*d9f75844SAndroid Build Coastguard Worker }
545*d9f75844SAndroid Build Coastguard Worker
TEST(TestUpdateRectScale,CropOnlyToOddOffset)546*d9f75844SAndroid Build Coastguard Worker TEST(TestUpdateRectScale, CropOnlyToOddOffset) {
547*d9f75844SAndroid Build Coastguard Worker const int width = 640;
548*d9f75844SAndroid Build Coastguard Worker const int height = 480;
549*d9f75844SAndroid Build Coastguard Worker VideoFrame::UpdateRect a = {100, 50, 100, 200};
550*d9f75844SAndroid Build Coastguard Worker VideoFrame::UpdateRect scaled = a.ScaleWithFrame(
551*d9f75844SAndroid Build Coastguard Worker width, height, 5, 5, width - 10, height - 10, width - 10, height - 10);
552*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(scaled, VideoFrame::UpdateRect({94, 44, 102, 202}));
553*d9f75844SAndroid Build Coastguard Worker }
554*d9f75844SAndroid Build Coastguard Worker
TEST(TestUpdateRectScale,ScaleByHalf)555*d9f75844SAndroid Build Coastguard Worker TEST(TestUpdateRectScale, ScaleByHalf) {
556*d9f75844SAndroid Build Coastguard Worker const int width = 640;
557*d9f75844SAndroid Build Coastguard Worker const int height = 480;
558*d9f75844SAndroid Build Coastguard Worker VideoFrame::UpdateRect a = {100, 60, 100, 200};
559*d9f75844SAndroid Build Coastguard Worker VideoFrame::UpdateRect scaled = a.ScaleWithFrame(
560*d9f75844SAndroid Build Coastguard Worker width, height, 0, 0, width, height, width / 2, height / 2);
561*d9f75844SAndroid Build Coastguard Worker // Scaled by half and +2 pixels in all directions.
562*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(scaled, VideoFrame::UpdateRect({48, 28, 54, 104}));
563*d9f75844SAndroid Build Coastguard Worker }
564*d9f75844SAndroid Build Coastguard Worker
TEST(TestUpdateRectScale,CropToUnchangedRegionBelowUpdateRect)565*d9f75844SAndroid Build Coastguard Worker TEST(TestUpdateRectScale, CropToUnchangedRegionBelowUpdateRect) {
566*d9f75844SAndroid Build Coastguard Worker const int width = 640;
567*d9f75844SAndroid Build Coastguard Worker const int height = 480;
568*d9f75844SAndroid Build Coastguard Worker VideoFrame::UpdateRect a = {100, 60, 100, 200};
569*d9f75844SAndroid Build Coastguard Worker VideoFrame::UpdateRect scaled = a.ScaleWithFrame(
570*d9f75844SAndroid Build Coastguard Worker width, height, (width - 10) / 2, (height - 10) / 2, 10, 10, 10, 10);
571*d9f75844SAndroid Build Coastguard Worker // Update is out of the cropped frame.
572*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(scaled, VideoFrame::UpdateRect({0, 0, 0, 0}));
573*d9f75844SAndroid Build Coastguard Worker }
574*d9f75844SAndroid Build Coastguard Worker
TEST(TestUpdateRectScale,CropToUnchangedRegionAboveUpdateRect)575*d9f75844SAndroid Build Coastguard Worker TEST(TestUpdateRectScale, CropToUnchangedRegionAboveUpdateRect) {
576*d9f75844SAndroid Build Coastguard Worker const int width = 640;
577*d9f75844SAndroid Build Coastguard Worker const int height = 480;
578*d9f75844SAndroid Build Coastguard Worker VideoFrame::UpdateRect a = {600, 400, 10, 10};
579*d9f75844SAndroid Build Coastguard Worker VideoFrame::UpdateRect scaled = a.ScaleWithFrame(
580*d9f75844SAndroid Build Coastguard Worker width, height, (width - 10) / 2, (height - 10) / 2, 10, 10, 10, 10);
581*d9f75844SAndroid Build Coastguard Worker // Update is out of the cropped frame.
582*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(scaled, VideoFrame::UpdateRect({0, 0, 0, 0}));
583*d9f75844SAndroid Build Coastguard Worker }
584*d9f75844SAndroid Build Coastguard Worker
TEST(TestUpdateRectScale,CropInsideUpdate)585*d9f75844SAndroid Build Coastguard Worker TEST(TestUpdateRectScale, CropInsideUpdate) {
586*d9f75844SAndroid Build Coastguard Worker const int width = 640;
587*d9f75844SAndroid Build Coastguard Worker const int height = 480;
588*d9f75844SAndroid Build Coastguard Worker VideoFrame::UpdateRect a = {300, 200, 100, 100};
589*d9f75844SAndroid Build Coastguard Worker VideoFrame::UpdateRect scaled = a.ScaleWithFrame(
590*d9f75844SAndroid Build Coastguard Worker width, height, (width - 10) / 2, (height - 10) / 2, 10, 10, 10, 10);
591*d9f75844SAndroid Build Coastguard Worker // Cropped frame is inside the update rect.
592*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(scaled, VideoFrame::UpdateRect({0, 0, 10, 10}));
593*d9f75844SAndroid Build Coastguard Worker }
594*d9f75844SAndroid Build Coastguard Worker
TEST(TestUpdateRectScale,CropAndScaleByHalf)595*d9f75844SAndroid Build Coastguard Worker TEST(TestUpdateRectScale, CropAndScaleByHalf) {
596*d9f75844SAndroid Build Coastguard Worker const int width = 640;
597*d9f75844SAndroid Build Coastguard Worker const int height = 480;
598*d9f75844SAndroid Build Coastguard Worker VideoFrame::UpdateRect a = {100, 60, 100, 200};
599*d9f75844SAndroid Build Coastguard Worker VideoFrame::UpdateRect scaled =
600*d9f75844SAndroid Build Coastguard Worker a.ScaleWithFrame(width, height, 10, 10, width - 20, height - 20,
601*d9f75844SAndroid Build Coastguard Worker (width - 20) / 2, (height - 20) / 2);
602*d9f75844SAndroid Build Coastguard Worker // Scaled by half and +3 pixels in all directions, because of odd offset after
603*d9f75844SAndroid Build Coastguard Worker // crop and scale.
604*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(scaled, VideoFrame::UpdateRect({42, 22, 56, 106}));
605*d9f75844SAndroid Build Coastguard Worker }
606*d9f75844SAndroid Build Coastguard Worker
607*d9f75844SAndroid Build Coastguard Worker } // namespace webrtc
608