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_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播放时会一闪而过,修改后的函数如下:
- static void Packet_PS_header(char* pDestBuf, int length, int currPts)
- {
- unsigned long long lScrExt = 0;//(currPts) % 100;
- unsigned long s64Scr = 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, (s64Scr>>30)&0x07); /*System clock [32..30]*/
- bits_write(&bits, 1, 1); /*marker bit*/
- bits_write(&bits, 15, (s64Scr>>15)&0x7FFF); /*System clock [29..15]*/
- bits_write(&bits, 1, 1); /*marker bit*/
- bits_write(&bits, 15, s64Scr&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
- //UINT64 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的组包发送上面,根据H264的RTP打包方式,有单NALU、FU-A、FU-B多种形式,根据适配需要调整。
GB28181协议支持的H264的PS封装实现相关推荐
- LiveGBS国标视频平台GB28181协议支持CAS单点登录快速对接业务系统
LiveGBS国标视频平台GB28181协议支持CAS单点登录快速对接业务系统 1.如何配置CAS单点登陆 2.单点登录调整测试 3.搭建GB28181视频直播平台 1.如何配置CAS单点登陆 Liv ...
- PS封装H264码流
H264的PS封装 一个完整的ps包封装: PSheader + PS system header + PS system Map + PES header + h264 data 因为一般视频数据都 ...
- PS封装格式:GB28181协议RTP传输
PS封装格式:GB28181协议RTP传输 1. GB28181要求的RTP流格式 2. 头部信息 在安防行业,有个协议是无论如何都要适配的,因为公安监控网络用的就是它,它就是:GB28181 ...
- 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 + ...
- GB28181协议实现系列之----PS流封装(6)
前面的文章收到了不少同仁希望我开放源码,由于之前时间太忙了,一直在做另外产品线的架构设计及架构演化,核心模块的编码,关键技术问题解决等工作确实有较长的时间未继续写文章了.以至于博客的排名越来越低,从2 ...
- H264 NALU 使用PS封装 RTP发送
最近由于项目平台需求,要将H264 NALU封装为PS再用RTP发送,PS封装按照ISO DEC-13818-1标准.一个PS包包含PS Header, PES Header, PS system h ...
- 视频流PS,PS封装H264
出处: ISOIEC 13818-1 PS流: PS流由PSGOP组成,每个PSGOP是由I帧起始的多帧集合,每个GOP之间没有相互依赖信息,可以剪切拼接. | PSGOP0 | PSGOP1 | P ...
- H264码流的 ps封装
1.写在开始之前: 最近因为新工作要维护别人留下的GB模块代码,先熟悉了流程,然后也试着封装了下ps流,结果也能通过测试正常预览了,当然,其中开发读文档的头疼,预览花屏,卡帧的事情都有遇到,当时慢慢的 ...
- 【解决方案】GB28181/RTSP/SDK/Ehome协议支持级联视频智能分析平台EasyCVR搭建小区园区视频监控系统
一.背景分析 在社会信息化飞速迈进的今天,人们对住宅的关注已经不再局限于居室面积.周边环境.交通等方面,而是把更多的兴趣和注意力放在与外界沟通.信息服务.安全防范.物业管理方面,这就要求传统的住宅小区 ...
最新文章
- 项目实践:SpringBoot三招组合拳,手把手教你打出优雅的后端接口
- Python爬虫入门教程 33-100 《海王》评论数据抓取 scrapy
- linux系统下pid的取值范围了解一下
- TFboys:使用Tensorflow搭建深层网络分类器
- Caddy Web服务器QUIC部署
- 同批号不同批次同一单据中出现数量不限制
- Mybatis批量更新转
- mac上的mysql管理工具sequel pro
- 机器学习、深度学习方面书籍收集(持续更新……)
- 测试枕头软件,智能枕头:一款神器监测您的睡眠
- flume---2中channel file和memory
- 案例学习BlazeDS+Spring之九Company Manager
- kafak 命令使用
- 通过JS获取页面表格选中行信息
- 编程语言的通用概念[共同特征]
- 如何配置VS使得可以通过域名或IP访问
- SignalR主动通知订阅者示例
- 《Java程序性能优化》-葛一鸣
- C# 控制台程序(Console Application )启动后隐藏
- log4j配置详解(非常详细)
热门文章
- python求二维数组各行最大值_python+numpy按行求一个二维数组的最大值方法
- 初中计算机知识点 考题,初中信息技术考题规律及趋势_教师资格面试初中信息技术...
- c++ 从混合中英文数字等的string 中按顺序分别输出
- Android Studio 单刷《第一行代码》系列 06 —— Fragment 生命周期
- 工作以后如何有效学习
- 关于 Java 对象序列化您不知道的 5 件事
- 你真的很熟分布式和事务吗?
- 你必须学会的Git入门基本操作
- 【OpenCV】透视变换 Perspective Transformation(续)
- Python爬虫实战(5):模拟登录淘宝并获取所有订单