From:http://yate.null.ro/pmwiki/index.php?n=Main.CppTutorial3
Yate的編解碼模塊不處理任何消息,而是通過API方式調用。其他模塊通常兩者機制都使用。實現一個編解碼模塊要求需要對編解碼庫和算法有相當深的理解與研究。在Yate中實現它是相當簡單的。希望這個教程對你有幫助。
在這個教程中我們將使用到以下的ate API
1. class TranslatorFactory
2. class DataTranslator
3. class DataBlock
4. class FormatRepository
5. struct FormatInfo
6. struct TranslatorCaps
假定你已經看過我的第一個教程。這裏我們iLBC編解碼庫爲例子。我們使用iLBC 20ms的編解碼器。本教程的編解碼庫和項目中的代碼並不是100%的相同。所以如果你想使用iLBC,必須從CVS或Release版本獲取最新代碼,而不是使用本例代碼運用於實際項目之中。
第一步:創建一個插件(Plugin)
我們需從Plugin派生出一個類。雖然普通模塊一般都是從類Module派生,但是由於我們無需處理消息,因此我們只需要類Plugin派生,Plugin的核心功能已經能滿足咱們的需求。我們同樣需要從TranslatorFactory派生出一個類,使得我們的模塊具有編解碼的能力。你這樣聲明你的類:
注意,從Plugin類繼承的initialize方法。我們不需要爲ILBC 20ms編解碼庫做任何事情。
第二步:申明一個TranslatorCaps結構體變量
模塊需通過某種途徑來指定說明他所支持的編碼和解碼的數據格式。編解碼器將一種格式數據轉化成另外一種格式數據使用的編碼/解碼。編解碼器通過使用slin(Signed Linear Audio)格式,編碼成指定的數據格式(我們的例子是 iLBC 20ms),解碼過程亦是將iLBC 20ms轉換成slin數據。但是如果你的編解碼器能夠編碼或解碼除了slin之外的格式,你可以在TranslatorCaps指定編解碼的數據格式,並通知Yate。在我們的例子中我們只能編碼slin和解碼iLBC 20ms。總而言之,TranslatorCaps是你的編解碼器數據類型轉換的表格。TranslatorCaps變量聲明爲全局變量。
關於這點後面詳述
第三步:定義編解碼器功能
在構造函數中,我們將用到類FormatRepository定義編解碼器的功能,FormatRepository僅有兩個靜態的public成員變量。FormatInfo是一個含有編解碼信息(例名稱、比特率、幀數、通道數等等)的結構體。我們需要使用FormatRepository來構建FormatInfo信息。我們在Plugin插件的構造函數中做這事。
FormatRepository::addFormat函數有六個參數,後三個有缺省值,Kdoc文檔的註釋如下
1.name 標準無空白小寫的格式名稱
2 drate 每秒數據樣本大小 Data rate in octets/xsecond, 0 for variable
3 fsize 每幀大小(字節) Frame size in octets/frame, 0 for non-framed formats
Yate 3.0版本參數
*2 fsize 每幀大小 Data frame size in octets/frame, 0 for non-framed formats
*3 ftime 每幀時間間隔單位爲ms (實際代碼確實微妙) Data frame duration in microseconds, 0 for variable
4 type 格式類型 audio video text
5 srate 採樣率 音頻 樣本數/秒(audio) 1e-6 幀數/秒(video) 0位置
6 nchan 通道數量 缺省爲1
最後三個參數的缺省值
1. "audio"
2. 8000
3. 1
你可以根據你的需要和編解碼器使用而不同參數。
在addFormat中參數name值爲ilbc,第二個參數字節/秒(octets/second)可由幀大小乘以每秒幀數而得。在編解碼器中我們是幀/ms,因此你須將轉換成幀/秒。例ilbc 20ms我們每秒幀數爲1000/20=50,所以我們得到的值應該爲
1900 = 38*(1000/20)
幀大小僅僅是編解碼幀大小, iLBC 20ms每幀大小爲38字節,也就是38 octects,GSM每幀大小33字節。
所以,我們的格式轉換表的應該是這樣的:
IN OUT
slin ilbc (編碼)
ilbc slin (解碼)
第四步 提供所需功能
我們需要向YATE提供我們的編解碼器功能,因此我們需實現這個方法
第五步 編解碼器類
所有編解碼器相關功能都封轉到編解碼類中。我們需要再次從YATE的某個類中派生出一個類,這個類爲DataTranslator。在運行中我們可以擁有多個實例。
m_enc和m_dec分包負責編碼和解碼iLBC指定的數據。這些類型由iLBC類庫定義,在我們的代碼中沒有定義。Consume是我們實際執行編碼和解碼的方法。現在我們來寫構造函數
第六步 編解碼器的構造函數
第七步 編解碼器數據和實例的初始化
至今爲止我們僅僅向Yate提供了我們編解碼器的相關信息。有趣的是,Yate在需要做數據轉化時,還需要創建一個編解碼器。因此一
個編解碼器應該是可由任一通道根據編解碼的需求來創建的。
這裏,我們需要檢查/查找IN和OUT的數據格式。根據我們選擇的編解碼器。這裏我們用slin數據轉換成ilbc類型數據,稱爲編碼,反之爲解碼。