linphone开源代码开发总结

来源:互联网 发布:法拉克系统编程实例 编辑:程序博客网 时间:2024/06/07 04:17

Linphone移植到实际项目及应用

 

一、Linphone依赖库简介及移植:

用到的开源库简介:

Alsa

ALSAAdvanced Linux Sound Architecture,高级Linux声音架构的简称,它在Linux操作系统上提供了音频和MIDIMusical Instrument Digital Interface,音乐设备数字化接口)的支持。在2.6系列内核中,ALSA已经成为默认的声音子系统。Alsa的主要功能是从音频设备中读数据或向播放设备写数据,还可以做一些音频处理,如重采样等。

Osip

Libosip2 SIP协议栈的简单实现。libexosip2libosip2 的调用进行封装,隐藏了多媒体会话建立过程中SIP 的细节。

ffpmeg

ffmpeg是一套录制,转换各种音视频各式的工具集,也提供SDKcodec接口。主要包括ffmpeg ffplay ffserver libavcodec libavformat,其中很多编解码库依赖于第三方,比如xVid lampMP3 等等。ffmpeg的编译大全

ogg

Ogg全称应该是OGGVobis(oggVorbis)是一种新的音频压缩格式,类似于MP3等的音乐格式。Ogg是完全免费、开放和没有专利限制的。OggVorbis文件的扩展名是.OGGOgg文件格式可以不断地进行大小和音质的改良,而不影响旧有的编码器或播放器。

Speex

Speex是一套主要针对语音的开源免费,无专利保护的音频压缩格式。Speex工程着力于通过提供一个可以替代高性能语音编解码来降低语音应用输入门槛 。另外,相对于其它编解码器,Speex也很适合网络应用,在网络应用上有着自己独特的优势。同时,Speex还是GNU工程的一部分,在改版的BSD协议中得到了很好的支持。

Speex是基于CELP并且专门为码率在2-44kbps的语音压缩而设计的。它的特点有: 

  ■窄带(8kHz),宽带(16kHz)和超宽带(32kHz)压缩于同一位流。 

  ■强化立体编码 

  ■数据包丢失隐蔽 

  ■可变比特率(VBR) 

  ■语音捕捉(VAD) 

  ■非连续传输(DTX) 

  ■定点运算 

  ■感官回声消除(AEC) 

  ■噪音屏蔽 

  目前最新的版本是2008723日发布的Speex1.2 rc1

SDL

SDLSimple DirectMedia Layer)是一个自由的跨平台的多媒体开发包,适用于 游戏、游戏SDK、演示软件、模拟器、MPEG播放器和其他应用软件。   

功能介绍

  ·SDL有哪些功能? 

  ·视频 

  设置8bpp或更高的任意色彩深度的视频模式。如果某个模式硬件不支持,可以选择转化为另一模式。 

  直接写入线性的图像帧缓冲(framebuffer)。 

  用颜色键值(colorkey)或者alpha混合属性创建surface。 

  Surfaceblit能自动的转化为目标格式。blit是优化过的,并能使用硬件加速。x86平台上有针对MMX优化过的blit。 

  硬件加速的blitfill(填充)操作,如果硬件支持的话。 

  ·事件 

  提供以下事件: 

  应用程序的visibility发生改变 

  键盘输入 

  鼠标输入 

  用户要求的退出 

  每种事件都能通过SDL_EventState()关闭或者打开。 

  事件经由用户指定的过滤函数再被加入到内部的事件队列。 

  线程安全的事件队列。 

  ·音频 

  设置8位和16位的音频,单声道或者立体声,如果格式硬件不支持,可以选择转换。 

  由独立的线程执行音频部分,并提供用户回调(callback)机制。 

  设计上考虑到了客户定制的软混音器,但实际上在例程中就包含了一个完整的音频/音乐输出库。 

  ·CD音频 

  完整的CD音频控制API 

  ·线程 

  简单的线程创建API 

  用于同步的简单的二进制信号量(semaphores) 

  ·定时器 

  读取已流逝的毫秒数。 

  等待指定的毫秒数。 

  设置一个10毫秒精度的周期性定时器。 

  ·字节序无关 

  侦测当前系统的字节序 

  快速转换数据的函数 

  读写指定字节序的数据 

 

Linphone交叉编译:

CFLAGS="-march=armv7-a -mcpu=cortex-a9 -mfloat-abi=softfp -mfpu=vfpv3-d16 -g"

tar xf tar/libosip2-3.1.0-suzhou.tar.gz

cd libosip2-3.1.0

./configure --prefix=$/usr/ipphone --host=arm-hisiv200-linux CFLAGS="-march=armv7-a -mcpu=cortex-a9 -mfloat-abi=softfp -mfpu=vfpv3-d16 -g" PKG_CONFIG_PATH=$/usr/ipphone/lib/pkgconfig --enable-shared

make -j 20

make install

cd ..

 

tar xf  tar/libeXosip2-3.1.0.tar.gz

cd libeXosip2-3.1.0

./configure --prefix=$/usr/ipphone --host=arm-hisiv200-linux CFLAGS="-march=armv7-a -mcpu=cortex-a9 -mfloat-abi=softfp -mfpu=vfpv3-d16 -g" PKG_CONFIG_PATH=$/usr/ipphone/lib/pkgconfig --enable-shared

make -j 20

make install

cd ..

 

tar xf tar/libogg-1.2.1.tar.bz2

cd libogg-1.2.1

./configure --prefix=$/usr/ipphone --host=arm-hisiv200-linux --enable-shared CFLAGS="-march=armv7-a -mcpu=cortex-a9 -mfloat-abi=softfp -mfpu=vfpv3-d16 -g" PKG_CONFIG_PATH=$/usr/ipphone/lib/pkgconfig --enable-shared

make -j 20

make install

cd ..

 

tar xf tar/speex-1.2rc1.tar.gz

cd speex-1.2rc1

./configure --prefix=$/usr/ipphone --host=arm-hisiv200-linux --enable-shared CFLAGS="-march=armv7-a -mcpu=cortex-a9 -mfloat-abi=softfp -mfpu=vfpv3-d16 -g"  PKG_CONFIG_PATH=$/usr/ipphone/lib/pkgconfig --enable-shared --with-ogg=$/usr/ipphone

make -j 20

make install

cd ..

 

tar xf tar/ffmpeg-0.6.6.tar.bz2

cd ffmpeg-0.6.6

./configure --prefix=$/usr/ipphone --cross-prefix=arm-hisiv200-linux- --enable-cross-compile --arch=arm --target-os=linux --enable-shared --extra-cflags="-march=armv7-a -mcpu=cortex-a9 -mfloat-abi=softfp -mfpu=vfpv3-d16 -g" --enable-gpl --enable-shared  --enable-swscale --enable-pthreads

make -j 20

make install

cd ..

 

#tar xf tar/libv4l_0.6.4.orig.tar.gz

#cd libv4l-0.6.4/

#make CC="arm-hisiv200-linux-gcc -march=armv7-a -mcpu=cortex-a9 -mfloat-abi=softfp -mfpu=vfpv3-d16 -g" PREFIX=$/usr/ipphone

#make install

#cd ..

 

tar xf tar/SDL-1.2.15.tar.gz

cd SDL-1.2.15/

chmod -R 777 ./

./configure --prefix=$/usr/ipphone --host=arm-hisiv200-linux CFLAGS="-march=armv7-a -mcpu=cortex-a9 -mfloat-abi=softfp -mfpu=vfpv3-d16 -g" PKG_CONFIG_PATH=$/usr/ipphone/lib/pkgconfig --enable-shared  --enable-input-tslib=no --enable-audio=no  --enable-joystick=no --enable-cdrom=no --enable-video-x11=no --enable-video-x11-dgamouse=no  --enable-video-x11-xv=no --enable-video-x11-xme=no --enable-video-x11-xrandr=no --enable-nanox-direct-fb --enable-video-fbcon --enable-video-opengl=no

make -j 20

make install

cd ..

 

tar xf tar/alsa-lib-1.0.23.tar.bz2

cd alsa-lib-1.0.23

./configure --prefix=$/usr/ipphone --with-configdir=$/usr/ipphone/share/alsa --host=arm-hisiv200-linux CFLAGS="-march=armv7-a -mcpu=cortex-a9 -mfloat-abi=softfp -mfpu=vfpv3-d16 -g" PKG_CONFIG_PATH=$/usr/ipphone/lib/pkgconfig --enable-shared --disable-python

make -j 20

make install

cd ..

 

 

tar xf tar/linphone-3.4.3-suzhou.tar.bz2

cd linphone-3.4.3

./configure --prefix=$/usr/ipphone --host=arm-hisiv200-linux CFLAGS="-march=armv7-a -mcpu=cortex-a9 -mfloat-abi=softfp -mfpu=vfpv3-d16 -g" PKG_CONFIG_PATH=$/usr/ipphone/lib/pkgconfig --enable-alsa=yes --enable-portaudio --enable-console_ui=yes --enable-speex=yes --with-ffmpeg=$/usr/ipphone --with-osip=$/usr/ipphone --with-readline=$/usr/ipphone  CPPFLAGS=-I$/usr/ipphone/include LDFLAGS=-L$/usr/ipphone/lib  --disable-libv4l  --enable-sdl  --enable-video  --disable-x11 --enable-xv=no --disable-x11 --enable-gtk_ui=no

make -j 20

make install

cd ..

 

##也可以单独进入oRTPmediastreamer2进行./configure --prefix=/usr这样单独编译

 

常出错误:

编译时提示头文件或库的版本太老或者找不到

原因:没有指定linphone依赖的库和头文件的安装路径

解决方法:在编译选项后加CFLAGSCPPFLAGS =-I头文件路径 LDFLAGS=L库路径

 

二、新音视频格式的添加

linphone新音视频格式支持是以插件的形式添加的,下载插件的源码,然后编译安装(主要用交叉编译后的插件库)即可支持新的音视频格式

tar xf tar/bcg729-1.0.0.tar.gz

cd bcg729-1.0.0

cp ../linphone-3.4.3/mediastreamer2/include/mediastreamer2/mscodecutils.h $/usr/ipphone/include/mediastreamer2/

./configure --prefix=$/usr/ipphone --host=arm-hisiv200-linux --enable-shared PKG_CONFIG_PATH=$/usr/ipphone/lib/pkgconfig CFLAGS="-march=armv7-a -mcpu=cortex-a9 -mfloat-abi=softfp -mfpu=vfpv3-d16 -g"

make -j 20

make install

cd ..

 

tar xf tar/msilbc-2.0.1.tar.gz

cd msilbc-2.0.1

tar -xvf ilbc-rfc3951.tar.gz

cd ilbc-rfc3951

./configure --prefix=$/usr/ipphone --host=arm-hisiv200-linux CFLAGS="-march=armv7-a -mcpu=cortex-a9 -mfloat-abi=softfp -mfpu=vfpv3-d16 -g" --enable-shared PKG_CONFIG_PATH=$/usr/ipphone/lib/pkgconfig

make

make install

cd ..

./configure --prefix=$/usr/ipphone --host=arm-hisiv200-linux CFLAGS="-march=armv7-a -mcpu=cortex-a9 -mfloat-abi=softfp -mfpu=vfpv3-d16 -g" --enable-shared PKG_CONFIG_PATH=$/usr/ipphone/lib/pkgconfig

 

三、移植到hisi平台标准版步骤

经过上面的交叉编译生成了我们需要的库、头文件和配置文件,下面我们把这些交叉编译出来的东西拷贝到我们平台版本里就OK了。

首先我们把这个linphone当做一个功能模块要用宏控制下,

1. 在顶层目录cfg.mk里添加控制变量,如:CFG_ENABLE_IPPHONE=y

2. 在顶层目录Makefile添加:

   ipphone_install:

   ifeq ($(CFG_ENABLE_IPPHONE),y)

-rm -rf $(INCLUDE_DIR)/ipphone

-rm -rf $(LIB_DIR)/ipphone

mkdir -p $(INCLUDE_DIR)/ipphone

mkdir -p $(LIB_DIR)/ipphone

@-cp -rf $(IPPHONE_DIR)/install/include/* $(INCLUDE_DIR)/ipphone/

@-cp -rf $(IPPHONE_DIR)/install/lib/* $(LIB_DIR)/ipphone/

for aaa in $$(find $(IPPHONE_DIR)/install/lib -name "*.a");do rm -rf $$aaa;done

-find $(IPPHONE_DIR)/install/bin $(IPPHONE_DIR)/install/lib | xargs $(STRIP) 2> /dev/null

mkdir -p $(ROOTBOX_DIR)/usr/ipphone

-find $(IPPHONE_DIR)/install/ -name ".svn" | xargs rm -rf

@-cp -rf $(IPPHONE_DIR)/install/* $(ROOTBOX_DIR)/usr/ipphone/

   Endif

3.在make目录下的ysstb.mkt添加:

  ENABLE_IPPHONE=1

  ifeq "$(ENABLE_IPPHONE)" "1"

  INCLUDES := $(INCLUDES) -I$(YSENV_DIR_PROJ)/pub/include/ipphone

  Endif

4.在ysstb目录下的Makefile添加:

  ifeq "$(ENABLE_IPPHONE)" "1"

  IPPHONE_H_PATH := $(YSENV_DIR_PROJ)/pub/include/ipphone

  IPPHONE_LIB_PATH := $(YSENV_DIR_PROJ)/pub/lib/ipphone

  IPPHONE_CFLAGS += -I$(IPPHONE_H_PATH) 

  IPPHONE_LDFLAGS  += -L$(IPPHONE_LIB_PATH)

  IPPHONE_LDFLAGS  += -llinphone -lmediastreamer -lortp -losipparser2 -losip2 -lmshisix264  -Wl,-rpath -Wl,$(YSENV_DIR_PROJ)/pub/lib/ipphone/

  Endif

 

  在目标 all后添加编译选项 IPPHONE_CFLAGSIPPHONE_LDFLAGS

5.在ysstb/driver下的Makefile添加:

  ifeq "$(ENABLE_IPPHONE)" "1"

  ST40_IMPORTS += libysipphone.a

  Endif

   

   ifeq "$(ENABLE_IPPHONE)" "1"

   LINK_PATH += driver$(LOCALIZATION_STRING)/ysipphone

   Endif

   

   ifeq "$(ENABLE_IPPHONE)" "1"

   libysipphone.a :

   $(MAKE) -C driver$(LOCALIZATION_STRING)/ysipphone

   Endif

 

   ifeq "$(ENABLE_IPPHONE)" "1"

   -$(MAKE) -KC driver$(LOCALIZATION_STRING)/ysipphone clean

   endif

    

6.ysstb\driver\driver_stdver目录下创建ysipphone目录并在ysipphone下添加commands.c  

drv_ipphone.c  linphonec.c  mshisix264.c 及 Makefile

其中commands.c是我们根据linphone源码中的commands.c添加了视频显示控制命令主要关于分辨率的控制及视频采集设备硬件配置获取接口

drv_ipphone.c 是我们封装的linphone初始化及常用接口

Linphonec.c 主要修改原linphone  main函数及添加一些基础设置如:auto_answer=FALSE;

mshisix264.c 是我们自己添加的H264格式硬件编解码接口

 

四、linphone简介:

    Linphone是一款可以运行在多平台多操作系统上的VOIP开源软件,通过linphone可以在互联网上和其他人自由地进行声音、视频通信。Linphone是遵从SIP协议开发的,他需要和支持SIP协议的电话或者代理服务器进行相互操作。Linphone有两种模式:GNOME/GTK+模式和CONSOLE模式。嵌入式一般应用CONSOLE模式。

Linphone采用分层架构,对不同层次功能的实现接口进行了封装,整个软件系统分为interface模块、core engine模块、SIP模块、mediastreamer2模块、pcm/gsm/speex模块、ffmpeg模块、ORTP模块,如图所示:

 

   Interface模块内部负责系统的初始化,并打开一个循环结构来循环定时查询来自exosipevent,并根据事物的类型进行处理。初始化成功后,系统进入linphonec的主循环,等待用户输入,若有输入就会调用相应的命令处理函数,处理函数被注册在静态的数组linphone LPC_COMMAND commands[]中。Interface调用core engine封装好的api即可容易的实现系统功能。

Core enginelinphone基于ortpexosipmediastreamer2等开源库编写成的API,用来实现linphone的主要功能。这些API函数几乎实现了一个SIP电话所需的所有功能,借用这些API可以很容易的开发出基于SIPVOIP系统。Coreapi内建一个linphone的核心数据结构linphonecore,这个结构几乎包括了所有终端设计要用到的数据结构。一下的所有操作都是基于这个数据结构的。这个模块对这个数据结构做初始化等操作,供下层处理应用。

    Exosip模块:该模块主要实现SIP协议。Exosiposip2的一个扩展协议集,它部分封装了osip2协议栈,使得它更容易被使用。如exosip增加了calldialogregistrationsubscription等过程的解析,使得实用性更强。它实现了作为单个sip终端的大部分功能。Exosip使用UDP socket套接字实现底层sip协议的接收/发送。并且封装了sip消息的解释器。Exosip使用定时轮循的方式调用osip2transaction处理函数,这部分是协议栈运转的核心。透过添加/读取transaction消息管道的方式,驱动transaction的状态机,使得来自远端的sip信令能汇报给调用程序,来自调用程序的反馈能通过sip信令回传给远端。Exosip增加了对各个类型transaction的超时处理,确保所有资源都能循环使用,不会被耗用殆尽。Exosip使用jevent消息管道来向上通知调用程序底层发生的事件,调用程序只要读取该消息管道,就能获得感兴趣的事件,进行相关的处理。该模块根据用户界面模块的各种请求,协调调度各协议栈来实现各种通信请求。客户端控制模块内部负责系统初始化工作,并进入一个循环结构,这个循环结构定时查询来自exosip的事务event,根据事务的类型进行相应的处理。同时客户端模块还要调用音频模块、视频模块、ORTP模块处理通话语音视频及铃音等信息。

Mediastreamer2是一个强大的多媒体SDK,主要用于音、视频流的处理。Mediastreamer2调用音频编解码库(pcmgsmspeex等)、视频编解码库(ffmpeg),RTP库(ortp)完成整个音视频流的处理。Mediastreamer2库主要有一下功能:能对使用alsaosswindowswaveapi设备驱动的声卡设备中读和写;接收或发送RTP包;读或者写一个wav文件;从使用v4l驱动的摄像头中读YUV格式的图像;显示YUV格式的图像。

各模块流程架构介绍:

Interface模块:

Interface模块负责实现两个功能:

一是系统的初始化,将系统运行时将会调用的模块进行初始化,并根据配置文件中的参数进行系统自动参数配置。初始化ortp模块,将系统将会用到的音视频编解码的格式标准注册到RTP的载荷索引列表中。初始化mediastream2模块,主要是对系统将要调用的filter进行注册。初始化readline模块,还将linphone_idle_call注册到readline的事件循环中,根据系统时间的定义,每隔一秒调用一次检查是否有等待处理的事件:

二是建立主循环,循环检测命令输入,并对输入的命令进行解析。系统自动将解析出的命令与命令函数列表中注册的函数进行匹配,并将需调用的对应的函数添加入lclinphonecore结构体)的事件队列中。若需要添加其他处理命令及其处理函数,可在./console/command.c文件中的LPC_COMMAND commands[]数组中进行添加。正是如此,我们需要在此模块中进行命令的添加。

首先对信息传送命令格式进行如下规定:

Send [to] [message]

其中“send”为命令的关键标识词。“to”为目的地址参数,“message”为传递信息内容。

其次在LPC_COMMAND commands数组中添加传送即时消息命令的元素:

{send,lpc_cmd_send_message,”send message to others”,”send <sip-url> <message-content> ‘or’ c <sip-url> <message-content>” “send the message to the specified destination”}

“send”为命令的关键标识词,“lpc_cmd_send_message”为即时消息的实现功能实现的函数,“send message to others”为命令的简单说明,元素的最后一部分为命令的使用帮助说明。

最后进行即时消息传送功能函数lpc_cmd_send_message的主体实现。

lpc_cmd_send_message函数主要实现两个功能,一是参数解析,二是消息发送。其中参数解析部分我们在interface模块层进行说明,而消息发送我们将其在core engine模块层实现。

interface模块中,主函数首先对输入命令进行解析,当主函数解析出命令关键标识词则会对LPC_COMMAND commands数组中的元素进行匹配。

Core engine模块:

正如上文所述,core enginelinphone基于ortpexosipmediastream2等开源库编写成的实现linphone主要功能的API。这些API函数几乎实现了一个SIP电话所需的所有功能,例如呼叫建立、新加入会话、撤离会话、音视频配置及建立、代理操作、事件处理队列等。调用这些封装好的特定功能的API可以很容易的开发出基于SIP的视频电话系统。Coreapi内建一个linphone的核心数据结构linphonecore,这个数据结构几乎包括了所有终端设计要用到的数据。我们的即时消息的传送也是基于这个linphonecore数据结构实现的。此数据结构在系统进行初始化时就已经由系统进行建立并赋值,后续对于系统的操作都是基于对这个数据结构的操作来进行的。

 

Mediastreamer2架构

Mediastreamer2的处理对象为媒体流,而每一个处理对象都包含一个或多个处理实体、连接器、Mediastreamer2触发器以及RTP会话。

处理实体是指包含MSFilter对象的实体。MSFilterMediastreamer2中用于处理数据组成部分。一个filter可以有0或多个输入/输出接口。不同的filter用来实现不同的功能,例如MSRtpRecv是一个MSFilter,它能够实现从网络接收RTP包,并将其进行解封装,而后将数据包发送到其唯一的输出端口;MSSpeexDec也是一个MSFilter,它主要实现将输入端口的经speex编码的数据进行解码,并将解码完成的数据发送到输出端口。Mediastreamer2默认提供了一部分filter供开发者进行调用;

支持所有平台的filter

RTP reciver filterRTP sender filter

音频处理的filter

Audio capture filter; audio playback filter; several audio encoder/decoder filter;PCMU,PCMA,speex,gsm;

 

Wav file reader filter;  wav file recorder filter; resampler filter; conference bridge filter;

Volume analyser filter; acoustic echo canceller filter; dtmf generation filter;

视频处理filter

Video capture filter; video dispaly filter; several audio encoder/decoder filter; H263-1998,MP4-ES,theora; image resizer filter; format converter filter(RBG24,1420...);

插件filter

iLBC decoder/encoder filter;

连接器即Graph,他是filter连接的管理器,他将数据从输出接口传输到输入接口并且负责filter的运行。具体来说,例如我们建立一个媒体流,它用来实现听筒接收到话机传输的链操作,则基本的graph示例如下:

AUDIO CAPTURE -> ENCODE -> RTP

这个graph由三个filter组成,第一个没有输入,他直接从驱动捕获音频数据,并将数据输出到输出端口。这个音频数据被传送到ENCODE的输入端口,这样可以将编码后的数据封装为RTP包并发送出去。

当我们需要应用不同格式编码对数据进行编码时,应用这个标准设计能够让我们在只替换不同功能的ENCODE FILTER就可以实现这个要求。Mediastreamer2包含g711u,g711a,speexgsm的内部支持。同时,我们也可以自己通过添加其他新的编码格式来实现其他的功能。

Mediastreamer2触发器即MSTicker对象时整个Mediastreamer2处理的心脏,是用来完成媒体处理的执行工作的,系统中有一特定的进程,它每隔10ms将被唤醒一次来对MSTicker对象所管理的MSFilter链进行数据处理。多个MSTicker可以同时被调用,正如我们的系统中,我们可以设定一个MSTicker管理音频的filter,一个用来管理视频的filter,我们同时进行音频和视频的通话将不会收到其相互之间的影响。

RTP会话即RtpSession,此部分主要用来构造RTPSession实例,并能在创建时安装一个内存管理器;结束已经建立的会话,设定是否支持多播,以及对多播的加入、离开等功能;在RtpSession中还可以获取本地的SSRC,并且添加或删除目标RTP地址;开发者通过对负载类型、标志、时间戳单元以及打包时间的进行参数设定来进行RTP包以及RTCP包的发送和接收。

Mediastreamer2数据结构关系

Mediastreamer2使用的方便性让其成为linphone媒体流处理的最终选择。而对于开发人员来说,只有深入理解了Mediastreamer2中媒体流的处理才可以充分利用Mediastreamer2所带来的便捷性,才可以将更多精力投放到filter算法研究中。下面以音频流audioStream为例,对Mediastreamer2的数据结构关系进行分析。

Struct _AudioStream

{

   MSTicker *ticker;

   RtpSession *session;

   MSFilter *soundread;

   MSFilter *soundwrite;

   MSFilter *encoder;

   MSFilter *decoder;

   MSFilter *rtprecv;

   MSFilter *rtpsend;

   ......

};

AudioStream 中定义了整个音频流的数据结构主干:Mediastreamer2触发器、MSTickerRTP会话RtpSession、声卡读写、音频编解码以及rtp收发等MSfilter对象。每一个MSfilter对象的定义如下:

Struct _MSFilter{

   MSFilterDesc *desc;

   MSQueue **inputs;

   MSQueue **outputs;

   MSFilterNotifyFunc notify;

   Struct _MSTicker *ticker;

   ......

};

对每一个filter都需定义其MSFilterDesc、输入输出接口、MSFilterNotifyFuncMSTicker,其中MSFilterDesc的定义取自MSFilterDesc *ms_filter_descs[]列表中。

MSFilterDesc *ms_filter_descs[] = {

&ms_alaw_dec_desc,

&ms_alaw_enc_desc,

&ms_file_player_desc,

&ms_rtp_send_desc,

&ms_rtp_recv_desc,

&ms_file_rec_desc,

&ms_file_rec_data_desc,

&ms_speex_dec_desc,

&ms_speex_enc_desc,

&ms_gsm_dec_desc,

&ms_gsm_enc_desc,

&ms_speex_ec_desc,

&ms_tee_desc,

&ms_conf_desc,

......

};

Ms_filter_descs列表中的每个描述元素在程序中均需要有正式的声明和定义,对idname、输入、输出和相应的处理函数,都需要进行处理,其中处理函数实现的功能主要算法。

 

Linphone命令简介:

Linphone命令实现都在commands.c里面

命令分析:

lpc_cmd_help:打印所有命令及注释

用法:'help <command>'   'help advanced'

lpc_cmd_call: 呼叫指定SIP url或number

用法:'call <sip-url or number>  [options]'options--audio-only--early-media

lpc_cmd_calls: 显示当前所有通话及通话状态

用法:calls

lpc_cmd_chat: 与指定SIP url通讯发送指定信息

用法: 'chat <sip-url> \"message\"' 

lpc_cmd_terminate: 结束通话

用法:'terminate' 结束当前通话  'terminate <call id>' 结束指定通话 'terminate <all>' 结束所有通话

lpc_cmd_answer: 接听通话

用法:'answer' 接听当前进来的通话  'answer <call id>' 接听指定通话

lpc_cmd_pause: 暂停通话

用法:'pause' 暂停当前通话

lpc_cmd_resume: 恢复通话

用法:'resume' 恢复唯一通话 'resume <call id>' 恢复指定通话

lpc_cmd_transfer: 把一个通话转移到指定目标

用法:'transfer <sip-uri>' 转移到指定SIPurl 'transfer <call id> <sip-uri>' 把指定id的通话转移到指定SIPurl  'transfer <call id1> --to-call <call id2>' 把指定id的通话转移到指定id

lpc_cmd_mute_mic: 将mic静音

用法:mute

lpc_cmd_camera: 发送摄像头输出

用法:'camera on' 打开摄像头功能  'camera off' 关闭摄像头功能

lpc_cmd_unmute_mic: 将mic消除静音

用法:unmute

lpc_cmd_duration: 打印最后通话持续秒数

用法: duration

lpc_cmd_autoanswer: 设置自动接听模式

用法: 'autoanswer' 显示当前自动接听模式  'autoanswer enable' 使能自动接听模式  'autoanswer disable' 去使能自动接听模式

lpc_cmd_proxy:代理管理

用法: 'proxy list' 列出所有代理体制  'proxy add' 添加一个新的代理设置  'proxy remove <index>' 删除指定index的代理  'proxy use <index>' 将指定index的代理设置为默认代理  'proxy unuse' 不使用默认代理  'proxy show <index>' 显示指定index的代理配置和状态  'proxy show default' 显示默认代理配置和状态

lpc_cmd_soundcard: 声卡管理

用法:'soundcard list' 列出所有声音设备  'soundcard show' 显示当前声音设备配置

'soundcard use <index>' 选择指定声音设备  'soundcard use files' 用.Wav文件代替当前声音设备

lpc_cmd_webcam: 视频设备管理

用法: 'webcam list' 列出所有的视频设备  'webcam use <index>' 选择一个视频设备

'webcam show'  显示当前视频设备配置

lpc_cmd_ipv6: 使用IPV6协议

用法:ipv6 status 显示IPV6状态   'ipv6 enable' 使能IPV6网络协议   'ipv6 disable' 去使能IPV6网络协议

lpc_cmd_nat: 设置nat地址

用法: nat 显示nat设置   'nat <addr>' 设置nat地址

lpc_cmd_stun: 设置stun server地址

用法: 'stun' 显示stun设置  'stun <addr>' 设置stun server地址

lpc_cmd_firewall: 设置防火墙

用法: 'firewall' 显示当前防火墙设置  'firewall none' 设置直接连接  'firewall nat' 使用nat命令设置的nat地址  'firewall stun' 使用stun设置的stun server地址

lpc_cmd_call_logs: 显示通话记录

用法:call-logs

lpc_cmd_friend: 好友管理

用法: 'friend list [<pattern>]' 显示好友列表  'friend call <index>' 呼叫好友  'friend add <name> <addr>'  添加好友  'friend delete <index>' 删除指定好友

lpc_cmd_play: 播放wav文件

用法: 'play <wav file>'

lpc_cmd_record: 录制到wav文件

用法: 'record <wav file>'

lpc_cmd_quit: 退出

用法:quit

lpc_cmd_video:视频显示控制

用法: 'video list' 列出所有视频分辨率  'video show' 显示当前视频分辨率  'video use <index>' 选定一个视频分辨率

Advanced commands

lpc_cmd_acodec:音频codec配置

用法: 'codec list' 列出所有codecs   'codec enable <index>' 使能指定音频codec  'codec disable <index>'  去使能指定音频codec

lpc_cmd_vcodec: 视频codec配置

用法: 'vcodec list' 列出所有codecs  'vcodec enable <index>' 使能指定视频codec    'vcodec disable <index>' 去使能指定视频codec

lpc_cmd_echocancellation: 回声消除

用法: 'ec on [<delay>] [<tail>] [<framesize>]' 打开回声消除功能  'ec off' 关闭回声消除功能  'ec show' 显示回声消除状态

lpc_cmd_echolimiter: 回声抑制

用法: el on 打开回声抑制功能  'el off' 关闭回声抑制功能  'el show' 显示回声抑制状态

lpc_cmd_rtp_no_xmit_on_audio_mute: 设置rtp_no_xmit_on_audio_mute配置参数 设置成1表示音频静音时rtp传输也静音 

用法: nortp-on-audio-mute

lpc_cmd_video_window: 视频显示窗口控制

用法: 'vwindow show' 显示视频窗口  'vwindow hide' 隐藏视频窗口  'vwindow pos <x> <y>' 将视频窗口移动到显示器指定位置   'vwindow size <width> <height>' 重置视频窗口大小   'vwindow id <window id>' 将指定窗口嵌入到视频显示窗口  

lpc_cmd_preview_window: 本地视频显示控制

用法: 'pwindow show' 显示本地视频  'pwindow hide' 隐藏本地视频  'pwindow pos <x> <y>'将本地视频窗口移动到显示器指定位置  'pwindow size <width> <height>' 重置本地视频窗口大小  'pwindow id <window id>' 将指定窗口嵌入到视频显示窗口  'pwindow integrated'  整合本地视频到通话中  'pwindow standalone' 单机显示本地视频

lpc_cmd_snapshot: 将当前视频截图并保存到指定文件

用法: 'snapshot <file path>'

lpc_cmd_vfureq: 请求对方发VFU到当前对话

用法: vfureq

lpc_cmd_states: 显示linphone注册及通话内部状态

用法: 'states global' 显示liblinphone全局状态  'states calls' 显示通话状态  'states proxies' 显示代理配置

lpc_cmd_register: 用户注册

用法: register <sip identity> <sip proxy> <password>

lpc_cmd_unregister: 用户注销

用法: unregister

lpc_cmd_status: 打印各种状态信息

用法: 'status register'  打印注册状态  'status autoanswer' 打印autoanswer状态  'status hook'  打印hook状态 

lpc_cmd_ports:网络端口设置

用法: 'ports' 打印当前使用的端口  'ports sip <port number>' 设置SIP端口  

lpc_cmd_param: 设置或读取.linphonerc里的参数

用法: 'param <section> <parameter> [<value>]' 设置或读取指定的参数  

lpc_cmd_speak: 用espeak TTS引擎说一句话

用法: 'speak <voice name> <sentence>' 用指定的espeak voice 说一句话

lpc_cmd_staticpic: 静态图片管理

用法: 'staticpic set' 设置选取图片的路径  'staticpic fps' 获取或设置图片每秒发送的帧数

lpc_cmd_identify: 返回远端的用户代理

用法: 'identify' 返回当前通话远端用户代理  'identify <id>' 返回指定id的通话远端用户代理

lpc_cmd_ringback: 选择远端呼叫时听到的铃音

用法: 'ringback <path of mono .wav file>' 选择指定文件为远端呼叫时听到的铃音  'ringback disable' 设置远端呼叫时无铃音

 

 

五、实际问题分析:

1.回声消除代码见Speexec.c

首先在drv_ipphone.c添加相应的(ec on)控制命令接口

然后在初始化是调用并填入合适的参数

 

2.音频处理部分ossalsa 

主要修改Drv_ipphone.c  alsa.c

首先在Drv_ipphone.c修改声卡设备设置写入配置文件

然后在alsa.c里把原先直接往播放设备送数据播放的接口改为向我们自己创建的pipe中写入数据

3.3716CV200 alsa无法识别出声卡问题

a.配置hisiSDK  msp->audio config->AO ALSA SUPPORTALSA I2S SUPPORTAI SUPPORTAI ALSA SUPPORT kernel rootfs

b.做设备节点连接,可添加到profile中  

mkdir /dev/snd

cd /dev/snd

ln -s ../controlC0 controlC0

ln -s ../controlC1 controlC1

ln -s ../controlC2 controlC2

ln -s ../pcmC0D0c pcmC0D0c

ln -s ../pcmC0D0p pcmC0D0p

ln -s ../pcmC1D0c pcmC1D0c

ln -s ../pcmC1D0p pcmC1D0p

ln -s ../pcmC2D0c pcmC2D0c

ln -s ../timer timer

 

4.来电话时远端铃声失真

代码中解析出来的铃声采样率和声道数没有传下来,在alsa.c添加preprocess函数

alsa_write_desc添加.preprocess=pipe_write_preprocess,

 

5.本地视频窗口显示黑屏

使能窗口时如果出现三层窗口区域有重叠第三个窗口会使能失败,使能第三个窗口前把不用的pip窗口缩小,远端窗口显示前把pip窗口销毁

 

6.远端视频和直播视频同时显示时两个窗口都会花屏

直播与远端播放器资源冲突,在远端视频显示前重启直播播放器

 

7.添加蓝牙耳机支持

主要修改drv_ipphone.c mshisix264.c alsa_cp.c添加蓝牙耳机aplay注入播放程序,修改audio线程切换电视与蓝牙耳机播放,声音采集调用DRV_IpPhone_Soundcard切换;在逻辑上打/接电话时判断蓝牙耳机连接状态去切换,对于低功耗或者蓝牙耳机关闭重新打开需要在判断状态时去连接一下。创建.asoundrc时听说分2个逻辑设备名时,不同同时使用,需要将蓝牙耳机写成一个逻辑设备名,此时蓝牙耳机播放音乐仅支持播放单声道、8000采样率,同时将Linphone被叫铃声也更换为单声道、8000采样率。

 aplay注入播放写的时候,没有按aply原有方式而是直接调用snd_pcm_writei,同时对于写返回EPIPE做延时重写入处理

 

    配置文件配置选项说明:

con_type

It's a setting to tell linphone how much bandwidth it can use: 
0=analog 28k modem 
1=56k modem 
2=128k modem 
3=minimum ADSL modem 
4=unlimited (Ethernet)

con_type is deprecated and no more used by linphone>=1.4.0, in favour of upload_bw and download_bw.

 

use_nat 

0=don't use the NAT setting 
1=use the NAT setting 

nat_address

This value can be used to override contact header IP. This is usefeul to supress automatival too "smart" IP address selection if you have more IPs. Put the IP number of the NAT router here.

download_bw

The bandwidth you have available for incoming data. This is noted in kbit/sec. A setting of "0" means unlimited bandwidth. Specific allocations of bandwidth may exclude the use of codecs that require more bandwidth than the setting chosen. Has similar purpose as the con_type. Different codecs are offered in SDP when different bandwidth is available. 

upload_bw 

The bandwidth you have available for outgoing data. This is noted in kbit/sec. A setting of "0" means unlimited bandwidth. Specific allocations of bandwidth may exclude the use of codecs that require more bandwidth than the setting chosen. Has similar purpose as the con_type. Different codecs are offered in SDP when different bandwidth is available.

use_stun

STUN is used by Linphone for traversing NAT routers. STUN stands for Simple Traversal ofUDP through NATs (Network Address Translation).  Linphone can be a STUN client, in which case it will send a request to an external STUN server. The STUN server then tells Linphone the public IP address of the NAT router. It also reports to Linphone which port was opened by the NAT device for incoming traffic. Linphone then uses this information for connecting with a VoIP server or other soft phones. 

0=use STUN 
1= don't use STUN 

stun_server

The address of the STUN server to use. The format will look something like this: 
stun.me.com

[SIP]

All details regarding your SIP configuration go here.  SIP has two kinds of addresses: 

SIP Address of Record (AOR). This is the address people use to call you, the format looks like an email address.

SIP Contact Address is the temporary address and is determined by what IP address you currently have, the device name, and the port number you are using for SIP. This address is usually temporary and stored in memory. When you register with a SIP server, the server maps this address onto your SIP Address of Record (AOR).  

sip_port

The port on your computer that is used for SIP traffic (default is "5060")

 

guess_hostname

0=don't guess the hostname of your computer 
1=guess the hostname of your computer (use this if you don't know it) 

contact

Put here the SIP Address of Record for your account. The format should be: 
sip:accountname@siprovider  

inc_timeout

This is the timeout setting for incoming calls. If you do not make it to answer an incoming call after the time set here then linphone will timeout. The setting is measure in seconds and the default is "15" (seconds). 

use_info

0 = don't use SIP INFO messages for DTMFs 
    1 = use use sip info messages for DTMFs

(双音多频信号(DTMF),电话系统中电话机与交换机之间的一种用户信令,通常用于发送被叫号码。在使用双音多频信号之前,电话系统中使用一连串的断续脉冲来传送被叫号码,称为脉冲拨号。脉冲拨号需要电信局中的操作员手工完成长途接续。)

use_ipv6

Essentially there are not enough IP Addresses. An IP Address is the group of numbers that identifies you on the internet, they look something like this: "192.168.0.123". Because there are not enough combinations of these number groups to account for every device that needs to connect to the internet a new way of addressing is being developed, this is called "IPv6".  An IPv6 address might look something like this: "E2D6:0000:0000:0000:01B4:7BD8:D0A3:1220"

If  you are in a IPv6 network then you can use these addresses instead of the more common IPV4. Linphone is not able to combine different IP protocols at the same time (e.g. SIP over IPv4 and RTP over IPv6). 
0 = don't use IPv6 
1 = use IPv6

default_proxy

Linphone has a section in the config file for storing different registration server information. These are numbered (starting at zero). Put the number here for the index of the registration setting you wish to use. "-1" means do not use a proxy.

[rtp]

audio_rtp_port

The port number used by the RTP protocol for audio (default 7078) 

video_rtp_port

The port number used by the RTP protocol for video (default 9078)

audio_jitt_comp

Number of milliseconds of audio buffered before playing, measured in seconds (default 60). 

video_jitt_comp 

Number of milliseconds of video buffered before playing, measured in seconds (default 60)

[sound]

playback_dev_id=ALSA: default device 
    ringer_dev_id=ALSA: default device 
    capture_dev_id=ALSA: default device 
    rec_lev=80 
    play_lev=80 
    ring_lev=80 
    source=m 
    local_ring=/usr//share/sounds/linphone/rings/oldphone.wav 
    remote_ring=/usr//share/sounds/linphone/ringback.wav 
    echocancelation=0

盒子:

0: ALSA: default device

1: ALSA: hiao

2: ALSA: USB Device 0x46d:0x825

3: OSS: /dev/dsp

4: OSS: /dev/dsp1

[video]

enabled=0 
    show_local=0

[audio_codec_0]

mime=PCMU 
    rate=8000 
    enabled=1

[proxy_0]

reg_proxy=sip:papercuptelephone.org 
reg_identity=sip:adam@papercuptelephone.org 
reg_expires=900 
reg_sendregister=1 
publish=0 

 

 

3.网络连接及交互 

     协商音视频格式

Linphonecore.ccodec_pref_order的修改。

在进行sip协商时,主叫放会将自己的codec_pref_order所列的支持音视频的格式通过Session Initiation Protocol->Message Body字段发送过去。被叫也会将自己的codec_pref_order反馈回来。根据主叫端的codec_pref_order所列格式顺序去匹配具体采用哪种音视频格式。

 

 

 SIP协议介绍与分析 
  
  会话初始协议(SIP)是一信令协议用于初始、管理和终止分组网络中的语音和 
视频会话,具体地说就是用来生成、修改和终结一个或多个参与者之间的会话。SI 
P是互联网工程任务组(IETF)多媒体数据和控制体系结构的一个组成部分,因此它 
IETF的许多其他协议都有联系,例如RTP(实时传输协议)和本文提到的SAPSD 
P协议。 
  
  SIP主要提供了与会话建立和终结相关的五个方面功能,它们是: 
  
  (1)用户定位:用于通信的终端系统的决定; 
  
  (2)用户可用性:被呼叫方参与通信的意愿的决定; 
  
  (3)用户能力:使用的媒体和媒体参数的决定; 
  
  (4)会话建立:“振铃”,呼叫和被呼叫方会话参数的建立; 
  
  (5)会话管理:包括转移和终结会话,修改会话参数,以及调用业务等。 
  
  SIP网络由四种类型的逻辑SIP实体组成。每一实体具有特定的功能,并且作为 
客户机(初始请求),或作为服务器(响应请求),或作为两者的结合参与到SIP通 
信中。一个“物理设备”能够具有多于一个逻辑SIP实体的功能性。例如,作为代理 
服务器的网络服务器可同时具备注册服务器的功能。 
  
  下面是四种功能实体: 
  
  (1)用户代理 
  
  在SIP中,用户代理(UA)是端点实体。用户代理通过交换请求和响应初始和终 
止会话。UA作为一应用程序,它包含用户代理客户机和用户代理服务器,如下: 
  
  · 用户代理客户机(UAC):客户机应用程序,它初始SIP请求。 
  
  · 用户代理服务器(UAS):服务器应用程序,当接收到SIP请求时它联系用户 
并且代表用户返回一响应。 
  
  在SIP网络中具有UA功能的设备是:工作站,IP电话,电话网关,呼叫代理,自 
动应答服务。 
  
  (2)代理服务器 
  
  代理服务器是同时作为服务器和客户机的中间实体,其目的是代表其他客户机 
生成请求。请求被内部处理或可能在翻译之后将其传递到其他服务器。如果需要, 
代理在转发之前可解释和重写请求消息。 
  
  (3)重定向服务器 
  
  重定向服务器接受SIP请求,并将被呼叫方的SIP地址映射成零个(如果没有可 
知地址)或更多的新地址并且将它们返回客户机。不像代理服务器,重定向服务器 
不传递请求到其他服务器。 
  
  (4)注册服务器 
  
  注册服务器是接受REGISTER请求的服务器,其目的是根据用户在请求中规定的 
联系信息更新位置数据库。 
  
  SIP通过E-mail形式的地址来标明用户地址。每一用户通过一等级化的URL来标 
识,它通过诸如用户电话号码或主机名等元素来构造(例如:SIPuser@company. 
com)。因为它与E-mail地址的相似性,SIP URLs容易与用户的E-mail地址关联。 
  
  SIP有两种类型的消息,它们是: 
  
  (1)请求:从客户机发到服务器的消息。 
  
  (2)响应:从服务器发到客户机的消息。 
  
  其中请求消息包括: 
  
  · INVITE:初始呼叫,改变所以参数(re-INVITE)。 
  
  · ACK:确认INVITE的最终应答。 
  
  · BYE:终止呼叫。 
  
  · CANCEL:撤消搜索和振玲。 
  
  · OPTIONS:查询另一方能力。 
  
  · REGISTER:注册位置服务。 
  
  · INFO:发送会话中信息而不改变会话状态。 
  
  · PRACK:与ACK作用相同,但是用于临时响应。 
  
  · SUBSCRIBE:该方法用来向远端端点预订其状态变化的通知。 
  
  · NOTIFY:该方法发送消息以通知预订者它所预定的状态的变化。 
  
  · UPDATE:允许客户更新一个会话的参数而不影响该会话的当前状态。 
  
  · MESSAGE:通过在其请求体中承载即时消息内容实现即时消息。 
  
  · REFER:其功能是指示接受方通过使用在请求中提供的联系地址信息联系第 
三方。 
  
  响应消息包含数字响应代码。SIP响应代码集部分基于HTTP响应代码。有两种类 
型的响应,它们是: 
  
  · 临时响应(1XX):临时响应被服务器用来指示进程,但是不终结SIP事物。 
  
  
  · 最终响应(2XX3XX4XX5XX6XX):最终响应终止SIP事物。 
  
  每条SIP消息由以下三部分组成: 
  
  (1)起始行(Start Line):每个SIP消息由起始行开始。起始行传达消息类 
型(在请求中是方法类型,在响应中是响应代码)与协议版本。起始行可以是一请 
求行(请求)或状态行(响应)。 
  
  (2SIP头:用来传递消息属性和修改消息意义。它们在语法和语义上与HTTP 
头域相同(实际上有些头就是借自HTTP),并且总是保持格式:<名字>:<>。 
  
  (3)消息体:用于描述被初始的会话(例如,在多媒体会话中包括音频和视频 
编码类型,采样率等)。消息体能够显示在请求与响应中。SIP清晰区别了在SIP起 
始行和头中传递的信令信息与在SIP范围之外的会话描述信息。可能的体类型就包括 
本文将要描述的SDP会话描述协议。 
  
  2.2 SAP协议介绍与分析 
  
  SAP的全称是会话通告协议,其目的是为了通知一个多播的多媒体会议或其他多 
播会话而将相关的会话建立信息发送给所期望的会议参与者。SAP协议本身并不建立 
会话,它只是将建立会话所必要的信息,例如所采取的视频或音频编码方式通知给 
其他在一个多播组内的参与者,当参与者接收到该通知数据包后就可以启动相应的 
工具并设置正确的参数向该会议的发起者建立会话了(建立会话可以使用SIP协议) 
。 
  
  通知的发起者并不知道各参与者是否收到了会话通知,也就是说每个参与者并 
不向通知发起者回复“我收到了通知”的确认;因此,通知发起者只能够通过周期 
性地发送这个会话通知从而最大可能地使参与者收到通知。 
  
  SAP并不是向每个参与者一一发通知数据包,它是通过多播的机制(multicast 
)向一个已知的多播地址和端口一次性发送一个通知数据包,该多播组内的成员如 
果工作正常的化就会收到该通知数据包。因此,为了使会议的参与者都能够接收到 
通知,就要确保其参加到该多播组内。  一个通知数据报除了可以通知某会话将 
要发起外,还可以通知该会话取消了或该会话的某些通信参数已被修改了。当然, 
这需要相应机制使这几个通知都是针对同一会话的。 
  
  那么SAP如何描述会话的相关信息,这就需要借助SDP协议了。在SAP数据包的
ayload字段中一般情况下填充的就是SDP数据,它描述了建立会话所必要的基本信息 
。 
  
  SDP将在1.3节中介绍。 
  
  2.3 SDP协议介绍与分析 
  
  上面介绍的两个协议都用到了SDP,实际上SDP就是用来描述多媒体会话通告, 
多媒体会话邀请和其他形式的多媒体会话初始化的协议。SDP包通常包括以下信息: 
  
  
  (1)会话信息 
  
  · 会话名和目的。 
  
  · 会话活动时间。 
  
  由于参与会话的资源是受限制的,因此包括以下附加信息是非常有用的。 
  
  · 会话使用的带宽信息。 
  
  · 会话负责人的联系信息。 
  
  (2)媒体信息 
  
  · 媒体类型,例如视频和音频。 
  
  · 传输协议,例如RTP/UDP/IPH.320。 
  
  · 媒体格式,例如H.261视频和MPEG视频。 
  
  · 多播地址和媒体传输端口(IP多播会话)。 
  
  · 用于联系地址的媒体和传输端口的远端地址(IP单播会话)。 
  
  SDP描述由许多文本行组成,文本行的格式为<类型>=<><类型>是一个字母 
<>是结构化的文本串,其格式依<类型>而定。 
  
  3 SAPSIPSDP组合应用实例 
  
  在这个应用实例中,我们设计了这样一种场景:某公司领导需要与本公司各部 
门负责人召开电视会议。他使用的多媒体会议系统采用了本文所描述的这种SAP
IPSDP组合应用技术。该公司领导首先通过一台具有Web浏览功能的客户机登陆会 
议服务器,注册一个会议。在注册的同时,他就将各部门负责人纳入了本次会议的 
参与者之列(当然,还需要该公司领导和各部门负责人的客户机在同一个多播组内 
)。然后,他在页面上点击一个“会议通知”按钮,会议服务器就通过SAP协议向本 
次会议的各参与者(包括公司领导和部门负责人)所在客户机发送召开会议的通知 
。此时,若各参与者所在客户机是正常的连接到网络上并且SAP通知接收器正常工作 
的话,它就会以声音或图形的方式通知该参与者,同时准备好本客户机参加此次会 
议的客户端程序。当各参与者发现会议通知后,他在已经准备好的会议客户端程序 
上点击一个“参加会议”的按钮,客户端就通过SIP协议将该客户机轻松地加入到会 
议之中。当参与者到齐后,在会议主席(公司领导)的控制下,此次会议就可以正 
式开始了。 
  
  各参与者客户机上的SAP通知接收器接收到会议通知后,它会尽可能地调用客户 
机上的各种资源以满足本次会议的要求,如果实在不能够满足的话,它也可以以书 
面形式通知参与者本机所缺的资源。在整个会议的SAPSIP交互过程中都用到了SD 
P协议来描述会话和媒体信息。

假设主叫Alice 在她的提供中包含下列SDP 描述。其中包含一个双向音频流和两个双向视频流(视频流分别使用编解码H.261(载荷类型31)和MPEG (载荷类型32 。
v=0
o=alice 2890844526 2890844526 IN IP4 host.anywhere.com (用户名,会话id,版本,。。。。)
s=
c=IN IP4 host.anywhere.com
t=0 0 (起始时间,终止时间)
m=audio 49170 RTP/AVP 0 (净荷类型是0 ,发往UDP协议的49170端口)
a=rtpmap:0 PCMU/8000 (双声道 净荷类型0 时钟频率8000每秒,RTP类型编码)
m=video 51372 RTP/AVP 31
a=rtpmap:31 H261/90000
m=video 53000 RTP/AVP 32
a=rtpmap:32 MPV/90000
--------------------------------------------------------------------------------------------------
被叫Bob 不希望接收或发送第一个视频流,那么他将在应答中返回如下SDP:
v=0
o=bob 2890844730 2890844730 IN IP4 host.example.com
s=
c=IN IP4 host.example.com
t=0 0
m=audio 49920 RTP/AVP 0
a=rtpmap:0 PCMU/8000
m=video 0 RTP/AVP 31 (如果不希望接收其中的一个流,就在返回中把他的端口设置为0,其他的媒体流必须按原来返回)
m=video 53000 RTP/AVP 32
a=rtpmap:32 MPV/90000
----------------------------------------------------------------------------------------------------
之后的某个时刻,Bob 想改变音频流的接收端口(从49920 改为65422),同时增加另外一个只收音频流,并使用RTP 载荷类型,那么Bob 将在提供中包含如下SDP:
v=0
o=bob 2890844730 2890844731 IN IP4 host.example.com (会话号要自动加一)
s=
c=IN IP4 host.example.com
t=0 0
m=audio 65422 RTP/AVP 0 (把49920改为65422端口)
a=rtpmap:0 PCMU/8000
m=video 0 RTP/AVP 31
m=video 53000 RTP/AVP 32
a=rtpmap:32 MPV/90000
m=audio 51434 RTP/AVP 110 (增加只收的音频流,载荷类型为RTP)
a=rtpmap:110 telephone-events/8000
a=recvonly (只收模式)
---------------------------------------------------------------------------------------------------------
Alice 接收增加的媒体流,将产生如下应答:
v=0
o=alice 2890844526 2890844527 IN IP4 host.anywhere.com (会话号要自动加一)
s=
c=IN IP4 host.anywhere.com 
t=0 0 
m=audio 49170 RTP/AVP 0
a=rtpmap:0 PCMU/8000
m=video 0 RTP/AVP 31
a=rtpmap:31 H261/90000
m=video 53000 RTP/AVP 32
a=rtpmap:32 MPV/90000
m=audio 53122 RTP/AVP 110
a=rtpmap:110 telephone-events/8000
a=sendonly (只发模式)

 

 

六、SIP服务器搭建

1.首先安装mysql,可以在终端提示符后运行下列命令: 

sudo apt-get install mysql-server
sudo apt-get install mysql-client

Sudo apt-get install openser

 

先安装rtpproxy

 

取得 rtpproxy-1.1 (官網 http://www.rtpproxy.org/)

# wget http://b2bua.org/chrome/site/rtpproxy-1.1.tar.gz

 

 

編譯 rtpproxy

# cd rtpproxy-1.1

# ./configure

# make ; make install

 

 

-- RTP Proxy --

設定為開機執行 rtpproxy 

# vi /etc/rc.local (加入以下兩行)

/usr/local/bin/rtpproxy -F

/usr/local/sbin/opensipsctl start

 

手動執行 rtpproxy

# /usr/local/bin/rtpproxy -F

 

若跑起來成功則可以在 /var/run 目錄底下看到有2個檔案

rtpproxy.pid

rtpproxy.sock=

 

 

3.配置:openser.cfg文件和openserctlrc文件以支持mysql

 

(1)vi /etc/openser/openser.cfg
Uncomment the line for MySQL DB support:
loadmodule mysql.so
Uncomment the following lines for MySQL based authentication support:
loadmodule auth.so
loadmodule auth_db.so
153 # ----- auth_db params -----

modparam("auth", "calculate_ha1", yes)
modparam("auth_db", "password_column", "password")
if (!www_authorize("sip.org", "subscriber")) { www_challenge("sip.org", "0"); break; };
Change the two sip.org instances in the above config, to your domain, or realm. In our case, the servers IP address. 192.16.125.160

Uncomment the following line to enable DB persistency for location entries:
modparam("usrloc", "db_mode", 2)
And comment the following line:
modparam("usrloc", "db_mode", 0)

(2) vi /usr/local/etc/openser/openserctlrc

# $Id: openserctlrc,v 1.2 2006/07/05 19:37:20 miconda Exp $
#
# openser control tool resource file
#
# here you can set variables used in the openserctl

## your SIP domain
SIP_DOMAIN=192.168.5.236###Add

## database type: MYSQL or PGSQL, by defaulte none is loaded
DBENGINE=MYSQL###Edit

## database host
DBHOST=localhost### Edit

## database name
DBNAME=openser### Edit

## database read/write user
DBRWUSER=openser### Edit

## database read only user
DBROUSER=openserro### Edit

## password for database read only user
DBROPW=openserro### Edit

## database super user
DBROOTUSER="root"### Edit

## type of aliases used: DB - database aliases; UL - usrloc aliases
## - default: none
#ALIASES_TYPE="DB"

## control engine: FIFO or UNIXSOCK
## - default FIFO
# CTLENGINE="FIFO"

## path to FIFO file
# OSER_FIFO="FIFO"

## check ACL names; default on (1); off (0)
# VERIFY_ACL=1

## ACL names - if VERIFY_ACL is set, only the ACL names from below list
## are accepted
# ACL_GROUPS="local ld int voicemail free-pstn"

## verbose - debug purposes - default '0'
# VERBOSE=1

 

4.创建openser所需的数据库及数据表

# sudo /usr/sbin/openserdbctl create        //一定注意这个在ubuntu下是openserdbctl,在其他版本linux可能会是openser_mysql.sh

~$ sudo /usr/sbin/openserdbctl create
MySQL password for root:                                      //这里输入root用户密码 
INFO: test server charset
INFO: creating database openser ...
INFO: Core OpenSER tables succesfully created.
Install presence related tables? (y/n): y
INFO: creating presence tables into openser ...
INFO: Presence tables succesfully created.
Install tables for imc cpl siptrace domainpolicy carrierroute? (y/n): y
INFO: creating extra tables into openser ...
INFO: Extra tables succesfully created.

5.添加用户:

这里需要用到openser数据库的密码,默认是openserrw

 

 

例如:

:~$ openserctl add 8004 8004 8004@192.168.0.101
MySQL password for user 'openser@localhost': 
new user '8004' added

6.启动服务器

Openserctl start

 

常见问题:

Fedora8启动mysql 报错:

 

ERROR 2002 (HY000): Cant connect to local MySQL server through socket /var/lib/mysql/mysql.sock’ (2)

 

1、先查看 /etc/rc.d/init.d/mysqld status 看看m y s q l 是否已经启动.

另外看看是不是权限问题.

 

2、确定你的mysql.sock是不是在那个位置,

mysql -u 你的mysql用户名 -p -S /var/lib/mysql/mysql.sock

 

3、试试:service mysqld start

 

4、如果是权限问题,则先改变权限 #chown -R mysql:mysql /var/lib/mysql

 

[root@localhost ~]# /etc/init.d/mysqld start

启动 MySQL: 确定 ]

[root@localhost ~]# mysql -uroot -p

 

ERROR 2002 (HY000): Can't connect to local MySQL server through socket '/var/lib/mysql/mysql.sock' (2)

原因是,/var/lib/mysql 的访问权限问题。

 

shell> chown -R mysql:mysql /var/lib/mysql

 

接着启动服务器

 

shell> /etc/init.d/mysql start

 

服务器正常启动后察看 /var/lib/mysql 自动生成mysql.sock文件。

 

但是我的问题仍然没有得到解决。

 

问题终于解决:

方法: 修改/etc/my.conf:

[mysqld]

datadir=/usr/local/mysql/data

socket=/var/lib/mysql/mysql.sock

 

[mysql.server]

user=mysql

basedir=/usr/local/mysql

 

If there is not currently a section called [client], add one at the bottom of the file and copy the socket= line under the [mysqld] section such as:

 

[client]

socket=/var/lib/mysql/mysql.sock

 

发现依旧如此,运行/etc/init.d/mysql start报错:Starting MySQLCouldn't find MySQL manager or server

mysqld服务没启,运行/usr/local/mysql/bin/mysqld_safe &

 

问题解决。

 

 

第二次使用openserctl start打开sip服务时出现

ERROR: PID file /var/run/openser.pid does not exist -- OpenSER start failed

错误

解决方法: 

1)在fedora中,要关闭openser,然后启动openserctl,就不会出现了; 

2)在DebianUbuntu中,不用考虑这个文件,因为,只要按照说明提示安装好并配置好/etc/openser中的openser.cfg文件和openserctl文件后,重新启动openser就可以了。

ubuntu中网上说openserctl start这种命令已经过时,直接使用 /etc/init.d/openser start /etc/init.d/openser stop命令来打开关闭即可

 

0 0
原创粉丝点击