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.
5 #include "content/browser/renderer_host/media/video_capture_host.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"
16 VideoCaptureHost::VideoCaptureHost(MediaStreamManager
* media_stream_manager
)
17 : BrowserMessageFilter(VideoCaptureMsgStart
),
18 media_stream_manager_(media_stream_manager
) {
21 VideoCaptureHost::~VideoCaptureHost() {}
23 void VideoCaptureHost::OnChannelClosing() {
24 // Since the IPC channel is gone, close all requested VideoCaptureDevices.
25 for (EntryMap::iterator it
= entries_
.begin(); it
!= entries_
.end(); ) {
26 const base::WeakPtr
<VideoCaptureController
>& controller
= it
->second
;
28 VideoCaptureControllerID
controller_id(it
->first
);
29 media_stream_manager_
->video_capture_manager()->StopCaptureForClient(
30 controller
.get(), controller_id
, this, false);
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.
41 void VideoCaptureHost::OnDestruct() const {
42 BrowserThread::DeleteOnIOThread::Destruct(this);
45 ///////////////////////////////////////////////////////////////////////////////
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
));
56 void VideoCaptureHost::OnBufferCreated(
57 const VideoCaptureControllerID
& controller_id
,
58 base::SharedMemoryHandle handle
,
61 BrowserThread::PostTask(
62 BrowserThread::IO
, FROM_HERE
,
63 base::Bind(&VideoCaptureHost::DoSendNewBufferOnIOThread
,
64 this, controller_id
, handle
, length
, buffer_id
));
67 void VideoCaptureHost::OnBufferDestroyed(
68 const VideoCaptureControllerID
& controller_id
,
70 BrowserThread::PostTask(
71 BrowserThread::IO
, FROM_HERE
,
72 base::Bind(&VideoCaptureHost::DoSendFreeBufferOnIOThread
,
73 this, controller_id
, buffer_id
));
76 void VideoCaptureHost::OnBufferReady(
77 const VideoCaptureControllerID
& controller_id
,
79 const media::VideoCaptureFormat
& frame_format
,
80 base::TimeTicks timestamp
) {
81 BrowserThread::PostTask(
84 base::Bind(&VideoCaptureHost::DoSendFilledBufferOnIOThread
,
92 void VideoCaptureHost::OnMailboxBufferReady(
93 const VideoCaptureControllerID
& controller_id
,
95 const gpu::MailboxHolder
& mailbox_holder
,
96 const media::VideoCaptureFormat
& frame_format
,
97 base::TimeTicks timestamp
) {
98 BrowserThread::PostTask(
101 base::Bind(&VideoCaptureHost::DoSendFilledMailboxBufferOnIOThread
,
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
));
117 void VideoCaptureHost::DoSendNewBufferOnIOThread(
118 const VideoCaptureControllerID
& controller_id
,
119 base::SharedMemoryHandle handle
,
122 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
124 if (entries_
.find(controller_id
) == entries_
.end())
127 Send(new VideoCaptureMsg_NewBuffer(controller_id
.device_id
, handle
,
131 void VideoCaptureHost::DoSendFreeBufferOnIOThread(
132 const VideoCaptureControllerID
& controller_id
,
134 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
136 if (entries_
.find(controller_id
) == entries_
.end())
139 Send(new VideoCaptureMsg_FreeBuffer(controller_id
.device_id
, buffer_id
));
142 void VideoCaptureHost::DoSendFilledBufferOnIOThread(
143 const VideoCaptureControllerID
& controller_id
,
145 const media::VideoCaptureFormat
& format
,
146 base::TimeTicks timestamp
) {
147 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
149 if (entries_
.find(controller_id
) == entries_
.end())
152 Send(new VideoCaptureMsg_BufferReady(
153 controller_id
.device_id
, buffer_id
, format
, timestamp
));
156 void VideoCaptureHost::DoSendFilledMailboxBufferOnIOThread(
157 const VideoCaptureControllerID
& controller_id
,
159 const gpu::MailboxHolder
& mailbox_holder
,
160 const media::VideoCaptureFormat
& format
,
161 base::TimeTicks timestamp
) {
162 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
164 if (entries_
.find(controller_id
) == entries_
.end())
167 Send(new VideoCaptureMsg_MailboxBufferReady(
168 controller_id
.device_id
, buffer_id
, mailbox_holder
, format
, timestamp
));
171 void VideoCaptureHost::DoHandleErrorOnIOThread(
172 const VideoCaptureControllerID
& controller_id
) {
173 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
175 if (entries_
.find(controller_id
) == entries_
.end())
178 Send(new VideoCaptureMsg_StateChanged(controller_id
.device_id
,
179 VIDEO_CAPTURE_STATE_ERROR
));
180 DeleteVideoCaptureControllerOnIOThread(controller_id
, true);
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())
190 Send(new VideoCaptureMsg_StateChanged(controller_id
.device_id
,
191 VIDEO_CAPTURE_STATE_ENDED
));
192 DeleteVideoCaptureControllerOnIOThread(controller_id
, false);
195 ///////////////////////////////////////////////////////////////////////////////
196 // IPC Messages handler.
197 bool VideoCaptureHost::OnMessageReceived(const IPC::Message
& message
,
198 bool* message_was_ok
) {
200 IPC_BEGIN_MESSAGE_MAP_EX(VideoCaptureHost
, message
, *message_was_ok
)
201 IPC_MESSAGE_HANDLER(VideoCaptureHostMsg_Start
, OnStartCapture
)
202 IPC_MESSAGE_HANDLER(VideoCaptureHostMsg_Pause
, OnPauseCapture
)
203 IPC_MESSAGE_HANDLER(VideoCaptureHostMsg_Stop
, OnStopCapture
)
204 IPC_MESSAGE_HANDLER(VideoCaptureHostMsg_BufferReady
, OnReceiveEmptyBuffer
)
205 IPC_MESSAGE_HANDLER(VideoCaptureHostMsg_GetDeviceSupportedFormats
,
206 OnGetDeviceSupportedFormats
)
207 IPC_MESSAGE_HANDLER(VideoCaptureHostMsg_GetDeviceFormatsInUse
,
208 OnGetDeviceFormatsInUse
)
209 IPC_MESSAGE_UNHANDLED(handled
= false)
210 IPC_END_MESSAGE_MAP_EX()
215 void VideoCaptureHost::OnStartCapture(int device_id
,
216 media::VideoCaptureSessionId session_id
,
217 const media::VideoCaptureParams
& params
) {
218 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
219 DVLOG(1) << "VideoCaptureHost::OnStartCapture:"
220 << " session_id=" << session_id
221 << ", device_id=" << device_id
222 << ", format=" << params
.requested_format
.frame_size
.ToString()
223 << "@" << params
.requested_format
.frame_rate
224 << " (" << (params
.allow_resolution_change
? "variable" : "constant")
226 VideoCaptureControllerID
controller_id(device_id
);
227 if (entries_
.find(controller_id
) != entries_
.end()) {
228 Send(new VideoCaptureMsg_StateChanged(device_id
,
229 VIDEO_CAPTURE_STATE_ERROR
));
233 entries_
[controller_id
] = base::WeakPtr
<VideoCaptureController
>();
234 media_stream_manager_
->video_capture_manager()->StartCaptureForClient(
240 base::Bind(&VideoCaptureHost::OnControllerAdded
, this, device_id
));
243 void VideoCaptureHost::OnControllerAdded(
245 const base::WeakPtr
<VideoCaptureController
>& controller
) {
246 BrowserThread::PostTask(
249 base::Bind(&VideoCaptureHost::DoControllerAddedOnIOThread
,
255 void VideoCaptureHost::DoControllerAddedOnIOThread(
257 const base::WeakPtr
<VideoCaptureController
>& controller
) {
258 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
259 VideoCaptureControllerID
controller_id(device_id
);
260 EntryMap::iterator it
= entries_
.find(controller_id
);
261 if (it
== entries_
.end()) {
263 media_stream_manager_
->video_capture_manager()->StopCaptureForClient(
264 controller
.get(), controller_id
, this, false);
270 Send(new VideoCaptureMsg_StateChanged(device_id
,
271 VIDEO_CAPTURE_STATE_ERROR
));
272 entries_
.erase(controller_id
);
277 it
->second
= controller
;
280 void VideoCaptureHost::OnStopCapture(int device_id
) {
281 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
282 DVLOG(1) << "VideoCaptureHost::OnStopCapture, device_id " << device_id
;
284 VideoCaptureControllerID
controller_id(device_id
);
286 Send(new VideoCaptureMsg_StateChanged(device_id
,
287 VIDEO_CAPTURE_STATE_STOPPED
));
288 DeleteVideoCaptureControllerOnIOThread(controller_id
, false);
291 void VideoCaptureHost::OnPauseCapture(int device_id
) {
292 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
293 DVLOG(1) << "VideoCaptureHost::OnPauseCapture, device_id " << device_id
;
295 Send(new VideoCaptureMsg_StateChanged(device_id
, VIDEO_CAPTURE_STATE_ERROR
));
298 void VideoCaptureHost::OnReceiveEmptyBuffer(
301 const std::vector
<uint32
>& sync_points
) {
302 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
304 VideoCaptureControllerID
controller_id(device_id
);
305 EntryMap::iterator it
= entries_
.find(controller_id
);
306 if (it
!= entries_
.end()) {
307 const base::WeakPtr
<VideoCaptureController
>& controller
= it
->second
;
309 controller
->ReturnBuffer(controller_id
, this, buffer_id
, sync_points
);
313 void VideoCaptureHost::OnGetDeviceSupportedFormats(
315 media::VideoCaptureSessionId capture_session_id
) {
316 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
317 DVLOG(1) << "VideoCaptureHost::OnGetDeviceFormats, capture_session_id "
318 << capture_session_id
;
319 media::VideoCaptureFormats device_supported_formats
;
320 if (!media_stream_manager_
->video_capture_manager()
321 ->GetDeviceSupportedFormats(capture_session_id
,
322 &device_supported_formats
)) {
324 << "Could not retrieve device supported formats for device_id="
325 << device_id
<< " capture_session_id=" << capture_session_id
;
327 Send(new VideoCaptureMsg_DeviceSupportedFormatsEnumerated(
328 device_id
, device_supported_formats
));
331 void VideoCaptureHost::OnGetDeviceFormatsInUse(
333 media::VideoCaptureSessionId capture_session_id
) {
334 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
335 DVLOG(1) << "VideoCaptureHost::OnGetDeviceFormatsInUse, capture_session_id "
336 << capture_session_id
;
337 media::VideoCaptureFormats formats_in_use
;
338 if (!media_stream_manager_
->video_capture_manager()->GetDeviceFormatsInUse(
339 capture_session_id
, &formats_in_use
)) {
340 DVLOG(1) << "Could not retrieve device format(s) in use for device_id="
341 << device_id
<< " capture_session_id=" << capture_session_id
;
343 Send(new VideoCaptureMsg_DeviceFormatsInUseReceived(device_id
,
347 void VideoCaptureHost::DeleteVideoCaptureControllerOnIOThread(
348 const VideoCaptureControllerID
& controller_id
, bool on_error
) {
349 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
351 EntryMap::iterator it
= entries_
.find(controller_id
);
352 if (it
== entries_
.end())
356 media_stream_manager_
->video_capture_manager()->StopCaptureForClient(
357 it
->second
.get(), controller_id
, this, on_error
);
362 } // namespace content