因此,我正在努力学习核心媒体的基础知识,因为我需要在我的应用程序中处理实时音频样本.现在,我知道我需要配置一个AVCaptureSession设置,一个是用于获取样本的AVCaptureDevice,一个是处理来自设备的输入并通过captureOutput(...)方法"通知"AN AVCaptureAudioDataSampleBufferDelegateAVCaptureDataOutput.

现在,这一个方法作为一个CMSampleBuffer对象传递给样本,根据Apple的CM文档,它将包含零个或多个媒体(在我的例子中是音频)样本和一个CMBlockBuffer,即

[.]表示数据偏移量的连续范围的CFType对象[...]跨越可能不连续的存储区域.

好的,这有点令人困惑.我不是以英语为母语的人,我很难理解这是什么意思.为什么我需要这个来访问我的样本?它们不是存储为原始二进制数据的数组(因此是同类的和连续的)吗?我猜这与Core Media如何管理底层内存有关,但我搞不清楚.

此外,最后一批样本通过这个CMSampleBufferGetAudioBufferListWithRetainedBlockBuffer方法访问,该方法需要一个指向AudioBufferList的不安全可变指针和指向可选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
        }

}

这背后的内存模型(或管道)是什么?我真的很感谢你的帮助.

推荐答案

它们不是存储为原始二进制数据的数组(因此是同类的和连续的)吗?

不是的.它们显然不是以这种方式存储的,这就是您必须使用CMBlockBuffer来使用它们的原因.如果需要,您可以使用withUnsafeMutableBytes将它们强制到一个连续的块中,但这可能会强制进行复制,并且不能保证闭包接收的指针在闭包之外有效.

分配和复制内存是代价高昂的操作.在实时音频中,最好尽可能避免它们.CMBlockBuffer可以将现有的内存块拼接在一起,而不需要分配单个大块,然后进行复制.它可以只使用指向所有退出块的指针.

保留意味着增加缓冲区上的引用计数.多个对象可以参照相同的块,而无需复制.这是一个引用计数系统.保留会增加计数,释放会减少计数.当它达到零时,内存块变得可供重复使用或被释放.

大多数情况下,SWIFT程序员除了避免保留周期外,并不需要真正与此保留/释放系统进行交互.细节通常由ARC自动处理.但是,在性能关键型环境中理解它可能会很有用.详细信息,请参见Memory Management Programming Guide for Core Foundation.(核心媒体类型通常是核心基础类型,遵循与Cocoa/Objc规则略有不同的核心基础规则.)

有关如何使用此功能的示例,请参阅CMMemoryPool.

Ios相关问答推荐

Swift addtarget方法的默认参数不生效

更新@PersistableEnum时是否需要执行迁移块?

如何解释在SwiftUI视图中观察到持续的数据更改

如何在iOS中以编程方式推送另一个页面?

Xamarin Forms CustomPin iOS Render

如果没有等待,SWIFT Async让任务抛出取消异常

如何删除NavigationView中的默认透明标头?

将 Riverpod 从 StateNotifier 修复为 NotifierProvider 以及应用程序生命周期监控

在 iOS 上启用明文本地流量在 .NET MAUI 中不起作用

uikit中如何触发swiftui功能

SKScene 的更新功能似乎不起作用

SwiftUI 图像与下拉视图切换一起 skip

SwiftUI withAnimation 在视图出现之前不会启动

如何在 Swift 中从另一个视图控制器将元素附加到数组中

如何在 Swift 中使用包含多个值的查询参数构建一个 URL?

无论我将构建版本或应用程序版本更改为什么,都会出现 ITEMS-4238冗余二进制上传错误

为信用卡输入格式化 UITextField,例如 (xxxx xxxx xxxx xxxx)

在 iPhone 应用程序中使用 SSL - 出口合规性

Parse for iOS:try 运行应用程序时出错

Flutter:如何创建一个新项目