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,
|
"maxZoom": 123.75,
|
||||||
"name": "Back Dual Wide Camera",
|
"name": "Back Dual Wide Camera",
|
||||||
"position": "back",
|
"position": "back",
|
||||||
"supportsDepthCapture": false,
|
|
||||||
"supportsFocus": true,
|
"supportsFocus": true,
|
||||||
"supportsLowLightBoost": false,
|
"supportsLowLightBoost": false,
|
||||||
"supportsParallelVideoProcessing": true,
|
"supportsParallelVideoProcessing": true,
|
||||||
|
@ -73,7 +73,15 @@ class CameraDevicesManager(private val reactContext: ReactApplicationContext) :
|
|||||||
|
|
||||||
override fun hasConstants(): Boolean = true
|
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:
|
// Required for NativeEventEmitter, this is just a dummy implementation:
|
||||||
@ReactMethod
|
@ReactMethod
|
||||||
|
@ -183,6 +183,7 @@ class CameraDeviceDetails(private val cameraManager: CameraManager, private val
|
|||||||
map.putDouble("fieldOfView", getFieldOfView())
|
map.putDouble("fieldOfView", getFieldOfView())
|
||||||
map.putBoolean("supportsVideoHDR", supportsVideoHdr)
|
map.putBoolean("supportsVideoHDR", supportsVideoHdr)
|
||||||
map.putBoolean("supportsPhotoHDR", supportsPhotoHdr)
|
map.putBoolean("supportsPhotoHDR", supportsPhotoHdr)
|
||||||
|
map.putBoolean("supportsDepthCapture", supportsDepthCapture)
|
||||||
map.putString("autoFocusSystem", "contrast-detection") // TODO: Is this wrong?
|
map.putString("autoFocusSystem", "contrast-detection") // TODO: Is this wrong?
|
||||||
map.putArray("videoStabilizationModes", createStabilizationModes())
|
map.putArray("videoStabilizationModes", createStabilizationModes())
|
||||||
map.putArray("pixelFormats", createPixelFormats(videoSize))
|
map.putArray("pixelFormats", createPixelFormats(videoSize))
|
||||||
@ -192,14 +193,13 @@ class CameraDeviceDetails(private val cameraManager: CameraManager, private val
|
|||||||
fun toMap(): ReadableMap {
|
fun toMap(): ReadableMap {
|
||||||
val map = Arguments.createMap()
|
val map = Arguments.createMap()
|
||||||
map.putString("id", cameraId)
|
map.putString("id", cameraId)
|
||||||
map.putArray("devices", getDeviceTypes())
|
map.putArray("physicalDevices", getDeviceTypes())
|
||||||
map.putString("position", lensFacing.unionValue)
|
map.putString("position", lensFacing.unionValue)
|
||||||
map.putString("name", name)
|
map.putString("name", name)
|
||||||
map.putBoolean("hasFlash", hasFlash)
|
map.putBoolean("hasFlash", hasFlash)
|
||||||
map.putBoolean("hasTorch", hasFlash)
|
map.putBoolean("hasTorch", hasFlash)
|
||||||
map.putBoolean("isMultiCam", isMultiCam)
|
map.putBoolean("isMultiCam", isMultiCam)
|
||||||
map.putBoolean("supportsRawCapture", supportsRawCapture)
|
map.putBoolean("supportsRawCapture", supportsRawCapture)
|
||||||
map.putBoolean("supportsDepthCapture", supportsDepthCapture)
|
|
||||||
map.putBoolean("supportsLowLightBoost", supportsLowLightBoost)
|
map.putBoolean("supportsLowLightBoost", supportsLowLightBoost)
|
||||||
map.putBoolean("supportsFocus", true) // I believe every device here supports focussing
|
map.putBoolean("supportsFocus", true) // I believe every device here supports focussing
|
||||||
map.putDouble("minZoom", minZoom)
|
map.putDouble("minZoom", minZoom)
|
||||||
|
@ -216,7 +216,7 @@ export function CameraPage({ navigation }: Props): React.ReactElement {
|
|||||||
)}
|
)}
|
||||||
{supports60Fps && (
|
{supports60Fps && (
|
||||||
<PressableOpacity style={styles.button} onPress={() => setTargetFps((t) => (t === 30 ? 60 : 30))}>
|
<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>
|
</PressableOpacity>
|
||||||
)}
|
)}
|
||||||
{supportsHdr && (
|
{supportsHdr && (
|
||||||
|
@ -37,47 +37,55 @@ class CameraDevicesManager: RCTEventEmitter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override func constantsToExport() -> [AnyHashable: Any]! {
|
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 [
|
return [
|
||||||
"availableCameraDevices": getDevicesJson(),
|
"availableCameraDevices": devices,
|
||||||
|
"userPreferredCameraDevice": preferredDevice,
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
private func getDevicesJson() -> [[String: Any]] {
|
private func getDevicesJson() -> [[String: Any]] {
|
||||||
return discoverySession.devices.map {
|
return discoverySession.devices.map {
|
||||||
return [
|
return $0.toDictionary()
|
||||||
"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()
|
|
||||||
},
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static func getAllDeviceTypes() -> [AVCaptureDevice.DeviceType] {
|
private static func getAllDeviceTypes() -> [AVCaptureDevice.DeviceType] {
|
||||||
var deviceTypes: [AVCaptureDevice.DeviceType] = []
|
var deviceTypes: [AVCaptureDevice.DeviceType] = []
|
||||||
|
deviceTypes.append(.builtInDualCamera)
|
||||||
|
deviceTypes.append(.builtInWideAngleCamera)
|
||||||
|
deviceTypes.append(.builtInTelephotoCamera)
|
||||||
|
deviceTypes.append(.builtInTrueDepthCamera)
|
||||||
if #available(iOS 13.0, *) {
|
if #available(iOS 13.0, *) {
|
||||||
deviceTypes.append(.builtInTripleCamera)
|
deviceTypes.append(.builtInTripleCamera)
|
||||||
deviceTypes.append(.builtInDualWideCamera)
|
deviceTypes.append(.builtInDualWideCamera)
|
||||||
deviceTypes.append(.builtInUltraWideCamera)
|
deviceTypes.append(.builtInUltraWideCamera)
|
||||||
}
|
}
|
||||||
deviceTypes.append(.builtInDualCamera)
|
if #available(iOS 15.4, *) {
|
||||||
deviceTypes.append(.builtInWideAngleCamera)
|
deviceTypes.append(.builtInLiDARDepthCamera)
|
||||||
deviceTypes.append(.builtInTelephotoCamera)
|
}
|
||||||
|
|
||||||
|
// 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
|
return deviceTypes
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -84,6 +84,8 @@ extension CameraView {
|
|||||||
photoOutput!.isDualCameraDualPhotoDeliveryEnabled = photoOutput!.isDualCameraDualPhotoDeliverySupported
|
photoOutput!.isDualCameraDualPhotoDeliveryEnabled = photoOutput!.isDualCameraDualPhotoDeliverySupported
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// TODO: Enable isResponsiveCaptureEnabled? (iOS 17+)
|
||||||
|
// TODO: Enable isFastCapturePrioritizationEnabled? (iOS 17+)
|
||||||
if enableDepthData {
|
if enableDepthData {
|
||||||
photoOutput!.isDepthDataDeliveryEnabled = photoOutput!.isDepthDataDeliverySupported
|
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,
|
"minFps": minFrameRate,
|
||||||
"maxFps": maxFrameRate,
|
"maxFps": maxFrameRate,
|
||||||
"pixelFormats": pixelFormats.map(\.unionValue),
|
"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 */; };
|
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 */; };
|
B86DC977260E315100FB17B2 /* CameraView+AVCaptureSession.swift in Sources */ = {isa = PBXBuildFile; fileRef = B86DC976260E315100FB17B2 /* CameraView+AVCaptureSession.swift */; };
|
||||||
B87B11BF2A8E63B700732EBF /* PixelFormat.swift in Sources */ = {isa = PBXBuildFile; fileRef = B87B11BE2A8E63B700732EBF /* PixelFormat.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 */; };
|
B882721026AEB1A100B14107 /* AVCaptureConnection+setInterfaceOrientation.swift in Sources */ = {isa = PBXBuildFile; fileRef = B882720F26AEB1A100B14107 /* AVCaptureConnection+setInterfaceOrientation.swift */; };
|
||||||
B887518525E0102000DB86D6 /* PhotoCaptureDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = B887515C25E0102000DB86D6 /* PhotoCaptureDelegate.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 */; };
|
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 */; };
|
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 */; };
|
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 */; };
|
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 */; };
|
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 */; };
|
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 */; };
|
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>"; };
|
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>"; };
|
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>"; };
|
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>"; };
|
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>"; };
|
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>"; };
|
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>"; };
|
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>"; };
|
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>"; };
|
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>"; };
|
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>"; };
|
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>"; };
|
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 */,
|
B887516625E0102000DB86D6 /* AVCaptureDevice+physicalDevices.swift */,
|
||||||
B887516725E0102000DB86D6 /* AVFrameRateRange+includes.swift */,
|
B887516725E0102000DB86D6 /* AVFrameRateRange+includes.swift */,
|
||||||
B887516825E0102000DB86D6 /* AVCapturePhotoOutput+mirror.swift */,
|
B887516825E0102000DB86D6 /* AVCapturePhotoOutput+mirror.swift */,
|
||||||
|
B881D35D2ABC775E009B21C8 /* AVCaptureDevice+toDictionary.swift */,
|
||||||
B887516925E0102000DB86D6 /* AVCaptureDevice.Format+matchesFilter.swift */,
|
B887516925E0102000DB86D6 /* AVCaptureDevice.Format+matchesFilter.swift */,
|
||||||
B887516A25E0102000DB86D6 /* AVCaptureDevice.Format+toDictionary.swift */,
|
B887516A25E0102000DB86D6 /* AVCaptureDevice.Format+toDictionary.swift */,
|
||||||
B88B47462667C8E00091F538 /* AVCaptureSession+setVideoStabilizationMode.swift */,
|
B88B47462667C8E00091F538 /* AVCaptureSession+setVideoStabilizationMode.swift */,
|
||||||
@ -239,7 +242,7 @@
|
|||||||
B887517525E0102000DB86D6 /* AVVideoCodecType+descriptor.swift */,
|
B887517525E0102000DB86D6 /* AVVideoCodecType+descriptor.swift */,
|
||||||
B887517725E0102000DB86D6 /* AVCaptureDevice.TorchMode+descriptor.swift */,
|
B887517725E0102000DB86D6 /* AVCaptureDevice.TorchMode+descriptor.swift */,
|
||||||
B887517925E0102000DB86D6 /* AVCapturePhotoOutput.QualityPrioritization+descriptor.swift */,
|
B887517925E0102000DB86D6 /* AVCapturePhotoOutput.QualityPrioritization+descriptor.swift */,
|
||||||
B887517A25E0102000DB86D6 /* AVCaptureDevice.DeviceType+descriptor.swift */,
|
B887517A25E0102000DB86D6 /* AVCaptureDevice.DeviceType+physicalDeviceDescriptor.swift */,
|
||||||
B887517B25E0102000DB86D6 /* AVAuthorizationStatus+descriptor.swift */,
|
B887517B25E0102000DB86D6 /* AVAuthorizationStatus+descriptor.swift */,
|
||||||
B887517C25E0102000DB86D6 /* AVCaptureDevice.Position+descriptor.swift */,
|
B887517C25E0102000DB86D6 /* AVCaptureDevice.Position+descriptor.swift */,
|
||||||
B887517E25E0102000DB86D6 /* AVCaptureDevice.FlashMode+descriptor.swift */,
|
B887517E25E0102000DB86D6 /* AVCaptureDevice.FlashMode+descriptor.swift */,
|
||||||
@ -408,9 +411,10 @@
|
|||||||
B887519A25E0102000DB86D6 /* AVVideoCodecType+descriptor.swift in Sources */,
|
B887519A25E0102000DB86D6 /* AVVideoCodecType+descriptor.swift in Sources */,
|
||||||
B88751A825E0102000DB86D6 /* CameraError.swift in Sources */,
|
B88751A825E0102000DB86D6 /* CameraError.swift in Sources */,
|
||||||
B85F7AE92A77BB680089C539 /* FrameProcessorPlugin.m in Sources */,
|
B85F7AE92A77BB680089C539 /* FrameProcessorPlugin.m in Sources */,
|
||||||
|
B881D35E2ABC775E009B21C8 /* AVCaptureDevice+toDictionary.swift in Sources */,
|
||||||
B87B11BF2A8E63B700732EBF /* PixelFormat.swift in Sources */,
|
B87B11BF2A8E63B700732EBF /* PixelFormat.swift in Sources */,
|
||||||
B88751A625E0102000DB86D6 /* CameraViewManager.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 */,
|
B8D22CDC2642DB4D00234472 /* AVAssetWriterInputPixelBufferAdaptor+initWithVideoSettings.swift in Sources */,
|
||||||
B84760DF2608F57D004C3180 /* CameraQueues.swift in Sources */,
|
B84760DF2608F57D004C3180 /* CameraQueues.swift in Sources */,
|
||||||
B8446E502ABA14C900E56077 /* CameraDevicesManager.m 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)
|
* 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)
|
* * `"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)
|
* * `"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:
|
* 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
|
* Specifies whether this format supports HDR mode for photo capture
|
||||||
*/
|
*/
|
||||||
supportsPhotoHDR: boolean;
|
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.
|
* 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;
|
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 **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**, there is only a single element 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.
|
* 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)
|
* 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.
|
* Whether this camera device supports low light boost.
|
||||||
*/
|
*/
|
||||||
supportsLowLightBoost: boolean;
|
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
|
* Whether this camera supports taking photos in RAW format
|
||||||
*
|
*
|
||||||
|
@ -4,6 +4,7 @@ import { CameraDevice } from './CameraDevice';
|
|||||||
const CameraDevicesManager = NativeModules.CameraDevices as {
|
const CameraDevicesManager = NativeModules.CameraDevices as {
|
||||||
getConstants: () => {
|
getConstants: () => {
|
||||||
availableCameraDevices: CameraDevice[];
|
availableCameraDevices: CameraDevice[];
|
||||||
|
userPreferredCameraDevice: CameraDevice | undefined;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -18,6 +19,7 @@ eventEmitter.addListener(DEVICES_CHANGED_NAME, (newDevices: CameraDevice[]) => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
export const CameraDevices = {
|
export const CameraDevices = {
|
||||||
|
userPreferredCameraDevice: constants.userPreferredCameraDevice,
|
||||||
getAvailableCameraDevices: () => devices,
|
getAvailableCameraDevices: () => devices,
|
||||||
addCameraDevicesChangedListener: (callback: (newDevices: CameraDevice[]) => void) => {
|
addCameraDevicesChangedListener: (callback: (newDevices: CameraDevice[]) => void) => {
|
||||||
return eventEmitter.addListener(DEVICES_CHANGED_NAME, callback);
|
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.
|
// 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.
|
// 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) {
|
if (filter.physicalDevices != null) {
|
||||||
for (const device of left.devices) {
|
for (const device of left.physicalDevices) {
|
||||||
if (filter.physicalDevices.includes(device)) leftPoints += 1;
|
if (filter.physicalDevices.includes(device)) leftPoints += 1;
|
||||||
else leftPoints -= 1;
|
else leftPoints -= 1;
|
||||||
}
|
}
|
||||||
for (const device of right.devices) {
|
for (const device of right.physicalDevices) {
|
||||||
if (filter.physicalDevices.includes(device)) rightPoints += 1;
|
if (filter.physicalDevices.includes(device)) rightPoints += 1;
|
||||||
else rightPoints -= 1;
|
else rightPoints -= 1;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user