+----------------------------------------------------------------------------------------------------------------------------------------------------------------+
+ linphone code analyse
+----------------------------------------------------------------------------------------------------------------------------------------------------------------+
manager sip account
你的SIP標識 sip:[email protected]
SIP代理地址 sip:10.50.146.31
直接用IP撥打
sip:[email protected]
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讀取事件後,進行處理