Upstream version 7.35.139.0
[platform/framework/web/crosswalk.git] / src / content / renderer / media / media_stream_center.cc
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_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"
30
31 using blink::WebFrame;
32 using blink::WebView;
33
34 namespace content {
35
36 namespace {
37
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);
45 }
46
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);
55   if (!native_source) {
56     // TODO(perkj): Implement support for sources from
57     // remote MediaStreams.
58     NOTIMPLEMENTED();
59     return;
60   }
61   blink::WebMediaStreamTrack writable_track(track);
62   writable_track.setExtraData(
63       new MediaStreamVideoTrack(native_source, source.constraints(),
64                                 MediaStreamVideoSource::ConstraintsCallback(),
65                                 track.isEnabled(), factory));
66 }
67
68 void CreateNativeMediaStreamTrack(const blink::WebMediaStreamTrack& track,
69                                   MediaStreamDependencyFactory* factory) {
70   DCHECK(!track.isNull() && !track.extraData());
71   DCHECK(!track.source().isNull());
72
73   switch (track.source().type()) {
74     case blink::WebMediaStreamSource::TypeAudio:
75       CreateNativeAudioMediaStreamTrack(track, factory);
76       break;
77     case blink::WebMediaStreamSource::TypeVideo:
78       CreateNativeVideoMediaStreamTrack(track, factory);
79       break;
80   }
81 }
82
83 }  // namespace
84
85 MediaStreamCenter::MediaStreamCenter(blink::WebMediaStreamCenterClient* client,
86                                      MediaStreamDependencyFactory* factory)
87     : rtc_factory_(factory), next_request_id_(0) {}
88
89 MediaStreamCenter::~MediaStreamCenter() {}
90
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())));
99     return true;
100   }
101   return false;
102 }
103
104 void MediaStreamCenter::didCreateMediaStreamTrack(
105     const blink::WebMediaStreamTrack& track) {
106   DVLOG(1) << "MediaStreamCenter::didCreateMediaStreamTrack";
107   CreateNativeMediaStreamTrack(track, rtc_factory_);
108 }
109
110 void MediaStreamCenter::didEnableMediaStreamTrack(
111     const blink::WebMediaStreamTrack& track) {
112   MediaStreamTrack* native_track =
113       MediaStreamTrack::GetTrack(track);
114   if (native_track)
115     native_track->SetEnabled(true);
116 }
117
118 void MediaStreamCenter::didDisableMediaStreamTrack(
119     const blink::WebMediaStreamTrack& track) {
120   MediaStreamTrack* native_track =
121       MediaStreamTrack::GetTrack(track);
122   if (native_track)
123     native_track->SetEnabled(false);
124 }
125
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());
132   if (!extra_data) {
133     DVLOG(1) << "didStopMediaStreamTrack called on a remote track.";
134     return false;
135   }
136
137   extra_data->StopSource();
138   return true;
139 }
140
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 ()) {
150     NOTIMPLEMENTED();
151     return NULL;
152   }
153
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;
159 }
160
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) {
166     NOTREACHED();
167     return;
168   }
169
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]);
180
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]);
185
186   native_stream->OnStreamStopped();
187 }
188
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(),
195                       stream));
196   writable_stream.setExtraData(native_stream);
197
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_);
205   }
206
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_);
212   }
213
214 }
215
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);
226 }
227
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);
234 }
235
236 bool MediaStreamCenter::OnControlMessageReceived(const IPC::Message& message) {
237   bool handled = true;
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()
243   return handled;
244 }
245
246 void MediaStreamCenter::OnGetSourcesComplete(
247     int request_id,
248     const content::StreamDeviceInfoArray& devices) {
249   RequestMap::iterator request_it = requests_.find(request_id);
250   DCHECK(request_it != requests_.end());
251
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;
261         break;
262       case MEDIA_VIDEO_FACING_ENVIRONMENT:
263         video_facing = blink::WebSourceInfo::VideoFacingModeEnvironment;
264         break;
265       default:
266         video_facing = blink::WebSourceInfo::VideoFacingModeNone;
267     }
268
269     sourceInfos[i]
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),
275                     video_facing);
276   }
277   request_it->second.requestSucceeded(sourceInfos);
278 }
279
280 }  // namespace content