Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(355)

Unified Diff: content/browser/device_monitor_mac.mm

Issue 276573009: DeviceMonitorMac AVFoundation: move mgmt of |suspend_observer_| to a class living in Device Thread. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: rsesek@ comments Created 6 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: content/browser/device_monitor_mac.mm
diff --git a/content/browser/device_monitor_mac.mm b/content/browser/device_monitor_mac.mm
index ae720cbdd9686017b2b934438eb6af6e00e1b8f5..eb429afe6402bb07bfc3f100ec31e9c05e2665e9 100644
--- a/content/browser/device_monitor_mac.mm
+++ b/content/browser/device_monitor_mac.mm
@@ -11,6 +11,8 @@
#include "base/bind_helpers.h"
#include "base/logging.h"
#include "base/mac/scoped_nsobject.h"
+#include "base/threading/thread_checker.h"
+#include "content/public/browser/browser_thread.h"
#import "media/video/capture/mac/avfoundation_glue.h"
namespace {
@@ -208,22 +210,21 @@ void QTKitMonitorImpl::OnDeviceChanged() {
}
// Forward declaration for use by CrAVFoundationDeviceObserver.
-class AVFoundationMonitorImpl;
+class SuspendObserverDelegate;
} // namespace
// This class is a Key-Value Observer (KVO) shim. It is needed because C++
-// classes cannot observe Key-Values directly. This class is used by
-// AVfoundationMonitorImpl and executed in its |device_task_runner_|, a.k.a.
-// "Device Thread". -stopObserving is called dutifully on -dealloc on UI thread.
+// classes cannot observe Key-Values directly. Created, manipulated, and
+// destroyed on the Device Thread by SuspendedObserverDelegate.
@interface CrAVFoundationDeviceObserver : NSObject {
@private
- AVFoundationMonitorImpl* receiver_;
+ SuspendObserverDelegate* receiver_; // weak
// Member to keep track of the devices we are already monitoring.
std::set<CrAVCaptureDevice*> monitoredDevices_;
}
-- (id)initWithChangeReceiver:(AVFoundationMonitorImpl*)receiver;
+- (id)initWithChangeReceiver:(SuspendObserverDelegate*)receiver;
- (void)startObserving:(CrAVCaptureDevice*)device;
- (void)stopObserving:(CrAVCaptureDevice*)device;
@@ -231,10 +232,91 @@ class AVFoundationMonitorImpl;
namespace {
+// This class owns and manages the lifetime of a CrAVFoundationDeviceObserver.
+// Provides a callback for this device observer to indicate that there has been
+// a device change of some kind. Created by AVFoundationMonitorImpl in UI thread
+// but living in Device Thread.
+class SuspendObserverDelegate :
+ public base::RefCountedThreadSafe<SuspendObserverDelegate> {
+ public:
+ explicit SuspendObserverDelegate(DeviceMonitorMacImpl* monitor)
+ : avfoundation_monitor_impl_(monitor) {
+ device_thread_checker_.DetachFromThread();
+ }
+
+ void OnDeviceChanged();
+ void StartObserver();
+ void ResetDeviceMonitorOnUIThread();
+
+ private:
+ friend class base::RefCountedThreadSafe<SuspendObserverDelegate>;
+
+ virtual ~SuspendObserverDelegate() {}
+
+ void OnDeviceChangedOnUIThread(
+ const std::vector<DeviceInfo>& snapshot_devices);
+
+ base::ThreadChecker device_thread_checker_;
+ base::scoped_nsobject<CrAVFoundationDeviceObserver> suspend_observer_;
+ DeviceMonitorMacImpl* avfoundation_monitor_impl_;
+};
+
+void SuspendObserverDelegate::OnDeviceChanged() {
+ DCHECK(device_thread_checker_.CalledOnValidThread());
+ NSArray* devices = [AVCaptureDeviceGlue devices];
+ std::vector<DeviceInfo> snapshot_devices;
+ for (CrAVCaptureDevice* device in devices) {
+ [suspend_observer_ startObserving:device];
+ BOOL suspended = [device respondsToSelector:@selector(isSuspended)] &&
+ [device isSuspended];
+ DeviceInfo::DeviceType device_type = DeviceInfo::kUnknown;
+ if ([device hasMediaType:AVFoundationGlue::AVMediaTypeVideo()]) {
+ if (suspended)
+ continue;
+ device_type = DeviceInfo::kVideo;
+ } else if ([device hasMediaType:AVFoundationGlue::AVMediaTypeMuxed()]) {
+ device_type = suspended ? DeviceInfo::kAudio : DeviceInfo::kMuxed;
+ } else if ([device hasMediaType:AVFoundationGlue::AVMediaTypeAudio()]) {
+ device_type = DeviceInfo::kAudio;
+ }
+ snapshot_devices.push_back(DeviceInfo([[device uniqueID] UTF8String],
+ device_type));
+ }
+ // Post the consolidation of enumerated devices to be done on UI thread.
+ content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE,
+ base::Bind(&SuspendObserverDelegate::OnDeviceChangedOnUIThread,
+ this, snapshot_devices));
+}
+
+void SuspendObserverDelegate::StartObserver() {
+ DCHECK(device_thread_checker_.CalledOnValidThread());
+ suspend_observer_.reset([[CrAVFoundationDeviceObserver alloc]
+ initWithChangeReceiver:this]);
+ for (CrAVCaptureDevice* device in [AVCaptureDeviceGlue devices])
+ [suspend_observer_ startObserving:device];
+}
+
+void SuspendObserverDelegate::ResetDeviceMonitorOnUIThread() {
+ DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
+ avfoundation_monitor_impl_ = NULL;
+}
+
+void SuspendObserverDelegate::OnDeviceChangedOnUIThread(
+ const std::vector<DeviceInfo>& snapshot_devices) {
+ DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
+ // |avfoundation_monitor_impl_| might have been NULLed asynchronously before
+ // arriving at this line.
+ if (avfoundation_monitor_impl_) {
+ avfoundation_monitor_impl_->ConsolidateDevicesListAndNotify(
+ snapshot_devices);
+ }
+}
+
// AVFoundation implementation of the Mac Device Monitor, registers as a global
// device connect/disconnect observer and plugs suspend/wake up device observers
-// per device. This class is created and lives in UI thread; device enumeration
-// and operations involving |suspend_observer_| happen on |device_task_runner_|.
+// per device. Owns a SuspendObserverDelegate living in |device_task_runner_|
+// and gets notified when a device is suspended/resumed. This class is created
+// and lives in UI thread;
class AVFoundationMonitorImpl : public DeviceMonitorMacImpl {
public:
AVFoundationMonitorImpl(
@@ -245,18 +327,14 @@ class AVFoundationMonitorImpl : public DeviceMonitorMacImpl {
virtual void OnDeviceChanged() OVERRIDE;
private:
- void OnDeviceChangedOnDeviceThread(
- const scoped_refptr<base::MessageLoopProxy>& ui_thread);
- void StartObserverOnDeviceThread();
-
base::ThreadChecker thread_checker_;
// {Video,AudioInput}DeviceManager's "Device" thread task runner used for
- // device enumeration, valid after MediaStreamManager calls StartMonitoring().
+ // posting tasks to |suspend_observer_delegate_|; valid after
+ // MediaStreamManager calls StartMonitoring().
const scoped_refptr<base::SingleThreadTaskRunner> device_task_runner_;
- // Created and executed in |device_task_runnner_|.
- base::scoped_nsobject<CrAVFoundationDeviceObserver> suspend_observer_;
+ scoped_refptr<SuspendObserverDelegate> suspend_observer_delegate_;
DISALLOW_COPY_AND_ASSIGN(AVFoundationMonitorImpl);
};
@@ -265,7 +343,8 @@ AVFoundationMonitorImpl::AVFoundationMonitorImpl(
content::DeviceMonitorMac* monitor,
const scoped_refptr<base::SingleThreadTaskRunner>& device_task_runner)
: DeviceMonitorMacImpl(monitor),
- device_task_runner_(device_task_runner) {
+ device_task_runner_(device_task_runner),
+ suspend_observer_delegate_(new SuspendObserverDelegate(this)) {
NSNotificationCenter* nc = [NSNotificationCenter defaultCenter];
device_arrival_ =
[nc addObserverForName:AVFoundationGlue::
@@ -282,11 +361,13 @@ AVFoundationMonitorImpl::AVFoundationMonitorImpl(
usingBlock:^(NSNotification* notification) {
OnDeviceChanged();}];
device_task_runner_->PostTask(FROM_HERE,
- base::Bind(&AVFoundationMonitorImpl::StartObserverOnDeviceThread,
- base::Unretained(this)));
+ base::Bind(&SuspendObserverDelegate::StartObserver,
+ suspend_observer_delegate_));
}
AVFoundationMonitorImpl::~AVFoundationMonitorImpl() {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ suspend_observer_delegate_->ResetDeviceMonitorOnUIThread();
NSNotificationCenter* nc = [NSNotificationCenter defaultCenter];
[nc removeObserver:device_arrival_];
[nc removeObserver:device_removal_];
@@ -295,52 +376,15 @@ AVFoundationMonitorImpl::~AVFoundationMonitorImpl() {
void AVFoundationMonitorImpl::OnDeviceChanged() {
DCHECK(thread_checker_.CalledOnValidThread());
device_task_runner_->PostTask(FROM_HERE,
- base::Bind(&AVFoundationMonitorImpl::OnDeviceChangedOnDeviceThread,
- base::Unretained(this),
- base::MessageLoop::current()->message_loop_proxy()));
-}
-
-void AVFoundationMonitorImpl::OnDeviceChangedOnDeviceThread(
- const scoped_refptr<base::MessageLoopProxy>& ui_thread) {
- DCHECK(device_task_runner_->BelongsToCurrentThread());
- NSArray* devices = [AVCaptureDeviceGlue devices];
- std::vector<DeviceInfo> snapshot_devices;
- for (CrAVCaptureDevice* device in devices) {
- [suspend_observer_ startObserving:device];
- BOOL suspended = [device respondsToSelector:@selector(isSuspended)] &&
- [device isSuspended];
- DeviceInfo::DeviceType device_type = DeviceInfo::kUnknown;
- if ([device hasMediaType:AVFoundationGlue::AVMediaTypeVideo()]) {
- if (suspended)
- continue;
- device_type = DeviceInfo::kVideo;
- } else if ([device hasMediaType:AVFoundationGlue::AVMediaTypeMuxed()]) {
- device_type = suspended ? DeviceInfo::kAudio : DeviceInfo::kMuxed;
- } else if ([device hasMediaType:AVFoundationGlue::AVMediaTypeAudio()]) {
- device_type = DeviceInfo::kAudio;
- }
- snapshot_devices.push_back(DeviceInfo([[device uniqueID] UTF8String],
- device_type));
- }
- // Post the consolidation of enumerated devices to be done on UI thread.
- ui_thread->PostTask(FROM_HERE,
- base::Bind(&DeviceMonitorMacImpl::ConsolidateDevicesListAndNotify,
- base::Unretained(this), snapshot_devices));
-}
-
-void AVFoundationMonitorImpl::StartObserverOnDeviceThread() {
- DCHECK(device_task_runner_->BelongsToCurrentThread());
- suspend_observer_.reset([[CrAVFoundationDeviceObserver alloc]
- initWithChangeReceiver:this]);
- for (CrAVCaptureDevice* device in [AVCaptureDeviceGlue devices])
- [suspend_observer_ startObserving:device];
+ base::Bind(&SuspendObserverDelegate::OnDeviceChanged,
+ suspend_observer_delegate_));
}
} // namespace
@implementation CrAVFoundationDeviceObserver
-- (id)initWithChangeReceiver:(AVFoundationMonitorImpl*)receiver {
+- (id)initWithChangeReceiver:(SuspendObserverDelegate*)receiver {
if ((self = [super init])) {
DCHECK(receiver != NULL);
receiver_ = receiver;
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698