如何正确释放 AVCaptureSession [英] How to properly release an AVCaptureSession

查看:23
本文介绍了如何正确释放 AVCaptureSession的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I'm using the AVFoundation classes to capture the live video stream from the camera and to process the video samples. This works nicely. However, I do have problems properly releasing the AVFoundation instances (capture session, preview layer, input and output) once I'm done.

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

When I no longer need the session and all associated objects, I stop the capture session and release it. This works most of the time. However, sometimes the app crashes with an EXEC_BAD_ACCESS signal raised in the second thread that was created by the dispatch queue (and where the video samples are processed). The crash is mainly due to my own class instance, which serves as the sample buffer delegate and is freed after I've stopped the capture session.

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

The Apple documentation mentions the problem: Stopping the capture session is an asynchronous operation. That is: it doesn't happen immediately. In particular, the second thread continues to process video samples and access different instances like the capture session or the input and output devices.

那么如何正确释放 AVCaptureSession 和所有相关实例?是否有可靠的通知告诉我 AVCaptureSession 已完成?

So how do I properly release the AVCaptureSession and all related instances? Is there a notification that reliably tells me that the AVCaptureSession has finished?

这是我的代码:

声明:

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

推荐答案

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

Here's the best solution I've found so far. The basic idea is to use the finalizer of the dispatch queue. When the dispatch queue quits, we can be sure that there won't be any more action in the second thread where the sample buffers are processed.

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

...

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

Unfortunately, I now have to explicitly stop capturing. Otherwise releasing my instance won't free it because the second thread now increments and decrements the counter as well.

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

A further problem is that my class is now released from two different threads. Is this reliable or is it the next problem causing crashes?

这篇关于如何正确释放 AVCaptureSession的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆