Я использую классы AV Foundation для захвата живого видеопотока с камеры и обработки образцов видео. Это хорошо работает. Тем не менее, у меня возникают проблемы с тем, чтобы правильно освободить экземпляры баз данных AV (сеанс захвата, уровень предварительного просмотра, ввод и вывод), как только я закончу.
Когда мне больше не нужен сеанс и все связанные объекты, я останавливаю сеанс захвата и отпускаю его. Это работает большую часть времени. Однако иногда приложение выходит из строя с сигналом EXEC_BAD_ACCESS, поднятым во втором потоке, который был создан диспетчерской очередью (и где обрабатываются образцы видео). Авария в основном связана с моим собственным экземпляром класса, который служит делегатом примера буфера и освобождается после того, как я остановил сеанс захвата.
В документации Apple упоминается проблема: остановка сеанса захвата - асинхронная операция. То есть: это происходит не сразу. В частности, второй поток продолжает обрабатывать образцы видео и получать доступ к различным экземплярам, таким как сеанс захвата или устройства ввода и вывода.
Итак, как правильно освободить AVCaptureSession и все связанные с ней экземпляры? Есть ли уведомление, которое достоверно сообщает мне о завершении работы AVCaptureSession?
Здесь мой код:
Объявления:
AVCaptureSession* session;
AVCaptureVideoPreviewLayer* previewLayer;
UIView* view;
Настройка экземпляров:
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];
Очистка:
[previewLayer removeFromSuperlayer];
[previewLayer release];
[session stopRunning];
[session release];