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

罗索

基于RTP的H264视频数据打包解包类(2)

落鹤生 发布于 2011-01-14 16:17 点击:次 
RTP 承载H.264 Payload的解包类源码 // class CH264_RTP_UNPACK start class CH264_RTP_UNPACK { #defineRTP_VERSION2 #defineBUF_SIZE(1024*500) typedef struct { //LITTLE_ENDIAN unsigned short cc:4; /
TAG:


RTP 承载H.264 Payload的解包类源码

// class CH264_RTP_UNPACK start

  1. class CH264_RTP_UNPACK 
  2.  
  3. #define RTP_VERSION 2 
  4. #define BUF_SIZE (1024 * 500) 
  5.  
  6.     typedef struct 
  7.     { 
  8.         //LITTLE_ENDIAN 
  9.         unsigned short   cc:4;/* CSRC count                 */ 
  10.         unsigned short   x:1; /* header extension flag      */ 
  11.         unsigned short   p:1; /* padding flag               */ 
  12.         unsigned short   v:2; /* packet type                */ 
  13.         unsigned short   pt:7;/* payload type               */ 
  14.         unsigned short   m:1; /* marker bit                 */ 
  15.  
  16.         unsigned short    seq;/* sequence number            */ 
  17.         unsigned long     ts; /* timestamp                  */ 
  18.         unsigned long     ssrc;/*synchronization source     */ 
  19.     } rtp_hdr_t; 
  20. public
  21.  
  22.     CH264_RTP_UNPACK ( HRESULT &hr, unsigned char H264PAYLOADTYPE = 96 ) 
  23.         : m_bSPSFound(false
  24.         , m_bWaitKeyFrame(true
  25.         , m_bPrevFrameEnd(false
  26.         , m_bAssemblingFrame(false
  27.         , m_wSeq(1234) 
  28.         , m_ssrc(0) 
  29.     { 
  30.         m_pBuf = new BYTE[BUF_SIZE] ; 
  31.         if ( m_pBuf == NULL ) 
  32.         { 
  33.             hr = E_OUTOFMEMORY ; 
  34.             return ; 
  35.         } 
  36.  
  37.         m_H264PAYLOADTYPE = H264PAYLOADTYPE ; 
  38.         m_pEnd = m_pBuf + BUF_SIZE ; 
  39.         m_pStart = m_pBuf ; 
  40.         m_dwSize = 0 ; 
  41.         hr = S_OK ; 
  42.     } 
  43.  
  44.     ~CH264_RTP_UNPACK(void
  45.     { 
  46.         delete [] m_pBuf ; 
  47.     } 
  48.  
  49. //pBuf为H264 RTP视频数据包,nSize为RTP视频数据包字节长度,outSize为输出视频数据帧字节长度。 
  50. //返回值为指向视频数据帧的指针。输入数据可能被破坏。 
  51.     BYTE* Parse_RTP_Packet ( BYTE *pBuf, unsigned short nSize, int *outSize ) 
  52.     { 
  53.         if ( nSize <= 12 ) 
  54.         { 
  55.             return NULL ; 
  56.         } 
  57.  
  58.         BYTE *cp = (BYTE*)&m_RTP_Header ; 
  59.         cp[0] = pBuf[0] ; 
  60.         cp[1] = pBuf[1] ; 
  61.  
  62.         m_RTP_Header.seq = pBuf[2] ; 
  63.         m_RTP_Header.seq <<= 8 ; 
  64.         m_RTP_Header.seq |= pBuf[3] ; 
  65.  
  66.         m_RTP_Header.ts = pBuf[4] ; 
  67.         m_RTP_Header.ts <<= 8 ; 
  68.         m_RTP_Header.ts |= pBuf[5] ; 
  69.         m_RTP_Header.ts <<= 8 ; 
  70.         m_RTP_Header.ts |= pBuf[6] ; 
  71.         m_RTP_Header.ts <<= 8 ; 
  72.         m_RTP_Header.ts |= pBuf[7] ; 
  73.  
  74.         m_RTP_Header.ssrc = pBuf[8] ; 
  75.         m_RTP_Header.ssrc <<= 8 ; 
  76.         m_RTP_Header.ssrc |= pBuf[9] ; 
  77.         m_RTP_Header.ssrc <<= 8 ; 
  78.         m_RTP_Header.ssrc |= pBuf[10] ; 
  79.         m_RTP_Header.ssrc <<= 8 ; 
  80.         m_RTP_Header.ssrc |= pBuf[11] ; 
  81.  
  82.         BYTE *pPayload = pBuf + 12 ; 
  83.         DWORD PayloadSize = nSize - 12 ; 
  84.  
  85.         // Check the RTP version number (it should be 2): 
  86.         if ( m_RTP_Header.v != RTP_VERSION ) 
  87.         { 
  88.             return NULL ; 
  89.         } 
  90.  
  91.         /* 
  92.         // Skip over any CSRC identifiers in the header: 
  93.         if ( m_RTP_Header.cc ) 
  94.         { 
  95.             long cc = m_RTP_Header.cc * 4 ; 
  96.             if ( Size < cc ) 
  97.             { 
  98.                 return NULL ; 
  99.             } 
  100.  
  101.             Size -= cc ; 
  102.             p += cc ; 
  103.         }
  104.  
  105.         // Check for (& ignore) any RTP header extension 
  106.         if ( m_RTP_Header.x ) 
  107.         { 
  108.             if ( Size < 4 ) 
  109.             { 
  110.                 return NULL ; 
  111.             } 
  112.  
  113.             Size -= 4 ; 
  114.             p += 2 ; 
  115.             long l = p[0] ; 
  116.             l <<= 8 ; 
  117.             l |= p[1] ; 
  118.             p += 2 ; 
  119.             l *= 4 ; 
  120.             if ( Size < l ) ; 
  121.             { 
  122.                 return NULL ; 
  123.             } 
  124.             Size -= l ; 
  125.             p += l ; 
  126.         } 
  127.         
  128.         // Discard any padding bytes: 
  129.         if ( m_RTP_Header.p ) 
  130.         { 
  131.             if ( Size == 0 ) 
  132.             { 
  133.                 return NULL ; 
  134.             } 
  135.             long Padding = p[Size-1] ; 
  136.             if ( Size < Padding ) 
  137.             { 
  138.                 return NULL ; 
  139.             } 
  140.             Size -= Padding ; 
  141.         }*/ 
  142.  
  143.         // Check the Payload Type. 
  144.         if ( m_RTP_Header.pt != m_H264PAYLOADTYPE ) 
  145.         { 
  146.             return NULL ; 
  147.         } 
  148.  
  149.         int PayloadType = pPayload[0] & 0x1f ; 
  150.         int NALType = PayloadType ; 
  151.         if ( NALType == 28 ) // FU_A 
  152.         { 
  153.             if ( PayloadSize < 2 ) 
  154.             { 
  155.                 return NULL ; 
  156.             } 
  157.  
  158.             NALType = pPayload[1] & 0x1f ; 
  159.         } 
  160.  
  161.         if ( m_ssrc != m_RTP_Header.ssrc ) 
  162.         { 
  163.             m_ssrc = m_RTP_Header.ssrc ; 
  164.             SetLostPacket () ; 
  165.         } 
  166.     
  167.         if ( NALType == 0x07 ) // SPS 
  168.         { 
  169.             m_bSPSFound = true ; 
  170.         } 
  171.  
  172.         if ( !m_bSPSFound ) 
  173.         { 
  174.             return NULL ; 
  175.         } 
  176.  
  177.         if ( NALType == 0x07 || NALType == 0x08 ) // SPS PPS 
  178.         { 
  179.             m_wSeq = m_RTP_Header.seq ; 
  180.             m_bPrevFrameEnd = true ; 
  181.  
  182.             pPayload -= 4 ; 
  183.             *((DWORD*)(pPayload)) = 0x01000000 ; 
  184.             *outSize = PayloadSize + 4 ; 
  185.             return pPayload ; 
  186.         } 
  187.  
  188.         if ( m_bWaitKeyFrame ) 
  189.         { 
  190.             if ( m_RTP_Header.m ) // frame end 
  191.             { 
  192.                 m_bPrevFrameEnd = true ; 
  193.                 if ( !m_bAssemblingFrame ) 
  194.                 { 
  195.                     m_wSeq = m_RTP_Header.seq ; 
  196.                     return NULL ; 
  197.                 } 
  198.             } 
  199.  
  200.             if ( !m_bPrevFrameEnd ) 
  201.             { 
  202.                 m_wSeq = m_RTP_Header.seq ; 
  203.                 return NULL ; 
  204.             } 
  205.             else 
  206.             { 
  207.                 if ( NALType != 0x05 ) // KEY FRAME 
  208.                 { 
  209.                     m_wSeq = m_RTP_Header.seq ; 
  210.                     m_bPrevFrameEnd = false ; 
  211.                     return NULL ; 
  212.                 } 
  213.             }
  214.         }
  215.         if ( m_RTP_Header.seq != (WORD)( m_wSeq + 1 ) )//lost packet 
  216.         { 
  217.             m_wSeq = m_RTP_Header.seq ; 
  218.             SetLostPacket () ;            
  219.             return NULL ; 
  220.         } 
  221.         else 
  222.         { 
  223.             // 码流正常 
  224.  
  225.             m_wSeq = m_RTP_Header.seq ; 
  226.             m_bAssemblingFrame = true ; 
  227.             
  228.             if ( PayloadType != 28 ) // whole NAL 
  229.             { 
  230.                 *((DWORD*)(m_pStart)) = 0x01000000 ; 
  231.                 m_pStart += 4 ; 
  232.                 m_dwSize += 4 ; 
  233.             } 
  234.             else // FU_A 
  235.             { 
  236.                 if ( pPayload[1] & 0x80 ) // FU_A start 
  237.                 { 
  238.                     *((DWORD*)(m_pStart)) = 0x01000000 ; 
  239.                     m_pStart += 4 ; 
  240.                     m_dwSize += 4 ; 
  241.  
  242.                     pPayload[1] = ( pPayload[0] & 0xE0 ) | NALType ; 
  243.                     
  244.                     pPayload += 1 ; 
  245.                     PayloadSize -= 1 ; 
  246.                 } 
  247.                 else 
  248.                 { 
  249.                     pPayload += 2 ; 
  250.                     PayloadSize -= 2 ; 
  251.                 } 
  252.             } 
  253.  
  254.             if ( m_pStart + PayloadSize < m_pEnd ) 
  255.             { 
  256.                 CopyMemory ( m_pStart, pPayload, PayloadSize ) ; 
  257.                 m_dwSize += PayloadSize ; 
  258.                 m_pStart += PayloadSize ; 
  259.             } 
  260.             else // memory overflow 
  261.             { 
  262.                 SetLostPacket () ; 
  263.                 return NULL ; 
  264.             } 
  265.  
  266.             if ( m_RTP_Header.m ) // frame end 
  267.             { 
  268.                 *outSize = m_dwSize ; 
  269.  
  270.                 m_pStart = m_pBuf ; 
  271.                 m_dwSize = 0 ; 
  272.  
  273.                 if ( NALType == 0x05 ) // KEY FRAME 
  274.                 { 
  275.                     m_bWaitKeyFrame = false ; 
  276.                 } 
  277.                 return m_pBuf ; 
  278.             } 
  279.             else 
  280.             { 
  281.                 return NULL ; 
  282.             } 
  283.         } 
  284.     } 
  285.  
  286.     void SetLostPacket() 
  287.     { 
  288.         m_bSPSFound = false ; 
  289.         m_bWaitKeyFrame = true ; 
  290.         m_bPrevFrameEnd = false ; 
  291.         m_bAssemblingFrame = false ; 
  292.         m_pStart = m_pBuf ; 
  293.         m_dwSize = 0 ; 
  294.     } 
  295.  
  296. private
  297.     rtp_hdr_t m_RTP_Header ; 
  298.  
  299.     BYTE *m_pBuf ; 
  300.  
  301.     bool m_bSPSFound ; 
  302.     bool m_bWaitKeyFrame ; 
  303.     bool m_bAssemblingFrame ; 
  304.     bool m_bPrevFrameEnd ; 
  305.     BYTE *m_pStart ; 
  306.     BYTE *m_pEnd ; 
  307.     DWORD m_dwSize ; 
  308.  
  309.     WORD m_wSeq ; 
  310.  
  311.     BYTE m_H264PAYLOADTYPE ; 
  312.     DWORD m_ssrc ; 
  313. }; 
  314.  
  315. // class CH264_RTP_UNPACK end 

使用范例:

  1. HRESULT hr ; 
  2. CH264_RTP_UNPACK unpack ( hr ) ; 
  3. BYTE *pRtpData ; 
  4. WORD inSize; 
  5. int outSize ; 
  6. BYTE *pFrame = unpack.Parse_RTP_Packet ( pRtpData, inSize, &outSize ) ; 
  7. if ( pFrame != NULL ) 
  8. // frame process 
  9. // ... 

文章:来源

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