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

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

Issue 23731007: Implicit audio output device selection for getUserMedia. (Closed) Base URL: http://git.chromium.org/chromium/src.git@master
Patch Set: Rebase Created 7 years, 3 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/media_stream_impl.h" 5 #include "content/renderer/media/media_stream_impl.h"
6 6
7 #include <utility> 7 #include <utility>
8 8
9 #include "base/logging.h" 9 #include "base/logging.h"
10 #include "base/strings/string_number_conversions.h" 10 #include "base/strings/string_number_conversions.h"
11 #include "base/strings/stringprintf.h" 11 #include "base/strings/stringprintf.h"
12 #include "base/strings/utf_string_conversions.h" 12 #include "base/strings/utf_string_conversions.h"
13 #include "content/public/common/desktop_media_id.h" 13 #include "content/public/common/desktop_media_id.h"
14 #include "content/renderer/media/media_stream_audio_renderer.h" 14 #include "content/renderer/media/media_stream_audio_renderer.h"
15 #include "content/renderer/media/media_stream_dependency_factory.h" 15 #include "content/renderer/media/media_stream_dependency_factory.h"
16 #include "content/renderer/media/media_stream_dispatcher.h" 16 #include "content/renderer/media/media_stream_dispatcher.h"
17 #include "content/renderer/media/media_stream_extra_data.h" 17 #include "content/renderer/media/media_stream_extra_data.h"
18 #include "content/renderer/media/media_stream_source_extra_data.h" 18 #include "content/renderer/media/media_stream_source_extra_data.h"
19 #include "content/renderer/media/rtc_video_renderer.h" 19 #include "content/renderer/media/rtc_video_renderer.h"
20 #include "content/renderer/media/webrtc_audio_capturer.h" 20 #include "content/renderer/media/webrtc_audio_capturer.h"
21 #include "content/renderer/media/webrtc_audio_renderer.h" 21 #include "content/renderer/media/webrtc_audio_renderer.h"
22 #include "content/renderer/media/webrtc_local_audio_renderer.h" 22 #include "content/renderer/media/webrtc_local_audio_renderer.h"
23 #include "content/renderer/media/webrtc_uma_histograms.h" 23 #include "content/renderer/media/webrtc_uma_histograms.h"
24 #include "content/renderer/render_thread_impl.h"
25 #include "media/base/audio_hardware_config.h"
24 #include "third_party/WebKit/public/platform/WebMediaConstraints.h" 26 #include "third_party/WebKit/public/platform/WebMediaConstraints.h"
25 #include "third_party/WebKit/public/platform/WebMediaStreamSource.h" 27 #include "third_party/WebKit/public/platform/WebMediaStreamSource.h"
26 #include "third_party/WebKit/public/platform/WebMediaStreamTrack.h" 28 #include "third_party/WebKit/public/platform/WebMediaStreamTrack.h"
27 #include "third_party/WebKit/public/platform/WebVector.h" 29 #include "third_party/WebKit/public/platform/WebVector.h"
28 #include "third_party/WebKit/public/web/WebDocument.h" 30 #include "third_party/WebKit/public/web/WebDocument.h"
29 #include "third_party/WebKit/public/web/WebFrame.h" 31 #include "third_party/WebKit/public/web/WebFrame.h"
30 #include "third_party/WebKit/public/web/WebMediaStreamRegistry.h" 32 #include "third_party/WebKit/public/web/WebMediaStreamRegistry.h"
31 33
32 namespace content { 34 namespace content {
33 namespace { 35 namespace {
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after
113 115
114 webrtc::MediaStreamInterface* GetNativeMediaStream( 116 webrtc::MediaStreamInterface* GetNativeMediaStream(
115 const WebKit::WebMediaStream& web_stream) { 117 const WebKit::WebMediaStream& web_stream) {
116 content::MediaStreamExtraData* extra_data = 118 content::MediaStreamExtraData* extra_data =
117 static_cast<content::MediaStreamExtraData*>(web_stream.extraData()); 119 static_cast<content::MediaStreamExtraData*>(web_stream.extraData());
118 if (!extra_data) 120 if (!extra_data)
119 return NULL; 121 return NULL;
120 return extra_data->stream().get(); 122 return extra_data->stream().get();
121 } 123 }
122 124
125 void GetDefaultOutputDeviceParams(
126 int* output_sample_rate, int* output_buffer_size) {
127 // Fetch the default audio output hardware config.
128 media::AudioHardwareConfig* hardware_config =
129 RenderThreadImpl::current()->GetAudioHardwareConfig();
130 *output_sample_rate = hardware_config->GetOutputSampleRate();
131 *output_buffer_size = hardware_config->GetOutputBufferSize();
132 }
133
123 } // namespace 134 } // namespace
124 135
125 MediaStreamImpl::MediaStreamImpl( 136 MediaStreamImpl::MediaStreamImpl(
126 RenderView* render_view, 137 RenderView* render_view,
127 MediaStreamDispatcher* media_stream_dispatcher, 138 MediaStreamDispatcher* media_stream_dispatcher,
128 MediaStreamDependencyFactory* dependency_factory) 139 MediaStreamDependencyFactory* dependency_factory)
129 : RenderViewObserver(render_view), 140 : RenderViewObserver(render_view),
130 dependency_factory_(dependency_factory), 141 dependency_factory_(dependency_factory),
131 media_stream_dispatcher_(media_stream_dispatcher) { 142 media_stream_dispatcher_(media_stream_dispatcher) {
132 } 143 }
(...skipping 452 matching lines...) Expand 10 before | Expand all | Expand 10 after
585 } 596 }
586 597
587 scoped_refptr<WebRtcAudioRenderer> MediaStreamImpl::CreateRemoteAudioRenderer( 598 scoped_refptr<WebRtcAudioRenderer> MediaStreamImpl::CreateRemoteAudioRenderer(
588 webrtc::MediaStreamInterface* stream) { 599 webrtc::MediaStreamInterface* stream) {
589 if (stream->GetAudioTracks().empty()) 600 if (stream->GetAudioTracks().empty())
590 return NULL; 601 return NULL;
591 602
592 DVLOG(1) << "MediaStreamImpl::CreateRemoteAudioRenderer label:" 603 DVLOG(1) << "MediaStreamImpl::CreateRemoteAudioRenderer label:"
593 << stream->label(); 604 << stream->label();
594 605
595 return new WebRtcAudioRenderer(RenderViewObserver::routing_id()); 606 int session_id = 0, sample_rate = 0, buffer_size = 0;
607 if (!GetAuthorizedDeviceInfoForAudioRenderer(&session_id,
608 &sample_rate,
609 &buffer_size)) {
610 GetDefaultOutputDeviceParams(&sample_rate, &buffer_size);
611 }
612
613 return new WebRtcAudioRenderer(RenderViewObserver::routing_id(),
614 session_id, sample_rate, buffer_size);
596 } 615 }
597 616
598 scoped_refptr<WebRtcLocalAudioRenderer> 617 scoped_refptr<WebRtcLocalAudioRenderer>
599 MediaStreamImpl::CreateLocalAudioRenderer( 618 MediaStreamImpl::CreateLocalAudioRenderer(
600 webrtc::MediaStreamInterface* stream) { 619 webrtc::MediaStreamInterface* stream) {
601 if (stream->GetAudioTracks().empty()) 620 if (stream->GetAudioTracks().empty())
602 return NULL; 621 return NULL;
603 622
604 DVLOG(1) << "MediaStreamImpl::CreateLocalAudioRenderer label:" 623 DVLOG(1) << "MediaStreamImpl::CreateLocalAudioRenderer label:"
605 << stream->label(); 624 << stream->label();
606 625
607 webrtc::AudioTrackVector audio_tracks = stream->GetAudioTracks(); 626 webrtc::AudioTrackVector audio_tracks = stream->GetAudioTracks();
608 DCHECK_EQ(audio_tracks.size(), 1u); 627 DCHECK_EQ(audio_tracks.size(), 1u);
609 webrtc::AudioTrackInterface* audio_track = audio_tracks[0]; 628 webrtc::AudioTrackInterface* audio_track = audio_tracks[0];
610 DVLOG(1) << "audio_track.kind : " << audio_track->kind() 629 DVLOG(1) << "audio_track.kind : " << audio_track->kind()
611 << "audio_track.id : " << audio_track->id() 630 << "audio_track.id : " << audio_track->id()
612 << "audio_track.enabled: " << audio_track->enabled(); 631 << "audio_track.enabled: " << audio_track->enabled();
613 632
633 int session_id = 0, sample_rate = 0, buffer_size = 0;
634 if (!GetAuthorizedDeviceInfoForAudioRenderer(&session_id,
635 &sample_rate,
636 &buffer_size)) {
637 GetDefaultOutputDeviceParams(&sample_rate, &buffer_size);
638 }
639
614 // Create a new WebRtcLocalAudioRenderer instance and connect it to the 640 // Create a new WebRtcLocalAudioRenderer instance and connect it to the
615 // existing WebRtcAudioCapturer so that the renderer can use it as source. 641 // existing WebRtcAudioCapturer so that the renderer can use it as source.
616 return new WebRtcLocalAudioRenderer( 642 return new WebRtcLocalAudioRenderer(
617 static_cast<WebRtcLocalAudioTrack*>(audio_track), 643 static_cast<WebRtcLocalAudioTrack*>(audio_track),
618 RenderViewObserver::routing_id()); 644 RenderViewObserver::routing_id(),
645 session_id,
646 sample_rate,
647 buffer_size);
619 } 648 }
620 649
621 void MediaStreamImpl::StopLocalAudioTrack( 650 void MediaStreamImpl::StopLocalAudioTrack(
622 const WebKit::WebMediaStream& web_stream) { 651 const WebKit::WebMediaStream& web_stream) {
623 MediaStreamExtraData* extra_data = static_cast<MediaStreamExtraData*>( 652 MediaStreamExtraData* extra_data = static_cast<MediaStreamExtraData*>(
624 web_stream.extraData()); 653 web_stream.extraData());
625 if (extra_data && extra_data->is_local() && extra_data->stream().get() && 654 if (extra_data && extra_data->is_local() && extra_data->stream().get() &&
626 !extra_data->stream()->GetAudioTracks().empty()) { 655 !extra_data->stream()->GetAudioTracks().empty()) {
627 webrtc::AudioTrackVector audio_tracks = 656 webrtc::AudioTrackVector audio_tracks =
628 extra_data->stream()->GetAudioTracks(); 657 extra_data->stream()->GetAudioTracks();
629 for (size_t i = 0; i < audio_tracks.size(); ++i) { 658 for (size_t i = 0; i < audio_tracks.size(); ++i) {
630 WebRtcLocalAudioTrack* audio_track = static_cast<WebRtcLocalAudioTrack*>( 659 WebRtcLocalAudioTrack* audio_track = static_cast<WebRtcLocalAudioTrack*>(
631 audio_tracks[i].get()); 660 audio_tracks[i].get());
632 // Remove the WebRtcAudioDevice as the sink to the local audio track. 661 // Remove the WebRtcAudioDevice as the sink to the local audio track.
633 audio_track->RemoveSink(dependency_factory_->GetWebRtcAudioDevice()); 662 audio_track->RemoveSink(dependency_factory_->GetWebRtcAudioDevice());
634 // Stop the audio track. This will unhook the audio track from the 663 // Stop the audio track. This will unhook the audio track from the
635 // capturer and will shutdown the source of the capturer if it is the 664 // capturer and will shutdown the source of the capturer if it is the
636 // last audio track connecting to the capturer. 665 // last audio track connecting to the capturer.
637 audio_track->Stop(); 666 audio_track->Stop();
638 } 667 }
639 } 668 }
640 } 669 }
641 670
671 bool MediaStreamImpl::GetAuthorizedDeviceInfoForAudioRenderer(
672 int* session_id,
673 int* output_sample_rate,
674 int* output_frames_per_buffer) {
675 DCHECK(CalledOnValidThread());
676
677 const StreamDeviceInfo* device_info = NULL;
678 WebKit::WebString session_id_str;
679 UserMediaRequests::iterator it = user_media_requests_.begin();
680 for (; it != user_media_requests_.end(); ++it) {
681 UserMediaRequestInfo* request = (*it);
682 for (size_t i = 0; i < request->audio_sources.size(); ++i) {
683 const WebKit::WebMediaStreamSource& source = request->audio_sources[i];
684 if (source.readyState() == WebKit::WebMediaStreamSource::ReadyStateEnded)
685 continue;
686
687 if (!session_id_str.isEmpty() &&
688 !session_id_str.equals(source.deviceId())) {
689 DVLOG(1) << "Multiple capture devices are open so we can't pick a "
690 "session for a matching output device.";
691 return false;
692 }
693
694 // TODO(tommi): Storing the session id in the deviceId field doesn't
695 // feel right. Move it over to MediaStreamSourceExtraData?
696 session_id_str = source.deviceId();
697 content::MediaStreamSourceExtraData* extra_data =
698 static_cast<content::MediaStreamSourceExtraData*>(source.extraData());
699 device_info = &extra_data->device_info();
700 }
701 }
702
703 if (session_id_str.isEmpty() || !device_info)
704 return false;
705
706 base::StringToInt(UTF16ToUTF8(session_id_str), session_id);
707 *output_sample_rate = device_info->device.matched_output.sample_rate;
708 *output_frames_per_buffer =
709 device_info->device.matched_output.frames_per_buffer;
710
711 return true;
712 }
713
642 MediaStreamSourceExtraData::MediaStreamSourceExtraData( 714 MediaStreamSourceExtraData::MediaStreamSourceExtraData(
643 const StreamDeviceInfo& device_info, 715 const StreamDeviceInfo& device_info,
644 const WebKit::WebMediaStreamSource& webkit_source) 716 const WebKit::WebMediaStreamSource& webkit_source)
645 : device_info_(device_info), 717 : device_info_(device_info),
646 webkit_source_(webkit_source) { 718 webkit_source_(webkit_source) {
647 } 719 }
648 720
649 MediaStreamSourceExtraData::MediaStreamSourceExtraData( 721 MediaStreamSourceExtraData::MediaStreamSourceExtraData(
650 media::AudioCapturerSource* source) 722 media::AudioCapturerSource* source)
651 : audio_source_(source) { 723 : audio_source_(source) {
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
697 } 769 }
698 770
699 for (size_t i = 0; i < video_sources.size(); ++i) { 771 for (size_t i = 0; i < video_sources.size(); ++i) {
700 video_sources[i].setReadyState( 772 video_sources[i].setReadyState(
701 WebKit::WebMediaStreamSource::ReadyStateEnded); 773 WebKit::WebMediaStreamSource::ReadyStateEnded);
702 video_sources[i].setExtraData(NULL); 774 video_sources[i].setExtraData(NULL);
703 } 775 }
704 } 776 }
705 777
706 } // namespace content 778 } // namespace content
OLDNEW
« no previous file with comments | « content/renderer/media/media_stream_impl.h ('k') | content/renderer/media/webrtc_audio_device_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698