jrtplib介绍
程序流程
發送:獲得接收端的 IP 地址和端口號??????? 創建 RTP 會話??????? 指定 RTP 數據接收端 設置 RTP 會話 默認參數?? 發送流媒體數據
接收:獲得用戶指定的端口號? 創建RTP會話? 設置接收模式? 接受RTP數據? 檢索RTP數據源? 獲取RTP數據報 刪除RTP數據報
1.初始化
I、在使用 JRTPLIB 進行實時流媒體數據傳輸之前,首先應該生成 RTPSession 類的一個實例來表示此次 RTP會話,然后調用 Create() 方法來對其進行初始化操作。RTPSession 類的 Create() 方法只有一個參數,用來指明此次 RTP 會話所采用的端口號。
RTPSession sess;? sess.Create(5000);JRTPLIB-3.11中已經修改了Create(prot)方法。新的Create方法被修改為Create(sessparams,&transparams)。其中的兩個參數需要如下先定義:
RTPUDPv4TransmissionParams transparams; RTPSessionParams sessparams;sessparams.SetOwnTimestampUnit(1.0/8000.0);/*設置時間戳,1/8000表示1秒鐘采樣8000次,即錄音時的8KHz*/sessparams.SetAcceptOwnPackets(true);transparams.SetPortbase(portbase);/*本地通訊端口*/II、設置恰當的時戳單元,是 RTP 會話初始化過程所要進行的另外一項重要工作,這是通過調用 RTPSession類的 SetTimestampUnit() 方法來實現的,前面已經提過。
?
2.數據發送
I、當 RTP 會話成功建立起來之后,接下去就可以開始進行流媒體數據的實時傳輸了。首先需要設置好數據發送的目標地址,RTP 協議允許同一會話存在多個目標地址,這可以通過調用 RTPSession 類的AddDestination()、DeleteDestination() 和 ClearDestinations() 方法來完成。例如,下面的語句表示的是讓 RTP 會話將數據發送到本地主機的 6000 端口:
unsigned long addr = ntohl(inet_addr("127.0.0.1"));? sess.AddDestination(addr, 6000);II、目標地址全部指定之后,接著就可以調用 RTPSession 類的 SendPacket() 方法,向所有的目標地址發送流媒體數據。SendPacket() 是 RTPSession 類提供的一個重載函數對于同一個 RTP 會話來講,負載類型、標識和時戳增量通常來講都是相同的,JRTPLIB 允許將它們設置為會話的默認參數,這是通過調用 RTPSession 類的 SetDefaultPayloadType()、SetDefaultMark() 和SetDefaultTimeStampIncrement() 方法來完成的。為 RTP 會話設置這些默認參數的好處是可以簡化數據的發送,例如,如果為 RTP 會話設置了默認參數:
sess.SetDefaultPayloadType(0); sess.SetDefaultMark(false);?? sess.SetDefaultTimeStampIncrement(10);之后在進行數據發送時只需指明要發送的數據及其長度就可以了:
sess.SendPacket(buffer, 5);在真正的語音傳輸中,上面的buffer就是我們錄音時所得到的buffer。使用上面的函數可以簡單的發送,但無法真正的實現RTP傳輸,我們需要調用另一個接口:sess.SendPacket((void *)buffer,sizeof(buffer),0,false,8000);詳細的說明可以查看JRTPLIB的說明文檔。
?
3.數據接收
對于流媒體數據的接收端,首先需要調用 RTPSession 類的 PollData() 方法來接收發送過來的 RTP 或者RTCP 數據報。
JRTPLIB-3.11中修改PollData()方法為Poll(),使用都一樣
由于同一個 RTP 會話中允許有多個參與者(源),你既可以通過調用 RTPSession 類的
GotoFirstSource() 和 GotoNextSource() 方法來遍歷所有的源,也可以通過調用 RTPSession 類的GotoFirstSourceWithData() 和 GotoNextSourceWithData() 方法來遍歷那些攜帶有數據的源。在從 RTP 會話中檢測出有效的數據源之后,接下去就可以調用 RTPSession 類的 GetNextPacket() 方法從中抽取 RTP 數據報,當接收到的 RTP 數據報處理完之后,一定要記得及時釋放。
JRTPLIB 為 RTP 數據報定義了三種接收模式,其中每種接收模式都具體規定了哪些到達的 RTP 數據報將會被接受,而哪些到達的 RTP 數據報將會被拒絕。通過調用 RTPSession 類的 SetReceiveMode() 方法可以設置下列這些接收模式:?
RECEIVEMODE_ALL 缺省的接收模式,所有到達的 RTP 數據報都將被接受;?
RECEIVEMODE_IGNORESOME 除了某些特定的發送者之外,所有到達的 RTP 數據報都將被接受,而被拒絕的發送者列表可以通過調用 AddToIgnoreList()、DeleteFromIgnoreList() 和 ClearIgnoreList() 方法來進行設置;?
RECEIVEMODE_ACCEPTSOME 除了某些特定的發送者之外,所有到達的 RTP 數據報都將被拒絕,而被接受的發送者列表可以通過調用 AddToAcceptList ()、DeleteFromAcceptList 和 ClearAcceptList () 方法來進行設置。 下面是采用第三種接收模式的程序示例。
完整的代碼中,首先需調用Poll()方法接收RTP數據報,然后在BeginDataAccess()和EndDataAccess()之間進行數據接收的操作。此時,我們設定程序一直do-while等待并處理數據
do{#ifndef RTP_SUPPORT_THREADerror_status = sess_client.Poll();checkerror(error_status); #endif // RTP_SUPPORT_THREADsess_client.BeginDataAccess();// check incoming packetsif (sess_client.GotoFirstSourceWithData()){printf("Begin play/n");do{RTPPacket *pack;while ((pack = sess_client.GetNextPacket()) != NULL){// You can examine the data hereprintf("Got packet !/n");timestamp1 = pack->GetTimestamp();lengh=pack->GetPayloadLength();RawData=pack->GetPayloadData();?? //得到數據printf("? timestamp: %dlengh=%d/n",timestamp1,lengh);int fd = open("/dev/dsp", O_RDWR);int status = write(fd, RawData,lengh );printf("Play bytes:%d/n",status);if (status != lengh)perror("wrote wrong number of bytes");status = ioctl(fd, SOUND_PCM_SYNC, 0);if (status == -1)perror("SOUND_PCM_SYNC ioctl failed");printf("Play end/n");close(fd);sess_client.DeletePacket(pack);}} while (sess_client.GotoNextSourceWithData());//return 0;}sess_client.EndDataAccess();}while(1);說明 :?jrtp-3.x?中有兩種數據接收方式:
第一種是用 jthread 庫提供的線程自動在后臺執行對數據的接收。
第二種是用戶自己調用 RTPSession 中的 Poll 方法。
如果采取第一種方法則要安裝 jthread 庫,則安裝 jthread-1.x.tar.gz ,而且 jthread-1.x 必須先與 jrtp-3.x?的安裝。因為在 jrtp-3.x 的 configure 中,會查找系統是否有編譯了 jthread 庫,如果有,那么編譯的 jrtp 庫會開啟對 jthread 的支持。因此如果先編譯jrtp 在編譯 jthread ,編譯出來的 jrtp 是沒有開啟對 jthread 的支持的。如果采用第二種方法,那么可以不用編譯 jthread 庫,而直接編譯 jrtp 庫。
?
可以加入環境變量 export LD_LIBRARY_PATH=/XXX/lib,避免將所有lib都放入/usr下
./ example
總結
- 上一篇: 黑马程序员_毕向东_Java基础视频教程
- 下一篇: PageRank算法在社交网络上的应用