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

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: Rebased to latest codec base. 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 // |socket_dispatcher_| is a weak reference, owned by RenderThreadImpl.
61 // for the lifetime of RenderView. 70 // It's valid for the lifetime of RenderThreadImpl.
62 content::P2PSocketDispatcher* socket_dispatcher_; 71 content::P2PSocketDispatcher* socket_dispatcher_;
tommi (sloooow) - chröme 2012/09/12 13:10:24 can this now be a scoped_refptr?
perkj_chrome 2012/09/12 13:54:39 Done.
63 // network_manager_ and socket_factory_ are a weak references, owned by 72 // |network_manager_| and |socket_factory_| are a weak references, owned by
64 // MediaStreamImpl. 73 // MediaStreamDependencyFactory.
65 talk_base::NetworkManager* network_manager_; 74 talk_base::NetworkManager* network_manager_;
66 talk_base::PacketSocketFactory* socket_factory_; 75 talk_base::PacketSocketFactory* socket_factory_;
67 }; 76 };
68 77
69 MediaStreamDependencyFactory::MediaStreamDependencyFactory( 78 MediaStreamDependencyFactory::MediaStreamDependencyFactory(
70 VideoCaptureImplManager* vc_manager) 79 VideoCaptureImplManager* vc_manager,
71 : vc_manager_(vc_manager) { 80 content::P2PSocketDispatcher* p2p_socket_dispatcher)
81 : network_manager_(NULL),
82 vc_manager_(vc_manager),
83 p2p_socket_dispatcher_(p2p_socket_dispatcher),
84 signaling_thread_(NULL),
85 worker_thread_(NULL),
86 chrome_worker_thread_("Chrome_libJingle_WorkerThread") {
72 } 87 }
73 88
74 MediaStreamDependencyFactory::~MediaStreamDependencyFactory() {} 89 MediaStreamDependencyFactory::~MediaStreamDependencyFactory() {
90 CleanupPeerConnectionFactory();
91 }
92
93 WebKit::WebPeerConnection00Handler*
94 MediaStreamDependencyFactory::CreatePeerConnectionHandlerJsep(
95 WebKit::WebPeerConnection00HandlerClient* client) {
96 // Save histogram data so we can see how much PeerConnetion is used.
97 // The histogram counts the number of calls to the JS API
98 // webKitPeerConnection00.
99 UpdateWebRTCMethodCount(kWebkitPeerConnection);
100
101 if (!EnsurePeerConnectionFactory()) {
102 return NULL;
103 }
104
105 PeerConnectionHandlerJsep* pc_handler = new PeerConnectionHandlerJsep(
106 client,
107 this);
108 return pc_handler;
109 }
110
111 bool MediaStreamDependencyFactory::CreateNativeLocalMediaStream(
112 WebKit::WebMediaStreamDescriptor* description) {
113 // Creating the peer connection factory can fail if for example the audio
114 // (input or output) or video device cannot be opened. Handling such cases
115 // better is a higher level design discussion which involves the media
116 // manager, webrtc and libjingle. We cannot create any native
117 // track objects however, so we'll just have to skip that. Furthermore,
118 // creating a peer connection later on will fail if we don't have a factory.
119 if (!EnsurePeerConnectionFactory())
120 return false;
121
122 std::string label = UTF16ToUTF8(description->label());
123 talk_base::scoped_refptr<webrtc::LocalMediaStreamInterface> native_stream =
124 CreateLocalMediaStream(label);
125
126 // Add audio tracks.
127 WebKit::WebVector<WebKit::WebMediaStreamComponent> audio_components;
128 description->audioSources(audio_components);
129 for (size_t i = 0; i < audio_components.size(); ++i) {
130 const WebKit::WebMediaStreamSource& source = audio_components[i].source();
131 MediaStreamSourceExtraData* source_data =
132 static_cast<MediaStreamSourceExtraData*>(source.extraData());
133 if (!source_data) {
134 // TODO(perkj): Implement support for sources from remote MediaStreams.
135 NOTIMPLEMENTED();
136 continue;
137 }
138 // TODO(perkj): Refactor the creation of audio tracks to use a proper
139 // interface for receiving audio input data. Currently NULL is passed since
140 // the |audio_device| is the wrong class and is unused.
141 talk_base::scoped_refptr<webrtc::LocalAudioTrackInterface> audio_track(
142 CreateLocalAudioTrack(UTF16ToUTF8(source.id()), NULL));
143 native_stream->AddTrack(audio_track);
144 audio_track->set_enabled(audio_components[i].isEnabled());
145 // TODO(xians): This set the source of all audio tracks to the same
146 // microphone. Implement support for setting the source per audio track
147 // instead.
148 SetAudioDeviceSessionId(source_data->device_info().session_id);
149 }
150
151 // Add video tracks.
152 WebKit::WebVector<WebKit::WebMediaStreamComponent> video_components;
153 description->videoSources(video_components);
154 for (size_t i = 0; i < video_components.size(); ++i) {
155 const WebKit::WebMediaStreamSource& source = video_components[i].source();
156 MediaStreamSourceExtraData* source_data =
157 static_cast<MediaStreamSourceExtraData*>(source.extraData());
158 if (!source_data) {
159 // TODO(perkj): Implement support for sources from remote MediaStreams.
160 NOTIMPLEMENTED();
161 continue;
162 }
163 talk_base::scoped_refptr<webrtc::LocalVideoTrackInterface> video_track(
164 CreateLocalVideoTrack(UTF16ToUTF8(source.id()),
165 source_data->device_info().session_id));
166 native_stream->AddTrack(video_track);
167 video_track->set_enabled(video_components[i].isEnabled());
168 }
169
170 description->setExtraData(new MediaStreamExtraData(native_stream));
171 return true;
172 }
75 173
76 bool MediaStreamDependencyFactory::CreatePeerConnectionFactory( 174 bool MediaStreamDependencyFactory::CreatePeerConnectionFactory(
77 talk_base::Thread* worker_thread, 175 talk_base::Thread* worker_thread,
78 talk_base::Thread* signaling_thread, 176 talk_base::Thread* signaling_thread,
79 content::P2PSocketDispatcher* socket_dispatcher, 177 content::P2PSocketDispatcher* socket_dispatcher,
80 talk_base::NetworkManager* network_manager, 178 talk_base::NetworkManager* network_manager,
81 talk_base::PacketSocketFactory* socket_factory) { 179 talk_base::PacketSocketFactory* socket_factory) {
82 if (!pc_factory_.get()) { 180 if (!pc_factory_.get()) {
83 talk_base::scoped_refptr<P2PPortAllocatorFactory> pa_factory = 181 talk_base::scoped_refptr<P2PPortAllocatorFactory> pa_factory =
84 new talk_base::RefCountedObject<P2PPortAllocatorFactory>( 182 new talk_base::RefCountedObject<P2PPortAllocatorFactory>(
85 socket_dispatcher, 183 socket_dispatcher,
86 network_manager, 184 network_manager,
87 socket_factory); 185 socket_factory);
88 186
89 DCHECK(!audio_device_); 187 DCHECK(!audio_device_);
90 audio_device_ = new WebRtcAudioDeviceImpl(); 188 audio_device_ = new WebRtcAudioDeviceImpl();
91 talk_base::scoped_refptr<webrtc::PeerConnectionFactoryInterface> factory( 189 talk_base::scoped_refptr<webrtc::PeerConnectionFactoryInterface> factory(
92 webrtc::CreatePeerConnectionFactory(worker_thread, 190 webrtc::CreatePeerConnectionFactory(worker_thread,
93 signaling_thread, 191 signaling_thread,
94 pa_factory.release(), 192 pa_factory.release(),
95 audio_device_)); 193 audio_device_));
96 if (factory.get()) 194 if (factory.get())
97 pc_factory_ = factory.release(); 195 pc_factory_ = factory.release();
98 } 196 }
99 return pc_factory_.get() != NULL; 197 return pc_factory_.get() != NULL;
100 } 198 }
101 199
102 void MediaStreamDependencyFactory::ReleasePeerConnectionFactory() {
103 if (pc_factory_.get())
104 pc_factory_ = NULL;
105 }
106
107 bool MediaStreamDependencyFactory::PeerConnectionFactoryCreated() { 200 bool MediaStreamDependencyFactory::PeerConnectionFactoryCreated() {
108 return pc_factory_.get() != NULL; 201 return pc_factory_.get() != NULL;
109 } 202 }
110 203
111 talk_base::scoped_refptr<webrtc::PeerConnectionInterface> 204 talk_base::scoped_refptr<webrtc::PeerConnectionInterface>
112 MediaStreamDependencyFactory::CreatePeerConnection( 205 MediaStreamDependencyFactory::CreatePeerConnection(
113 const std::string& config, 206 const std::string& config,
114 webrtc::PeerConnectionObserver* observer) { 207 webrtc::PeerConnectionObserver* observer) {
115 return pc_factory_->CreatePeerConnection(config, observer); 208 return pc_factory_->CreatePeerConnection(config, observer);
116 } 209 }
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
148 webrtc::IceCandidateInterface* MediaStreamDependencyFactory::CreateIceCandidate( 241 webrtc::IceCandidateInterface* MediaStreamDependencyFactory::CreateIceCandidate(
149 const std::string& sdp_mid, 242 const std::string& sdp_mid,
150 int sdp_mline_index, 243 int sdp_mline_index,
151 const std::string& sdp) { 244 const std::string& sdp) {
152 return webrtc::CreateIceCandidate(sdp_mid, sdp_mline_index, sdp); 245 return webrtc::CreateIceCandidate(sdp_mid, sdp_mline_index, sdp);
153 } 246 }
154 247
155 void MediaStreamDependencyFactory::SetAudioDeviceSessionId(int session_id) { 248 void MediaStreamDependencyFactory::SetAudioDeviceSessionId(int session_id) {
156 audio_device_->SetSessionId(session_id); 249 audio_device_->SetSessionId(session_id);
157 } 250 }
251
252 void MediaStreamDependencyFactory::InitializeWorkerThread(
253 talk_base::Thread** thread,
254 base::WaitableEvent* event) {
255 jingle_glue::JingleThreadWrapper::EnsureForCurrentMessageLoop();
256 jingle_glue::JingleThreadWrapper::current()->set_send_allowed(true);
257 *thread = jingle_glue::JingleThreadWrapper::current();
258 event->Signal();
259 }
260
261 void MediaStreamDependencyFactory::CreateIpcNetworkManagerOnWorkerThread(
262 base::WaitableEvent* event) {
263 DCHECK_EQ(MessageLoop::current(), chrome_worker_thread_.message_loop());
264 network_manager_ = new content::IpcNetworkManager(p2p_socket_dispatcher_);
265 event->Signal();
266 }
267
268 void MediaStreamDependencyFactory::DeleteIpcNetworkManager() {
269 DCHECK_EQ(MessageLoop::current(), chrome_worker_thread_.message_loop());
270 delete network_manager_;
271 network_manager_ = NULL;
272 }
273
274 bool MediaStreamDependencyFactory::EnsurePeerConnectionFactory() {
275 DCHECK(CalledOnValidThread());
276 if (!signaling_thread_) {
277 jingle_glue::JingleThreadWrapper::EnsureForCurrentMessageLoop();
278 jingle_glue::JingleThreadWrapper::current()->set_send_allowed(true);
279 signaling_thread_ = jingle_glue::JingleThreadWrapper::current();
tommi (sloooow) - chröme 2012/09/12 13:10:24 should we CHECK that this isn't NULL?
perkj_chrome 2012/09/12 13:54:39 Done.
280 }
281
282 if (!worker_thread_) {
283 if (!chrome_worker_thread_.IsRunning()) {
284 if (!chrome_worker_thread_.Start()) {
285 LOG(ERROR) << "Could not start worker thread";
286 signaling_thread_ = NULL;
287 return false;
288 }
289 }
290 base::WaitableEvent event(true, false);
291 chrome_worker_thread_.message_loop()->PostTask(FROM_HERE, base::Bind(
292 &MediaStreamDependencyFactory::InitializeWorkerThread,
293 base::Unretained(this),
294 &worker_thread_,
295 &event));
296 event.Wait();
297 DCHECK(worker_thread_);
298 }
299
300 if (!network_manager_) {
301 base::WaitableEvent event(true, false);
302 chrome_worker_thread_.message_loop()->PostTask(FROM_HERE, base::Bind(
303 &MediaStreamDependencyFactory::CreateIpcNetworkManagerOnWorkerThread,
tommi (sloooow) - chröme 2012/09/12 13:10:24 fix indent
perkj_chrome 2012/09/12 13:54:39 Done.
304 base::Unretained(this),
305 &event));
306 event.Wait();
307 }
308
309 if (!socket_factory_.get()) {
310 socket_factory_.reset(
311 new content::IpcPacketSocketFactory(p2p_socket_dispatcher_));
312 }
313
314 if (!PeerConnectionFactoryCreated()) {
tommi (sloooow) - chröme 2012/09/12 13:10:24 could you have this check at the top and return ea
perkj_chrome 2012/09/12 13:54:39 Done.
315 if (!CreatePeerConnectionFactory(
316 worker_thread_,
317 signaling_thread_,
318 p2p_socket_dispatcher_,
319 network_manager_,
320 socket_factory_.get())) {
321 LOG(ERROR) << "Could not create PeerConnection factory";
322 return false;
323 }
324 }
325
326 return true;
327 }
328
329 void MediaStreamDependencyFactory::CleanupPeerConnectionFactory() {
330 pc_factory_ = NULL;
331 if (network_manager_) {
332 // The network manager needs to free its resources on the thread they were
333 // created, which is the worked thread.
334 if (chrome_worker_thread_.IsRunning()) {
335 chrome_worker_thread_.message_loop()->PostTask(FROM_HERE, base::Bind(
336 &MediaStreamDependencyFactory::DeleteIpcNetworkManager,
337 base::Unretained(this)));
338 // Stopping the thread will wait until all tasks have been
339 // processed before returning. We wait for the above task to finish before
340 // letting the the function continue to avoid any potential race issues.
341 chrome_worker_thread_.Stop();
342 } else {
343 NOTREACHED() << "Worker thread not running.";
344 }
345 }
346 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698