您好,欢迎来到小侦探旅游网。
搜索
您的当前位置:首页国标28181视频流分析

国标28181视频流分析

来源:小侦探旅游网
国标28181视频流分析

转载:1、写在前⾯:

最开始接触H2的PS封装的时候,参考的是: , 确实是很有帮助,但完全参照这个实现,发现问题也很多,主要还是对MPEG213818的封装协议理解不深产⽣,所以我们在参考代码实现时,还是需要对原理做深⼊细致的分析,特别是封装涉及到bit级别的配置,⼀个bit配错了,可能就播放不了,所以记录下,做个备份。2、封装需要基本了解的概念:

RTP:是流媒体实时传输协议,RTP头有12个字节

H2视频帧:由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播放时会⼀闪⽽过,修改后的函数如下:

static void Packet_PS_header(char* pDestBuf, int length, int currPts) {

unsigned long long lScrExt = 0;//(currPts) % 100; unsigned long sScr = currPts;//currPts / 100;

bits_buffer_t bits;

if ( NULL == pDestBuf) {

return PS_Error_Param; }

bits_initwrite( &bits, length, pDestBuf);

bits_write(&bits, 32, 0x000001BA); /*start codes*/ bits_write(&bits, 2, 1); /*marker bits '01b'*/

bits_write(&bits, 3, (sScr>>30)&0x07); /*System clock [32..30]*/ bits_write(&bits, 1, 1); /*marker bit*/

bits_write(&bits, 15, (sScr>>15)&0x7FFF); /*System clock [29..15]*/ bits_write(&bits, 1, 1); /*marker bit*/

bits_write(&bits, 15, sScr&0x7fff); /*System clock [29..15]*/ bits_write(&bits, 1, 1); /*marker bit*/

bits_write(&bits, 9, lScrExt&0x01ff); /*System clock [14..0]*/ bits_write(&bits, 1, 1); /*marker bit*/

bits_write(&bits, 22, (160001)&0x3fffff); /*bit rate(n units of 50 bytes per second.)*/ bits_write(&bits, 2, 3); /*marker bits '11'*/

bits_write(&bits, 5, 0x1f); /*reserved(reserved for future use)*/

bits_write(&bits, 3, 0); /*stuffing length*/ }

3、PES头中,如果只包括PTS时间戳,则需要修改为下⾯代码:

修改的时候把DTS去掉了,然后配套修改了第8个字节,但没有检查原来参考⽂章中设置的是同时包括PTS和DTS,所以需要关注修改:第七字节的⾼两位是PTS和DTS指⽰位,00表⽰⽆PTS⽆DTS,01禁⽌使⽤,10表⽰PES头部字段会附加PTS结构,11表⽰PTS和DTS都包括

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 ); // header bits_write( &bits, 8, 0xe0 );

bits_write( &bits, 16, datalen); //pes_packet_length : es len and the following pes len bits_write( &bits, 8, 0x8c ); //

bits_write( &bits, 2, 0x02 ); //第七字节的⾼两位是PTS和DTS指⽰位,00表⽰⽆PTS⽆DTS,01禁⽌使⽤,10表⽰PES头部字段会附加PTS结构,11表⽰PTS和DTS都包括 bits_write( &bits, 6, 0x00 ); // bits_write( &bits, 8, 0x05 ); //8

//UINT i_scr = I_SCR(_iFrameIndextemp);

bits_write( &bits, 4, 2 ); /*'0010'*/

bits_write( &bits, 3, ((pts)>>30)&0x07 ); /*PTS[32..30]*/ bits_write( &bits, 1, 1 );

bits_write( &bits, 15,((pts)>>15)&0x7FFF); /*PTS[29..15]*/ bits_write( &bits, 1, 1 );

bits_write( &bits, 15,(pts)&0x7FFF); /*PTS[14..0]*/ bits_write( &bits, 1, 1 ); }

4、RTP的组包发送上⾯,根据H2的RTP打包⽅式,有单NALU、FU-A、FU-B多种形式,根据适配需要调整。

因篇幅问题不能全部显示,请点此查看更多更全内容

Copyright © 2019- xiaozhentang.com 版权所有 湘ICP备2023022495号-4

违法及侵权请联系:TEL:199 1889 7713 E-MAIL:2724546146@qq.com

本站由北京市万商天勤律师事务所王兴未律师提供法律服务