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

Unified 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 side-by-side diff with in-line comments
Download patch
Index: content/renderer/media/media_stream_dependency_factory.cc
diff --git a/content/renderer/media/media_stream_dependency_factory.cc b/content/renderer/media/media_stream_dependency_factory.cc
index e44ecd8edb49411ad47fe6bfb7c686c5efd9f6cb..4f4565646f9aa8a155ceeee710bf8af92158da70 100644
--- a/content/renderer/media/media_stream_dependency_factory.cc
+++ b/content/renderer/media/media_stream_dependency_factory.cc
@@ -6,14 +6,23 @@
#include <vector>
+#include "base/synchronization/waitable_event.h"
+#include "base/utf_string_conversions.h"
+#include "content/renderer/media/media_stream_extra_data.h"
+#include "content/renderer/media/media_stream_source_extra_data.h"
#include "content/renderer/media/rtc_video_capturer.h"
+#include "content/renderer/media/peer_connection_handler_jsep.h"
#include "content/renderer/media/video_capture_impl_manager.h"
#include "content/renderer/media/webrtc_audio_device_impl.h"
+#include "content/renderer/media/webrtc_uma_histograms.h"
#include "content/renderer/p2p/ipc_network_manager.h"
#include "content/renderer/p2p/ipc_socket_factory.h"
#include "content/renderer/p2p/port_allocator.h"
#include "jingle/glue/thread_wrapper.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/WebFrame.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebMediaStreamComponent.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebMediaStreamDescriptor.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebMediaStreamSource.h"
class P2PPortAllocatorFactory : public webrtc::PortAllocatorFactoryInterface {
public:
@@ -57,21 +66,105 @@ class P2PPortAllocatorFactory : public webrtc::PortAllocatorFactoryInterface {
virtual ~P2PPortAllocatorFactory() {}
private:
- // socket_dispatcher_ is a weak reference, owned by RenderView. It's valid
- // for the lifetime of RenderView.
- content::P2PSocketDispatcher* socket_dispatcher_;
- // network_manager_ and socket_factory_ are a weak references, owned by
- // MediaStreamImpl.
+ scoped_refptr<content::P2PSocketDispatcher> socket_dispatcher_;
+ // |network_manager_| and |socket_factory_| are a weak references, owned by
+ // MediaStreamDependencyFactory.
talk_base::NetworkManager* network_manager_;
talk_base::PacketSocketFactory* socket_factory_;
};
MediaStreamDependencyFactory::MediaStreamDependencyFactory(
- VideoCaptureImplManager* vc_manager)
- : vc_manager_(vc_manager) {
+ VideoCaptureImplManager* vc_manager,
+ content::P2PSocketDispatcher* p2p_socket_dispatcher)
+ : network_manager_(NULL),
+ vc_manager_(vc_manager),
+ p2p_socket_dispatcher_(p2p_socket_dispatcher),
+ signaling_thread_(NULL),
+ worker_thread_(NULL),
+ chrome_worker_thread_("Chrome_libJingle_WorkerThread") {
}
-MediaStreamDependencyFactory::~MediaStreamDependencyFactory() {}
+MediaStreamDependencyFactory::~MediaStreamDependencyFactory() {
+ CleanupPeerConnectionFactory();
+}
+
+WebKit::WebPeerConnection00Handler*
+MediaStreamDependencyFactory::CreatePeerConnectionHandlerJsep(
+ WebKit::WebPeerConnection00HandlerClient* client) {
+ // Save histogram data so we can see how much PeerConnetion is used.
+ // The histogram counts the number of calls to the JS API
+ // webKitPeerConnection00.
+ UpdateWebRTCMethodCount(WEBKIT_PEER_CONNECTION);
+
+ if (!EnsurePeerConnectionFactory()) {
+ return NULL;
+ }
+
+ return new PeerConnectionHandlerJsep(client, this);
+}
+
+bool MediaStreamDependencyFactory::CreateNativeLocalMediaStream(
+ WebKit::WebMediaStreamDescriptor* description) {
+ // Creating the peer connection factory can fail if for example the audio
+ // (input or output) or video device cannot be opened. Handling such cases
+ // better is a higher level design discussion which involves the media
+ // manager, webrtc and libjingle. We cannot create any native
+ // track objects however, so we'll just have to skip that. Furthermore,
+ // creating a peer connection later on will fail if we don't have a factory.
+ if (!EnsurePeerConnectionFactory())
+ return false;
+
+ std::string label = UTF16ToUTF8(description->label());
+ talk_base::scoped_refptr<webrtc::LocalMediaStreamInterface> native_stream =
+ CreateLocalMediaStream(label);
+
+ // Add audio tracks.
+ WebKit::WebVector<WebKit::WebMediaStreamComponent> audio_components;
+ description->audioSources(audio_components);
+ for (size_t i = 0; i < audio_components.size(); ++i) {
+ const WebKit::WebMediaStreamSource& source = audio_components[i].source();
+ MediaStreamSourceExtraData* source_data =
+ static_cast<MediaStreamSourceExtraData*>(source.extraData());
+ if (!source_data) {
+ // TODO(perkj): Implement support for sources from remote MediaStreams.
+ NOTIMPLEMENTED();
+ continue;
+ }
+ // TODO(perkj): Refactor the creation of audio tracks to use a proper
+ // interface for receiving audio input data. Currently NULL is passed since
+ // the |audio_device| is the wrong class and is unused.
+ talk_base::scoped_refptr<webrtc::LocalAudioTrackInterface> audio_track(
+ CreateLocalAudioTrack(UTF16ToUTF8(source.id()), NULL));
+ native_stream->AddTrack(audio_track);
+ audio_track->set_enabled(audio_components[i].isEnabled());
+ // TODO(xians): This set the source of all audio tracks to the same
+ // microphone. Implement support for setting the source per audio track
+ // instead.
+ SetAudioDeviceSessionId(source_data->device_info().session_id);
+ }
+
+ // Add video tracks.
+ WebKit::WebVector<WebKit::WebMediaStreamComponent> video_components;
+ description->videoSources(video_components);
+ for (size_t i = 0; i < video_components.size(); ++i) {
+ const WebKit::WebMediaStreamSource& source = video_components[i].source();
+ MediaStreamSourceExtraData* source_data =
+ static_cast<MediaStreamSourceExtraData*>(source.extraData());
+ if (!source_data) {
+ // TODO(perkj): Implement support for sources from remote MediaStreams.
+ NOTIMPLEMENTED();
+ continue;
+ }
+ talk_base::scoped_refptr<webrtc::LocalVideoTrackInterface> video_track(
+ CreateLocalVideoTrack(UTF16ToUTF8(source.id()),
+ source_data->device_info().session_id));
+ native_stream->AddTrack(video_track);
+ video_track->set_enabled(video_components[i].isEnabled());
+ }
+
+ description->setExtraData(new MediaStreamExtraData(native_stream));
+ return true;
+}
bool MediaStreamDependencyFactory::CreatePeerConnectionFactory(
talk_base::Thread* worker_thread,
@@ -99,11 +192,6 @@ bool MediaStreamDependencyFactory::CreatePeerConnectionFactory(
return pc_factory_.get() != NULL;
}
-void MediaStreamDependencyFactory::ReleasePeerConnectionFactory() {
- if (pc_factory_.get())
- pc_factory_ = NULL;
-}
-
bool MediaStreamDependencyFactory::PeerConnectionFactoryCreated() {
return pc_factory_.get() != NULL;
}
@@ -155,3 +243,100 @@ webrtc::IceCandidateInterface* MediaStreamDependencyFactory::CreateIceCandidate(
void MediaStreamDependencyFactory::SetAudioDeviceSessionId(int session_id) {
audio_device_->SetSessionId(session_id);
}
+
+void MediaStreamDependencyFactory::InitializeWorkerThread(
+ talk_base::Thread** thread,
+ base::WaitableEvent* event) {
+ jingle_glue::JingleThreadWrapper::EnsureForCurrentMessageLoop();
+ jingle_glue::JingleThreadWrapper::current()->set_send_allowed(true);
+ *thread = jingle_glue::JingleThreadWrapper::current();
+ event->Signal();
+}
+
+void MediaStreamDependencyFactory::CreateIpcNetworkManagerOnWorkerThread(
+ base::WaitableEvent* event) {
+ DCHECK_EQ(MessageLoop::current(), chrome_worker_thread_.message_loop());
+ network_manager_ = new content::IpcNetworkManager(p2p_socket_dispatcher_);
+ event->Signal();
+}
+
+void MediaStreamDependencyFactory::DeleteIpcNetworkManager() {
+ DCHECK_EQ(MessageLoop::current(), chrome_worker_thread_.message_loop());
+ delete network_manager_;
+ network_manager_ = NULL;
+}
+
+bool MediaStreamDependencyFactory::EnsurePeerConnectionFactory() {
+ DCHECK(CalledOnValidThread());
+ if(PeerConnectionFactoryCreated())
+ return true;
+
+ if (!signaling_thread_) {
+ jingle_glue::JingleThreadWrapper::EnsureForCurrentMessageLoop();
+ jingle_glue::JingleThreadWrapper::current()->set_send_allowed(true);
+ signaling_thread_ = jingle_glue::JingleThreadWrapper::current();
+ CHECK(signaling_thread_);
+ }
+
+ if (!worker_thread_) {
+ if (!chrome_worker_thread_.IsRunning()) {
+ if (!chrome_worker_thread_.Start()) {
+ LOG(ERROR) << "Could not start worker thread";
+ signaling_thread_ = NULL;
+ return false;
+ }
+ }
+ base::WaitableEvent event(true, false);
+ chrome_worker_thread_.message_loop()->PostTask(FROM_HERE, base::Bind(
+ &MediaStreamDependencyFactory::InitializeWorkerThread,
+ base::Unretained(this),
+ &worker_thread_,
+ &event));
+ event.Wait();
+ DCHECK(worker_thread_);
+ }
+
+ if (!network_manager_) {
+ base::WaitableEvent event(true, false);
+ chrome_worker_thread_.message_loop()->PostTask(FROM_HERE, base::Bind(
+ &MediaStreamDependencyFactory::CreateIpcNetworkManagerOnWorkerThread,
+ base::Unretained(this),
+ &event));
+ event.Wait();
+ }
+
+ if (!socket_factory_.get()) {
+ socket_factory_.reset(
+ new content::IpcPacketSocketFactory(p2p_socket_dispatcher_));
+ }
+
+ if (!CreatePeerConnectionFactory(
+ worker_thread_,
+ signaling_thread_,
+ p2p_socket_dispatcher_,
+ network_manager_,
+ socket_factory_.get())) {
+ LOG(ERROR) << "Could not create PeerConnection factory";
+ return false;
+ }
+ return true;
+}
+
+void MediaStreamDependencyFactory::CleanupPeerConnectionFactory() {
+ pc_factory_ = NULL;
+ if (network_manager_) {
+ // The network manager needs to free its resources on the thread they were
+ // created, which is the worked thread.
+ if (chrome_worker_thread_.IsRunning()) {
+ chrome_worker_thread_.message_loop()->PostTask(FROM_HERE, base::Bind(
+ &MediaStreamDependencyFactory::DeleteIpcNetworkManager,
+ base::Unretained(this)));
+ // Stopping the thread will wait until all tasks have been
+ // processed before returning. We wait for the above task to finish before
+ // letting the the function continue to avoid any potential race issues.
+ chrome_worker_thread_.Stop();
+ } else {
+ NOTREACHED() << "Worker thread not running.";
+ }
+ }
+}

Powered by Google App Engine
This is Rietveld 408576698