封装音视频流为RTP包来网络传输
ios没有直接得api用来封装传输rtp,但是经常有用到得接收过来得音视频数据,经过X264处理转换便可以封装为Rtp包进行直接发送。大家可以看代码:
1 #include "rtpsession.h" 2 3 02. #include "rtppacket.h" 4 5 03. #include "rtpudpv4transmitter.h" 6 7 04. #include "rtpipv4address.h" 8 9 05. #include "rtpsessionparams.h" 10 11 06. #include "rtperrors.h" 12 13 07. 14 15 08. @interface VideoRTPPack : NSObject<SocketHandlerDelegate> 16 17 09. { 18 19 10. RTPSession m_RTPSession; 20 21 11. 22 23 12. NSMutableDictionary *dicDataBuffer; 24 25 13. } 26 27 14. 28 29 15. @property(nonatomic, retain) NSMutableDictionary *dicDataBuffer; 30 31 16. 32 33 17. - (id)initWithVideoRTP:(NSString *)hostIP onPort:(unsigned short)port; 34 35 18. 36 37 19. - (void)createVideoRTP:(NSString *)host onPort:(unsigned short)port; 38 39 20. 40 41 21. - (void)SendVideoPacket:(unsigned char*)videoData 42 43 22. Nal:(int)_nal 44 45 23. Size:(size_t)videoDataSize 46 47 24. User:(unsigned long)user_id 48 49 25. FrameID:(int)video_frame_id; 50 51 26. 52 53 27. - (void)resendSubPacketData:(int)frameID withSubPack:(int)packID; 54 55 28. 56 57 29. - (void)closeVideoRTP; 58 59 30. 60 61 31. @end
1 #import "VideoRTPPack.h" 2 3 02. 4 5 03. @implementation VideoRTPPack 6 7 04. 8 9 05. @synthesize dicDataBuffer; 10 11 06. 12 13 07. - (id)initWithVideoRTP:(NSString *)hostIP onPort:(unsigned short)port 14 15 08. { 16 17 09. if (self = [super init]) 18 19 10. { 20 21 11. [self createVideoRTP:hostIP onPort:port]; 22 23 12. 24 25 13. dicDataBuffer = [[NSMutableDictionary alloc] init]; 26 27 14. } 28 29 15. 30 31 16. return self; 32 33 17. } 34 35 18. 36 37 19. - (void)dealloc 38 39 20. { 40 41 21. KLC_RELEASE_SAFELY(self.dicDataBuffer) 42 43 22. 44 45 23. [super dealloc]; 46 47 24. } 48 49 25. 50 51 26. - (void)createVideoRTP:(NSString *)host onPort:(unsigned short)port 52 53 27. { 54 55 28. RTPUDPv4TransmissionParams m_VideoTransparams; 56 57 29. RTPSessionParams m_VideoSessionparams; 58 59 30. 60 61 31. m_VideoSessionparams.SetOwnTimestampUnit(1.0/10.0); 62 63 32. m_VideoSessionparams.SetAcceptOwnPackets(TRUE); 64 65 33. m_VideoSessionparams.SetUsePollThread(0); 66 67 34. m_VideoTransparams.SetPortbase(port); 68 69 35. 70 71 36. int nStatus = m_RTPSession.Create(m_VideoSessionparams, &m_VideoTransparams); 72 73 37. if(nStatus < 0) 74 75 38. { 76 77 39. NSLog(@"create rtp faild!"); 78 79 40. return; 80 81 41. } 82 83 42. 84 85 43. unsigned long ipAddress = ntohl(inet_addr([host UTF8String])); 86 87 44. 88 89 45. RTPIPv4Address JRTPVideoAddr(ipAddress, port); 90 91 46. nStatus = m_RTPSession.AddDestination(JRTPVideoAddr); 92 93 47. if(nStatus < 0) 94 95 48. { 96 97 49. NSLog(@"add destination faild!"); 98 99 50. return; 100 101 51. } 102 103 52. 104 105 53. m_RTPSession.SetDefaultPayloadType(96); 106 107 54. m_RTPSession.SetDefaultMark(FALSE); 108 109 55. m_RTPSession.SetDefaultTimestampIncrement(160); 110 111 56. } 112 113 57. 114 115 58. - (void)SendVideoPacket:(unsigned char*)videoData 116 117 59. Nal:(int)_nal 118 119 60. Size:(size_t)videoDataSize 120 121 61. User:(unsigned long)user_id 122 123 62. FrameID:(int)video_frame_id 124 125 63. { 126 127 64. NSLog(@"video_frame_id = %d", video_frame_id); 128 129 65. 130 131 66. unsigned short length = 0; 132 133 67. int subPackIndex = 1; 134 135 68. int i_video_loop = 0, offset = 0, video_pack_len = 0; 136 137 69. NSMutableArray *subPackArray = [[NSMutableArray alloc] init]; 138 139 70. 140 141 71. MSQ_PACK_MID msq_pack_mid; 142 143 72. strcpy(msq_pack_mid.msq_head.AppName, GAppName); 144 145 73. msq_pack_mid.msq_head.sTransType = htons(TRANSTYPE_CLIENTTOSERVER); 146 147 74. msq_pack_mid.msq_head.sDataType = htons(SENDSTREAM_VIDEO_DATATYPE); 148 149 75. msq_pack_mid.msq_head.lSendID = htonl(user_id); 150 151 76. 152 153 77. i_video_loop = videoDataSize / VIDEO_PACKET_SIZE; 154 155 78. if ((videoDataSize % VIDEO_PACKET_SIZE) > 0) i_video_loop ++; 156 157 79. 158 159 80. while (videoDataSize) 160 161 81. { 162 163 82. VideoPacket *pVideoPacket = (VideoPacket*)msq_pack_mid.msq_data; 164 165 83. 166 167 84. pVideoPacket->PacketHead.TotalPackets = i_video_loop; 168 169 85. pVideoPacket->PacketHead.subpacketindex = subPackIndex; 170 171 86. pVideoPacket->PacketHead.sOffset = htons(offset); 172 173 87. 174 175 88. video_pack_len = (videoDataSize < VIDEO_PACKET_SIZE) ? videoDataSize:VIDEO_PACKET_SIZE; 176 177 89. pVideoPacket->PacketHead.sDataLength = htons(video_pack_len); 178 179 90. videoDataSize = videoDataSize - video_pack_len; 180 181 91. 182 183 92. pVideoPacket->PacketHead.lFrameID = htonl(video_frame_id); 184 185 93. pVideoPacket->PacketHead.timeStart = 0; 186 187 94. pVideoPacket->PacketHead.timeEnd = 0; 188 189 95. pVideoPacket->PacketHead.s_nal = _nal; 190 191 96. 192 193 97. memcpy(pVideoPacket->rawData, videoData+offset, video_pack_len); 194 195 98. offset = offset + video_pack_len; 196 197 99. 198 199 100. length = sizeof(VideoPacketHead) + video_pack_len; 200 201 101. 202 203 102. msq_pack_mid.msq_head.sTCPLength = htons(length); 204 205 103. msq_pack_mid.msq_head.sDataLength = msq_pack_mid.msq_head.sTCPLength; 206 207 104. 208 209 105. NSData *subData = [NSData dataWithBytes:(void *)&msq_pack_mid length:sizeof(MSQ_HEAD)+length]; 210 211 106. [subPackArray addObject:subData]; 212 213 107. 214 215 108. m_RTPSession.SendPacket(&msq_pack_mid, sizeof(MSQ_HEAD)+length); 216 217 109. 218 219 110. subPackIndex ++; 220 221 111. } 222 223 112. 224 225 113. // 把视频数据存入缓冲区 226 227 114. if ([[self.dicDataBuffer allKeys] count] < 50) 228 229 115. { 230 231 116. [self.dicDataBuffer setObject:subPackArray 232 233 117. forKey:[NSNumber numberWithInt:video_frame_id]]; 234 235 118. } 236 237 119. else 238 239 120. { 240 241 121. [self.dicDataBuffer removeObjectForKey:[NSNumber numberWithInt:video_frame_id-51]]; 242 243 122. [self.dicDataBuffer setObject:subPackArray 244 245 123. forKey:[NSNumber numberWithInt:video_frame_id]]; 246 247 124. } 248 249 125. 250 251 126. KLC_RELEASE_SAFELY(subPackArray) 252 253 127. } 254 255 128. 256 257 129. - (void)resendSubPacketData:(int)frameID withSubPack:(int)packID 258 259 130. { 260 261 131. NSArray *lostArray = (NSArray *)[self.dicDataBuffer objectForKey:[NSNumber numberWithInt:frameID]]; 262 263 132. NSData *lostData = [lostArray objectAtIndex:packID-1]; 264 265 133. 266 267 134. int nStatus = m_RTPSession.SendPacket([lostData bytes], [lostData length]); 268 269 135. if (nStatus == 0) NSLog(@"ReSend Packet Data Succeed!"); 270 271 136. } 272 273 137. 274 275 138. - (void)closeVideoRTP 276 277 139. { 278 279 140. if (m_RTPSession.IsActive()) 280 281 141. { 282 283 142. m_RTPSession.Destroy(); 284 285 143. } 286 287 144. } 288 289 145. 290 291 146. 292 293 147. @end