| Index: webkit/plugins/ppapi/ppb_video_capture_impl.cc
|
| diff --git a/webkit/plugins/ppapi/ppb_video_capture_impl.cc b/webkit/plugins/ppapi/ppb_video_capture_impl.cc
|
| index 63a19a4cbc607ca3df5339a8a6fd8057c41af20e..cab216e8bcf8daff2f90c85adf7388424feacb25 100644
|
| --- a/webkit/plugins/ppapi/ppb_video_capture_impl.cc
|
| +++ b/webkit/plugins/ppapi/ppb_video_capture_impl.cc
|
| @@ -7,13 +7,17 @@
|
| #include <algorithm>
|
| #include <string>
|
|
|
| +#include "base/bind.h"
|
| #include "base/logging.h"
|
| +#include "base/memory/scoped_ptr.h"
|
| #include "ppapi/c/dev/pp_video_capture_dev.h"
|
| #include "ppapi/c/dev/ppb_video_capture_dev.h"
|
| #include "ppapi/c/pp_completion_callback.h"
|
| #include "ppapi/c/pp_errors.h"
|
| #include "ppapi/shared_impl/ppapi_globals.h"
|
| +#include "ppapi/shared_impl/ppb_device_ref_shared.h"
|
| #include "ppapi/shared_impl/resource_tracker.h"
|
| +#include "ppapi/shared_impl/tracked_callback.h"
|
| #include "ppapi/thunk/enter.h"
|
| #include "webkit/plugins/ppapi/common.h"
|
| #include "webkit/plugins/ppapi/plugin_module.h"
|
| @@ -21,10 +25,12 @@
|
| #include "webkit/plugins/ppapi/ppb_buffer_impl.h"
|
| #include "webkit/plugins/ppapi/resource_helper.h"
|
|
|
| +using ppapi::DeviceRefData;
|
| using ppapi::PpapiGlobals;
|
| using ppapi::thunk::EnterResourceNoLock;
|
| using ppapi::thunk::PPB_Buffer_API;
|
| using ppapi::thunk::PPB_VideoCapture_API;
|
| +using ppapi::TrackedCallback;
|
|
|
| namespace {
|
|
|
| @@ -37,18 +43,17 @@ namespace webkit {
|
| namespace ppapi {
|
|
|
| PPB_VideoCapture_Impl::PPB_VideoCapture_Impl(PP_Instance instance)
|
| - : Resource(::ppapi::OBJECT_IS_IMPL, instance),
|
| + : PPB_VideoCapture_Shared(instance),
|
| buffer_count_hint_(0),
|
| ppp_videocapture_(NULL),
|
| - status_(PP_VIDEO_CAPTURE_STATUS_STOPPED),
|
| - is_dead_(false) {
|
| + capability_() {
|
| }
|
|
|
| PPB_VideoCapture_Impl::~PPB_VideoCapture_Impl() {
|
| + Close();
|
| }
|
|
|
| bool PPB_VideoCapture_Impl::Init() {
|
| - DCHECK(!is_dead_);
|
| PluginInstance* instance = ResourceHelper::GetPluginInstance(this);
|
| if (!instance)
|
| return false;
|
| @@ -57,188 +62,61 @@ bool PPB_VideoCapture_Impl::Init() {
|
| if (!ppp_videocapture_)
|
| return false;
|
|
|
| - platform_video_capture_.reset(
|
| - instance->delegate()->CreateVideoCapture(this));
|
| - return !!platform_video_capture_.get();
|
| -}
|
| -
|
| -PPB_VideoCapture_API* PPB_VideoCapture_Impl::AsPPB_VideoCapture_API() {
|
| - return this;
|
| -}
|
| -
|
| -void PPB_VideoCapture_Impl::LastPluginRefWasDeleted() {
|
| - if (platform_video_capture_.get())
|
| - StopCapture();
|
| - DCHECK(buffers_.empty());
|
| - ppp_videocapture_ = NULL;
|
| - is_dead_ = true;
|
| -
|
| - ::ppapi::Resource::LastPluginRefWasDeleted();
|
| -}
|
| -
|
| -int32_t PPB_VideoCapture_Impl::StartCapture(
|
| - const PP_VideoCaptureDeviceInfo_Dev& requested_info,
|
| - uint32_t buffer_count) {
|
| - DCHECK(!is_dead_);
|
| - switch (status_) {
|
| - case PP_VIDEO_CAPTURE_STATUS_STARTING:
|
| - case PP_VIDEO_CAPTURE_STATUS_STARTED:
|
| - case PP_VIDEO_CAPTURE_STATUS_PAUSED:
|
| - default:
|
| - return PP_ERROR_FAILED;
|
| - case PP_VIDEO_CAPTURE_STATUS_STOPPED:
|
| - case PP_VIDEO_CAPTURE_STATUS_STOPPING:
|
| - break;
|
| - }
|
| - DCHECK(buffers_.empty());
|
| -
|
| - // Clamp the buffer count to between 1 and |kMaxBuffers|.
|
| - buffer_count_hint_ = std::min(std::max(buffer_count, 1U), kMaxBuffers);
|
| - media::VideoCapture::VideoCaptureCapability capability = {
|
| - requested_info.width,
|
| - requested_info.height,
|
| - requested_info.frames_per_second,
|
| - 0, // ignored.
|
| - media::VideoFrame::I420,
|
| - false, // ignored
|
| - };
|
| - status_ = PP_VIDEO_CAPTURE_STATUS_STARTING;
|
| - AddRef(); // Balanced in |OnRemoved()|.
|
| - platform_video_capture_->StartCapture(this, capability);
|
| - return PP_OK;
|
| -}
|
| -
|
| -int32_t PPB_VideoCapture_Impl::ReuseBuffer(uint32_t buffer) {
|
| - DCHECK(!is_dead_);
|
| - if (buffer >= buffers_.size() || !buffers_[buffer].in_use)
|
| - return PP_ERROR_BADARGUMENT;
|
| - buffers_[buffer].in_use = false;
|
| - return PP_OK;
|
| -}
|
| -
|
| -int32_t PPB_VideoCapture_Impl::StopCapture() {
|
| - DCHECK(!is_dead_);
|
| - switch (status_) {
|
| - case PP_VIDEO_CAPTURE_STATUS_STOPPED:
|
| - case PP_VIDEO_CAPTURE_STATUS_STOPPING:
|
| - default:
|
| - return PP_ERROR_FAILED;
|
| - case PP_VIDEO_CAPTURE_STATUS_STARTING:
|
| - case PP_VIDEO_CAPTURE_STATUS_STARTED:
|
| - case PP_VIDEO_CAPTURE_STATUS_PAUSED:
|
| - break;
|
| - }
|
| - ReleaseBuffers();
|
| - status_ = PP_VIDEO_CAPTURE_STATUS_STOPPING;
|
| - platform_video_capture_->StopCapture(this);
|
| - return PP_OK;
|
| + return true;
|
| }
|
|
|
| void PPB_VideoCapture_Impl::OnStarted(media::VideoCapture* capture) {
|
| - if (is_dead_)
|
| - return;
|
| -
|
| - switch (status_) {
|
| - case PP_VIDEO_CAPTURE_STATUS_STARTING:
|
| - case PP_VIDEO_CAPTURE_STATUS_PAUSED:
|
| - break;
|
| - case PP_VIDEO_CAPTURE_STATUS_STOPPED:
|
| - case PP_VIDEO_CAPTURE_STATUS_STOPPING:
|
| - case PP_VIDEO_CAPTURE_STATUS_STARTED:
|
| - default:
|
| - return;
|
| - }
|
| - status_ = PP_VIDEO_CAPTURE_STATUS_STARTED;
|
| - SendStatus();
|
| + if (SetStatus(PP_VIDEO_CAPTURE_STATUS_STARTED, false))
|
| + SendStatus();
|
| }
|
|
|
| void PPB_VideoCapture_Impl::OnStopped(media::VideoCapture* capture) {
|
| - if (is_dead_)
|
| - return;
|
| -
|
| - switch (status_) {
|
| - case PP_VIDEO_CAPTURE_STATUS_STOPPING:
|
| - break;
|
| - case PP_VIDEO_CAPTURE_STATUS_STARTING:
|
| - case PP_VIDEO_CAPTURE_STATUS_PAUSED:
|
| - case PP_VIDEO_CAPTURE_STATUS_STOPPED:
|
| - case PP_VIDEO_CAPTURE_STATUS_STARTED:
|
| - default:
|
| - return;
|
| - }
|
| - status_ = PP_VIDEO_CAPTURE_STATUS_STOPPED;
|
| - SendStatus();
|
| + if (SetStatus(PP_VIDEO_CAPTURE_STATUS_STOPPED, false))
|
| + SendStatus();
|
| }
|
|
|
| void PPB_VideoCapture_Impl::OnPaused(media::VideoCapture* capture) {
|
| - if (is_dead_)
|
| - return;
|
| -
|
| - switch (status_) {
|
| - case PP_VIDEO_CAPTURE_STATUS_STARTING:
|
| - case PP_VIDEO_CAPTURE_STATUS_STARTED:
|
| - break;
|
| - case PP_VIDEO_CAPTURE_STATUS_STOPPED:
|
| - case PP_VIDEO_CAPTURE_STATUS_STOPPING:
|
| - case PP_VIDEO_CAPTURE_STATUS_PAUSED:
|
| - default:
|
| - return;
|
| - }
|
| - status_ = PP_VIDEO_CAPTURE_STATUS_PAUSED;
|
| - SendStatus();
|
| + if (SetStatus(PP_VIDEO_CAPTURE_STATUS_PAUSED, false))
|
| + SendStatus();
|
| }
|
|
|
| void PPB_VideoCapture_Impl::OnError(media::VideoCapture* capture,
|
| int error_code) {
|
| - if (is_dead_)
|
| - return;
|
| -
|
| // Today, the media layer only sends "1" as an error.
|
| DCHECK(error_code == 1);
|
| // It either comes because some error was detected while starting (e.g. 2
|
| // conflicting "master" resolution), or because the browser failed to start
|
| // the capture.
|
| - status_ = PP_VIDEO_CAPTURE_STATUS_STOPPED;
|
| + SetStatus(PP_VIDEO_CAPTURE_STATUS_STOPPED, true);
|
| ppp_videocapture_->OnError(pp_instance(), pp_resource(), PP_ERROR_FAILED);
|
| }
|
|
|
| void PPB_VideoCapture_Impl::OnRemoved(media::VideoCapture* capture) {
|
| - Release();
|
| }
|
|
|
| void PPB_VideoCapture_Impl::OnBufferReady(
|
| media::VideoCapture* capture,
|
| scoped_refptr<media::VideoCapture::VideoFrameBuffer> buffer) {
|
| - if (!is_dead_) {
|
| - DCHECK(buffer.get());
|
| - for (uint32_t i = 0; i < buffers_.size(); ++i) {
|
| - if (!buffers_[i].in_use) {
|
| - // TODO(ihf): Switch to a size calculation based on stride.
|
| - // Stride is filled out now but not more meaningful than size
|
| - // until wjia unifies VideoFrameBuffer and media::VideoFrame.
|
| - size_t size = std::min(static_cast<size_t>(buffers_[i].buffer->size()),
|
| - buffer->buffer_size);
|
| - memcpy(buffers_[i].data, buffer->memory_pointer, size);
|
| - buffers_[i].in_use = true;
|
| - platform_video_capture_->FeedBuffer(buffer);
|
| - ppp_videocapture_->OnBufferReady(pp_instance(), pp_resource(), i);
|
| - return;
|
| - }
|
| + DCHECK(buffer.get());
|
| + for (uint32_t i = 0; i < buffers_.size(); ++i) {
|
| + if (!buffers_[i].in_use) {
|
| + // TODO(ihf): Switch to a size calculation based on stride.
|
| + // Stride is filled out now but not more meaningful than size
|
| + // until wjia unifies VideoFrameBuffer and media::VideoFrame.
|
| + size_t size = std::min(static_cast<size_t>(buffers_[i].buffer->size()),
|
| + buffer->buffer_size);
|
| + memcpy(buffers_[i].data, buffer->memory_pointer, size);
|
| + buffers_[i].in_use = true;
|
| + platform_video_capture_->FeedBuffer(buffer);
|
| + ppp_videocapture_->OnBufferReady(pp_instance(), pp_resource(), i);
|
| + return;
|
| }
|
| }
|
| - // Even after we have stopped and are dead we have to return buffers that
|
| - // are in flight to us. Otherwise VideoCaptureController will not tear down.
|
| - platform_video_capture_->FeedBuffer(buffer);
|
| }
|
|
|
| void PPB_VideoCapture_Impl::OnDeviceInfoReceived(
|
| media::VideoCapture* capture,
|
| const media::VideoCaptureParams& device_info) {
|
| - // No need to call |ReleaseBuffers()|: if we're dead, |StopCapture()| should
|
| - // already have been called.
|
| - if (is_dead_)
|
| - return;
|
| -
|
| PP_VideoCaptureDeviceInfo_Dev info = {
|
| device_info.width,
|
| device_info.height,
|
| @@ -277,7 +155,7 @@ void PPB_VideoCapture_Impl::OnDeviceInfoReceived(
|
| // We couldn't allocate/map buffers at all. Send an error and stop the
|
| // capture.
|
| ppp_videocapture_->OnError(pp_instance(), pp_resource(), PP_ERROR_NOMEMORY);
|
| - status_ = PP_VIDEO_CAPTURE_STATUS_STOPPING;
|
| + SetStatus(PP_VIDEO_CAPTURE_STATUS_STOPPING, true);
|
| platform_video_capture_->StopCapture(this);
|
| return;
|
| }
|
| @@ -286,8 +164,112 @@ void PPB_VideoCapture_Impl::OnDeviceInfoReceived(
|
| buffers_.size(), resources.get());
|
| }
|
|
|
| +void PPB_VideoCapture_Impl::OnInitialized(media::VideoCapture* capture,
|
| + bool succeeded) {
|
| + DCHECK(capture == platform_video_capture_.get());
|
| +
|
| + OnOpenComplete(succeeded ? PP_OK : PP_ERROR_FAILED);
|
| +}
|
| +
|
| +int32_t PPB_VideoCapture_Impl::InternalEnumerateDevices(
|
| + PP_Resource* devices,
|
| + PP_CompletionCallback callback) {
|
| + PluginInstance* instance = ResourceHelper::GetPluginInstance(this);
|
| + if (!instance)
|
| + return PP_ERROR_FAILED;
|
| +
|
| + devices_ = devices;
|
| + enumerate_devices_callback_ = new TrackedCallback(this, callback);
|
| + instance->delegate()->EnumerateDevices(
|
| + PP_DEVICETYPE_DEV_VIDEOCAPTURE,
|
| + base::Bind(&PPB_VideoCapture_Impl::EnumerateDevicesCallbackFunc,
|
| + AsWeakPtr()));
|
| + return PP_OK_COMPLETIONPENDING;
|
| +}
|
| +
|
| +int32_t PPB_VideoCapture_Impl::InternalOpen(
|
| + const std::string& device_id,
|
| + const PP_VideoCaptureDeviceInfo_Dev& requested_info,
|
| + uint32_t buffer_count,
|
| + PP_CompletionCallback callback) {
|
| + // It is able to complete synchronously if the default device is used.
|
| + bool sync_completion = device_id.empty();
|
| +
|
| + if (!callback.func && !sync_completion)
|
| + return PP_ERROR_BLOCKS_MAIN_THREAD;
|
| +
|
| + PluginInstance* instance = ResourceHelper::GetPluginInstance(this);
|
| + if (!instance)
|
| + return PP_ERROR_FAILED;
|
| +
|
| + SetRequestedInfo(requested_info, buffer_count);
|
| +
|
| + DCHECK(!platform_video_capture_.get());
|
| + platform_video_capture_ =
|
| + instance->delegate()->CreateVideoCapture(device_id, this);
|
| +
|
| + if (sync_completion) {
|
| + OnInitialized(platform_video_capture_.get(), true);
|
| + return PP_OK;
|
| + } else {
|
| + open_callback_ = new TrackedCallback(this, callback);
|
| + return PP_OK_COMPLETIONPENDING;
|
| + }
|
| +}
|
| +
|
| +int32_t PPB_VideoCapture_Impl::InternalStartCapture() {
|
| + DCHECK(buffers_.empty());
|
| + platform_video_capture_->StartCapture(this, capability_);
|
| + return PP_OK;
|
| +}
|
| +
|
| +int32_t PPB_VideoCapture_Impl::InternalReuseBuffer(uint32_t buffer) {
|
| + if (buffer >= buffers_.size() || !buffers_[buffer].in_use)
|
| + return PP_ERROR_BADARGUMENT;
|
| + buffers_[buffer].in_use = false;
|
| + return PP_OK;
|
| +}
|
| +
|
| +int32_t PPB_VideoCapture_Impl::InternalStopCapture() {
|
| + ReleaseBuffers();
|
| + platform_video_capture_->StopCapture(this);
|
| + return PP_OK;
|
| +}
|
| +
|
| +void PPB_VideoCapture_Impl::InternalClose() {
|
| + StopCapture();
|
| + DCHECK(buffers_.empty());
|
| +
|
| + DetachPlatformVideoCapture();
|
| +}
|
| +
|
| +int32_t PPB_VideoCapture_Impl::InternalStartCapture0_1(
|
| + const PP_VideoCaptureDeviceInfo_Dev& requested_info,
|
| + uint32_t buffer_count) {
|
| + PluginInstance* instance = ResourceHelper::GetPluginInstance(this);
|
| + if (!instance) {
|
| + SetStatus(PP_VIDEO_CAPTURE_STATUS_STOPPED, true);
|
| + return PP_ERROR_FAILED;
|
| + }
|
| +
|
| + DCHECK(buffers_.empty());
|
| +
|
| + SetRequestedInfo(requested_info, buffer_count);
|
| +
|
| + DetachPlatformVideoCapture();
|
| + platform_video_capture_ =
|
| + instance->delegate()->CreateVideoCapture("", this);
|
| + platform_video_capture_->StartCapture(this, capability_);
|
| +
|
| + return PP_OK;
|
| +}
|
| +
|
| +const PPB_VideoCapture_Impl::DeviceRefDataVector&
|
| + PPB_VideoCapture_Impl::InternalGetDeviceRefData() const {
|
| + return devices_data_;
|
| +}
|
| +
|
| void PPB_VideoCapture_Impl::ReleaseBuffers() {
|
| - DCHECK(!is_dead_);
|
| ::ppapi::ResourceTracker* tracker = PpapiGlobals::Get()->GetResourceTracker();
|
| for (size_t i = 0; i < buffers_.size(); ++i) {
|
| buffers_[i].buffer->Unmap();
|
| @@ -297,10 +279,41 @@ void PPB_VideoCapture_Impl::ReleaseBuffers() {
|
| }
|
|
|
| void PPB_VideoCapture_Impl::SendStatus() {
|
| - DCHECK(!is_dead_);
|
| ppp_videocapture_->OnStatus(pp_instance(), pp_resource(), status_);
|
| }
|
|
|
| +void PPB_VideoCapture_Impl::SetRequestedInfo(
|
| + const PP_VideoCaptureDeviceInfo_Dev& device_info,
|
| + uint32_t buffer_count) {
|
| + // Clamp the buffer count to between 1 and |kMaxBuffers|.
|
| + buffer_count_hint_ = std::min(std::max(buffer_count, 1U), kMaxBuffers);
|
| +
|
| + capability_.width = device_info.width;
|
| + capability_.height = device_info.height;
|
| + capability_.max_fps = device_info.frames_per_second;
|
| + capability_.expected_capture_delay = 0; // Ignored.
|
| + capability_.raw_type = media::VideoFrame::I420;
|
| + capability_.interlaced = false; // Ignored.
|
| +}
|
| +
|
| +void PPB_VideoCapture_Impl::DetachPlatformVideoCapture() {
|
| + if (platform_video_capture_.get()) {
|
| + platform_video_capture_->DetachEventHandler();
|
| + platform_video_capture_ = NULL;
|
| + }
|
| +}
|
| +
|
| +void PPB_VideoCapture_Impl::EnumerateDevicesCallbackFunc(
|
| + int request_id,
|
| + bool succeeded,
|
| + const DeviceRefDataVector& devices) {
|
| + devices_data_.clear();
|
| + if (succeeded)
|
| + devices_data_ = devices;
|
| +
|
| + OnEnumerateDevicesComplete(succeeded ? PP_OK : PP_ERROR_FAILED, devices);
|
| +}
|
| +
|
| PPB_VideoCapture_Impl::BufferInfo::BufferInfo()
|
| : in_use(false),
|
| data(NULL),
|
|
|