Upstreaming browser/ui/uikit_ui_util from iOS.
[chromium-blink-merge.git] / content / renderer / media / media_stream_video_capture_source_unittest.cc
blob1a1df9170c6ef219e4f15c27218a0b283fa3f79d
1 // Copyright 2014 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.
5 #include "base/bind.h"
6 #include "base/callback_helpers.h"
7 #include "base/location.h"
8 #include "base/run_loop.h"
9 #include "base/single_thread_task_runner.h"
10 #include "base/strings/utf_string_conversions.h"
11 #include "content/child/child_process.h"
12 #include "content/public/renderer/media_stream_video_sink.h"
13 #include "content/renderer/media/media_stream_video_capturer_source.h"
14 #include "content/renderer/media/media_stream_video_track.h"
15 #include "content/renderer/media/mock_media_constraint_factory.h"
16 #include "media/base/bind_to_current_loop.h"
17 #include "testing/gmock/include/gmock/gmock.h"
18 #include "testing/gtest/include/gtest/gtest.h"
19 #include "third_party/WebKit/public/web/WebHeap.h"
21 namespace content {
23 class MockVideoCapturerDelegate : public VideoCapturerDelegate {
24 public:
25 explicit MockVideoCapturerDelegate(const StreamDeviceInfo& device_info)
26 : VideoCapturerDelegate(device_info) {}
28 MOCK_METHOD4(
29 StartCapture,
30 void(const media::VideoCaptureParams& params,
31 const VideoCaptureDeliverFrameCB& new_frame_callback,
32 scoped_refptr<base::SingleThreadTaskRunner>
33 frame_callback_task_runner,
34 const RunningCallback& running_callback));
35 MOCK_METHOD0(StopCapture, void());
38 class MediaStreamVideoCapturerSourceTest : public testing::Test {
39 public:
40 MediaStreamVideoCapturerSourceTest()
41 : child_process_(new ChildProcess()),
42 source_(NULL),
43 delegate_(NULL),
44 source_stopped_(false) {
47 void TearDown() override {
48 webkit_source_.reset();
49 blink::WebHeap::collectAllGarbageForTesting();
52 void InitWithDeviceInfo(const StreamDeviceInfo& device_info) {
53 scoped_ptr<MockVideoCapturerDelegate> delegate(
54 new MockVideoCapturerDelegate(device_info));
55 delegate_ = delegate.get();
56 source_ = new MediaStreamVideoCapturerSource(
57 base::Bind(&MediaStreamVideoCapturerSourceTest::OnSourceStopped,
58 base::Unretained(this)),
59 delegate.Pass());
60 source_->SetDeviceInfo(device_info);
62 webkit_source_.initialize(base::UTF8ToUTF16("dummy_source_id"),
63 blink::WebMediaStreamSource::TypeVideo,
64 base::UTF8ToUTF16("dummy_source_name"),
65 false /* remote */ , true /* readonly */);
66 webkit_source_.setExtraData(source_);
67 webkit_source_id_ = webkit_source_.id();
70 MockMediaConstraintFactory* constraint_factory() {
71 return &constraint_factory_;
74 blink::WebMediaStreamTrack StartSource() {
75 bool enabled = true;
76 // CreateVideoTrack will trigger OnConstraintsApplied.
77 return MediaStreamVideoTrack::CreateVideoTrack(
78 source_, constraint_factory_.CreateWebMediaConstraints(),
79 base::Bind(
80 &MediaStreamVideoCapturerSourceTest::OnConstraintsApplied,
81 base::Unretained(this)),
82 enabled);
85 MockVideoCapturerDelegate& mock_delegate() {
86 return *delegate_;
89 void OnSourceStopped(const blink::WebMediaStreamSource& source) {
90 source_stopped_ = true;
91 EXPECT_EQ(source.id(), webkit_source_id_);
94 protected:
95 void OnConstraintsApplied(MediaStreamSource* source,
96 MediaStreamRequestResult result,
97 const blink::WebString& result_name) {
100 base::MessageLoopForUI message_loop_;
101 scoped_ptr<ChildProcess> child_process_;
102 blink::WebMediaStreamSource webkit_source_;
103 MediaStreamVideoCapturerSource* source_; // owned by |webkit_source_|.
104 MockVideoCapturerDelegate* delegate_; // owned by |source|.
105 blink::WebString webkit_source_id_;
106 bool source_stopped_;
107 MockMediaConstraintFactory constraint_factory_;
110 TEST_F(MediaStreamVideoCapturerSourceTest, TabCaptureFixedResolutionByDefault) {
111 StreamDeviceInfo device_info;
112 device_info.device.type = MEDIA_TAB_VIDEO_CAPTURE;
113 InitWithDeviceInfo(device_info);
115 // No constraints are being provided to the implementation, so expect only
116 // default values.
117 media::VideoCaptureParams expected_params;
118 expected_params.requested_format.frame_size.SetSize(
119 MediaStreamVideoSource::kDefaultWidth,
120 MediaStreamVideoSource::kDefaultHeight);
121 expected_params.requested_format.frame_rate =
122 MediaStreamVideoSource::kDefaultFrameRate;
123 expected_params.requested_format.pixel_format =
124 media::VIDEO_CAPTURE_PIXEL_FORMAT_I420;
125 expected_params.resolution_change_policy =
126 media::RESOLUTION_POLICY_FIXED_RESOLUTION;
128 EXPECT_CALL(mock_delegate(), StartCapture(
129 expected_params,
130 testing::_,
131 testing::_,
132 testing::_)).Times(1);
133 blink::WebMediaStreamTrack track = StartSource();
134 // When the track goes out of scope, the source will be stopped.
135 EXPECT_CALL(mock_delegate(), StopCapture());
138 TEST_F(MediaStreamVideoCapturerSourceTest,
139 DesktopCaptureAllowAnyResolutionChangeByDefault) {
140 StreamDeviceInfo device_info;
141 device_info.device.type = MEDIA_DESKTOP_VIDEO_CAPTURE;
142 InitWithDeviceInfo(device_info);
144 // No constraints are being provided to the implementation, so expect only
145 // default values.
146 media::VideoCaptureParams expected_params;
147 expected_params.requested_format.frame_size.SetSize(
148 MediaStreamVideoSource::kDefaultWidth,
149 MediaStreamVideoSource::kDefaultHeight);
150 expected_params.requested_format.frame_rate =
151 MediaStreamVideoSource::kDefaultFrameRate;
152 expected_params.requested_format.pixel_format =
153 media::VIDEO_CAPTURE_PIXEL_FORMAT_I420;
154 expected_params.resolution_change_policy =
155 media::RESOLUTION_POLICY_ANY_WITHIN_LIMIT;
157 EXPECT_CALL(mock_delegate(), StartCapture(
158 expected_params,
159 testing::_,
160 testing::_,
161 testing::_)).Times(1);
162 blink::WebMediaStreamTrack track = StartSource();
163 // When the track goes out of scope, the source will be stopped.
164 EXPECT_CALL(mock_delegate(), StopCapture());
167 TEST_F(MediaStreamVideoCapturerSourceTest,
168 TabCaptureConstraintsImplyFixedAspectRatio) {
169 StreamDeviceInfo device_info;
170 device_info.device.type = MEDIA_TAB_VIDEO_CAPTURE;
171 InitWithDeviceInfo(device_info);
173 // Specify max and min size constraints that have the same ~16:9 aspect ratio.
174 constraint_factory()->AddMandatory(MediaStreamVideoSource::kMaxWidth, 1920);
175 constraint_factory()->AddMandatory(MediaStreamVideoSource::kMaxHeight, 1080);
176 constraint_factory()->AddMandatory(MediaStreamVideoSource::kMinWidth, 854);
177 constraint_factory()->AddMandatory(MediaStreamVideoSource::kMinHeight, 480);
178 constraint_factory()->AddMandatory(MediaStreamVideoSource::kMaxFrameRate,
179 60.0);
181 media::VideoCaptureParams expected_params;
182 expected_params.requested_format.frame_size.SetSize(1920, 1080);
183 expected_params.requested_format.frame_rate = 60.0;
184 expected_params.requested_format.pixel_format =
185 media::VIDEO_CAPTURE_PIXEL_FORMAT_I420;
186 expected_params.resolution_change_policy =
187 media::RESOLUTION_POLICY_FIXED_ASPECT_RATIO;
189 EXPECT_CALL(mock_delegate(), StartCapture(
190 testing::Field(&media::VideoCaptureParams::resolution_change_policy,
191 media::RESOLUTION_POLICY_FIXED_ASPECT_RATIO),
192 testing::_,
193 testing::_,
194 testing::_)).Times(1);
195 blink::WebMediaStreamTrack track = StartSource();
196 // When the track goes out of scope, the source will be stopped.
197 EXPECT_CALL(mock_delegate(), StopCapture());
200 TEST_F(MediaStreamVideoCapturerSourceTest,
201 TabCaptureConstraintsImplyAllowingAnyResolutionChange) {
202 StreamDeviceInfo device_info;
203 device_info.device.type = MEDIA_TAB_VIDEO_CAPTURE;
204 InitWithDeviceInfo(device_info);
206 // Specify max and min size constraints with different aspect ratios.
207 constraint_factory()->AddMandatory(MediaStreamVideoSource::kMaxWidth, 1920);
208 constraint_factory()->AddMandatory(MediaStreamVideoSource::kMaxHeight, 1080);
209 constraint_factory()->AddMandatory(MediaStreamVideoSource::kMinWidth, 0);
210 constraint_factory()->AddMandatory(MediaStreamVideoSource::kMinHeight, 0);
211 constraint_factory()->AddMandatory(MediaStreamVideoSource::kMaxFrameRate,
212 60.0);
214 media::VideoCaptureParams expected_params;
215 expected_params.requested_format.frame_size.SetSize(1920, 1080);
216 expected_params.requested_format.frame_rate = 60.0;
217 expected_params.requested_format.pixel_format =
218 media::VIDEO_CAPTURE_PIXEL_FORMAT_I420;
219 expected_params.resolution_change_policy =
220 media::RESOLUTION_POLICY_ANY_WITHIN_LIMIT;
222 EXPECT_CALL(mock_delegate(), StartCapture(
223 expected_params,
224 testing::_,
225 testing::_,
226 testing::_)).Times(1);
227 blink::WebMediaStreamTrack track = StartSource();
228 // When the track goes out of scope, the source will be stopped.
229 EXPECT_CALL(mock_delegate(), StopCapture());
232 TEST_F(MediaStreamVideoCapturerSourceTest, Ended) {
233 StreamDeviceInfo device_info;
234 device_info.device.type = MEDIA_DESKTOP_VIDEO_CAPTURE;
235 scoped_ptr<VideoCapturerDelegate> delegate(
236 new VideoCapturerDelegate(device_info));
237 VideoCapturerDelegate* delegate_ptr = delegate.get();
238 source_ = new MediaStreamVideoCapturerSource(
239 base::Bind(&MediaStreamVideoCapturerSourceTest::OnSourceStopped,
240 base::Unretained(this)),
241 delegate.Pass());
242 source_->SetDeviceInfo(device_info);
243 webkit_source_.initialize(base::UTF8ToUTF16("dummy_source_id"),
244 blink::WebMediaStreamSource::TypeVideo,
245 base::UTF8ToUTF16("dummy_source_name"),
246 false /* remote */ , true /* readonly */);
247 webkit_source_.setExtraData(source_);
248 webkit_source_id_ = webkit_source_.id();
249 blink::WebMediaStreamTrack track = StartSource();
250 message_loop_.RunUntilIdle();
252 delegate_ptr->OnStateUpdate(VIDEO_CAPTURE_STATE_STARTED);
253 message_loop_.RunUntilIdle();
254 EXPECT_EQ(blink::WebMediaStreamSource::ReadyStateLive,
255 webkit_source_.readyState());
257 EXPECT_FALSE(source_stopped_);
258 delegate_ptr->OnStateUpdate(VIDEO_CAPTURE_STATE_ERROR);
259 message_loop_.RunUntilIdle();
260 EXPECT_EQ(blink::WebMediaStreamSource::ReadyStateEnded,
261 webkit_source_.readyState());
262 // Verify that MediaStreamSource::SourceStoppedCallback has been triggered.
263 EXPECT_TRUE(source_stopped_);
266 class FakeMediaStreamVideoSink : public MediaStreamVideoSink {
267 public:
268 FakeMediaStreamVideoSink(base::TimeTicks* capture_time,
269 media::VideoFrameMetadata* metadata,
270 base::Closure got_frame_cb)
271 : capture_time_(capture_time),
272 metadata_(metadata),
273 got_frame_cb_(got_frame_cb) {
276 void OnVideoFrame(const scoped_refptr<media::VideoFrame>& frame,
277 const base::TimeTicks& capture_time) {
278 *capture_time_ = capture_time;
279 metadata_->Clear();
280 base::DictionaryValue tmp;
281 frame->metadata()->MergeInternalValuesInto(&tmp);
282 metadata_->MergeInternalValuesFrom(tmp);
283 base::ResetAndReturn(&got_frame_cb_).Run();
286 private:
287 base::TimeTicks* const capture_time_;
288 media::VideoFrameMetadata* const metadata_;
289 base::Closure got_frame_cb_;
292 TEST_F(MediaStreamVideoCapturerSourceTest, CaptureTimeAndMetadataPlumbing) {
293 StreamDeviceInfo device_info;
294 device_info.device.type = MEDIA_DESKTOP_VIDEO_CAPTURE;
295 InitWithDeviceInfo(device_info);
297 VideoCaptureDeliverFrameCB deliver_frame_cb;
298 VideoCapturerDelegate::RunningCallback running_cb;
300 EXPECT_CALL(mock_delegate(), StartCapture(
301 testing::_,
302 testing::_,
303 testing::_,
304 testing::_))
305 .Times(1)
306 .WillOnce(testing::DoAll(testing::SaveArg<1>(&deliver_frame_cb),
307 testing::SaveArg<3>(&running_cb)));
308 EXPECT_CALL(mock_delegate(), StopCapture());
309 blink::WebMediaStreamTrack track = StartSource();
310 running_cb.Run(true);
312 base::RunLoop run_loop;
313 base::TimeTicks reference_capture_time =
314 base::TimeTicks::FromInternalValue(60013);
315 base::TimeTicks capture_time;
316 media::VideoFrameMetadata metadata;
317 FakeMediaStreamVideoSink fake_sink(
318 &capture_time,
319 &metadata,
320 media::BindToCurrentLoop(run_loop.QuitClosure()));
321 FakeMediaStreamVideoSink::AddToVideoTrack(
322 &fake_sink,
323 base::Bind(&FakeMediaStreamVideoSink::OnVideoFrame,
324 base::Unretained(&fake_sink)),
325 track);
326 const scoped_refptr<media::VideoFrame> frame =
327 media::VideoFrame::CreateBlackFrame(gfx::Size(2, 2));
328 frame->metadata()->SetDouble(media::VideoFrameMetadata::FRAME_RATE, 30.0);
329 child_process_->io_task_runner()->PostTask(
330 FROM_HERE, base::Bind(deliver_frame_cb, frame, reference_capture_time));
331 run_loop.Run();
332 FakeMediaStreamVideoSink::RemoveFromVideoTrack(&fake_sink, track);
333 EXPECT_EQ(reference_capture_time, capture_time);
334 double metadata_value;
335 EXPECT_TRUE(metadata.GetDouble(media::VideoFrameMetadata::FRAME_RATE,
336 &metadata_value));
337 EXPECT_EQ(30.0, metadata_value);
340 } // namespace content