video_capture_host.cc revision 5f1c94371a64b3196d4be9466099bb892df9b88e
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 14namespace content { 15 16VideoCaptureHost::VideoCaptureHost(MediaStreamManager* media_stream_manager) 17 : BrowserMessageFilter(VideoCaptureMsgStart), 18 media_stream_manager_(media_stream_manager) { 19} 20 21VideoCaptureHost::~VideoCaptureHost() {} 22 23void 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 41void VideoCaptureHost::OnDestruct() const { 42 BrowserThread::DeleteOnIOThread::Destruct(this); 43} 44 45/////////////////////////////////////////////////////////////////////////////// 46 47// Implements VideoCaptureControllerEventHandler. 48void 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 56void 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 67void 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 76void 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 92void 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 110void 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 117void 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 131void 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 142void 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 156void 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 171void 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 183void 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. 197bool 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 214void 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 242void 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 254void 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 279void 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 290void 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 297void VideoCaptureHost::OnReceiveEmptyBuffer(int device_id, 298 int buffer_id, 299 uint32 sync_point) { 300 DCHECK_CURRENTLY_ON(BrowserThread::IO); 301 302 VideoCaptureControllerID controller_id(device_id); 303 EntryMap::iterator it = entries_.find(controller_id); 304 if (it != entries_.end()) { 305 const base::WeakPtr<VideoCaptureController>& controller = it->second; 306 if (controller) 307 controller->ReturnBuffer(controller_id, this, buffer_id, sync_point); 308 } 309} 310 311void VideoCaptureHost::OnGetDeviceSupportedFormats( 312 int device_id, 313 media::VideoCaptureSessionId capture_session_id) { 314 DCHECK_CURRENTLY_ON(BrowserThread::IO); 315 DVLOG(1) << "VideoCaptureHost::OnGetDeviceFormats, capture_session_id " 316 << capture_session_id; 317 media::VideoCaptureFormats device_supported_formats; 318 if (!media_stream_manager_->video_capture_manager() 319 ->GetDeviceSupportedFormats(capture_session_id, 320 &device_supported_formats)) { 321 DLOG(WARNING) 322 << "Could not retrieve device supported formats for device_id=" 323 << device_id << " capture_session_id=" << capture_session_id; 324 } 325 Send(new VideoCaptureMsg_DeviceSupportedFormatsEnumerated( 326 device_id, device_supported_formats)); 327} 328 329void VideoCaptureHost::OnGetDeviceFormatsInUse( 330 int device_id, 331 media::VideoCaptureSessionId capture_session_id) { 332 DCHECK_CURRENTLY_ON(BrowserThread::IO); 333 DVLOG(1) << "VideoCaptureHost::OnGetDeviceFormatsInUse, capture_session_id " 334 << capture_session_id; 335 media::VideoCaptureFormats formats_in_use; 336 if (!media_stream_manager_->video_capture_manager()->GetDeviceFormatsInUse( 337 capture_session_id, &formats_in_use)) { 338 DVLOG(1) << "Could not retrieve device format(s) in use for device_id=" 339 << device_id << " capture_session_id=" << capture_session_id; 340 } 341 Send(new VideoCaptureMsg_DeviceFormatsInUseReceived(device_id, 342 formats_in_use)); 343} 344 345void VideoCaptureHost::DeleteVideoCaptureControllerOnIOThread( 346 const VideoCaptureControllerID& controller_id, bool on_error) { 347 DCHECK_CURRENTLY_ON(BrowserThread::IO); 348 349 EntryMap::iterator it = entries_.find(controller_id); 350 if (it == entries_.end()) 351 return; 352 353 if (it->second) { 354 media_stream_manager_->video_capture_manager()->StopCaptureForClient( 355 it->second.get(), controller_id, this, on_error); 356 } 357 entries_.erase(it); 358} 359 360} // namespace content 361