轉載地址:http://blog.csdn.net/futurepeter/article/details/5312814
一、移植JRTPLib到嵌入式(arm)平臺
JRTPLIB庫是一個RTP協議的開源庫,使用這套庫文件,我們可以創建端到端的RTP連接,實現數據的實時傳輸。
JRTPLIB是使用標準c++編寫的.
下載
你可以在這裏下載JRtplib,同時,需要下載JThread。
解壓
解壓目錄/usr/local/software/
tar -jxvf jrtplib-3.7.1.tar.bz2
tar -zxvf jthread-1.2.1.tar.gz
解壓後在當前文件夾下會生成rtplib-3.7.1,jthread-1.2.1兩個目錄。
安裝jthread
採用默認的安裝路徑,安裝結束後將回在/usr/local/include /usr/local/lib下生成相應的頭文件與庫。此外,還需要指定編譯環境,將Host設置爲arm -linux,CC設定爲交叉編譯器的路徑,具體設置方法可以在終端中輸入./configure –help查看。
進入解壓文件目錄:
cd /usr/local/software/ jthread-1.2.1
在終端中輸入:
./configure
-host=arm-linux
CC=arm-linux-gcc
CXX=arm-linux-g++
將生成一個Makefile文件。
執行
make
make install
jthread安裝完畢。
安裝JRtpLib
和安裝JThread類似
進入解壓後目錄
cd /usr/local/software/ rtplib-3.7.1
執行配置文件
./configure
-host=arm-linux
CC=arm-linux-gcc
CXX=arm-linux-g++
編譯:
1. 遇到了第一個棘手的問題,提示can't retrieve login name,建立不了rtpsession。在rtpsession.cpp中。
後來發現是RTPSession::CreateCNAME這個函數搞得鬼
這個函數會從系統調用裏獲取loginname,但是一般的板子由於內核和文件系統的原因都沒有loginname,所以
if (!gotlogin)
{
char *logname = getenv("LOGNAME");
if (logname == 0)
return ERR_RTP_SESSION_CANTGETLOGINNAME;//這裏return了一個error
strncpy((char *)buffer,logname,*bufferlength);
}
所以我強制將logname的值設爲root,就ok了。
2、有些人會遇到arm和pc無法互相接受數據包的問題,但是pc和pc,arm和arm就可以收到。我用sniffer抓了一下包發現確實是有數據包的,所以應該不是程序的問題。這個問題上網查了一下,也沒人說的明白,只有一個高人點了一下,可能是字節序和位域的問題。自己又研究了一下,也是一知半解。
一般x86的pc機是用小端字節序(little endian),而嵌入式平臺一般是大端字節序(big endian),可能是由於字節序的不同,導致了明明存在數據包,卻認不出來的問題
解決方法:在/usr/local/software/jrtplib3/src/rtpconfig_unix.h 中註銷掉大端模式
//#define RTP_BIG_ENDIAN // comment this if the target is a little endian system
//#define RTP_SUPPORT_THREAD
添加線程後編譯不通過,所以一起把線程宏定義註銷掉
make
make install
完成後,可以看到/usr/local/lib目錄下多了JThread和JRtpLib的庫文件:
測試
在JRtpLib目錄下有幾個例子程序,我們可以用來測試JRtpLib。進入/prj/share/source/jrtplib-3.7.1/examples目錄:
cd /prj/share/source/jrtplib-3.7.1/examples
將編譯好(下載時已交叉編譯好,可以通過file example1查看,如果看到目標使用環境是ARM則說明以交叉編譯好,另外如果沒有剪裁,也可以通過arm_v5t_le-strip example1進行剪裁以去掉調試信息)的例子文件複製到nfs目錄下:
cp example1 /opt/nfs//opt/dvsdemos/
登陸到開發板,進入文件所在目錄,輸入:
./example1
即可看到運行結果:
enter local portbase
JRTPLIB在arm和pc間收不到數據包的問題
最近本人在作關於RTP的項目,要求在arm和pc間用RTP協議傳輸數據。
1. 下載jrtplib-3.7.1和jthread-1.2.1。
2. pc上編譯很簡單,windows下編譯過程如下:
首先編譯jthread庫。然後解壓縮jrtplib,打開jrtplib.dsw工程,注意工程的include路徑設置,要包含jrtplib和jthread的頭文件,然後編譯。將編譯生成的jrtplib.lib和jthread.lib拷貝到Microsoft
Visual Studio的VC98/Lib目錄下。在編譯jrtplib.lib和jthread.lib的時候,在project——settings——C/C++——Code
generation:use run-time library中,對於debug,選擇:Debug Multithreaded DLL,對於release,則選擇:Multithreaded
DLL。
那些example的編譯,需要在cpp文件開頭加上:
#pragma comment(lib, "jrtplib.lib")
#pragma comment(lib, "jthread.lib")
#pragma comment(lib, "WS2_32.lib")//pragma的作用自己上網查吧
編譯的時候,同樣選擇編譯選項:Debug Multithreaded DLL(對於debug);Multithreaded
DLL(對於release)。
然後在windows上測試example1,這是一個往指定IP的端口上發包的程序,同樣也可以收包,測試通過。
3.jrtplib庫的移植,主要參考了這篇文章http://blog.csdn.net/neohuo/archive/2006/03/08/618684.aspx
編譯器我用的arm-linux-gcc3.4.1,2.95.3也用過,不過需要修改一下rtperror裏面的代碼。可能還有些問題沒提到,自己注意一下吧。
4.移植成功後,我遇到了第一個棘手的問題,提示can't retrieve login name,建立不了rtpsession。
後來發現是RTPSession::CreateCNAME這個函數搞得鬼
這個函數會從系統調用裏獲取loginname,但是一般的板子由於內核和文件系統的原因都沒有loginname,所以
if (!gotlogin)
{
char *logname = getenv("LOGNAME");
if (logname == 0)
return ERR_RTP_SESSION_CANTGETLOGINNAME;//這裏return了一個error
strncpy((char *)buffer,logname,*bufferlength);
}
所以我強制將logname的值設爲root,就ok了。
5.有些人會遇到arm和pc無法互相接受數據包的問題,但是pc和pc,arm和arm就可以收到。我用sniffer抓了一下包發現確實是有數據包的,所以應該不是程序的問題。這個問題上網查了一下,也沒人說的明白,只有一個高人點了一下,可能是字節序和位域的問題。自己又研究了一下,也是一知半解。
一般x86的pc機是用小端字節序(little endian),而嵌入式平臺一般是大端字節序(big endian),可能是由於字節序的不同,導致了明明存在數據包,卻認不出來的問題。其實,JRTPLIB的開發者可能已經考慮到了這個問題(真牛),在rtpstructs.h中,有這樣的代碼定義:
struct RTPHeader
{
#ifdef RTP_BIG_ENDIAN
uint8_t version:2;
uint8_t padding:1;
uint8_t extension:1;
uint8_t csrccount:4;
uint8_t marker:1;
uint8_t payloadtype:7;
#else // little endian
uint8_t csrccount:4;
uint8_t extension:1;
uint8_t padding:1;
uint8_t version:2;
uint8_t payloadtype:7;
uint8_t marker:1;
#endif // RTP_BIG_ENDIAN
uint16_t sequencenumber;
uint32_t timestamp;
uint32_t ssrc;
};
這是一個位域結構體,明眼人一下子就看出來了,jrtplib庫使用哪種字節序完全取決於RTP_BIG_ENDIAN的定義,這樣問題就簡單化了。
我看了一下我編譯arm下jrtplib庫的rtpconfig_unix.h這個文件,裏面果然定義了一個RTP_BIG_ENDIAN,所以要和pc採用的小端字節序一樣,將這個定義取消掉,重新編譯庫。
最後運行exmaple1例子,pc 和arm可以互相接受數據包拉!:)這樣會引起其他什麼問題我還不知道,明天就可以動手編寫自己的程序了,呵呵。