You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

AVFoundation存储实时CMSampleBuffer到数组时回调停止问题

解决AVCaptureVideoDataOutput缓冲区耗尽导致回调停止的问题

问题背景

修改苹果AVCam示例代码,想要存储最新的20个CMSampleBuffer到数组中。实现AVCaptureVideoDataOutputSampleBufferDelegate协议、创建并连接VideoDataOutput并设置代理后,在回调中直接将sampleBuffer存入数组:

var bufferArray:[CMSampleBuffer] = []
func captureOutput(_ output: AVCaptureOutput, didOutput sampleBuffer: CMSampleBuffer, from connection: AVCaptureConnection) {
    if bufferArray.count > 20{
       bufferArray.removeFirst()
     }
     bufferArray.append(sampleBuffer)
}

但回调执行5-10次后就停止,同时其他相机应用预览出现卡顿。仅持有单个buffer引用时一切正常,调整捕获设置无效。后续在didDrop回调中发现报错:DroppedFrameReason(P) = OutOfBuffers,对应苹果文档说明:

提供sample buffer的模块已耗尽源缓冲区。此情况通常由客户端长时间持有缓冲区导致,可通过将缓冲区返回给提供者缓解。

问题根源

CMSampleBuffer是AVFoundation内部缓冲区池管理的对象,直接将原始sampleBuffer存入数组会持续持有其引用,导致AVFoundation无法回收这些缓冲区进行复用。当缓冲区池被耗尽后,AVFoundation就会停止触发didOutput回调,同时出现丢帧、其他相机应用卡顿的情况。

而仅持有单个buffer时,新的buffer会覆盖旧的引用,旧的buffer引用释放后能被AVFoundation回收,因此不会出现缓冲区耗尽问题。

解决方案

核心是不要直接持有原始CMSampleBuffer,而是创建副本存入数组,同时及时释放原始buffer归还到缓冲区池:

代码实现

var bufferArray:[CMSampleBuffer] = []

func captureOutput(_ output: AVCaptureOutput, didOutput sampleBuffer: CMSampleBuffer, from connection: AVCaptureConnection) {
    // 创建原始buffer的副本,保留数据内容
    var copiedBuffer: CMSampleBuffer?
    CMSampleBufferCreateCopy(nil, sampleBuffer, &copiedBuffer)
    
    guard let validCopiedBuffer = copiedBuffer else {
        // 副本创建失败时,直接释放原始buffer
        CMSampleBufferInvalidate(sampleBuffer)
        return
    }
    
    // 维护数组最多保留20个副本,同时释放旧的副本
    if bufferArray.count >= 20 {
        let oldBuffer = bufferArray.removeFirst()
        CMSampleBufferInvalidate(oldBuffer)
    }
    bufferArray.append(validCopiedBuffer)
    
    // 释放原始buffer,归还到AVFoundation的缓冲区池
    CMSampleBufferInvalidate(sampleBuffer)
}

关键说明

  1. 使用CMSampleBufferCreateCopy创建副本:数组中存储独立的buffer副本,不会占用AVFoundation的缓冲区池资源。
  2. 调用CMSampleBufferInvalidate释放资源:无论是原始buffer还是不再需要的副本,调用该方法可释放对应资源,避免内存泄漏和缓冲区池耗尽。
  3. 控制数组容量:当元素超过20个时,移除最旧的副本并释放资源,保证内存占用可控。

内容的提问来源于stack exchange,提问作者Perry Wang

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.06 16:05:24