前文咱們說到如何在基於 libRTMP 庫的流媒體直播過程當中推送 AAC 、H264 音視頻流。本文以上文爲基礎,闡釋如何對 RTMP 包進行解析、重組獲得原始的 AAC 音頻幀以及 H264 碼流。
php
在繼續閱讀本文以前,咱們首先假設讀者已經可以使用 libRTMP 庫從 RTMP 直播服務器不斷地獲取 RTMP 包,如前提不成立,請自行閱讀 [拋開flash,本身開發實現C++ RTMP直播流播放器] 一文,實現一個簡單的 RtmpDownloader 測試用例。這一部分恕 Bill 再也不贅述。
html
廢話頗多,下面讓咱們一塊兒來看看如何對 RTMP 包進行解析和重組。服務器
根據前文所述,咱們在推送音、視頻包以前,會首先向服務器推送一個音、視頻同步包,該包包含了 AAC 音頻幀以及 H264 碼流的解碼信息。所以當咱們首次向服務器請求 RTMP 包以後,服務器會下發給咱們對應的音、視頻同步包,這將決定咱們如何解析並重組音、視頻。ide
RTMP 音頻包的解析及 AAC 重組 測試
當咱們獲得服務器下發的第一個音頻包(音頻同步包)以後,便可按照前文所述的封包順序進行逆操做,解析獲得咱們所須要的 AAC 音頻信息,根據這些信息,咱們即可重組在推送時被咱們去掉的那 7 個(或 9 個)字節:ADTS(Audio Data Transport Stream),請參見維基百科 [ADTS]。一旦 ADTS 構造完畢,直接在其後添加原始 AAC 音頻數據即完成了整個 AAC 音頻幀的重組。
編碼
根據 ADTS 屬性的描述,咱們不難抽象出一個反映該信息的結構體以下:
spa
接着讓咱們回顧一下前文提到的音頻同步包的結構:.net
咱們只須要從服務器得到的音頻同步包中獲取 AACDecoderSpecificInfo 以及 AudioSpecificConfig 這 4 個字節,並將其中的內容解析到 RtmpLiveAudioMetadataTy 這個結構中以備使用。示例代碼以下:3d
在得到了 AAC 音頻所必要的信息以後,咱們即可構造 ADTS 並重組 RTMP 服務器下發來的後續音頻包。構造 ADTS 示例代碼以下:
code
至此,ADTS 7個字節便重構完畢,咱們只須要在這 7 個字節後面添加上 AAC 的原始數據即可重組一個 AAC 音頻幀。針對以後的每個 RTMP 音頻包,都進行上述步驟,不斷將重組後的 AAC 音頻幀寫入文件,使用支持的播放器播放以驗證解析正確與否。
RTMP 視頻包的解析及 H.264 重組
與重組音頻幀相似的,咱們首先會從服務器得到視頻同步包,首先對視頻同步包進行拆包解析,獲得本次 H264 碼流的 Sps 以及 Pps,並從 Sps 中獲取視頻的寬高信息以備使用。根據前文提到的視頻同步包封包流程,咱們進行逆向解析的示例以下:
其中從 Sps 獲取視頻的寬高信息請讀者自行 Google,Bill 再也不贅述。解析完視頻同步包,咱們只須要對接下來的視頻包進行分類便可,針對 H264 P 幀,咱們直接將原始數據寫入文件,針對 I 幀,咱們在其前面添加保存好的 Sps 以及 Pps,而後寫入原始數據便可。針對以後從 RTMP 服務器接收的每個視頻包,均進行上述重組操做,並將得到的 H264 編碼寫入文件,使用 Elecard StreamEye Tools 播放便可。
參考博文
[1][拋開flash,本身開發實現C++ RTMP直播流播放器]
[2][使用 libRtmp 進行 H264 與 AAC 直播]
[3][RTMP直播到FMS中的AAC音頻直播]