r117430 - in trunk/src/content: . renderer renderer/media renderer/p2p

117 views
Skip to first unread message

gru...@chromium.org

unread,
Jan 12, 2012, 10:03:51 AM1/12/12
to chromium...@chromium.org
Author: gru...@chromium.org
Date: Thu Jan 12 07:03:51 2012
New Revision: 117430

Log:
Adding support for MediaStream and PeerConnection functionality.

BUG=
TEST=content_unittests

Review URL: http://codereview.chromium.org/8060055

Added:
trunk/src/content/renderer/media/media_stream_dependency_factory.cc (contents, props changed)
trunk/src/content/renderer/media/media_stream_dependency_factory.h (contents, props changed)
trunk/src/content/renderer/media/media_stream_impl_unittest.cc (contents, props changed)
trunk/src/content/renderer/media/mock_media_stream_dependency_factory.cc (contents, props changed)
trunk/src/content/renderer/media/mock_media_stream_dependency_factory.h (contents, props changed)
trunk/src/content/renderer/media/mock_media_stream_dispatcher.cc (contents, props changed)
trunk/src/content/renderer/media/mock_media_stream_dispatcher.h (contents, props changed)
trunk/src/content/renderer/media/mock_media_stream_impl.cc (contents, props changed)
trunk/src/content/renderer/media/mock_media_stream_impl.h (contents, props changed)
trunk/src/content/renderer/media/mock_peer_connection_impl.cc (contents, props changed)
trunk/src/content/renderer/media/mock_peer_connection_impl.h (contents, props changed)
trunk/src/content/renderer/media/mock_web_peer_connection_handler_client.cc (contents, props changed)
trunk/src/content/renderer/media/mock_web_peer_connection_handler_client.h (contents, props changed)
trunk/src/content/renderer/media/peer_connection_handler.cc (contents, props changed)
trunk/src/content/renderer/media/peer_connection_handler.h (contents, props changed)
trunk/src/content/renderer/media/peer_connection_handler_unittest.cc (contents, props changed)
Modified:
trunk/src/content/content_renderer.gypi
trunk/src/content/content_tests.gypi
trunk/src/content/renderer/media/media_stream_dispatcher.h
trunk/src/content/renderer/media/media_stream_impl.cc
trunk/src/content/renderer/media/media_stream_impl.h
trunk/src/content/renderer/p2p/socket_dispatcher.h
trunk/src/content/renderer/render_view_impl.cc
trunk/src/content/renderer/render_view_impl.h
trunk/src/content/renderer/renderer_webkitplatformsupport_impl.cc
trunk/src/content/renderer/renderer_webkitplatformsupport_impl.h

Modified: trunk/src/content/content_renderer.gypi
==============================================================================
--- trunk/src/content/content_renderer.gypi (original)
+++ trunk/src/content/content_renderer.gypi Thu Jan 12 07:03:51 2012
@@ -14,6 +14,7 @@
'../third_party/icu/icu.gyp:icui18n',
'../third_party/libjingle/libjingle.gyp:libjingle',
'../third_party/libjingle/libjingle.gyp:libjingle_p2p',
+ '../third_party/libjingle/libjingle.gyp:libjingle_peerconnection',
'../third_party/npapi/npapi.gyp:npapi',
'../third_party/WebKit/Source/WebKit/chromium/WebKit.gyp:webkit',
'../ui/gfx/surface/surface.gyp:surface',
@@ -108,11 +109,15 @@
'renderer/media/audio_renderer_impl.h',
'renderer/media/capture_video_decoder.cc',
'renderer/media/capture_video_decoder.h',
+ 'renderer/media/media_stream_dependency_factory.cc',
+ 'renderer/media/media_stream_dependency_factory.h',
'renderer/media/media_stream_dispatcher.cc',
'renderer/media/media_stream_dispatcher.h',
'renderer/media/media_stream_dispatcher_eventhandler.h',
'renderer/media/media_stream_impl.cc',
'renderer/media/media_stream_impl.h',
+ 'renderer/media/peer_connection_handler.cc',
+ 'renderer/media/peer_connection_handler.h',
'renderer/media/render_media_log.cc',
'renderer/media/render_media_log.h',
'renderer/media/rtc_video_decoder.cc',

Modified: trunk/src/content/content_tests.gypi
==============================================================================
--- trunk/src/content/content_tests.gypi (original)
+++ trunk/src/content/content_tests.gypi Thu Jan 12 07:03:51 2012
@@ -15,8 +15,10 @@
'../skia/skia.gyp:skia',
'../testing/gmock.gyp:gmock',
'../testing/gtest.gyp:gtest',
+ '../third_party/libjingle/libjingle.gyp:libjingle_peerconnection',
'../third_party/libvpx/libvpx.gyp:libvpx',
'../third_party/WebKit/Source/WebKit/chromium/WebKit.gyp:webkit',
+ '../third_party/webrtc/modules/modules.gyp:audio_device',
'../third_party/webrtc/modules/modules.gyp:video_capture_module',
'../third_party/webrtc/system_wrappers/source/system_wrappers.gyp:system_wrappers',
'../third_party/webrtc/video_engine/video_engine.gyp:video_engine_core',
@@ -66,6 +68,16 @@
'common/test_url_constants.h',
'gpu/gpu_idirect3d9_mock_win.cc',
'gpu/gpu_idirect3d9_mock_win.h',
+ 'renderer/media/mock_media_stream_dependency_factory.cc',
+ 'renderer/media/mock_media_stream_dependency_factory.h',
+ 'renderer/media/mock_media_stream_dispatcher.cc',
+ 'renderer/media/mock_media_stream_dispatcher.h',
+ 'renderer/media/mock_media_stream_impl.cc',
+ 'renderer/media/mock_media_stream_impl.h',
+ 'renderer/media/mock_peer_connection_impl.cc',
+ 'renderer/media/mock_peer_connection_impl.h',
+ 'renderer/media/mock_web_peer_connection_handler_client.cc',
+ 'renderer/media/mock_web_peer_connection_handler_client.h',
'renderer/mock_content_renderer_client.cc',
'renderer/mock_content_renderer_client.h',
'test/browser_test.h',
@@ -262,6 +274,8 @@
'renderer/media/audio_renderer_impl_unittest.cc',
'renderer/media/capture_video_decoder_unittest.cc',
'renderer/media/media_stream_dispatcher_unittest.cc',
+ 'renderer/media/media_stream_impl_unittest.cc',
+ 'renderer/media/peer_connection_handler_unittest.cc',
'renderer/media/rtc_video_decoder_unittest.cc',
'renderer/media/video_capture_impl_unittest.cc',
'renderer/media/video_capture_message_filter_unittest.cc',

Added: trunk/src/content/renderer/media/media_stream_dependency_factory.cc
==============================================================================
--- (empty file)
+++ trunk/src/content/renderer/media/media_stream_dependency_factory.cc Thu Jan 12 07:03:51 2012
@@ -0,0 +1,72 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/renderer/media/media_stream_dependency_factory.h"
+
+#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/webrtc/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/WebKit/Source/WebKit/chromium/public/WebFrame.h"
+
+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) {
+ 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());
+ }
+ return pc_factory_.get() != NULL;
+}
+
+void MediaStreamDependencyFactory::DeletePeerConnectionFactory() {
+ pc_factory_.reset();
+}
+
+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);
+}
+
+webrtc::PeerConnection* MediaStreamDependencyFactory::CreatePeerConnection(
+ cricket::PortAllocator* port_allocator,
+ talk_base::Thread* signaling_thread) {
+ return pc_factory_->CreatePeerConnection(port_allocator, signaling_thread);
+}

Added: trunk/src/content/renderer/media/media_stream_dependency_factory.h
==============================================================================
--- (empty file)
+++ trunk/src/content/renderer/media/media_stream_dependency_factory.h Thu Jan 12 07:03:51 2012
@@ -0,0 +1,78 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_RENDERER_MEDIA_MEDIA_STREAM_DEPENDENCY_FACTORY_H_
+#define CONTENT_RENDERER_MEDIA_MEDIA_STREAM_DEPENDENCY_FACTORY_H_
+
+#include <string>
+
+#include "base/basictypes.h"
+#include "base/memory/scoped_ptr.h"
+#include "content/common/content_export.h"
+#include "third_party/libjingle/source/talk/app/webrtc/peerconnectionfactory.h"
+#include "webkit/glue/p2p_transport.h"
+
+namespace content {
+class IpcNetworkManager;
+class IpcPacketSocketFactory;
+class P2PSocketDispatcher;
+}
+
+namespace cricket {
+class MediaEngineInterface;
+class PortAllocator;
+class WebRtcMediaEngine;
+}
+
+namespace talk_base {
+class NetworkManager;
+class PacketSocketFactory;
+class Thread;
+}
+
+namespace webrtc {
+class PeerConnection;
+class VideoCaptureModule;
+}
+
+// Object factory for MediaStreamImpl and PeerConnectionHandler.
+class CONTENT_EXPORT MediaStreamDependencyFactory {
+ public:
+ 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.
+ 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(
+ content::P2PSocketDispatcher* socket_dispatcher,
+ talk_base::NetworkManager* network_manager,
+ talk_base::PacketSocketFactory* socket_factory,
+ const webkit_glue::P2PTransport::Config& config);
+
+ // 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);
+
+ private:
+ scoped_ptr<webrtc::PeerConnectionFactory> pc_factory_;
+
+ DISALLOW_COPY_AND_ASSIGN(MediaStreamDependencyFactory);
+};
+
+#endif // CONTENT_RENDERER_MEDIA_MEDIA_STREAM_DEPENDENCY_FACTORY_H_

Modified: trunk/src/content/renderer/media/media_stream_dispatcher.h
==============================================================================
--- trunk/src/content/renderer/media/media_stream_dispatcher.h (original)
+++ trunk/src/content/renderer/media/media_stream_dispatcher.h Thu Jan 12 07:03:51 2012
@@ -1,4 +1,4 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

@@ -32,21 +32,22 @@
// Request a new media stream to be created.
// This can be used either of WebKit or a plugin.
// Note: The event_handler must be valid for as long as the stream exists.
- void GenerateStream(int request_id,
- MediaStreamDispatcherEventHandler* event_handler,
- media_stream::StreamOptions components,
- const std::string& security_origin);
+ virtual void GenerateStream(
+ int request_id,
+ MediaStreamDispatcherEventHandler* event_handler,
+ media_stream::StreamOptions components,
+ const std::string& security_origin);

// Stop a started stream. Label is the label provided in OnStreamGenerated.
- void StopStream(const std::string& label);
+ virtual void StopStream(const std::string& label);

// Check if the label is a valid stream.
- bool IsStream(const std::string& label);
+ virtual bool IsStream(const std::string& label);
// Get the video session_id given a label. The label identifies a stream.
// index is the index in the video_device_array of the stream.
- int video_session_id(const std::string& label, int index);
+ virtual int video_session_id(const std::string& label, int index);
// Returns an audio session_id given a label and an index.
- int audio_session_id(const std::string& label, int index);
+ virtual int audio_session_id(const std::string& label, int index);

private:
FRIEND_TEST_ALL_PREFIXES(MediaStreamDispatcherTest, Basic);

Modified: trunk/src/content/renderer/media/media_stream_impl.cc
==============================================================================
--- trunk/src/content/renderer/media/media_stream_impl.cc (original)
+++ trunk/src/content/renderer/media/media_stream_impl.cc Thu Jan 12 07:03:51 2012
@@ -1,15 +1,35 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "content/renderer/media/media_stream_impl.h"

-#include "base/string_util.h"
+#include <utility>
+
+#include "base/bind.h"
+#include "base/logging.h"
+#include "base/synchronization/waitable_event.h"
+#include "base/utf_string_conversions.h"
#include "content/renderer/media/capture_video_decoder.h"
+#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 "googleurl/src/gurl.h"
+#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/socket_dispatcher.h"
+#include "jingle/glue/thread_wrapper.h"
#include "media/base/message_loop_factory.h"
-#include "media/base/pipeline.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"
+#include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebVector.h"

namespace {

@@ -17,24 +37,211 @@
static const int kVideoCaptureHeight = 288;
static const int kVideoCaptureFramePerSecond = 30;

-static const int kStartOpenSessionId = 1;
+} // namespace

-// TODO(wjia): remove this string when full media stream code is checked in.
-static const char kRawMediaScheme[] = "mediastream";
+int MediaStreamImpl::next_request_id_ = 0;

-} // namespace
+MediaStreamImpl::MediaStreamImpl(
+ MediaStreamDispatcher* media_stream_dispatcher,
+ content::P2PSocketDispatcher* p2p_socket_dispatcher,
+ VideoCaptureImplManager* vc_manager,
+ 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),
+ peer_connection_handler_(NULL),
+ message_loop_proxy_(base::MessageLoopProxy::current()),
+ signaling_thread_(NULL),
+ worker_thread_(NULL),
+ chrome_worker_thread_("Chrome_libJingle_WorkerThread"),
+ vcm_created_(false) {
+}
+
+MediaStreamImpl::~MediaStreamImpl() {
+ DCHECK(!peer_connection_handler_);
+ if (dependency_factory_.get())
+ dependency_factory_->DeletePeerConnectionFactory();
+ if (network_manager_) {
+ // The network manager needs to free its resources on the thread they were
+ // created, which is the worked thread.
+ if (chrome_worker_thread_.IsRunning()) {
+ chrome_worker_thread_.message_loop()->PostTask(FROM_HERE, base::Bind(
+ &MediaStreamImpl::DeleteIpcNetworkManager,
+ base::Unretained(this)));
+ } else {
+ NOTREACHED() << "Worker thread not running.";
+ }
+ }
+}
+
+WebKit::WebPeerConnectionHandler* MediaStreamImpl::CreatePeerConnectionHandler(
+ WebKit::WebPeerConnectionHandlerClient* client) {
+ DCHECK(CalledOnValidThread());
+ if (peer_connection_handler_) {
+ 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;
+ }
+ }
+
+ peer_connection_handler_ = new PeerConnectionHandler(
+ client,
+ this,
+ dependency_factory_.get(),
+ signaling_thread_,
+ p2p_socket_dispatcher_,
+ network_manager_,
+ socket_factory_.get());
+
+ return peer_connection_handler_;
+}
+
+void MediaStreamImpl::ClosePeerConnection() {
+ DCHECK(CalledOnValidThread());
+ rtc_video_decoder_ = NULL;
+ media_engine_->SetVideoCaptureModule(NULL);
+ vcm_created_ = false;
+ peer_connection_handler_ = NULL;
+}
+
+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;
+}
+
+void MediaStreamImpl::requestUserMedia(
+ const WebKit::WebUserMediaRequest& user_media_request,
+ const WebKit::WebVector<WebKit::WebMediaStreamSource>&
+ media_stream_source_vector) {
+ DCHECK(CalledOnValidThread());
+ DCHECK(!user_media_request.isNull());
+
+ int request_id = next_request_id_++;
+
+ bool audio = user_media_request.audio();
+ media_stream::StreamOptions::VideoOption video_option =
+ media_stream::StreamOptions::kNoCamera;
+ if (user_media_request.video()) {
+ // If no preference is set, use user facing camera.
+ video_option = media_stream::StreamOptions::kFacingUser;
+ if (user_media_request.cameraPreferenceUser() &&
+ user_media_request.cameraPreferenceEnvironment()) {
+ video_option = media_stream::StreamOptions::kFacingBoth;
+ } else if (user_media_request.cameraPreferenceEnvironment()) {
+ video_option = media_stream::StreamOptions::kFacingEnvironment;
+ }
+ }
+
+ std::string security_origin = UTF16ToUTF8(
+ user_media_request.securityOrigin().toString());

-MediaStreamImpl::MediaStreamImpl(VideoCaptureImplManager* vc_manager)
- : vc_manager_(vc_manager) {
+ DVLOG(1) << "MediaStreamImpl::generateStream(" << request_id << ", [ "
+ << (audio ? "audio " : "")
+ << ((user_media_request.cameraPreferenceUser()) ?
+ "video_facing_user " : "")
+ << ((user_media_request.cameraPreferenceEnvironment()) ?
+ "video_facing_environment " : "") << "], "
+ << security_origin << ")";
+
+ user_media_requests_.insert(
+ std::pair<int, WebKit::WebUserMediaRequest>(
+ request_id, user_media_request));
+
+ media_stream_dispatcher_->GenerateStream(
+ request_id,
+ this,
+ media_stream::StreamOptions(audio, video_option),
+ security_origin);
}

-MediaStreamImpl::~MediaStreamImpl() {}
+void MediaStreamImpl::cancelUserMediaRequest(
+ const WebKit::WebUserMediaRequest& user_media_request) {
+ // TODO(grunell): Implement.
+ NOTIMPLEMENTED();
+}

scoped_refptr<media::VideoDecoder> MediaStreamImpl::GetVideoDecoder(
- const GURL& url, media::MessageLoopFactory* message_loop_factory) {
- bool raw_media = (url.spec().find(kRawMediaScheme) == 0);
- media::VideoDecoder* decoder = NULL;
- if (raw_media) {
+ const GURL& url,
+ media::MessageLoopFactory* message_loop_factory) {
+ DCHECK(CalledOnValidThread());
+ WebKit::WebMediaStreamDescriptor descriptor(
+ WebKit::WebMediaStreamRegistry::lookupMediaStreamDescriptor(url));
+ if (descriptor.isNull())
+ return NULL; // This is not a valid stream.
+ WebKit::WebVector<WebKit::WebMediaStreamSource> source_vector;
+ descriptor.sources(source_vector);
+ std::string 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());
+ break;
+ }
+ }
+ if (label.empty())
+ return NULL;
+
+ scoped_refptr<media::VideoDecoder> decoder;
+ if (media_stream_dispatcher_->IsStream(label)) {
+ // It's a local stream.
+ int video_session_id = media_stream_dispatcher_->video_session_id(label, 0);
media::VideoCapture::VideoCaptureCapability capability;
capability.width = kVideoCaptureWidth;
capability.height = kVideoCaptureHeight;
@@ -42,10 +249,118 @@
capability.expected_capture_delay = 0;
capability.raw_type = media::VideoFrame::I420;
capability.interlaced = false;
-
decoder = new CaptureVideoDecoder(
- message_loop_factory->GetMessageLoopProxy("CaptureVideoDecoder").get(),
- kStartOpenSessionId, vc_manager_.get(), capability);
+ message_loop_factory->GetMessageLoopProxy("CaptureVideoDecoderThread"),
+ video_session_id,
+ vc_manager_.get(),
+ 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()) {
+ // The renderer is used by PeerConnection, release it first.
+ if (peer_connection_handler_)
+ peer_connection_handler_->SetVideoRenderer(label, NULL);
+ }
+ 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_);
}
return decoder;
}
+
+void MediaStreamImpl::OnStreamGenerated(
+ int request_id,
+ const std::string& label,
+ const media_stream::StreamDeviceInfoArray& audio_array,
+ const media_stream::StreamDeviceInfoArray& video_array) {
+ DCHECK(CalledOnValidThread());
+
+ // 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),
+ WebKit::WebMediaStreamSource::TypeAudio,
+ track_label_audio);
+ } else {
+ source_vector[track_num].initialize(
+ UTF8ToUTF16(label),
+ WebKit::WebMediaStreamSource::TypeVideo,
+ track_label_video);
+ }
+ }
+
+ MediaRequestMap::iterator it = user_media_requests_.find(request_id);
+ if (it == user_media_requests_.end()) {
+ DVLOG(1) << "Request ID not found";
+ return;
+ }
+ WebKit::WebUserMediaRequest user_media_request = it->second;
+ user_media_requests_.erase(it);
+ stream_labels_.push_back(label);
+
+ user_media_request.requestSucceeded(source_vector);
+}
+
+void MediaStreamImpl::OnStreamGenerationFailed(int request_id) {
+ DCHECK(CalledOnValidThread());
+ DVLOG(1) << "MediaStreamImpl::OnStreamGenerationFailed("
+ << request_id << ")";
+ MediaRequestMap::iterator it = user_media_requests_.find(request_id);
+ if (it == user_media_requests_.end()) {
+ DVLOG(1) << "Request ID not found";
+ return;
+ }
+ WebKit::WebUserMediaRequest user_media_request = it->second;
+ user_media_requests_.erase(it);
+
+ user_media_request.requestFailed();
+}
+
+void MediaStreamImpl::OnVideoDeviceFailed(const std::string& label,
+ int index) {
+ DCHECK(CalledOnValidThread());
+ DVLOG(1) << "MediaStreamImpl::OnVideoDeviceFailed("
+ << label << ", " << index << ")";
+ // TODO(grunell): Implement. Currently not supported in WebKit.
+ NOTIMPLEMENTED();
+}
+
+void MediaStreamImpl::OnAudioDeviceFailed(const std::string& label,
+ int index) {
+ DCHECK(CalledOnValidThread());
+ DVLOG(1) << "MediaStreamImpl::OnAudioDeviceFailed("
+ << label << ", " << index << ")";
+ // TODO(grunell): Implement. Currently not supported in WebKit.
+ NOTIMPLEMENTED();
+}
+
+void MediaStreamImpl::InitializeWorkerThread(talk_base::Thread** thread,
+ base::WaitableEvent* event) {
+ jingle_glue::JingleThreadWrapper::EnsureForCurrentThread();
+ jingle_glue::JingleThreadWrapper::current()->set_send_allowed(true);
+ *thread = jingle_glue::JingleThreadWrapper::current();
+ event->Signal();
+}
+
+void MediaStreamImpl::DeleteIpcNetworkManager() {
+ DCHECK_EQ(MessageLoop::current(), chrome_worker_thread_.message_loop());
+ delete network_manager_;
+ network_manager_ = NULL;
+}

Modified: trunk/src/content/renderer/media/media_stream_impl.h
==============================================================================
--- trunk/src/content/renderer/media/media_stream_impl.h (original)
+++ trunk/src/content/renderer/media/media_stream_impl.h Thu Jan 12 07:03:51 2012
@@ -1,34 +1,168 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

-#ifndef CONTENT_RENDERER_MEDIA_STREAM_MEDIA_STREAM_IMPL_H_
-#define CONTENT_RENDERER_MEDIA_STREAM_MEDIA_STREAM_IMPL_H_
+#ifndef CONTENT_RENDERER_MEDIA_MEDIA_STREAM_IMPL_H_
+#define CONTENT_RENDERER_MEDIA_MEDIA_STREAM_IMPL_H_
+
+#include <list>
+#include <map>
+#include <string>

#include "base/basictypes.h"
+#include "base/compiler_specific.h"
+#include "base/gtest_prod_util.h"
#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/message_loop_proxy.h"
+#include "base/threading/non_thread_safe.h"
+#include "base/threading/thread.h"
+#include "content/common/content_export.h"
+#include "content/renderer/media/media_stream_dispatcher_eventhandler.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"

+namespace base {
+class WaitableEvent;
+}
+
+namespace content {
+class IpcNetworkManager;
+class IpcPacketSocketFactory;
+class P2PSocketDispatcher;
+}
+
+namespace cricket {
+class WebRtcMediaEngine;
+}
+
+namespace talk_base {
+class Thread;
+}
+
+namespace WebKit {
+class WebPeerConnectionHandler;
+class WebPeerConnectionHandlerClient;
+}
+
+class MediaStreamDispatcher;
+class MediaStreamDependencyFactory;
+class PeerConnectionHandler;
class VideoCaptureImplManager;
+class RTCVideoDecoder;

-// A implementation of StreamClient to provide supporting functions, such as
-// GetVideoDecoder.
-class MediaStreamImpl
- : public webkit_media::MediaStreamClient,
+// MediaStreamImpl is a delegate for the Media Stream API messages used by
+// WebKit. It ties together WebKit, native PeerConnection in libjingle and
+// MediaStreamManager (via MediaStreamDispatcher and MediaStreamDispatcherHost)
+// in the browser process. It must be created, called and destroyed on the
+// render thread.
+class CONTENT_EXPORT MediaStreamImpl
+ : NON_EXPORTED_BASE(public WebKit::WebUserMediaClient),
+ NON_EXPORTED_BASE(public webkit_media::MediaStreamClient),
+ public MediaStreamDispatcherEventHandler,
+ NON_EXPORTED_BASE(public base::NonThreadSafe),
public base::RefCountedThreadSafe<MediaStreamImpl> {
public:
- explicit MediaStreamImpl(VideoCaptureImplManager* vc_manager);
+ MediaStreamImpl(
+ MediaStreamDispatcher* media_stream_dispatcher,
+ content::P2PSocketDispatcher* p2p_socket_dispatcher,
+ VideoCaptureImplManager* vc_manager,
+ MediaStreamDependencyFactory* dependency_factory);
virtual ~MediaStreamImpl();

- // Implement webkit_media::StreamClient.
+ 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);
+
+ // WebKit::WebUserMediaClient implementation
+ virtual void requestUserMedia(
+ const WebKit::WebUserMediaRequest& user_media_request,
+ const WebKit::WebVector<WebKit::WebMediaStreamSource>&
+ media_stream_source_vector) OVERRIDE;
+ virtual void cancelUserMediaRequest(
+ const WebKit::WebUserMediaRequest& user_media_request) OVERRIDE;
+
+ // webkit_media::MediaStreamClient implementation.
virtual scoped_refptr<media::VideoDecoder> GetVideoDecoder(
const GURL& url,
media::MessageLoopFactory* message_loop_factory) OVERRIDE;

+ // MediaStreamDispatcherEventHandler implementation.
+ virtual void OnStreamGenerated(
+ int request_id,
+ const std::string& label,
+ const media_stream::StreamDeviceInfoArray& audio_array,
+ const media_stream::StreamDeviceInfoArray& video_array) OVERRIDE;
+ virtual void OnStreamGenerationFailed(int request_id) OVERRIDE;
+ virtual void OnVideoDeviceFailed(
+ const std::string& label,
+ int index) OVERRIDE;
+ virtual void OnAudioDeviceFailed(
+ const std::string& label,
+ int index) OVERRIDE;
+
private:
+ FRIEND_TEST_ALL_PREFIXES(MediaStreamImplTest, Basic);
+
+ void InitializeWorkerThread(
+ talk_base::Thread** thread,
+ base::WaitableEvent* event);
+ void DeleteIpcNetworkManager();
+
+ scoped_ptr<MediaStreamDependencyFactory> dependency_factory_;
+
+ // media_stream_dispatcher_ is a weak reference, owned by RenderView. It's
+ // 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_;
+
+ // We own network_manager_, must be deleted on the worker thread.
+ content::IpcNetworkManager* network_manager_;
+
+ scoped_ptr<content::IpcPacketSocketFactory> socket_factory_;
+
scoped_refptr<VideoCaptureImplManager> vc_manager_;

+ // peer_connection_handler_ is a weak reference, owned by WebKit. It's valid
+ // until stop is called on it (which will call ClosePeerConnection on us).
+ // TODO(grunell): Support several PeerConnectionsHandlers.
+ PeerConnectionHandler* peer_connection_handler_;
+
+ scoped_refptr<RTCVideoDecoder> rtc_video_decoder_;
+ scoped_refptr<base::MessageLoopProxy> message_loop_proxy_;
+
+ // PeerConnection threads. signaling_thread_ is created from the
+ // "current" chrome thread.
+ talk_base::Thread* signaling_thread_;
+ talk_base::Thread* worker_thread_;
+ base::Thread chrome_worker_thread_;
+
+ static int next_request_id_;
+ 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);
};

-#endif // CONTENT_RENDERER_MEDIA_STREAM_MEDIA_STREAM_IMPL_H_
+#endif // CONTENT_RENDERER_MEDIA_MEDIA_STREAM_IMPL_H_

Added: trunk/src/content/renderer/media/media_stream_impl_unittest.cc
==============================================================================
--- (empty file)
+++ trunk/src/content/renderer/media/media_stream_impl_unittest.cc Thu Jan 12 07:03:51 2012
@@ -0,0 +1,45 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/memory/scoped_ptr.h"
+#include "base/message_loop.h"
+#include "content/renderer/media/media_stream_impl.h"
+#include "content/renderer/media/mock_media_stream_dependency_factory.h"
+#include "content/renderer/media/mock_media_stream_dispatcher.h"
+#include "content/renderer/media/mock_web_peer_connection_handler_client.h"
+#include "content/renderer/media/video_capture_impl_manager.h"
+#include "content/renderer/p2p/socket_dispatcher.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebPeerConnectionHandler.h"
+
+TEST(MediaStreamImplTest, Basic) {
+ MessageLoop loop;
+
+ // Create our test object.
+ scoped_ptr<MockMediaStreamDispatcher> ms_dispatcher(
+ new MockMediaStreamDispatcher());
+ scoped_ptr<content::P2PSocketDispatcher> p2p_socket_dispatcher(
+ new content::P2PSocketDispatcher(NULL));
+ scoped_refptr<VideoCaptureImplManager> vc_manager(
+ new VideoCaptureImplManager());
+ MockMediaStreamDependencyFactory* dependency_factory =
+ new MockMediaStreamDependencyFactory();
+ scoped_refptr<MediaStreamImpl> ms_impl(new MediaStreamImpl(
+ ms_dispatcher.get(),
+ p2p_socket_dispatcher.get(),
+ vc_manager.get(),
+ dependency_factory));
+
+ // TODO(grunell): Add tests for WebKit::WebUserMediaClient and
+ // MediaStreamDispatcherEventHandler implementations.
+
+ WebKit::MockWebPeerConnectionHandlerClient client;
+ WebKit::WebPeerConnectionHandler* pc_handler =
+ ms_impl->CreatePeerConnectionHandler(&client);
+ EXPECT_TRUE(ms_impl->peer_connection_handler_);
+
+ ms_impl->ClosePeerConnection();
+ EXPECT_FALSE(ms_impl->peer_connection_handler_);
+ delete pc_handler;
+}

Added: trunk/src/content/renderer/media/mock_media_stream_dependency_factory.cc
==============================================================================
--- (empty file)
+++ trunk/src/content/renderer/media/mock_media_stream_dependency_factory.cc Thu Jan 12 07:03:51 2012
@@ -0,0 +1,50 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#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"
+
+MockMediaStreamDependencyFactory::MockMediaStreamDependencyFactory()
+ : mock_pc_factory_created_(false) {
+}
+
+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) {
+ mock_pc_factory_created_ = true;
+ media_engine_.reset(media_engine);
+ return true;
+}
+
+void MockMediaStreamDependencyFactory::DeletePeerConnectionFactory() {
+ mock_pc_factory_created_ = false;
+}
+
+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;
+}
+
+webrtc::PeerConnection* MockMediaStreamDependencyFactory::CreatePeerConnection(
+ cricket::PortAllocator* port_allocator,
+ talk_base::Thread* signaling_thread) {
+ DCHECK(mock_pc_factory_created_);
+ return new webrtc::MockPeerConnectionImpl();
+}

Added: trunk/src/content/renderer/media/mock_media_stream_dependency_factory.h
==============================================================================
--- (empty file)
+++ trunk/src/content/renderer/media/mock_media_stream_dependency_factory.h Thu Jan 12 07:03:51 2012
@@ -0,0 +1,39 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_RENDERER_MEDIA_MOCK_MEDIA_STREAM_DEPENDENCY_FACTORY_H_
+#define CONTENT_RENDERER_MEDIA_MOCK_MEDIA_STREAM_DEPENDENCY_FACTORY_H_
+
+#include "base/compiler_specific.h"
+#include "content/renderer/media/media_stream_dependency_factory.h"
+
+// 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(
+ 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;
+
+ private:
+ bool mock_pc_factory_created_;
+ scoped_ptr<cricket::MediaEngineInterface> media_engine_;
+
+ DISALLOW_COPY_AND_ASSIGN(MockMediaStreamDependencyFactory);
+};
+
+#endif // CONTENT_RENDERER_MEDIA_MOCK_MEDIA_STREAM_DEPENDENCY_FACTORY_H_

Added: trunk/src/content/renderer/media/mock_media_stream_dispatcher.cc
==============================================================================
--- (empty file)
+++ trunk/src/content/renderer/media/mock_media_stream_dispatcher.cc Thu Jan 12 07:03:51 2012
@@ -0,0 +1,49 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/renderer/media/mock_media_stream_dispatcher.h"
+
+MockMediaStreamDispatcher::MockMediaStreamDispatcher()
+ : MediaStreamDispatcher(NULL),
+ request_id_(-1),
+ event_handler_(NULL),
+ components_(NULL),
+ stop_stream_counter_(0) {
+}
+
+MockMediaStreamDispatcher::~MockMediaStreamDispatcher() {}
+
+void MockMediaStreamDispatcher::GenerateStream(
+ int request_id,
+ MediaStreamDispatcherEventHandler* event_handler,
+ media_stream::StreamOptions components,
+ const std::string& security_origin) {
+ request_id_ = request_id;
+ event_handler_ = event_handler;
+ delete components_;
+ components_ = new media_stream::StreamOptions(components.audio,
+ components.video_option);
+ security_origin_ = security_origin;
+}
+
+void MockMediaStreamDispatcher::StopStream(const std::string& label) {
+ ++stop_stream_counter_;
+}
+
+bool MockMediaStreamDispatcher::IsStream(const std::string& label) {
+ NOTIMPLEMENTED();
+ return false;
+}
+
+int MockMediaStreamDispatcher::video_session_id(const std::string& label,
+ int index) {
+ NOTIMPLEMENTED();
+ return -1;
+}
+
+int MockMediaStreamDispatcher::audio_session_id(const std::string& label,
+ int index) {
+ NOTIMPLEMENTED();
+ return -1;
+}

Added: trunk/src/content/renderer/media/mock_media_stream_dispatcher.h
==============================================================================
--- (empty file)
+++ trunk/src/content/renderer/media/mock_media_stream_dispatcher.h Thu Jan 12 07:03:51 2012
@@ -0,0 +1,45 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_RENDERER_MEDIA_MOCK_MEDIA_STREAM_DISPATCHER_H_
+#define CONTENT_RENDERER_MEDIA_MOCK_MEDIA_STREAM_DISPATCHER_H_
+
+#include <string>
+
+#include "content/renderer/media/media_stream_dispatcher.h"
+
+// This class is a mock implementation of MediaStreamDispatcher.
+class MockMediaStreamDispatcher : public MediaStreamDispatcher {
+ public:
+ MockMediaStreamDispatcher();
+ virtual ~MockMediaStreamDispatcher();
+
+ virtual void GenerateStream(int request_id,
+ MediaStreamDispatcherEventHandler* event_handler,
+ media_stream::StreamOptions components,
+ const std::string& security_origin) OVERRIDE;
+ virtual void StopStream(const std::string& label) OVERRIDE;
+ virtual bool IsStream(const std::string& label) OVERRIDE;
+ virtual int video_session_id(const std::string& label, int index) OVERRIDE;
+ virtual int audio_session_id(const std::string& label, int index) OVERRIDE;
+
+ int request_id() const { return request_id_; }
+ MediaStreamDispatcherEventHandler* event_handler() const {
+ return event_handler_;
+ }
+ media_stream::StreamOptions* components() const { return components_; }
+ const std::string& security_origin() const { return security_origin_; }
+ int stop_stream_counter() const { return stop_stream_counter_; }
+
+ private:
+ int request_id_;
+ MediaStreamDispatcherEventHandler* event_handler_;
+ media_stream::StreamOptions* components_;
+ std::string security_origin_;
+ int stop_stream_counter_;
+
+ DISALLOW_COPY_AND_ASSIGN(MockMediaStreamDispatcher);
+};
+
+#endif // CONTENT_RENDERER_MEDIA_MOCK_MEDIA_STREAM_DISPATCHER_H_

Added: trunk/src/content/renderer/media/mock_media_stream_impl.cc
==============================================================================
--- (empty file)
+++ trunk/src/content/renderer/media/mock_media_stream_impl.cc Thu Jan 12 07:03:51 2012
@@ -0,0 +1,60 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/renderer/media/mock_media_stream_impl.h"
+
+#include "content/renderer/media/rtc_video_decoder.h"
+
+MockMediaStreamImpl::MockMediaStreamImpl()
+ : MediaStreamImpl(NULL, NULL, NULL, NULL) {
+}
+
+MockMediaStreamImpl::~MockMediaStreamImpl() {}
+
+WebKit::WebPeerConnectionHandler*
+MockMediaStreamImpl::CreatePeerConnectionHandler(
+ WebKit::WebPeerConnectionHandlerClient* client) {
+ NOTIMPLEMENTED();
+ return NULL;
+}
+
+void MockMediaStreamImpl::ClosePeerConnection() {
+ video_label_.clear();
+}
+
+bool MockMediaStreamImpl::SetVideoCaptureModule(const std::string& label) {
+ video_label_ = label;
+ return true;
+}
+
+scoped_refptr<media::VideoDecoder> MockMediaStreamImpl::GetVideoDecoder(
+ const GURL& url,
+ media::MessageLoopFactory* message_loop_factory) {
+ NOTIMPLEMENTED();
+ return NULL;
+}
+
+void MockMediaStreamImpl::OnStreamGenerated(
+ int request_id,
+ const std::string& label,
+ const media_stream::StreamDeviceInfoArray& audio_array,
+ const media_stream::StreamDeviceInfoArray& video_array) {
+ NOTIMPLEMENTED();
+}
+
+void MockMediaStreamImpl::OnStreamGenerationFailed(int request_id) {
+ NOTIMPLEMENTED();
+}
+
+void MockMediaStreamImpl::OnVideoDeviceFailed(
+ const std::string& label,
+ int index) {
+ NOTIMPLEMENTED();
+}
+
+void MockMediaStreamImpl::OnAudioDeviceFailed(
+ const std::string& label,
+ int index) {
+ NOTIMPLEMENTED();
+}

Added: trunk/src/content/renderer/media/mock_media_stream_impl.h
==============================================================================
--- (empty file)
+++ trunk/src/content/renderer/media/mock_media_stream_impl.h Thu Jan 12 07:03:51 2012
@@ -0,0 +1,50 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_RENDERER_MEDIA_MOCK_MEDIA_STREAM_IMPL_H_
+#define CONTENT_RENDERER_MEDIA_MOCK_MEDIA_STREAM_IMPL_H_
+
+#include <string>
+
+#include "content/renderer/media/media_stream_impl.h"
+
+class MockMediaStreamImpl : public MediaStreamImpl {
+ public:
+ MockMediaStreamImpl();
+ virtual ~MockMediaStreamImpl();
+
+ 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;
+
+ // Implement webkit_glue::MediaStreamClient.
+ virtual scoped_refptr<media::VideoDecoder> GetVideoDecoder(
+ const GURL& url,
+ media::MessageLoopFactory* message_loop_factory) OVERRIDE;
+
+ // Implement MediaStreamDispatcherEventHandler.
+ virtual void OnStreamGenerated(
+ int request_id,
+ const std::string& label,
+ const media_stream::StreamDeviceInfoArray& audio_array,
+ const media_stream::StreamDeviceInfoArray& video_array) OVERRIDE;
+ virtual void OnStreamGenerationFailed(int request_id) OVERRIDE;
+ virtual void OnVideoDeviceFailed(
+ const std::string& label,
+ int index) OVERRIDE;
+ virtual void OnAudioDeviceFailed(
+ const std::string& label,
+ int index) OVERRIDE;
+
+ const std::string& video_label() const { return video_label_; }
+
+ private:
+ std::string video_label_;
+
+ DISALLOW_COPY_AND_ASSIGN(MockMediaStreamImpl);
+};
+
+#endif // CONTENT_RENDERER_MEDIA_MOCK_MEDIA_STREAM_IMPL_H_

Added: trunk/src/content/renderer/media/mock_peer_connection_impl.cc
==============================================================================
--- (empty file)
+++ trunk/src/content/renderer/media/mock_peer_connection_impl.cc Thu Jan 12 07:03:51 2012
@@ -0,0 +1,91 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/renderer/media/mock_peer_connection_impl.h"
+
+#include "base/logging.h"
+
+namespace webrtc {
+
+MockPeerConnectionImpl::MockPeerConnectionImpl()
+ : observer_(NULL),
+ video_stream_(false),
+ connected_(false),
+ video_capture_set_(false) {
+}
+
+MockPeerConnectionImpl::~MockPeerConnectionImpl() {}
+
+void MockPeerConnectionImpl::RegisterObserver(
+ PeerConnectionObserver* observer) {
+ observer_ = observer;
+}
+
+bool MockPeerConnectionImpl::SignalingMessage(
+ const std::string& signaling_message) {
+ signaling_message_ = signaling_message;
+ return true;
+}
+
+bool MockPeerConnectionImpl::AddStream(
+ const std::string& stream_id,
+ bool video) {
+ stream_id_ = stream_id;
+ video_stream_ = video;
+ return true;
+}
+
+bool MockPeerConnectionImpl::RemoveStream(const std::string& stream_id) {
+ stream_id_.clear();
+ video_stream_ = false;
+ return true;
+}
+
+bool MockPeerConnectionImpl::Connect() {
+ connected_ = true;
+ return true;
+}
+
+bool MockPeerConnectionImpl::Close() {
+ observer_ = NULL;
+ signaling_message_.clear();
+ stream_id_.clear();
+ video_stream_ = false;
+ connected_ = false;
+ video_capture_set_ = false;
+ return true;
+}
+
+bool MockPeerConnectionImpl::SetAudioDevice(
+ const std::string& wave_in_device,
+ const std::string& wave_out_device,
+ int opts) {
+ NOTIMPLEMENTED();
+ return false;
+}
+
+bool MockPeerConnectionImpl::SetLocalVideoRenderer(
+ cricket::VideoRenderer* renderer) {
+ NOTIMPLEMENTED();
+ return false;
+}
+
+bool MockPeerConnectionImpl::SetVideoRenderer(
+ const std::string& stream_id,
+ cricket::VideoRenderer* renderer) {
+ video_renderer_stream_id_ = stream_id;
+ return true;
+}
+
+bool MockPeerConnectionImpl::SetVideoCapture(const std::string& cam_device) {
+ video_capture_set_ = true;
+ return true;
+}
+
+MockPeerConnectionImpl::ReadyState MockPeerConnectionImpl::GetReadyState() {
+ NOTIMPLEMENTED();
+ return NEW;
+}
+
+} // namespace webrtc

Added: trunk/src/content/renderer/media/mock_peer_connection_impl.h
==============================================================================
--- (empty file)
+++ trunk/src/content/renderer/media/mock_peer_connection_impl.h Thu Jan 12 07:03:51 2012
@@ -0,0 +1,62 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_RENDERER_MEDIA_MOCK_PEER_CONNECTION_IMPL_H_
+#define CONTENT_RENDERER_MEDIA_MOCK_PEER_CONNECTION_IMPL_H_
+
+#include <string>
+
+#include "base/basictypes.h"
+#include "base/compiler_specific.h"
+#include "third_party/libjingle/source/talk/app/webrtc/peerconnection.h"
+
+namespace webrtc {
+
+class MockPeerConnectionImpl : public PeerConnection {
+ 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_; }
+ 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_;
+ }
+
+ 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_;
+
+ DISALLOW_COPY_AND_ASSIGN(MockPeerConnectionImpl);
+};
+
+} // namespace webrtc
+
+#endif // CONTENT_RENDERER_MEDIA_MOCK_PEER_CONNECTION_IMPL_H_

Added: trunk/src/content/renderer/media/mock_web_peer_connection_handler_client.cc
==============================================================================
--- (empty file)
+++ trunk/src/content/renderer/media/mock_web_peer_connection_handler_client.cc Thu Jan 12 07:03:51 2012
@@ -0,0 +1,38 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/logging.h"
+#include "base/utf_string_conversions.h"
+#include "content/renderer/media/mock_web_peer_connection_handler_client.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebMediaStreamDescriptor.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebString.h"
+
+namespace WebKit {
+
+MockWebPeerConnectionHandlerClient::MockWebPeerConnectionHandlerClient() {}
+
+MockWebPeerConnectionHandlerClient::~MockWebPeerConnectionHandlerClient() {}
+
+void MockWebPeerConnectionHandlerClient::didCompleteICEProcessing() {}
+
+void MockWebPeerConnectionHandlerClient::didGenerateSDP(const WebString& sdp) {
+ sdp_ = UTF16ToUTF8(sdp);
+}
+
+void MockWebPeerConnectionHandlerClient::didReceiveDataStreamMessage(
+ const char* data, size_t length) {
+}
+
+void MockWebPeerConnectionHandlerClient::didAddRemoteStream(
+ const WebMediaStreamDescriptor& stream_descriptor) {
+ stream_label_ = UTF16ToUTF8(stream_descriptor.label());
+}
+
+void MockWebPeerConnectionHandlerClient::didRemoveRemoteStream(
+ const WebMediaStreamDescriptor& stream_descriptor) {
+ DCHECK(stream_label_ == UTF16ToUTF8(stream_descriptor.label()));
+ stream_label_.clear();
+}
+
+} // namespace WebKit

Added: trunk/src/content/renderer/media/mock_web_peer_connection_handler_client.h
==============================================================================
--- (empty file)
+++ trunk/src/content/renderer/media/mock_web_peer_connection_handler_client.h Thu Jan 12 07:03:51 2012
@@ -0,0 +1,42 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_RENDERER_MEDIA_MOCK_WEB_PEER_CONNECTION_HANDLER_CLIENT_H_
+#define CONTENT_RENDERER_MEDIA_MOCK_WEB_PEER_CONNECTION_HANDLER_CLIENT_H_
+
+#include <string>
+
+#include "base/basictypes.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebPeerConnectionHandlerClient.h"
+
+namespace WebKit {
+
+class MockWebPeerConnectionHandlerClient
+ : public WebPeerConnectionHandlerClient {
+ public:
+ MockWebPeerConnectionHandlerClient();
+ virtual ~MockWebPeerConnectionHandlerClient();
+
+ // WebPeerConnectionHandlerClient implementation.
+ virtual void didCompleteICEProcessing();
+ virtual void didGenerateSDP(const WebString& sdp);
+ virtual void didReceiveDataStreamMessage(const char* data, size_t length);
+ virtual void didAddRemoteStream(
+ const WebMediaStreamDescriptor& stream_descriptor);
+ virtual void didRemoveRemoteStream(
+ const WebMediaStreamDescriptor& stream_descriptor);
+
+ const std::string& stream_label() { return stream_label_; }
+ const std::string& sdp() const { return sdp_; }
+
+ private:
+ std::string stream_label_;
+ std::string sdp_;
+
+ DISALLOW_COPY_AND_ASSIGN(MockWebPeerConnectionHandlerClient);
+};
+
+} // namespace WebKit
+
+#endif // CONTENT_RENDERER_MEDIA_MOCK_WEB_PEER_CONNECTION_HANDLER_CLIENT_H_

Added: trunk/src/content/renderer/media/peer_connection_handler.cc
==============================================================================
--- (empty file)
+++ trunk/src/content/renderer/media/peer_connection_handler.cc Thu Jan 12 07:03:51 2012
@@ -0,0 +1,274 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/renderer/media/peer_connection_handler.h"
+
+#include <stdlib.h>
+#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"
+#include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebVector.h"
+
+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)
+ : 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) {
+}
+
+PeerConnectionHandler::~PeerConnectionHandler() {
+ if (native_peer_connection_.get()) {
+ native_peer_connection_->RegisterObserver(NULL);
+ native_peer_connection_->Close();
+ }
+}
+
+bool PeerConnectionHandler::SetVideoRenderer(
+ const std::string& stream_label,
+ cricket::VideoRenderer* renderer) {
+ return native_peer_connection_->SetVideoRenderer(stream_label, renderer);
+}
+
+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);
+}
+
+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);
+}
+
+void PeerConnectionHandler::handleInitialOffer(const WebKit::WebString& sdp) {
+ native_peer_connection_->SignalingMessage(UTF16ToUTF8(sdp));
+}
+
+void PeerConnectionHandler::processSDP(const WebKit::WebString& sdp) {
+ native_peer_connection_->SignalingMessage(UTF16ToUTF8(sdp));
+}
+
+void PeerConnectionHandler::processPendingStreams(
+ const WebKit::WebVector<WebKit::WebMediaStreamDescriptor>&
+ 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.
+}
+
+void PeerConnectionHandler::sendDataStreamMessage(
+ const char* data,
+ size_t length) {
+ // TODO(grunell): Implement. Not supported in native PeerConnection.
+ NOTIMPLEMENTED();
+}
+
+void PeerConnectionHandler::stop() {
+ if (native_peer_connection_.get())
+ native_peer_connection_->RegisterObserver(NULL);
+ native_peer_connection_.reset();
+ // The close function will delete us.
+ media_stream_impl_->ClosePeerConnection();
+}
+
+void PeerConnectionHandler::OnSignalingMessage(const std::string& msg) {
+ if (!message_loop_proxy_->BelongsToCurrentThread()) {
+ message_loop_proxy_->PostTask(FROM_HERE, base::Bind(
+ &PeerConnectionHandler::OnSignalingMessage,
+ base::Unretained(this),
+ msg));
+ return;
+ }
+ client_->didGenerateSDP(UTF8ToUTF16(msg));
+}
+
+void PeerConnectionHandler::OnAddStream(const std::string& stream_id,
+ bool video) {
+ if (!video)
+ return;
+
+ if (!message_loop_proxy_->BelongsToCurrentThread()) {
+ message_loop_proxy_->PostTask(FROM_HERE, base::Bind(
+ &PeerConnectionHandler::OnAddStreamCallback,
+ base::Unretained(this),
+ stream_id));
+ } else {
+ OnAddStreamCallback(stream_id);
+ }
+}
+
+void PeerConnectionHandler::OnRemoveStream(
+ const std::string& stream_id,
+ bool video) {
+ if (!video)
+ return;
+
+ if (!message_loop_proxy_->BelongsToCurrentThread()) {
+ message_loop_proxy_->PostTask(FROM_HERE, base::Bind(
+ &PeerConnectionHandler::OnRemoveStreamCallback,
+ base::Unretained(this),
+ remote_label_));
+ } else {
+ OnRemoveStreamCallback(remote_label_);
+ }
+}
+
+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::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;
+ }
+
+ // 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);
+ client_->didAddRemoteStream(descriptor);
+}
+
+void PeerConnectionHandler::OnRemoveStreamCallback(
+ const std::string& stream_label) {
+ // TODO(grunell): Support several 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"));
+ WebKit::WebMediaStreamDescriptor descriptor;
+ descriptor.initialize(UTF8ToUTF16(stream_label), source_vector);
+ client_->didRemoveRemoteStream(descriptor);
+}

Added: trunk/src/content/renderer/media/peer_connection_handler.h
==============================================================================
--- (empty file)
+++ trunk/src/content/renderer/media/peer_connection_handler.h Thu Jan 12 07:03:51 2012
@@ -0,0 +1,160 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_RENDERER_MEDIA_PEER_CONNECTION_HANDLER_H_
+#define CONTENT_RENDERER_MEDIA_PEER_CONNECTION_HANDLER_H_
+
+#include <string>
+
+#include "base/basictypes.h"
+#include "base/compiler_specific.h"
+#include "base/gtest_prod_util.h"
+#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/webrtc/peerconnection.h"
+#include "third_party/libjingle/source/talk/base/socketaddress.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.
+class CONTENT_EXPORT PeerConnectionHandler
+ : NON_EXPORTED_BASE(public WebKit::WebPeerConnectionHandler),
+ NON_EXPORTED_BASE(public webrtc::PeerConnectionObserver) {
+ public:
+ 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);
+ virtual ~PeerConnectionHandler();
+
+ // Set the video renderer for the specified stream.
+ virtual bool SetVideoRenderer(const std::string& stream_label,
+ cricket::VideoRenderer* renderer);
+
+ // WebKit::WebPeerConnectionHandler implementation
+ virtual void initialize(
+ const WebKit::WebString& server_configuration,
+ const WebKit::WebSecurityOrigin& security_origin) OVERRIDE;
+ virtual void produceInitialOffer(
+ const WebKit::WebVector<WebKit::WebMediaStreamDescriptor>&
+ pending_add_streams) OVERRIDE;
+ virtual void handleInitialOffer(const WebKit::WebString& sdp) OVERRIDE;
+ virtual void processSDP(const WebKit::WebString& sdp) OVERRIDE;
+ virtual void processPendingStreams(
+ const WebKit::WebVector<WebKit::WebMediaStreamDescriptor>&
+ pending_add_streams,
+ const WebKit::WebVector<WebKit::WebMediaStreamDescriptor>&
+ pending_remove_streams) OVERRIDE;
+ virtual void sendDataStreamMessage(const char* data, size_t length) OVERRIDE;
+ virtual void stop() OVERRIDE;
+
+ // webrtc::PeerConnectionObserver implementation
+ 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;
+
+ 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);
+
+ // client_ is a weak pointer, and is valid until stop() has returned.
+ WebKit::WebPeerConnectionHandlerClient* client_;
+
+ // media_stream_impl_ is a weak pointer, and is valid for the lifetime of this
+ // class. Calls to it must be done on the render thread.
+ MediaStreamImpl* media_stream_impl_;
+
+ // dependency_factory_ is a weak pointer, and is valid for the lifetime of
+ // MediaStreamImpl.
+ MediaStreamDependencyFactory* dependency_factory_;
+
+ // native_peer_connection_ is the native PeerConnection object,
+ // it handles the ICE processing and media engine.
+ scoped_ptr<webrtc::PeerConnection> native_peer_connection_;
+
+ scoped_refptr<base::MessageLoopProxy> message_loop_proxy_;
+
+ 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_;
+
+ DISALLOW_COPY_AND_ASSIGN(PeerConnectionHandler);
+};
+
+#endif // CONTENT_RENDERER_MEDIA_PEER_CONNECTION_HANDLER_H_

Added: trunk/src/content/renderer/media/peer_connection_handler_unittest.cc
==============================================================================
--- (empty file)
+++ trunk/src/content/renderer/media/peer_connection_handler_unittest.cc Thu Jan 12 07:03:51 2012
@@ -0,0 +1,124 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <string>
+
+#include "base/memory/scoped_ptr.h"
+#include "base/message_loop.h"
+#include "base/utf_string_conversions.h"
+#include "content/renderer/media/mock_media_stream_dependency_factory.h"
+#include "content/renderer/media/mock_media_stream_impl.h"
+#include "content/renderer/media/mock_web_peer_connection_handler_client.h"
+#include "content/renderer/media/mock_peer_connection_impl.h"
+#include "content/renderer/media/peer_connection_handler.h"
+#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/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"
+
+TEST(PeerConnectionHandlerTest, Basic) {
+ MessageLoop loop;
+
+ scoped_ptr<WebKit::MockWebPeerConnectionHandlerClient> mock_client(
+ new WebKit::MockWebPeerConnectionHandlerClient());
+ scoped_refptr<MockMediaStreamImpl> mock_ms_impl(new MockMediaStreamImpl());
+ scoped_ptr<MockMediaStreamDependencyFactory> mock_dependency_factory(
+ new MockMediaStreamDependencyFactory());
+ mock_dependency_factory->CreatePeerConnectionFactory(NULL, NULL);
+ scoped_ptr<PeerConnectionHandler> pc_handler(
+ new PeerConnectionHandler(mock_client.get(),
+ mock_ms_impl.get(),
+ mock_dependency_factory.get(),
+ NULL,
+ NULL,
+ NULL,
+ NULL));
+
+ WebKit::WebString server_config(
+ WebKit::WebString::fromUTF8("STUN stun.l.google.com:19302"));
+ WebKit::WebSecurityOrigin security_origin;
+ pc_handler->initialize(server_config, security_origin);
+ EXPECT_TRUE(pc_handler->native_peer_connection_.get());
+ 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");
+ WebKit::WebVector<WebKit::WebMediaStreamSource> source_vector(
+ static_cast<size_t>(1));
+ source_vector[0].initialize(WebKit::WebString::fromUTF8(label),
+ WebKit::WebMediaStreamSource::TypeVideo,
+ WebKit::WebString::fromUTF8("RemoteVideo"));
+ WebKit::WebVector<WebKit::WebMediaStreamDescriptor> pendingAddStreams(
+ 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());
+
+ std::string message("message1");
+ pc_handler->handleInitialOffer(WebKit::WebString::fromUTF8(message));
+ EXPECT_EQ(message, mock_peer_connection->signaling_message());
+
+ message = "message2";
+ pc_handler->processSDP(WebKit::WebString::fromUTF8(message));
+ EXPECT_EQ(message, mock_peer_connection->signaling_message());
+
+ message = "message3";
+ 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());
+
+ pc_handler->OnRemoveStream(remote_label, true);
+ EXPECT_TRUE(mock_client->stream_label().empty());
+
+ 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();
+}

Modified: trunk/src/content/renderer/p2p/socket_dispatcher.h
==============================================================================
--- trunk/src/content/renderer/p2p/socket_dispatcher.h (original)
+++ trunk/src/content/renderer/p2p/socket_dispatcher.h Thu Jan 12 07:03:51 2012
@@ -1,4 +1,4 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

@@ -26,6 +26,7 @@
#include "base/id_map.h"
#include "base/observer_list_threadsafe.h"
#include "base/synchronization/lock.h"
+#include "content/common/content_export.h"
#include "content/common/p2p_sockets.h"
#include "content/public/renderer/render_view_observer.h"
#include "net/base/net_util.h"
@@ -48,7 +49,7 @@
// P2PSocketDispatcher works on the renderer thread. It dispatches all
// messages on that thread, and all its methods must be called on the
// same thread.
-class P2PSocketDispatcher : public content::RenderViewObserver {
+class CONTENT_EXPORT P2PSocketDispatcher : public content::RenderViewObserver {
public:
class NetworkListObserver {
public:

Modified: trunk/src/content/renderer/render_view_impl.cc
==============================================================================
--- trunk/src/content/renderer/render_view_impl.cc (original)
+++ trunk/src/content/renderer/render_view_impl.cc Thu Jan 12 07:03:51 2012
@@ -59,6 +59,8 @@
#include "content/renderer/load_progress_tracker.h"
#include "content/renderer/media/audio_message_filter.h"
#include "content/renderer/media/audio_renderer_impl.h"
+#include "content/renderer/media/media_stream_dependency_factory.h"
+#include "content/renderer/media/media_stream_dispatcher.h"
#include "content/renderer/media/media_stream_impl.h"
#include "content/renderer/media/render_media_log.h"
#include "content/renderer/mhtml_generator.h"
@@ -118,12 +120,15 @@
#include "third_party/WebKit/Source/WebKit/chromium/public/WebSettings.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/WebStorageNamespace.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/WebStorageQuotaCallbacks.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebUserMediaClient.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/WebView.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/WebWindowFeatures.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebCString.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebDragData.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebGraphicsContext3D.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebImage.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebPeerConnectionHandler.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebPeerConnectionHandlerClient.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebPoint.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebRect.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebSize.h"
@@ -360,6 +365,7 @@
geolocation_dispatcher_(NULL),
speech_input_dispatcher_(NULL),
device_orientation_dispatcher_(NULL),
+ media_stream_dispatcher_(NULL),
p2p_socket_dispatcher_(NULL),
devtools_agent_(NULL),
renderer_accessibility_(NULL),
@@ -421,7 +427,8 @@
host_window_ = parent_hwnd;

#if defined(ENABLE_P2P_APIS)
- p2p_socket_dispatcher_ = new content::P2PSocketDispatcher(this);
+ if (!p2p_socket_dispatcher_)
+ p2p_socket_dispatcher_ = new content::P2PSocketDispatcher(this);
#endif

new MHTMLGenerator(this);
@@ -435,12 +442,6 @@

new IdleUserDetector(this);

- const CommandLine& command_line = *CommandLine::ForCurrentProcess();
- if (command_line.HasSwitch(switches::kEnableMediaStream)) {
- media_stream_impl_ = new MediaStreamImpl(
- RenderThreadImpl::current()->video_capture_impl_manager());
- }
-
content::GetContentClient()->renderer()->RenderViewCreated(this);
}

@@ -476,6 +477,10 @@
DCHECK_NE(this, it->second) << "Failed to call Close?";
#endif

+ // MediaStreamImpl holds weak references to RenderViewObserver objects,
+ // ensure it's deleted before the observers.
+ media_stream_impl_ = NULL;
+
FOR_EACH_OBSERVER(RenderViewObserver, observers_, RenderViewGone());
FOR_EACH_OBSERVER(RenderViewObserver, observers_, OnDestruct());
}
@@ -526,6 +531,15 @@
next_page_id); // adds reference
}

+WebKit::WebPeerConnectionHandler* RenderViewImpl::CreatePeerConnectionHandler(
+ WebKit::WebPeerConnectionHandlerClient* client) {
+ const CommandLine* cmd_line = CommandLine::ForCurrentProcess();
+ if (!cmd_line->HasSwitch(switches::kEnableMediaStream))
+ return NULL;
+ EnsureMediaStreamImpl();
+ return media_stream_impl_->CreatePeerConnectionHandler(client);
+}
+
void RenderViewImpl::AddObserver(RenderViewObserver* observer) {
observers_.AddObserver(observer);
}
@@ -2982,6 +2996,25 @@
preferred_size_));
}

+void RenderViewImpl::EnsureMediaStreamImpl() {
+#if defined(ENABLE_P2P_APIS)
+ if (!p2p_socket_dispatcher_)
+ p2p_socket_dispatcher_ = new content::P2PSocketDispatcher(this);
+#endif
+
+ if (!media_stream_dispatcher_)
+ media_stream_dispatcher_ = new MediaStreamDispatcher(this);
+
+ if (!media_stream_impl_.get()) {
+ MediaStreamDependencyFactory* factory = new MediaStreamDependencyFactory();
+ media_stream_impl_ = new MediaStreamImpl(
+ media_stream_dispatcher_,
+ p2p_socket_dispatcher_,
+ RenderThreadImpl::current()->video_capture_impl_manager(),
+ factory);
+ }
+}
+
void RenderViewImpl::didChangeContentsSize(WebFrame* frame,
const WebSize& size) {
if (webview()->mainFrame() != frame)
@@ -4710,6 +4743,14 @@
return current_state;
}

+WebKit::WebUserMediaClient* RenderViewImpl::userMediaClient() {
+ const CommandLine* cmd_line = CommandLine::ForCurrentProcess();
+ if (!cmd_line->HasSwitch(switches::kEnableMediaStream))
+ return NULL;
+ EnsureMediaStreamImpl();
+ return media_stream_impl_;
+}
+
bool RenderViewImpl::IsNonLocalTopLevelNavigation(
const GURL& url, WebKit::WebFrame* frame, WebKit::WebNavigationType type) {
// Must be a top level frame.

Modified: trunk/src/content/renderer/render_view_impl.h
==============================================================================
--- trunk/src/content/renderer/render_view_impl.h (original)
+++ trunk/src/content/renderer/render_view_impl.h Thu Jan 12 07:03:51 2012
@@ -64,6 +64,7 @@
class GURL;
class JavaBridgeDispatcher;
class LoadProgressTracker;
+class MediaStreamDispatcher;
class MediaStreamImpl;
class NotificationProvider;
class PepperDeviceTest;
@@ -118,12 +119,15 @@
class WebMediaPlayer;
class WebMediaPlayerClient;
class WebMouseEvent;
+class WebPeerConnectionHandler;
+class WebPeerConnectionHandlerClient;
class WebSpeechInputController;
class WebSpeechInputListener;
class WebStorageNamespace;
class WebTouchEvent;
class WebURLLoader;
class WebURLRequest;
+class WebUserMediaClient;
struct WebFileChooserParams;
struct WebFindOptions;
struct WebMediaPlayerAction;
@@ -198,11 +202,18 @@
send_content_state_immediately_ = value;
}

+ MediaStreamDispatcher* media_stream_dispatcher() {
+ return media_stream_dispatcher_;
+ }
+
// Current P2PSocketDispatcher. Set to NULL if P2P API is disabled.
content::P2PSocketDispatcher* p2p_socket_dispatcher() {
return p2p_socket_dispatcher_;
}

+ WebKit::WebPeerConnectionHandler* CreatePeerConnectionHandler(
+ WebKit::WebPeerConnectionHandlerClient* client);
+
// Functions to add and remove observers for this object.
void AddObserver(content::RenderViewObserver* observer);
void RemoveObserver(content::RenderViewObserver* observer);
@@ -383,6 +394,7 @@
const WebKit::WebString& url,
const WebKit::WebString& title);
virtual WebKit::WebPageVisibilityState visibilityState() const;
+ virtual WebKit::WebUserMediaClient* userMediaClient();

// WebKit::WebFrameClient implementation -------------------------------------

@@ -868,6 +880,8 @@
// Check whether the preferred size has changed.
void CheckPreferredSize();

+ void EnsureMediaStreamImpl();
+
// This callback is triggered when DownloadFavicon completes, either
// succesfully or with a failure. See DownloadFavicon for more
// details.
@@ -1129,6 +1143,9 @@
// Device orientation dispatcher attached to this view; lazily initialized.
DeviceOrientationDispatcher* device_orientation_dispatcher_;

+ // MediaStream dispatcher attached to this view; lazily initialized.
+ MediaStreamDispatcher* media_stream_dispatcher_;
+
// MediaStreamImpl attached to this view; lazily initialized.
scoped_refptr<MediaStreamImpl> media_stream_impl_;

Modified: trunk/src/content/renderer/renderer_webkitplatformsupport_impl.cc
==============================================================================
--- trunk/src/content/renderer/renderer_webkitplatformsupport_impl.cc (original)
+++ trunk/src/content/renderer/renderer_webkitplatformsupport_impl.cc Thu Jan 12 07:03:51 2012
@@ -1,4 +1,4 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

@@ -26,6 +26,7 @@
#include "content/renderer/media/audio_device.h"
#include "content/renderer/media/audio_hardware.h"
#include "content/renderer/render_thread_impl.h"
+#include "content/renderer/render_view_impl.h"
#include "content/renderer/renderer_clipboard_client.h"
#include "content/renderer/renderer_webaudiodevice_impl.h"
#include "content/renderer/renderer_webstoragenamespace_impl.h"
@@ -39,6 +40,9 @@
#include "third_party/WebKit/Source/WebKit/chromium/public/WebIDBFactory.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/WebIDBKey.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/WebIDBKeyPath.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebPeerConnectionHandler.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebPeerConnectionHandlerClient.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebRuntimeFeatures.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebSerializedScriptValue.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/WebStorageEventDispatcher.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebURL.h"
@@ -643,3 +647,17 @@
RenderThreadImpl::current()->Send(
new ViewHostMsg_GetPlugins(refresh, plugins));
}
+
+//------------------------------------------------------------------------------
+
+WebKit::WebPeerConnectionHandler*
+RendererWebKitPlatformSupportImpl::createPeerConnectionHandler(
+ WebKit::WebPeerConnectionHandlerClient* client) {
+ WebFrame* web_frame = WebFrame::frameForCurrentContext();
+ if (!web_frame)
+ return NULL;
+ RenderViewImpl* render_view = RenderViewImpl::FromWebView(web_frame->view());
+ if (!render_view)
+ return NULL;
+ return render_view->CreatePeerConnectionHandler(client);
+}

Modified: trunk/src/content/renderer/renderer_webkitplatformsupport_impl.h
==============================================================================
--- trunk/src/content/renderer/renderer_webkitplatformsupport_impl.h (original)
+++ trunk/src/content/renderer/renderer_webkitplatformsupport_impl.h Thu Jan 12 07:03:51 2012
@@ -1,4 +1,4 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

@@ -92,6 +92,8 @@
virtual WebKit::WebString userAgent(const WebKit::WebURL& url) OVERRIDE;
virtual void GetPlugins(bool refresh,
std::vector<webkit::WebPluginInfo>* plugins) OVERRIDE;
+ virtual WebKit::WebPeerConnectionHandler* createPeerConnectionHandler(
+ WebKit::WebPeerConnectionHandlerClient* client) OVERRIDE;

private:
bool CheckPreparsedJsCachingEnabled() const;

Reply all
Reply to author
Forward
0 new messages