IT博客汇
  • 首页
  • 精华
  • 技术
  • 设计
  • 资讯
  • 扯淡
  • 权利声明
  • 登录 注册

    WebRTC之二 iOS

    王龙发表于 2016-01-04 07:09:18
    love 0

    WebRTC是Google搞出来的,但很多浏览器并不支持,还有一些移动端的设备也没有支持,所以在这种情况下,要使用WebRTC,需要从官方的代码入手。官方有什么文档是针对这方面的,不过如果不是做平台移植方面的,不建议从源代码开始,因为1,要翻墙,2代码很大,一共有几个G的东西要下载,3,好像还不支持断点续传,所以还是算了吧。

    以iOS为例,建议直接使用CocoaPods上面的东西,名字是libjingle_peerconnection。

    使用这个库里面的东西并不是很麻烦,但要搞清楚里面的逻辑却挺头大的,因为Google提供了一个例子,AppRTCDemo,里面由于使用了很多Google自己的一个架构,把整个Demo搞得剧复杂无比,不过搞清楚原理后,只需要使用几个简单的API就可以实现WebRTC的通信。

    WebRTC要工作起来,需要一下几个方面
    1. 双方建立PeerConnection
    2. 一端创建和发出Offer,另一端接收Offer后响应Answer
    3. PeerConnection的两端交换SDP信息

    建立PeerConnection需要ICE信息,里面提供的网络打洞穿墙等路径数据,

    RTCIceServer *iceServer = [[RTCICEServer alloc] initWithURI:[NSURL URLWithString:YOUR_SERVER]
        username:USERNAME_OR_EMPTY_STRING
        password:PASSWORD_OR_EMPTY_STRING]];
    
    RTCPeerConnectionFactory *pcFactory = [[RTCPeerConnectionFactory alloc] init];
    RTCPeerConnection *peerConnection = [pcFactory peerConnectionWithICEServers:iceServers
                                                    constraints:nil delegate:self];
    

    一端创建Offer

    RTCMediaConstraints *constraints = [RTCMediaConstraints alloc] initWithMandatoryConstraints:
        @[
            [[RTCPair alloc] initWithKey:@"OfferToReceiveAudio" value:@"true"],
            [[RTCPair alloc] initWithKey:@"OfferToReceiveVideo" value:@"true"]
        ]
        optionalConstraints: nil];
    
    [peerConnection createOfferWithConstraints:constraints];
    

    这之后的动作都是通过peerConnection的delegate来完成的
    createOffer之后,会触发didCreateSessionDescription方法,可以在这个方法中来设置localDescription

    - (void)peerConnection:(RTCPeerConnection *)peerConnection
        didCreateSessionDescription:(RTCSessionDescription *)sdp error:(NSError *)error
    {
    	[peerConnection setLocalDescription:sdp]
    }
    

    localDescription设置成功后,会触发didSetSessionDescriptionWithError的方法

    - (void)peerConnection:(RTCPeerConnection *)peerConnection
        didSetSessionDescriptionWithError:(NSError *)error
    {
        if (peerConnection.signalingState == RTCSignalingHaveLocalOffer) {
            // 通过Signaling Channel发送Offer之类的信息
        }
    }
    

    当另一端收到Offer时,要设置remoteDescription

    RTCSessionDescription *remoteDesc = [[RTCSessionDescription alloc] initWithType:@"answer" sdp:sdp];
    [peerConnection setRemoteDescription:remoteDesc];
    

    剩下的一些delegate都是跟ICE的candidate相关的,处理在建立PeerConnection时的P2P连接信息

    - (void)peerConnection:(RTCPeerConnection *)peerConnection
         gotICECandidate:(RTCICECandidate *)candidate
    {
    	// 获得Candidate信息,通过signaling channel发送给另一端
    }
    

    当通过signaling channel收到candidate信息后,添加到peerConnection,让P2P来处理打洞信息

    RTCICECandidate *candidate = [[RTCICECandidate alloc] initWithMid:SDP_MID
                                                          index:SDP_M_LINE_INDEX
                                                            sdp:SDP_CANDIDATE];
    [self.rtcPeerConnection addICECandidate:candidate];
    

    最后一个是媒体数据处理,当peerConnection收到媒体数据时,会触发另一个方法

    - (void)peerConnection:(RTCPeerConnection *)peerConnection addedStream:(RTCMediaStream *)stream
    {
        // Create a new render view with a size of your choice
        RTCEAGLVideoView *renderView = [[RTCEAGLVideoView alloc] initWithFrame:CGRectMake(100, 100)];
        [stream.videoTracks.lastObject addRenderer:self.renderView];
    
        // RTCEAGLVideoView is a subclass of UIView, so renderView
        // can be inserted into your view hierarchy where it suits your application.
    }
    

    总共这些方法就能够简单的让WebRTC工作起来,但还需要很多别的处理,比如iOS的默认speaker播放声音,音视频编解码,chrome用的v8,iOS用的是H264,还有很多问题要等待一一处理



沪ICP备19023445号-2号
友情链接