2016-03-16 49 views
0

我有一个将数据包排入AudioQueue的应用程序,它的工作完美。问题是当我在网络中出现延迟时,我无法及时向AudioQueue提供数据包。IOS AudioQueue在排队时迟到时不起作用

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

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

因为延迟可能会非常大,我不能使用一个很大的缓冲,因为这将minimice错误,但不能解决它

非常感谢您

回答

0

你在正确的轨道上。您可以在到达网络缓冲区末尾时检测回拨过程,然后暂停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.packetsReadkNumPacketsToBuffer的最佳编号取决于编解码器和网络条件。我建议使用256作为AAC,并根据性能调整向上/向下。

+0

非常感谢。这是非常有用的信息。如果我可以强制播放所有数据包(根本不丢弃),那将是非常棒的。但至少,这是个好主意。 – WotG

+0

暂停队列不会导致数据包被丢弃。音频队列维持一个内部时间线(您可以使用'AudioQueueGetCurrentTime:'进行检索),即使在没有任何数据包正在播放的情况下,该时间线也会继续前进。当您使用比当前时间早的数据包入队缓冲区时,这些数据包将被丢弃。暂停队列也会暂停时间线,因此如果您在用完数据包之前暂停,则在收到延迟的数据包后继续播放,这些数据包将不会被认为是旧的并且会被正确播放。 – RobHsieh