我有两个Java线程,一个在我的电脑上,另一个在Android的手机上。我想通过UDP数据包(点对点连接)将从我电脑上的音频线路上获得的音频流式传输到Android的手机上。
一切都很好,除了有时音频延迟和我的主要问题是延迟。我已经尝试了不同的采样频率和不同的缓冲区大小,但我仍然在两个设备之间有延迟(1-2秒)。
那是我的代码。
Java音频发送器
(new Thread(() -> {
while (true) {
System.out.println(">>"+status);
while (status) {
try {
int size = tdl.read(buffer, 0, buffer.length);
if(size>0){
DatagramPacket sendPacket
= new DatagramPacket(buffer, size, hostAddress, port);
socket.send(sendPacket);
}
} catch (IOException ex) {
Logger.getLogger(AudioSender.class.getName()).log(Level.SEVERE, null, ex);
} catch (java.lang.NullPointerException ne) {
}
}
}
})).start();
public static void setUpAudioDriverInput() throws LineUnavailableException {
if (tdl != null) {
tdl.close();
}
int channels = 1;
int sampleSize = 16;
boolean bigEndian = false;
format = new AudioFormat(rate, sampleSize, channels, true, bigEndian);
DataLine.Info info = new DataLine.Info(TargetDataLine.class, format);
Mixer.Info[] mixerInfo = AudioSystem.getMixerInfo();
Mixer mixer = AudioSystem.getMixer(mixerInfoFinal.get(lineIndex));
tdl = (TargetDataLine) mixer.getLine(info);
tdl.open(format);
tdl.start();
}
Java安卓音频接收器
public void getStreaming(){
getThread = new Thread(new Runnable() {
@Override
public void run() {
try {
System.out.println("Thread Streamer is Starting.. status2"+ status2);
int rate = Integer.parseInt(((Spinner) findViewById(R.id.rateSpinner)).getSelectedItem().toString());
int bufferSize = Integer.parseInt(((Spinner) findViewById(R.id.bufferSizeSpinner)).getSelectedItem().toString());
String payload = ((EditText) findViewById(R.id.nameEditText)).getText().toString();
payload += "#" + rate;
payload += "#" + bufferSize;
payload += "#";
System.out.println(">>>"+payload);
InetAddress address = InetAddress.getByName(((EditText) findViewById(R.id.ipAddressEditText)).getText().toString());
DatagramPacket dp = new DatagramPacket(payload.getBytes(),payload.length(),address,8088);
socket.send(dp);
byte[] buffer = new byte[bufferSize];
AudioTrack audioTrack = new AudioTrack(AudioManager.STREAM_MUSIC, rate, channelConfigOUT, audioFormat, buffer.length, AudioTrack.MODE_STREAM);
audioTrack.play();
DatagramPacket receivedPacket = new DatagramPacket(buffer,buffer.length);
System.out.println("BufferSize "+ bufferSize);
boolean skip=false;
while(status2 && !Thread.currentThread().isInterrupted()){
try {
socket.receive(receivedPacket);
}catch(SocketTimeoutException ste){
skip=true;
Thread.currentThread().interrupt();
stopStreaming();
}
if(!skip) {
buffer = receivedPacket.getData();
audioTrack.write(buffer, 0, buffer.length);
System.out.println("aaa" + Thread.currentThread().getName());
}
}
} catch (SocketException e) {
e.printStackTrace();
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
});
getThread.start();
}
谢谢。
更新我发现这是我尝试的网络,它正在超级转发数据包。对于另一个网络,延迟真的减少到不到半秒。昨天,我可以用它看一部电影,延迟达到了极限。如果我会改进这个系统,我会让你知道的。
发布于 2018-07-05 05:31:19
您不应使用TargetDataLine读取大小来创建DatagramPacket。创建的数据包太多。
最好的方法是读取一些千字节的数据(即多个tdl读取),然后在一个“大”DatagramPacket中发送它们。
https://stackoverflow.com/questions/51180897
复制相似问题