OLD | NEW |
(Empty) | |
| 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. |
| 4 |
| 5 #include "ppapi/proxy/video_capture_resource.h" |
| 6 |
| 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/array_writer.h" |
| 16 #include "ppapi/shared_impl/proxy_lock.h" |
| 17 #include "ppapi/shared_impl/tracked_callback.h" |
| 18 |
| 19 namespace ppapi { |
| 20 namespace proxy { |
| 21 |
| 22 VideoCaptureResource::VideoCaptureResource( |
| 23 Connection connection, |
| 24 PP_Instance instance, |
| 25 PluginDispatcher* dispatcher) |
| 26 : PluginResource(connection, instance), |
| 27 open_state_(BEFORE_OPEN), |
| 28 has_pending_enum_devices_callback_(false) { |
| 29 SendCreate(RENDERER, PpapiHostMsg_VideoCapture_Create()); |
| 30 |
| 31 ppp_video_capture_impl_ = static_cast<const PPP_VideoCapture_Dev*>( |
| 32 dispatcher->local_get_interface()(PPP_VIDEO_CAPTURE_DEV_INTERFACE)); |
| 33 } |
| 34 |
| 35 VideoCaptureResource::~VideoCaptureResource() { |
| 36 } |
| 37 |
| 38 void VideoCaptureResource::OnReplyReceived( |
| 39 const ResourceMessageReplyParams& params, |
| 40 const IPC::Message& msg) { |
| 41 if (params.sequence()) { |
| 42 PluginResource::OnReplyReceived(params, msg); |
| 43 return; |
| 44 } |
| 45 |
| 46 IPC_BEGIN_MESSAGE_MAP(VideoCaptureResource, msg) |
| 47 PPAPI_DISPATCH_PLUGIN_RESOURCE_CALL( |
| 48 PpapiPluginMsg_VideoCapture_OnDeviceInfo, |
| 49 OnPluginMsgOnDeviceInfo) |
| 50 PPAPI_DISPATCH_PLUGIN_RESOURCE_CALL( |
| 51 PpapiPluginMsg_VideoCapture_OnStatus, |
| 52 OnPluginMsgOnStatus) |
| 53 PPAPI_DISPATCH_PLUGIN_RESOURCE_CALL( |
| 54 PpapiPluginMsg_VideoCapture_OnError, |
| 55 OnPluginMsgOnError) |
| 56 PPAPI_DISPATCH_PLUGIN_RESOURCE_CALL( |
| 57 PpapiPluginMsg_VideoCapture_OnBufferReady, |
| 58 OnPluginMsgOnBufferReady) |
| 59 PPAPI_DISPATCH_PLUGIN_RESOURCE_CALL_UNHANDLED(NOTREACHED()) |
| 60 IPC_END_MESSAGE_MAP() |
| 61 } |
| 62 |
| 63 int32_t VideoCaptureResource::EnumerateDevices( |
| 64 PP_Resource* devices, |
| 65 scoped_refptr<TrackedCallback> callback) { |
| 66 if (has_pending_enum_devices_callback_) |
| 67 return PP_ERROR_INPROGRESS; |
| 68 |
| 69 has_pending_enum_devices_callback_ = true; |
| 70 |
| 71 Call<PpapiPluginMsg_VideoCapture_EnumerateDevicesReply>( |
| 72 RENDERER, |
| 73 PpapiHostMsg_VideoCapture_EnumerateDevices(), |
| 74 base::Bind(&VideoCaptureResource::OnPluginMsgEnumerateDevicesReply, |
| 75 this, |
| 76 devices, |
| 77 callback)); |
| 78 return PP_OK_COMPLETIONPENDING; |
| 79 } |
| 80 |
| 81 int32_t VideoCaptureResource::Open( |
| 82 const std::string& device_id, |
| 83 const PP_VideoCaptureDeviceInfo_Dev& requested_info, |
| 84 uint32_t buffer_count, |
| 85 scoped_refptr<TrackedCallback> callback) { |
| 86 if (open_state_ != BEFORE_OPEN) |
| 87 return PP_ERROR_FAILED; |
| 88 |
| 89 if (TrackedCallback::IsPending(open_callback_)) |
| 90 return PP_ERROR_INPROGRESS; |
| 91 |
| 92 open_callback_ = callback; |
| 93 |
| 94 Call<PpapiPluginMsg_VideoCapture_OpenReply>( |
| 95 RENDERER, |
| 96 PpapiHostMsg_VideoCapture_Open(device_id, requested_info, buffer_count), |
| 97 base::Bind(&VideoCaptureResource::OnPluginMsgOpenReply, this)); |
| 98 return PP_OK_COMPLETIONPENDING; |
| 99 } |
| 100 |
| 101 int32_t VideoCaptureResource::StartCapture() { |
| 102 if (open_state_ != OPENED) |
| 103 return PP_ERROR_FAILED; |
| 104 |
| 105 buffer_in_use_.clear(); |
| 106 Post(RENDERER, PpapiHostMsg_VideoCapture_StartCapture()); |
| 107 return PP_OK; |
| 108 } |
| 109 |
| 110 int32_t VideoCaptureResource::ReuseBuffer(uint32_t buffer) { |
| 111 if (buffer >= buffer_in_use_.size() || !buffer_in_use_[buffer]) |
| 112 return PP_ERROR_BADARGUMENT; |
| 113 Post(RENDERER, PpapiHostMsg_VideoCapture_ReuseBuffer(buffer)); |
| 114 return PP_OK; |
| 115 } |
| 116 |
| 117 int32_t VideoCaptureResource::StopCapture() { |
| 118 if (open_state_ != OPENED) |
| 119 return PP_ERROR_FAILED; |
| 120 |
| 121 Post(RENDERER, PpapiHostMsg_VideoCapture_StopCapture()); |
| 122 return PP_OK; |
| 123 } |
| 124 |
| 125 void VideoCaptureResource::Close() { |
| 126 if (open_state_ == CLOSED) |
| 127 return; |
| 128 |
| 129 Post(RENDERER, PpapiHostMsg_VideoCapture_Close()); |
| 130 |
| 131 open_state_ = CLOSED; |
| 132 |
| 133 if (TrackedCallback::IsPending(open_callback_)) |
| 134 open_callback_->PostAbort(); |
| 135 } |
| 136 |
| 137 int32_t VideoCaptureResource::EnumerateDevicesSync( |
| 138 const PP_ArrayOutput& devices) { |
| 139 ArrayWriter output; |
| 140 output.set_pp_array_output(devices); |
| 141 if (!output.is_valid()) |
| 142 return PP_ERROR_BADARGUMENT; |
| 143 |
| 144 std::vector<ppapi::DeviceRefData> device_ref_data; |
| 145 int32_t result = SyncCall<PpapiPluginMsg_VideoCapture_EnumerateDevicesReply>( |
| 146 RENDERER, |
| 147 PpapiHostMsg_VideoCapture_EnumerateDevices(), |
| 148 &device_ref_data); |
| 149 |
| 150 std::vector<scoped_refptr<Resource> > device_resources; |
| 151 for (size_t i = 0; i < device_ref_data.size(); ++i) { |
| 152 scoped_refptr<Resource> resource(new PPB_DeviceRef_Shared( |
| 153 OBJECT_IS_PROXY, pp_instance(), device_ref_data[i])); |
| 154 device_resources.push_back(resource); |
| 155 } |
| 156 |
| 157 if (!output.StoreResourceVector(device_resources)) |
| 158 return PP_ERROR_FAILED; |
| 159 |
| 160 return result; |
| 161 } |
| 162 |
| 163 void VideoCaptureResource::OnPluginMsgOnDeviceInfo( |
| 164 const ResourceMessageReplyParams& params, |
| 165 const struct PP_VideoCaptureDeviceInfo_Dev& info, |
| 166 const std::vector<HostResource>& buffers, |
| 167 uint32_t buffer_size) { |
| 168 if (!ppp_video_capture_impl_) |
| 169 return; |
| 170 |
| 171 std::vector<base::SharedMemoryHandle> handles; |
| 172 params.TakeAllSharedMemoryHandles(&handles); |
| 173 CHECK(handles.size() == buffers.size()); |
| 174 |
| 175 PluginResourceTracker* tracker = |
| 176 PluginGlobals::Get()->plugin_resource_tracker(); |
| 177 scoped_array<PP_Resource> resources(new PP_Resource[buffers.size()]); |
| 178 for (size_t i = 0; i < buffers.size(); ++i) { |
| 179 // We assume that the browser created a new set of resources. |
| 180 DCHECK(!tracker->PluginResourceForHostResource(buffers[i])); |
| 181 resources[i] = ppapi::proxy::PPB_Buffer_Proxy::AddProxyResource( |
| 182 buffers[i], handles[i], buffer_size); |
| 183 } |
| 184 |
| 185 buffer_in_use_ = std::vector<bool>(buffers.size()); |
| 186 |
| 187 CallWhileUnlocked(ppp_video_capture_impl_->OnDeviceInfo, |
| 188 pp_instance(), |
| 189 pp_resource(), |
| 190 &info, |
| 191 static_cast<uint32_t>(buffers.size()), |
| 192 const_cast<const PP_Resource*>(resources.get())); |
| 193 |
| 194 for (size_t i = 0; i < buffers.size(); ++i) |
| 195 tracker->ReleaseResource(resources[i]); |
| 196 } |
| 197 |
| 198 void VideoCaptureResource::OnPluginMsgOnStatus( |
| 199 const ResourceMessageReplyParams& params, |
| 200 uint32_t status) { |
| 201 switch (status) { |
| 202 case PP_VIDEO_CAPTURE_STATUS_STARTING: |
| 203 case PP_VIDEO_CAPTURE_STATUS_STOPPING: |
| 204 // Those states are not sent by the browser. |
| 205 NOTREACHED(); |
| 206 break; |
| 207 } |
| 208 if (ppp_video_capture_impl_) { |
| 209 CallWhileUnlocked(ppp_video_capture_impl_->OnStatus, |
| 210 pp_instance(), |
| 211 pp_resource(), |
| 212 status); |
| 213 } |
| 214 } |
| 215 |
| 216 void VideoCaptureResource::OnPluginMsgOnError( |
| 217 const ResourceMessageReplyParams& params, |
| 218 uint32_t error_code) { |
| 219 open_state_ = CLOSED; |
| 220 if (ppp_video_capture_impl_) { |
| 221 CallWhileUnlocked(ppp_video_capture_impl_->OnError, |
| 222 pp_instance(), |
| 223 pp_resource(), |
| 224 error_code); |
| 225 } |
| 226 } |
| 227 |
| 228 void VideoCaptureResource::OnPluginMsgOnBufferReady( |
| 229 const ResourceMessageReplyParams& params, |
| 230 uint32_t buffer) { |
| 231 SetBufferInUse(buffer); |
| 232 if (ppp_video_capture_impl_) { |
| 233 CallWhileUnlocked(ppp_video_capture_impl_->OnBufferReady, |
| 234 pp_instance(), |
| 235 pp_resource(), |
| 236 buffer); |
| 237 } |
| 238 } |
| 239 |
| 240 void VideoCaptureResource::OnPluginMsgOpenReply( |
| 241 const ResourceMessageReplyParams& params) { |
| 242 if (open_state_ == BEFORE_OPEN && params.result() == PP_OK) |
| 243 open_state_ = OPENED; |
| 244 |
| 245 // The callback may have been aborted by Close(). |
| 246 if (TrackedCallback::IsPending(open_callback_)) |
| 247 open_callback_->Run(params.result()); |
| 248 } |
| 249 |
| 250 void VideoCaptureResource::OnPluginMsgEnumerateDevicesReply( |
| 251 PP_Resource* devices_output, |
| 252 scoped_refptr<TrackedCallback> callback, |
| 253 const ResourceMessageReplyParams& params, |
| 254 const std::vector<DeviceRefData>& devices) { |
| 255 if (!TrackedCallback::IsPending(callback)) |
| 256 return; |
| 257 |
| 258 DCHECK(has_pending_enum_devices_callback_); |
| 259 has_pending_enum_devices_callback_ = false; |
| 260 |
| 261 if (params.result() == PP_OK && devices_output) { |
| 262 // devices_output points to the resource array of PP_ArrayOutput. In C++, |
| 263 // it's typically allocated in VideoCapture_Dev. |
| 264 *devices_output = PPB_DeviceRef_Shared::CreateResourceArray( |
| 265 OBJECT_IS_PROXY, pp_instance(), devices); |
| 266 } |
| 267 |
| 268 callback->Run(params.result()); |
| 269 } |
| 270 |
| 271 void VideoCaptureResource::SetBufferInUse(uint32_t buffer_index) { |
| 272 DCHECK(buffer_index < buffer_in_use_.size()); |
| 273 buffer_in_use_[buffer_index] = true; |
| 274 } |
| 275 |
| 276 } // namespace proxy |
| 277 } // namespace ppapi |
OLD | NEW |