【问题标题】:How do I properly cleanup an AVCaptureSession and AVCaptureVideoPreviewLayer如何正确清理 AVCaptureSession 和 AVCaptureVideoPreviewLayer
【发布时间】:2011-03-23 18:52:18
【问题描述】:

我正在使用 AVFoundation api 创建相机预览视图,完成后我无法清理。

我发现这个问题的最佳答案是SO thread,感谢 Codo。

但是,他没有解决 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 的超级层中删除 _previewLayer 会导致以下控制台错误:

"...修改正在完成的层..."

但是我需要删除层,以便它被释放和解除分配,以便它释放 _camSession,这反过来又释放 dispatch_queue,然后最终调用我的 capture_cleanup 回调,最终释放自我。

我不明白为什么我会收到控制台错误以及如何解决它。如果 self.dealloc 没有被调用,为什么在我打电话给[_previewLayer removeFromSuperlayer] 的时候图层正在完成。

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

【问题讨论】:

    标签: ios ios4


    【解决方案1】:

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

    [captureSession stopRunning];
    

    【讨论】:

      猜你喜欢
      • 2020-02-03
      • 2011-06-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-01-11
      相关资源
      最近更新 更多