+----------------------------------------------------------------------------------------------------------------------------------------------------------------+
+ linphone code analyse
+----------------------------------------------------------------------------------------------------------------------------------------------------------------+
manager sip account
你的SIP标识 sip:2135@10.50.146.31
SIP代理地址 sip:10.50.146.31
直接用IP拨打
sip:toto@10.51.3.55
linphone所依赖的库:
osip, eXosip,
实时传输协议库ORTP
回声消除算法speex
语音压缩和解压算法库libogg
生成音频和视频流的mediastreamer2
视频支持 ffmpeg
eXosip库
__osip_global_init --> __ict_load_fsm --> (transition)ict_rcv_2xx (迁态)-->
__osip_message_callback(OSIP_ICT_STATUS_2XX_RECEIVED, ict, evt->sip); ---> cb_rcv2xx (上报eXosip事件)
osip_set_message_callback(osip, OSIP_ICT_STATUS_2XX_RECEIVED, &cb_rcv2xx);
注册:
1。eXosip_execute 一个线程不断循环地收消息,处理各种事件(包括1。发送消息和收消息处理(2。收到401),超时处理)
// 处理底层事情:发送消息,收到消息后的状态机运转,上报eXosip事件给下面处理
2。系统循环调用此函数 linphone_core_iterate -。。。-〉sal_iterate(3. 处理401,发送第二个register) / proxy_update(sal_register 1。发送第一个register)
主叫:
1。以linphone发送INVITE后,收到200ok消息为例:
OSIP_ICT_STATUS_2XX_RECEIVED
cb_rcv2xx // eXosip init时设置回调
ict_rcv_2xx // osip init时设置 fsm 有限状态机 回调
osip_ict_execute //eXosip_listen_addr--> _eXosip_thread --> eXosip_execute 执行 ict_rcv_2xx
2. 以收到事件后的处理
// process_execute --> call_accepted(Sal *, eXosip_event_t *) --> call_accepted(SalOp *)
static void call_accepted(Sal *sal, eXosip_event_t *ev){ //信令处理:发送ACK
sal->callbacks.call_accepted(op); //
// 初始化时设置 linphone_core_init-->sal_set_callbacks
// static void call_accepted(SalOp *op) 主要是媒体处理:更新媒体,设置状态
被叫: 收到Invite的处理,即接电话 linphone_core_accept_call
process_event-->EXOSIP_CALL_INVITE-->inc_new_call-->sal->callbacks.call_received(op);-->linphone_core_accept_call
采样率 * 通道数 = 每秒总的采样个数,还 *2 *(它是每个采样2 byte) MAX_LATENCY *(0.08秒,就是4倍的冗余. 大于这个数表示q过长,一般的语音处理长度大约是20 milisec)
线程:
主线程:sal_iterate //循环执行此函数,有事件就处理,应用层处理(知道收到200,就发送ACK,并且处理媒体)
消息处理线程:eXosip_listen_addr // 循环的收消息,处理各种事件,SIP层处理(发送消息;收到消息后的状态机运转,上报eXosip事件,如收到200,上报EXOSIP_CALL_ANSWERED)
rtp处理:应答后,start_media中启动一个线程处理audioStream, ticker, rtp sendto/recvfrom
(audio_stream_start_full rtp_session_recvm_with_ts)
混音: MS_AUDIO_MIXER_ID
conference_button_clicked 点击conference后,把未加入会议的呼叫都加入到会议中
linphone_core_add_to_conference(lc, call);
b. resume暂停的呼叫 linphone_core_resume_call : 发送reinvite, 并加入到远端中
b1 正在进行的呼叫:停止媒体流,update呼叫(发送reinvite),加本地端点到会议中
QQQ?
1 本端/远端 :为何?本端指进行混音的linphone, 其他的为远端
本端:收集到本地的声音后就进行混合处理,之后放音:
soundread(mix in) |encoder --> rtpsend
rtprecv --> decoder| soundwrite(mixer_out)
final: soundread(mix in) -->in_resampler --> mix --> out_resampler --> soundwrite(mixer_out)
远端:收到远端的声音后进行混合,再编码后送出
rtprecv --> decoder --> volrecv(mixer_in)| soundwrite
soundread |encoder(mixer_out) --> rtpsend
final: rtprecv --> decoder --> volrecv(mixer_in) -->in_resampler --> mix --> out_resampler --> encoder(mixer_out) --> rtpsend
2 conference后的filter link? 如上所示
原来的 soundread --> (read_resampler ec volsend dtmfgen_rtp)encoder --> rtpsend
rtprecv --> decoder (dtmfgen volrecv equalizer ec write_resampler)--> soundwrite
3. conference后的线程? mix线程, 每路呼叫一个线程处理rtp
4. reinvite ?
纯音频时, UA和confServ协商即可;
有视频时,confServ只转发视频,所以需要UA之间进行协商,即confServ在收到新加入的带有视频的invite时,
给其他在线用户发送reinvite, 并将结果转发给新成员
conferenc中 普通呼叫和会议的invite的媒体格式不同,怎么选择的?
3。 非WIN的用pipe,win用一对TCP socket连接来模拟管道
管道,半双工,用于2个进程间通信(指明了往那个管道的哪个端口读写),一个读端,一个写端。
eXosip_event_t *eXosip_event_wait(int tv_s, int tv_ms) // OSIP_MT版本:等待一段时间后去读,读不到阻塞(写端是非阻塞的,时间为0时读不到立即返回null)
线程_eXosip_thread : 循环执行eXosip_execute, 有事件时 eXosip_event_add --> __eXosip_wakeup_event(exosip.c) 写入W
线程sal_iterate : eXosip_event_wait读取事件后,进行处理