封装音视频流为RTP包来网络传输

转载 2013年12月05日 13:20:15

转自:  http://www.devdiv.com/iOS_iPhone-_rtp_-thread-118648-1-1.html


ios没有直接得api用来封装传输rtp,但是经常有用到得接收过来得音视频数据,经过X264处理转换便可以封装为Rtp包进行直接发送。大家可以看代码:

  1. #include "rtpsession.h"
  2. #include "rtppacket.h"
  3. #include "rtpudpv4transmitter.h"
  4. #include "rtpipv4address.h"
  5. #include "rtpsessionparams.h"
  6. #include "rtperrors.h"

  7. @interface VideoRTPPack : NSObject<SocketHandlerDelegate> 
  8. {
  9.         RTPSession          m_RTPSession;
  10.         
  11.         NSMutableDictionary *dicDataBuffer;
  12. }

  13. @property(nonatomic, retain) NSMutableDictionary *dicDataBuffer;

  14. - (id)initWithVideoRTP:(NSString *)hostIP onPort:(unsigned short)port;

  15. - (void)createVideoRTP:(NSString *)host onPort:(unsigned short)port;

  16. - (void)SendVideoPacket:(unsigned char*)videoData 
  17.                                         Nal:(int)_nal
  18.                                    Size:(size_t)videoDataSize 
  19.                                    User:(unsigned long)user_id
  20.                                 FrameID:(int)video_frame_id;

  21. - (void)resendSubPacketData:(int)frameID withSubPack:(int)packID;

  22. - (void)closeVideoRTP;

  23. @end
复制代码
  1. #import "VideoRTPPack.h"

  2. @implementation VideoRTPPack

  3. @synthesize dicDataBuffer;

  4. - (id)initWithVideoRTP:(NSString *)hostIP onPort:(unsigned short)port
  5. {
  6.         if (self = [super init]) 
  7.         {
  8.                 [self createVideoRTP:hostIP onPort:port];
  9.                 
  10.                 dicDataBuffer = [[NSMutableDictionary alloc] init];
  11.         }
  12.         
  13.         return self;
  14. }

  15. - (void)dealloc
  16. {
  17.         KLC_RELEASE_SAFELY(self.dicDataBuffer)
  18.         
  19.         [super dealloc];
  20. }

  21. - (void)createVideoRTP:(NSString *)host onPort:(unsigned short)port
  22. {
  23.         RTPUDPv4TransmissionParams m_VideoTransparams;
  24.         RTPSessionParams m_VideoSessionparams;
  25.         
  26.         m_VideoSessionparams.SetOwnTimestampUnit(1.0/10.0);
  27.         m_VideoSessionparams.SetAcceptOwnPackets(TRUE);
  28.         m_VideoSessionparams.SetUsePollThread(0);
  29.         m_VideoTransparams.SetPortbase(port);
  30.         
  31.         int nStatus = m_RTPSession.Create(m_VideoSessionparams, &m_VideoTransparams);
  32.         if(nStatus < 0) 
  33.         {
  34.                 NSLog(@"create rtp faild!");
  35.                 return;
  36.         }
  37.         
  38.         unsigned long ipAddress = ntohl(inet_addr([host UTF8String]));
  39.         
  40.         RTPIPv4Address JRTPVideoAddr(ipAddress, port);
  41.         nStatus = m_RTPSession.AddDestination(JRTPVideoAddr);
  42.         if(nStatus < 0) 
  43.         {
  44.                 NSLog(@"add destination faild!");
  45.                 return;
  46.         }
  47.         
  48.         m_RTPSession.SetDefaultPayloadType(96);
  49.         m_RTPSession.SetDefaultMark(FALSE);
  50.         m_RTPSession.SetDefaultTimestampIncrement(160);
  51. }

  52. - (void)SendVideoPacket:(unsigned char*)videoData 
  53.                                         Nal:(int)_nal
  54.                                    Size:(size_t)videoDataSize 
  55.                                    User:(unsigned long)user_id
  56.                                 FrameID:(int)video_frame_id
  57. {
  58.         NSLog(@"video_frame_id = %d", video_frame_id);
  59.         
  60.         unsigned short length = 0;
  61.         int subPackIndex = 1;
  62.         int i_video_loop = 0, offset = 0, video_pack_len = 0;
  63.         NSMutableArray *subPackArray = [[NSMutableArray alloc] init];
  64.         
  65.         MSQ_PACK_MID msq_pack_mid;
  66.         strcpy(msq_pack_mid.msq_head.AppName, GAppName);
  67.         msq_pack_mid.msq_head.sTransType  = htons(TRANSTYPE_CLIENTTOSERVER);
  68.         msq_pack_mid.msq_head.sDataType   = htons(SENDSTREAM_VIDEO_DATATYPE);
  69.         msq_pack_mid.msq_head.lSendID     = htonl(user_id);
  70.         
  71.         i_video_loop = videoDataSize / VIDEO_PACKET_SIZE;
  72.         if ((videoDataSize % VIDEO_PACKET_SIZE) > 0) i_video_loop ++;
  73.         
  74.         while (videoDataSize)
  75.         {
  76.                 VideoPacket *pVideoPacket = (VideoPacket*)msq_pack_mid.msq_data;
  77.                 
  78.                 pVideoPacket->PacketHead.TotalPackets   = i_video_loop;
  79.                 pVideoPacket->PacketHead.subpacketindex = subPackIndex;
  80.                 pVideoPacket->PacketHead.sOffset        = htons(offset);
  81.                 
  82.                 video_pack_len = (videoDataSize < VIDEO_PACKET_SIZE) ? videoDataSize:VIDEO_PACKET_SIZE;
  83.                 pVideoPacket->PacketHead.sDataLength    = htons(video_pack_len);
  84.                 videoDataSize = videoDataSize - video_pack_len;
  85.                 
  86.                 pVideoPacket->PacketHead.lFrameID       = htonl(video_frame_id);
  87.                 pVideoPacket->PacketHead.timeStart      = 0;
  88.                 pVideoPacket->PacketHead.timeEnd        = 0;
  89.                 pVideoPacket->PacketHead.s_nal          = _nal;
  90.                 
  91.                 memcpy(pVideoPacket->rawData, videoData+offset, video_pack_len);
  92.                 offset = offset + video_pack_len;
  93.                 
  94.                 length = sizeof(VideoPacketHead) + video_pack_len;
  95.                 
  96.                 msq_pack_mid.msq_head.sTCPLength = htons(length);
  97.                 msq_pack_mid.msq_head.sDataLength = msq_pack_mid.msq_head.sTCPLength;
  98.                 
  99.                 NSData *subData = [NSData dataWithBytes:(void *)&msq_pack_mid length:sizeof(MSQ_HEAD)+length];
  100.                 [subPackArray addObject:subData];
  101.                 
  102.                 m_RTPSession.SendPacket(&msq_pack_mid, sizeof(MSQ_HEAD)+length);
  103.                 
  104.                 subPackIndex ++;
  105.         }
  106.         
  107.         // 把视频数据存入缓冲区
  108.         if ([[self.dicDataBuffer allKeys] count] < 50) 
  109.         {
  110.                 [self.dicDataBuffer setObject:subPackArray 
  111.                                                            forKey:[NSNumber numberWithInt:video_frame_id]];
  112.         }
  113.         else 
  114.         {
  115.                 [self.dicDataBuffer removeObjectForKey:[NSNumber numberWithInt:video_frame_id-51]];
  116.                 [self.dicDataBuffer setObject:subPackArray 
  117.                                                            forKey:[NSNumber numberWithInt:video_frame_id]];
  118.         }
  119.         
  120.         KLC_RELEASE_SAFELY(subPackArray)
  121. }

  122. - (void)resendSubPacketData:(int)frameID withSubPack:(int)packID
  123. {
  124.         NSArray *lostArray = (NSArray *)[self.dicDataBuffer objectForKey:[NSNumber numberWithInt:frameID]];
  125.         NSData *lostData = [lostArray objectAtIndex:packID-1];
  126.         
  127.         int nStatus = m_RTPSession.SendPacket([lostData bytes], [lostData length]);
  128.         if (nStatus == 0) NSLog(@"ReSend Packet Data Succeed!");
  129. }

  130. - (void)closeVideoRTP
  131. {
  132.         if (m_RTPSession.IsActive()) 
  133.         {
  134.                 m_RTPSession.Destroy();
  135.         }
  136. }


  137. @end

js如何创建类(封装)

学过其他面向对象语言的JavaScripter,可能都应用过类,如:class{},等定义的一系列方法, 但是初学者看是学习js的时候,经常会看到这样一句话,那就是JavaScript是面向对象语言...
  • xi_2130
  • xi_2130
  • 2015年12月12日 16:43
  • 7902

jquery封装之--css封装

我之间我的博客里面有提到,自定义的库和jquery库是水火不相容的,其实在我学习了CSS封装后,我算是大彻大悟。 在前面的时候我提到,获取节点,要用到繁琐的getId,getClass,getTag...
  • xiaoerduo123x
  • xiaoerduo123x
  • 2016年02月12日 14:41
  • 756

Mybatis 进行简单通用的封装

配置文件当Spring和Mybatis集成时,可以利用通配符的形式注册Mapper配置文件 ...
  • qq_17612199
  • qq_17612199
  • 2016年11月30日 21:57
  • 3019

自己封装的几个函数

封装简单的函数
  • wongsiusan
  • wongsiusan
  • 2015年09月21日 16:21
  • 3066

Java中什么叫封装啊?

Java中什么叫封装啊? 2008-09-27 15:21rsun1986  分类:JAVA相关 | 浏览 8553 次  java Java中什么叫封装呢? 继承和多态都明白些,就...
  • evilcry2012
  • evilcry2012
  • 2015年07月28日 10:41
  • 1316

面向对象——(9)封装和接口

封装:每个对象都包含它能进行操作所需要的所有信息,这个特性叫封装,因此对象不必依赖其他对象来完成自己的操作。   它有两重含义:第一,它把对象的属性和服务结合成一个独立的系统单位(即对象);第二,“信...
  • u010066934
  • u010066934
  • 2014年03月12日 19:52
  • 2433

jquery插件封装

扩展jQuery插件和方法的作用是非常强大的,它可以节省大量开发时间。这篇文章将概述jQuery插件开发的基本知识,最佳做法和常见的陷阱。 入门 编写一个jQuery插件开始于给jQuer...
  • qq_19244423
  • qq_19244423
  • 2015年07月09日 10:22
  • 12579

对Jquery中的ajax再封装,简化操作

jQueryAjaxJson取值示例 $(function () { jsonAjax("AjaxQuery.aspx", "ty...
  • smartsmile2012
  • smartsmile2012
  • 2013年11月30日 16:30
  • 14362

AsyncTask 使用及封装实践

前言这篇博客主要是讲解AsyncTask的使用及封装实践,对于新手们还是有很大的参考意义的,尤其是AsyncTask的封装实践这部分。这篇博客主要讲解以下问题: - AsyncTask的简单使用...
  • gdutxiaoxu
  • gdutxiaoxu
  • 2017年02月26日 12:54
  • 1024

Angularjs封装指令

AngularJS是一款非常强大的前端MVC框架。同时,它也引入了相当多的概念,这些概念我们可能不是太熟悉。(译者注:老外真谦虚,我大天朝的码农对这些概念那是相当熟悉啊!)这些概念有:     ...
  • qq_26702065
  • qq_26702065
  • 2016年03月24日 20:56
  • 3441
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:封装音视频流为RTP包来网络传输
举报原因:
原因补充:

(最多只允许输入30个字)