當前位置:
首頁 >
linux 下基于jrtplib库的实时传送实现
發布時間:2025/3/21
60
豆豆
生活随笔
收集整理的這篇文章主要介紹了
linux 下基于jrtplib库的实时传送实现
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
linux 下基于jrtplib庫的實時傳送實現
一、RTP 是進行實時流媒體傳輸的標準協議和關鍵技術
實時傳輸協議(Real-time Transport Protocol,PRT)是在 Internet 上處理多媒體數據流的一種網絡協議,利用它能夠在一對一(unicast,單播)或者一對多(multicast,多播)的網絡環境中實現傳流媒體數據的 實時傳輸。RTP 通常使用 UDP 來進行多媒體數據的傳輸,但如果需要的話可以使用 TCP 或者 ATM 等其它協議。
協議分析 :每一個RTP數據報都由頭部(Header)和負載(Payload)兩個部分組成,其中頭部前 12 個字節的含義是固定的,而負載則可以是音頻或者視頻數據。
? ? ?RTP 是目前解決流媒體實時傳輸問題的最好辦法,要在 Linux 平臺上進行實時傳送編程,可以考慮使用一些開放源代碼的 RTP 庫,如 LIBRTP、JRTPLIB 等。JRTPLIB 是一個面向對象的 RTP 庫,它完全遵循 RFC 1889 設計,在很多場合下是一個非常不錯的選擇。JRTPLIB 是一個用 C++ 語言實現的 RTP 庫,這個庫使用socket 機制實現網絡通訊 因此可以運行在 Windows、Linux、FreeBSD、Solaris、Unix和VxWorks 等多種操作系統上。
二、JRTPLIB 庫的使用方法及程序實現
(1)JRTPLIB ?函數 的使用
a、在使用 JRTPLIB 進行實時流媒體數據傳輸之前,首先應該生成 RTPSession 類的一個實例來表示此次 RTP 會話,然后調用 Create() 方法來對其進行初始化操作。RTPSession 類的 Create() 方法只有一個參數,用來指明此次 RTP 會話所采用的端口號。
RTPSession sess; ?sess.Create(5000);
b、設置恰當的時戳單元,是 RTP 會話初始化過程所要進行的另外一項重要工作,這是通過調用 RTPSession 類的 SetTimestampUnit() 方法來實現的,該方法同樣也只有一個參數,表示的是以秒為單元的時戳單元。
sess.SetTimestampUnit(1.0/8000.0);
c、當 RTP 會話成功建立起來之后,接下去就可以開始進行流媒體數據的實時傳輸了。首先需要設置好數據發送的目標地址,RTP 協議允許同一會話存在多個目標地址,這可以通過調用 RTPSession 類的 AddDestination()、DeleteDestination() 和 ClearDestinations() 方法來完成。例如,下面的語句表示的是讓 RTP 會話將數據發送到本地主機的 6000 端口:
unsigned long addr = ntohl(inet_addr("127.0.0.1"));
sess.AddDestination(addr, 6000);
d、目標地址全部指定之后,接著就可以調用 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);
e、對于流媒體數據的接收端,首先需要調用 RTPSession 類的 PollData() 方法來接收發送過來的 RTP 或者 RTCP 數據報。由于同一個 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 () 方法來進行設置。 下面是采用第三種接收模式的程序示例。
if (sess.GotoFirstSourceWithData()) { ?
?do { ?
? sess.AddToAcceptList(remoteIP, allports,portbase);
? ? ? ? ?sess.SetReceiveMode(RECEIVEMODE_ACCEPTSOME);
? ?RTPPacket *pack; ? ? ? ?
? ?pack = sess.GetNextPacket(); ? ? ? ? ? ?// 處理接收到的數據 ? ?
? ?delete pack; ? }
?while (sess.GotoNextSourceWithData());
?}
?(2)程序流程圖
發送:獲得接 收端的 IP 地址和端口號 ? ? ? ?創建 RTP 會話 ? ? ? ?指定 RTP 數據接收端 設置 RTP 會話默認參數 ? 發送流媒體數據
接收:獲得用戶指定的端口號 ?創建RTP會話 ?設置接收模式 ?接受RTP數據 ?檢索RTP數據源 ?獲取RTP數據報 ?刪除RTP數據報
三、環境搭建及編譯方法
引用(1)Toolchain的安裝
首先找到xscale-arm-toolchain.tgz文件,假設該文件包放在/tmp/下
#cd /
#tar -zxvf /tmp/xscale-arm-toolchain.tgz
再設置環境變量
#export PATH=/usr/local/arm-linux/bin:$PATH
最后檢查一下交叉編譯工具是否安裝成功
#arm-linux-g++ --version
看是否顯示arm-linux-g++的版本,如有則安裝成功。
(2)JRTPLIB 庫的交叉編譯及安裝
首先從 JRTPLIB 的網站(http://lumumba.luc.ac.be/jori/jrtplib/jrtplib.htmll) 下載最新的源碼包,此處使用的是jrtplib-2.8.tar,假設下載后的源碼包放在/tmp下,執 行下面的命令對其解壓縮:
#cd /tmp
#tar -zxvf jrtplib-2.8.tar
然后要對jrtplib進行配置和編譯
#cd jrtplib-2.8
#./configure CC=arm-linux-g++ cross-compile=yes
修改Makefile文件
將鏈接命令ld 和ar改為arm-linux-ld和 arm-linux-ar
#make
最后再執行如下命令就可以完成 JRTPLIB 的安裝:
#make install
(3)程序編譯
a、配置編譯環境
可以用export來配置,也可以用編寫Makefile的方法。這里采用Makefile。
編寫Makefile&:
INCL = -I/usr/local/include
CFLAGS = -pipe -O2 -fno-strength-reduce
LFLAGS = /usr/local/lib/libjrtp.a -L/usr/X11R6/lib
LIBS = -LX11 -LXext /usr/local/lib/libjrtp.a
CC = arm-linux-g++
main:main.o
$(CC) $(LFLAGS) $(INCL) -o main main.o $(LIBS)
main.o:main.cpp
clean:
rm -f main
rm -f *.o
.SUFFIXES:.cpp
.cpp.o:
$(CC) -c $(CFLAGS) $(INCL) -o $@ $< ? ? ? ? /* ?$@表示目標的完整名字 ? ? ?*/
? ? ? ? ?/* $<表示第一個依賴文件的名字 */
b、編譯
假設發送和接收程序分別放在/tmp/send和/tmp/receive目錄下
#cd /tmp/send
#make
#cd /tmp/receive
#make
四、易出錯誤及注意問題
引用1、找不到一些標準的最 基本的一些頭文件。
?主要是因為Toolchain路徑沒安裝對,要 嚴格按照步驟安裝。
2、找不到使用的jrtplib庫中的一些頭文件。
?在 jrtplib的安裝目錄下,include路徑下不能再有別的目錄。
3、recieve函數接收數據包不能正確提出所要數據。
?由于每一個RTP數據報都由頭部(Header)和負載(Payload)兩個部分組成,若使用getrawdata()是返回整個數據包的數據,包含 傳輸媒體的類型、格式、序列號、時間戳以及是否有附加數據等信息。getpayload()函數是返回所發送的數據。兩者一定要分清。
4、設置RECEIVEMODE_ACCEPTSOME 接收模式后,運行程序接收端不能接包。
?IP地址格式出了問題。iner_addr()與ntohl()函數要用對,否則參數傳不進去,接受列表中無值,當然接收不了數據包。
5、編譯通過,但測試時接收端不能接收到數據。
?可能是接收機防火墻未關閉。運行:
?#iptables -F
?也可能是IP地址沒有設置好。運行:
?#ifocnfig eth0 ?*.*.*.* ?netmask *.*.*.*
6、使用jrtolib庫時,在程序中include 后最好加上庫所在的路徑。五、程序
send:
view plainprint?#include?<stdio.h>?? #include?<string.h>?? #include?"rtpsession.h"?? ?? //?錯誤處理函數?? void?checkerror(int?err)?? {?? ??if?(err?<?0)?{?? ????char*?errstr?=?RTPGetErrorString(err);?? ????printf("Error:%s\\n",?errstr);?? ????exit(-1);?? ??}?? }?? ?? int?main(int?argc,?char**?argv)?? {?? ??RTPSession?sess;?? ??unsigned?long?destip;?? ??int?destport;?? ??int?portbase?=?6000;?? ??int?status,?index;?? ??char?buffer[128];?? ?? ??if?(argc?!=?3)?{?? ????printf("Usage:?./sender?destip?destport\\n");?? ????return?-1;?? ??}?? ?? ??//?獲得接收端的IP地址和端口號?? ??destip?=?inet_addr(argv[1]);?? ??if?(destip?==?INADDR_NONE)?{?? ????printf("Bad?IP?address?specified.\\n");?? ????return?-1;?? ??}?? ??destip?=?ntohl(destip);?? ??destport?=?atoi(argv[2]);?? ?? ??//?創建RTP會話?? ??status?=?sess.Create(portbase);?? ??checkerror(status);?? ?? ??//?指定RTP數據接收端?? ??status?=?sess.AddDestination(destip,?destport);?? ??checkerror(status);?? ?? ??//?設置RTP會話默認參數?? ??sess.SetDefaultPayloadType(0);?? ??sess.SetDefaultMark(false);?? ??sess.SetDefaultTimeStampIncrement(10);?? ?? ??//?發送流媒體數據?? ??index?=?1;?? ??do?{?? ????sprintf(buffer,?"%d:?RTP?packet",?index?++);?? ????sess.SendPacket(buffer,?strlen(buffer));?? ????printf("Send?packet?!\\n");?? ??}?while(1);?? ?? ??return?0;?? }?? #include <stdio.h> #include <string.h> #include "rtpsession.h" // 錯誤處理函數 void checkerror(int err) { ?if (err < 0) { ? ?char* errstr = RTPGetErrorString(err); ? ?printf("Error:%s\\n", errstr); ? ?exit(-1); ?} } int main(int argc, char** argv) { ?RTPSession sess; ?unsigned long destip; ?int destport; ?int portbase = 6000; ?int status, index; ?char buffer[128]; ?if (argc != 3) { ? ?printf("Usage: ./sender destip destport\\n"); ? ?return -1; ?} ?// 獲得接收端的IP地址和端口號 ?destip = inet_addr(argv[1]); ?if (destip == INADDR_NONE) { ? ?printf("Bad IP address specified.\\n"); ? ?return -1; ?} ?destip = ntohl(destip); ?destport = atoi(argv[2]); ?// 創建RTP會話 ?status = sess.Create(portbase); ?checkerror(status); ?// 指定RTP數據接收端 ?status = sess.AddDestination(destip, destport); ?checkerror(status); ?// 設置RTP會話默認參數 ?sess.SetDefaultPayloadType(0); ?sess.SetDefaultMark(false); ?sess.SetDefaultTimeStampIncrement(10); ?// 發送流媒體數據 ?index = 1; ?do { ? ?sprintf(buffer, "%d: RTP packet", index ++); ? ?sess.SendPacket(buffer, strlen(buffer)); ? ?printf("Send packet !\\n"); ?} while(1); ?return 0; }
receive:
view plainprint?#include?<stdio.h>?? #include?"rtpsession.h"?? #include?"rtppacket.h"?? ?? //?錯誤處理函數?? void?checkerror(int?err)?? {?? ??if?(err?<?0)?{?? ????char*?errstr?=?RTPGetErrorString(err);?? ????printf("Error:%s\\n",?errstr);?? ????exit(-1);?? ??}?? }?? ?? int?main(int?argc,?char**?argv)?? {?? ??RTPSession?sess;?? ??int?localport,portbase;?? ??int?status;?? ??unsigned?long?remoteIP;?? ??if?(argc?!=?4)?{?? ????printf("Usage:?./sender?localport\\n");?? ????return?-1;?? ??}?? ?? ???//?獲得用戶指定的端口號?? ????? ??remoteIP?=?inet_addr(argv[1]);?? ??localport?=?atoi(argv[2]);?? ??portbase?=?atoi(argv[3]);?? ??//?創建RTP會話?? ??status?=?sess.Create(localport);?? ??checkerror(status);?? ???? ??//RTPHeader?*rtphdr;?? ??unsigned?long?timestamp1;?? ??unsigned?char?*?RawData;?? ??unsigned?char?temp[30];?? ??int?lengh?,i;?? ??bool?allports?=?1;?? ???? ??sess.AddToAcceptList(remoteIP,?allports,portbase);?? ???? ?????do?{?? ?//設置接收模式?? ????????sess.SetReceiveMode(RECEIVEMODE_ACCEPTSOME);?? ???sess.AddToAcceptList(remoteIP,?allports,portbase);?? ?? ????//?接受RTP數據?? ????status?=?sess.PollData();?? ?? ?????? ?//?檢索RTP數據源?? ????if?(sess.GotoFirstSourceWithData())?{?? ??????do?{?? ?????????? ????????RTPPacket*?packet;?? ????????//?獲取RTP數據報?? ????????while?((packet?=?sess.GetNextPacket())?!=?NULL)?{?? ??????????printf("Got?packet?!\n");?? ?? ???timestamp1?=?packet->GetTimeStamp();?? ???lengh=packet->GetPayloadLength();?? ???RawData=packet->GetPayload();?? ????? ???for(i=0;i<lengh;i++){?? ??????temp[i]=RawData[i];?? ??printf("%c",temp[i]);?? ???}?? ???temp[i]='\0';?? ???printf("??timestamp:?%d?lengh=%d?data:%s\n",timestamp1,lengh,&temp);?? ??????????//?刪除RTP數據報?? ????? ??????????delete?packet;?? ????????}?? ??????}?while?(sess.GotoNextSourceWithData());?? ????}?? ??}?while(1);?? ?? ??return?0;?? }?? #include <stdio.h> #include "rtpsession.h" #include "rtppacket.h" // 錯誤處理函數 void checkerror(int err) { ?if (err < 0) { ? ?char* errstr = RTPGetErrorString(err); ? ?printf("Error:%s\\n", errstr); ? ?exit(-1); ?} } int main(int argc, char** argv) { ?RTPSession sess; ?int localport,portbase; ?int status; ?unsigned long remoteIP; ?if (argc != 4) { ? ?printf("Usage: ./sender localport\\n"); ? ?return -1; ?} ? // 獲得用戶指定的端口號 ? ?remoteIP = inet_addr(argv[1]); ?localport = atoi(argv[2]); ?portbase = atoi(argv[3]); ?// 創建RTP會話 ?status = sess.Create(localport); ?checkerror(status); ? ?//RTPHeader *rtphdr; ?unsigned long timestamp1; ?unsigned char * RawData; ?unsigned char temp[30]; ?int lengh ,i; ?bool allports = 1; ? ?sess.AddToAcceptList(remoteIP, allports,portbase); ? ? ? do { //設置接收模式 ? ? ? ?sess.SetReceiveMode(RECEIVEMODE_ACCEPTSOME); ? sess.AddToAcceptList(remoteIP, allports,portbase); ? ?// 接受RTP數據 ? ?status = sess.PollData(); ? ? // 檢索RTP數據源 ? ?if (sess.GotoFirstSourceWithData()) { ? ? ?do { ? ? ? ? ? ? ? ?RTPPacket* packet; ? ? ? ?// 獲取RTP數據報 ? ? ? ?while ((packet = sess.GetNextPacket()) != NULL) { ? ? ? ? ?printf("Got packet !\n"); ? timestamp1 = packet->GetTimeStamp(); ? lengh=packet->GetPayloadLength(); ? RawData=packet->GetPayload(); ? ? for(i=0;i<lengh;i++){ ? ? ?temp[i]=RawData[i]; ?printf("%c",temp[i]); ? } ? temp[i]='\0'; ? printf(" ?timestamp: %d lengh=%d data:%s\n",timestamp1,lengh,&temp); ? ? ? ? ?// 刪除RTP數據報 ? ? ? ? ? ?delete packet; ? ? ? ?} ? ? ?} while (sess.GotoNextSourceWithData()); ? ?} ?} while(1); ?return 0; } 相關日志
一、RTP 是進行實時流媒體傳輸的標準協議和關鍵技術
實時傳輸協議(Real-time Transport Protocol,PRT)是在 Internet 上處理多媒體數據流的一種網絡協議,利用它能夠在一對一(unicast,單播)或者一對多(multicast,多播)的網絡環境中實現傳流媒體數據的 實時傳輸。RTP 通常使用 UDP 來進行多媒體數據的傳輸,但如果需要的話可以使用 TCP 或者 ATM 等其它協議。
協議分析 :每一個RTP數據報都由頭部(Header)和負載(Payload)兩個部分組成,其中頭部前 12 個字節的含義是固定的,而負載則可以是音頻或者視頻數據。
? ? ?RTP 是目前解決流媒體實時傳輸問題的最好辦法,要在 Linux 平臺上進行實時傳送編程,可以考慮使用一些開放源代碼的 RTP 庫,如 LIBRTP、JRTPLIB 等。JRTPLIB 是一個面向對象的 RTP 庫,它完全遵循 RFC 1889 設計,在很多場合下是一個非常不錯的選擇。JRTPLIB 是一個用 C++ 語言實現的 RTP 庫,這個庫使用socket 機制實現網絡通訊 因此可以運行在 Windows、Linux、FreeBSD、Solaris、Unix和VxWorks 等多種操作系統上。
二、JRTPLIB 庫的使用方法及程序實現
(1)JRTPLIB ?函數 的使用
a、在使用 JRTPLIB 進行實時流媒體數據傳輸之前,首先應該生成 RTPSession 類的一個實例來表示此次 RTP 會話,然后調用 Create() 方法來對其進行初始化操作。RTPSession 類的 Create() 方法只有一個參數,用來指明此次 RTP 會話所采用的端口號。
RTPSession sess; ?sess.Create(5000);
b、設置恰當的時戳單元,是 RTP 會話初始化過程所要進行的另外一項重要工作,這是通過調用 RTPSession 類的 SetTimestampUnit() 方法來實現的,該方法同樣也只有一個參數,表示的是以秒為單元的時戳單元。
sess.SetTimestampUnit(1.0/8000.0);
c、當 RTP 會話成功建立起來之后,接下去就可以開始進行流媒體數據的實時傳輸了。首先需要設置好數據發送的目標地址,RTP 協議允許同一會話存在多個目標地址,這可以通過調用 RTPSession 類的 AddDestination()、DeleteDestination() 和 ClearDestinations() 方法來完成。例如,下面的語句表示的是讓 RTP 會話將數據發送到本地主機的 6000 端口:
unsigned long addr = ntohl(inet_addr("127.0.0.1"));
sess.AddDestination(addr, 6000);
d、目標地址全部指定之后,接著就可以調用 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);
e、對于流媒體數據的接收端,首先需要調用 RTPSession 類的 PollData() 方法來接收發送過來的 RTP 或者 RTCP 數據報。由于同一個 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 () 方法來進行設置。 下面是采用第三種接收模式的程序示例。
if (sess.GotoFirstSourceWithData()) { ?
?do { ?
? sess.AddToAcceptList(remoteIP, allports,portbase);
? ? ? ? ?sess.SetReceiveMode(RECEIVEMODE_ACCEPTSOME);
? ?RTPPacket *pack; ? ? ? ?
? ?pack = sess.GetNextPacket(); ? ? ? ? ? ?// 處理接收到的數據 ? ?
? ?delete pack; ? }
?while (sess.GotoNextSourceWithData());
?}
?(2)程序流程圖
發送:獲得接 收端的 IP 地址和端口號 ? ? ? ?創建 RTP 會話 ? ? ? ?指定 RTP 數據接收端 設置 RTP 會話默認參數 ? 發送流媒體數據
接收:獲得用戶指定的端口號 ?創建RTP會話 ?設置接收模式 ?接受RTP數據 ?檢索RTP數據源 ?獲取RTP數據報 ?刪除RTP數據報
三、環境搭建及編譯方法
引用(1)Toolchain的安裝
首先找到xscale-arm-toolchain.tgz文件,假設該文件包放在/tmp/下
#cd /
#tar -zxvf /tmp/xscale-arm-toolchain.tgz
再設置環境變量
#export PATH=/usr/local/arm-linux/bin:$PATH
最后檢查一下交叉編譯工具是否安裝成功
#arm-linux-g++ --version
看是否顯示arm-linux-g++的版本,如有則安裝成功。
(2)JRTPLIB 庫的交叉編譯及安裝
首先從 JRTPLIB 的網站(http://lumumba.luc.ac.be/jori/jrtplib/jrtplib.htmll) 下載最新的源碼包,此處使用的是jrtplib-2.8.tar,假設下載后的源碼包放在/tmp下,執 行下面的命令對其解壓縮:
#cd /tmp
#tar -zxvf jrtplib-2.8.tar
然后要對jrtplib進行配置和編譯
#cd jrtplib-2.8
#./configure CC=arm-linux-g++ cross-compile=yes
修改Makefile文件
將鏈接命令ld 和ar改為arm-linux-ld和 arm-linux-ar
#make
最后再執行如下命令就可以完成 JRTPLIB 的安裝:
#make install
(3)程序編譯
a、配置編譯環境
可以用export來配置,也可以用編寫Makefile的方法。這里采用Makefile。
編寫Makefile&:
INCL = -I/usr/local/include
CFLAGS = -pipe -O2 -fno-strength-reduce
LFLAGS = /usr/local/lib/libjrtp.a -L/usr/X11R6/lib
LIBS = -LX11 -LXext /usr/local/lib/libjrtp.a
CC = arm-linux-g++
main:main.o
$(CC) $(LFLAGS) $(INCL) -o main main.o $(LIBS)
main.o:main.cpp
clean:
rm -f main
rm -f *.o
.SUFFIXES:.cpp
.cpp.o:
$(CC) -c $(CFLAGS) $(INCL) -o $@ $< ? ? ? ? /* ?$@表示目標的完整名字 ? ? ?*/
? ? ? ? ?/* $<表示第一個依賴文件的名字 */
b、編譯
假設發送和接收程序分別放在/tmp/send和/tmp/receive目錄下
#cd /tmp/send
#make
#cd /tmp/receive
#make
四、易出錯誤及注意問題
引用1、找不到一些標準的最 基本的一些頭文件。
?主要是因為Toolchain路徑沒安裝對,要 嚴格按照步驟安裝。
2、找不到使用的jrtplib庫中的一些頭文件。
?在 jrtplib的安裝目錄下,include路徑下不能再有別的目錄。
3、recieve函數接收數據包不能正確提出所要數據。
?由于每一個RTP數據報都由頭部(Header)和負載(Payload)兩個部分組成,若使用getrawdata()是返回整個數據包的數據,包含 傳輸媒體的類型、格式、序列號、時間戳以及是否有附加數據等信息。getpayload()函數是返回所發送的數據。兩者一定要分清。
4、設置RECEIVEMODE_ACCEPTSOME 接收模式后,運行程序接收端不能接包。
?IP地址格式出了問題。iner_addr()與ntohl()函數要用對,否則參數傳不進去,接受列表中無值,當然接收不了數據包。
5、編譯通過,但測試時接收端不能接收到數據。
?可能是接收機防火墻未關閉。運行:
?#iptables -F
?也可能是IP地址沒有設置好。運行:
?#ifocnfig eth0 ?*.*.*.* ?netmask *.*.*.*
6、使用jrtolib庫時,在程序中include 后最好加上庫所在的路徑。五、程序
send:
view plainprint?
receive:
view plainprint?
轉載于:https://blog.51cto.com/general/328224
總結
以上是生活随笔為你收集整理的linux 下基于jrtplib库的实时传送实现的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 如何使用grup制作U盘多重启动盘
- 下一篇: linux DNS服务器配置