VoIP的RTP流从/服务器(在Java中)向/从机器人机器人、服务器、VoIP、RTP

2023-09-13 02:14:56 作者:时光取名叫无心

我的目标是要在GSM / UMTS / LTE网络即按即说应用聊天;起初我想使用多播地址和对等无过载的服务器;不幸的是,经过深入调查,我发现,多播没有在GSM / UMTS / LTE网络允许,所以我必须使用服务器,以反弹VoIP的数据包。我不很喜欢这个解决方案,因为我有过载的服务器上,但我没有发现任何更好的解决方案。如果你有一个替代的解决方案是非常apprieciated ...

所以我必须从Android客户端发送的VoIP服务器(PC),反之亦然。服务器是在Java中,它具有接收VoIP分组,然后发送VoIP分组到其他N个客户端;服务器的VoIP数据包的保镖。

我developped的code,但它不工作;我没有任何错误,只是我有非常不好的VoIP服务:我失去了很多件和我听到的是非常消噪......哪里的错误?我想这应该是在服务器code;服务器简单地将数据包并重新发送它们,而不知道他们是VoIP的RTP的。

请在下面找到

的code我使用到VoIP数据包发送到服务器。它的工作原理,因为我没有问题,当我使用它的单个呼叫直接从安卓发送的VoIP数据包到Android;在code接收的机器人从服务器的数据包很相似,所以我不重新复制它。正如你可以看到我用android.net.rtp。 的code我用的是Java服务器上,以反弹的VoIP数据包

感谢你在前进,福斯托

// ANDROID code用于发送VOIP服务器

  //属性定义
私有静态最后音频codeC myAudio codec_COSTANTE =音频codec.PCMU;
私有静态最终诠释myAudioGroupTX_COSTANTE = AudioGroup.MODE_NORMAL;
私有静态最终诠释myAudioGroupRX_COSTANTE = AudioGroup.MODE_NORMAL;
私有静态最终诠释myRtpStreamTX_COSTANTE = RtpStream.MODE_SEND_ONLY;
私有静态最终诠释myRtpStreamRX_COSTANTE = RtpStream.MODE_RECEIVE_ONLY;
私有静态最终诠释myAudioManagerTX_COSTANTE = AudioManager.MODE_IN_COMMUNICATION;
私有静态最终诠释myAudioManagerRX_COSTANTE = AudioManager.MODE_IN_COMMUNICATION;

//所谓的VoIP trasmission方法
myAudioStream =新AudioStream(localClientIP);
myAudioGroup =新AudioGroup();
myAudioManager =(AudioManager)myContext.getSystemService(Context.AUDIO_SERVICE);

myAudioGroup.setMode(myAudioGroupTX_COSTANTE);
myAudioStream.join(空);
myAudioStream.set codeC(myAudio codec_COSTANTE);
myAudioStream.setMode(myRtpStreamTX_COSTANTE);
myAudioStream.associate(ipaddress_Server,port_Server)
myAudioStream.join(myAudioGroup);
myAudioManager.setMode(myAudioManagerTX_COSTANTE);
myAudioManager.setSpeakerphoneOn(假);
myAudioManager.setMicrophoneMute(假);
 
新课上线 建立客户体验管理路径,优化客服流程 保险公司客户体验管理课

// Java服务器code用来接收VOIP从Android和重新发送到服务器

  DatagramSocket的datagramSocket_RX_VoIP =新的DatagramSocket();
DatagramSocket的datagramSocket_TX_VoIP =新的DatagramSocket();
INT unicast_port_TX_VoIP = 5000;
字符串unicast_ip_TX_VoIP =192.168.0.3;

    线程t =新主题(新的Runnable(){
    公共无效的run(){
    尝试 {
        DatagramPacket类myPacket;
        而(真){
            myPacket = ManagePacket.initializePacket(); //功能为prepare的PACKE;问题不在这里!
            datagramSocket_RX_VoIP.receive(myPacket);

            InetAddress类PPP = InetAddress.getByName(unicast_ip_TX_VoIP);
            myPacket.setAddress(PPP);
            myPacket.setPort(unicast_port_TX_VoIP);
            datagramSocket_TX_VoIP.send(myPacket);
        }

    }赶上(例外前){
        log.debug(异常:+ ex.getMessage(),前);
    }
    }
    });
    t.start();
 

解决方案

您没有提供足够的细节对您的申请。对于任何UDP流的应用程序,你需要解决以下问题:

网络抖动和缓冲:当数据包到达时您会收到它,因为下一个数据包可能会晚于预期之后,您不能播放音频,你会在你的音频播放的差距。在到达率的差异被称为网络抖动。你需要的数据缓冲一定量的尝试播放之前。通常你使用某种环形缓冲区。

丢包:会有丢包用UDP。你需要解决这个问题。如果发送10个数据包和包#4丢失,你可以不玩包#3,那么数据包#5。它会发出声音不好。方式来处理这样的:

丢失掩盖:尽量减少不良影响过丢失的数据包。你可以玩沉默(虽然这听起来不是最好的,除非你淡化它沉默)。你可以估计丢失的音频通过生成丢失的音频通过检查周围的包。 前向纠错:发送的数据包超过一次。有许多方法和计划。代价是更高的延迟和更多的网络利用率 在乱序到达的:包可以到达的顺序。使用RTP序列号来处理这个

音频流并不是一个简单的任务。你不能只是打开一个套接字,发送数据,并发挥它的另一端,并期望它的工作。您与UDP流最关心的是网络抖动和数据包丢失。如果你不想处理的损失,你可以有一些额外的延迟,使用TCP但要确保在开始播放前缓冲了足够多的音频。

My target is to have a push-to-talk chat app in GSM/UMTS/LTE networks; initially I wanted use multicast addresses and peer-to-peer without overload the server; unfortunatly, after deep investigation, I discovered that multicast is not allowed in GSM/UMTS/LTE networks, therefore I have to use the server in order to bounce the VoIP packets. I' don't like very much this solution because I have to overload the server, but I didn't find any better solution. If you have an alternative solution is very much apprieciated...

Therefore I have to send VoIP from an android client to a server (PC), and viceversa. The server is in Java, it has to receive the VoIP packets and then to send the VoIP packets to other N clients; the server is a bouncer of VoIP packets.

I developped the code, but it doesn't work; I don't have any error, simply I had very bad VoIP service: I loose a lot of pieces and what I hear is very much noised... Where is the error? I suppose It should be in the server code; the server simply get the packet and resend them, without know that they are VoIP on RTP.

Please find below

the code I use to send the VoIP packets to server. It works because I don't have problems when I use it for individual call sending the VoIP packets directly from Android to Android; the code to receive in android the packets from server is very similar, so I don't recopy it. As you can see I use android.net.rtp . the code I use on the Java server to bounce the VoIP packets

Thank you in advance, Fausto

// ANDROID CODE USED TO SEND VOIP TO SERVER

//Attribute definition
private static final AudioCodec myAudioCodec_COSTANTE = AudioCodec.PCMU ; 
private static final int myAudioGroupTX_COSTANTE = AudioGroup.MODE_NORMAL ; 
private static final int myAudioGroupRX_COSTANTE = AudioGroup.MODE_NORMAL ;
private static final int myRtpStreamTX_COSTANTE = RtpStream.MODE_SEND_ONLY ;
private static final int myRtpStreamRX_COSTANTE = RtpStream.MODE_RECEIVE_ONLY ; 
private static final int myAudioManagerTX_COSTANTE = AudioManager.MODE_IN_COMMUNICATION;
private static final int myAudioManagerRX_COSTANTE = AudioManager.MODE_IN_COMMUNICATION; 

//Method called for VoIP trasmission
myAudioStream = new AudioStream(localClientIP);
myAudioGroup = new AudioGroup();
myAudioManager =  (AudioManager) myContext.getSystemService(Context.AUDIO_SERVICE);

myAudioGroup.setMode(myAudioGroupTX_COSTANTE);
myAudioStream.join(null); 
myAudioStream.setCodec(myAudioCodec_COSTANTE);
myAudioStream.setMode(myRtpStreamTX_COSTANTE);
myAudioStream.associate(ipaddress_Server, port_Server)    
myAudioStream.join(myAudioGroup); 
myAudioManager.setMode(myAudioManagerTX_COSTANTE);
myAudioManager.setSpeakerphoneOn(false);
myAudioManager.setMicrophoneMute(false);

//JAVA SERVER CODE USED TO RECEIVE VOIP FROM ANDROID AND TO RESEND IT TO SERVER

DatagramSocket datagramSocket_RX_VoIP= new DatagramSocket();
DatagramSocket datagramSocket_TX_VoIP= new DatagramSocket();
int unicast_port_TX_VoIP = 5000 ;
String unicast_ip_TX_VoIP = "192.168.0.3";

    Thread t = new Thread(new Runnable() {
    public void run() {
    try {
        DatagramPacket myPacket;
        while (true) {
            myPacket = ManagePacket.initializePacket(); //Function to prepare the packe ; the problem is not here!!!
            datagramSocket_RX_VoIP.receive(myPacket);

            InetAddress ppp =  InetAddress.getByName(unicast_ip_TX_VoIP);
            myPacket.setAddress(ppp);
            myPacket.setPort( unicast_port_TX_VoIP ) ;
            datagramSocket_TX_VoIP.send(myPacket);
        }

    }  catch (Exception ex) {
        log.debug("Exception: " + ex.getMessage(), ex);
    }
    }
    });
    t.start();                                        

解决方案

You don't give enough detail about your application. With any UDP streaming application you need to address the following issues:

Network Jitter and Buffering: When a packet arrives, you cannot play the audio immediately after you receive it because the next packet might be later than expected and you will have a gap in your audio playback. The variance in the arrival rate is called network jitter. You need to buffer some amount of data before you try to play back. Usually you use some sort of ring buffer.

Packet loss: There will be packet losses with UDP. You need to "deal" with this. If you send 10 packets and packet #4 is missing, you can't play packet #3 then packet #5. It will sound bad. Ways to deal with this:

Loss Concealment: Try to minimize the bad effect off a packet lost. You can play silence (although this doesn't sound the best unless you fade it to silence). You can "estimate" the lost audio by generating a missing audio by examining the surrounding packets. Forward Error Correction: Send packets more than once. There are numerous ways and schemes. The tradeoff is higher latency and more network utilization Out of order arrivals: Packets may arrive out of order. Use the RTP sequence numbers to deal with this.

Audio streaming is not a trivial task. You can't just open a socket, send data, and play it on the other end and expect it to work. Your biggest concern with UDP streaming is network jitter and packet loss. If you don't want to deal with losses and you can have some extra latency, use TCP but be sure to buffer up enough audio before you start playing.