我正在实施一个RTP接收器。它接收UDP数据包,解码编解码器并将PCM样本写入AudioTrack
进行回放。一个问题似乎是,AudioTrack.write
正在阻塞,因此我会在此期间错过UDP数据包。
有没有关于如何处理这个问题的已知解决方案?
我尝试将自己的缓冲区用于音频数据和setNotificationMarkerPosition
,但似乎只有在缓冲区填充到某种程度时才会播放音频轨道,因此永远不会达到标记位置或{{1}再次变得阻塞。
我还尝试在每次写入之前执行audioTrack.write
,然后再次audioTrack.pause()
,但这似乎会显着影响音质。
答案 0 :(得分:3)
我不知道你是否解决了你的问题,我有一些问题。我能做的最好的事情是将一个线程中的UDP数据包抓取到ArrayBlockingQueue(ABQ)中,然后在另一个从ABQ中逐个获取的线程中播放它们。但是这次播放受到影响(并非所有设备都有,一些设备很酷,双线程),ABQ的大小增加,这意味着延迟增加。因此,我检查大小并系统地丢弃一些数据包(只是不写入AudioTrack)以减少延迟,但如果你对延迟没问题就是你的电话。
还有一件事,我正在增加线程的优先级:
private class Player extends Thread {
public void run() {
Process.setThreadPriority(Process.THREAD_PRIORITY_AUDIO );
....
}
}
提供更好的速度。
解决方案仍然以某种方式阻塞,但是UDP数据包不会被播放器阻止,直到ABQ大小增加为容量。
答案 1 :(得分:0)
我认为我可能比“添加缓冲区和线程”解决方案更具吸引力。该解决方案为您的(可能)延迟敏感系统增加了一些延迟。这是你可以做的:
注意AudioTrack的缓冲区大小。然后跟踪在最后X毫秒内已经写入缓冲区的字节数(这应该以不太强大的计算方式实现),其中X是您可以适应的音频的毫秒数。缓冲区(基于缓冲区大小和采样率和量化速率(位/样本)和通道数的简单计算)。如果您在X毫秒内写入“缓冲区大小”数据量,那么您应该删除音频数据包。请注意,丢弃数据包也将成为“添加缓冲区和线程”解决方案的症状。
您可能想要添加一个小阈值,以便您永远不会实际填充缓冲区(假设缓冲区比实际缓冲区小一点)。
祝你好运!