So I am using Unity 2017.2.0f3 with the Vuforia Extension, and I imported the project in an extant iOS project following the https://github.com/blitzagency/ios-unity5 tutorial. The extant iOS project included a view in which you can toggle between an AR view which uses Vuforia, and a native iOS AVCaptureSession which can scan barcodes. The former works without error, but as soon as I try to do session.addInput
or session.addOutput
the latter feature crashes with:
EXC_BAD_ACCESS
within the com.apple.avfoundation.videodataoutput.bufferqueue
Queue.
I tried to use NSZombie to learn more about what kind of object was trying to be sent a message, but i can only run the application on a physical device, and thus I can't learn more about the actual object it tries to send a message to which causes the crash.
My reasoning is that it may have to do with Vuforia persisting a reference to a freed VIdeoDataOutput Buffer Queue which is triggered by my creation of a new AVCaptureSession
with an AVCaptureOutput
and an AVCaptureInput
. What is tricky is that I don't know how to actually ascertain this or not since it is a third party library. The only ViewController which has an Objective-C wrapper is called CameraCapture.mm
but this seems to be a vestigial Unity only View Controller, since any NSLogs
or breakpoints I put in that method are not called.
private func setupCamera() {
guard let device = AVCaptureDevice.defaultDevice(withMediaType: AVMediaTypeVideo),
let input = try? AVCaptureDeviceInput(device: device) else {
return
}
if session.canAddInput(input) {
session.addInputWithNoConnections(input)
}
previewLayer = AVCaptureVideoPreviewLayer(session: session)
previewLayer.frame = self.view.bounds
previewLayer.videoGravity = AVLayerVideoGravityResizeAspectFill
view.layer.addSublayer(previewLayer)
cameraPreviewView.layer.addSublayer(previewLayer)
let metadataOutput = AVCaptureMetadataOutput()
if session.canAddOutput(metadataOutput) {
session.addOutputWithNoConnections(metadataOutput)
metadataOutput.setMetadataObjectsDelegate(self, queue: DispatchQueue.main)
metadataOutput.metadataObjectTypes = metadataOutput.availableMetadataObjectTypes
} else {
print("Could not add metadata output")
}
}
Once the above method is called, even after calling the AppDelegate
function from the blitz tutorial appDelegate.stopUnity()
always crashes the app.
So basically the error I was getting was from Unity not truly exiting when in background. This is a setting which is configurable for iOS Unity exports in Unity itself. If you go to Edit> Player Settings> and then in the Inspector on the right under Other Settings there is a field called Behavior In Background. My original export had this set to Suspend and this caused the AVCaptureSession intrinsic to a Camera in Unity/Vuforia to not be probably cleaned up, in terms of its videoOutput delegate buffer, when Unity wasn't running, thus the resulting EXC_BAD_ACCESS
when thinking I had Unity stopped and starting a new AVCaptureSession
. So by switching Behavior In Background to Exit and then guaranteeing in my app that I had called appDelegate.stopUnity()
before doing setting up input/output pairs for a new AVCaptureSession()
successfully fixed the issue.