blob: 7f5e64aa187ffe65a2b1995e102f5a64b5809aef [file] [log] [blame]
Torne (Richard Coles)58218062012-11-14 11:43:16 +00001// 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_dependency_factory.h"
6
7#include <vector>
8
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +01009#include "base/command_line.h"
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +010010#include "base/strings/utf_string_conversions.h"
Torne (Richard Coles)58218062012-11-14 11:43:16 +000011#include "base/synchronization/waitable_event.h"
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +010012#include "content/public/common/content_switches.h"
Torne (Richard Coles)58218062012-11-14 11:43:16 +000013#include "content/renderer/media/media_stream_source_extra_data.h"
Ben Murdochca12bfa2013-07-23 11:17:05 +010014#include "content/renderer/media/peer_connection_identity_service.h"
Torne (Richard Coles)58218062012-11-14 11:43:16 +000015#include "content/renderer/media/rtc_media_constraints.h"
16#include "content/renderer/media/rtc_peer_connection_handler.h"
17#include "content/renderer/media/rtc_video_capturer.h"
Ben Murdoch7dbb3d52013-07-17 14:55:54 +010018#include "content/renderer/media/rtc_video_decoder_factory.h"
Torne (Richard Coles)58218062012-11-14 11:43:16 +000019#include "content/renderer/media/video_capture_impl_manager.h"
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000020#include "content/renderer/media/webaudio_capturer_source.h"
Torne (Richard Coles)58218062012-11-14 11:43:16 +000021#include "content/renderer/media/webrtc_audio_device_impl.h"
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +010022#include "content/renderer/media/webrtc_local_audio_track.h"
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +010023#include "content/renderer/media/webrtc_logging_initializer.h"
Torne (Richard Coles)58218062012-11-14 11:43:16 +000024#include "content/renderer/media/webrtc_uma_histograms.h"
25#include "content/renderer/p2p/ipc_network_manager.h"
26#include "content/renderer/p2p/ipc_socket_factory.h"
27#include "content/renderer/p2p/port_allocator.h"
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +010028#include "content/renderer/render_thread_impl.h"
Torne (Richard Coles)58218062012-11-14 11:43:16 +000029#include "jingle/glue/thread_wrapper.h"
Ben Murdocha3f7b4e2013-07-24 10:36:34 +010030#include "media/filters/gpu_video_decoder_factories.h"
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +010031#include "third_party/WebKit/public/platform/WebMediaConstraints.h"
32#include "third_party/WebKit/public/platform/WebMediaStream.h"
33#include "third_party/WebKit/public/platform/WebMediaStreamSource.h"
34#include "third_party/WebKit/public/platform/WebMediaStreamTrack.h"
35#include "third_party/WebKit/public/platform/WebURL.h"
Torne (Richard Coles)7d4cd472013-06-19 11:58:07 +010036#include "third_party/WebKit/public/web/WebDocument.h"
37#include "third_party/WebKit/public/web/WebFrame.h"
Ben Murdocheb525c52013-07-10 11:40:50 +010038#include "third_party/libjingle/source/talk/app/webrtc/mediaconstraintsinterface.h"
39
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000040#if defined(USE_OPENSSL)
41#include "third_party/libjingle/source/talk/base/ssladapter.h"
42#else
Torne (Richard Coles)58218062012-11-14 11:43:16 +000043#include "net/socket/nss_ssl_util.h"
44#endif
45
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +010046#if defined(GOOGLE_TV)
47#include "content/renderer/media/rtc_video_decoder_factory_tv.h"
48#endif
49
Torne (Richard Coles)58218062012-11-14 11:43:16 +000050namespace content {
51
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +010052// The constraint key for the PeerConnection constructor for enabling diagnostic
53// WebRTC logging. It's a Google specific key, hence the "goog" prefix.
54const char kWebRtcLoggingConstraint[] = "googLog";
55
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000056// Constant constraint keys which disables all audio constraints.
57// Only used in combination with WebAudio sources.
58struct {
59 const char* key;
60 const char* value;
61} const kWebAudioConstraints[] = {
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +010062 {webrtc::MediaConstraintsInterface::kEchoCancellation,
Ben Murdocheb525c52013-07-10 11:40:50 +010063 webrtc::MediaConstraintsInterface::kValueTrue},
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +010064 {webrtc::MediaConstraintsInterface::kAutoGainControl,
Ben Murdocheb525c52013-07-10 11:40:50 +010065 webrtc::MediaConstraintsInterface::kValueTrue},
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +010066 {webrtc::MediaConstraintsInterface::kNoiseSuppression,
Ben Murdocheb525c52013-07-10 11:40:50 +010067 webrtc::MediaConstraintsInterface::kValueTrue},
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +010068 {webrtc::MediaConstraintsInterface::kHighpassFilter,
Ben Murdocheb525c52013-07-10 11:40:50 +010069 webrtc::MediaConstraintsInterface::kValueTrue},
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000070};
71
72class WebAudioConstraints : public RTCMediaConstraints {
73 public:
74 WebAudioConstraints()
75 : RTCMediaConstraints(WebKit::WebMediaConstraints()) {
76 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kWebAudioConstraints); ++i) {
77 webrtc::MediaConstraintsInterface::Constraint constraint;
78 constraint.key = kWebAudioConstraints[i].key;
79 constraint.value = kWebAudioConstraints[i].value;
80
81 DVLOG(1) << "WebAudioConstraints: " << constraint.key
82 << " : " << constraint.value;
83 mandatory_.push_back(constraint);
84 }
85 }
86
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +010087 virtual ~WebAudioConstraints() {}
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +000088};
89
Torne (Richard Coles)58218062012-11-14 11:43:16 +000090class P2PPortAllocatorFactory : public webrtc::PortAllocatorFactoryInterface {
91 public:
92 P2PPortAllocatorFactory(
93 P2PSocketDispatcher* socket_dispatcher,
94 talk_base::NetworkManager* network_manager,
95 talk_base::PacketSocketFactory* socket_factory,
96 WebKit::WebFrame* web_frame)
97 : socket_dispatcher_(socket_dispatcher),
98 network_manager_(network_manager),
99 socket_factory_(socket_factory),
100 web_frame_(web_frame) {
101 }
102
103 virtual cricket::PortAllocator* CreatePortAllocator(
104 const std::vector<StunConfiguration>& stun_servers,
105 const std::vector<TurnConfiguration>& turn_configurations) OVERRIDE {
106 CHECK(web_frame_);
107 P2PPortAllocator::Config config;
108 if (stun_servers.size() > 0) {
109 config.stun_server = stun_servers[0].server.hostname();
110 config.stun_server_port = stun_servers[0].server.port();
111 }
Ben Murdocheb525c52013-07-10 11:40:50 +0100112 config.legacy_relay = false;
113 for (size_t i = 0; i < turn_configurations.size(); ++i) {
114 P2PPortAllocator::Config::RelayServerConfig relay_config;
115 relay_config.server_address = turn_configurations[i].server.hostname();
116 relay_config.port = turn_configurations[i].server.port();
117 relay_config.username = turn_configurations[i].username;
118 relay_config.password = turn_configurations[i].password;
119 relay_config.transport_type = turn_configurations[i].transport_type;
120 config.relays.push_back(relay_config);
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000121 }
122
Ben Murdocheb525c52013-07-10 11:40:50 +0100123 // Use first turn server as the stun server.
124 if (turn_configurations.size() > 0) {
125 config.stun_server = config.relays[0].server_address;
126 config.stun_server_port = config.relays[0].port;
127 }
128
129 return new P2PPortAllocator(
130 web_frame_, socket_dispatcher_.get(), network_manager_,
131 socket_factory_, config);
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000132 }
133
134 protected:
135 virtual ~P2PPortAllocatorFactory() {}
136
137 private:
138 scoped_refptr<P2PSocketDispatcher> socket_dispatcher_;
139 // |network_manager_| and |socket_factory_| are a weak references, owned by
140 // MediaStreamDependencyFactory.
141 talk_base::NetworkManager* network_manager_;
142 talk_base::PacketSocketFactory* socket_factory_;
143 // Raw ptr to the WebFrame that created the P2PPortAllocatorFactory.
144 WebKit::WebFrame* web_frame_;
145};
146
147// SourceStateObserver is a help class used for observing the startup state
148// transition of webrtc media sources such as a camera or microphone.
149// An instance of the object deletes itself after use.
150// Usage:
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000151// 1. Create an instance of the object with the WebKit::WebMediaStream
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000152// the observed sources belongs to a callback.
153// 2. Add the sources to the observer using AddSource.
154// 3. Call StartObserving()
155// 4. The callback will be triggered when all sources have transitioned from
156// webrtc::MediaSourceInterface::kInitializing.
157class SourceStateObserver : public webrtc::ObserverInterface,
158 public base::NonThreadSafe {
159 public:
160 SourceStateObserver(
Ben Murdochbbcdd452013-07-25 10:06:34 +0100161 WebKit::WebMediaStream* web_stream,
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000162 const MediaStreamDependencyFactory::MediaSourcesCreatedCallback& callback)
Ben Murdochbbcdd452013-07-25 10:06:34 +0100163 : web_stream_(web_stream),
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000164 ready_callback_(callback),
165 live_(true) {
166 }
167
168 void AddSource(webrtc::MediaSourceInterface* source) {
169 DCHECK(CalledOnValidThread());
170 switch (source->state()) {
171 case webrtc::MediaSourceInterface::kInitializing:
172 sources_.push_back(source);
173 source->RegisterObserver(this);
174 break;
175 case webrtc::MediaSourceInterface::kLive:
176 // The source is already live so we don't need to wait for it.
177 break;
178 case webrtc::MediaSourceInterface::kEnded:
179 // The source have already failed.
180 live_ = false;
181 break;
182 default:
183 NOTREACHED();
184 }
185 }
186
187 void StartObservering() {
188 DCHECK(CalledOnValidThread());
189 CheckIfSourcesAreLive();
190 }
191
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000192 virtual void OnChanged() OVERRIDE {
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000193 DCHECK(CalledOnValidThread());
194 CheckIfSourcesAreLive();
195 }
196
197 private:
198 void CheckIfSourcesAreLive() {
199 ObservedSources::iterator it = sources_.begin();
200 while (it != sources_.end()) {
201 if ((*it)->state() != webrtc::MediaSourceInterface::kInitializing) {
202 live_ &= (*it)->state() == webrtc::MediaSourceInterface::kLive;
203 (*it)->UnregisterObserver(this);
204 it = sources_.erase(it);
205 } else {
206 ++it;
207 }
208 }
209 if (sources_.empty()) {
Ben Murdochbbcdd452013-07-25 10:06:34 +0100210 ready_callback_.Run(web_stream_, live_);
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000211 delete this;
212 }
213 }
214
Ben Murdochbbcdd452013-07-25 10:06:34 +0100215 WebKit::WebMediaStream* web_stream_;
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000216 MediaStreamDependencyFactory::MediaSourcesCreatedCallback ready_callback_;
217 bool live_;
218 typedef std::vector<scoped_refptr<webrtc::MediaSourceInterface> >
219 ObservedSources;
220 ObservedSources sources_;
221};
222
223MediaStreamDependencyFactory::MediaStreamDependencyFactory(
224 VideoCaptureImplManager* vc_manager,
225 P2PSocketDispatcher* p2p_socket_dispatcher)
226 : network_manager_(NULL),
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100227#if defined(GOOGLE_TV)
228 decoder_factory_tv_(NULL),
229#endif
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000230 vc_manager_(vc_manager),
231 p2p_socket_dispatcher_(p2p_socket_dispatcher),
232 signaling_thread_(NULL),
233 worker_thread_(NULL),
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100234 chrome_worker_thread_("Chrome_libJingle_WorkerThread") {
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000235}
236
237MediaStreamDependencyFactory::~MediaStreamDependencyFactory() {
238 CleanupPeerConnectionFactory();
239}
240
241WebKit::WebRTCPeerConnectionHandler*
242MediaStreamDependencyFactory::CreateRTCPeerConnectionHandler(
243 WebKit::WebRTCPeerConnectionHandlerClient* client) {
244 // Save histogram data so we can see how much PeerConnetion is used.
245 // The histogram counts the number of calls to the JS API
246 // webKitRTCPeerConnection.
247 UpdateWebRTCMethodCount(WEBKIT_RTC_PEER_CONNECTION);
248
249 if (!EnsurePeerConnectionFactory())
250 return NULL;
251
252 return new RTCPeerConnectionHandler(client, this);
253}
254
255void MediaStreamDependencyFactory::CreateNativeMediaSources(
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100256 int render_view_id,
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000257 const WebKit::WebMediaConstraints& audio_constraints,
258 const WebKit::WebMediaConstraints& video_constraints,
Ben Murdochbbcdd452013-07-25 10:06:34 +0100259 WebKit::WebMediaStream* web_stream,
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000260 const MediaSourcesCreatedCallback& sources_created) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000261 DVLOG(1) << "MediaStreamDependencyFactory::CreateNativeMediaSources()";
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000262 if (!EnsurePeerConnectionFactory()) {
Ben Murdochbbcdd452013-07-25 10:06:34 +0100263 sources_created.Run(web_stream, false);
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000264 return;
265 }
266
267 // |source_observer| clean up itself when it has completed
268 // source_observer->StartObservering.
269 SourceStateObserver* source_observer =
Ben Murdochbbcdd452013-07-25 10:06:34 +0100270 new SourceStateObserver(web_stream, sources_created);
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000271
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000272 // Create local video sources.
273 RTCMediaConstraints native_video_constraints(video_constraints);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000274 WebKit::WebVector<WebKit::WebMediaStreamTrack> video_tracks;
Ben Murdochbbcdd452013-07-25 10:06:34 +0100275 web_stream->videoTracks(video_tracks);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000276 for (size_t i = 0; i < video_tracks.size(); ++i) {
277 const WebKit::WebMediaStreamSource& source = video_tracks[i].source();
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000278 MediaStreamSourceExtraData* source_data =
279 static_cast<MediaStreamSourceExtraData*>(source.extraData());
280 if (!source_data) {
281 // TODO(perkj): Implement support for sources from remote MediaStreams.
282 NOTIMPLEMENTED();
283 continue;
284 }
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000285 const bool is_screencast =
286 source_data->device_info().device.type ==
287 content::MEDIA_TAB_VIDEO_CAPTURE ||
288 source_data->device_info().device.type ==
289 content::MEDIA_SCREEN_VIDEO_CAPTURE;
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000290 source_data->SetVideoSource(
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000291 CreateLocalVideoSource(source_data->device_info().session_id,
292 is_screencast,
Torne (Richard Coles)7d4cd472013-06-19 11:58:07 +0100293 &native_video_constraints).get());
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000294 source_observer->AddSource(source_data->video_source());
295 }
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000296
297 // Do additional source initialization if the audio source is a valid
298 // microphone or tab audio.
299 RTCMediaConstraints native_audio_constraints(audio_constraints);
300 WebKit::WebVector<WebKit::WebMediaStreamTrack> audio_tracks;
Ben Murdochbbcdd452013-07-25 10:06:34 +0100301 web_stream->audioTracks(audio_tracks);
Ben Murdochbb1529c2013-08-08 10:24:53 +0100302 const CommandLine& command_line = *CommandLine::ForCurrentProcess();
303 if (command_line.HasSwitch(switches::kEnableWebRtcAecRecordings)) {
304 native_audio_constraints.AddOptional(
305 RTCMediaConstraints::kInternalAecDump, "true");
306 }
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000307 for (size_t i = 0; i < audio_tracks.size(); ++i) {
308 const WebKit::WebMediaStreamSource& source = audio_tracks[i].source();
309 MediaStreamSourceExtraData* source_data =
310 static_cast<MediaStreamSourceExtraData*>(source.extraData());
311 if (!source_data) {
312 // TODO(henrika): Implement support for sources from remote MediaStreams.
313 NOTIMPLEMENTED();
314 continue;
315 }
316
Ben Murdochbb1529c2013-08-08 10:24:53 +0100317 // TODO(xians): Create a new capturer for difference microphones when we
318 // support multiple microphones. See issue crbug/262117 .
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000319 const StreamDeviceInfo device_info = source_data->device_info();
Ben Murdochbb1529c2013-08-08 10:24:53 +0100320 scoped_refptr<WebRtcAudioCapturer> capturer(
321 MaybeCreateAudioCapturer(render_view_id, device_info));
322 if (!capturer.get()) {
323 DLOG(WARNING) << "Failed to create the capturer for device "
324 << device_info.device.id;
325 sources_created.Run(web_stream, false);
326 return;
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100327 }
328
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000329 // Creates a LocalAudioSource object which holds audio options.
Ben Murdochbb1529c2013-08-08 10:24:53 +0100330 // TODO(xians): The option should apply to the track instead of the source.
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000331 source_data->SetLocalAudioSource(
Torne (Richard Coles)7d4cd472013-06-19 11:58:07 +0100332 CreateLocalAudioSource(&native_audio_constraints).get());
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000333 source_observer->AddSource(source_data->local_audio_source());
334 }
335
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000336 source_observer->StartObservering();
337}
338
339void MediaStreamDependencyFactory::CreateNativeLocalMediaStream(
Ben Murdochbbcdd452013-07-25 10:06:34 +0100340 WebKit::WebMediaStream* web_stream) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000341 DVLOG(1) << "MediaStreamDependencyFactory::CreateNativeLocalMediaStream()";
342 if (!EnsurePeerConnectionFactory()) {
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100343 DVLOG(1) << "EnsurePeerConnectionFactory() failed!";
344 return;
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000345 }
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000346
Ben Murdochbbcdd452013-07-25 10:06:34 +0100347 std::string label = UTF16ToUTF8(web_stream->id());
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000348 scoped_refptr<webrtc::MediaStreamInterface> native_stream =
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000349 CreateLocalMediaStream(label);
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100350 MediaStreamExtraData* extra_data =
351 new MediaStreamExtraData(native_stream.get(), true);
Ben Murdochbbcdd452013-07-25 10:06:34 +0100352 web_stream->setExtraData(extra_data);
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000353
354 // Add audio tracks.
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000355 WebKit::WebVector<WebKit::WebMediaStreamTrack> audio_tracks;
Ben Murdochbbcdd452013-07-25 10:06:34 +0100356 web_stream->audioTracks(audio_tracks);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000357 for (size_t i = 0; i < audio_tracks.size(); ++i) {
Ben Murdochbbcdd452013-07-25 10:06:34 +0100358 AddNativeMediaStreamTrack(*web_stream, audio_tracks[i]);
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000359 }
360
361 // Add video tracks.
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000362 WebKit::WebVector<WebKit::WebMediaStreamTrack> video_tracks;
Ben Murdochbbcdd452013-07-25 10:06:34 +0100363 web_stream->videoTracks(video_tracks);
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000364 for (size_t i = 0; i < video_tracks.size(); ++i) {
Ben Murdochbbcdd452013-07-25 10:06:34 +0100365 AddNativeMediaStreamTrack(*web_stream, video_tracks[i]);
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000366 }
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000367}
368
369void MediaStreamDependencyFactory::CreateNativeLocalMediaStream(
Ben Murdochbbcdd452013-07-25 10:06:34 +0100370 WebKit::WebMediaStream* web_stream,
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000371 const MediaStreamExtraData::StreamStopCallback& stream_stop) {
Ben Murdochbbcdd452013-07-25 10:06:34 +0100372 CreateNativeLocalMediaStream(web_stream);
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000373
374 MediaStreamExtraData* extra_data =
Ben Murdochbbcdd452013-07-25 10:06:34 +0100375 static_cast<MediaStreamExtraData*>(web_stream->extraData());
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000376 extra_data->SetLocalStreamStopCallback(stream_stop);
377}
378
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100379bool MediaStreamDependencyFactory::AddNativeMediaStreamTrack(
380 const WebKit::WebMediaStream& stream,
381 const WebKit::WebMediaStreamTrack& track) {
382 MediaStreamExtraData* extra_data =
383 static_cast<MediaStreamExtraData*>(stream.extraData());
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100384 webrtc::MediaStreamInterface* native_stream = extra_data->stream().get();
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100385 DCHECK(native_stream);
386
387 WebKit::WebMediaStreamSource source = track.source();
388 MediaStreamSourceExtraData* source_data =
389 static_cast<MediaStreamSourceExtraData*>(source.extraData());
390
Ben Murdochbb1529c2013-08-08 10:24:53 +0100391 scoped_refptr<WebRtcAudioCapturer> capturer;
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100392 if (!source_data) {
393 if (source.requiresAudioConsumer()) {
394 // We're adding a WebAudio MediaStream.
Ben Murdochbb1529c2013-08-08 10:24:53 +0100395 // Create a specific capturer for each WebAudio consumer.
396 capturer = CreateWebAudioSource(&source);
397 source_data =
398 static_cast<MediaStreamSourceExtraData*>(source.extraData());
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100399 } else {
400 // TODO(perkj): Implement support for sources from
401 // remote MediaStreams.
402 NOTIMPLEMENTED();
403 return false;
404 }
405 }
406
407 WebKit::WebMediaStreamSource::Type type = track.source().type();
408 DCHECK(type == WebKit::WebMediaStreamSource::TypeAudio ||
409 type == WebKit::WebMediaStreamSource::TypeVideo);
410
411 std::string track_id = UTF16ToUTF8(track.id());
412 if (source.type() == WebKit::WebMediaStreamSource::TypeAudio) {
Ben Murdochbb1529c2013-08-08 10:24:53 +0100413 if (!capturer.get() && GetWebRtcAudioDevice())
414 capturer = GetWebRtcAudioDevice()->GetDefaultCapturer();
Torne (Richard Coles)7d4cd472013-06-19 11:58:07 +0100415
Ben Murdochbb1529c2013-08-08 10:24:53 +0100416 scoped_refptr<webrtc::AudioTrackInterface> audio_track(
417 CreateLocalAudioTrack(track_id,
418 capturer,
419 source_data->local_audio_source()));
420 audio_track->set_enabled(track.isEnabled());
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100421 return native_stream->AddTrack(audio_track.get());
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100422 } else {
Ben Murdochbb1529c2013-08-08 10:24:53 +0100423 DCHECK(source.type() == WebKit::WebMediaStreamSource::TypeVideo);
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100424 scoped_refptr<webrtc::VideoTrackInterface> video_track(
425 CreateLocalVideoTrack(track_id, source_data->video_source()));
426 video_track->set_enabled(track.isEnabled());
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100427 return native_stream->AddTrack(video_track.get());
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100428 }
429}
430
431bool MediaStreamDependencyFactory::AddNativeVideoMediaTrack(
432 const std::string& track_id,
433 WebKit::WebMediaStream* stream,
434 cricket::VideoCapturer* capturer) {
435 if (!stream) {
436 LOG(ERROR) << "AddNativeVideoMediaTrack called with null WebMediaStream.";
437 return false;
438 }
439
440 // Create native track from the source.
441 scoped_refptr<webrtc::VideoTrackInterface> native_track =
442 CreateLocalVideoTrack(track_id, capturer);
443
444 // Add the native track to native stream
445 MediaStreamExtraData* extra_data =
446 static_cast<MediaStreamExtraData*>(stream->extraData());
447 DCHECK(extra_data);
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100448 webrtc::MediaStreamInterface* native_stream = extra_data->stream().get();
449 native_stream->AddTrack(native_track.get());
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100450
451 // Create a new webkit video track.
452 WebKit::WebMediaStreamTrack webkit_track;
453 WebKit::WebMediaStreamSource webkit_source;
454 WebKit::WebString webkit_track_id(UTF8ToUTF16(track_id));
455 WebKit::WebMediaStreamSource::Type type =
456 WebKit::WebMediaStreamSource::TypeVideo;
457 webkit_source.initialize(webkit_track_id, type, webkit_track_id);
458 webkit_track.initialize(webkit_track_id, webkit_source);
459
460 // Add the track to WebMediaStream.
461 stream->addTrack(webkit_track);
462 return true;
463}
464
465bool MediaStreamDependencyFactory::RemoveNativeMediaStreamTrack(
466 const WebKit::WebMediaStream& stream,
467 const WebKit::WebMediaStreamTrack& track) {
468 MediaStreamExtraData* extra_data =
469 static_cast<MediaStreamExtraData*>(stream.extraData());
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100470 webrtc::MediaStreamInterface* native_stream = extra_data->stream().get();
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100471 DCHECK(native_stream);
472
473 WebKit::WebMediaStreamSource::Type type = track.source().type();
474 DCHECK(type == WebKit::WebMediaStreamSource::TypeAudio ||
475 type == WebKit::WebMediaStreamSource::TypeVideo);
476
477 std::string track_id = UTF16ToUTF8(track.id());
478 return type == WebKit::WebMediaStreamSource::TypeAudio ?
479 native_stream->RemoveTrack(native_stream->FindAudioTrack(track_id)) :
480 native_stream->RemoveTrack(native_stream->FindVideoTrack(track_id));
481}
482
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000483bool MediaStreamDependencyFactory::CreatePeerConnectionFactory() {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000484 DVLOG(1) << "MediaStreamDependencyFactory::CreatePeerConnectionFactory()";
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100485 if (!pc_factory_.get()) {
486 DCHECK(!audio_device_.get());
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000487 audio_device_ = new WebRtcAudioDeviceImpl();
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100488
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100489 scoped_ptr<cricket::WebRtcVideoDecoderFactory> decoder_factory;
Ben Murdocheb525c52013-07-10 11:40:50 +0100490
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100491 const CommandLine* cmd_line = CommandLine::ForCurrentProcess();
492 if (cmd_line->HasSwitch(switches::kEnableWebRtcHWDecoding)) {
Ben Murdochbbcdd452013-07-25 10:06:34 +0100493 scoped_refptr<base::MessageLoopProxy> media_loop_proxy =
494 RenderThreadImpl::current()->GetMediaThreadMessageLoopProxy();
495 scoped_refptr<RendererGpuVideoDecoderFactories> gpu_factories =
496 RenderThreadImpl::current()->GetGpuFactories(media_loop_proxy);
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100497 if (gpu_factories.get() != NULL)
498 decoder_factory.reset(new RTCVideoDecoderFactory(gpu_factories));
499 }
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100500#if defined(GOOGLE_TV)
501 // PeerConnectionFactory will hold the ownership of this
502 // VideoDecoderFactory.
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100503 decoder_factory.reset(decoder_factory_tv_ = new RTCVideoDecoderFactoryTv);
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100504#endif
505
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000506 scoped_refptr<webrtc::PeerConnectionFactoryInterface> factory(
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100507 webrtc::CreatePeerConnectionFactory(worker_thread_,
508 signaling_thread_,
509 audio_device_.get(),
Ben Murdochbb1529c2013-08-08 10:24:53 +0100510 NULL,
Ben Murdoch7dbb3d52013-07-17 14:55:54 +0100511 decoder_factory.release()));
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100512 if (factory.get())
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000513 pc_factory_ = factory;
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000514 else
515 audio_device_ = NULL;
516 }
517 return pc_factory_.get() != NULL;
518}
519
520bool MediaStreamDependencyFactory::PeerConnectionFactoryCreated() {
521 return pc_factory_.get() != NULL;
522}
523
524scoped_refptr<webrtc::PeerConnectionInterface>
525MediaStreamDependencyFactory::CreatePeerConnection(
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000526 const webrtc::PeerConnectionInterface::IceServers& ice_servers,
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000527 const webrtc::MediaConstraintsInterface* constraints,
528 WebKit::WebFrame* web_frame,
529 webrtc::PeerConnectionObserver* observer) {
530 CHECK(web_frame);
531 CHECK(observer);
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100532
533 webrtc::MediaConstraintsInterface::Constraints optional_constraints =
534 constraints->GetOptional();
535 std::string constraint_value;
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100536 if (optional_constraints.FindFirst(kWebRtcLoggingConstraint,
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100537 &constraint_value)) {
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100538 std::string url = web_frame->document().url().spec();
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100539 RenderThreadImpl::current()->GetIOMessageLoopProxy()->PostTask(
540 FROM_HERE, base::Bind(
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100541 &InitWebRtcLogging,
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +0100542 constraint_value,
543 url));
544 }
545
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000546 scoped_refptr<P2PPortAllocatorFactory> pa_factory =
547 new talk_base::RefCountedObject<P2PPortAllocatorFactory>(
548 p2p_socket_dispatcher_.get(),
549 network_manager_,
550 socket_factory_.get(),
551 web_frame);
Ben Murdochca12bfa2013-07-23 11:17:05 +0100552
553 PeerConnectionIdentityService* identity_service =
554 new PeerConnectionIdentityService(GURL(web_frame->document().url().spec())
555 .GetOrigin());
556
557 return pc_factory_->CreatePeerConnection(ice_servers,
558 constraints,
559 pa_factory.get(),
560 identity_service,
561 observer).get();
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000562}
563
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000564scoped_refptr<webrtc::MediaStreamInterface>
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000565MediaStreamDependencyFactory::CreateLocalMediaStream(
566 const std::string& label) {
567 return pc_factory_->CreateLocalMediaStream(label).get();
568}
569
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000570scoped_refptr<webrtc::AudioSourceInterface>
571MediaStreamDependencyFactory::CreateLocalAudioSource(
572 const webrtc::MediaConstraintsInterface* constraints) {
573 scoped_refptr<webrtc::AudioSourceInterface> source =
574 pc_factory_->CreateAudioSource(constraints).get();
575 return source;
576}
577
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000578scoped_refptr<webrtc::VideoSourceInterface>
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000579MediaStreamDependencyFactory::CreateLocalVideoSource(
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000580 int video_session_id,
581 bool is_screencast,
582 const webrtc::MediaConstraintsInterface* constraints) {
583 RtcVideoCapturer* capturer = new RtcVideoCapturer(
584 video_session_id, vc_manager_.get(), is_screencast);
585
586 // The video source takes ownership of |capturer|.
587 scoped_refptr<webrtc::VideoSourceInterface> source =
588 pc_factory_->CreateVideoSource(capturer, constraints).get();
589 return source;
590}
591
Ben Murdochbb1529c2013-08-08 10:24:53 +0100592scoped_refptr<WebRtcAudioCapturer>
593MediaStreamDependencyFactory::CreateWebAudioSource(
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000594 WebKit::WebMediaStreamSource* source) {
595 DVLOG(1) << "MediaStreamDependencyFactory::CreateWebAudioSource()";
596 DCHECK(GetWebRtcAudioDevice());
597
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000598 // Set up the source and ensure that WebAudio is driving things instead of
Ben Murdochbb1529c2013-08-08 10:24:53 +0100599 // a microphone. For WebAudio, we always create a new capturer without
600 // calling initialize(), WebAudio will re-configure the capturer later on.
601 // Pass -1 as the |render_view_id| and an empty device struct to tell the
602 // capturer not to start the default source.
603 scoped_refptr<WebRtcAudioCapturer> capturer(
604 MaybeCreateAudioCapturer(-1, StreamDeviceInfo()));
605 DCHECK(capturer.get());
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000606
607 scoped_refptr<WebAudioCapturerSource>
Ben Murdochbb1529c2013-08-08 10:24:53 +0100608 webaudio_capturer_source(new WebAudioCapturerSource(capturer.get()));
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000609 MediaStreamSourceExtraData* source_data =
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100610 new content::MediaStreamSourceExtraData(webaudio_capturer_source.get());
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000611
612 // Create a LocalAudioSource object which holds audio options.
613 // Use audio constraints where all values are false, i.e., disable
614 // echo cancellation, automatic gain control, noise suppression and
615 // high-pass filter. SetLocalAudioSource() affects core audio parts in
616 // third_party/Libjingle.
617 WebAudioConstraints webaudio_audio_constraints_all_false;
618 source_data->SetLocalAudioSource(
Torne (Richard Coles)7d4cd472013-06-19 11:58:07 +0100619 CreateLocalAudioSource(&webaudio_audio_constraints_all_false).get());
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000620 source->setExtraData(source_data);
621
622 // Replace the default source with WebAudio as source instead.
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100623 source->addAudioConsumer(webaudio_capturer_source.get());
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000624
Ben Murdochbb1529c2013-08-08 10:24:53 +0100625 return capturer;
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000626}
627
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000628scoped_refptr<webrtc::VideoTrackInterface>
629MediaStreamDependencyFactory::CreateLocalVideoTrack(
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000630 const std::string& id,
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000631 webrtc::VideoSourceInterface* source) {
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000632 return pc_factory_->CreateVideoTrack(id, source).get();
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000633}
634
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100635scoped_refptr<webrtc::VideoTrackInterface>
636MediaStreamDependencyFactory::CreateLocalVideoTrack(
637 const std::string& id, cricket::VideoCapturer* capturer) {
638 if (!capturer) {
639 LOG(ERROR) << "CreateLocalVideoTrack called with null VideoCapturer.";
640 return NULL;
641 }
642
643 // Create video source from the |capturer|.
644 scoped_refptr<webrtc::VideoSourceInterface> source =
645 pc_factory_->CreateVideoSource(capturer, NULL).get();
646
647 // Create native track from the source.
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100648 return pc_factory_->CreateVideoTrack(id, source.get()).get();
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100649}
650
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000651scoped_refptr<webrtc::AudioTrackInterface>
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000652MediaStreamDependencyFactory::CreateLocalAudioTrack(
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000653 const std::string& id,
Ben Murdochbb1529c2013-08-08 10:24:53 +0100654 const scoped_refptr<WebRtcAudioCapturer>& capturer,
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000655 webrtc::AudioSourceInterface* source) {
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100656 // TODO(xians): Merge |source| to the capturer(). We can't do this today
657 // because only one capturer() is supported while one |source| is created
658 // for each audio track.
Ben Murdochbb1529c2013-08-08 10:24:53 +0100659 scoped_refptr<WebRtcLocalAudioTrack> audio_track(
660 WebRtcLocalAudioTrack::Create(id, capturer, source));
661 // Add the WebRtcAudioDevice as the sink to the local audio track.
662 audio_track->AddSink(GetWebRtcAudioDevice());
663 // Start the audio track. This will hook the |audio_track| to the capturer
664 // as the sink of the audio, and only start the source of the capturer if
665 // it is the first audio track connecting to the capturer.
666 audio_track->Start();
667 return audio_track;
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000668}
669
670webrtc::SessionDescriptionInterface*
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000671MediaStreamDependencyFactory::CreateSessionDescription(
672 const std::string& type,
673 const std::string& sdp,
674 webrtc::SdpParseError* error) {
675 return webrtc::CreateSessionDescription(type, sdp, error);
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000676}
677
678webrtc::IceCandidateInterface* MediaStreamDependencyFactory::CreateIceCandidate(
679 const std::string& sdp_mid,
680 int sdp_mline_index,
681 const std::string& sdp) {
682 return webrtc::CreateIceCandidate(sdp_mid, sdp_mline_index, sdp);
683}
684
685WebRtcAudioDeviceImpl*
686MediaStreamDependencyFactory::GetWebRtcAudioDevice() {
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100687 return audio_device_.get();
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000688}
689
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000690void MediaStreamDependencyFactory::InitializeWorkerThread(
691 talk_base::Thread** thread,
692 base::WaitableEvent* event) {
693 jingle_glue::JingleThreadWrapper::EnsureForCurrentMessageLoop();
694 jingle_glue::JingleThreadWrapper::current()->set_send_allowed(true);
695 *thread = jingle_glue::JingleThreadWrapper::current();
696 event->Signal();
697}
698
699void MediaStreamDependencyFactory::CreateIpcNetworkManagerOnWorkerThread(
700 base::WaitableEvent* event) {
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100701 DCHECK_EQ(base::MessageLoop::current(), chrome_worker_thread_.message_loop());
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100702 network_manager_ = new IpcNetworkManager(p2p_socket_dispatcher_.get());
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000703 event->Signal();
704}
705
706void MediaStreamDependencyFactory::DeleteIpcNetworkManager() {
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100707 DCHECK_EQ(base::MessageLoop::current(), chrome_worker_thread_.message_loop());
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000708 delete network_manager_;
709 network_manager_ = NULL;
710}
711
712bool MediaStreamDependencyFactory::EnsurePeerConnectionFactory() {
713 DCHECK(CalledOnValidThread());
714 if (PeerConnectionFactoryCreated())
715 return true;
716
717 if (!signaling_thread_) {
718 jingle_glue::JingleThreadWrapper::EnsureForCurrentMessageLoop();
719 jingle_glue::JingleThreadWrapper::current()->set_send_allowed(true);
720 signaling_thread_ = jingle_glue::JingleThreadWrapper::current();
721 CHECK(signaling_thread_);
722 }
723
724 if (!worker_thread_) {
725 if (!chrome_worker_thread_.IsRunning()) {
726 if (!chrome_worker_thread_.Start()) {
727 LOG(ERROR) << "Could not start worker thread";
728 signaling_thread_ = NULL;
729 return false;
730 }
731 }
732 base::WaitableEvent event(true, false);
733 chrome_worker_thread_.message_loop()->PostTask(FROM_HERE, base::Bind(
734 &MediaStreamDependencyFactory::InitializeWorkerThread,
735 base::Unretained(this),
736 &worker_thread_,
737 &event));
738 event.Wait();
739 DCHECK(worker_thread_);
740 }
741
742 if (!network_manager_) {
743 base::WaitableEvent event(true, false);
744 chrome_worker_thread_.message_loop()->PostTask(FROM_HERE, base::Bind(
745 &MediaStreamDependencyFactory::CreateIpcNetworkManagerOnWorkerThread,
746 base::Unretained(this),
747 &event));
748 event.Wait();
749 }
750
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100751 if (!socket_factory_) {
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000752 socket_factory_.reset(
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100753 new IpcPacketSocketFactory(p2p_socket_dispatcher_.get()));
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000754 }
755
Torne (Richard Coles)2a99a7e2013-03-28 15:31:22 +0000756 // Init SSL, which will be needed by PeerConnection.
757#if defined(USE_OPENSSL)
758 if (!talk_base::InitializeSSL()) {
759 LOG(ERROR) << "Failed on InitializeSSL.";
760 return false;
761 }
762#else
763 // TODO(ronghuawu): Replace this call with InitializeSSL.
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000764 net::EnsureNSSSSLInit();
765#endif
766
767 if (!CreatePeerConnectionFactory()) {
768 LOG(ERROR) << "Could not create PeerConnection factory";
769 return false;
770 }
771 return true;
772}
773
774void MediaStreamDependencyFactory::CleanupPeerConnectionFactory() {
775 pc_factory_ = NULL;
776 if (network_manager_) {
777 // The network manager needs to free its resources on the thread they were
778 // created, which is the worked thread.
779 if (chrome_worker_thread_.IsRunning()) {
780 chrome_worker_thread_.message_loop()->PostTask(FROM_HERE, base::Bind(
781 &MediaStreamDependencyFactory::DeleteIpcNetworkManager,
782 base::Unretained(this)));
783 // Stopping the thread will wait until all tasks have been
784 // processed before returning. We wait for the above task to finish before
785 // letting the the function continue to avoid any potential race issues.
786 chrome_worker_thread_.Stop();
787 } else {
788 NOTREACHED() << "Worker thread not running.";
789 }
790 }
791}
792
Ben Murdochbb1529c2013-08-08 10:24:53 +0100793scoped_refptr<WebRtcAudioCapturer>
794MediaStreamDependencyFactory::MaybeCreateAudioCapturer(
795 int render_view_id,
796 const StreamDeviceInfo& device_info) {
797 scoped_refptr<WebRtcAudioCapturer> capturer;
798 if (render_view_id != -1) {
799 // From a normal getUserMedia, re-use the existing default capturer.
800 capturer = GetWebRtcAudioDevice()->GetDefaultCapturer();
801 }
802 // If the default capturer does not exist or |render_view_id| == -1, create
803 // a new capturer.
804 bool is_new_capturer = false;
805 if (!capturer.get()) {
806 capturer = WebRtcAudioCapturer::CreateCapturer();
807 is_new_capturer = true;
808 }
809
810 if (!capturer->Initialize(
811 render_view_id,
812 static_cast<media::ChannelLayout>(device_info.device.channel_layout),
813 device_info.device.sample_rate, device_info.session_id,
814 device_info.device.id)) {
815 return NULL;
816 }
817
818 // Add the capturer to the WebRtcAudioDeviceImpl if it is a new capturer.
819 if (is_new_capturer)
820 GetWebRtcAudioDevice()->AddAudioCapturer(capturer);
821
822 return capturer;
823}
824
Torne (Richard Coles)58218062012-11-14 11:43:16 +0000825} // namespace content