I'm using the AVFoundation api to create a camera preview view and I'm having trouble cleaning up after I'm done.
The best answer I've found to this problem is in this SO thread, thanks Codo.
However, he doesn't address the deallocation of the AVCaptureVideoPreviewLayer, and that's where I'm having trouble.
In my view controller class I have some initialization code in a startCameraCapture method. Listening to Codo's answer, I'm using dispatch_set_finalizer_f(_captureQueue, capture_cleanup);
to register a callback to be called when the queue is truly closed.
I'm also retaining self, to make sure my object doesn't go away before the queue is done calling my object. I then use the capture_cleanup callback to release self.
-(void) startCameraCapture {
_camSession = [[AVCaptureSession alloc] init];
if (_previewLayer == nil) {
_previewLayer = [AVCaptureVideoPreviewLayer layerWithSession:_camSession];
}
_previewLayer.frame = self.compView.bgView.frame;
[self.compView.bgView.layer addSublayer:_previewLayer];
// Get the default camera device
AVCaptureDevice* camera = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
// Create a AVCaptureInput with the camera device
NSError *error=nil;
AVCaptureInput* cameraInput = [[AVCaptureDeviceInput alloc] initWithDevice:camera error:&error];
if (cameraInput == nil) {
NSLog(@"Error to create camera capture:%@",error);
}
AVCaptureVideoDataOutput* videoOutput = [[[AVCaptureVideoDataOutput alloc] init] autorelease];
// create a queue to run the capture on
_captureQueue=dispatch_queue_create("captureQueue", NULL);
dispatch_set_context(_captureQueue, self);
dispatch_set_finalizer_f(_captureQueue, capture_cleanup);
// setup our delegate
[videoOutput setSampleBufferDelegate:self queue:_captureQueue];
dispatch_release(_captureQueue);
// retain self as a workouround a queue finalization bug in apples's sdk
// per Stackoverflow answer https://stackoverflow.com/questions/3741121/how-to-properly-release-an-avcapturesession
[self retain];
// configure the pixel format
videoOutput.videoSettings = [NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithUnsignedInt:kCVPixelFormatType_32BGRA], (id)kCVPixelBufferPixelFormatTypeKey,
nil];
// and the size of the frames we want
[_camSession setSessionPreset:AVCaptureSessionPresetMedium];
// Add the input and output
[_camSession addInput:cameraInput];
[_camSession addOutput:videoOutput];
[cameraInput release];
// Start the session
[_camSession startRunning];
}
Here the capture_cleanup callback:
static void capture_cleanup(void* p)
{
LiveCompViewController* ar = (LiveCompViewController*)p;
[ar release]; // releases capture session if dealloc is called
}
Then my cleanup code looks like this:
-(void) stopCameraCapture {
[_camSession stopRunning];
[_camSession release];
_camSession=nil;
// Remove the layer in order to release the camSession
[_previewLayer removeFromSuperlayer];
_previewLayer = nil;
}
The problem I'm having is that removing the _previewLayer from the superlayer in stopCameraCapture is causing the following console error:
"...modifying layer that is being finalized..."
But I need to remove the layer so that it gets released and deallocated so that it releases the _camSession which in turn releases the dispatch_queue and then finally calls my capture_cleanup callback which finally releases self.
I don't understand why I'm getting the console error and how to fix it. Why is the Layer being finalized at the time I'm calling [_previewLayer removeFromSuperlayer]
if self.dealloc hasn't been called.
Note: self is a viewController and I haven't popped it yet, so it is retained by the NavigationContoller.
Try stopping the session before releasing:
[captureSession stopRunning];
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With