| OLD | NEW |
| (Empty) |
| 1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. | |
| 2 // Use of this source code is governed by a BSD-style license that can be | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 #include "media/base/video_frame_impl.h" | |
| 6 | |
| 7 #include "base/format_macros.h" | |
| 8 #include "base/string_util.h" | |
| 9 #include "media/base/buffers.h" | |
| 10 #include "media/base/mock_filters.h" | |
| 11 #include "media/base/yuv_convert.h" | |
| 12 #include "testing/gtest/include/gtest/gtest.h" | |
| 13 | |
| 14 namespace media { | |
| 15 | |
| 16 // Helper function that initializes a YV12 frame with white and black scan | |
| 17 // lines based on the |white_to_black| parameter. If 0, then the entire | |
| 18 // frame will be black, if 1 then the entire frame will be white. | |
| 19 void InitializeYV12Frame(VideoFrame* frame, double white_to_black) { | |
| 20 VideoSurface surface; | |
| 21 if (!frame->Lock(&surface)) { | |
| 22 ADD_FAILURE(); | |
| 23 return; | |
| 24 } | |
| 25 EXPECT_EQ(VideoSurface::YV12, surface.format); | |
| 26 size_t first_black_row = static_cast<size_t>(surface.height * white_to_black); | |
| 27 uint8* y_plane = surface.data[VideoSurface::kYPlane]; | |
| 28 for (size_t row = 0; row < surface.height; ++row) { | |
| 29 int color = (row < first_black_row) ? 0xFF : 0x00; | |
| 30 memset(y_plane, color, surface.width); | |
| 31 y_plane += surface.strides[VideoSurface::kYPlane]; | |
| 32 } | |
| 33 uint8* u_plane = surface.data[VideoSurface::kUPlane]; | |
| 34 uint8* v_plane = surface.data[VideoSurface::kVPlane]; | |
| 35 for (size_t row = 0; row < surface.height; row += 2) { | |
| 36 memset(u_plane, 0x80, surface.width / 2); | |
| 37 memset(v_plane, 0x80, surface.width / 2); | |
| 38 u_plane += surface.strides[VideoSurface::kUPlane]; | |
| 39 v_plane += surface.strides[VideoSurface::kVPlane]; | |
| 40 } | |
| 41 frame->Unlock(); | |
| 42 } | |
| 43 | |
| 44 // Given a |yv12_frame| this method converts the YV12 frame to RGBA and | |
| 45 // makes sure that all the pixels of the RBG frame equal |expect_rgb_color|. | |
| 46 void ExpectFrameColor(media::VideoFrame* yv12_frame, uint32 expect_rgb_color) { | |
| 47 // On linux and mac builds if you directly compare using EXPECT_EQ and use | |
| 48 // the VideoSurface::kNumxxxPlanes constants, it generates an error when | |
| 49 // linking. These are declared so that we can compare against locals. | |
| 50 const size_t expect_yuv_planes = VideoSurface::kNumYUVPlanes; | |
| 51 const size_t expect_rgb_planes = VideoSurface::kNumRGBPlanes; | |
| 52 | |
| 53 VideoSurface yuv_surface; | |
| 54 ASSERT_TRUE(yv12_frame->Lock(&yuv_surface)); | |
| 55 ASSERT_EQ(VideoSurface::YV12, yuv_surface.format); | |
| 56 ASSERT_EQ(expect_yuv_planes, yuv_surface.planes); | |
| 57 ASSERT_EQ(yuv_surface.strides[VideoSurface::kUPlane], | |
| 58 yuv_surface.strides[VideoSurface::kVPlane]); | |
| 59 | |
| 60 scoped_refptr<media::VideoFrame> rgb_frame; | |
| 61 media::VideoFrameImpl::CreateFrame(VideoSurface::RGBA, | |
| 62 yuv_surface.width, | |
| 63 yuv_surface.height, | |
| 64 yv12_frame->GetTimestamp(), | |
| 65 yv12_frame->GetDuration(), | |
| 66 &rgb_frame); | |
| 67 media::VideoSurface rgb_surface; | |
| 68 ASSERT_TRUE(rgb_frame->Lock(&rgb_surface)); | |
| 69 ASSERT_EQ(yuv_surface.width, rgb_surface.width); | |
| 70 ASSERT_EQ(yuv_surface.height, rgb_surface.height); | |
| 71 ASSERT_EQ(expect_rgb_planes, rgb_surface.planes); | |
| 72 | |
| 73 media::ConvertYUVToRGB32(yuv_surface.data[VideoSurface::kYPlane], | |
| 74 yuv_surface.data[VideoSurface::kUPlane], | |
| 75 yuv_surface.data[VideoSurface::kVPlane], | |
| 76 rgb_surface.data[VideoSurface::kRGBPlane], | |
| 77 rgb_surface.width, | |
| 78 rgb_surface.height, | |
| 79 yuv_surface.strides[VideoSurface::kYPlane], | |
| 80 yuv_surface.strides[VideoSurface::kUPlane], | |
| 81 rgb_surface.strides[VideoSurface::kRGBPlane], | |
| 82 media::YV12); | |
| 83 | |
| 84 for (size_t row = 0; row < rgb_surface.height; ++row) { | |
| 85 uint32* rgb_row_data = reinterpret_cast<uint32*>( | |
| 86 rgb_surface.data[VideoSurface::kRGBPlane] + | |
| 87 (rgb_surface.strides[VideoSurface::kRGBPlane] * row)); | |
| 88 for (size_t col = 0; col < rgb_surface.width; ++col) { | |
| 89 SCOPED_TRACE(StringPrintf("Checking (%" PRIuS ", %" PRIuS ")", row, col)); | |
| 90 EXPECT_EQ(expect_rgb_color, rgb_row_data[col]); | |
| 91 } | |
| 92 } | |
| 93 rgb_frame->Unlock(); | |
| 94 yv12_frame->Unlock(); | |
| 95 } | |
| 96 | |
| 97 TEST(VideoFrameImpl, CreateFrame) { | |
| 98 const size_t kWidth = 64; | |
| 99 const size_t kHeight = 48; | |
| 100 const base::TimeDelta kTimestampA = base::TimeDelta::FromMicroseconds(1337); | |
| 101 const base::TimeDelta kDurationA = base::TimeDelta::FromMicroseconds(1667); | |
| 102 const base::TimeDelta kTimestampB = base::TimeDelta::FromMicroseconds(1234); | |
| 103 const base::TimeDelta kDurationB = base::TimeDelta::FromMicroseconds(5678); | |
| 104 | |
| 105 // Create a YV12 Video Frame. | |
| 106 scoped_refptr<media::VideoFrame> frame; | |
| 107 VideoFrameImpl::CreateFrame(media::VideoSurface::YV12, kWidth, kHeight, | |
| 108 kTimestampA, kDurationA, &frame); | |
| 109 ASSERT_TRUE(frame); | |
| 110 | |
| 111 // Test StreamSample implementation. | |
| 112 EXPECT_EQ(kTimestampA.InMicroseconds(), | |
| 113 frame->GetTimestamp().InMicroseconds()); | |
| 114 EXPECT_EQ(kDurationA.InMicroseconds(), frame->GetDuration().InMicroseconds()); | |
| 115 EXPECT_FALSE(frame->IsEndOfStream()); | |
| 116 EXPECT_FALSE(frame->IsDiscontinuous()); | |
| 117 frame->SetTimestamp(kTimestampB); | |
| 118 frame->SetDuration(kDurationB); | |
| 119 EXPECT_EQ(kTimestampB.InMicroseconds(), | |
| 120 frame->GetTimestamp().InMicroseconds()); | |
| 121 EXPECT_EQ(kDurationB.InMicroseconds(), frame->GetDuration().InMicroseconds()); | |
| 122 EXPECT_FALSE(frame->IsEndOfStream()); | |
| 123 frame->SetDiscontinuous(true); | |
| 124 EXPECT_TRUE(frame->IsDiscontinuous()); | |
| 125 frame->SetDiscontinuous(false); | |
| 126 EXPECT_FALSE(frame->IsDiscontinuous()); | |
| 127 | |
| 128 // Test VideoFrame implementation. | |
| 129 { | |
| 130 SCOPED_TRACE(""); | |
| 131 InitializeYV12Frame(frame, 0.0f); | |
| 132 ExpectFrameColor(frame, 0xFF000000); | |
| 133 } | |
| 134 { | |
| 135 SCOPED_TRACE(""); | |
| 136 InitializeYV12Frame(frame, 1.0f); | |
| 137 ExpectFrameColor(frame, 0xFFFFFFFF); | |
| 138 } | |
| 139 | |
| 140 // Test an empty frame. | |
| 141 VideoFrameImpl::CreateEmptyFrame(&frame); | |
| 142 EXPECT_TRUE(frame->IsEndOfStream()); | |
| 143 } | |
| 144 | |
| 145 TEST(VideoFrameImpl, CreateBlackFrame) { | |
| 146 const size_t kWidth = 2; | |
| 147 const size_t kHeight = 2; | |
| 148 const uint8 kExpectedYRow[] = { 0, 0 }; | |
| 149 const uint8 kExpectedUVRow[] = { 128 }; | |
| 150 | |
| 151 scoped_refptr<media::VideoFrame> frame; | |
| 152 VideoFrameImpl::CreateBlackFrame(kWidth, kHeight, &frame); | |
| 153 ASSERT_TRUE(frame); | |
| 154 | |
| 155 // Test basic properties. | |
| 156 EXPECT_EQ(0, frame->GetTimestamp().InMicroseconds()); | |
| 157 EXPECT_EQ(0, frame->GetDuration().InMicroseconds()); | |
| 158 EXPECT_FALSE(frame->IsEndOfStream()); | |
| 159 | |
| 160 // Test surface properties. | |
| 161 VideoSurface surface; | |
| 162 EXPECT_TRUE(frame->Lock(&surface)); | |
| 163 EXPECT_EQ(VideoSurface::YV12, surface.format); | |
| 164 EXPECT_EQ(kWidth, surface.width); | |
| 165 EXPECT_EQ(kHeight, surface.height); | |
| 166 EXPECT_EQ(3u, surface.planes); | |
| 167 | |
| 168 // Test surfaces themselves. | |
| 169 for (size_t y = 0; y < surface.height; ++y) { | |
| 170 EXPECT_EQ(0, memcmp(kExpectedYRow, surface.data[VideoSurface::kYPlane], | |
| 171 arraysize(kExpectedYRow))); | |
| 172 surface.data[VideoSurface::kYPlane] += | |
| 173 surface.strides[VideoSurface::kYPlane]; | |
| 174 } | |
| 175 for (size_t y = 0; y < surface.height / 2; ++y) { | |
| 176 EXPECT_EQ(0, memcmp(kExpectedUVRow, surface.data[VideoSurface::kUPlane], | |
| 177 arraysize(kExpectedUVRow))); | |
| 178 EXPECT_EQ(0, memcmp(kExpectedUVRow, surface.data[VideoSurface::kVPlane], | |
| 179 arraysize(kExpectedUVRow))); | |
| 180 surface.data[VideoSurface::kUPlane] += | |
| 181 surface.strides[VideoSurface::kUPlane]; | |
| 182 surface.data[VideoSurface::kVPlane] += | |
| 183 surface.strides[VideoSurface::kVPlane]; | |
| 184 } | |
| 185 } | |
| 186 | |
| 187 } // namespace media | |
| OLD | NEW |