feat: New Core/ library (#1975)
Moves everything Camera related into `core/` / `Core/` so that it is better encapsulated from React Native.
Benefits:
1. Code is much better organized. Should be easier for collaborators now, and cleaner codebase for me.
2. Locking is fully atomically as you can now only configure the session through a lock/Mutex which is batch-overridable
* On iOS, this makes Camera startup time **MUCH** faster, I measured speedups from **1.5 seconds** to only **240 milliseconds** since we only lock/commit once! 🚀
* On Android, this fixes a few out-of-sync/concurrency issues like "Capture Request contains unconfigured Input/Output Surface!" since it is now a single lock-operation! 💪
3. It is easier to integrate VisionCamera outside of React Native (e.g. Native iOS Apps, NativeScript, Flutter, etc)
With this PR, VisionCamera V3 is up to **7x** faster than V2
This commit is contained in:
80
package/ios/Core/CameraSession+CodeScanner.swift
Normal file
80
package/ios/Core/CameraSession+CodeScanner.swift
Normal file
@@ -0,0 +1,80 @@
|
||||
//
|
||||
// CameraSession+CodeScanner.swift
|
||||
// VisionCamera
|
||||
//
|
||||
// Created by Marc Rousavy on 11.10.23.
|
||||
// Copyright © 2023 mrousavy. All rights reserved.
|
||||
//
|
||||
|
||||
import AVFoundation
|
||||
import Foundation
|
||||
|
||||
extension CameraSession: AVCaptureMetadataOutputObjectsDelegate {
|
||||
public func metadataOutput(_: AVCaptureMetadataOutput, didOutput metadataObjects: [AVMetadataObject], from _: AVCaptureConnection) {
|
||||
guard let onCodeScanned = delegate?.onCodeScanned else {
|
||||
// No delegate callback
|
||||
return
|
||||
}
|
||||
guard !metadataObjects.isEmpty else {
|
||||
// No codes detected
|
||||
return
|
||||
}
|
||||
guard let device = videoDeviceInput?.device else {
|
||||
// No cameraId set
|
||||
return
|
||||
}
|
||||
let size = device.activeFormat.videoDimensions
|
||||
|
||||
// Map codes to JS values
|
||||
let codes = metadataObjects.map { object in
|
||||
var value: String?
|
||||
if let code = object as? AVMetadataMachineReadableCodeObject {
|
||||
value = code.stringValue
|
||||
}
|
||||
let x = object.bounds.origin.x * Double(size.width)
|
||||
let y = object.bounds.origin.y * Double(size.height)
|
||||
let w = object.bounds.width * Double(size.width)
|
||||
let h = object.bounds.height * Double(size.height)
|
||||
let frame = CGRect(x: x, y: y, width: w, height: h)
|
||||
|
||||
return Code(type: object.type, value: value, frame: frame)
|
||||
}
|
||||
|
||||
// Call delegate (JS) event
|
||||
onCodeScanned(codes)
|
||||
}
|
||||
|
||||
/**
|
||||
A scanned QR/Barcode.
|
||||
*/
|
||||
struct Code {
|
||||
/**
|
||||
Type of the scanned Code
|
||||
*/
|
||||
let type: AVMetadataObject.ObjectType
|
||||
/**
|
||||
Decoded value of the code
|
||||
*/
|
||||
let value: String?
|
||||
/**
|
||||
Location of the code on-screen, relative to the video output layer
|
||||
*/
|
||||
let frame: CGRect
|
||||
|
||||
/**
|
||||
Converts this Code to a JS Object (Dictionary)
|
||||
*/
|
||||
func toJSValue() -> [String: AnyHashable] {
|
||||
return [
|
||||
"type": type.descriptor,
|
||||
"value": value,
|
||||
"frame": [
|
||||
"x": frame.origin.x,
|
||||
"y": frame.origin.y,
|
||||
"width": frame.size.width,
|
||||
"height": frame.size.height,
|
||||
],
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user