OLD | NEW |
---|---|
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "content/browser/renderer_host/media/video_capture_manager.h" | 5 #include "content/browser/renderer_host/media/video_capture_manager.h" |
6 | 6 |
7 #include <set> | 7 #include <set> |
8 | 8 |
9 #include "base/bind.h" | 9 #include "base/bind.h" |
10 #include "base/command_line.h" | 10 #include "base/command_line.h" |
(...skipping 19 matching lines...) Expand all Loading... | |
30 namespace content { | 30 namespace content { |
31 | 31 |
32 // Starting id for the first capture session. | 32 // Starting id for the first capture session. |
33 // VideoCaptureManager::kStartOpenSessionId is used as default id without | 33 // VideoCaptureManager::kStartOpenSessionId is used as default id without |
34 // explicitly calling open device. | 34 // explicitly calling open device. |
35 enum { kFirstSessionId = VideoCaptureManager::kStartOpenSessionId + 1 }; | 35 enum { kFirstSessionId = VideoCaptureManager::kStartOpenSessionId + 1 }; |
36 | 36 |
37 VideoCaptureManager::DeviceEntry::DeviceEntry( | 37 VideoCaptureManager::DeviceEntry::DeviceEntry( |
38 MediaStreamType stream_type, | 38 MediaStreamType stream_type, |
39 const std::string& id, | 39 const std::string& id, |
40 scoped_refptr<VideoCaptureController> controller) | 40 scoped_ptr<VideoCaptureController> controller) |
41 : stream_type(stream_type), | 41 : stream_type(stream_type), |
42 id(id), | 42 id(id), |
43 video_capture_controller(controller) {} | 43 video_capture_controller(controller.Pass()) {} |
44 | 44 |
45 VideoCaptureManager::DeviceEntry::~DeviceEntry() {} | 45 VideoCaptureManager::DeviceEntry::~DeviceEntry() {} |
46 | 46 |
47 VideoCaptureManager::VideoCaptureManager() | 47 VideoCaptureManager::VideoCaptureManager() |
48 : listener_(NULL), | 48 : listener_(NULL), |
49 new_capture_session_id_(kFirstSessionId), | 49 new_capture_session_id_(kFirstSessionId), |
50 use_fake_device_(false) { | 50 use_fake_device_(false) { |
51 } | 51 } |
52 | 52 |
53 VideoCaptureManager::~VideoCaptureManager() { | 53 VideoCaptureManager::~VideoCaptureManager() { |
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
132 sessions_.erase(session_it); | 132 sessions_.erase(session_it); |
133 } | 133 } |
134 | 134 |
135 void VideoCaptureManager::UseFakeDevice() { | 135 void VideoCaptureManager::UseFakeDevice() { |
136 use_fake_device_ = true; | 136 use_fake_device_ = true; |
137 } | 137 } |
138 | 138 |
139 void VideoCaptureManager::DoStartDeviceOnDeviceThread( | 139 void VideoCaptureManager::DoStartDeviceOnDeviceThread( |
140 DeviceEntry* entry, | 140 DeviceEntry* entry, |
141 const media::VideoCaptureCapability& capture_params, | 141 const media::VideoCaptureCapability& capture_params, |
142 media::VideoCaptureDevice::EventHandler* controller_as_handler) { | 142 scoped_ptr<media::VideoCaptureDevice::EventHandler> device_client) { |
Ami GONE FROM CHROMIUM
2013/09/13 21:17:59
IWBN if someday VCD::EH was named VCD::Client.
ncarter (slow)
2013/09/14 00:07:24
It's on my list, but I've been de-prioritizing it
| |
143 SCOPED_UMA_HISTOGRAM_TIMER("Media.VideoCaptureManager.StartDeviceTime"); | 143 SCOPED_UMA_HISTOGRAM_TIMER("Media.VideoCaptureManager.StartDeviceTime"); |
144 DCHECK(IsOnDeviceThread()); | 144 DCHECK(IsOnDeviceThread()); |
145 | 145 |
146 scoped_ptr<media::VideoCaptureDevice> video_capture_device; | 146 scoped_ptr<media::VideoCaptureDevice> video_capture_device; |
147 switch (entry->stream_type) { | 147 switch (entry->stream_type) { |
148 case MEDIA_DEVICE_VIDEO_CAPTURE: { | 148 case MEDIA_DEVICE_VIDEO_CAPTURE: { |
149 // We look up the device id from the renderer in our local enumeration | 149 // We look up the device id from the renderer in our local enumeration |
150 // since the renderer does not have all the information that might be | 150 // since the renderer does not have all the information that might be |
151 // held in the browser-side VideoCaptureDevice::Name structure. | 151 // held in the browser-side VideoCaptureDevice::Name structure. |
152 media::VideoCaptureDevice::Name* found = | 152 media::VideoCaptureDevice::Name* found = |
(...skipping 19 matching lines...) Expand all Loading... | |
172 #endif // defined(ENABLE_SCREEN_CAPTURE) | 172 #endif // defined(ENABLE_SCREEN_CAPTURE) |
173 break; | 173 break; |
174 } | 174 } |
175 default: { | 175 default: { |
176 NOTIMPLEMENTED(); | 176 NOTIMPLEMENTED(); |
177 break; | 177 break; |
178 } | 178 } |
179 } | 179 } |
180 | 180 |
181 if (!video_capture_device) { | 181 if (!video_capture_device) { |
182 controller_as_handler->OnError(); | 182 device_client->OnError(); |
183 return; | 183 return; |
184 } | 184 } |
185 | 185 |
186 // TODO(nick): Merge Allocate() and Start(). http://crbug.com/285562 | 186 video_capture_device->AllocateAndStart(capture_params, device_client.Pass()); |
187 video_capture_device->Allocate(capture_params, controller_as_handler); | |
188 video_capture_device->Start(); | |
189 entry->video_capture_device = video_capture_device.Pass(); | 187 entry->video_capture_device = video_capture_device.Pass(); |
190 } | 188 } |
191 | 189 |
192 void VideoCaptureManager::StartCaptureForClient( | 190 void VideoCaptureManager::StartCaptureForClient( |
193 const media::VideoCaptureParams& capture_params, | 191 const media::VideoCaptureParams& capture_params, |
194 base::ProcessHandle client_render_process, | 192 base::ProcessHandle client_render_process, |
195 VideoCaptureControllerID client_id, | 193 VideoCaptureControllerID client_id, |
196 VideoCaptureControllerEventHandler* client_handler, | 194 VideoCaptureControllerEventHandler* client_handler, |
197 base::Callback<void(VideoCaptureController*)> done_cb) { | 195 base::Callback<void(base::WeakPtr<VideoCaptureController>)> done_cb) { |
198 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 196 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
199 DVLOG(1) << "VideoCaptureManager::StartCaptureForClient, (" | 197 DVLOG(1) << "VideoCaptureManager::StartCaptureForClient, (" |
200 << capture_params.width | 198 << capture_params.width |
201 << ", " << capture_params.height | 199 << ", " << capture_params.height |
202 << ", " << capture_params.frame_rate | 200 << ", " << capture_params.frame_rate |
203 << ", #" << capture_params.session_id | 201 << ", #" << capture_params.session_id |
204 << ")"; | 202 << ")"; |
205 | 203 |
206 if (capture_params.session_id == kStartOpenSessionId) { | 204 if (capture_params.session_id == kStartOpenSessionId) { |
207 // Solution for not using MediaStreamManager. Enumerate the devices and | 205 // Solution for not using MediaStreamManager. Enumerate the devices and |
208 // open the first one, and then start it. | 206 // open the first one, and then start it. |
209 base::PostTaskAndReplyWithResult(device_loop_, FROM_HERE, | 207 base::PostTaskAndReplyWithResult(device_loop_, FROM_HERE, |
210 base::Bind(&VideoCaptureManager::GetAvailableDevicesOnDeviceThread, | 208 base::Bind(&VideoCaptureManager::GetAvailableDevicesOnDeviceThread, |
211 this, MEDIA_DEVICE_VIDEO_CAPTURE), | 209 this, MEDIA_DEVICE_VIDEO_CAPTURE), |
212 base::Bind(&VideoCaptureManager::OpenAndStartDefaultSession, this, | 210 base::Bind(&VideoCaptureManager::OpenAndStartDefaultSession, this, |
213 capture_params, client_render_process, client_id, | 211 capture_params, client_render_process, client_id, |
214 client_handler, done_cb)); | 212 client_handler, done_cb)); |
215 return; | 213 return; |
216 } else { | 214 } else { |
217 DoStartCaptureForClient(capture_params, client_render_process, client_id, | 215 DoStartCaptureForClient(capture_params, client_render_process, client_id, |
218 client_handler, done_cb); | 216 client_handler, done_cb); |
219 } | 217 } |
220 } | 218 } |
221 | 219 |
222 void VideoCaptureManager::DoStartCaptureForClient( | 220 void VideoCaptureManager::DoStartCaptureForClient( |
223 const media::VideoCaptureParams& capture_params, | 221 const media::VideoCaptureParams& capture_params, |
224 base::ProcessHandle client_render_process, | 222 base::ProcessHandle client_render_process, |
225 VideoCaptureControllerID client_id, | 223 VideoCaptureControllerID client_id, |
226 VideoCaptureControllerEventHandler* client_handler, | 224 VideoCaptureControllerEventHandler* client_handler, |
227 base::Callback<void(VideoCaptureController*)> done_cb) { | 225 base::Callback<void(base::WeakPtr<VideoCaptureController>)> done_cb) { |
228 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 226 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
229 | 227 |
230 DeviceEntry* entry = GetOrCreateDeviceEntry(capture_params.session_id); | 228 DeviceEntry* entry = GetOrCreateDeviceEntry(capture_params.session_id); |
231 if (!entry) { | 229 if (!entry) { |
232 done_cb.Run(NULL); | 230 done_cb.Run(base::WeakPtr<VideoCaptureController>()); |
233 return; | 231 return; |
234 } | 232 } |
235 | 233 |
236 DCHECK(entry->video_capture_controller); | 234 DCHECK(entry->video_capture_controller); |
237 | 235 |
238 // First client starts the device. | 236 // First client starts the device. |
239 if (entry->video_capture_controller->GetClientCount() == 0) { | 237 if (entry->video_capture_controller->GetClientCount() == 0) { |
240 DVLOG(1) << "VideoCaptureManager starting device (type = " | 238 DVLOG(1) << "VideoCaptureManager starting device (type = " |
241 << entry->stream_type << ", id = " << entry->id << ")"; | 239 << entry->stream_type << ", id = " << entry->id << ")"; |
242 | 240 |
243 media::VideoCaptureCapability params_as_capability; | 241 media::VideoCaptureCapability params_as_capability; |
244 params_as_capability.width = capture_params.width; | 242 params_as_capability.width = capture_params.width; |
245 params_as_capability.height = capture_params.height; | 243 params_as_capability.height = capture_params.height; |
246 params_as_capability.frame_rate = capture_params.frame_rate; | 244 params_as_capability.frame_rate = capture_params.frame_rate; |
247 params_as_capability.session_id = capture_params.session_id; | 245 params_as_capability.session_id = capture_params.session_id; |
248 params_as_capability.frame_size_type = capture_params.frame_size_type; | 246 params_as_capability.frame_size_type = capture_params.frame_size_type; |
249 | 247 |
250 device_loop_->PostTask(FROM_HERE, base::Bind( | 248 device_loop_->PostTask(FROM_HERE, base::Bind( |
251 &VideoCaptureManager::DoStartDeviceOnDeviceThread, this, | 249 &VideoCaptureManager::DoStartDeviceOnDeviceThread, this, |
252 entry, params_as_capability, entry->video_capture_controller)); | 250 entry, params_as_capability, |
251 base::Passed(entry->video_capture_controller->NewDeviceClient()))); | |
253 } | 252 } |
254 // Run the callback first, as AddClient() may trigger OnFrameInfo(). | 253 // Run the callback first, as AddClient() may trigger OnFrameInfo(). |
255 done_cb.Run(entry->video_capture_controller); | 254 done_cb.Run(entry->video_capture_controller->AsWeakPtr()); |
256 entry->video_capture_controller->AddClient(client_id, | 255 entry->video_capture_controller->AddClient(client_id, |
257 client_handler, | 256 client_handler, |
258 client_render_process, | 257 client_render_process, |
259 capture_params); | 258 capture_params); |
260 } | 259 } |
261 | 260 |
262 void VideoCaptureManager::StopCaptureForClient( | 261 void VideoCaptureManager::StopCaptureForClient( |
263 VideoCaptureController* controller, | 262 VideoCaptureController* controller, |
264 VideoCaptureControllerID client_id, | 263 VideoCaptureControllerID client_id, |
265 VideoCaptureControllerEventHandler* client_handler) { | 264 VideoCaptureControllerEventHandler* client_handler) { |
(...skipping 21 matching lines...) Expand all Loading... | |
287 base::MessageLoop::current()->PostTask(FROM_HERE, | 286 base::MessageLoop::current()->PostTask(FROM_HERE, |
288 base::Bind(&VideoCaptureManager::OnClosed, this, | 287 base::Bind(&VideoCaptureManager::OnClosed, this, |
289 MEDIA_DEVICE_VIDEO_CAPTURE, kStartOpenSessionId)); | 288 MEDIA_DEVICE_VIDEO_CAPTURE, kStartOpenSessionId)); |
290 } | 289 } |
291 } | 290 } |
292 | 291 |
293 void VideoCaptureManager::DoStopDeviceOnDeviceThread(DeviceEntry* entry) { | 292 void VideoCaptureManager::DoStopDeviceOnDeviceThread(DeviceEntry* entry) { |
294 SCOPED_UMA_HISTOGRAM_TIMER("Media.VideoCaptureManager.StopDeviceTime"); | 293 SCOPED_UMA_HISTOGRAM_TIMER("Media.VideoCaptureManager.StopDeviceTime"); |
295 DCHECK(IsOnDeviceThread()); | 294 DCHECK(IsOnDeviceThread()); |
296 if (entry->video_capture_device) { | 295 if (entry->video_capture_device) { |
297 // TODO(nick): Merge Stop() and DeAllocate(). http://crbug.com/285562 | 296 entry->video_capture_device->StopAndDeAllocate(); |
298 entry->video_capture_device->Stop(); | |
299 entry->video_capture_device->DeAllocate(); | |
300 entry->video_capture_device.reset(); | |
301 } | 297 } |
302 } | 298 entry->video_capture_device.reset(); |
303 | |
304 void VideoCaptureManager::FreeDeviceEntryOnIOThread( | |
305 scoped_ptr<DeviceEntry> entry) { | |
306 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | |
307 entry->video_capture_controller = NULL; | |
308 entry.reset(); | |
309 } | 299 } |
310 | 300 |
311 void VideoCaptureManager::OnOpened(MediaStreamType stream_type, | 301 void VideoCaptureManager::OnOpened(MediaStreamType stream_type, |
312 int capture_session_id) { | 302 int capture_session_id) { |
313 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 303 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
314 if (!listener_) { | 304 if (!listener_) { |
315 // Listener has been removed. | 305 // Listener has been removed. |
316 return; | 306 return; |
317 } | 307 } |
318 listener_->Opened(stream_type, capture_session_id); | 308 listener_->Opened(stream_type, capture_session_id); |
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
416 } | 406 } |
417 } | 407 } |
418 return NULL; | 408 return NULL; |
419 } | 409 } |
420 | 410 |
421 void VideoCaptureManager::OpenAndStartDefaultSession( | 411 void VideoCaptureManager::OpenAndStartDefaultSession( |
422 const media::VideoCaptureParams& capture_params, | 412 const media::VideoCaptureParams& capture_params, |
423 base::ProcessHandle client_render_process, | 413 base::ProcessHandle client_render_process, |
424 VideoCaptureControllerID client_id, | 414 VideoCaptureControllerID client_id, |
425 VideoCaptureControllerEventHandler* client_handler, | 415 VideoCaptureControllerEventHandler* client_handler, |
426 base::Callback<void(VideoCaptureController*)> done_cb, | 416 base::Callback<void(base::WeakPtr<VideoCaptureController>)> done_cb, |
427 const media::VideoCaptureDevice::Names& device_names) { | 417 const media::VideoCaptureDevice::Names& device_names) { |
428 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 418 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
429 | 419 |
430 // |device_names| is a value returned by GetAvailableDevicesOnDeviceThread(). | 420 // |device_names| is a value returned by GetAvailableDevicesOnDeviceThread(). |
431 // We'll mimic an Open() operation on the first element in that list. | 421 // We'll mimic an Open() operation on the first element in that list. |
432 DCHECK(capture_params.session_id == kStartOpenSessionId); | 422 DCHECK(capture_params.session_id == kStartOpenSessionId); |
433 if (device_names.empty() || | 423 if (device_names.empty() || |
434 sessions_.count(capture_params.session_id) != 0) { | 424 sessions_.count(capture_params.session_id) != 0) { |
435 done_cb.Run(NULL); | 425 done_cb.Run(base::WeakPtr<VideoCaptureController>()); |
436 return; | 426 return; |
437 } | 427 } |
438 | 428 |
439 // Open the device by creating a |sessions_| entry. | 429 // Open the device by creating a |sessions_| entry. |
440 sessions_[capture_params.session_id] = | 430 sessions_[capture_params.session_id] = |
441 MediaStreamDevice(MEDIA_DEVICE_VIDEO_CAPTURE, | 431 MediaStreamDevice(MEDIA_DEVICE_VIDEO_CAPTURE, |
442 device_names.front().id(), | 432 device_names.front().id(), |
443 device_names.front().GetNameAndModel()); | 433 device_names.front().GetNameAndModel()); |
444 | 434 |
445 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, | 435 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, |
446 base::Bind(&VideoCaptureManager::OnOpened, this, | 436 base::Bind(&VideoCaptureManager::OnOpened, this, |
447 MEDIA_DEVICE_VIDEO_CAPTURE, kStartOpenSessionId)); | 437 MEDIA_DEVICE_VIDEO_CAPTURE, kStartOpenSessionId)); |
448 | 438 |
449 DoStartCaptureForClient(capture_params, client_render_process, client_id, | 439 DoStartCaptureForClient(capture_params, client_render_process, client_id, |
450 client_handler, done_cb); | 440 client_handler, done_cb); |
451 } | 441 } |
452 | 442 |
453 void VideoCaptureManager::DestroyDeviceEntryIfNoClients(DeviceEntry* entry) { | 443 void VideoCaptureManager::DestroyDeviceEntryIfNoClients(DeviceEntry* entry) { |
454 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 444 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
455 // Removal of the last client stops the device. | 445 // Removal of the last client stops the device. |
456 if (entry->video_capture_controller->GetClientCount() == 0) { | 446 if (entry->video_capture_controller->GetClientCount() == 0) { |
457 DVLOG(1) << "VideoCaptureManager stopping device (type = " | 447 DVLOG(1) << "VideoCaptureManager stopping device (type = " |
458 << entry->stream_type << ", id = " << entry->id << ")"; | 448 << entry->stream_type << ", id = " << entry->id << ")"; |
459 | 449 |
460 // The DeviceEntry is removed from |devices_| immediately, but will be torn | 450 // The DeviceEntry is removed from |devices_| immediately. The controller is |
461 // down asynchronously. After this point, subsequent request to open this | 451 // deleted immediately, and the device is freed asynchronously. After this |
462 // same device ID will create a new DeviceEntry, VideoCaptureController, | 452 // point, subsequent requests to open this same device ID will create a new |
463 // and VideoCaptureDevice. | 453 // DeviceEntry, VideoCaptureController, and VideoCaptureDevice. |
464 devices_.erase(entry); | 454 devices_.erase(entry); |
465 device_loop_->PostTaskAndReply( | 455 entry->video_capture_controller.reset(); |
456 device_loop_->PostTask( | |
466 FROM_HERE, | 457 FROM_HERE, |
467 base::Bind(&VideoCaptureManager::DoStopDeviceOnDeviceThread, this, | 458 base::Bind(&VideoCaptureManager::DoStopDeviceOnDeviceThread, this, |
468 base::Unretained(entry)), | 459 base::Owned(entry))); |
469 base::Bind(&VideoCaptureManager::FreeDeviceEntryOnIOThread, this, | |
470 base::Passed(make_scoped_ptr(entry).Pass()))); | |
471 } | 460 } |
472 } | 461 } |
473 | 462 |
474 VideoCaptureManager::DeviceEntry* VideoCaptureManager::GetOrCreateDeviceEntry( | 463 VideoCaptureManager::DeviceEntry* VideoCaptureManager::GetOrCreateDeviceEntry( |
475 int capture_session_id) { | 464 int capture_session_id) { |
476 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 465 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
477 | 466 |
478 std::map<int, MediaStreamDevice>::iterator session_it = | 467 std::map<int, MediaStreamDevice>::iterator session_it = |
479 sessions_.find(capture_session_id); | 468 sessions_.find(capture_session_id); |
480 if (session_it == sessions_.end()) { | 469 if (session_it == sessions_.end()) { |
481 return NULL; | 470 return NULL; |
482 } | 471 } |
483 const MediaStreamDevice& device_info = session_it->second; | 472 const MediaStreamDevice& device_info = session_it->second; |
484 | 473 |
485 // Check if another session has already opened this device. If so, just | 474 // Check if another session has already opened this device. If so, just |
486 // use that opened device. | 475 // use that opened device. |
487 DeviceEntry* const existing_device = | 476 DeviceEntry* const existing_device = |
488 GetDeviceEntryForMediaStreamDevice(device_info); | 477 GetDeviceEntryForMediaStreamDevice(device_info); |
489 if (existing_device) { | 478 if (existing_device) { |
490 DCHECK_EQ(device_info.type, existing_device->stream_type); | 479 DCHECK_EQ(device_info.type, existing_device->stream_type); |
491 return existing_device; | 480 return existing_device; |
492 } | 481 } |
493 | 482 |
494 scoped_refptr<VideoCaptureController> video_capture_controller = | 483 scoped_ptr<VideoCaptureController> video_capture_controller( |
495 new VideoCaptureController(); | 484 new VideoCaptureController()); |
496 DeviceEntry* new_device = new DeviceEntry(device_info.type, | 485 DeviceEntry* new_device = new DeviceEntry(device_info.type, |
497 device_info.id, | 486 device_info.id, |
498 video_capture_controller); | 487 video_capture_controller.Pass()); |
499 devices_.insert(new_device); | 488 devices_.insert(new_device); |
500 return new_device; | 489 return new_device; |
501 } | 490 } |
502 | 491 |
503 } // namespace content | 492 } // namespace content |
OLD | NEW |