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 "base/memory/scoped_ptr.h" 12 #include "base/strings/string_number_conversions.h" 13 #include "base/strings/utf_string_conversions.h" 14 #include "content/common/media/media_stream_messages.h" 15 #include "content/public/common/content_switches.h" 16 #include "content/public/renderer/render_thread.h" 17 #include "content/renderer/media/media_stream_dependency_factory.h" 18 #include "content/renderer/media/media_stream_extra_data.h" 19 #include "content/renderer/media/media_stream_source_extra_data.h" 20 #include "content/renderer/media/media_stream_track_extra_data.h" 21 #include "content/renderer/render_view_impl.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 #include "third_party/libjingle/source/talk/app/webrtc/jsep.h" 31 32 using blink::WebFrame; 33 using blink::WebView; 34 35 namespace content { 36 37 MediaStreamCenter::MediaStreamCenter(blink::WebMediaStreamCenterClient* client, 38 MediaStreamDependencyFactory* factory) 39 : rtc_factory_(factory), next_request_id_(0) {} 40 41 MediaStreamCenter::~MediaStreamCenter() {} 42 43 bool MediaStreamCenter::getMediaStreamTrackSources( 44 const blink::WebMediaStreamTrackSourcesRequest& request) { 45 if (!CommandLine::ForCurrentProcess()->HasSwitch( 46 switches::kDisableDeviceEnumeration)) { 47 int request_id = next_request_id_++; 48 requests_.insert(std::make_pair(request_id, request)); 49 RenderThread::Get()->Send(new MediaStreamHostMsg_GetSources( 50 request_id, GURL(request.origin().utf8()))); 51 return true; 52 } 53 return false; 54 } 55 56 void MediaStreamCenter::didCreateMediaStreamTrack( 57 const blink::WebMediaStreamTrack& track) { 58 if (!rtc_factory_) 59 return; 60 rtc_factory_->CreateNativeMediaStreamTrack(track); 61 } 62 63 void MediaStreamCenter::didEnableMediaStreamTrack( 64 const blink::WebMediaStreamTrack& track) { 65 webrtc::MediaStreamTrackInterface* native_track = 66 MediaStreamDependencyFactory::GetNativeMediaStreamTrack(track); 67 if (native_track) 68 native_track->set_enabled(true); 69 } 70 71 void MediaStreamCenter::didDisableMediaStreamTrack( 72 const blink::WebMediaStreamTrack& track) { 73 webrtc::MediaStreamTrackInterface* native_track = 74 MediaStreamDependencyFactory::GetNativeMediaStreamTrack(track); 75 if (native_track) 76 native_track->set_enabled(false); 77 } 78 79 bool MediaStreamCenter::didStopMediaStreamTrack( 80 const blink::WebMediaStreamTrack& track) { 81 DVLOG(1) << "MediaStreamCenter::didStopMediaStreamTrack"; 82 blink::WebMediaStreamSource source = track.source(); 83 MediaStreamSourceExtraData* extra_data = 84 static_cast<MediaStreamSourceExtraData*>(source.extraData()); 85 if (!extra_data) { 86 DVLOG(1) << "didStopMediaStreamTrack called on a remote track."; 87 return false; 88 } 89 90 extra_data->OnLocalSourceStop(); 91 return true; 92 } 93 94 void MediaStreamCenter::didStopLocalMediaStream( 95 const blink::WebMediaStream& stream) { 96 DVLOG(1) << "MediaStreamCenter::didStopLocalMediaStream"; 97 MediaStreamExtraData* extra_data = 98 static_cast<MediaStreamExtraData*>(stream.extraData()); 99 if (!extra_data) { 100 NOTREACHED(); 101 return; 102 } 103 104 // TODO(perkj): MediaStream::Stop is being deprecated. But for the moment we 105 // need to support the old behavior and the new. Since we only create one 106 // source object per actual device- we need to fake stopping a 107 // MediaStreamTrack by disabling it if the same device is used as source by 108 // multiple tracks. Note that disabling a track here, don't affect the 109 // enabled property in JS. 110 blink::WebVector<blink::WebMediaStreamTrack> audio_tracks; 111 stream.audioTracks(audio_tracks); 112 for (size_t i = 0; i < audio_tracks.size(); ++i) 113 didDisableMediaStreamTrack(audio_tracks[i]); 114 115 blink::WebVector<blink::WebMediaStreamTrack> video_tracks; 116 stream.videoTracks(video_tracks); 117 for (size_t i = 0; i < video_tracks.size(); ++i) 118 didDisableMediaStreamTrack(video_tracks[i]); 119 120 extra_data->OnLocalStreamStop(); 121 } 122 123 void MediaStreamCenter::didCreateMediaStream( 124 blink::WebMediaStream& stream) { 125 if (!rtc_factory_) 126 return; 127 rtc_factory_->CreateNativeLocalMediaStream(&stream); 128 } 129 130 bool MediaStreamCenter::didAddMediaStreamTrack( 131 const blink::WebMediaStream& stream, 132 const blink::WebMediaStreamTrack& track) { 133 if (!rtc_factory_) 134 return false; 135 136 return rtc_factory_->AddNativeMediaStreamTrack(stream, track); 137 } 138 139 bool MediaStreamCenter::didRemoveMediaStreamTrack( 140 const blink::WebMediaStream& stream, 141 const blink::WebMediaStreamTrack& track) { 142 if (!rtc_factory_) 143 return false; 144 145 return rtc_factory_->RemoveNativeMediaStreamTrack(stream, track); 146 } 147 148 bool MediaStreamCenter::OnControlMessageReceived(const IPC::Message& message) { 149 bool handled = true; 150 IPC_BEGIN_MESSAGE_MAP(MediaStreamCenter, message) 151 IPC_MESSAGE_HANDLER(MediaStreamMsg_GetSourcesACK, 152 OnGetSourcesComplete) 153 IPC_MESSAGE_UNHANDLED(handled = false) 154 IPC_END_MESSAGE_MAP() 155 return handled; 156 } 157 158 void MediaStreamCenter::OnGetSourcesComplete( 159 int request_id, 160 const content::StreamDeviceInfoArray& devices) { 161 RequestMap::iterator request_it = requests_.find(request_id); 162 DCHECK(request_it != requests_.end()); 163 164 blink::WebVector<blink::WebSourceInfo> sourceInfos(devices.size()); 165 for (size_t i = 0; i < devices.size(); ++i) { 166 const MediaStreamDevice& device = devices[i].device; 167 DCHECK(device.type == MEDIA_DEVICE_AUDIO_CAPTURE || 168 device.type == MEDIA_DEVICE_VIDEO_CAPTURE); 169 blink::WebSourceInfo::VideoFacingMode video_facing; 170 switch (device.video_facing) { 171 case MEDIA_VIDEO_FACING_USER: 172 video_facing = blink::WebSourceInfo::VideoFacingModeUser; 173 break; 174 case MEDIA_VIDEO_FACING_ENVIRONMENT: 175 video_facing = blink::WebSourceInfo::VideoFacingModeEnvironment; 176 break; 177 default: 178 video_facing = blink::WebSourceInfo::VideoFacingModeNone; 179 } 180 181 sourceInfos[i] 182 .initialize(blink::WebString::fromUTF8(device.id), 183 device.type == MEDIA_DEVICE_AUDIO_CAPTURE 184 ? blink::WebSourceInfo::SourceKindAudio 185 : blink::WebSourceInfo::SourceKindVideo, 186 blink::WebString::fromUTF8(device.name), 187 video_facing); 188 } 189 request_it->second.requestSucceeded(sourceInfos); 190 } 191 192 } // namespace content 193