Decode from Video Sample - Use AVCaptureSession as Image Source
DecodeWithAVCaptureSession
is another sample of recognizing barcodes from the video streaming. In this sample, instead of DynamsoftCameraEnhancer
, AVCaptureSession
is used to implement the ImageSourceAdapter
(ISA) so that the CaptureVisionRouter
is able to fetch the video frames.
View the sample code
Generate ImageData from AVCaptureVideoDataOutput
ImageData
is the standard image data type that can be recognized by Dynamsoft SDKs. ISA
is the interface that maintains a video buffer of the ImageData
and deliver the ImageData
objects to Dynamsoft image processing SDKs.
- Create a Class for implementing the video streaming functions with
AVCaptureSession
. - Let your class extend
ImageSourceAdapter
so that you can use ISA APIs. - Receive video frames from AVCaptureVideoDataOutput and generate the image data to ImageData object.
- Send the
ImageData
to the ISA with itsaddImageToBuffer
method. After that the ImageData will be maintained in the video buffer of the ISA.
The following code snippet shows how to generate ImageData from the AVCaptureVideoDataOutput
Code Snippet
- Objective-C
- Swift
@implementation DSCaptureEnhancer - (void)captureOutput:(AVCaptureOutput *)output didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer fromConnection:(AVCaptureConnection *)connection { CVImageBufferRef imageBuffer = CMSampleBufferGetImageBuffer(sampleBuffer); CVPixelBufferLockBaseAddress(imageBuffer, kCVPixelBufferLock_ReadOnly); void *baseAddress = CVPixelBufferGetBaseAddress(imageBuffer); size_t bufferSize = CVPixelBufferGetDataSize(imageBuffer); size_t width = CVPixelBufferGetWidth(imageBuffer); size_t height = CVPixelBufferGetHeight(imageBuffer); size_t bytesPerRow = CVPixelBufferGetBytesPerRow(imageBuffer); CVPixelBufferUnlockBaseAddress(imageBuffer, kCVPixelBufferLock_ReadOnly); NSData *buffer = [NSData dataWithBytes:baseAddress length:bufferSize]; // Create an ImageDate object with the data you extract from the CVImageBuffer DSImageData *imageData = [[DSImageData alloc] initWithBytes:buffer width:width height:heightstride:bytesPerRow format:DSImagePixelFormatARGB8888 orientation:0 tag:nil]; // addImageToBuffer method can add your ImageData to the buffer of ISA. [self addImageToBuffer:imageData]; } @end
// Let your class extend ImageSourceAdapter so that you can use ImageSourceAdapter APIs. class CaptureEnhancer: ImageSourceAdapter, AVCaptureVideoDataOutputSampleBufferDelegate { ... func captureOutput(_ output: AVCaptureOutput, didOutput sampleBuffer: CMSampleBuffer, from connection: AVCaptureConnection) { let imageBuffer:CVImageBuffer = CMSampleBufferGetImageBuffer(sampleBuffer)! CVPixelBufferLockBaseAddress(imageBuffer, .readOnly) let baseAddress = CVPixelBufferGetBaseAddress(imageBuffer) let bufferSize = CVPixelBufferGetDataSize(imageBuffer) let width = CVPixelBufferGetWidth(imageBuffer) let height = CVPixelBufferGetHeight(imageBuffer) let bytesPerRow = CVPixelBufferGetBytesPerRow(imageBuffer) CVPixelBufferUnlockBaseAddress(imageBuffer, .readOnly) let buffer = Data(bytes: baseAddress!, count: bufferSize) // Create an ImageDate object with the data you extract from the CVImageBuffer let imageData = ImageData(bytes: buffer, width: UInt(width), height: UInt(height), stride: UInt(bytesPerRow), format: .ARGB8888, orientation: 0, tag: nil) // addImageToBuffer method can add your ImageData to the buffer of ISA. addImageToBuffer(imageData) } }
Setup CaptureVisionRouter with the ISA You Implemented Above
The following code snippet show how to bind the ISA
you implemented above to the CaptureVisionRouter
and start barcode decoding.
- Objective-C
- Swift
// Let your view controller implement CapturedResultReceiver. @interface ViewController () <DSCapturedResultReceiver> ... - (void)setUpDCV { // Initialize the class you created above. self.capture = [[DSCaptureEnhancer alloc] init]; self.cvr = [[DSCaptureVisionRouter alloc] init]; NSError *error; // Bind the `capture` as an ISA instance to your CaptureVisionRouter. [self.cvr setInput:self.capture error:&error]; // Add CapturedResultReceiver to receive barcode decoding results. [self.cvr addResultReceiver:self]; } - (void)onDecodedBarcodesReceived:(DSDecodedBarcodesResult *)result { // Add code to do when barcode decoding results are received. } - (void)viewWillAppear:(BOOL)animated { // Start capturing. [self.cvr startCapturing:DSPresetTemplateReadBarcodes completionHandler:^(BOOL isSuccess, NSError * _Nullable error) { NSAssert((error == nil), error.description); }]; }
// Let your view controller implement CapturedResultReceiver. class ViewController: UIViewController, CapturedResultReceiver { var capture:CaptureEnhancer! let cvr = CaptureVisionRouter() ... func setUpDCV() { // Initialize the class you created above. capture = .init() // Bind the `capture` as an ISA instance to your CaptureVisionRouter. try! cvr.setInput(capture) // Add CapturedResultReceiver to receive barcode decoding results. cvr.addResultReceiver(self) } override func viewWillAppear(_ animated: Bool) { // Start capturing. cvr.startCapturing(PresetTemplate.readBarcodes.rawValue) { isSuccess, error in if (!isSuccess) { if let error = error { print(error) } } } } func onDecodedBarcodesReceived(_ result: DecodedBarcodesResult) { // Add code to do when barcode decoding results are received. } }