GBT28181中的RTP

摘要:
国家标准表示h264数据是根据RFC3984进行封装的,但国家标准测试工具SPVMN不支持RFC3984封装方法。无奈之下,您可以直接使用RFC3550进行打包,这实际上是分包,然后添加RTP标头。对于帧的结尾,在RTP报头中将MARK设置为1,并在帧的开头增加时间戳。这种打包方法实际上与RFC冲突。播放和解码用VLC打包和处理的RTP数据是不正常的,但可以用SPVMN播放。这样,就不需要测试音频和视频混合。

国标中说h264数据按照RFC3984打包,但是国标的测试工具——SPVMN,却不支持RFC3984的打包方式。
无奈之下直接用RFC3550的方式打包,其实就是分包,然后加上RTP头,对于一帧的结束,在RTP头中把MARK置1,并且在一帧的开始把时间戳增加而已。
这种打包方式其实和RFC有冲突,打包处理的RTP数据用VLC播放解码不正常,但用SPVMN是可以播的。
这种方式下没有测试音视频混合的情况,待测。

贴上代码(代码不全,体现下流程和重点):

 1 int NewRTPPacket(unsigned short channel, unsigned short sequenceNumber, unsigned long timeStamp, 
RTSP_DATE_TIME time, const unsigned char *pRTPData, unsigned long dataLen, bool bIsKeyFrame, bool mark) 2 { 3 if (dataLen > MAX_RTP_PAYLOAD_DATA_LEN) 4 { 5 assert(false); 6 return -1; 7 } 8 m_Sec = time.seconds; 9 m_MicroSec = time.microsecond; 10 Clear(); 11 12 m_bIsKeyFrame = bIsKeyFrame; 13 m_channel = channel; 14 m_pRTPHeader->sequenceNumber = htons(sequenceNumber); 15 m_pRTPHeader->timeStamp = htonl(timeStamp); 16 17 m_rtpDataLen = dataLen + sizeof(RTP_HEADER); 18 19 CreateCommonInfo(RTP_PAYLOAD_TYPE_H264, mark, STREAM_LIVE_VIDEO); 20 21 memcpy(m_pRTPData + sizeof(RTP_HEADER) + sizeof(INTERLEAVED_INFO), pRTPData, dataLen); 22 }
 1 int CreateRFC3550Packet(unsigned short channel, const unsigned char *pRTPData, unsigned long dataLen, 
 2         bool bIsKeyFrame, unsigned long TimeStamp, bool mark)  
 3 {  
 4         CRTPPacket *pRTPPacket = m_mapRTPPacketFree[channel]->front();  
 5         m_mapRTPPacketFree[channel]->pop_front();  
 6       
 7         pRTPPacket->NewRTPPacket(channel, ++m_VSequenceNum[channel], TimeStamp,   
 8             RTSPGetCurrTime(), pRTPData, dataLen, bIsKeyFrame, mark);  
 9       
10         m_mapRTPPacket[channel]->push_back(pRTPPacket);  
11         DistributePacket(pRTPPacket, channel);  
12       
13         return 0;  
14 }  
 1  //pData是一帧数据的首地址,dataLen是该帧的长度  
 2         while(dataLen > 0)  
 3         {  
 4             if (dataLen > MAX_RTP_PAYLOAD_DATA_LEN)  
 5             {  
 6                 CreateRFC3550Packet(channel, pData, MAX_RTP_PAYLOAD_DATA_LEN, bIsKeyFrame, m_LastFrameTs[streamType][channel], false);  
 7                 dataLen -= MAX_RTP_PAYLOAD_DATA_LEN;  
 8                 pData += MAX_RTP_PAYLOAD_DATA_LEN;  
 9             }  
10             else  
11             {  
12                 CreateRFC3550Packet(channel, pData, dataLen, bIsKeyFrame, m_LastFrameTs[streamType][channel], true);  
13                 dataLen = 0;  
14                 pData = NULL;  
15             }  
16         }  


值得一提的是,时间戳增量并不一定要严格按照固定的值增长,比如:
帧率为25帧的视频数据,时间戳增量一般为3600,但是实际的帧率可能是动态的,上一帧的时间和下一帧的时间间隔可能不是严格的40ms,实际上也不可能这么严格,
那么我在打时间戳的时候可以把这一帧的时间戳打成3500的增量,再把下一帧的增量达成3700,这也没关系。

注: 本文转载自 http://blog.csdn.net/c__allen/article/details/8960631

免责声明:文章转载自《GBT28181中的RTP》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇EF的左连接查询【C#写日志两个简单方法】下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

分布式系统唯一ID生成方案汇总

系统唯一ID是我们在设计一个系统的时候常常会遇见的问题,也常常为这个问题而纠结。生成ID的方法有很多,适应不同的场景、需求以及性能要求。所以有些比较复杂的系统会有多个ID生成的策略。下面就介绍一些常见的ID生成策略。 1. 数据库自增长序列或字段 最常见的方式。利用数据库,全数据库唯一。 优点: 1)简单,代码方便,性能可以接受。 2)数字ID天然排序,...

SpringBoot集成Nacos

SpringBoot集成Nacos 1、SpringBoot集成Nacos 2、Nacos配置 2.1 命名空间 2.2 资源配置 2.2.1 Data ID 2.2.2 Group 2.2.3 Namespace 2.2.4 配置内容 2.3 配置操作 2.3.1 历史版本 2.3.2 监听查询 3、扩展配置注意事项 3.1 客户端配置...

HBase1.2官方文档——ACID

原文链接:http://hbase.apache.org/acid-semantics.html 关于这篇文档 Apache HBase (TM) 不是一个适用于ACID的数据库。但是它可以保证特定的属性。这篇说明列举了HBase中ACID的属性 定义 为了共同的词汇表,我们定义以下术语: Atomicity原子性 一个操作是原子的,它要么整体都...

Oracle中TIMESTAMP时间的显示格式

Oracle中的TIMESTAMP数据类型很多人用的都很少,所以即使最简单的一个查询返回的结果也会搞不清楚到底这个时间是什么时间点。 例如: 27-1月 -08 12.04.35.877000 上午 这个时间到底是几点呢?中午12:04分,那就错了,其实使用to_char函数转换后得到如下结果: 2008-01-27 00:04:35:877000 说明这...

[转载]oracle删除数据后的恢复

原文地址:oracle删除数据后的恢复作者:無心傷害 今天一哥们把正式服务器上oracle数据表给delete了,我晕。吓我一身冷汗。赶紧google一下,终于找到正解。记录下来备忘。 要达到删除数据,有以下几种方式都可以:1、delete2、drop一个表3、truncate一个表重要的不是怎么删除一个表,而是误删除数据后怎么立即恢复(不考虑全库...

开放API接口签名验证

我们开放的api接口如果不做验证,完全暴露在外面是极其不安全的,所以我们要把我们的接口进行签名。 那签名有什么意义呢? 1、保证数据未被篡改 2、请求来源身份合法性 3、请求的唯一性 (不可复制) 那我们该如何实施呢: 1、首先我们得给客户端分配对应的key和secret 2、客户端访问数据接口之前需要用md5加密算法进行一次签名,签名内容是把我们提交的值...