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

罗索

SIP与RTP综合应用5-RTP解包过程

落鹤生 发布于 2010-09-17 09:14 点击:次 
RTP接收部分比较简单(不用考虑jitterbuffer等),先从这里入手。 其实主要就3步: 1 创建一个udp,监听一个端口,比如5200。 2 收到RTP包,送到解包程序,继续收第 二个。 3 收齐一帧后,或保存文件,或解码去播放。
TAG:

RTP接收部分比较简单(不用考虑jitterbuffer等),先从这里入手。

其实主要就3步:

1 创建一个udp,监听一个端口,比如5200。

2 收到RTP包,送到解包程序,继续收第 二个。

3 收齐一帧后,或保存文件,或解码去播放。

下面详细说一下具体过程:

1 创建UDP,非常非常地简单(这里只是简单地模拟RTP接收,虽然能正常工作,但是没有处理RTCP部分,会影响发送端):

  1. class CUDPSocket : public CAsyncSocket 
  2. public
  3.     CUDPSocket(); 
  4.     virtual ~CUDPSocket(); 
  5.     
  6.     virtual void OnReceive(int nErrorCode); 
  7.  
  8. }; 

调用者:CUDPSocket m_udp; m_udp.Create(...);这样就可以了。注意端口,如果指定端口创建不成功,就端口+1或+2重试一下。

重写OnReceive:

  1. void CUDPSocket::OnReceive(int nErrorCode) 
  2.     char szBuffer[1500]; 
  3.  
  4.     SOCKADDR_IN sockAddr; 
  5.     memset(&sockAddr, 0, sizeof(sockAddr)); 
  6.     int nSockAddrLen = sizeof(sockAddr); 
  7.  
  8. int nResult = ReceiveFrom(szBuffer, 1500, (SOCKADDR*)&sockAddr, &nSockAddrLen, 0); 
  9.     if(nResult == SOCKET_ERROR) 
  10.     { 
  11.         return
  12.     } 
  13. //如果必要可以处理对方IP端口 
  14.  
  15.    USHORT unPort = ntohs(sockAddr.sin_port); 
  16.    ULONG ulIP = sockAddr.sin_addr.s_addr; 
  17.  
  18. //收到的数据送去解码 
  19.  
  20.     Decode((BYTE*)szBuffer, nResult); 
  21.  

2 收到了数据,开始Decode,一般通过RTP传输的视频主要有h263 (old,1998,2000),h264,mpeg4-es。mpeg4-es格式最简单,就从它入手。

如果了解RFC3160,直接分析格式写就是了。如果想偷懒,用现成的, 也找的到:在opal项目下,有个plugins目录,视频中包含了h261,h263,h264,mpeg4等多种解包,解码的源码,稍加改动就可以拿来用。

首先看:video\common下的rtpframe.h这个文件,这是对RTP包头的数据和操作的封装:

  1. /*****************************************************************************/ 
  2. /*                                                                           */ 
  3. /* The Original Code is the Open H323 Library.                               */ 
  4. /*                                                                           */ 
  5. /* The Initial Developer of the Original Code is Matthias Schneider          */ 
  6. /* Copyright (C) 2007 Matthias Schneider, All Rights Reserved.               */ 
  7. /*                                                                           */ 
  8. /* Contributor(s): Matthias Schneider (ma30002000@yahoo.de)                  */ 
  9. /*                                                                           */ 
  10. /* Alternatively, the contents of this file may be used under the terms of   */ 
  11. /* the GNU General Public License Version 2 or later (the "GPL"), in which   */ 
  12. /* case the provisions of the GPL are applicable instead of those above.  If */ 
  13. /* you wish to allow use of your version of this file only under the terms   */ 
  14. /* of the GPL and not to allow others to use your version of this file under */ 
  15. /* the MPL, indicate your decision by deleting the provisions above and      */ 
  16. /* replace them with the notice and other provisions required by the GPL.    */ 
  17. /* If you do not delete the provisions above, a recipient may use your       */ 
  18. /* version of this file under either the MPL or the GPL.                     */ 
  19. /*                                                                           */ 
  20. /* The Original Code was written by Matthias Schneider <ma30002000@yahoo.de> */ 
  21. /*****************************************************************************/ 
  22.  
  23. #ifndef __RTPFRAME_H__ 
  24. #define __RTPFRAME_H__ 1 
  25.  
  26. #ifdef _MSC_VER 
  27. #pragma warning(disable:4800)  // disable performance warning 
  28. #endif 
  29.  
  30. class RTPFrame { 
  31. public
  32.   RTPFrame(const unsigned char * frame, int frameLen) { 
  33.     _frame = (unsigned char*) frame; 
  34.     _frameLen = frameLen; 
  35.   }; 
  36.  
  37.   RTPFrame(unsigned char * frame, int frameLen, unsigned char payloadType) { 
  38.     _frame = frame; 
  39.     _frameLen = frameLen; 
  40.     if (_frameLen > 0) 
  41.       _frame [0] = 0x80; 
  42.     SetPayloadType(payloadType); 
  43.   } 
  44.  
  45.   unsigned GetPayloadSize() const { 
  46.     return (_frameLen - GetHeaderSize()); 
  47.   } 
  48.  
  49.   void SetPayloadSize(int size) { 
  50.     _frameLen = size + GetHeaderSize(); 
  51.   } 
  52.  
  53.   int GetFrameLen () const { 
  54.     return (_frameLen); 
  55.   } 
  56.  
  57.   unsigned char * GetPayloadPtr() const { 
  58.     return (_frame + GetHeaderSize()); 
  59.   } 
  60.  
  61.   int GetHeaderSize() const { 
  62.     int size; 
  63.     size = 12; 
  64.     if (_frameLen < 12) 
  65.       return 0; 
  66.     size += (_frame[0] & 0x0f) * 4; 
  67.     if (!(_frame[0] & 0x10)) 
  68.       return size; 
  69.     if ((size + 4) < _frameLen) 
  70.       return (size + 4 + (_frame[size + 2] << 8) + _frame[size + 3]); 
  71.     return 0; 
  72.   } 
  73.  
  74.   bool GetMarker() const { 
  75.     if (_frameLen < 2) 
  76.       return false
  77.     return (_frame[1] & 0x80); 
  78.   } 
  79.  
  80.   unsigned GetSequenceNumber() const { 
  81.     if (_frameLen < 4) 
  82.       return 0; 
  83.     return (_frame[2] << 8) + _frame[3]; 
  84.   } 
  85.  
  86.   void SetMarker(bool set) { 
  87.     if (_frameLen < 2) 
  88.       return
  89.     _frame[1] = _frame[1] & 0x7f; 
  90.     if (set) _frame[1] = _frame[1] | 0x80; 
  91.   } 
  92.  
  93.   void SetPayloadType(unsigned char type) { 
  94.     if (_frameLen < 2) 
  95.       return
  96.     _frame[1] = _frame [1] & 0x80; 
  97.     _frame[1] = _frame [1] | (type & 0x7f); 
  98.   } 
  99.  
  100.   unsigned char GetPayloadType() const 
  101.   { 
  102.     if (_frameLen < 1) 
  103.       return 0xff; 
  104.     return _frame[1] & 0x7f; 
  105.   } 
  106.  
  107.   unsigned long GetTimestamp() const { 
  108.     if (_frameLen < 8) 
  109.       return 0; 
  110.     return ((_frame[4] << 24) + (_frame[5] << 16) + (_frame[6] << 8) + _frame[7]); 
  111.   } 
  112.  
  113.   void SetTimestamp(unsigned long timestamp) { 
  114.      if (_frameLen < 8) 
  115.        return
  116.      _frame[4] = (unsigned char) ((timestamp >> 24) & 0xff); 
  117.      _frame[5] = (unsigned char) ((timestamp >> 16) & 0xff); 
  118.      _frame[6] = (unsigned char) ((timestamp >> 8) & 0xff);
  119.      _frame[7] = (unsigned char) (timestamp & 0xff); 
  120.   }; 
  121.  
  122. protected
  123.   unsigned char* _frame; 
  124.   int _frameLen; 
  125. }; 
  126.  
  127. struct frameHeader { 
  128.   unsigned int  x; 
  129.   unsigned int  y; 
  130.   unsigned int  width; 
  131.   unsigned int  height; 
  132. }; 
  133.     
  134. #endif /* __RTPFRAME_H__ */ 

原封不动,可以直接拿来使用。当然,自己写一个也不麻烦。很多人写不好估计是卡在位运算上了。

(sxcong)

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