android - Recibir transmisión RTP-AudioStream, AudioGroup
ffmpeg audio-streaming (2)
Disculpas si lo siguiente es tonto:
La línea de comando ffmpeg parece estar generando un sonido de prueba y emitiéndolo como un flujo de datos pcm a través de RTP.
RTP en sí mismo no garantiza la entrega confiable de los datos transmitidos, simplemente proporciona suficiente información para decirle al receptor si ha recibido todos los datos, y exactamente qué información falta si algo se perdió en tránsito. Además, normalmente se usa sobre UDP.
Por lo tanto, con RTP se pone énfasis en el usuario de RTP para enviar datos codificados de tal manera (es decir, con codificación de corrección de errores, redundancia en los datos, etc.) para que el receptor pueda reconstruir suficientes datos originales para cumplir con la aplicación necesariamente. Entonces, con una transmisión de audio necesitarías algún tipo de formato de codificación que se adapte a tus necesidades.
No he encontrado una referencia para lo que significa pcm_u8, pero es altamente sugestivo de que sea un flujo de datos modulado por código de pulso directo, con datos de 8 bits. Eso no parece tener ninguna codificación de corrección de errores ni redundancia de datos incorporada. Perder un byte de eso significa perder una muestra, y no hay nada que se pueda hacer en el receptor para completar.
Creo que lo que ocurre es que algo en su red está descartando paquetes UDP, que RTP le dice al AudioStream qué datos faltan y el resultado son lagunas porque no hay corrección de errores ni redundancia de datos en el flujo de datos pcm_u8 para permitir la pérdida de datos. ser reconstruido por AudioStream.
He visto cosas como que VMWare abandona deliberadamente los paquetes UDP en una red virtual como una forma de garantizar un buen rendimiento, la justificación es que UDP no garantiza la entrega de todos modos, por lo que "no importa". Eso afectó severamente a un colega que estaba usando RTP y esperaba entrega garantizada, pero no la recibió. Tenía un segmento de red cerrado con un servidor en cada extremo del servidor, uno de ellos hospedaba una única máquina virtual.
Por lo tanto, podría tratarse simplemente de cambiar qué códec está utilizando. No puedo recomendar uno. Para empezar, vale la pena examinar lo que utiliza una transmisión multimedia digital. DVB-T utiliza MPEG Transport Stream (que tiene codificación de corrección de errores, etc.) como, AFAIK, un contenedor alrededor de MPEG-2.
Me gustaría escuchar una transmisión de audio RTP, sin embargo, la voz tiene pequeños huecos, no continúa. ¿Cuál puede ser la solución? ¿Me estoy perdiendo algo en el lado del receptor (android) o Streamer (ffmpeg)?
Estoy usando ffmpeg para transmitir audio RTP,
ffmpeg -f lavfi -i aevalsrc="sin(400*2*PI*t)" -ar 8000 -vcodec pcm_u8 -f rtp rtp://192.168.0.15:41954 (port changes.)
Y aquí está mi código relacionado con Android:
AudioStream audioStream;
AudioGroup audioGroup;
@Override
public void onStart() {
super.onStart();
StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitNetwork().build();
StrictMode.setThreadPolicy(policy);
AudioManager audio = (AudioManager)getSystemService(AUDIO_SERVICE);
audio.setMode(AudioManager.MODE_IN_COMMUNICATION);
audioGroup = new AudioGroup();
audioGroup.setMode(AudioGroup.MODE_ECHO_SUPPRESSION);
InetAddress inetAddress;
try {
inetAddress = InetAddress.getByName("192.168.0.15");
audioStream = new AudioStream(inetAddress);
audioStream.setCodec(AudioCodec.PCMU);
audioStream.setMode(RtpStream.MODE_NORMAL);
InetAddress inetAddressRemote = InetAddress.getByName("192.168.0.14");
audioStream.associate(inetAddressRemote, 6000);
((TextView)findViewById(R.id.tv_port)).setText("Port : " + String.valueOf(audioStream.getLocalPort()));
audioStream.join(audioGroup);
}
catch ( UnknownHostException e ) {
e.printStackTrace();
}
catch ( SocketException e ) {
e.printStackTrace();
}
}
Respondiendo a mi propia pregunta, el problema era con la administración de paquetes android rtp.
Android dijo que ... assume packet interval is 50ms or less.
en el archivo fuente de AudioGroup .
Sin embargo, los paquetes RTP se envían con un intervalo de 60 ms.
Eso significa que 50 ms no es suficiente y esto lleva el problema como se describe a continuación.
Incoming: X X X X X X Y Y Y Y Y Y X X X X X X Y Y Y Y Y Y X X X X X X
Reading : X X X X X Y Y Y Y Y X X X X X Y Y Y Y Y X X X X X Y Y Y Y Y
^ ^ ^ ^ ^ - - - - - - - - - - - - - - - - - - - - ^ ^ ^ ^ ^
^ ^
| |
|---- just these overlapping packets is valid ----|
|---- and other packets discarding due to --------|
|---- invalid RTP headers. -----------------------|
X, Y < packets
Tengo solo un paquete en cada intervalo de 300ms. Eso resulta un sonido nervioso.
Enviaré un informe de error para esto, espero que ayude a alguien.
Para aquellos que realmente quieren escuchar transmisión RTP sin procesar, les sugiero que lean paquetes manualmente y decodifiquen en PCM 16 bits (que es el único formato de audio compatible con la tarjeta de sonido Android) y escríbalo en AudioTrack.