summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLauri Laanmets <lauri@laanmets.ee>2024-01-23 10:27:44 +0200
committerQt Cherry-pick Bot <cherrypick_bot@qt-project.org>2024-03-06 18:34:59 +0000
commit5da455d8f70080d4f2468da43899060f6d97daf3 (patch)
tree48666723a1f093b3d3326326200ae08d865357f5
parentc33e6f69b0ebe8c1f66bf454150273380fd96aaa (diff)
Support multi-lens (dual, triple) logical cameras on Apple devices
Use 'AVCaptureDeviceDiscoverySession' to discover all multi-lens camera types that automatically switch between lenses. Use [AVCaptureDevice defaultDeviceWithDeviceType] to try to find most "powerful" camera type as default. Pick-to: 6.6 6.5 6.2 Task-number: QTBUG-121422 Change-Id: I04aa9a64ee459359d117b928baaaf0970df7ce21 Reviewed-by: Artem Dyomin <artem.dyomin@qt.io> Reviewed-by: Timur Pocheptsov <timur.pocheptsov@qt.io> (cherry picked from commit 681b93eb85c5460d2415960c6fba21cb0281cd64) Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
-rw-r--r--src/plugins/multimedia/darwin/camera/qavfcamerabase.mm52
1 files changed, 49 insertions, 3 deletions
diff --git a/src/plugins/multimedia/darwin/camera/qavfcamerabase.mm b/src/plugins/multimedia/darwin/camera/qavfcamerabase.mm
index 15c79d544..9d99de0b9 100644
--- a/src/plugins/multimedia/darwin/camera/qavfcamerabase.mm
+++ b/src/plugins/multimedia/darwin/camera/qavfcamerabase.mm
@@ -8,6 +8,7 @@
#include "qavfhelpers_p.h"
#include <private/qplatformmediaintegration_p.h>
#include <QtCore/qset.h>
+#include <QtCore/qsystemdetection.h>
QT_USE_NAMESPACE
@@ -137,12 +138,57 @@ void QAVFVideoDevices::updateCameraDevices()
QList<QCameraDevice> cameras;
- AVCaptureDevice *defaultDevice = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
- NSArray *videoDevices = [AVCaptureDevice devicesWithMediaType:AVMediaTypeVideo];
+ // List of all capture device types that we want to discover. Seems that this is the
+ // only way to discover all types. This filter is mandatory and has no "unspecified"
+ // option like AVCaptureDevicePosition(Unspecified) has. Order of the list is important
+ // because discovered devices will be in the same order and we want the first one found
+ // to be our default device.
+ NSArray *discoveryDevices = @[
+#ifdef Q_OS_IOS
+ AVCaptureDeviceTypeBuiltInTripleCamera, // We always prefer triple camera.
+ AVCaptureDeviceTypeBuiltInDualCamera, // If triple is not available, we prefer
+ // dual with wide + tele lens.
+ AVCaptureDeviceTypeBuiltInDualWideCamera, // Dual with wide and ultrawide is still
+ // better than single.
+#endif
+ AVCaptureDeviceTypeBuiltInWideAngleCamera, // This is the most common single camera type.
+ // We prefer that over tele and ultra-wide.
+#ifdef Q_OS_IOS
+ AVCaptureDeviceTypeBuiltInTelephotoCamera, // Cannot imagine how, but if only tele and
+ // ultrawide are available, we prefer tele.
+ AVCaptureDeviceTypeBuiltInUltraWideCamera,
+#endif
+ ];
+
+#if QT_DARWIN_PLATFORM_SDK_EQUAL_OR_ABOVE(__MAC_14_0, __IPHONE_17_0, __TVOS_NA, __WATCHOS_NA)
+ if (@available(macOS 14, iOS 17, *)) {
+ discoveryDevices = [discoveryDevices arrayByAddingObjectsFromArray: @[
+ AVCaptureDeviceTypeExternal,
+ AVCaptureDeviceTypeContinuityCamera
+ ]];
+ } else
+#endif
+ {
+#ifdef Q_OS_MACOS
+ QT_WARNING_PUSH
+ QT_WARNING_DISABLE_DEPRECATED
+ discoveryDevices = [discoveryDevices arrayByAddingObjectsFromArray: @[
+ AVCaptureDeviceTypeExternalUnknown
+ ]];
+ QT_WARNING_POP
+#endif
+ }
+ // Create discovery session to discover all possible camera types of the system.
+ // Both "hard" and "soft" types.
+ AVCaptureDeviceDiscoverySession *discoverySession = [AVCaptureDeviceDiscoverySession
+ discoverySessionWithDeviceTypes:discoveryDevices
+ mediaType:AVMediaTypeVideo
+ position:AVCaptureDevicePositionUnspecified];
+ NSArray<AVCaptureDevice *> *videoDevices = discoverySession.devices;
for (AVCaptureDevice *device in videoDevices) {
auto info = std::make_unique<QCameraDevicePrivate>();
- if (defaultDevice && [defaultDevice.uniqueID isEqualToString:device.uniqueID])
+ if ([videoDevices[0].uniqueID isEqualToString:device.uniqueID])
info->isDefault = true;
info->id = QByteArray([[device uniqueID] UTF8String]);
info->description = QString::fromNSString([device localizedName]);