Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "content/renderer/media/video_track_recorder.h" | 5 #include "content/renderer/media/video_track_recorder.h" |
| 6 | 6 |
| 7 #include <stddef.h> | 7 #include <stddef.h> |
| 8 | 8 |
| 9 #include <memory> | 9 #include <memory> |
| 10 | 10 |
| (...skipping 22 matching lines...) Expand all Loading... | |
| 33 using ::testing::SaveArg; | 33 using ::testing::SaveArg; |
| 34 using ::testing::TestWithParam; | 34 using ::testing::TestWithParam; |
| 35 using ::testing::ValuesIn; | 35 using ::testing::ValuesIn; |
| 36 | 36 |
| 37 namespace content { | 37 namespace content { |
| 38 | 38 |
| 39 ACTION_P(RunClosure, closure) { | 39 ACTION_P(RunClosure, closure) { |
| 40 closure.Run(); | 40 closure.Run(); |
| 41 } | 41 } |
| 42 | 42 |
| 43 // VideoFrame holding ARGB memory-backed pixels (VideoFrame has no public API | |
| 44 // surface for creating this type of frames nor their storage). | |
| 45 class ARGBVideoFrame : public media::VideoFrame { | |
| 46 public: | |
| 47 ARGBVideoFrame(const gfx::Size& size) | |
| 48 : VideoFrame(media::PIXEL_FORMAT_ARGB, | |
| 49 STORAGE_OWNED_MEMORY, | |
| 50 size, | |
| 51 gfx::Rect(size), | |
| 52 size, | |
| 53 base::TimeDelta()), | |
| 54 buffer_(size.GetArea()) { | |
| 55 set_data(kARGBPlane, buffer_.data()); | |
| 56 set_stride(kARGBPlane, size.GetArea()); | |
| 57 } | |
| 58 | |
| 59 private: | |
| 60 ~ARGBVideoFrame() final {} | |
| 61 | |
| 62 std::vector<uint8_t> buffer_; | |
| 63 DISALLOW_COPY_AND_ASSIGN(ARGBVideoFrame); | |
| 64 }; | |
| 65 | |
| 43 const VideoTrackRecorder::CodecId kTrackRecorderTestCodec[] = { | 66 const VideoTrackRecorder::CodecId kTrackRecorderTestCodec[] = { |
| 44 VideoTrackRecorder::CodecId::VP8, | 67 VideoTrackRecorder::CodecId::VP8, |
| 45 VideoTrackRecorder::CodecId::VP9 | 68 VideoTrackRecorder::CodecId::VP9 |
| 46 #if BUILDFLAG(RTC_USE_H264) | 69 #if BUILDFLAG(RTC_USE_H264) |
| 47 , VideoTrackRecorder::CodecId::H264 | 70 , VideoTrackRecorder::CodecId::H264 |
| 48 #endif | 71 #endif |
| 49 }; | 72 }; |
| 50 | 73 |
| 74 // Typical frame size; cannot be arbitrarily small, should be reasonable. | |
| 75 static const gfx::Size kFrameSize(80,40); | |
| 76 | |
| 77 static void DummyReleaseMailboxCB(const gpu::SyncToken& sync_token) {} | |
| 78 | |
| 51 class VideoTrackRecorderTest | 79 class VideoTrackRecorderTest |
| 52 : public TestWithParam<VideoTrackRecorder::CodecId> { | 80 : public TestWithParam<VideoTrackRecorder::CodecId> { |
| 53 public: | 81 public: |
| 54 VideoTrackRecorderTest() | 82 VideoTrackRecorderTest() |
| 55 : mock_source_(new MockMediaStreamVideoSource(false)) { | 83 : mock_source_(new MockMediaStreamVideoSource(false)) { |
| 56 const blink::WebString webkit_track_id(base::UTF8ToUTF16("dummy")); | 84 const blink::WebString webkit_track_id(base::UTF8ToUTF16("dummy")); |
| 57 blink_source_.initialize(webkit_track_id, | 85 blink_source_.initialize(webkit_track_id, |
| 58 blink::WebMediaStreamSource::TypeVideo, | 86 blink::WebMediaStreamSource::TypeVideo, |
| 59 webkit_track_id); | 87 webkit_track_id); |
| 60 blink_source_.setExtraData(mock_source_); | 88 blink_source_.setExtraData(mock_source_); |
| (...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 121 DISALLOW_COPY_AND_ASSIGN(VideoTrackRecorderTest); | 149 DISALLOW_COPY_AND_ASSIGN(VideoTrackRecorderTest); |
| 122 }; | 150 }; |
| 123 | 151 |
| 124 // Construct and destruct all objects, in particular |video_track_recorder_| and | 152 // Construct and destruct all objects, in particular |video_track_recorder_| and |
| 125 // its inner object(s). This is a non trivial sequence. | 153 // its inner object(s). This is a non trivial sequence. |
| 126 TEST_P(VideoTrackRecorderTest, ConstructAndDestruct) {} | 154 TEST_P(VideoTrackRecorderTest, ConstructAndDestruct) {} |
| 127 | 155 |
| 128 // Creates the encoder and encodes 2 frames of the same size; the encoder should | 156 // Creates the encoder and encodes 2 frames of the same size; the encoder should |
| 129 // be initialised and produce a keyframe, then a non-keyframe. Finally a frame | 157 // be initialised and produce a keyframe, then a non-keyframe. Finally a frame |
| 130 // of larger size is sent and is expected to be encoded as a keyframe. | 158 // of larger size is sent and is expected to be encoded as a keyframe. |
| 131 TEST_P(VideoTrackRecorderTest, VideoEncoding) { | 159 TEST_P(VideoTrackRecorderTest, Encoding) { |
| 132 // |frame_size| cannot be arbitrarily small, should be reasonable. | |
| 133 const gfx::Size frame_size(160, 80); | |
| 134 const scoped_refptr<VideoFrame> video_frame = | 160 const scoped_refptr<VideoFrame> video_frame = |
| 135 VideoFrame::CreateBlackFrame(frame_size); | 161 VideoFrame::CreateBlackFrame(kFrameSize); |
| 136 const double kFrameRate = 60.0f; | 162 const double kFrameRate = 60.0f; |
| 137 video_frame->metadata()->SetDouble(media::VideoFrameMetadata::FRAME_RATE, | 163 video_frame->metadata()->SetDouble(media::VideoFrameMetadata::FRAME_RATE, |
| 138 kFrameRate); | 164 kFrameRate); |
| 139 | 165 |
| 140 InSequence s; | 166 InSequence s; |
| 141 const base::TimeTicks timeticks_now = base::TimeTicks::Now(); | 167 const base::TimeTicks timeticks_now = base::TimeTicks::Now(); |
| 142 base::StringPiece first_frame_encoded_data; | 168 base::StringPiece first_frame_encoded_data; |
| 143 EXPECT_CALL(*this, DoOnEncodedVideo(video_frame, _, timeticks_now, true)) | 169 EXPECT_CALL(*this, DoOnEncodedVideo(video_frame, _, timeticks_now, true)) |
| 144 .Times(1) | 170 .Times(1) |
| 145 .WillOnce(SaveArg<1>(&first_frame_encoded_data)); | 171 .WillOnce(SaveArg<1>(&first_frame_encoded_data)); |
| (...skipping 25 matching lines...) Expand all Loading... | |
| 171 run_loop.Run(); | 197 run_loop.Run(); |
| 172 | 198 |
| 173 const size_t kEncodedSizeThreshold = 14; | 199 const size_t kEncodedSizeThreshold = 14; |
| 174 EXPECT_GE(first_frame_encoded_data.size(), kEncodedSizeThreshold); | 200 EXPECT_GE(first_frame_encoded_data.size(), kEncodedSizeThreshold); |
| 175 EXPECT_GE(second_frame_encoded_data.size(), kEncodedSizeThreshold); | 201 EXPECT_GE(second_frame_encoded_data.size(), kEncodedSizeThreshold); |
| 176 EXPECT_GE(third_frame_encoded_data.size(), kEncodedSizeThreshold); | 202 EXPECT_GE(third_frame_encoded_data.size(), kEncodedSizeThreshold); |
| 177 | 203 |
| 178 Mock::VerifyAndClearExpectations(this); | 204 Mock::VerifyAndClearExpectations(this); |
| 179 } | 205 } |
| 180 | 206 |
| 207 // Verifies that a Mappable ARGB Video Frame can be correctly encoded. | |
| 208 TEST_P(VideoTrackRecorderTest, EncodingARGBFrame) { | |
| 209 const scoped_refptr<VideoFrame> video_frame(new ARGBVideoFrame(kFrameSize)); | |
| 210 | |
| 211 InSequence s; | |
| 212 base::RunLoop run_loop; | |
| 213 base::Closure quit_closure = run_loop.QuitClosure(); | |
| 214 scoped_refptr<VideoFrame> encoded_frame; | |
| 215 base::StringPiece encoded_data; | |
| 216 EXPECT_CALL(*this, DoOnEncodedVideo(_, _, _, true)) | |
| 217 .Times(1) | |
| 218 .WillOnce(DoAll(SaveArg<0>(&encoded_frame), | |
| 219 SaveArg<1>(&encoded_data), | |
| 220 RunClosure(quit_closure))); | |
| 221 Encode(video_frame, base::TimeTicks::Now()); | |
| 222 run_loop.Run(); | |
| 223 | |
| 224 EXPECT_EQ(media::PIXEL_FORMAT_I420, encoded_frame->format()); | |
| 225 EXPECT_EQ(video_frame->coded_size(), encoded_frame->coded_size()); | |
| 226 | |
| 227 const size_t kEncodedSizeThreshold = 14; | |
| 228 EXPECT_GE(encoded_data.size(), kEncodedSizeThreshold); | |
| 229 | |
| 230 Mock::VerifyAndClearExpectations(this); | |
| 231 } | |
| 232 | |
| 233 // Tests that a not IsMappable() frame is encoded as a full black one. | |
| 234 TEST_P(VideoTrackRecorderTest, EncodingNonMappableFrame) { | |
| 235 gpu::MailboxHolder mailbox_holders[media::VideoFrame::kMaxPlanes] = {}; | |
| 236 const scoped_refptr<VideoFrame> video_frame = VideoFrame::WrapNativeTextures( | |
| 237 media::PIXEL_FORMAT_ARGB, mailbox_holders, | |
| 238 base::Bind(&DummyReleaseMailboxCB), kFrameSize, gfx::Rect(kFrameSize), | |
| 239 kFrameSize, base::TimeDelta()); | |
| 240 ASSERT_FALSE(video_frame->IsMappable()); | |
| 241 | |
| 242 InSequence s; | |
| 243 base::RunLoop run_loop; | |
| 244 base::Closure quit_closure = run_loop.QuitClosure(); | |
| 245 scoped_refptr<VideoFrame> encoded_frame; | |
| 246 EXPECT_CALL(*this, DoOnEncodedVideo(_, _, _, true)) | |
| 247 .Times(1) | |
| 248 .WillOnce(DoAll(SaveArg<0>(&encoded_frame), RunClosure(quit_closure))); | |
| 249 Encode(video_frame, base::TimeTicks::Now()); | |
| 250 run_loop.Run(); | |
| 251 | |
| 252 // |encoded_frame| should be full-black, since |video_frame| is not mappable. | |
| 253 ASSERT_EQ(media::PIXEL_FORMAT_YV12, encoded_frame->format()); | |
| 254 EXPECT_EQ(video_frame->coded_size(), encoded_frame->coded_size()); | |
| 255 const uint8_t* y_plane = encoded_frame->data(media::VideoFrame::kYPlane); | |
|
emircan
2016/07/12 22:57:00
Can we have this in a for loop?
mcasas
2016/07/13 00:45:31
Do you mean:
for (int i = 0; i < y_plane_size; ++
| |
| 256 const int y_plane_size = encoded_frame->row_bytes(media::VideoFrame::kYPlane); | |
| 257 for (int i = 0; i < y_plane_size; ++i) | |
| 258 EXPECT_EQ(0u, y_plane[i]); | |
| 259 const uint8_t* u_plane = encoded_frame->data(media::VideoFrame::kUPlane); | |
| 260 const int u_plane_size = encoded_frame->row_bytes(media::VideoFrame::kUPlane); | |
| 261 for (int i = 0; i < u_plane_size; ++i) | |
| 262 EXPECT_EQ(0x80, u_plane[i]); | |
| 263 const uint8_t* v_plane = encoded_frame->data(media::VideoFrame::kVPlane); | |
| 264 const int v_plane_size = encoded_frame->row_bytes(media::VideoFrame::kVPlane); | |
| 265 for (int i = 0; i < v_plane_size; ++i) | |
| 266 EXPECT_EQ(0x80, v_plane[i]); | |
| 267 | |
| 268 Mock::VerifyAndClearExpectations(this); | |
| 269 } | |
| 270 | |
| 181 INSTANTIATE_TEST_CASE_P(, | 271 INSTANTIATE_TEST_CASE_P(, |
| 182 VideoTrackRecorderTest, | 272 VideoTrackRecorderTest, |
| 183 ValuesIn(kTrackRecorderTestCodec)); | 273 ValuesIn(kTrackRecorderTestCodec)); |
| 184 | 274 |
| 185 } // namespace content | 275 } // namespace content |
| OLD | NEW |