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 16 VideoCaptureHost::VideoCaptureHost(MediaStreamManager* media_stream_manager) 17 : BrowserMessageFilter(VideoCaptureMsgStart), 18 media_stream_manager_(media_stream_manager) { 19 } 20 21 VideoCaptureHost::~VideoCaptureHost() {} 22 23 void VideoCaptureHost::OnChannelClosing() { 24 // Since the IPC sender is gone, close all requested VideoCaptureDevices. 25 for (EntryMap::iterator it = entries_.begin(); it != entries_.end(); ) { 26 const base::WeakPtr<VideoCaptureController>& controller = it->second; 27 if (controller) { 28 VideoCaptureControllerID controller_id(it->first); 29 media_stream_manager_->video_capture_manager()->StopCaptureForClient( 30 controller.get(), controller_id, this, false); 31 ++it; 32 } else { 33 // Remove the entry for this controller_id so that when the controller 34 // is added, the controller will be notified to stop for this client 35 // in DoControllerAddedOnIOThread. 36 entries_.erase(it++); 37 } 38 } 39 } 40 41 void VideoCaptureHost::OnDestruct() const { 42 BrowserThread::DeleteOnIOThread::Destruct(this); 43 } 44 45 /////////////////////////////////////////////////////////////////////////////// 46 47 // Implements VideoCaptureControllerEventHandler. 48 void VideoCaptureHost::OnError(const VideoCaptureControllerID& controller_id) { 49 DVLOG(1) << "VideoCaptureHost::OnError"; 50 BrowserThread::PostTask( 51 BrowserThread::IO, FROM_HERE, 52 base::Bind(&VideoCaptureHost::DoHandleErrorOnIOThread, 53 this, controller_id)); 54 } 55 56 void VideoCaptureHost::OnBufferCreated( 57 const VideoCaptureControllerID& controller_id, 58 base::SharedMemoryHandle handle, 59 int length, 60 int buffer_id) { 61 BrowserThread::PostTask( 62 BrowserThread::IO, FROM_HERE, 63 base::Bind(&VideoCaptureHost::DoSendNewBufferOnIOThread, 64 this, controller_id, handle, length, buffer_id)); 65 } 66 67 void VideoCaptureHost::OnBufferDestroyed( 68 const VideoCaptureControllerID& controller_id, 69 int buffer_id) { 70 BrowserThread::PostTask( 71 BrowserThread::IO, FROM_HERE, 72 base::Bind(&VideoCaptureHost::DoSendFreeBufferOnIOThread, 73 this, controller_id, buffer_id)); 74 } 75 76 void VideoCaptureHost::OnBufferReady( 77 const VideoCaptureControllerID& controller_id, 78 int buffer_id, 79 const media::VideoCaptureFormat& frame_format, 80 base::TimeTicks timestamp) { 81 BrowserThread::PostTask( 82 BrowserThread::IO, 83 FROM_HERE, 84 base::Bind(&VideoCaptureHost::DoSendFilledBufferOnIOThread, 85 this, 86 controller_id, 87 buffer_id, 88 frame_format, 89 timestamp)); 90 } 91 92 void VideoCaptureHost::OnMailboxBufferReady( 93 const VideoCaptureControllerID& controller_id, 94 int buffer_id, 95 const gpu::MailboxHolder& mailbox_holder, 96 const media::VideoCaptureFormat& frame_format, 97 base::TimeTicks timestamp) { 98 BrowserThread::PostTask( 99 BrowserThread::IO, 100 FROM_HERE, 101 base::Bind(&VideoCaptureHost::DoSendFilledMailboxBufferOnIOThread, 102 this, 103 controller_id, 104 buffer_id, 105 mailbox_holder, 106 frame_format, 107 timestamp)); 108 } 109 110 void VideoCaptureHost::OnEnded(const VideoCaptureControllerID& controller_id) { 111 DVLOG(1) << "VideoCaptureHost::OnEnded"; 112 BrowserThread::PostTask( 113 BrowserThread::IO, FROM_HERE, 114 base::Bind(&VideoCaptureHost::DoEndedOnIOThread, this, controller_id)); 115 } 116 117 void VideoCaptureHost::DoSendNewBufferOnIOThread( 118 const VideoCaptureControllerID& controller_id, 119 base::SharedMemoryHandle handle, 120 int length, 121 int buffer_id) { 122 DCHECK_CURRENTLY_ON(BrowserThread::IO); 123 124 if (entries_.find(controller_id) == entries_.end()) 125 return; 126 127 Send(new VideoCaptureMsg_NewBuffer(controller_id.device_id, handle, 128 length, buffer_id)); 129 } 130 131 void VideoCaptureHost::DoSendFreeBufferOnIOThread( 132 const VideoCaptureControllerID& controller_id, 133 int buffer_id) { 134 DCHECK_CURRENTLY_ON(BrowserThread::IO); 135 136 if (entries_.find(controller_id) == entries_.end()) 137 return; 138 139 Send(new VideoCaptureMsg_FreeBuffer(controller_id.device_id, buffer_id)); 140 } 141 142 void VideoCaptureHost::DoSendFilledBufferOnIOThread( 143 const VideoCaptureControllerID& controller_id, 144 int buffer_id, 145 const media::VideoCaptureFormat& format, 146 base::TimeTicks timestamp) { 147 DCHECK_CURRENTLY_ON(BrowserThread::IO); 148 149 if (entries_.find(controller_id) == entries_.end()) 150 return; 151 152 Send(new VideoCaptureMsg_BufferReady( 153 controller_id.device_id, buffer_id, format, timestamp)); 154 } 155 156 void VideoCaptureHost::DoSendFilledMailboxBufferOnIOThread( 157 const VideoCaptureControllerID& controller_id, 158 int buffer_id, 159 const gpu::MailboxHolder& mailbox_holder, 160 const media::VideoCaptureFormat& format, 161 base::TimeTicks timestamp) { 162 DCHECK_CURRENTLY_ON(BrowserThread::IO); 163 164 if (entries_.find(controller_id) == entries_.end()) 165 return; 166 167 Send(new VideoCaptureMsg_MailboxBufferReady( 168 controller_id.device_id, buffer_id, mailbox_holder, format, timestamp)); 169 } 170 171 void VideoCaptureHost::DoHandleErrorOnIOThread( 172 const VideoCaptureControllerID& controller_id) { 173 DCHECK_CURRENTLY_ON(BrowserThread::IO); 174 175 if (entries_.find(controller_id) == entries_.end()) 176 return; 177 178 Send(new VideoCaptureMsg_StateChanged(controller_id.device_id, 179 VIDEO_CAPTURE_STATE_ERROR)); 180 DeleteVideoCaptureControllerOnIOThread(controller_id, true); 181 } 182 183 void VideoCaptureHost::DoEndedOnIOThread( 184 const VideoCaptureControllerID& controller_id) { 185 DCHECK_CURRENTLY_ON(BrowserThread::IO); 186 DVLOG(1) << "VideoCaptureHost::DoEndedOnIOThread"; 187 if (entries_.find(controller_id) == entries_.end()) 188 return; 189 190 Send(new VideoCaptureMsg_StateChanged(controller_id.device_id, 191 VIDEO_CAPTURE_STATE_ENDED)); 192 DeleteVideoCaptureControllerOnIOThread(controller_id, false); 193 } 194 195 /////////////////////////////////////////////////////////////////////////////// 196 // IPC Messages handler. 197 bool VideoCaptureHost::OnMessageReceived(const IPC::Message& message) { 198 bool handled = true; 199 IPC_BEGIN_MESSAGE_MAP(VideoCaptureHost, message) 200 IPC_MESSAGE_HANDLER(VideoCaptureHostMsg_Start, OnStartCapture) 201 IPC_MESSAGE_HANDLER(VideoCaptureHostMsg_Pause, OnPauseCapture) 202 IPC_MESSAGE_HANDLER(VideoCaptureHostMsg_Stop, OnStopCapture) 203 IPC_MESSAGE_HANDLER(VideoCaptureHostMsg_BufferReady, OnReceiveEmptyBuffer) 204 IPC_MESSAGE_HANDLER(VideoCaptureHostMsg_GetDeviceSupportedFormats, 205 OnGetDeviceSupportedFormats) 206 IPC_MESSAGE_HANDLER(VideoCaptureHostMsg_GetDeviceFormatsInUse, 207 OnGetDeviceFormatsInUse) 208 IPC_MESSAGE_UNHANDLED(handled = false) 209 IPC_END_MESSAGE_MAP() 210 211 return handled; 212 } 213 214 void VideoCaptureHost::OnStartCapture(int device_id, 215 media::VideoCaptureSessionId session_id, 216 const media::VideoCaptureParams& params) { 217 DCHECK_CURRENTLY_ON(BrowserThread::IO); 218 DVLOG(1) << "VideoCaptureHost::OnStartCapture:" 219 << " session_id=" << session_id 220 << ", device_id=" << device_id 221 << ", format=" << params.requested_format.frame_size.ToString() 222 << "@" << params.requested_format.frame_rate 223 << " (" << (params.allow_resolution_change ? "variable" : "constant") 224 << ")"; 225 VideoCaptureControllerID controller_id(device_id); 226 if (entries_.find(controller_id) != entries_.end()) { 227 Send(new VideoCaptureMsg_StateChanged(device_id, 228 VIDEO_CAPTURE_STATE_ERROR)); 229 return; 230 } 231 232 entries_[controller_id] = base::WeakPtr<VideoCaptureController>(); 233 media_stream_manager_->video_capture_manager()->StartCaptureForClient( 234 session_id, 235 params, 236 PeerHandle(), 237 controller_id, 238 this, 239 base::Bind(&VideoCaptureHost::OnControllerAdded, this, device_id)); 240 } 241 242 void VideoCaptureHost::OnControllerAdded( 243 int device_id, 244 const base::WeakPtr<VideoCaptureController>& controller) { 245 BrowserThread::PostTask( 246 BrowserThread::IO, 247 FROM_HERE, 248 base::Bind(&VideoCaptureHost::DoControllerAddedOnIOThread, 249 this, 250 device_id, 251 controller)); 252 } 253 254 void VideoCaptureHost::DoControllerAddedOnIOThread( 255 int device_id, 256 const base::WeakPtr<VideoCaptureController>& controller) { 257 DCHECK_CURRENTLY_ON(BrowserThread::IO); 258 VideoCaptureControllerID controller_id(device_id); 259 EntryMap::iterator it = entries_.find(controller_id); 260 if (it == entries_.end()) { 261 if (controller) { 262 media_stream_manager_->video_capture_manager()->StopCaptureForClient( 263 controller.get(), controller_id, this, false); 264 } 265 return; 266 } 267 268 if (!controller) { 269 Send(new VideoCaptureMsg_StateChanged(device_id, 270 VIDEO_CAPTURE_STATE_ERROR)); 271 entries_.erase(controller_id); 272 return; 273 } 274 275 DCHECK(!it->second); 276 it->second = controller; 277 } 278 279 void VideoCaptureHost::OnStopCapture(int device_id) { 280 DCHECK_CURRENTLY_ON(BrowserThread::IO); 281 DVLOG(1) << "VideoCaptureHost::OnStopCapture, device_id " << device_id; 282 283 VideoCaptureControllerID controller_id(device_id); 284 285 Send(new VideoCaptureMsg_StateChanged(device_id, 286 VIDEO_CAPTURE_STATE_STOPPED)); 287 DeleteVideoCaptureControllerOnIOThread(controller_id, false); 288 } 289 290 void VideoCaptureHost::OnPauseCapture(int device_id) { 291 DCHECK_CURRENTLY_ON(BrowserThread::IO); 292 DVLOG(1) << "VideoCaptureHost::OnPauseCapture, device_id " << device_id; 293 // Not used. 294 Send(new VideoCaptureMsg_StateChanged(device_id, VIDEO_CAPTURE_STATE_ERROR)); 295 } 296 297 void VideoCaptureHost::OnReceiveEmptyBuffer( 298 int device_id, 299 int buffer_id, 300 const std::vector<uint32>& sync_points) { 301 DCHECK_CURRENTLY_ON(BrowserThread::IO); 302 303 VideoCaptureControllerID controller_id(device_id); 304 EntryMap::iterator it = entries_.find(controller_id); 305 if (it != entries_.end()) { 306 const base::WeakPtr<VideoCaptureController>& controller = it->second; 307 if (controller) 308 controller->ReturnBuffer(controller_id, this, buffer_id, sync_points); 309 } 310 } 311 312 void VideoCaptureHost::OnGetDeviceSupportedFormats( 313 int device_id, 314 media::VideoCaptureSessionId capture_session_id) { 315 DCHECK_CURRENTLY_ON(BrowserThread::IO); 316 DVLOG(1) << "VideoCaptureHost::OnGetDeviceFormats, capture_session_id " 317 << capture_session_id; 318 media::VideoCaptureFormats device_supported_formats; 319 if (!media_stream_manager_->video_capture_manager() 320 ->GetDeviceSupportedFormats(capture_session_id, 321 &device_supported_formats)) { 322 DLOG(WARNING) 323 << "Could not retrieve device supported formats for device_id=" 324 << device_id << " capture_session_id=" << capture_session_id; 325 } 326 Send(new VideoCaptureMsg_DeviceSupportedFormatsEnumerated( 327 device_id, device_supported_formats)); 328 } 329 330 void VideoCaptureHost::OnGetDeviceFormatsInUse( 331 int device_id, 332 media::VideoCaptureSessionId capture_session_id) { 333 DCHECK_CURRENTLY_ON(BrowserThread::IO); 334 DVLOG(1) << "VideoCaptureHost::OnGetDeviceFormatsInUse, capture_session_id " 335 << capture_session_id; 336 media::VideoCaptureFormats formats_in_use; 337 if (!media_stream_manager_->video_capture_manager()->GetDeviceFormatsInUse( 338 capture_session_id, &formats_in_use)) { 339 DVLOG(1) << "Could not retrieve device format(s) in use for device_id=" 340 << device_id << " capture_session_id=" << capture_session_id; 341 } 342 Send(new VideoCaptureMsg_DeviceFormatsInUseReceived(device_id, 343 formats_in_use)); 344 } 345 346 void VideoCaptureHost::DeleteVideoCaptureControllerOnIOThread( 347 const VideoCaptureControllerID& controller_id, bool on_error) { 348 DCHECK_CURRENTLY_ON(BrowserThread::IO); 349 350 EntryMap::iterator it = entries_.find(controller_id); 351 if (it == entries_.end()) 352 return; 353 354 if (it->second) { 355 media_stream_manager_->video_capture_manager()->StopCaptureForClient( 356 it->second.get(), controller_id, this, on_error); 357 } 358 entries_.erase(it); 359 } 360 361 } // namespace content 362