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   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
    241