1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "ppapi/proxy/video_capture_resource.h"
7 #include "ppapi/c/dev/ppp_video_capture_dev.h"
8 #include "ppapi/proxy/dispatch_reply_message.h"
9 #include "ppapi/proxy/plugin_dispatcher.h"
10 #include "ppapi/proxy/plugin_globals.h"
11 #include "ppapi/proxy/plugin_resource_tracker.h"
12 #include "ppapi/proxy/ppapi_messages.h"
13 #include "ppapi/proxy/ppb_buffer_proxy.h"
14 #include "ppapi/proxy/resource_message_params.h"
15 #include "ppapi/shared_impl/proxy_lock.h"
16 #include "ppapi/shared_impl/tracked_callback.h"
21 VideoCaptureResource::VideoCaptureResource(
22 Connection connection,
24 PluginDispatcher* dispatcher)
25 : PluginResource(connection, instance),
26 open_state_(BEFORE_OPEN),
27 enumeration_helper_(this) {
28 SendCreate(RENDERER, PpapiHostMsg_VideoCapture_Create());
30 ppp_video_capture_impl_ = static_cast<const PPP_VideoCapture_Dev*>(
31 dispatcher->local_get_interface()(PPP_VIDEO_CAPTURE_DEV_INTERFACE));
34 VideoCaptureResource::~VideoCaptureResource() {
37 void VideoCaptureResource::OnReplyReceived(
38 const ResourceMessageReplyParams& params,
39 const IPC::Message& msg) {
40 if (enumeration_helper_.HandleReply(params, msg))
43 if (params.sequence()) {
44 PluginResource::OnReplyReceived(params, msg);
48 IPC_BEGIN_MESSAGE_MAP(VideoCaptureResource, msg)
49 PPAPI_DISPATCH_PLUGIN_RESOURCE_CALL(
50 PpapiPluginMsg_VideoCapture_OnDeviceInfo,
51 OnPluginMsgOnDeviceInfo)
52 PPAPI_DISPATCH_PLUGIN_RESOURCE_CALL(
53 PpapiPluginMsg_VideoCapture_OnStatus,
55 PPAPI_DISPATCH_PLUGIN_RESOURCE_CALL(
56 PpapiPluginMsg_VideoCapture_OnError,
58 PPAPI_DISPATCH_PLUGIN_RESOURCE_CALL(
59 PpapiPluginMsg_VideoCapture_OnBufferReady,
60 OnPluginMsgOnBufferReady)
61 PPAPI_DISPATCH_PLUGIN_RESOURCE_CALL_UNHANDLED(NOTREACHED())
65 int32_t VideoCaptureResource::EnumerateDevices0_2(
67 scoped_refptr<TrackedCallback> callback) {
68 return enumeration_helper_.EnumerateDevices0_2(devices, callback);
71 int32_t VideoCaptureResource::EnumerateDevices(
72 const PP_ArrayOutput& output,
73 scoped_refptr<TrackedCallback> callback) {
74 return enumeration_helper_.EnumerateDevices(output, callback);
77 int32_t VideoCaptureResource::MonitorDeviceChange(
78 PP_MonitorDeviceChangeCallback callback,
80 return enumeration_helper_.MonitorDeviceChange(callback, user_data);
83 int32_t VideoCaptureResource::Open(
84 const std::string& device_id,
85 const PP_VideoCaptureDeviceInfo_Dev& requested_info,
86 uint32_t buffer_count,
87 scoped_refptr<TrackedCallback> callback) {
88 if (open_state_ != BEFORE_OPEN)
89 return PP_ERROR_FAILED;
91 if (TrackedCallback::IsPending(open_callback_))
92 return PP_ERROR_INPROGRESS;
94 open_callback_ = callback;
96 Call<PpapiPluginMsg_VideoCapture_OpenReply>(
98 PpapiHostMsg_VideoCapture_Open(device_id, requested_info, buffer_count),
99 base::Bind(&VideoCaptureResource::OnPluginMsgOpenReply, this));
100 return PP_OK_COMPLETIONPENDING;
103 int32_t VideoCaptureResource::StartCapture() {
104 if (open_state_ != OPENED)
105 return PP_ERROR_FAILED;
107 Post(RENDERER, PpapiHostMsg_VideoCapture_StartCapture());
111 int32_t VideoCaptureResource::ReuseBuffer(uint32_t buffer) {
112 if (buffer >= buffer_in_use_.size() || !buffer_in_use_[buffer])
113 return PP_ERROR_BADARGUMENT;
114 Post(RENDERER, PpapiHostMsg_VideoCapture_ReuseBuffer(buffer));
118 int32_t VideoCaptureResource::StopCapture() {
119 if (open_state_ != OPENED)
120 return PP_ERROR_FAILED;
122 Post(RENDERER, PpapiHostMsg_VideoCapture_StopCapture());
126 void VideoCaptureResource::Close() {
127 if (open_state_ == CLOSED)
130 Post(RENDERER, PpapiHostMsg_VideoCapture_Close());
132 open_state_ = CLOSED;
134 if (TrackedCallback::IsPending(open_callback_))
135 open_callback_->PostAbort();
138 int32_t VideoCaptureResource::EnumerateDevicesSync(
139 const PP_ArrayOutput& devices) {
140 return enumeration_helper_.EnumerateDevicesSync(devices);
143 void VideoCaptureResource::LastPluginRefWasDeleted() {
144 enumeration_helper_.LastPluginRefWasDeleted();
147 void VideoCaptureResource::OnPluginMsgOnDeviceInfo(
148 const ResourceMessageReplyParams& params,
149 const struct PP_VideoCaptureDeviceInfo_Dev& info,
150 const std::vector<HostResource>& buffers,
151 uint32_t buffer_size) {
152 if (!ppp_video_capture_impl_)
155 std::vector<base::SharedMemoryHandle> handles;
156 params.TakeAllSharedMemoryHandles(&handles);
157 CHECK(handles.size() == buffers.size());
159 PluginResourceTracker* tracker =
160 PluginGlobals::Get()->plugin_resource_tracker();
161 scoped_ptr<PP_Resource[]> resources(new PP_Resource[buffers.size()]);
162 for (size_t i = 0; i < buffers.size(); ++i) {
163 // We assume that the browser created a new set of resources.
164 DCHECK(!tracker->PluginResourceForHostResource(buffers[i]));
165 resources[i] = ppapi::proxy::PPB_Buffer_Proxy::AddProxyResource(
166 buffers[i], handles[i], buffer_size);
169 buffer_in_use_ = std::vector<bool>(buffers.size());
171 CallWhileUnlocked(ppp_video_capture_impl_->OnDeviceInfo,
175 static_cast<uint32_t>(buffers.size()),
176 const_cast<const PP_Resource*>(resources.get()));
178 for (size_t i = 0; i < buffers.size(); ++i)
179 tracker->ReleaseResource(resources[i]);
182 void VideoCaptureResource::OnPluginMsgOnStatus(
183 const ResourceMessageReplyParams& params,
186 case PP_VIDEO_CAPTURE_STATUS_STARTING:
187 case PP_VIDEO_CAPTURE_STATUS_STOPPING:
188 // Those states are not sent by the browser.
192 if (ppp_video_capture_impl_) {
193 CallWhileUnlocked(ppp_video_capture_impl_->OnStatus,
200 void VideoCaptureResource::OnPluginMsgOnError(
201 const ResourceMessageReplyParams& params,
202 uint32_t error_code) {
203 open_state_ = CLOSED;
204 if (ppp_video_capture_impl_) {
205 CallWhileUnlocked(ppp_video_capture_impl_->OnError,
212 void VideoCaptureResource::OnPluginMsgOnBufferReady(
213 const ResourceMessageReplyParams& params,
215 SetBufferInUse(buffer);
216 if (ppp_video_capture_impl_) {
217 CallWhileUnlocked(ppp_video_capture_impl_->OnBufferReady,
224 void VideoCaptureResource::OnPluginMsgOpenReply(
225 const ResourceMessageReplyParams& params) {
226 if (open_state_ == BEFORE_OPEN && params.result() == PP_OK)
227 open_state_ = OPENED;
229 // The callback may have been aborted by Close().
230 if (TrackedCallback::IsPending(open_callback_))
231 open_callback_->Run(params.result());
234 void VideoCaptureResource::SetBufferInUse(uint32_t buffer_index) {
235 CHECK(buffer_index < buffer_in_use_.size());
236 buffer_in_use_[buffer_index] = true;