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

Unified Diff: content/renderer/media/media_stream_impl.cc

Issue 9284020: Enabling usage of native PeerConnection v2 in libjingle. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 8 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: content/renderer/media/media_stream_impl.cc
diff --git a/content/renderer/media/media_stream_impl.cc b/content/renderer/media/media_stream_impl.cc
index ab48883cbd1eee4aaede86848f823cc6a537496a..fd698115561ae92f8b2cc5a9e05a2b12f4c7e57f 100644
--- a/content/renderer/media/media_stream_impl.cc
+++ b/content/renderer/media/media_stream_impl.cc
@@ -23,9 +23,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"
@@ -41,6 +38,9 @@ static const int kVideoCaptureFramePerSecond = 30;
int MediaStreamImpl::next_request_id_ = 0;
+// TODO(grunell): BEFORE COMMIT. Add DCHECK(CalledOnValidThread()) in all
+// functions.
+
MediaStreamImpl::MediaStreamImpl(
MediaStreamDispatcher* media_stream_dispatcher,
content::P2PSocketDispatcher* p2p_socket_dispatcher,
@@ -48,7 +48,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 +55,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 +82,34 @@ 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) {
- 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;
+webrtc::MediaStreamTrackInterface* MediaStreamImpl::GetLocalMediaStreamTrack(
+ std::string label) {
+ MediaStreamTrackPtrMap::iterator it = local_tracks_.find(label);
+ if (it == local_tracks_.end())
+ return NULL;
+ MediaStreamTrackPtr stream = it->second;
+ return stream.get();
}
void MediaStreamImpl::requestUserMedia(
@@ -226,22 +171,33 @@ 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. The tracks in a local
+ // stream have IDs that are in the form
+ // <MediaStreamManager-label>#{audio,video}-<session-ID>. We extract the
tommi (sloooow) - chröme 2012/01/24 15:18:56 can we move the code that does this parsing out to
Henrik Grunell 2012/01/26 13:03:16 Broke out the generation and parsing of the track
+ // MSM-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 = UTF16ToUTF8(source_vector[i].id());
+ size_t pos = msm_label.rfind("#");
+ msm_label = msm_label.substr(0, pos);
tommi (sloooow) - chröme 2012/01/24 15:18:56 what if pos is npos?
Henrik Grunell 2012/01/26 13:03:16 Commented on that in the new functions. (Doesn't m
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 +212,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 +243,57 @@ 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),
+ // The 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.
+
+ // Add audio tracks.
+ size_t i = 0;
tommi (sloooow) - chröme 2012/01/24 15:18:56 unless you use 'i' outside the loops, just declare
Henrik Grunell 2012/01/26 13:03:16 Relic from earlier stage of local dev. Fixed.
+ std::string track_label;
+ for (; i < audio_array.size(); ++i) {
+ track_label = label;
+ track_label += "#audio-";
+ track_label += audio_array[i].session_id;
+ talk_base::scoped_refptr<webrtc::LocalAudioTrackInterface> 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 (i = 0; i < video_array.size(); ++i) {
+ track_label = label;
+ track_label += "#video-";
+ track_label += video_array[i].session_id;
+ webrtc::VideoCaptureModule* vcm =
+ new VideoCaptureModuleImpl(video_array[i].session_id,
+ vc_manager_.get());
+ talk_base::scoped_refptr<webrtc::LocalVideoTrackInterface> video_track(
tommi (sloooow) - chröme 2012/01/24 15:18:56 should video_track be of type MediaStreamTrackPtr?
Henrik Grunell 2012/01/26 13:03:16 Yes, that's better. Changed it and for audio_track
+ dependency_factory_->CreateLocalVideoTrack(
+ video_array[i].name,
+ webrtc::CreateVideoCapturer(vcm)));
tommi (sloooow) - chröme 2012/01/24 15:18:56 add a comment about the ownership of vcm?
Henrik Grunell 2012/01/26 13:03:16 Done.
+ 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 +301,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);
}
@@ -364,3 +351,65 @@ 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();
tommi (sloooow) - chröme 2012/01/24 15:18:56 is there a specific reason why we need to do this
Henrik Grunell 2012/01/26 13:03:16 Yes there's a reason. worker_thread_ must be set b
+ 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_,
tommi (sloooow) - chröme 2012/01/24 15:18:56 it feels weird to me to see parameters indented to
Henrik Grunell 2012/01/26 13:03:16 That seems better. Fixed.
+ 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() {}
+
+cricket::VideoRenderer* MediaStreamImpl::VideoRendererWrapper::renderer() {
tommi (sloooow) - chröme 2012/01/24 15:18:56 nit: one liners like this one (all lower case) usu
Henrik Grunell 2012/01/26 13:03:16 Done.
+ return rtc_video_decoder_.get();
+}
+
+void MediaStreamImpl::VideoRendererWrapper::SetVideoDecoder(
+ RTCVideoDecoder* decoder) {
+ rtc_video_decoder_ = decoder;
+}

Powered by Google App Engine
This is Rietveld 408576698