Diff
Modified: trunk/Source/WebCore/ChangeLog (212843 => 212844)
--- trunk/Source/WebCore/ChangeLog 2017-02-22 19:33:02 UTC (rev 212843)
+++ trunk/Source/WebCore/ChangeLog 2017-02-22 20:06:57 UTC (rev 212844)
@@ -1,3 +1,44 @@
+2017-02-22 Eric Carlson <[email protected]>
+
+ [MediaStream iOS] Respond to capture interruptions and notifications
+ https://bugs.webkit.org/show_bug.cgi?id=168610
+
+ Reviewed by Jer Noble.
+
+ * platform/graphics/avfoundation/objc/MediaPlayerPrivateMediaStreamAVFObjC.mm:
+ (WebCore::MediaPlayerPrivateMediaStreamAVFObjC::ensureLayer): Drive-by cleanup: don't create
+ a sample buffer display layer unless there is an active video track.
+
+ * platform/mediastream/mac/AVMediaCaptureSource.h:
+ * platform/mediastream/mac/AVMediaCaptureSource.mm:
+ (WebCore::AVMediaCaptureSource::AVMediaCaptureSource): Add static_asserts to ensure that
+ WebCore::InterruptionReason values map directly to AVCaptureSessionInterruptionReason values.
+ (WebCore::AVMediaCaptureSource::~AVMediaCaptureSource): Minor cleanup.
+ (WebCore::AVMediaCaptureSource::startProducingData): Start listening for notifications before
+ starting the session.
+ (WebCore::AVMediaCaptureSource::stopProducingData): Remove the notification observers before
+ stopping the session.
+ (WebCore::AVMediaCaptureSource::setupSession): Minor style cleanup.
+ (WebCore::AVMediaCaptureSource::captureSessionRuntimeError): New. When the error is AVErrorMediaServicesWereReset,
+ sometimes caused by a mediaserverd crash, try to restart the session one time.
+ (WebCore::AVMediaCaptureSource::captureSessionBeginInterruption): Store the interruption reason.
+ (WebCore::AVMediaCaptureSource::captureSessionEndInterruption): Try to restart the session if
+ it was interrupted because the app went into multi-app layout mode.
+ (WebCore::sessionKVOProperties): Drive-by cleanup.
+ (-[WebCoreAVMediaCaptureSourceObserver initWithCallback:]):
+ (-[WebCoreAVMediaCaptureSourceObserver disconnect]):
+ (-[WebCoreAVMediaCaptureSourceObserver addNotificationObservers]):
+ (-[WebCoreAVMediaCaptureSourceObserver removeNotificationObservers]):
+ (-[WebCoreAVMediaCaptureSourceObserver sessionRuntimeError:]):
+ (-[WebCoreAVMediaCaptureSourceObserver beginSessionInterrupted:]):
+ (-[WebCoreAVMediaCaptureSourceObserver endSessionInterrupted:]):
+
+ * platform/mediastream/mac/AVVideoCaptureSource.mm:
+ (WebCore::AVVideoCaptureSource::initializeCapabilities): Not all AVCaptureSession preset strings
+ are available on all platforms so load with SOFT_LINK_POINTER_OPTIONAL and NULL check before use.
+ (WebCore::sizeForPreset): Ditto.
+ (WebCore::AVVideoCaptureSource::bestSessionPresetForVideoDimensions): Ditto.
+
2017-02-22 Zalan Bujtas <[email protected]>
Simple line layout: ensureLineBoxes for paginated content.
Modified: trunk/Source/WebCore/platform/mediastream/mac/AVMediaCaptureSource.h (212843 => 212844)
--- trunk/Source/WebCore/platform/mediastream/mac/AVMediaCaptureSource.h 2017-02-22 19:33:02 UTC (rev 212843)
+++ trunk/Source/WebCore/platform/mediastream/mac/AVMediaCaptureSource.h 2017-02-22 20:06:57 UTC (rev 212844)
@@ -39,6 +39,7 @@
OBJC_CLASS AVCaptureOutput;
OBJC_CLASS AVCaptureSession;
OBJC_CLASS AVCaptureVideoDataOutput;
+OBJC_CLASS NSError;
OBJC_CLASS WebCoreAVMediaCaptureSourceObserver;
typedef struct opaqueCMSampleBuffer *CMSampleBufferRef;
@@ -53,8 +54,13 @@
virtual void captureOutputDidOutputSampleBufferFromConnection(AVCaptureOutput*, CMSampleBufferRef, AVCaptureConnection*) = 0;
- virtual void captureSessionIsRunningDidChange(bool);
+ void captureSessionIsRunningDidChange(bool);
+ void captureSessionRuntimeError(RetainPtr<NSError>);
+ enum class InterruptionReason { None, VideoNotAllowedInBackground, AudioInUse, VideoInUse, VideoNotAllowedInSideBySide };
+ void captureSessionBeginInterruption(RetainPtr<NSNotification>);
+ void captureSessionEndInterruption(RetainPtr<NSNotification>);
+
AVCaptureSession *session() const { return m_session.get(); }
const RealtimeMediaSourceSettings& settings() const final;
@@ -98,7 +104,8 @@
RefPtr<RealtimeMediaSourceCapabilities> m_capabilities;
RetainPtr<AVCaptureSession> m_session;
RetainPtr<AVCaptureDevice> m_device;
- bool m_isRunning { false};
+ InterruptionReason m_interruption { InterruptionReason::None };
+ bool m_isRunning { false };
};
} // namespace WebCore
Modified: trunk/Source/WebCore/platform/mediastream/mac/AVMediaCaptureSource.mm (212843 => 212844)
--- trunk/Source/WebCore/platform/mediastream/mac/AVMediaCaptureSource.mm 2017-02-22 19:33:02 UTC (rev 212843)
+++ trunk/Source/WebCore/platform/mediastream/mac/AVMediaCaptureSource.mm 2017-02-22 20:06:57 UTC (rev 212844)
@@ -38,6 +38,7 @@
#import <AVFoundation/AVCaptureInput.h>
#import <AVFoundation/AVCaptureOutput.h>
#import <AVFoundation/AVCaptureSession.h>
+#import <AVFoundation/AVError.h>
#import <objc/runtime.h>
#import <wtf/MainThread.h>
@@ -72,21 +73,25 @@
SOFT_LINK_POINTER(AVFoundation, AVMediaTypeAudio, NSString *)
SOFT_LINK_POINTER(AVFoundation, AVMediaTypeMuxed, NSString *)
SOFT_LINK_POINTER(AVFoundation, AVMediaTypeVideo, NSString *)
-SOFT_LINK_POINTER(AVFoundation, AVCaptureSessionPreset1280x720, NSString *)
-SOFT_LINK_POINTER(AVFoundation, AVCaptureSessionPreset640x480, NSString *)
-SOFT_LINK_POINTER(AVFoundation, AVCaptureSessionPreset352x288, NSString *)
-SOFT_LINK_POINTER(AVFoundation, AVCaptureSessionPresetLow, NSString *)
-SOFT_LINK_POINTER(AVFoundation, AVCaptureSessionDidStopRunningNotification, NSString *)
#define AVMediaTypeAudio getAVMediaTypeAudio()
#define AVMediaTypeMuxed getAVMediaTypeMuxed()
#define AVMediaTypeVideo getAVMediaTypeVideo()
-#define AVCaptureSessionPreset1280x720 getAVCaptureSessionPreset1280x720()
-#define AVCaptureSessionPreset640x480 getAVCaptureSessionPreset640x480()
-#define AVCaptureSessionPreset352x288 getAVCaptureSessionPreset352x288()
-#define AVCaptureSessionPresetLow getAVCaptureSessionPresetLow()
-#define AVCaptureSessionDidStopRunningNotification getAVCaptureSessionDidStopRunningNotification()
+#if PLATFORM(IOS)
+SOFT_LINK_POINTER_OPTIONAL(AVFoundation, AVCaptureSessionRuntimeErrorNotification, NSString *)
+SOFT_LINK_POINTER_OPTIONAL(AVFoundation, AVCaptureSessionWasInterruptedNotification, NSString *)
+SOFT_LINK_POINTER_OPTIONAL(AVFoundation, AVCaptureSessionInterruptionEndedNotification, NSString *)
+SOFT_LINK_POINTER_OPTIONAL(AVFoundation, AVCaptureSessionInterruptionReasonKey, NSString *)
+SOFT_LINK_POINTER_OPTIONAL(AVFoundation, AVCaptureSessionErrorKey, NSString *)
+
+#define AVCaptureSessionRuntimeErrorNotification getAVCaptureSessionRuntimeErrorNotification()
+#define AVCaptureSessionWasInterruptedNotification getAVCaptureSessionWasInterruptedNotification()
+#define AVCaptureSessionInterruptionEndedNotification getAVCaptureSessionInterruptionEndedNotification()
+#define AVCaptureSessionInterruptionReasonKey getAVCaptureSessionInterruptionReasonKey()
+#define AVCaptureSessionErrorKey getAVCaptureSessionErrorKey()
+#endif
+
using namespace WebCore;
@interface WebCoreAVMediaCaptureSourceObserver : NSObject<AVCaptureAudioDataOutputSampleBufferDelegate, AVCaptureVideoDataOutputSampleBufferDelegate>
@@ -96,13 +101,20 @@
-(id)initWithCallback:(AVMediaCaptureSource*)callback;
-(void)disconnect;
--(void)captureOutput:(AVCaptureOutputType *)captureOutput didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer fromConnection:(AVCaptureConnectionType *)connection;
--(void)observeValueForKeyPath:keyPath ofObject:(id)object change:(NSDictionary *)change context:(void*)context;
+-(void)addNotificationObservers;
+-(void)removeNotificationObservers;
+-(void)captureOutput:(AVCaptureOutputType*)captureOutput didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer fromConnection:(AVCaptureConnectionType*)connection;
+-(void)observeValueForKeyPath:keyPath ofObject:(id)object change:(NSDictionary*)change context:(void*)context;
+#if PLATFORM(IOS)
+-(void)sessionRuntimeError:(NSNotification*)notification;
+-(void)beginSessionInterrupted:(NSNotification*)notification;
+-(void)endSessionInterrupted:(NSNotification*)notification;
+#endif
@end
namespace WebCore {
-static NSArray* sessionKVOProperties();
+static NSArray<NSString*>* sessionKVOProperties();
static dispatch_queue_t globaAudioCaptureSerialQueue()
{
@@ -130,6 +142,13 @@
, m_objcObserver(adoptNS([[WebCoreAVMediaCaptureSourceObserver alloc] initWithCallback:this]))
, m_device(device)
{
+#if PLATFORM(IOS)
+ static_assert(static_cast<int>(InterruptionReason::VideoNotAllowedInBackground) == static_cast<int>(AVCaptureSessionInterruptionReasonVideoDeviceNotAvailableInBackground), "InterruptionReason::VideoNotAllowedInBackground is not AVCaptureSessionInterruptionReasonVideoDeviceNotAvailableInBackground as expected");
+ static_assert(static_cast<int>(InterruptionReason::VideoNotAllowedInSideBySide) == AVCaptureSessionInterruptionReasonVideoDeviceNotAvailableWithMultipleForegroundApps, "InterruptionReason::VideoNotAllowedInSideBySide is not AVCaptureSessionInterruptionReasonVideoDeviceNotAvailableWithMultipleForegroundApps as expected");
+ static_assert(static_cast<int>(InterruptionReason::VideoInUse) == AVCaptureSessionInterruptionReasonVideoDeviceInUseByAnotherClient, "InterruptionReason::VideoInUse is not AVCaptureSessionInterruptionReasonVideoDeviceInUseByAnotherClient as expected");
+ static_assert(static_cast<int>(InterruptionReason::AudioInUse) == AVCaptureSessionInterruptionReasonAudioDeviceInUseByAnotherClient, "InterruptionReason::AudioInUse is not AVCaptureSessionInterruptionReasonAudioDeviceInUseByAnotherClient as expected");
+#endif
+
setPersistentID(device.uniqueID);
setMuted(true);
}
@@ -138,11 +157,15 @@
{
[m_objcObserver disconnect];
- if (m_session) {
- for (NSString *keyName in sessionKVOProperties())
- [m_session removeObserver:m_objcObserver.get() forKeyPath:keyName];
+ if (!m_session)
+ return;
+
+ for (NSString *keyName in sessionKVOProperties())
+ [m_session removeObserver:m_objcObserver.get() forKeyPath:keyName];
+
+ if ([m_session isRunning])
[m_session stopRunning];
- }
+
}
void AVMediaCaptureSource::startProducingData()
@@ -152,7 +175,8 @@
if ([m_session isRunning])
return;
-
+
+ [m_objcObserver addNotificationObservers];
[m_session startRunning];
}
@@ -161,6 +185,7 @@
if (!m_session || ![m_session isRunning])
return;
+ [m_objcObserver removeNotificationObservers];
[m_session stopRunning];
}
@@ -223,7 +248,7 @@
return;
m_session = adoptNS([allocAVCaptureSessionInstance() init]);
- for (NSString *keyName in sessionKVOProperties())
+ for (NSString* keyName in sessionKVOProperties())
[m_session addObserver:m_objcObserver.get() forKeyPath:keyName options:NSKeyValueObservingOptionNew context:(void *)nil];
[m_session beginConfiguration];
@@ -253,6 +278,35 @@
});
}
+#if PLATFORM(IOS)
+void AVMediaCaptureSource::captureSessionRuntimeError(RetainPtr<NSError> error)
+{
+ if (!m_isRunning || error.get().code != AVErrorMediaServicesWereReset)
+ return;
+
+ // Try to restart the session, but reset m_isRunning immediately so if it fails we won't try again.
+ [m_session startRunning];
+ m_isRunning = [m_session isRunning];
+}
+
+void AVMediaCaptureSource::captureSessionBeginInterruption(RetainPtr<NSNotification> notification)
+{
+ m_interruption = static_cast<AVMediaCaptureSource::InterruptionReason>([notification.get().userInfo[AVCaptureSessionInterruptionReasonKey] integerValue]);
+}
+
+void AVMediaCaptureSource::captureSessionEndInterruption(RetainPtr<NSNotification>)
+{
+ InterruptionReason reason = m_interruption;
+
+ m_interruption = InterruptionReason::None;
+ if (reason != InterruptionReason::VideoNotAllowedInSideBySide || m_isRunning)
+ return;
+
+ [m_session startRunning];
+ m_isRunning = [m_session isRunning];
+}
+#endif
+
void AVMediaCaptureSource::setVideoSampleBufferDelegate(AVCaptureVideoDataOutputType* videoOutput)
{
[videoOutput setSampleBufferDelegate:m_objcObserver.get() queue:globaVideoCaptureSerialQueue()];
@@ -269,7 +323,7 @@
return nullptr;
}
-NSArray* sessionKVOProperties()
+NSArray<NSString*>* sessionKVOProperties()
{
static NSArray* keys = [@[@"running"] retain];
return keys;
@@ -286,6 +340,7 @@
return nil;
m_callback = callback;
+
return self;
}
@@ -293,10 +348,33 @@
{
[NSObject cancelPreviousPerformRequestsWithTarget:self];
m_callback = 0;
+ [self removeNotificationObservers];
}
-- (void)captureOutput:(AVCaptureOutputType *)captureOutput didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer fromConnection:(AVCaptureConnectionType *)connection
+- (void)addNotificationObservers
{
+#if PLATFORM(IOS)
+ ASSERT(m_callback);
+
+ NSNotificationCenter* center = [NSNotificationCenter defaultCenter];
+ AVCaptureSessionType* session = m_callback->session();
+
+ [center addObserver:self selector:@selector(sessionRuntimeError:) name:AVCaptureSessionRuntimeErrorNotification object:session];
+ [center addObserver:self selector:@selector(beginSessionInterrupted:) name:AVCaptureSessionWasInterruptedNotification object:session];
+ [center addObserver:self selector:@selector(endSessionInterrupted:) name:AVCaptureSessionInterruptionEndedNotification object:session];
+#endif
+}
+
+- (void)removeNotificationObservers
+{
+#if PLATFORM(IOS)
+ ASSERT(m_callback);
+ [[NSNotificationCenter defaultCenter] removeObserver:m_callback->session()];
+#endif
+}
+
+- (void)captureOutput:(AVCaptureOutputType*)captureOutput didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer fromConnection:(AVCaptureConnectionType*)connection
+{
if (!m_callback)
return;
@@ -303,7 +381,7 @@
m_callback->captureOutputDidOutputSampleBufferFromConnection(captureOutput, sampleBuffer, connection);
}
--(void)observeValueForKeyPath:keyPath ofObject:(id)object change:(NSDictionary *)change context:(void*)context
+- (void)observeValueForKeyPath:keyPath ofObject:(id)object change:(NSDictionary*)change context:(void*)context
{
UNUSED_PARAM(object);
UNUSED_PARAM(context);
@@ -328,6 +406,33 @@
m_callback->captureSessionIsRunningDidChange([newValue boolValue]);
}
+#if PLATFORM(IOS)
+- (void)sessionRuntimeError:(NSNotification*)notification
+{
+ NSError *error = notification.userInfo[AVCaptureSessionErrorKey];
+ LOG(Media, "WebCoreAVMediaCaptureSourceObserver::sessionRuntimeError(%p) - error = %s", self, [[error localizedDescription] UTF8String]);
+
+ if (m_callback)
+ m_callback->captureSessionRuntimeError(error);
+}
+
+-(void)beginSessionInterrupted:(NSNotification*)notification
+{
+ LOG(Media, "WebCoreAVMediaCaptureSourceObserver::beginSessionInterrupted(%p) - reason = %d", self, [notification.userInfo[AVCaptureSessionInterruptionReasonKey] integerValue]);
+
+ if (m_callback)
+ m_callback->captureSessionBeginInterruption(notification);
+}
+
+- (void)endSessionInterrupted:(NSNotification*)notification
+{
+ LOG(Media, "WebCoreAVMediaCaptureSourceObserver::endSessionInterrupted(%p) ", self);
+
+ if (m_callback)
+ m_callback->captureSessionEndInterruption(notification);
+}
+#endif
+
@end
#endif // ENABLE(MEDIA_STREAM)
Modified: trunk/Source/WebCore/platform/mediastream/mac/AVVideoCaptureSource.mm (212843 => 212844)
--- trunk/Source/WebCore/platform/mediastream/mac/AVVideoCaptureSource.mm 2017-02-22 19:33:02 UTC (rev 212843)
+++ trunk/Source/WebCore/platform/mediastream/mac/AVVideoCaptureSource.mm 2017-02-22 20:06:57 UTC (rev 212844)
@@ -84,12 +84,12 @@
#define AVCaptureVideoPreviewLayer getAVCaptureVideoPreviewLayerClass()
#define AVFrameRateRange getAVFrameRateRangeClass()
-SOFT_LINK_POINTER(AVFoundation, AVCaptureSessionPreset1280x720, NSString *)
-SOFT_LINK_POINTER(AVFoundation, AVCaptureSessionPreset960x540, NSString *)
-SOFT_LINK_POINTER(AVFoundation, AVCaptureSessionPreset640x480, NSString *)
-SOFT_LINK_POINTER(AVFoundation, AVCaptureSessionPreset352x288, NSString *)
-SOFT_LINK_POINTER(AVFoundation, AVCaptureSessionPreset320x240, NSString *)
-SOFT_LINK_POINTER(AVFoundation, AVCaptureSessionPresetLow, NSString *)
+SOFT_LINK_POINTER_OPTIONAL(AVFoundation, AVCaptureSessionPreset1280x720, NSString *)
+SOFT_LINK_POINTER_OPTIONAL(AVFoundation, AVCaptureSessionPreset960x540, NSString *)
+SOFT_LINK_POINTER_OPTIONAL(AVFoundation, AVCaptureSessionPreset640x480, NSString *)
+SOFT_LINK_POINTER_OPTIONAL(AVFoundation, AVCaptureSessionPreset352x288, NSString *)
+SOFT_LINK_POINTER_OPTIONAL(AVFoundation, AVCaptureSessionPreset320x240, NSString *)
+SOFT_LINK_POINTER_OPTIONAL(AVFoundation, AVCaptureSessionPresetLow, NSString *)
#define AVCaptureSessionPreset1280x720 getAVCaptureSessionPreset1280x720()
#define AVCaptureSessionPreset960x540 getAVCaptureSessionPreset960x540()
@@ -164,27 +164,27 @@
highestFrameRateRange = std::max<Float64>(highestFrameRateRange, range.maxFrameRate);
}
- if ([videoDevice supportsAVCaptureSessionPreset:AVCaptureSessionPreset1280x720]) {
+ if (AVCaptureSessionPreset1280x720 && [videoDevice supportsAVCaptureSessionPreset:AVCaptureSessionPreset1280x720]) {
updateSizeMinMax(minimumWidth, maximumWidth, 1280);
updateSizeMinMax(minimumHeight, maximumHeight, 720);
updateAspectRatioMinMax(minimumAspectRatio, maximumAspectRatio, 1280.0 / 720);
}
- if ([videoDevice supportsAVCaptureSessionPreset:AVCaptureSessionPreset960x540]) {
+ if (AVCaptureSessionPreset960x540 && [videoDevice supportsAVCaptureSessionPreset:AVCaptureSessionPreset960x540]) {
updateSizeMinMax(minimumWidth, maximumWidth, 960);
updateSizeMinMax(minimumHeight, maximumHeight, 540);
updateAspectRatioMinMax(minimumAspectRatio, maximumAspectRatio, 960 / 540);
}
- if ([videoDevice supportsAVCaptureSessionPreset:AVCaptureSessionPreset640x480]) {
+ if (AVCaptureSessionPreset640x480 && [videoDevice supportsAVCaptureSessionPreset:AVCaptureSessionPreset640x480]) {
updateSizeMinMax(minimumWidth, maximumWidth, 640);
updateSizeMinMax(minimumHeight, maximumHeight, 480);
updateAspectRatioMinMax(minimumAspectRatio, maximumAspectRatio, 640 / 480);
}
- if ([videoDevice supportsAVCaptureSessionPreset:AVCaptureSessionPreset352x288]) {
+ if (AVCaptureSessionPreset352x288 && [videoDevice supportsAVCaptureSessionPreset:AVCaptureSessionPreset352x288]) {
updateSizeMinMax(minimumWidth, maximumWidth, 352);
updateSizeMinMax(minimumHeight, maximumHeight, 288);
updateAspectRatioMinMax(minimumAspectRatio, maximumAspectRatio, 352 / 288);
}
- if ([videoDevice supportsAVCaptureSessionPreset:AVCaptureSessionPreset320x240]) {
+ if (AVCaptureSessionPreset320x240 && [videoDevice supportsAVCaptureSessionPreset:AVCaptureSessionPreset320x240]) {
updateSizeMinMax(minimumWidth, maximumWidth, 320);
updateSizeMinMax(minimumHeight, maximumHeight, 240);
updateAspectRatioMinMax(minimumAspectRatio, maximumAspectRatio, 320 / 240);
@@ -239,19 +239,19 @@
if (!preset)
return { };
- if ([preset isEqualToString:AVCaptureSessionPreset1280x720])
+ if (AVCaptureSessionPreset1280x720 && [preset isEqualToString:AVCaptureSessionPreset1280x720])
return { 1280, 720 };
- if ([preset isEqualToString:AVCaptureSessionPreset960x540])
+ if (AVCaptureSessionPreset960x540 && [preset isEqualToString:AVCaptureSessionPreset960x540])
return { 960, 540 };
- if ([preset isEqualToString:AVCaptureSessionPreset640x480])
+ if (AVCaptureSessionPreset640x480 && [preset isEqualToString:AVCaptureSessionPreset640x480])
return { 640, 480 };
- if ([preset isEqualToString:AVCaptureSessionPreset352x288])
+ if (AVCaptureSessionPreset352x288 && [preset isEqualToString:AVCaptureSessionPreset352x288])
return { 352, 288 };
- if ([preset isEqualToString:AVCaptureSessionPreset320x240])
+ if (AVCaptureSessionPreset320x240 && [preset isEqualToString:AVCaptureSessionPreset320x240])
return { 320, 240 };
return { };
@@ -495,19 +495,19 @@
return nil;
AVCaptureDeviceTypedef *videoDevice = device();
- if ((!width || width.value() == 1280) && (!height || height.value() == 720))
+ if ((!width || width.value() == 1280) && (!height || height.value() == 720) && AVCaptureSessionPreset1280x720)
return [videoDevice supportsAVCaptureSessionPreset:AVCaptureSessionPreset1280x720] ? AVCaptureSessionPreset1280x720 : nil;
- if ((!width || width.value() == 960) && (!height || height.value() == 540 ))
+ if ((!width || width.value() == 960) && (!height || height.value() == 540) && AVCaptureSessionPreset960x540)
return [videoDevice supportsAVCaptureSessionPreset:AVCaptureSessionPreset960x540] ? AVCaptureSessionPreset960x540 : nil;
- if ((!width || width.value() == 640) && (!height || height.value() == 480 ))
+ if ((!width || width.value() == 640) && (!height || height.value() == 480 ) && AVCaptureSessionPreset640x480)
return [videoDevice supportsAVCaptureSessionPreset:AVCaptureSessionPreset640x480] ? AVCaptureSessionPreset640x480 : nil;
- if ((!width || width.value() == 352) && (!height || height.value() == 288 ))
+ if ((!width || width.value() == 352) && (!height || height.value() == 288 ) && AVCaptureSessionPreset352x288)
return [videoDevice supportsAVCaptureSessionPreset:AVCaptureSessionPreset352x288] ? AVCaptureSessionPreset352x288 : nil;
- if ((!width || width.value() == 320) && (!height || height.value() == 240 ))
+ if ((!width || width.value() == 320) && (!height || height.value() == 240 ) && AVCaptureSessionPreset320x240)
return [videoDevice supportsAVCaptureSessionPreset:AVCaptureSessionPreset320x240] ? AVCaptureSessionPreset320x240 : nil;
return nil;