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

captureOutput使用dispatch_async处理sampleBuffer报EXC_BAD_ACCESS如何解决

问题根本原因
  • CMSampleBuffer属于Core Foundation类型对象,AVCaptureOutput的captureOutput:didOutputSampleBuffer:fromConnection:代理方法执行结束后,系统会自动回收传入的sampleBuffer
  • 直接用dispatch_async捕获sampleBuffer时,ARC不会自动管理Core Foundation对象的引用计数,也不会自动延长它的生命周期,等异步队列执行block的时候,sampleBuffer已经被释放,访问就触发野指针类的EXC_BAD_ACCESS错误
修复方案

核心逻辑

手动管理sampleBuffer的引用计数,在传入异步block前增加引用计数,使用完成后释放,既可以保证异步访问时buffer有效,也不会出现内存泄漏。

修改后可运行代码

queue1 = dispatch_queue_create("testqueue", DISPATCH_QUEUE_SERIAL);
...

-(void) captureOutput:(AVCaptureOutput*)captureOutput didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer fromConnection:(AVCaptureConnection*)connection{
    // 手动持有sampleBuffer,延长生命周期
    CFRetain(sampleBuffer);
    dispatch_async(queue1, ^{
        if(captureOutput == videoOutput){
            // 原有像素buffer处理逻辑保持不变
            if([writerVideoInput isReadyForMoreMediaData] && recordingAssetWriter.status == AVAssetWriterStatusWriting) {
                [adaptor appendPixelBuffer:pxBuffer withPresentationTime:CMSampleBufferGetPresentationTimeStamp(sampleBuffer)];
            }
        } else if(captureOutput == audioOutput){
            if([assetWriterAudioInput isReadyForMoreMediaData] && recordingAssetWriter.status == AVAssetWriterStatusWriting) {
                [assetWriterAudioInput appendSampleBuffer:sampleBuffer];
            }
        }
        // 使用完成后手动释放,避免内存泄漏
        CFRelease(sampleBuffer);
    });
}
老旧设备额外优化建议
  • 把硬编码的recordingAssetWriter.status == 1替换为系统枚举AVAssetWriterStatusWriting,避免枚举值变动带来的潜在问题
  • 若图像处理逻辑耗时过高,可改用vImage、Metal这类高性能框架做渲染,进一步降低CPU负载
  • 当输入源处于不可写入状态时,主动丢弃当前buffer,避免队列堆积过多未处理数据导致内存暴涨
  • 可适当降低录制分辨率、帧率,匹配老旧设备的性能上限

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.24 16:54:03