• GBT28181中的RTP


    国标中说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

  • 相关阅读:
    [转]java中的匿名内部类总结
    linux 命令总结
    [转载]nohub java -jar xx.jar >/dev/null 2>&1 &
    Java正则表达式Pattern和Matcher类详解
    spark基础知识介绍(包含foreachPartition写入mysql)
    spark 运行架构
    spark核心原理
    行动操作
    控制操作
    键值转换操作
  • 原文地址:https://www.cnblogs.com/elisha-blogs/p/gbt28181_rtp.html
Copyright © 2020-2023  润新知