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.
4
5 #include "content/browser/renderer_host/media/video_capture_host.h"
6
7 #include "base/bind.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"
13
14 namespace content {
15
VideoCaptureHost(MediaStreamManager * media_stream_manager)16 VideoCaptureHost::VideoCaptureHost(MediaStreamManager* media_stream_manager)
17 : media_stream_manager_(media_stream_manager) {
18 }
19
~VideoCaptureHost()20 VideoCaptureHost::~VideoCaptureHost() {}
21
OnChannelClosing()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;
26 if (controller) {
27 VideoCaptureControllerID controller_id(it->first);
28 media_stream_manager_->video_capture_manager()->StopCaptureForClient(
29 controller.get(), controller_id, this);
30 }
31 }
32 }
33
OnDestruct() const34 void VideoCaptureHost::OnDestruct() const {
35 BrowserThread::DeleteOnIOThread::Destruct(this);
36 }
37
38 ///////////////////////////////////////////////////////////////////////////////
39
40 // Implements VideoCaptureControllerEventHandler.
OnError(const VideoCaptureControllerID & controller_id)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));
47 }
48
OnBufferCreated(const VideoCaptureControllerID & controller_id,base::SharedMemoryHandle handle,int length,int buffer_id)49 void VideoCaptureHost::OnBufferCreated(
50 const VideoCaptureControllerID& controller_id,
51 base::SharedMemoryHandle handle,
52 int length,
53 int buffer_id) {
54 BrowserThread::PostTask(
55 BrowserThread::IO, FROM_HERE,
56 base::Bind(&VideoCaptureHost::DoSendNewBufferOnIOThread,
57 this, controller_id, handle, length, buffer_id));
58 }
59
OnBufferDestroyed(const VideoCaptureControllerID & controller_id,int buffer_id)60 void VideoCaptureHost::OnBufferDestroyed(
61 const VideoCaptureControllerID& controller_id,
62 int buffer_id) {
63 BrowserThread::PostTask(
64 BrowserThread::IO, FROM_HERE,
65 base::Bind(&VideoCaptureHost::DoSendFreeBufferOnIOThread,
66 this, controller_id, buffer_id));
67 }
68
OnBufferReady(const VideoCaptureControllerID & controller_id,int buffer_id,base::Time timestamp,const media::VideoCaptureFormat & frame_format)69 void VideoCaptureHost::OnBufferReady(
70 const VideoCaptureControllerID& controller_id,
71 int buffer_id,
72 base::Time timestamp,
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,
78 frame_format));
79 }
80
OnEnded(const VideoCaptureControllerID & controller_id)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));
86 }
87
DoSendNewBufferOnIOThread(const VideoCaptureControllerID & controller_id,base::SharedMemoryHandle handle,int length,int buffer_id)88 void VideoCaptureHost::DoSendNewBufferOnIOThread(
89 const VideoCaptureControllerID& controller_id,
90 base::SharedMemoryHandle handle,
91 int length,
92 int buffer_id) {
93 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
94
95 if (entries_.find(controller_id) == entries_.end())
96 return;
97
98 Send(new VideoCaptureMsg_NewBuffer(controller_id.device_id, handle,
99 length, buffer_id));
100 }
101
DoSendFreeBufferOnIOThread(const VideoCaptureControllerID & controller_id,int buffer_id)102 void VideoCaptureHost::DoSendFreeBufferOnIOThread(
103 const VideoCaptureControllerID& controller_id,
104 int buffer_id) {
105 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
106
107 if (entries_.find(controller_id) == entries_.end())
108 return;
109
110 Send(new VideoCaptureMsg_FreeBuffer(controller_id.device_id, buffer_id));
111 }
112
DoSendFilledBufferOnIOThread(const VideoCaptureControllerID & controller_id,int buffer_id,base::Time timestamp,const media::VideoCaptureFormat & format)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));
118
119 if (entries_.find(controller_id) == entries_.end())
120 return;
121
122 Send(new VideoCaptureMsg_BufferReady(controller_id.device_id, buffer_id,
123 timestamp, format));
124 }
125
DoHandleErrorOnIOThread(const VideoCaptureControllerID & controller_id)126 void VideoCaptureHost::DoHandleErrorOnIOThread(
127 const VideoCaptureControllerID& controller_id) {
128 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
129
130 if (entries_.find(controller_id) == entries_.end())
131 return;
132
133 Send(new VideoCaptureMsg_StateChanged(controller_id.device_id,
134 VIDEO_CAPTURE_STATE_ERROR));
135 DeleteVideoCaptureControllerOnIOThread(controller_id);
136 }
137
DoEndedOnIOThread(const VideoCaptureControllerID & 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())
143 return;
144
145 Send(new VideoCaptureMsg_StateChanged(controller_id.device_id,
146 VIDEO_CAPTURE_STATE_ENDED));
147 DeleteVideoCaptureControllerOnIOThread(controller_id);
148 }
149
150 ///////////////////////////////////////////////////////////////////////////////
151 // IPC Messages handler.
OnMessageReceived(const IPC::Message & message,bool * message_was_ok)152 bool VideoCaptureHost::OnMessageReceived(const IPC::Message& message,
153 bool* message_was_ok) {
154 bool handled = true;
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()
162
163 return handled;
164 }
165
OnStartCapture(int device_id,media::VideoCaptureSessionId session_id,const media::VideoCaptureParams & params)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")
176 << ")";
177 VideoCaptureControllerID controller_id(device_id);
178 DCHECK(entries_.find(controller_id) == entries_.end());
179
180 entries_[controller_id] = base::WeakPtr<VideoCaptureController>();
181 media_stream_manager_->video_capture_manager()->StartCaptureForClient(
182 session_id,
183 params,
184 PeerHandle(),
185 controller_id,
186 this,
187 base::Bind(&VideoCaptureHost::OnControllerAdded, this, device_id));
188 }
189
OnControllerAdded(int device_id,const base::WeakPtr<VideoCaptureController> & controller)190 void VideoCaptureHost::OnControllerAdded(
191 int device_id,
192 const base::WeakPtr<VideoCaptureController>& controller) {
193 BrowserThread::PostTask(
194 BrowserThread::IO,
195 FROM_HERE,
196 base::Bind(&VideoCaptureHost::DoControllerAddedOnIOThread,
197 this,
198 device_id,
199 controller));
200 }
201
DoControllerAddedOnIOThread(int device_id,const base::WeakPtr<VideoCaptureController> & controller)202 void VideoCaptureHost::DoControllerAddedOnIOThread(
203 int device_id,
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()) {
209 if (controller) {
210 media_stream_manager_->video_capture_manager()->StopCaptureForClient(
211 controller.get(), controller_id, this);
212 }
213 return;
214 }
215
216 if (!controller) {
217 Send(new VideoCaptureMsg_StateChanged(device_id,
218 VIDEO_CAPTURE_STATE_ERROR));
219 entries_.erase(controller_id);
220 return;
221 }
222
223 DCHECK(!it->second);
224 it->second = controller;
225 }
226
OnStopCapture(int device_id)227 void VideoCaptureHost::OnStopCapture(int device_id) {
228 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
229 DVLOG(1) << "VideoCaptureHost::OnStopCapture, device_id " << device_id;
230
231 VideoCaptureControllerID controller_id(device_id);
232
233 Send(new VideoCaptureMsg_StateChanged(device_id,
234 VIDEO_CAPTURE_STATE_STOPPED));
235 DeleteVideoCaptureControllerOnIOThread(controller_id);
236 }
237
OnPauseCapture(int device_id)238 void VideoCaptureHost::OnPauseCapture(int device_id) {
239 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
240 DVLOG(1) << "VideoCaptureHost::OnPauseCapture, device_id " << device_id;
241 // Not used.
242 Send(new VideoCaptureMsg_StateChanged(device_id, VIDEO_CAPTURE_STATE_ERROR));
243 }
244
OnReceiveEmptyBuffer(int device_id,int buffer_id)245 void VideoCaptureHost::OnReceiveEmptyBuffer(int device_id, int buffer_id) {
246 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
247
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;
252 if (controller)
253 controller->ReturnBuffer(controller_id, this, buffer_id);
254 }
255 }
256
DeleteVideoCaptureControllerOnIOThread(const VideoCaptureControllerID & controller_id)257 void VideoCaptureHost::DeleteVideoCaptureControllerOnIOThread(
258 const VideoCaptureControllerID& controller_id) {
259 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
260
261 EntryMap::iterator it = entries_.find(controller_id);
262 if (it == entries_.end())
263 return;
264
265 if (it->second) {
266 media_stream_manager_->video_capture_manager()->StopCaptureForClient(
267 it->second.get(), controller_id, this);
268 }
269 entries_.erase(it);
270 }
271
272 } // namespace content
273