如何接收RTP流并提取音频? (Java)

时间:2019-07-26 02:43:31

标签: java audio udp rtp codec

简介

您好,我本人和一些同事对通过RTP正确接收音频,然后提取音频流的想法已经用尽,希望在那里的人能为我们指明正确的方向。

背景:

音频流量是通过多播地址和端口通过网络发送的。此流量是基于UDP的RTP。我们需要从数据包中提取音频,然后将其打包到另一个UDP数据包中,然后将其发送到其他地方。

到目前为止,我们的程序目前正在做一些事情,它将接收在多播地址上接收到的数据包并将数据复制到缓冲区中。然后我们删除了前12个字节的数据,因为我们知道这是RTP标头。

在删除字节后,我们使用JAVA JMF库将其转换为InputStream并对其应用了AudioFormat。然后将其发送到SourceDataLine进行本地回放,以验证音频质量。

问题:

播放音频时,声音听起来很差。我可以辨认出音频,但是有很多噪音和破裂/爆裂声。我们无法弄清楚为什么听起来这么糟糕。

我们已经使用VLC验证了RTP音频质量。它可以完美播放,因此我们知道这与我们的代码有关。音频在G.711 PCMU中进行编码,可以使用RTP流分析器中内置的VLC或Wiresharks播放。我们搞砸了AudioFormat设置,但仍然无法使音频干净播放。

我们唯一的想法是音频采样过多,并添加了大量噪声,或者格式化不正确。我提供了一些文件的链接,这些文件可能在尝试重新创建我们的设置时很有用。我们使用bittwist发送wireshark文件中捕获的数据包。

捕获的声音播放听起来很糟糕: https://drive.google.com/open?id=1f4XiNELRVFUsMXgokNwUSnkVO10Ysq_T

G711 Wireshark数据包捕获: https://drive.google.com/open?id=1bZ54KH-KXeHd8CKQEVAU5vawoSiGWZFS

具有良好音频的Wireshark音频提取: https://drive.google.com/open?id=1-ZLXcoPesqsHdniiNqcCwUoZX50PP_mG

Java代码

信用:RustedBrain / MusicHole

ByteArrayOutputStream byteOutputStream;
AudioFormat adFormat;
TargetDataLine targetDataLine;
AudioInputStream InputStream;
SourceDataLine sourceLine;


private AudioFormat getAudioFormat() {
    float sampleRate = 8000.0F;
    int sampleInbits = 8;
    int channels = 1;
    boolean signed = true;
    boolean bigEndian = false;
    return new AudioFormat(sampleRate, sampleInbits, channels, signed, 
bigEndian);
}

public static void main(String args[]) {
    new VUServer().runVOIP();
}

public void runVOIP() {
    try {
        MulticastSocket serverSocket = new MulticastSocket(22202);
        InetAddress group = InetAddress.getByName("239.1.1.1");
        serverSocket.joinGroup(group);
        byte[] receiveData = new byte[10000];
        while (true) {
        DatagramPacket receivePacket = new 
        DatagramPacket(receiveData, receiveData.length);
        serverSocket.receive(receivePacket);
        System.out.println("RECEIVED: " + receivePacket.getAddress().getHostAddress() + " " + receivePacket.getPort() + " " + "Packet Size: " + receivePacket.getLength());
        try {
            byte temp[] = receivePacket.getData();
            byte[] filteredByteArray = Arrays.copyOfRange(temp, 12, receivePacket.getLength() - 12);
            byte audioData[] = filteredByteArray.clone();
            InputStream byteInputStream = new ByteArrayInputStream(audioData);
            AudioFormat adFormat = getAudioFormat();
            InputStream = new AudioInputStream(byteInputStream, adFormat, audioData.length / adFormat.getFrameSize());
            DataLine.Info dataLineInfo = new DataLine.Info(SourceDataLine.class, adFormat);
            sourceLine = (SourceDataLine) AudioSystem.getLine(dataLineInfo);
            sourceLine.open(adFormat);
            sourceLine.start();
            Thread playThread = new Thread(new PlayThread());
            playThread.start();
        } catch (Exception e) {
            System.out.println(e);
            System.exit(0);
        }
    }
} catch (Exception e) {
    e.printStackTrace();
}
}

class PlayThread extends Thread {

byte tempBuffer[] = new byte[10000];

public void run() {
    try {
        int cnt;
        while ((cnt = InputStream.read(tempBuffer, 0, tempBuffer.length)) != -1) {
            if (cnt > 0) {
                sourceLine.write(tempBuffer, 0, cnt);
            }
        }
        //  sourceLine.drain();
        // sourceLine.close();
    } catch (Exception e) {
        System.out.println(e);
        System.exit(0);
    }
}
}

希望我已经对我们的问题进行了充分的解释,以便有人可以找到我们搞砸的地方,并帮助我们重回正轨。

谢谢

奥斯丁

0 个答案:

没有答案