iOS音视频开发相关文章:
tutk的demo下载:
本站下载:TUTK demo iOS
github(有用的话记得给star):https://github.com/bingly/AvSamplePlayer_TUTK
视频数据基本是通过网络传输获取的。针对音视频数据量大的特点,有一套专门的网络传输协议RTP/RTSP,它的运行流程是这样的:
RTSP
RTSP(Real Time Streaming Protocol)是一款网络控制协议,用来控制流媒体服务器的,并提供了一些命令,如 play, record, pause。play表示服务开始向请求端发送流媒体数据,pause表示停止。先贴上一篇文章,非常详细的讲解了rtsp的操作,没接触过的童鞋可以了解一些。RTSP交互命令简介及过程参数描述
以下是客户端同流媒体服务器交互的完整示例,采用WireShark抓包(192.168.0.107->客户端,192.168.0.103->服务端,图片在网页上显示过小,需要保存到本地看):
图书中第二部分为RTSP交互的过程,命令的发送顺序为:OPTIONS、DESCRIBE、SETUP(两次)、PLAY。当PLAY命令发送后,就进入了第三部分RTP协议传输的流媒体数据包。
#import "RTSPConnection.h" #import "RTPReceiver.h" #import "CocoaAsyncSocket.h" #define HOST @"192.168.0.102" //camera //#define HOST @"192.168.0.111" #define PORT 554 #define WRITE_TIMEOUT 3.0 #define READ_TIMEOUT 60.0 const static NSString *VERSION = @" RTSP/1.0\r\n"; const static NSString *RTSP_OK = @"RTSP/1.0 200 OK"; @interface RTSPConnection() <GCDAsyncSocketDelegate> { dispatch_queue_t socketQueue; GCDAsyncSocket *clientSocket; NSString *_host; uint16_t _port; int _rtpPort; NSString *_rtspAddress; // 服务端返回数据 NSString *_sessionId; NSString *_cliendPort; //RTP、RTCP端口 RTPReceiver *_rtpReceiver; } @end @implementation RTSPConnection - (instancetype)init { if (self = [super init]) { socketQueue = dispatch_queue_create("tcpSocketQueue", NULL); clientSocket = [[GCDAsyncSocket alloc] initWithDelegate:self delegateQueue:socketQueue]; _host = HOST; _port = PORT; // _rtspAddress = [NSString stringWithFormat:@"rtsp://%@:%d/", _host, _port]; _rtspAddress = [NSString stringWithFormat:@"rtsp://%@:%d/live.264", _host, _port]; _rtpPort = arc4random() % 10000 + 6000; _cliendPort = [NSString stringWithFormat:@"%d-%d", _rtpPort , _rtpPort + 1]; _rtpReceiver = [[RTPReceiver alloc] initWithPort:_rtpPort]; [_rtpReceiver startReceive]; [self connectSocket]; } return self; } - (void)connectSocket { NSError *error; int connectRet = [clientSocket connectToHost:_host onPort:_port error:&error]; if (!connectRet) { NSLog(@"Error Connection: %@", error.localizedDescription); } } #pragma mard socketDelegate - (void)socket:(GCDAsyncSocket *)sock didConnectToHost:(NSString *)host port:(uint16_t)port { NSLog(@"didConnectToHost, host: %@, port: %d", host, port); [self doOption]; } - (void)socket:(GCDAsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag { NSString *dataString = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; NSLog(@"didReadData: %ld, %@", tag, dataString); switch (tag) { case 0: [self doDecribe]; break; case 1: [self doSetup]; break; case 2: { NSError *error; //@"Session:\\s(\\w+)[\\s\\S]+?client_port=(\\w+) NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:@"Session:\\s(\\w+)" options:NSRegularExpressionAllowCommentsAndWhitespace error:&error]; NSArray *result = [regex matchesInString:dataString options:NSMatchingReportCompletion range:NSMakeRange(0, dataString.length)]; if ([result count] == 0) { NSLog(@"ERROR!!! Cann't find session id and client port"); return; } _sessionId = [dataString substringWithRange:[result[0] rangeAtIndex:1]]; // [self doSetupSession]; [self doPlay]; } break; case 3: // [self doPlay]; break; default: break; } } - (void)socket:(GCDAsyncSocket *)sock didWriteDataWithTag:(long)tag { NSLog(@"didWriteDataWithTag: %ld", tag); } - (void)socketDidDisconnect:(GCDAsyncSocket *)sock withError:(NSError *)err { NSLog(@"socketDidDisconnect: %@", err.localizedDescription); } - (NSTimeInterval)socket:(GCDAsyncSocket *)sock shouldTimeoutReadWithTag:(long)tag elapsed:(NSTimeInterval)elapsed bytesDone:(NSUInteger)length { NSLog(@"shouldTimeoutReadWithTag, elapsed: %f, bytesDone: %ld", elapsed, length); return 0.0; } #pragma mark send RTSP data - (void)doOption { NSMutableString *dataString = [NSMutableString string]; // [dataString appendString:@"OPTIONS "]; [dataString appendString:[NSString stringWithFormat:@"OPTIONS %@ RTSP/1.0\r\n", _rtspAddress]]; [dataString appendString:@"CSeq: 1\r\n"]; [dataString appendString:@"\r\n"]; NSData *data = [dataString dataUsingEncoding:NSUTF8StringEncoding]; [clientSocket writeData:data withTimeout:WRITE_TIMEOUT tag:0]; [clientSocket readDataWithTimeout:READ_TIMEOUT tag:0]; } - (void)doDecribe { NSMutableString *dataString = [NSMutableString string]; [dataString appendString:[NSString stringWithFormat:@"DESCRIBE %@ RTSP/1.0\r\n", _rtspAddress]]; [dataString appendString:@"Accept: application/sdp\r\n"]; [dataString appendString:@"CSeq: 2\r\n"]; [dataString appendString:@"\r\n"]; NSData *data = [dataString dataUsingEncoding:NSUTF8StringEncoding]; [clientSocket writeData:data withTimeout:WRITE_TIMEOUT tag:1]; [clientSocket readDataWithTimeout:READ_TIMEOUT tag:1]; } - (void)doSetup { NSMutableString *dataString = [NSMutableString string]; [dataString appendString:[NSString stringWithFormat:@"SETUP %@/track1 RTSP/1.0\r\n", _rtspAddress]]; [dataString appendString:[NSString stringWithFormat:@"Transport: RTP/AVP/UDP;unicast;client_port=%@\r\n", _cliendPort]]; [dataString appendString:@"x-Dynamic-Rate: 0\r\n"]; [dataString appendString:@"CSeq: 3\r\n"]; [dataString appendString:@"\r\n"]; NSData *data = [dataString dataUsingEncoding:NSUTF8StringEncoding]; [clientSocket writeData:data withTimeout:WRITE_TIMEOUT tag:2]; [clientSocket readDataWithTimeout:READ_TIMEOUT tag:2]; } - (void)doSetupSession { NSMutableString *dataString = [NSMutableString string]; [dataString appendString:[NSString stringWithFormat:@"SETUP %@/track2 RTSP/1.0\r\n", _rtspAddress]]; [dataString appendString:[NSString stringWithFormat:@"Transport: RTP/AVP/UDP;unicast;client_port=%@\r\n", _cliendPort]]; [dataString appendString:@"x-Dynamic-Rate: 0\r\n"]; [dataString appendString:@"CSeq: 4\r\n"]; // [dataString appendString:[NSString stringWithFormat:@"Session: %@", _sessionId]]; [dataString appendString:@"\r\n"]; NSData *data = [dataString dataUsingEncoding:NSUTF8StringEncoding]; [clientSocket writeData:data withTimeout:WRITE_TIMEOUT tag:3]; [clientSocket readDataWithTimeout:READ_TIMEOUT tag:3]; } - (void)doPlay { NSMutableString *dataString = [NSMutableString string]; [dataString appendString:[NSString stringWithFormat:@"PLAY %@ RTSP/1.0\r\n", _rtspAddress]]; [dataString appendString:@"Range: npt=0.000-\r\n"]; [dataString appendString:@"CSeq: 4\r\n"]; [dataString appendString:@"\r\n"]; NSData *data = [dataString dataUsingEncoding:NSUTF8StringEncoding]; [clientSocket writeData:data withTimeout:WRITE_TIMEOUT tag:4]; [clientSocket readDataWithTimeout:READ_TIMEOUT tag:4]; }
2016-08-10 13:41:02.696 RTSPClient[2457:961862] didConnectToHost, host: 192.168.0.102, port: 554 2016-08-10 13:41:02.697 RTSPClient[2457:961862] didWriteDataWithTag: 0 2016-08-10 13:41:02.708 RTSPClient[2457:961874] didReadData: 0, RTSP/1.0 200 OK CSeq: 1 Date: Wed, Aug 10 2016 05:41:03 GMT Public: OPTIONS, DESCRIBE, SETUP, PLAY, PAUSE, TEARDOWN, GET_PARAMETER, SET_PARAMETER 2016-08-10 13:41:02.708 RTSPClient[2457:961874] didWriteDataWithTag: 1 2016-08-10 13:41:02.728 RTSPClient[2457:961862] didReadData: 1, RTSP/1.0 200 OK CSeq: 2 Content-Length: 508 Content-Base: rtsp://192.168.0.102:554/live.264/ Content-Type: application/sdp Date: Wed, Aug 10 2016 05:41:03 GMT x-Accept-Dynamic-Rate: 1 v=0 o=- 1773926623 1 IN IP4 s=Session Streamed by LIBZRTSP i=live.264 t=0 0 a=tool:LIBZRTSPD v1/0.3 a=type:broadcast a=control:* a=range:npt=0- a=x-qt-text-nam:Session Streamed by LIBZRTSP a=x-qt-text-inf:live.264 m=video 0 RTP/AVP 96 c=IN IP4 b=AS:0 a=rtpmap:96 H264/90000 a=fmtp:96 packetization-mode=1;profile-level-id=4D001E;sprop-parameter-sets=Z00AHpWoLQ9oQAAA+gAAHUwB,aO48gA== a=control:track1 m=audio 0 RTP/AVP 0 c=IN IP4 0.0.0.0 b=AS:64 a=rtpmap:0 PCMU/8000 a=control:track2 2016-08-10 13:41:02.729 RTSPClient[2457:961862] didWriteDataWithTag: 2 2016-08-10 13:41:02.738 RTSPClient[2457:961862] didReadData: 2, RTSP/1.0 200 OK CSeq: 3 Date: Wed, Aug 10 2016 05:41:03 GMT Session: 63A3E5E6;timeout=60 Transport: RTP/AVP/UDP;unicast;destination=192.168.0.110;source=192.168.0.102;client_port=12849-12850;server_port=30040-30041;mode=PLAY; x-Dynamic-Rate: 1 2016-08-10 13:41:02.743 RTSPClient[2457:961862] didWriteDataWithTag: 4 2016-08-10 13:41:02.748 RTSPClient[2457:961857] didReadData: 4, RTSP/1.0 200 OK CSeq: 4 Date: Wed, Aug 10 2016 05:41:03 GMT Range: npt=0.000- Session: 63A3E5E6 RTP-Info: url=rtsp://192.168.0.102:554/live.264/track1;seq=18553;rtptime=3987283666,url=rtsp://192.168.0.102:554/live.264/track2;seq=0;rtptime=0
本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系我们删除。