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中有完整的分包傳送和接收的處理以及資料同步的多執行緒實現
- package com.eric.androidrtpsenddata;
- import java.net.DatagramSocket;
- import java.net.InetSocketAddress;
- import jlibrtp.*;
- public class InitSession implements RTPAppIntf{
- public RTPSession rtpSession = null;
- public InitSession() {
- DatagramSocket rtpSocket = null;
- DatagramSocket rtcpSocket = null;
- try {
- rtpSocket = new DatagramSocket(8002);
- rtcpSocket = new DatagramSocket(8003);
- } catch (Exception e) {
- System.out.println("傳送建立會話異常丟擲:"+e);
- }
- //建立會話
- rtpSession = new RTPSession(rtpSocket, rtcpSocket);
- rtpSession.RTPSessionRegister(this,null,null);
- //設定參與者(目標IP地址,RTP埠,RTCP埠)
- Participant p = new Participant("192.168.226.116", 8004, 8005);
- rtpSession.addParticipant(p);
- }
- public void receiveData(DataFrame frame, Participant p){
- String s = new String(frame.getConcatenatedData());
- System.out.println("接收到資料: "+s+" , 參與者CNAME: "
- +p.getCNAME()+"同步源識別符號("+p.getSSRC()+")");
- }
- public void userEvent(int type, Participant[] participant) {
- // TODO Auto-generated method stub
- }
- public int frameSize(int payloadType) {
- return 1;
- }
- }
2、MainActivity.java中傳送資料;其中資料傳送部分demo中做了修改資料來自真實的音訊資料採集,採用AudioRecod,接收端採用AudioPlay來播放傳送客戶端採集來的實時音訊資料,達到語音通話的效果。測試效果還不錯。
以下是別人寫的,下面demo下載中與下面是不一致的,完實際demo已經完全按照實際sdk的要求進行了封裝,解決了大資料實時傳送和接收的問題。有興趣的可以自行下載。也可以操作以下簡單例子的實現自行實現。
- package com.eric.androidrtpsenddata;
- import android.app.Activity;
- import android.os.Bundle;
- public class MainActivity extends Activity{
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_main);
- /*Thread receiveThread = new Thread(new Runnable() {
- @Override
- public void run() {
- try {
- receiveData();
- } catch (Exception e) {
- e.printStackTrace();
- System.out.println("RTP接收資料異常:"+e);
- }
- }
- });
- receiveThread.start();*/
- Thread sendThread = new Thread(new Runnable() {
- @Override
- public void run() {
- try {
- openSession();
- } catch (Exception e) {
- e.printStackTrace();
- System.out.println("RTP傳送資料異常:"+e);
- }
- }
- });
- sendThread.start();
- }
- //Jlibrtp開啟會話傳送資料 ,這裡的虛擬碼,實際demo中的程式碼輸入的實時流通過MIC採集的資料然後分包傳送給服務端
- public void openSession(){
- InitSession test = new InitSession();
- long teststart = System.currentTimeMillis();
- String str = "abce abcd abce abce abce abcd abcd abce " +
- "abcd abce abcd abce abcd abce abcd abce abcd abce " +
- "abcd abce abcd abce abcd abce abcd abce abcd abce abcd " +
- "abce abcd abce abcd abce abcd abce abcd abce abcd abce " +
- "abcd abce abcd abce abcd abce abcd abce abcd abce abcd " +
- "abce abcd abce abcd abce abcd abce abcd abce abcd abce " +
- "abcd abce abcd abce abcd abce abcd abce abcd abce abcd " +
- "abce abcd abce abcd abce abcd abce abcd abce abcd abce " +
- "abcd abce abcd abce abcd abce abcd abce abcd abce abcd " +
- "abce abcd abce abcd abce abcd abce abcd abce abcd abce " +
- "abcd abce abcd abce abcd abce abcd abce abcd abce abcd " +
- "abce abcd abce abcd abce abcd abce abcd ";
- byte[] data = str.getBytes();
- System.out.println(data.length);
- int i=0;
- while(i<data.length) {
- System.out.println("已傳送第"+i+"個位元組陣列:"+data);
- test.rtpSession.sendData(data);
- i++;
- }
- long testend = System.currentTimeMillis();
- System.out.println("傳送用時:" + (testend - teststart));
- System.out.println("結束時間:" + testend);
- System.out.println("開始時間:" + teststart);
- }
- public void receiveData(){
- ReceiveData receive = new ReceiveData();
- }
- }
例子Demo執行結果:
附上Demo地址:https://download.csdn.net/download/jwq1220/10400795
注意:demo共7個包才是完整的 區域網內實時通訊測試效果不錯