summaryrefslogtreecommitdiffstats
path: root/content
diff options
context:
space:
mode:
authorgrunell@chromium.org <grunell@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-01-28 02:30:33 +0000
committergrunell@chromium.org <grunell@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-01-28 02:30:33 +0000
commitbf47de28e9c36a4b9390e8ce48a48c5917fd9a04 (patch)
treeecb2f6e2cd19e39e1675f2c295ce77b26532dca3 /content
parentbaacb23598bfad687e1388fe2956e43d0ef0c7d8 (diff)
downloadchromium_src-bf47de28e9c36a4b9390e8ce48a48c5917fd9a04.zip
chromium_src-bf47de28e9c36a4b9390e8ce48a48c5917fd9a04.tar.gz
chromium_src-bf47de28e9c36a4b9390e8ce48a48c5917fd9a04.tar.bz2
Enabling usage of native PeerConnection v2 in libjingle.
The new PeerConnection in libjingle follows the current specification much closer and allows us to remove workarounds and limitations in the glue for WebRTC functionality. TEST=content_unittests Review URL: http://codereview.chromium.org/9284020 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@119568 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'content')
-rw-r--r--content/renderer/media/media_stream_dependency_factory.cc150
-rw-r--r--content/renderer/media/media_stream_dependency_factory.h52
-rw-r--r--content/renderer/media/media_stream_impl.cc281
-rw-r--r--content/renderer/media/media_stream_impl.h51
-rw-r--r--content/renderer/media/mock_media_stream_dependency_factory.cc175
-rw-r--r--content/renderer/media/mock_media_stream_dependency_factory.h68
-rw-r--r--content/renderer/media/mock_media_stream_impl.cc20
-rw-r--r--content/renderer/media/mock_media_stream_impl.h13
-rw-r--r--content/renderer/media/mock_peer_connection_impl.cc113
-rw-r--r--content/renderer/media/mock_peer_connection_impl.h63
-rw-r--r--content/renderer/media/peer_connection_handler.cc304
-rw-r--r--content/renderer/media/peer_connection_handler.h111
-rw-r--r--content/renderer/media/peer_connection_handler_unittest.cc120
13 files changed, 896 insertions, 625 deletions
diff --git a/content/renderer/media/media_stream_dependency_factory.cc b/content/renderer/media/media_stream_dependency_factory.cc
index a9e9d46..43c5d60 100644
--- a/content/renderer/media/media_stream_dependency_factory.cc
+++ b/content/renderer/media/media_stream_dependency_factory.cc
@@ -4,69 +4,141 @@
#include "content/renderer/media/media_stream_dependency_factory.h"
+#include <vector>
+
#include "content/renderer/media/video_capture_module_impl.h"
#include "content/renderer/media/webrtc_audio_device_impl.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/libjingle/source/talk/app/webrtcv1/peerconnection.h"
-#include "third_party/libjingle/source/talk/session/phone/dummydevicemanager.h"
-#include "third_party/libjingle/source/talk/session/phone/webrtcmediaengine.h"
+#include "third_party/libjingle/source/talk/app/webrtc/peerconnection.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/WebFrame.h"
+static std::string ParseHostName(const std::string& hostname) {
+ std::string address;
+ size_t pos = hostname.find(':');
+ if (pos == std::string::npos) {
+ DVLOG(1) << "No port specified.";
+ } else {
+ address = hostname.substr(0, pos);
+ }
+ return address;
+}
+
+class P2PPortAllocatorFactory : public webrtc::PortAllocatorFactoryInterface {
+ public:
+ P2PPortAllocatorFactory(
+ content::P2PSocketDispatcher* socket_dispatcher,
+ talk_base::NetworkManager* network_manager,
+ talk_base::PacketSocketFactory* socket_factory)
+ : socket_dispatcher_(socket_dispatcher),
+ network_manager_(network_manager),
+ socket_factory_(socket_factory) {
+ }
+
+ virtual cricket::PortAllocator* CreatePortAllocator(
+ const std::vector<StunConfiguration>& stun_servers,
+ const std::vector<TurnConfiguration>& turn_configurations) OVERRIDE {
+ WebKit::WebFrame* web_frame = WebKit::WebFrame::frameForCurrentContext();
+ if (!web_frame) {
+ LOG(ERROR) << "WebFrame is NULL.";
+ return NULL;
+ }
+ webkit_glue::P2PTransport::Config config;
+ if (stun_servers.size() > 0) {
+ config.stun_server = ParseHostName(stun_servers[0].server.hostname());
+ config.stun_server_port = stun_servers[0].server.port();
+ }
+ if (turn_configurations.size() > 0) {
+ config.relay_server = ParseHostName(
+ turn_configurations[0].server.hostname());
+ config.relay_server_port = turn_configurations[0].server.port();
+ config.relay_username = turn_configurations[0].username;
+ config.relay_password = turn_configurations[0].password;
+ }
+
+ return new content::P2PPortAllocator(web_frame,
+ socket_dispatcher_,
+ network_manager_,
+ socket_factory_,
+ config);
+ }
+
+ protected:
+ 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.
+ talk_base::NetworkManager* network_manager_;
+ talk_base::PacketSocketFactory* socket_factory_;
+};
+
+
MediaStreamDependencyFactory::MediaStreamDependencyFactory() {}
MediaStreamDependencyFactory::~MediaStreamDependencyFactory() {}
-cricket::WebRtcMediaEngine*
-MediaStreamDependencyFactory::CreateWebRtcMediaEngine() {
- webrtc::AudioDeviceModule* adm = new WebRtcAudioDeviceImpl();
- webrtc::AudioDeviceModule* adm_sc = new WebRtcAudioDeviceImpl();
- return new cricket::WebRtcMediaEngine(adm, adm_sc, NULL);
-}
-
bool MediaStreamDependencyFactory::CreatePeerConnectionFactory(
- cricket::MediaEngineInterface* media_engine,
- talk_base::Thread* worker_thread) {
+ talk_base::Thread* worker_thread,
+ talk_base::Thread* signaling_thread,
+ content::P2PSocketDispatcher* socket_dispatcher,
+ talk_base::NetworkManager* network_manager,
+ talk_base::PacketSocketFactory* socket_factory) {
if (!pc_factory_.get()) {
- scoped_ptr<webrtc::PeerConnectionFactory> factory(
- new webrtc::PeerConnectionFactory(media_engine,
- new cricket::DummyDeviceManager(),
- worker_thread));
- if (factory->Initialize())
- pc_factory_.reset(factory.release());
+ talk_base::scoped_refptr<P2PPortAllocatorFactory> pa_factory =
+ new talk_base::RefCountedObject<P2PPortAllocatorFactory>(
+ socket_dispatcher,
+ network_manager,
+ socket_factory);
+
+ talk_base::scoped_refptr<webrtc::PeerConnectionFactoryInterface> factory(
+ webrtc::CreatePeerConnectionFactory(worker_thread,
+ signaling_thread,
+ pa_factory.release(),
+ new WebRtcAudioDeviceImpl()));
+ if (factory.get())
+ pc_factory_ = factory.release();
}
return pc_factory_.get() != NULL;
}
-void MediaStreamDependencyFactory::DeletePeerConnectionFactory() {
- pc_factory_.reset();
+void MediaStreamDependencyFactory::ReleasePeerConnectionFactory() {
+ if (pc_factory_.get())
+ pc_factory_ = NULL;
}
bool MediaStreamDependencyFactory::PeerConnectionFactoryCreated() {
return pc_factory_.get() != NULL;
}
-cricket::PortAllocator* MediaStreamDependencyFactory::CreatePortAllocator(
- content::P2PSocketDispatcher* socket_dispatcher,
- talk_base::NetworkManager* network_manager,
- talk_base::PacketSocketFactory* socket_factory,
- const webkit_glue::P2PTransport::Config& config) {
- WebKit::WebFrame* web_frame = WebKit::WebFrame::frameForCurrentContext();
- if (!web_frame) {
- DVLOG(1) << "WebFrame is NULL.";
- return NULL;
- }
- return new content::P2PPortAllocator(web_frame,
- socket_dispatcher,
- network_manager,
- socket_factory,
- config);
+talk_base::scoped_refptr<webrtc::PeerConnectionInterface>
+MediaStreamDependencyFactory::CreatePeerConnection(
+ const std::string& config,
+ webrtc::PeerConnectionObserver* observer) {
+ return pc_factory_->CreatePeerConnection(config, observer);
+}
+
+talk_base::scoped_refptr<webrtc::LocalMediaStreamInterface>
+MediaStreamDependencyFactory::CreateLocalMediaStream(
+ const std::string& label) {
+ return pc_factory_->CreateLocalMediaStream(label);
+}
+
+talk_base::scoped_refptr<webrtc::LocalVideoTrackInterface>
+MediaStreamDependencyFactory::CreateLocalVideoTrack(
+ const std::string& label,
+ cricket::VideoCapturer* video_device) {
+ return pc_factory_->CreateLocalVideoTrack(label, video_device);
}
-webrtc::PeerConnection* MediaStreamDependencyFactory::CreatePeerConnection(
- cricket::PortAllocator* port_allocator,
- talk_base::Thread* signaling_thread) {
- return pc_factory_->CreatePeerConnection(port_allocator, signaling_thread);
+talk_base::scoped_refptr<webrtc::LocalAudioTrackInterface>
+MediaStreamDependencyFactory::CreateLocalAudioTrack(
+ const std::string& label,
+ webrtc::AudioDeviceModule* audio_device) {
+ return pc_factory_->CreateLocalAudioTrack(label, audio_device);
}
diff --git a/content/renderer/media/media_stream_dependency_factory.h b/content/renderer/media/media_stream_dependency_factory.h
index ea51b58..20efd9e 100644
--- a/content/renderer/media/media_stream_dependency_factory.h
+++ b/content/renderer/media/media_stream_dependency_factory.h
@@ -10,7 +10,7 @@
#include "base/basictypes.h"
#include "base/memory/scoped_ptr.h"
#include "content/common/content_export.h"
-#include "third_party/libjingle/source/talk/app/webrtcv1/peerconnectionfactory.h"
+#include "third_party/libjingle/source/talk/app/webrtc/peerconnection.h"
#include "webkit/glue/p2p_transport.h"
namespace content {
@@ -20,9 +20,7 @@ class P2PSocketDispatcher;
}
namespace cricket {
-class MediaEngineInterface;
class PortAllocator;
-class WebRtcMediaEngine;
}
namespace talk_base {
@@ -42,35 +40,39 @@ class CONTENT_EXPORT MediaStreamDependencyFactory {
MediaStreamDependencyFactory();
virtual ~MediaStreamDependencyFactory();
- // WebRtcMediaEngine is used in CreatePeerConnectionFactory().
- virtual cricket::WebRtcMediaEngine* CreateWebRtcMediaEngine();
-
// Creates and deletes |pc_factory_|, which in turn is used for
- // creating PeerConnection objects. |media_engine| is the engine created by
- // CreateWebRtcMediaEngine(). |port_allocator| and |media_engine| will be
- // owned by |pc_factory_|. |worker_thread| is owned by MediaStreamImpl.
+ // creating PeerConnection objects.
virtual bool CreatePeerConnectionFactory(
- cricket::MediaEngineInterface* media_engine,
- talk_base::Thread* worker_thread);
- virtual void DeletePeerConnectionFactory();
- virtual bool PeerConnectionFactoryCreated();
-
- // The port allocator is used in CreatePeerConnection().
- virtual cricket::PortAllocator* CreatePortAllocator(
+ talk_base::Thread* worker_thread,
+ talk_base::Thread* signaling_thread,
content::P2PSocketDispatcher* socket_dispatcher,
talk_base::NetworkManager* network_manager,
- talk_base::PacketSocketFactory* socket_factory,
- const webkit_glue::P2PTransport::Config& config);
+ talk_base::PacketSocketFactory* socket_factory);
+ virtual void ReleasePeerConnectionFactory();
+ virtual bool PeerConnectionFactoryCreated();
+
+ // Asks the PeerConnection factory to create a PeerConnection object.
+ // The PeerConnection object is owned by PeerConnectionHandler.
+ virtual talk_base::scoped_refptr<webrtc::PeerConnectionInterface>
+ CreatePeerConnection(const std::string& config,
+ webrtc::PeerConnectionObserver* observer);
+
+ // Asks the PeerConnection factory to create a Local MediaStream object.
+ virtual talk_base::scoped_refptr<webrtc::LocalMediaStreamInterface>
+ CreateLocalMediaStream(const std::string& label);
+
+ // Asks the PeerConnection factory to create a Local VideoTrack object.
+ virtual talk_base::scoped_refptr<webrtc::LocalVideoTrackInterface>
+ CreateLocalVideoTrack(const std::string& label,
+ cricket::VideoCapturer* video_device);
- // Asks the PeerConnection factory to create a PeerConnection object. See
- // MediaStreamImpl for details about |signaling_thread|. The PeerConnection
- // object is owned by PeerConnectionHandler.
- virtual webrtc::PeerConnection* CreatePeerConnection(
- cricket::PortAllocator* port_allocator,
- talk_base::Thread* signaling_thread);
+ // Asks the PeerConnection factory to create a Local AudioTrack object.
+ virtual talk_base::scoped_refptr<webrtc::LocalAudioTrackInterface>
+ CreateLocalAudioTrack(const std::string& label,
+ webrtc::AudioDeviceModule* audio_device);
private:
- scoped_ptr<webrtc::PeerConnectionFactory> pc_factory_;
+ talk_base::scoped_refptr<webrtc::PeerConnectionFactoryInterface> pc_factory_;
DISALLOW_COPY_AND_ASSIGN(MediaStreamDependencyFactory);
};
diff --git a/content/renderer/media/media_stream_impl.cc b/content/renderer/media/media_stream_impl.cc
index 3236a1f..e9117cc 100644
--- a/content/renderer/media/media_stream_impl.cc
+++ b/content/renderer/media/media_stream_impl.cc
@@ -14,7 +14,6 @@
#include "content/renderer/media/media_stream_dependency_factory.h"
#include "content/renderer/media/media_stream_dispatcher.h"
#include "content/renderer/media/peer_connection_handler.h"
-#include "content/renderer/media/rtc_video_decoder.h"
#include "content/renderer/media/video_capture_impl_manager.h"
#include "content/renderer/media/video_capture_module_impl.h"
#include "content/renderer/media/webrtc_audio_device_impl.h"
@@ -23,9 +22,6 @@
#include "content/renderer/p2p/socket_dispatcher.h"
#include "jingle/glue/thread_wrapper.h"
#include "media/base/message_loop_factory.h"
-#include "third_party/libjingle/source/talk/p2p/client/httpportallocator.h"
-#include "third_party/libjingle/source/talk/session/phone/dummydevicemanager.h"
-#include "third_party/libjingle/source/talk/session/phone/webrtcmediaengine.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebMediaStreamDescriptor.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/WebMediaStreamRegistry.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebMediaStreamSource.h"
@@ -39,6 +35,39 @@ const int kVideoCaptureFramePerSecond = 30;
} // namespace
+// The MediaStreamMananger label for a stream is globally unique. The track
+// session id is globally unique for the set of audio tracks and video tracks
+// respectively. An audio track and a video track can have the same session id
+// (without being related). Hence we create a unique track label from the stream
+// label, track type and track session id:
+// <MediaStreamManager-label>#{audio,video}-<session-ID>.
+static std::string CreateTrackLabel(
+ const std::string& manager_label,
+ int session_id,
+ bool is_video) {
+ std::string track_label = manager_label;
+ if (is_video) {
+ track_label += "#video-";
+ } else {
+ track_label += "#audio-";
+ }
+ track_label += session_id;
+ return track_label;
+}
+
+// Extracting the MediaStreamManager stream label will only work for track
+// labels created by CreateTrackLabel. If is wasn't, the contents of the
+// returned string is undefined.
+static std::string ExtractManagerStreamLabel(
+ const std::string& track_label) {
+ std::string manager_label = track_label;
+ size_t pos = manager_label.rfind("#");
+ // If # isn't found, the string is left intact.
+ manager_label = manager_label.substr(0, pos);
+ return manager_label;
+}
+
+
int MediaStreamImpl::next_request_id_ = 0;
MediaStreamImpl::MediaStreamImpl(
@@ -48,7 +77,6 @@ MediaStreamImpl::MediaStreamImpl(
MediaStreamDependencyFactory* dependency_factory)
: dependency_factory_(dependency_factory),
media_stream_dispatcher_(media_stream_dispatcher),
- media_engine_(NULL),
p2p_socket_dispatcher_(p2p_socket_dispatcher),
network_manager_(NULL),
vc_manager_(vc_manager),
@@ -56,14 +84,13 @@ MediaStreamImpl::MediaStreamImpl(
message_loop_proxy_(base::MessageLoopProxy::current()),
signaling_thread_(NULL),
worker_thread_(NULL),
- chrome_worker_thread_("Chrome_libJingle_WorkerThread"),
- vcm_created_(false) {
+ chrome_worker_thread_("Chrome_libJingle_WorkerThread") {
}
MediaStreamImpl::~MediaStreamImpl() {
DCHECK(!peer_connection_handler_);
if (dependency_factory_.get())
- dependency_factory_->DeletePeerConnectionFactory();
+ dependency_factory_->ReleasePeerConnectionFactory();
if (network_manager_) {
// The network manager needs to free its resources on the thread they were
// created, which is the worked thread.
@@ -84,87 +111,35 @@ WebKit::WebPeerConnectionHandler* MediaStreamImpl::CreatePeerConnectionHandler(
DVLOG(1) << "A PeerConnection already exists";
return NULL;
}
-
- if (!media_engine_) {
- media_engine_ = dependency_factory_->CreateWebRtcMediaEngine();
- }
-
- if (!signaling_thread_) {
- jingle_glue::JingleThreadWrapper::EnsureForCurrentThread();
- jingle_glue::JingleThreadWrapper::current()->set_send_allowed(true);
- signaling_thread_ = jingle_glue::JingleThreadWrapper::current();
- }
-
- if (!worker_thread_) {
- if (!chrome_worker_thread_.IsRunning()) {
- if (!chrome_worker_thread_.Start()) {
- LOG(ERROR) << "Could not start worker thread";
- delete media_engine_;
- media_engine_ = NULL;
- signaling_thread_ = NULL;
- return NULL;
- }
- }
- base::WaitableEvent event(true, false);
- chrome_worker_thread_.message_loop()->PostTask(
- FROM_HERE,
- base::Bind(&MediaStreamImpl::InitializeWorkerThread, this,
- &worker_thread_, &event));
- event.Wait();
- DCHECK(worker_thread_);
- }
-
- if (!network_manager_)
- network_manager_ = new content::IpcNetworkManager(p2p_socket_dispatcher_);
-
- if (!socket_factory_.get()) {
- socket_factory_.reset(
- new content::IpcPacketSocketFactory(p2p_socket_dispatcher_));
- }
-
- if (!dependency_factory_->PeerConnectionFactoryCreated()) {
- if (!dependency_factory_->CreatePeerConnectionFactory(media_engine_,
- worker_thread_)) {
- LOG(ERROR) << "Could not initialize PeerConnection factory";
- return NULL;
- }
- }
+ EnsurePeerConnectionFactory();
peer_connection_handler_ = new PeerConnectionHandler(
client,
this,
- dependency_factory_.get(),
- signaling_thread_,
- p2p_socket_dispatcher_,
- network_manager_,
- socket_factory_.get());
+ dependency_factory_.get());
return peer_connection_handler_;
}
void MediaStreamImpl::ClosePeerConnection() {
DCHECK(CalledOnValidThread());
- rtc_video_decoder_ = NULL;
- media_engine_->SetVideoCaptureModule(NULL);
- vcm_created_ = false;
+ video_renderer_ = NULL;
peer_connection_handler_ = NULL;
+ // TODO(grunell): This is a temporary workaround for an error in native
+ // PeerConnection where added live tracks are not seen on the remote side.
+ MediaStreamTrackPtrMap::const_iterator it = local_tracks_.begin();
+ for (; it != local_tracks_.end(); ++it)
+ it->second->set_state(webrtc::MediaStreamTrackInterface::kEnded);
}
-bool MediaStreamImpl::SetVideoCaptureModule(const std::string& label) {
+webrtc::MediaStreamTrackInterface* MediaStreamImpl::GetLocalMediaStreamTrack(
+ const std::string& label) {
DCHECK(CalledOnValidThread());
- if (vcm_created_)
- return true;
- // Set the capture device.
- // TODO(grunell): Instead of using the first track, the selected track
- // should be used.
- int id = media_stream_dispatcher_->video_session_id(label, 0);
- if (id == media_stream::StreamDeviceInfo::kNoId)
- return false;
- webrtc::VideoCaptureModule* vcm =
- new VideoCaptureModuleImpl(id, vc_manager_.get());
- vcm_created_ = true;
- media_engine_->SetVideoCaptureModule(vcm);
- return true;
+ MediaStreamTrackPtrMap::iterator it = local_tracks_.find(label);
+ if (it == local_tracks_.end())
+ return NULL;
+ MediaStreamTrackPtr stream = it->second;
+ return stream.get();
}
void MediaStreamImpl::requestUserMedia(
@@ -214,6 +189,7 @@ void MediaStreamImpl::requestUserMedia(
void MediaStreamImpl::cancelUserMediaRequest(
const WebKit::WebUserMediaRequest& user_media_request) {
+ DCHECK(CalledOnValidThread());
// TODO(grunell): Implement.
NOTIMPLEMENTED();
}
@@ -226,22 +202,31 @@ scoped_refptr<media::VideoDecoder> MediaStreamImpl::GetVideoDecoder(
WebKit::WebMediaStreamRegistry::lookupMediaStreamDescriptor(url));
if (descriptor.isNull())
return NULL; // This is not a valid stream.
+
+ // We must find out if this is a local or remote stream. We extract the
+ // MediaStreamManager stream label and if found in the dispatcher we have a
+ // local stream, otherwise we have a remote stream. There will be changes soon
+ // so that we don't have to bother about the type of stream here. Hence this
+ // solution is OK for now.
+
WebKit::WebVector<WebKit::WebMediaStreamSource> source_vector;
descriptor.sources(source_vector);
- std::string label;
+ std::string msm_label;
for (size_t i = 0; i < source_vector.size(); ++i) {
if (source_vector[i].type() == WebKit::WebMediaStreamSource::TypeVideo) {
- label = UTF16ToUTF8(source_vector[i].id());
+ // We assume there is one video track only.
+ msm_label = ExtractManagerStreamLabel(UTF16ToUTF8(source_vector[i].id()));
break;
}
}
- if (label.empty())
+ if (msm_label.empty())
return NULL;
scoped_refptr<media::VideoDecoder> decoder;
- if (media_stream_dispatcher_->IsStream(label)) {
+ if (media_stream_dispatcher_->IsStream(msm_label)) {
// It's a local stream.
- int video_session_id = media_stream_dispatcher_->video_session_id(label, 0);
+ int video_session_id =
+ media_stream_dispatcher_->video_session_id(msm_label, 0);
media::VideoCapture::VideoCaptureCapability capability;
capability.width = kVideoCaptureWidth;
capability.height = kVideoCaptureHeight;
@@ -256,20 +241,27 @@ scoped_refptr<media::VideoDecoder> MediaStreamImpl::GetVideoDecoder(
capability);
} else {
// It's a remote stream.
- size_t found = label.rfind("-remote");
- if (found != std::string::npos)
- label = label.substr(0, found);
- if (rtc_video_decoder_.get()) {
+ if (!video_renderer_.get())
+ video_renderer_ = new talk_base::RefCountedObject<VideoRendererWrapper>();
+ if (video_renderer_->renderer()) {
// The renderer is used by PeerConnection, release it first.
- if (peer_connection_handler_)
- peer_connection_handler_->SetVideoRenderer(label, NULL);
+ if (peer_connection_handler_) {
+ peer_connection_handler_->SetVideoRenderer(
+ UTF16ToUTF8(descriptor.label()),
+ NULL);
+ }
+ video_renderer_->SetVideoDecoder(NULL);
}
- rtc_video_decoder_ = new RTCVideoDecoder(
+ RTCVideoDecoder* rtc_video_decoder = new RTCVideoDecoder(
message_loop_factory->GetMessageLoop("RtcVideoDecoderThread"),
url.spec());
- decoder = rtc_video_decoder_;
- if (peer_connection_handler_)
- peer_connection_handler_->SetVideoRenderer(label, rtc_video_decoder_);
+ decoder = rtc_video_decoder;
+ video_renderer_->SetVideoDecoder(rtc_video_decoder);
+ if (peer_connection_handler_) {
+ peer_connection_handler_->SetVideoRenderer(
+ UTF16ToUTF8(descriptor.label()),
+ video_renderer_);
+ }
}
return decoder;
}
@@ -280,32 +272,46 @@ void MediaStreamImpl::OnStreamGenerated(
const media_stream::StreamDeviceInfoArray& audio_array,
const media_stream::StreamDeviceInfoArray& video_array) {
DCHECK(CalledOnValidThread());
+ EnsurePeerConnectionFactory();
- // We only support max one audio track and one video track. If the UI
- // for selecting device starts to allow several devices, we must implement
- // handling for this.
- DCHECK_LE(audio_array.size(), 1u);
- DCHECK_LE(video_array.size(), 1u);
WebKit::WebVector<WebKit::WebMediaStreamSource> source_vector(
audio_array.size() + video_array.size());
- WebKit::WebString track_label_audio(UTF8ToUTF16("AudioDevice"));
- WebKit::WebString track_label_video(UTF8ToUTF16("VideoCapture"));
- size_t track_num = source_vector.size();
- while (track_num--) {
- if (track_num < audio_array.size()) {
- source_vector[track_num].initialize(
- UTF8ToUTF16(label),
+ // Add audio tracks.
+ std::string track_label;
+ for (size_t i = 0; i < audio_array.size(); ++i) {
+ track_label = CreateTrackLabel(label, audio_array[i].session_id, false);
+ MediaStreamTrackPtr audio_track(
+ dependency_factory_->CreateLocalAudioTrack(audio_array[i].name, NULL));
+ local_tracks_.insert(
+ std::pair<std::string, MediaStreamTrackPtr>(track_label, audio_track));
+ source_vector[i].initialize(
+ UTF8ToUTF16(track_label),
WebKit::WebMediaStreamSource::TypeAudio,
- track_label_audio);
- } else {
- source_vector[track_num].initialize(
- UTF8ToUTF16(label),
+ UTF8ToUTF16(audio_array[i].name));
+ }
+
+ // Add video tracks.
+ for (size_t i = 0; i < video_array.size(); ++i) {
+ track_label = CreateTrackLabel(label, video_array[i].session_id, true);
+ webrtc::VideoCaptureModule* vcm =
+ new VideoCaptureModuleImpl(video_array[i].session_id,
+ vc_manager_.get());
+ MediaStreamTrackPtr video_track(dependency_factory_->CreateLocalVideoTrack(
+ video_array[i].name,
+ // The video capturer takes ownership of |vcm|.
+ webrtc::CreateVideoCapturer(vcm)));
+ local_tracks_.insert(
+ std::pair<std::string, MediaStreamTrackPtr>(track_label, video_track));
+ source_vector[audio_array.size() + i].initialize(
+ UTF8ToUTF16(track_label),
WebKit::WebMediaStreamSource::TypeVideo,
- track_label_video);
- }
+ UTF8ToUTF16(video_array[i].name));
}
+ // TODO(grunell): Remove tracks from the map when support to stop is
+ // added in WebKit.
+
MediaRequestMap::iterator it = user_media_requests_.find(request_id);
if (it == user_media_requests_.end()) {
DVLOG(1) << "Request ID not found";
@@ -313,7 +319,6 @@ void MediaStreamImpl::OnStreamGenerated(
}
WebKit::WebUserMediaRequest user_media_request = it->second;
user_media_requests_.erase(it);
- stream_labels_.push_back(label);
user_media_request.requestSucceeded(source_vector);
}
@@ -393,3 +398,61 @@ void MediaStreamImpl::DeleteIpcNetworkManager() {
delete network_manager_;
network_manager_ = NULL;
}
+
+bool MediaStreamImpl::EnsurePeerConnectionFactory() {
+ DCHECK(CalledOnValidThread());
+ if (!signaling_thread_) {
+ jingle_glue::JingleThreadWrapper::EnsureForCurrentThread();
+ jingle_glue::JingleThreadWrapper::current()->set_send_allowed(true);
+ signaling_thread_ = jingle_glue::JingleThreadWrapper::current();
+ }
+
+ 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(
+ &MediaStreamImpl::InitializeWorkerThread,
+ this,
+ &worker_thread_,
+ &event));
+ event.Wait();
+ DCHECK(worker_thread_);
+ }
+
+ if (!network_manager_)
+ network_manager_ = new content::IpcNetworkManager(p2p_socket_dispatcher_);
+
+ if (!socket_factory_.get()) {
+ socket_factory_.reset(
+ new content::IpcPacketSocketFactory(p2p_socket_dispatcher_));
+ }
+
+ if (!dependency_factory_->PeerConnectionFactoryCreated()) {
+ if (!dependency_factory_->CreatePeerConnectionFactory(
+ worker_thread_,
+ signaling_thread_,
+ p2p_socket_dispatcher_,
+ network_manager_,
+ socket_factory_.get())) {
+ LOG(ERROR) << "Could not initialize PeerConnection factory";
+ return false;
+ }
+ }
+
+ return true;
+}
+
+MediaStreamImpl::VideoRendererWrapper::VideoRendererWrapper() {}
+
+MediaStreamImpl::VideoRendererWrapper::~VideoRendererWrapper() {}
+
+void MediaStreamImpl::VideoRendererWrapper::SetVideoDecoder(
+ RTCVideoDecoder* decoder) {
+ rtc_video_decoder_ = decoder;
+}
diff --git a/content/renderer/media/media_stream_impl.h b/content/renderer/media/media_stream_impl.h
index 2aa6be3..503c510 100644
--- a/content/renderer/media/media_stream_impl.h
+++ b/content/renderer/media/media_stream_impl.h
@@ -19,6 +19,9 @@
#include "base/threading/thread.h"
#include "content/common/content_export.h"
#include "content/renderer/media/media_stream_dispatcher_eventhandler.h"
+#include "content/renderer/media/rtc_video_decoder.h"
+#include "third_party/libjingle/source/talk/app/webrtc/mediastream.h"
+#include "third_party/libjingle/source/talk/base/scoped_ref_ptr.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/WebUserMediaClient.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/WebUserMediaRequest.h"
#include "webkit/media/media_stream_client.h"
@@ -33,10 +36,6 @@ class IpcPacketSocketFactory;
class P2PSocketDispatcher;
}
-namespace cricket {
-class WebRtcMediaEngine;
-}
-
namespace talk_base {
class Thread;
}
@@ -74,9 +73,8 @@ class CONTENT_EXPORT MediaStreamImpl
virtual WebKit::WebPeerConnectionHandler* CreatePeerConnectionHandler(
WebKit::WebPeerConnectionHandlerClient* client);
virtual void ClosePeerConnection();
-
- // Returns true if created successfully or already exists, false otherwise.
- virtual bool SetVideoCaptureModule(const std::string& label);
+ virtual webrtc::MediaStreamTrackInterface* GetLocalMediaStreamTrack(
+ const std::string& label);
// WebKit::WebUserMediaClient implementation
virtual void requestUserMedia(
@@ -117,10 +115,26 @@ class CONTENT_EXPORT MediaStreamImpl
private:
FRIEND_TEST_ALL_PREFIXES(MediaStreamImplTest, Basic);
+ class VideoRendererWrapper : public webrtc::VideoRendererWrapperInterface {
+ public:
+ VideoRendererWrapper();
+ virtual cricket::VideoRenderer* renderer() OVERRIDE {
+ return rtc_video_decoder_.get();
+ }
+ void SetVideoDecoder(RTCVideoDecoder* decoder);
+
+ protected:
+ virtual ~VideoRendererWrapper();
+
+ private:
+ scoped_refptr<RTCVideoDecoder> rtc_video_decoder_;
+ };
+
void InitializeWorkerThread(
talk_base::Thread** thread,
base::WaitableEvent* event);
void DeleteIpcNetworkManager();
+ bool EnsurePeerConnectionFactory();
scoped_ptr<MediaStreamDependencyFactory> dependency_factory_;
@@ -128,11 +142,6 @@ class CONTENT_EXPORT MediaStreamImpl
// valid for the lifetime of RenderView.
MediaStreamDispatcher* media_stream_dispatcher_;
- // media_engine_ is owned by PeerConnectionFactory (which is owned by
- // dependency_factory_) and is valid for the lifetime of
- // PeerConnectionFactory.
- cricket::WebRtcMediaEngine* media_engine_;
-
// p2p_socket_dispatcher_ is a weak reference, owned by RenderView. It's valid
// for the lifetime of RenderView.
content::P2PSocketDispatcher* p2p_socket_dispatcher_;
@@ -149,7 +158,14 @@ class CONTENT_EXPORT MediaStreamImpl
// TODO(grunell): Support several PeerConnectionsHandlers.
PeerConnectionHandler* peer_connection_handler_;
- scoped_refptr<RTCVideoDecoder> rtc_video_decoder_;
+ // We keep a list of the generated local tracks, so that we can add capture
+ // devices when generated and also use them for recording.
+ typedef talk_base::scoped_refptr<webrtc::MediaStreamTrackInterface>
+ MediaStreamTrackPtr;
+ typedef std::map<std::string, MediaStreamTrackPtr> MediaStreamTrackPtrMap;
+ MediaStreamTrackPtrMap local_tracks_;
+
+ talk_base::scoped_refptr<VideoRendererWrapper> video_renderer_;
scoped_refptr<base::MessageLoopProxy> message_loop_proxy_;
// PeerConnection threads. signaling_thread_ is created from the
@@ -162,15 +178,6 @@ class CONTENT_EXPORT MediaStreamImpl
typedef std::map<int, WebKit::WebUserMediaRequest> MediaRequestMap;
MediaRequestMap user_media_requests_;
- std::list<std::string> stream_labels_;
-
- // Make sure we only create the video capture module once. This is also
- // temporary and will be handled differently when several PeerConnections
- // and/or streams is supported.
- // TODO(grunell): This shall be removed or changed when native PeerConnection
- // has been updated to closer follow the specification.
- bool vcm_created_;
-
DISALLOW_COPY_AND_ASSIGN(MediaStreamImpl);
};
diff --git a/content/renderer/media/mock_media_stream_dependency_factory.cc b/content/renderer/media/mock_media_stream_dependency_factory.cc
index 5cbcbd4..71adfb4 100644
--- a/content/renderer/media/mock_media_stream_dependency_factory.cc
+++ b/content/renderer/media/mock_media_stream_dependency_factory.cc
@@ -5,7 +5,125 @@
#include "base/logging.h"
#include "content/renderer/media/mock_media_stream_dependency_factory.h"
#include "content/renderer/media/mock_peer_connection_impl.h"
-#include "third_party/libjingle/source/talk/session/phone/webrtcmediaengine.h"
+#include "third_party/libjingle/source/talk/app/webrtc/mediastream.h"
+#include "third_party/libjingle/source/talk/base/scoped_ref_ptr.h"
+
+namespace webrtc {
+
+template <class TrackType>
+class MockMediaStreamTrackList
+ : public MediaStreamTrackListInterface<TrackType> {
+ public:
+ virtual size_t count() OVERRIDE {
+ return tracks_.size();
+ }
+ virtual TrackType* at(size_t index) OVERRIDE {
+ return tracks_[index];
+ }
+ void AddTrack(TrackType* track) {
+ tracks_.push_back(track);
+ }
+
+ protected:
+ virtual ~MockMediaStreamTrackList() {}
+
+ private:
+ std::vector<TrackType*> tracks_;
+};
+
+typedef MockMediaStreamTrackList<AudioTrackInterface> MockAudioTracks;
+typedef MockMediaStreamTrackList<VideoTrackInterface> MockVideoTracks;
+
+class MockLocalMediaStream : public LocalMediaStreamInterface {
+ public:
+ explicit MockLocalMediaStream(std::string label)
+ : label_(label),
+ audio_tracks_(new talk_base::RefCountedObject<MockAudioTracks>),
+ video_tracks_(new talk_base::RefCountedObject<MockVideoTracks>) {
+ }
+ virtual bool AddTrack(AudioTrackInterface* track) OVERRIDE {
+ audio_tracks_->AddTrack(track);
+ return true;
+ }
+ virtual bool AddTrack(VideoTrackInterface* track) OVERRIDE {
+ video_tracks_->AddTrack(track);
+ return true;
+ }
+ virtual std::string label() const OVERRIDE { return label_; }
+ virtual AudioTracks* audio_tracks() OVERRIDE {
+ return audio_tracks_;
+ }
+ virtual VideoTracks* video_tracks() OVERRIDE {
+ return video_tracks_;
+ }
+ virtual ReadyState ready_state() OVERRIDE {
+ NOTIMPLEMENTED();
+ return kInitializing;
+ }
+ virtual void set_ready_state(ReadyState state) OVERRIDE { NOTIMPLEMENTED(); }
+ virtual void RegisterObserver(ObserverInterface* observer) OVERRIDE {
+ NOTIMPLEMENTED();
+ }
+ virtual void UnregisterObserver(ObserverInterface* observer) {
+ NOTIMPLEMENTED();
+ }
+
+ protected:
+ virtual ~MockLocalMediaStream() {}
+
+ private:
+ std::string label_;
+ talk_base::scoped_refptr<MockAudioTracks> audio_tracks_;
+ talk_base::scoped_refptr<MockVideoTracks> video_tracks_;
+};
+
+cricket::VideoCapturer* MockLocalVideoTrack::GetVideoCapture() {
+ NOTIMPLEMENTED();
+ return NULL;
+}
+
+void MockLocalVideoTrack::SetRenderer(VideoRendererWrapperInterface* renderer) {
+ renderer_ = renderer;
+}
+
+VideoRendererWrapperInterface* MockLocalVideoTrack::GetRenderer() {
+ NOTIMPLEMENTED();
+ return NULL;
+}
+
+std::string MockLocalVideoTrack::kind() const {
+ NOTIMPLEMENTED();
+ return "";
+}
+
+std::string MockLocalVideoTrack::label() const { return label_; }
+
+bool MockLocalVideoTrack::enabled() const { return enabled_; }
+
+MockLocalVideoTrack::TrackState MockLocalVideoTrack::state() const {
+ NOTIMPLEMENTED();
+ return kInitializing;
+}
+
+bool MockLocalVideoTrack::set_enabled(bool enable) {
+ enabled_ = enable;
+ return true;
+}
+
+bool MockLocalVideoTrack::set_state(TrackState new_state) {
+ NOTIMPLEMENTED();
+ return false;
+}
+
+void MockLocalVideoTrack::RegisterObserver(ObserverInterface* observer) {
+ NOTIMPLEMENTED();
+}
+
+void MockLocalVideoTrack::UnregisterObserver(ObserverInterface* observer) {
+ NOTIMPLEMENTED();
+}
+
+} // namespace webrtc
MockMediaStreamDependencyFactory::MockMediaStreamDependencyFactory()
: mock_pc_factory_created_(false) {
@@ -13,20 +131,17 @@ MockMediaStreamDependencyFactory::MockMediaStreamDependencyFactory()
MockMediaStreamDependencyFactory::~MockMediaStreamDependencyFactory() {}
-cricket::WebRtcMediaEngine*
-MockMediaStreamDependencyFactory::CreateWebRtcMediaEngine() {
- return new cricket::WebRtcMediaEngine(NULL, NULL, NULL);
-}
-
bool MockMediaStreamDependencyFactory::CreatePeerConnectionFactory(
- cricket::MediaEngineInterface* media_engine,
- talk_base::Thread* worker_thread) {
+ talk_base::Thread* worker_thread,
+ talk_base::Thread* signaling_thread,
+ content::P2PSocketDispatcher* socket_dispatcher,
+ talk_base::NetworkManager* network_manager,
+ talk_base::PacketSocketFactory* socket_factory) {
mock_pc_factory_created_ = true;
- media_engine_.reset(media_engine);
return true;
}
-void MockMediaStreamDependencyFactory::DeletePeerConnectionFactory() {
+void MockMediaStreamDependencyFactory::ReleasePeerConnectionFactory() {
mock_pc_factory_created_ = false;
}
@@ -34,17 +149,35 @@ bool MockMediaStreamDependencyFactory::PeerConnectionFactoryCreated() {
return mock_pc_factory_created_;
}
-cricket::PortAllocator* MockMediaStreamDependencyFactory::CreatePortAllocator(
- content::P2PSocketDispatcher* socket_dispatcher,
- talk_base::NetworkManager* network_manager,
- talk_base::PacketSocketFactory* socket_factory,
- const webkit_glue::P2PTransport::Config& config) {
- return NULL;
+talk_base::scoped_refptr<webrtc::PeerConnectionInterface>
+MockMediaStreamDependencyFactory::CreatePeerConnection(
+ const std::string& config,
+ webrtc::PeerConnectionObserver* observer) {
+ DCHECK(mock_pc_factory_created_);
+ return new talk_base::RefCountedObject<webrtc::MockPeerConnectionImpl>();
}
-webrtc::PeerConnection* MockMediaStreamDependencyFactory::CreatePeerConnection(
- cricket::PortAllocator* port_allocator,
- talk_base::Thread* signaling_thread) {
- DCHECK(mock_pc_factory_created_);
- return new webrtc::MockPeerConnectionImpl();
+talk_base::scoped_refptr<webrtc::LocalMediaStreamInterface>
+MockMediaStreamDependencyFactory::CreateLocalMediaStream(
+ const std::string& label) {
+ talk_base::scoped_refptr<webrtc::LocalMediaStreamInterface> stream(
+ new talk_base::RefCountedObject<webrtc::MockLocalMediaStream>(label));
+ return stream;
+}
+
+talk_base::scoped_refptr<webrtc::LocalVideoTrackInterface>
+MockMediaStreamDependencyFactory::CreateLocalVideoTrack(
+ const std::string& label,
+ cricket::VideoCapturer* video_device) {
+ talk_base::scoped_refptr<webrtc::LocalVideoTrackInterface> stream(
+ new talk_base::RefCountedObject<webrtc::MockLocalVideoTrack>(label));
+ return stream;
+}
+
+talk_base::scoped_refptr<webrtc::LocalAudioTrackInterface>
+MockMediaStreamDependencyFactory::CreateLocalAudioTrack(
+ const std::string& label,
+ webrtc::AudioDeviceModule* audio_device) {
+ NOTIMPLEMENTED();
+ return NULL;
}
diff --git a/content/renderer/media/mock_media_stream_dependency_factory.h b/content/renderer/media/mock_media_stream_dependency_factory.h
index 163baab..00c797f 100644
--- a/content/renderer/media/mock_media_stream_dependency_factory.h
+++ b/content/renderer/media/mock_media_stream_dependency_factory.h
@@ -5,33 +5,77 @@
#ifndef CONTENT_RENDERER_MEDIA_MOCK_MEDIA_STREAM_DEPENDENCY_FACTORY_H_
#define CONTENT_RENDERER_MEDIA_MOCK_MEDIA_STREAM_DEPENDENCY_FACTORY_H_
+#include <string>
+#include <vector>
+
#include "base/compiler_specific.h"
#include "content/renderer/media/media_stream_dependency_factory.h"
+namespace webrtc {
+
+class MockLocalVideoTrack : public LocalVideoTrackInterface {
+ public:
+ explicit MockLocalVideoTrack(std::string label)
+ : enabled_(false),
+ label_(label),
+ renderer_(NULL) {
+ }
+ virtual cricket::VideoCapturer* GetVideoCapture() OVERRIDE;
+ virtual void SetRenderer(VideoRendererWrapperInterface* renderer) OVERRIDE;
+ virtual VideoRendererWrapperInterface* GetRenderer() OVERRIDE;
+ virtual std::string kind() const OVERRIDE;
+ virtual std::string label() const OVERRIDE;
+ virtual bool enabled() const OVERRIDE;
+ virtual TrackState state() const OVERRIDE;
+ virtual bool set_enabled(bool enable) OVERRIDE;
+ virtual bool set_state(TrackState new_state) OVERRIDE;
+ virtual void RegisterObserver(ObserverInterface* observer) OVERRIDE;
+ virtual void UnregisterObserver(ObserverInterface* observer) OVERRIDE;
+
+ VideoRendererWrapperInterface* renderer() const { return renderer_; }
+
+ protected:
+ virtual ~MockLocalVideoTrack() {}
+
+ private:
+ bool enabled_;
+ std::string label_;
+ VideoRendererWrapperInterface* renderer_;
+};
+
+} // namespace webrtc
+
// A mock factory for creating different objects for MediaStreamImpl.
class MockMediaStreamDependencyFactory : public MediaStreamDependencyFactory {
public:
MockMediaStreamDependencyFactory();
virtual ~MockMediaStreamDependencyFactory();
- virtual cricket::WebRtcMediaEngine* CreateWebRtcMediaEngine() OVERRIDE;
virtual bool CreatePeerConnectionFactory(
- cricket::MediaEngineInterface* media_engine,
- talk_base::Thread* worker_thread) OVERRIDE;
- virtual void DeletePeerConnectionFactory() OVERRIDE;
- virtual bool PeerConnectionFactoryCreated() OVERRIDE;
- virtual cricket::PortAllocator* CreatePortAllocator(
+ talk_base::Thread* worker_thread,
+ talk_base::Thread* signaling_thread,
content::P2PSocketDispatcher* socket_dispatcher,
talk_base::NetworkManager* network_manager,
- talk_base::PacketSocketFactory* socket_factory,
- const webkit_glue::P2PTransport::Config& config) OVERRIDE;
- virtual webrtc::PeerConnection* CreatePeerConnection(
- cricket::PortAllocator* port_allocator,
- talk_base::Thread* signaling_thread) OVERRIDE;
+ talk_base::PacketSocketFactory* socket_factory) OVERRIDE;
+ virtual void ReleasePeerConnectionFactory() OVERRIDE;
+ virtual bool PeerConnectionFactoryCreated() OVERRIDE;
+ virtual talk_base::scoped_refptr<webrtc::PeerConnectionInterface>
+ CreatePeerConnection(
+ const std::string& config,
+ webrtc::PeerConnectionObserver* observer) OVERRIDE;
+ virtual talk_base::scoped_refptr<webrtc::LocalMediaStreamInterface>
+ CreateLocalMediaStream(const std::string& label) OVERRIDE;
+ virtual talk_base::scoped_refptr<webrtc::LocalVideoTrackInterface>
+ CreateLocalVideoTrack(
+ const std::string& label,
+ cricket::VideoCapturer* video_device) OVERRIDE;
+ virtual talk_base::scoped_refptr<webrtc::LocalAudioTrackInterface>
+ CreateLocalAudioTrack(
+ const std::string& label,
+ webrtc::AudioDeviceModule* audio_device) OVERRIDE;
private:
bool mock_pc_factory_created_;
- scoped_ptr<cricket::MediaEngineInterface> media_engine_;
DISALLOW_COPY_AND_ASSIGN(MockMediaStreamDependencyFactory);
};
diff --git a/content/renderer/media/mock_media_stream_impl.cc b/content/renderer/media/mock_media_stream_impl.cc
index 9109989..4996e95 100644
--- a/content/renderer/media/mock_media_stream_impl.cc
+++ b/content/renderer/media/mock_media_stream_impl.cc
@@ -4,6 +4,8 @@
#include "content/renderer/media/mock_media_stream_impl.h"
+#include <utility>
+
#include "content/renderer/media/rtc_video_decoder.h"
MockMediaStreamImpl::MockMediaStreamImpl()
@@ -20,12 +22,15 @@ MockMediaStreamImpl::CreatePeerConnectionHandler(
}
void MockMediaStreamImpl::ClosePeerConnection() {
- video_label_.clear();
}
-bool MockMediaStreamImpl::SetVideoCaptureModule(const std::string& label) {
- video_label_ = label;
- return true;
+webrtc::MediaStreamTrackInterface*
+MockMediaStreamImpl::GetLocalMediaStreamTrack(const std::string& label) {
+ MockMediaStreamTrackPtrMap::iterator it = mock_local_tracks_.find(label);
+ if (it == mock_local_tracks_.end())
+ return NULL;
+ webrtc::MediaStreamTrackInterface* stream = it->second;
+ return stream;
}
scoped_refptr<media::VideoDecoder> MockMediaStreamImpl::GetVideoDecoder(
@@ -58,3 +63,10 @@ void MockMediaStreamImpl::OnAudioDeviceFailed(
int index) {
NOTIMPLEMENTED();
}
+
+void MockMediaStreamImpl::AddTrack(
+ const std::string& label,
+ webrtc::MediaStreamTrackInterface* track) {
+ mock_local_tracks_.insert(
+ std::pair<std::string, webrtc::MediaStreamTrackInterface*>(label, track));
+}
diff --git a/content/renderer/media/mock_media_stream_impl.h b/content/renderer/media/mock_media_stream_impl.h
index b297b49..8340b9e 100644
--- a/content/renderer/media/mock_media_stream_impl.h
+++ b/content/renderer/media/mock_media_stream_impl.h
@@ -5,6 +5,7 @@
#ifndef CONTENT_RENDERER_MEDIA_MOCK_MEDIA_STREAM_IMPL_H_
#define CONTENT_RENDERER_MEDIA_MOCK_MEDIA_STREAM_IMPL_H_
+#include <map>
#include <string>
#include "content/renderer/media/media_stream_impl.h"
@@ -17,8 +18,8 @@ class MockMediaStreamImpl : public MediaStreamImpl {
virtual WebKit::WebPeerConnectionHandler* CreatePeerConnectionHandler(
WebKit::WebPeerConnectionHandlerClient* client) OVERRIDE;
virtual void ClosePeerConnection() OVERRIDE;
- // Returns true if created successfully or already exists, false otherwise.
- virtual bool SetVideoCaptureModule(const std::string& label) OVERRIDE;
+ virtual webrtc::MediaStreamTrackInterface* GetLocalMediaStreamTrack(
+ const std::string& label) OVERRIDE;
// Implement webkit_glue::MediaStreamClient.
virtual scoped_refptr<media::VideoDecoder> GetVideoDecoder(
@@ -39,10 +40,14 @@ class MockMediaStreamImpl : public MediaStreamImpl {
const std::string& label,
int index) OVERRIDE;
- const std::string& video_label() const { return video_label_; }
+ void AddTrack(
+ const std::string& label,
+ webrtc::MediaStreamTrackInterface* track);
private:
- std::string video_label_;
+ typedef std::map<std::string, webrtc::MediaStreamTrackInterface*>
+ MockMediaStreamTrackPtrMap;
+ MockMediaStreamTrackPtrMap mock_local_tracks_;
DISALLOW_COPY_AND_ASSIGN(MockMediaStreamImpl);
};
diff --git a/content/renderer/media/mock_peer_connection_impl.cc b/content/renderer/media/mock_peer_connection_impl.cc
index 365f18b..09a164d 100644
--- a/content/renderer/media/mock_peer_connection_impl.cc
+++ b/content/renderer/media/mock_peer_connection_impl.cc
@@ -4,88 +4,95 @@
#include "content/renderer/media/mock_peer_connection_impl.h"
+#include <vector>
+
#include "base/logging.h"
namespace webrtc {
+class MockStreamCollection : public StreamCollectionInterface {
+ public:
+ virtual size_t count() OVERRIDE {
+ return streams_.size();
+ }
+ virtual MediaStreamInterface* at(size_t index) OVERRIDE {
+ return streams_[index];
+ }
+ virtual MediaStreamInterface* find(const std::string& label) OVERRIDE {
+ for (size_t i = 0; i < streams_.size(); ++i) {
+ if (streams_[i]->label() == label)
+ return streams_[i];
+ }
+ return NULL;
+ }
+ void AddStream(MediaStreamInterface* stream) {
+ streams_.push_back(stream);
+ }
+
+ protected:
+ virtual ~MockStreamCollection() {}
+
+ private:
+ std::vector<MediaStreamInterface*> streams_;
+};
+
MockPeerConnectionImpl::MockPeerConnectionImpl()
- : observer_(NULL),
- video_stream_(false),
- connected_(false),
- video_capture_set_(false) {
+ : stream_changes_committed_(false),
+ remote_streams_(new talk_base::RefCountedObject<MockStreamCollection>) {
}
MockPeerConnectionImpl::~MockPeerConnectionImpl() {}
-void MockPeerConnectionImpl::RegisterObserver(
- PeerConnectionObserver* observer) {
- observer_ = observer;
+void MockPeerConnectionImpl::ProcessSignalingMessage(const std::string& msg) {
+ signaling_message_ = msg;
}
-bool MockPeerConnectionImpl::SignalingMessage(
- const std::string& signaling_message) {
- signaling_message_ = signaling_message;
- return true;
+bool MockPeerConnectionImpl::Send(const std::string& msg) {
+ NOTIMPLEMENTED();
+ return false;
}
-bool MockPeerConnectionImpl::AddStream(
- const std::string& stream_id,
- bool video) {
- stream_id_ = stream_id;
- video_stream_ = video;
- return true;
+talk_base::scoped_refptr<StreamCollectionInterface>
+MockPeerConnectionImpl::local_streams() {
+ NOTIMPLEMENTED();
+ return NULL;
}
-bool MockPeerConnectionImpl::RemoveStream(const std::string& stream_id) {
- stream_id_.clear();
- video_stream_ = false;
- return true;
+talk_base::scoped_refptr<StreamCollectionInterface>
+MockPeerConnectionImpl::remote_streams() {
+ return remote_streams_;
}
-bool MockPeerConnectionImpl::Connect() {
- connected_ = true;
- return true;
+void MockPeerConnectionImpl::AddStream(LocalMediaStreamInterface* stream) {
+ stream_label_ = stream->label();
}
-bool MockPeerConnectionImpl::Close() {
- observer_ = NULL;
- signaling_message_.clear();
- stream_id_.clear();
- video_stream_ = false;
- connected_ = false;
- video_capture_set_ = false;
- return true;
+void MockPeerConnectionImpl::RemoveStream(LocalMediaStreamInterface* stream) {
+ stream_label_.clear();
}
-bool MockPeerConnectionImpl::SetAudioDevice(
- const std::string& wave_in_device,
- const std::string& wave_out_device,
- int opts) {
- NOTIMPLEMENTED();
- return false;
+void MockPeerConnectionImpl::CommitStreamChanges() {
+ stream_changes_committed_ = true;
}
-bool MockPeerConnectionImpl::SetLocalVideoRenderer(
- cricket::VideoRenderer* renderer) {
- NOTIMPLEMENTED();
- return false;
+void MockPeerConnectionImpl::Close() {
+ signaling_message_.clear();
+ stream_label_.clear();
+ stream_changes_committed_ = false;
}
-bool MockPeerConnectionImpl::SetVideoRenderer(
- const std::string& stream_id,
- cricket::VideoRenderer* renderer) {
- video_renderer_stream_id_ = stream_id;
- return true;
+MockPeerConnectionImpl::ReadyState MockPeerConnectionImpl::ready_state() {
+ NOTIMPLEMENTED();
+ return kNew;
}
-bool MockPeerConnectionImpl::SetVideoCapture(const std::string& cam_device) {
- video_capture_set_ = true;
- return true;
+MockPeerConnectionImpl::SdpState MockPeerConnectionImpl::sdp_state() {
+ NOTIMPLEMENTED();
+ return kSdpNew;
}
-MockPeerConnectionImpl::ReadyState MockPeerConnectionImpl::GetReadyState() {
- NOTIMPLEMENTED();
- return NEW;
+void MockPeerConnectionImpl::AddRemoteStream(MediaStreamInterface* stream) {
+ remote_streams_->AddStream(stream);
}
} // namespace webrtc
diff --git a/content/renderer/media/mock_peer_connection_impl.h b/content/renderer/media/mock_peer_connection_impl.h
index 4d74355..9f20e8b 100644
--- a/content/renderer/media/mock_peer_connection_impl.h
+++ b/content/renderer/media/mock_peer_connection_impl.h
@@ -9,50 +9,45 @@
#include "base/basictypes.h"
#include "base/compiler_specific.h"
-#include "third_party/libjingle/source/talk/app/webrtcv1/peerconnection.h"
+#include "third_party/libjingle/source/talk/app/webrtc/peerconnection.h"
namespace webrtc {
-class MockPeerConnectionImpl : public PeerConnection {
+class MockStreamCollection;
+
+class MockPeerConnectionImpl : public PeerConnectionInterface {
public:
MockPeerConnectionImpl();
- virtual ~MockPeerConnectionImpl();
- // PeerConnection implementation.
- virtual void RegisterObserver(PeerConnectionObserver* observer) OVERRIDE;
- virtual bool SignalingMessage(const std::string& msg) OVERRIDE;
- virtual bool AddStream(const std::string& stream_id, bool video) OVERRIDE;
- virtual bool RemoveStream(const std::string& stream_id) OVERRIDE;
- virtual bool Connect() OVERRIDE;
- virtual bool Close() OVERRIDE;
- virtual bool SetAudioDevice(
- const std::string& wave_in_device,
- const std::string& wave_out_device, int opts) OVERRIDE;
- virtual bool SetLocalVideoRenderer(cricket::VideoRenderer* renderer) OVERRIDE;
- virtual bool SetVideoRenderer(
- const std::string& stream_id,
- cricket::VideoRenderer* renderer) OVERRIDE;
- virtual bool SetVideoCapture(const std::string& cam_device) OVERRIDE;
- virtual ReadyState GetReadyState() OVERRIDE;
-
- PeerConnectionObserver* observer() const { return observer_; }
+ // PeerConnectionInterface implementation.
+ virtual void ProcessSignalingMessage(const std::string& msg) OVERRIDE;
+ virtual bool Send(const std::string& msg) OVERRIDE;
+ virtual talk_base::scoped_refptr<StreamCollectionInterface>
+ local_streams() OVERRIDE;
+ virtual talk_base::scoped_refptr<StreamCollectionInterface>
+ remote_streams() OVERRIDE;
+ virtual void AddStream(LocalMediaStreamInterface* stream) OVERRIDE;
+ virtual void RemoveStream(LocalMediaStreamInterface* stream) OVERRIDE;
+ virtual void CommitStreamChanges() OVERRIDE;
+ virtual void Close() OVERRIDE;
+ virtual ReadyState ready_state() OVERRIDE;
+ virtual SdpState sdp_state() OVERRIDE;
+
+ void AddRemoteStream(MediaStreamInterface* stream);
+ void ClearStreamChangesCommitted() { stream_changes_committed_ = false; }
+
const std::string& signaling_message() const { return signaling_message_; }
- const std::string& stream_id() const { return stream_id_; }
- bool video_stream() const { return video_stream_; }
- bool connected() const { return connected_; }
- bool video_capture_set() const { return video_capture_set_; }
- const std::string& video_renderer_stream_id() const {
- return video_renderer_stream_id_;
- }
+ const std::string& stream_label() const { return stream_label_; }
+ bool stream_changes_committed() const { return stream_changes_committed_; }
+
+ protected:
+ virtual ~MockPeerConnectionImpl();
private:
- PeerConnectionObserver* observer_;
std::string signaling_message_;
- std::string stream_id_;
- bool video_stream_;
- bool connected_;
- bool video_capture_set_;
- std::string video_renderer_stream_id_;
+ std::string stream_label_;
+ bool stream_changes_committed_;
+ talk_base::scoped_refptr<MockStreamCollection> remote_streams_;
DISALLOW_COPY_AND_ASSIGN(MockPeerConnectionImpl);
};
diff --git a/content/renderer/media/peer_connection_handler.cc b/content/renderer/media/peer_connection_handler.cc
index d1729e5..51cfb10 100644
--- a/content/renderer/media/peer_connection_handler.cc
+++ b/content/renderer/media/peer_connection_handler.cc
@@ -4,21 +4,15 @@
#include "content/renderer/media/peer_connection_handler.h"
-#include <stdlib.h>
+#include <utility>
#include <vector>
#include "base/bind.h"
#include "base/logging.h"
#include "base/string_number_conversions.h"
-#include "base/synchronization/waitable_event.h"
-#include "base/threading/thread.h"
#include "base/utf_string_conversions.h"
#include "content/renderer/media/media_stream_dependency_factory.h"
#include "content/renderer/media/media_stream_impl.h"
-#include "content/renderer/p2p/ipc_network_manager.h"
-#include "content/renderer/p2p/ipc_socket_factory.h"
-#include "third_party/libjingle/source/talk/base/thread.h"
-#include "third_party/libjingle/source/talk/p2p/base/portallocator.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebMediaStreamDescriptor.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebMediaStreamSource.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebPeerConnectionHandlerClient.h"
@@ -27,108 +21,54 @@
PeerConnectionHandler::PeerConnectionHandler(
WebKit::WebPeerConnectionHandlerClient* client,
MediaStreamImpl* msi,
- MediaStreamDependencyFactory* dependency_factory,
- talk_base::Thread* signaling_thread,
- content::P2PSocketDispatcher* socket_dispatcher,
- content::IpcNetworkManager* network_manager,
- content::IpcPacketSocketFactory* socket_factory)
+ MediaStreamDependencyFactory* dependency_factory)
: client_(client),
media_stream_impl_(msi),
dependency_factory_(dependency_factory),
- message_loop_proxy_(base::MessageLoopProxy::current()),
- signaling_thread_(signaling_thread),
- socket_dispatcher_(socket_dispatcher),
- network_manager_(network_manager),
- socket_factory_(socket_factory),
- call_state_(NOT_STARTED) {
+ message_loop_proxy_(base::MessageLoopProxy::current()) {
}
PeerConnectionHandler::~PeerConnectionHandler() {
- if (native_peer_connection_.get()) {
- native_peer_connection_->RegisterObserver(NULL);
- native_peer_connection_->Close();
- }
}
-bool PeerConnectionHandler::SetVideoRenderer(
+void PeerConnectionHandler::SetVideoRenderer(
const std::string& stream_label,
- cricket::VideoRenderer* renderer) {
- return native_peer_connection_->SetVideoRenderer(stream_label, renderer);
+ webrtc::VideoRendererWrapperInterface* renderer) {
+ webrtc::MediaStreamInterface* stream =
+ native_peer_connection_->remote_streams()->find(stream_label);
+ webrtc::VideoTracks* video_tracks = stream->video_tracks();
+ // We assume there is only one enabled video track.
+ for(size_t i = 0; i < video_tracks->count(); ++i) {
+ webrtc::VideoTrackInterface* video_track = video_tracks->at(i);
+ if (video_track->enabled()) {
+ video_track->SetRenderer(renderer);
+ return;
+ }
+ }
+ DVLOG(1) << "No enabled video track.";
}
void PeerConnectionHandler::initialize(
const WebKit::WebString& server_configuration,
const WebKit::WebSecurityOrigin& security_origin) {
- // We support the following server configuration format:
- // "STUN <address>:<port>". We only support STUN at the moment.
- // TODO(grunell): Support TURN.
-
- // Strip "STUN ".
- std::string strip_string = "STUN ";
- std::string config = UTF16ToUTF8(server_configuration);
- size_t pos = config.find(strip_string);
- if (pos != 0) {
- DVLOG(1) << "Invalid configuration string.";
- return;
- }
- config = config.substr(strip_string.length());
- // Parse out port.
- pos = config.find(':');
- if (pos == std::string::npos) {
- DVLOG(1) << "Invalid configuration string.";
- return;
- }
- int port = 0;
- bool success = base::StringToInt(config.substr(pos+1), &port);
- if (!success || (port == 0)) {
- DVLOG(1) << "Invalid configuration string.";
- return;
- }
- // Get address.
- std::string address = config.substr(0, pos);
-
- webkit_glue::P2PTransport::Config p2p_config;
- p2p_config.stun_server = address;
- p2p_config.stun_server_port = port;
-
- port_allocator_.reset(dependency_factory_->CreatePortAllocator(
- socket_dispatcher_,
- network_manager_,
- socket_factory_,
- p2p_config));
-
- native_peer_connection_.reset(dependency_factory_->CreatePeerConnection(
- port_allocator_.get(),
- signaling_thread_));
- native_peer_connection_->RegisterObserver(this);
+ native_peer_connection_ = dependency_factory_->CreatePeerConnection(
+ UTF16ToUTF8(server_configuration),
+ this);
}
void PeerConnectionHandler::produceInitialOffer(
const WebKit::WebVector<WebKit::WebMediaStreamDescriptor>&
pending_add_streams) {
- // We currently don't support creating an initial offer without a stream.
- // Native PeerConnection will anyway create the initial offer when the first
- // (and only) stream is added, so it will be done when processPendingStreams
- // is called if not here.
- if (pending_add_streams.isEmpty()) {
- DVLOG(1) << "Can't produce initial offer with no stream.";
- return;
- }
- // TODO(grunell): Support several streams.
- DCHECK_EQ(pending_add_streams.size(), 1u);
- WebKit::WebVector<WebKit::WebMediaStreamSource> source_vector;
- pending_add_streams[0].sources(source_vector);
- DCHECK_GT(source_vector.size(), 0u);
- std::string label = UTF16ToUTF8(source_vector[0].id());
- AddStream(label);
+ AddStreams(pending_add_streams);
+ native_peer_connection_->CommitStreamChanges();
}
void PeerConnectionHandler::handleInitialOffer(const WebKit::WebString& sdp) {
- native_peer_connection_->SignalingMessage(UTF16ToUTF8(sdp));
+ native_peer_connection_->ProcessSignalingMessage(UTF16ToUTF8(sdp));
}
void PeerConnectionHandler::processSDP(const WebKit::WebString& sdp) {
- native_peer_connection_->SignalingMessage(UTF16ToUTF8(sdp));
+ native_peer_connection_->ProcessSignalingMessage(UTF16ToUTF8(sdp));
}
void PeerConnectionHandler::processPendingStreams(
@@ -136,33 +76,36 @@ void PeerConnectionHandler::processPendingStreams(
pending_add_streams,
const WebKit::WebVector<WebKit::WebMediaStreamDescriptor>&
pending_remove_streams) {
- // TODO(grunell): Support several streams.
- if (!pending_add_streams.isEmpty()) {
- DCHECK_EQ(pending_add_streams.size(), 1u);
- WebKit::WebVector<WebKit::WebMediaStreamSource> source_vector;
- pending_add_streams[0].sources(source_vector);
- DCHECK_GT(source_vector.size(), 0u);
- std::string label = UTF16ToUTF8(source_vector[0].id());
- AddStream(label);
- }
- // Currently we ignore remove stream, no support in native PeerConnection.
+ AddStreams(pending_add_streams);
+ RemoveStreams(pending_remove_streams);
+ native_peer_connection_->CommitStreamChanges();
}
void PeerConnectionHandler::sendDataStreamMessage(
const char* data,
size_t length) {
- // TODO(grunell): Implement. Not supported in native PeerConnection.
+ // TODO(grunell): Implement.
NOTIMPLEMENTED();
}
void PeerConnectionHandler::stop() {
- if (native_peer_connection_.get())
- native_peer_connection_->RegisterObserver(NULL);
- native_peer_connection_.reset();
- // The close function will delete us.
+ // TODO(ronghuawu): There's an issue with signaling messages being sent during
+ // close. We need to investigate further. Not calling Close() on native
+ // PeerConnection is OK for now.
+ native_peer_connection_ = NULL;
media_stream_impl_->ClosePeerConnection();
}
+void PeerConnectionHandler::OnError() {
+ // TODO(grunell): Implement.
+ NOTIMPLEMENTED();
+}
+
+void PeerConnectionHandler::OnMessage(const std::string& msg) {
+ // TODO(grunell): Implement.
+ NOTIMPLEMENTED();
+}
+
void PeerConnectionHandler::OnSignalingMessage(const std::string& msg) {
if (!message_loop_proxy_->BelongsToCurrentThread()) {
message_loop_proxy_->PostTask(FROM_HERE, base::Bind(
@@ -174,101 +117,134 @@ void PeerConnectionHandler::OnSignalingMessage(const std::string& msg) {
client_->didGenerateSDP(UTF8ToUTF16(msg));
}
-void PeerConnectionHandler::OnAddStream(const std::string& stream_id,
- bool video) {
- if (!video)
+void PeerConnectionHandler::OnStateChange(StateType state_changed) {
+ // TODO(grunell): Implement.
+ NOTIMPLEMENTED();
+}
+
+void PeerConnectionHandler::OnAddStream(webrtc::MediaStreamInterface* stream) {
+ if (!stream)
return;
if (!message_loop_proxy_->BelongsToCurrentThread()) {
message_loop_proxy_->PostTask(FROM_HERE, base::Bind(
&PeerConnectionHandler::OnAddStreamCallback,
base::Unretained(this),
- stream_id));
+ stream));
} else {
- OnAddStreamCallback(stream_id);
+ OnAddStreamCallback(stream);
}
}
void PeerConnectionHandler::OnRemoveStream(
- const std::string& stream_id,
- bool video) {
- if (!video)
+ webrtc::MediaStreamInterface* stream) {
+ if (!stream)
return;
if (!message_loop_proxy_->BelongsToCurrentThread()) {
message_loop_proxy_->PostTask(FROM_HERE, base::Bind(
&PeerConnectionHandler::OnRemoveStreamCallback,
base::Unretained(this),
- remote_label_));
+ stream));
} else {
- OnRemoveStreamCallback(remote_label_);
+ OnRemoveStreamCallback(stream);
}
}
-void PeerConnectionHandler::AddStream(const std::string label) {
- // TODO(grunell): Fix code in this function after a new native PeerConnection
- // version has been rolled out.
- if (call_state_ == NOT_STARTED) {
- // TODO(grunell): Add audio and/or video depending on what's enabled
- // in the stream.
- std::string audio_label = label;
- audio_label.append("-audio");
- native_peer_connection_->AddStream(audio_label, false); // Audio
- native_peer_connection_->AddStream(label, true); // Video
- call_state_ = INITIATING;
- }
- if (call_state_ == INITIATING || call_state_ == RECEIVING) {
- local_label_ = label;
- if (media_stream_impl_->SetVideoCaptureModule(label))
- native_peer_connection_->SetVideoCapture("");
- if (call_state_ == INITIATING)
- native_peer_connection_->Connect();
- else if (call_state_ == RECEIVING)
- call_state_ = SENDING_AND_RECEIVING;
- } else {
- DLOG(ERROR) << "Multiple streams not supported";
+void PeerConnectionHandler::AddStreams(
+ const WebKit::WebVector<WebKit::WebMediaStreamDescriptor>& streams) {
+ for (size_t i = 0; i < streams.size(); ++i) {
+ talk_base::scoped_refptr<webrtc::LocalMediaStreamInterface> stream =
+ dependency_factory_->CreateLocalMediaStream(
+ UTF16ToUTF8(streams[i].label()));
+ WebKit::WebVector<WebKit::WebMediaStreamSource> source_vector;
+ streams[i].sources(source_vector);
+
+ // Get and add all tracks.
+ for (size_t j = 0; j < source_vector.size(); ++j) {
+ webrtc::MediaStreamTrackInterface* track =
+ media_stream_impl_->GetLocalMediaStreamTrack(
+ UTF16ToUTF8(source_vector[j].id()));
+ DCHECK(track);
+ if (source_vector[j].type() == WebKit::WebMediaStreamSource::TypeVideo) {
+ stream->AddTrack(static_cast<webrtc::VideoTrackInterface*>(track));
+ } else {
+ stream->AddTrack(static_cast<webrtc::AudioTrackInterface*>(track));
+ }
+ }
+
+ native_peer_connection_->AddStream(stream);
}
}
-void PeerConnectionHandler::OnAddStreamCallback(
- const std::string& stream_label) {
- // TODO(grunell): Fix code in this function after a new native PeerConnection
- // version has been rolled out.
- if (call_state_ == NOT_STARTED) {
- remote_label_ = stream_label;
- call_state_ = RECEIVING;
- } else if (call_state_ == INITIATING) {
- remote_label_ = local_label_;
- remote_label_ += "-remote";
- call_state_ = SENDING_AND_RECEIVING;
+void PeerConnectionHandler::RemoveStreams(
+ const WebKit::WebVector<WebKit::WebMediaStreamDescriptor>& streams) {
+ for (size_t i = 0; i < streams.size(); ++i) {
+ webrtc::MediaStreamInterface* stream =
+ native_peer_connection_->remote_streams()->find(
+ UTF16ToUTF8(streams[i].label()));
+ native_peer_connection_->RemoveStream(
+ static_cast<webrtc::LocalMediaStreamInterface*>(stream));
}
+}
- // TODO(grunell): Support several tracks.
- WebKit::WebVector<WebKit::WebMediaStreamSource> source_vector(
- static_cast<size_t>(2));
- source_vector[0].initialize(WebKit::WebString::fromUTF8(remote_label_),
- WebKit::WebMediaStreamSource::TypeVideo,
- WebKit::WebString::fromUTF8("RemoteVideo"));
- source_vector[1].initialize(WebKit::WebString::fromUTF8(remote_label_),
- WebKit::WebMediaStreamSource::TypeAudio,
- WebKit::WebString::fromUTF8("RemoteAudio"));
- WebKit::WebMediaStreamDescriptor descriptor;
- descriptor.initialize(UTF8ToUTF16(remote_label_), source_vector);
+void PeerConnectionHandler::OnAddStreamCallback(
+ webrtc::MediaStreamInterface* stream) {
+ DCHECK(remote_streams_.find(stream) == remote_streams_.end());
+ WebKit::WebMediaStreamDescriptor descriptor =
+ CreateWebKitStreamDescriptor(stream);
+ remote_streams_.insert(
+ std::pair<webrtc::MediaStreamInterface*,
+ WebKit::WebMediaStreamDescriptor>(stream, descriptor));
client_->didAddRemoteStream(descriptor);
}
void PeerConnectionHandler::OnRemoveStreamCallback(
- const std::string& stream_label) {
- // TODO(grunell): Support several tracks.
+ webrtc::MediaStreamInterface* stream) {
+ RemoteStreamMap::iterator it = remote_streams_.find(stream);
+ if (it == remote_streams_.end()) {
+ NOTREACHED() << "Stream not found";
+ return;
+ }
+ WebKit::WebMediaStreamDescriptor descriptor = it->second;
+ DCHECK(!descriptor.isNull());
+ remote_streams_.erase(it);
+ client_->didRemoveRemoteStream(descriptor);
+}
+
+WebKit::WebMediaStreamDescriptor
+PeerConnectionHandler::CreateWebKitStreamDescriptor(
+ webrtc::MediaStreamInterface* stream) {
+ webrtc::AudioTracks* audio_tracks = stream->audio_tracks();
+ webrtc::VideoTracks* video_tracks = stream->video_tracks();
WebKit::WebVector<WebKit::WebMediaStreamSource> source_vector(
- static_cast<size_t>(2));
- source_vector[0].initialize(WebKit::WebString::fromUTF8(stream_label),
- WebKit::WebMediaStreamSource::TypeVideo,
- WebKit::WebString::fromUTF8("RemoteVideo"));
- source_vector[1].initialize(WebKit::WebString::fromUTF8(stream_label),
- WebKit::WebMediaStreamSource::TypeAudio,
- WebKit::WebString::fromUTF8("RemoteAudio"));
+ audio_tracks->count() + video_tracks->count());
+
+ // Add audio tracks.
+ size_t i = 0;
+ for (; i < audio_tracks->count(); ++i) {
+ webrtc::AudioTrackInterface* audio_track = audio_tracks->at(i);
+ DCHECK(audio_track);
+ source_vector[i].initialize(
+ // TODO(grunell): Set id to something unique.
+ UTF8ToUTF16(audio_track->label()),
+ WebKit::WebMediaStreamSource::TypeAudio,
+ UTF8ToUTF16(audio_track->label()));
+ }
+
+ // Add video tracks.
+ for (i = 0; i < video_tracks->count(); ++i) {
+ webrtc::VideoTrackInterface* video_track = video_tracks->at(i);
+ DCHECK(video_track);
+ source_vector[audio_tracks->count() + i].initialize(
+ // TODO(grunell): Set id to something unique.
+ UTF8ToUTF16(video_track->label()),
+ WebKit::WebMediaStreamSource::TypeVideo,
+ UTF8ToUTF16(video_track->label()));
+ }
+
WebKit::WebMediaStreamDescriptor descriptor;
- descriptor.initialize(UTF8ToUTF16(stream_label), source_vector);
- client_->didRemoveRemoteStream(descriptor);
+ descriptor.initialize(UTF8ToUTF16(stream->label()), source_vector);
+
+ return descriptor;
}
diff --git a/content/renderer/media/peer_connection_handler.h b/content/renderer/media/peer_connection_handler.h
index 589f865..6765ece 100644
--- a/content/renderer/media/peer_connection_handler.h
+++ b/content/renderer/media/peer_connection_handler.h
@@ -5,6 +5,7 @@
#ifndef CONTENT_RENDERER_MEDIA_PEER_CONNECTION_HANDLER_H_
#define CONTENT_RENDERER_MEDIA_PEER_CONNECTION_HANDLER_H_
+#include <map>
#include <string>
#include "base/basictypes.h"
@@ -13,35 +14,16 @@
#include "base/memory/scoped_ptr.h"
#include "base/message_loop_proxy.h"
#include "content/common/content_export.h"
-#include "third_party/libjingle/source/talk/app/webrtcv1/peerconnection.h"
-#include "third_party/libjingle/source/talk/base/socketaddress.h"
+#include "third_party/libjingle/source/talk/app/webrtc/mediastream.h"
+#include "third_party/libjingle/source/talk/app/webrtc/peerconnection.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebPeerConnectionHandler.h"
-namespace base {
-class Thread;
-class WaitableEvent;
-}
-
-namespace content {
-class IpcNetworkManager;
-class IpcPacketSocketFactory;
-class P2PSocketDispatcher;
-}
-
-namespace cricket {
-class PortAllocator;
-}
-
-namespace talk_base {
-class Thread;
-}
-
class MediaStreamDependencyFactory;
class MediaStreamImpl;
// PeerConnectionHandler is a delegate for the PeerConnection API messages going
// between WebKit and native PeerConnection in libjingle. It's owned by
-// MediaStreamImpl.
+// WebKit.
class CONTENT_EXPORT PeerConnectionHandler
: NON_EXPORTED_BASE(public WebKit::WebPeerConnectionHandler),
NON_EXPORTED_BASE(public webrtc::PeerConnectionObserver) {
@@ -49,16 +31,13 @@ class CONTENT_EXPORT PeerConnectionHandler
PeerConnectionHandler(
WebKit::WebPeerConnectionHandlerClient* client,
MediaStreamImpl* msi,
- MediaStreamDependencyFactory* dependency_factory,
- talk_base::Thread* signaling_thread,
- content::P2PSocketDispatcher* socket_dispatcher,
- content::IpcNetworkManager* network_manager,
- content::IpcPacketSocketFactory* socket_factory);
+ MediaStreamDependencyFactory* dependency_factory);
virtual ~PeerConnectionHandler();
// Set the video renderer for the specified stream.
- virtual bool SetVideoRenderer(const std::string& stream_label,
- cricket::VideoRenderer* renderer);
+ virtual void SetVideoRenderer(
+ const std::string& stream_label,
+ webrtc::VideoRendererWrapperInterface* renderer);
// WebKit::WebPeerConnectionHandler implementation
virtual void initialize(
@@ -75,21 +54,28 @@ class CONTENT_EXPORT PeerConnectionHandler
const WebKit::WebVector<WebKit::WebMediaStreamDescriptor>&
pending_remove_streams) OVERRIDE;
virtual void sendDataStreamMessage(const char* data, size_t length) OVERRIDE;
+ // We will be deleted by WebKit after stop has been returned.
virtual void stop() OVERRIDE;
// webrtc::PeerConnectionObserver implementation
+ virtual void OnError() OVERRIDE;
+ virtual void OnMessage(const std::string& msg) OVERRIDE;
virtual void OnSignalingMessage(const std::string& msg) OVERRIDE;
- virtual void OnAddStream(const std::string& stream_id, bool video) OVERRIDE;
- virtual void OnRemoveStream(
- const std::string& stream_id,
- bool video) OVERRIDE;
+ virtual void OnStateChange(StateType state_changed) OVERRIDE;
+ virtual void OnAddStream(webrtc::MediaStreamInterface* stream) OVERRIDE;
+ virtual void OnRemoveStream(webrtc::MediaStreamInterface* stream) OVERRIDE;
private:
FRIEND_TEST_ALL_PREFIXES(PeerConnectionHandlerTest, Basic);
- void AddStream(const std::string label);
- void OnAddStreamCallback(const std::string& stream_label);
- void OnRemoveStreamCallback(const std::string& stream_label);
+ void AddStreams(
+ const WebKit::WebVector<WebKit::WebMediaStreamDescriptor>& streams);
+ void RemoveStreams(
+ const WebKit::WebVector<WebKit::WebMediaStreamDescriptor>& streams);
+ void OnAddStreamCallback(webrtc::MediaStreamInterface* stream);
+ void OnRemoveStreamCallback(webrtc::MediaStreamInterface* stream);
+ WebKit::WebMediaStreamDescriptor CreateWebKitStreamDescriptor(
+ webrtc::MediaStreamInterface* stream);
// client_ is a weak pointer, and is valid until stop() has returned.
WebKit::WebPeerConnectionHandlerClient* client_;
@@ -104,55 +90,14 @@ class CONTENT_EXPORT PeerConnectionHandler
// native_peer_connection_ is the native PeerConnection object,
// it handles the ICE processing and media engine.
- scoped_ptr<webrtc::PeerConnection> native_peer_connection_;
+ talk_base::scoped_refptr<webrtc::PeerConnectionInterface>
+ native_peer_connection_;
- scoped_refptr<base::MessageLoopProxy> message_loop_proxy_;
+ typedef std::map<webrtc::MediaStreamInterface*,
+ WebKit::WebMediaStreamDescriptor> RemoteStreamMap;
+ RemoteStreamMap remote_streams_;
- talk_base::Thread* signaling_thread_;
-
- // 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.
- content::IpcNetworkManager* network_manager_;
- content::IpcPacketSocketFactory* socket_factory_;
-
- scoped_ptr<cricket::PortAllocator> port_allocator_;
-
- // Currently, a stream in WebKit has audio and/or video and has one label.
- // Local and remote streams have different labels.
- // In native PeerConnection, a stream has audio or video (not both), and they
- // have separate labels. A remote stream has the same label as the
- // corresponding local stream. Hence the workarounds in the implementation to
- // handle this. It could look like this:
- // WebKit: Local, audio and video: label "foo".
- // Remote, audio and video: label "foo-remote".
- // Native: Local and remote, audio: label "foo-audio".
- // Local and remote, video: label "foo".
- // TODO(grunell): This shall be removed or changed when native PeerConnection
- // has been updated to closer follow the specification.
- std::string local_label_; // Label used in WebKit
- std::string remote_label_; // Label used in WebKit
-
- // Call states. Possible transitions:
- // NOT_STARTED -> INITIATING -> SENDING_AND_RECEIVING
- // NOT_STARTED -> RECEIVING
- // RECEIVING -> NOT_STARTED
- // RECEIVING -> SENDING_AND_RECEIVING
- // SENDING_AND_RECEIVING -> NOT_STARTED
- // Note that when in state SENDING_AND_RECEIVING, the other side may or may
- // not send media. Thus, this state does not necessarily mean full duplex.
- // TODO(grunell): This shall be removed or changed when native PeerConnection
- // has been updated to closer follow the specification.
- enum CallState {
- NOT_STARTED,
- INITIATING,
- RECEIVING,
- SENDING_AND_RECEIVING
- };
- CallState call_state_;
+ scoped_refptr<base::MessageLoopProxy> message_loop_proxy_;
DISALLOW_COPY_AND_ASSIGN(PeerConnectionHandler);
};
diff --git a/content/renderer/media/peer_connection_handler_unittest.cc b/content/renderer/media/peer_connection_handler_unittest.cc
index 766db5d..8cb4076 100644
--- a/content/renderer/media/peer_connection_handler_unittest.cc
+++ b/content/renderer/media/peer_connection_handler_unittest.cc
@@ -15,10 +15,22 @@
#include "content/renderer/media/rtc_video_decoder.h"
#include "jingle/glue/thread_wrapper.h"
#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/libjingle/source/talk/app/webrtcv1/peerconnection.h"
+#include "third_party/libjingle/source/talk/app/webrtc/peerconnection.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebMediaStreamDescriptor.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebMediaStreamSource.h"
+namespace webrtc {
+
+class MockVideoRendererWrapper : public VideoRendererWrapperInterface {
+ public:
+ virtual cricket::VideoRenderer* renderer() OVERRIDE { return NULL; }
+
+ protected:
+ virtual ~MockVideoRendererWrapper() {}
+};
+
+} // namespace webrtc
+
TEST(PeerConnectionHandlerTest, Basic) {
MessageLoop loop;
@@ -27,15 +39,15 @@ TEST(PeerConnectionHandlerTest, Basic) {
scoped_refptr<MockMediaStreamImpl> mock_ms_impl(new MockMediaStreamImpl());
scoped_ptr<MockMediaStreamDependencyFactory> mock_dependency_factory(
new MockMediaStreamDependencyFactory());
- mock_dependency_factory->CreatePeerConnectionFactory(NULL, NULL);
+ mock_dependency_factory->CreatePeerConnectionFactory(NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL);
scoped_ptr<PeerConnectionHandler> pc_handler(
new PeerConnectionHandler(mock_client.get(),
mock_ms_impl.get(),
- mock_dependency_factory.get(),
- NULL,
- NULL,
- NULL,
- NULL));
+ mock_dependency_factory.get()));
WebKit::WebString server_config(
WebKit::WebString::fromUTF8("STUN stun.l.google.com:19302"));
@@ -45,24 +57,24 @@ TEST(PeerConnectionHandlerTest, Basic) {
webrtc::MockPeerConnectionImpl* mock_peer_connection =
static_cast<webrtc::MockPeerConnectionImpl*>(
pc_handler->native_peer_connection_.get());
- EXPECT_EQ(static_cast<webrtc::PeerConnectionObserver*>(pc_handler.get()),
- mock_peer_connection->observer());
- std::string label("label");
+ // TODO(grunell): Add an audio track as well.
+ std::string stream_label("stream-label");
+ std::string video_track_label("video-label");
+ talk_base::scoped_refptr<webrtc::LocalVideoTrackInterface> local_video_track(
+ mock_dependency_factory->CreateLocalVideoTrack(video_track_label, NULL));
+ mock_ms_impl->AddTrack(video_track_label, local_video_track);
WebKit::WebVector<WebKit::WebMediaStreamSource> source_vector(
static_cast<size_t>(1));
- source_vector[0].initialize(WebKit::WebString::fromUTF8(label),
+ source_vector[0].initialize(WebKit::WebString::fromUTF8(video_track_label),
WebKit::WebMediaStreamSource::TypeVideo,
WebKit::WebString::fromUTF8("RemoteVideo"));
- WebKit::WebVector<WebKit::WebMediaStreamDescriptor> pendingAddStreams(
+ WebKit::WebVector<WebKit::WebMediaStreamDescriptor> local_streams(
static_cast<size_t>(1));
- pendingAddStreams[0].initialize(UTF8ToUTF16(label), source_vector);
- pc_handler->produceInitialOffer(pendingAddStreams);
- EXPECT_EQ(label, mock_ms_impl->video_label());
- EXPECT_EQ(label, mock_peer_connection->stream_id());
- EXPECT_TRUE(mock_peer_connection->video_stream());
- EXPECT_TRUE(mock_peer_connection->connected());
- EXPECT_TRUE(mock_peer_connection->video_capture_set());
+ local_streams[0].initialize(UTF8ToUTF16(stream_label), source_vector);
+ pc_handler->produceInitialOffer(local_streams);
+ EXPECT_EQ(stream_label, mock_peer_connection->stream_label());
+ EXPECT_TRUE(mock_peer_connection->stream_changes_committed());
std::string message("message1");
pc_handler->handleInitialOffer(WebKit::WebString::fromUTF8(message));
@@ -76,49 +88,47 @@ TEST(PeerConnectionHandlerTest, Basic) {
pc_handler->OnSignalingMessage(message);
EXPECT_EQ(message, mock_client->sdp());
- std::string remote_label(label);
- remote_label.append("-remote");
- pc_handler->OnAddStream(remote_label, true);
- EXPECT_EQ(remote_label, mock_client->stream_label());
-
- scoped_refptr<RTCVideoDecoder> rtc_video_decoder(
- new RTCVideoDecoder(&loop, ""));
- pc_handler->SetVideoRenderer(label, rtc_video_decoder.get());
- EXPECT_EQ(label, mock_peer_connection->video_renderer_stream_id());
+ std::string remote_stream_label(stream_label);
+ remote_stream_label += "-remote";
+ std::string remote_video_track_label(video_track_label);
+ remote_video_track_label += "-remote";
+ // We use a local stream as a remote since for testing purposes we really
+ // only need the MediaStreamInterface.
+ talk_base::scoped_refptr<webrtc::LocalMediaStreamInterface> remote_stream(
+ mock_dependency_factory->CreateLocalMediaStream(remote_stream_label));
+ talk_base::scoped_refptr<webrtc::LocalVideoTrackInterface> remote_video_track(
+ mock_dependency_factory->CreateLocalVideoTrack(remote_video_track_label,
+ NULL));
+ remote_video_track->set_enabled(true);
+ remote_stream->AddTrack(remote_video_track);
+ mock_peer_connection->AddRemoteStream(remote_stream);
+ pc_handler->OnAddStream(remote_stream);
+ EXPECT_EQ(remote_stream_label, mock_client->stream_label());
+
+ talk_base::scoped_refptr<webrtc::MockVideoRendererWrapper> renderer(
+ new talk_base::RefCountedObject<webrtc::MockVideoRendererWrapper>());
+ pc_handler->SetVideoRenderer(remote_stream_label, renderer);
+ EXPECT_EQ(renderer, static_cast<webrtc::MockLocalVideoTrack*>(
+ remote_video_track.get())->renderer());
+
+ WebKit::WebVector<WebKit::WebMediaStreamDescriptor> empty_streams(
+ static_cast<size_t>(0));
+ pc_handler->processPendingStreams(empty_streams, local_streams);
+ EXPECT_EQ("", mock_peer_connection->stream_label());
+ mock_peer_connection->ClearStreamChangesCommitted();
+ EXPECT_TRUE(!mock_peer_connection->stream_changes_committed());
- pc_handler->OnRemoveStream(remote_label, true);
+ pc_handler->OnRemoveStream(remote_stream);
EXPECT_TRUE(mock_client->stream_label().empty());
+ pc_handler->processPendingStreams(local_streams, empty_streams);
+ EXPECT_EQ(stream_label, mock_peer_connection->stream_label());
+ EXPECT_TRUE(mock_peer_connection->stream_changes_committed());
+
pc_handler->stop();
EXPECT_FALSE(pc_handler->native_peer_connection_.get());
// PC handler is expected to be deleted when stop calls
// MediaStreamImpl::ClosePeerConnection. We own and delete it here instead of
// in the mock.
pc_handler.reset();
-
- // processPendingStreams must be tested on a new PC handler since removing
- // streams is currently not supported.
- pc_handler.reset(new PeerConnectionHandler(mock_client.get(),
- mock_ms_impl.get(),
- mock_dependency_factory.get(),
- NULL,
- NULL,
- NULL,
- NULL));
- pc_handler->initialize(server_config, security_origin);
- EXPECT_TRUE(pc_handler->native_peer_connection_.get());
- mock_peer_connection = static_cast<webrtc::MockPeerConnectionImpl*>(
- pc_handler->native_peer_connection_.get());
-
- WebKit::WebVector<WebKit::WebMediaStreamDescriptor> pendingRemoveStreams(
- static_cast<size_t>(0));
- pc_handler->processPendingStreams(pendingAddStreams, pendingRemoveStreams);
- EXPECT_EQ(label, mock_ms_impl->video_label());
- EXPECT_EQ(label, mock_peer_connection->stream_id());
- EXPECT_TRUE(mock_peer_connection->video_stream());
- EXPECT_TRUE(mock_peer_connection->connected());
- EXPECT_TRUE(mock_peer_connection->video_capture_set());
-
- pc_handler->stop();
- pc_handler.reset();
}