生活随笔
收集整理的這篇文章主要介紹了
GB28181协议支持的H264的PS封装实现
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
1、寫在前面:
最開始接觸H264的PS封裝的時候,參考的是:關于對H264碼流的PS的封裝的相關代碼實現?, 確實是很有幫助,但完全參照這個實現,發現問題也很多,主要還是對MPEG213818的封裝協議理解不深產生,所以我們在參考代碼實現時,還是需要對原理做深入細致的分析,特別是封裝涉及到bit級別的配置,一個bit配錯了,可能就播放不了,所以記錄下,做個備份。
2、封裝需要基本了解的概念:
RTP:是流媒體實時傳輸協議,RTP頭有12個字節
H264視頻幀:由NALU單元組成,其中I幀起始是00 00 00 01 65
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 非I幀 00 00 00 01 41
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?SPS 00 00 00 01 67
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?PPS 00 00 00 01 68
根據上面參考文章的說法,I幀前面需要增加PS頭+System 頭+ System Map 頭+ PES 頭
非I幀前面增加PS 頭 + PES 頭
3、對比參考文章做的一些修改:
1、PS封裝頭的長度是可以變化的,不是固定長度
? ? ? 參考文章中PS頭:
? ? ??
#define?PS_HDR_LEN??14?? #define?SYS_HDR_LEN?18?? #define?PSM_HDR_LEN?24?? #define?PES_HDR_LEN?19 我們定義的長度如下:
#define PS_HDR_LEN ?14
#define PSM_HDR_LEN?24
#define SYS_HDR_LEN?18
#define PES_HDR_LEN?14
2、關鍵的PTS和DTS是播放的關鍵因素,PTS:顯示時間戳,DTS:解碼時間戳
? ? ? PTS可以是一個相對值,以90KHZ采樣,25fps的視頻為例,每幀視頻的步長應該為3600
? ? ? 另外:參考文章中PTS的計算和DTS的計算有問題,封裝后的視頻通過VLC播放時會一閃而過,修改后的函數如下:
[cpp] view plain
copy static?void?Packet_PS_header(char*?pDestBuf,?int?length,?int?currPts)??{??????unsigned?long?long?lScrExt?=?0;??????unsigned?long?s64Scr?=?currPts;????????bits_buffer_t?bits;??????if?(?NULL?==?pDestBuf)??????{??????????return?PS_Error_Param;??????}??????bits_initwrite(?&bits,?length,?pDestBuf);??????bits_write(&bits,?32,?0x000001BA);??????????????????bits_write(&bits,?2,??1);???????????????????????????bits_write(&bits,?3,??(s64Scr>>30)&0x07);???????????bits_write(&bits,?1,??1);???????????????????????????bits_write(&bits,?15,?(s64Scr>>15)&0x7FFF);?????????bits_write(&bits,?1,??1);???????????????????????????bits_write(&bits,?15,?s64Scr&0x7fff);???????????????bits_write(&bits,?1,??1);???????????????????????????bits_write(&bits,?9,??lScrExt&0x01ff);??????????????bits_write(&bits,?1,??1);???????????????????????????bits_write(&bits,?22,?(160001)&0x3fffff);??????????????bits_write(&bits,?2,??3);???????????????????????????bits_write(&bits,?5,??0x1f);????????????????????????bits_write(&bits,?3,??0);???????????????????????}?? 3、PES頭中,如果只包括PTS時間戳,則需要修改為下面代碼:
修改的時候把DTS去掉了,然后配套修改了第8個字節,但沒有檢查原來參考文章中設置的是同時包括PTS和DTS,所以需要關注修改:第七字節的高兩位是PTS和DTS指示位,00表示無PTS無DTS,01禁止使用,10表示PES頭部字段會附加PTS結構,11表示PTS和DTS都包括
[cpp] view plain
copy static?void?gb28181_make_pes_header?(unsigned?char?*dst?,?int32_t?dstlen,?int32_t?data_length,?int?pts)??{??????short?datalen?=?data_length?+?8;??????bits_buffer_t?bits;??????bits_initwrite(?&bits,?dstlen,?dst);??????bits_write(?&bits,?24,?0x000001?);???????bits_write(?&bits,?8,?0xe0?);????????bits_write(?&bits,?16,?datalen);???????bits_write(?&bits,?8,?0x8c?);???????bits_write(?&bits,?2,?0x02?);???????bits_write(?&bits,?6,?0x00?);???????bits_write(?&bits,?8,?0x05?);???????????????bits_write(?&bits,?4,?2?);??????????????????????????bits_write(?&bits,?3,?((pts)>>30)&0x07?);???????????bits_write(?&bits,?1,?1?);???????bits_write(?&bits,?15,((pts)>>15)&0x7FFF);??????????bits_write(?&bits,?1,?1?);??????bits_write(?&bits,?15,(pts)&0x7FFF);????????????????bits_write(?&bits,?1,?1?);??}?? 4、RTP的組包發送上面,根據H264的RTP打包方式,有單NALU、FU-A、FU-B多種形式,根據適配需要調整。
總結
以上是生活随笔為你收集整理的GB28181协议支持的H264的PS封装实现的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。