| 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 "media/device_monitors/device_monitor_mac.h" | 5 #include "media/device_monitors/device_monitor_mac.h" |
| 6 | 6 |
| 7 #include <AVFoundation/AVFoundation.h> |
| 7 #include <set> | 8 #include <set> |
| 8 | 9 |
| 9 #include "base/bind_helpers.h" | 10 #include "base/bind_helpers.h" |
| 10 #include "base/logging.h" | 11 #include "base/logging.h" |
| 11 #include "base/mac/bind_objc_block.h" | 12 #include "base/mac/bind_objc_block.h" |
| 12 #include "base/mac/scoped_nsobject.h" | 13 #include "base/mac/scoped_nsobject.h" |
| 13 #include "base/macros.h" | 14 #include "base/macros.h" |
| 14 #include "base/profiler/scoped_tracker.h" | 15 #include "base/profiler/scoped_tracker.h" |
| 15 #include "base/task_runner_util.h" | 16 #include "base/task_runner_util.h" |
| 16 #include "base/threading/thread_checker.h" | 17 #include "base/threading/thread_checker.h" |
| 17 #import "media/base/mac/avfoundation_glue.h" | |
| 18 | 18 |
| 19 namespace { | 19 namespace { |
| 20 | 20 |
| 21 // This class is used to keep track of system devices names and their types. | 21 // This class is used to keep track of system devices names and their types. |
| 22 class DeviceInfo { | 22 class DeviceInfo { |
| 23 public: | 23 public: |
| 24 enum DeviceType { kAudio, kVideo, kMuxed, kUnknown, kInvalid }; | 24 enum DeviceType { kAudio, kVideo, kMuxed, kUnknown, kInvalid }; |
| 25 | 25 |
| 26 DeviceInfo(const std::string& unique_id, DeviceType type) | 26 DeviceInfo(const std::string& unique_id, DeviceType type) |
| 27 : unique_id_(unique_id), type_(type) {} | 27 : unique_id_(unique_id), type_(type) {} |
| (...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 131 | 131 |
| 132 // This class is a Key-Value Observer (KVO) shim. It is needed because C++ | 132 // This class is a Key-Value Observer (KVO) shim. It is needed because C++ |
| 133 // classes cannot observe Key-Values directly. Created, manipulated, and | 133 // classes cannot observe Key-Values directly. Created, manipulated, and |
| 134 // destroyed on the UI Thread by SuspendObserverDelegate. | 134 // destroyed on the UI Thread by SuspendObserverDelegate. |
| 135 @interface CrAVFoundationDeviceObserver : NSObject { | 135 @interface CrAVFoundationDeviceObserver : NSObject { |
| 136 @private | 136 @private |
| 137 // Callback for device changed, has to run on Device Thread. | 137 // Callback for device changed, has to run on Device Thread. |
| 138 base::Closure onDeviceChangedCallback_; | 138 base::Closure onDeviceChangedCallback_; |
| 139 | 139 |
| 140 // Member to keep track of the devices we are already monitoring. | 140 // Member to keep track of the devices we are already monitoring. |
| 141 std::set<base::scoped_nsobject<CrAVCaptureDevice>> monitoredDevices_; | 141 std::set<base::scoped_nsobject<AVCaptureDevice>> monitoredDevices_; |
| 142 | 142 |
| 143 // Pegged to the "main" thread -- usually content::BrowserThread::UI. | 143 // Pegged to the "main" thread -- usually content::BrowserThread::UI. |
| 144 base::ThreadChecker mainThreadChecker_; | 144 base::ThreadChecker mainThreadChecker_; |
| 145 } | 145 } |
| 146 | 146 |
| 147 - (id)initWithOnChangedCallback:(const base::Closure&)callback; | 147 - (id)initWithOnChangedCallback:(const base::Closure&)callback; |
| 148 - (void)startObserving:(base::scoped_nsobject<CrAVCaptureDevice>)device; | 148 - (void)startObserving:(base::scoped_nsobject<AVCaptureDevice>)device; |
| 149 - (void)stopObserving:(CrAVCaptureDevice*)device; | 149 - (void)stopObserving:(AVCaptureDevice*)device; |
| 150 - (void)clearOnDeviceChangedCallback; | 150 - (void)clearOnDeviceChangedCallback; |
| 151 | 151 |
| 152 @end | 152 @end |
| 153 | 153 |
| 154 namespace { | 154 namespace { |
| 155 | 155 |
| 156 // This class owns and manages the lifetime of a CrAVFoundationDeviceObserver. | 156 // This class owns and manages the lifetime of a CrAVFoundationDeviceObserver. |
| 157 // It is created and destroyed on AVFoundationMonitorImpl's main thread (usually | 157 // It is created and destroyed on AVFoundationMonitorImpl's main thread (usually |
| 158 // browser's UI thread), and it operates on this thread except for the expensive | 158 // browser's UI thread), and it operates on this thread except for the expensive |
| 159 // device enumerations which are run on Device Thread. | 159 // device enumerations which are run on Device Thread. |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 209 base::Closure on_device_changed_callback = base::Bind( | 209 base::Closure on_device_changed_callback = base::Bind( |
| 210 &SuspendObserverDelegate::OnDeviceChanged, this, device_thread); | 210 &SuspendObserverDelegate::OnDeviceChanged, this, device_thread); |
| 211 suspend_observer_.reset([[CrAVFoundationDeviceObserver alloc] | 211 suspend_observer_.reset([[CrAVFoundationDeviceObserver alloc] |
| 212 initWithOnChangedCallback:on_device_changed_callback]); | 212 initWithOnChangedCallback:on_device_changed_callback]); |
| 213 | 213 |
| 214 // Enumerate the devices in Device thread and post the observers start to be | 214 // Enumerate the devices in Device thread and post the observers start to be |
| 215 // done on UI thread. The devices array is retained in |device_thread| and | 215 // done on UI thread. The devices array is retained in |device_thread| and |
| 216 // released in DoStartObserver(). | 216 // released in DoStartObserver(). |
| 217 base::PostTaskAndReplyWithResult( | 217 base::PostTaskAndReplyWithResult( |
| 218 device_thread.get(), FROM_HERE, base::BindBlock(^{ | 218 device_thread.get(), FROM_HERE, base::BindBlock(^{ |
| 219 return [[AVCaptureDeviceGlue devices] retain]; | 219 return [[AVCaptureDevice devices] retain]; |
| 220 }), | 220 }), |
| 221 base::Bind(&SuspendObserverDelegate::DoStartObserver, this)); | 221 base::Bind(&SuspendObserverDelegate::DoStartObserver, this)); |
| 222 } | 222 } |
| 223 | 223 |
| 224 void SuspendObserverDelegate::OnDeviceChanged( | 224 void SuspendObserverDelegate::OnDeviceChanged( |
| 225 const scoped_refptr<base::SingleThreadTaskRunner>& device_thread) { | 225 const scoped_refptr<base::SingleThreadTaskRunner>& device_thread) { |
| 226 DCHECK(main_thread_checker_.CalledOnValidThread()); | 226 DCHECK(main_thread_checker_.CalledOnValidThread()); |
| 227 // Enumerate the devices in Device thread and post the consolidation of the | 227 // Enumerate the devices in Device thread and post the consolidation of the |
| 228 // new devices and the old ones to be done on main thread. The devices array | 228 // new devices and the old ones to be done on main thread. The devices array |
| 229 // is retained in |device_thread| and released in DoOnDeviceChanged(). | 229 // is retained in |device_thread| and released in DoOnDeviceChanged(). |
| 230 PostTaskAndReplyWithResult( | 230 PostTaskAndReplyWithResult( |
| 231 device_thread.get(), FROM_HERE, base::BindBlock(^{ | 231 device_thread.get(), FROM_HERE, base::BindBlock(^{ |
| 232 return [[AVCaptureDeviceGlue devices] retain]; | 232 return [[AVCaptureDevice devices] retain]; |
| 233 }), | 233 }), |
| 234 base::Bind(&SuspendObserverDelegate::DoOnDeviceChanged, this)); | 234 base::Bind(&SuspendObserverDelegate::DoOnDeviceChanged, this)); |
| 235 } | 235 } |
| 236 | 236 |
| 237 void SuspendObserverDelegate::ResetDeviceMonitor() { | 237 void SuspendObserverDelegate::ResetDeviceMonitor() { |
| 238 DCHECK(main_thread_checker_.CalledOnValidThread()); | 238 DCHECK(main_thread_checker_.CalledOnValidThread()); |
| 239 avfoundation_monitor_impl_ = NULL; | 239 avfoundation_monitor_impl_ = NULL; |
| 240 [suspend_observer_ clearOnDeviceChangedCallback]; | 240 [suspend_observer_ clearOnDeviceChangedCallback]; |
| 241 } | 241 } |
| 242 | 242 |
| 243 SuspendObserverDelegate::~SuspendObserverDelegate() { | 243 SuspendObserverDelegate::~SuspendObserverDelegate() { |
| 244 DCHECK(main_thread_checker_.CalledOnValidThread()); | 244 DCHECK(main_thread_checker_.CalledOnValidThread()); |
| 245 } | 245 } |
| 246 | 246 |
| 247 void SuspendObserverDelegate::DoStartObserver(NSArray* devices) { | 247 void SuspendObserverDelegate::DoStartObserver(NSArray* devices) { |
| 248 DCHECK(main_thread_checker_.CalledOnValidThread()); | 248 DCHECK(main_thread_checker_.CalledOnValidThread()); |
| 249 base::scoped_nsobject<NSArray> auto_release(devices); | 249 base::scoped_nsobject<NSArray> auto_release(devices); |
| 250 for (CrAVCaptureDevice* device in devices) { | 250 for (AVCaptureDevice* device in devices) { |
| 251 base::scoped_nsobject<CrAVCaptureDevice> device_ptr([device retain]); | 251 base::scoped_nsobject<AVCaptureDevice> device_ptr([device retain]); |
| 252 [suspend_observer_ startObserving:device_ptr]; | 252 [suspend_observer_ startObserving:device_ptr]; |
| 253 } | 253 } |
| 254 } | 254 } |
| 255 | 255 |
| 256 void SuspendObserverDelegate::DoOnDeviceChanged(NSArray* devices) { | 256 void SuspendObserverDelegate::DoOnDeviceChanged(NSArray* devices) { |
| 257 DCHECK(main_thread_checker_.CalledOnValidThread()); | 257 DCHECK(main_thread_checker_.CalledOnValidThread()); |
| 258 base::scoped_nsobject<NSArray> auto_release(devices); | 258 base::scoped_nsobject<NSArray> auto_release(devices); |
| 259 std::vector<DeviceInfo> snapshot_devices; | 259 std::vector<DeviceInfo> snapshot_devices; |
| 260 for (CrAVCaptureDevice* device in devices) { | 260 for (AVCaptureDevice* device in devices) { |
| 261 base::scoped_nsobject<CrAVCaptureDevice> device_ptr([device retain]); | 261 base::scoped_nsobject<AVCaptureDevice> device_ptr([device retain]); |
| 262 [suspend_observer_ startObserving:device_ptr]; | 262 [suspend_observer_ startObserving:device_ptr]; |
| 263 | 263 |
| 264 BOOL suspended = [device respondsToSelector:@selector(isSuspended)] && | 264 BOOL suspended = [device respondsToSelector:@selector(isSuspended)] && |
| 265 [device isSuspended]; | 265 [device isSuspended]; |
| 266 DeviceInfo::DeviceType device_type = DeviceInfo::kUnknown; | 266 DeviceInfo::DeviceType device_type = DeviceInfo::kUnknown; |
| 267 if ([device hasMediaType:AVFoundationGlue::AVMediaTypeVideo()]) { | 267 if ([device hasMediaType:AVMediaTypeVideo]) { |
| 268 if (suspended) | 268 if (suspended) |
| 269 continue; | 269 continue; |
| 270 device_type = DeviceInfo::kVideo; | 270 device_type = DeviceInfo::kVideo; |
| 271 } else if ([device hasMediaType:AVFoundationGlue::AVMediaTypeMuxed()]) { | 271 } else if ([device hasMediaType:AVMediaTypeMuxed]) { |
| 272 device_type = suspended ? DeviceInfo::kAudio : DeviceInfo::kMuxed; | 272 device_type = suspended ? DeviceInfo::kAudio : DeviceInfo::kMuxed; |
| 273 } else if ([device hasMediaType:AVFoundationGlue::AVMediaTypeAudio()]) { | 273 } else if ([device hasMediaType:AVMediaTypeAudio]) { |
| 274 device_type = DeviceInfo::kAudio; | 274 device_type = DeviceInfo::kAudio; |
| 275 } | 275 } |
| 276 snapshot_devices.push_back( | 276 snapshot_devices.push_back( |
| 277 DeviceInfo([[device uniqueID] UTF8String], device_type)); | 277 DeviceInfo([[device uniqueID] UTF8String], device_type)); |
| 278 } | 278 } |
| 279 // Make sure no references are held to |devices| when | 279 // Make sure no references are held to |devices| when |
| 280 // ConsolidateDevicesListAndNotify is called since the VideoCaptureManager | 280 // ConsolidateDevicesListAndNotify is called since the VideoCaptureManager |
| 281 // and AudioCaptureManagers also enumerates the available devices but on | 281 // and AudioCaptureManagers also enumerates the available devices but on |
| 282 // another thread. | 282 // another thread. |
| 283 auto_release.reset(); | 283 auto_release.reset(); |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 318 | 318 |
| 319 AVFoundationMonitorImpl::AVFoundationMonitorImpl( | 319 AVFoundationMonitorImpl::AVFoundationMonitorImpl( |
| 320 media::DeviceMonitorMac* monitor, | 320 media::DeviceMonitorMac* monitor, |
| 321 const scoped_refptr<base::SingleThreadTaskRunner>& device_task_runner) | 321 const scoped_refptr<base::SingleThreadTaskRunner>& device_task_runner) |
| 322 : DeviceMonitorMacImpl(monitor), | 322 : DeviceMonitorMacImpl(monitor), |
| 323 device_task_runner_(device_task_runner), | 323 device_task_runner_(device_task_runner), |
| 324 suspend_observer_delegate_(new SuspendObserverDelegate(this)) { | 324 suspend_observer_delegate_(new SuspendObserverDelegate(this)) { |
| 325 DCHECK(main_thread_checker_.CalledOnValidThread()); | 325 DCHECK(main_thread_checker_.CalledOnValidThread()); |
| 326 NSNotificationCenter* nc = [NSNotificationCenter defaultCenter]; | 326 NSNotificationCenter* nc = [NSNotificationCenter defaultCenter]; |
| 327 device_arrival_ = | 327 device_arrival_ = |
| 328 [nc addObserverForName:AVFoundationGlue:: | 328 [nc addObserverForName:AVCaptureDeviceWasConnectedNotification |
| 329 AVCaptureDeviceWasConnectedNotification() | |
| 330 object:nil | 329 object:nil |
| 331 queue:nil | 330 queue:nil |
| 332 usingBlock:^(NSNotification* notification) { | 331 usingBlock:^(NSNotification* notification) { |
| 333 OnDeviceChanged(); | 332 OnDeviceChanged(); |
| 334 }]; | 333 }]; |
| 335 device_removal_ = | 334 device_removal_ = |
| 336 [nc addObserverForName:AVFoundationGlue:: | 335 [nc addObserverForName:AVCaptureDeviceWasDisconnectedNotification |
| 337 AVCaptureDeviceWasDisconnectedNotification() | |
| 338 object:nil | 336 object:nil |
| 339 queue:nil | 337 queue:nil |
| 340 usingBlock:^(NSNotification* notification) { | 338 usingBlock:^(NSNotification* notification) { |
| 341 OnDeviceChanged(); | 339 OnDeviceChanged(); |
| 342 }]; | 340 }]; |
| 343 suspend_observer_delegate_->StartObserver(device_task_runner_); | 341 suspend_observer_delegate_->StartObserver(device_task_runner_); |
| 344 } | 342 } |
| 345 | 343 |
| 346 AVFoundationMonitorImpl::~AVFoundationMonitorImpl() { | 344 AVFoundationMonitorImpl::~AVFoundationMonitorImpl() { |
| 347 DCHECK(main_thread_checker_.CalledOnValidThread()); | 345 DCHECK(main_thread_checker_.CalledOnValidThread()); |
| (...skipping 16 matching lines...) Expand all Loading... |
| 364 DCHECK(mainThreadChecker_.CalledOnValidThread()); | 362 DCHECK(mainThreadChecker_.CalledOnValidThread()); |
| 365 if ((self = [super init])) { | 363 if ((self = [super init])) { |
| 366 DCHECK(!callback.is_null()); | 364 DCHECK(!callback.is_null()); |
| 367 onDeviceChangedCallback_ = callback; | 365 onDeviceChangedCallback_ = callback; |
| 368 } | 366 } |
| 369 return self; | 367 return self; |
| 370 } | 368 } |
| 371 | 369 |
| 372 - (void)dealloc { | 370 - (void)dealloc { |
| 373 DCHECK(mainThreadChecker_.CalledOnValidThread()); | 371 DCHECK(mainThreadChecker_.CalledOnValidThread()); |
| 374 std::set<base::scoped_nsobject<CrAVCaptureDevice>>::iterator it = | 372 std::set<base::scoped_nsobject<AVCaptureDevice>>::iterator it = |
| 375 monitoredDevices_.begin(); | 373 monitoredDevices_.begin(); |
| 376 while (it != monitoredDevices_.end()) | 374 while (it != monitoredDevices_.end()) |
| 377 [self removeObservers:*(it++)]; | 375 [self removeObservers:*(it++)]; |
| 378 [super dealloc]; | 376 [super dealloc]; |
| 379 } | 377 } |
| 380 | 378 |
| 381 - (void)startObserving:(base::scoped_nsobject<CrAVCaptureDevice>)device { | 379 - (void)startObserving:(base::scoped_nsobject<AVCaptureDevice>)device { |
| 382 DCHECK(mainThreadChecker_.CalledOnValidThread()); | 380 DCHECK(mainThreadChecker_.CalledOnValidThread()); |
| 383 DCHECK(device != nil); | 381 DCHECK(device != nil); |
| 384 // Skip this device if there are already observers connected to it. | 382 // Skip this device if there are already observers connected to it. |
| 385 if (std::find(monitoredDevices_.begin(), monitoredDevices_.end(), device) != | 383 if (std::find(monitoredDevices_.begin(), monitoredDevices_.end(), device) != |
| 386 monitoredDevices_.end()) { | 384 monitoredDevices_.end()) { |
| 387 return; | 385 return; |
| 388 } | 386 } |
| 389 [device addObserver:self | 387 [device addObserver:self |
| 390 forKeyPath:@"suspended" | 388 forKeyPath:@"suspended" |
| 391 options:0 | 389 options:0 |
| 392 context:device.get()]; | 390 context:device.get()]; |
| 393 [device addObserver:self | 391 [device addObserver:self |
| 394 forKeyPath:@"connected" | 392 forKeyPath:@"connected" |
| 395 options:0 | 393 options:0 |
| 396 context:device.get()]; | 394 context:device.get()]; |
| 397 monitoredDevices_.insert(device); | 395 monitoredDevices_.insert(device); |
| 398 } | 396 } |
| 399 | 397 |
| 400 - (void)stopObserving:(CrAVCaptureDevice*)device { | 398 - (void)stopObserving:(AVCaptureDevice*)device { |
| 401 DCHECK(mainThreadChecker_.CalledOnValidThread()); | 399 DCHECK(mainThreadChecker_.CalledOnValidThread()); |
| 402 DCHECK(device != nil); | 400 DCHECK(device != nil); |
| 403 | 401 |
| 404 std::set<base::scoped_nsobject<CrAVCaptureDevice>>::iterator found = | 402 std::set<base::scoped_nsobject<AVCaptureDevice>>::iterator found = |
| 405 std::find(monitoredDevices_.begin(), monitoredDevices_.end(), device); | 403 std::find(monitoredDevices_.begin(), monitoredDevices_.end(), device); |
| 406 DCHECK(found != monitoredDevices_.end()); | 404 DCHECK(found != monitoredDevices_.end()); |
| 407 [self removeObservers:*found]; | 405 [self removeObservers:*found]; |
| 408 monitoredDevices_.erase(found); | 406 monitoredDevices_.erase(found); |
| 409 } | 407 } |
| 410 | 408 |
| 411 - (void)clearOnDeviceChangedCallback { | 409 - (void)clearOnDeviceChangedCallback { |
| 412 DCHECK(mainThreadChecker_.CalledOnValidThread()); | 410 DCHECK(mainThreadChecker_.CalledOnValidThread()); |
| 413 onDeviceChangedCallback_.Reset(); | 411 onDeviceChangedCallback_.Reset(); |
| 414 } | 412 } |
| 415 | 413 |
| 416 - (void)removeObservers:(CrAVCaptureDevice*)device { | 414 - (void)removeObservers:(AVCaptureDevice*)device { |
| 417 DCHECK(mainThreadChecker_.CalledOnValidThread()); | 415 DCHECK(mainThreadChecker_.CalledOnValidThread()); |
| 418 // Check sanity of |device| via its -observationInfo. http://crbug.com/371271. | 416 // Check sanity of |device| via its -observationInfo. http://crbug.com/371271. |
| 419 if ([device observationInfo]) { | 417 if ([device observationInfo]) { |
| 420 [device removeObserver:self | 418 [device removeObserver:self |
| 421 forKeyPath:@"suspended"]; | 419 forKeyPath:@"suspended"]; |
| 422 [device removeObserver:self | 420 [device removeObserver:self |
| 423 forKeyPath:@"connected"]; | 421 forKeyPath:@"connected"]; |
| 424 } | 422 } |
| 425 } | 423 } |
| 426 | 424 |
| 427 - (void)observeValueForKeyPath:(NSString*)keyPath | 425 - (void)observeValueForKeyPath:(NSString*)keyPath |
| 428 ofObject:(id)object | 426 ofObject:(id)object |
| 429 change:(NSDictionary*)change | 427 change:(NSDictionary*)change |
| 430 context:(void*)context { | 428 context:(void*)context { |
| 431 DCHECK(mainThreadChecker_.CalledOnValidThread()); | 429 DCHECK(mainThreadChecker_.CalledOnValidThread()); |
| 432 if ([keyPath isEqual:@"suspended"]) | 430 if ([keyPath isEqual:@"suspended"]) |
| 433 onDeviceChangedCallback_.Run(); | 431 onDeviceChangedCallback_.Run(); |
| 434 if ([keyPath isEqual:@"connected"]) | 432 if ([keyPath isEqual:@"connected"]) |
| 435 [self stopObserving:static_cast<CrAVCaptureDevice*>(context)]; | 433 [self stopObserving:static_cast<AVCaptureDevice*>(context)]; |
| 436 } | 434 } |
| 437 | 435 |
| 438 @end // @implementation CrAVFoundationDeviceObserver | 436 @end // @implementation CrAVFoundationDeviceObserver |
| 439 | 437 |
| 440 namespace media { | 438 namespace media { |
| 441 | 439 |
| 442 DeviceMonitorMac::DeviceMonitorMac() { | 440 DeviceMonitorMac::DeviceMonitorMac() { |
| 443 // AVFoundation do not need to be fired up until the user | 441 // AVFoundation do not need to be fired up until the user |
| 444 // exercises a GetUserMedia. Bringing up either library and enumerating the | 442 // exercises a GetUserMedia. Bringing up either library and enumerating the |
| 445 // devices in the system is an operation taking in the range of hundred of ms, | 443 // devices in the system is an operation taking in the range of hundred of ms, |
| 446 // so it is triggered explicitly from MediaStreamManager::StartMonitoring(). | 444 // so it is triggered explicitly from MediaStreamManager::StartMonitoring(). |
| 447 } | 445 } |
| 448 | 446 |
| 449 DeviceMonitorMac::~DeviceMonitorMac() {} | 447 DeviceMonitorMac::~DeviceMonitorMac() {} |
| 450 | 448 |
| 451 void DeviceMonitorMac::StartMonitoring( | 449 void DeviceMonitorMac::StartMonitoring( |
| 452 const scoped_refptr<base::SingleThreadTaskRunner>& device_task_runner) { | 450 const scoped_refptr<base::SingleThreadTaskRunner>& device_task_runner) { |
| 453 DCHECK(thread_checker_.CalledOnValidThread()); | 451 DCHECK(thread_checker_.CalledOnValidThread()); |
| 454 | 452 |
| 455 // We're on the UI thread so let's try to initialize AVFoundation. | |
| 456 AVFoundationGlue::InitializeAVFoundation(); | |
| 457 | |
| 458 // TODO(erikchen): Remove ScopedTracker below once http://crbug.com/458404 | 453 // TODO(erikchen): Remove ScopedTracker below once http://crbug.com/458404 |
| 459 // is fixed. | 454 // is fixed. |
| 460 tracked_objects::ScopedTracker tracking_profile( | 455 tracked_objects::ScopedTracker tracking_profile( |
| 461 FROM_HERE_WITH_EXPLICIT_FUNCTION( | 456 FROM_HERE_WITH_EXPLICIT_FUNCTION( |
| 462 "458404 DeviceMonitorMac::StartMonitoring::AVFoundation")); | 457 "458404 DeviceMonitorMac::StartMonitoring::AVFoundation")); |
| 463 DVLOG(1) << "Monitoring via AVFoundation"; | 458 DVLOG(1) << "Monitoring via AVFoundation"; |
| 464 device_monitor_impl_.reset( | 459 device_monitor_impl_.reset( |
| 465 new AVFoundationMonitorImpl(this, device_task_runner)); | 460 new AVFoundationMonitorImpl(this, device_task_runner)); |
| 466 } | 461 } |
| 467 | 462 |
| 468 void DeviceMonitorMac::NotifyDeviceChanged( | 463 void DeviceMonitorMac::NotifyDeviceChanged( |
| 469 base::SystemMonitor::DeviceType type) { | 464 base::SystemMonitor::DeviceType type) { |
| 470 DCHECK(thread_checker_.CalledOnValidThread()); | 465 DCHECK(thread_checker_.CalledOnValidThread()); |
| 471 // TODO(xians): Remove the global variable for SystemMonitor. | 466 // TODO(xians): Remove the global variable for SystemMonitor. |
| 472 base::SystemMonitor::Get()->ProcessDevicesChanged(type); | 467 base::SystemMonitor::Get()->ProcessDevicesChanged(type); |
| 473 } | 468 } |
| 474 | 469 |
| 475 } // namespace media | 470 } // namespace media |
| OLD | NEW |