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 scoped_refptr
<media::VideoFrame
>& video_frame
,
82 const base::TimeTicks
& timestamp
) {
83 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
84 if (entries_
.find(controller_id
) == entries_
.end())
87 VideoCaptureMsg_BufferReady_Params params
;
88 params
.device_id
= controller_id
;
89 params
.buffer_id
= buffer_id
;
90 params
.timestamp
= timestamp
;
91 video_frame
->metadata()->MergeInternalValuesInto(¶ms
.metadata
);
92 params
.pixel_format
= video_frame
->format();
93 params
.storage_type
= video_frame
->storage_type();
94 params
.coded_size
= video_frame
->coded_size();
95 params
.visible_rect
= video_frame
->visible_rect();
96 if (video_frame
->HasTextures()) {
97 DCHECK_EQ(media::VideoFrame::NumPlanes(video_frame
->format()), 1u)
98 << "Multiplanar textures not supported";
99 params
.mailbox_holder
= video_frame
->mailbox_holder(0);
102 Send(new VideoCaptureMsg_BufferReady(params
));
105 void VideoCaptureHost::OnEnded(VideoCaptureControllerID controller_id
) {
106 DVLOG(1) << "VideoCaptureHost::OnEnded";
107 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
108 BrowserThread::PostTask(
109 BrowserThread::IO
, FROM_HERE
,
110 base::Bind(&VideoCaptureHost::DoEnded
, this, controller_id
));
113 void VideoCaptureHost::DoError(VideoCaptureControllerID controller_id
) {
114 DVLOG(1) << "VideoCaptureHost::DoError";
115 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
116 if (entries_
.find(controller_id
) == entries_
.end())
119 Send(new VideoCaptureMsg_StateChanged(controller_id
,
120 VIDEO_CAPTURE_STATE_ERROR
));
121 DeleteVideoCaptureController(controller_id
, true);
124 void VideoCaptureHost::DoEnded(VideoCaptureControllerID controller_id
) {
125 DVLOG(1) << "VideoCaptureHost::DoEnded";
126 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
127 if (entries_
.find(controller_id
) == entries_
.end())
130 Send(new VideoCaptureMsg_StateChanged(controller_id
,
131 VIDEO_CAPTURE_STATE_ENDED
));
132 DeleteVideoCaptureController(controller_id
, false);
135 ///////////////////////////////////////////////////////////////////////////////
136 // IPC Messages handler.
137 bool VideoCaptureHost::OnMessageReceived(const IPC::Message
& message
) {
139 IPC_BEGIN_MESSAGE_MAP(VideoCaptureHost
, message
)
140 IPC_MESSAGE_HANDLER(VideoCaptureHostMsg_Start
, OnStartCapture
)
141 IPC_MESSAGE_HANDLER(VideoCaptureHostMsg_Pause
, OnPauseCapture
)
142 IPC_MESSAGE_HANDLER(VideoCaptureHostMsg_Resume
, OnResumeCapture
)
143 IPC_MESSAGE_HANDLER(VideoCaptureHostMsg_Stop
, OnStopCapture
)
144 IPC_MESSAGE_HANDLER(VideoCaptureHostMsg_BufferReady
,
145 OnRendererFinishedWithBuffer
)
146 IPC_MESSAGE_HANDLER(VideoCaptureHostMsg_GetDeviceSupportedFormats
,
147 OnGetDeviceSupportedFormats
)
148 IPC_MESSAGE_HANDLER(VideoCaptureHostMsg_GetDeviceFormatsInUse
,
149 OnGetDeviceFormatsInUse
)
150 IPC_MESSAGE_UNHANDLED(handled
= false)
151 IPC_END_MESSAGE_MAP()
156 void VideoCaptureHost::OnStartCapture(int device_id
,
157 media::VideoCaptureSessionId session_id
,
158 const media::VideoCaptureParams
& params
) {
159 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
160 DVLOG(1) << "VideoCaptureHost::OnStartCapture:"
161 << " session_id=" << session_id
<< ", device_id=" << device_id
163 << media::VideoCaptureFormat::ToString(params
.requested_format
)
164 << "@" << params
.requested_format
.frame_rate
<< " ("
165 << (params
.resolution_change_policy
==
166 media::RESOLUTION_POLICY_FIXED_RESOLUTION
168 : (params
.resolution_change_policy
==
169 media::RESOLUTION_POLICY_FIXED_ASPECT_RATIO
170 ? "fixed aspect ratio"
171 : "variable resolution")) << ")";
172 VideoCaptureControllerID
controller_id(device_id
);
173 if (entries_
.find(controller_id
) != entries_
.end()) {
174 Send(new VideoCaptureMsg_StateChanged(device_id
,
175 VIDEO_CAPTURE_STATE_ERROR
));
179 entries_
[controller_id
] = base::WeakPtr
<VideoCaptureController
>();
180 media_stream_manager_
->video_capture_manager()->StartCaptureForClient(
186 base::Bind(&VideoCaptureHost::OnControllerAdded
, this, device_id
));
189 void VideoCaptureHost::OnControllerAdded(
191 const base::WeakPtr
<VideoCaptureController
>& controller
) {
192 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
193 VideoCaptureControllerID
controller_id(device_id
);
194 EntryMap::iterator it
= entries_
.find(controller_id
);
195 if (it
== entries_
.end()) {
197 media_stream_manager_
->video_capture_manager()->StopCaptureForClient(
198 controller
.get(), controller_id
, this, false);
204 Send(new VideoCaptureMsg_StateChanged(device_id
,
205 VIDEO_CAPTURE_STATE_ERROR
));
206 entries_
.erase(controller_id
);
211 it
->second
= controller
;
214 void VideoCaptureHost::OnStopCapture(int device_id
) {
215 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
216 DVLOG(1) << "VideoCaptureHost::OnStopCapture, device_id " << device_id
;
218 VideoCaptureControllerID
controller_id(device_id
);
220 Send(new VideoCaptureMsg_StateChanged(device_id
,
221 VIDEO_CAPTURE_STATE_STOPPED
));
222 DeleteVideoCaptureController(controller_id
, false);
225 void VideoCaptureHost::OnPauseCapture(int device_id
) {
226 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
227 DVLOG(1) << "VideoCaptureHost::OnPauseCapture, device_id " << device_id
;
229 VideoCaptureControllerID
controller_id(device_id
);
230 EntryMap::iterator it
= entries_
.find(controller_id
);
231 if (it
== entries_
.end())
235 media_stream_manager_
->video_capture_manager()->PauseCaptureForClient(
236 it
->second
.get(), controller_id
, this);
240 void VideoCaptureHost::OnResumeCapture(
242 media::VideoCaptureSessionId session_id
,
243 const media::VideoCaptureParams
& params
) {
244 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
245 DVLOG(1) << "VideoCaptureHost::OnResumeCapture, device_id " << device_id
;
247 VideoCaptureControllerID
controller_id(device_id
);
248 EntryMap::iterator it
= entries_
.find(controller_id
);
249 if (it
== entries_
.end())
253 media_stream_manager_
->video_capture_manager()->ResumeCaptureForClient(
254 session_id
, params
, it
->second
.get(), controller_id
, this);
258 void VideoCaptureHost::OnRendererFinishedWithBuffer(
262 double consumer_resource_utilization
) {
263 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
265 VideoCaptureControllerID
controller_id(device_id
);
266 EntryMap::iterator it
= entries_
.find(controller_id
);
267 if (it
!= entries_
.end()) {
268 const base::WeakPtr
<VideoCaptureController
>& controller
= it
->second
;
270 controller
->ReturnBuffer(controller_id
,
274 consumer_resource_utilization
);
279 void VideoCaptureHost::OnGetDeviceSupportedFormats(
281 media::VideoCaptureSessionId capture_session_id
) {
282 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
283 DVLOG(1) << "VideoCaptureHost::OnGetDeviceFormats, capture_session_id "
284 << capture_session_id
;
285 media::VideoCaptureFormats device_supported_formats
;
286 if (!media_stream_manager_
->video_capture_manager()
287 ->GetDeviceSupportedFormats(capture_session_id
,
288 &device_supported_formats
)) {
290 << "Could not retrieve device supported formats for device_id="
291 << device_id
<< " capture_session_id=" << capture_session_id
;
293 Send(new VideoCaptureMsg_DeviceSupportedFormatsEnumerated(
294 device_id
, device_supported_formats
));
297 void VideoCaptureHost::OnGetDeviceFormatsInUse(
299 media::VideoCaptureSessionId capture_session_id
) {
300 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
301 DVLOG(1) << "VideoCaptureHost::OnGetDeviceFormatsInUse, capture_session_id "
302 << capture_session_id
;
303 media::VideoCaptureFormats formats_in_use
;
304 if (!media_stream_manager_
->video_capture_manager()->GetDeviceFormatsInUse(
305 capture_session_id
, &formats_in_use
)) {
306 DVLOG(1) << "Could not retrieve device format(s) in use for device_id="
307 << device_id
<< " capture_session_id=" << capture_session_id
;
309 Send(new VideoCaptureMsg_DeviceFormatsInUseReceived(device_id
,
313 void VideoCaptureHost::DeleteVideoCaptureController(
314 VideoCaptureControllerID controller_id
, bool on_error
) {
315 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
317 EntryMap::iterator it
= entries_
.find(controller_id
);
318 if (it
== entries_
.end())
322 media_stream_manager_
->video_capture_manager()->StopCaptureForClient(
323 it
->second
.get(), controller_id
, this, on_error
);
328 } // namespace content