RTP en Android MediaPlayer

He implementado RTSP en Android MediaPlayer utilizando VLC como servidor rtsp con este código:

# vlc -vvv /home/marco/Videos/pippo.mp4 --sout #rtp{dst=192.168.100.246,port=6024-6025,sdp=rtsp://192.168.100.243:8080/test.sdp} 

Y en el proyecto de Android:


 Uri videoUri = Uri.parse("rtsp://192.168.100.242:8080/test.sdp"); videoView.setVideoURI(videoUri); videoView.start(); 

Esto funciona bien, pero si también quisiera reproducir la transmisión en vivo RTP, copié el archivo sdp en la tarjeta sdcard (/mnt/sdcard/test.sdp) y configurando vlc:

 # vlc -vvv /home/marco/Videos/pippo.mp4 --sout #rtp{dst=192.168.100.249,port=6024-6025} 

Intenté jugar el RTP de la corriente que fijaba la trayectoria del archivo del sdp localmente:


 Uri videoUri = Uri.parse("/mnt/sdcard/test.sdp"); videoView.setVideoURI(videoUri); videoView.start(); 

Pero tengo un error:


 D/MediaPlayer( 9616): Couldn't open file on client side, trying server side W/MediaPlayer( 9616): info/warning (1, 26) I/MediaPlayer( 9616): Info (1,26) E/PlayerDriver( 76): Command PLAYER_INIT completed with an error or info PVMFFailure E/MediaPlayer( 9616): error (1, -1) E/MediaPlayer( 9616): Error (1,-1) D/VideoView( 9616): Error: 1,-1 

¿Alguien sabe dónde está el problema? ¿Estoy equivocado o no es posible reproducir RTP en MediaPlayer? Saludos Giorgio

Tengo una solución parcial para usted.

Actualmente estoy trabajando en un proyecto de Ra & D que involucra la transmisión de medios de RTP de un servidor a clientes Android.

Al hacer este trabajo, contribuyo a mi propia biblioteca llamada smpte2022lib que puede encontrar aquí: http://sourceforge.net/projects/smpte-2022lib/ .

Ayudado con tal biblioteca (la implementación de Java es actualmente la mejor) puede ser capaz de analizar los flujos de multidifusión RTP procedentes de equipos de streaming profesional, sesiones VLC RTP, …

Ya lo probé con éxito con los flujos procedentes de flujos RTP profesionnal capturados con SMPTE-2022 2D-FEC o con flujos simples generados con VLC.

Desafortunadamente no puedo poner un fragmento de código aquí ya que el proyecto que lo usa está bajo copyright, pero te aseguro que puedes usarlo simplemente analizando flujos UDP ayudados con el constructor RtpPacket.

Si los paquetes son paquetes RTP válidos (los bytes) se decodificarán como tales.

En este momento de tiempo, envuelvo la llamada al constructor de RtpPacket a un subproceso que realmente almacena la carga útil decodificada como un archivo multimedia. Entonces voy a llamar a la VideoView con este archivo como parámetro.

Cruzando los dedos 😉

Saludos cordiales,

David Fischer

Posible en android usando (no mediaPlayer pero otras cosas más abajo de la pila), pero ¿realmente quieres perseguir RTSP / RTP cuando el resto del ecosistema de medios no?

IMO – hay mucho mejores medios / corrientes enfoques bajo el paraguas de HTML5 / WebRTC. Como mirar lo que 'Ondello' está haciendo con los arroyos.

Dicho esto, aquí está un código de proyecto antiguo para android / RTSP / SDP / RTP usando 'netty' y 'efflux'. Negociará algunas partes de 'Sesiones' en los proveedores de archivos SDP. No recuerdo si realmente tocaría la parte de audio de Youtube / RTSP cosas , pero eso es lo que mi objetivo era en ese momento. (Creo que funcionó con el códec AMR-NB, pero había un montón de problemas y me caí RTSP en Android como un mal hábito!)

En Git

  @Override public void mediaDescriptor(Client client, String descriptor) { // searches for control: session and media arguments. final String target = "control:"; Log.d(TAG, "Session Descriptor\n" + descriptor); int position = -1; while((position = descriptor.indexOf(target)) > -1) { descriptor = descriptor.substring(position + target.length()); resourceList.add(descriptor.substring(0, descriptor.indexOf('\r'))); } } private int nextPort() { return (port += 2) - 2; } private void getRTPStream(TransportHeader transport){ String[] words; // only want 2000 part of 'client_port=2000-2001' in the Transport header in the response words = transport.getParameter("client_port").substring(transport.getParameter("client_port").indexOf("=") +1).split("-"); port_lc = Integer.parseInt(words[0]); words = transport.getParameter("server_port").substring(transport.getParameter("server_port").indexOf("=") +1).split("-"); port_rm = Integer.parseInt(words[0]); source = transport.getParameter("source").substring(transport.getParameter("source").indexOf("=") +1); ssrc = transport.getParameter("ssrc").substring(transport.getParameter("ssrc").indexOf("=") +1); // assume dynamic Packet type = RTP , 99 getRTPStream(session, source, port_lc, port_rm, 99); //getRTPStream("sessiona", source, port_lc, port_rm, 99); Log.d(TAG, "raw parms " +port_lc +" " +port_rm +" " +source ); // String[] words = session.split(";"); Log.d(TAG, "session: " +session); Log.d(TAG, "transport: " +transport.getParameter("client_port") +" " +transport.getParameter("server_port") +" " +transport.getParameter("source") +" " +transport.getParameter("ssrc")); } private void getRTPStream(String session, String source, int portl, int portr, int payloadFormat ){ // what do u do with ssrc? InetAddress addr; try { addr = InetAddress.getLocalHost(); // Get IP Address // LAN_IP_ADDR = addr.getHostAddress(); LAN_IP_ADDR = "192.168.1.125"; Log.d(TAG, "using client IP addr " +LAN_IP_ADDR); } catch (UnknownHostException e1) { // TODO Auto-generated catch block e1.printStackTrace(); } final CountDownLatch latch = new CountDownLatch(2); RtpParticipant local1 = RtpParticipant.createReceiver(new RtpParticipantInfo(1), LAN_IP_ADDR, portl, portl+=1); // RtpParticipant local1 = RtpParticipant.createReceiver(new RtpParticipantInfo(1), "127.0.0.1", portl, portl+=1); RtpParticipant remote1 = RtpParticipant.createReceiver(new RtpParticipantInfo(2), source, portr, portr+=1); remote1.getInfo().setSsrc( Long.parseLong(ssrc, 16)); session1 = new SingleParticipantSession(session, payloadFormat, local1, remote1); Log.d(TAG, "remote ssrc " +session1.getRemoteParticipant().getInfo().getSsrc()); session1.init(); session1.addDataListener(new RtpSessionDataListener() { @Override public void dataPacketReceived(RtpSession session, RtpParticipantInfo participant, DataPacket packet) { // System.err.println("Session 1 received packet: " + packet + "(session: " + session.getId() + ")"); //TODO close the file, flush the buffer // if (_sink != null) _sink.getPackByte(packet); getPackByte(packet); // System.err.println("Ssn 1 packet seqn: typ: datasz " +packet.getSequenceNumber() + " " +packet.getPayloadType() +" " +packet.getDataSize()); // System.err.println("Ssn 1 packet sessn: typ: datasz " + session.getId() + " " +packet.getPayloadType() +" " +packet.getDataSize()); // latch.countDown(); } }); // DataPacket packet = new DataPacket(); // packet.setData(new byte[]{0x45, 0x45, 0x45, 0x45}); // packet.setSequenceNumber(1); // session1.sendDataPacket(packet); // try { // latch.await(2000, TimeUnit.MILLISECONDS); // } catch (Exception e) { // fail("Exception caught: " + e.getClass().getSimpleName() + " - " + e.getMessage()); // } } //TODO below should collaborate with the audioTrack object and should write to the AT buffr // audioTrack write was blocking forever public void getPackByte(DataPacket packet) { //TODO this is getting called but not sure why only one time // or whether it is stalling in mid-exec?? //TODO on firstPacket write bytes and start audioTrack // AMR-nb frames at 12.2 KB or format type 7 frames are handled . // after the normal header, the getDataArray contains extra 10 bytes of dynamic header that are bypassed by 'limit' // real value for the frame separator comes in the input stream at position 1 in the data array // returned by // int newFrameSep = 0x3c; // bytes avail = packet.getDataSize() - limit; // byte[] lbuf = new byte[packet.getDataSize()]; // if ( packet.getDataSize() > 0) // lbuf = packet.getDataAsArray(); //first frame includes the 1 byte frame header whose value should be used // to write subsequent frame separators Log.d(TAG, "getPackByt start and play"); if(!started){ Log.d(TAG, " PLAY audioTrak"); track.play(); started = true; } // track.write(packet.getDataAsArray(), limit, (packet.getDataSize() - limit)); track.write(packet.getDataAsArray(), 0, packet.getDataSize() ); Log.d(TAG, "getPackByt aft write"); // if(!started && nBytesRead > minBufferSize){ // Log.d(TAG, " PLAY audioTrak"); // track.play(); // started = true;} nBytesRead += packet.getDataSize(); if (nBytesRead % 500 < 375) Log.d(TAG, " getPackByte plus 5K received"); } } 

Desafortunadamente, no es posible reproducir un Stream RTP con el MediaPlayer de Android.

Las soluciones a este problema incluyen la decodificación del flujo RTP con ffmpeg. Tutoriales sobre cómo compilar ffmpeg para Android se pueden encontrar en la Web.

  • Aplicación de cliente RTP en Android Mobile Device
  • Aplicación de cliente RTP en Android Mobile Device
  • ¿Es factible la adición de una dependencia libjitsi a un proyecto Android?
  • Recepción de flujo RTP - AudioStream, AudioGroup
  • Creación de paquetes RTP desde la cámara Android para enviar
  • Problema de calidad de voz en Android VoIP app con PJSIP
  • Android RTP enviar y recibir el programa
  • Creación / búsqueda de bibliotecas compartidas desde el código fuente de Android
  • Cámara de streaming con RTP de Android a PC
  • Convertir secuencias de entrada de vídeo a RTMP
  • Sip stack para iphone y android
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.