jrtplib+jthread 交叉編譯

轉載地址: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.1jthread-1.2.1兩個目錄。

安裝jthread

 

採用默認的安裝路徑,安裝結束後將回在/usr/local/include  /usr/local/lib下生成相應的頭文件與庫。此外,還需要指定編譯環境,將Host設置爲arm -linuxCC設定爲交叉編譯器的路徑,具體設置方法可以在終端中輸入./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有些人會遇到armpc無法互相接受數據包的問題,但是pcpcarmarm就可以收到。我用sniffer抓了一下包發現確實是有數據包的,所以應該不是程序的問題。這個問題上網查了一下,也沒人說的明白,只有一個高人點了一下,可能是字節序和位域的問題。自己又研究了一下,也是一知半解。

一般x86pc機是用小端字節序(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目錄下多了JThreadJRtpLib的庫文件:

 

測試

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

 

 

 

JRTPLIBarmpc間收不到數據的問題

最近本人在作關於RTP的項目,要求在armpc間用RTP協議傳輸數據。

1. 下載jrtplib-3.7.1jthread-1.2.1

2. pc上編譯很簡單,windows下編譯過程如下:

首先編譯jthread庫。然後解壓縮jrtplib,打開jrtplib.dsw工程,注意工程的include路徑設置,要包含jrtplibjthread的頭文件,然後編譯。將編譯生成的jrtplib.libjthread.lib拷貝到Microsoft Visual StudioVC98/Lib目錄下。在編譯jrtplib.libjthread.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.12.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.有些人會遇到armpc無法互相接受數據包的問題,但是pcpcarmarm就可以收到。我用sniffer抓了一下包發現確實是有數據包的,所以應該不是程序的問題。這個問題上網查了一下,也沒人說的明白,只有一個高人點了一下,可能是字節序和位域的問題。自己又研究了一下,也是一知半解。

一般x86pc機是用小端字節序(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的定義,這樣問題就簡單化了。

我看了一下我編譯armjrtplib庫的rtpconfig_unix.h這個文件,裏面果然定義了一個RTP_BIG_ENDIAN,所以要和pc採用的小端字節序一樣,將這個定義取消掉,重新編譯庫。

最後運行exmaple1例子,pc arm可以互相接受數據包拉!:)這樣會引起其他什麼問題我還不知道,明天就可以動手編寫自己的程序了,呵呵。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章