mirror of
https://github.com/divkit/divkit.git
synced 2026-06-06 20:07:59 +00:00
111 lines
2.8 KiB
Swift
111 lines
2.8 KiB
Swift
import AVFoundation
|
|
import UIKit
|
|
import VGSL
|
|
|
|
typealias LogError = (String) -> Void
|
|
|
|
final class MetadataCaptureSession: NSObject, AVCaptureMetadataOutputObjectsDelegate {
|
|
let result: ObservableProperty<String>
|
|
|
|
private let captureSession = AVCaptureSession()
|
|
private let previewLayer: AVCaptureVideoPreviewLayer
|
|
|
|
private let logError: LogError
|
|
|
|
private var isInitialized = false
|
|
|
|
var layer: CALayer { previewLayer }
|
|
|
|
init(
|
|
result: ObservableProperty<String>,
|
|
logError: @escaping LogError
|
|
) {
|
|
self.result = result
|
|
self.logError = logError
|
|
|
|
previewLayer = AVCaptureVideoPreviewLayer(session: captureSession)
|
|
previewLayer.videoGravity = .resizeAspectFill
|
|
|
|
super.init()
|
|
|
|
guard let videoCaptureDevice = AVCaptureDevice.default(for: .video) else {
|
|
logError("Can't create video capture device")
|
|
return
|
|
}
|
|
|
|
let videoInput: AVCaptureDeviceInput
|
|
do {
|
|
videoInput = try AVCaptureDeviceInput(device: videoCaptureDevice)
|
|
} catch {
|
|
logError("Can't create video input: \(error)")
|
|
return
|
|
}
|
|
|
|
if captureSession.canAddInput(videoInput) {
|
|
captureSession.addInput(videoInput)
|
|
} else {
|
|
logError("Capture session can't add video input")
|
|
return
|
|
}
|
|
|
|
let metadataOutput = AVCaptureMetadataOutput()
|
|
if captureSession.canAddOutput(metadataOutput) {
|
|
captureSession.addOutput(metadataOutput)
|
|
metadataOutput.setMetadataObjectsDelegate(self, queue: DispatchQueue.main)
|
|
metadataOutput.metadataObjectTypes = [.qr]
|
|
} else {
|
|
logError("Capture session can't add metadata output")
|
|
return
|
|
}
|
|
|
|
isInitialized = true
|
|
}
|
|
|
|
func pause() {
|
|
if isInitialized, captureSession.isRunning == true {
|
|
captureSession.stopRunning()
|
|
}
|
|
}
|
|
|
|
func resume() {
|
|
if isInitialized, captureSession.isRunning == false {
|
|
captureSession.startRunning()
|
|
}
|
|
}
|
|
|
|
func didChangeOrientation(to orientation: UIDeviceOrientation) {
|
|
previewLayer.connection?.videoOrientation = orientation.videoOrientation
|
|
}
|
|
|
|
func metadataOutput(
|
|
_: AVCaptureMetadataOutput,
|
|
didOutput metadataObjects: [AVMetadataObject],
|
|
from _: AVCaptureConnection
|
|
) {
|
|
guard let readableObject = metadataObjects.first as? AVMetadataMachineReadableCodeObject,
|
|
let stringValue = readableObject.stringValue else {
|
|
logError("Can't retrieve string value from metadata")
|
|
return
|
|
}
|
|
|
|
result.value = stringValue
|
|
}
|
|
}
|
|
|
|
extension UIDeviceOrientation {
|
|
fileprivate var videoOrientation: AVCaptureVideoOrientation {
|
|
switch self {
|
|
case .portraitUpsideDown:
|
|
return .portraitUpsideDown
|
|
case .landscapeRight:
|
|
return .landscapeLeft
|
|
case .landscapeLeft:
|
|
return .landscapeRight
|
|
case .portrait, .unknown, .faceUp, .faceDown:
|
|
return .portrait
|
|
@unknown default:
|
|
return .portrait
|
|
}
|
|
}
|
|
}
|