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头:

  1. #define PS_HDR_LEN  14
  2. #define SYS_HDR_LEN 18
  3. #define PSM_HDR_LEN 24
  4. #define PES_HDR_LEN 19

我们定义的长度如下:

#define PS_HDR_LEN14
#define PSM_HDR_LEN24
#define SYS_HDR_LEN18
#define PES_HDR_LEN14

2、关键的PTS和DTS是播放的关键因素,PTS:显示时间戳,DTS:解码时间戳

PTS可以是一个相对值,以90KHZ采样,25fps的视频为例,每帧视频的步长应该为3600

另外:参考文章中PTS的计算和DTS的计算有问题,封装后的视频通过VLC播放时会一闪而过,修改后的函数如下:

[cpp] view plain copy
  1. static void Packet_PS_header(char* pDestBuf, int length, int currPts)
  2. {
  3. unsigned long long lScrExt = 0;//(currPts) % 100;
  4. unsigned long s64Scr = currPts;//currPts / 100;
  5. bits_buffer_t bits;
  6. if ( NULL == pDestBuf)
  7. {
  8. return PS_Error_Param;
  9. }
  10. bits_initwrite( &bits, length, pDestBuf);
  11. bits_write(&bits, 32, 0x000001BA);            /*start codes*/
  12. bits_write(&bits, 2,  1);                     /*marker bits '01b'*/
  13. bits_write(&bits, 3,  (s64Scr>>30)&0x07);     /*System clock [32..30]*/
  14. bits_write(&bits, 1,  1);                     /*marker bit*/
  15. bits_write(&bits, 15, (s64Scr>>15)&0x7FFF);   /*System clock [29..15]*/
  16. bits_write(&bits, 1,  1);                     /*marker bit*/
  17. bits_write(&bits, 15, s64Scr&0x7fff);         /*System clock [29..15]*/
  18. bits_write(&bits, 1,  1);                     /*marker bit*/
  19. bits_write(&bits, 9,  lScrExt&0x01ff);        /*System clock [14..0]*/
  20. bits_write(&bits, 1,  1);                     /*marker bit*/
  21. bits_write(&bits, 22, (160001)&0x3fffff);        /*bit rate(n units of 50 bytes per second.)*/
  22. bits_write(&bits, 2,  3);                     /*marker bits '11'*/
  23. bits_write(&bits, 5,  0x1f);                  /*reserved(reserved for future use)*/
  24. bits_write(&bits, 3,  0);                     /*stuffing length*/
  25. }

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

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

[cpp] view plain copy
  1. static void gb28181_make_pes_header (unsigned char *dst , int32_t dstlen, int32_t data_length, int pts)
  2. {
  3. short datalen = data_length + 8;
  4. bits_buffer_t bits;
  5. bits_initwrite( &bits, dstlen, dst);
  6. bits_write( &bits, 24, 0x000001 ); // header
  7. bits_write( &bits, 8, 0xe0 );
  8. bits_write( &bits, 16, datalen); //pes_packet_length : es len and the following pes len
  9. bits_write( &bits, 8, 0x8c ); //
  10. bits_write( &bits, 2, 0x02 ); //第七字节的高两位是PTS和DTS指示位,00表示无PTS无DTS,01禁止使用,10表示PES头部字段会附加PTS结构,11表示PTS和DTS都包括
  11. bits_write( &bits, 6, 0x00 ); //
  12. bits_write( &bits, 8, 0x05 ); //8
  13. //UINT64 i_scr = I_SCR(_iFrameIndextemp);
  14. bits_write( &bits, 4, 2 );                    /*'0010'*/
  15. bits_write( &bits, 3, ((pts)>>30)&0x07 );     /*PTS[32..30]*/
  16. bits_write( &bits, 1, 1 );
  17. bits_write( &bits, 15,((pts)>>15)&0x7FFF);    /*PTS[29..15]*/
  18. bits_write( &bits, 1, 1 );
  19. bits_write( &bits, 15,(pts)&0x7FFF);          /*PTS[14..0]*/
  20. bits_write( &bits, 1, 1 );
  21. }

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

GB28181协议支持的H264的PS封装实现相关推荐

  1. LiveGBS国标视频平台GB28181协议支持CAS单点登录快速对接业务系统

    LiveGBS国标视频平台GB28181协议支持CAS单点登录快速对接业务系统 1.如何配置CAS单点登陆 2.单点登录调整测试 3.搭建GB28181视频直播平台 1.如何配置CAS单点登陆 Liv ...

  2. PS封装H264码流

    H264的PS封装 一个完整的ps包封装: PSheader + PS system header + PS system Map + PES header + h264 data 因为一般视频数据都 ...

  3. PS封装格式:GB28181协议RTP传输

    PS封装格式:GB28181协议RTP传输 1. GB28181要求的RTP流格式 2. 头部信息     在安防行业,有个协议是无论如何都要适配的,因为公安监控网络用的就是它,它就是:GB28181 ...

  4. GB28181协议实现系列之----IPC音视频PS封装(5)

    RTP封装PS  RTP报文头格式(见RFC3550 Page12): 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 12 3 4 5 6 7 8 9 0 1 + ...

  5. GB28181协议实现系列之----PS流封装(6)

    前面的文章收到了不少同仁希望我开放源码,由于之前时间太忙了,一直在做另外产品线的架构设计及架构演化,核心模块的编码,关键技术问题解决等工作确实有较长的时间未继续写文章了.以至于博客的排名越来越低,从2 ...

  6. H264 NALU 使用PS封装 RTP发送

    最近由于项目平台需求,要将H264 NALU封装为PS再用RTP发送,PS封装按照ISO DEC-13818-1标准.一个PS包包含PS Header, PES Header, PS system h ...

  7. 视频流PS,PS封装H264

    出处: ISOIEC 13818-1 PS流: PS流由PSGOP组成,每个PSGOP是由I帧起始的多帧集合,每个GOP之间没有相互依赖信息,可以剪切拼接. | PSGOP0 | PSGOP1 | P ...

  8. H264码流的 ps封装

    1.写在开始之前: 最近因为新工作要维护别人留下的GB模块代码,先熟悉了流程,然后也试着封装了下ps流,结果也能通过测试正常预览了,当然,其中开发读文档的头疼,预览花屏,卡帧的事情都有遇到,当时慢慢的 ...

  9. 【解决方案】GB28181/RTSP/SDK/Ehome协议支持级联视频智能分析平台EasyCVR搭建小区园区视频监控系统

    一.背景分析 在社会信息化飞速迈进的今天,人们对住宅的关注已经不再局限于居室面积.周边环境.交通等方面,而是把更多的兴趣和注意力放在与外界沟通.信息服务.安全防范.物业管理方面,这就要求传统的住宅小区 ...

最新文章

  1. 项目实践:SpringBoot三招组合拳,手把手教你打出优雅的后端接口
  2. Python爬虫入门教程 33-100 《海王》评论数据抓取 scrapy
  3. linux系统下pid的取值范围了解一下
  4. TFboys:使用Tensorflow搭建深层网络分类器
  5. Caddy Web服务器QUIC部署
  6. 同批号不同批次同一单据中出现数量不限制
  7. Mybatis批量更新转
  8. mac上的mysql管理工具sequel pro
  9. 机器学习、深度学习方面书籍收集(持续更新……)
  10. 测试枕头软件,智能枕头:一款神器监测您的睡眠
  11. flume---2中channel file和memory
  12. 案例学习BlazeDS+Spring之九Company Manager
  13. kafak 命令使用
  14. 通过JS获取页面表格选中行信息
  15. 编程语言的通用概念[共同特征]
  16. 如何配置VS使得可以通过域名或IP访问
  17. SignalR主动通知订阅者示例
  18. 《Java程序性能优化》-葛一鸣
  19. C# 控制台程序(Console Application )启动后隐藏
  20. log4j配置详解(非常详细)

热门文章

  1. python求二维数组各行最大值_python+numpy按行求一个二维数组的最大值方法
  2. 初中计算机知识点 考题,初中信息技术考题规律及趋势_教师资格面试初中信息技术...
  3. c++ 从混合中英文数字等的string 中按顺序分别输出
  4. Android Studio 单刷《第一行代码》系列 06 —— Fragment 生命周期
  5. 工作以后如何有效学习
  6. 关于 Java 对象序列化您不知道的 5 件事
  7. 你真的很熟分布式和事务吗?
  8. 你必须学会的Git入门基本操作
  9. 【OpenCV】透视变换 Perspective Transformation(续)
  10. Python爬虫实战(5):模拟登录淘宝并获取所有订单