Skip to content

Instantly share code, notes, and snippets.

@SatoTakeshiX
Last active December 12, 2022 23:15
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save SatoTakeshiX/440a0b8b3c859d44fcf91dae3e0f8a32 to your computer and use it in GitHub Desktop.
Save SatoTakeshiX/440a0b8b3c859d44fcf91dae3e0f8a32 to your computer and use it in GitHub Desktop.
AVFundation by SwiftUI with Coordinator.
struct ErrorInfo: Error {
var showError: Bool
var message: String
}
struct ContentView: View {
@State var errorInfo: ErrorInfo = ErrorInfo(showError: false, message: "")
@State var onAppear: Bool = false
var body: some View {
ZStack {
VideoView(showError: $errorInfo.showError, errorMessage: $errorInfo.message, onAppear: $onAppear)
.alert(isPresented: $errorInfo.showError) { () -> Alert in
Alert(title: Text($errorInfo.message.wrappedValue))
}
Text("dddd")
}
.edgesIgnoringSafeArea(.all)
}
}
final class VideoCoordinator: NSObject {
var parent: VideoView
let session: AVCaptureSession = AVCaptureSession()
var previewLayer: AVCaptureVideoPreviewLayer?
private var videoDataOutput: AVCaptureVideoDataOutput?
private var videoDataOutputQueue: DispatchQueue?
private var captureDevice: AVCaptureDevice?
init(parent: VideoView) {
self.parent = parent
}
func sessionStart() {
if session.isRunning { return }
print("session start")
session.startRunning()
}
func stopSession() {
if !session.isRunning { return }
session.stopRunning()
}
/// - Tag: CreateCaptureSession
func setupAVCaptureSession() {
print(#function)
session.sessionPreset = .photo
if let availableDevice = AVCaptureDevice.DiscoverySession(deviceTypes: [.builtInWideAngleCamera], mediaType: .video, position: .back).devices.first {
captureDevice = availableDevice
}
do {
let captureDeviceInput = try AVCaptureDeviceInput(device: captureDevice!)
session.addInput(captureDeviceInput)
} catch let error {
print(error.localizedDescription)
}
let previewLayer = AVCaptureVideoPreviewLayer(session: session)
self.previewLayer = previewLayer
let dataOutput = AVCaptureVideoDataOutput()
dataOutput.videoSettings = [kCVPixelBufferPixelFormatTypeKey as String:kCVPixelFormatType_32BGRA]
if session.canAddOutput(dataOutput) {
session.addOutput(dataOutput)
}
session.commitConfiguration()
let queue = DispatchQueue(label: "FromF.github.com.AVFoundationSwiftUI.AVFoundation")
dataOutput.setSampleBufferDelegate(self, queue: queue)
}
// Removes infrastructure for AVCapture as part of cleanup.
fileprivate func teardownAVCapture() {
if let previewLayer = self.previewLayer {
previewLayer.removeFromSuperlayer()
self.previewLayer = nil
}
}
}
extension VideoCoordinator: AVCaptureVideoDataOutputSampleBufferDelegate {
func captureOutput(_ output: AVCaptureOutput, didDrop sampleBuffer: CMSampleBuffer, from connection: AVCaptureConnection) {
}
}
struct VideoView: UIViewControllerRepresentable {
typealias UIViewControllerType = UIViewController
typealias Coordinator = VideoCoordinator
@Binding var showError: Bool
@Binding var errorMessage: String
@Binding var onAppear: Bool
func makeUIViewController(context: Context) -> UIViewController {
let viewController = UIViewController()
context.coordinator.sessionStart()
if let previewLayer = context.coordinator.previewLayer {
viewController.view.layer.addSublayer(previewLayer)
previewLayer.frame = viewController.view.layer.frame
print("context.coordinator.previewLayer?.frame: make \(String(describing: context.coordinator.previewLayer?.frame))")
}
return viewController
}
func updateUIViewController(_ uiViewController: UIViewController, context: Context) {
context.coordinator.previewLayer?.frame = uiViewController.view.layer.frame
print("context.coordinator.previewLayer?.frame: update \(String(describing: context.coordinator.previewLayer?.frame))")
}
func makeCoordinator() -> VideoCoordinator {
let coordinator = VideoCoordinator(parent: self)
coordinator.setupAVCaptureSession()
return coordinator
}
static func dismantleUIView(_ uiView: UIView, coordinator: VideoCoordinator) {
coordinator.stopSession()
coordinator.teardownAVCapture()
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment