1. 程式人生 > >Linux下編譯jrtplib和jthread 大致過程 再修改

Linux下編譯jrtplib和jthread 大致過程 再修改

Linux下編譯jrtplib和jthread


 操作環境:
 


Host OS: Windows 7
 
VMware Workstation:6.5.1
 
Guest OS: Fedora 9
 
Develop Board: MINI2440
 
Cross-Complier: ARM-Linux-GCC 4.3.2
 
 
 
關於jrtp的一些說明:
 
說明1:jrtp有兩種資料接收方式:第一種是用jthread庫提供的執行緒自動在後臺執行對資料的接收。第二種是使用者自己呼叫RTPSession中的Poll方法。如果採取第一種方法則要安裝jthread庫,則安裝 jthread-1.2.1.tar.gz,而且 jthread-1.2.1必須先與jrtp-3.7.1的安裝。因為在jrtp-3.7.1的configure中,會查詢系統是否有編譯了jthread庫,如果有,那麼編譯的jrtp庫會開啟對jthread的支援。因此如果先編譯jrtp在編譯jthread,編譯出來的jrtp是沒有開啟對jthread的支援的。如果採用第二種方法,那麼可以不用編譯jthread庫,而直接編譯jrtp庫。
 
 
 


jrtp-3.7.1.tar.gz與jthread-1.2.1.tar.gz的下載地址
 
http://research.edm.uhasselt.be/~jori/page/index.php?n=CS.Jrtplib
 
 
 
 
 
一,編譯為PC所用:
 


PS:./configure –help 可以檢視一些可以配置選項
 
jthread-1.2.1的編譯
 
[roo
[email protected]
pc-jrtp]# tar -zxvf jthread-1.2.1.tar.gz
 
[[email protected] pc-jrtp]# cd jthread-1.2.1
 
[[email protected] jthread-1.2.1]# ./configure --prefix=/opt/mini2440/pc-jrtp
 
[[email protected] jthread-1.2.1]# make
 
[[email protected] jthread-1.2.1]# make install
 
說明: --prefix=指定編譯後的jthread庫安裝到什麼目錄。
 
 
 
執行make install時會出現如下資訊:
 


-----------------------------------------------------------------
 
Libraries have been installed in:
 
   /opt/mini2440/pc-jrtp/lib
 
 
 
If you ever happen to want to link against installed libraries
 
in a given directory, LIBDIR, you must either use libtool, and
 
specify the full pathname of the library, or use the `-LLIBDIR'
 
flag during linking and do at least one of the following:
 
   - add LIBDIR to the `LD_LIBRARY_PATH' environment variable
 
     during execution
 
   - add LIBDIR to the `LD_RUN_PATH' environment variable
 
     during linking
 
   - use the `-Wl,--rpath -Wl,LIBDIR' linker flag
 
   - have your system administrator add LIBDIR to `/etc/ld.so.conf'
 
 
 
See any operating system documentation about shared libraries for
 
more information, such as the ld(1) and ld.so(8) manual pages.
 
-----------------------------------------------------------------
 
這段英文告訴我們編譯後的jthread庫安裝到什麼目錄下,而且如果使用這個庫編譯自己的檔案應該怎麼做。可以參考靜態函式庫與動態函式庫。
 
 
 
安裝成功後在自己指定目錄下有:include與lib兩個資料夾
 
include中又有一個jthread的資料夾,裡面包含了jthread庫的標頭檔案
 
lib中包含了編譯成功的jthread庫:包括動態庫libjthread-1.2.1.so與靜態庫libjthread.a
 
 
 
(2) jrtplib-3.7.1的編譯
 


[
[email protected]
pc-jrtp]# tar -zxvf jrtplib-3.7.1.tar.gz
 
[[email protected] pc-jrtp]# cd jrtplib-3.7.1
 
[[email protected] pc-jrtp]#./configure--prefix=/opt/mini2440/pc-jrtp/--with-jthread-includes=/opt/mini2440/pc-jrtp/include/jthreadLDFLAGS=-L/opt/mini2440/pc-jrtp/lib
 
 
 //*    tq2440 test  *///
 ./configure --prefix=/opt/tq2440/pc-jrtp/ --with-jthread-includes=/opt/tq2440/pc-jrtp/include/jthread LDFLAGS=-L/opt/tq2440/pc-jrtp/lib
/////
 說明:
 
--prefix= --prefix:指定編譯後的jrtplib庫安裝到什麼目錄。
 
--with-jthread-includes:指定之前安裝的jthread庫的標頭檔案安裝在什麼目錄下。如果不需要jthread的支援,這個選項可以不用。
 
LDFLAGS:為編譯時需要連線的動態庫的路徑。如果不需要jthread庫的支援,這個選項不要。
 
 
 
configure過程中出現的提示資訊:
 


checking for JThread include files... in "/opt/mini2440/pc-jrtp/include/jthread"
 
checking JThread version... >= 1.1.0
 
checking if we can link against jthread and pthread... yes
 
說明jthread路徑正確,配置檔案開啟了對jthread的支援。
 
 
 
接著進行make與make install
 


[
[email protected]
jrtplib-3.7.1]# make
 
[[email protected] jrtplib-3.7.1]# make install
 
在不修改原始檔情況下, make的過程中直接編譯可能出現的錯誤:
 
在Fedora 9中make提示的錯誤:
 


rtppacket.cpp:311: error: 'memcpy' was not declared in this scope
 
或者:
 
在Fedora 13中make提示的錯誤:
 


rtperrors.cpp: In function 'std::string RTPGetErrorString(int)':
 
rtperrors.cpp:225: error: 'snprintf' was not declared in this scope
 
為了make成功,需要修改jrtplib-3.7.1原始檔rtpdefines.h
 
新增如下語句: 
 #include <stdio.h> 
 #include <stdarg.h> 
 #include <string.h>
 
操作如下:
 


[[email protected] jrtplib-3.7.1]# cd src/
 
[[email protected] src]# vim rtpdefines.h
 
// rtpdefines.h
 
75 #include <stdio.h>
 
 76 #include <stdarg.h>
 
 77 #include <string.h>
 
 78 #if (defined(WIN32) || defined(_WIN32_WCE))
 
 79         #if (!defined(_WIN32_WCE)) && (defined(_MSC_VER) && _MSC_VER >= 1400 )
 
 80                 #define RTP_SNPRINTF _snprintf_s
 
 81         #else
 
 82                 #define RTP_SNPRINTF _snprintf
 
 83         #endif
 
 84 #else
 
 85         #define RTP_SNPRINTF snprintf
 
 86 #endif // WIN32 || _WIN32_WCE
 
重新make後可以成功。
 
 
 
make isntall後有如下資訊
 


-----------------------------------------------------------------
 
Libraries have been installed in:
 
   /opt/mini2440/pc-jrtp/lib
 
 
 
If you ever happen to want to link against installed libraries
 
in a given directory, LIBDIR, you must either use libtool, and
 
specify the full pathname of the library, or use the `-LLIBDIR'
 
flag during linking and do at least one of the following:
 
   - add LIBDIR to the `LD_LIBRARY_PATH' environment variable
 
     during execution
 
   - add LIBDIR to the `LD_RUN_PATH' environment variable
 
     during linking
 
   - use the `-Wl,--rpath -Wl,LIBDIR' linker flag
 
   - have your system administrator add LIBDIR to `/etc/ld.so.conf'
 
 
 
See any operating system documentation about shared libraries for
 
more information, such as the ld(1) and ld.so(8) manual pages.
 
-----------------------------------------------------------------
 
這段英文告訴我們編譯後的jrtp庫安裝到什麼目錄下,而且如果使用這個庫編譯自己的檔案應該怎麼做。
 
 
 
安裝成功後在自己指定目錄下有:include與lib兩個資料夾
 
include中又有一個jrtplib的資料夾,裡面包含了jrtplib庫的標頭檔案
 
lib中包含了編譯成功的jrtp庫:包括動態庫libjrtp-3.7.1.so與靜態庫libjrtp.a。
 
 
 
 
 
二,編譯為MINI2440(ARM)所用:
 
步驟與編譯為PC所用一樣,但是configure的設定過有所不同,現在說明:
 
(1) 對於jthread
 
<1>
./configure  --prefix=/opt/mini2440/arm-jrtp –host=arm-linux CC=arm-linux-gcc CXX=arm-linux-g++\
//*****arm_v5t_le-gcc//


./configure  --prefix=/opt/tq2440/arm-jrtp  --host=arm-montavista-linux CC=arm_v5t_le-gcc CXX=arm_v5t_le-g++


//*****//




<2> make 
<3 > make install
 (2) 對於jrtlib
 
<1>
./configure–prefix=/opt/mini2440/arm-jrtp –host=arm-linux–with-jthread-includes=/opt/mini2440/arm-jrtp/includes CC=arm-linux-gccCXX=arm-linux LDFLAGS=-L/opt/mini2440/arm-jrtp/lib
 ////****arm_v5t*****///
 
 ./configure -–prefix=/opt/tq2440/arm-jrtp --host=arm-montavista-linux –with-jthread-includes=/opt/tq2440/arm-jrtp/includes CC=arm_v5t_le-gcc CXX=arm_v5t_le-g++ LDFLAGS=-L/opt/tq2440/arm-jrtp/lib
 
 ////****/////
然後會看到如下提示資訊:
 


ASSUMING TARGET IS BIG ENDIAN:
 
  The script detected a cross-compiler on your system. This can mean that
 
  there really is a cross-compiler installed, or that for some other reason,
 
  a simple program could not be run. You should check the config.log file
 
  to verify this.
 
  Since we are assuming a cross-compiler, we won't be able to actually test
 
  any program. More important, we cannot test if the system is big or little
 
  endian.
 
  For now, big endian is assumed. If this assumption should be wrong, you will
 
  have to comment the appropriate line in 'rtpconfig_unix.h'
 
說明:configure把目標平臺預設為是大端模式。如果需要改變則要修改rtpconfig_ unix.h。
 
 
 
我們那麼應該測試開發板是大端模式還是小端模式:
 
至於什麼是大端模式,什麼小端模式,以及為什麼要測試請看我部落格上的大端模式與小端模式。
 
 
 
測試程式:
 


1 #include
 
  2 int main(void)
 
  3 {
 
  4         int num = 0x1234;
 
  5         char *p = &num;
 
  6         if (*p == 0x12){
 
  7                 printf("Big Endian/n");
 
  8         }
 
  9         else{
 
 10                 printf("Little Endian/n");
 
 11         }
 
 12         return 0;
 
 13  }
 
儲存後用交叉編譯器編譯生成可執行檔案後,放到目標平臺上執行。從而判斷出目標平臺是什麼模式。
 
通過測試下,得知MINI2440預設為小端模式,因此需要修改rtpconfig_ unix.h
 
檔案在:
 


/opt/mini2440/arm-jrtp/jrtplib-3.7.1/src/rtpconfig_unix.h
 
修改操作如下:
 


33 #ifndef RTPCONFIG_UNIX_H
 
 34
 
 35 #define RTPCONFIG_UNIX_H
 
 36
 
 37 // Don't have
 
 38
 
 39 // Don't have
 
 40
 
 41 //#define RTP_BIG_ENDIAN // comment this if the target is a little endian system
 
 42
 
 43 #define RTP_SOCKLENTYPE_UINT
 
則是把第41行註釋了。註釋後則以小段模式來編譯。
 
















7.由於板子上的linux作業系統可以在沒有使用者名稱的情況下登入,所以rtpsession.cpp中的CreateCNAME可能報Can't retrieve login name的錯誤,因此需要修改幾句程式碼:
 








[cpp] view plaincopy


 01. if (!gotlogin)  
02. {  
03.     char *logname = getenv("LOGNAME");  
04.     if (logname == 0)  
05.     {  
06.         strncpy((char*)buffer, "root", *bufferlength);  
07.     }  
08.     else  
09.         strncpy((char *)buffer,logname,*bufferlength);  
10. }  
 
.arm板執行時出現Can't retrieve login name   
 
    原因:RTP的JRTPLIB庫中的RTPSession中的Create->InternalCreate->CreateCNAME中,有對使用者名稱進行一定操作,其中的getlogin_r(),getlogin()和getenv()操作都會因為使用者名稱為空,而返回錯誤ERR_RTP_SESSION_CANTGETLOGINNAME。
     解決的方式有3種:1)在開發板上輸入export   LOGNAME=root  2)大部分開發板還是需要使用者名稱登陸的,即在檔案系//// example2.cpp的改進 簡單的發包
/////////////////////////////
////////////////////////////////
///////////////////////////////////
#include "rtpsession.h"
#include "rtpsessionparams.h"
#include "rtpudpv4transmitter.h"
#include "rtpipv4address.h"
#include "rtptimeutilities.h"
#include "rtppacket.h"
#include <stdlib.h>
#include <iostream>


int main(void)
{
#ifdef WIN32
WSADATA dat;
WSAStartup(MAKEWORD(2,2),&dat);
#endif // WIN32

RTPSession session;

RTPSessionParams sessionparams;
sessionparams.SetOwnTimestampUnit(1.0/8000.0);

RTPUDPv4TransmissionParams transparams;
transparams.SetPortbase(8000);

int status = session.Create(sessionparams,&transparams);
if (status < 0)
{
std::cerr << RTPGetErrorString(status) << std::endl;
exit(-1);
}

   //uint8_t localip[]={127,0,0,1};
uint8_t localip[]={101,69,255,130};
RTPIPv4Address addr(localip,9000);

status = session.AddDestination(addr);
if (status < 0)
{
std::cerr << RTPGetErrorString(status) << std::endl;
exit(-1);
}

session.SetDefaultPayloadType(96);
session.SetDefaultMark(false);
session.SetDefaultTimestampIncrement(160);

uint8_t silencebuffer[160];
for (int i = 0 ; i < 160 ; i++)
silencebuffer[i] = 128;


RTPTime delay(2);
RTPTime starttime = RTPTime::CurrentTime();

bool done = false;
while (!done)
{
status = session.SendPacket(silencebuffer,160);
  
        if (status < 0)
{
std::cerr << RTPGetErrorString(status) << std::endl;
exit(-1);
}
    printf("send package succeeful \n");
#if 1
session.BeginDataAccess();
if (session.GotoFirstSource())
{


       printf("receive package succeeful \n");
do
{
RTPPacket *packet;


while ((packet = session.GetNextPacket()) != 0)
{


               printf("receive package data  \n");
std::cout << "Got packet with " 
         << "extended sequence number " 
         << packet->GetExtendedSequenceNumber() 
         << " from SSRC " << packet->GetSSRC() 
         << std::endl;
session.DeletePacket(packet);
}
} while (session.GotoNextSource());
}
session.EndDataAccess();
#endif
RTPTime::Wait(delay);

RTPTime t = RTPTime::CurrentTime();
t -= starttime;
if (t > RTPTime(60.0))
done = true;
}

delay = RTPTime(10.0);
session.BYEDestroy(delay,"Time's up",9);

#ifdef WIN32
WSACleanup();
#endif // WIN32
return 0;
}

統完全啟動後再執行,也能解決。 3)因為板子上的檔案系統有時不需要使用者名稱就可以直接登入,而在我們可以通過修改JRTPLIB庫的CreateCNAME原始碼來為系統預設設定一個使用者名稱。在RTPSession.cpp的第1400行。
 








然後就可以make與make install了。
 
 
 
三,最後一步就是測試了:
 
(1) 首先把編譯為PC所用的庫檔案:libjrtp-3.7.1.so與libjthread.so複製到Fedora9的 /lib。
 
(2) 把交叉編譯後生成的庫檔案:libjrtp-3.7.1.so與libjthread.so複製到開發板上的/lib。
 
//// example2.cpp的改進 簡單的發包
/////////////////////////////
////////////////////////////////
///////////////////////////////////
#include "rtpsession.h"
#include "rtpsessionparams.h"
#include "rtpudpv4transmitter.h"
#include "rtpipv4address.h"
#include "rtptimeutilities.h"
#include "rtppacket.h"
#include <stdlib.h>
#include <iostream>

int main(void)
{
#ifdef WIN32
	WSADATA dat;
	WSAStartup(MAKEWORD(2,2),&dat);
#endif // WIN32
		
	RTPSession session;
	
	RTPSessionParams sessionparams;
	sessionparams.SetOwnTimestampUnit(1.0/8000.0);
			
	RTPUDPv4TransmissionParams transparams;
	transparams.SetPortbase(8000);
			
	int status = session.Create(sessionparams,&transparams);
	if (status < 0)
	{
		std::cerr << RTPGetErrorString(status) << std::endl;
		exit(-1);
	}
	
   //uint8_t localip[]={127,0,0,1};
	uint8_t localip[]={101,69,255,130};
	RTPIPv4Address addr(localip,9000);
	
	status = session.AddDestination(addr);
	if (status < 0)
	{
		std::cerr << RTPGetErrorString(status) << std::endl;
		exit(-1);
	}
	
	session.SetDefaultPayloadType(96);
	session.SetDefaultMark(false);
	session.SetDefaultTimestampIncrement(160);
	
	uint8_t silencebuffer[160];
	for (int i = 0 ; i < 160 ; i++)
		silencebuffer[i] = 128;

	RTPTime delay(2);
	RTPTime starttime = RTPTime::CurrentTime();
	
	bool done = false;
	while (!done)
	{
		status = session.SendPacket(silencebuffer,160);
	   
        if (status < 0)
		{
			std::cerr << RTPGetErrorString(status) << std::endl;
			exit(-1);
		}
    	printf("send package succeeful \n");	
#if 1
		session.BeginDataAccess();
		if (session.GotoFirstSource())
		{

	        printf("receive package succeeful \n");	
			do
			{
				RTPPacket *packet;

				while ((packet = session.GetNextPacket()) != 0)
				{

	                printf("receive package data  \n");	
					std::cout << "Got packet with " 
					          << "extended sequence number " 
					          << packet->GetExtendedSequenceNumber() 
					          << " from SSRC " << packet->GetSSRC() 
					          << std::endl;
					session.DeletePacket(packet);
				}
			} while (session.GotoNextSource());
		}
		session.EndDataAccess();
#endif		
		RTPTime::Wait(delay);
		
		RTPTime t = RTPTime::CurrentTime();
		t -= starttime;
		if (t > RTPTime(60.0))
			done = true;
	}
	
	delay = RTPTime(10.0);
	session.BYEDestroy(delay,"Time's up",9);
	
#ifdef WIN32
	WSACleanup();
#endif // WIN32
	return 0;
}
/////////////////////
makefile 
////////////////////
DIR=/opt/tq2440/arm-jrtp/
LIB_PATH+=$(DIR)/lib

#CFLAGS +=-static
CFLAGS += $(PJ_CFLAGS)
CFLAGS += -I/opt/mv_pro_5.0/montavista/pro/devkit/arm/v5t_le/include/
CFLAGS += -I/opt/mv_pro_5.0/montavista/pro/devkit/arm/v5t_le/lib/gcc/armv5tl-montavista-linux-gnueabi/4.2.0/include

#CFLAGS += -I$(DIR)/include/PnCppLib
CFLAGS += -I$(DIR)/include/jthread
CFLAGS += -I$(DIR)/include/jrtplib3
#CFLAGS += -I$(DIR)/include/tinyxml
#CFLAGS += -I$(DIR)/include/dfdulib

CFLAGS += -I$(PWD)
#CFLAGS += -I./Client_socket
#CFLAGS += -I./Media
#CFLAGS += -I./Work_Order
#CFLAGS += -I./FTP

#CFLAGS += -I./Ini
#CFLAGS += -I./Msq
#CFLAGS += -I./Manage
#CFLAGS += -I./RTC
#CFLAGS += -I./Sysinfo
#CFLAGS += -I./Xml

sources+=$(PWD)/main.cpp
#sources+=$(PWD)/comm.h
#sources+=$(PWD)/Client_socket/*.cpp
#sources+=$(PWD)/Ini/*.cpp
#sources+=$(PWD)/Msq/*.cpp
#sources+=$(PWD)/Manage/*.cpp
#sources+=$(PWD)/Media/*.cpp
#sources+=$(PWD)/Work_Order/*.cpp
#sources+=$(PWD)/FTP/*.cpp
#sources+=$(PWD)/RTC/*.cpp
#sources+=$(PWD)/Sysinfo/*.cpp
#sources+=$(PWD)/Xml/*.cpp


CC=/opt/mv_pro_5.0/montavista/pro/devkit/arm/v5t_le/bin/arm_v5t_le-g++
example:$(sources)
	$(CC) -DDEBUG -Wall -o [email protected] $(CFLAGS) $^ -L$(LIB_PATH) -ljthread -ljrtp -lpthread

clean:
	rm -rf example *.o