video_capture_host.cc revision 58537e28ecd584eab876aee8be7156509866d23a
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 "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" 14 15namespace content { 16 17struct VideoCaptureHost::Entry { 18 Entry(VideoCaptureController* controller) 19 : controller(controller) {} 20 21 ~Entry() {} 22 23 scoped_refptr<VideoCaptureController> controller; 24}; 25 26VideoCaptureHost::VideoCaptureHost(MediaStreamManager* media_stream_manager) 27 : media_stream_manager_(media_stream_manager) { 28} 29 30VideoCaptureHost::~VideoCaptureHost() {} 31 32void VideoCaptureHost::OnChannelClosing() { 33 BrowserMessageFilter::OnChannelClosing(); 34 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(); 38 if (controller) { 39 VideoCaptureControllerID controller_id(it->first); 40 controller->StopCapture(controller_id, this); 41 media_stream_manager_->video_capture_manager()->RemoveController( 42 controller, this); 43 } 44 } 45 STLDeleteValues(&entries_); 46} 47 48void VideoCaptureHost::OnDestruct() const { 49 BrowserThread::DeleteOnIOThread::Destruct(this); 50} 51 52/////////////////////////////////////////////////////////////////////////////// 53 54// Implements VideoCaptureControllerEventHandler. 55void 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)); 61} 62 63void VideoCaptureHost::OnBufferCreated( 64 const VideoCaptureControllerID& controller_id, 65 base::SharedMemoryHandle handle, 66 int length, 67 int buffer_id) { 68 BrowserThread::PostTask( 69 BrowserThread::IO, FROM_HERE, 70 base::Bind(&VideoCaptureHost::DoSendNewBufferOnIOThread, 71 this, controller_id, handle, length, buffer_id)); 72} 73 74void VideoCaptureHost::OnBufferReady( 75 const VideoCaptureControllerID& controller_id, 76 int buffer_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)); 82} 83 84void VideoCaptureHost::OnFrameInfo( 85 const VideoCaptureControllerID& controller_id, 86 const media::VideoCaptureCapability& format) { 87 BrowserThread::PostTask( 88 BrowserThread::IO, 89 FROM_HERE, 90 base::Bind(&VideoCaptureHost::DoSendFrameInfoOnIOThread, 91 this, controller_id, format)); 92} 93 94void VideoCaptureHost::OnFrameInfoChanged( 95 const VideoCaptureControllerID& controller_id, 96 int width, 97 int height, 98 int frame_rate) { 99 BrowserThread::PostTask( 100 BrowserThread::IO, FROM_HERE, 101 base::Bind(&VideoCaptureHost::DoSendFrameInfoChangedOnIOThread, 102 this, controller_id, width, height, frame_rate)); 103} 104 105void VideoCaptureHost::OnEnded(const VideoCaptureControllerID& controller_id) { 106 DVLOG(1) << "VideoCaptureHost::OnEnded"; 107 BrowserThread::PostTask( 108 BrowserThread::IO, FROM_HERE, 109 base::Bind(&VideoCaptureHost::DoEndedOnIOThread, this, controller_id)); 110} 111 112void VideoCaptureHost::DoSendNewBufferOnIOThread( 113 const VideoCaptureControllerID& controller_id, 114 base::SharedMemoryHandle handle, 115 int length, 116 int buffer_id) { 117 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 118 119 if (entries_.find(controller_id) == entries_.end()) 120 return; 121 122 Send(new VideoCaptureMsg_NewBuffer(controller_id.device_id, handle, 123 length, buffer_id)); 124} 125 126void VideoCaptureHost::DoSendFilledBufferOnIOThread( 127 const VideoCaptureControllerID& controller_id, 128 int buffer_id, base::Time timestamp) { 129 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 130 131 if (entries_.find(controller_id) == entries_.end()) 132 return; 133 134 Send(new VideoCaptureMsg_BufferReady(controller_id.device_id, buffer_id, 135 timestamp)); 136} 137 138void VideoCaptureHost::DoHandleErrorOnIOThread( 139 const VideoCaptureControllerID& controller_id) { 140 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 141 142 if (entries_.find(controller_id) == entries_.end()) 143 return; 144 145 Send(new VideoCaptureMsg_StateChanged(controller_id.device_id, 146 VIDEO_CAPTURE_STATE_ERROR)); 147 DeleteVideoCaptureControllerOnIOThread(controller_id); 148} 149 150void VideoCaptureHost::DoEndedOnIOThread( 151 const VideoCaptureControllerID& controller_id) { 152 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 153 DVLOG(1) << "VideoCaptureHost::DoEndedOnIOThread"; 154 if (entries_.find(controller_id) == entries_.end()) 155 return; 156 157 Send(new VideoCaptureMsg_StateChanged(controller_id.device_id, 158 VIDEO_CAPTURE_STATE_ENDED)); 159 DeleteVideoCaptureControllerOnIOThread(controller_id); 160} 161 162void VideoCaptureHost::DoSendFrameInfoOnIOThread( 163 const VideoCaptureControllerID& controller_id, 164 const media::VideoCaptureCapability& format) { 165 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 166 167 if (entries_.find(controller_id) == entries_.end()) 168 return; 169 170 media::VideoCaptureParams params; 171 params.width = format.width; 172 params.height = format.height; 173 params.frame_rate = format.frame_rate; 174 params.frame_size_type = format.frame_size_type; 175 Send(new VideoCaptureMsg_DeviceInfo(controller_id.device_id, params)); 176 Send(new VideoCaptureMsg_StateChanged(controller_id.device_id, 177 VIDEO_CAPTURE_STATE_STARTED)); 178} 179 180void VideoCaptureHost::DoSendFrameInfoChangedOnIOThread( 181 const VideoCaptureControllerID& controller_id, 182 int width, 183 int height, 184 int frame_rate) { 185 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 186 187 if (entries_.find(controller_id) == entries_.end()) 188 return; 189 190 media::VideoCaptureParams params; 191 params.width = width; 192 params.height = height; 193 params.frame_rate = frame_rate; 194 Send(new VideoCaptureMsg_DeviceInfoChanged(controller_id.device_id, params)); 195} 196 197/////////////////////////////////////////////////////////////////////////////// 198// IPC Messages handler. 199bool VideoCaptureHost::OnMessageReceived(const IPC::Message& message, 200 bool* message_was_ok) { 201 bool handled = true; 202 IPC_BEGIN_MESSAGE_MAP_EX(VideoCaptureHost, message, *message_was_ok) 203 IPC_MESSAGE_HANDLER(VideoCaptureHostMsg_Start, OnStartCapture) 204 IPC_MESSAGE_HANDLER(VideoCaptureHostMsg_Pause, OnPauseCapture) 205 IPC_MESSAGE_HANDLER(VideoCaptureHostMsg_Stop, OnStopCapture) 206 IPC_MESSAGE_HANDLER(VideoCaptureHostMsg_BufferReady, OnReceiveEmptyBuffer) 207 IPC_MESSAGE_UNHANDLED(handled = false) 208 IPC_END_MESSAGE_MAP_EX() 209 210 return handled; 211} 212 213void VideoCaptureHost::OnStartCapture(int device_id, 214 const media::VideoCaptureParams& params) { 215 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 216 DVLOG(1) << "VideoCaptureHost::OnStartCapture, device_id " << device_id 217 << ", (" << params.width << ", " << params.height << ", " 218 << params.frame_rate << ", " << params.session_id 219 << ", variable resolution device:" 220 << ((params.frame_size_type == 221 media::VariableResolutionVideoCaptureDevice) ? "yes" : "no") 222 << ")"; 223 VideoCaptureControllerID controller_id(device_id); 224 DCHECK(entries_.find(controller_id) == entries_.end()); 225 226 entries_[controller_id] = new Entry(NULL); 227 media_stream_manager_->video_capture_manager()->AddController( 228 params, this, base::Bind(&VideoCaptureHost::OnControllerAdded, this, 229 device_id, params)); 230} 231 232void VideoCaptureHost::OnControllerAdded( 233 int device_id, const media::VideoCaptureParams& params, 234 VideoCaptureController* controller) { 235 BrowserThread::PostTask( 236 BrowserThread::IO, FROM_HERE, 237 base::Bind(&VideoCaptureHost::DoControllerAddedOnIOThread, 238 this, device_id, params, make_scoped_refptr(controller))); 239} 240 241void VideoCaptureHost::DoControllerAddedOnIOThread( 242 int device_id, const media::VideoCaptureParams params, 243 VideoCaptureController* controller) { 244 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 245 VideoCaptureControllerID controller_id(device_id); 246 EntryMap::iterator it = entries_.find(controller_id); 247 if (it == entries_.end()) { 248 if (controller) { 249 media_stream_manager_->video_capture_manager()->RemoveController( 250 controller, this); 251 } 252 return; 253 } 254 255 if (controller == NULL) { 256 Send(new VideoCaptureMsg_StateChanged(device_id, 257 VIDEO_CAPTURE_STATE_ERROR)); 258 delete it->second; 259 entries_.erase(controller_id); 260 return; 261 } 262 263 it->second->controller = controller; 264 controller->StartCapture(controller_id, this, PeerHandle(), params); 265} 266 267void VideoCaptureHost::OnStopCapture(int device_id) { 268 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 269 DVLOG(1) << "VideoCaptureHost::OnStopCapture, device_id " << device_id; 270 271 VideoCaptureControllerID controller_id(device_id); 272 273 Send(new VideoCaptureMsg_StateChanged(device_id, 274 VIDEO_CAPTURE_STATE_STOPPED)); 275 DeleteVideoCaptureControllerOnIOThread(controller_id); 276} 277 278void VideoCaptureHost::OnPauseCapture(int device_id) { 279 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 280 DVLOG(1) << "VideoCaptureHost::OnPauseCapture, device_id " << device_id; 281 // Not used. 282 Send(new VideoCaptureMsg_StateChanged(device_id, VIDEO_CAPTURE_STATE_ERROR)); 283} 284 285void VideoCaptureHost::OnReceiveEmptyBuffer(int device_id, int buffer_id) { 286 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 287 288 VideoCaptureControllerID controller_id(device_id); 289 EntryMap::iterator it = entries_.find(controller_id); 290 if (it != entries_.end()) { 291 scoped_refptr<VideoCaptureController> controller = it->second->controller; 292 if (controller.get()) 293 controller->ReturnBuffer(controller_id, this, buffer_id); 294 } 295} 296 297void VideoCaptureHost::DeleteVideoCaptureControllerOnIOThread( 298 const VideoCaptureControllerID& controller_id) { 299 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 300 301 EntryMap::iterator it = entries_.find(controller_id); 302 if (it == entries_.end()) 303 return; 304 305 VideoCaptureController* controller = it->second->controller.get(); 306 if (controller) { 307 controller->StopCapture(controller_id, this); 308 media_stream_manager_->video_capture_manager()->RemoveController( 309 controller, this); 310 } 311 delete it->second; 312 entries_.erase(controller_id); 313} 314 315} // namespace content 316