2015-06-19 5 views
4

Моя цель - использовать приложение чата в сетях GSM/UMTS/LTE; сначала я хотел использовать многоадресные адреса и одноранговые сети без перегрузки сервера; к сожалению, после глубокого расследования я обнаружил, что многоадресная рассылка не разрешена в сетях GSM/UMTS/LTE, поэтому я должен использовать сервер, чтобы отказываться от пакетов VoIP. Я не очень люблю это решение, потому что мне приходится перегружать сервер, но я не нашел лучшего решения. Если у вас есть альтернативное решение, это очень выгодно ...VoIP RTP Потоковая передача с/на сервер (на Java) в/из android

Поэтому я должен отправить VoIP от клиента android на сервер (ПК) и наоборот. Сервер находится на Java, он должен получать пакеты VoIP, а затем отправлять VoIP-пакеты другим клиентам N; сервер является вышибалой пакетов VoIP.

Я разработал код, но он не работает; У меня нет никакой ошибки, просто у меня очень плохое обслуживание VoIP: я теряю много штук, и то, что я слышу, очень шумел ... Где ошибка? Полагаю, что это должно быть в коде сервера; сервер просто получает пакет и повторно отправляет их, не зная, что они VoIP на RTP.

Вы найдете ниже

  • код я использую для отправки пакетов VoIP на сервер. Это работает, потому что у меня нет проблем, когда я использую его для индивидуального вызова, отправляющего пакеты VoIP непосредственно с Android на Android; код для приема в android пакетов с сервера очень похож, поэтому я не возвращаю его. Как вы можете видеть, я использую android.net.rtp.
  • код я использую на сервере Java подпрыгивать пакеты VoIP

Спасибо заранее, Фаусто

// ANDROID КОД используется для отправки VOIP С СЕРВЕРОМ

//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, ИСПОЛЬЗУЕМЫЙ ДЛЯ ПОЛУЧЕНИЯ ГОЛОСОВАНИЯ ИЗ ANDROID И ОТОБРАЗИТЬ ЭТО К СЕРВЕРУ

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

ответ

5

Вы не даете достаточно подробных сведений о своем приложении. При любом UDP потокового приложения вам необходимо рассмотреть следующие вопросы:

  • сети джиттера и Буферизация: Когда пакет прибывает, вы не можете воспроизводить аудио сразу после того, как вы получите его, потому что следующий пакет может быть позже, чем ожидалось, и у вас будет разрыв в воспроизведении звука. Разница в скорости прибытия называется джиттером сети. Перед тем, как вы попытаетесь воспроизвести, вам нужно буферизовать некоторый объем данных. Обычно вы используете какой-то кольцевой буфер.

  • Потеря пакета: будут потери пакетов с UDP. Вам нужно «справиться» с этим. Если вы отправляете 10 пакетов и пакет №4 отсутствует, вы не можете играть в пакет №3, а затем пакет №5. Это будет звучать плохо. Способы решения этой проблемы:

    • Устранение потерь: попытайтесь свести к минимуму плохой эффект от потерянного пакета. Вы можете играть в тишину (хотя это не кажется лучшим, если вы не затухаете в тишине). Вы можете «оценить» потерянный звук, создавая отсутствующий звук, исследуя окружающие пакеты.
    • Прямая коррекция ошибок: отправка пакетов более одного раза. Существует множество способов и схем.Компромисс выше латентности и больше использования сети
  • Непринужденный порядок прибытия: Пакеты могут выходить из строя. Используйте порядковые номера RTP, чтобы справиться с этим.

Аудиопоток - это не тривиальная задача. Вы не можете просто открыть сокет, отправить данные и воспроизвести его на другом конце и ожидать, что он будет работать. Ваша самая большая проблема с потоковой передачей UDP - это дрожание сети и потеря пакетов. Если вы не хотите иметь дело с потерями, и у вас может быть дополнительная латентность, используйте TCP, но будьте уверены, что достаточно будировать звук до начала воспроизведения.

+1

Firt of all thank you very much; я попытался принять ваш ответ, но у меня получилось, что мне нужна 15 репутации ... кстати, некоторые сомнения: я отправляю VoIP по пакету Android.net.rtp, который, я полагаю, должен уже заботиться обо всем (RTP, jitter, FEC , и т.д...); проблема заключается в том, что я должен использовать, чтобы получать на сервере эти пакеты и повторно отправлять их другим клиентам adroids (они будут использовать снова пакет android.net.RTP для получения). ps: Я бы добавил все подробности о моем приложении, чего не хватает? – Fausto70

+0

android.net.RTP только реализует RTP, который является протоколом приложения поверх UDP. То есть, rtp является только спецификацией данных. Качество доставки данных полностью абстрагируется от формата (спецификации) данных. Скорость доставки, FEC, утаивание потерь, дрожание, буферизация и т. Д. Полностью реализованы вне спецификации RTP. Таким образом, вы решаете, как это должно быть реализовано на основе вашего приложения. Существует не один лучший способ делать буферизацию, FEC и т. Д. Это зависит от вашего приложения. – jaybers

+1

@jaybers - Ваш пост очень полезен. Я только что видел ваш ответ после публикации моего вопроса. [Ссылка] (http://stackoverflow.com/questions/32269305/android-play-pcm-byte-array-from-converted-from-base64-string-slow-sounds). Можете ли вы, пожалуйста, быстро проверить мою реализацию, если я все еще могу справиться с дрожанием сети и буферизацией? – hadez30