afriscic / BarcodeScanning.Native.Maui

Barcode scanning library for .NET MAUI
https://www.nuget.org/packages/BarcodeScanning.Native.Maui
MIT License
183 stars 33 forks source link

Use AVCaptureMetadataOutput for efficiency #72

Closed breyed closed 4 months ago

breyed commented 4 months ago

To minimize power consumption (and possibly improve performance) on iOS, BarcodeScanning.Native.Maui can use AVCaptureMetadataOutput to detect barcodes rather constantly capturing and analyzing frames. Here is a typical pattern:

let captureSession = AVCaptureSession()
let metadataOutput = AVCaptureMetadataOutput()

override func viewDidAppear(_ animated: Bool) {
    do {
        guard let captureDevice = AVCaptureDevice.default(for: .video) else { throw AvailabilityError() }
        let captureDeviceInput = try AVCaptureDeviceInput(device: captureDevice)
        captureSession.sessionPreset = .medium
        captureSession.addInput(captureDeviceInput)
        captureSession.addOutput(metadataOutput)

        metadataOutput.metadataObjectTypes = [.ean8, .ean13]
        metadataOutput.setMetadataObjectsDelegate(this, queue: DispatchQueue.main)
        Task.detached(priority: .userInitiated) { [weak self] in self?.captureSession.startRunning() }
    } catch {
        // Report error
    }
}

func metadataOutput(_ metadataOutput: AVCaptureMetadataOutput, didOutput metadataObjects: [AVMetadataObject], from _: AVCaptureConnection) {
    guard let barcode = metadataObjects.first as? AVMetadataMachineReadableCodeObject else { return }
    let barcodeText = barcode.stringValue
    // Report the barcode found
}

override func viewWillDisappear(_ animated: Bool) {
    super.viewWillDisappear(animated)
    Task.detached(priority: .userInitiated) { self.captureSession.stopRunning() }
}
afriscic commented 4 months ago

Hello,

I have looked a bit into documentation and other resources online and by the looks of it this is useful for "quick and easy" barcode scanning but other people reported that the detection performance is lower and the detection speed gets slower with time. Also, the result has less data than Vision implementation, especially when all the features get implemented in .NET like payloadData. This projects main focus is continuous barcode scanning with maximum performance so I think I will stick to Vision implementation for now, although Vision consumes more memory even when doing nothing. You can always set PauseScanning to true to bypass the detection logic to save some battery.

breyed commented 4 months ago

I had just assumed that the integrated AVCaptureMetadataOutput solution would be preferable. I didn’t realize that the existing solution was a conscious decision based on awareness of all the options. Thanks for the research and attention to detail.