织梦CMS - 轻松建站从此开始!

罗索

GBT28181中的RTP

落鹤生 发布于 2015-09-06 11:18 点击:次 
国标中说h264数据按照RFC3984打包,但是国标的测试工具——SPVMN,却不支持RFC3984的打包方式。无奈之下直接用RFC3550的方式打包,其实就是分包,然后加上RTP头,对于一帧的结束,在RTP头中把MARK置1,并且在一帧的开始把时间戳增加而已。
TAG: GB28181  

国标中说h264数据按照RFC3984打包,但是国标的测试工具——SPVMN,却不支持RFC3984的打包方式。

无奈之下直接用RFC3550的方式打包,其实就是分包,然后加上RTP头,对于一帧的结束,在RTP头中把MARK置1,并且在一帧的开始把时间戳增加而已。

这种打包方式其实和RFC有冲突,打包处理的RTP数据用VLC播放解码不正常,但用SPVMN是可以播的。

这种方式下没有测试音视频混合的情况,待测。

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

  1. int NewRTPPacket(unsigned short channel, unsigned short sequenceNumber
  2. , unsigned long timeStamp, RTSP_DATE_TIME time, \ 
  3.                  const unsigned char *pRTPData, unsigned long dataLen
  4. bool bIsKeyFrame, bool mark) 
  5.     if (dataLen > MAX_RTP_PAYLOAD_DATA_LEN) 
  6.     { 
  7.         assert(false); 
  8.         return -1; 
  9.     } 
  10.     m_Sec = time.seconds; 
  11.     m_MicroSec = time.microsecond; 
  12.     Clear(); 
  13.  
  14.     m_bIsKeyFrame = bIsKeyFrame; 
  15.     m_channel = channel; 
  16.     m_pRTPHeader->sequenceNumber = htons(sequenceNumber); 
  17.     m_pRTPHeader->timeStamp = htonl(timeStamp); 
  18.  
  19.     m_rtpDataLen = dataLen + sizeof(RTP_HEADER); 
  20.  
  21.     CreateCommonInfo(RTP_PAYLOAD_TYPE_H264, mark, STREAM_LIVE_VIDEO); 
  22.  
  23.     memcpy(m_pRTPData + sizeof(RTP_HEADER) + sizeof(INTERLEAVED_INFO)
  24. , pRTPData, dataLen); 
  25.  
  26. int CreateRFC3550Packet(unsigned short channel, const unsigned char *pRTPData
  27. , unsigned long dataLen
  28. bool bIsKeyFrame, unsigned long TimeStamp, bool mark) 
  29.     CRTPPacket *pRTPPacket = m_mapRTPPacketFree[channel]->front(); 
  30.     m_mapRTPPacketFree[channel]->pop_front(); 
  31.  
  32.     pRTPPacket->NewRTPPacket(channel, ++m_VSequenceNum[channel], TimeStamp, \ 
  33.         RTSPGetCurrTime(), pRTPData, dataLen, bIsKeyFrame, mark); 
  34.  
  35.     m_mapRTPPacket[channel]->push_back(pRTPPacket); 
  36.     DistributePacket(pRTPPacket, channel); 
  37.  
  38.     return 0; 

 

  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
  7. , bIsKeyFrame
  8. , m_LastFrameTs[streamType][channel], false); 
  9.             dataLen -= MAX_RTP_PAYLOAD_DATA_LEN; 
  10.             pData += MAX_RTP_PAYLOAD_DATA_LEN; 
  11.         } 
  12.         else 
  13.         { 
  14.             CreateRFC3550Packet(channel, pData, dataLen, bIsKeyFrame
  15. , m_LastFrameTs[streamType][channel], true); 
  16.             dataLen = 0; 
  17.             pData = NULL; 
  18.         } 
  19.     } 

值得一提的是,时间戳增量并不一定要严格按照固定的值增长,比如:

帧率为25帧的视频数据,时间戳增量一般为3600,但是实际的帧率可能是动态的,上一帧的时间和下一帧的时间间隔可能不是严格的40ms,实际上也不可能这么严格,

那么我在打时间戳的时候可以把这一帧的时间戳打成3500的增量,再把下一帧的增量达成3700,这也没关系。

(c__allen)
本站文章除注明转载外,均为本站原创或编译欢迎任何形式的转载,但请务必注明出处,尊重他人劳动,同学习共成长。转载请注明:文章转载自:罗索实验室 [http://www.rosoo.net/a/201509/17377.html]
本文出处:2cto 作者:c__allen 原文
顶一下
(0)
0%
踩一下
(0)
0%
------分隔线----------------------------
发表评论
请自觉遵守互联网相关的政策法规,严禁发布色情、暴力、反动的言论。
评价:
表情:
用户名: 验证码:点击我更换图片
栏目列表
将本文分享到微信
织梦二维码生成器
推荐内容