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 f2cb26cd87ab95516792e47f40bc078db904a5e9..a628d8b819315b0f4590acabf27966b54861ca10 100644 |
--- a/webkit/plugins/ppapi/ppb_video_capture_impl.cc |
+++ b/webkit/plugins/ppapi/ppb_video_capture_impl.cc |
@@ -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. |
@@ -7,12 +7,15 @@ |
#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/thunk/enter.h" |
#include "webkit/plugins/ppapi/common.h" |
@@ -21,10 +24,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 { |
@@ -41,14 +46,19 @@ PPB_VideoCapture_Impl::PPB_VideoCapture_Impl(PP_Instance instance) |
buffer_count_hint_(0), |
ppp_videocapture_(NULL), |
status_(PP_VIDEO_CAPTURE_STATUS_STOPPED), |
- is_dead_(false) { |
+ ALLOW_THIS_IN_INITIALIZER_LIST(weak_ptr_factory_(this)), |
+ devices_(0), |
+ capability_() { |
} |
PPB_VideoCapture_Impl::~PPB_VideoCapture_Impl() { |
+ StopCapture(); |
+ DCHECK(buffers_.empty()); |
+ ClearCachedDeviceResourceArray(); |
+ DetachPlatformVideoCapture(); |
} |
bool PPB_VideoCapture_Impl::Init() { |
- DCHECK(!is_dead_); |
PluginInstance* instance = ResourceHelper::GetPluginInstance(this); |
if (!instance) |
return false; |
@@ -57,59 +67,83 @@ bool PPB_VideoCapture_Impl::Init() { |
if (!ppp_videocapture_) |
return false; |
- platform_video_capture_.reset( |
- instance->delegate()->CreateVideoCapture(this)); |
- return !!platform_video_capture_.get(); |
+ return true; |
} |
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; |
+int32_t PPB_VideoCapture_Impl::EnumerateDevices( |
+ PP_CompletionCallback callback) { |
+ if (!callback.func) |
+ return PP_ERROR_BLOCKS_MAIN_THREAD; |
+ if (TrackedCallback::IsPending(enumerate_devices_callback_)) |
+ return PP_ERROR_INPROGRESS; |
- ::ppapi::Resource::LastPluginRefWasDeleted(); |
+ PluginInstance* instance = ResourceHelper::GetPluginInstance(this); |
+ if (!instance) |
+ return PP_ERROR_FAILED; |
+ |
+ enumerate_devices_callback_ = new TrackedCallback(this, callback); |
+ instance->delegate()->EnumerateDevices( |
+ PP_DEVICETYPE_DEV_VIDEOCAPTURE, |
+ base::Bind(&PPB_VideoCapture_Impl::OnEnumerateDevicesComplete, |
+ weak_ptr_factory_.GetWeakPtr())); |
+ return PP_OK_COMPLETIONPENDING; |
+} |
+ |
+PP_Resource PPB_VideoCapture_Impl::GetDevices() { |
+ if (devices_) |
+ PpapiGlobals::Get()->GetResourceTracker()->AddRefResource(devices_); |
+ return devices_; |
} |
int32_t PPB_VideoCapture_Impl::StartCapture( |
+ const std::string& device_id, |
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: |
+ case PP_VIDEO_CAPTURE_STATUS_STOPPING: |
default: |
return PP_ERROR_FAILED; |
case PP_VIDEO_CAPTURE_STATUS_STOPPED: |
- case PP_VIDEO_CAPTURE_STATUS_STOPPING: |
break; |
} |
+ |
+ PluginInstance* instance = ResourceHelper::GetPluginInstance(this); |
+ if (!instance) |
+ return PP_ERROR_FAILED; |
+ |
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 |
- }; |
+ |
+ capability_.width = requested_info.width; |
+ capability_.height = requested_info.height; |
+ capability_.max_fps = requested_info.frames_per_second; |
+ capability_.expected_capture_delay = 0; // Ignored. |
+ capability_.raw_type = media::VideoFrame::I420; |
+ capability_.interlaced = false; // Ignored. |
wjia(left Chromium)
2012/01/27 06:13:09
is it possible Pepper client would call StartCaptu
yzshen1
2012/01/27 18:00:24
If the status_ is not PP_VIDEO_CAPTURE_STATUS_STOP
|
+ |
status_ = PP_VIDEO_CAPTURE_STATUS_STARTING; |
- AddRef(); // Balanced in |OnRemoved()|. |
- platform_video_capture_->StartCapture(this, capability); |
+ |
+ DetachPlatformVideoCapture(); |
wjia(left Chromium)
2012/01/27 06:13:09
same question as above.
yzshen1
2012/01/27 18:00:24
Please see above.
On 2012/01/27 06:13:09, wjia wr
|
+ platform_video_capture_ = |
+ instance->delegate()->CreateVideoCapture(device_id, this); |
+ // If |device_id| is not empty, StartCapture() will be performed in the |
+ // OnInitialized() handler. |
+ if (device_id.empty()) |
+ 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; |
@@ -117,7 +151,6 @@ int32_t PPB_VideoCapture_Impl::ReuseBuffer(uint32_t buffer) { |
} |
int32_t PPB_VideoCapture_Impl::StopCapture() { |
- DCHECK(!is_dead_); |
switch (status_) { |
case PP_VIDEO_CAPTURE_STATUS_STOPPED: |
case PP_VIDEO_CAPTURE_STATUS_STOPPING: |
@@ -128,16 +161,20 @@ int32_t PPB_VideoCapture_Impl::StopCapture() { |
case PP_VIDEO_CAPTURE_STATUS_PAUSED: |
break; |
} |
+ DCHECK(platform_video_capture_.get()); |
+ |
ReleaseBuffers(); |
status_ = PP_VIDEO_CAPTURE_STATUS_STOPPING; |
platform_video_capture_->StopCapture(this); |
return PP_OK; |
} |
-void PPB_VideoCapture_Impl::OnStarted(media::VideoCapture* capture) { |
- if (is_dead_) |
- return; |
+const std::vector<DeviceRefData>& |
+ PPB_VideoCapture_Impl::GetDeviceRefData() const { |
+ return devices_data_; |
+} |
+void PPB_VideoCapture_Impl::OnStarted(media::VideoCapture* capture) { |
switch (status_) { |
case PP_VIDEO_CAPTURE_STATUS_STARTING: |
case PP_VIDEO_CAPTURE_STATUS_PAUSED: |
@@ -153,9 +190,6 @@ void PPB_VideoCapture_Impl::OnStarted(media::VideoCapture* capture) { |
} |
void PPB_VideoCapture_Impl::OnStopped(media::VideoCapture* capture) { |
- if (is_dead_) |
- return; |
- |
switch (status_) { |
case PP_VIDEO_CAPTURE_STATUS_STOPPING: |
break; |
@@ -166,14 +200,12 @@ void PPB_VideoCapture_Impl::OnStopped(media::VideoCapture* capture) { |
default: |
return; |
} |
+ |
status_ = PP_VIDEO_CAPTURE_STATUS_STOPPED; |
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: |
@@ -190,9 +222,6 @@ void PPB_VideoCapture_Impl::OnPaused(media::VideoCapture* capture) { |
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 |
@@ -203,42 +232,31 @@ void PPB_VideoCapture_Impl::OnError(media::VideoCapture* capture, |
} |
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, |
@@ -286,8 +304,22 @@ 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()); |
+ |
+ if (status_ != PP_VIDEO_CAPTURE_STATUS_STARTING) |
+ return; |
+ |
+ if (succeeded) { |
+ platform_video_capture_->StartCapture(this, capability_); |
+ } else { |
+ status_ = PP_VIDEO_CAPTURE_STATUS_STOPPED; |
+ SendStatus(); |
+ } |
+} |
+ |
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 +329,43 @@ 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::ClearCachedDeviceResourceArray() { |
+ if (devices_) |
+ PpapiGlobals::Get()->GetResourceTracker()->ReleaseResource(devices_); |
+ devices_ = 0; |
+ |
+ devices_data_.clear(); |
+} |
+ |
+void PPB_VideoCapture_Impl::DetachPlatformVideoCapture() { |
+ if (platform_video_capture_.get()) { |
+ platform_video_capture_->DetachEventHandler(); |
+ platform_video_capture_ = NULL; |
+ } |
+} |
+ |
+void PPB_VideoCapture_Impl::OnEnumerateDevicesComplete( |
+ int request_id, |
+ bool succeeded, |
+ const std::vector<::ppapi::DeviceRefData>& devices) { |
+ ClearCachedDeviceResourceArray(); |
+ if (succeeded) { |
+ devices_data_ = devices; |
+ devices_ = ::ppapi::PPB_DeviceRef_Shared::CreateResourceArray( |
+ true, pp_instance(), devices_data_); |
+ } |
+ |
+ if (!TrackedCallback::IsPending(enumerate_devices_callback_)) { |
+ NOTREACHED(); |
+ return; |
+ } |
+ TrackedCallback::ClearAndRun(&enumerate_devices_callback_, |
+ succeeded ? PP_OK : PP_ERROR_FAILED); |
+} |
+ |
PPB_VideoCapture_Impl::BufferInfo::BufferInfo() |
: in_use(false), |
data(NULL), |