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 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 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 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 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 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 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 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 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 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 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 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 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