| OLD | NEW |
| 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_util.h" | 10 #include "base/strings/string_util.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/renderer/media/media_stream.h" | 13 #include "content/renderer/media/media_stream.h" |
| 14 #include "content/renderer/media/media_stream_audio_renderer.h" | |
| 15 #include "content/renderer/media/media_stream_audio_source.h" | 14 #include "content/renderer/media/media_stream_audio_source.h" |
| 16 #include "content/renderer/media/media_stream_dispatcher.h" | 15 #include "content/renderer/media/media_stream_dispatcher.h" |
| 17 #include "content/renderer/media/media_stream_video_capturer_source.h" | 16 #include "content/renderer/media/media_stream_video_capturer_source.h" |
| 18 #include "content/renderer/media/media_stream_video_track.h" | 17 #include "content/renderer/media/media_stream_video_track.h" |
| 19 #include "content/renderer/media/peer_connection_tracker.h" | 18 #include "content/renderer/media/peer_connection_tracker.h" |
| 20 #include "content/renderer/media/rtc_video_renderer.h" | |
| 21 #include "content/renderer/media/webrtc/webrtc_video_capturer_adapter.h" | 19 #include "content/renderer/media/webrtc/webrtc_video_capturer_adapter.h" |
| 22 #include "content/renderer/media/webrtc_audio_capturer.h" | 20 #include "content/renderer/media/webrtc_audio_capturer.h" |
| 23 #include "content/renderer/media/webrtc_audio_renderer.h" | |
| 24 #include "content/renderer/media/webrtc_local_audio_renderer.h" | |
| 25 #include "content/renderer/media/webrtc_logging.h" | 21 #include "content/renderer/media/webrtc_logging.h" |
| 26 #include "content/renderer/media/webrtc_uma_histograms.h" | 22 #include "content/renderer/media/webrtc_uma_histograms.h" |
| 27 #include "content/renderer/render_thread_impl.h" | 23 #include "content/renderer/render_thread_impl.h" |
| 28 #include "media/base/audio_hardware_config.h" | |
| 29 #include "third_party/WebKit/public/platform/WebMediaConstraints.h" | 24 #include "third_party/WebKit/public/platform/WebMediaConstraints.h" |
| 30 #include "third_party/WebKit/public/platform/WebMediaStreamTrack.h" | 25 #include "third_party/WebKit/public/platform/WebMediaStreamTrack.h" |
| 31 #include "third_party/WebKit/public/web/WebDocument.h" | 26 #include "third_party/WebKit/public/web/WebDocument.h" |
| 32 #include "third_party/WebKit/public/web/WebLocalFrame.h" | 27 #include "third_party/WebKit/public/web/WebLocalFrame.h" |
| 33 #include "third_party/WebKit/public/web/WebMediaStreamRegistry.h" | |
| 34 | 28 |
| 35 namespace content { | 29 namespace content { |
| 36 namespace { | 30 namespace { |
| 37 | 31 |
| 38 void CopyStreamConstraints(const blink::WebMediaConstraints& constraints, | 32 void CopyStreamConstraints(const blink::WebMediaConstraints& constraints, |
| 39 StreamOptions::Constraints* mandatory, | 33 StreamOptions::Constraints* mandatory, |
| 40 StreamOptions::Constraints* optional) { | 34 StreamOptions::Constraints* optional) { |
| 41 blink::WebVector<blink::WebMediaConstraint> mandatory_constraints; | 35 blink::WebVector<blink::WebMediaConstraint> mandatory_constraints; |
| 42 constraints.getMandatoryConstraints(mandatory_constraints); | 36 constraints.getMandatoryConstraints(mandatory_constraints); |
| 43 for (size_t i = 0; i < mandatory_constraints.size(); i++) { | 37 for (size_t i = 0; i < mandatory_constraints.size(); i++) { |
| 44 mandatory->push_back(StreamOptions::Constraint( | 38 mandatory->push_back(StreamOptions::Constraint( |
| 45 mandatory_constraints[i].m_name.utf8(), | 39 mandatory_constraints[i].m_name.utf8(), |
| 46 mandatory_constraints[i].m_value.utf8())); | 40 mandatory_constraints[i].m_value.utf8())); |
| 47 } | 41 } |
| 48 | 42 |
| 49 blink::WebVector<blink::WebMediaConstraint> optional_constraints; | 43 blink::WebVector<blink::WebMediaConstraint> optional_constraints; |
| 50 constraints.getOptionalConstraints(optional_constraints); | 44 constraints.getOptionalConstraints(optional_constraints); |
| 51 for (size_t i = 0; i < optional_constraints.size(); i++) { | 45 for (size_t i = 0; i < optional_constraints.size(); i++) { |
| 52 optional->push_back(StreamOptions::Constraint( | 46 optional->push_back(StreamOptions::Constraint( |
| 53 optional_constraints[i].m_name.utf8(), | 47 optional_constraints[i].m_name.utf8(), |
| 54 optional_constraints[i].m_value.utf8())); | 48 optional_constraints[i].m_value.utf8())); |
| 55 } | 49 } |
| 56 } | 50 } |
| 57 | 51 |
| 58 static int g_next_request_id = 0; | 52 static int g_next_request_id = 0; |
| 59 | 53 |
| 60 void GetDefaultOutputDeviceParams( | |
| 61 int* output_sample_rate, int* output_buffer_size) { | |
| 62 // Fetch the default audio output hardware config. | |
| 63 media::AudioHardwareConfig* hardware_config = | |
| 64 RenderThreadImpl::current()->GetAudioHardwareConfig(); | |
| 65 *output_sample_rate = hardware_config->GetOutputSampleRate(); | |
| 66 *output_buffer_size = hardware_config->GetOutputBufferSize(); | |
| 67 } | |
| 68 | |
| 69 } // namespace | 54 } // namespace |
| 70 | 55 |
| 71 MediaStreamImpl::MediaStreamImpl( | 56 MediaStreamImpl::MediaStreamImpl( |
| 72 RenderView* render_view, | 57 RenderView* render_view, |
| 73 MediaStreamDispatcher* media_stream_dispatcher, | 58 MediaStreamDispatcher* media_stream_dispatcher, |
| 74 PeerConnectionDependencyFactory* dependency_factory) | 59 PeerConnectionDependencyFactory* dependency_factory) |
| 75 : RenderViewObserver(render_view), | 60 : RenderViewObserver(render_view), |
| 76 dependency_factory_(dependency_factory), | 61 dependency_factory_(dependency_factory), |
| 77 media_stream_dispatcher_(media_stream_dispatcher) { | 62 media_stream_dispatcher_(media_stream_dispatcher) { |
| 78 } | 63 } |
| (...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 178 DCHECK(CalledOnValidThread()); | 163 DCHECK(CalledOnValidThread()); |
| 179 UserMediaRequestInfo* request = FindUserMediaRequestInfo(user_media_request); | 164 UserMediaRequestInfo* request = FindUserMediaRequestInfo(user_media_request); |
| 180 if (request) { | 165 if (request) { |
| 181 // We can't abort the stream generation process. | 166 // We can't abort the stream generation process. |
| 182 // Instead, erase the request. Once the stream is generated we will stop the | 167 // Instead, erase the request. Once the stream is generated we will stop the |
| 183 // stream if the request does not exist. | 168 // stream if the request does not exist. |
| 184 DeleteUserMediaRequestInfo(request); | 169 DeleteUserMediaRequestInfo(request); |
| 185 } | 170 } |
| 186 } | 171 } |
| 187 | 172 |
| 188 blink::WebMediaStream MediaStreamImpl::GetMediaStream( | |
| 189 const GURL& url) { | |
| 190 return blink::WebMediaStreamRegistry::lookupMediaStreamDescriptor(url); | |
| 191 } | |
| 192 | |
| 193 bool MediaStreamImpl::IsMediaStream(const GURL& url) { | |
| 194 blink::WebMediaStream web_stream( | |
| 195 blink::WebMediaStreamRegistry::lookupMediaStreamDescriptor(url)); | |
| 196 | |
| 197 return (!web_stream.isNull() && | |
| 198 (MediaStream::GetMediaStream(web_stream) != NULL)); | |
| 199 } | |
| 200 | |
| 201 scoped_refptr<VideoFrameProvider> | |
| 202 MediaStreamImpl::GetVideoFrameProvider( | |
| 203 const GURL& url, | |
| 204 const base::Closure& error_cb, | |
| 205 const VideoFrameProvider::RepaintCB& repaint_cb) { | |
| 206 DCHECK(CalledOnValidThread()); | |
| 207 blink::WebMediaStream web_stream(GetMediaStream(url)); | |
| 208 | |
| 209 if (web_stream.isNull() || !web_stream.extraData()) | |
| 210 return NULL; // This is not a valid stream. | |
| 211 | |
| 212 DVLOG(1) << "MediaStreamImpl::GetVideoFrameProvider stream:" | |
| 213 << base::UTF16ToUTF8(web_stream.id()); | |
| 214 | |
| 215 blink::WebVector<blink::WebMediaStreamTrack> video_tracks; | |
| 216 web_stream.videoTracks(video_tracks); | |
| 217 if (video_tracks.isEmpty() || | |
| 218 !MediaStreamVideoTrack::GetTrack(video_tracks[0])) { | |
| 219 return NULL; | |
| 220 } | |
| 221 | |
| 222 return new RTCVideoRenderer(video_tracks[0], error_cb, repaint_cb); | |
| 223 } | |
| 224 | |
| 225 scoped_refptr<MediaStreamAudioRenderer> | |
| 226 MediaStreamImpl::GetAudioRenderer(const GURL& url, int render_frame_id) { | |
| 227 DCHECK(CalledOnValidThread()); | |
| 228 blink::WebMediaStream web_stream(GetMediaStream(url)); | |
| 229 | |
| 230 if (web_stream.isNull() || !web_stream.extraData()) | |
| 231 return NULL; // This is not a valid stream. | |
| 232 | |
| 233 DVLOG(1) << "MediaStreamImpl::GetAudioRenderer stream:" | |
| 234 << base::UTF16ToUTF8(web_stream.id()); | |
| 235 | |
| 236 MediaStream* native_stream = MediaStream::GetMediaStream(web_stream); | |
| 237 | |
| 238 // TODO(tommi): MediaStreams do not have a 'local or not' concept. | |
| 239 // Tracks _might_, but even so, we need to fix the data flow so that | |
| 240 // it works the same way for all track implementations, local, remote or what | |
| 241 // have you. | |
| 242 // In this function, we should simply create a renderer object that receives | |
| 243 // and mixes audio from all the tracks that belong to the media stream. | |
| 244 // We need to remove the |is_local| property from MediaStreamExtraData since | |
| 245 // this concept is peerconnection specific (is a previously recorded stream | |
| 246 // local or remote?). | |
| 247 if (native_stream->is_local()) { | |
| 248 // Create the local audio renderer if the stream contains audio tracks. | |
| 249 blink::WebVector<blink::WebMediaStreamTrack> audio_tracks; | |
| 250 web_stream.audioTracks(audio_tracks); | |
| 251 if (audio_tracks.isEmpty()) | |
| 252 return NULL; | |
| 253 | |
| 254 // TODO(xians): Add support for the case where the media stream contains | |
| 255 // multiple audio tracks. | |
| 256 return CreateLocalAudioRenderer(audio_tracks[0], render_frame_id); | |
| 257 } | |
| 258 | |
| 259 webrtc::MediaStreamInterface* stream = | |
| 260 MediaStream::GetAdapter(web_stream); | |
| 261 if (stream->GetAudioTracks().empty()) | |
| 262 return NULL; | |
| 263 | |
| 264 // This is a remote WebRTC media stream. | |
| 265 WebRtcAudioDeviceImpl* audio_device = | |
| 266 dependency_factory_->GetWebRtcAudioDevice(); | |
| 267 | |
| 268 // Share the existing renderer if any, otherwise create a new one. | |
| 269 scoped_refptr<WebRtcAudioRenderer> renderer(audio_device->renderer()); | |
| 270 if (!renderer.get()) { | |
| 271 renderer = CreateRemoteAudioRenderer(stream, render_frame_id); | |
| 272 | |
| 273 if (renderer.get() && !audio_device->SetAudioRenderer(renderer.get())) | |
| 274 renderer = NULL; | |
| 275 } | |
| 276 | |
| 277 return renderer.get() ? | |
| 278 renderer->CreateSharedAudioRendererProxy(stream) : NULL; | |
| 279 } | |
| 280 | |
| 281 // Callback from MediaStreamDispatcher. | 173 // Callback from MediaStreamDispatcher. |
| 282 // The requested stream have been generated by the MediaStreamDispatcher. | 174 // The requested stream have been generated by the MediaStreamDispatcher. |
| 283 void MediaStreamImpl::OnStreamGenerated( | 175 void MediaStreamImpl::OnStreamGenerated( |
| 284 int request_id, | 176 int request_id, |
| 285 const std::string& label, | 177 const std::string& label, |
| 286 const StreamDeviceInfoArray& audio_array, | 178 const StreamDeviceInfoArray& audio_array, |
| 287 const StreamDeviceInfoArray& video_array) { | 179 const StreamDeviceInfoArray& video_array) { |
| 288 DCHECK(CalledOnValidThread()); | 180 DCHECK(CalledOnValidThread()); |
| 289 DVLOG(1) << "MediaStreamImpl::OnStreamGenerated stream:" << label; | 181 DVLOG(1) << "MediaStreamImpl::OnStreamGenerated stream:" << label; |
| 290 | 182 |
| (...skipping 420 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 711 DVLOG(1) << "MediaStreamImpl::StopLocalSource(" | 603 DVLOG(1) << "MediaStreamImpl::StopLocalSource(" |
| 712 << "{device_id = " << source_impl->device_info().device.id << "})"; | 604 << "{device_id = " << source_impl->device_info().device.id << "})"; |
| 713 | 605 |
| 714 if (notify_dispatcher) | 606 if (notify_dispatcher) |
| 715 media_stream_dispatcher_->StopStreamDevice(source_impl->device_info()); | 607 media_stream_dispatcher_->StopStreamDevice(source_impl->device_info()); |
| 716 | 608 |
| 717 source_impl->ResetSourceStoppedCallback(); | 609 source_impl->ResetSourceStoppedCallback(); |
| 718 source_impl->StopSource(); | 610 source_impl->StopSource(); |
| 719 } | 611 } |
| 720 | 612 |
| 721 scoped_refptr<WebRtcAudioRenderer> MediaStreamImpl::CreateRemoteAudioRenderer( | |
| 722 webrtc::MediaStreamInterface* stream, | |
| 723 int render_frame_id) { | |
| 724 if (stream->GetAudioTracks().empty()) | |
| 725 return NULL; | |
| 726 | |
| 727 DVLOG(1) << "MediaStreamImpl::CreateRemoteAudioRenderer label:" | |
| 728 << stream->label(); | |
| 729 | |
| 730 // TODO(tommi): Change the default value of session_id to be | |
| 731 // StreamDeviceInfo::kNoId. Also update AudioOutputDevice etc. | |
| 732 int session_id = 0, sample_rate = 0, buffer_size = 0; | |
| 733 if (!GetAuthorizedDeviceInfoForAudioRenderer(&session_id, | |
| 734 &sample_rate, | |
| 735 &buffer_size)) { | |
| 736 GetDefaultOutputDeviceParams(&sample_rate, &buffer_size); | |
| 737 } | |
| 738 | |
| 739 return new WebRtcAudioRenderer( | |
| 740 stream, RenderViewObserver::routing_id(), render_frame_id, session_id, | |
| 741 sample_rate, buffer_size); | |
| 742 } | |
| 743 | |
| 744 scoped_refptr<WebRtcLocalAudioRenderer> | |
| 745 MediaStreamImpl::CreateLocalAudioRenderer( | |
| 746 const blink::WebMediaStreamTrack& audio_track, | |
| 747 int render_frame_id) { | |
| 748 DVLOG(1) << "MediaStreamImpl::CreateLocalAudioRenderer"; | |
| 749 | |
| 750 int session_id = 0, sample_rate = 0, buffer_size = 0; | |
| 751 if (!GetAuthorizedDeviceInfoForAudioRenderer(&session_id, | |
| 752 &sample_rate, | |
| 753 &buffer_size)) { | |
| 754 GetDefaultOutputDeviceParams(&sample_rate, &buffer_size); | |
| 755 } | |
| 756 | |
| 757 // Create a new WebRtcLocalAudioRenderer instance and connect it to the | |
| 758 // existing WebRtcAudioCapturer so that the renderer can use it as source. | |
| 759 return new WebRtcLocalAudioRenderer( | |
| 760 audio_track, | |
| 761 RenderViewObserver::routing_id(), | |
| 762 render_frame_id, | |
| 763 session_id, | |
| 764 buffer_size); | |
| 765 } | |
| 766 | |
| 767 bool MediaStreamImpl::GetAuthorizedDeviceInfoForAudioRenderer( | |
| 768 int* session_id, | |
| 769 int* output_sample_rate, | |
| 770 int* output_frames_per_buffer) { | |
| 771 DCHECK(CalledOnValidThread()); | |
| 772 WebRtcAudioDeviceImpl* audio_device = | |
| 773 dependency_factory_->GetWebRtcAudioDevice(); | |
| 774 if (!audio_device) | |
| 775 return false; | |
| 776 | |
| 777 return audio_device->GetAuthorizedDeviceInfoForAudioRenderer( | |
| 778 session_id, output_sample_rate, output_frames_per_buffer); | |
| 779 } | |
| 780 | |
| 781 MediaStreamImpl::UserMediaRequestInfo::UserMediaRequestInfo( | 613 MediaStreamImpl::UserMediaRequestInfo::UserMediaRequestInfo( |
| 782 int request_id, | 614 int request_id, |
| 783 blink::WebFrame* frame, | 615 blink::WebFrame* frame, |
| 784 const blink::WebUserMediaRequest& request, | 616 const blink::WebUserMediaRequest& request, |
| 785 bool enable_automatic_output_device_selection) | 617 bool enable_automatic_output_device_selection) |
| 786 : request_id(request_id), | 618 : request_id(request_id), |
| 787 generated(false), | 619 generated(false), |
| 788 enable_automatic_output_device_selection( | 620 enable_automatic_output_device_selection( |
| 789 enable_automatic_output_device_selection), | 621 enable_automatic_output_device_selection), |
| 790 frame(frame), | 622 frame(frame), |
| (...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 877 sources_.begin(); | 709 sources_.begin(); |
| 878 it != sources_.end(); ++it) { | 710 it != sources_.end(); ++it) { |
| 879 if (source.id() == it->id()) { | 711 if (source.id() == it->id()) { |
| 880 sources_.erase(it); | 712 sources_.erase(it); |
| 881 return; | 713 return; |
| 882 } | 714 } |
| 883 } | 715 } |
| 884 } | 716 } |
| 885 | 717 |
| 886 } // namespace content | 718 } // namespace content |
| OLD | NEW |