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/bind_helpers.h"
9 #include "base/memory/scoped_ptr.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"
17 VideoCaptureHost::VideoCaptureHost(MediaStreamManager
* media_stream_manager
)
18 : BrowserMessageFilter(VideoCaptureMsgStart
),
19 media_stream_manager_(media_stream_manager
) {
20 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
23 VideoCaptureHost::~VideoCaptureHost() {}
25 void VideoCaptureHost::OnChannelClosing() {
26 // Since the IPC sender is gone, close all requested VideoCaptureDevices.
27 for (EntryMap::iterator it
= entries_
.begin(); it
!= entries_
.end(); ) {
28 const base::WeakPtr
<VideoCaptureController
>& controller
= it
->second
;
30 const VideoCaptureControllerID
controller_id(it
->first
);
31 media_stream_manager_
->video_capture_manager()->StopCaptureForClient(
32 controller
.get(), controller_id
, this, false);
35 // Remove the entry for this controller_id so that when the controller
36 // is added, the controller will be notified to stop for this client
37 // in DoControllerAdded.
43 void VideoCaptureHost::OnDestruct() const {
44 BrowserThread::DeleteOnIOThread::Destruct(this);
47 ///////////////////////////////////////////////////////////////////////////////
49 // Implements VideoCaptureControllerEventHandler.
50 void VideoCaptureHost::OnError(VideoCaptureControllerID controller_id
) {
51 DVLOG(1) << "VideoCaptureHost::OnError";
52 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
53 BrowserThread::PostTask(
54 BrowserThread::IO
, FROM_HERE
,
55 base::Bind(&VideoCaptureHost::DoError
, this, controller_id
));
58 void VideoCaptureHost::OnBufferCreated(VideoCaptureControllerID controller_id
,
59 base::SharedMemoryHandle handle
,
62 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
63 if (entries_
.find(controller_id
) == entries_
.end())
66 Send(new VideoCaptureMsg_NewBuffer(controller_id
, handle
, length
, buffer_id
));
69 void VideoCaptureHost::OnBufferDestroyed(VideoCaptureControllerID controller_id
,
71 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
72 if (entries_
.find(controller_id
) == entries_
.end())
75 Send(new VideoCaptureMsg_FreeBuffer(controller_id
, buffer_id
));
78 void VideoCaptureHost::OnBufferReady(
79 VideoCaptureControllerID controller_id
,
81 const gfx::Size
& coded_size
,
82 const gfx::Rect
& visible_rect
,
83 const base::TimeTicks
& timestamp
,
84 scoped_ptr
<base::DictionaryValue
> metadata
) {
85 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
86 if (entries_
.find(controller_id
) == entries_
.end())
89 VideoCaptureMsg_BufferReady_Params params
;
90 params
.device_id
= controller_id
;
91 params
.buffer_id
= buffer_id
;
92 params
.coded_size
= coded_size
;
93 params
.visible_rect
= visible_rect
;
94 params
.timestamp
= timestamp
;
96 params
.metadata
.Swap(metadata
.get());
97 Send(new VideoCaptureMsg_BufferReady(params
));
100 void VideoCaptureHost::OnMailboxBufferReady(
101 VideoCaptureControllerID controller_id
,
103 const gpu::MailboxHolder
& mailbox_holder
,
104 const gfx::Size
& packed_frame_size
,
105 const base::TimeTicks
& timestamp
,
106 scoped_ptr
<base::DictionaryValue
> metadata
) {
107 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
109 if (entries_
.find(controller_id
) == entries_
.end())
112 VideoCaptureMsg_MailboxBufferReady_Params params
;
113 params
.device_id
= controller_id
;
114 params
.buffer_id
= buffer_id
;
115 params
.mailbox_holder
= mailbox_holder
;
116 params
.packed_frame_size
= packed_frame_size
;
117 params
.timestamp
= timestamp
;
119 params
.metadata
.Swap(metadata
.get());
120 Send(new VideoCaptureMsg_MailboxBufferReady(params
));
123 void VideoCaptureHost::OnEnded(VideoCaptureControllerID controller_id
) {
124 DVLOG(1) << "VideoCaptureHost::OnEnded";
125 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
126 BrowserThread::PostTask(
127 BrowserThread::IO
, FROM_HERE
,
128 base::Bind(&VideoCaptureHost::DoEnded
, this, controller_id
));
131 void VideoCaptureHost::DoError(VideoCaptureControllerID controller_id
) {
132 DVLOG(1) << "VideoCaptureHost::DoError";
133 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
134 if (entries_
.find(controller_id
) == entries_
.end())
137 Send(new VideoCaptureMsg_StateChanged(controller_id
,
138 VIDEO_CAPTURE_STATE_ERROR
));
139 DeleteVideoCaptureController(controller_id
, true);
142 void VideoCaptureHost::DoEnded(VideoCaptureControllerID controller_id
) {
143 DVLOG(1) << "VideoCaptureHost::DoEnded";
144 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
145 if (entries_
.find(controller_id
) == entries_
.end())
148 Send(new VideoCaptureMsg_StateChanged(controller_id
,
149 VIDEO_CAPTURE_STATE_ENDED
));
150 DeleteVideoCaptureController(controller_id
, false);
153 ///////////////////////////////////////////////////////////////////////////////
154 // IPC Messages handler.
155 bool VideoCaptureHost::OnMessageReceived(const IPC::Message
& message
) {
157 IPC_BEGIN_MESSAGE_MAP(VideoCaptureHost
, message
)
158 IPC_MESSAGE_HANDLER(VideoCaptureHostMsg_Start
, OnStartCapture
)
159 IPC_MESSAGE_HANDLER(VideoCaptureHostMsg_Pause
, OnPauseCapture
)
160 IPC_MESSAGE_HANDLER(VideoCaptureHostMsg_Resume
, OnResumeCapture
)
161 IPC_MESSAGE_HANDLER(VideoCaptureHostMsg_Stop
, OnStopCapture
)
162 IPC_MESSAGE_HANDLER(VideoCaptureHostMsg_BufferReady
, OnReceiveEmptyBuffer
)
163 IPC_MESSAGE_HANDLER(VideoCaptureHostMsg_GetDeviceSupportedFormats
,
164 OnGetDeviceSupportedFormats
)
165 IPC_MESSAGE_HANDLER(VideoCaptureHostMsg_GetDeviceFormatsInUse
,
166 OnGetDeviceFormatsInUse
)
167 IPC_MESSAGE_UNHANDLED(handled
= false)
168 IPC_END_MESSAGE_MAP()
173 void VideoCaptureHost::OnStartCapture(int device_id
,
174 media::VideoCaptureSessionId session_id
,
175 const media::VideoCaptureParams
& params
) {
176 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
177 DVLOG(1) << "VideoCaptureHost::OnStartCapture:"
178 << " session_id=" << session_id
179 << ", device_id=" << device_id
180 << ", format=" << params
.requested_format
.ToString()
181 << "@" << params
.requested_format
.frame_rate
182 << " (" << (params
.resolution_change_policy
==
183 media::RESOLUTION_POLICY_DYNAMIC_WITHIN_LIMIT
?
184 "variable" : "constant")
186 VideoCaptureControllerID
controller_id(device_id
);
187 if (entries_
.find(controller_id
) != entries_
.end()) {
188 Send(new VideoCaptureMsg_StateChanged(device_id
,
189 VIDEO_CAPTURE_STATE_ERROR
));
193 entries_
[controller_id
] = base::WeakPtr
<VideoCaptureController
>();
194 media_stream_manager_
->video_capture_manager()->StartCaptureForClient(
200 base::Bind(&VideoCaptureHost::OnControllerAdded
, this, device_id
));
203 void VideoCaptureHost::OnControllerAdded(
205 const base::WeakPtr
<VideoCaptureController
>& controller
) {
206 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
207 VideoCaptureControllerID
controller_id(device_id
);
208 EntryMap::iterator it
= entries_
.find(controller_id
);
209 if (it
== entries_
.end()) {
211 media_stream_manager_
->video_capture_manager()->StopCaptureForClient(
212 controller
.get(), controller_id
, this, false);
218 Send(new VideoCaptureMsg_StateChanged(device_id
,
219 VIDEO_CAPTURE_STATE_ERROR
));
220 entries_
.erase(controller_id
);
225 it
->second
= controller
;
228 void VideoCaptureHost::OnStopCapture(int device_id
) {
229 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
230 DVLOG(1) << "VideoCaptureHost::OnStopCapture, device_id " << device_id
;
232 VideoCaptureControllerID
controller_id(device_id
);
234 Send(new VideoCaptureMsg_StateChanged(device_id
,
235 VIDEO_CAPTURE_STATE_STOPPED
));
236 DeleteVideoCaptureController(controller_id
, false);
239 void VideoCaptureHost::OnPauseCapture(int device_id
) {
240 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
241 DVLOG(1) << "VideoCaptureHost::OnPauseCapture, device_id " << device_id
;
243 VideoCaptureControllerID
controller_id(device_id
);
244 EntryMap::iterator it
= entries_
.find(controller_id
);
245 if (it
== entries_
.end())
249 media_stream_manager_
->video_capture_manager()->PauseCaptureForClient(
250 it
->second
.get(), controller_id
, this);
254 void VideoCaptureHost::OnResumeCapture(
256 media::VideoCaptureSessionId session_id
,
257 const media::VideoCaptureParams
& params
) {
258 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
259 DVLOG(1) << "VideoCaptureHost::OnResumeCapture, device_id " << device_id
;
261 VideoCaptureControllerID
controller_id(device_id
);
262 EntryMap::iterator it
= entries_
.find(controller_id
);
263 if (it
== entries_
.end())
267 media_stream_manager_
->video_capture_manager()->ResumeCaptureForClient(
268 session_id
, params
, it
->second
.get(), controller_id
, this);
272 void VideoCaptureHost::OnReceiveEmptyBuffer(int device_id
,
275 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
277 VideoCaptureControllerID
controller_id(device_id
);
278 EntryMap::iterator it
= entries_
.find(controller_id
);
279 if (it
!= entries_
.end()) {
280 const base::WeakPtr
<VideoCaptureController
>& controller
= it
->second
;
282 controller
->ReturnBuffer(controller_id
, this, buffer_id
, sync_point
);
286 void VideoCaptureHost::OnGetDeviceSupportedFormats(
288 media::VideoCaptureSessionId capture_session_id
) {
289 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
290 DVLOG(1) << "VideoCaptureHost::OnGetDeviceFormats, capture_session_id "
291 << capture_session_id
;
292 media::VideoCaptureFormats device_supported_formats
;
293 if (!media_stream_manager_
->video_capture_manager()
294 ->GetDeviceSupportedFormats(capture_session_id
,
295 &device_supported_formats
)) {
297 << "Could not retrieve device supported formats for device_id="
298 << device_id
<< " capture_session_id=" << capture_session_id
;
300 Send(new VideoCaptureMsg_DeviceSupportedFormatsEnumerated(
301 device_id
, device_supported_formats
));
304 void VideoCaptureHost::OnGetDeviceFormatsInUse(
306 media::VideoCaptureSessionId capture_session_id
) {
307 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
308 DVLOG(1) << "VideoCaptureHost::OnGetDeviceFormatsInUse, capture_session_id "
309 << capture_session_id
;
310 media::VideoCaptureFormats formats_in_use
;
311 if (!media_stream_manager_
->video_capture_manager()->GetDeviceFormatsInUse(
312 capture_session_id
, &formats_in_use
)) {
313 DVLOG(1) << "Could not retrieve device format(s) in use for device_id="
314 << device_id
<< " capture_session_id=" << capture_session_id
;
316 Send(new VideoCaptureMsg_DeviceFormatsInUseReceived(device_id
,
320 void VideoCaptureHost::DeleteVideoCaptureController(
321 VideoCaptureControllerID controller_id
, bool on_error
) {
322 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
324 EntryMap::iterator it
= entries_
.find(controller_id
);
325 if (it
== entries_
.end())
329 media_stream_manager_
->video_capture_manager()->StopCaptureForClient(
330 it
->second
.get(), controller_id
, this, on_error
);
335 } // namespace content