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

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

Issue 2684233005: Revert of Use spec-compliant algorithm to select video devices in getUserMedia. (Closed)
Patch Set: Created 3 years, 10 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 (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 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/user_media_client_impl.h" 5 #include "content/renderer/media/user_media_client_impl.h"
6 6
7 #include <stddef.h> 7 #include <stddef.h>
8 8
9 #include <algorithm> 9 #include <algorithm>
10 #include <utility> 10 #include <utility>
11 11
12 #include "base/hash.h" 12 #include "base/hash.h"
13 #include "base/location.h" 13 #include "base/location.h"
14 #include "base/logging.h" 14 #include "base/logging.h"
15 #include "base/memory/ptr_util.h" 15 #include "base/memory/ptr_util.h"
16 #include "base/single_thread_task_runner.h" 16 #include "base/single_thread_task_runner.h"
17 #include "base/strings/string_number_conversions.h" 17 #include "base/strings/string_number_conversions.h"
18 #include "base/strings/string_util.h" 18 #include "base/strings/string_util.h"
19 #include "base/strings/stringprintf.h" 19 #include "base/strings/stringprintf.h"
20 #include "base/strings/utf_string_conversions.h" 20 #include "base/strings/utf_string_conversions.h"
21 #include "base/task_runner.h"
22 #include "base/task_runner_util.h"
23 #include "base/threading/thread_task_runner_handle.h" 21 #include "base/threading/thread_task_runner_handle.h"
24 #include "build/build_config.h" 22 #include "build/build_config.h"
25 #include "content/public/renderer/render_frame.h" 23 #include "content/public/renderer/render_frame.h"
26 #include "content/renderer/media/local_media_stream_audio_source.h" 24 #include "content/renderer/media/local_media_stream_audio_source.h"
27 #include "content/renderer/media/media_stream.h" 25 #include "content/renderer/media/media_stream.h"
28 #include "content/renderer/media/media_stream_constraints_util.h" 26 #include "content/renderer/media/media_stream_constraints_util.h"
29 #include "content/renderer/media/media_stream_constraints_util_video_source.h"
30 #include "content/renderer/media/media_stream_dispatcher.h" 27 #include "content/renderer/media/media_stream_dispatcher.h"
31 #include "content/renderer/media/media_stream_video_capturer_source.h" 28 #include "content/renderer/media/media_stream_video_capturer_source.h"
32 #include "content/renderer/media/media_stream_video_track.h" 29 #include "content/renderer/media/media_stream_video_track.h"
33 #include "content/renderer/media/peer_connection_tracker.h" 30 #include "content/renderer/media/peer_connection_tracker.h"
34 #include "content/renderer/media/webrtc/processed_local_audio_source.h" 31 #include "content/renderer/media/webrtc/processed_local_audio_source.h"
35 #include "content/renderer/media/webrtc/webrtc_video_capturer_adapter.h" 32 #include "content/renderer/media/webrtc/webrtc_video_capturer_adapter.h"
36 #include "content/renderer/media/webrtc_logging.h" 33 #include "content/renderer/media/webrtc_logging.h"
37 #include "content/renderer/media/webrtc_uma_histograms.h" 34 #include "content/renderer/media/webrtc_uma_histograms.h"
38 #include "content/renderer/render_thread_impl.h" 35 #include "content/renderer/render_thread_impl.h"
39 #include "media/capture/video_capture_types.h"
40 #include "third_party/WebKit/public/platform/URLConversion.h" 36 #include "third_party/WebKit/public/platform/URLConversion.h"
41 #include "third_party/WebKit/public/platform/WebMediaConstraints.h" 37 #include "third_party/WebKit/public/platform/WebMediaConstraints.h"
42 #include "third_party/WebKit/public/platform/WebMediaDeviceInfo.h" 38 #include "third_party/WebKit/public/platform/WebMediaDeviceInfo.h"
43 #include "third_party/WebKit/public/platform/WebMediaStreamTrack.h" 39 #include "third_party/WebKit/public/platform/WebMediaStreamTrack.h"
44 #include "third_party/WebKit/public/platform/WebString.h" 40 #include "third_party/WebKit/public/platform/WebString.h"
45 #include "third_party/WebKit/public/web/WebDocument.h" 41 #include "third_party/WebKit/public/web/WebDocument.h"
46 #include "third_party/WebKit/public/web/WebLocalFrame.h" 42 #include "third_party/WebKit/public/web/WebLocalFrame.h"
47 #include "third_party/WebKit/public/web/WebUserGestureIndicator.h"
48 43
49 namespace content { 44 namespace content {
50 namespace { 45 namespace {
51 46
52 void CopyFirstString(const blink::StringConstraint& constraint, 47 void CopyFirstString(const blink::StringConstraint& constraint,
53 std::string* destination) { 48 std::string* destination) {
54 if (!constraint.exact().isEmpty()) 49 if (!constraint.exact().isEmpty())
55 *destination = constraint.exact()[0].utf8(); 50 *destination = constraint.exact()[0].utf8();
56 } 51 }
57 52
(...skipping 154 matching lines...) Expand 10 before | Expand all | Expand 10 after
212 default: 207 default:
213 NOTREACHED(); 208 NOTREACHED();
214 return blink::WebMediaDeviceInfo::MediaDeviceKindAudioInput; 209 return blink::WebMediaDeviceInfo::MediaDeviceKindAudioInput;
215 } 210 }
216 } 211 }
217 212
218 static int g_next_request_id = 0; 213 static int g_next_request_id = 0;
219 214
220 } // namespace 215 } // namespace
221 216
222 struct UserMediaClientImpl::RequestSettings {
223 RequestSettings(bool is_processing_user_gesture, url::Origin security_origin)
224 : enable_automatic_audio_output_device_selection(false),
225 is_processing_user_gesture(is_processing_user_gesture),
226 security_origin(security_origin) {}
227 ~RequestSettings() = default;
228
229 bool enable_automatic_audio_output_device_selection;
230 bool is_processing_user_gesture;
231 url::Origin security_origin;
232 };
233
234 UserMediaClientImpl::UserMediaClientImpl( 217 UserMediaClientImpl::UserMediaClientImpl(
235 RenderFrame* render_frame, 218 RenderFrame* render_frame,
236 PeerConnectionDependencyFactory* dependency_factory, 219 PeerConnectionDependencyFactory* dependency_factory,
237 std::unique_ptr<MediaStreamDispatcher> media_stream_dispatcher, 220 std::unique_ptr<MediaStreamDispatcher> media_stream_dispatcher)
238 const scoped_refptr<base::TaskRunner>& worker_task_runner)
239 : RenderFrameObserver(render_frame), 221 : RenderFrameObserver(render_frame),
240 dependency_factory_(dependency_factory), 222 dependency_factory_(dependency_factory),
241 media_stream_dispatcher_(std::move(media_stream_dispatcher)), 223 media_stream_dispatcher_(std::move(media_stream_dispatcher)),
242 worker_task_runner_(worker_task_runner),
243 weak_factory_(this) { 224 weak_factory_(this) {
244 DCHECK(dependency_factory_); 225 DCHECK(dependency_factory_);
245 DCHECK(media_stream_dispatcher_.get()); 226 DCHECK(media_stream_dispatcher_.get());
246 } 227 }
247 228
248 UserMediaClientImpl::~UserMediaClientImpl() { 229 UserMediaClientImpl::~UserMediaClientImpl() {
249 // Force-close all outstanding user media requests and local sources here, 230 // Force-close all outstanding user media requests and local sources here,
250 // before the outstanding WeakPtrs are invalidated, to ensure a clean 231 // before the outstanding WeakPtrs are invalidated, to ensure a clean
251 // shutdown. 232 // shutdown.
252 WillCommitProvisionalLoad(); 233 WillCommitProvisionalLoad();
(...skipping 15 matching lines...) Expand all
268 user_media_request.ownerDocument().frame())); 249 user_media_request.ownerDocument().frame()));
269 250
270 if (RenderThreadImpl::current()) { 251 if (RenderThreadImpl::current()) {
271 RenderThreadImpl::current()->peer_connection_tracker()->TrackGetUserMedia( 252 RenderThreadImpl::current()->peer_connection_tracker()->TrackGetUserMedia(
272 user_media_request); 253 user_media_request);
273 } 254 }
274 255
275 int request_id = g_next_request_id++; 256 int request_id = g_next_request_id++;
276 std::unique_ptr<StreamControls> controls = base::MakeUnique<StreamControls>(); 257 std::unique_ptr<StreamControls> controls = base::MakeUnique<StreamControls>();
277 258
278 // The value returned by isProcessingUserGesture() is used by the browser to 259 bool enable_automatic_output_device_selection = false;
279 // make decisions about the permissions UI. Its value can be lost while 260 bool request_audio_input_devices = false;
280 // switching threads, so saving its value here.
281 RequestSettings request_settings(
282 blink::WebUserGestureIndicator::isProcessingUserGesture(),
283 static_cast<url::Origin>(user_media_request.getSecurityOrigin()));
284 if (user_media_request.audio()) { 261 if (user_media_request.audio()) {
285 bool request_audio_input_devices = false;
286 // TODO(guidou): Implement spec-compliant device selection for audio. See
287 // http://crbug.com/623104.
288 CopyConstraintsToTrackControls(user_media_request.audioConstraints(), 262 CopyConstraintsToTrackControls(user_media_request.audioConstraints(),
289 &controls->audio, 263 &controls->audio,
290 &request_audio_input_devices); 264 &request_audio_input_devices);
291 CopyHotwordAndLocalEchoToStreamControls( 265 CopyHotwordAndLocalEchoToStreamControls(
292 user_media_request.audioConstraints(), controls.get()); 266 user_media_request.audioConstraints(), controls.get());
293 // Check if this input device should be used to select a matching output 267 // Check if this input device should be used to select a matching output
294 // device for audio rendering. 268 // device for audio rendering.
295 GetConstraintValueAsBoolean( 269 GetConstraintValueAsBoolean(
296 user_media_request.audioConstraints(), 270 user_media_request.audioConstraints(),
297 &blink::WebMediaTrackConstraintSet::renderToAssociatedSink, 271 &blink::WebMediaTrackConstraintSet::renderToAssociatedSink,
298 &request_settings.enable_automatic_audio_output_device_selection); 272 &enable_automatic_output_device_selection);
273 }
274 bool request_video_input_devices = false;
275 if (user_media_request.video()) {
276 CopyConstraintsToTrackControls(user_media_request.videoConstraints(),
277 &controls->video,
278 &request_video_input_devices);
279 }
299 280
300 if (request_audio_input_devices) { 281 url::Origin security_origin = user_media_request.getSecurityOrigin();
301 GetMediaDevicesDispatcher()->EnumerateDevices( 282 if (request_audio_input_devices || request_video_input_devices) {
302 true /* audio_input */, false /* video_input */, 283 GetMediaDevicesDispatcher()->EnumerateDevices(
303 false /* audio_output */, request_settings.security_origin, 284 request_audio_input_devices, request_video_input_devices,
304 base::Bind(&UserMediaClientImpl::SelectAudioInputDevice, 285 false /* request_audio_output_devices */, security_origin,
305 weak_factory_.GetWeakPtr(), request_id, user_media_request, 286 base::Bind(&UserMediaClientImpl::SelectUserMediaDevice,
306 base::Passed(&controls), request_settings)); 287 weak_factory_.GetWeakPtr(), request_id, user_media_request,
288 base::Passed(&controls),
289 enable_automatic_output_device_selection, security_origin));
290 } else {
291 FinalizeRequestUserMedia(
292 request_id, user_media_request, std::move(controls),
293 enable_automatic_output_device_selection, security_origin);
294 }
295 }
296
297 void UserMediaClientImpl::SelectUserMediaDevice(
298 int request_id,
299 const blink::WebUserMediaRequest& user_media_request,
300 std::unique_ptr<StreamControls> controls,
301 bool enable_automatic_output_device_selection,
302 const url::Origin& security_origin,
303 const EnumerationResult& device_enumeration) {
304 DCHECK(CalledOnValidThread());
305
306 if (controls->audio.requested &&
307 IsDeviceSource(controls->audio.stream_source)) {
308 if (!PickDeviceId(user_media_request.audioConstraints(),
309 device_enumeration[MEDIA_DEVICE_TYPE_AUDIO_INPUT],
310 &controls->audio.device_id)) {
311 GetUserMediaRequestFailed(user_media_request, MEDIA_DEVICE_NO_HARDWARE,
312 "");
307 return; 313 return;
308 } 314 }
309 } 315 }
310 316
311 SetupVideoInput(request_id, user_media_request, std::move(controls), 317 if (controls->video.requested &&
312 request_settings); 318 IsDeviceSource(controls->video.stream_source)) {
313 } 319 if (!PickDeviceId(user_media_request.videoConstraints(),
314 320 device_enumeration[MEDIA_DEVICE_TYPE_VIDEO_INPUT],
315 void UserMediaClientImpl::SelectAudioInputDevice( 321 &controls->video.device_id)) {
316 int request_id, 322 GetUserMediaRequestFailed(user_media_request, MEDIA_DEVICE_NO_HARDWARE,
317 const blink::WebUserMediaRequest& user_media_request, 323 "");
318 std::unique_ptr<StreamControls> controls,
319 const RequestSettings& request_settings,
320 const EnumerationResult& device_enumeration) {
321 DCHECK(CalledOnValidThread());
322 DCHECK(controls->audio.requested);
323 DCHECK(IsDeviceSource(controls->audio.stream_source));
324
325 if (!PickDeviceId(user_media_request.audioConstraints(),
326 device_enumeration[MEDIA_DEVICE_TYPE_AUDIO_INPUT],
327 &controls->audio.device_id)) {
328 GetUserMediaRequestFailed(user_media_request, MEDIA_DEVICE_NO_HARDWARE, "");
329 return;
330 }
331
332 SetupVideoInput(request_id, user_media_request, std::move(controls),
333 request_settings);
334 }
335
336 void UserMediaClientImpl::SetupVideoInput(
337 int request_id,
338 const blink::WebUserMediaRequest& user_media_request,
339 std::unique_ptr<StreamControls> controls,
340 const RequestSettings& request_settings) {
341 if (user_media_request.video()) {
342 bool ignore;
343 CopyConstraintsToTrackControls(user_media_request.videoConstraints(),
344 &controls->video, &ignore);
345 if (IsDeviceSource(controls->video.stream_source)) {
346 GetMediaDevicesDispatcher()->GetVideoInputCapabilities(
347 request_settings.security_origin,
348 base::Bind(&UserMediaClientImpl::SelectVideoDeviceSourceSettings,
349 weak_factory_.GetWeakPtr(), request_id, user_media_request,
350 base::Passed(&controls), request_settings));
351 return; 324 return;
352 } 325 }
353 } 326 }
327
354 FinalizeRequestUserMedia(request_id, user_media_request, std::move(controls), 328 FinalizeRequestUserMedia(request_id, user_media_request, std::move(controls),
355 request_settings); 329 enable_automatic_output_device_selection,
356 } 330 security_origin);
357
358 void UserMediaClientImpl::SelectVideoDeviceSourceSettings(
359 int request_id,
360 const blink::WebUserMediaRequest& user_media_request,
361 std::unique_ptr<StreamControls> controls,
362 const RequestSettings& request_settings,
363 std::vector<::mojom::VideoInputDeviceCapabilitiesPtr>
364 video_input_capabilities) {
365 DCHECK(CalledOnValidThread());
366 DCHECK(controls->video.requested);
367 DCHECK(IsDeviceSource(controls->video.stream_source));
368
369 VideoCaptureCapabilities capabilities;
370 capabilities.device_capabilities = std::move(video_input_capabilities);
371 capabilities.power_line_capabilities = {
372 media::PowerLineFrequency::FREQUENCY_DEFAULT,
373 media::PowerLineFrequency::FREQUENCY_50HZ,
374 media::PowerLineFrequency::FREQUENCY_60HZ};
375
376 base::PostTaskAndReplyWithResult(
377 worker_task_runner_.get(), FROM_HERE,
378 base::Bind(&SelectVideoCaptureSourceSettings, std::move(capabilities),
379 user_media_request.videoConstraints()),
380 base::Bind(&UserMediaClientImpl::FinalizeSelectVideoDeviceSourceSettings,
381 weak_factory_.GetWeakPtr(), request_id, user_media_request,
382 base::Passed(&controls), request_settings));
383 }
384
385 void UserMediaClientImpl::FinalizeSelectVideoDeviceSourceSettings(
386 int request_id,
387 const blink::WebUserMediaRequest& user_media_request,
388 std::unique_ptr<StreamControls> controls,
389 const RequestSettings& request_settings,
390 const VideoCaptureSourceSelectionResult& selection_result) {
391 DCHECK(CalledOnValidThread());
392 // Select video device.
393 if (!selection_result.has_value()) {
394 blink::WebString failed_constraint_name =
395 blink::WebString::fromASCII(selection_result.failed_constraint_name);
396 MediaStreamRequestResult result =
397 failed_constraint_name.isEmpty()
398 ? MEDIA_DEVICE_NO_HARDWARE
399 : MEDIA_DEVICE_CONSTRAINT_NOT_SATISFIED;
400 GetUserMediaRequestFailed(user_media_request, result,
401 failed_constraint_name);
402 return;
403 }
404 controls->video.device_id = selection_result.settings.device_id();
405 FinalizeRequestUserMedia(request_id, user_media_request, std::move(controls),
406 request_settings);
407 } 331 }
408 332
409 void UserMediaClientImpl::FinalizeRequestUserMedia( 333 void UserMediaClientImpl::FinalizeRequestUserMedia(
410 int request_id, 334 int request_id,
411 const blink::WebUserMediaRequest& user_media_request, 335 const blink::WebUserMediaRequest& user_media_request,
412 std::unique_ptr<StreamControls> controls, 336 std::unique_ptr<StreamControls> controls,
413 const RequestSettings& request_settings) { 337 bool enable_automatic_output_device_selection,
338 const url::Origin& security_origin) {
414 DCHECK(CalledOnValidThread()); 339 DCHECK(CalledOnValidThread());
415 340
416 WebRtcLogMessage( 341 WebRtcLogMessage(
417 base::StringPrintf("MSI::requestUserMedia. request_id=%d" 342 base::StringPrintf("MSI::requestUserMedia. request_id=%d"
418 ", audio source id=%s" 343 ", audio source id=%s"
419 ", video source id=%s", 344 ", video source id=%s",
420 request_id, controls->audio.device_id.c_str(), 345 request_id, controls->audio.device_id.c_str(),
421 controls->video.device_id.c_str())); 346 controls->video.device_id.c_str()));
422 347
423 user_media_requests_.push_back(base::MakeUnique<UserMediaRequestInfo>( 348 user_media_requests_.push_back(std::unique_ptr<UserMediaRequestInfo>(
424 request_id, user_media_request, 349 new UserMediaRequestInfo(request_id, user_media_request,
425 request_settings.enable_automatic_audio_output_device_selection)); 350 enable_automatic_output_device_selection)));
426 351
427 media_stream_dispatcher_->GenerateStream( 352 media_stream_dispatcher_->GenerateStream(
428 request_id, weak_factory_.GetWeakPtr(), *controls, 353 request_id, weak_factory_.GetWeakPtr(), *controls, security_origin);
429 request_settings.security_origin,
430 request_settings.is_processing_user_gesture);
431 } 354 }
432 355
433 void UserMediaClientImpl::cancelUserMediaRequest( 356 void UserMediaClientImpl::cancelUserMediaRequest(
434 const blink::WebUserMediaRequest& user_media_request) { 357 const blink::WebUserMediaRequest& user_media_request) {
435 DCHECK(CalledOnValidThread()); 358 DCHECK(CalledOnValidThread());
436 UserMediaRequestInfo* request = FindUserMediaRequestInfo(user_media_request); 359 UserMediaRequestInfo* request = FindUserMediaRequestInfo(user_media_request);
437 if (request) { 360 if (request) {
438 // We can't abort the stream generation process. 361 // We can't abort the stream generation process.
439 // Instead, erase the request. Once the stream is generated we will stop the 362 // Instead, erase the request. Once the stream is generated we will stop the
440 // stream if the request does not exist. 363 // stream if the request does not exist.
(...skipping 794 matching lines...) Expand 10 before | Expand all | Expand 10 after
1235 sources_waiting_for_callback_.end(), source); 1158 sources_waiting_for_callback_.end(), source);
1236 if (found != sources_waiting_for_callback_.end()) 1159 if (found != sources_waiting_for_callback_.end())
1237 OnTrackStarted(source, result, result_name); 1160 OnTrackStarted(source, result, result_name);
1238 } 1161 }
1239 1162
1240 void UserMediaClientImpl::OnDestruct() { 1163 void UserMediaClientImpl::OnDestruct() {
1241 delete this; 1164 delete this;
1242 } 1165 }
1243 1166
1244 } // namespace content 1167 } // namespace content
OLDNEW
« no previous file with comments | « content/renderer/media/user_media_client_impl.h ('k') | content/renderer/media/user_media_client_impl_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698