- add sources.
[platform/framework/web/crosswalk.git] / src / ppapi / proxy / video_capture_resource.cc
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
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
34 VideoCaptureResource::~VideoCaptureResource() {
35 }
36
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   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,
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   IPC_END_MESSAGE_MAP()
63 }
64
65 int32_t VideoCaptureResource::EnumerateDevices0_2(
66     PP_Resource* devices,
67     scoped_refptr<TrackedCallback> callback) {
68   return enumeration_helper_.EnumerateDevices0_2(devices, callback);
69 }
70
71 int32_t VideoCaptureResource::EnumerateDevices(
72     const PP_ArrayOutput& output,
73     scoped_refptr<TrackedCallback> callback) {
74   return enumeration_helper_.EnumerateDevices(output, callback);
75 }
76
77 int32_t VideoCaptureResource::MonitorDeviceChange(
78     PP_MonitorDeviceChangeCallback callback,
79     void* user_data) {
80   return enumeration_helper_.MonitorDeviceChange(callback, user_data);
81 }
82
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;
90
91   if (TrackedCallback::IsPending(open_callback_))
92     return PP_ERROR_INPROGRESS;
93
94   open_callback_ = callback;
95
96   Call<PpapiPluginMsg_VideoCapture_OpenReply>(
97       RENDERER,
98       PpapiHostMsg_VideoCapture_Open(device_id, requested_info, buffer_count),
99       base::Bind(&VideoCaptureResource::OnPluginMsgOpenReply, this));
100   return PP_OK_COMPLETIONPENDING;
101 }
102
103 int32_t VideoCaptureResource::StartCapture() {
104   if (open_state_ != OPENED)
105     return PP_ERROR_FAILED;
106
107   Post(RENDERER, PpapiHostMsg_VideoCapture_StartCapture());
108   return PP_OK;
109 }
110
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));
115   return PP_OK;
116 }
117
118 int32_t VideoCaptureResource::StopCapture() {
119   if (open_state_ != OPENED)
120     return PP_ERROR_FAILED;
121
122   Post(RENDERER, PpapiHostMsg_VideoCapture_StopCapture());
123   return PP_OK;
124 }
125
126 void VideoCaptureResource::Close() {
127   if (open_state_ == CLOSED)
128     return;
129
130   Post(RENDERER, PpapiHostMsg_VideoCapture_Close());
131
132   open_state_ = CLOSED;
133
134   if (TrackedCallback::IsPending(open_callback_))
135     open_callback_->PostAbort();
136 }
137
138 int32_t VideoCaptureResource::EnumerateDevicesSync(
139     const PP_ArrayOutput& devices) {
140   return enumeration_helper_.EnumerateDevicesSync(devices);
141 }
142
143 void VideoCaptureResource::LastPluginRefWasDeleted() {
144   enumeration_helper_.LastPluginRefWasDeleted();
145 }
146
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_)
153     return;
154
155   std::vector<base::SharedMemoryHandle> handles;
156   params.TakeAllSharedMemoryHandles(&handles);
157   CHECK(handles.size() == buffers.size());
158
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);
167   }
168
169   buffer_in_use_ = std::vector<bool>(buffers.size());
170
171   CallWhileUnlocked(ppp_video_capture_impl_->OnDeviceInfo,
172                     pp_instance(),
173                     pp_resource(),
174                     &info,
175                     static_cast<uint32_t>(buffers.size()),
176                     const_cast<const PP_Resource*>(resources.get()));
177
178   for (size_t i = 0; i < buffers.size(); ++i)
179     tracker->ReleaseResource(resources[i]);
180 }
181
182 void VideoCaptureResource::OnPluginMsgOnStatus(
183     const ResourceMessageReplyParams& params,
184     uint32_t status) {
185   switch (status) {
186     case PP_VIDEO_CAPTURE_STATUS_STARTING:
187     case PP_VIDEO_CAPTURE_STATUS_STOPPING:
188       // Those states are not sent by the browser.
189       NOTREACHED();
190       break;
191   }
192   if (ppp_video_capture_impl_) {
193     CallWhileUnlocked(ppp_video_capture_impl_->OnStatus,
194                       pp_instance(),
195                       pp_resource(),
196                       status);
197   }
198 }
199
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,
206                       pp_instance(),
207                       pp_resource(),
208                       error_code);
209   }
210 }
211
212 void VideoCaptureResource::OnPluginMsgOnBufferReady(
213     const ResourceMessageReplyParams& params,
214     uint32_t buffer) {
215   SetBufferInUse(buffer);
216   if (ppp_video_capture_impl_) {
217     CallWhileUnlocked(ppp_video_capture_impl_->OnBufferReady,
218                       pp_instance(),
219                       pp_resource(),
220                       buffer);
221   }
222 }
223
224 void VideoCaptureResource::OnPluginMsgOpenReply(
225     const ResourceMessageReplyParams& params) {
226   if (open_state_ == BEFORE_OPEN && params.result() == PP_OK)
227     open_state_ = OPENED;
228
229   // The callback may have been aborted by Close().
230   if (TrackedCallback::IsPending(open_callback_))
231     open_callback_->Run(params.result());
232 }
233
234 void VideoCaptureResource::SetBufferInUse(uint32_t buffer_index) {
235   CHECK(buffer_index < buffer_in_use_.size());
236   buffer_in_use_[buffer_index] = true;
237 }
238
239 }  // namespace proxy
240 }  // namespace ppapi