[FFmpeg-devel] [PATCH] avdevice/avfoundation: fix macOS/iOS/tvOS SDK conditional checks

Marvin Scholz epirat07 at gmail.com
Wed Apr 17 18:12:34 EEST 2024


This fixes the checks to properly use runtime feature detection and
check the SDK version (*_MAX_ALLOWED) instead of the targeted version
for the relevant APIs.

The target is still checked (*_MIN_REQUIRED) to avoid using deprecated
methods when targeting new enough versions.
---
 libavdevice/avfoundation.m | 164 ++++++++++++++++++++++++++-----------
 1 file changed, 116 insertions(+), 48 deletions(-)

diff --git a/libavdevice/avfoundation.m b/libavdevice/avfoundation.m
index e558ad7d90..a52e7df37b 100644
--- a/libavdevice/avfoundation.m
+++ b/libavdevice/avfoundation.m
@@ -28,6 +28,7 @@
 #import <AVFoundation/AVFoundation.h>
 #include <pthread.h>
 
+#include "libavutil/avassert.h"
 #include "libavutil/channel_layout.h"
 #include "libavutil/mem.h"
 #include "libavutil/pixdesc.h"
@@ -764,57 +765,124 @@ static int get_audio_config(AVFormatContext *s)
 }
 
 static NSArray* getDevicesWithMediaType(AVMediaType mediaType) {
-#if ((TARGET_OS_IPHONE && __IPHONE_OS_VERSION_MIN_REQUIRED >= 100000) || (TARGET_OS_OSX && __MAC_OS_X_VERSION_MIN_REQUIRED >= 101500))
-    NSMutableArray *deviceTypes = nil;
-    if (mediaType == AVMediaTypeVideo) {
-        deviceTypes = [NSMutableArray arrayWithArray:@[AVCaptureDeviceTypeBuiltInWideAngleCamera]];
-        #if (TARGET_OS_IPHONE && __IPHONE_OS_VERSION_MIN_REQUIRED >= 100000)
-            [deviceTypes addObject: AVCaptureDeviceTypeBuiltInDualCamera];
-            [deviceTypes addObject: AVCaptureDeviceTypeBuiltInTelephotoCamera];
-        #endif
-        #if (TARGET_OS_IPHONE && __IPHONE_OS_VERSION_MIN_REQUIRED >= 110100)
-            [deviceTypes addObject: AVCaptureDeviceTypeBuiltInTrueDepthCamera];
-        #endif
-        #if (TARGET_OS_IPHONE && __IPHONE_OS_VERSION_MIN_REQUIRED >= 130000)
-            [deviceTypes addObject: AVCaptureDeviceTypeBuiltInTripleCamera];
-            [deviceTypes addObject: AVCaptureDeviceTypeBuiltInDualWideCamera];
-            [deviceTypes addObject: AVCaptureDeviceTypeBuiltInUltraWideCamera];
-        #endif
-        #if (TARGET_OS_OSX && __MAC_OS_X_VERSION_MIN_REQUIRED >= 130000)
-            [deviceTypes addObject: AVCaptureDeviceTypeDeskViewCamera];
-        #endif
-        #if (TARGET_OS_IPHONE && __IPHONE_OS_VERSION_MIN_REQUIRED >= 150400)
-            [deviceTypes addObject: AVCaptureDeviceTypeBuiltInLiDARDepthCamera];
-        #endif
-        #if (TARGET_OS_IPHONE && __IPHONE_OS_VERSION_MIN_REQUIRED >= 170000 || (TARGET_OS_OSX && __MAC_OS_X_VERSION_MIN_REQUIRED >= 140000))
-            [deviceTypes addObject: AVCaptureDeviceTypeContinuityCamera];
-        #endif
-    } else if (mediaType == AVMediaTypeAudio) {
-        #if (TARGET_OS_IPHONE && __IPHONE_OS_VERSION_MIN_REQUIRED >= 170000 || (TARGET_OS_OSX && __MAC_OS_X_VERSION_MIN_REQUIRED >= 140000))
-            deviceTypes = [NSMutableArray arrayWithArray:@[AVCaptureDeviceTypeMicrophone]];
-        #else
-            deviceTypes = [NSMutableArray arrayWithArray:@[AVCaptureDeviceTypeBuiltInMicrophone]];
-        #endif
-    } else if (mediaType == AVMediaTypeMuxed) {
-        #if (TARGET_OS_IPHONE && __IPHONE_OS_VERSION_MIN_REQUIRED >= 170000 || (TARGET_OS_OSX && __MAC_OS_X_VERSION_MIN_REQUIRED >= 140000))
-            deviceTypes = [NSMutableArray arrayWithArray:@[AVCaptureDeviceTypeExternal]];
-        #elif (TARGET_OS_OSX && __MAC_OS_X_VERSION_MIN_REQUIRED < 140000)
-            deviceTypes = [NSMutableArray arrayWithArray:@[AVCaptureDeviceTypeExternalUnknown]];
-        #else
+
+#if (TARGET_OS_OSX    && defined(__MAC_10_15)   && MAC_OS_X_VERSION_MAX_ALLOWED    >= __MAC_10_15) || \
+    (TARGET_OS_IOS    && defined(__IPHONE_10_0) && __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_10_0) || \
+    (TARGET_OS_TV     && defined(__TVOS_17_0)   && __TV_OS_VERSION_MAX_ALLOWED     >= __TVOS_17_0)
+    if (__builtin_available(macOS 10.15, iOS 10, tvOS 17, *)) {
+
+        NSMutableArray *deviceTypes = nil;
+
+        if (mediaType == AVMediaTypeVideo) {
+            deviceTypes = [NSMutableArray arrayWithArray:@[AVCaptureDeviceTypeBuiltInWideAngleCamera]];
+
+            #if (TARGET_OS_IOS || TARGET_OS_TV)
+                // Devices only available on iOS/tvOS
+                [deviceTypes addObject: AVCaptureDeviceTypeBuiltInDualCamera];
+                [deviceTypes addObject: AVCaptureDeviceTypeBuiltInTelephotoCamera];
+
+                #if (TARGET_OS_IOS && defined(__IPHONE_11_1) && __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_11_1) || \
+                    (TARGET_OS_TV  && defined(__TVOS_17_0)   && __TV_OS_VERSION_MAX_ALLOWED     >= __TVOS_17_0)
+                    if (__builtin_available(iOS 11.1, tvOS 17, *)) {
+                        [deviceTypes addObject: AVCaptureDeviceTypeBuiltInTrueDepthCamera];
+                    }
+                #endif
+
+                #if (TARGET_OS_IOS && defined(__IPHONE_13_0) && __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_13_0) || \
+                    (TARGET_OS_TV  && defined(__TVOS_17_0)   && __TV_OS_VERSION_MAX_ALLOWED     >= __TVOS_17_0)
+                    if (__builtin_available(iOS 13.0, tvOS 17, *)) {
+                        [deviceTypes addObject: AVCaptureDeviceTypeBuiltInTripleCamera];
+                        [deviceTypes addObject: AVCaptureDeviceTypeBuiltInDualWideCamera];
+                        [deviceTypes addObject: AVCaptureDeviceTypeBuiltInUltraWideCamera];
+                    }
+                #endif
+
+                #if (TARGET_OS_IOS && defined(__IPHONE_15_4) && __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_15_4) || \
+                    (TARGET_OS_TV  && defined(__TVOS_17_0)   && __TV_OS_VERSION_MAX_ALLOWED     >= __TVOS_17_0)
+                    if (__builtin_available(iOS 15.4, tvOS 17, *)) {
+                        [deviceTypes addObject: AVCaptureDeviceTypeBuiltInLiDARDepthCamera];
+                    }
+                #endif
+            #endif
+
+            #if (TARGET_OS_OSX    && defined(__MAC_13_0)   && MAC_OS_X_VERSION_MAX_ALLOWED    >= __MAC_13_0)
+                if (__builtin_available(macOS 13.0, *)) {
+                    [deviceTypes addObject: AVCaptureDeviceTypeDeskViewCamera];
+                }
+            #endif
+
+            #if (TARGET_OS_OSX    && defined(__MAC_14_0)    && MAC_OS_X_VERSION_MAX_ALLOWED    >= __MAC_14_0) || \
+                (TARGET_OS_IOS    && defined(__IPHONE_17_0) && __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_17_0) || \
+                (TARGET_OS_TV     && defined(__TVOS_17_0)   && __TV_OS_VERSION_MAX_ALLOWED     >= __TVOS_17_0)
+                if (__builtin_available(macOS 14.0, iOS 17, tvOS 17, *)) {
+                    [deviceTypes addObject: AVCaptureDeviceTypeContinuityCamera];
+                }
+            #endif
+
+        } else if (mediaType == AVMediaTypeAudio) {
+            #if (TARGET_OS_OSX    && defined(__MAC_14_0)    && MAC_OS_X_VERSION_MAX_ALLOWED    >= __MAC_14_0) || \
+                (TARGET_OS_IOS    && defined(__IPHONE_17_0) && __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_17_0) || \
+                (TARGET_OS_TV     && defined(__TVOS_17_0)   && __TV_OS_VERSION_MAX_ALLOWED     >= __TVOS_17_0)
+                if (__builtin_available(macOS 14.0, iOS 17, tvOS 17, *)) {
+                    deviceTypes = [NSMutableArray arrayWithArray:@[AVCaptureDeviceTypeMicrophone]];
+                } else
+            #endif
+                {
+                    #if (TARGET_OS_OSX    && defined(__MAC_14_0)    && __MAC_OS_X_VERSION_MIN_REQUIRED    >= __MAC_14_0) || \
+                        (TARGET_OS_IOS    && defined(__IPHONE_17_0) && __IPHONE_OS_VERSION_MIN_REQUIRED   >= __IPHONE_17_0) || \
+                        (TARGET_OS_TV     && defined(__TVOS_17_0)   && __TV_OS_VERSION_MIN_REQUIRED       >= __TVOS_17_0)
+                            /* If the targeted macOS is new enough, this fallback case can never be reached, so do not
+                             * use a deprecated API to avoid compiler warnings.
+                             */
+                            av_assert0(!"Unreachable reached!");
+                    #else
+                            deviceTypes = [NSMutableArray arrayWithArray:@[AVCaptureDeviceTypeBuiltInMicrophone]];
+                    #endif
+                }
+        } else if (mediaType == AVMediaTypeMuxed) {
+            #if (TARGET_OS_OSX    && defined(__MAC_14_0)    && MAC_OS_X_VERSION_MAX_ALLOWED    >= __MAC_14_0) || \
+                (TARGET_OS_IOS    && defined(__IPHONE_17_0) && __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_17_0) || \
+                (TARGET_OS_TV     && defined(__TVOS_17_0)   && __TV_OS_VERSION_MAX_ALLOWED     >= __TVOS_17_0)
+                if (__builtin_available(macOS 14.0, iOS 17, tvOS 17, *)) {
+                    deviceTypes = [NSMutableArray arrayWithArray:@[AVCaptureDeviceTypeExternal]];
+                } else
+            #endif
+            #if (TARGET_OS_OSX && defined(__MAC_14_0)    && __MAC_OS_X_VERSION_MIN_REQUIRED    < __MAC_14_0)
+                // macOS 10.15+ already guaranteed here by previous check
+                {
+                    deviceTypes = [NSMutableArray arrayWithArray:@[AVCaptureDeviceTypeExternalUnknown]];
+                }
+            #else
+                {
+                    return nil;
+                }
+            #endif
+        } else {
             return nil;
-        #endif
-    } else {
-        return nil;
-    }
+        }
+
+        AVCaptureDeviceDiscoverySession *captureDeviceDiscoverySession =
+            [AVCaptureDeviceDiscoverySession
+            discoverySessionWithDeviceTypes:deviceTypes
+                                  mediaType:mediaType
+                                   position:AVCaptureDevicePositionUnspecified];
+        return [captureDeviceDiscoverySession devices];
+    } else
+#endif
 
-    AVCaptureDeviceDiscoverySession *captureDeviceDiscoverySession =
-        [AVCaptureDeviceDiscoverySession
-        discoverySessionWithDeviceTypes:deviceTypes
-                              mediaType:mediaType
-                               position:AVCaptureDevicePositionUnspecified];
-    return [captureDeviceDiscoverySession devices];
+#if (TARGET_OS_OSX    && defined(__MAC_10_15)   && __MAC_OS_X_VERSION_MIN_REQUIRED    >= __MAC_10_15) || \
+    (TARGET_OS_IOS    && defined(__IPHONE_10_0) && __IPHONE_OS_VERSION_MIN_REQUIRED   >= __IPHONE_10_0) || \
+    (TARGET_OS_TV     && defined(__TVOS_17_0)   && __TV_OS_VERSION_MIN_REQUIRED       >= __TVOS_17_0)
+    {
+        /* If the targeted macOS is new enough, this fallback case can never be reached, so do not
+         * use a deprecated API to avoid compiler warnings.
+         */
+        av_assert0(!"Unreachable reached!");
+    }
 #else
-    return [AVCaptureDevice devicesWithMediaType:mediaType];
+    {
+        return [AVCaptureDevice devicesWithMediaType:mediaType];
+    }
 #endif
 }
 

base-commit: 257bc2a82ab6709ddfc8dd9cf570beefcef7d43f
-- 
2.39.3 (Apple Git-145)


More information about the ffmpeg-devel mailing list