Chromium Code Reviews| 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()); |
| 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()); |
|
mcasas
2017/03/03 00:21:13
Not your fault, but this function name is inaccura
chfremer
2017/03/03 18:21:13
An issue related to this already exists, see https
| |
| 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 |