summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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
-rw-r--r--third_party/libjingle/libjingle.gyp50
14 files changed, 935 insertions, 636 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();
}
diff --git a/third_party/libjingle/libjingle.gyp b/third_party/libjingle/libjingle.gyp
index a276e98..7531ae6 100644
--- a/third_party/libjingle/libjingle.gyp
+++ b/third_party/libjingle/libjingle.gyp
@@ -481,17 +481,45 @@
'target_name': 'libjingle_peerconnection',
'type': 'static_library',
'sources': [
- 'source/talk/app/webrtcv1/peerconnection.h',
- 'source/talk/app/webrtcv1/peerconnectionfactory.cc',
- 'source/talk/app/webrtcv1/peerconnectionfactory.h',
- 'source/talk/app/webrtcv1/peerconnectionimpl.cc',
- 'source/talk/app/webrtcv1/peerconnectionimpl.h',
- 'source/talk/app/webrtcv1/peerconnectionproxy.cc',
- 'source/talk/app/webrtcv1/peerconnectionproxy.h',
- 'source/talk/app/webrtcv1/webrtcsession.cc',
- 'source/talk/app/webrtcv1/webrtcsession.h',
- 'source/talk/app/webrtcv1/webrtcjson.cc',
- 'source/talk/app/webrtcv1/webrtcjson.h',
+ 'source/talk/app/webrtc/audiotrackimpl.cc',
+ 'source/talk/app/webrtc/audiotrackimpl.h',
+ 'source/talk/app/webrtc/mediastream.h',
+ 'source/talk/app/webrtc/mediastreamhandler.cc',
+ 'source/talk/app/webrtc/mediastreamhandler.h',
+ 'source/talk/app/webrtc/mediastreamimpl.cc',
+ 'source/talk/app/webrtc/mediastreamimpl.h',
+ 'source/talk/app/webrtc/mediastreamprovider.h',
+ 'source/talk/app/webrtc/mediastreamproxy.cc',
+ 'source/talk/app/webrtc/mediastreamproxy.h',
+ 'source/talk/app/webrtc/mediastreamtrackproxy.cc',
+ 'source/talk/app/webrtc/mediastreamtrackproxy.h',
+ 'source/talk/app/webrtc/mediatrackimpl.h',
+ 'source/talk/app/webrtc/notifierimpl.h',
+ 'source/talk/app/webrtc/peerconnectionfactoryimpl.cc',
+ 'source/talk/app/webrtc/peerconnectionfactoryimpl.h',
+ 'source/talk/app/webrtc/peerconnectionimpl.cc',
+ 'source/talk/app/webrtc/peerconnectionimpl.h',
+ 'source/talk/app/webrtc/peerconnectionsignaling.cc',
+ 'source/talk/app/webrtc/peerconnectionsignaling.h',
+ 'source/talk/app/webrtc/portallocatorfactory.cc',
+ 'source/talk/app/webrtc/portallocatorfactory.h',
+ 'source/talk/app/webrtc/roaperrorcodes.h',
+ 'source/talk/app/webrtc/roapmessages.cc',
+ 'source/talk/app/webrtc/roapmessages.h',
+ 'source/talk/app/webrtc/roapsession.cc',
+ 'source/talk/app/webrtc/roapsession.h',
+ 'source/talk/app/webrtc/sessiondescriptionprovider.h',
+ 'source/talk/app/webrtc/streamcollectionimpl.h',
+ 'source/talk/app/webrtc/videorendererimpl.cc',
+ 'source/talk/app/webrtc/videotrackimpl.cc',
+ 'source/talk/app/webrtc/videotrackimpl.h',
+ 'source/talk/app/webrtc/webrtcjson.cc',
+ 'source/talk/app/webrtc/webrtcjson.h',
+ 'source/talk/app/webrtc/webrtcsdp.cc',
+ 'source/talk/app/webrtc/webrtcsdp.h',
+ 'source/talk/app/webrtc/webrtcsession.cc',
+ 'source/talk/app/webrtc/webrtcsession.h',
+ 'source/talk/app/webrtc/webrtcsessionobserver.h',
'source/talk/session/phone/audiomonitor.cc',
'source/talk/session/phone/audiomonitor.h',
'source/talk/session/phone/call.cc',