你在正确的轨道上。您可以在到达网络缓冲区末尾时检测回拨过程,然后暂停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,并根据性能调整向上/向下。
非常感谢。这是非常有用的信息。如果我可以强制播放所有数据包(根本不丢弃),那将是非常棒的。但至少,这是个好主意。 – WotG
暂停队列不会导致数据包被丢弃。音频队列维持一个内部时间线(您可以使用'AudioQueueGetCurrentTime:'进行检索),即使在没有任何数据包正在播放的情况下,该时间线也会继续前进。当您使用比当前时间早的数据包入队缓冲区时,这些数据包将被丢弃。暂停队列也会暂停时间线,因此如果您在用完数据包之前暂停,则在收到延迟的数据包后继续播放,这些数据包将不会被认为是旧的并且会被正确播放。 – RobHsieh