AVCaptureOutput didOutputSampleBuffer 停止被调用

AVCaptureOutput didOutputSampleBuffer stops getting called

我对 AVCaptureOutput 的委托方法 didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer fromConnection:(AVCaptureConnection *)connection 有疑问。

当我将 sampleBuffer 添加到 CFArray 时,它会在一两秒内停止调用。如果我删除 CFArray 代码,委托方法将继续被调用,所以我不知道为什么 CFArray 代码导致它停止。如果有任何帮助,我将不胜感激。

@property CFMutableArrayRef sampleBufferArray;

- (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer fromConnection:(AVCaptureConnection *)connection
{
    NSLog(@"Called");

    if (!self.sampleBufferArray)
    {
        self.sampleBufferArray = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
        CFArrayAppendValue(self.sampleBufferArray, sampleBuffer);
    }
    else
    {
        CFArrayAppendValue(self.sampleBufferArray, sampleBuffer);
    }
}

控制台输出:

// Session start
2015-06-15 13:06:07.264 App[22467:5897858] Called
2015-06-15 13:06:07.286 App[22467:5897858] Called
2015-06-15 13:06:07.289 App[22467:5897858] Called
2015-06-15 13:06:07.315 App[22467:5897895] Called
2015-06-15 13:06:07.366 App[22467:5897895] Called
2015-06-15 13:06:07.384 App[22467:5897895] Called
2015-06-15 13:06:07.411 App[22467:5897895] Called
2015-06-15 13:06:07.449 App[22467:5897858] Called
2015-06-15 13:06:07.480 App[22467:5897858] Called
2015-06-15 13:06:07.513 App[22467:5897895] Called
2015-06-15 13:06:07.546 App[22467:5897895] Called
2015-06-15 13:06:07.579 App[22467:5897895] Called
2015-06-15 13:06:07.614 App[22467:5897895] Called
// No more calls after this point

你的问题其实在Docs里有提到,具体来说;

If your application is causing samples to be dropped by retaining the provided CMSampleBufferRef objects for too long, but it needs access to the sample data for a long period of time, consider copying the data into a new buffer and then releasing the sample buffer (if it was previously retained) so that the memory it references can be reused.

本质上,回调操作要尽量简单,回调中传给你的frame如果需要进一步处理,需要复制到新的buffer中进行处理在后台。另外,请记住,Core Foundation 对象必须显式保留和释放。

进一步考虑是内存压力。帧包含大量数据,保留太多会导致您的应用程序崩溃。

我在 Xamarin(C#) iOS 开发中遇到了类似的问题。在 Xamarin 中使用以下代码释放 CMSampleBuffer if:

GC.Collect();
GC.WaitForPendingFinalizers();