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 "base/stl_util.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 struct VideoCaptureHost::Entry
{
18 Entry(VideoCaptureController
* controller
)
19 : controller(controller
) {}
23 scoped_refptr
<VideoCaptureController
> controller
;
26 VideoCaptureHost::VideoCaptureHost(MediaStreamManager
* media_stream_manager
)
27 : media_stream_manager_(media_stream_manager
) {
30 VideoCaptureHost::~VideoCaptureHost() {}
32 void VideoCaptureHost::OnChannelClosing() {
33 BrowserMessageFilter::OnChannelClosing();
35 // Since the IPC channel is gone, close all requested VideCaptureDevices.
36 for (EntryMap::iterator it
= entries_
.begin(); it
!= entries_
.end(); it
++) {
37 VideoCaptureController
* controller
= it
->second
->controller
.get();
39 VideoCaptureControllerID
controller_id(it
->first
);
40 controller
->StopCapture(controller_id
, this);
41 media_stream_manager_
->video_capture_manager()->RemoveController(
45 STLDeleteValues(&entries_
);
48 void VideoCaptureHost::OnDestruct() const {
49 BrowserThread::DeleteOnIOThread::Destruct(this);
52 ///////////////////////////////////////////////////////////////////////////////
54 // Implements VideoCaptureControllerEventHandler.
55 void VideoCaptureHost::OnError(const VideoCaptureControllerID
& controller_id
) {
56 DVLOG(1) << "VideoCaptureHost::OnError";
57 BrowserThread::PostTask(
58 BrowserThread::IO
, FROM_HERE
,
59 base::Bind(&VideoCaptureHost::DoHandleErrorOnIOThread
,
60 this, controller_id
));
63 void VideoCaptureHost::OnBufferCreated(
64 const VideoCaptureControllerID
& controller_id
,
65 base::SharedMemoryHandle handle
,
68 BrowserThread::PostTask(
69 BrowserThread::IO
, FROM_HERE
,
70 base::Bind(&VideoCaptureHost::DoSendNewBufferOnIOThread
,
71 this, controller_id
, handle
, length
, buffer_id
));
74 void VideoCaptureHost::OnBufferReady(
75 const VideoCaptureControllerID
& controller_id
,
77 base::Time timestamp
) {
78 BrowserThread::PostTask(
79 BrowserThread::IO
, FROM_HERE
,
80 base::Bind(&VideoCaptureHost::DoSendFilledBufferOnIOThread
,
81 this, controller_id
, buffer_id
, timestamp
));
84 void VideoCaptureHost::OnFrameInfo(
85 const VideoCaptureControllerID
& controller_id
,
88 int frame_per_second
) {
89 BrowserThread::PostTask(
90 BrowserThread::IO
, FROM_HERE
,
91 base::Bind(&VideoCaptureHost::DoSendFrameInfoOnIOThread
,
92 this, controller_id
, width
, height
, frame_per_second
));
95 void VideoCaptureHost::OnEnded(const VideoCaptureControllerID
& controller_id
) {
96 DVLOG(1) << "VideoCaptureHost::OnEnded";
97 BrowserThread::PostTask(
98 BrowserThread::IO
, FROM_HERE
,
99 base::Bind(&VideoCaptureHost::DoEndedOnIOThread
, this, controller_id
));
102 void VideoCaptureHost::DoSendNewBufferOnIOThread(
103 const VideoCaptureControllerID
& controller_id
,
104 base::SharedMemoryHandle handle
,
107 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO
));
109 if (entries_
.find(controller_id
) == entries_
.end())
112 Send(new VideoCaptureMsg_NewBuffer(controller_id
.device_id
, handle
,
116 void VideoCaptureHost::DoSendFilledBufferOnIOThread(
117 const VideoCaptureControllerID
& controller_id
,
118 int buffer_id
, base::Time timestamp
) {
119 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO
));
121 if (entries_
.find(controller_id
) == entries_
.end())
124 Send(new VideoCaptureMsg_BufferReady(controller_id
.device_id
, buffer_id
,
128 void VideoCaptureHost::DoHandleErrorOnIOThread(
129 const VideoCaptureControllerID
& controller_id
) {
130 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO
));
132 if (entries_
.find(controller_id
) == entries_
.end())
135 Send(new VideoCaptureMsg_StateChanged(controller_id
.device_id
,
136 VIDEO_CAPTURE_STATE_ERROR
));
137 DeleteVideoCaptureControllerOnIOThread(controller_id
);
140 void VideoCaptureHost::DoEndedOnIOThread(
141 const VideoCaptureControllerID
& controller_id
) {
142 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO
));
143 DVLOG(1) << "VideoCaptureHost::DoEndedOnIOThread";
144 if (entries_
.find(controller_id
) == entries_
.end())
147 Send(new VideoCaptureMsg_StateChanged(controller_id
.device_id
,
148 VIDEO_CAPTURE_STATE_ENDED
));
149 DeleteVideoCaptureControllerOnIOThread(controller_id
);
152 void VideoCaptureHost::DoSendFrameInfoOnIOThread(
153 const VideoCaptureControllerID
& controller_id
,
154 int width
, int height
, int frame_per_second
) {
155 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO
));
157 if (entries_
.find(controller_id
) == entries_
.end())
160 media::VideoCaptureParams params
;
161 params
.width
= width
;
162 params
.height
= height
;
163 params
.frame_per_second
= frame_per_second
;
164 Send(new VideoCaptureMsg_DeviceInfo(controller_id
.device_id
, params
));
165 Send(new VideoCaptureMsg_StateChanged(controller_id
.device_id
,
166 VIDEO_CAPTURE_STATE_STARTED
));
169 ///////////////////////////////////////////////////////////////////////////////
170 // IPC Messages handler.
171 bool VideoCaptureHost::OnMessageReceived(const IPC::Message
& message
,
172 bool* message_was_ok
) {
174 IPC_BEGIN_MESSAGE_MAP_EX(VideoCaptureHost
, message
, *message_was_ok
)
175 IPC_MESSAGE_HANDLER(VideoCaptureHostMsg_Start
, OnStartCapture
)
176 IPC_MESSAGE_HANDLER(VideoCaptureHostMsg_Pause
, OnPauseCapture
)
177 IPC_MESSAGE_HANDLER(VideoCaptureHostMsg_Stop
, OnStopCapture
)
178 IPC_MESSAGE_HANDLER(VideoCaptureHostMsg_BufferReady
, OnReceiveEmptyBuffer
)
179 IPC_MESSAGE_UNHANDLED(handled
= false)
180 IPC_END_MESSAGE_MAP_EX()
185 void VideoCaptureHost::OnStartCapture(int device_id
,
186 const media::VideoCaptureParams
& params
) {
187 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO
));
188 DVLOG(1) << "VideoCaptureHost::OnStartCapture, device_id " << device_id
189 << ", (" << params
.width
190 << ", " << params
.height
191 << ", " << params
.frame_per_second
192 << ", " << params
.session_id
194 VideoCaptureControllerID
controller_id(device_id
);
195 DCHECK(entries_
.find(controller_id
) == entries_
.end());
197 entries_
[controller_id
] = new Entry(NULL
);
198 media_stream_manager_
->video_capture_manager()->AddController(
199 params
, this, base::Bind(&VideoCaptureHost::OnControllerAdded
, this,
203 void VideoCaptureHost::OnControllerAdded(
204 int device_id
, const media::VideoCaptureParams
& params
,
205 VideoCaptureController
* controller
) {
206 BrowserThread::PostTask(
207 BrowserThread::IO
, FROM_HERE
,
208 base::Bind(&VideoCaptureHost::DoControllerAddedOnIOThread
,
209 this, device_id
, params
, make_scoped_refptr(controller
)));
212 void VideoCaptureHost::DoControllerAddedOnIOThread(
213 int device_id
, const media::VideoCaptureParams params
,
214 VideoCaptureController
* controller
) {
215 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO
));
216 VideoCaptureControllerID
controller_id(device_id
);
217 EntryMap::iterator it
= entries_
.find(controller_id
);
218 if (it
== entries_
.end()) {
220 media_stream_manager_
->video_capture_manager()->RemoveController(
226 if (controller
== NULL
) {
227 Send(new VideoCaptureMsg_StateChanged(device_id
,
228 VIDEO_CAPTURE_STATE_ERROR
));
230 entries_
.erase(controller_id
);
234 it
->second
->controller
= controller
;
235 controller
->StartCapture(controller_id
, this, peer_handle(), params
);
238 void VideoCaptureHost::OnStopCapture(int device_id
) {
239 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO
));
240 DVLOG(1) << "VideoCaptureHost::OnStopCapture, device_id " << device_id
;
242 VideoCaptureControllerID
controller_id(device_id
);
244 Send(new VideoCaptureMsg_StateChanged(device_id
,
245 VIDEO_CAPTURE_STATE_STOPPED
));
246 DeleteVideoCaptureControllerOnIOThread(controller_id
);
249 void VideoCaptureHost::OnPauseCapture(int device_id
) {
250 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO
));
251 DVLOG(1) << "VideoCaptureHost::OnPauseCapture, device_id " << device_id
;
253 Send(new VideoCaptureMsg_StateChanged(device_id
, VIDEO_CAPTURE_STATE_ERROR
));
256 void VideoCaptureHost::OnReceiveEmptyBuffer(int device_id
, int buffer_id
) {
257 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO
));
259 VideoCaptureControllerID
controller_id(device_id
);
260 EntryMap::iterator it
= entries_
.find(controller_id
);
261 if (it
!= entries_
.end()) {
262 scoped_refptr
<VideoCaptureController
> controller
= it
->second
->controller
;
263 if (controller
.get())
264 controller
->ReturnBuffer(controller_id
, this, buffer_id
);
268 void VideoCaptureHost::DeleteVideoCaptureControllerOnIOThread(
269 const VideoCaptureControllerID
& controller_id
) {
270 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO
));
272 EntryMap::iterator it
= entries_
.find(controller_id
);
273 if (it
== entries_
.end())
276 VideoCaptureController
* controller
= it
->second
->controller
.get();
278 controller
->StopCapture(controller_id
, this);
279 media_stream_manager_
->video_capture_manager()->RemoveController(
283 entries_
.erase(controller_id
);
286 } // namespace content