【问题标题】:VoIP RTP Streaming from/to server (in Java) to/from androidVoIP RTP 从/到服务器(在 Java 中)到/从 android 流式传输
【发布时间】:2015-09-06 00:56:12
【问题描述】:

我的目标是在 GSM/UMTS/LTE 网络中拥有一键通聊天应用;最初我想使用多播地址和点对点而不会使服务器过载;不幸的是,经过深入调查,我发现在 GSM/UMTS/LTE 网络中不允许多播,因此我必须使用服务器来反弹 VoIP 数据包。我不太喜欢这个解决方案,因为我必须使服务器超载,但我没有找到更好的解决方案。如果您有替代解决方案,非常感谢...

因此,我必须将 VoIP 从 android 客户端发送到服务器 (PC),反之亦然。服务器是Java,它必须接收VoIP数据包,然后将VoIP数据包发送给其他N个客户端;服务器是 VoIP 数据包的保镖。

我开发了代码,但它不起作用;我没有任何错误,只是我的 VoIP 服务非常糟糕:我丢失了很多碎片,而且我听到的噪音很大……错误在哪里?我想它应该在服务器代码中;服务器只是获取数据包并重新发送它们,而不知道它们是 RTP 上的 VoIP。

请在下面找到

  • 我用来将 VoIP 数据包发送到服务器的代码。它之所以有效,是因为当我将它用于将 VoIP 数据包直接从 Android 发送到 Android 的个人呼叫时,我没有问题;在android中接收来自服务器的数据包的代码非常相似,所以我不重新复制它。如您所见,我使用 android.net.rtp 。
  • 我在 Java 服务器上用于反弹 VoIP 数据包的代码

提前谢谢你,福斯托

// 用于向服务器发送 VOIP 的 ANDROID 代码

//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);

//用于从 ANDROID 接收 VOIP 并将其重新发送到服务器的 JAVA 服务器代码

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();                                        

【问题讨论】:

    标签: java android voip rtp datagram


    【解决方案1】:

    您没有提供有关您的应用程序的足够详细信息。对于任何 UDP 流应用程序,您需要解决以下问题:

    • 网络抖动和缓冲:当一个数据包到达时,您无法在收到它后立即播放音频,因为下一个数据包可能比预期的晚,并且您的音频播放会有间隙。到达率的变化称为网络抖动。在尝试播放之前,您需要缓冲一些数据。通常你会使用某种环形缓冲区。

    • 丢包:UDP 会丢包。你需要“处理”这个问题。如果您发送 10 个数据包而数据包 #4 丢失,则不能播放数据包 #3 和数据包 #5。听起来会很糟糕。处理方法:

      • 丢失隐藏:尽量减少丢失数据包的不良影响。您可以播放静音(尽管这听起来不是最好的,除非您将其淡化为静音)。您可以通过检查周围的数据包生成丢失的音频来“估计”丢失的音频。
      • 前向纠错:多次发送数据包。有很多方法和方案。权衡是更高的延迟和更高的网络利用率
    • 无序到达:数据包可能无序到达。使用 RTP 序列号来处理这个问题。

    音频流不是一项简单的任务。您不能只是打开一个套接字,发送数据,然后在另一端播放它并期望它能够工作。您对 UDP 流媒体最大的担忧是网络抖动和数据包丢失。如果您不想处理损失并且可能会有一些额外的延迟,请使用 TCP,但请确保在开始播放之前缓冲足够的音频。

    【讨论】:

    • 首先非常感谢您;我试图接受你的回答,但我知道我需要 15 名声望……顺便说一下,有些疑问:我通过 Android.net.rtp 包发送 VoIP,我想应该已经处理好了所有事情(RTP、抖动、FEC , 等等...);问题是我必须使用什么才能在服务器中接收这些数据包并将它们重新发送给其他adroids客户端(他们将再次使用android.net.RTP包来接收)。 ps:我认为已经添加了有关我的应用程序的所有详细信息,缺少什么?
    • android.net.RTP 只实现了 RTP,它是 UDP 之上的应用协议。也就是说,rtp 只是数据的一种规范。数据交付的质量完全从数据的格式(规范)中抽象出来。传输速度、FEC、丢失隐藏、抖动、缓冲等完全在 RTP 规范之外实现。因此,您已经决定如何根据您的应用程序实现它。没有单一的最佳方法来进行缓冲、FEC 等。这取决于您的应用程序。
    • @jaybers - 你的帖子非常有帮助。发布我的问题后才看到您的答案。 link。如果我仍然可以处理网络抖动和缓冲,您能否快速检查一下我的实现?
    • 如果您觉得我的帖子有用,请增加我的声誉。 :-) 。只需单击“向上”箭头...在此先感谢您。福斯托
    • 当你说缓冲一些数据量时,你的意思是减小接收缓冲区大小吗?
    猜你喜欢
    • 2014-06-06
    • 1970-01-01
    • 2019-01-20
    • 2013-05-11
    • 2010-12-09
    • 2010-09-27
    • 1970-01-01
    • 1970-01-01
    • 2012-01-24
    相关资源
    最近更新 更多