From 89917798513c71ff1c84287af1886b16a7c7f4cd Mon Sep 17 00:00:00 2001 From: Volodymyr Smolianinov Date: Tue, 8 Oct 2024 15:53:47 +0200 Subject: [PATCH] iOS Camera Settings --- package/ios/CameraView+RecordVideo.swift | 8 +++ package/ios/CameraViewManager.m | 8 +++ package/ios/CameraViewManager.swift | 12 +++++ package/ios/Core/CameraSession+Video.swift | 61 ++++++++++++++++------ package/src/Camera.tsx | 16 ++++++ 5 files changed, 88 insertions(+), 17 deletions(-) diff --git a/package/ios/CameraView+RecordVideo.swift b/package/ios/CameraView+RecordVideo.swift index 11c4906..7f9d00b 100644 --- a/package/ios/CameraView+RecordVideo.swift +++ b/package/ios/CameraView+RecordVideo.swift @@ -50,4 +50,12 @@ extension CameraView: AVCaptureVideoDataOutputSampleBufferDelegate, AVCaptureAud func resumeRecording(promise: Promise) { cameraSession.resumeRecording(promise: promise) } + + func lockExposure(promise: Promise) { + cameraSession.lockCurrentExposure(promise: promise) + } + + func unlockExposure(promise: Promise) { + cameraSession.unlockCurrentExposure(promise: promise) + } } diff --git a/package/ios/CameraViewManager.m b/package/ios/CameraViewManager.m index fcf632f..9ebbb6e 100644 --- a/package/ios/CameraViewManager.m +++ b/package/ios/CameraViewManager.m @@ -86,5 +86,13 @@ RCT_EXTERN_METHOD(focus : (NSDictionary*)point resolve : (RCTPromiseResolveBlock)resolve reject : (RCTPromiseRejectBlock)reject); +RCT_EXTERN_METHOD(lockCurrentExposure + : (nonnull NSNumber*)node resolve + : (RCTPromiseResolveBlock)resolve reject + : (RCTPromiseRejectBlock)reject); +RCT_EXTERN_METHOD(unlockCurrentExposure + : (nonnull NSNumber*)node resolve + : (RCTPromiseResolveBlock)resolve reject + : (RCTPromiseRejectBlock)reject); @end diff --git a/package/ios/CameraViewManager.swift b/package/ios/CameraViewManager.swift index 250daf0..2db0e76 100644 --- a/package/ios/CameraViewManager.swift +++ b/package/ios/CameraViewManager.swift @@ -110,6 +110,18 @@ final class CameraViewManager: RCTViewManager { resolve(result.descriptor) } } + + @objc + final func lockCurrentExposure(_ node: NSNumber, resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) { + let component = getCameraView(withTag: node) + component.lockExposure(promise: Promise(resolver: resolve, rejecter: reject)) + } + + @objc + final func unlockCurrentExposure(_ node: NSNumber, resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) { + let component = getCameraView(withTag: node) + component.unlockExposure(promise: Promise(resolver: resolve, rejecter: reject)) + } // MARK: Private diff --git a/package/ios/Core/CameraSession+Video.swift b/package/ios/Core/CameraSession+Video.swift index 5489997..fc3f769 100644 --- a/package/ios/Core/CameraSession+Video.swift +++ b/package/ios/Core/CameraSession+Video.swift @@ -18,8 +18,6 @@ extension CameraSession { filePath: String, onVideoRecorded: @escaping (_ video: Video) -> Void, onError: @escaping (_ error: CameraError) -> Void) { - - lockCurrentExposure(for: captureSession) // Run on Camera Queue CameraQueues.cameraQueue.async { let start = DispatchTime.now() @@ -194,34 +192,63 @@ extension CameraSession { } } - func lockCurrentExposure(for session: AVCaptureSession) { - guard let captureDevice = AVCaptureDevice.default(for: .video) else { + func lockCurrentExposure(promise: Promise) { + CameraQueues.cameraQueue.async { + withPromise(promise) { + guard let captureDevice = AVCaptureDevice.default(for: .video) else { print("No capture device available") return - } - - do { + } + + do { // Lock the device for configuration try captureDevice.lockForConfiguration() - + // Get the current exposure duration and ISO let currentExposureDuration = captureDevice.exposureDuration let currentISO = captureDevice.iso - + // Check if the device supports custom exposure settings if captureDevice.isExposureModeSupported(.custom) { - // Lock the current exposure and ISO by setting custom exposure mode - captureDevice.setExposureModeCustom(duration: currentExposureDuration, iso: currentISO, completionHandler: nil) - ReactLogger.log(level: .info, message: "Exposure and ISO locked at current values") + // Lock the current exposure and ISO by setting custom exposure mode + captureDevice.setExposureModeCustom(duration: currentExposureDuration, iso: currentISO, completionHandler: nil) + ReactLogger.log(level: .info, message: "Exposure and ISO locked at current values") } else { - ReactLogger.log(level: .info, message:"Custom exposure mode not supported") + ReactLogger.log(level: .info, message:"Custom exposure mode not supported") } - + // Unlock the device after configuration captureDevice.unlockForConfiguration() - - } catch { - ReactLogger.log(level: .warning, message:"Error locking exposure: \(error)") + + } catch { + ReactLogger.log(level: .warning, message:"Error locking exposure: \(error)") + } + + return nil } + } + } + + func unlockCurrentExposure(promise: Promise) { + CameraQueues.cameraQueue.async { + withPromise(promise) { + guard let captureDevice = AVCaptureDevice.default(for: .video) else { + print("No capture device available") + return + } + + do { + if captureDevice.isExposureModeSupported(.autoExpose) { + try captureDevice.lockForConfiguration() + captureDevice.exposureMode = .continuousAutoExposure + captureDevice.unlockForConfiguration() + } + } catch { + ReactLogger.log(level: .warning, message:"Error unlocking exposure: \(error)") + } + + return nil + } + } } } diff --git a/package/src/Camera.tsx b/package/src/Camera.tsx index 1abaaa9..efa8d24 100644 --- a/package/src/Camera.tsx +++ b/package/src/Camera.tsx @@ -319,6 +319,22 @@ export class Camera extends React.PureComponent { throw tryParseNativeCameraError(e) } } + + public async lockCurrentExposure(): Promise { + try { + return await CameraModule.lockCurrentExposure(this.handle) + } catch (e) { + throw tryParseNativeCameraError(e) + } + } + + public async unlockCurrentExposure(): Promise { + try { + return await CameraModule.unlockCurrentExposure(this.handle) + } catch (e) { + throw tryParseNativeCameraError(e) + } + } //#endregion //#region Static Functions (NativeModule) -- 2.46.1