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 3// found in the LICENSE file. 4 5#include "content/renderer/media/media_stream_center.h" 6 7#include <string> 8 9#include "base/command_line.h" 10#include "base/logging.h" 11#include "content/common/media/media_stream_messages.h" 12#include "content/public/common/content_switches.h" 13#include "content/public/renderer/media_stream_audio_sink.h" 14#include "content/public/renderer/render_thread.h" 15#include "content/renderer/media/media_stream.h" 16#include "content/renderer/media/media_stream_source.h" 17#include "content/renderer/media/media_stream_video_source.h" 18#include "content/renderer/media/media_stream_video_track.h" 19#include "content/renderer/media/webrtc/peer_connection_dependency_factory.h" 20#include "content/renderer/media/webrtc_local_audio_source_provider.h" 21#include "third_party/WebKit/public/platform/WebMediaConstraints.h" 22#include "third_party/WebKit/public/platform/WebMediaStream.h" 23#include "third_party/WebKit/public/platform/WebMediaStreamCenterClient.h" 24#include "third_party/WebKit/public/platform/WebMediaStreamSource.h" 25#include "third_party/WebKit/public/platform/WebMediaStreamTrack.h" 26#include "third_party/WebKit/public/platform/WebMediaStreamTrackSourcesRequest.h" 27#include "third_party/WebKit/public/platform/WebSourceInfo.h" 28#include "third_party/WebKit/public/platform/WebVector.h" 29#include "third_party/WebKit/public/web/WebFrame.h" 30 31using blink::WebFrame; 32using blink::WebView; 33 34namespace content { 35 36namespace { 37 38void CreateNativeAudioMediaStreamTrack( 39 const blink::WebMediaStreamTrack& track, 40 PeerConnectionDependencyFactory* factory) { 41 DCHECK(!track.extraData()); 42 blink::WebMediaStreamSource source = track.source(); 43 DCHECK_EQ(source.type(), blink::WebMediaStreamSource::TypeAudio); 44 factory->CreateLocalAudioTrack(track); 45} 46 47void CreateNativeVideoMediaStreamTrack( 48 const blink::WebMediaStreamTrack& track) { 49 DCHECK(track.extraData() == NULL); 50 blink::WebMediaStreamSource source = track.source(); 51 DCHECK_EQ(source.type(), blink::WebMediaStreamSource::TypeVideo); 52 MediaStreamVideoSource* native_source = 53 MediaStreamVideoSource::GetVideoSource(source); 54 DCHECK(native_source); 55 blink::WebMediaStreamTrack writable_track(track); 56 // TODO(perkj): The constraints to use here should be passed from blink when 57 // a new track is created. For cloning, it should be the constraints of the 58 // cloned track and not the originating source. 59 // Also - source.constraints() returns an uninitialized constraint if the 60 // source is coming from a remote video track. See http://crbug/287805. 61 blink::WebMediaConstraints constraints = source.constraints(); 62 if (constraints.isNull()) 63 constraints.initialize(); 64 writable_track.setExtraData( 65 new MediaStreamVideoTrack(native_source, constraints, 66 MediaStreamVideoSource::ConstraintsCallback(), 67 track.isEnabled())); 68} 69 70void CreateNativeMediaStreamTrack(const blink::WebMediaStreamTrack& track, 71 PeerConnectionDependencyFactory* factory) { 72 DCHECK(!track.isNull() && !track.extraData()); 73 DCHECK(!track.source().isNull()); 74 75 switch (track.source().type()) { 76 case blink::WebMediaStreamSource::TypeAudio: 77 CreateNativeAudioMediaStreamTrack(track, factory); 78 break; 79 case blink::WebMediaStreamSource::TypeVideo: 80 CreateNativeVideoMediaStreamTrack(track); 81 break; 82 } 83} 84 85} // namespace 86 87MediaStreamCenter::MediaStreamCenter(blink::WebMediaStreamCenterClient* client, 88 PeerConnectionDependencyFactory* factory) 89 : rtc_factory_(factory), next_request_id_(0) {} 90 91MediaStreamCenter::~MediaStreamCenter() {} 92 93bool MediaStreamCenter::getMediaStreamTrackSources( 94 const blink::WebMediaStreamTrackSourcesRequest& request) { 95 int request_id = next_request_id_++; 96 requests_.insert(std::make_pair(request_id, request)); 97 RenderThread::Get()->Send(new MediaStreamHostMsg_GetSources( 98 request_id, 99 GURL(request.origin().utf8()))); 100 return true; 101} 102 103void MediaStreamCenter::didCreateMediaStreamTrack( 104 const blink::WebMediaStreamTrack& track) { 105 DVLOG(1) << "MediaStreamCenter::didCreateMediaStreamTrack"; 106 CreateNativeMediaStreamTrack(track, rtc_factory_); 107} 108 109void MediaStreamCenter::didEnableMediaStreamTrack( 110 const blink::WebMediaStreamTrack& track) { 111 MediaStreamTrack* native_track = 112 MediaStreamTrack::GetTrack(track); 113 if (native_track) 114 native_track->SetEnabled(true); 115} 116 117void MediaStreamCenter::didDisableMediaStreamTrack( 118 const blink::WebMediaStreamTrack& track) { 119 MediaStreamTrack* native_track = 120 MediaStreamTrack::GetTrack(track); 121 if (native_track) 122 native_track->SetEnabled(false); 123} 124 125bool MediaStreamCenter::didStopMediaStreamTrack( 126 const blink::WebMediaStreamTrack& track) { 127 DVLOG(1) << "MediaStreamCenter::didStopMediaStreamTrack"; 128 MediaStreamTrack* native_track = MediaStreamTrack::GetTrack(track); 129 native_track->Stop(); 130 return true; 131} 132 133blink::WebAudioSourceProvider* 134MediaStreamCenter::createWebAudioSourceFromMediaStreamTrack( 135 const blink::WebMediaStreamTrack& track) { 136 DVLOG(1) << "MediaStreamCenter::createWebAudioSourceFromMediaStreamTrack"; 137 MediaStreamTrack* media_stream_track = 138 static_cast<MediaStreamTrack*>(track.extraData()); 139 // Only local audio track is supported now. 140 // TODO(xians): Support remote audio track. 141 if (!media_stream_track || !media_stream_track->is_local_track()) { 142 NOTIMPLEMENTED(); 143 return NULL; 144 } 145 146 blink::WebMediaStreamSource source = track.source(); 147 DCHECK_EQ(source.type(), blink::WebMediaStreamSource::TypeAudio); 148 WebRtcLocalAudioSourceProvider* source_provider = 149 new WebRtcLocalAudioSourceProvider(track); 150 return source_provider; 151} 152 153void MediaStreamCenter::didStopLocalMediaStream( 154 const blink::WebMediaStream& stream) { 155 DVLOG(1) << "MediaStreamCenter::didStopLocalMediaStream"; 156 MediaStream* native_stream = MediaStream::GetMediaStream(stream); 157 if (!native_stream) { 158 NOTREACHED(); 159 return; 160 } 161 162 // TODO(perkj): MediaStream::Stop is being deprecated. But for the moment we 163 // need to support both MediaStream::Stop and MediaStreamTrack::Stop. 164 blink::WebVector<blink::WebMediaStreamTrack> audio_tracks; 165 stream.audioTracks(audio_tracks); 166 for (size_t i = 0; i < audio_tracks.size(); ++i) 167 didStopMediaStreamTrack(audio_tracks[i]); 168 169 blink::WebVector<blink::WebMediaStreamTrack> video_tracks; 170 stream.videoTracks(video_tracks); 171 for (size_t i = 0; i < video_tracks.size(); ++i) 172 didStopMediaStreamTrack(video_tracks[i]); 173} 174 175void MediaStreamCenter::didCreateMediaStream(blink::WebMediaStream& stream) { 176 DVLOG(1) << "MediaStreamCenter::didCreateMediaStream"; 177 blink::WebMediaStream writable_stream(stream); 178 MediaStream* native_stream( 179 new MediaStream(stream)); 180 writable_stream.setExtraData(native_stream); 181 182 blink::WebVector<blink::WebMediaStreamTrack> video_tracks; 183 stream.videoTracks(video_tracks); 184 for (size_t i = 0; i < video_tracks.size(); ++i) { 185 if (!MediaStreamTrack::GetTrack(video_tracks[i])) 186 CreateNativeMediaStreamTrack(video_tracks[i], rtc_factory_); 187 } 188} 189 190bool MediaStreamCenter::didAddMediaStreamTrack( 191 const blink::WebMediaStream& stream, 192 const blink::WebMediaStreamTrack& track) { 193 DVLOG(1) << "MediaStreamCenter::didAddMediaStreamTrack"; 194 MediaStream* native_stream = MediaStream::GetMediaStream(stream); 195 return native_stream->AddTrack(track); 196} 197 198bool MediaStreamCenter::didRemoveMediaStreamTrack( 199 const blink::WebMediaStream& stream, 200 const blink::WebMediaStreamTrack& track) { 201 DVLOG(1) << "MediaStreamCenter::didRemoveMediaStreamTrack"; 202 MediaStream* native_stream = MediaStream::GetMediaStream(stream); 203 return native_stream->RemoveTrack(track); 204} 205 206bool MediaStreamCenter::OnControlMessageReceived(const IPC::Message& message) { 207 bool handled = true; 208 IPC_BEGIN_MESSAGE_MAP(MediaStreamCenter, message) 209 IPC_MESSAGE_HANDLER(MediaStreamMsg_GetSourcesACK, 210 OnGetSourcesComplete) 211 IPC_MESSAGE_UNHANDLED(handled = false) 212 IPC_END_MESSAGE_MAP() 213 return handled; 214} 215 216void MediaStreamCenter::OnGetSourcesComplete( 217 int request_id, 218 const content::StreamDeviceInfoArray& devices) { 219 RequestMap::iterator request_it = requests_.find(request_id); 220 DCHECK(request_it != requests_.end()); 221 222 blink::WebVector<blink::WebSourceInfo> sourceInfos(devices.size()); 223 for (size_t i = 0; i < devices.size(); ++i) { 224 const MediaStreamDevice& device = devices[i].device; 225 DCHECK(device.type == MEDIA_DEVICE_AUDIO_CAPTURE || 226 device.type == MEDIA_DEVICE_VIDEO_CAPTURE); 227 blink::WebSourceInfo::VideoFacingMode video_facing; 228 switch (device.video_facing) { 229 case MEDIA_VIDEO_FACING_USER: 230 video_facing = blink::WebSourceInfo::VideoFacingModeUser; 231 break; 232 case MEDIA_VIDEO_FACING_ENVIRONMENT: 233 video_facing = blink::WebSourceInfo::VideoFacingModeEnvironment; 234 break; 235 default: 236 video_facing = blink::WebSourceInfo::VideoFacingModeNone; 237 } 238 239 sourceInfos[i] 240 .initialize(blink::WebString::fromUTF8(device.id), 241 device.type == MEDIA_DEVICE_AUDIO_CAPTURE 242 ? blink::WebSourceInfo::SourceKindAudio 243 : blink::WebSourceInfo::SourceKindVideo, 244 blink::WebString::fromUTF8(device.name), 245 video_facing); 246 } 247 request_it->second.requestSucceeded(sourceInfos); 248} 249 250} // namespace content 251