ios 核心媒体基础知识,了解CMSampleBuffer、CMBlockBuffer和CMSampleBufferGetAudioBufferListWithRetainedBlockBuffer

svgewumm  于 2023-03-14  发布在  iOS
关注(0)|答案(1)|浏览(340)

因此,我正在尝试学习Core Media的基础知识,因为我需要在应用程序中处理真实的音频样本。现在我知道我需要配置AVCaptureSession设置、用于采集样本的AVCaptureDevice和处理设备输入并通过captureOutput(...)方法“通知”AVCaptureAudioDataSampleBufferDelegateAVCaptureDataOutput
现在,这个方法将样本作为CMSampleBuffer对象传递,根据Apple的CM文档,它将包含零个或多个媒体(在我的例子中是音频)样本和一个CMBlockBuffer,即
[...]一个CFType对象,表示可能不连续的内存区域中连续的数据偏移量[...]范围。
好吧,这有点让人困惑。我不是一个母语为英语的人,我很难理解这是什么意思。为什么我需要这个来访问我的样本?它们不是存储为原始二进制数据的数组吗(因此同质和连续)?我猜这与Core Media管理底层内存的方式有关,但我不明白。
最后一批样本也是通过CMSampleBufferGetAudioBufferListWithRetainedBlockBuffer方法访问的,该方法需要一个指向AudioBufferList的不安全可变指针和一个指向可选CMBlockBuffer的指针,第一个将填充指向可选CMBlockBuffer的指针,然后我可能(也可能不)能够通过myAudioBufferList.mBuffers.mData访问样本,可能是nil
来自Apple开发人员代码片段的示例代码:

public func captureOutput(_ output: AVCaptureOutput,
                              didOutput sampleBuffer: CMSampleBuffer,
                              from connection: AVCaptureConnection) {

        var audioBufferList = AudioBufferList()
        var blockBuffer: CMBlockBuffer?
  
        CMSampleBufferGetAudioBufferListWithRetainedBlockBuffer(
            sampleBuffer,
            bufferListSizeNeededOut: nil,
            bufferListOut: &audioBufferList,
            bufferListSize: MemoryLayout.stride(ofValue: audioBufferList),
            blockBufferAllocator: nil,
            blockBufferMemoryAllocator: nil,
            flags: kCMSampleBufferFlag_AudioBufferList_Assure16ByteAlignment,
            blockBufferOut: &blockBuffer)
        
        guard let data = audioBufferList.mBuffers.mData else {
            return
        }

}

这背后的内存模型(或管道)是什么?我真诚地感谢任何帮助。

vuktfyat

vuktfyat1#

它们不是存储为原始二进制数据的数组吗(因此是同质的和连续的)?
不可以。它们不是这样存储的,这就是为什么你必须使用CMBlockBuffer来处理它们。如果需要,你可以使用withUnsafeMutableBytes将它们强制放到一个连续的块中,但是这可能会强制进行复制,并且不能保证闭包接收到的指针在闭包之外有效。
分配和复制内存都是代价高昂的操作。在实时音频中,最好尽可能避免这些操作。CMBlockBuffer可以将现有的内存块缝合在一起,而无需分配单个大块,然后进行复制。它可以只使用指向所有现有块的指针。
保留意味着增加缓冲区上的引用计数。多个对象可以引用相同的块而不需要复制。这是一个引用计数系统。保留增加计数,释放减少计数。当它达到零时,内存块可供重用或被释放。
大多数时候Swift程序员并不需要真正与这个保留/释放系统交互,只是为了避免保留周期。细节通常由ARC自动处理。但是在性能关键的上下文中理解它可能是有用的。请参见Core Foundation的内存管理编程指南。(核心媒体类型通常是核心基础类型,并遵循与可可/ObjC规则略有不同的核心基础规则。)
请参见CMMemoryPool,以了解如何使用此函数。

相关问题