1、安装一些必要的依赖库
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-devhtml
2、交叉编译asoundlinux
先下载alsa-lib-1.2.1.2.tar.bz2解压缩。c++
而后./configure CC=arm-linux-gnueabihf-gcc --host=arm-linux-gnueabihf git
makeweb
make installide
3、编译pjsip函数
./configure CC=arm-linux-gnueabihf-gcc --host=arm-linux-gnueabihf --disable-libwebrtc --disable-ssl --disable-openh264 --disable-libyuv --enable-static --prefix=/system/binoop
makeui
make installes5
4、使用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; }