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.
5 #include "content/renderer/media/media_stream_center.h"
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_dependency_factory.h"
17 #include "content/renderer/media/media_stream_source.h"
18 #include "content/renderer/media/media_stream_video_source.h"
19 #include "content/renderer/media/media_stream_video_track.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"
31 using blink::WebFrame;
38 void CreateNativeAudioMediaStreamTrack(
39 const blink::WebMediaStreamTrack& track,
40 MediaStreamDependencyFactory* factory) {
41 DCHECK(!track.extraData());
42 blink::WebMediaStreamSource source = track.source();
43 DCHECK_EQ(source.type(), blink::WebMediaStreamSource::TypeAudio);
44 factory->CreateLocalAudioTrack(track);
47 void CreateNativeVideoMediaStreamTrack(
48 const blink::WebMediaStreamTrack& track,
49 MediaStreamDependencyFactory* factory) {
50 DCHECK(track.extraData() == NULL);
51 blink::WebMediaStreamSource source = track.source();
52 DCHECK_EQ(source.type(), blink::WebMediaStreamSource::TypeVideo);
53 MediaStreamVideoSource* native_source =
54 MediaStreamVideoSource::GetVideoSource(source);
56 // TODO(perkj): Implement support for sources from
57 // remote MediaStreams.
61 blink::WebMediaStreamTrack writable_track(track);
62 writable_track.setExtraData(
63 new MediaStreamVideoTrack(native_source, source.constraints(),
64 MediaStreamVideoSource::ConstraintsCallback(),
65 track.isEnabled(), factory));
68 void CreateNativeMediaStreamTrack(const blink::WebMediaStreamTrack& track,
69 MediaStreamDependencyFactory* factory) {
70 DCHECK(!track.isNull() && !track.extraData());
71 DCHECK(!track.source().isNull());
73 switch (track.source().type()) {
74 case blink::WebMediaStreamSource::TypeAudio:
75 CreateNativeAudioMediaStreamTrack(track, factory);
77 case blink::WebMediaStreamSource::TypeVideo:
78 CreateNativeVideoMediaStreamTrack(track, factory);
85 MediaStreamCenter::MediaStreamCenter(blink::WebMediaStreamCenterClient* client,
86 MediaStreamDependencyFactory* factory)
87 : rtc_factory_(factory), next_request_id_(0) {}
89 MediaStreamCenter::~MediaStreamCenter() {}
91 bool MediaStreamCenter::getMediaStreamTrackSources(
92 const blink::WebMediaStreamTrackSourcesRequest& request) {
93 if (!CommandLine::ForCurrentProcess()->HasSwitch(
94 switches::kDisableDeviceEnumeration)) {
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, GURL(request.origin().utf8())));
104 void MediaStreamCenter::didCreateMediaStreamTrack(
105 const blink::WebMediaStreamTrack& track) {
106 DVLOG(1) << "MediaStreamCenter::didCreateMediaStreamTrack";
107 CreateNativeMediaStreamTrack(track, rtc_factory_);
110 void MediaStreamCenter::didEnableMediaStreamTrack(
111 const blink::WebMediaStreamTrack& track) {
112 MediaStreamTrack* native_track =
113 MediaStreamTrack::GetTrack(track);
115 native_track->SetEnabled(true);
118 void MediaStreamCenter::didDisableMediaStreamTrack(
119 const blink::WebMediaStreamTrack& track) {
120 MediaStreamTrack* native_track =
121 MediaStreamTrack::GetTrack(track);
123 native_track->SetEnabled(false);
126 bool MediaStreamCenter::didStopMediaStreamTrack(
127 const blink::WebMediaStreamTrack& track) {
128 DVLOG(1) << "MediaStreamCenter::didStopMediaStreamTrack";
129 blink::WebMediaStreamSource source = track.source();
130 MediaStreamSource* extra_data =
131 static_cast<MediaStreamSource*>(source.extraData());
133 DVLOG(1) << "didStopMediaStreamTrack called on a remote track.";
137 extra_data->StopSource();
141 blink::WebAudioSourceProvider*
142 MediaStreamCenter::createWebAudioSourceFromMediaStreamTrack(
143 const blink::WebMediaStreamTrack& track) {
144 DVLOG(1) << "MediaStreamCenter::createWebAudioSourceFromMediaStreamTrack";
145 MediaStreamTrack* media_stream_track =
146 static_cast<MediaStreamTrack*>(track.extraData());
147 // Only local audio track is supported now.
148 // TODO(xians): Support remote audio track.
149 if (!media_stream_track || !media_stream_track->is_local_track ()) {
154 blink::WebMediaStreamSource source = track.source();
155 DCHECK_EQ(source.type(), blink::WebMediaStreamSource::TypeAudio);
156 WebRtcLocalAudioSourceProvider* source_provider =
157 new WebRtcLocalAudioSourceProvider(track);
158 return source_provider;
161 void MediaStreamCenter::didStopLocalMediaStream(
162 const blink::WebMediaStream& stream) {
163 DVLOG(1) << "MediaStreamCenter::didStopLocalMediaStream";
164 MediaStream* native_stream = MediaStream::GetMediaStream(stream);
165 if (!native_stream) {
170 // TODO(perkj): MediaStream::Stop is being deprecated. But for the moment we
171 // need to support the old behavior and the new. Since we only create one
172 // source object per actual device- we need to fake stopping a
173 // MediaStreamTrack by disabling it if the same device is used as source by
174 // multiple tracks. Note that disabling a track here, don't affect the
175 // enabled property in JS.
176 blink::WebVector<blink::WebMediaStreamTrack> audio_tracks;
177 stream.audioTracks(audio_tracks);
178 for (size_t i = 0; i < audio_tracks.size(); ++i)
179 didDisableMediaStreamTrack(audio_tracks[i]);
181 blink::WebVector<blink::WebMediaStreamTrack> video_tracks;
182 stream.videoTracks(video_tracks);
183 for (size_t i = 0; i < video_tracks.size(); ++i)
184 didDisableMediaStreamTrack(video_tracks[i]);
186 native_stream->OnStreamStopped();
189 void MediaStreamCenter::didCreateMediaStream(blink::WebMediaStream& stream) {
190 DVLOG(1) << "MediaStreamCenter::didCreateMediaStream";
191 blink::WebMediaStream writable_stream(stream);
192 MediaStream* native_stream(
193 new MediaStream(rtc_factory_,
194 MediaStream::StreamStopCallback(),
196 writable_stream.setExtraData(native_stream);
198 // TODO(perkj): Remove track creation once crbug/294145 is fixed. A track
199 // should already have been created before reaching here.
200 blink::WebVector<blink::WebMediaStreamTrack> audio_tracks;
201 stream.audioTracks(audio_tracks);
202 for (size_t i = 0; i < audio_tracks.size(); ++i) {
203 if (!MediaStreamTrack::GetTrack(audio_tracks[i]))
204 CreateNativeMediaStreamTrack(audio_tracks[i], rtc_factory_);
207 blink::WebVector<blink::WebMediaStreamTrack> video_tracks;
208 stream.videoTracks(video_tracks);
209 for (size_t i = 0; i < video_tracks.size(); ++i) {
210 if (!MediaStreamTrack::GetTrack(video_tracks[i]))
211 CreateNativeMediaStreamTrack(video_tracks[i], rtc_factory_);
216 bool MediaStreamCenter::didAddMediaStreamTrack(
217 const blink::WebMediaStream& stream,
218 const blink::WebMediaStreamTrack& track) {
219 DVLOG(1) << "MediaStreamCenter::didAddMediaStreamTrack";
220 // TODO(perkj): Remove track creation once crbug/294145 is fixed. A track
221 // should already have been created before reaching here.
222 if (!MediaStreamTrack::GetTrack(track))
223 CreateNativeMediaStreamTrack(track, rtc_factory_);
224 MediaStream* native_stream = MediaStream::GetMediaStream(stream);
225 return native_stream->AddTrack(stream, track);
228 bool MediaStreamCenter::didRemoveMediaStreamTrack(
229 const blink::WebMediaStream& stream,
230 const blink::WebMediaStreamTrack& track) {
231 DVLOG(1) << "MediaStreamCenter::didRemoveMediaStreamTrack";
232 MediaStream* native_stream = MediaStream::GetMediaStream(stream);
233 return native_stream->RemoveTrack(stream, track);
236 bool MediaStreamCenter::OnControlMessageReceived(const IPC::Message& message) {
238 IPC_BEGIN_MESSAGE_MAP(MediaStreamCenter, message)
239 IPC_MESSAGE_HANDLER(MediaStreamMsg_GetSourcesACK,
240 OnGetSourcesComplete)
241 IPC_MESSAGE_UNHANDLED(handled = false)
242 IPC_END_MESSAGE_MAP()
246 void MediaStreamCenter::OnGetSourcesComplete(
248 const content::StreamDeviceInfoArray& devices) {
249 RequestMap::iterator request_it = requests_.find(request_id);
250 DCHECK(request_it != requests_.end());
252 blink::WebVector<blink::WebSourceInfo> sourceInfos(devices.size());
253 for (size_t i = 0; i < devices.size(); ++i) {
254 const MediaStreamDevice& device = devices[i].device;
255 DCHECK(device.type == MEDIA_DEVICE_AUDIO_CAPTURE ||
256 device.type == MEDIA_DEVICE_VIDEO_CAPTURE);
257 blink::WebSourceInfo::VideoFacingMode video_facing;
258 switch (device.video_facing) {
259 case MEDIA_VIDEO_FACING_USER:
260 video_facing = blink::WebSourceInfo::VideoFacingModeUser;
262 case MEDIA_VIDEO_FACING_ENVIRONMENT:
263 video_facing = blink::WebSourceInfo::VideoFacingModeEnvironment;
266 video_facing = blink::WebSourceInfo::VideoFacingModeNone;
270 .initialize(blink::WebString::fromUTF8(device.id),
271 device.type == MEDIA_DEVICE_AUDIO_CAPTURE
272 ? blink::WebSourceInfo::SourceKindAudio
273 : blink::WebSourceInfo::SourceKindVideo,
274 blink::WebString::fromUTF8(device.name),
277 request_it->second.requestSucceeded(sourceInfos);
280 } // namespace content