Home | History | Annotate | Download | only in proxy
      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   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 
     65 int32_t VideoCaptureResource::EnumerateDevices(
     66     const PP_ArrayOutput& output,
     67     scoped_refptr<TrackedCallback> callback) {
     68   return enumeration_helper_.EnumerateDevices(output, callback);
     69 }
     70 
     71 int32_t VideoCaptureResource::MonitorDeviceChange(
     72     PP_MonitorDeviceChangeCallback callback,
     73     void* user_data) {
     74   return enumeration_helper_.MonitorDeviceChange(callback, user_data);
     75 }
     76 
     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 
     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 
    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 
    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 
    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 
    132 int32_t VideoCaptureResource::EnumerateDevicesSync(
    133     const PP_ArrayOutput& devices) {
    134   return enumeration_helper_.EnumerateDevicesSync(devices);
    135 }
    136 
    137 void VideoCaptureResource::LastPluginRefWasDeleted() {
    138   enumeration_helper_.LastPluginRefWasDeleted();
    139 }
    140 
    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                     buffers.size(),
    170                     resources.get());
    171 
    172   for (size_t i = 0; i < buffers.size(); ++i)
    173     tracker->ReleaseResource(resources[i]);
    174 }
    175 
    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 
    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 
    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 
    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 
    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