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 <algorithm> | 7 #include <algorithm> |
8 #include <set> | 8 #include <set> |
9 #include <utility> | 9 #include <utility> |
10 | 10 |
(...skipping 283 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
294 : serial_id_(serial_id), | 294 : serial_id_(serial_id), |
295 session_id_(session_id), | 295 session_id_(session_id), |
296 params_(params), | 296 params_(params), |
297 abort_start_(false) { | 297 abort_start_(false) { |
298 } | 298 } |
299 | 299 |
300 VideoCaptureManager::VideoCaptureManager( | 300 VideoCaptureManager::VideoCaptureManager( |
301 std::unique_ptr<media::VideoCaptureDeviceFactory> factory, | 301 std::unique_ptr<media::VideoCaptureDeviceFactory> factory, |
302 scoped_refptr<base::SingleThreadTaskRunner> device_task_runner) | 302 scoped_refptr<base::SingleThreadTaskRunner> device_task_runner) |
303 : device_task_runner_(std::move(device_task_runner)), | 303 : device_task_runner_(std::move(device_task_runner)), |
304 listener_(nullptr), | |
305 new_capture_session_id_(1), | 304 new_capture_session_id_(1), |
306 video_capture_device_factory_(std::move(factory)) {} | 305 video_capture_device_factory_(std::move(factory)) {} |
307 | 306 |
308 VideoCaptureManager::~VideoCaptureManager() { | 307 VideoCaptureManager::~VideoCaptureManager() { |
309 DCHECK(devices_.empty()); | 308 DCHECK(devices_.empty()); |
310 DCHECK(device_start_queue_.empty()); | 309 DCHECK(device_start_queue_.empty()); |
311 } | 310 } |
312 | 311 |
313 void VideoCaptureManager::AddVideoCaptureObserver( | 312 void VideoCaptureManager::AddVideoCaptureObserver( |
314 media::VideoCaptureObserver* observer) { | 313 media::VideoCaptureObserver* observer) { |
315 DCHECK(observer); | 314 DCHECK(observer); |
316 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 315 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
317 capture_observers_.AddObserver(observer); | 316 capture_observers_.AddObserver(observer); |
318 } | 317 } |
319 | 318 |
320 void VideoCaptureManager::RemoveAllVideoCaptureObservers() { | 319 void VideoCaptureManager::RemoveAllVideoCaptureObservers() { |
321 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 320 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
322 capture_observers_.Clear(); | 321 capture_observers_.Clear(); |
323 } | 322 } |
324 | 323 |
325 void VideoCaptureManager::RegisterListener( | 324 void VideoCaptureManager::RegisterListener( |
326 MediaStreamProviderListener* listener) { | 325 MediaStreamProviderListener* listener) { |
327 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 326 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
328 DCHECK(!listener_); | 327 DCHECK(listener); |
329 DCHECK(device_task_runner_); | 328 DCHECK(device_task_runner_); |
330 listener_ = listener; | 329 listeners_.AddObserver(listener); |
331 #if defined(OS_ANDROID) | 330 #if defined(OS_ANDROID) |
332 application_state_has_running_activities_ = true; | 331 application_state_has_running_activities_ = true; |
333 app_status_listener_.reset(new base::android::ApplicationStatusListener( | 332 app_status_listener_.reset(new base::android::ApplicationStatusListener( |
334 base::Bind(&VideoCaptureManager::OnApplicationStateChange, | 333 base::Bind(&VideoCaptureManager::OnApplicationStateChange, |
335 base::Unretained(this)))); | 334 base::Unretained(this)))); |
336 #endif | 335 #endif |
337 } | 336 } |
338 | 337 |
339 void VideoCaptureManager::UnregisterListener() { | 338 void VideoCaptureManager::UnregisterListener( |
339 MediaStreamProviderListener* listener) { | |
340 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 340 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
341 DCHECK(listener_); | 341 listeners_.RemoveObserver(listener); |
342 listener_ = nullptr; | |
343 } | 342 } |
344 | 343 |
345 void VideoCaptureManager::EnumerateDevices( | 344 void VideoCaptureManager::EnumerateDevices( |
346 const EnumerationCallback& client_callback) { | 345 const EnumerationCallback& client_callback) { |
347 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 346 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
348 DVLOG(1) << "VideoCaptureManager::EnumerateDevices"; | 347 DVLOG(1) << "VideoCaptureManager::EnumerateDevices"; |
349 | 348 |
350 // Bind a callback to ConsolidateDevicesInfoOnDeviceThread() with an argument | 349 // Bind a callback to ConsolidateDevicesInfoOnDeviceThread() with an argument |
351 // for another callback to OnDevicesInfoEnumerated() to be run in the current | 350 // for another callback to OnDevicesInfoEnumerated() to be run in the current |
352 // loop, i.e. IO loop. Pass a timer for UMA histogram collection. | 351 // loop, i.e. IO loop. Pass a timer for UMA histogram collection. |
353 base::Callback<void(std::unique_ptr<VideoCaptureDeviceDescriptors>)> | 352 base::Callback<void(std::unique_ptr<VideoCaptureDeviceDescriptors>)> |
354 devices_enumerated_callback = base::Bind( | 353 devices_enumerated_callback = base::Bind( |
355 &VideoCaptureManager::ConsolidateDevicesInfoOnDeviceThread, this, | 354 &VideoCaptureManager::ConsolidateDevicesInfoOnDeviceThread, this, |
356 media::BindToCurrentLoop(base::Bind( | 355 media::BindToCurrentLoop(base::Bind( |
357 &VideoCaptureManager::OnDevicesInfoEnumerated, this, | 356 &VideoCaptureManager::OnDevicesInfoEnumerated, this, |
358 base::Owned(new base::ElapsedTimer()), client_callback)), | 357 base::Owned(new base::ElapsedTimer()), client_callback)), |
359 devices_info_cache_); | 358 devices_info_cache_); |
360 // OK to use base::Unretained() since we own the VCDFactory and |this| is | 359 // OK to use base::Unretained() since we own the VCDFactory and |this| is |
361 // bound in |devices_enumerated_callback|. | 360 // bound in |devices_enumerated_callback|. |
362 device_task_runner_->PostTask( | 361 device_task_runner_->PostTask( |
363 FROM_HERE, | 362 FROM_HERE, |
364 base::Bind(&media::VideoCaptureDeviceFactory::EnumerateDeviceDescriptors, | 363 base::Bind(&media::VideoCaptureDeviceFactory::EnumerateDeviceDescriptors, |
365 base::Unretained(video_capture_device_factory_.get()), | 364 base::Unretained(video_capture_device_factory_.get()), |
366 devices_enumerated_callback)); | 365 devices_enumerated_callback)); |
367 } | 366 } |
368 | 367 |
369 int VideoCaptureManager::Open(const StreamDeviceInfo& device_info) { | 368 int VideoCaptureManager::Open(const MediaStreamDevice& device) { |
370 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 369 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
371 DCHECK(listener_); | 370 DCHECK(listeners_.might_have_observers()); |
miu
2017/03/06 21:54:10
ditto: too-pedantic DCHECK?
chfremer
2017/03/06 23:39:38
Done.
| |
372 | 371 |
373 // Generate a new id for the session being opened. | 372 // Generate a new id for the session being opened. |
374 const media::VideoCaptureSessionId capture_session_id = | 373 const media::VideoCaptureSessionId capture_session_id = |
375 new_capture_session_id_++; | 374 new_capture_session_id_++; |
376 | 375 |
377 DCHECK(sessions_.find(capture_session_id) == sessions_.end()); | 376 DCHECK(sessions_.find(capture_session_id) == sessions_.end()); |
378 DVLOG(1) << "VideoCaptureManager::Open, id " << capture_session_id; | 377 DVLOG(1) << "VideoCaptureManager::Open, id " << capture_session_id; |
379 | 378 |
380 // We just save the stream info for processing later. | 379 // We just save the stream info for processing later. |
381 sessions_[capture_session_id] = device_info.device; | 380 sessions_[capture_session_id] = device; |
382 | 381 |
383 // Notify our listener asynchronously; this ensures that we return | 382 // Notify our listener asynchronously; this ensures that we return |
384 // |capture_session_id| to the caller of this function before using that same | 383 // |capture_session_id| to the caller of this function before using that same |
385 // id in a listener event. | 384 // id in a listener event. |
386 base::ThreadTaskRunnerHandle::Get()->PostTask( | 385 base::ThreadTaskRunnerHandle::Get()->PostTask( |
387 FROM_HERE, base::Bind(&VideoCaptureManager::OnOpened, this, | 386 FROM_HERE, base::Bind(&VideoCaptureManager::OnOpened, this, device.type, |
388 device_info.device.type, capture_session_id)); | 387 capture_session_id)); |
389 return capture_session_id; | 388 return capture_session_id; |
390 } | 389 } |
391 | 390 |
392 void VideoCaptureManager::Close(int capture_session_id) { | 391 void VideoCaptureManager::Close(int capture_session_id) { |
393 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 392 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
394 DCHECK(listener_); | 393 DCHECK(listeners_.might_have_observers()); |
miu
2017/03/06 21:54:10
ditto: too-pedantic DCHECK?
chfremer
2017/03/06 23:39:38
Done.
| |
395 DVLOG(1) << "VideoCaptureManager::Close, id " << capture_session_id; | 394 DVLOG(1) << "VideoCaptureManager::Close, id " << capture_session_id; |
396 | 395 |
397 SessionMap::iterator session_it = sessions_.find(capture_session_id); | 396 SessionMap::iterator session_it = sessions_.find(capture_session_id); |
398 if (session_it == sessions_.end()) { | 397 if (session_it == sessions_.end()) { |
399 NOTREACHED(); | 398 NOTREACHED(); |
400 return; | 399 return; |
401 } | 400 } |
402 | 401 |
403 DeviceEntry* const existing_device = | 402 DeviceEntry* const existing_device = |
404 GetDeviceEntryByTypeAndId(session_it->second.type, session_it->second.id); | 403 GetDeviceEntryByTypeAndId(session_it->second.type, session_it->second.id); |
(...skipping 355 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
760 LogVideoCaptureEvent( | 759 LogVideoCaptureEvent( |
761 VIDEO_CAPTURE_STOP_CAPTURE_OK_NO_FRAMES_PRODUCED_BY_DEVICE); | 760 VIDEO_CAPTURE_STOP_CAPTURE_OK_NO_FRAMES_PRODUCED_BY_DEVICE); |
762 } else { | 761 } else { |
763 LogVideoCaptureEvent( | 762 LogVideoCaptureEvent( |
764 VIDEO_CAPTURE_STOP_CAPTURE_OK_NO_FRAMES_PRODUCED_BY_DESKTOP_OR_TAB); | 763 VIDEO_CAPTURE_STOP_CAPTURE_OK_NO_FRAMES_PRODUCED_BY_DESKTOP_OR_TAB); |
765 } | 764 } |
766 } else { | 765 } else { |
767 LogVideoCaptureEvent(VIDEO_CAPTURE_STOP_CAPTURE_DUE_TO_ERROR); | 766 LogVideoCaptureEvent(VIDEO_CAPTURE_STOP_CAPTURE_DUE_TO_ERROR); |
768 for (auto it : sessions_) { | 767 for (auto it : sessions_) { |
769 if (it.second.type == entry->stream_type && it.second.id == entry->id) { | 768 if (it.second.type == entry->stream_type && it.second.id == entry->id) { |
770 listener_->Aborted(it.second.type, it.first); | 769 for (auto& listener : listeners_) |
770 listener.Aborted(it.second.type, it.first); | |
771 // Aborted() call might synchronously destroy |entry|, recheck. | 771 // Aborted() call might synchronously destroy |entry|, recheck. |
772 entry = GetDeviceEntryByController(controller); | 772 entry = GetDeviceEntryByController(controller); |
773 if (!entry) | 773 if (!entry) |
774 return; | 774 return; |
775 break; | 775 break; |
776 } | 776 } |
777 } | 777 } |
778 } | 778 } |
779 | 779 |
780 // Detach client from controller. | 780 // Detach client from controller. |
(...skipping 253 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1034 SCOPED_UMA_HISTOGRAM_TIMER("Media.VideoCaptureManager.StopDeviceTime"); | 1034 SCOPED_UMA_HISTOGRAM_TIMER("Media.VideoCaptureManager.StopDeviceTime"); |
1035 DCHECK(IsOnDeviceThread()); | 1035 DCHECK(IsOnDeviceThread()); |
1036 device->StopAndDeAllocate(); | 1036 device->StopAndDeAllocate(); |
1037 DVLOG(3) << "DoStopDeviceOnDeviceThread"; | 1037 DVLOG(3) << "DoStopDeviceOnDeviceThread"; |
1038 } | 1038 } |
1039 | 1039 |
1040 void VideoCaptureManager::OnOpened( | 1040 void VideoCaptureManager::OnOpened( |
1041 MediaStreamType stream_type, | 1041 MediaStreamType stream_type, |
1042 media::VideoCaptureSessionId capture_session_id) { | 1042 media::VideoCaptureSessionId capture_session_id) { |
1043 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 1043 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
1044 if (!listener_) { | 1044 for (auto& listener : listeners_) |
1045 // Listener has been removed. | 1045 listener.Opened(stream_type, capture_session_id); |
1046 return; | |
1047 } | |
1048 listener_->Opened(stream_type, capture_session_id); | |
1049 } | 1046 } |
1050 | 1047 |
1051 void VideoCaptureManager::OnClosed( | 1048 void VideoCaptureManager::OnClosed( |
1052 MediaStreamType stream_type, | 1049 MediaStreamType stream_type, |
1053 media::VideoCaptureSessionId capture_session_id) { | 1050 media::VideoCaptureSessionId capture_session_id) { |
1054 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 1051 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
1055 if (!listener_) { | 1052 for (auto& listener : listeners_) |
1056 // Listener has been removed. | 1053 listener.Closed(stream_type, capture_session_id); |
1057 return; | |
1058 } | |
1059 listener_->Closed(stream_type, capture_session_id); | |
1060 } | 1054 } |
1061 | 1055 |
1062 void VideoCaptureManager::OnDevicesInfoEnumerated( | 1056 void VideoCaptureManager::OnDevicesInfoEnumerated( |
1063 base::ElapsedTimer* timer, | 1057 base::ElapsedTimer* timer, |
1064 const EnumerationCallback& client_callback, | 1058 const EnumerationCallback& client_callback, |
1065 const VideoCaptureManager::DeviceInfos& new_devices_info_cache) { | 1059 const VideoCaptureManager::DeviceInfos& new_devices_info_cache) { |
1066 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 1060 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
1067 UMA_HISTOGRAM_TIMES( | 1061 UMA_HISTOGRAM_TIMES( |
1068 "Media.VideoCaptureManager.GetAvailableDevicesInfoOnDeviceThreadTime", | 1062 "Media.VideoCaptureManager.GetAvailableDevicesInfoOnDeviceThreadTime", |
1069 timer->Elapsed()); | 1063 timer->Elapsed()); |
(...skipping 266 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1336 if (!device_in_queue) { | 1330 if (!device_in_queue) { |
1337 // Session ID is only valid for Screen capture. So we can fake it to | 1331 // Session ID is only valid for Screen capture. So we can fake it to |
1338 // resume video capture devices here. | 1332 // resume video capture devices here. |
1339 QueueStartDevice(kFakeSessionId, entry.get(), entry->parameters); | 1333 QueueStartDevice(kFakeSessionId, entry.get(), entry->parameters); |
1340 } | 1334 } |
1341 } | 1335 } |
1342 } | 1336 } |
1343 #endif // defined(OS_ANDROID) | 1337 #endif // defined(OS_ANDROID) |
1344 | 1338 |
1345 } // namespace content | 1339 } // namespace content |
OLD | NEW |