Android MediaPlayer上的RTP

我已经使用VLC作为rtsp服务器在Android MediaPlayer上实现了RTSP,代码如下:

# 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} 

和Android项目上:


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

这工作正常,但如果我也想播放实时streamRTP,所以我复制SD卡文件到SD卡(/mnt/sdcard/test.sdp)和设置VLC:

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

我试图在本地播放sdp文件的streamRTP设置path:


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

但是我得到一个错误:


 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 

有谁知道问题在哪里? 我是我错了,或者不能在MediaPlayer上播放RTP? 干杯乔治

Solutions Collecting From Web of "Android MediaPlayer上的RTP"

我有你的一个部分解决scheme。

我目前正在从事一个Ra&D项目,涉及从服务器到Android客户端的媒体RTPstream媒体。

通过做这个工作,我贡献给我自己的图书馆叫smpte2022lib你可以在这里find: http : //sourceforge.net/projects/smpte-2022lib/ 。

借助这样的库(Java实现当前是最好的),您可能能够parsing来自专业stream媒体设备,VLC RTP会话的RTP组播stream…

我已经使用SMPTE-2022 2D-FEC捕获的专用RTPstream或使用VLC生成的简单stream成功testing了它。

不幸的是,我不能在这里放置一个代码片段,因为使用它的项目实际上是在版权下,但是我确保你可以简单地通过parsingUDPstream帮助RtpPacket构造函数来使用它。

如果数据包是有效的RTP数据包(字节),它们将被解码。

在这一刻,我把调用RtpPacket的构造函数包装为一个线程,实际上将解码后的有效载荷存储为一个媒体文件。 然后我会用这个文件作为参数调用VideoView。

穿越手指;-)

亲切的问候,

大卫·菲舍尔

可能在Android使用(不mediaPlayer,但其他的东西进一步下来),但你真的想追求RTSP / RTP时,其余的媒体生态系统不?

国际海事组织 – 在HTML5 / WebRTC的框架下,有更好的媒体/stream媒体方法。 就像看看Ondello在stream中所做的一样。

这就是说,这里是一些使用'netty'和'efflux'的android / RTSP / SDP / RTP的旧项目代码。 它将在SDP文件提供商中协商“会话”的某些部分。 不能记得它是否真的会播放Youtube / RTSP内容的audio部分,但这正是我当时的目标。 (我认为它使用AMR-NB编解码器,但是,有大量的问题,我像一个坏习惯,在Android上丢弃RTSP!)

在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"); } } 

不幸的是,用Android MediaPlayer播放RTPstream是不可能的。

解决这个问题的方法包括用ffmpeg解码RTPstream。 有关如何编译Android的ffmpeg的教程可以在Web上find。