Asterisk1.8 轉碼策略分析

最近在修改asterisk轉碼和編碼協商的問題,發現asterisk的轉碼策略的選擇仍是有些問題的(基於1.8.9.3版本)。
——————————————
相關的CLI命令
轉碼路徑的調試命令:
core show channels
core show channel ${CHANNEL}數據結構

查看不一樣編碼之間進行轉換的時間開銷:
core show translationapp

查看某種編碼轉換爲其它編碼的路徑:
core show translation paths {codec}
eg: core show translation paths ulaw函數


ast_channel中與轉碼相關的數據成員:
ast_channel->nativeformats
ast_channel->writeformat
ast_channel->readformat
ast_channel->rawwriteformat
ast_channel->rawreadformat
ast_channel->writetrans
ast_channel->readtrans
——————————————
如下是測試用的case:
phone A: PCMU phone B:GSM
user A:PCMU,GSM user B:PCMA,GSM
測試

對於該用例asterisk的轉碼路徑是這樣的。
1.phone A => phone B
channel A讀轉碼(PCMU => PCMA)
channel B寫轉碼(PCMA => SLINEAR => GSM)
2.phone B => phone A
channel B讀轉碼(GSM => SLINEAR => PCMU)
channel A寫轉碼(PCMU,無需轉碼)ui

codec_trans.png從主叫到被叫與從被叫到主叫的轉碼路徑是不一致的,前者比後者多了一次從 PCMU 到 PCMA 的轉換。爲何會出現這種狀況呢?this

打開log開關、結合CLI命令進行分析,開始看代碼。編碼

asterisk對因而否須要轉碼及轉碼策略的選擇是在ast_channel_make_compatible中作的。該函數又調用ast_channel_make_compatible_helper來設置從主叫到被叫及被叫到主叫的轉碼策略。spa

在ast_set_read_format中,先調用ast_translator_best_choice(&fmt,&native)從native(即對應通道的nativeformates)和fmt(要設置的編碼集合)中分別選擇最優的一種編碼,並將選擇出的編碼從新賦值給native和fmt,這裏是傳地址的,經過指針修改。而後把native的值賦值給rawformat(通道的rawreadformat),將fmt的值賦值給format(通道的readformat)。最後,若是format與native值不相同的話,就調用ast_translator_build_path(*format, *rawformat)來創建轉碼路徑的鏈表。ast_set_write_format與ast_set_read_format同理,只不過fmt是賦值給通道的writeformat,native是賦值給通道的rawwriteformat。指針

收到200 OK後,會調用process_sdp(file:channels/chan_sip.c)來解析SDP,在處理被叫終端的SDP時,被叫通道的nativeformats可能會改變,此時須要從新設置被叫通道的讀寫轉碼路徑,對於writetranscode: 從channel->writeformat到channel->nativeformats進行轉換,對於readtranscode: 從channel->nativeformats到channel->readformat進行轉換。被叫通道的writeformat和readformat在以前調用ast_channel_make_compatible時已經被設置過了。

再回到咱們的問題上來。通過分析,出現該問題的緣由是在收到被叫的200 OK以前channelB->nativeformats的音頻編碼是Ulaw,而在收到200 OK後,channelB->nativeformats的音頻編碼是G729,而在通道橋接時,並無檢查channelB->nativeformats是否發生變化,沒有去更改channelB->writeformat(例子中爲ulaw)和channelA->readformat(例子中爲ulaw),使主叫仍按照以前選擇的路徑去進行轉碼,從而致使了沒必要要的轉碼步驟。

另外,在asterisk關於轉碼的實現中,主叫和被叫通道都分別有 WriteTranscode和ReadTranscode(能夠在通話時經過core show channel sip/{EXTEN}查看),這樣每一路通話最多可能會用到四個轉碼資源(ast_trans_pvt)。針對這些問題,我修改後的作法是:只在被叫通道一側作轉碼,主叫、被叫通道的readformat與writeformat設置爲主叫通道的nativeformats(主叫的nativeformats是不會改變的),這樣主叫通道不須要分配轉碼資源,最多隻佔用兩個轉碼資源。而且若是在處理完被叫終端回覆的SDP後被叫通道的nativeformats改變了,不須要對主叫和被叫的readformat和writeformat從新設置,只須要從新設置被叫通道的讀寫轉碼路徑便可(具體修改見以上代碼中modify和add部分)。

ast_channel_make_compatible這個函數只是檢查呼叫中的兩個channel的數據結構的一些編碼成員並設置兩個channel之間的編碼路徑。實際的轉碼是橋接時(如:ast_generic_bridge)在ast_read或ast_write中進行的,在讀寫幀以前調用ast_translate按照設置好的轉碼

相關文章
相關標籤/搜索