Home | History | Annotate | Download | only in pepper
      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 "content/renderer/pepper/pepper_platform_video_capture.h"
      6 
      7 #include "base/bind.h"
      8 #include "base/logging.h"
      9 #include "base/message_loop/message_loop_proxy.h"
     10 #include "content/renderer/media/video_capture_impl_manager.h"
     11 #include "content/renderer/pepper/pepper_media_device_manager.h"
     12 #include "content/renderer/pepper/pepper_video_capture_host.h"
     13 #include "content/renderer/render_thread_impl.h"
     14 #include "content/renderer/render_view_impl.h"
     15 #include "media/video/capture/video_capture_proxy.h"
     16 #include "url/gurl.h"
     17 
     18 namespace content {
     19 
     20 PepperPlatformVideoCapture::PepperPlatformVideoCapture(
     21     const base::WeakPtr<RenderViewImpl>& render_view,
     22     const std::string& device_id,
     23     const GURL& document_url,
     24     PepperVideoCaptureHost* handler)
     25     : render_view_(render_view),
     26       device_id_(device_id),
     27       session_id_(0),
     28       handler_proxy_(new media::VideoCaptureHandlerProxy(
     29           this, base::MessageLoopProxy::current())),
     30       handler_(handler),
     31       video_capture_(NULL),
     32       unbalanced_start_(false),
     33       pending_open_device_(false),
     34       pending_open_device_id_(-1) {
     35   // We need to open the device and obtain the label and session ID before
     36   // initializing.
     37   if (render_view_.get()) {
     38     pending_open_device_id_ = GetMediaDeviceManager()->OpenDevice(
     39         PP_DEVICETYPE_DEV_VIDEOCAPTURE,
     40         device_id,
     41         document_url,
     42         base::Bind(&PepperPlatformVideoCapture::OnDeviceOpened, this));
     43     pending_open_device_ = true;
     44   }
     45 }
     46 
     47 void PepperPlatformVideoCapture::StartCapture(
     48     media::VideoCapture::EventHandler* handler,
     49     const media::VideoCaptureCapability& capability) {
     50   DCHECK(handler == handler_);
     51 
     52   if (unbalanced_start_)
     53     return;
     54 
     55   if (video_capture_) {
     56     unbalanced_start_ = true;
     57     AddRef();  // Will be balanced in OnRemoved().
     58     video_capture_->StartCapture(handler_proxy_.get(), capability);
     59   }
     60 }
     61 
     62 void PepperPlatformVideoCapture::StopCapture(
     63     media::VideoCapture::EventHandler* handler) {
     64   DCHECK(handler == handler_);
     65   if (!unbalanced_start_)
     66     return;
     67 
     68   if (video_capture_) {
     69     unbalanced_start_ = false;
     70     video_capture_->StopCapture(handler_proxy_.get());
     71   }
     72 }
     73 
     74 void PepperPlatformVideoCapture::FeedBuffer(
     75     scoped_refptr<VideoFrameBuffer> buffer) {
     76   if (video_capture_)
     77     video_capture_->FeedBuffer(buffer);
     78 }
     79 
     80 bool PepperPlatformVideoCapture::CaptureStarted() {
     81   return handler_proxy_->state().started;
     82 }
     83 
     84 int PepperPlatformVideoCapture::CaptureWidth() {
     85   return handler_proxy_->state().width;
     86 }
     87 
     88 int PepperPlatformVideoCapture::CaptureHeight() {
     89   return handler_proxy_->state().height;
     90 }
     91 
     92 int PepperPlatformVideoCapture::CaptureFrameRate() {
     93   return handler_proxy_->state().frame_rate;
     94 }
     95 
     96 void PepperPlatformVideoCapture::DetachEventHandler() {
     97   handler_ = NULL;
     98   StopCapture(NULL);
     99 
    100   if (video_capture_) {
    101     VideoCaptureImplManager* manager =
    102         RenderThreadImpl::current()->video_capture_impl_manager();
    103     manager->RemoveDevice(session_id_, handler_proxy_.get());
    104     video_capture_ = NULL;
    105   }
    106 
    107   if (render_view_.get()) {
    108     if (!label_.empty()) {
    109       GetMediaDeviceManager()->CloseDevice(label_);
    110       label_.clear();
    111     }
    112     if (pending_open_device_) {
    113       GetMediaDeviceManager()->CancelOpenDevice(pending_open_device_id_);
    114       pending_open_device_ = false;
    115       pending_open_device_id_ = -1;
    116     }
    117   }
    118 }
    119 
    120 void PepperPlatformVideoCapture::OnStarted(VideoCapture* capture) {
    121   if (handler_)
    122     handler_->OnStarted(capture);
    123 }
    124 
    125 void PepperPlatformVideoCapture::OnStopped(VideoCapture* capture) {
    126   if (handler_)
    127     handler_->OnStopped(capture);
    128 }
    129 
    130 void PepperPlatformVideoCapture::OnPaused(VideoCapture* capture) {
    131   if (handler_)
    132     handler_->OnPaused(capture);
    133 }
    134 
    135 void PepperPlatformVideoCapture::OnError(VideoCapture* capture,
    136                                          int error_code) {
    137   if (handler_)
    138     handler_->OnError(capture, error_code);
    139 }
    140 
    141 void PepperPlatformVideoCapture::OnRemoved(VideoCapture* capture) {
    142   if (handler_)
    143     handler_->OnRemoved(capture);
    144 
    145   Release();  // Balance the AddRef() in StartCapture().
    146 }
    147 
    148 void PepperPlatformVideoCapture::OnBufferReady(
    149     VideoCapture* capture,
    150     scoped_refptr<VideoFrameBuffer> buffer) {
    151   if (handler_) {
    152     handler_->OnBufferReady(capture, buffer);
    153   } else {
    154     // Even after handler_ is detached, we have to return buffers that are in
    155     // flight to us. Otherwise VideoCaptureController will not tear down.
    156     FeedBuffer(buffer);
    157   }
    158 }
    159 
    160 void PepperPlatformVideoCapture::OnDeviceInfoReceived(
    161     VideoCapture* capture,
    162     const media::VideoCaptureParams& device_info) {
    163   if (handler_)
    164     handler_->OnDeviceInfoReceived(capture, device_info);
    165 }
    166 
    167 PepperPlatformVideoCapture::~PepperPlatformVideoCapture() {
    168   DCHECK(!video_capture_);
    169   DCHECK(label_.empty());
    170   DCHECK(!pending_open_device_);
    171 }
    172 
    173 void PepperPlatformVideoCapture::Initialize() {
    174   VideoCaptureImplManager* manager =
    175       RenderThreadImpl::current()->video_capture_impl_manager();
    176   video_capture_ = manager->AddDevice(session_id_, handler_proxy_.get());
    177 }
    178 
    179 void PepperPlatformVideoCapture::OnDeviceOpened(int request_id,
    180                                                 bool succeeded,
    181                                                 const std::string& label) {
    182   pending_open_device_ = false;
    183   pending_open_device_id_ = -1;
    184 
    185   succeeded = succeeded && render_view_.get();
    186   if (succeeded) {
    187     label_ = label;
    188     session_id_ = GetMediaDeviceManager()->GetSessionID(
    189         PP_DEVICETYPE_DEV_VIDEOCAPTURE, label);
    190     Initialize();
    191   }
    192 
    193   if (handler_)
    194     handler_->OnInitialized(this, succeeded);
    195 }
    196 
    197 PepperMediaDeviceManager*
    198     PepperPlatformVideoCapture::GetMediaDeviceManager() {
    199   return PepperMediaDeviceManager::GetForRenderView(render_view_.get());
    200 }
    201 
    202 }  // namespace content
    203