iOS语音对讲(二)RTSP+RTP协议实时传输

本文介绍iOS实时语音双向对讲(语音通话)功能:
(一)实时采集PCM并编码AAC
(二)RTSP+RTP协议实时传输
(三)FFmpeg实时解码AAC并播放PCM

第二篇介绍使用基于CocoaAsyncSocket的第三方开源库GCDAsyncSocket进行RTSP协议的Socket网络通讯。
GitHub下载地址:https://github.com/robbiehanson/CocoaAsyncSocket


具体过程如下:
创建socket并建立一个连接

- (int)connectServer:(NSString *)hostIP port:(int)hostPort {
    if (_socket == nil) {
        _socket = [[GCDAsyncSocket alloc] initWithDelegate:self delegateQueue:dispatch_get_main_queue()];
        NSError *err = nil;
        int t = [_socket connectToHost:hostIP onPort:hostPort error:&err];
        if (!t) {
            return 0;
        }else{
            return 1;
        }
    }else {
        [_socket readDataWithTimeout:-1 tag:0];
        return 1;
    }
}

GCDAsyncSocketDelegate代理方法

//连接成功
- (void)socket:(GCDAsyncSocket *)sock didConnectToHost:(NSString *)host port:(uint16_t)port {
    BOOL state = [self.socket isConnected];
    if (state) {
        [self sendCmd];
    }
}
//断开连接
- (void)socketDidDisconnect:(GCDAsyncSocket *)sock withError:(NSError *)err {
    BOOL state = [_socket isConnected];
    NSLog(@"disconnect,state=%d",state);
    self.socket = nil;
}

发送RTSP命令

- (void)sendCmd
{
    [self doSetup:self.url];
}

- (void)doSetup:(NSString *)url {
    NSMutableString *dataString = [NSMutableString string];
    [dataString appendString:[NSString stringWithFormat:@"SETUP %@ RTSP/1.0\r\n", url]];
    [dataString appendString:@"Content-Length: 0\r\n"];
    [dataString appendFormat:@"CSeq: 0\r\n"];
    [dataString appendString:@"Transport: RTP/AVP/DHTP;unicast\r\n"];
    [dataString appendString:@"\r\n"];
    NSData *data = [dataString dataUsingEncoding:NSUTF8StringEncoding];
    [self.socket writeData:data withTimeout:-1 tag:0];
    [self.socket readDataWithTimeout:-1 tag:0];
}

- (void)doPlay:(NSString *)url {
    NSMutableString *dataString = [NSMutableString string];
    [dataString appendString:[NSString stringWithFormat:@"PLAY %@ RTSP/1.0\r\n", url]];
    [dataString appendString:@"Content-Length: 0\r\n"];
    [dataString appendFormat:@"CSeq: 1\r\n"];
    [dataString appendString:@"\r\n"];
    NSData *data = [dataString dataUsingEncoding:NSUTF8StringEncoding];
    [self.socket writeData:data withTimeout:-1 tag:1];
    [self.socket readDataWithTimeout:-1 tag:1];
}

- (void)doTeardown:(NSString *)url {
    NSMutableString *dataString = [NSMutableString string];
    [dataString appendString:[NSString stringWithFormat:@"TEARDOWN %@ RTSP/1.0\r\n", url]];
    [dataString appendString:@"Content-Length: 0\r\n"];
    [dataString appendString:@"CSeq: 2\r\n"];
    [dataString appendString:@"\r\n"];
    NSData *data = [dataString dataUsingEncoding:NSUTF8StringEncoding];
    [self.socket writeData:data withTimeout:-1 tag:2];
}

读取数据

- (void)socket:(GCDAsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag {
    NSString *dataString = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
    switch (tag) {
        case 0:
            [self doPlay:self.url];
            break;
        case 1:
            [self startCapture];
            break;
        case 200:
            if (!dataString) {
                [self getPayload:data];
            }
            break;
        default:
            break;
    }
    [sock readDataWithTimeout:-1 tag:200];
}
PS:标准的RTSP协议DESCRIBE、OPTIONS、SETUP、PLAY、TEARDOWN等方法一般都需要发送,作者这里为非标准RTSP,只需发送SETUP、PLAY、TEARDOWN。可参考RTSP百科:RTSP

其中readDataWithTimeout表示需要读取发送后返回的数据,-1表示不会使用超时。

以上,则实现了RTSP的通讯,可将编码后的AAC以RTP的形式进行传输,且可以一边发送一边读取。


Demo地址:https://github.com/XuningZhai/TalkDemo
支持G711的Demo地址:https://github.com/XuningZhai/TalkDemo_G711_AAC

你可能感兴趣的:(iOS语音对讲(二)RTSP+RTP协议实时传输)