• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/proxy_lock.h"
16 #include "ppapi/shared_impl/tracked_callback.h"
17 
18 namespace ppapi {
19 namespace proxy {
20 
VideoCaptureResource(Connection connection,PP_Instance instance,PluginDispatcher * dispatcher)21 VideoCaptureResource::VideoCaptureResource(
22     Connection connection,
23     PP_Instance instance,
24     PluginDispatcher* dispatcher)
25     : PluginResource(connection, instance),
26       open_state_(BEFORE_OPEN),
27       enumeration_helper_(this) {
28   SendCreate(RENDERER, PpapiHostMsg_VideoCapture_Create());
29 
30   ppp_video_capture_impl_ = static_cast<const PPP_VideoCapture_Dev*>(
31       dispatcher->local_get_interface()(PPP_VIDEO_CAPTURE_DEV_INTERFACE));
32 }
33 
~VideoCaptureResource()34 VideoCaptureResource::~VideoCaptureResource() {
35 }
36 
OnReplyReceived(const ResourceMessageReplyParams & params,const IPC::Message & msg)37 void VideoCaptureResource::OnReplyReceived(
38     const ResourceMessageReplyParams& params,
39     const IPC::Message& msg) {
40   if (enumeration_helper_.HandleReply(params, msg))
41     return;
42 
43   if (params.sequence()) {
44     PluginResource::OnReplyReceived(params, msg);
45     return;
46   }
47 
48   PPAPI_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,
54         OnPluginMsgOnStatus)
55     PPAPI_DISPATCH_PLUGIN_RESOURCE_CALL(
56         PpapiPluginMsg_VideoCapture_OnError,
57         OnPluginMsgOnError)
58     PPAPI_DISPATCH_PLUGIN_RESOURCE_CALL(
59         PpapiPluginMsg_VideoCapture_OnBufferReady,
60         OnPluginMsgOnBufferReady)
61     PPAPI_DISPATCH_PLUGIN_RESOURCE_CALL_UNHANDLED(NOTREACHED())
62   PPAPI_END_MESSAGE_MAP()
63 }
64 
EnumerateDevices(const PP_ArrayOutput & output,scoped_refptr<TrackedCallback> callback)65 int32_t VideoCaptureResource::EnumerateDevices(
66     const PP_ArrayOutput& output,
67     scoped_refptr<TrackedCallback> callback) {
68   return enumeration_helper_.EnumerateDevices(output, callback);
69 }
70 
MonitorDeviceChange(PP_MonitorDeviceChangeCallback callback,void * user_data)71 int32_t VideoCaptureResource::MonitorDeviceChange(
72     PP_MonitorDeviceChangeCallback callback,
73     void* user_data) {
74   return enumeration_helper_.MonitorDeviceChange(callback, user_data);
75 }
76 
Open(const std::string & device_id,const PP_VideoCaptureDeviceInfo_Dev & requested_info,uint32_t buffer_count,scoped_refptr<TrackedCallback> callback)77 int32_t VideoCaptureResource::Open(
78     const std::string& device_id,
79     const PP_VideoCaptureDeviceInfo_Dev& requested_info,
80     uint32_t buffer_count,
81     scoped_refptr<TrackedCallback> callback) {
82   if (open_state_ != BEFORE_OPEN)
83     return PP_ERROR_FAILED;
84 
85   if (TrackedCallback::IsPending(open_callback_))
86     return PP_ERROR_INPROGRESS;
87 
88   open_callback_ = callback;
89 
90   Call<PpapiPluginMsg_VideoCapture_OpenReply>(
91       RENDERER,
92       PpapiHostMsg_VideoCapture_Open(device_id, requested_info, buffer_count),
93       base::Bind(&VideoCaptureResource::OnPluginMsgOpenReply, this));
94   return PP_OK_COMPLETIONPENDING;
95 }
96 
StartCapture()97 int32_t VideoCaptureResource::StartCapture() {
98   if (open_state_ != OPENED)
99     return PP_ERROR_FAILED;
100 
101   Post(RENDERER, PpapiHostMsg_VideoCapture_StartCapture());
102   return PP_OK;
103 }
104 
ReuseBuffer(uint32_t buffer)105 int32_t VideoCaptureResource::ReuseBuffer(uint32_t buffer) {
106   if (buffer >= buffer_in_use_.size() || !buffer_in_use_[buffer])
107     return PP_ERROR_BADARGUMENT;
108   Post(RENDERER, PpapiHostMsg_VideoCapture_ReuseBuffer(buffer));
109   return PP_OK;
110 }
111 
StopCapture()112 int32_t VideoCaptureResource::StopCapture() {
113   if (open_state_ != OPENED)
114     return PP_ERROR_FAILED;
115 
116   Post(RENDERER, PpapiHostMsg_VideoCapture_StopCapture());
117   return PP_OK;
118 }
119 
Close()120 void VideoCaptureResource::Close() {
121   if (open_state_ == CLOSED)
122     return;
123 
124   Post(RENDERER, PpapiHostMsg_VideoCapture_Close());
125 
126   open_state_ = CLOSED;
127 
128   if (TrackedCallback::IsPending(open_callback_))
129     open_callback_->PostAbort();
130 }
131 
EnumerateDevicesSync(const PP_ArrayOutput & devices)132 int32_t VideoCaptureResource::EnumerateDevicesSync(
133     const PP_ArrayOutput& devices) {
134   return enumeration_helper_.EnumerateDevicesSync(devices);
135 }
136 
LastPluginRefWasDeleted()137 void VideoCaptureResource::LastPluginRefWasDeleted() {
138   enumeration_helper_.LastPluginRefWasDeleted();
139 }
140 
OnPluginMsgOnDeviceInfo(const ResourceMessageReplyParams & params,const struct PP_VideoCaptureDeviceInfo_Dev & info,const std::vector<HostResource> & buffers,uint32_t buffer_size)141 void VideoCaptureResource::OnPluginMsgOnDeviceInfo(
142     const ResourceMessageReplyParams& params,
143     const struct PP_VideoCaptureDeviceInfo_Dev& info,
144     const std::vector<HostResource>& buffers,
145     uint32_t buffer_size) {
146   if (!ppp_video_capture_impl_)
147     return;
148 
149   std::vector<base::SharedMemoryHandle> handles;
150   params.TakeAllSharedMemoryHandles(&handles);
151   CHECK(handles.size() == buffers.size());
152 
153   PluginResourceTracker* tracker =
154       PluginGlobals::Get()->plugin_resource_tracker();
155   scoped_ptr<PP_Resource[]> resources(new PP_Resource[buffers.size()]);
156   for (size_t i = 0; i < buffers.size(); ++i) {
157     // We assume that the browser created a new set of resources.
158     DCHECK(!tracker->PluginResourceForHostResource(buffers[i]));
159     resources[i] = ppapi::proxy::PPB_Buffer_Proxy::AddProxyResource(
160         buffers[i], handles[i], buffer_size);
161   }
162 
163   buffer_in_use_ = std::vector<bool>(buffers.size());
164 
165   CallWhileUnlocked(ppp_video_capture_impl_->OnDeviceInfo,
166                     pp_instance(),
167                     pp_resource(),
168                     &info,
169                     static_cast<uint32_t>(buffers.size()),
170                     const_cast<const PP_Resource*>(resources.get()));
171 
172   for (size_t i = 0; i < buffers.size(); ++i)
173     tracker->ReleaseResource(resources[i]);
174 }
175 
OnPluginMsgOnStatus(const ResourceMessageReplyParams & params,uint32_t status)176 void VideoCaptureResource::OnPluginMsgOnStatus(
177     const ResourceMessageReplyParams& params,
178     uint32_t status) {
179   switch (status) {
180     case PP_VIDEO_CAPTURE_STATUS_STARTING:
181     case PP_VIDEO_CAPTURE_STATUS_STOPPING:
182       // Those states are not sent by the browser.
183       NOTREACHED();
184       break;
185   }
186   if (ppp_video_capture_impl_) {
187     CallWhileUnlocked(ppp_video_capture_impl_->OnStatus,
188                       pp_instance(),
189                       pp_resource(),
190                       status);
191   }
192 }
193 
OnPluginMsgOnError(const ResourceMessageReplyParams & params,uint32_t error_code)194 void VideoCaptureResource::OnPluginMsgOnError(
195     const ResourceMessageReplyParams& params,
196     uint32_t error_code) {
197   open_state_ = CLOSED;
198   if (ppp_video_capture_impl_) {
199     CallWhileUnlocked(ppp_video_capture_impl_->OnError,
200                       pp_instance(),
201                       pp_resource(),
202                       error_code);
203   }
204 }
205 
OnPluginMsgOnBufferReady(const ResourceMessageReplyParams & params,uint32_t buffer)206 void VideoCaptureResource::OnPluginMsgOnBufferReady(
207     const ResourceMessageReplyParams& params,
208     uint32_t buffer) {
209   SetBufferInUse(buffer);
210   if (ppp_video_capture_impl_) {
211     CallWhileUnlocked(ppp_video_capture_impl_->OnBufferReady,
212                       pp_instance(),
213                       pp_resource(),
214                       buffer);
215   }
216 }
217 
OnPluginMsgOpenReply(const ResourceMessageReplyParams & params)218 void VideoCaptureResource::OnPluginMsgOpenReply(
219     const ResourceMessageReplyParams& params) {
220   if (open_state_ == BEFORE_OPEN && params.result() == PP_OK)
221     open_state_ = OPENED;
222 
223   // The callback may have been aborted by Close().
224   if (TrackedCallback::IsPending(open_callback_))
225     open_callback_->Run(params.result());
226 }
227 
SetBufferInUse(uint32_t buffer_index)228 void VideoCaptureResource::SetBufferInUse(uint32_t buffer_index) {
229   CHECK(buffer_index < buffer_in_use_.size());
230   buffer_in_use_[buffer_index] = true;
231 }
232 
233 }  // namespace proxy
234 }  // namespace ppapi
235