通過libfdk-aac的使用來看音頻參數配置的策略

靈活性

背景

在一些實時音視頻系統中,終端軟件通常可以設置音頻編碼參數,如採樣率,通道數,碼率等。開放編碼參數可配,增加了靈活性,但是在實現增加了複雜度。特別是某些編碼格式,如果考慮到音頻的採集,回放,實時性。這裏針對AAC的編解碼庫libfdk-aac來說說參數可配的限制及對應的策略。

libfdk-aac不同AAC規格的差異性

  • 不通規格AAC編碼輸入幀的長度要求不一樣,如下所示:
AACENC_GRANULE_LENGTH =
      0x0105, /*!< Core encoder (AAC) audio frame length in samples:
                   - 1024: Default configuration.
                   - 512: Default length in LD/ELD configuration.
                   - 480: Length in LD/ELD configuration.
                   - 256: Length for ELD reduced delay mode (x2).
                   - 240: Length for ELD reduced delay mode (x2).
                   - 128: Length for ELD reduced delay mode (x4).
                   - 120: Length for ELD reduced delay mode (x4). */

AAC-ELD的範圍是最廣的,包括 1024,512,480,其次是AAC-LD範圍爲:1024,512,480,那麼對AAC-LC來說就只有1024了。(注意這裏的長度是採樣點的個數)。

這個輸入幀的長度會直接影響音頻採集的採樣率,因爲在特定的採樣率下,採集的音頻幀的長度如果與編碼要求輸入的幀長相等或者是整數倍時,這樣程序處理最簡單。

例如:

在我前面的文章<< 使用libfdk-aac編碼所需注意的細節 >> 介紹過,通過LATM格式封裝AAC-LD時,設置的輸入幀長度爲480,採樣點位數爲2個字節時,則幀長字節數爲960個字節。這時可以將音頻採樣率設置爲48000,單聲道。那麼採集的20ms音頻數據剛好是編碼要求的輸入長度的兩倍。那麼20ms的採樣音頻數據可以產生兩個AAC-LD數據幀,打包時,一個RTP包就攜帶了兩幀AAC-LD數據,剛好切合LATM格式複用的目的。

如果要兼容採樣率可配,那就需要考慮採集幀長不滿足編碼器要求輸入幀長的情況。再考慮RTP打包的要求,那麼程序必定會更加複雜。(如果通過緩存隊列來兼容採集輸出與編碼輸入的要求,那麼就會引入延遲)。

對AAC-LC而言,要求輸入長度是1024,下面是libfdk-aac支持的採樣率,每個採樣率產生的長度都不能滿足編碼器要求的整數倍的要求。

AACENC_SAMPLERATE = 0x0103, /*!< Audio input data sampling rate. Encoder
                                 supports following sampling rates: 8000, 11025,
                                 12000, 16000, 22050, 24000, 32000, 44100,
                                 48000, 64000, 88200, 96000 */

封裝這種差異性還是比較困難的,因爲在實時系統中,不單單是要考慮API的封裝,還要考慮數據的採集及RTP封包,延遲的引入。

  • 解決方式

我認爲的最優的解決方式就是將AAC的支持格式及封包方式固化,比如就只支持AAC-LD , LATM封裝模式,採樣率爲48000,ptime爲20ms,不可配置。在媒體協商時也進行固化,比如在sdp中就標明只支持這一種套餐,如果沒交集就協商失敗。

依此類推到其它音頻編碼格式,可能會出現各種不同的侷限。要滿足音頻參數全範圍可配的靈活性,難度還是挺大的。其實從用戶體驗的角度,32k採樣和48k採樣在聲音效果上,區別並不大。所以應該在滿足業務需求的情況下來提供有限的靈活性。

  • 一個參數配置例子

下面是某款華爲IP電話的媒體配置界面
在這裏插入圖片描述

上圖紅框所示,對AAC就只支持AAC-LD(封裝格式固化爲LATM),並且採樣率,聲道,編碼都不可配(固化爲48000,單聲道,96k)。對opus的編碼則開放了採樣率的配置。所以這種音頻參數可配的原則應該採用利於實現的原則,開放有限的參數配置。

額外記錄

LOAS與ADTS的判斷

LOAS與ADTS結構比較相似,頭+數據的形式。RTP打包都比較簡單一個包攜帶一幀數據。如果有與別的系統互通的要求,可以通過RFC3640方式打包。

  • ADTS封裝格式的判斷

ADTS 的頭長爲7個字節。Syncword長度爲12 bits,值爲0xFFF,代表一個ADTS幀的開始,作爲分界符,用於同步每幀的起始位置。

if (packet[0] != 0xff || (packet[1] & 0xf0) != 0xf0)
{
    //不爲ADTS格式
}

ADTS幀長度的獲取

packet_size = ((packet[3] & 0x03) << 11) | (packet[4] << 3) | (packet[5] >> 5);

packet指向ADTS的起始

  • LOAS封裝格式的判斷

LOAS的頭長爲3字節。Syncword長度爲11 bits,值爲0x2b7

LOASFlag = packet[0]<<3|((packet[1]&0xe0)>>5);
if (LOASFlag != 0x2b7)
{
    //不爲LOAS格式
}

LOAS幀長度獲取,Syncword的後13 bits爲幀的剩餘長度

packet_size = (packet[1]&0x1f)<<8 |packet[2];
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章