一、安装一些必要的依赖库
apt-get install build-essential git-core checkinstall yasm texi2html libvorbis-dev libx11-dev libvpx-dev libxfixes-dev zlib1g-dev
apt-get install pkg-config netcat libncurses5-dev
apt-get install nasm libx264-dev
apt-get install libv4l-dev
apt-get install libasound2-dev
apt-get install libsdl2-dev
apt-get install libxext-dev
二、交叉编译asound
先下载alsa-lib-1.2.1.2.tar.bz2解压缩。
然后./configure CC=arm-linux-gnueabihf-gcc --host=arm-linux-gnueabihf
make
make install
三、编译pjsip
./configure CC=arm-linux-gnueabihf-gcc --host=arm-linux-gnueabihf --disable-libwebrtc --disable-ssl --disable-openh264 --disable-libyuv --enable-static --prefix=/system/bin
make
make install
四、使用pjsip静态库编译一个demo
makefile如下
OBJ= main
CC= arm-linux-gnueabihf-gcc
CFLAGS= -Wall -O -O2 -DPJ_IS_BIG_ENDIAN=0 -DPJ_IS_LITTLE_ENDIAN=1
VPATH= ./
#LIBS= -lpthread -lm
INCLUDE= -I$(VPATH)include
LIB_DIR= -L$(VPATH)lib
LIB= -lpjsua2-arm-unknown-linux-gnueabihf -lstdc++ -lpjsua-arm-unknown-linux-gnueabihf -lpjsip-ua-arm-unknown-linux-gnueabihf -lpjsip-simple-arm-unknown-linux-gnueabihf -lpjsip-arm-unknown-linux-gnueabihf -lpjmedia-codec-arm-unknown-linux-gnueabihf -lpjmedia-arm-unknown-linux-gnueabihf -lpjmedia-videodev-arm-unknown-linux-gnueabihf -lpjmedia-audiodev-arm-unknown-linux-gnueabihf -lpjmedia-arm-unknown-linux-gnueabihf -lpjnath-arm-unknown-linux-gnueabihf -lpjlib-util-arm-unknown-linux-gnueabihf -lsrtp-arm-unknown-linux-gnueabihf -lresample-arm-unknown-linux-gnueabihf -lgsmcodec-arm-unknown-linux-gnueabihf -lspeex-arm-unknown-linux-gnueabihf -lilbccodec-arm-unknown-linux-gnueabihf -lg7221codec-arm-unknown-linux-gnueabihf -lpj-arm-unknown-linux-gnueabihf -lrt -lpthread -lasound -ldl -lm
$(OBJ):
$(CC) -o main.o main.c -Wall $(INCLUDE) $(LIB_DIR) $(LIB) -static
clean:
rm -f main
#include "pj/log.h"
#include "pjlib.h"
#include "pjlib-util.h"
#include "pjnath.h"
#include "pjmedia.h"
#include "pjsip.h"
#include "pjsip_simple.h"
#include "pjsip_ua.h"
#include "pjsua-lib/pjsua.h"
#include "pjmedia-codec.h"
#define THIS_FILE "#### windaka_log"
#define SIP_DOMAIN "10.10.5.250"
#define SIP_USER "01010011"
#define SIP_PASSWD "0000"
#define current_acc pjsua_acc_get_default()
/*####获取所有声卡设备的结构####*/
typedef struct pjmedia_aud_sount_cnt{
int devcnt;
char name[32][32];
unsigned devid[32];
}pjmedia_aud_sound_cnt;
/*####收到呼叫后的回调函数####*/
static void on_incoming_call(pjsua_acc_id acc_id, pjsua_call_id call_id,
pjsip_rx_data *rdata)
{
pjsua_call_info ci;
PJ_UNUSED_ARG(acc_id);
PJ_UNUSED_ARG(rdata);
/*####获取主叫信息####*/
pjsua_call_get_info(call_id, &ci);
/*####打印出主叫的URL####*/
PJ_LOG(3,(THIS_FILE, "#### ---->Incoming call from %.*s!!",
(int)ci.remote_info.slen,
ci.remote_info.ptr));
/*####收到呼叫后的应答函数接口####*/
pjsua_call_answer(call_id, 200, NULL, NULL);
}
/* Callback called by the library when call's state has changed */
static void on_call_state(pjsua_call_id call_id, pjsip_event *e)
{
pjsua_call_info ci;
PJ_UNUSED_ARG(e);
pjsua_call_get_info(call_id, &ci);
PJ_LOG(3,(THIS_FILE, "Call %d state=%.*s,state=%d,last_status=%d", call_id,
(int)ci.state_text.slen,
ci.state_text.ptr,ci.state,ci.last_status));
}
/* Callback called by the library when call's media state has changed */
static void on_call_media_state(pjsua_call_id call_id)
{
pjsua_call_info ci;
pjsua_call_get_info(call_id, &ci);
if (ci.media_status == PJSUA_CALL_MEDIA_ACTIVE) {
// When media is active, connect call to sound device.
pjsua_conf_connect(ci.conf_slot, 0);
pjsua_conf_connect(0, ci.conf_slot);
}
}
/*####程序异常退出接口####*/
static void error_exit(const char *title, pj_status_t status)
{
pjsua_perror(THIS_FILE, title, status);
pjsua_destroy();
exit(1);
}
void get_device_sound_name(char *pathName,char *sound_name){
FILE *fp;
char tmp[32];
if(pathName == NULL){
return ;
}
fp = fopen(pathName,"r");
if(fp == NULL){
return ;
}
memset(tmp,0,sizeof(tmp));
fread(tmp,1,32,fp);
strcpy(sound_name,tmp);
fclose(fp);
return ;
}
void del_str_line(char *str){
char *p = str;
while('\n' != *p){
p++;
if(*p =='\0'){
return ;
}
}
*p = '\0';
return ;
}
int main(int argc,char *argv[]){
pjsua_acc_id acc_id;
pj_status_t status;
/*####创建pjsua####*/
status = pjsua_create();
if (status != PJ_SUCCESS){
error_exit("Error in pjsua_create()", status);
}
/*####初始化pjsua####*/
{
pjsua_config cfg;
pjsua_logging_config log_cfg;
pjsua_config_default(&cfg);
cfg.cb.on_incoming_call = &on_incoming_call;
cfg.cb.on_call_media_state = &on_call_media_state;
cfg.cb.on_call_state = &on_call_state;
pjsua_logging_config_default(&log_cfg);
log_cfg.console_level = 4;
status = pjsua_init(&cfg, &log_cfg, NULL);
if (status != PJ_SUCCESS){
error_exit("Error in pjsua_init()", status);
}
}
/*####设置pjsua使用的本地端口####*/
{
pjsua_transport_config cfg;
pjsua_transport_config_default(&cfg);
/*####本地使用5061端口####*/
cfg.port = 5060;
status = pjsua_transport_create(PJSIP_TRANSPORT_UDP, &cfg, NULL);
if (status != PJ_SUCCESS){
error_exit("Error creating transport", status);
}
}
/* Initialization is done, now start pjsua */
status = pjsua_start();
if (status != PJ_SUCCESS){
error_exit("Error starting pjsua", status);
}
/* Register to SIP server by creating SIP account. */
{
pjsua_acc_config cfg;
pjsua_acc_config_default(&cfg);
int iloop = 0;
char devName[32];
unsigned devId = 0;
static pjmedia_aud_sound_cnt *p = NULL;
/*####获取系统指定声卡的name####*/
memset(devName,0,sizeof(devName));
//get_device_sound_name("/proc/asound/card0/id",devName);
/*####获取设备所有的声卡信息####*/
//printf("#### ---->get_card_calc_dev() \n");
//p = get_card_calc_dev();
//printf("#### ---->p->devcnt=[%d]\n",p->devcnt);
#if 0
char tmp[64];
memset(tmp,0,sizeof(tmp));
strcpy(tmp,"default:CARD=");
strcat(tmp,devName);
del_str_line(tmp);
/*####根据指定声卡的name获取声卡的ID####*/
printf("#### ---->p->devcnt = [%d]\n",p->devcnt);
for(iloop = 0; iloop < p->devcnt;iloop++){
printf("#### ---->tmp=[%s],p->name[iloop]=[%s]\n",tmp,p->name[iloop]);
if(strcmp(tmp,p->name[iloop]) == 0){
devId = p->devid[iloop];
printf("#### ---->get device [%s],id = [%d]\n",p->name[iloop],devId);
break;
}
}
/*####指定设备使用哪个声卡####*/
pjsua_set_snd_dev(devId,devId);
#endif
/*####设置SIP账号信息####*/
cfg.vid_out_auto_transmit = PJ_TRUE;
cfg.id = pj_str("sip:" SIP_USER "@" SIP_DOMAIN);
cfg.reg_uri = pj_str("sip:" SIP_DOMAIN);
cfg.cred_count = 1;
cfg.cred_info[0].realm = pj_str("*");
cfg.cred_info[0].scheme = pj_str("digest");
cfg.cred_info[0].username = pj_str(SIP_USER);
cfg.cred_info[0].data_type = PJSIP_CRED_DATA_PLAIN_PASSWD;
cfg.cred_info[0].data = pj_str(SIP_PASSWD);
/*####添加SIP账号####*/
status = pjsua_acc_add(&cfg, PJ_TRUE, &acc_id);
if (status != PJ_SUCCESS){
error_exit("Error adding account", status);
}
}
/* Wait until user press "q" to quit. */
for (;;) {
char option[10];
puts("\n'h' to hangup all calls\n'q' to quit\n'm' is call 17001010101\n'r' is register\n");
if (fgets(option, sizeof(option), stdin) == NULL) {
puts("EOF while reading stdin, will quit now..");
break;
}
if(option[0] == 'r'){
pjsua_acc_set_registration(current_acc,PJ_TRUE);
}
if(option[0] == 'm'){
pj_str_t uri=pj_str("sip:01010301@10.10.5.250");
status = pjsua_call_make_call(acc_id,&uri,0,NULL,NULL,NULL);
if(status != PJ_SUCCESS){
printf("#### make call Error\n");
}
}
if (option[0] == 'q'){
break;
}
if (option[0] == 'h'){
/*####挂断接口####*/
pjsua_call_hangup_all();
}
}
/* Destroy pjsua */
pjsua_destroy();
return 0;
}