我正在开发一个传输音频的应用程序。我有两个服务正在运行,一个用于接收,一个用于发送。发件人的重要内容如下:
final DatagramSocket dSocket = new DatagramSocket();
android.os.Process
.setThreadPriority(android.os.Process.THREAD_PRIORITY_URGENT_AUDIO);
Log.d(TAG, "Thread starting...");
int buffersize = AudioRecord.getMinBufferSize(11025,
AudioFormat.CHANNEL_CONFIGURATION_MONO,
AudioFormat.ENCODING_PCM_16BIT);
AudioRecord arec = new AudioRecord(
MediaRecorder.AudioSource.MIC, 11025,
AudioFormat.CHANNEL_CONFIGURATION_MONO,
AudioFormat.ENCODING_PCM_16BIT, buffersize);
byte[] buffer = new byte[buffersize];
Log.d(TAG, "Starting to record, buffersize=" + buffersize);
arec.startRecording();
while (isRunning && !isInterrupted()) {
try {
Log.d(TAG, "Recording..");
arec.read(buffer, 0, buffersize);
DatagramPacket dPacket = new DatagramPacket(buffer,
buffersize);
for (Peer cur : mPeers) {
if(cur.isSelf) continue;
dPacket.setAddress(InetAddress
.getByName(cur.IP_ADDRESS));
dPacket.setPort(Config.UDP_PORT);
dSocket.send(dPacket);
}
} catch (Exception e) {
e.printStackTrace();
}
}
此代码可以工作并提交音频数据包。
接收器服务如下所示:
// DatagramSocket dSocket = new DatagramSocket();
DatagramChannel dChannel = DatagramChannel.open();
DatagramSocket dSocket = dChannel.socket();
dSocket.setReuseAddress(true);
dSocket.setSoTimeout(2000);
dSocket.bind(new InetSocketAddress(Config.UDP_PORT));
Log.d(TAG, "DatagramSocket open.");
android.os.Process.setThreadPriority(android.os.Process.THREAD_PRIORITY_URGENT_AUDIO);
int buffersize = AudioRecord.getMinBufferSize(11025,
AudioFormat.CHANNEL_CONFIGURATION_MONO,
AudioFormat.ENCODING_PCM_16BIT);
AudioTrack aTrack = new AudioTrack(
AudioManager.STREAM_VOICE_CALL, 11025,
AudioFormat.CHANNEL_CONFIGURATION_MONO,
AudioFormat.ENCODING_PCM_16BIT, buffersize,
AudioTrack.MODE_STREAM);
DatagramPacket dPacket = new DatagramPacket(
new byte[buffersize], buffersize);
Log.d(TAG, "Packet with buffersize=" + buffersize);
aTrack.play();
Log.d(TAG, "Playing track..");
byte[] buffer = new byte[buffersize];
while (isRunning && !isInterrupted()) {
try {
dSocket.receive(dPacket);
buffer = dPacket.getData();
aTrack.setPlaybackRate(11025);
aTrack.write(buffer, 0, buffer.length);
} catch (Exception e) {
e.printStackTrace();
}
}
aTrack.stop();
这也有效,但是在发送超过几秒后,存在很大的延迟,数据包仍然存在但速度慢且音频播放只是“滞后” - 我该怎么做才能提高质量?这是一种直接的点对点连接,不涉及任何服务器。我应该增加缓冲区大小吗?当前缓冲区大小是我从Android获得的最小缓冲区大小,在我的设备上是1024(两个Galaxy Nexus)。 BTW,启动另一个线程的服务,其优先级设置为“URGENT”(我认为是最高的可用)。就我的目的而言,mPeers列表只有一个对等体,所以“for”循环并没有真正推迟这个我猜。
答案 0 :(得分:2)
您是否检查过删除发送方循环中与网络相关的部分后会发生什么?即,来自麦克风的read() - 呼叫是否立即返回?此外,您描述了数据包缓慢到达,但是您是否检查过它们之间是否存在较长的延迟?
我问的原因是你描述的现象可能是由发送套接字阻塞引起的,因为它的缓冲区已满。如果套接字阻塞,send() - 调用将需要很长时间才能完成。除非你有非常高带宽的流量或非常慢的CPU,否则它不应该发生在UDP套接字上(它们通常会发生故障),但值得检查。
为了避免阻塞,请创建一个非阻塞套接字。我对Java网络不太熟悉,但似乎需要DatagramChannel才能做到这一点。
答案 1 :(得分:0)
好的,所以延迟消失了。我所做的是我只是增加了UDP数据包的缓冲区大小。我从Android收到的最小缓冲区大小是(在我的设备上)1024字节。现在我做这样的事情:
int maxBufferSize = 4096; // my value. see what's working best for you.
int minBufferSize = AudioRecord.getMinBufferSize(11025,
AudioFormat.CHANNEL_CONFIGURATION_MONO,
AudioFormat.ENCODING_PCM_16BIT);
int actualBufferSize = Math.max(minBufferSize, maxBufferSize);
使用4 KB缓冲区,音频传输非常好,绝对没有延迟。