2011-03-23 131 views
7

我正在使用AVFoundation api创建相机预览视图,并且在完成后我遇到了清理问题。如何正确清理AVCaptureSession和AVCaptureVideoPreviewLayer

我发现这个问题的最佳答案是在SO thread,谢谢科多。

但是,他没有解决AVCaptureVideoPreviewLayer的重新分配问题,这就是我遇到麻烦的地方。

在我的视图控制器类中我有startCameraCapture方法中的一些初始化代码。听着Codo的回答,我使用dispatch_set_finalizer_f(_captureQueue, capture_cleanup);来注册一个在队列真正关闭时要调用的回调函数。 我也保持自我,以确保我的对象不会在队列完成调用我的对象之前消失。然后我使用capture_cleanup回调释放自我。

-(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];  
} 

这里capture_cleanup回调:

static void capture_cleanup(void* p) 
    { 
     LiveCompViewController* ar = (LiveCompViewController*)p; 
     [ar release]; // releases capture session if dealloc is called 
    } 

然后我清理代码看起来是这样的:

-(void) stopCameraCapture { 
[_camSession stopRunning]; 
    [_camSession release]; 
    _camSession=nil;  

    // Remove the layer in order to release the camSession 
    [_previewLayer removeFromSuperlayer]; 
    _previewLayer = nil; 

} 

我遇到的问题是,从stopCameraCapture的superlayer去除_previewLayer导致以下控制台错误:

"...modifying layer that is being finalized..."

但我需要删除该层,以便它释放并释放,以便它释放_camSession,然后释放dispatch_queue,最后调用我的capture_cleanup回调,最终释放self。

我不明白为什么我得到控制台错误以及如何解决它。为什么当我打电话给[_previewLayer removeFromSuperlayer]时,如果self.dealloc没有被调用,该图层正在最终确定。

注意:self是viewController,我还没有弹出它,所以它由NavigationContoller保留。

回答

2

尝试释放之前停止该会话:

[captureSession stopRunning];