summaryrefslogtreecommitdiffstats
path: root/src/plugins/avfoundation/camera/avfcamerautility.mm
diff options
context:
space:
mode:
Diffstat (limited to 'src/plugins/avfoundation/camera/avfcamerautility.mm')
-rw-r--r--src/plugins/avfoundation/camera/avfcamerautility.mm183
1 files changed, 181 insertions, 2 deletions
diff --git a/src/plugins/avfoundation/camera/avfcamerautility.mm b/src/plugins/avfoundation/camera/avfcamerautility.mm
index 3668bb124..0caf07f07 100644
--- a/src/plugins/avfoundation/camera/avfcamerautility.mm
+++ b/src/plugins/avfoundation/camera/avfcamerautility.mm
@@ -171,8 +171,7 @@ QVector<AVCaptureDeviceFormat *> qt_unique_device_formats(AVCaptureDevice *captu
QSize qt_device_format_resolution(AVCaptureDeviceFormat *format)
{
- Q_ASSERT(format);
- if (!format.formatDescription)
+ if (!format || !format.formatDescription)
return QSize();
const CMVideoDimensions res = CMVideoFormatDescriptionGetDimensions(format.formatDescription);
@@ -383,4 +382,184 @@ AVFrameRateRange *qt_find_supported_framerate_range(AVCaptureDeviceFormat *forma
#endif // SDK
+void qt_set_framerate_limits(AVCaptureConnection *videoConnection, qreal minFPS, qreal maxFPS)
+{
+ Q_ASSERT(videoConnection);
+
+ if (minFPS < 0. || maxFPS < 0. || (maxFPS && maxFPS < minFPS)) {
+ qDebugCamera() << Q_FUNC_INFO << "invalid framerates (min, max):"
+ << minFPS << maxFPS;
+ return;
+ }
+
+ CMTime minDuration = kCMTimeInvalid;
+ if (maxFPS > 0.) {
+ if (!videoConnection.supportsVideoMinFrameDuration)
+ qDebugCamera() << Q_FUNC_INFO << "maximum framerate is not supported";
+ else
+ minDuration = CMTimeMake(1, maxFPS);
+ }
+ if (videoConnection.supportsVideoMinFrameDuration)
+ videoConnection.videoMinFrameDuration = minDuration;
+
+#if QT_MAC_PLATFORM_SDK_EQUAL_OR_ABOVE(__MAC_10_9, __IPHONE_5_0)
+#if QT_OSX_DEPLOYMENT_TARGET_BELOW(__MAC_10_9)
+ if (QSysInfo::MacintoshVersion < QSysInfo::MV_10_9) {
+ if (minFPS > 0.)
+ qDebugCamera() << Q_FUNC_INFO << "minimum framerate is not supported";
+ } else
+#endif
+ {
+ CMTime maxDuration = kCMTimeInvalid;
+ if (minFPS > 0.) {
+ if (!videoConnection.supportsVideoMaxFrameDuration)
+ qDebugCamera() << Q_FUNC_INFO << "minimum framerate is not supported";
+ else
+ maxDuration = CMTimeMake(1, minFPS);
+ }
+ if (videoConnection.supportsVideoMaxFrameDuration)
+ videoConnection.videoMaxFrameDuration = maxDuration;
+ }
+#else
+ if (minFPS > 0.)
+ qDebugCamera() << Q_FUNC_INFO << "minimum framerate is not supported";
+#endif
+}
+
+#if QT_MAC_PLATFORM_SDK_EQUAL_OR_ABOVE(__MAC_10_7, __IPHONE_7_0)
+
+CMTime qt_adjusted_frame_duration(AVFrameRateRange *range, qreal fps)
+{
+ Q_ASSERT(range);
+ Q_ASSERT(fps > 0.);
+
+ if (range.maxFrameRate - range.minFrameRate < 0.1) {
+ // Can happen on OS X.
+ return range.minFrameDuration;
+ }
+
+ if (fps <= range.minFrameRate)
+ return range.maxFrameDuration;
+ if (fps >= range.maxFrameRate)
+ return range.minFrameDuration;
+
+ int n, d;
+ qt_real_to_fraction(1. / fps, &n, &d);
+ return CMTimeMake(n, d);
+}
+
+void qt_set_framerate_limits(AVCaptureDevice *captureDevice, qreal minFPS, qreal maxFPS)
+{
+ Q_ASSERT(captureDevice);
+ if (!captureDevice.activeFormat) {
+ qDebugCamera() << Q_FUNC_INFO << "no active capture device format";
+ return;
+ }
+
+ if (minFPS < 0. || maxFPS < 0. || (maxFPS && maxFPS < minFPS)) {
+ qDebugCamera() << Q_FUNC_INFO << "invalid framerates (min, max):"
+ << minFPS << maxFPS;
+ return;
+ }
+
+ CMTime minFrameDuration = kCMTimeInvalid;
+ CMTime maxFrameDuration = kCMTimeInvalid;
+ if (maxFPS || minFPS) {
+ AVFrameRateRange *range = qt_find_supported_framerate_range(captureDevice.activeFormat,
+ maxFPS ? maxFPS : minFPS);
+ if (!range) {
+ qDebugCamera() << Q_FUNC_INFO << "no framerate range found, (min, max):"
+ << minFPS << maxFPS;
+ return;
+ }
+
+ if (maxFPS)
+ minFrameDuration = qt_adjusted_frame_duration(range, maxFPS);
+ if (minFPS)
+ maxFrameDuration = qt_adjusted_frame_duration(range, minFPS);
+ }
+
+ const AVFConfigurationLock lock(captureDevice);
+ if (!lock) {
+ qDebugCamera() << Q_FUNC_INFO << "failed to lock for configuration";
+ return;
+ }
+
+ // While Apple's docs say kCMTimeInvalid will end in default
+ // settings for this format, kCMTimeInvalid on OS X ends with a runtime
+ // exception:
+ // "The activeVideoMinFrameDuration passed is not supported by the device."
+#ifdef Q_OS_IOS
+ [captureDevice setActiveVideoMinFrameDuration:minFrameDuration];
+ [captureDevice setActiveVideoMaxFrameDuration:maxFrameDuration];
+#else // Q_OS_OSX
+
+ if (CMTimeCompare(minFrameDuration, kCMTimeInvalid))
+ [captureDevice setActiveVideoMinFrameDuration:minFrameDuration];
+
+#if QT_OSX_PLATFORM_SDK_EQUAL_OR_ABOVE(__MAC_10_9)
+#if QT_OSX_DEPLOYMENT_TARGET_BELOW(__MAC_10_9)
+ if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_9)
+#endif
+ {
+ if (CMTimeCompare(maxFrameDuration, kCMTimeInvalid))
+ [captureDevice setActiveVideoMaxFrameDuration:maxFrameDuration];
+ }
+#endif // QT_OSX_PLATFORM_SDK_EQUAL_OR_ABOVE(__MAC_10_9)
+#endif // Q_OS_OSX
+}
+
+#endif // Platform SDK >= 10.9, >= 7.0.
+
+void qt_set_framerate_limits(AVCaptureDevice *captureDevice, AVCaptureConnection *videoConnection,
+ qreal minFPS, qreal maxFPS)
+{
+ Q_ASSERT(captureDevice);
+#if QT_MAC_PLATFORM_SDK_EQUAL_OR_ABOVE(__MAC_10_7, __IPHONE_7_0)
+ if (QSysInfo::MacintoshVersion >= qt_OS_limit(QSysInfo::MV_10_9, QSysInfo::MV_IOS_7_0))
+ qt_set_framerate_limits(captureDevice, minFPS, maxFPS);
+ else
+#endif
+ if (videoConnection)
+ qt_set_framerate_limits(videoConnection, minFPS, maxFPS);
+
+}
+
+AVFPSRange qt_current_framerates(AVCaptureDevice *captureDevice, AVCaptureConnection *videoConnection)
+{
+ Q_ASSERT(captureDevice);
+
+ AVFPSRange fps;
+#if QT_MAC_PLATFORM_SDK_EQUAL_OR_ABOVE(__MAC_10_7, __IPHONE_7_0)
+ if (QSysInfo::MacintoshVersion >= qt_OS_limit(QSysInfo::MV_10_7, QSysInfo::MV_IOS_7_0)) {
+ const CMTime minDuration = captureDevice.activeVideoMinFrameDuration;
+ if (CMTimeCompare(minDuration, kCMTimeInvalid)) {
+ if (const Float64 minSeconds = CMTimeGetSeconds(minDuration))
+ fps.second = 1. / minSeconds; // Max FPS = 1 / MinDuration.
+ }
+
+#if QT_OSX_PLATFORM_SDK_EQUAL_OR_ABOVE(__MAC_10_9)
+#if QT_OSX_DEPLOYMENT_TARGET_BELOW(__MAC_10_9)
+ if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_9)
+#endif
+ {
+ const CMTime maxDuration = captureDevice.activeVideoMaxFrameDuration;
+ if (CMTimeCompare(maxDuration, kCMTimeInvalid)) {
+ if (const Float64 maxSeconds = CMTimeGetSeconds(maxDuration))
+ fps.first = 1. / maxSeconds; // Min FPS = 1 / MaxDuration.
+ }
+ }
+#endif // QT_OSX_PLATFORM_SDK_EQUAL_OR_ABOVE(__MAC_10_9)
+
+ } else {
+#else // OSX < 10.7 or iOS < 7.0
+ {
+#endif // QT_MAC_PLATFORM_SDK_EQUAL_OR_ABOVE(__MAC_10_7, __IPHONE_7_0)
+ if (videoConnection)
+ fps = qt_connection_framerates(videoConnection);
+ }
+
+ return fps;
+}
+
QT_END_NAMESPACE