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的编译
 
[root@localhost pc-jrtp]# tar -zxvf jthread-1.2.1.tar.gz
 
[root@localhost pc-jrtp]# cd jthread-1.2.1
 
[root@localhost jthread-1.2.1]# ./configure --prefix=/opt/mini2440/pc-jrtp
 
[root@localhost jthread-1.2.1]# make
 
[root@localhost 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的编译
 


[root@localhost pc-jrtp]# tar -zxvf jrtplib-3.7.1.tar.gz
 
[root@localhost pc-jrtp]# cd jrtplib-3.7.1
 
[root@localhost 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
 


[root@localhost jrtplib-3.7.1]# make
 
[root@localhost 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  
 #include  
 #include
 
操作如下:
 


[root@localhost jrtplib-3.7.1]# cd src/
 
[root@localhost src]# vim rtpdefines.h
 
// rtpdefines.h
 
75 #include
 
 76 #include
 
 77 #include
 
 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 = #
 
  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
#include


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 
#include 

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 $@ $(CFLAGS) $^ -L$(LIB_PATH) -ljthread -ljrtp -lpthread

clean:
	rm -rf example *.o













 

你可能感兴趣的:(Linux下编译jrtplib和jthread 大致过程 再修改)