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