1. 程式人生 > >Android端做RTP實時傳送音訊資料實現

Android端做RTP實時傳送音訊資料實現

       如果你也在Android端做RTP傳送資料的話,通過網上查詢資料,相信你不難發現,在使用RTP/RTCP協議傳送資料是有現成的庫進行呼叫的,Jlibrtp這個庫就是Java實現的,但是這個庫是沒有說明文件的,比較摳腳,而且百度谷歌找到例子又很少,基本上都沒什麼卵用;一般搜到都是Jrtplib庫,這是C實現庫,對我們沒多大用,除非你願意先研究這個庫的RTP實現,在用JNI呼叫,明顯更蛋疼。這個沒文件就只能自己瞎倒騰一下,還好勉強倒騰出來了。

       首先,你必須下一個Jlibrtp庫:https://download.csdn.net/download/jwq1220/10354020 裡面包含Jlibrtp的實現和java呼叫的Demo。

       下完後,新建一個Android工程,將Jlibrtp-0.2.2中的jlibrtp資料夾中的所有.java檔案匯入工程,全丟到一個新建的jlibrtp包裡面,準備工作算是完成,在需要地方直接import這個包,就可以使用了。

demo中標已經將原始碼打包成jar形式可以直接使用,也可以通過上面連結下載最新的C庫和java庫。C庫中包含demo親測在linux上面機器間通訊正常

簡單整理一下Jlibrtp實現RTP的過程:

1、首先建立收發端的會話,呼叫Jlibrtp庫的實時傳輸會話類RTPSession,該類可以建立一個RTP會話,並設定傳輸的RTP埠和RTCP埠,以及與RTP包的相關的時間戳資料等。

2、然後通過RTPSessionRegister方法用於新增RTP會話的參與者,同時開啟接收包的AppCallerThread執行緒類,其run方法呼叫回撥函式receiveData,才開始接收RTP包,receiveData函式會去掉RTP包頭,直接將RTP負載存入快取,之後再進行分包的判斷。

具體實現過程如下:

1、InitSession.java類初始化會話基礎引數,設定目標IP及RTP埠號和RTCP埠號等;

資料傳送和接收需要分包來處理,這裡沒有貼出來,demo中有完整的分包傳送和接收的處理以及資料同步的多執行緒實現

  1. package com.eric.androidrtpsenddata;  
  2. import java.net.DatagramSocket;  
  3. import java.net.InetSocketAddress;  
  4. import jlibrtp.*;  
  5. public class InitSession implements RTPAppIntf{  
  6.     public RTPSession rtpSession = null;  
  7.     public InitSession() {  
  8.         DatagramSocket rtpSocket = null;  
  9.         DatagramSocket rtcpSocket = null;  
  10.         try {  
  11.             rtpSocket = new DatagramSocket(8002);  
  12.             rtcpSocket = new DatagramSocket(8003);  
  13.         } catch (Exception e) {  
  14.             System.out.println("傳送建立會話異常丟擲:"+e);  
  15.         }  
  16.         //建立會話  
  17.         rtpSession = new RTPSession(rtpSocket, rtcpSocket);  
  18.         rtpSession.RTPSessionRegister(this,null,null);  
  19.         //設定參與者(目標IP地址,RTP埠,RTCP埠)  
  20.         Participant p = new Participant("192.168.226.116"80048005);  
  21.         rtpSession.addParticipant(p);  
  22.     }  
  23.     public void receiveData(DataFrame frame, Participant p){  
  24.         String s = new String(frame.getConcatenatedData());  
  25.         System.out.println("接收到資料: "+s+" , 參與者CNAME: "  
  26.                 +p.getCNAME()+"同步源識別符號("+p.getSSRC()+")");  
  27.     }  
  28.     public void userEvent(int type, Participant[] participant) {  
  29.         // TODO Auto-generated method stub  
  30.     }  
  31.     public int frameSize(int payloadType) {  
  32.         return 1;  
  33.     }  
  34. }  

2、MainActivity.java中傳送資料;其中資料傳送部分demo中做了修改資料來自真實的音訊資料採集,採用AudioRecod,接收端採用AudioPlay來播放傳送客戶端採集來的實時音訊資料,達到語音通話的效果。測試效果還不錯。

以下是別人寫的,下面demo下載中與下面是不一致的,完實際demo已經完全按照實際sdk的要求進行了封裝,解決了大資料實時傳送和接收的問題。有興趣的可以自行下載。也可以操作以下簡單例子的實現自行實現。

  1. package com.eric.androidrtpsenddata;  
  2. import android.app.Activity;  
  3. import android.os.Bundle;  
  4. public class MainActivity extends Activity{  
  5.      @Override  
  6.         protected void onCreate(Bundle savedInstanceState) {  
  7.             super.onCreate(savedInstanceState);  
  8.             setContentView(R.layout.activity_main);   
  9.             /*Thread receiveThread = new Thread(new Runnable() { 
  10.                 @Override 
  11.                 public void run() { 
  12.                     try { 
  13.                         receiveData(); 
  14.                     } catch (Exception e) { 
  15.                         e.printStackTrace(); 
  16.                         System.out.println("RTP接收資料異常:"+e); 
  17.                     } 
  18.                 } 
  19.             }); 
  20.             receiveThread.start();*/  
  21.             Thread sendThread = new Thread(new Runnable() {  
  22.                 @Override  
  23.                 public void run() {  
  24.                     try {  
  25.                         openSession();  
  26.                     } catch (Exception e) {  
  27.                         e.printStackTrace();  
  28.                         System.out.println("RTP傳送資料異常:"+e);  
  29.                     }  
  30.                 }  
  31.             });  
  32.             sendThread.start();  
  33.         }  
  34.      //Jlibrtp開啟會話傳送資料  ,這裡的虛擬碼,實際demo中的程式碼輸入的實時流通過MIC採集的資料然後分包傳送給服務端
  35.      public void openSession(){  
  36.         InitSession test = new InitSession();  
  37.         long teststart = System.currentTimeMillis();  
  38.         String str = "abce abcd abce abce abce abcd abcd abce " +  
  39.                 "abcd abce abcd abce abcd abce abcd abce abcd abce " +  
  40.                 "abcd abce abcd abce abcd abce abcd abce abcd abce abcd " +  
  41.                 "abce abcd abce abcd abce abcd abce abcd abce abcd abce " +  
  42.                 "abcd abce abcd abce abcd abce abcd abce abcd abce abcd " +  
  43.                 "abce abcd abce abcd abce abcd abce abcd abce abcd abce " +  
  44.                 "abcd abce abcd abce abcd abce abcd abce abcd abce abcd " +  
  45.                 "abce abcd abce abcd abce abcd abce abcd abce abcd abce " +  
  46.                 "abcd abce abcd abce abcd abce abcd abce abcd abce abcd " +  
  47.                 "abce abcd abce abcd abce abcd abce abcd abce abcd abce " +  
  48.                 "abcd abce abcd abce abcd abce abcd abce abcd abce abcd " +  
  49.                 "abce abcd abce abcd abce abcd abce abcd ";  
  50.         byte[] data = str.getBytes();  
  51.         System.out.println(data.length);  
  52.         int i=0;  
  53.         while(i<data.length) {  
  54.                 System.out.println("已傳送第"+i+"個位元組陣列:"+data);  
  55.                 test.rtpSession.sendData(data);  
  56.                 i++;  
  57.         }  
  58.         long testend = System.currentTimeMillis();  
  59.         System.out.println("傳送用時:" + (testend - teststart));  
  60.         System.out.println("結束時間:" + testend);  
  61.         System.out.println("開始時間:" + teststart);  
  62.      }  
  63.      public void receiveData(){  
  64.          ReceiveData receive = new ReceiveData();  
  65.      }  
  66. }  

例子Demo執行結果:


 

附上Demo地址:https://download.csdn.net/download/jwq1220/10400795

注意:demo共7個包才是完整的  區域網內實時通訊測試效果不錯