1 /*
2 * Copyright (c) 2012 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 <math.h>
12 #include <string.h>
13
14 #include "testing/gtest/include/gtest/gtest.h"
15 #include "webrtc/common_video/interface/i420_video_frame.h"
16 #include "webrtc/system_wrappers/interface/ref_count.h"
17 #include "webrtc/system_wrappers/interface/scoped_ptr.h"
18 #include "webrtc/system_wrappers/interface/scoped_refptr.h"
19
20 namespace webrtc {
21
22 bool EqualFrames(const I420VideoFrame& frame1,
23 const I420VideoFrame& frame2);
24 bool EqualFramesExceptSize(const I420VideoFrame& frame1,
25 const I420VideoFrame& frame2);
26 int ExpectedSize(int plane_stride, int image_height, PlaneType type);
27
TEST(TestI420VideoFrame,InitialValues)28 TEST(TestI420VideoFrame, InitialValues) {
29 I420VideoFrame frame;
30 // Invalid arguments - one call for each variable.
31 EXPECT_TRUE(frame.IsZeroSize());
32 EXPECT_EQ(-1, frame.CreateEmptyFrame(0, 10, 10, 14, 14));
33 EXPECT_EQ(-1, frame.CreateEmptyFrame(10, -1, 10, 90, 14));
34 EXPECT_EQ(-1, frame.CreateEmptyFrame(10, 10, 0, 14, 18));
35 EXPECT_EQ(-1, frame.CreateEmptyFrame(10, 10, 10, -2, 13));
36 EXPECT_EQ(-1, frame.CreateEmptyFrame(10, 10, 10, 14, 0));
37 EXPECT_EQ(0, frame.CreateEmptyFrame(10, 10, 10, 14, 90));
38 EXPECT_FALSE(frame.IsZeroSize());
39 }
40
TEST(TestI420VideoFrame,WidthHeightValues)41 TEST(TestI420VideoFrame, WidthHeightValues) {
42 I420VideoFrame frame;
43 const int valid_value = 10;
44 const int invalid_value = -1;
45 EXPECT_EQ(0, frame.CreateEmptyFrame(10, 10, 10, 14, 90));
46 EXPECT_EQ(valid_value, frame.width());
47 EXPECT_EQ(invalid_value, frame.set_width(invalid_value));
48 EXPECT_EQ(valid_value, frame.height());
49 EXPECT_EQ(valid_value, frame.height());
50 EXPECT_EQ(invalid_value, frame.set_height(0));
51 EXPECT_EQ(valid_value, frame.height());
52 frame.set_timestamp(123u);
53 EXPECT_EQ(123u, frame.timestamp());
54 frame.set_ntp_time_ms(456);
55 EXPECT_EQ(456, frame.ntp_time_ms());
56 frame.set_render_time_ms(789);
57 EXPECT_EQ(789, frame.render_time_ms());
58 }
59
TEST(TestI420VideoFrame,SizeAllocation)60 TEST(TestI420VideoFrame, SizeAllocation) {
61 I420VideoFrame frame;
62 EXPECT_EQ(0, frame. CreateEmptyFrame(10, 10, 12, 14, 220));
63 int height = frame.height();
64 int stride_y = frame.stride(kYPlane);
65 int stride_u = frame.stride(kUPlane);
66 int stride_v = frame.stride(kVPlane);
67 // Verify that allocated size was computed correctly.
68 EXPECT_EQ(ExpectedSize(stride_y, height, kYPlane),
69 frame.allocated_size(kYPlane));
70 EXPECT_EQ(ExpectedSize(stride_u, height, kUPlane),
71 frame.allocated_size(kUPlane));
72 EXPECT_EQ(ExpectedSize(stride_v, height, kVPlane),
73 frame.allocated_size(kVPlane));
74 }
75
TEST(TestI420VideoFrame,ResetSize)76 TEST(TestI420VideoFrame, ResetSize) {
77 I420VideoFrame frame;
78 EXPECT_EQ(0, frame. CreateEmptyFrame(10, 10, 12, 14, 220));
79 EXPECT_FALSE(frame.IsZeroSize());
80 frame.ResetSize();
81 EXPECT_TRUE(frame.IsZeroSize());
82 }
83
TEST(TestI420VideoFrame,CopyFrame)84 TEST(TestI420VideoFrame, CopyFrame) {
85 I420VideoFrame frame1, frame2;
86 uint32_t timestamp = 1;
87 int64_t ntp_time_ms = 2;
88 int64_t render_time_ms = 3;
89 int stride_y = 15;
90 int stride_u = 10;
91 int stride_v = 10;
92 int width = 15;
93 int height = 15;
94 // Copy frame.
95 EXPECT_EQ(0, frame1.CreateEmptyFrame(width, height,
96 stride_y, stride_u, stride_v));
97 frame1.set_timestamp(timestamp);
98 frame1.set_ntp_time_ms(ntp_time_ms);
99 frame1.set_render_time_ms(render_time_ms);
100 const int kSizeY = 225;
101 const int kSizeU = 80;
102 const int kSizeV = 80;
103 uint8_t buffer_y[kSizeY];
104 uint8_t buffer_u[kSizeU];
105 uint8_t buffer_v[kSizeV];
106 memset(buffer_y, 16, kSizeY);
107 memset(buffer_u, 8, kSizeU);
108 memset(buffer_v, 4, kSizeV);
109 frame2.CreateFrame(kSizeY, buffer_y,
110 kSizeU, buffer_u,
111 kSizeV, buffer_v,
112 width + 5, height + 5, stride_y + 5, stride_u, stride_v);
113 // Frame of smaller dimensions - allocated sizes should not vary.
114 EXPECT_EQ(0, frame1.CopyFrame(frame2));
115 EXPECT_TRUE(EqualFramesExceptSize(frame1, frame2));
116 EXPECT_EQ(kSizeY, frame1.allocated_size(kYPlane));
117 EXPECT_EQ(kSizeU, frame1.allocated_size(kUPlane));
118 EXPECT_EQ(kSizeV, frame1.allocated_size(kVPlane));
119 // Verify copy of all parameters.
120 // Frame of larger dimensions - update allocated sizes.
121 EXPECT_EQ(0, frame2.CopyFrame(frame1));
122 EXPECT_TRUE(EqualFrames(frame1, frame2));
123 }
124
TEST(TestI420VideoFrame,CloneFrame)125 TEST(TestI420VideoFrame, CloneFrame) {
126 I420VideoFrame frame1;
127 scoped_ptr<I420VideoFrame> frame2;
128 const int kSizeY = 225;
129 const int kSizeU = 80;
130 const int kSizeV = 80;
131 uint8_t buffer_y[kSizeY];
132 uint8_t buffer_u[kSizeU];
133 uint8_t buffer_v[kSizeV];
134 memset(buffer_y, 16, kSizeY);
135 memset(buffer_u, 8, kSizeU);
136 memset(buffer_v, 4, kSizeV);
137 frame1.CreateFrame(
138 kSizeY, buffer_y, kSizeU, buffer_u, kSizeV, buffer_v, 20, 20, 20, 10, 10);
139 frame1.set_timestamp(1);
140 frame1.set_ntp_time_ms(2);
141 frame1.set_render_time_ms(3);
142
143 frame2.reset(frame1.CloneFrame());
144 EXPECT_TRUE(frame2.get() != NULL);
145 EXPECT_TRUE(EqualFrames(frame1, *frame2));
146 }
147
TEST(TestI420VideoFrame,CopyBuffer)148 TEST(TestI420VideoFrame, CopyBuffer) {
149 I420VideoFrame frame1, frame2;
150 int width = 15;
151 int height = 15;
152 int stride_y = 15;
153 int stride_uv = 10;
154 const int kSizeY = 225;
155 const int kSizeUv = 80;
156 EXPECT_EQ(0, frame2.CreateEmptyFrame(width, height,
157 stride_y, stride_uv, stride_uv));
158 uint8_t buffer_y[kSizeY];
159 uint8_t buffer_u[kSizeUv];
160 uint8_t buffer_v[kSizeUv];
161 memset(buffer_y, 16, kSizeY);
162 memset(buffer_u, 8, kSizeUv);
163 memset(buffer_v, 4, kSizeUv);
164 frame2.CreateFrame(kSizeY, buffer_y,
165 kSizeUv, buffer_u,
166 kSizeUv, buffer_v,
167 width, height, stride_y, stride_uv, stride_uv);
168 // Copy memory (at least allocated size).
169 EXPECT_EQ(memcmp(buffer_y, frame2.buffer(kYPlane), kSizeY), 0);
170 EXPECT_EQ(memcmp(buffer_u, frame2.buffer(kUPlane), kSizeUv), 0);
171 EXPECT_EQ(memcmp(buffer_v, frame2.buffer(kVPlane), kSizeUv), 0);
172 // Comapre size.
173 EXPECT_LE(kSizeY, frame2.allocated_size(kYPlane));
174 EXPECT_LE(kSizeUv, frame2.allocated_size(kUPlane));
175 EXPECT_LE(kSizeUv, frame2.allocated_size(kVPlane));
176 }
177
TEST(TestI420VideoFrame,FrameSwap)178 TEST(TestI420VideoFrame, FrameSwap) {
179 I420VideoFrame frame1, frame2;
180 uint32_t timestamp1 = 1;
181 int64_t ntp_time_ms1 = 2;
182 int64_t render_time_ms1 = 3;
183 int stride_y1 = 15;
184 int stride_u1 = 10;
185 int stride_v1 = 10;
186 int width1 = 15;
187 int height1 = 15;
188 const int kSizeY1 = 225;
189 const int kSizeU1 = 80;
190 const int kSizeV1 = 80;
191 uint32_t timestamp2 = 4;
192 int64_t ntp_time_ms2 = 5;
193 int64_t render_time_ms2 = 6;
194 int stride_y2 = 30;
195 int stride_u2 = 20;
196 int stride_v2 = 20;
197 int width2 = 30;
198 int height2 = 30;
199 const int kSizeY2 = 900;
200 const int kSizeU2 = 300;
201 const int kSizeV2 = 300;
202 // Initialize frame1 values.
203 EXPECT_EQ(0, frame1.CreateEmptyFrame(width1, height1,
204 stride_y1, stride_u1, stride_v1));
205 frame1.set_timestamp(timestamp1);
206 frame1.set_ntp_time_ms(ntp_time_ms1);
207 frame1.set_render_time_ms(render_time_ms1);
208 // Set memory for frame1.
209 uint8_t buffer_y1[kSizeY1];
210 uint8_t buffer_u1[kSizeU1];
211 uint8_t buffer_v1[kSizeV1];
212 memset(buffer_y1, 2, kSizeY1);
213 memset(buffer_u1, 4, kSizeU1);
214 memset(buffer_v1, 8, kSizeV1);
215 frame1.CreateFrame(kSizeY1, buffer_y1,
216 kSizeU1, buffer_u1,
217 kSizeV1, buffer_v1,
218 width1, height1, stride_y1, stride_u1, stride_v1);
219 // Initialize frame2 values.
220 EXPECT_EQ(0, frame2.CreateEmptyFrame(width2, height2,
221 stride_y2, stride_u2, stride_v2));
222 frame2.set_timestamp(timestamp2);
223 frame1.set_ntp_time_ms(ntp_time_ms2);
224 frame2.set_render_time_ms(render_time_ms2);
225 // Set memory for frame2.
226 uint8_t buffer_y2[kSizeY2];
227 uint8_t buffer_u2[kSizeU2];
228 uint8_t buffer_v2[kSizeV2];
229 memset(buffer_y2, 0, kSizeY2);
230 memset(buffer_u2, 1, kSizeU2);
231 memset(buffer_v2, 2, kSizeV2);
232 frame2.CreateFrame(kSizeY2, buffer_y2,
233 kSizeU2, buffer_u2,
234 kSizeV2, buffer_v2,
235 width2, height2, stride_y2, stride_u2, stride_v2);
236 // Copy frames for subsequent comparison.
237 I420VideoFrame frame1_copy, frame2_copy;
238 frame1_copy.CopyFrame(frame1);
239 frame2_copy.CopyFrame(frame2);
240 // Swap frames.
241 frame1.SwapFrame(&frame2);
242 // Verify swap.
243 EXPECT_TRUE(EqualFrames(frame1_copy, frame2));
244 EXPECT_TRUE(EqualFrames(frame2_copy, frame1));
245 }
246
TEST(TestI420VideoFrame,RefCountedInstantiation)247 TEST(TestI420VideoFrame, RefCountedInstantiation) {
248 // Refcounted instantiation - ref_count should correspond to the number of
249 // instances.
250 scoped_refptr<I420VideoFrame> ref_count_frame(
251 new RefCountImpl<I420VideoFrame>());
252 EXPECT_EQ(2, ref_count_frame->AddRef());
253 EXPECT_EQ(3, ref_count_frame->AddRef());
254 EXPECT_EQ(2, ref_count_frame->Release());
255 EXPECT_EQ(1, ref_count_frame->Release());
256 }
257
EqualFrames(const I420VideoFrame & frame1,const I420VideoFrame & frame2)258 bool EqualFrames(const I420VideoFrame& frame1,
259 const I420VideoFrame& frame2) {
260 return (EqualFramesExceptSize(frame1, frame2) &&
261 (frame1.allocated_size(kYPlane) == frame2.allocated_size(kYPlane)) &&
262 (frame1.allocated_size(kUPlane) == frame2.allocated_size(kUPlane)) &&
263 (frame1.allocated_size(kVPlane) == frame2.allocated_size(kVPlane)));
264 }
265
EqualFramesExceptSize(const I420VideoFrame & frame1,const I420VideoFrame & frame2)266 bool EqualFramesExceptSize(const I420VideoFrame& frame1,
267 const I420VideoFrame& frame2) {
268 if ((frame1.width() != frame2.width()) ||
269 (frame1.height() != frame2.height()) ||
270 (frame1.stride(kYPlane) != frame2.stride(kYPlane)) ||
271 (frame1.stride(kUPlane) != frame2.stride(kUPlane)) ||
272 (frame1.stride(kVPlane) != frame2.stride(kVPlane)) ||
273 (frame1.timestamp() != frame2.timestamp()) ||
274 (frame1.ntp_time_ms() != frame2.ntp_time_ms()) ||
275 (frame1.render_time_ms() != frame2.render_time_ms())) {
276 return false;
277 }
278 // Memory should be the equal for the minimum of the two sizes.
279 int size_y = std::min(frame1.allocated_size(kYPlane),
280 frame2.allocated_size(kYPlane));
281 int size_u = std::min(frame1.allocated_size(kUPlane),
282 frame2.allocated_size(kUPlane));
283 int size_v = std::min(frame1.allocated_size(kVPlane),
284 frame2.allocated_size(kVPlane));
285 return (memcmp(frame1.buffer(kYPlane), frame2.buffer(kYPlane), size_y) == 0 &&
286 memcmp(frame1.buffer(kUPlane), frame2.buffer(kUPlane), size_u) == 0 &&
287 memcmp(frame1.buffer(kVPlane), frame2.buffer(kVPlane), size_v) == 0);
288 }
289
ExpectedSize(int plane_stride,int image_height,PlaneType type)290 int ExpectedSize(int plane_stride, int image_height, PlaneType type) {
291 if (type == kYPlane) {
292 return (plane_stride * image_height);
293 } else {
294 int half_height = (image_height + 1) / 2;
295 return (plane_stride * half_height);
296 }
297 }
298
299 } // namespace webrtc
300