iphone - 如何正确释放 AVCaptureSession

标签 iphone multithreading ios camera avfoundation

我正在使用 AVFoundation 类从摄像机捕获实时视频流并处理视频样本。这很好用。但是,完成后我确实无法正确释放 AVFoundation 实例(捕获 session 、预览层、输入和输出)。

当我不再需要 session 和所有关联的对象时,我会停止捕获 session 并释放它。这在大多数情况下都有效。但是,有时应用程序会因调度队列(以及处理视频样本的位置)创建的第二个线程中引发的 EXEC_BAD_ACCESS 信号而崩溃。崩溃主要是由于我自己的类实例,它充当示例缓冲区委托(delegate)并在我停止捕获 session 后被释放。

Apple 文档提到了这个问题:停止捕获 session 是一个异步操作。也就是说:它不会立即发生。特别是,第二个线程继续处理视频样本并访问不同的实例,如捕获 session 或输入和输出设备。

那么我该如何正确释放 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];

最佳答案

这是迄今为止我找到的最佳解决方案。基本思想是使用调度队列的终结器。当调度队列退出时,我们可以确定在处理样本缓冲区的第二个线程中不会再有任何操作。

static void capture_cleanup(void* p)
{
    AugmReality* ar = (AugmReality *)p; // cast to original context instance
    [ar release];  // releases capture session if dealloc is called
}

...

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

...

不幸的是,我现在必须明确停止捕获。否则释放我的实例不会释放它,因为第二个线程现在也会递增和递减计数器。

另一个问题是我的类现在从两个不同的线程中释放。这是可靠的还是下一个导致崩溃的问题?

关于iphone - 如何正确释放 AVCaptureSession,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3741121/

相关文章:

c++ - 什么时候使用 std::launch::deferred?

ios - 如何在 Swift 代码中为 3 个条件编写三元条件运算符

ios - 如何替换 Xcode 生成的包标识符,如何在另一台 Mac 上测试 iPad 应用程序到 mac Catalyst,如何进行直播

ios - 将 NSUInteger 赋值给 BOOL 概念理解

iphone - 导致 SIGABRT 的 NSNumber

ios - 核心数据保存数组和字典 - 最佳实践

ios - 在 subview 中添加相同的图层会改变其视觉位置

ios - CIContext、iOS 9 和内存问题

.net - 空工作线程,它们是什么?

c# - Webbrowser InvokeScript 函数阻塞 Windows Phone 8 中的 UI 线程