feat: Add support for LiDAR, TrueDepth, External (USB) and Continuity Camera Devices (iOS 17) (#1824)
* feat: Add support for LiDAR, TrueDepth, External (USB) and Continuity Camera Devices (iOS 17) * Rename `devices` -> `physicalDevices` * fix: Comment out iOS 17 cameras for now * fix: Move `supportsDepthCapture` to `format` * fix: Fall back to `wide-angle-camera` for any unknown types * Update CameraPage.tsx * `descriptor` -> `physicalDeviceDescriptor` * Update CameraDevice.ts * Format * feat: Expose `userPreferredCameraDevice` Uses the new iOS 17 API where the user can prefer a default device, otherwise fall back to the first device of the available ones * fix: Expose as property * Add TODO comments * fix: Format code * fix: Compile below Swift 5.9
This commit is contained in:
parent
8864866f80
commit
cf4882b152
1
.github/ISSUE_TEMPLATE/BUG_REPORT.yml
vendored
1
.github/ISSUE_TEMPLATE/BUG_REPORT.yml
vendored
@ -85,7 +85,6 @@ body:
|
||||
"maxZoom": 123.75,
|
||||
"name": "Back Dual Wide Camera",
|
||||
"position": "back",
|
||||
"supportsDepthCapture": false,
|
||||
"supportsFocus": true,
|
||||
"supportsLowLightBoost": false,
|
||||
"supportsParallelVideoProcessing": true,
|
||||
|
@ -73,7 +73,15 @@ class CameraDevicesManager(private val reactContext: ReactApplicationContext) :
|
||||
|
||||
override fun hasConstants(): Boolean = true
|
||||
|
||||
override fun getConstants(): MutableMap<String, Any> = mutableMapOf("availableCameraDevices" to getDevicesJson())
|
||||
override fun getConstants(): MutableMap<String, Any?> {
|
||||
val devices = getDevicesJson()
|
||||
val preferredDevice = if (devices.size() > 0) devices.getMap(0) else null
|
||||
|
||||
return mutableMapOf(
|
||||
"availableCameraDevices" to devices,
|
||||
"userPreferredCameraDevice" to preferredDevice
|
||||
)
|
||||
}
|
||||
|
||||
// Required for NativeEventEmitter, this is just a dummy implementation:
|
||||
@ReactMethod
|
||||
|
@ -183,6 +183,7 @@ class CameraDeviceDetails(private val cameraManager: CameraManager, private val
|
||||
map.putDouble("fieldOfView", getFieldOfView())
|
||||
map.putBoolean("supportsVideoHDR", supportsVideoHdr)
|
||||
map.putBoolean("supportsPhotoHDR", supportsPhotoHdr)
|
||||
map.putBoolean("supportsDepthCapture", supportsDepthCapture)
|
||||
map.putString("autoFocusSystem", "contrast-detection") // TODO: Is this wrong?
|
||||
map.putArray("videoStabilizationModes", createStabilizationModes())
|
||||
map.putArray("pixelFormats", createPixelFormats(videoSize))
|
||||
@ -192,14 +193,13 @@ class CameraDeviceDetails(private val cameraManager: CameraManager, private val
|
||||
fun toMap(): ReadableMap {
|
||||
val map = Arguments.createMap()
|
||||
map.putString("id", cameraId)
|
||||
map.putArray("devices", getDeviceTypes())
|
||||
map.putArray("physicalDevices", getDeviceTypes())
|
||||
map.putString("position", lensFacing.unionValue)
|
||||
map.putString("name", name)
|
||||
map.putBoolean("hasFlash", hasFlash)
|
||||
map.putBoolean("hasTorch", hasFlash)
|
||||
map.putBoolean("isMultiCam", isMultiCam)
|
||||
map.putBoolean("supportsRawCapture", supportsRawCapture)
|
||||
map.putBoolean("supportsDepthCapture", supportsDepthCapture)
|
||||
map.putBoolean("supportsLowLightBoost", supportsLowLightBoost)
|
||||
map.putBoolean("supportsFocus", true) // I believe every device here supports focussing
|
||||
map.putDouble("minZoom", minZoom)
|
||||
|
@ -216,7 +216,7 @@ export function CameraPage({ navigation }: Props): React.ReactElement {
|
||||
)}
|
||||
{supports60Fps && (
|
||||
<PressableOpacity style={styles.button} onPress={() => setTargetFps((t) => (t === 30 ? 60 : 30))}>
|
||||
<Text style={styles.text}>{`${targetFps} FPS`}</Text>
|
||||
<Text style={styles.text}>{`${targetFps}\nFPS`}</Text>
|
||||
</PressableOpacity>
|
||||
)}
|
||||
{supportsHdr && (
|
||||
|
@ -37,47 +37,55 @@ class CameraDevicesManager: RCTEventEmitter {
|
||||
}
|
||||
|
||||
override func constantsToExport() -> [AnyHashable: Any]! {
|
||||
let devices = getDevicesJson()
|
||||
let preferredDevice: [String: Any]
|
||||
// TODO: Remove this #if once Xcode 15 is rolled out
|
||||
#if swift(>=5.9)
|
||||
if #available(iOS 17.0, *),
|
||||
let userPreferred = AVCaptureDevice.userPreferredCamera {
|
||||
preferredDevice = userPreferred.toDictionary()
|
||||
} else {
|
||||
preferredDevice = devices[0]
|
||||
}
|
||||
#else
|
||||
preferredDevice = devices[0]
|
||||
#endif
|
||||
|
||||
return [
|
||||
"availableCameraDevices": getDevicesJson(),
|
||||
"availableCameraDevices": devices,
|
||||
"userPreferredCameraDevice": preferredDevice,
|
||||
]
|
||||
}
|
||||
|
||||
private func getDevicesJson() -> [[String: Any]] {
|
||||
return discoverySession.devices.map {
|
||||
return [
|
||||
"id": $0.uniqueID,
|
||||
"devices": $0.physicalDevices.map(\.deviceType.descriptor),
|
||||
"position": $0.position.descriptor,
|
||||
"name": $0.localizedName,
|
||||
"hasFlash": $0.hasFlash,
|
||||
"hasTorch": $0.hasTorch,
|
||||
"minZoom": $0.minAvailableVideoZoomFactor,
|
||||
"neutralZoom": $0.neutralZoomFactor,
|
||||
"maxZoom": $0.maxAvailableVideoZoomFactor,
|
||||
"isMultiCam": $0.isMultiCam,
|
||||
"supportsDepthCapture": false, // TODO: supportsDepthCapture
|
||||
"supportsRawCapture": false, // TODO: supportsRawCapture
|
||||
"supportsLowLightBoost": $0.isLowLightBoostSupported,
|
||||
"supportsFocus": $0.isFocusPointOfInterestSupported,
|
||||
"hardwareLevel": "full",
|
||||
"sensorOrientation": "portrait", // TODO: Sensor Orientation?
|
||||
"formats": $0.formats.map { format -> [String: Any] in
|
||||
format.toDictionary()
|
||||
},
|
||||
]
|
||||
return $0.toDictionary()
|
||||
}
|
||||
}
|
||||
|
||||
private static func getAllDeviceTypes() -> [AVCaptureDevice.DeviceType] {
|
||||
var deviceTypes: [AVCaptureDevice.DeviceType] = []
|
||||
deviceTypes.append(.builtInDualCamera)
|
||||
deviceTypes.append(.builtInWideAngleCamera)
|
||||
deviceTypes.append(.builtInTelephotoCamera)
|
||||
deviceTypes.append(.builtInTrueDepthCamera)
|
||||
if #available(iOS 13.0, *) {
|
||||
deviceTypes.append(.builtInTripleCamera)
|
||||
deviceTypes.append(.builtInDualWideCamera)
|
||||
deviceTypes.append(.builtInUltraWideCamera)
|
||||
}
|
||||
deviceTypes.append(.builtInDualCamera)
|
||||
deviceTypes.append(.builtInWideAngleCamera)
|
||||
deviceTypes.append(.builtInTelephotoCamera)
|
||||
if #available(iOS 15.4, *) {
|
||||
deviceTypes.append(.builtInLiDARDepthCamera)
|
||||
}
|
||||
|
||||
// iOS 17 specifics:
|
||||
// This is only reported if `NSCameraUseExternalDeviceType` is set to true in Info.plist,
|
||||
// otherwise external devices are just reported as wide-angle-cameras
|
||||
// deviceTypes.append(.external)
|
||||
// This is only reported if `NSCameraUseContinuityCameraDeviceType` is set to true in Info.plist,
|
||||
// otherwise continuity camera devices are just reported as wide-angle-cameras
|
||||
// deviceTypes.append(.continuityCamera)
|
||||
|
||||
return deviceTypes
|
||||
}
|
||||
}
|
||||
|
@ -84,6 +84,8 @@ extension CameraView {
|
||||
photoOutput!.isDualCameraDualPhotoDeliveryEnabled = photoOutput!.isDualCameraDualPhotoDeliverySupported
|
||||
}
|
||||
}
|
||||
// TODO: Enable isResponsiveCaptureEnabled? (iOS 17+)
|
||||
// TODO: Enable isFastCapturePrioritizationEnabled? (iOS 17+)
|
||||
if enableDepthData {
|
||||
photoOutput!.isDepthDataDeliveryEnabled = photoOutput!.isDepthDataDeliverySupported
|
||||
}
|
||||
|
34
package/ios/Extensions/AVCaptureDevice+toDictionary.swift
Normal file
34
package/ios/Extensions/AVCaptureDevice+toDictionary.swift
Normal file
@ -0,0 +1,34 @@
|
||||
//
|
||||
// AVCaptureDevice+toDictionary.swift
|
||||
// VisionCamera
|
||||
//
|
||||
// Created by Marc Rousavy on 21.09.23.
|
||||
// Copyright © 2023 mrousavy. All rights reserved.
|
||||
//
|
||||
|
||||
import AVFoundation
|
||||
|
||||
extension AVCaptureDevice {
|
||||
func toDictionary() -> [String: Any] {
|
||||
return [
|
||||
"id": uniqueID,
|
||||
"physicalDevices": physicalDevices.map(\.deviceType.physicalDeviceDescriptor),
|
||||
"position": position.descriptor,
|
||||
"name": localizedName,
|
||||
"hasFlash": hasFlash,
|
||||
"hasTorch": hasTorch,
|
||||
"minZoom": minAvailableVideoZoomFactor,
|
||||
"neutralZoom": neutralZoomFactor,
|
||||
"maxZoom": maxAvailableVideoZoomFactor,
|
||||
"isMultiCam": isMultiCam,
|
||||
"supportsRawCapture": false, // TODO: supportsRawCapture
|
||||
"supportsLowLightBoost": isLowLightBoostSupported,
|
||||
"supportsFocus": isFocusPointOfInterestSupported,
|
||||
"hardwareLevel": "full",
|
||||
"sensorOrientation": "portrait", // TODO: Sensor Orientation?
|
||||
"formats": formats.map { format -> [String: Any] in
|
||||
format.toDictionary()
|
||||
},
|
||||
]
|
||||
}
|
||||
}
|
@ -55,6 +55,7 @@ extension AVCaptureDevice.Format {
|
||||
"minFps": minFrameRate,
|
||||
"maxFps": maxFrameRate,
|
||||
"pixelFormats": pixelFormats.map(\.unionValue),
|
||||
"supportsDepthCapture": !supportedDepthDataFormats.isEmpty,
|
||||
]
|
||||
}
|
||||
}
|
||||
|
@ -1,38 +0,0 @@
|
||||
//
|
||||
// AVCaptureDevice.DeviceType+descriptor.swift
|
||||
// mrousavy
|
||||
//
|
||||
// Created by Marc Rousavy on 15.12.20.
|
||||
// Copyright © 2020 mrousavy. All rights reserved.
|
||||
//
|
||||
|
||||
import AVFoundation
|
||||
import Foundation
|
||||
|
||||
extension AVCaptureDevice.DeviceType {
|
||||
var descriptor: String {
|
||||
if #available(iOS 13.0, *) {
|
||||
switch self {
|
||||
case .builtInDualWideCamera:
|
||||
return "dual-wide-camera"
|
||||
case .builtInTripleCamera:
|
||||
return "triple-camera"
|
||||
case .builtInUltraWideCamera:
|
||||
return "ultra-wide-angle-camera"
|
||||
default:
|
||||
break
|
||||
}
|
||||
}
|
||||
switch self {
|
||||
case .builtInDualCamera:
|
||||
return "dual-camera"
|
||||
case .builtInTelephotoCamera:
|
||||
return "telephoto-camera"
|
||||
case .builtInWideAngleCamera:
|
||||
return "wide-angle-camera"
|
||||
default:
|
||||
// e.g. `.builtInTrueDepthCamera`
|
||||
fatalError("AVCaptureDevice.Position has unknown state.")
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,33 @@
|
||||
//
|
||||
// AVCaptureDevice.DeviceType+physicalDeviceDescriptor.swift
|
||||
// mrousavy
|
||||
//
|
||||
// Created by Marc Rousavy on 15.12.20.
|
||||
// Copyright © 2020 mrousavy. All rights reserved.
|
||||
//
|
||||
|
||||
import AVFoundation
|
||||
import Foundation
|
||||
|
||||
extension AVCaptureDevice.DeviceType {
|
||||
/**
|
||||
Gets a descriptor if this is a physical device (wide, ultra-wide and telephoto), or "unknown-camera" otherwise (TrueDepth, LiDAR, InfraRed, USB, ..)
|
||||
*/
|
||||
var physicalDeviceDescriptor: String {
|
||||
if #available(iOS 13.0, *) {
|
||||
if self == .builtInUltraWideCamera {
|
||||
return "ultra-wide-angle-camera"
|
||||
}
|
||||
}
|
||||
switch self {
|
||||
case .builtInTelephotoCamera:
|
||||
return "telephoto-camera"
|
||||
case .builtInWideAngleCamera:
|
||||
return "wide-angle-camera"
|
||||
default:
|
||||
// e.g. Infra-Red, LiDAR, Depth Data, USB or Continuity Camera Devices
|
||||
ReactLogger.log(level: .error, message: "Unknown AVCaptureDevice.DeviceType (\(rawValue))! Falling back to wide-angle-camera..")
|
||||
return "wide-angle-camera"
|
||||
}
|
||||
}
|
||||
}
|
@ -22,6 +22,7 @@
|
||||
B86DC974260E310600FB17B2 /* CameraView+AVAudioSession.swift in Sources */ = {isa = PBXBuildFile; fileRef = B86DC973260E310600FB17B2 /* CameraView+AVAudioSession.swift */; };
|
||||
B86DC977260E315100FB17B2 /* CameraView+AVCaptureSession.swift in Sources */ = {isa = PBXBuildFile; fileRef = B86DC976260E315100FB17B2 /* CameraView+AVCaptureSession.swift */; };
|
||||
B87B11BF2A8E63B700732EBF /* PixelFormat.swift in Sources */ = {isa = PBXBuildFile; fileRef = B87B11BE2A8E63B700732EBF /* PixelFormat.swift */; };
|
||||
B881D35E2ABC775E009B21C8 /* AVCaptureDevice+toDictionary.swift in Sources */ = {isa = PBXBuildFile; fileRef = B881D35D2ABC775E009B21C8 /* AVCaptureDevice+toDictionary.swift */; };
|
||||
B882721026AEB1A100B14107 /* AVCaptureConnection+setInterfaceOrientation.swift in Sources */ = {isa = PBXBuildFile; fileRef = B882720F26AEB1A100B14107 /* AVCaptureConnection+setInterfaceOrientation.swift */; };
|
||||
B887518525E0102000DB86D6 /* PhotoCaptureDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = B887515C25E0102000DB86D6 /* PhotoCaptureDelegate.swift */; };
|
||||
B887518625E0102000DB86D6 /* CameraView+RecordVideo.swift in Sources */ = {isa = PBXBuildFile; fileRef = B887515D25E0102000DB86D6 /* CameraView+RecordVideo.swift */; };
|
||||
@ -44,7 +45,7 @@
|
||||
B887519A25E0102000DB86D6 /* AVVideoCodecType+descriptor.swift in Sources */ = {isa = PBXBuildFile; fileRef = B887517525E0102000DB86D6 /* AVVideoCodecType+descriptor.swift */; };
|
||||
B887519C25E0102000DB86D6 /* AVCaptureDevice.TorchMode+descriptor.swift in Sources */ = {isa = PBXBuildFile; fileRef = B887517725E0102000DB86D6 /* AVCaptureDevice.TorchMode+descriptor.swift */; };
|
||||
B887519E25E0102000DB86D6 /* AVCapturePhotoOutput.QualityPrioritization+descriptor.swift in Sources */ = {isa = PBXBuildFile; fileRef = B887517925E0102000DB86D6 /* AVCapturePhotoOutput.QualityPrioritization+descriptor.swift */; };
|
||||
B887519F25E0102000DB86D6 /* AVCaptureDevice.DeviceType+descriptor.swift in Sources */ = {isa = PBXBuildFile; fileRef = B887517A25E0102000DB86D6 /* AVCaptureDevice.DeviceType+descriptor.swift */; };
|
||||
B887519F25E0102000DB86D6 /* AVCaptureDevice.DeviceType+physicalDeviceDescriptor.swift in Sources */ = {isa = PBXBuildFile; fileRef = B887517A25E0102000DB86D6 /* AVCaptureDevice.DeviceType+physicalDeviceDescriptor.swift */; };
|
||||
B88751A025E0102000DB86D6 /* AVAuthorizationStatus+descriptor.swift in Sources */ = {isa = PBXBuildFile; fileRef = B887517B25E0102000DB86D6 /* AVAuthorizationStatus+descriptor.swift */; };
|
||||
B88751A125E0102000DB86D6 /* AVCaptureDevice.Position+descriptor.swift in Sources */ = {isa = PBXBuildFile; fileRef = B887517C25E0102000DB86D6 /* AVCaptureDevice.Position+descriptor.swift */; };
|
||||
B88751A325E0102000DB86D6 /* AVCaptureDevice.FlashMode+descriptor.swift in Sources */ = {isa = PBXBuildFile; fileRef = B887517E25E0102000DB86D6 /* AVCaptureDevice.FlashMode+descriptor.swift */; };
|
||||
@ -99,6 +100,7 @@
|
||||
B86DC973260E310600FB17B2 /* CameraView+AVAudioSession.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "CameraView+AVAudioSession.swift"; sourceTree = "<group>"; };
|
||||
B86DC976260E315100FB17B2 /* CameraView+AVCaptureSession.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "CameraView+AVCaptureSession.swift"; sourceTree = "<group>"; };
|
||||
B87B11BE2A8E63B700732EBF /* PixelFormat.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PixelFormat.swift; sourceTree = "<group>"; };
|
||||
B881D35D2ABC775E009B21C8 /* AVCaptureDevice+toDictionary.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "AVCaptureDevice+toDictionary.swift"; sourceTree = "<group>"; };
|
||||
B882720F26AEB1A100B14107 /* AVCaptureConnection+setInterfaceOrientation.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "AVCaptureConnection+setInterfaceOrientation.swift"; sourceTree = "<group>"; };
|
||||
B887515C25E0102000DB86D6 /* PhotoCaptureDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PhotoCaptureDelegate.swift; sourceTree = "<group>"; };
|
||||
B887515D25E0102000DB86D6 /* CameraView+RecordVideo.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "CameraView+RecordVideo.swift"; sourceTree = "<group>"; };
|
||||
@ -122,7 +124,7 @@
|
||||
B887517525E0102000DB86D6 /* AVVideoCodecType+descriptor.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "AVVideoCodecType+descriptor.swift"; sourceTree = "<group>"; };
|
||||
B887517725E0102000DB86D6 /* AVCaptureDevice.TorchMode+descriptor.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "AVCaptureDevice.TorchMode+descriptor.swift"; sourceTree = "<group>"; };
|
||||
B887517925E0102000DB86D6 /* AVCapturePhotoOutput.QualityPrioritization+descriptor.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "AVCapturePhotoOutput.QualityPrioritization+descriptor.swift"; sourceTree = "<group>"; };
|
||||
B887517A25E0102000DB86D6 /* AVCaptureDevice.DeviceType+descriptor.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "AVCaptureDevice.DeviceType+descriptor.swift"; sourceTree = "<group>"; };
|
||||
B887517A25E0102000DB86D6 /* AVCaptureDevice.DeviceType+physicalDeviceDescriptor.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "AVCaptureDevice.DeviceType+physicalDeviceDescriptor.swift"; sourceTree = "<group>"; };
|
||||
B887517B25E0102000DB86D6 /* AVAuthorizationStatus+descriptor.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "AVAuthorizationStatus+descriptor.swift"; sourceTree = "<group>"; };
|
||||
B887517C25E0102000DB86D6 /* AVCaptureDevice.Position+descriptor.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "AVCaptureDevice.Position+descriptor.swift"; sourceTree = "<group>"; };
|
||||
B887517E25E0102000DB86D6 /* AVCaptureDevice.FlashMode+descriptor.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "AVCaptureDevice.FlashMode+descriptor.swift"; sourceTree = "<group>"; };
|
||||
@ -211,6 +213,7 @@
|
||||
B887516625E0102000DB86D6 /* AVCaptureDevice+physicalDevices.swift */,
|
||||
B887516725E0102000DB86D6 /* AVFrameRateRange+includes.swift */,
|
||||
B887516825E0102000DB86D6 /* AVCapturePhotoOutput+mirror.swift */,
|
||||
B881D35D2ABC775E009B21C8 /* AVCaptureDevice+toDictionary.swift */,
|
||||
B887516925E0102000DB86D6 /* AVCaptureDevice.Format+matchesFilter.swift */,
|
||||
B887516A25E0102000DB86D6 /* AVCaptureDevice.Format+toDictionary.swift */,
|
||||
B88B47462667C8E00091F538 /* AVCaptureSession+setVideoStabilizationMode.swift */,
|
||||
@ -239,7 +242,7 @@
|
||||
B887517525E0102000DB86D6 /* AVVideoCodecType+descriptor.swift */,
|
||||
B887517725E0102000DB86D6 /* AVCaptureDevice.TorchMode+descriptor.swift */,
|
||||
B887517925E0102000DB86D6 /* AVCapturePhotoOutput.QualityPrioritization+descriptor.swift */,
|
||||
B887517A25E0102000DB86D6 /* AVCaptureDevice.DeviceType+descriptor.swift */,
|
||||
B887517A25E0102000DB86D6 /* AVCaptureDevice.DeviceType+physicalDeviceDescriptor.swift */,
|
||||
B887517B25E0102000DB86D6 /* AVAuthorizationStatus+descriptor.swift */,
|
||||
B887517C25E0102000DB86D6 /* AVCaptureDevice.Position+descriptor.swift */,
|
||||
B887517E25E0102000DB86D6 /* AVCaptureDevice.FlashMode+descriptor.swift */,
|
||||
@ -408,9 +411,10 @@
|
||||
B887519A25E0102000DB86D6 /* AVVideoCodecType+descriptor.swift in Sources */,
|
||||
B88751A825E0102000DB86D6 /* CameraError.swift in Sources */,
|
||||
B85F7AE92A77BB680089C539 /* FrameProcessorPlugin.m in Sources */,
|
||||
B881D35E2ABC775E009B21C8 /* AVCaptureDevice+toDictionary.swift in Sources */,
|
||||
B87B11BF2A8E63B700732EBF /* PixelFormat.swift in Sources */,
|
||||
B88751A625E0102000DB86D6 /* CameraViewManager.swift in Sources */,
|
||||
B887519F25E0102000DB86D6 /* AVCaptureDevice.DeviceType+descriptor.swift in Sources */,
|
||||
B887519F25E0102000DB86D6 /* AVCaptureDevice.DeviceType+physicalDeviceDescriptor.swift in Sources */,
|
||||
B8D22CDC2642DB4D00234472 /* AVAssetWriterInputPixelBufferAdaptor+initWithVideoSettings.swift in Sources */,
|
||||
B84760DF2608F57D004C3180 /* CameraQueues.swift in Sources */,
|
||||
B8446E502ABA14C900E56077 /* CameraDevicesManager.m in Sources */,
|
||||
|
@ -14,7 +14,7 @@ export type CameraPosition = 'front' | 'back' | 'external';
|
||||
* Indentifiers for a physical camera (one that actually exists on the back/front of the device)
|
||||
*
|
||||
* * `"ultra-wide-angle-camera"`: A built-in camera with a shorter focal length than that of a wide-angle camera. (focal length between below 24mm)
|
||||
* * `"wide-angle-camera"`: A built-in wide-angle camera. (focal length between 24mm and 35mm)
|
||||
* * `"wide-angle-camera"`: A built-in wide-angle camera. (focal length between 24mm and 43mm)
|
||||
* * `"telephoto-camera"`: A built-in camera device with a longer focal length than a wide-angle camera. (focal length between above 85mm)
|
||||
*
|
||||
* Some Camera devices consist of multiple physical devices. They can be interpreted as _logical devices_, for example:
|
||||
@ -89,6 +89,10 @@ export interface CameraDeviceFormat {
|
||||
* Specifies whether this format supports HDR mode for photo capture
|
||||
*/
|
||||
supportsPhotoHDR: boolean;
|
||||
/**
|
||||
* Specifies whether this format supports delivering depth data for photo or video capture.
|
||||
*/
|
||||
supportsDepthCapture: boolean;
|
||||
/**
|
||||
* The minum frame rate this Format needs to run at. High resolution formats often run at lower frame rates.
|
||||
*/
|
||||
@ -121,14 +125,14 @@ export interface CameraDevice {
|
||||
*/
|
||||
id: string;
|
||||
/**
|
||||
* The physical devices this `CameraDevice` contains.
|
||||
* The physical devices this `CameraDevice` consists of.
|
||||
*
|
||||
* * If this camera device is a **logical camera** (combination of multiple physical cameras), there are multiple cameras in this array.
|
||||
* * If this camera device is a **physical camera**, there is only a single element in this array.
|
||||
* * If this camera device is a **logical camera** (combination of multiple physical cameras, e.g. "Triple Camera"), there are multiple cameras in this array.
|
||||
* * If this camera device is a **physical camera** (e.g. "wide-angle-camera"), there is only a single element in this array.
|
||||
*
|
||||
* You can check if the camera is a logical multi-camera by using the `isMultiCam` property.
|
||||
*/
|
||||
devices: PhysicalCameraDeviceType[];
|
||||
physicalDevices: PhysicalCameraDeviceType[];
|
||||
/**
|
||||
* Specifies the physical position of this camera. (back or front)
|
||||
*/
|
||||
@ -187,12 +191,6 @@ export interface CameraDevice {
|
||||
* Whether this camera device supports low light boost.
|
||||
*/
|
||||
supportsLowLightBoost: boolean;
|
||||
/**
|
||||
* Whether this camera supports taking photos with depth data.
|
||||
*
|
||||
* **! Work in Progress !**
|
||||
*/
|
||||
supportsDepthCapture: boolean;
|
||||
/**
|
||||
* Whether this camera supports taking photos in RAW format
|
||||
*
|
||||
|
@ -4,6 +4,7 @@ import { CameraDevice } from './CameraDevice';
|
||||
const CameraDevicesManager = NativeModules.CameraDevices as {
|
||||
getConstants: () => {
|
||||
availableCameraDevices: CameraDevice[];
|
||||
userPreferredCameraDevice: CameraDevice | undefined;
|
||||
};
|
||||
};
|
||||
|
||||
@ -18,6 +19,7 @@ eventEmitter.addListener(DEVICES_CHANGED_NAME, (newDevices: CameraDevice[]) => {
|
||||
});
|
||||
|
||||
export const CameraDevices = {
|
||||
userPreferredCameraDevice: constants.userPreferredCameraDevice,
|
||||
getAvailableCameraDevices: () => devices,
|
||||
addCameraDevicesChangedListener: (callback: (newDevices: CameraDevice[]) => void) => {
|
||||
return eventEmitter.addListener(DEVICES_CHANGED_NAME, callback);
|
||||
|
@ -43,11 +43,11 @@ export function getCameraDevice(devices: CameraDevice[], position: CameraPositio
|
||||
// 1. user wants all cameras ([ultra-wide, wide, tele]) to zoom. prefer those devices that have all 3 cameras.
|
||||
// 2. user wants only one ([wide]) for faster performance. prefer those devices that only have one camera, if they have more, we rank them lower.
|
||||
if (filter.physicalDevices != null) {
|
||||
for (const device of left.devices) {
|
||||
for (const device of left.physicalDevices) {
|
||||
if (filter.physicalDevices.includes(device)) leftPoints += 1;
|
||||
else leftPoints -= 1;
|
||||
}
|
||||
for (const device of right.devices) {
|
||||
for (const device of right.physicalDevices) {
|
||||
if (filter.physicalDevices.includes(device)) rightPoints += 1;
|
||||
else rightPoints -= 1;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user