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

Unified Diff: content/renderer/pepper_plugin_delegate_impl.cc

Issue 9234064: Implement device enumeration for PPB_VideoCapture_Dev. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Change interface and move shared code into shared_impl. Created 8 years, 10 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/pepper_plugin_delegate_impl.cc
diff --git a/content/renderer/pepper_plugin_delegate_impl.cc b/content/renderer/pepper_plugin_delegate_impl.cc
index ffc7fc1960c0092dbff193f32dd4a6e2e3198cf1..c166db0608f142a128da03e3d3c9ff6f2082cb2a 100644
--- a/content/renderer/pepper_plugin_delegate_impl.cc
+++ b/content/renderer/pepper_plugin_delegate_impl.cc
@@ -5,6 +5,7 @@
#include "content/renderer/pepper_plugin_delegate_impl.h"
#include <cmath>
+#include <map>
#include <queue>
#include "base/bind.h"
@@ -13,8 +14,6 @@
#include "base/file_path.h"
#include "base/file_util_proxy.h"
#include "base/logging.h"
-#include "base/memory/scoped_ptr.h"
-#include "base/memory/weak_ptr.h"
#include "base/string_split.h"
#include "base/sync_socket.h"
#include "base/time.h"
@@ -38,6 +37,8 @@
#include "content/renderer/gpu/webgraphicscontext3d_command_buffer_impl.h"
#include "content/renderer/media/audio_input_message_filter.h"
#include "content/renderer/media/audio_message_filter.h"
+#include "content/renderer/media/media_stream_dispatcher.h"
+#include "content/renderer/media/media_stream_dispatcher_eventhandler.h"
#include "content/renderer/media/video_capture_impl_manager.h"
#include "content/renderer/p2p/p2p_transport_impl.h"
#include "content/renderer/pepper_platform_context_3d_impl.h"
@@ -55,6 +56,7 @@
#include "ppapi/c/private/ppb_flash_net_connector.h"
#include "ppapi/proxy/host_dispatcher.h"
#include "ppapi/proxy/ppapi_messages.h"
+#include "ppapi/shared_impl/ppb_device_ref_shared.h"
#include "ppapi/shared_impl/platform_file.h"
#include "ppapi/shared_impl/ppapi_preferences.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/WebCursorInfo.h"
@@ -587,62 +589,257 @@ class QuotaCallbackTranslator : public QuotaDispatcher::Callback {
};
class PlatformVideoCaptureImpl
brettw 2012/02/10 23:46:23 Do you think you can move this to its own file? It
yzshen1 2012/02/13 20:55:41 Done.
- : public webkit::ppapi::PluginDelegate::PlatformVideoCapture {
+ : public webkit::ppapi::PluginDelegate::PlatformVideoCapture,
+ public media::VideoCapture::EventHandler {
public:
- PlatformVideoCaptureImpl(media::VideoCapture::EventHandler* handler)
- : handler_proxy_(new media::VideoCaptureHandlerProxy(
- handler, base::MessageLoopProxy::current())) {
- VideoCaptureImplManager* manager =
- RenderThreadImpl::current()->video_capture_impl_manager();
- // 1 means the "default" video capture device.
- // TODO(piman): Add a way to enumerate devices and pass them through the
- // API.
- video_capture_ = manager->AddDevice(1, handler_proxy_.get());
+ PlatformVideoCaptureImpl(
+ const base::WeakPtr<PepperPluginDelegateImpl>& plugin_delegate,
+ const std::string& device_id,
+ webkit::ppapi::PluginDelegate::PlatformVideoCaptureEventHandler* handler);
+ virtual ~PlatformVideoCaptureImpl();
+
+ // webkit::ppapi::PluginDelegate::PlatformVideoCapture implementation.
+ virtual void StartCapture(EventHandler* handler,
+ const VideoCaptureCapability& capability) OVERRIDE;
+ virtual void StopCapture(EventHandler* handler) OVERRIDE;
+ virtual void FeedBuffer(scoped_refptr<VideoFrameBuffer> buffer) OVERRIDE;
+ virtual bool CaptureStarted() OVERRIDE;
+ virtual int CaptureWidth() OVERRIDE;
+ virtual int CaptureHeight() OVERRIDE;
+ virtual int CaptureFrameRate() OVERRIDE;
+ virtual void DetachEventHandler() OVERRIDE;
+
+ // media::VideoCapture::EventHandler implementation
+ virtual void OnStarted(VideoCapture* capture) OVERRIDE;
+ virtual void OnStopped(VideoCapture* capture) OVERRIDE;
+ virtual void OnPaused(VideoCapture* capture) OVERRIDE;
+ virtual void OnError(VideoCapture* capture, int error_code) OVERRIDE;
+ virtual void OnRemoved(VideoCapture* capture) OVERRIDE;
+ virtual void OnBufferReady(VideoCapture* capture,
+ scoped_refptr<VideoFrameBuffer> buffer) OVERRIDE;
+ virtual void OnDeviceInfoReceived(
+ VideoCapture* capture,
+ const media::VideoCaptureParams& device_info) OVERRIDE;
+
+ private:
+ void Initialize();
+
+ void OnDeviceOpened(int request_id,
+ bool succeeded,
+ const std::string& label);
+
+ base::WeakPtr<PepperPluginDelegateImpl> plugin_delegate_;
+
+ std::string device_id_;
+ std::string label_;
+ int session_id_;
+
+ scoped_ptr<media::VideoCaptureHandlerProxy> handler_proxy_;
+
+ webkit::ppapi::PluginDelegate::PlatformVideoCaptureEventHandler* handler_;
+
+ media::VideoCapture* video_capture_;
+
+ // StartCapture() must be balanced by StopCapture(), otherwise this object
+ // will leak.
+ bool unbalanced_start_;
+};
+
+PlatformVideoCaptureImpl::PlatformVideoCaptureImpl(
+ const base::WeakPtr<PepperPluginDelegateImpl>& plugin_delegate,
+ const std::string& device_id,
+ webkit::ppapi::PluginDelegate::PlatformVideoCaptureEventHandler* handler)
+ : plugin_delegate_(plugin_delegate),
+ device_id_(device_id),
+ session_id_(0),
+ ALLOW_THIS_IN_INITIALIZER_LIST(
+ handler_proxy_(new media::VideoCaptureHandlerProxy(
+ this, base::MessageLoopProxy::current()))),
+ handler_(handler),
+ video_capture_(NULL),
+ unbalanced_start_(false) {
+ if (device_id.empty()) {
+ // "1" is the session ID for the default device.
+ session_id_ = 1;
+ Initialize();
+ } else {
+ // We need to open the device and obtain the label and session ID before
+ // initializing.
+ if (plugin_delegate_) {
+ plugin_delegate_->OpenDevice(
+ PP_DEVICETYPE_DEV_VIDEOCAPTURE, device_id,
+ base::Bind(&PlatformVideoCaptureImpl::OnDeviceOpened, this));
+ }
}
+}
- // Overrides from media::VideoCapture::EventHandler
- virtual ~PlatformVideoCaptureImpl() {
+PlatformVideoCaptureImpl::~PlatformVideoCaptureImpl() {
+ if (video_capture_) {
VideoCaptureImplManager* manager =
RenderThreadImpl::current()->video_capture_impl_manager();
- manager->RemoveDevice(1, handler_proxy_.get());
+ manager->RemoveDevice(session_id_, handler_proxy_.get());
}
- virtual void StartCapture(
- EventHandler* handler,
- const VideoCaptureCapability& capability) OVERRIDE {
- DCHECK(handler == handler_proxy_->proxied());
+ if (plugin_delegate_ && !label_.empty())
+ plugin_delegate_->CloseDevice(label_);
+}
+
+void PlatformVideoCaptureImpl::StartCapture(
+ EventHandler* handler,
+ const VideoCaptureCapability& capability) {
+ DCHECK(handler == handler_);
+
+ if (unbalanced_start_)
+ return;
+
+ if (video_capture_) {
+ unbalanced_start_ = true;
+ AddRef(); // Will be balanced in OnRemoved().
video_capture_->StartCapture(handler_proxy_.get(), capability);
}
+}
+
+void PlatformVideoCaptureImpl::StopCapture(EventHandler* handler) {
+ DCHECK(handler == handler_);
+ if (!unbalanced_start_)
+ return;
- virtual void StopCapture(EventHandler* handler) OVERRIDE {
- DCHECK(handler == handler_proxy_->proxied());
+ if (video_capture_) {
+ unbalanced_start_ = false;
video_capture_->StopCapture(handler_proxy_.get());
}
+}
- virtual void FeedBuffer(scoped_refptr<VideoFrameBuffer> buffer) OVERRIDE {
+void PlatformVideoCaptureImpl::FeedBuffer(
+ scoped_refptr<VideoFrameBuffer> buffer) {
+ if (video_capture_)
video_capture_->FeedBuffer(buffer);
- }
+}
+
+bool PlatformVideoCaptureImpl::CaptureStarted() {
+ return handler_proxy_->state().started;
+}
+
+int PlatformVideoCaptureImpl::CaptureWidth() {
+ return handler_proxy_->state().width;
+}
+
+int PlatformVideoCaptureImpl::CaptureHeight() {
+ return handler_proxy_->state().height;
+}
+
+int PlatformVideoCaptureImpl::CaptureFrameRate() {
+ return handler_proxy_->state().frame_rate;
+}
+
+void PlatformVideoCaptureImpl::DetachEventHandler() {
+ handler_ = NULL;
+ StopCapture(NULL);
+}
+
+void PlatformVideoCaptureImpl::OnStarted(VideoCapture* capture) {
+ if (handler_)
+ handler_->OnStarted(capture);
+}
+
+void PlatformVideoCaptureImpl::OnStopped(VideoCapture* capture) {
+ if (handler_)
+ handler_->OnStopped(capture);
+}
+
+void PlatformVideoCaptureImpl::OnPaused(VideoCapture* capture) {
+ if (handler_)
+ handler_->OnPaused(capture);
+}
- virtual bool CaptureStarted() OVERRIDE {
- return handler_proxy_->state().started;
+void PlatformVideoCaptureImpl::OnError(VideoCapture* capture, int error_code) {
+ if (handler_)
+ handler_->OnError(capture, error_code);
+}
+
+void PlatformVideoCaptureImpl::OnRemoved(VideoCapture* capture) {
+ if (handler_)
+ handler_->OnRemoved(capture);
+
+ Release(); // Balance the AddRef() in StartCapture().
+}
+
+void PlatformVideoCaptureImpl::OnBufferReady(
+ VideoCapture* capture,
+ scoped_refptr<VideoFrameBuffer> buffer) {
+ if (handler_) {
+ handler_->OnBufferReady(capture, buffer);
+ } else {
+ // Even after handler_ is detached, we have to return buffers that are in
+ // flight to us. Otherwise VideoCaptureController will not tear down.
+ FeedBuffer(buffer);
}
+}
- virtual int CaptureWidth() OVERRIDE {
- return handler_proxy_->state().width;
+void PlatformVideoCaptureImpl::OnDeviceInfoReceived(
+ VideoCapture* capture,
+ const media::VideoCaptureParams& device_info) {
+ if (handler_)
+ handler_->OnDeviceInfoReceived(capture, device_info);
+}
+
+void PlatformVideoCaptureImpl::Initialize() {
+ VideoCaptureImplManager* manager =
+ RenderThreadImpl::current()->video_capture_impl_manager();
+ video_capture_ = manager->AddDevice(session_id_, handler_proxy_.get());
+}
+
+void PlatformVideoCaptureImpl::OnDeviceOpened(int request_id,
+ bool succeeded,
+ const std::string& label) {
+ succeeded = succeeded && plugin_delegate_;
+ if (succeeded) {
+ label_ = label;
+ session_id_ = plugin_delegate_->GetSessionID(PP_DEVICETYPE_DEV_VIDEOCAPTURE,
+ label);
+ Initialize();
}
- virtual int CaptureHeight() OVERRIDE {
- return handler_proxy_->state().height;
+ if (handler_)
+ handler_->OnInitialized(this, succeeded);
+}
+
+media_stream::MediaStreamType FromPepperDeviceType(PP_DeviceType_Dev type) {
+ switch (type) {
+ case PP_DEVICETYPE_DEV_INVALID:
+ return media_stream::kNoService;
+ case PP_DEVICETYPE_DEV_AUDIOCAPTURE:
+ return media_stream::kAudioCapture;
+ case PP_DEVICETYPE_DEV_VIDEOCAPTURE:
+ return media_stream::kVideoCapture;
+ default:
+ NOTREACHED();
+ return media_stream::kNoService;
}
+}
- virtual int CaptureFrameRate() OVERRIDE {
- return handler_proxy_->state().frame_rate;
+PP_DeviceType_Dev FromMediaStreamType(media_stream::MediaStreamType type) {
+ switch (type) {
+ case media_stream::kNoService:
+ return PP_DEVICETYPE_DEV_INVALID;
+ case media_stream::kAudioCapture:
+ return PP_DEVICETYPE_DEV_AUDIOCAPTURE;
+ case media_stream::kVideoCapture:
+ return PP_DEVICETYPE_DEV_VIDEOCAPTURE;
+ default:
+ NOTREACHED();
+ return PP_DEVICETYPE_DEV_INVALID;
}
+}
- private:
- scoped_ptr<media::VideoCaptureHandlerProxy> handler_proxy_;
- media::VideoCapture* video_capture_;
-};
+ppapi::DeviceRefData FromStreamDeviceInfo(
+ const media_stream::StreamDeviceInfo& info) {
+ ppapi::DeviceRefData data;
+ data.id = info.device_id;
+ data.name = info.name;
+ data.type = FromMediaStreamType(info.stream_type);
+ return data;
+}
} // namespace
@@ -844,6 +1041,120 @@ void PpapiBrokerImpl::ConnectPluginToBroker(
client->BrokerConnected(ppapi::PlatformFileToInt(plugin_handle), result);
}
+class PepperPluginDelegateImpl::DeviceEnumerationEventHandler
+ : public MediaStreamDispatcherEventHandler {
+ public:
+ DeviceEnumerationEventHandler() : next_id_(1) {
+ }
+
+ virtual ~DeviceEnumerationEventHandler() {
+ DCHECK(enumerate_callbacks_.empty());
+ DCHECK(open_callbacks_.empty());
+ }
+
+ int RegisterEnumerateDevicesCallback(
+ const EnumerateDevicesCallback& callback) {
+ enumerate_callbacks_[next_id_] = callback;
+ return next_id_++;
+ }
+
+ int RegisterOpenDeviceCallback(const OpenDeviceCallback& callback) {
+ open_callbacks_[next_id_] = callback;
+ return next_id_++;
+ }
+
+ // MediaStreamDispatcherEventHandler implementation.
+ virtual void OnStreamGenerated(
+ int request_id,
+ const std::string& label,
+ const media_stream::StreamDeviceInfoArray& audio_device_array,
+ const media_stream::StreamDeviceInfoArray& video_device_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 {
+ }
+
+ virtual void OnDevicesEnumerated(
+ int request_id,
+ const media_stream::StreamDeviceInfoArray& device_array) OVERRIDE {
+ NotifyDevicesEnumerated(request_id, true, device_array);
+ }
+
+ virtual void OnDevicesEnumerationFailed(int request_id) OVERRIDE {
+ NotifyDevicesEnumerated(request_id, false,
+ media_stream::StreamDeviceInfoArray());
+ }
+
+ virtual void OnDeviceOpened(
+ int request_id,
+ const std::string& label,
+ const media_stream::StreamDeviceInfo& device_info) OVERRIDE {
+ NotifyDeviceOpened(request_id, true, label);
+ }
+
+ virtual void OnDeviceOpenFailed(int request_id) OVERRIDE {
+ NotifyDeviceOpened(request_id, false, "");
+ }
+
+ private:
+ void NotifyDevicesEnumerated(
+ int request_id,
+ bool succeeded,
+ const media_stream::StreamDeviceInfoArray& device_array) {
+ EnumerateCallbackMap::iterator iter = enumerate_callbacks_.find(request_id);
+ if (iter == enumerate_callbacks_.end()) {
+ NOTREACHED();
+ return;
+ }
+
+ EnumerateDevicesCallback callback = iter->second;
+ enumerate_callbacks_.erase(iter);
+
+ std::vector<ppapi::DeviceRefData> devices;
+ if (succeeded) {
+ devices.reserve(device_array.size());
+ for (media_stream::StreamDeviceInfoArray::const_iterator info =
+ device_array.begin(); info != device_array.end(); ++info) {
+ devices.push_back(FromStreamDeviceInfo(*info));
+ }
+ }
+ callback.Run(request_id, succeeded, devices);
+ }
+
+ void NotifyDeviceOpened(int request_id,
+ bool succeeded,
+ const std::string& label) {
+ OpenCallbackMap::iterator iter = open_callbacks_.find(request_id);
+ if (iter == open_callbacks_.end()) {
+ NOTREACHED();
+ return;
+ }
+
+ OpenDeviceCallback callback = iter->second;
+ open_callbacks_.erase(iter);
+
+ callback.Run(request_id, succeeded, label);
+ }
+
+ int next_id_;
+
+ typedef std::map<int, EnumerateDevicesCallback> EnumerateCallbackMap;
+ EnumerateCallbackMap enumerate_callbacks_;
+
+ typedef std::map<int, OpenDeviceCallback> OpenCallbackMap;
+ OpenCallbackMap open_callbacks_;
+
+ DISALLOW_COPY_AND_ASSIGN(DeviceEnumerationEventHandler);
+};
+
PepperPluginDelegateImpl::PepperPluginDelegateImpl(RenderViewImpl* render_view)
: content::RenderViewObserver(render_view),
render_view_(render_view),
@@ -854,7 +1165,8 @@ PepperPluginDelegateImpl::PepperPluginDelegateImpl(RenderViewImpl* render_view)
mouse_locked_(false),
pending_lock_request_(false),
pending_unlock_request_(false),
- last_mouse_event_target_(NULL) {
+ last_mouse_event_target_(NULL),
+ device_enumeration_event_handler_(new DeviceEnumerationEventHandler()) {
}
PepperPluginDelegateImpl::~PepperPluginDelegateImpl() {
@@ -1228,8 +1540,9 @@ webkit::ppapi::PluginDelegate::PlatformContext3D*
webkit::ppapi::PluginDelegate::PlatformVideoCapture*
PepperPluginDelegateImpl::CreateVideoCapture(
- media::VideoCapture::EventHandler* handler) {
- return new PlatformVideoCaptureImpl(handler);
+ const std::string& device_id,
+ PlatformVideoCaptureEventHandler* handler) {
+ return new PlatformVideoCaptureImpl(AsWeakPtr(), device_id, handler);
}
webkit::ppapi::PluginDelegate::PlatformVideoDecoder*
@@ -2044,6 +2357,18 @@ bool PepperPluginDelegateImpl::IsPageVisible() const {
return !render_view_->is_hidden();
}
+int PepperPluginDelegateImpl::EnumerateDevices(
+ PP_DeviceType_Dev type,
+ const EnumerateDevicesCallback& callback) {
+ int request_id =
+ device_enumeration_event_handler_->RegisterEnumerateDevicesCallback(
+ callback);
+ render_view_->media_stream_dispatcher()->EnumerateDevices(
+ request_id, device_enumeration_event_handler_.get(),
+ FromPepperDeviceType(type), "");
+ return request_id;
+}
+
bool PepperPluginDelegateImpl::OnMessageReceived(const IPC::Message& message) {
bool handled = true;
IPC_BEGIN_MESSAGE_MAP(PepperPluginDelegateImpl, message)
@@ -2145,6 +2470,36 @@ int PepperPluginDelegateImpl::GetRoutingId() const {
return render_view_->routing_id();
}
+int PepperPluginDelegateImpl::OpenDevice(PP_DeviceType_Dev type,
+ const std::string& device_id,
+ const OpenDeviceCallback& callback) {
+ int request_id =
+ device_enumeration_event_handler_->RegisterOpenDeviceCallback(callback);
+ render_view_->media_stream_dispatcher()->OpenDevice(
+ request_id, device_enumeration_event_handler_.get(), device_id,
+ FromPepperDeviceType(type), "");
+ return request_id;
+}
+
+void PepperPluginDelegateImpl::CloseDevice(const std::string& label) {
+ render_view_->media_stream_dispatcher()->CloseDevice(label);
+}
+
+int PepperPluginDelegateImpl::GetSessionID(PP_DeviceType_Dev type,
+ const std::string& label) {
+ switch (type) {
+ case PP_DEVICETYPE_DEV_AUDIOCAPTURE:
+ return render_view_->media_stream_dispatcher()->audio_session_id(label,
+ 0);
+ case PP_DEVICETYPE_DEV_VIDEOCAPTURE:
+ return render_view_->media_stream_dispatcher()->video_session_id(label,
+ 0);
+ default:
+ NOTREACHED();
+ return 0;
+ }
+}
+
RendererGLContext*
PepperPluginDelegateImpl::GetParentContextForPlatformContext3D() {
WebGraphicsContext3DCommandBufferImpl* context =

Powered by Google App Engine
This is Rietveld 408576698