Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1)

Side by Side Diff: content/renderer/media/video_track_recorder_unittest.cc

Issue 2147753002: VideoTrackRecorder: add support for texture backed ARGB VideoFrames (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 4 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698