Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Sources/Internal/Manager/CameraManager+Attributes.swift
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ struct CameraManagerAttributes {
var outputType: CameraOutputType = .photo
var cameraPosition: CameraPosition = .back
var isAudioSourceAvailable: Bool = true
var stabilizationLevel: AVCaptureVideoStabilizationMode = .auto
var zoomFactor: CGFloat = 1.0
var flashMode: CameraFlashMode = .off
var lightMode: CameraLightMode = .off
Expand Down
4 changes: 4 additions & 0 deletions Sources/Internal/Manager/CameraManager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ extension CameraManager {
setupCameraLayer()
try setupDeviceInputs()
try setupDeviceOutput()
setVideoStabilizationMode(parent: self)
try setupFrameRecorder()
notificationCenterManager.setup(parent: self)
motionManager.setup(parent: self)
Expand All @@ -84,6 +85,9 @@ private extension CameraManager {
try photoOutput.setup(parent: self)
try videoOutput.setup(parent: self)
}
func setVideoStabilizationMode(parent: CameraManager) {
captureSession.setStabilizationLevel(parent.attributes.stabilizationLevel)
}
func setupFrameRecorder() throws(MCameraError) {
let captureVideoOutput = AVCaptureVideoDataOutput()
captureVideoOutput.setSampleBufferDelegate(cameraMetalView, queue: .main)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,17 @@ import AVKit

extension AVCaptureSession: @unchecked @retroactive Sendable {}
extension AVCaptureSession: CaptureSession {
var deviceInputs: [any CaptureDeviceInput] { inputs as? [any CaptureDeviceInput] ?? [] }

var deviceInputs: [any CaptureDeviceInput] {
inputs as? [any CaptureDeviceInput] ?? []
}

func setStabilizationLevel(_ level: AVCaptureVideoStabilizationMode) {
for connection in self.connections
where connection.isVideoStabilizationSupported {
connection.preferredVideoStabilizationMode = level
}
}
}


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,9 @@
import AVKit

extension MockCaptureSession: @unchecked Sendable {}
class MockCaptureSession: NSObject, CaptureSession { required override init() {}
class MockCaptureSession: NSObject, CaptureSession {
func setStabilizationLevel(_ level: AVCaptureVideoStabilizationMode) { }
required override init() {}
// MARK: Attributes
var isRunning: Bool { _isRunning }
var deviceInputs: [any CaptureDeviceInput] { _deviceInputs }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,4 +24,5 @@ protocol CaptureSession: Sendable {
func add(input: (any CaptureDeviceInput)?) throws(MCameraError)
func remove(input: (any CaptureDeviceInput)?)
func add(output: AVCaptureOutput?) throws(MCameraError)
func setStabilizationLevel(_ level: AVCaptureVideoStabilizationMode)
}
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,15 @@ public extension MCamera {
If disabled, the camera will not record audio, and will not ask for permission to access the microphone.
*/
func setAudioAvailability(_ isAvailable: Bool) -> Self { manager.attributes.isAudioSourceAvailable = isAvailable; return self }

/**
By default, the camera system disables Stabilization.

Setting all video connections to the desired AVCaptureVideoStabilizationMode.
Note: if the desired AVCaptureVideoStabilizationMode is not available, the system will fall back to .off.
It is recommended to perform a separate test for the highest available AVCaptureVideoStabilizationMode.
*/
func setVideoStabilization(_ stabilizationLevel: AVCaptureVideoStabilizationMode) -> Self { manager.attributes.stabilizationLevel = stabilizationLevel; return self }

/**
Changes the initial camera zoom level.
Expand Down