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

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

Issue 11783059: Ensures that WebRTC works for device selection using a different sample rate than default (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Fix after review from Chris Created 7 years, 11 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 | Annotate | Revision Log
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/media_stream_dependency_factory.h" 5 #include "content/renderer/media/media_stream_dependency_factory.h"
6 6
7 #include <vector> 7 #include <vector>
8 8
9 #include "base/synchronization/waitable_event.h" 9 #include "base/synchronization/waitable_event.h"
10 #include "base/utf_string_conversions.h" 10 #include "base/utf_string_conversions.h"
11 #include "content/renderer/media/media_stream_source_extra_data.h" 11 #include "content/renderer/media/media_stream_source_extra_data.h"
12 #include "content/renderer/media/rtc_media_constraints.h" 12 #include "content/renderer/media/rtc_media_constraints.h"
13 #include "content/renderer/media/rtc_peer_connection_handler.h" 13 #include "content/renderer/media/rtc_peer_connection_handler.h"
14 #include "content/renderer/media/rtc_video_capturer.h" 14 #include "content/renderer/media/rtc_video_capturer.h"
15 #include "content/renderer/media/video_capture_impl_manager.h" 15 #include "content/renderer/media/video_capture_impl_manager.h"
16 #include "content/renderer/media/webaudio_capturer_source.h"
16 #include "content/renderer/media/webrtc_audio_device_impl.h" 17 #include "content/renderer/media/webrtc_audio_device_impl.h"
17 #include "content/renderer/media/webrtc_uma_histograms.h" 18 #include "content/renderer/media/webrtc_uma_histograms.h"
18 #include "content/renderer/p2p/ipc_network_manager.h" 19 #include "content/renderer/p2p/ipc_network_manager.h"
19 #include "content/renderer/p2p/ipc_socket_factory.h" 20 #include "content/renderer/p2p/ipc_socket_factory.h"
20 #include "content/renderer/p2p/port_allocator.h" 21 #include "content/renderer/p2p/port_allocator.h"
21 #include "jingle/glue/thread_wrapper.h" 22 #include "jingle/glue/thread_wrapper.h"
22 #include "third_party/WebKit/Source/Platform/chromium/public/WebMediaStreamCompo nent.h" 23 #include "third_party/WebKit/Source/Platform/chromium/public/WebMediaStreamCompo nent.h"
23 #include "third_party/WebKit/Source/Platform/chromium/public/WebMediaStreamDescr iptor.h" 24 #include "third_party/WebKit/Source/Platform/chromium/public/WebMediaStreamDescr iptor.h"
24 #include "third_party/WebKit/Source/Platform/chromium/public/WebMediaStreamSourc e.h" 25 #include "third_party/WebKit/Source/Platform/chromium/public/WebMediaStreamSourc e.h"
25 #include "third_party/WebKit/Source/WebKit/chromium/public/WebFrame.h" 26 #include "third_party/WebKit/Source/WebKit/chromium/public/WebFrame.h"
(...skipping 157 matching lines...) Expand 10 before | Expand all | Expand 10 after
183 return NULL; 184 return NULL;
184 185
185 return new RTCPeerConnectionHandler(client, this); 186 return new RTCPeerConnectionHandler(client, this);
186 } 187 }
187 188
188 void MediaStreamDependencyFactory::CreateNativeMediaSources( 189 void MediaStreamDependencyFactory::CreateNativeMediaSources(
189 const WebKit::WebMediaConstraints& audio_constraints, 190 const WebKit::WebMediaConstraints& audio_constraints,
190 const WebKit::WebMediaConstraints& video_constraints, 191 const WebKit::WebMediaConstraints& video_constraints,
191 WebKit::WebMediaStreamDescriptor* description, 192 WebKit::WebMediaStreamDescriptor* description,
192 const MediaSourcesCreatedCallback& sources_created) { 193 const MediaSourcesCreatedCallback& sources_created) {
194 DVLOG(1) << "MediaStreamDependencyFactory::CreateNativeMediaSources()";
193 if (!EnsurePeerConnectionFactory()) { 195 if (!EnsurePeerConnectionFactory()) {
194 sources_created.Run(description, false); 196 sources_created.Run(description, false);
195 return; 197 return;
196 } 198 }
197 199
198 // |source_observer| clean up itself when it has completed 200 // |source_observer| clean up itself when it has completed
199 // source_observer->StartObservering. 201 // source_observer->StartObservering.
200 SourceStateObserver* source_observer = 202 SourceStateObserver* source_observer =
201 new SourceStateObserver(description, sources_created); 203 new SourceStateObserver(description, sources_created);
202 204
203 // TODO(perkj): Implement local audio sources.
204
205 // Create local video sources. 205 // Create local video sources.
206 RTCMediaConstraints native_video_constraints(video_constraints); 206 RTCMediaConstraints native_video_constraints(video_constraints);
207 WebKit::WebVector<WebKit::WebMediaStreamComponent> video_components; 207 WebKit::WebVector<WebKit::WebMediaStreamComponent> video_components;
208 description->videoSources(video_components); 208 description->videoSources(video_components);
209 for (size_t i = 0; i < video_components.size(); ++i) { 209 for (size_t i = 0; i < video_components.size(); ++i) {
210 const WebKit::WebMediaStreamSource& source = video_components[i].source(); 210 const WebKit::WebMediaStreamSource& source = video_components[i].source();
211 MediaStreamSourceExtraData* source_data = 211 MediaStreamSourceExtraData* source_data =
212 static_cast<MediaStreamSourceExtraData*>(source.extraData()); 212 static_cast<MediaStreamSourceExtraData*>(source.extraData());
213 if (!source_data) { 213 if (!source_data) {
214 // TODO(perkj): Implement support for sources from remote MediaStreams. 214 // TODO(perkj): Implement support for sources from remote MediaStreams.
215 NOTIMPLEMENTED(); 215 NOTIMPLEMENTED();
216 continue; 216 continue;
217 } 217 }
218 const bool is_screencast = (source_data->device_info().device.type == 218 const bool is_screencast = (source_data->device_info().device.type ==
219 content::MEDIA_TAB_VIDEO_CAPTURE); 219 content::MEDIA_TAB_VIDEO_CAPTURE);
220 source_data->SetVideoSource( 220 source_data->SetVideoSource(
221 CreateVideoSource(source_data->device_info().session_id, 221 CreateVideoSource(source_data->device_info().session_id,
222 is_screencast, 222 is_screencast,
223 &native_video_constraints)); 223 &native_video_constraints));
224 source_observer->AddSource(source_data->video_source()); 224 source_observer->AddSource(source_data->video_source());
225 } 225 }
226
227 // Do additional source initialization if the audio source is a valid
228 // microphone.
229 WebKit::WebVector<WebKit::WebMediaStreamComponent> audio_components;
230 description->audioSources(audio_components);
231 for (size_t i = 0; i < audio_components.size(); ++i) {
232 const WebKit::WebMediaStreamSource& source = audio_components[i].source();
233 MediaStreamSourceExtraData* source_data =
234 static_cast<MediaStreamSourceExtraData*>(source.extraData());
235 if (!source_data) {
236 // TODO(henrika): Implement support for sources from remote MediaStreams.
237 NOTIMPLEMENTED();
238 continue;
239 }
240
241 const StreamDeviceInfo device_info = source_data->device_info();
242 if (device_info.device.type == content::MEDIA_DEVICE_AUDIO_CAPTURE) {
243 if (!InitializeAudioSource(device_info)) {
244 DLOG(WARNING) << "Unsupported audio source";
245 sources_created.Run(description, false);
246 return;
247 }
248 }
249 }
250
226 source_observer->StartObservering(); 251 source_observer->StartObservering();
227 } 252 }
228 253
229 void MediaStreamDependencyFactory::CreateNativeLocalMediaStream( 254 void MediaStreamDependencyFactory::CreateNativeLocalMediaStream(
230 WebKit::WebMediaStreamDescriptor* description) { 255 WebKit::WebMediaStreamDescriptor* description) {
256 DVLOG(1) << "MediaStreamDependencyFactory::CreateNativeLocalMediaStream()";
231 if (!EnsurePeerConnectionFactory()) { 257 if (!EnsurePeerConnectionFactory()) {
232 DVLOG(1) << "EnsurePeerConnectionFactory() failed!"; 258 DVLOG(1) << "EnsurePeerConnectionFactory() failed!";
233 return; 259 return;
234 } 260 }
235 261
236 std::string label = UTF16ToUTF8(description->label()); 262 std::string label = UTF16ToUTF8(description->label());
237 scoped_refptr<webrtc::LocalMediaStreamInterface> native_stream = 263 scoped_refptr<webrtc::LocalMediaStreamInterface> native_stream =
238 CreateLocalMediaStream(label); 264 CreateLocalMediaStream(label);
239 265
240 WebRtcAudioCapturer* capturer =
241 GetWebRtcAudioDevice() ? GetWebRtcAudioDevice()->capturer() : 0;
242 if (!capturer)
243 DVLOG(1) << "CreateNativeLocalMediaStream: missing WebRtcAudioCapturer.";
244
245 // Add audio tracks. 266 // Add audio tracks.
246 WebKit::WebVector<WebKit::WebMediaStreamComponent> audio_components; 267 WebKit::WebVector<WebKit::WebMediaStreamComponent> audio_components;
247 description->audioSources(audio_components); 268 description->audioSources(audio_components);
248 269
249 for (size_t i = 0; i < audio_components.size(); ++i) { 270 for (size_t i = 0; i < audio_components.size(); ++i) {
250 WebKit::WebMediaStreamSource source = audio_components[i].source(); 271 WebKit::WebMediaStreamSource source = audio_components[i].source();
251 272
252 // See if we're adding a WebAudio MediaStream. 273 // See if we're adding a WebAudio MediaStream.
253 if (source.requiresAudioConsumer()) { 274 if (source.requiresAudioConsumer()) {
254 if (!webaudio_capturer_source_.get() && capturer) { 275 // TODO(crogers, xians): In reality we should be able to send a unique
255 DCHECK(GetWebRtcAudioDevice()); 276 // audio stream to each PeerConnection separately. But currently WebRTC
277 // is only able to handle a global audio stream sent to ALL peers.
256 278
257 // TODO(crogers, xians): In reality we should be able to send a unique 279 // TODO(henrika): refactor and utilize audio constraints.
258 // audio stream to each PeerConnection separately. But currently WebRTC 280 if (CreateWebAudioSource(&source)) {
259 // is only able to handle a global audio stream sent to ALL peers.
260
261 // For lifetime, we're relying on the fact that
262 // |webaudio_capturer_source_| will live longer than any
263 // MediaStreamSource, since we're never calling removeAudioConsumer().
264 webaudio_capturer_source_ = new WebAudioCapturerSource(capturer);
265 source.addAudioConsumer(webaudio_capturer_source_.get());
266
267 scoped_refptr<webrtc::LocalAudioTrackInterface> audio_track( 281 scoped_refptr<webrtc::LocalAudioTrackInterface> audio_track(
268 CreateLocalAudioTrack(label + "a0", NULL)); 282 CreateLocalAudioTrack(UTF16ToUTF8(audio_components[i].id()), NULL));
269 native_stream->AddTrack(audio_track); 283 native_stream->AddTrack(audio_track);
270 audio_track->set_enabled(audio_components[i].isEnabled()); 284 audio_track->set_enabled(audio_components[i].isEnabled());
271 } else { 285 } else {
272 // TODO(crogers): this is very likely to be less important, but 286 DLOG(WARNING) << "Failed to create WebAudio source";
273 // in theory we should be able to "connect" multiple WebAudio
274 // MediaStreams to a single peer, mixing their results.
275 // Instead we just ignore additional ones after the first.
276 LOG(WARNING)
277 << "Multiple MediaStreamAudioDestinationNodes not yet supported!";
278 } 287 }
279 } else { 288 } else {
280 MediaStreamSourceExtraData* source_data = 289 MediaStreamSourceExtraData* source_data =
281 static_cast<MediaStreamSourceExtraData*>(source.extraData()); 290 static_cast<MediaStreamSourceExtraData*>(source.extraData());
282 291
283 if (!source_data) { 292 if (!source_data) {
284 // TODO(perkj): Implement support for sources from 293 // TODO(perkj): Implement support for sources from
285 // remote MediaStreams. 294 // remote MediaStreams.
286 NOTIMPLEMENTED(); 295 NOTIMPLEMENTED();
287 continue; 296 continue;
288 } 297 }
289 298
290 // TODO(perkj): Refactor the creation of audio tracks to use a proper 299 // TODO(perkj): Refactor the creation of audio tracks to use a proper
291 // interface for receiving audio input data. Currently NULL is passed 300 // interface for receiving audio input data. Currently NULL is passed
292 // since the |audio_device| is the wrong class and is unused. 301 // since the |audio_device| is the wrong class and is unused.
293 scoped_refptr<webrtc::LocalAudioTrackInterface> audio_track( 302 scoped_refptr<webrtc::LocalAudioTrackInterface> audio_track(
294 CreateLocalAudioTrack(UTF16ToUTF8(source.id()), NULL)); 303 CreateLocalAudioTrack(UTF16ToUTF8(source.id()), NULL));
295 native_stream->AddTrack(audio_track); 304 native_stream->AddTrack(audio_track);
296 audio_track->set_enabled(audio_components[i].isEnabled()); 305 audio_track->set_enabled(audio_components[i].isEnabled());
297 // TODO(xians): This set the source of all audio tracks to the same
298 // microphone. Implement support for setting the source per audio track
299 // instead.
300 SetAudioDeviceSessionId(source_data->device_info().session_id);
301 } 306 }
302 } 307 }
303 308
304 // Add video tracks. 309 // Add video tracks.
305 WebKit::WebVector<WebKit::WebMediaStreamComponent> video_components; 310 WebKit::WebVector<WebKit::WebMediaStreamComponent> video_components;
306 description->videoSources(video_components); 311 description->videoSources(video_components);
307 for (size_t i = 0; i < video_components.size(); ++i) { 312 for (size_t i = 0; i < video_components.size(); ++i) {
308 const WebKit::WebMediaStreamSource& source = video_components[i].source(); 313 const WebKit::WebMediaStreamSource& source = video_components[i].source();
309 MediaStreamSourceExtraData* source_data = 314 MediaStreamSourceExtraData* source_data =
310 static_cast<MediaStreamSourceExtraData*>(source.extraData()); 315 static_cast<MediaStreamSourceExtraData*>(source.extraData());
(...skipping 19 matching lines...) Expand all
330 WebKit::WebMediaStreamDescriptor* description, 335 WebKit::WebMediaStreamDescriptor* description,
331 const MediaStreamExtraData::StreamStopCallback& stream_stop) { 336 const MediaStreamExtraData::StreamStopCallback& stream_stop) {
332 CreateNativeLocalMediaStream(description); 337 CreateNativeLocalMediaStream(description);
333 338
334 MediaStreamExtraData* extra_data = 339 MediaStreamExtraData* extra_data =
335 static_cast<MediaStreamExtraData*>(description->extraData()); 340 static_cast<MediaStreamExtraData*>(description->extraData());
336 extra_data->SetLocalStreamStopCallback(stream_stop); 341 extra_data->SetLocalStreamStopCallback(stream_stop);
337 } 342 }
338 343
339 bool MediaStreamDependencyFactory::CreatePeerConnectionFactory() { 344 bool MediaStreamDependencyFactory::CreatePeerConnectionFactory() {
345 DVLOG(1) << "MediaStreamDependencyFactory::CreatePeerConnectionFactory()";
340 if (!pc_factory_.get()) { 346 if (!pc_factory_.get()) {
341 DCHECK(!audio_device_); 347 DCHECK(!audio_device_);
342 audio_device_ = new WebRtcAudioDeviceImpl(); 348 audio_device_ = new WebRtcAudioDeviceImpl();
343 scoped_refptr<webrtc::PeerConnectionFactoryInterface> factory( 349 scoped_refptr<webrtc::PeerConnectionFactoryInterface> factory(
344 webrtc::CreatePeerConnectionFactory(worker_thread_, 350 webrtc::CreatePeerConnectionFactory(worker_thread_,
345 signaling_thread_, 351 signaling_thread_,
346 audio_device_)); 352 audio_device_));
347 if (factory.get()) 353 if (factory.get())
348 pc_factory_ = factory; 354 pc_factory_ = factory;
349 else 355 else
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
387 const webrtc::MediaConstraintsInterface* constraints) { 393 const webrtc::MediaConstraintsInterface* constraints) {
388 RtcVideoCapturer* capturer = new RtcVideoCapturer( 394 RtcVideoCapturer* capturer = new RtcVideoCapturer(
389 video_session_id, vc_manager_.get(), is_screencast); 395 video_session_id, vc_manager_.get(), is_screencast);
390 396
391 // The video source takes ownership of |capturer|. 397 // The video source takes ownership of |capturer|.
392 scoped_refptr<webrtc::VideoSourceInterface> source = 398 scoped_refptr<webrtc::VideoSourceInterface> source =
393 pc_factory_->CreateVideoSource(capturer, constraints).get(); 399 pc_factory_->CreateVideoSource(capturer, constraints).get();
394 return source; 400 return source;
395 } 401 }
396 402
403 bool MediaStreamDependencyFactory::InitializeAudioSource(
404 const StreamDeviceInfo& device_info) {
405 DVLOG(1) << "MediaStreamDependencyFactory::InitializeAudioSource()";
406 const MediaStreamDevice device = device_info.device;
407
408 // Initialize the source using audio parameters for the selected
409 // capture device.
410 WebRtcAudioCapturer* capturer = GetWebRtcAudioDevice()->capturer();
411 // TODO(henrika): refactor \content\public\common\media_stream_request.h
412 // to allow dependency of media::ChannelLayout and avoid static_cast.
413 if (!capturer->Initialize(
414 static_cast<media::ChannelLayout>(device.channel_layout),
415 device.sample_rate))
416 return false;
417
418 // Specify which capture device to use. The acquired session id is used
419 // for identification.
420 // TODO(henrika): the current design does not support a uniqe source
421 // for each audio track.
422 if (device_info.session_id <= 0)
423 return false;
424
425 capturer->SetDevice(device_info.session_id);
426 return true;
427 }
428
429 bool MediaStreamDependencyFactory::CreateWebAudioSource(
430 WebKit::WebMediaStreamSource* source) {
431 DVLOG(1) << "MediaStreamDependencyFactory::CreateWebAudioSource()";
432 DCHECK(GetWebRtcAudioDevice());
433
434 // WebAudio needs the WebRtcAudioCapturer to be able to send its data
435 // over a PeerConnection. The microphone source is not utilized in this
436 // case; instead the WebRtcAudioCapturer is driving.
437 WebRtcAudioCapturer* capturer = GetWebRtcAudioDevice()->capturer();
438 if (!capturer)
439 return false;
440
441 // TODO(henrika): life-time handling is not perfect here; there is room
442 // for improvements.
443 scoped_refptr<WebAudioCapturerSource>
444 webaudio_capturer_source(new WebAudioCapturerSource(capturer));
445 source->setExtraData(new content::MediaStreamSourceExtraData(
446 webaudio_capturer_source));
447 source->addAudioConsumer(webaudio_capturer_source);
448
449 return true;
450 }
451
397 scoped_refptr<webrtc::VideoTrackInterface> 452 scoped_refptr<webrtc::VideoTrackInterface>
398 MediaStreamDependencyFactory::CreateLocalVideoTrack( 453 MediaStreamDependencyFactory::CreateLocalVideoTrack(
399 const std::string& label, 454 const std::string& label,
400 webrtc::VideoSourceInterface* source) { 455 webrtc::VideoSourceInterface* source) {
401 return pc_factory_->CreateVideoTrack(label, source).get(); 456 return pc_factory_->CreateVideoTrack(label, source).get();
402 } 457 }
403 458
404 scoped_refptr<webrtc::LocalAudioTrackInterface> 459 scoped_refptr<webrtc::LocalAudioTrackInterface>
405 MediaStreamDependencyFactory::CreateLocalAudioTrack( 460 MediaStreamDependencyFactory::CreateLocalAudioTrack(
406 const std::string& label, 461 const std::string& label,
(...skipping 12 matching lines...) Expand all
419 int sdp_mline_index, 474 int sdp_mline_index,
420 const std::string& sdp) { 475 const std::string& sdp) {
421 return webrtc::CreateIceCandidate(sdp_mid, sdp_mline_index, sdp); 476 return webrtc::CreateIceCandidate(sdp_mid, sdp_mline_index, sdp);
422 } 477 }
423 478
424 WebRtcAudioDeviceImpl* 479 WebRtcAudioDeviceImpl*
425 MediaStreamDependencyFactory::GetWebRtcAudioDevice() { 480 MediaStreamDependencyFactory::GetWebRtcAudioDevice() {
426 return audio_device_; 481 return audio_device_;
427 } 482 }
428 483
429 void MediaStreamDependencyFactory::SetAudioDeviceSessionId(int session_id) {
430 audio_device_->SetSessionId(session_id);
431 }
432
433 void MediaStreamDependencyFactory::InitializeWorkerThread( 484 void MediaStreamDependencyFactory::InitializeWorkerThread(
434 talk_base::Thread** thread, 485 talk_base::Thread** thread,
435 base::WaitableEvent* event) { 486 base::WaitableEvent* event) {
436 jingle_glue::JingleThreadWrapper::EnsureForCurrentMessageLoop(); 487 jingle_glue::JingleThreadWrapper::EnsureForCurrentMessageLoop();
437 jingle_glue::JingleThreadWrapper::current()->set_send_allowed(true); 488 jingle_glue::JingleThreadWrapper::current()->set_send_allowed(true);
438 *thread = jingle_glue::JingleThreadWrapper::current(); 489 *thread = jingle_glue::JingleThreadWrapper::current();
439 event->Signal(); 490 event->Signal();
440 } 491 }
441 492
442 void MediaStreamDependencyFactory::CreateIpcNetworkManagerOnWorkerThread( 493 void MediaStreamDependencyFactory::CreateIpcNetworkManagerOnWorkerThread(
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after
521 // processed before returning. We wait for the above task to finish before 572 // processed before returning. We wait for the above task to finish before
522 // letting the the function continue to avoid any potential race issues. 573 // letting the the function continue to avoid any potential race issues.
523 chrome_worker_thread_.Stop(); 574 chrome_worker_thread_.Stop();
524 } else { 575 } else {
525 NOTREACHED() << "Worker thread not running."; 576 NOTREACHED() << "Worker thread not running.";
526 } 577 }
527 } 578 }
528 } 579 }
529 580
530 } // namespace content 581 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698