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 : media_stream_manager_(media_stream_manager
) {
20 VideoCaptureHost::~VideoCaptureHost() {}
22 void VideoCaptureHost::OnChannelClosing() {
23 // Since the IPC channel is gone, close all requested VideoCaptureDevices.
24 for (EntryMap::iterator it
= entries_
.begin(); it
!= entries_
.end(); it
++) {
25 const base::WeakPtr
<VideoCaptureController
>& controller
= it
->second
;
27 VideoCaptureControllerID
controller_id(it
->first
);
28 media_stream_manager_
->video_capture_manager()->StopCaptureForClient(
29 controller
.get(), controller_id
, this);
34 void VideoCaptureHost::OnDestruct() const {
35 BrowserThread::DeleteOnIOThread::Destruct(this);
38 ///////////////////////////////////////////////////////////////////////////////
40 // Implements VideoCaptureControllerEventHandler.
41 void VideoCaptureHost::OnError(const VideoCaptureControllerID
& controller_id
) {
42 DVLOG(1) << "VideoCaptureHost::OnError";
43 BrowserThread::PostTask(
44 BrowserThread::IO
, FROM_HERE
,
45 base::Bind(&VideoCaptureHost::DoHandleErrorOnIOThread
,
46 this, controller_id
));
49 void VideoCaptureHost::OnBufferCreated(
50 const VideoCaptureControllerID
& controller_id
,
51 base::SharedMemoryHandle handle
,
54 BrowserThread::PostTask(
55 BrowserThread::IO
, FROM_HERE
,
56 base::Bind(&VideoCaptureHost::DoSendNewBufferOnIOThread
,
57 this, controller_id
, handle
, length
, buffer_id
));
60 void VideoCaptureHost::OnBufferDestroyed(
61 const VideoCaptureControllerID
& controller_id
,
63 BrowserThread::PostTask(
64 BrowserThread::IO
, FROM_HERE
,
65 base::Bind(&VideoCaptureHost::DoSendFreeBufferOnIOThread
,
66 this, controller_id
, buffer_id
));
69 void VideoCaptureHost::OnBufferReady(
70 const VideoCaptureControllerID
& controller_id
,
73 const media::VideoCaptureFormat
& frame_format
) {
74 BrowserThread::PostTask(
75 BrowserThread::IO
, FROM_HERE
,
76 base::Bind(&VideoCaptureHost::DoSendFilledBufferOnIOThread
,
77 this, controller_id
, buffer_id
, timestamp
,
81 void VideoCaptureHost::OnEnded(const VideoCaptureControllerID
& controller_id
) {
82 DVLOG(1) << "VideoCaptureHost::OnEnded";
83 BrowserThread::PostTask(
84 BrowserThread::IO
, FROM_HERE
,
85 base::Bind(&VideoCaptureHost::DoEndedOnIOThread
, this, controller_id
));
88 void VideoCaptureHost::DoSendNewBufferOnIOThread(
89 const VideoCaptureControllerID
& controller_id
,
90 base::SharedMemoryHandle handle
,
93 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO
));
95 if (entries_
.find(controller_id
) == entries_
.end())
98 Send(new VideoCaptureMsg_NewBuffer(controller_id
.device_id
, handle
,
102 void VideoCaptureHost::DoSendFreeBufferOnIOThread(
103 const VideoCaptureControllerID
& controller_id
,
105 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO
));
107 if (entries_
.find(controller_id
) == entries_
.end())
110 Send(new VideoCaptureMsg_FreeBuffer(controller_id
.device_id
, buffer_id
));
113 void VideoCaptureHost::DoSendFilledBufferOnIOThread(
114 const VideoCaptureControllerID
& controller_id
,
115 int buffer_id
, base::Time timestamp
,
116 const media::VideoCaptureFormat
& format
) {
117 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO
));
119 if (entries_
.find(controller_id
) == entries_
.end())
122 Send(new VideoCaptureMsg_BufferReady(controller_id
.device_id
, buffer_id
,
126 void VideoCaptureHost::DoHandleErrorOnIOThread(
127 const VideoCaptureControllerID
& controller_id
) {
128 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO
));
130 if (entries_
.find(controller_id
) == entries_
.end())
133 Send(new VideoCaptureMsg_StateChanged(controller_id
.device_id
,
134 VIDEO_CAPTURE_STATE_ERROR
));
135 DeleteVideoCaptureControllerOnIOThread(controller_id
);
138 void VideoCaptureHost::DoEndedOnIOThread(
139 const VideoCaptureControllerID
& controller_id
) {
140 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO
));
141 DVLOG(1) << "VideoCaptureHost::DoEndedOnIOThread";
142 if (entries_
.find(controller_id
) == entries_
.end())
145 Send(new VideoCaptureMsg_StateChanged(controller_id
.device_id
,
146 VIDEO_CAPTURE_STATE_ENDED
));
147 DeleteVideoCaptureControllerOnIOThread(controller_id
);
150 ///////////////////////////////////////////////////////////////////////////////
151 // IPC Messages handler.
152 bool VideoCaptureHost::OnMessageReceived(const IPC::Message
& message
,
153 bool* message_was_ok
) {
155 IPC_BEGIN_MESSAGE_MAP_EX(VideoCaptureHost
, message
, *message_was_ok
)
156 IPC_MESSAGE_HANDLER(VideoCaptureHostMsg_Start
, OnStartCapture
)
157 IPC_MESSAGE_HANDLER(VideoCaptureHostMsg_Pause
, OnPauseCapture
)
158 IPC_MESSAGE_HANDLER(VideoCaptureHostMsg_Stop
, OnStopCapture
)
159 IPC_MESSAGE_HANDLER(VideoCaptureHostMsg_BufferReady
, OnReceiveEmptyBuffer
)
160 IPC_MESSAGE_UNHANDLED(handled
= false)
161 IPC_END_MESSAGE_MAP_EX()
166 void VideoCaptureHost::OnStartCapture(int device_id
,
167 media::VideoCaptureSessionId session_id
,
168 const media::VideoCaptureParams
& params
) {
169 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO
));
170 DVLOG(1) << "VideoCaptureHost::OnStartCapture:"
171 << " session_id=" << session_id
172 << ", device_id=" << device_id
173 << ", format=" << params
.requested_format
.frame_size
.ToString()
174 << "@" << params
.requested_format
.frame_rate
175 << " (" << (params
.allow_resolution_change
? "variable" : "constant")
177 VideoCaptureControllerID
controller_id(device_id
);
178 DCHECK(entries_
.find(controller_id
) == entries_
.end());
180 entries_
[controller_id
] = base::WeakPtr
<VideoCaptureController
>();
181 media_stream_manager_
->video_capture_manager()->StartCaptureForClient(
187 base::Bind(&VideoCaptureHost::OnControllerAdded
, this, device_id
));
190 void VideoCaptureHost::OnControllerAdded(
192 const base::WeakPtr
<VideoCaptureController
>& controller
) {
193 BrowserThread::PostTask(
196 base::Bind(&VideoCaptureHost::DoControllerAddedOnIOThread
,
202 void VideoCaptureHost::DoControllerAddedOnIOThread(
204 const base::WeakPtr
<VideoCaptureController
>& controller
) {
205 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO
));
206 VideoCaptureControllerID
controller_id(device_id
);
207 EntryMap::iterator it
= entries_
.find(controller_id
);
208 if (it
== entries_
.end()) {
210 media_stream_manager_
->video_capture_manager()->StopCaptureForClient(
211 controller
.get(), controller_id
, this);
217 Send(new VideoCaptureMsg_StateChanged(device_id
,
218 VIDEO_CAPTURE_STATE_ERROR
));
219 entries_
.erase(controller_id
);
224 it
->second
= controller
;
227 void VideoCaptureHost::OnStopCapture(int device_id
) {
228 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO
));
229 DVLOG(1) << "VideoCaptureHost::OnStopCapture, device_id " << device_id
;
231 VideoCaptureControllerID
controller_id(device_id
);
233 Send(new VideoCaptureMsg_StateChanged(device_id
,
234 VIDEO_CAPTURE_STATE_STOPPED
));
235 DeleteVideoCaptureControllerOnIOThread(controller_id
);
238 void VideoCaptureHost::OnPauseCapture(int device_id
) {
239 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO
));
240 DVLOG(1) << "VideoCaptureHost::OnPauseCapture, device_id " << device_id
;
242 Send(new VideoCaptureMsg_StateChanged(device_id
, VIDEO_CAPTURE_STATE_ERROR
));
245 void VideoCaptureHost::OnReceiveEmptyBuffer(int device_id
, int buffer_id
) {
246 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO
));
248 VideoCaptureControllerID
controller_id(device_id
);
249 EntryMap::iterator it
= entries_
.find(controller_id
);
250 if (it
!= entries_
.end()) {
251 const base::WeakPtr
<VideoCaptureController
>& controller
= it
->second
;
253 controller
->ReturnBuffer(controller_id
, this, buffer_id
);
257 void VideoCaptureHost::DeleteVideoCaptureControllerOnIOThread(
258 const VideoCaptureControllerID
& controller_id
) {
259 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO
));
261 EntryMap::iterator it
= entries_
.find(controller_id
);
262 if (it
== entries_
.end())
266 media_stream_manager_
->video_capture_manager()->StopCaptureForClient(
267 it
->second
.get(), controller_id
, this);
272 } // namespace content