Reputation: 12123
So I'm trying to set camera orientation for AVCaptureVideoPreviewLayer
in SwiftUI without deprecated methods (AVCaptureConnection.videoOrientation
is deprecated now) but it doesn't work correct:
struct CameraPreview: UIViewRepresentable {
let previewLayer: AVCaptureVideoPreviewLayer
let rotationCoordiantor: AVCaptureDevice.RotationCoordinator
func makeUIView(context: Context) -> CameraPreviewView {
let view = CameraPreviewView(previewLayer: previewLayer, rotationCoordiantor: rotationCoordiantor)
return view
}
func updateUIView(_ uiView: CameraPreviewView, context: Context) {
// Update the preview layer's frame whenever the view's size changes
uiView.updatePreviewLayerFrame()
}
}
class CameraPreviewView: UIView {
private let previewLayer: AVCaptureVideoPreviewLayer
private let rotationCoordiantor: AVCaptureDevice.RotationCoordinator
init(previewLayer: AVCaptureVideoPreviewLayer, rotationCoordiantor: AVCaptureDevice.RotationCoordinator) {
self.previewLayer = previewLayer
self.rotationCoordiantor = rotationCoordiantor
super.init(frame: .zero)
self.layer.addSublayer(previewLayer)
// actually we don't need to observe device orientation, but just for test
NotificationCenter.default.addObserver(
self,
selector: #selector(orientationDidChange),
name: UIDevice.orientationDidChangeNotification,
object: nil
)
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func layoutSubviews() {
super.layoutSubviews()
updatePreviewLayerFrame()
}
@objc private func orientationDidChange() {
updatePreviewLayerFrame()
}
func updatePreviewLayerFrame() {
previewLayer.frame = self.bounds
print("angle \(rotationCoordiantor.videoRotationAngleForHorizonLevelPreview)")
previewLayer.connection?.videoRotationAngle = rotationCoordiantor.videoRotationAngleForHorizonLevelPreview
Task {
try await Task.sleep(nanoseconds: 1000000000) // delay one second
print("angle \(rotationCoordiantor.videoRotationAngleForHorizonLevelPreview)")
// I get different values here after a second without changing phone orientation,
// so rotationCoordiantor is not synced fast enough with device orientation
}
}
}
When I previously used previewLayer?.connection.videoOrientation = ...
instead of previewLayer.connection?.videoRotationAngle = ...
it worked fine
p.s. RotationCoordiantor
instance was created in ViewModel like this:
rotationCoordiantor = AVCaptureDevice.RotationCoordinator(
device: camera,
previewLayer: previewLayer
)
Upvotes: 2
Views: 132