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/renderer/media/video_capture_message_filter.h"
      6 
      7 #include "content/common/media/video_capture_messages.h"
      8 #include "content/common/view_messages.h"
      9 #include "ipc/ipc_sender.h"
     10 
     11 namespace content {
     12 
     13 VideoCaptureMessageFilter::VideoCaptureMessageFilter()
     14     : last_device_id_(0),
     15       sender_(NULL) {
     16 }
     17 
     18 void VideoCaptureMessageFilter::AddDelegate(Delegate* delegate) {
     19   if (++last_device_id_ <= 0)
     20     last_device_id_ = 1;
     21   while (delegates_.find(last_device_id_) != delegates_.end())
     22     last_device_id_++;
     23 
     24   if (sender_) {
     25     delegates_[last_device_id_] = delegate;
     26     delegate->OnDelegateAdded(last_device_id_);
     27   } else {
     28     pending_delegates_[last_device_id_] = delegate;
     29   }
     30 }
     31 
     32 void VideoCaptureMessageFilter::RemoveDelegate(Delegate* delegate) {
     33   for (Delegates::iterator it = delegates_.begin();
     34        it != delegates_.end(); it++) {
     35     if (it->second == delegate) {
     36       delegates_.erase(it);
     37       break;
     38     }
     39   }
     40   for (Delegates::iterator it = pending_delegates_.begin();
     41        it != pending_delegates_.end(); it++) {
     42     if (it->second == delegate) {
     43       pending_delegates_.erase(it);
     44       break;
     45     }
     46   }
     47 }
     48 
     49 bool VideoCaptureMessageFilter::Send(IPC::Message* message) {
     50   if (!sender_) {
     51     delete message;
     52     return false;
     53   }
     54 
     55   return sender_->Send(message);
     56 }
     57 
     58 bool VideoCaptureMessageFilter::OnMessageReceived(const IPC::Message& message) {
     59   bool handled = true;
     60   IPC_BEGIN_MESSAGE_MAP(VideoCaptureMessageFilter, message)
     61     IPC_MESSAGE_HANDLER(VideoCaptureMsg_BufferReady, OnBufferReceived)
     62     IPC_MESSAGE_HANDLER(VideoCaptureMsg_MailboxBufferReady,
     63                         OnMailboxBufferReceived)
     64     IPC_MESSAGE_HANDLER(VideoCaptureMsg_StateChanged, OnDeviceStateChanged)
     65     IPC_MESSAGE_HANDLER(VideoCaptureMsg_NewBuffer, OnBufferCreated)
     66     IPC_MESSAGE_HANDLER(VideoCaptureMsg_FreeBuffer, OnBufferDestroyed)
     67     IPC_MESSAGE_HANDLER(VideoCaptureMsg_DeviceSupportedFormatsEnumerated,
     68                         OnDeviceSupportedFormatsEnumerated)
     69     IPC_MESSAGE_HANDLER(VideoCaptureMsg_DeviceFormatsInUseReceived,
     70                         OnDeviceFormatsInUseReceived)
     71     IPC_MESSAGE_UNHANDLED(handled = false)
     72   IPC_END_MESSAGE_MAP()
     73   return handled;
     74 }
     75 
     76 void VideoCaptureMessageFilter::OnFilterAdded(IPC::Sender* sender) {
     77   DVLOG(1) << "VideoCaptureMessageFilter::OnFilterAdded()";
     78   sender_ = sender;
     79 
     80   for (Delegates::iterator it = pending_delegates_.begin();
     81        it != pending_delegates_.end(); it++) {
     82     it->second->OnDelegateAdded(it->first);
     83     delegates_[it->first] = it->second;
     84   }
     85   pending_delegates_.clear();
     86 }
     87 
     88 void VideoCaptureMessageFilter::OnFilterRemoved() {
     89   sender_ = NULL;
     90 }
     91 
     92 void VideoCaptureMessageFilter::OnChannelClosing() {
     93   sender_ = NULL;
     94 }
     95 
     96 VideoCaptureMessageFilter::~VideoCaptureMessageFilter() {}
     97 
     98 VideoCaptureMessageFilter::Delegate* VideoCaptureMessageFilter::find_delegate(
     99     int device_id) const {
    100   Delegates::const_iterator i = delegates_.find(device_id);
    101   return i != delegates_.end() ? i->second : NULL;
    102 }
    103 
    104 void VideoCaptureMessageFilter::OnBufferCreated(
    105     int device_id,
    106     base::SharedMemoryHandle handle,
    107     int length,
    108     int buffer_id) {
    109   Delegate* delegate = find_delegate(device_id);
    110   if (!delegate) {
    111     DLOG(WARNING) << "OnBufferCreated: Got video SHM buffer for a "
    112                      "non-existent or removed video capture.";
    113 
    114     // Send the buffer back to Host in case it's waiting for all buffers
    115     // to be returned.
    116     base::SharedMemory::CloseHandle(handle);
    117     Send(new VideoCaptureHostMsg_BufferReady(device_id, buffer_id, 0));
    118     return;
    119   }
    120 
    121   delegate->OnBufferCreated(handle, length, buffer_id);
    122 }
    123 
    124 void VideoCaptureMessageFilter::OnBufferReceived(
    125     int device_id,
    126     int buffer_id,
    127     const media::VideoCaptureFormat& format,
    128     const gfx::Rect& visible_rect,
    129     base::TimeTicks timestamp) {
    130   Delegate* delegate = find_delegate(device_id);
    131   if (!delegate) {
    132     DLOG(WARNING) << "OnBufferReceived: Got video SHM buffer for a "
    133                      "non-existent or removed video capture.";
    134 
    135     // Send the buffer back to Host in case it's waiting for all buffers
    136     // to be returned.
    137     Send(new VideoCaptureHostMsg_BufferReady(device_id, buffer_id, 0));
    138     return;
    139   }
    140 
    141   delegate->OnBufferReceived(buffer_id, format, visible_rect, timestamp);
    142 }
    143 
    144 void VideoCaptureMessageFilter::OnMailboxBufferReceived(
    145     int device_id,
    146     int buffer_id,
    147     const gpu::MailboxHolder& mailbox_holder,
    148     const media::VideoCaptureFormat& format,
    149     base::TimeTicks timestamp) {
    150   Delegate* delegate = find_delegate(device_id);
    151 
    152   if (!delegate) {
    153     DLOG(WARNING) << "OnMailboxBufferReceived: Got video mailbox buffer for a "
    154                      "non-existent or removed video capture.";
    155 
    156     // Send the buffer back to Host in case it's waiting for all buffers
    157     // to be returned.
    158     Send(new VideoCaptureHostMsg_BufferReady(device_id, buffer_id, 0));
    159     return;
    160   }
    161 
    162   delegate->OnMailboxBufferReceived(
    163       buffer_id, mailbox_holder, format, timestamp);
    164 }
    165 
    166 void VideoCaptureMessageFilter::OnBufferDestroyed(
    167     int device_id,
    168     int buffer_id) {
    169   Delegate* delegate = find_delegate(device_id);
    170   if (!delegate) {
    171     DLOG(WARNING) << "OnBufferDestroyed: Instructed to free buffer for a "
    172         "non-existent or removed video capture.";
    173     return;
    174   }
    175 
    176   delegate->OnBufferDestroyed(buffer_id);
    177 }
    178 
    179 void VideoCaptureMessageFilter::OnDeviceStateChanged(
    180     int device_id,
    181     VideoCaptureState state) {
    182   Delegate* delegate = find_delegate(device_id);
    183   if (!delegate) {
    184     DLOG(WARNING) << "OnDeviceStateChanged: Got video capture event for a "
    185         "non-existent or removed video capture.";
    186     return;
    187   }
    188   delegate->OnStateChanged(state);
    189 }
    190 
    191 void VideoCaptureMessageFilter::OnDeviceSupportedFormatsEnumerated(
    192     int device_id,
    193     const media::VideoCaptureFormats& supported_formats) {
    194   Delegate* delegate = find_delegate(device_id);
    195   if (!delegate) {
    196     DLOG(WARNING) << "OnDeviceFormatsEnumerated: unknown device";
    197     return;
    198   }
    199   delegate->OnDeviceSupportedFormatsEnumerated(supported_formats);
    200 }
    201 
    202 void VideoCaptureMessageFilter::OnDeviceFormatsInUseReceived(
    203     int device_id,
    204     const media::VideoCaptureFormats& formats_in_use) {
    205   Delegate* delegate = find_delegate(device_id);
    206   if (!delegate) {
    207     DLOG(WARNING) << "OnDeviceFormatInUse: unknown device";
    208     return;
    209   }
    210   delegate->OnDeviceFormatsInUseReceived(formats_in_use);
    211 }
    212 
    213 }  // namespace content
    214