diff --git a/packages/react-native-vision-camera/ios/Extensions/AVFoundation/AVCaptureSession+addAudioInput.swift b/packages/react-native-vision-camera/ios/Extensions/AVFoundation/AVCaptureSession+addAudioInput.swift index f27e90e02a..a3a9f7cb58 100644 --- a/packages/react-native-vision-camera/ios/Extensions/AVFoundation/AVCaptureSession+addAudioInput.swift +++ b/packages/react-native-vision-camera/ios/Extensions/AVFoundation/AVCaptureSession+addAudioInput.swift @@ -37,7 +37,7 @@ extension AVCaptureSession { private func getDefaultMicrophone() throws -> AVCaptureDevice { // TODO: Make microphone input selectable from JS - if #available(iOS 18.0, *) { + if #available(iOS 17.0, *) { if let microphone = AVCaptureDevice.default(.microphone, for: .audio, position: .unspecified) { return microphone } diff --git a/packages/react-native-vision-camera/ios/Hybrid Objects/Outputs/HybridCameraFrameOutput.swift b/packages/react-native-vision-camera/ios/Hybrid Objects/Outputs/HybridCameraFrameOutput.swift index afba918669..eb56fb8d97 100644 --- a/packages/react-native-vision-camera/ios/Hybrid Objects/Outputs/HybridCameraFrameOutput.swift +++ b/packages/react-native-vision-camera/ios/Hybrid Objects/Outputs/HybridCameraFrameOutput.swift @@ -61,18 +61,18 @@ final class HybridCameraFrameOutput: HybridCameraFrameOutputSpec, NativeCameraOu output.alwaysDiscardsLateVideoFrames = options.dropFramesWhileBusy // JS configures the video resolution, we don't want to downscale here by default. output.automaticallyConfiguresOutputBufferDimensions = false - if #available(iOS 26.0, *), output.isDeferredStartSupported { - // Deferred start allows the Session to delay this output's startup in favor - // of preview-related outputs to make preview appear faster. - output.isDeferredStartEnabled = options.allowDeferredStart - } // TODO: Add a flag called `allowBufferResizing` and probably get rid of `enablePreviewSizedOutputBuffers` // If `allowBufferResizing` is true, we can set `.videoSettings`/dimensions here to `options.targetResolution` // and `targetResolution` to `.any` (to not participate in resolution negotiations). // If `allowBufferResizing` is false, we don't set `.videoSettings` ("native" resolution), and reflect our // target resolution via `targetResolution` to participate in resolution negotiations. - if #available(iOS 17.0, *), options.enablePreviewSizedOutputBuffers { - output.deliversPreviewSizedOutputBuffers = true + if #available(iOS 13.0, *) { + output.deliversPreviewSizedOutputBuffers = options.enablePreviewSizedOutputBuffers + } + if #available(iOS 26.0, *), output.isDeferredStartSupported { + // Deferred start allows the Session to delay this output's startup in favor + // of preview-related outputs to make preview appear faster. + output.isDeferredStartEnabled = options.allowDeferredStart } if #available(iOS 26.0, *) { // We don't need HDR metadata, as that's only useful for encoders. diff --git a/packages/react-native-vision-camera/ios/Hybrid Objects/Outputs/HybridCameraPhotoOutput.swift b/packages/react-native-vision-camera/ios/Hybrid Objects/Outputs/HybridCameraPhotoOutput.swift index 1f5a54cf18..9a736548b8 100644 --- a/packages/react-native-vision-camera/ios/Hybrid Objects/Outputs/HybridCameraPhotoOutput.swift +++ b/packages/react-native-vision-camera/ios/Hybrid Objects/Outputs/HybridCameraPhotoOutput.swift @@ -56,23 +56,6 @@ final class HybridCameraPhotoOutput: HybridCameraPhotoOutputSpec, NativeCameraOu super.init() output.maxPhotoQualityPrioritization = options.qualityPrioritization.toAVQualityPrioritization() - - if options.containerFormat == .dng { - // If we capture RAW photos, try using Apple ProRAW. If not, Bayer14 RAW will be used. - output.isAppleProRAWEnabled = output.isAppleProRAWSupported - } - - if #available(iOS 26, *), - output.isCameraSensorOrientationCompensationSupported - { - // Don't rotate Photo buffers - we handle orientation later on in file capture or toImage(). - output.isCameraSensorOrientationCompensationEnabled = false - } - - // Prepare the default Photo Settings to make the pipeline ready - some things (like flashMode) - // might change on a per-capture basis, but containerFormat and preview size is already known - // and can be prepared already. - try? prepareDefaultPhotoSettings() } func configure(config: CameraOutputConfiguration) { @@ -82,6 +65,17 @@ final class HybridCameraPhotoOutput: HybridCameraPhotoOutputSpec, NativeCameraOu try? connection.setOrientation(outputOrientation) try? connection.setMirrorMode(config.mirrorMode) + let enableAppleProRAW = options.containerFormat == .dng && output.isAppleProRAWSupported + if output.isAppleProRAWEnabled != enableAppleProRAW { + // If we capture RAW photos, try using Apple ProRAW. If not, Bayer14 RAW will be used. + output.isAppleProRAWEnabled = enableAppleProRAW + } + + if #available(iOS 26, *) { + // Don't rotate Photo buffers - we handle orientation later on in file capture or toImage(). + output.isCameraSensorOrientationCompensationEnabled = false + } + if #available(iOS 16.0, *) { // Configure PhotoOutput to the currently selected Format's max photo size if let nativeDevice = connection.deviceInput { @@ -93,10 +87,14 @@ final class HybridCameraPhotoOutput: HybridCameraPhotoOutputSpec, NativeCameraOu { // Target max photo dimensions have changed, re-configure output.maxPhotoDimensions = nearestPhotoDimension - try? prepareDefaultPhotoSettings() } } } + + // Prepare the default Photo Settings to make the pipeline ready - some things (like flashMode) + // might change on a per-capture basis, but containerFormat and preview size is already known + // and can be prepared already. + try? prepareDefaultPhotoSettings() } private func prepareDefaultPhotoSettings() throws { diff --git a/packages/react-native-vision-camera/ios/Public/NativeCameraOutput.swift b/packages/react-native-vision-camera/ios/Public/NativeCameraOutput.swift index b1a1db6b75..e895b3ed61 100644 --- a/packages/react-native-vision-camera/ios/Public/NativeCameraOutput.swift +++ b/packages/react-native-vision-camera/ios/Public/NativeCameraOutput.swift @@ -53,7 +53,10 @@ public protocol NativeCameraOutput: AnyObject, ResolutionNegotiationParticipant * change, in a `beginConfiguration()`/`commitConfiguration()` * batch. * The `NativeCameraOutput` is expected to apply all configs - * such as orientation or mirroring settings in here. + * such as orientation or mirroring settings in here, as well + * as any output properties that depend on session configuration, + * like `isResponsiveCaptureEnabled` which depends on + * the `isResponsiveCaptureSupported` property. */ func configure(config: CameraOutputConfiguration) }