入队数据包延迟时,IOS AudioQueue 不播放

Posted

技术标签:

【中文标题】入队数据包延迟时,IOS AudioQueue 不播放【英文标题】:IOS AudioQueue doesnt play when enqueue packets late 【发布时间】:2016-03-16 18:30:05 【问题描述】:

我有一个将数据包排队到 AudioQueue 的应用程序,它运行良好。问题是当我在网络中出现延迟时,我无法及时向 AudioQueue 提供数据包。

所有应用程序运行良好,enqueueBuffer 没有返回任何错误,但 AudioQueue 正在丢弃数据包(所以我没有声音),因为它们太旧了。

我可以强制 AudioQueue 播放那些音频包吗?或者至少,知道这些包被丢弃了吗?因为如果我知道的话,我可以做 Pause-Play 来重新启动队列......(不是很好的解决方案,但我没有更好的解决方案)

因为延迟可能很大,我不能使用大缓冲区,因为这样可以减少错误,但不能解决它

非常感谢

【问题讨论】:

【参考方案1】:

你在正确的轨道上。当您到达网络缓冲区的末尾时,您可以通过在回调过程中检测,然后暂停 AudioQueue 来处理网络延迟。稍后,一旦缓冲了足够的数据包,就重新启动队列。你的代码应该是这样的

if playerState.packetsRead == playerState.packetsWritten 
    playerState.isPlaying = false
    AudioQueuePause(aq)

在你的网络代码中

if (playerState.packetsWritten >= playerState.packetsRead + kNumPacketsToBuffer) 
    if !playerState.isPlaying 
        playerState.isPlaying = true

        for buffer in playerState.buffers 
            audioCallback(playerState, aq: playerState.queue, buffer: buffer)
        

        AudioQueueStart(playerState.queue, nil)
    

您还需要更新您的代码,以便每次从网络收到数据包时,playerState.packetsWritten 都会增加,当您将数据包添加到音频队列时,playerState.packetsRead 也是如此。 kNumPacketsToBuffer 的最佳数量取决于编解码器和网络条件。我建议将 256 用于 AAC 并根据性能向上/向下调整。

【讨论】:

非常感谢。那是非常有用的信息。如果我可以强制播放所有数据包(完全不丢弃),那就太好了。但至少,这是个好主意。 暂停队列不会导致数据包被丢弃。音频队列维护一个内部时间线(您可以使用AudioQueueGetCurrentTime: 检索),即使没有任何数据包正在播放,它也会继续前进。当您将包含比当前时间更早的数据包的缓冲区排入队列时,这些数据包将被丢弃。暂停队列也会暂停时间线,因此如果您在数据包用完之前暂停,然后在收到延迟的数据包后恢复播放,这些数据包不会被视为旧数据包,并且会正确播放。

以上是关于入队数据包延迟时,IOS AudioQueue 不播放的主要内容,如果未能解决你的问题,请参考以下文章

ios AudioQueue 流式传输多首歌曲

iOS:使用 AudioQueue 时快进音频

ios音频:使用audioqueue改变播放进度

如何从 iOS 上的 AudioQueue 服务获取样本

ios 使用audioQueue 录音以及播放 (pcm)

iPhone 上的音频硬件延迟