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

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: Rebase 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 2ee52213f102ec246e1dcc4841022e64e8a2d4b2..389de6f44aebd2e9bcc7809bc406e05ea7671740 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 @@ static 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;
+}
« no previous file with comments | « content/renderer/media/media_stream_impl.h ('k') | content/renderer/media/mock_media_stream_dependency_factory.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698