video_capture_host.cc revision 5c02ac1a9c1b504631c0a3d2b6e737b5d738bae1
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 channel 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* message_was_ok) { 199 bool handled = true; 200 IPC_BEGIN_MESSAGE_MAP_EX(VideoCaptureHost, message, *message_was_ok) 201 IPC_MESSAGE_HANDLER(VideoCaptureHostMsg_Start, OnStartCapture) 202 IPC_MESSAGE_HANDLER(VideoCaptureHostMsg_Pause, OnPauseCapture) 203 IPC_MESSAGE_HANDLER(VideoCaptureHostMsg_Stop, OnStopCapture) 204 IPC_MESSAGE_HANDLER(VideoCaptureHostMsg_BufferReady, OnReceiveEmptyBuffer) 205 IPC_MESSAGE_HANDLER(VideoCaptureHostMsg_GetDeviceSupportedFormats, 206 OnGetDeviceSupportedFormats) 207 IPC_MESSAGE_HANDLER(VideoCaptureHostMsg_GetDeviceFormatsInUse, 208 OnGetDeviceFormatsInUse) 209 IPC_MESSAGE_UNHANDLED(handled = false) 210 IPC_END_MESSAGE_MAP_EX() 211 212 return handled; 213} 214 215void VideoCaptureHost::OnStartCapture(int device_id, 216 media::VideoCaptureSessionId session_id, 217 const media::VideoCaptureParams& params) { 218 DCHECK_CURRENTLY_ON(BrowserThread::IO); 219 DVLOG(1) << "VideoCaptureHost::OnStartCapture:" 220 << " session_id=" << session_id 221 << ", device_id=" << device_id 222 << ", format=" << params.requested_format.frame_size.ToString() 223 << "@" << params.requested_format.frame_rate 224 << " (" << (params.allow_resolution_change ? "variable" : "constant") 225 << ")"; 226 VideoCaptureControllerID controller_id(device_id); 227 if (entries_.find(controller_id) != entries_.end()) { 228 Send(new VideoCaptureMsg_StateChanged(device_id, 229 VIDEO_CAPTURE_STATE_ERROR)); 230 return; 231 } 232 233 entries_[controller_id] = base::WeakPtr<VideoCaptureController>(); 234 media_stream_manager_->video_capture_manager()->StartCaptureForClient( 235 session_id, 236 params, 237 PeerHandle(), 238 controller_id, 239 this, 240 base::Bind(&VideoCaptureHost::OnControllerAdded, this, device_id)); 241} 242 243void VideoCaptureHost::OnControllerAdded( 244 int device_id, 245 const base::WeakPtr<VideoCaptureController>& controller) { 246 BrowserThread::PostTask( 247 BrowserThread::IO, 248 FROM_HERE, 249 base::Bind(&VideoCaptureHost::DoControllerAddedOnIOThread, 250 this, 251 device_id, 252 controller)); 253} 254 255void VideoCaptureHost::DoControllerAddedOnIOThread( 256 int device_id, 257 const base::WeakPtr<VideoCaptureController>& controller) { 258 DCHECK_CURRENTLY_ON(BrowserThread::IO); 259 VideoCaptureControllerID controller_id(device_id); 260 EntryMap::iterator it = entries_.find(controller_id); 261 if (it == entries_.end()) { 262 if (controller) { 263 media_stream_manager_->video_capture_manager()->StopCaptureForClient( 264 controller.get(), controller_id, this, false); 265 } 266 return; 267 } 268 269 if (!controller) { 270 Send(new VideoCaptureMsg_StateChanged(device_id, 271 VIDEO_CAPTURE_STATE_ERROR)); 272 entries_.erase(controller_id); 273 return; 274 } 275 276 DCHECK(!it->second); 277 it->second = controller; 278} 279 280void VideoCaptureHost::OnStopCapture(int device_id) { 281 DCHECK_CURRENTLY_ON(BrowserThread::IO); 282 DVLOG(1) << "VideoCaptureHost::OnStopCapture, device_id " << device_id; 283 284 VideoCaptureControllerID controller_id(device_id); 285 286 Send(new VideoCaptureMsg_StateChanged(device_id, 287 VIDEO_CAPTURE_STATE_STOPPED)); 288 DeleteVideoCaptureControllerOnIOThread(controller_id, false); 289} 290 291void VideoCaptureHost::OnPauseCapture(int device_id) { 292 DCHECK_CURRENTLY_ON(BrowserThread::IO); 293 DVLOG(1) << "VideoCaptureHost::OnPauseCapture, device_id " << device_id; 294 // Not used. 295 Send(new VideoCaptureMsg_StateChanged(device_id, VIDEO_CAPTURE_STATE_ERROR)); 296} 297 298void VideoCaptureHost::OnReceiveEmptyBuffer( 299 int device_id, 300 int buffer_id, 301 const std::vector<uint32>& sync_points) { 302 DCHECK_CURRENTLY_ON(BrowserThread::IO); 303 304 VideoCaptureControllerID controller_id(device_id); 305 EntryMap::iterator it = entries_.find(controller_id); 306 if (it != entries_.end()) { 307 const base::WeakPtr<VideoCaptureController>& controller = it->second; 308 if (controller) 309 controller->ReturnBuffer(controller_id, this, buffer_id, sync_points); 310 } 311} 312 313void VideoCaptureHost::OnGetDeviceSupportedFormats( 314 int device_id, 315 media::VideoCaptureSessionId capture_session_id) { 316 DCHECK_CURRENTLY_ON(BrowserThread::IO); 317 DVLOG(1) << "VideoCaptureHost::OnGetDeviceFormats, capture_session_id " 318 << capture_session_id; 319 media::VideoCaptureFormats device_supported_formats; 320 if (!media_stream_manager_->video_capture_manager() 321 ->GetDeviceSupportedFormats(capture_session_id, 322 &device_supported_formats)) { 323 DLOG(WARNING) 324 << "Could not retrieve device supported formats for device_id=" 325 << device_id << " capture_session_id=" << capture_session_id; 326 } 327 Send(new VideoCaptureMsg_DeviceSupportedFormatsEnumerated( 328 device_id, device_supported_formats)); 329} 330 331void VideoCaptureHost::OnGetDeviceFormatsInUse( 332 int device_id, 333 media::VideoCaptureSessionId capture_session_id) { 334 DCHECK_CURRENTLY_ON(BrowserThread::IO); 335 DVLOG(1) << "VideoCaptureHost::OnGetDeviceFormatsInUse, capture_session_id " 336 << capture_session_id; 337 media::VideoCaptureFormats formats_in_use; 338 if (!media_stream_manager_->video_capture_manager()->GetDeviceFormatsInUse( 339 capture_session_id, &formats_in_use)) { 340 DVLOG(1) << "Could not retrieve device format(s) in use for device_id=" 341 << device_id << " capture_session_id=" << capture_session_id; 342 } 343 Send(new VideoCaptureMsg_DeviceFormatsInUseReceived(device_id, 344 formats_in_use)); 345} 346 347void VideoCaptureHost::DeleteVideoCaptureControllerOnIOThread( 348 const VideoCaptureControllerID& controller_id, bool on_error) { 349 DCHECK_CURRENTLY_ON(BrowserThread::IO); 350 351 EntryMap::iterator it = entries_.find(controller_id); 352 if (it == entries_.end()) 353 return; 354 355 if (it->second) { 356 media_stream_manager_->video_capture_manager()->StopCaptureForClient( 357 it->second.get(), controller_id, this, on_error); 358 } 359 entries_.erase(it); 360} 361 362} // namespace content 363