Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(448)

Side by Side Diff: content/renderer/media/media_stream_dependency_factory.cc

Issue 10919122: Move creation of PeerConnection from the RenderView to the RenderThreadImpl. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: #if defined(ENABLE_WEBRTC) in RendererWebKitPlatformSupportImpl::createPeerConnection00Handler to b… Created 8 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "content/renderer/media/media_stream_dependency_factory.h" 5 #include "content/renderer/media/media_stream_dependency_factory.h"
6 6
7 #include <vector> 7 #include <vector>
8 8
9 #include "base/synchronization/waitable_event.h"
10 #include "base/utf_string_conversions.h"
11 #include "content/renderer/media/media_stream_extra_data.h"
12 #include "content/renderer/media/media_stream_source_extra_data.h"
9 #include "content/renderer/media/rtc_video_capturer.h" 13 #include "content/renderer/media/rtc_video_capturer.h"
14 #include "content/renderer/media/peer_connection_handler_jsep.h"
10 #include "content/renderer/media/video_capture_impl_manager.h" 15 #include "content/renderer/media/video_capture_impl_manager.h"
11 #include "content/renderer/media/webrtc_audio_device_impl.h" 16 #include "content/renderer/media/webrtc_audio_device_impl.h"
17 #include "content/renderer/media/webrtc_uma_histograms.h"
12 #include "content/renderer/p2p/ipc_network_manager.h" 18 #include "content/renderer/p2p/ipc_network_manager.h"
13 #include "content/renderer/p2p/ipc_socket_factory.h" 19 #include "content/renderer/p2p/ipc_socket_factory.h"
14 #include "content/renderer/p2p/port_allocator.h" 20 #include "content/renderer/p2p/port_allocator.h"
15 #include "jingle/glue/thread_wrapper.h" 21 #include "jingle/glue/thread_wrapper.h"
16 #include "third_party/WebKit/Source/WebKit/chromium/public/WebFrame.h" 22 #include "third_party/WebKit/Source/WebKit/chromium/public/WebFrame.h"
23 #include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebMediaStre amComponent.h"
24 #include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebMediaStre amDescriptor.h"
25 #include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebMediaStre amSource.h"
17 26
18 class P2PPortAllocatorFactory : public webrtc::PortAllocatorFactoryInterface { 27 class P2PPortAllocatorFactory : public webrtc::PortAllocatorFactoryInterface {
19 public: 28 public:
20 P2PPortAllocatorFactory( 29 P2PPortAllocatorFactory(
21 content::P2PSocketDispatcher* socket_dispatcher, 30 content::P2PSocketDispatcher* socket_dispatcher,
22 talk_base::NetworkManager* network_manager, 31 talk_base::NetworkManager* network_manager,
23 talk_base::PacketSocketFactory* socket_factory) 32 talk_base::PacketSocketFactory* socket_factory)
24 : socket_dispatcher_(socket_dispatcher), 33 : socket_dispatcher_(socket_dispatcher),
25 network_manager_(network_manager), 34 network_manager_(network_manager),
26 socket_factory_(socket_factory) { 35 socket_factory_(socket_factory) {
(...skipping 23 matching lines...) Expand all
50 socket_dispatcher_, 59 socket_dispatcher_,
51 network_manager_, 60 network_manager_,
52 socket_factory_, 61 socket_factory_,
53 config); 62 config);
54 } 63 }
55 64
56 protected: 65 protected:
57 virtual ~P2PPortAllocatorFactory() {} 66 virtual ~P2PPortAllocatorFactory() {}
58 67
59 private: 68 private:
60 // socket_dispatcher_ is a weak reference, owned by RenderView. It's valid 69 scoped_refptr<content::P2PSocketDispatcher> socket_dispatcher_;
61 // for the lifetime of RenderView. 70 // |network_manager_| and |socket_factory_| are a weak references, owned by
62 content::P2PSocketDispatcher* socket_dispatcher_; 71 // MediaStreamDependencyFactory.
63 // network_manager_ and socket_factory_ are a weak references, owned by
64 // MediaStreamImpl.
65 talk_base::NetworkManager* network_manager_; 72 talk_base::NetworkManager* network_manager_;
66 talk_base::PacketSocketFactory* socket_factory_; 73 talk_base::PacketSocketFactory* socket_factory_;
67 }; 74 };
68 75
69 MediaStreamDependencyFactory::MediaStreamDependencyFactory( 76 MediaStreamDependencyFactory::MediaStreamDependencyFactory(
70 VideoCaptureImplManager* vc_manager) 77 VideoCaptureImplManager* vc_manager,
71 : vc_manager_(vc_manager) { 78 content::P2PSocketDispatcher* p2p_socket_dispatcher)
79 : network_manager_(NULL),
80 vc_manager_(vc_manager),
81 p2p_socket_dispatcher_(p2p_socket_dispatcher),
82 signaling_thread_(NULL),
83 worker_thread_(NULL),
84 chrome_worker_thread_("Chrome_libJingle_WorkerThread") {
72 } 85 }
73 86
74 MediaStreamDependencyFactory::~MediaStreamDependencyFactory() {} 87 MediaStreamDependencyFactory::~MediaStreamDependencyFactory() {
88 CleanupPeerConnectionFactory();
89 }
90
91 WebKit::WebPeerConnection00Handler*
92 MediaStreamDependencyFactory::CreatePeerConnectionHandlerJsep(
93 WebKit::WebPeerConnection00HandlerClient* client) {
94 // Save histogram data so we can see how much PeerConnetion is used.
95 // The histogram counts the number of calls to the JS API
96 // webKitPeerConnection00.
97 UpdateWebRTCMethodCount(WEBKIT_PEER_CONNECTION);
98
99 if (!EnsurePeerConnectionFactory()) {
100 return NULL;
101 }
102
103 return new PeerConnectionHandlerJsep(client, this);
104 }
105
106 bool MediaStreamDependencyFactory::CreateNativeLocalMediaStream(
107 WebKit::WebMediaStreamDescriptor* description) {
108 // Creating the peer connection factory can fail if for example the audio
109 // (input or output) or video device cannot be opened. Handling such cases
110 // better is a higher level design discussion which involves the media
111 // manager, webrtc and libjingle. We cannot create any native
112 // track objects however, so we'll just have to skip that. Furthermore,
113 // creating a peer connection later on will fail if we don't have a factory.
114 if (!EnsurePeerConnectionFactory())
115 return false;
116
117 std::string label = UTF16ToUTF8(description->label());
118 talk_base::scoped_refptr<webrtc::LocalMediaStreamInterface> native_stream =
119 CreateLocalMediaStream(label);
120
121 // Add audio tracks.
122 WebKit::WebVector<WebKit::WebMediaStreamComponent> audio_components;
123 description->audioSources(audio_components);
124 for (size_t i = 0; i < audio_components.size(); ++i) {
125 const WebKit::WebMediaStreamSource& source = audio_components[i].source();
126 MediaStreamSourceExtraData* source_data =
127 static_cast<MediaStreamSourceExtraData*>(source.extraData());
128 if (!source_data) {
129 // TODO(perkj): Implement support for sources from remote MediaStreams.
130 NOTIMPLEMENTED();
131 continue;
132 }
133 // TODO(perkj): Refactor the creation of audio tracks to use a proper
134 // interface for receiving audio input data. Currently NULL is passed since
135 // the |audio_device| is the wrong class and is unused.
136 talk_base::scoped_refptr<webrtc::LocalAudioTrackInterface> audio_track(
137 CreateLocalAudioTrack(UTF16ToUTF8(source.id()), NULL));
138 native_stream->AddTrack(audio_track);
139 audio_track->set_enabled(audio_components[i].isEnabled());
140 // TODO(xians): This set the source of all audio tracks to the same
141 // microphone. Implement support for setting the source per audio track
142 // instead.
143 SetAudioDeviceSessionId(source_data->device_info().session_id);
144 }
145
146 // Add video tracks.
147 WebKit::WebVector<WebKit::WebMediaStreamComponent> video_components;
148 description->videoSources(video_components);
149 for (size_t i = 0; i < video_components.size(); ++i) {
150 const WebKit::WebMediaStreamSource& source = video_components[i].source();
151 MediaStreamSourceExtraData* source_data =
152 static_cast<MediaStreamSourceExtraData*>(source.extraData());
153 if (!source_data) {
154 // TODO(perkj): Implement support for sources from remote MediaStreams.
155 NOTIMPLEMENTED();
156 continue;
157 }
158 talk_base::scoped_refptr<webrtc::LocalVideoTrackInterface> video_track(
159 CreateLocalVideoTrack(UTF16ToUTF8(source.id()),
160 source_data->device_info().session_id));
161 native_stream->AddTrack(video_track);
162 video_track->set_enabled(video_components[i].isEnabled());
163 }
164
165 description->setExtraData(new MediaStreamExtraData(native_stream));
166 return true;
167 }
75 168
76 bool MediaStreamDependencyFactory::CreatePeerConnectionFactory( 169 bool MediaStreamDependencyFactory::CreatePeerConnectionFactory(
77 talk_base::Thread* worker_thread, 170 talk_base::Thread* worker_thread,
78 talk_base::Thread* signaling_thread, 171 talk_base::Thread* signaling_thread,
79 content::P2PSocketDispatcher* socket_dispatcher, 172 content::P2PSocketDispatcher* socket_dispatcher,
80 talk_base::NetworkManager* network_manager, 173 talk_base::NetworkManager* network_manager,
81 talk_base::PacketSocketFactory* socket_factory) { 174 talk_base::PacketSocketFactory* socket_factory) {
82 if (!pc_factory_.get()) { 175 if (!pc_factory_.get()) {
83 talk_base::scoped_refptr<P2PPortAllocatorFactory> pa_factory = 176 talk_base::scoped_refptr<P2PPortAllocatorFactory> pa_factory =
84 new talk_base::RefCountedObject<P2PPortAllocatorFactory>( 177 new talk_base::RefCountedObject<P2PPortAllocatorFactory>(
85 socket_dispatcher, 178 socket_dispatcher,
86 network_manager, 179 network_manager,
87 socket_factory); 180 socket_factory);
88 181
89 DCHECK(!audio_device_); 182 DCHECK(!audio_device_);
90 audio_device_ = new WebRtcAudioDeviceImpl(); 183 audio_device_ = new WebRtcAudioDeviceImpl();
91 talk_base::scoped_refptr<webrtc::PeerConnectionFactoryInterface> factory( 184 talk_base::scoped_refptr<webrtc::PeerConnectionFactoryInterface> factory(
92 webrtc::CreatePeerConnectionFactory(worker_thread, 185 webrtc::CreatePeerConnectionFactory(worker_thread,
93 signaling_thread, 186 signaling_thread,
94 pa_factory.release(), 187 pa_factory.release(),
95 audio_device_)); 188 audio_device_));
96 if (factory.get()) 189 if (factory.get())
97 pc_factory_ = factory.release(); 190 pc_factory_ = factory.release();
98 } 191 }
99 return pc_factory_.get() != NULL; 192 return pc_factory_.get() != NULL;
100 } 193 }
101 194
102 void MediaStreamDependencyFactory::ReleasePeerConnectionFactory() {
103 if (pc_factory_.get())
104 pc_factory_ = NULL;
105 }
106
107 bool MediaStreamDependencyFactory::PeerConnectionFactoryCreated() { 195 bool MediaStreamDependencyFactory::PeerConnectionFactoryCreated() {
108 return pc_factory_.get() != NULL; 196 return pc_factory_.get() != NULL;
109 } 197 }
110 198
111 talk_base::scoped_refptr<webrtc::PeerConnectionInterface> 199 talk_base::scoped_refptr<webrtc::PeerConnectionInterface>
112 MediaStreamDependencyFactory::CreatePeerConnection( 200 MediaStreamDependencyFactory::CreatePeerConnection(
113 const std::string& config, 201 const std::string& config,
114 webrtc::PeerConnectionObserver* observer) { 202 webrtc::PeerConnectionObserver* observer) {
115 return pc_factory_->CreatePeerConnection(config, observer); 203 return pc_factory_->CreatePeerConnection(config, observer);
116 } 204 }
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
148 webrtc::IceCandidateInterface* MediaStreamDependencyFactory::CreateIceCandidate( 236 webrtc::IceCandidateInterface* MediaStreamDependencyFactory::CreateIceCandidate(
149 const std::string& sdp_mid, 237 const std::string& sdp_mid,
150 int sdp_mline_index, 238 int sdp_mline_index,
151 const std::string& sdp) { 239 const std::string& sdp) {
152 return webrtc::CreateIceCandidate(sdp_mid, sdp_mline_index, sdp); 240 return webrtc::CreateIceCandidate(sdp_mid, sdp_mline_index, sdp);
153 } 241 }
154 242
155 void MediaStreamDependencyFactory::SetAudioDeviceSessionId(int session_id) { 243 void MediaStreamDependencyFactory::SetAudioDeviceSessionId(int session_id) {
156 audio_device_->SetSessionId(session_id); 244 audio_device_->SetSessionId(session_id);
157 } 245 }
246
247 void MediaStreamDependencyFactory::InitializeWorkerThread(
248 talk_base::Thread** thread,
249 base::WaitableEvent* event) {
250 jingle_glue::JingleThreadWrapper::EnsureForCurrentMessageLoop();
251 jingle_glue::JingleThreadWrapper::current()->set_send_allowed(true);
252 *thread = jingle_glue::JingleThreadWrapper::current();
253 event->Signal();
254 }
255
256 void MediaStreamDependencyFactory::CreateIpcNetworkManagerOnWorkerThread(
257 base::WaitableEvent* event) {
258 DCHECK_EQ(MessageLoop::current(), chrome_worker_thread_.message_loop());
259 network_manager_ = new content::IpcNetworkManager(p2p_socket_dispatcher_);
260 event->Signal();
261 }
262
263 void MediaStreamDependencyFactory::DeleteIpcNetworkManager() {
264 DCHECK_EQ(MessageLoop::current(), chrome_worker_thread_.message_loop());
265 delete network_manager_;
266 network_manager_ = NULL;
267 }
268
269 bool MediaStreamDependencyFactory::EnsurePeerConnectionFactory() {
270 DCHECK(CalledOnValidThread());
271 if(PeerConnectionFactoryCreated())
272 return true;
273
274 if (!signaling_thread_) {
275 jingle_glue::JingleThreadWrapper::EnsureForCurrentMessageLoop();
276 jingle_glue::JingleThreadWrapper::current()->set_send_allowed(true);
277 signaling_thread_ = jingle_glue::JingleThreadWrapper::current();
278 CHECK(signaling_thread_);
279 }
280
281 if (!worker_thread_) {
282 if (!chrome_worker_thread_.IsRunning()) {
283 if (!chrome_worker_thread_.Start()) {
284 LOG(ERROR) << "Could not start worker thread";
285 signaling_thread_ = NULL;
286 return false;
287 }
288 }
289 base::WaitableEvent event(true, false);
290 chrome_worker_thread_.message_loop()->PostTask(FROM_HERE, base::Bind(
291 &MediaStreamDependencyFactory::InitializeWorkerThread,
292 base::Unretained(this),
293 &worker_thread_,
294 &event));
295 event.Wait();
296 DCHECK(worker_thread_);
297 }
298
299 if (!network_manager_) {
300 base::WaitableEvent event(true, false);
301 chrome_worker_thread_.message_loop()->PostTask(FROM_HERE, base::Bind(
302 &MediaStreamDependencyFactory::CreateIpcNetworkManagerOnWorkerThread,
303 base::Unretained(this),
304 &event));
305 event.Wait();
306 }
307
308 if (!socket_factory_.get()) {
309 socket_factory_.reset(
310 new content::IpcPacketSocketFactory(p2p_socket_dispatcher_));
311 }
312
313 if (!CreatePeerConnectionFactory(
314 worker_thread_,
315 signaling_thread_,
316 p2p_socket_dispatcher_,
317 network_manager_,
318 socket_factory_.get())) {
319 LOG(ERROR) << "Could not create PeerConnection factory";
320 return false;
321 }
322 return true;
323 }
324
325 void MediaStreamDependencyFactory::CleanupPeerConnectionFactory() {
326 pc_factory_ = NULL;
327 if (network_manager_) {
328 // The network manager needs to free its resources on the thread they were
329 // created, which is the worked thread.
330 if (chrome_worker_thread_.IsRunning()) {
331 chrome_worker_thread_.message_loop()->PostTask(FROM_HERE, base::Bind(
332 &MediaStreamDependencyFactory::DeleteIpcNetworkManager,
333 base::Unretained(this)));
334 // Stopping the thread will wait until all tasks have been
335 // processed before returning. We wait for the above task to finish before
336 // letting the the function continue to avoid any potential race issues.
337 chrome_worker_thread_.Stop();
338 } else {
339 NOTREACHED() << "Worker thread not running.";
340 }
341 }
342 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698