Wie man eine AVCaptureSession richtig veröffentlicht

Ich verwende die AV Foundation-Klassen, um den Live-Videostream von der Kamera aufzunehmen und die Videobeispiele zu verarbeiten. Das funktioniert gut. Ich habe jedoch Probleme, die AV-Foundation-Instanzen (Erfassungssitzung, Vorschauebene, Eingabe und Ausgabe) ordnungsgemäß freizugeben, sobald ich fertig bin.

Wenn ich die Sitzung und alle zugehörigen Objekte nicht mehr benötige, beende ich die Erfassungssitzung und gebe sie frei. Dies funktioniert meistens. Manchmal stürzt die App jedoch mit einem EXEC_BAD_ACCESS-Signal ab, das im zweiten Thread ausgelöst wird, der von der Versandwarteschlange erstellt wurde (und in dem die Videobeispiele verarbeitet werden). Der Absturz ist hauptsächlich auf meine eigene Klasseninstanz zurückzuführen, die als Beispielpuffer-Delegat fungiert und freigegeben wird, nachdem ich die Erfassungssitzung beendet habe.

In der Apple-Dokumentation wird das Problem erwähnt: Das Beenden der Erfassungssitzung ist eine asynchrone Operation. Das heißt: es passiert nicht sofort. Insbesondere verarbeitet der zweite Thread weiterhin Videobeispiele und greift auf verschiedene Instanzen zu, z. B. die Erfassungssitzung oder die Eingabe- und Ausgabegeräte.

Wie kann ich die AVCaptureSession und alle zugehörigen Instanzen ordnungsgemäß freigeben? Gibt es eine Benachrichtigung, die mir zuverlässig mitteilt, dass die AVCaptureSession beendet wurde?

Hier ist mein Code:

Deklarationen:

AVCaptureSession* session;
AVCaptureVideoPreviewLayer* previewLayer;
UIView* view;

Einrichtung von Instanzen:

AVCaptureDevice* camera = [AVCaptureDevice defaultDeviceWithMediaType: AVMediaTypeVideo];
session = [[AVCaptureSession alloc] init];

AVCaptureDeviceInput* input = [AVCaptureDeviceInput deviceInputWithDevice: camera error: &error];
[session addInput: input];
AVCaptureVideoDataOutput* output = [[[AVCaptureVideoDataOutput alloc] init] autorelease];
[session addOutput: output];

dispatch_queue_t queue = dispatch_queue_create("augm_reality", NULL);
[output setSampleBufferDelegate: self queue: queue];
dispatch_release(queue);

previewLayer = [[AVCaptureVideoPreviewLayer layerWithSession: session] retain];
previewLayer.frame = view.bounds;
[view.layer addSublayer: previewLayer];

[session startRunning];

Aufräumen

[previewLayer removeFromSuperlayer];
[previewLayer release];
[session stopRunning];
[session release];

Antworten auf die Frage(14)

Ihre Antwort auf die Frage