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 "base/stl_util.h"
     10 #include "content/browser/browser_main_loop.h"
     11 #include "content/browser/renderer_host/media/media_stream_manager.h"
     12 #include "content/browser/renderer_host/media/video_capture_manager.h"
     13 #include "content/common/media/video_capture_messages.h"
     14 
     15 namespace content {
     16 
     17 struct VideoCaptureHost::Entry {
     18   Entry(VideoCaptureController* controller)
     19       : controller(controller) {}
     20 
     21   ~Entry() {}
     22 
     23   scoped_refptr<VideoCaptureController> controller;
     24 };
     25 
     26 VideoCaptureHost::VideoCaptureHost(MediaStreamManager* media_stream_manager)
     27     : media_stream_manager_(media_stream_manager) {
     28 }
     29 
     30 VideoCaptureHost::~VideoCaptureHost() {}
     31 
     32 void VideoCaptureHost::OnChannelClosing() {
     33   BrowserMessageFilter::OnChannelClosing();
     34 
     35   // Since the IPC channel is gone, close all requested VideCaptureDevices.
     36   for (EntryMap::iterator it = entries_.begin(); it != entries_.end(); it++) {
     37     VideoCaptureController* controller = it->second->controller.get();
     38     if (controller) {
     39       VideoCaptureControllerID controller_id(it->first);
     40       controller->StopCapture(controller_id, this);
     41       media_stream_manager_->video_capture_manager()->RemoveController(
     42           controller, this);
     43     }
     44   }
     45   STLDeleteValues(&entries_);
     46 }
     47 
     48 void VideoCaptureHost::OnDestruct() const {
     49   BrowserThread::DeleteOnIOThread::Destruct(this);
     50 }
     51 
     52 ///////////////////////////////////////////////////////////////////////////////
     53 
     54 // Implements VideoCaptureControllerEventHandler.
     55 void VideoCaptureHost::OnError(const VideoCaptureControllerID& controller_id) {
     56   DVLOG(1) << "VideoCaptureHost::OnError";
     57   BrowserThread::PostTask(
     58       BrowserThread::IO, FROM_HERE,
     59       base::Bind(&VideoCaptureHost::DoHandleErrorOnIOThread,
     60                  this, controller_id));
     61 }
     62 
     63 void VideoCaptureHost::OnBufferCreated(
     64     const VideoCaptureControllerID& controller_id,
     65     base::SharedMemoryHandle handle,
     66     int length,
     67     int buffer_id) {
     68   BrowserThread::PostTask(
     69       BrowserThread::IO, FROM_HERE,
     70       base::Bind(&VideoCaptureHost::DoSendNewBufferOnIOThread,
     71                  this, controller_id, handle, length, buffer_id));
     72 }
     73 
     74 void VideoCaptureHost::OnBufferReady(
     75     const VideoCaptureControllerID& controller_id,
     76     int buffer_id,
     77     base::Time timestamp) {
     78   BrowserThread::PostTask(
     79       BrowserThread::IO, FROM_HERE,
     80       base::Bind(&VideoCaptureHost::DoSendFilledBufferOnIOThread,
     81                  this, controller_id, buffer_id, timestamp));
     82 }
     83 
     84 void VideoCaptureHost::OnFrameInfo(
     85     const VideoCaptureControllerID& controller_id,
     86     const media::VideoCaptureCapability& format) {
     87   BrowserThread::PostTask(
     88       BrowserThread::IO,
     89       FROM_HERE,
     90       base::Bind(&VideoCaptureHost::DoSendFrameInfoOnIOThread,
     91                  this, controller_id, format));
     92 }
     93 
     94 void VideoCaptureHost::OnFrameInfoChanged(
     95     const VideoCaptureControllerID& controller_id,
     96     int width,
     97     int height,
     98     int frame_per_second) {
     99   BrowserThread::PostTask(
    100       BrowserThread::IO, FROM_HERE,
    101       base::Bind(&VideoCaptureHost::DoSendFrameInfoChangedOnIOThread,
    102                  this, controller_id, width, height, frame_per_second));
    103 }
    104 
    105 void VideoCaptureHost::OnEnded(const VideoCaptureControllerID& controller_id) {
    106   DVLOG(1) << "VideoCaptureHost::OnEnded";
    107   BrowserThread::PostTask(
    108       BrowserThread::IO, FROM_HERE,
    109       base::Bind(&VideoCaptureHost::DoEndedOnIOThread, this, controller_id));
    110 }
    111 
    112 void VideoCaptureHost::DoSendNewBufferOnIOThread(
    113     const VideoCaptureControllerID& controller_id,
    114     base::SharedMemoryHandle handle,
    115     int length,
    116     int buffer_id) {
    117   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
    118 
    119   if (entries_.find(controller_id) == entries_.end())
    120     return;
    121 
    122   Send(new VideoCaptureMsg_NewBuffer(controller_id.device_id, handle,
    123                                      length, buffer_id));
    124 }
    125 
    126 void VideoCaptureHost::DoSendFilledBufferOnIOThread(
    127     const VideoCaptureControllerID& controller_id,
    128     int buffer_id, base::Time timestamp) {
    129   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
    130 
    131   if (entries_.find(controller_id) == entries_.end())
    132     return;
    133 
    134   Send(new VideoCaptureMsg_BufferReady(controller_id.device_id, buffer_id,
    135                                        timestamp));
    136 }
    137 
    138 void VideoCaptureHost::DoHandleErrorOnIOThread(
    139     const VideoCaptureControllerID& controller_id) {
    140   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
    141 
    142   if (entries_.find(controller_id) == entries_.end())
    143     return;
    144 
    145   Send(new VideoCaptureMsg_StateChanged(controller_id.device_id,
    146                                         VIDEO_CAPTURE_STATE_ERROR));
    147   DeleteVideoCaptureControllerOnIOThread(controller_id);
    148 }
    149 
    150 void VideoCaptureHost::DoEndedOnIOThread(
    151     const VideoCaptureControllerID& controller_id) {
    152   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
    153   DVLOG(1) << "VideoCaptureHost::DoEndedOnIOThread";
    154   if (entries_.find(controller_id) == entries_.end())
    155     return;
    156 
    157   Send(new VideoCaptureMsg_StateChanged(controller_id.device_id,
    158                                         VIDEO_CAPTURE_STATE_ENDED));
    159   DeleteVideoCaptureControllerOnIOThread(controller_id);
    160 }
    161 
    162 void VideoCaptureHost::DoSendFrameInfoOnIOThread(
    163     const VideoCaptureControllerID& controller_id,
    164     const media::VideoCaptureCapability& format) {
    165   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
    166 
    167   if (entries_.find(controller_id) == entries_.end())
    168     return;
    169 
    170   media::VideoCaptureParams params;
    171   params.width = format.width;
    172   params.height = format.height;
    173   params.frame_per_second = format.frame_rate;
    174   params.frame_size_type = format.frame_size_type;
    175   Send(new VideoCaptureMsg_DeviceInfo(controller_id.device_id, params));
    176   Send(new VideoCaptureMsg_StateChanged(controller_id.device_id,
    177                                         VIDEO_CAPTURE_STATE_STARTED));
    178 }
    179 
    180 void VideoCaptureHost::DoSendFrameInfoChangedOnIOThread(
    181     const VideoCaptureControllerID& controller_id,
    182     int width,
    183     int height,
    184     int frame_per_second) {
    185   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
    186 
    187   if (entries_.find(controller_id) == entries_.end())
    188     return;
    189 
    190   media::VideoCaptureParams params;
    191   params.width = width;
    192   params.height = height;
    193   params.frame_per_second = frame_per_second;
    194   Send(new VideoCaptureMsg_DeviceInfoChanged(controller_id.device_id, params));
    195 }
    196 
    197 ///////////////////////////////////////////////////////////////////////////////
    198 // IPC Messages handler.
    199 bool VideoCaptureHost::OnMessageReceived(const IPC::Message& message,
    200                                          bool* message_was_ok) {
    201   bool handled = true;
    202   IPC_BEGIN_MESSAGE_MAP_EX(VideoCaptureHost, message, *message_was_ok)
    203     IPC_MESSAGE_HANDLER(VideoCaptureHostMsg_Start, OnStartCapture)
    204     IPC_MESSAGE_HANDLER(VideoCaptureHostMsg_Pause, OnPauseCapture)
    205     IPC_MESSAGE_HANDLER(VideoCaptureHostMsg_Stop, OnStopCapture)
    206     IPC_MESSAGE_HANDLER(VideoCaptureHostMsg_BufferReady, OnReceiveEmptyBuffer)
    207     IPC_MESSAGE_UNHANDLED(handled = false)
    208   IPC_END_MESSAGE_MAP_EX()
    209 
    210   return handled;
    211 }
    212 
    213 void VideoCaptureHost::OnStartCapture(int device_id,
    214                                       const media::VideoCaptureParams& params) {
    215   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
    216   DVLOG(1) << "VideoCaptureHost::OnStartCapture, device_id " << device_id
    217            << ", (" << params.width << ", " << params.height << ", "
    218            << params.frame_per_second << ", " << params.session_id
    219            << ", variable resolution device:"
    220            << ((params.frame_size_type ==
    221                media::VariableResolutionVideoCaptureDevice) ? "yes" : "no")
    222             << ")";
    223   VideoCaptureControllerID controller_id(device_id);
    224   DCHECK(entries_.find(controller_id) == entries_.end());
    225 
    226   entries_[controller_id] = new Entry(NULL);
    227   media_stream_manager_->video_capture_manager()->AddController(
    228       params, this, base::Bind(&VideoCaptureHost::OnControllerAdded, this,
    229                                device_id, params));
    230 }
    231 
    232 void VideoCaptureHost::OnControllerAdded(
    233     int device_id, const media::VideoCaptureParams& params,
    234     VideoCaptureController* controller) {
    235   BrowserThread::PostTask(
    236       BrowserThread::IO, FROM_HERE,
    237       base::Bind(&VideoCaptureHost::DoControllerAddedOnIOThread,
    238                  this, device_id, params, make_scoped_refptr(controller)));
    239 }
    240 
    241 void VideoCaptureHost::DoControllerAddedOnIOThread(
    242     int device_id, const media::VideoCaptureParams params,
    243     VideoCaptureController* controller) {
    244   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
    245   VideoCaptureControllerID controller_id(device_id);
    246   EntryMap::iterator it = entries_.find(controller_id);
    247   if (it == entries_.end()) {
    248     if (controller) {
    249       media_stream_manager_->video_capture_manager()->RemoveController(
    250           controller, this);
    251     }
    252     return;
    253   }
    254 
    255   if (controller == NULL) {
    256     Send(new VideoCaptureMsg_StateChanged(device_id,
    257                                           VIDEO_CAPTURE_STATE_ERROR));
    258     delete it->second;
    259     entries_.erase(controller_id);
    260     return;
    261   }
    262 
    263   it->second->controller = controller;
    264   controller->StartCapture(controller_id, this, PeerHandle(), params);
    265 }
    266 
    267 void VideoCaptureHost::OnStopCapture(int device_id) {
    268   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
    269   DVLOG(1) << "VideoCaptureHost::OnStopCapture, device_id " << device_id;
    270 
    271   VideoCaptureControllerID controller_id(device_id);
    272 
    273   Send(new VideoCaptureMsg_StateChanged(device_id,
    274                                         VIDEO_CAPTURE_STATE_STOPPED));
    275   DeleteVideoCaptureControllerOnIOThread(controller_id);
    276 }
    277 
    278 void VideoCaptureHost::OnPauseCapture(int device_id) {
    279   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
    280   DVLOG(1) << "VideoCaptureHost::OnPauseCapture, device_id " << device_id;
    281   // Not used.
    282   Send(new VideoCaptureMsg_StateChanged(device_id, VIDEO_CAPTURE_STATE_ERROR));
    283 }
    284 
    285 void VideoCaptureHost::OnReceiveEmptyBuffer(int device_id, int buffer_id) {
    286   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
    287 
    288   VideoCaptureControllerID controller_id(device_id);
    289   EntryMap::iterator it = entries_.find(controller_id);
    290   if (it != entries_.end()) {
    291     scoped_refptr<VideoCaptureController> controller = it->second->controller;
    292     if (controller.get())
    293       controller->ReturnBuffer(controller_id, this, buffer_id);
    294   }
    295 }
    296 
    297 void VideoCaptureHost::DeleteVideoCaptureControllerOnIOThread(
    298     const VideoCaptureControllerID& controller_id) {
    299   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
    300 
    301   EntryMap::iterator it = entries_.find(controller_id);
    302   if (it == entries_.end())
    303     return;
    304 
    305   VideoCaptureController* controller = it->second->controller.get();
    306   if (controller) {
    307     controller->StopCapture(controller_id, this);
    308     media_stream_manager_->video_capture_manager()->RemoveController(
    309         controller, this);
    310   }
    311   delete it->second;
    312   entries_.erase(controller_id);
    313 }
    314 
    315 }  // namespace content
    316