Thalatta Thalatta - 8 months ago 114
iOS Question

Unity Vuforia Extension EXC_BAD_ACCESS with AVCaptureSession

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.

Answer Source

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.

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download