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 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
,
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())
62 PPAPI_END_MESSAGE_MAP()
65 int32_t VideoCaptureResource::EnumerateDevices(
66 const PP_ArrayOutput
& output
,
67 scoped_refptr
<TrackedCallback
> callback
) {
68 return enumeration_helper_
.EnumerateDevices(output
, callback
);
71 int32_t VideoCaptureResource::MonitorDeviceChange(
72 PP_MonitorDeviceChangeCallback callback
,
74 return enumeration_helper_
.MonitorDeviceChange(callback
, user_data
);
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
;
85 if (TrackedCallback::IsPending(open_callback_
))
86 return PP_ERROR_INPROGRESS
;
88 open_callback_
= callback
;
90 Call
<PpapiPluginMsg_VideoCapture_OpenReply
>(
92 PpapiHostMsg_VideoCapture_Open(device_id
, requested_info
, buffer_count
),
93 base::Bind(&VideoCaptureResource::OnPluginMsgOpenReply
, this));
94 return PP_OK_COMPLETIONPENDING
;
97 int32_t VideoCaptureResource::StartCapture() {
98 if (open_state_
!= OPENED
)
99 return PP_ERROR_FAILED
;
101 Post(RENDERER
, PpapiHostMsg_VideoCapture_StartCapture());
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
));
112 int32_t VideoCaptureResource::StopCapture() {
113 if (open_state_
!= OPENED
)
114 return PP_ERROR_FAILED
;
116 Post(RENDERER
, PpapiHostMsg_VideoCapture_StopCapture());
120 void VideoCaptureResource::Close() {
121 if (open_state_
== CLOSED
)
124 Post(RENDERER
, PpapiHostMsg_VideoCapture_Close());
126 open_state_
= CLOSED
;
128 if (TrackedCallback::IsPending(open_callback_
))
129 open_callback_
->PostAbort();
132 int32_t VideoCaptureResource::EnumerateDevicesSync(
133 const PP_ArrayOutput
& devices
) {
134 return enumeration_helper_
.EnumerateDevicesSync(devices
);
137 void VideoCaptureResource::LastPluginRefWasDeleted() {
138 enumeration_helper_
.LastPluginRefWasDeleted();
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_
)
149 std::vector
<base::SharedMemoryHandle
> handles
;
150 params
.TakeAllSharedMemoryHandles(&handles
);
151 CHECK(handles
.size() == buffers
.size());
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
);
163 buffer_in_use_
= std::vector
<bool>(buffers
.size());
165 CallWhileUnlocked(ppp_video_capture_impl_
->OnDeviceInfo
,
169 static_cast<uint32_t>(buffers
.size()),
170 const_cast<const PP_Resource
*>(resources
.get()));
172 for (size_t i
= 0; i
< buffers
.size(); ++i
)
173 tracker
->ReleaseResource(resources
[i
]);
176 void VideoCaptureResource::OnPluginMsgOnStatus(
177 const ResourceMessageReplyParams
& params
,
180 case PP_VIDEO_CAPTURE_STATUS_STARTING
:
181 case PP_VIDEO_CAPTURE_STATUS_STOPPING
:
182 // Those states are not sent by the browser.
186 if (ppp_video_capture_impl_
) {
187 CallWhileUnlocked(ppp_video_capture_impl_
->OnStatus
,
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
,
206 void VideoCaptureResource::OnPluginMsgOnBufferReady(
207 const ResourceMessageReplyParams
& params
,
209 SetBufferInUse(buffer
);
210 if (ppp_video_capture_impl_
) {
211 CallWhileUnlocked(ppp_video_capture_impl_
->OnBufferReady
,
218 void VideoCaptureResource::OnPluginMsgOpenReply(
219 const ResourceMessageReplyParams
& params
) {
220 if (open_state_
== BEFORE_OPEN
&& params
.result() == PP_OK
)
221 open_state_
= OPENED
;
223 // The callback may have been aborted by Close().
224 if (TrackedCallback::IsPending(open_callback_
))
225 open_callback_
->Run(params
.result());
228 void VideoCaptureResource::SetBufferInUse(uint32_t buffer_index
) {
229 CHECK(buffer_index
< buffer_in_use_
.size());
230 buffer_in_use_
[buffer_index
] = true;