【问题标题】:My application suffers OutOfBuffers as a frame dropping reason我的应用程序因丢帧原因而遭受 OutOfBuffers
【发布时间】:2017-04-29 22:29:49
【问题描述】:

在大量使用我的运行AVCaptureSession 实例的应用程序之后,它正在遭受痛苦

DroppedFrameReason(P) = OutOfBuffers

这是来自 - (void)captureOutput:(AVCaptureOutput *)captureOutput didDropSampleBuffer:(CMSampleBufferRef)sampleBuffer fromConnection:(AVCaptureConnection *)connection 中 SampleBuffer 对象的详细信息

CMSampleBuffer 0x10de70770 retainCount: 1 allocator: 0x1b45e2bb8
    invalid = NO
    dataReady = YES
    makeDataReadyCallback = 0x0
    makeDataReadyRefcon = 0x0
    buffer-level attachments:
        DroppedFrameReason(P) = OutOfBuffers
    formatDescription = <CMVideoFormatDescription 0x174441e90 [0x1b45e2bb8]> {
    mediaType:'vide' 
    mediaSubType:'BGRA' 
    mediaSpecific: {
        codecType: 'BGRA'       dimensions: 480 x 360 
    } 
    extensions: {<CFBasicHash 0x174a61100 [0x1b45e2bb8]>{type = immutable dict, count = 5,
entries =>
    0 : <CFString 0x1ae9fa7c8 [0x1b45e2bb8]>{contents = "CVImageBufferYCbCrMatrix"} = <CFString 0x1ae9fa808 [0x1b45e2bb8]>{contents = "ITU_R_601_4"}
    1 : <CFString 0x1ae9fa928 [0x1b45e2bb8]>{contents = "CVImageBufferTransferFunction"} = <CFString 0x1ae9fa7e8 [0x1b45e2bb8]>{contents = "ITU_R_709_2"}
    2 : <CFString 0x1aea2c3e0 [0x1b45e2bb8]>{contents = "CVBytesPerRow"} = <CFNumber 0xb000000000007802 [0x1b45e2bb8]>{value = +1920, type = kCFNumberSInt32Type}
    3 : <CFString 0x1aea2c460 [0x1b45e2bb8]>{contents = "Version"} = <CFNumber 0xb000000000000022 [0x1b45e2bb8]>{value = +2, type = kCFNumberSInt32Type}
    5 : <CFString 0x1ae9fa8a8 [0x1b45e2bb8]>{contents = "CVImageBufferColorPrimaries"} = <CFString 0x1ae9fa7e8 [0x1b45e2bb8]>{contents = "ITU_R_709_2"}
}
}
}
    sbufToTrackReadiness = 0x0
    numSamples = 0
    sampleTimingArray[1] = {
        {PTS = {3825121221333/1000000000 = 3825.121}, DTS = {INVALID}, duration = {INVALID}},
    }
    dataBuffer = 0x0

我做了一些挖掘,发现This

提供样本缓冲区的模块已用完源缓冲区。 这种情况通常是由客户端持有缓冲区引起的 时间过长,可以通过将缓冲区返回到 提供者。

它们是什么意思:将缓冲区返回给提供者? 有什么办法可以解决吗?

【问题讨论】:

  • 您好,您找到解决方案了吗?即使我被这个错误困住了。
  • 很遗憾,我没有找到解决方案。

标签: ios objective-c avcapturesession core-media


【解决方案1】:

最近遇到这个问题,在阅读这篇文章后找到了解决方案。我觉得值得分享。

在 OP 中提供的链接中,Apple 的文档并没有具体说明“坚持缓冲区”和“提供者”的含义,但这就是它们的意思。

提供者是 VideoOutput 对象,它通过其 AVCaptureVideoDataOutputSampleBufferDelegate 方法向您发送 CMSampleBuffer:

func captureOutput(
    _ output: AVCaptureOutput,
    didOutput sampleBuffer: CMSampleBuffer,
    from connection: AVCaptureConnection
) {
    //do stuff with frames here
}

但是,在 Apple 的文档中,它说它可以一次在内存中保存有限数量的 sampleBuffer。这意味着如果您持有样本缓冲区的时间超过下一帧进入所需的时间,您将遇到一个瓶颈,即当 SampleBuffer 内存被填满时。它必须等待它发出的一个旧的从堆栈中拉出并在它正在执行的任何进程中释放。

举个例子,如果您以 60fps 的速度拉入帧,并且在一个耗时超过 17 毫秒的过程中保持帧,那么您将减少帧。

您应该找出一种方法来更有效地使用框架执行任务,或者像我们一样(在使用 CoreML 时)找出一种方法来使您的流程使用更少的框架来工作。这意味着您只能以输入速率的一小部分发送帧。我们能够使我们的模型以大约 10 fps 的帧速率工作,因此我们只在后置摄像头上每 6 帧发送一个帧。

公平地说,Apple 确实表示这通常是该文档帖子中任何丢帧的罪魁祸首,但他们并不擅长传达这究竟意味着什么。

【讨论】:

    【解决方案2】:

    我注意到在 Swift 5 & Xcode 12.4 & iOS 14.3 中:

    我正在使用 CVMetalTextureCacheCreateTextureFromImage 从捕获会话的 CVPixelBuffer 创建纹理,这会在 10 次读取后导致 outofbuffers 错误。好像是贴图是永久存在还是存在时间过长导致缓冲池溢出的问题。

    奇怪的是,如果我在读取后直接将新创建的 metalTexture 设置为 nil,错误就会消失,可能是由于允许内存更快地释放。因此,可以复制纹理然后将原始纹理设置为 nil 以避免此问题。还在研究中……

    【讨论】:

    • 另外,您可以设置一个字段(我现在找不到它,因为它位于各种 AVCapturexxxyyyzzz 对象中的某个位置,我不记得在哪里)告诉它只显示最后一个缓冲区而不是持有缓冲区池。
    【解决方案3】:

    here你实际上提到了问题和答案

    “这种情况通常是由于客户端持有缓冲区的时间过长,可以通过将缓冲区返回给提供者来缓解。”

    【讨论】:

    • 您只是重复了他对他说的同样的话,而忽略了他的问题“他们的意思是:将缓冲区返回给提供者??我能做些什么修复吗?”
    猜你喜欢
    • 1970-01-01
    • 2020-09-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-01-04
    • 1970-01-01
    • 2013-04-09
    相关资源
    最近更新 更多