Home | History | Annotate | Download | only in media
      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/browser/renderer_host/media/video_capture_host.h"
      6 
      7 #include "base/bind.h"
      8 #include "base/memory/scoped_ptr.h"
      9 #include "content/browser/browser_main_loop.h"
     10 #include "content/browser/renderer_host/media/media_stream_manager.h"
     11 #include "content/browser/renderer_host/media/video_capture_manager.h"
     12 #include "content/common/media/video_capture_messages.h"
     13 
     14 namespace content {
     15 
     16 VideoCaptureHost::VideoCaptureHost(MediaStreamManager* media_stream_manager)
     17     : BrowserMessageFilter(VideoCaptureMsgStart),
     18       media_stream_manager_(media_stream_manager) {
     19 }
     20 
     21 VideoCaptureHost::~VideoCaptureHost() {}
     22 
     23 void VideoCaptureHost::OnChannelClosing() {
     24   // Since the IPC sender is gone, close all requested VideoCaptureDevices.
     25   for (EntryMap::iterator it = entries_.begin(); it != entries_.end(); ) {
     26     const base::WeakPtr<VideoCaptureController>& controller = it->second;
     27     if (controller) {
     28       VideoCaptureControllerID controller_id(it->first);
     29       media_stream_manager_->video_capture_manager()->StopCaptureForClient(
     30           controller.get(), controller_id, this, false);
     31       ++it;
     32     } else {
     33       // Remove the entry for this controller_id so that when the controller
     34       // is added, the controller will be notified to stop for this client
     35       // in DoControllerAddedOnIOThread.
     36       entries_.erase(it++);
     37     }
     38   }
     39 }
     40 
     41 void VideoCaptureHost::OnDestruct() const {
     42   BrowserThread::DeleteOnIOThread::Destruct(this);
     43 }
     44 
     45 ///////////////////////////////////////////////////////////////////////////////
     46 
     47 // Implements VideoCaptureControllerEventHandler.
     48 void VideoCaptureHost::OnError(const VideoCaptureControllerID& controller_id) {
     49   DVLOG(1) << "VideoCaptureHost::OnError";
     50   BrowserThread::PostTask(
     51       BrowserThread::IO, FROM_HERE,
     52       base::Bind(&VideoCaptureHost::DoHandleErrorOnIOThread,
     53                  this, controller_id));
     54 }
     55 
     56 void VideoCaptureHost::OnBufferCreated(
     57     const VideoCaptureControllerID& controller_id,
     58     base::SharedMemoryHandle handle,
     59     int length,
     60     int buffer_id) {
     61   BrowserThread::PostTask(
     62       BrowserThread::IO, FROM_HERE,
     63       base::Bind(&VideoCaptureHost::DoSendNewBufferOnIOThread,
     64                  this, controller_id, handle, length, buffer_id));
     65 }
     66 
     67 void VideoCaptureHost::OnBufferDestroyed(
     68     const VideoCaptureControllerID& controller_id,
     69     int buffer_id) {
     70   BrowserThread::PostTask(
     71       BrowserThread::IO, FROM_HERE,
     72       base::Bind(&VideoCaptureHost::DoSendFreeBufferOnIOThread,
     73                  this, controller_id, buffer_id));
     74 }
     75 
     76 void VideoCaptureHost::OnBufferReady(
     77     const VideoCaptureControllerID& controller_id,
     78     int buffer_id,
     79     const media::VideoCaptureFormat& frame_format,
     80     base::TimeTicks timestamp) {
     81   BrowserThread::PostTask(
     82       BrowserThread::IO,
     83       FROM_HERE,
     84       base::Bind(&VideoCaptureHost::DoSendFilledBufferOnIOThread,
     85                  this,
     86                  controller_id,
     87                  buffer_id,
     88                  frame_format,
     89                  timestamp));
     90 }
     91 
     92 void VideoCaptureHost::OnMailboxBufferReady(
     93     const VideoCaptureControllerID& controller_id,
     94     int buffer_id,
     95     const gpu::MailboxHolder& mailbox_holder,
     96     const media::VideoCaptureFormat& frame_format,
     97     base::TimeTicks timestamp) {
     98   BrowserThread::PostTask(
     99       BrowserThread::IO,
    100       FROM_HERE,
    101       base::Bind(&VideoCaptureHost::DoSendFilledMailboxBufferOnIOThread,
    102                  this,
    103                  controller_id,
    104                  buffer_id,
    105                  mailbox_holder,
    106                  frame_format,
    107                  timestamp));
    108 }
    109 
    110 void VideoCaptureHost::OnEnded(const VideoCaptureControllerID& controller_id) {
    111   DVLOG(1) << "VideoCaptureHost::OnEnded";
    112   BrowserThread::PostTask(
    113       BrowserThread::IO, FROM_HERE,
    114       base::Bind(&VideoCaptureHost::DoEndedOnIOThread, this, controller_id));
    115 }
    116 
    117 void VideoCaptureHost::DoSendNewBufferOnIOThread(
    118     const VideoCaptureControllerID& controller_id,
    119     base::SharedMemoryHandle handle,
    120     int length,
    121     int buffer_id) {
    122   DCHECK_CURRENTLY_ON(BrowserThread::IO);
    123 
    124   if (entries_.find(controller_id) == entries_.end())
    125     return;
    126 
    127   Send(new VideoCaptureMsg_NewBuffer(controller_id.device_id, handle,
    128                                      length, buffer_id));
    129 }
    130 
    131 void VideoCaptureHost::DoSendFreeBufferOnIOThread(
    132     const VideoCaptureControllerID& controller_id,
    133     int buffer_id) {
    134   DCHECK_CURRENTLY_ON(BrowserThread::IO);
    135 
    136   if (entries_.find(controller_id) == entries_.end())
    137     return;
    138 
    139   Send(new VideoCaptureMsg_FreeBuffer(controller_id.device_id, buffer_id));
    140 }
    141 
    142 void VideoCaptureHost::DoSendFilledBufferOnIOThread(
    143     const VideoCaptureControllerID& controller_id,
    144     int buffer_id,
    145     const media::VideoCaptureFormat& format,
    146     base::TimeTicks timestamp) {
    147   DCHECK_CURRENTLY_ON(BrowserThread::IO);
    148 
    149   if (entries_.find(controller_id) == entries_.end())
    150     return;
    151 
    152   Send(new VideoCaptureMsg_BufferReady(
    153       controller_id.device_id, buffer_id, format, timestamp));
    154 }
    155 
    156 void VideoCaptureHost::DoSendFilledMailboxBufferOnIOThread(
    157     const VideoCaptureControllerID& controller_id,
    158     int buffer_id,
    159     const gpu::MailboxHolder& mailbox_holder,
    160     const media::VideoCaptureFormat& format,
    161     base::TimeTicks timestamp) {
    162   DCHECK_CURRENTLY_ON(BrowserThread::IO);
    163 
    164   if (entries_.find(controller_id) == entries_.end())
    165     return;
    166 
    167   Send(new VideoCaptureMsg_MailboxBufferReady(
    168       controller_id.device_id, buffer_id, mailbox_holder, format, timestamp));
    169 }
    170 
    171 void VideoCaptureHost::DoHandleErrorOnIOThread(
    172     const VideoCaptureControllerID& controller_id) {
    173   DCHECK_CURRENTLY_ON(BrowserThread::IO);
    174 
    175   if (entries_.find(controller_id) == entries_.end())
    176     return;
    177 
    178   Send(new VideoCaptureMsg_StateChanged(controller_id.device_id,
    179                                         VIDEO_CAPTURE_STATE_ERROR));
    180   DeleteVideoCaptureControllerOnIOThread(controller_id, true);
    181 }
    182 
    183 void VideoCaptureHost::DoEndedOnIOThread(
    184     const VideoCaptureControllerID& controller_id) {
    185   DCHECK_CURRENTLY_ON(BrowserThread::IO);
    186   DVLOG(1) << "VideoCaptureHost::DoEndedOnIOThread";
    187   if (entries_.find(controller_id) == entries_.end())
    188     return;
    189 
    190   Send(new VideoCaptureMsg_StateChanged(controller_id.device_id,
    191                                         VIDEO_CAPTURE_STATE_ENDED));
    192   DeleteVideoCaptureControllerOnIOThread(controller_id, false);
    193 }
    194 
    195 ///////////////////////////////////////////////////////////////////////////////
    196 // IPC Messages handler.
    197 bool VideoCaptureHost::OnMessageReceived(const IPC::Message& message) {
    198   bool handled = true;
    199   IPC_BEGIN_MESSAGE_MAP(VideoCaptureHost, message)
    200     IPC_MESSAGE_HANDLER(VideoCaptureHostMsg_Start, OnStartCapture)
    201     IPC_MESSAGE_HANDLER(VideoCaptureHostMsg_Pause, OnPauseCapture)
    202     IPC_MESSAGE_HANDLER(VideoCaptureHostMsg_Stop, OnStopCapture)
    203     IPC_MESSAGE_HANDLER(VideoCaptureHostMsg_BufferReady, OnReceiveEmptyBuffer)
    204     IPC_MESSAGE_HANDLER(VideoCaptureHostMsg_GetDeviceSupportedFormats,
    205                         OnGetDeviceSupportedFormats)
    206     IPC_MESSAGE_HANDLER(VideoCaptureHostMsg_GetDeviceFormatsInUse,
    207                         OnGetDeviceFormatsInUse)
    208     IPC_MESSAGE_UNHANDLED(handled = false)
    209   IPC_END_MESSAGE_MAP()
    210 
    211   return handled;
    212 }
    213 
    214 void VideoCaptureHost::OnStartCapture(int device_id,
    215                                       media::VideoCaptureSessionId session_id,
    216                                       const media::VideoCaptureParams& params) {
    217   DCHECK_CURRENTLY_ON(BrowserThread::IO);
    218   DVLOG(1) << "VideoCaptureHost::OnStartCapture:"
    219            << " session_id=" << session_id
    220            << ", device_id=" << device_id
    221            << ", format=" << params.requested_format.frame_size.ToString()
    222            << "@" << params.requested_format.frame_rate
    223            << " (" << (params.allow_resolution_change ? "variable" : "constant")
    224            << ")";
    225   VideoCaptureControllerID controller_id(device_id);
    226   if (entries_.find(controller_id) != entries_.end()) {
    227     Send(new VideoCaptureMsg_StateChanged(device_id,
    228                                           VIDEO_CAPTURE_STATE_ERROR));
    229     return;
    230   }
    231 
    232   entries_[controller_id] = base::WeakPtr<VideoCaptureController>();
    233   media_stream_manager_->video_capture_manager()->StartCaptureForClient(
    234       session_id,
    235       params,
    236       PeerHandle(),
    237       controller_id,
    238       this,
    239       base::Bind(&VideoCaptureHost::OnControllerAdded, this, device_id));
    240 }
    241 
    242 void VideoCaptureHost::OnControllerAdded(
    243     int device_id,
    244     const base::WeakPtr<VideoCaptureController>& controller) {
    245   BrowserThread::PostTask(
    246       BrowserThread::IO,
    247       FROM_HERE,
    248       base::Bind(&VideoCaptureHost::DoControllerAddedOnIOThread,
    249                  this,
    250                  device_id,
    251                  controller));
    252 }
    253 
    254 void VideoCaptureHost::DoControllerAddedOnIOThread(
    255     int device_id,
    256     const base::WeakPtr<VideoCaptureController>& controller) {
    257   DCHECK_CURRENTLY_ON(BrowserThread::IO);
    258   VideoCaptureControllerID controller_id(device_id);
    259   EntryMap::iterator it = entries_.find(controller_id);
    260   if (it == entries_.end()) {
    261     if (controller) {
    262       media_stream_manager_->video_capture_manager()->StopCaptureForClient(
    263           controller.get(), controller_id, this, false);
    264     }
    265     return;
    266   }
    267 
    268   if (!controller) {
    269     Send(new VideoCaptureMsg_StateChanged(device_id,
    270                                           VIDEO_CAPTURE_STATE_ERROR));
    271     entries_.erase(controller_id);
    272     return;
    273   }
    274 
    275   DCHECK(!it->second);
    276   it->second = controller;
    277 }
    278 
    279 void VideoCaptureHost::OnStopCapture(int device_id) {
    280   DCHECK_CURRENTLY_ON(BrowserThread::IO);
    281   DVLOG(1) << "VideoCaptureHost::OnStopCapture, device_id " << device_id;
    282 
    283   VideoCaptureControllerID controller_id(device_id);
    284 
    285   Send(new VideoCaptureMsg_StateChanged(device_id,
    286                                         VIDEO_CAPTURE_STATE_STOPPED));
    287   DeleteVideoCaptureControllerOnIOThread(controller_id, false);
    288 }
    289 
    290 void VideoCaptureHost::OnPauseCapture(int device_id) {
    291   DCHECK_CURRENTLY_ON(BrowserThread::IO);
    292   DVLOG(1) << "VideoCaptureHost::OnPauseCapture, device_id " << device_id;
    293   // Not used.
    294   Send(new VideoCaptureMsg_StateChanged(device_id, VIDEO_CAPTURE_STATE_ERROR));
    295 }
    296 
    297 void VideoCaptureHost::OnReceiveEmptyBuffer(
    298     int device_id,
    299     int buffer_id,
    300     const std::vector<uint32>& sync_points) {
    301   DCHECK_CURRENTLY_ON(BrowserThread::IO);
    302 
    303   VideoCaptureControllerID controller_id(device_id);
    304   EntryMap::iterator it = entries_.find(controller_id);
    305   if (it != entries_.end()) {
    306     const base::WeakPtr<VideoCaptureController>& controller = it->second;
    307     if (controller)
    308       controller->ReturnBuffer(controller_id, this, buffer_id, sync_points);
    309   }
    310 }
    311 
    312 void VideoCaptureHost::OnGetDeviceSupportedFormats(
    313     int device_id,
    314     media::VideoCaptureSessionId capture_session_id) {
    315   DCHECK_CURRENTLY_ON(BrowserThread::IO);
    316   DVLOG(1) << "VideoCaptureHost::OnGetDeviceFormats, capture_session_id "
    317            << capture_session_id;
    318   media::VideoCaptureFormats device_supported_formats;
    319   if (!media_stream_manager_->video_capture_manager()
    320            ->GetDeviceSupportedFormats(capture_session_id,
    321                                        &device_supported_formats)) {
    322     DLOG(WARNING)
    323         << "Could not retrieve device supported formats for device_id="
    324         << device_id << " capture_session_id=" << capture_session_id;
    325   }
    326   Send(new VideoCaptureMsg_DeviceSupportedFormatsEnumerated(
    327       device_id, device_supported_formats));
    328 }
    329 
    330 void VideoCaptureHost::OnGetDeviceFormatsInUse(
    331     int device_id,
    332     media::VideoCaptureSessionId capture_session_id) {
    333   DCHECK_CURRENTLY_ON(BrowserThread::IO);
    334   DVLOG(1) << "VideoCaptureHost::OnGetDeviceFormatsInUse, capture_session_id "
    335            << capture_session_id;
    336   media::VideoCaptureFormats formats_in_use;
    337   if (!media_stream_manager_->video_capture_manager()->GetDeviceFormatsInUse(
    338            capture_session_id, &formats_in_use)) {
    339     DVLOG(1) << "Could not retrieve device format(s) in use for device_id="
    340              << device_id << " capture_session_id=" << capture_session_id;
    341   }
    342   Send(new VideoCaptureMsg_DeviceFormatsInUseReceived(device_id,
    343                                                       formats_in_use));
    344 }
    345 
    346 void VideoCaptureHost::DeleteVideoCaptureControllerOnIOThread(
    347     const VideoCaptureControllerID& controller_id, bool on_error) {
    348   DCHECK_CURRENTLY_ON(BrowserThread::IO);
    349 
    350   EntryMap::iterator it = entries_.find(controller_id);
    351   if (it == entries_.end())
    352     return;
    353 
    354   if (it->second) {
    355     media_stream_manager_->video_capture_manager()->StopCaptureForClient(
    356         it->second.get(), controller_id, this, on_error);
    357   }
    358   entries_.erase(it);
    359 }
    360 
    361 }  // namespace content
    362