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
11namespace content {
12
13VideoCaptureMessageFilter::VideoCaptureMessageFilter()
14    : last_device_id_(0),
15      sender_(NULL) {
16}
17
18void 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
32void 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
49bool VideoCaptureMessageFilter::Send(IPC::Message* message) {
50  if (!sender_) {
51    delete message;
52    return false;
53  }
54
55  return sender_->Send(message);
56}
57
58bool 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
76void 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
88void VideoCaptureMessageFilter::OnFilterRemoved() {
89  sender_ = NULL;
90}
91
92void VideoCaptureMessageFilter::OnChannelClosing() {
93  sender_ = NULL;
94}
95
96VideoCaptureMessageFilter::~VideoCaptureMessageFilter() {}
97
98VideoCaptureMessageFilter::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
104void 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
124void 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
144void 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
166void 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
179void 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
191void 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
202void 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