3

我试图找出在 iPhone 上使用 AudioFileStream 和 AudioQueue API 播放 mp4(或 m4a)音频文件时执行跳过或搜索的正确技术。

如果我将完整的 mp4 标头(直到 mdat 框)传递给打开的 AudioFileStream,则会正确识别底层音频文件类型(在我的情况下为 AAC),然后当我传递文件的实际 mdat 数据部分时,AudioFileStream正确开始生成音频数据包,这些数据包可以发送到 AudioQueue 和播放工作。

但是,如果我尝试使用随机访问方法来播放文件,我似乎无法让它正常工作,除非我总是将 mdat 框的第一帧发送到 AudioFileStream。相反,如果在将 mp4 标头发送到 AudioFileStream 之后,我尝试通过首先调用 AudioFileStreamSeek() 然后传递相关数据包的数据来最初跳到 mdat 中的后一帧,AudioFileStream 似乎会生成音频数据包,但是当我将这些传递给 AudioQueue 并调用 AudioQueuePrime() 时,我总是会收到一个返回“nope”的错误。

我的问题是:在尝试随机播放 mp4 文件中的其他数据包之前,我是否总是需要至少传递 mdat 框的第一个数据包?

在使用 AudioFileStream 和 AudioQueue 时,我似乎找不到任何关于随机播放 mp4 文件部分的文档。我发现 Apple 的 QuickTime File Format pdf 描述了在 mp4 文件中随机搜索的技术,但它只是一个高级描述,并没有提到使用特定的 API(例如 AudioFileStream)。

感谢您的任何见解。

4

1 回答 1

3

事实证明,我使用 AudioFileStreamSeek() 的方法是有效的,我只是没有将完整的初始 mp4 标头发送到 AudioFileStreamParseBytes() 例程。

问题是我假设数据包在 mdat 框标签之后立即开始。通过检查 AudioFileStream Property Listener 回调返回的数据偏移值(kAudioFileStreamProperty_DataOffset),我发现包数据的真正开始是在 18 个字节之后。

这 18 个字节被认为是初始 mp4 标头的一部分,在调用 AudioFileStreamSeek() 之后,在发送任意数据包的数据之前必须将其发送到 AudioFileStream 解析器。

如果这些额外的字节被遗漏,那么即使您可能已经向 AudioQueue 发送了有效的解析音频数据包,AudioQueuePrime() 调用也将始终失败并出现“nope”错误。

于 2009-12-10T18:30:59.360 回答