【基於libRTMP的流媒體直播之 AAC、H264 解析】

        前文我們說到如何在基於 libRTMP 庫的流媒體直播過程中推送 AAC 、H264 音視頻流。本文以上文爲基礎,闡釋如何對 RTMP 包進行解析、重組得到原始的 AAC 音頻幀以及 H264 碼流。

        在繼續閱讀本文之前,我們首先假設讀者已經能夠使用 libRTMP 庫從 RTMP 直播服務器不斷地獲取 RTMP 包,如前提不成立,請自行閱讀 [拋開flash,自己開發實現C++ RTMP直播流播放器] 一文,實現一個簡單的 RtmpDownloader 測試用例。這一部分恕 Bill 不再贅述。

        廢話頗多,下面讓我們一起來看看如何對 RTMP 包進行解析和重組。

        根據前文所述,我們在推送音、視頻包之前,會首先向服務器推送一個音、視頻同步包,該包包含了 AAC 音頻幀以及 H264 碼流的解碼信息。因此當我們首次向服務器請求 RTMP 包之後,服務器會下發給我們對應的音、視頻同步包,這將決定我們如何解析並重組音、視頻。


RTMP 音頻包的解析及 AAC 重組                 

        當我們得到服務器下發的第一個音頻包(音頻同步包)之後,即可按照前文所述的封包順序進行逆操作,解析得到我們所需要的 AAC 音頻信息,根據這些信息,我們便可重組在推送時被我們去掉的那 7 個(或 9 個)字節:ADTSAudio Data Transport Stream),請參見維基百科 [ADTS]。一旦 ADTS 構造完畢,直接在其後添加原始 AAC 音頻數據即完成了整個 AAC 音頻幀的重組。

        根據 ADTS 屬性的描述,我們不難抽象出一個反映該信息的結構體如下:

wKiom1QneDSCSvzZAAEoq6e7vv0953.jpg

        接着讓我們回顧一下前文提到的音頻同步包的結構:

wKioL1QneQ7gzPzqAAKNXyQMvTU227.jpg

        我們只需要從服務器獲得的音頻同步包中獲取 AACDecoderSpecificInfo 以及 AudioSpecificConfig 4 個字節,並將其中的內容解析到 RtmpLiveAudioMetadataTy 這個結構中以備使用。示例代碼如下:

wKiom1QneyCy6Vu9AAMM-JEbp-c240.jpg

        在獲得了 AAC 音頻所必要的信息之後,我們便可構造 ADTS 並重組 RTMP 服務器下發來的後續音頻包。構造 ADTS 示例代碼如下:

wKiom1QnfOPwtSxZAAKoOmSuPco828.jpg

wKiom1Qnfbvjs0rrAAGPacckG4E928.jpg

        至此,ADTS 7個字節便重構完畢,我們只需要在這 7 個字節後面添加上 AAC 的原始數據便可重組一個 AAC 音頻幀。針對之後的每一個 RTMP 音頻包,都進行上述步驟,不斷將重組後的 AAC 音頻幀寫入文件,使用支持的播放器播放以驗證解析正確與否。



RTMP 視頻包的解析及 H.264 重組               

        與重組音頻幀類似的,我們首先會從服務器獲得視頻同步包,首先對視頻同步包進行拆包解析,得到本次 H264 碼流的 Sps 以及 Pps,並從 Sps 中獲取視頻的寬高信息以備使用。根據前文提到的視頻同步包封包流程,我們進行逆向解析的示例如下:

wKiom1QngRKCQGkjAALprfsuRBc380.jpg

wKiom1QngUPhgjl-AAGPsu_PbYs052.jpg

        其中從 Sps 獲取視頻的寬高信息請讀者自行 GoogleBill 不再贅述。解析完視頻同步包,我們只需要對接下來的視頻包進行分類即可,針對 H264 P 幀,我們直接將原始數據寫入文件,針對 I 幀,我們在其前面添加保存好的 Sps 以及 Pps,然後寫入原始數據即可。針對之後從 RTMP 服務器接收的每一個視頻包,均進行上述重組操作,並將獲得的 H264 編碼寫入文件,使用 Elecard StreamEye Tools 播放即可。


參考博文

[1][拋開flash,自己開發實現C++ RTMP直播流播放器]

[2][使用 libRtmp 進行 H264 與 AAC 直播]

[3][RTMP直播到FMS中的AAC音頻直播]

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章