您的位置:首页 > 理论基础 > 计算机网络

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

2015-06-11 18:31 573 查看
转自: http://www.devdiv.com/iOS_iPhone-_rtp_-thread-118648-1-1.html

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

#include "rtpsession.h"

#include "rtppacket.h"

#include "rtpudpv4transmitter.h"

#include "rtpipv4address.h"

#include "rtpsessionparams.h"

#include "rtperrors.h"

@interface VideoRTPPack : NSObject<SocketHandlerDelegate>

{

RTPSession m_RTPSession;

NSMutableDictionary *dicDataBuffer;

}

@property(nonatomic, retain) NSMutableDictionary *dicDataBuffer;

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

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

- (void)SendVideoPacket:(unsigned char*)videoData

Nal:(int)_nal

Size:(size_t)videoDataSize

User:(unsigned long)user_id

FrameID:(int)video_frame_id;

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

- (void)closeVideoRTP;

@end

复制代码

#import "VideoRTPPack.h"

@implementation VideoRTPPack

@synthesize dicDataBuffer;

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

{

if (self = [super init])

{

[self createVideoRTP:hostIP onPort:port];

dicDataBuffer = [[NSMutableDictionary alloc] init];

}

return self;

}

- (void)dealloc

{

KLC_RELEASE_SAFELY(self.dicDataBuffer)

[super dealloc];

}

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

{

RTPUDPv4TransmissionParams m_VideoTransparams;

RTPSessionParams m_VideoSessionparams;

m_VideoSessionparams.SetOwnTimestampUnit(1.0/10.0);

m_VideoSessionparams.SetAcceptOwnPackets(TRUE);

m_VideoSessionparams.SetUsePollThread(0);

m_VideoTransparams.SetPortbase(port);

int nStatus = m_RTPSession.Create(m_VideoSessionparams, &m_VideoTransparams);

if(nStatus < 0)

{

NSLog(@"create rtp faild!");

return;

}

unsigned long ipAddress = ntohl(inet_addr([host UTF8String]));

RTPIPv4Address JRTPVideoAddr(ipAddress, port);

nStatus = m_RTPSession.AddDestination(JRTPVideoAddr);

if(nStatus < 0)

{

NSLog(@"add destination faild!");

return;

}

m_RTPSession.SetDefaultPayloadType(96);

m_RTPSession.SetDefaultMark(FALSE);

m_RTPSession.SetDefaultTimestampIncrement(160);

}

- (void)SendVideoPacket:(unsigned char*)videoData

Nal:(int)_nal

Size:(size_t)videoDataSize

User:(unsigned long)user_id

FrameID:(int)video_frame_id

{

NSLog(@"video_frame_id = %d", video_frame_id);

unsigned short length = 0;

int subPackIndex = 1;

int i_video_loop = 0, offset = 0, video_pack_len = 0;

NSMutableArray *subPackArray = [[NSMutableArray alloc] init];

MSQ_PACK_MID msq_pack_mid;

strcpy(msq_pack_mid.msq_head.AppName, GAppName);

msq_pack_mid.msq_head.sTransType = htons(TRANSTYPE_CLIENTTOSERVER);

msq_pack_mid.msq_head.sDataType = htons(SENDSTREAM_VIDEO_DATATYPE);

msq_pack_mid.msq_head.lSendID = htonl(user_id);

i_video_loop = videoDataSize / VIDEO_PACKET_SIZE;

if ((videoDataSize % VIDEO_PACKET_SIZE) > 0) i_video_loop ++;

while (videoDataSize)

{

VideoPacket *pVideoPacket = (VideoPacket*)msq_pack_mid.msq_data;

pVideoPacket->PacketHead.TotalPackets = i_video_loop;

pVideoPacket->PacketHead.subpacketindex = subPackIndex;

pVideoPacket->PacketHead.sOffset = htons(offset);

video_pack_len = (videoDataSize < VIDEO_PACKET_SIZE) ? videoDataSize:VIDEO_PACKET_SIZE;

pVideoPacket->PacketHead.sDataLength = htons(video_pack_len);

videoDataSize = videoDataSize - video_pack_len;

pVideoPacket->PacketHead.lFrameID = htonl(video_frame_id);

pVideoPacket->PacketHead.timeStart = 0;

pVideoPacket->PacketHead.timeEnd = 0;

pVideoPacket->PacketHead.s_nal = _nal;

memcpy(pVideoPacket->rawData, videoData+offset, video_pack_len);

offset = offset + video_pack_len;

length = sizeof(VideoPacketHead) + video_pack_len;

msq_pack_mid.msq_head.sTCPLength = htons(length);

msq_pack_mid.msq_head.sDataLength = msq_pack_mid.msq_head.sTCPLength;

NSData *subData = [NSData dataWithBytes:(void *)&msq_pack_mid length:sizeof(MSQ_HEAD)+length];

[subPackArray addObject:subData];

m_RTPSession.SendPacket(&msq_pack_mid, sizeof(MSQ_HEAD)+length);

subPackIndex ++;

}

// 把视频数据存入缓冲区

if ([[self.dicDataBuffer allKeys] count] < 50)

{

[self.dicDataBuffer setObject:subPackArray

forKey:[NSNumber numberWithInt:video_frame_id]];

}

else

{

[self.dicDataBuffer removeObjectForKey:[NSNumber numberWithInt:video_frame_id-51]];

[self.dicDataBuffer setObject:subPackArray

forKey:[NSNumber numberWithInt:video_frame_id]];

}

KLC_RELEASE_SAFELY(subPackArray)

}

- (void)resendSubPacketData:(int)frameID withSubPack:(int)packID

{

NSArray *lostArray = (NSArray *)[self.dicDataBuffer objectForKey:[NSNumber numberWithInt:frameID]];

NSData *lostData = [lostArray objectAtIndex:packID-1];

int nStatus = m_RTPSession.SendPacket([lostData bytes], [lostData length]);

if (nStatus == 0) NSLog(@"ReSend Packet Data Succeed!");

}

- (void)closeVideoRTP

{

if (m_RTPSession.IsActive())

{

m_RTPSession.Destroy();

}

}

@end
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: