@@ -14,15 +14,13 @@ import UIKit
1414extension CodeScannerView {
1515
1616 public final class ScannerViewController : UIViewController , UINavigationControllerDelegate {
17- private let photoOutput = AVCapturePhotoOutput ( )
18- private var isCapturing = false
1917 private var handler : ( ( UIImage ? ) -> Void ) ?
2018 var parentView : CodeScannerView !
2119 var codesFound = Set < String > ( )
2220 var didFinishScanning = false
2321 var lastTime = Date ( timeIntervalSince1970: 0 )
2422 private let showViewfinder : Bool
25-
23+ private var latestSampleBuffer : CMSampleBuffer ?
2624 let fallbackVideoCaptureDevice = AVCaptureDevice . default ( for: . video)
2725
2826 private var isGalleryShowing : Bool = false {
@@ -265,12 +263,15 @@ extension CodeScannerView {
265263 return
266264 }
267265 let metadataOutput = AVCaptureMetadataOutput ( )
266+ let videoOutput = AVCaptureVideoDataOutput ( )
268267
269268 if captureSession!. canAddOutput ( metadataOutput) {
270269 captureSession!. addOutput ( metadataOutput)
271- captureSession!. addOutput ( photoOutput )
270+ captureSession!. addOutput ( videoOutput )
272271 metadataOutput. setMetadataObjectsDelegate ( self , queue: DispatchQueue . main)
273272 metadataOutput. metadataObjectTypes = parentView. codeTypes
273+
274+ videoOutput. setSampleBufferDelegate ( self , queue: DispatchQueue ( label: " com.hackingwithswift.codeScanner.videoQueue " ) )
274275 } else {
275276 didFail ( reason: . badOutput)
276277 return
@@ -433,6 +434,25 @@ extension CodeScannerView {
433434 }
434435}
435436
437+ // MARK: - AVCaptureVideoDataOutputSampleBufferDelegate
438+ @available ( macCatalyst 14 . 0 , * )
439+ extension CodeScannerView . ScannerViewController : AVCaptureVideoDataOutputSampleBufferDelegate {
440+ public func captureOutput( _ output: AVCaptureOutput , didOutput sampleBuffer: CMSampleBuffer , from connection: AVCaptureConnection ) {
441+ latestSampleBuffer = sampleBuffer
442+ }
443+
444+ func processFrame( _ sampleBuffer: CMSampleBuffer ) {
445+ guard let imageBuffer = CMSampleBufferGetImageBuffer ( sampleBuffer) else { return }
446+
447+ let ciImage = CIImage ( cvPixelBuffer: imageBuffer)
448+
449+ let context = CIContext ( )
450+ if let cgImage = context. createCGImage ( ciImage, from: ciImage. extent) {
451+ handler ? ( UIImage ( cgImage: cgImage) )
452+ }
453+ }
454+ }
455+
436456// MARK: - AVCaptureMetadataOutputObjectsDelegate
437457
438458@available ( macCatalyst 14 . 0 , * )
@@ -443,7 +463,6 @@ extension CodeScannerView.ScannerViewController: AVCaptureMetadataOutputObjectsD
443463 guard let metadataObject = metadataObjects. first,
444464 !parentView. isPaused,
445465 !didFinishScanning,
446- !isCapturing,
447466 let readableObject = metadataObject as? AVMetadataMachineReadableCodeObject ,
448467 let stringValue = readableObject. stringValue else {
449468
@@ -484,9 +503,8 @@ extension CodeScannerView.ScannerViewController: AVCaptureMetadataOutputObjectsD
484503 }
485504 }
486505
487- if parentView. requiresPhotoOutput {
488- isCapturing = true
489- photoOutput. capturePhoto ( with: AVCapturePhotoSettings ( ) , delegate: self )
506+ if parentView. requiresPhotoOutput, let latestSampleBuffer {
507+ self . processFrame ( latestSampleBuffer)
490508 } else {
491509 handler ? ( nil )
492510 }
@@ -551,44 +569,6 @@ extension CodeScannerView.ScannerViewController: UIAdaptivePresentationControlle
551569 }
552570}
553571
554- // MARK: - AVCapturePhotoCaptureDelegate
555-
556- @available ( macCatalyst 14 . 0 , * )
557- extension CodeScannerView . ScannerViewController : AVCapturePhotoCaptureDelegate {
558-
559- public func photoOutput(
560- _ output: AVCapturePhotoOutput ,
561- didFinishProcessingPhoto photo: AVCapturePhoto ,
562- error: Error ?
563- ) {
564- isCapturing = false
565- guard let imageData = photo. fileDataRepresentation ( ) else {
566- print ( " Error while generating image from photo capture data. " ) ;
567- return
568- }
569- guard let qrImage = UIImage ( data: imageData) else {
570- print ( " Unable to generate UIImage from image data. " ) ;
571- return
572- }
573- handler ? ( qrImage)
574- }
575-
576- public func photoOutput(
577- _ output: AVCapturePhotoOutput ,
578- willCapturePhotoFor resolvedSettings: AVCaptureResolvedPhotoSettings
579- ) {
580- AudioServicesDisposeSystemSoundID ( 1108 )
581- }
582-
583- public func photoOutput(
584- _ output: AVCapturePhotoOutput ,
585- didCapturePhotoFor resolvedSettings: AVCaptureResolvedPhotoSettings
586- ) {
587- AudioServicesDisposeSystemSoundID ( 1108 )
588- }
589-
590- }
591-
592572// MARK: - AVCaptureDevice
593573
594574@available ( macCatalyst 14 . 0 , * )
0 commit comments