1/* 2 * libjingle 3 * Copyright 2011 Google Inc. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are met: 7 * 8 * 1. Redistributions of source code must retain the above copyright notice, 9 * this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright notice, 11 * this list of conditions and the following disclaimer in the documentation 12 * and/or other materials provided with the distribution. 13 * 3. The name of the author may not be used to endorse or promote products 14 * derived from this software without specific prior written permission. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 18 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 19 * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 20 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 21 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 22 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 23 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 24 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 25 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 */ 27 28#include <string.h> 29 30#include "talk/media/base/videoframe_unittest.h" 31#include "talk/media/webrtc/webrtcvideoframe.h" 32#include "webrtc/test/fake_texture_frame.h" 33 34namespace { 35 36class WebRtcVideoTestFrame : public cricket::WebRtcVideoFrame { 37 public: 38 using cricket::WebRtcVideoFrame::SetRotation; 39 40 virtual VideoFrame* CreateEmptyFrame(int w, 41 int h, 42 size_t pixel_width, 43 size_t pixel_height, 44 int64_t time_stamp) const override { 45 WebRtcVideoTestFrame* frame = new WebRtcVideoTestFrame(); 46 frame->InitToBlack(w, h, pixel_width, pixel_height, time_stamp); 47 return frame; 48 } 49}; 50 51} // namespace 52 53class WebRtcVideoFrameTest : public VideoFrameTest<cricket::WebRtcVideoFrame> { 54 public: 55 WebRtcVideoFrameTest() { 56 } 57 58 void TestInit(int cropped_width, int cropped_height, 59 webrtc::VideoRotation frame_rotation, 60 bool apply_rotation) { 61 const int frame_width = 1920; 62 const int frame_height = 1080; 63 64 // Build the CapturedFrame. 65 cricket::CapturedFrame captured_frame; 66 captured_frame.fourcc = cricket::FOURCC_I420; 67 captured_frame.pixel_width = 1; 68 captured_frame.pixel_height = 1; 69 captured_frame.time_stamp = 5678; 70 captured_frame.rotation = frame_rotation; 71 captured_frame.width = frame_width; 72 captured_frame.height = frame_height; 73 captured_frame.data_size = (frame_width * frame_height) + 74 ((frame_width + 1) / 2) * ((frame_height + 1) / 2) * 2; 75 rtc::scoped_ptr<uint8_t[]> captured_frame_buffer( 76 new uint8_t[captured_frame.data_size]); 77 // Initialize memory to satisfy DrMemory tests. 78 memset(captured_frame_buffer.get(), 0, captured_frame.data_size); 79 captured_frame.data = captured_frame_buffer.get(); 80 81 // Create the new frame from the CapturedFrame. 82 cricket::WebRtcVideoFrame frame; 83 EXPECT_TRUE( 84 frame.Init(&captured_frame, cropped_width, cropped_height, 85 apply_rotation)); 86 87 // Verify the new frame. 88 EXPECT_EQ(1u, frame.GetPixelWidth()); 89 EXPECT_EQ(1u, frame.GetPixelHeight()); 90 EXPECT_EQ(5678, frame.GetTimeStamp()); 91 if (apply_rotation) 92 EXPECT_EQ(webrtc::kVideoRotation_0, frame.GetRotation()); 93 else 94 EXPECT_EQ(frame_rotation, frame.GetRotation()); 95 // If |apply_rotation| and the frame rotation is 90 or 270, width and 96 // height are flipped. 97 if (apply_rotation && (frame_rotation == webrtc::kVideoRotation_90 98 || frame_rotation == webrtc::kVideoRotation_270)) { 99 EXPECT_EQ(static_cast<size_t>(cropped_width), frame.GetHeight()); 100 EXPECT_EQ(static_cast<size_t>(cropped_height), frame.GetWidth()); 101 } else { 102 EXPECT_EQ(static_cast<size_t>(cropped_width), frame.GetWidth()); 103 EXPECT_EQ(static_cast<size_t>(cropped_height), frame.GetHeight()); 104 } 105 } 106}; 107 108#define TEST_WEBRTCVIDEOFRAME(X) TEST_F(WebRtcVideoFrameTest, X) { \ 109 VideoFrameTest<cricket::WebRtcVideoFrame>::X(); \ 110} 111 112TEST_WEBRTCVIDEOFRAME(ConstructI420) 113TEST_WEBRTCVIDEOFRAME(ConstructI422) 114TEST_WEBRTCVIDEOFRAME(ConstructYuy2) 115TEST_WEBRTCVIDEOFRAME(ConstructYuy2Unaligned) 116TEST_WEBRTCVIDEOFRAME(ConstructYuy2Wide) 117TEST_WEBRTCVIDEOFRAME(ConstructYV12) 118TEST_WEBRTCVIDEOFRAME(ConstructUyvy) 119TEST_WEBRTCVIDEOFRAME(ConstructM420) 120TEST_WEBRTCVIDEOFRAME(ConstructNV21) 121TEST_WEBRTCVIDEOFRAME(ConstructNV12) 122TEST_WEBRTCVIDEOFRAME(ConstructABGR) 123TEST_WEBRTCVIDEOFRAME(ConstructARGB) 124TEST_WEBRTCVIDEOFRAME(ConstructARGBWide) 125TEST_WEBRTCVIDEOFRAME(ConstructBGRA) 126TEST_WEBRTCVIDEOFRAME(Construct24BG) 127TEST_WEBRTCVIDEOFRAME(ConstructRaw) 128TEST_WEBRTCVIDEOFRAME(ConstructRGB565) 129TEST_WEBRTCVIDEOFRAME(ConstructARGB1555) 130TEST_WEBRTCVIDEOFRAME(ConstructARGB4444) 131 132TEST_WEBRTCVIDEOFRAME(ConstructI420Mirror) 133TEST_WEBRTCVIDEOFRAME(ConstructI420Rotate0) 134TEST_WEBRTCVIDEOFRAME(ConstructI420Rotate90) 135TEST_WEBRTCVIDEOFRAME(ConstructI420Rotate180) 136TEST_WEBRTCVIDEOFRAME(ConstructI420Rotate270) 137TEST_WEBRTCVIDEOFRAME(ConstructYV12Rotate0) 138TEST_WEBRTCVIDEOFRAME(ConstructYV12Rotate90) 139TEST_WEBRTCVIDEOFRAME(ConstructYV12Rotate180) 140TEST_WEBRTCVIDEOFRAME(ConstructYV12Rotate270) 141TEST_WEBRTCVIDEOFRAME(ConstructNV12Rotate0) 142TEST_WEBRTCVIDEOFRAME(ConstructNV12Rotate90) 143TEST_WEBRTCVIDEOFRAME(ConstructNV12Rotate180) 144TEST_WEBRTCVIDEOFRAME(ConstructNV12Rotate270) 145TEST_WEBRTCVIDEOFRAME(ConstructNV21Rotate0) 146TEST_WEBRTCVIDEOFRAME(ConstructNV21Rotate90) 147TEST_WEBRTCVIDEOFRAME(ConstructNV21Rotate180) 148TEST_WEBRTCVIDEOFRAME(ConstructNV21Rotate270) 149TEST_WEBRTCVIDEOFRAME(ConstructUYVYRotate0) 150TEST_WEBRTCVIDEOFRAME(ConstructUYVYRotate90) 151TEST_WEBRTCVIDEOFRAME(ConstructUYVYRotate180) 152TEST_WEBRTCVIDEOFRAME(ConstructUYVYRotate270) 153TEST_WEBRTCVIDEOFRAME(ConstructYUY2Rotate0) 154TEST_WEBRTCVIDEOFRAME(ConstructYUY2Rotate90) 155TEST_WEBRTCVIDEOFRAME(ConstructYUY2Rotate180) 156TEST_WEBRTCVIDEOFRAME(ConstructYUY2Rotate270) 157TEST_WEBRTCVIDEOFRAME(ConstructI4201Pixel) 158TEST_WEBRTCVIDEOFRAME(ConstructI4205Pixel) 159// TODO(juberti): WebRtcVideoFrame does not support horizontal crop. 160// Re-evaluate once it supports 3 independent planes, since we might want to 161// just Init normally and then crop by adjusting pointers. 162// TEST_WEBRTCVIDEOFRAME(ConstructI420CropHorizontal) 163TEST_WEBRTCVIDEOFRAME(ConstructI420CropVertical) 164// TODO(juberti): WebRtcVideoFrame is not currently refcounted. 165// TEST_WEBRTCVIDEOFRAME(ConstructCopy) 166// TEST_WEBRTCVIDEOFRAME(ConstructCopyIsRef) 167TEST_WEBRTCVIDEOFRAME(ConstructBlack) 168// TODO(fbarchard): Implement Jpeg 169// TEST_WEBRTCVIDEOFRAME(ConstructMjpgI420) 170TEST_WEBRTCVIDEOFRAME(ConstructMjpgI422) 171// TEST_WEBRTCVIDEOFRAME(ConstructMjpgI444) 172// TEST_WEBRTCVIDEOFRAME(ConstructMjpgI411) 173// TEST_WEBRTCVIDEOFRAME(ConstructMjpgI400) 174// TEST_WEBRTCVIDEOFRAME(ValidateMjpgI420) 175// TEST_WEBRTCVIDEOFRAME(ValidateMjpgI422) 176// TEST_WEBRTCVIDEOFRAME(ValidateMjpgI444) 177// TEST_WEBRTCVIDEOFRAME(ValidateMjpgI411) 178// TEST_WEBRTCVIDEOFRAME(ValidateMjpgI400) 179TEST_WEBRTCVIDEOFRAME(ValidateI420) 180TEST_WEBRTCVIDEOFRAME(ValidateI420SmallSize) 181TEST_WEBRTCVIDEOFRAME(ValidateI420LargeSize) 182TEST_WEBRTCVIDEOFRAME(ValidateI420HugeSize) 183// TEST_WEBRTCVIDEOFRAME(ValidateMjpgI420InvalidSize) 184// TEST_WEBRTCVIDEOFRAME(ValidateI420InvalidSize) 185 186// TODO(fbarchard): WebRtcVideoFrame does not support odd sizes. 187// Re-evaluate once WebRTC switches to libyuv 188// TEST_WEBRTCVIDEOFRAME(ConstructYuy2AllSizes) 189// TEST_WEBRTCVIDEOFRAME(ConstructARGBAllSizes) 190TEST_WEBRTCVIDEOFRAME(ResetAndApplyRotation) 191TEST_WEBRTCVIDEOFRAME(ResetAndDontApplyRotation) 192TEST_WEBRTCVIDEOFRAME(ConvertToABGRBuffer) 193TEST_WEBRTCVIDEOFRAME(ConvertToABGRBufferStride) 194TEST_WEBRTCVIDEOFRAME(ConvertToABGRBufferInverted) 195TEST_WEBRTCVIDEOFRAME(ConvertToARGB1555Buffer) 196TEST_WEBRTCVIDEOFRAME(ConvertToARGB1555BufferStride) 197TEST_WEBRTCVIDEOFRAME(ConvertToARGB1555BufferInverted) 198TEST_WEBRTCVIDEOFRAME(ConvertToARGB4444Buffer) 199TEST_WEBRTCVIDEOFRAME(ConvertToARGB4444BufferStride) 200TEST_WEBRTCVIDEOFRAME(ConvertToARGB4444BufferInverted) 201TEST_WEBRTCVIDEOFRAME(ConvertToARGBBuffer) 202TEST_WEBRTCVIDEOFRAME(ConvertToARGBBufferStride) 203TEST_WEBRTCVIDEOFRAME(ConvertToARGBBufferInverted) 204TEST_WEBRTCVIDEOFRAME(ConvertToBGRABuffer) 205TEST_WEBRTCVIDEOFRAME(ConvertToBGRABufferStride) 206TEST_WEBRTCVIDEOFRAME(ConvertToBGRABufferInverted) 207TEST_WEBRTCVIDEOFRAME(ConvertToRAWBuffer) 208TEST_WEBRTCVIDEOFRAME(ConvertToRAWBufferStride) 209TEST_WEBRTCVIDEOFRAME(ConvertToRAWBufferInverted) 210TEST_WEBRTCVIDEOFRAME(ConvertToRGB24Buffer) 211TEST_WEBRTCVIDEOFRAME(ConvertToRGB24BufferStride) 212TEST_WEBRTCVIDEOFRAME(ConvertToRGB24BufferInverted) 213TEST_WEBRTCVIDEOFRAME(ConvertToRGB565Buffer) 214TEST_WEBRTCVIDEOFRAME(ConvertToRGB565BufferStride) 215TEST_WEBRTCVIDEOFRAME(ConvertToRGB565BufferInverted) 216TEST_WEBRTCVIDEOFRAME(ConvertToI400Buffer) 217TEST_WEBRTCVIDEOFRAME(ConvertToI400BufferStride) 218TEST_WEBRTCVIDEOFRAME(ConvertToI400BufferInverted) 219TEST_WEBRTCVIDEOFRAME(ConvertToYUY2Buffer) 220TEST_WEBRTCVIDEOFRAME(ConvertToYUY2BufferStride) 221TEST_WEBRTCVIDEOFRAME(ConvertToYUY2BufferInverted) 222TEST_WEBRTCVIDEOFRAME(ConvertToUYVYBuffer) 223TEST_WEBRTCVIDEOFRAME(ConvertToUYVYBufferStride) 224TEST_WEBRTCVIDEOFRAME(ConvertToUYVYBufferInverted) 225TEST_WEBRTCVIDEOFRAME(ConvertFromABGRBuffer) 226TEST_WEBRTCVIDEOFRAME(ConvertFromABGRBufferStride) 227TEST_WEBRTCVIDEOFRAME(ConvertFromABGRBufferInverted) 228TEST_WEBRTCVIDEOFRAME(ConvertFromARGB1555Buffer) 229TEST_WEBRTCVIDEOFRAME(ConvertFromARGB1555BufferStride) 230TEST_WEBRTCVIDEOFRAME(ConvertFromARGB1555BufferInverted) 231TEST_WEBRTCVIDEOFRAME(ConvertFromARGB4444Buffer) 232TEST_WEBRTCVIDEOFRAME(ConvertFromARGB4444BufferStride) 233TEST_WEBRTCVIDEOFRAME(ConvertFromARGB4444BufferInverted) 234TEST_WEBRTCVIDEOFRAME(ConvertFromARGBBuffer) 235TEST_WEBRTCVIDEOFRAME(ConvertFromARGBBufferStride) 236TEST_WEBRTCVIDEOFRAME(ConvertFromARGBBufferInverted) 237TEST_WEBRTCVIDEOFRAME(ConvertFromBGRABuffer) 238TEST_WEBRTCVIDEOFRAME(ConvertFromBGRABufferStride) 239TEST_WEBRTCVIDEOFRAME(ConvertFromBGRABufferInverted) 240TEST_WEBRTCVIDEOFRAME(ConvertFromRAWBuffer) 241TEST_WEBRTCVIDEOFRAME(ConvertFromRAWBufferStride) 242TEST_WEBRTCVIDEOFRAME(ConvertFromRAWBufferInverted) 243TEST_WEBRTCVIDEOFRAME(ConvertFromRGB24Buffer) 244TEST_WEBRTCVIDEOFRAME(ConvertFromRGB24BufferStride) 245TEST_WEBRTCVIDEOFRAME(ConvertFromRGB24BufferInverted) 246TEST_WEBRTCVIDEOFRAME(ConvertFromRGB565Buffer) 247TEST_WEBRTCVIDEOFRAME(ConvertFromRGB565BufferStride) 248TEST_WEBRTCVIDEOFRAME(ConvertFromRGB565BufferInverted) 249TEST_WEBRTCVIDEOFRAME(ConvertFromI400Buffer) 250TEST_WEBRTCVIDEOFRAME(ConvertFromI400BufferStride) 251TEST_WEBRTCVIDEOFRAME(ConvertFromI400BufferInverted) 252TEST_WEBRTCVIDEOFRAME(ConvertFromYUY2Buffer) 253TEST_WEBRTCVIDEOFRAME(ConvertFromYUY2BufferStride) 254TEST_WEBRTCVIDEOFRAME(ConvertFromYUY2BufferInverted) 255TEST_WEBRTCVIDEOFRAME(ConvertFromUYVYBuffer) 256TEST_WEBRTCVIDEOFRAME(ConvertFromUYVYBufferStride) 257TEST_WEBRTCVIDEOFRAME(ConvertFromUYVYBufferInverted) 258// TEST_WEBRTCVIDEOFRAME(ConvertToI422Buffer) 259TEST_WEBRTCVIDEOFRAME(CopyToBuffer) 260TEST_WEBRTCVIDEOFRAME(CopyToFrame) 261TEST_WEBRTCVIDEOFRAME(Write) 262TEST_WEBRTCVIDEOFRAME(CopyToBuffer1Pixel) 263// TEST_WEBRTCVIDEOFRAME(ConstructARGBBlackWhitePixel) 264 265TEST_WEBRTCVIDEOFRAME(StretchToFrame) 266TEST_WEBRTCVIDEOFRAME(Copy) 267TEST_WEBRTCVIDEOFRAME(CopyIsRef) 268TEST_WEBRTCVIDEOFRAME(MakeExclusive) 269 270// These functions test implementation-specific details. 271// Tests the Init function with different cropped size. 272TEST_F(WebRtcVideoFrameTest, InitEvenSize) { 273 TestInit(640, 360, webrtc::kVideoRotation_0, true); 274} 275 276TEST_F(WebRtcVideoFrameTest, InitOddWidth) { 277 TestInit(601, 480, webrtc::kVideoRotation_0, true); 278} 279 280TEST_F(WebRtcVideoFrameTest, InitOddHeight) { 281 TestInit(360, 765, webrtc::kVideoRotation_0, true); 282} 283 284TEST_F(WebRtcVideoFrameTest, InitOddWidthHeight) { 285 TestInit(355, 1021, webrtc::kVideoRotation_0, true); 286} 287 288TEST_F(WebRtcVideoFrameTest, InitRotated90ApplyRotation) { 289 TestInit(640, 360, webrtc::kVideoRotation_90, true); 290} 291 292TEST_F(WebRtcVideoFrameTest, InitRotated90DontApplyRotation) { 293 TestInit(640, 360, webrtc::kVideoRotation_90, false); 294} 295 296TEST_F(WebRtcVideoFrameTest, TextureInitialValues) { 297 webrtc::test::FakeNativeHandle* dummy_handle = 298 new webrtc::test::FakeNativeHandle(); 299 webrtc::NativeHandleBuffer* buffer = 300 new rtc::RefCountedObject<webrtc::test::FakeNativeHandleBuffer>( 301 dummy_handle, 640, 480); 302 cricket::WebRtcVideoFrame frame(buffer, 200, webrtc::kVideoRotation_0); 303 EXPECT_EQ(dummy_handle, frame.GetNativeHandle()); 304 EXPECT_EQ(640u, frame.GetWidth()); 305 EXPECT_EQ(480u, frame.GetHeight()); 306 EXPECT_EQ(200, frame.GetTimeStamp()); 307 frame.SetTimeStamp(400); 308 EXPECT_EQ(400, frame.GetTimeStamp()); 309} 310 311TEST_F(WebRtcVideoFrameTest, CopyTextureFrame) { 312 webrtc::test::FakeNativeHandle* dummy_handle = 313 new webrtc::test::FakeNativeHandle(); 314 webrtc::NativeHandleBuffer* buffer = 315 new rtc::RefCountedObject<webrtc::test::FakeNativeHandleBuffer>( 316 dummy_handle, 640, 480); 317 cricket::WebRtcVideoFrame frame1(buffer, 200, webrtc::kVideoRotation_0); 318 cricket::VideoFrame* frame2 = frame1.Copy(); 319 EXPECT_EQ(frame1.GetNativeHandle(), frame2->GetNativeHandle()); 320 EXPECT_EQ(frame1.GetWidth(), frame2->GetWidth()); 321 EXPECT_EQ(frame1.GetHeight(), frame2->GetHeight()); 322 EXPECT_EQ(frame1.GetTimeStamp(), frame2->GetTimeStamp()); 323 delete frame2; 324} 325 326TEST_F(WebRtcVideoFrameTest, ApplyRotationToFrame) { 327 WebRtcVideoTestFrame applied0; 328 EXPECT_TRUE(IsNull(applied0)); 329 rtc::scoped_ptr<rtc::MemoryStream> ms(CreateYuvSample(kWidth, kHeight, 12)); 330 EXPECT_TRUE( 331 LoadFrame(ms.get(), cricket::FOURCC_I420, kWidth, kHeight, &applied0)); 332 333 // Claim that this frame needs to be rotated for 90 degree. 334 applied0.SetRotation(webrtc::kVideoRotation_90); 335 336 // Apply rotation on frame 1. Output should be different from frame 1. 337 WebRtcVideoTestFrame* applied90 = const_cast<WebRtcVideoTestFrame*>( 338 static_cast<const WebRtcVideoTestFrame*>( 339 applied0.GetCopyWithRotationApplied())); 340 EXPECT_TRUE(applied90); 341 EXPECT_EQ(applied90->GetVideoRotation(), webrtc::kVideoRotation_0); 342 EXPECT_FALSE(IsEqual(applied0, *applied90, 0)); 343 344 // Claim the frame 2 needs to be rotated for another 270 degree. The output 345 // from frame 2 rotation should be the same as frame 1. 346 applied90->SetRotation(webrtc::kVideoRotation_270); 347 const cricket::VideoFrame* applied360 = 348 applied90->GetCopyWithRotationApplied(); 349 EXPECT_TRUE(applied360); 350 EXPECT_EQ(applied360->GetVideoRotation(), webrtc::kVideoRotation_0); 351 EXPECT_TRUE(IsEqual(applied0, *applied360, 0)); 352} 353