Handle iOS devices with no rear-facing camera
Devices exist (specifically the 16GB 5th generation iPod Touch) that do not have a rear-facing camera. This CL: - Adjusts RTCAVFoundationVideoCapturerInternal so initialization doesn't fail because a rear-facing camera doesn't exist, but still logs a warning - Provides a check for whether or not a rear-facing camera can be used (useful for toggling UI elements) - Turns an attempt to switch to the rear-facing camera into a no-op with a warning. BUG= Review URL: https://codereview.webrtc.org/1416303003 Cr-Commit-Position: refs/heads/master@{#11992}
This commit is contained in:
parent
e5d5e51a82
commit
a1cf366ea9
@ -46,6 +46,10 @@
|
|||||||
return [super initWithMediaSource:source];
|
return [super initWithMediaSource:source];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (BOOL)canUseBackCamera {
|
||||||
|
return self.capturer->CanUseBackCamera();
|
||||||
|
}
|
||||||
|
|
||||||
- (BOOL)useBackCamera {
|
- (BOOL)useBackCamera {
|
||||||
return self.capturer->GetUseBackCamera();
|
return self.capturer->GetUseBackCamera();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -56,6 +56,10 @@ class AVFoundationVideoCapturer : public cricket::VideoCapturer {
|
|||||||
// Returns the active capture session.
|
// Returns the active capture session.
|
||||||
AVCaptureSession* GetCaptureSession();
|
AVCaptureSession* GetCaptureSession();
|
||||||
|
|
||||||
|
// Returns whether the rear-facing camera can be used.
|
||||||
|
// e.g. It can't be used because it doesn't exist.
|
||||||
|
bool CanUseBackCamera() const;
|
||||||
|
|
||||||
// Switches the camera being used (either front or back).
|
// Switches the camera being used (either front or back).
|
||||||
void SetUseBackCamera(bool useBackCamera);
|
void SetUseBackCamera(bool useBackCamera);
|
||||||
bool GetUseBackCamera() const;
|
bool GetUseBackCamera() const;
|
||||||
|
|||||||
@ -34,6 +34,7 @@
|
|||||||
#import <UIKit/UIKit.h>
|
#import <UIKit/UIKit.h>
|
||||||
|
|
||||||
#import "webrtc/base/objc/RTCDispatcher.h"
|
#import "webrtc/base/objc/RTCDispatcher.h"
|
||||||
|
#import "webrtc/base/objc/RTCLogging.h"
|
||||||
|
|
||||||
// TODO(tkchin): support other formats.
|
// TODO(tkchin): support other formats.
|
||||||
static NSString* const kDefaultPreset = AVCaptureSessionPreset640x480;
|
static NSString* const kDefaultPreset = AVCaptureSessionPreset640x480;
|
||||||
@ -52,6 +53,7 @@ static cricket::VideoFormat const kDefaultFormat =
|
|||||||
|
|
||||||
@property(nonatomic, readonly) AVCaptureSession* captureSession;
|
@property(nonatomic, readonly) AVCaptureSession* captureSession;
|
||||||
@property(nonatomic, readonly) BOOL isRunning;
|
@property(nonatomic, readonly) BOOL isRunning;
|
||||||
|
@property(nonatomic, readonly) BOOL canUseBackCamera;
|
||||||
@property(nonatomic, assign) BOOL useBackCamera; // Defaults to NO.
|
@property(nonatomic, assign) BOOL useBackCamera; // Defaults to NO.
|
||||||
|
|
||||||
// We keep a pointer back to AVFoundationVideoCapturer to make callbacks on it
|
// We keep a pointer back to AVFoundationVideoCapturer to make callbacks on it
|
||||||
@ -105,10 +107,19 @@ static cricket::VideoFormat const kDefaultFormat =
|
|||||||
_capturer = nullptr;
|
_capturer = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (BOOL)canUseBackCamera {
|
||||||
|
return _backDeviceInput != nil;
|
||||||
|
}
|
||||||
|
|
||||||
- (void)setUseBackCamera:(BOOL)useBackCamera {
|
- (void)setUseBackCamera:(BOOL)useBackCamera {
|
||||||
if (_useBackCamera == useBackCamera) {
|
if (_useBackCamera == useBackCamera) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (!self.canUseBackCamera) {
|
||||||
|
RTCLog(@"No rear-facing camera exists or it cannot be used;"
|
||||||
|
"not switching.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
_useBackCamera = useBackCamera;
|
_useBackCamera = useBackCamera;
|
||||||
[self updateSessionInput];
|
[self updateSessionInput];
|
||||||
}
|
}
|
||||||
@ -203,10 +214,15 @@ static cricket::VideoFormat const kDefaultFormat =
|
|||||||
frontCaptureDevice = captureDevice;
|
frontCaptureDevice = captureDevice;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!frontCaptureDevice || !backCaptureDevice) {
|
if (!frontCaptureDevice) {
|
||||||
NSLog(@"Failed to get capture devices.");
|
RTCLog(@"Failed to get front capture device.");
|
||||||
return NO;
|
return NO;
|
||||||
}
|
}
|
||||||
|
if (!backCaptureDevice) {
|
||||||
|
RTCLog(@"Failed to get back capture device");
|
||||||
|
// Don't return NO here because devices exist (16GB 5th generation iPod
|
||||||
|
// Touch) that don't have a rear-facing camera.
|
||||||
|
}
|
||||||
|
|
||||||
// Set up the session inputs.
|
// Set up the session inputs.
|
||||||
NSError* error = nil;
|
NSError* error = nil;
|
||||||
@ -218,18 +234,21 @@ static cricket::VideoFormat const kDefaultFormat =
|
|||||||
error.localizedDescription);
|
error.localizedDescription);
|
||||||
return NO;
|
return NO;
|
||||||
}
|
}
|
||||||
_backDeviceInput =
|
if (backCaptureDevice) {
|
||||||
[AVCaptureDeviceInput deviceInputWithDevice:backCaptureDevice
|
error = nil;
|
||||||
error:&error];
|
_backDeviceInput =
|
||||||
if (!_backDeviceInput) {
|
[AVCaptureDeviceInput deviceInputWithDevice:backCaptureDevice
|
||||||
NSLog(@"Failed to get capture device input: %@",
|
error:&error];
|
||||||
error.localizedDescription);
|
if (error) {
|
||||||
return NO;
|
RTCLog(@"Failed to get capture device input: %@",
|
||||||
|
error.localizedDescription);
|
||||||
|
_backDeviceInput = nil;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add the inputs.
|
// Add the inputs.
|
||||||
if (![_captureSession canAddInput:_frontDeviceInput] ||
|
if (![_captureSession canAddInput:_frontDeviceInput] ||
|
||||||
![_captureSession canAddInput:_backDeviceInput]) {
|
(_backDeviceInput && ![_captureSession canAddInput:_backDeviceInput])) {
|
||||||
NSLog(@"Session does not support capture inputs.");
|
NSLog(@"Session does not support capture inputs.");
|
||||||
return NO;
|
return NO;
|
||||||
}
|
}
|
||||||
@ -353,6 +372,10 @@ AVCaptureSession* AVFoundationVideoCapturer::GetCaptureSession() {
|
|||||||
return _capturer.captureSession;
|
return _capturer.captureSession;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool AVFoundationVideoCapturer::CanUseBackCamera() const {
|
||||||
|
return _capturer.canUseBackCamera;
|
||||||
|
}
|
||||||
|
|
||||||
void AVFoundationVideoCapturer::SetUseBackCamera(bool useBackCamera) {
|
void AVFoundationVideoCapturer::SetUseBackCamera(bool useBackCamera) {
|
||||||
_capturer.useBackCamera = useBackCamera;
|
_capturer.useBackCamera = useBackCamera;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -41,6 +41,8 @@
|
|||||||
- (instancetype)initWithFactory:(RTCPeerConnectionFactory*)factory
|
- (instancetype)initWithFactory:(RTCPeerConnectionFactory*)factory
|
||||||
constraints:(RTCMediaConstraints*)constraints;
|
constraints:(RTCMediaConstraints*)constraints;
|
||||||
|
|
||||||
|
// Returns whether rear-facing camera is available for use.
|
||||||
|
@property(nonatomic, readonly) BOOL canUseBackCamera;
|
||||||
// Switches the camera being used (either front or back).
|
// Switches the camera being used (either front or back).
|
||||||
@property(nonatomic, assign) BOOL useBackCamera;
|
@property(nonatomic, assign) BOOL useBackCamera;
|
||||||
// Returns the active capture session.
|
// Returns the active capture session.
|
||||||
|
|||||||
@ -28,6 +28,9 @@ NS_ASSUME_NONNULL_BEGIN
|
|||||||
- (instancetype)initWithFactory:(RTCPeerConnectionFactory *)factory
|
- (instancetype)initWithFactory:(RTCPeerConnectionFactory *)factory
|
||||||
constraints:(nullable RTCMediaConstraints *)constraints;
|
constraints:(nullable RTCMediaConstraints *)constraints;
|
||||||
|
|
||||||
|
/** Returns whether rear-facing camera is available for use. */
|
||||||
|
@property(nonatomic, readonly) BOOL canUseBackCamera;
|
||||||
|
|
||||||
/** Switches the camera being used (either front or back). */
|
/** Switches the camera being used (either front or back). */
|
||||||
@property(nonatomic, assign) BOOL useBackCamera;
|
@property(nonatomic, assign) BOOL useBackCamera;
|
||||||
|
|
||||||
|
|||||||
@ -27,6 +27,10 @@
|
|||||||
return [super initWithNativeVideoSource:source];
|
return [super initWithNativeVideoSource:source];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (BOOL)canUseBackCamera {
|
||||||
|
return self.capturer->CanUseBackCamera();
|
||||||
|
}
|
||||||
|
|
||||||
- (BOOL)useBackCamera {
|
- (BOOL)useBackCamera {
|
||||||
return self.capturer->GetUseBackCamera();
|
return self.capturer->GetUseBackCamera();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -40,6 +40,12 @@ class AVFoundationVideoCapturer : public cricket::VideoCapturer {
|
|||||||
/** Returns the active capture session. */
|
/** Returns the active capture session. */
|
||||||
AVCaptureSession* GetCaptureSession();
|
AVCaptureSession* GetCaptureSession();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns whether the rear-facing camera can be used.
|
||||||
|
* e.g. It can't be used because it doesn't exist.
|
||||||
|
*/
|
||||||
|
bool CanUseBackCamera() const;
|
||||||
|
|
||||||
/** Switches the camera being used (either front or back). */
|
/** Switches the camera being used (either front or back). */
|
||||||
void SetUseBackCamera(bool useBackCamera);
|
void SetUseBackCamera(bool useBackCamera);
|
||||||
bool GetUseBackCamera() const;
|
bool GetUseBackCamera() const;
|
||||||
|
|||||||
@ -17,6 +17,7 @@
|
|||||||
#import <UIKit/UIKit.h>
|
#import <UIKit/UIKit.h>
|
||||||
|
|
||||||
#import "webrtc/base/objc/RTCDispatcher.h"
|
#import "webrtc/base/objc/RTCDispatcher.h"
|
||||||
|
#import "webrtc/base/objc/RTCLogging.h"
|
||||||
|
|
||||||
// TODO(tkchin): support other formats.
|
// TODO(tkchin): support other formats.
|
||||||
static NSString* const kDefaultPreset = AVCaptureSessionPreset640x480;
|
static NSString* const kDefaultPreset = AVCaptureSessionPreset640x480;
|
||||||
@ -35,6 +36,7 @@ static cricket::VideoFormat const kDefaultFormat =
|
|||||||
|
|
||||||
@property(nonatomic, readonly) AVCaptureSession *captureSession;
|
@property(nonatomic, readonly) AVCaptureSession *captureSession;
|
||||||
@property(nonatomic, readonly) BOOL isRunning;
|
@property(nonatomic, readonly) BOOL isRunning;
|
||||||
|
@property(nonatomic, readonly) BOOL canUseBackCamera;
|
||||||
@property(nonatomic, assign) BOOL useBackCamera; // Defaults to NO.
|
@property(nonatomic, assign) BOOL useBackCamera; // Defaults to NO.
|
||||||
|
|
||||||
// We keep a pointer back to AVFoundationVideoCapturer to make callbacks on it
|
// We keep a pointer back to AVFoundationVideoCapturer to make callbacks on it
|
||||||
@ -88,10 +90,19 @@ static cricket::VideoFormat const kDefaultFormat =
|
|||||||
_capturer = nullptr;
|
_capturer = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (BOOL)canUseBackCamera {
|
||||||
|
return _backDeviceInput != nil;
|
||||||
|
}
|
||||||
|
|
||||||
- (void)setUseBackCamera:(BOOL)useBackCamera {
|
- (void)setUseBackCamera:(BOOL)useBackCamera {
|
||||||
if (_useBackCamera == useBackCamera) {
|
if (_useBackCamera == useBackCamera) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (!self.canUseBackCamera) {
|
||||||
|
RTCLog(@"No rear-facing camera exists or it cannot be used;"
|
||||||
|
"not switching.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
_useBackCamera = useBackCamera;
|
_useBackCamera = useBackCamera;
|
||||||
[self updateSessionInput];
|
[self updateSessionInput];
|
||||||
}
|
}
|
||||||
@ -186,10 +197,15 @@ static cricket::VideoFormat const kDefaultFormat =
|
|||||||
frontCaptureDevice = captureDevice;
|
frontCaptureDevice = captureDevice;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!frontCaptureDevice || !backCaptureDevice) {
|
if (!frontCaptureDevice) {
|
||||||
NSLog(@"Failed to get capture devices.");
|
RTCLog(@"Failed to get front capture device.");
|
||||||
return NO;
|
return NO;
|
||||||
}
|
}
|
||||||
|
if (!backCaptureDevice) {
|
||||||
|
RTCLog(@"Failed to get back capture device");
|
||||||
|
// Don't return NO here because devices exist (16GB 5th generation iPod
|
||||||
|
// Touch) that don't have a rear-facing camera.
|
||||||
|
}
|
||||||
|
|
||||||
// Set up the session inputs.
|
// Set up the session inputs.
|
||||||
NSError *error = nil;
|
NSError *error = nil;
|
||||||
@ -201,18 +217,21 @@ static cricket::VideoFormat const kDefaultFormat =
|
|||||||
error.localizedDescription);
|
error.localizedDescription);
|
||||||
return NO;
|
return NO;
|
||||||
}
|
}
|
||||||
_backDeviceInput =
|
if (backCaptureDevice) {
|
||||||
[AVCaptureDeviceInput deviceInputWithDevice:backCaptureDevice
|
error = nil;
|
||||||
error:&error];
|
_backDeviceInput =
|
||||||
if (!_backDeviceInput) {
|
[AVCaptureDeviceInput deviceInputWithDevice:backCaptureDevice
|
||||||
NSLog(@"Failed to get capture device input: %@",
|
error:&error];
|
||||||
error.localizedDescription);
|
if (error) {
|
||||||
return NO;
|
RTCLog(@"Failed to get capture device input: %@",
|
||||||
|
error.localizedDescription);
|
||||||
|
_backDeviceInput = nil;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add the inputs.
|
// Add the inputs.
|
||||||
if (![_captureSession canAddInput:_frontDeviceInput] ||
|
if (![_captureSession canAddInput:_frontDeviceInput] ||
|
||||||
![_captureSession canAddInput:_backDeviceInput]) {
|
(_backDeviceInput && ![_captureSession canAddInput:_backDeviceInput])) {
|
||||||
NSLog(@"Session does not support capture inputs.");
|
NSLog(@"Session does not support capture inputs.");
|
||||||
return NO;
|
return NO;
|
||||||
}
|
}
|
||||||
@ -336,6 +355,10 @@ AVCaptureSession* AVFoundationVideoCapturer::GetCaptureSession() {
|
|||||||
return _capturer.captureSession;
|
return _capturer.captureSession;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool AVFoundationVideoCapturer::CanUseBackCamera() const {
|
||||||
|
return _capturer.canUseBackCamera;
|
||||||
|
}
|
||||||
|
|
||||||
void AVFoundationVideoCapturer::SetUseBackCamera(bool useBackCamera) {
|
void AVFoundationVideoCapturer::SetUseBackCamera(bool useBackCamera) {
|
||||||
_capturer.useBackCamera = useBackCamera;
|
_capturer.useBackCamera = useBackCamera;
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user