Chromium Code Reviews| Index: content/browser/device_monitor_mac.mm |
| diff --git a/content/browser/device_monitor_mac.mm b/content/browser/device_monitor_mac.mm |
| index 7b12e91cbdf4ed8b57fc020d3b75c0579240d0ef..dac06f1bb20de7901f17857d41b3af65138a0261 100644 |
| --- a/content/browser/device_monitor_mac.mm |
| +++ b/content/browser/device_monitor_mac.mm |
| @@ -7,39 +7,43 @@ |
| #import <QTKit/QTKit.h> |
| #include "base/logging.h" |
| +#include "base/synchronization/lock.h" |
| +#include "media/video/capture/mac/avfoundation_glue.h" |
| -namespace content { |
| +namespace { |
| -class DeviceMonitorMac::QTMonitorImpl { |
| +// Interface used by DeviceMonitorMac to interact with either a QTKit or an |
| +// AVFoundation implementation of events and notifications. |
| +class MacMonitorInterface { |
| public: |
| - explicit QTMonitorImpl(DeviceMonitorMac* monitor); |
| - virtual ~QTMonitorImpl() {} |
| + virtual ~MacMonitorInterface() {}; |
| - void Start(); |
| - void Stop(); |
| + virtual void OnDeviceChanged() = 0; |
| +}; |
| - private: |
| - void OnDeviceChanged(); |
| +class QTKitMonitorImpl : public MacMonitorInterface { |
| + public: |
| + QTKitMonitorImpl() {}; |
| + explicit QTKitMonitorImpl(content::DeviceMonitorMac* monitor); |
| + virtual ~QTKitMonitorImpl(); |
| - DeviceMonitorMac* monitor_; |
| + virtual void OnDeviceChanged() OVERRIDE; |
| + private: |
| + content::DeviceMonitorMac* monitor_; |
| int number_audio_devices_; |
| int number_video_devices_; |
| id device_arrival_; |
| id device_removal_; |
| - |
| - DISALLOW_COPY_AND_ASSIGN(QTMonitorImpl); |
| }; |
| -DeviceMonitorMac::QTMonitorImpl::QTMonitorImpl(DeviceMonitorMac* monitor) |
| +QTKitMonitorImpl::QTKitMonitorImpl(content::DeviceMonitorMac* monitor) |
| : monitor_(monitor), |
| number_audio_devices_(0), |
| number_video_devices_(0), |
| device_arrival_(nil), |
| device_removal_(nil) { |
| DCHECK(monitor); |
| -} |
| -void DeviceMonitorMac::QTMonitorImpl::Start() { |
| NSNotificationCenter* nc = [NSNotificationCenter defaultCenter]; |
| device_arrival_ = |
| [nc addObserverForName:QTCaptureDeviceWasConnectedNotification |
| @@ -56,7 +60,7 @@ void DeviceMonitorMac::QTMonitorImpl::Start() { |
| OnDeviceChanged();}]; |
| } |
| -void DeviceMonitorMac::QTMonitorImpl::Stop() { |
| +QTKitMonitorImpl::~QTKitMonitorImpl() { |
| if (!monitor_) |
| return; |
| @@ -65,7 +69,8 @@ void DeviceMonitorMac::QTMonitorImpl::Stop() { |
| [nc removeObserver:device_removal_]; |
| } |
| -void DeviceMonitorMac::QTMonitorImpl::OnDeviceChanged() { |
| +void QTKitMonitorImpl::OnDeviceChanged() { |
| + base::AutoLock lock(monitor_->lock_); |
|
Mark Mentovai
2013/10/02 14:24:34
How does this help?
The major problem here isn’t
mcasas
2013/10/02 16:16:00
I thought that when we register to the notificati
|
| NSArray* devices = [QTCaptureDevice inputDevices]; |
| int number_video_devices = 0; |
| int number_audio_devices = 0; |
| @@ -90,15 +95,115 @@ void DeviceMonitorMac::QTMonitorImpl::OnDeviceChanged() { |
| } |
| } |
| -DeviceMonitorMac::DeviceMonitorMac() { |
| - qt_monitor_.reset(new QTMonitorImpl(this)); |
| - qt_monitor_->Start(); |
| +class AVFoundationMonitorImpl : public MacMonitorInterface { |
| + public: |
| + AVFoundationMonitorImpl() {}; |
| + explicit AVFoundationMonitorImpl(content::DeviceMonitorMac* monitor); |
| + virtual ~AVFoundationMonitorImpl(); |
| + |
| + virtual void OnDeviceChanged() OVERRIDE; |
| + private: |
| + content::DeviceMonitorMac* monitor_; |
| + int number_audio_devices_; |
| + int number_video_devices_; |
| + id device_arrival_; |
| + id device_removal_; |
| +}; |
| + |
| +AVFoundationMonitorImpl::AVFoundationMonitorImpl( |
| + content::DeviceMonitorMac* monitor) |
| + : monitor_(monitor), |
| + number_audio_devices_(0), |
| + number_video_devices_(0), |
| + device_arrival_(nil), |
| + device_removal_(nil) { |
| + DCHECK(monitor); |
| + |
| + NSNotificationCenter* nc = [NSNotificationCenter defaultCenter]; |
| + NSOperationQueue *mainQueue = [NSOperationQueue mainQueue]; |
| + |
| + device_arrival_ = |
| + [nc addObserverForName:[AVFoundationGlue |
| + avCaptureDeviceWasConnectedNotification] |
| + object:nil |
| + queue:mainQueue |
| + usingBlock:^(NSNotification* notification) { |
| + OnDeviceChanged();}]; |
| + DCHECK(device_arrival_); |
| + device_removal_ = |
| + [nc addObserverForName:[AVFoundationGlue |
| + avCaptureDeviceWasDisconnectedNotification] |
| + object:nil |
| + queue:mainQueue |
| + usingBlock:^(NSNotification* notification) { |
| + OnDeviceChanged();}]; |
| + DCHECK(device_removal_); |
| +} |
| + |
| +AVFoundationMonitorImpl::~AVFoundationMonitorImpl() { |
| + if (!monitor_) |
| + return; |
| + |
| + NSNotificationCenter* nc = [NSNotificationCenter defaultCenter]; |
| + [nc removeObserver:device_arrival_]; |
| + [nc removeObserver:device_removal_]; |
| +} |
| + |
| +void AVFoundationMonitorImpl::OnDeviceChanged() { |
| + base::AutoLock lock(monitor_->lock_); |
| + NSArray* devices = [AVCaptureDeviceGlue devices]; |
| + int number_video_devices = 0; |
| + int number_audio_devices = 0; |
| + for (CrAVCaptureDevice* device in devices) { |
| + if ([AVCaptureDeviceGlue hasMediaType:[AVFoundationGlue avMediaTypeVideo] |
| + forCaptureDevice:device] || |
| + [AVCaptureDeviceGlue hasMediaType:[AVFoundationGlue avMediaTypeMuxed] |
| + forCaptureDevice:device]) { |
| + ++number_video_devices; |
| + } |
| + if ([AVCaptureDeviceGlue hasMediaType:[AVFoundationGlue avMediaTypeAudio] |
| + forCaptureDevice:device] || |
| + [AVCaptureDeviceGlue hasMediaType:[AVFoundationGlue avMediaTypeMuxed] |
| + forCaptureDevice:device]) { |
| + ++number_audio_devices; |
| + } |
| + } |
| + |
| + if (number_video_devices_ != number_video_devices) { |
| + DVLOG(1) << "Video device plugged " << |
| + ((number_video_devices_ > number_video_devices)? "out" : "in"); |
| + number_video_devices_ = number_video_devices; |
| + monitor_->NotifyDeviceChanged(base::SystemMonitor::DEVTYPE_VIDEO_CAPTURE); |
| + } |
| + |
| + if (number_audio_devices_ != number_audio_devices) { |
| + DVLOG(1) << "Audio device plugged " << |
| + ((number_audio_devices_ > number_audio_devices)? "out" : "in"); |
| + number_audio_devices_ = number_audio_devices; |
| + monitor_->NotifyDeviceChanged(base::SystemMonitor::DEVTYPE_AUDIO_CAPTURE); |
| + } |
| } |
| -DeviceMonitorMac::~DeviceMonitorMac() { |
| - qt_monitor_->Stop(); |
| +} // namespace |
| + |
| +namespace content { |
| + |
| +DeviceMonitorMac::DeviceMonitorMac() { |
| + if ([AVFoundationGlue isAVFoundationSupported]){ |
| + DVLOG(1) << "Monitoring via AVFoundation"; |
| + device_monitor_impl_.reset(new AVFoundationMonitorImpl(this)); |
| + // Force the device enumeration so we enumerate correctly devices already in |
| + // the system and at the same time use the AVCaptureDeviceGlue so it in |
| + // turn forces the AVCaptureDeviceGlue alloc-init. |
| + device_monitor_impl_->OnDeviceChanged(); |
| + } else { |
| + DVLOG(1) << "Monitoring via QTKit"; |
| + device_monitor_impl_.reset(new QTKitMonitorImpl(this)); |
| + } |
| } |
| +DeviceMonitorMac::~DeviceMonitorMac() {} |
| + |
| void DeviceMonitorMac::NotifyDeviceChanged( |
| base::SystemMonitor::DeviceType type) { |
| // TODO(xians): Remove the global variable for SystemMonitor. |