一 linphone 架构及组成模块 2
二 linphone 系统框图 3
三 linphone 中各个模块说明 3
四 linphone 中数据结构说明 7
五 linphone 的初始化过程 7
六 linphone 建立通话过程说明 10
1 拨号call过程 10
2 等待响应 16
3 Answer过程分析 21
4 关于RTP及音视频流的网络传输 22
5 总结 23
七 linphone 会话执行过程log分析 24
八 linphone 使用参考 40
基于linphone-3.3.2版本,新版本linphone-3.4.3支持同时有多路call,所以,相比之前版本会有不少变化。
一 linphone 架构及组成模块
Linphone是一款跨平台的可视电话客户端软件,同时支持视频通话功能。Linphone可以在Linux,windows等主流操作系统平台上运行。
Linphone基于开源软件构建,本身也是开源软件。Linphone架构中sip协议的处理基于osip以及exosip两个开源库实现,媒体数据的选择整合处理使用mediastream2完成,该软件使用ffmepg、speedx等多款开源软件完成音视频的编解码,并通过ortp完成基于rtp协议的音视频数据传输。ortp是一款处理RTP会话的开源软件。
1 整体架构图如下:
整个软件分为两层,上层为用户接口前端(user interface frontends),下层为linphone核心引擎(linphone core engine)。
2 功能模块说明:
Liblinphone 核心引擎实现了linphone所有的功能函数,而且能够方便的添加音频和视频的呼叫功能。Liblinphone也提供高层的API,用来初始化,接收或者终止呼叫。Liblinphone依赖于下面三个组件:
1 Mediastreamer2
这是一个支持多种平台的轻量级的流技术引擎,主要适合于开发语音和视频电话应用程序。该引擎主要为 linphone 的多媒体流的收发,包括语音和视频的捕获、编码解码以及渲染。
2 ortp2
Ortp是一个RTP库。为基于RTP协议的媒体流传输提供支持。通过mediastream2编码的数据就是使用ortp库发送到网络的另一端。
3 eXosip2
Exosip2为sip协议的实现。这部分实际上是由exosip2和osip2两个库共同完成的。使用sip协议完成路由、媒体协商以及会话的建立和管理,为直接的媒体流的传输提供基础。
二 linphone 系统框图
关于上面框图的一些说明:
通话双方在通信前使用exosip进行会话协商。上图左边部分展示这一部分的流程。Exosip后台任务完成数据的接收和发送,并通过事件队列通知linphone底层的状态变化。
filter的构建在会话协商成功建立后就顺带完成了,并且ticker任务也跑起来了。此时按照filter graphics构建的通道,音视频流不断的从硬件设备上读取,并经过编码压缩送给RTP会话,之后送到对端,对端到达的音视频流也经过RTP会话接收送到解码解压缩filter,还原出原始的音视频流交给硬件设备播放。媒体数据在这两路流中源源不断的流动,完成了双方的可视通话。
上层linphone的core任务也不断的对底层进行迭代检查。所做的基本工作如下:
对于sip协议部分,core一直等待从事件队列上拿事件。这些事件是exosip任务在处理sip消息过程中添加到事件队列上的。每当得到新的事件后,core就从应用层的角度出发,进行处理。
对于视频流:基本上只处理rtcp数据包到达的事件。stream上也有一个事件队列,用于保存该流上的相关事件。对于rtcp数据包事件,core也只处理sr类型rtcp包,即发送端报告,得到jitter 和包丢失率。如果设置了自适应比特率,则调用相关接口进行处理。此过程不断进行,直到当前事件上的包处理完。
对于音频流,检查流是否还是活动的。通过比较RTP stats中接收的数据包数目是否发生变化,如果在超时时间到达后,接收的数据量还没有发生变化,则认为音频没有响应。
三 linphone 中各个模块说明
1 Linphone coreapi中子模块说明:
Coreapi中的各个模块就是上层的处理模块,包括configure文件的处理接口,address的处理接口,chat的处理接口,sal的处理接口,proxy的处理接口,authorization的处理接口,friends的处理接口,callback的处理接口,state的处理接口,杂项处理接口等。这相当于高层的几个模块,提供给用户的接口调用主要都在linphonecore.c中
1.Callback模块:
该模块下的回调函数都是用于sal模块调用的。当sal处理完sip协议的处理后,就会调用相应的callback函数继续后续的处理,包括启动一个音视频传输流,启动响铃等。也就是说这里的callback完成了media媒体层的处理以及linphone上层的处理。
回调函数被保存在全局变量linphone_sal_callbacks中,在linphone初始化时调用sal_set_callbacks设置到sal的callback上去的。
2.Genera_stat模块:
主要提供linphone全局状态的修改与设置的接口
3.Address模块:
调用sal提供的接口,进行与地址相关的处理,这里的地址主要是uri相关的处理。包括获取地址以及地址中的部分信息或者设置这些信息。在上层地址是一个字符串指针,但是在内部处理时都会强制转换为osip_from结构体来处理。实际上就是对linphone_address结构体的处理。
4.Authorization模块:
处理认证信息。各个认证用户的信息都被保存到linphone_auto结构体中兵串接在linphone_core结构体上。这里的接口就是处理这些数据结构,提供设置和获取相关信息的接口。
5.Chat模块:
提供创建和销毁chat room,向chat room发送消息和从chat room接收消息的接口,以及设置和获取用户数据的接口。类似于authorization模块,所有的chat room信息也是保存在linphone_chat结构体中并串接在linphone_core结构体上的。
6.Friends模块:
提供处理friends相关信息的接口。所有的friends信息保存在linphone_friend结构体中并被串接在linphone_core结构体上,这样操作起来,包括设置,获取,添加以及移除都很方便。
7.Configure模块:
提供配置文件处理的相关接口,包括配置文件的解析,配置文件中信息的获取,写入,同步等。配置文件解析后便于程序处理的信息主要都保存在lpconfig结构体中,这与文本文件中便于编写和阅读的配置文件本身不同。
配置文件中的各个配置模块本身也按照section的方式进行了划分,各个section也都是挂接在lp_config的section链表上的。这个模块可以单独提取出来进行测试。
8.Offer_answer模块:
管理基于sdp的媒体协商。根据本地的支持能力和远端支持的能力,根据就低的原则,获得双方都可以支持的媒体信息。比如编解码格式等。
9.Presence模块:
提供与在线状态相关的处理。
10.Proxy模块:
处理代理相关的处理。代理相关的信息保存在linphone_proxy结构体上,但是该结构体只是代表了当前linphone_core使用的proxy。代理可能不止一个,所有的代理其信息都被串接在链表上,并被挂接在sip_conf的proxies上。添加一个代理,取得一个代理以及其他相关的操作接口也都在该模块中提供处理接口。
11.Sal模块:
Sal模块其实应该是最重要的,最核心的模块了。该模块对exosip进行了简单的封装,间接的对osip模块进行了封装,使用该模块的接口可以完成sip协议的处理以及媒体描述的处理。
Sal.c文件主要是对一些sal相关的结构体的操作,包括SalMediaDescription和sal_op。处理包括创建这些结构体的实例,获取或者设置其中的一些操作域。
Sal_exosip2_sdp.c基于osip库提供的sdp相关操作的接口,在sal层实现将其与sal相关的结构体关联起来操作。比如根据SalMediaDescription结构体信息将其转换为sdp结构体,或者反之。
Sal_exosip2_presence.c包括了对in和out的subscribe的操作。Text数据的发送(基于osip和exosip)。
Sal_exosip2.c sip这块比较重要的封装。包含了对sal_op结构体的创建和基本操作。对exosip重要结构体的封装,包括初始化和释放。包含了对sal结构体的创建和基本操作的封装,更重要的是包含了对sal和sal_op,sal_media_desc,sal_stream_desc这些上层结构体与底层osip_message,sip_message,sdp_message等数据结构之间数据的转换和共享,以及对底层相关接口的调用。这种调用主要包括跟据上层结构体中包含的信息设置底层结构体,并调用底层接口完成具体功能,以及根据底层结构体得到的数据设置上层结构体的相关信息。
一个基本的描述就是:sal作为signal abstract layer包含了上层所主要理解的交互信息,这些信息对于理解电话操作而言已经足够了,在底层,选择了osip和exosip来支持这项操作。所以实际上来说,可以用其他支持sip的库的接口来替代现有的,保留sal层接口的功能定义。在linphone中,虽然大部分使用了sal层的封装来完成sip交互过程,但是也调用osip和exosip库本身的其他接口,所以这层封装主要还是再次简化协议层的处理,使得功能更具体,而不是更单一。
几个关键数据结构之间的关系:
Sal一个基本的结构体,通过这个结构体可以搜寻到上层所需的所有sip协议相关的信息。具体的call,register等信息保存在sal_op这个结构体中,多个实体通过链表串接起来,挂在sal上。Sal_op包含了sal_op_base结构体,这个结构体保存了一些通用的不变的信息,对多个实体而言,比如路由信息,本地媒体信息,远端媒体信息等。其root指针由返回指向了sal这个基础,所以通过sal_op可以找到sal。另外,在媒体信息中包含了所有流的信息,所有这些类似一个树的组织结构,sal类似树根,通过它可以找到所有的枝叶及其上的信息。这些数据结构之间的关系如下图:
12.Core模块:
上层API及其封装实现。通过这些API接口,可以快速构建基于sip的可视电话系统。
2 底层模块说明
1.Mediastream实现的说明:
从代码上来看mediastreamer库,它的构成非常结构化。在mediastream2中实现了大量的filter,包括声卡视频卡的filter,编解码器的filter,RTP传输与接收的filter等等。每个.c文件实现一个filter,而且每个filter的实现也是非常结构化的。首先需要定义一个filter结构体实例,对于实例的各个部分进行赋值,主要是包括定义filter私有数据,filter的methods,init,preprocess,process,postprocess和uninit这几个函数的实现等。而关键的一些实现,比如编解码器的处理,是基于ffmpeg库提供的接口来完成的,而声卡视频卡摄像头数据的捕获由其他库实现,但是也是基于标准的驱动接口来完成的。对于RTP的接收和传输则是基于ortp库来完成的。
另外提供了两个文件,audiostream和vediostream,用来处理音视频流的filter连接,linphonecore主要就是调用这几个文件提供的接口来完成媒体流的启动的。<