Skip to content

Commit

Permalink
Added VideoCaptureDeviceAvFoundation class, implementing the
Browse files Browse the repository at this point in the history
PlatformVideoCapturingMac protocol. 

All the protocol methods are NOTIMPLEMENTED(), the static +getDeviceNames()
is implemented though and used to enumerate the devices in the system in 
VideoCaptureDeviceMac if IsAVFoundationSupported()==YES. 

The rest of the VideoCaptureDeviceMac operations use QTKit still.

This CL is part of a larger exercise to add support for Video Capture in 
Mac > 10.6 using AVFoundation. 

BUG=288562

Review URL: https://codereview.chromium.org/48983002

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@233971 0039d316-1c4b-4281-b951-d872f2087c98
  • Loading branch information
mcasas@chromium.org committed Nov 8, 2013
1 parent c9390bd commit 31279ff
Show file tree
Hide file tree
Showing 8 changed files with 148 additions and 31 deletions.
23 changes: 10 additions & 13 deletions content/browser/device_monitor_mac.mm
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,11 @@ explicit DeviceMonitorMacImpl(content::DeviceMonitorMac* monitor)
device_arrival_(nil),
device_removal_(nil) {
DCHECK(monitor);
// Initialise the devices_cache_ with a not-valid entry. For the case in
// which there is one single device in the system and we get notified when
// it gets removed, this will prevent the system from thinking that no
// devices were added nor removed and not notifying the |monitor_|.
cached_devices_.push_back(DeviceInfo("invalid", DeviceInfo::kInvalid));
}
virtual ~DeviceMonitorMacImpl() {}

Expand Down Expand Up @@ -134,9 +139,6 @@ void ConsolidateDevicesListAndNotify(

QTKitMonitorImpl::QTKitMonitorImpl(content::DeviceMonitorMac* monitor)
: DeviceMonitorMacImpl(monitor) {
// Initialise the devices_cache_ with a not-valid entry.
cached_devices_.push_back(DeviceInfo("invalid", DeviceInfo::kInvalid));

NSNotificationCenter* nc = [NSNotificationCenter defaultCenter];
device_arrival_ =
[nc addObserverForName:QTCaptureDeviceWasConnectedNotification
Expand Down Expand Up @@ -262,16 +264,11 @@ void ConsolidateDevicesListAndNotify(
if (AVFoundationGlue::IsAVFoundationSupported()) {
DVLOG(1) << "Monitoring via AVFoundation";
device_monitor_impl_.reset(new AVFoundationMonitorImpl(this));
// Force device enumeration to correctly list those already in the system,
// and more importantly to force AVFoundation NSBundle to create the devices
// so they can send notifications. This operation seems to take in the range
// of hundred of ms. and represent a startup penalty, so should be moved to
// the point when is needed.
// TODO(mcasas): Once the whole video capture moves to AVFoundation, the
// NSBundle devices will be created during JavaScript getUserMedia() call,
// so we should be able to remove this line let the AVFoundation loading
// happen then.
device_monitor_impl_->OnDeviceChanged();
// For the AVFoundation to start sending connect/disconnect notifications,
// the AVFoundation NSBundle has to be loaded and the devices enumerated.
// This operation seems to take in the range of hundred of ms. so should be
// moved to the point when is needed, and that is during
// DeviceVideoCaptureMac +getDeviceNames.
} else {
DVLOG(1) << "Monitoring via QTKit";
device_monitor_impl_.reset(new QTKitMonitorImpl(this));
Expand Down
2 changes: 2 additions & 0 deletions media/media.gyp
Original file line number Diff line number Diff line change
Expand Up @@ -401,6 +401,8 @@
'video/capture/mac/avfoundation_glue.h',
'video/capture/mac/avfoundation_glue.mm',
'video/capture/mac/platform_video_capturing_mac.h',
'video/capture/mac/video_capture_device_avfoundation_mac.h',
'video/capture/mac/video_capture_device_avfoundation_mac.mm',
'video/capture/mac/video_capture_device_mac.h',
'video/capture/mac/video_capture_device_mac.mm',
'video/capture/mac/video_capture_device_qtkit_mac.h',
Expand Down
2 changes: 2 additions & 0 deletions media/video/capture/mac/avfoundation_glue.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,8 @@ MEDIA_EXPORT

- (NSString*)uniqueID;

- (NSString*)localizedName;

@end

MEDIA_EXPORT
Expand Down
42 changes: 42 additions & 0 deletions media/video/capture/mac/video_capture_device_avfoundation_mac.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
// Copyright 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef MEDIA_VIDEO_CAPTURE_MAC_VIDEO_CAPTURE_DEVICE_AVFOUNDATION_MAC_H_
#define MEDIA_VIDEO_CAPTURE_MAC_VIDEO_CAPTURE_DEVICE_AVFOUNDATION_MAC_H_

#import <Foundation/Foundation.h>

#import "media/video/capture/mac/platform_video_capturing_mac.h"

namespace media {
class VideoCaptureDeviceMac;
}

// Class used by VideoCaptureDeviceMac for video capture using AVFoundation API.
@interface VideoCaptureDeviceAVFoundation : NSObject<PlatformVideoCapturingMac>

// Returns a dictionary of capture devices with friendly name and unique id.
+ (NSDictionary*)deviceNames;

// Initializes the instance and registers the frame receiver.
- (id)initWithFrameReceiver:(media::VideoCaptureDeviceMac*)frameReceiver;

// Set the frame receiver.
- (void)setFrameReceiver:(media::VideoCaptureDeviceMac*)frameReceiver;

// Sets which capture device to use. Returns YES on sucess, NO otherwise.
- (BOOL)setCaptureDevice:(NSString*)deviceId;

// Configures the capture properties.
- (BOOL)setCaptureHeight:(int)height width:(int)width frameRate:(int)frameRate;

// Start video capturing. Returns YES on sucess, NO otherwise.
- (BOOL)startCapture;

// Stops video capturing.
- (void)stopCapture;

@end

#endif // MEDIA_VIDEO_CAPTURE_MAC_VIDEO_CAPTURE_DEVICE_AVFOUNDATION_MAC_H_
65 changes: 65 additions & 0 deletions media/video/capture/mac/video_capture_device_avfoundation_mac.mm
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
// Copyright 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#import "media/video/capture/mac/video_capture_device_avfoundation_mac.h"

#include "base/logging.h"
#import "media/video/capture/mac/avfoundation_glue.h"

@implementation VideoCaptureDeviceAVFoundation

#pragma mark Class methods

+ (void)getDeviceNames:(NSMutableDictionary*)deviceNames {
// Calling the +devices method will load NSBundle and create device drivers.
NSArray* devices = [AVCaptureDeviceGlue devices];
for (CrAVCaptureDevice* device in devices) {
if ([device hasMediaType:AVFoundationGlue::AVMediaTypeVideo()] ||
[device hasMediaType:AVFoundationGlue::AVMediaTypeMuxed()]) {
[deviceNames setObject:[device localizedName]
forKey:[device uniqueID]];
}
}
}

+ (NSDictionary*)deviceNames {
NSMutableDictionary* deviceNames =
[[[NSMutableDictionary alloc] init] autorelease];
// The device name retrieval is not going to happen in the main thread, and
// this might cause instabilities (it did in QTKit), so keep an eye here.
[self getDeviceNames:deviceNames];
return deviceNames;
}

#pragma mark Public methods

- (id)initWithFrameReceiver:(media::VideoCaptureDeviceMac*)frameReceiver {
NOTIMPLEMENTED();
return nil;
}

- (void)setFrameReceiver:(media::VideoCaptureDeviceMac*)frameReceiver {
NOTIMPLEMENTED();
}

- (BOOL)setCaptureDevice:(NSString*)deviceId {
NOTIMPLEMENTED();
return NO;
}

- (BOOL)setCaptureHeight:(int)height width:(int)width frameRate:(int)frameRate {
NOTIMPLEMENTED();
return NO;
}

- (BOOL)startCapture {
NOTIMPLEMENTED();
return NO;
}

- (void)stopCapture {
NOTIMPLEMENTED();
}

@end
13 changes: 11 additions & 2 deletions media/video/capture/mac/video_capture_device_mac.mm
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,10 @@
#include "base/location.h"
#include "base/logging.h"
#include "base/time/time.h"
#import "media/video/capture/mac/avfoundation_glue.h"
#import "media/video/capture/mac/platform_video_capturing_mac.h"
#include "media/video/capture/mac/video_capture_device_qtkit_mac.h"
#import "media/video/capture/mac/video_capture_device_avfoundation_mac.h"
#import "media/video/capture/mac/video_capture_device_qtkit_mac.h"

namespace {

Expand Down Expand Up @@ -68,7 +70,14 @@ void GetBestMatchSupportedResolution(int* width, int* height) {
// Loop through all available devices and add to |device_names|.
device_names->clear();

NSDictionary* capture_devices = [VideoCaptureDeviceQTKit deviceNames];
NSDictionary* capture_devices;
if (AVFoundationGlue::IsAVFoundationSupported()) {
DVLOG(1) << "Enumerating video capture devices using AVFoundation";
capture_devices = [VideoCaptureDeviceAVFoundation deviceNames];
} else {
DVLOG(1) << "Enumerating video capture devices using QTKit";
capture_devices = [VideoCaptureDeviceQTKit deviceNames];
}
for (NSString* key in capture_devices) {
Name name([[capture_devices valueForKey:key] UTF8String],
[key UTF8String]);
Expand Down
16 changes: 8 additions & 8 deletions media/video/capture/mac/video_capture_device_qtkit_mac.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@
// VideoCaptureDeviceQTKit implements all QTKit related code for
// communicating with a QTKit capture device.

#ifndef MEDIA_VIDEO_CAPTURE_MAC_VIDEO_CAPTURE_DEVICE_MAC_QTKIT_H_
#define MEDIA_VIDEO_CAPTURE_MAC_VIDEO_CAPTURE_DEVICE_MAC_QTKIT_H_
#ifndef MEDIA_VIDEO_CAPTURE_MAC_VIDEO_CAPTURE_DEVICE_QTKIT_MAC_H_
#define MEDIA_VIDEO_CAPTURE_MAC_VIDEO_CAPTURE_DEVICE_QTKIT_MAC_H_

#import <Foundation/Foundation.h>

Expand Down Expand Up @@ -40,16 +40,16 @@ namespace media {
}

// Returns a dictionary of capture devices with friendly name and unique id.
+ (NSDictionary *)deviceNames;
+ (NSDictionary*)deviceNames;

// Initializes the instance and registers the frame receiver.
- (id)initWithFrameReceiver:(media::VideoCaptureDeviceMac *)frameReceiver;
- (id)initWithFrameReceiver:(media::VideoCaptureDeviceMac*)frameReceiver;

// Set the frame receiver.
- (void)setFrameReceiver:(media::VideoCaptureDeviceMac *)frameReceiver;
- (void)setFrameReceiver:(media::VideoCaptureDeviceMac*)frameReceiver;

// Sets which capture device to use. Returns YES on sucess, NO otherwise.
- (BOOL)setCaptureDevice:(NSString *)deviceId;
- (BOOL)setCaptureDevice:(NSString*)deviceId;

// Configures the capture properties.
- (BOOL)setCaptureHeight:(int)height width:(int)width frameRate:(int)frameRate;
Expand All @@ -61,8 +61,8 @@ namespace media {
- (void)stopCapture;

// Handle any QTCaptureSessionRuntimeErrorNotifications.
- (void)handleNotification:(NSNotification *)errorNotification;
- (void)handleNotification:(NSNotification*)errorNotification;

@end

#endif // MEDIA_VIDEO_CAPTURE_MAC_VIDEO_CAPTURE_DEVICE_MAC_QTKIT_H_
#endif // MEDIA_VIDEO_CAPTURE_MAC_VIDEO_CAPTURE_DEVICE_QTKIT_MAC_H_
16 changes: 8 additions & 8 deletions media/video/capture/mac/video_capture_device_qtkit_mac.mm
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ + (NSDictionary*)deviceNames {

#pragma mark Public methods

- (id)initWithFrameReceiver:(media::VideoCaptureDeviceMac *)frameReceiver {
- (id)initWithFrameReceiver:(media::VideoCaptureDeviceMac*)frameReceiver {
self = [super init];
if (self) {
frameReceiver_ = frameReceiver;
Expand All @@ -63,13 +63,13 @@ - (void)dealloc {
[super dealloc];
}

- (void)setFrameReceiver:(media::VideoCaptureDeviceMac *)frameReceiver {
- (void)setFrameReceiver:(media::VideoCaptureDeviceMac*)frameReceiver {
[lock_ lock];
frameReceiver_ = frameReceiver;
[lock_ unlock];
}

- (BOOL)setCaptureDevice:(NSString *)deviceId {
- (BOOL)setCaptureDevice:(NSString*)deviceId {
if (deviceId) {
// Set the capture device.
if (captureDeviceInput_) {
Expand Down Expand Up @@ -233,10 +233,10 @@ - (void)stopCapture {
}

// |captureOutput| is called by the capture device to deliver a new frame.
- (void)captureOutput:(QTCaptureOutput *)captureOutput
- (void)captureOutput:(QTCaptureOutput*)captureOutput
didOutputVideoFrame:(CVImageBufferRef)videoFrame
withSampleBuffer:(QTSampleBuffer *)sampleBuffer
fromConnection:(QTCaptureConnection *)connection {
withSampleBuffer:(QTSampleBuffer*)sampleBuffer
fromConnection:(QTCaptureConnection*)connection {
[lock_ lock];
if(!frameReceiver_) {
[lock_ unlock];
Expand Down Expand Up @@ -313,8 +313,8 @@ - (void)captureOutput:(QTCaptureOutput *)captureOutput
[lock_ unlock];
}

- (void)handleNotification:(NSNotification *)errorNotification {
NSError * error = (NSError *)[[errorNotification userInfo]
- (void)handleNotification:(NSNotification*)errorNotification {
NSError * error = (NSError*)[[errorNotification userInfo]
objectForKey:QTCaptureSessionErrorKey];
frameReceiver_->ReceiveError([[error localizedDescription] UTF8String]);
}
Expand Down

0 comments on commit 31279ff

Please sign in to comment.