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 PP_ArrayOutput& devices) { | |
yzshen1
2012/11/14 17:55:36
const please.
victorhsieh
2012/11/14 22:47:35
I tried to avoid having a const here, that's why I
yzshen1
2012/11/14 23:01:03
This is not an output "buffer" itself. Strictly sp
victorhsieh
2012/11/14 23:23:09
Done.
| |
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 |