无法在 webrtc android 客户端中添加远程会话描述
can't add Remote session description in webrtc android client
来自服务器的响应:
{
"rtcid": "wKAm8eeyI-mQ5dsslkhu",
"msgType": "offer",
"senderrtcid": "53wp_LP5CYDie3eIlkhw",
"msgData": {
"type": "offer",
"sdp": "v=0\r\no=- 951920257545056255 2 IN IP4 127.0.0.1\r\ns=-\r\nt=0 0\r\na=group:BUNDLE audio video\r\na=msid-semantic: WMS OfkjcHABgxUkHlk8mfJ8ayYZdCHqdpQGFSTM\r\nm=audio 1 RTP/SAVPF 111 103 104 0 8 106 105 13 126\r\nc=IN IP4 0.0.0.0\r\na=rtcp:1 IN IP4 0.0.0.0\r\na=ice-ufrag:CF4q+RW54gQVPaz0\r\na=ice-pwd:hEIbgX4MME6cPkZKGih7bjQM\r\na=ice-options:google-ice\r\na=fingerprint:sha-256 1E:7F:B8:BA:1A:8D:76:BE:A9:A5:A3:9D:59:3E:CC:BD:1B:90:7B:89:EF:F0:03:B3:9A:CA:9C:07:02:97:53:6F\r\na=setup:actpass\r\na=mid:audio\r\na=extmap:1 urn:ietf:params:rtp-hdrext:ssrc-audio-level\r\na=extmap:3 http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time\r\na=sendrecv\r\na=rtcp-mux\r\na=rtpmap:111 opus/48000/2\r\na=fmtp:111 minptime=10\r\na=rtpmap:103 ISAC/16000\r\na=rtpmap:104 ISAC/32000\r\na=rtpmap:0 PCMU/8000\r\na=rtpmap:8 PCMA/8000\r\na=rtpmap:106 CN/32000\r\na=rtpmap:105 CN/16000\r\na=rtpmap:13 CN/8000\r\na=rtpmap:126 telephone-event/8000\r\na=maxptime:60\r\na=ssrc:777379316 cname:Dl+cb/nGYCzEcTvH\r\na=ssrc:777379316 msid:OfkjcHABgxUkHlk8mfJ8ayYZdCHqdpQGFSTM 0937b040-5691-4ae3-b533-dd9ce82c4393\r\na=ssrc:777379316 mslabel:OfkjcHABgxUkHlk8mfJ8ayYZdCHqdpQGFSTM\r\na=ssrc:777379316 label:0937b040-5691-4ae3-b533-dd9ce82c4393\r\nm=video 1 RTP/SAVPF 100 116 117 96\r\nc=IN IP4 0.0.0.0\r\na=rtcp:1 IN IP4 0.0.0.0\r\na=ice-ufrag:CF4q+RW54gQVPaz0\r\na=ice-pwd:hEIbgX4MME6cPkZKGih7bjQM\r\na=ice-options:google-ice\r\na=fingerprint:sha-256 1E:7F:B8:BA:1A:8D:76:BE:A9:A5:A3:9D:59:3E:CC:BD:1B:90:7B:89:EF:F0:03:B3:9A:CA:9C:07:02:97:53:6F\r\na=setup:actpass\r\na=mid:video\r\na=extmap:2 urn:ietf:params:rtp-hdrext:toffset\r\na=extmap:3 http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time\r\na=sendrecv\r\na=rtcp-mux\r\na=rtpmap:100 VP8/90000\r\na=rtcp-fb:100 ccm fir\r\na=rtcp-fb:100 nack\r\na=rtcp-fb:100 nack pli\r\na=rtcp-fb:100 goog-remb\r\na=rtpmap:116 red/90000\r\na=rtpmap:117 ulpfec/90000\r\na=rtpmap:96 rtx/90000\r\na=fmtp:96 apt=100\r\na=ssrc-group:FID 187598656 415229902\r\na=ssrc:187598656 cname:Dl+cb/nGYCzEcTvH\r\na=ssrc:187598656 msid:OfkjcHABgxUkHlk8mfJ8ayYZdCHqdpQGFSTM 02ab4641-6cd5-43be-b0fe-9952585642bf\r\na=ssrc:187598656 mslabel:OfkjcHABgxUkHlk8mfJ8ayYZdCHqdpQGFSTM\r\na=ssrc:187598656 label:02ab4641-6cd5-43be-b0fe-9952585642bf\r\na=ssrc:415229902 cname:Dl+cb/nGYCzEcTvH\r\na=ssrc:415229902 msid:OfkjcHABgxUkHlk8mfJ8ayYZdCHqdpQGFSTM 02ab4641-6cd5-43be-b0fe-9952585642bf\r\na=ssrc:415229902 mslabel:OfkjcHABgxUkHlk8mfJ8ayYZdCHqdpQGFSTM\r\na=ssrc:415229902 label:02ab4641-6cd5-43be-b0fe-9952585642bf\r\n"
},
"serverTime": 1431342100822
}
日志
libjingle: Ignored line: c=IN IP4 0.0.0.0
libjingle: Error(transport.cc:97): Answerer must use either active or passive value for setup attribute.
libjingle:Error(webrtcsession.cc:272): Failed to set remote answer sdp: Failed to push down transport description: Answerer must use either active or passive value for setup attribute.
**首先我创建报价并添加 localdescription 然后使用 emit 将其发送到服务器并且服务器 return 回调包含远程 sdp **
public void onCreateSuccess(SessionDescription arg0) {
// TODO Auto-generated method stub
try {
if(arg0.type.canonicalForm().equalsIgnoreCase("answer")){
peer.setRemoteDescription(this, sdp);
// mListener.onAddRemoteStream(localMS, 0);
}
else{
payload = new JSONObject();
payload.put("type", arg0.type.canonicalForm());
Log.d("offer", arg0.type.canonicalForm().toString());
payload.put("sdp", arg0.description);
sendMessage("rtcsid", arg0.type.canonicalForm(), payload);
peer.setLocalDescription(this, arg0);
}
} catch (JSONException e) {
e.printStackTrace();
}
IceCandidate:
public void onIceCandidate(IceCandidate arg0) {
// TODO Auto-generated method stub
Log.d("IceCandidate", arg0.toString());
JSONObject payload = new JSONObject();
try {
payload.put("type", arg0.sdpMLineIndex);
Log.d("sdpMLineIndex", Integer.toString(arg0.sdpMLineIndex));
payload.put("id", arg0.sdpMid);
Log.d("sdpMid", arg0.sdpMid.toString());
payload.put("type", arg0.sdp);
Log.d("candidate", arg0.sdp.toString());
sendMessage("easyrtcsid", "candidate", payload);
if(peer.getRemoteDescription()!=null){
IceCandidate candidate = new IceCandidate(
arg0.sdpMid,
arg0.sdpMLineIndex,
arg0.sdp.toString()
);
peer.addIceCandidate(candidate);
}
} catch (JSONException e) {
e.printStackTrace();
}
}
考生日志
{
05-11 14:59:28.495: I/libjingle(14672): Local and Remote descriptions must be applied to get SSL Role of the session.
05-11 14:59:28.495: I/libjingle(14672): Transport: audio, allocating candidates
05-11 14:59:28.495: D/IceGatheringChange(14672): GATHERING
05-11 14:59:28.495: I/libjingle(14672): Transport: audio, allocating candidates
05-11 14:59:28.495: D/IceGatheringChange(14672): GATHERING
05-11 14:59:28.495: I/libjingle(14672): Transport: video, allocating candidates
05-11 14:59:28.495: D/IceGatheringChange(14672): GATHERING
05-11 14:59:28.495: I/libjingle(14672): Transport: video, allocating candidates
05-11 14:59:28.495: D/IceGatheringChange(14672): GATHERING
05-11 14:59:28.495: I/libjingle(14672): Jingle:Net[wlan0:10.0.0.0/8:Unknown]: Allocation Phase=Udp
05-11 14:59:28.505: I/libjingle(14672): Jingle:Port[:1:0::Net[wlan0:10.0.0.0/8:Unknown]]: Port created
05-11 14:59:28.505: I/libjingle(14672): AllocationSequence: UDPPort will be handling the STUN candidate generation.
05-11 14:59:28.505: I/libjingle(14672): Adding allocated port for audio
05-11 14:59:28.505: I/libjingle(14672): Jingle:Port[audio:1:0::Net[wlan0:10.0.0.0/8:Unknown]]: Added port to allocator
05-11 14:59:28.525: D/IceCandidate(14672): audio:0:candidate:1281544012 1 udp 2122260223 10.0.0.112 49865 typ host generation 0
05-11 14:59:28.525: D/sdpMLineIndex(14672): 0
05-11 14:59:28.525: D/sdpMid(14672): audio
05-11 14:59:28.525: D/candidate(14672): candidate:1281544012 1 udp 2122260223 10.0.0.112 49865 typ host generation 0
05-11 14:59:28.525: I/libjingle(14672): Jingle:Net[wlan0:10.0.0.0/8:Unknown]: Allocation Phase=Udp
05-11 14:59:28.525: I/libjingle(14672): Jingle:Port[:1:0::Net[wlan0:10.0.0.0/8:Unknown]]: Port created
05-11 14:59:28.525: I/libjingle(14672): AllocationSequence: UDPPort will be handling the STUN candidate generation.
05-11 14:59:28.525: I/libjingle(14672): Adding allocated port for audio
05-11 14:59:28.525: I/libjingle(14672): Jingle:Port[audio:2:0::Net[wlan0:10.0.0.0/8:Unknown]]: Added port to allocator
05-11 14:59:28.555: D/IceCandidate(14672): audio:0:candidate:1281544012 2 udp 2122260222 10.0.0.112 36221 typ host generation 0
05-11 14:59:28.555: D/sdpMLineIndex(14672): 0
05-11 14:59:28.555: D/sdpMid(14672): audio
05-11 14:59:28.555: D/candidate(14672): candidate:1281544012 2 udp 2122260222 10.0.0.112 36221 typ host generation 0
05-11 14:59:28.555: I/libjingle(14672): Jingle:Net[wlan0:10.0.0.0/8:Unknown]: Allocation Phase=Udp
05-11 14:59:28.555: I/libjingle(14672): Jingle:Port[:1:0::Net[wlan0:10.0.0.0/8:Unknown]]: Port created
05-11 14:59:28.555: I/libjingle(14672): AllocationSequence: UDPPort will be handling the STUN candidate generation.
05-11 14:59:28.555: I/libjingle(14672): Adding allocated port for video
05-11 14:59:28.555: I/libjingle(14672): Jingle:Port[video:1:0::Net[wlan0:10.0.0.0/8:Unknown]]: Added port to allocator
05-11 14:59:28.565: D/IceCandidate(14672): video:1:candidate:1281544012 1 udp 2122260223 10.0.0.112 57380 typ host generation 0
05-11 14:59:28.565: D/sdpMLineIndex(14672): 1
05-11 14:59:28.565: D/sdpMid(14672): video
05-11 14:59:28.565: D/candidate(14672): candidate:1281544012 1 udp 2122260223 10.0.0.112 57380 typ host generation 0
05-11 14:59:28.575: I/libjingle(14672): Jingle:Net[wlan0:10.0.0.0/8:Unknown]: Allocation Phase=Udp
05-11 14:59:28.575: I/libjingle(14672): Jingle:Port[:1:0::Net[wlan0:10.0.0.0/8:Unknown]]: Port created
05-11 14:59:28.575: I/libjingle(14672): AllocationSequence: UDPPort will be handling the STUN candidate generation.
05-11 14:59:28.575: I/libjingle(14672): Adding allocated port for video
05-11 14:59:28.575: I/libjingle(14672): Jingle:Port[video:2:0::Net[wlan0:10.0.0.0/8:Unknown]]: Added port to allocator
05-11 14:59:28.605: D/IceCandidate(14672): video:1:candidate:1281544012 2 udp 2122260222 10.0.0.112 48445 typ host generation 0
05-11 14:59:28.605: D/sdpMLineIndex(14672): 1
05-11 14:59:28.605: D/sdpMid(14672): video
05-11 14:59:28.605: D/candidate(14672): candidate:1281544012 2 udp 2122260222 10.0.0.112 48445 typ host generation 0
05-11 14:59:28.625: W/libjingle(14672): Warning(thread.cc:320): Waiting for the thread to join, but blocking calls have been disallowed
05-11 14:59:28.625: W/libjingle(14672): Warning(thread.cc:320): Waiting for the thread to join, but blocking calls have been disallowed
05-11 14:59:28.625: W/libjingle(14672): Warning(thread.cc:320): Waiting for the thread to join, but blocking calls have been disallowed
05-11 14:59:28.625: W/libjingle(14672): Warning(thread.cc:320): Waiting for the thread to join, but blocking calls have been disallowed
05-11 14:59:28.625: W/libjingle(14672): Warning(thread.cc:320): Waiting for the thread to join, but blocking calls have been disallowed
05-11 14:59:28.625: W/libjingle(14672): Warning(thread.cc:320): Waiting for the thread to join, but blocking calls have been disallowed
05-11 14:59:28.625: W/libjingle(14672): Warning(thread.cc:320): Waiting for the thread to join, but blocking calls have been disallowed
05-11 14:59:28.625: W/libjingle(14672): Warning(thread.cc:320): Waiting for the thread to join, but blocking calls have been disallowed
05-11 14:59:28.625: W/libjingle(14672): Warning(thread.cc:320): Waiting for the thread to join, but blocking calls have been disallowed
05-11 14:59:28.625: W/libjingle(14672): Warning(thread.cc:320): Waiting for the thread to join, but blocking calls have been disallowed
05-11 14:59:28.625: I/libjingle(14672): Jingle:Net[wlan0:10.0.0.0/8:Unknown]: Allocation Phase=Relay
05-11 14:59:28.625: I/libjingle(14672): Jingle:Net[wlan0:10.0.0.0/8:Unknown]: Allocation Phase=Relay
05-11 14:59:28.635: W/libjingle(14672): Warning(thread.cc:320): Waiting for the thread to join, but blocking calls have been disallowed
05-11 14:59:28.635: I/libjingle(14672): Jingle:Net[wlan0:10.0.0.0/8:Unknown]: Allocation Phase=Relay
05-11 14:59:28.635: W/libjingle(14672): Warning(thread.cc:320): Waiting for the thread to join, but blocking calls have been disallowed
05-11 14:59:28.635: D/IceCandidate(14672): audio:0:candidate:2940422560 1 udp 1686052607 197.44.239.36 49865 typ srflx raddr 10.0.0.112 rport 49865 generation 0
05-11 14:59:28.635: D/sdpMLineIndex(14672): 0
05-11 14:59:28.635: D/sdpMid(14672): audio
05-11 14:59:28.635: D/candidate(14672): candidate:2940422560 1 udp 1686052607 197.44.239.36 49865 typ srflx raddr 10.0.0.112 rport 49865 generation 0
05-11 14:59:28.645: D/IceCandidate(14672): audio:0:candidate:2940422560 2 udp 1686052606 197.44.239.36 36221 typ srflx raddr 10.0.0.112 rport 36221 generation 0
05-11 14:59:28.645: D/sdpMLineIndex(14672): 0
05-11 14:59:28.645: D/sdpMid(14672): audio
05-11 14:59:28.645: D/candidate(14672): candidate:2940422560 2 udp 1686052606 197.44.239.36 36221 typ srflx raddr 10.0.0.112 rport 36221 generation 0
05-11 14:59:28.665: I/libjingle(14672): Jingle:Net[wlan0:10.0.0.0/8:Unknown]: Allocation Phase=Relay
05-11 14:59:28.675: D/IceCandidate(14672): video:1:candidate:2940422560 1 udp 1686052607 197.44.239.36 57380 typ srflx raddr 10.0.0.112 rport 57380 generation 0
05-11 14:59:28.675: D/sdpMLineIndex(14672): 1
05-11 14:59:28.675: D/sdpMid(14672): video
05-11 14:59:28.675: D/candidate(14672): candidate:2940422560 1 udp 1686052607 197.44.239.36 57380 typ srflx raddr 10.0.0.112 rport 57380 generation 0
05-11 14:59:28.685: I/libjingle(14672): Jingle:Net[wlan0:10.0.0.0/8:Unknown]: Allocation Phase=Tcp
05-11 14:59:28.685: I/libjingle(14672): Jingle:Port[:1:0:local:Net[wlan0:10.0.0.0/8:Unknown]]: Port created
05-11 14:59:28.685: I/libjingle(14672): Adding allocated port for audio
05-11 14:59:28.685: I/libjingle(14672): Jingle:Port[audio:1:0:local:Net[wlan0:10.0.0.0/8:Unknown]]: Added port to allocator
05-11 14:59:28.685: I/libjingle(14672): Jingle:Net[wlan0:10.0.0.0/8:Unknown]: Allocation Phase=Tcp
05-11 14:59:28.685: D/IceCandidate(14672): audio:0:candidate:48313276 1 tcp 1518280447 10.0.0.112 40627 typ host tcptype passive generation 0
05-11 14:59:28.685: D/sdpMLineIndex(14672): 0
05-11 14:59:28.685: D/sdpMid(14672): audio
05-11 14:59:28.685: D/candidate(14672): candidate:48313276 1 tcp 1518280447 10.0.0.112 40627 typ host tcptype passive generation 0
05-11 14:59:28.685: I/libjingle(14672): Jingle:Port[:1:0:local:Net[wlan0:10.0.0.0/8:Unknown]]: Port created
05-11 14:59:28.685: I/libjingle(14672): Adding allocated port for audio
05-11 14:59:28.685: I/libjingle(14672): Jingle:Port[audio:2:0:local:Net[wlan0:10.0.0.0/8:Unknown]]: Added port to allocator
05-11 14:59:28.685: I/libjingle(14672): Jingle:Net[wlan0:10.0.0.0/8:Unknown]: Allocation Phase=Tcp
05-11 14:59:28.685: D/IceCandidate(14672): audio:0:candidate:48313276 2 tcp 1518280446 10.0.0.112 48390 typ host tcptype passive generation 0
05-11 14:59:28.685: D/sdpMLineIndex(14672): 0
05-11 14:59:28.685: D/sdpMid(14672): audio
05-11 14:59:28.685: D/candidate(14672): candidate:48313276 2 tcp 1518280446 10.0.0.112 48390 typ host tcptype passive generation 0
05-11 14:59:28.695: I/libjingle(14672): Jingle:Port[:1:0:local:Net[wlan0:10.0.0.0/8:Unknown]]: Port created
05-11 14:59:28.695: I/libjingle(14672): Adding allocated port for video
05-11 14:59:28.695: I/libjingle(14672): Jingle:Port[video:1:0:local:Net[wlan0:10.0.0.0/8:Unknown]]: Added port to allocator
05-11 14:59:28.695: D/IceCandidate(14672): video:1:candidate:48313276 1 tcp 1518280447 10.0.0.112 60960 typ host tcptype passive generation 0
05-11 14:59:28.695: D/sdpMLineIndex(14672): 1
05-11 14:59:28.695: D/sdpMid(14672): video
05-11 14:59:28.695: D/candidate(14672): candidate:48313276 1 tcp 1518280447 10.0.0.112 60960 typ host tcptype passive generation 0
05-11 14:59:28.705: D/IceCandidate(14672): video:1:candidate:2940422560 2 udp 1686052606 197.44.239.36 48445 typ srflx raddr 10.0.0.112 rport 48445 generation 0
05-11 14:59:28.705: D/sdpMLineIndex(14672): 1
05-11 14:59:28.715: D/sdpMid(14672): video
05-11 14:59:28.715: D/candidate(14672): candidate:2940422560 2 udp 1686052606 197.44.239.36 48445 typ srflx raddr 10.0.0.112 rport 48445 generation 0
05-11 14:59:28.725: I/libjingle(14672): Jingle:Net[wlan0:10.0.0.0/8:Unknown]: Allocation Phase=Tcp
05-11 14:59:28.725: I/libjingle(14672): Jingle:Port[:1:0:local:Net[wlan0:10.0.0.0/8:Unknown]]: Port created
05-11 14:59:28.725: I/libjingle(14672): Adding allocated port for video
05-11 14:59:28.725: I/libjingle(14672): Jingle:Port[video:2:0:local:Net[wlan0:10.0.0.0/8:Unknown]]: Added port to allocator
05-11 14:59:28.725: D/IceCandidate(14672): video:1:candidate:48313276 2 tcp 1518280446 10.0.0.112 59723 typ host tcptype passive generation 0
05-11 14:59:28.725: D/sdpMLineIndex(14672): 1
05-11 14:59:28.725: D/sdpMid(14672): video
05-11 14:59:28.725: D/candidate(14672): candidate:48313276 2 tcp 1518280446 10.0.0.112 59723 typ host tcptype passive generation 0
05-11 14:59:28.735: I/libjingle(14672): Jingle:Net[wlan0:10.0.0.0/8:Unknown]: Allocation Phase=SslTcp
05-11 14:59:28.735: I/libjingle(14672): Jingle:Net[wlan0:10.0.0.0/8:Unknown]: Allocation Phase=SslTcp
05-11 14:59:28.735: I/libjingle(14672): All candidates gathered for audio:2:0
05-11 14:59:28.735: I/libjingle(14672): Transport: audio, component 2 allocation complete
05-11 14:59:28.745: I/libjingle(14672): Jingle:Net[wlan0:10.0.0.0/8:Unknown]: Allocation Phase=SslTcp
05-11 14:59:28.745: I/libjingle(14672): All candidates gathered for video:1:0
05-11 14:59:28.745: I/libjingle(14672): Transport: video, component 1 allocation complete
05-11 14:59:28.775: I/libjingle(14672): Jingle:Net[wlan0:10.0.0.0/8:Unknown]: Allocation Phase=SslTcp
05-11 14:59:28.775: I/libjingle(14672): All candidates gathered for video:2:0
05-11 14:59:28.775: I/libjingle(14672): Transport: video, component 2 allocation complete
05-11 14:59:28.775: I/libjingle(14672): Transport: video allocation complete
05-11 14:59:28.775: I/libjingle(14672): Candidate allocation not done for audio
05-11 14:59:28.795: I/libjingle(14672): All candidates gathered for audio:1:0
05-11 14:59:28.795: I/libjingle(14672): Transport: audio, component 1 allocation complete
05-11 14:59:28.795: I/libjingle(14672): Transport: audio allocation complete
05-11 14:59:28.795: I/libjingle(14672): Candidate gathering is complete.
05-11 14:59:28.795: D/IceGatheringChange(14672): COMPLETE
}
MediaConstraints
pcConstraints.mandatory.add(new MediaConstraints.KeyValuePair("OfferToReceiveAudio", "true"));
pcConstraints.mandatory.add(new MediaConstraints.KeyValuePair("OfferToReceiveVideo", "true"));
pcConstraints.optional.add(new MediaConstraints.KeyValuePair("DtlsSrtpKeyAgreement", "true"));
请记住,这是我自己的简陋代码,它可能并不完美,并且可能很难将所有内容复制到您自己的项目中。它适用于我,但这并不意味着它适用于其他人。
建立通话的过程如下(注意,这不是一成不变的):
有 2 台设备,A 和 B,都连接到某种信令服务器,以允许它们交换 SDP 和 ICE 候选者,以及互相邀请通话等...
A 开始通话,第一步可能是向 B 发送邀请。此时我还想使用以下代码初始化 peerconnection 对象:
//initialize the peerconnection factory
PeerConnectionFactory.initializeAndroidGlobals(MainActivity.context, true, true, true, parent.tex_remote);
factory = new PeerConnectionFactory();
//ice server initialization
ArrayList<PeerConnection.IceServer> iceServers = new ArrayList<>();
iceServers.add(new PeerConnection.IceServer("stun:stun.xxx.xxx:xxx"));
iceServers.add(new PeerConnection.IceServer("turn:turn.xxx.xxx:xxx", "xxx", "xxx"));
//create a new contraints object to configure the connection
MediaConstraints connectionConstraints = new MediaConstraints();
connectionConstraints.mandatory.add(new MediaConstraints.KeyValuePair("offerToReceiveAudio", "true"));
connectionConstraints.mandatory.add(new MediaConstraints.KeyValuePair("offerToReceiveVideo", "true"));
connectionConstraints.optional.add(new MediaConstraints.KeyValuePair("DtlsSrtpKeyAgreement", "true"));
//create a new peerconnection object
peerConnection = factory.createPeerConnection(iceServers, connectionConstraints, observer);
完成后,您有了 peerconnection 对象,您可以使用以下代码初始化本地媒体流:
//create a new audio and video source, this is the stream that will be sent to the remote
VideoSource videoSource = factory.createVideoSource(VideoCapturer.create("Camera 1, Facing front, Orientation 270"), new MediaConstraints());
AudioSource audioSource = factory.createAudioSource(new MediaConstraints());
//create a new audio and video track
VideoTrack videoTrack = factory.createVideoTrack("ARDAMSv0", videoSource);
AudioTrack audioTrack = factory.createAudioTrack("ARDAMSa0", audioSource);
//create a new media stream, this holds all local streams and their tracks
MediaStream lms = factory.createLocalMediaStream("ARDAMS");
//create a new video renderer and add it to the video track
VideoRenderer renderer = new VideoRenderer(parent);
videoTrack.addRenderer(renderer);
//add the video track to the stream
lms.addTrack(videoTrack);
//add the audio track to the stream
lms.addTrack(audioTrack);
//add the stream to the connection
peerConnection.addStream(lms);
同时,B 会收到来自信令服务器的呼叫邀请,并且必须向用户呈现某种来电视图。当用户决定接听电话时,B 向 A 发送一个接受信号。
当 A 收到此接受信号时,就该开始自己设置呼叫了。在 A 上调用 createOffer(),如果成功,库将调用 onCreateSuccess():
peerConnection.createOffer(observer, new MediaConstraints());
在onCreateSuccess()中,可以用新建的SDP调用setLocalDescription()。您还必须将此 SDP 发送给 B,因此您不妨在此处执行此操作:
peerConnection.setLocalDescription(this, sessionDescription);
//send this SDP to your remote peer
B 现在将收到 A 的报价,您必须通过调用 setRemoteDescription() 进行设置:
peerConnection.setRemoteDescription(observer, sdp);
如果成功,库将调用 onSetSuccess()。在 onSetSuccess() 中你可以调用 createAnswer():
peerConnection.createAnswer(observer, constraints);
因为您现在确定已设置初始报价 SDP。该库将为您再次调用 onCreateSuccess() 。与 A 的报价相同的事情现在发生在 B 的回答上。它会将答案设置为本地 SDP,并将其发送给 A:
peerConnection.setLocalDescription(this, sessionDescription);
//send this SDP to your remote peer
当所有这些都完成后,交换 SDP 就完成了。该库还会多次调用 onIceCandidate()。您只需将此 ICE 候选人发送给其他同行并在收到来自其他同行的 ICE 候选人时调用 peerConnection.addIceCandidate()。
pcConstraints.optional.add(new KeyValuePair("DtlsSrtpKeyAgreement", "true"));
pcConstraints.optional.add(new KeyValuePair("RtpDataChannels", "true"));
来自服务器的响应:
{
"rtcid": "wKAm8eeyI-mQ5dsslkhu",
"msgType": "offer",
"senderrtcid": "53wp_LP5CYDie3eIlkhw",
"msgData": {
"type": "offer",
"sdp": "v=0\r\no=- 951920257545056255 2 IN IP4 127.0.0.1\r\ns=-\r\nt=0 0\r\na=group:BUNDLE audio video\r\na=msid-semantic: WMS OfkjcHABgxUkHlk8mfJ8ayYZdCHqdpQGFSTM\r\nm=audio 1 RTP/SAVPF 111 103 104 0 8 106 105 13 126\r\nc=IN IP4 0.0.0.0\r\na=rtcp:1 IN IP4 0.0.0.0\r\na=ice-ufrag:CF4q+RW54gQVPaz0\r\na=ice-pwd:hEIbgX4MME6cPkZKGih7bjQM\r\na=ice-options:google-ice\r\na=fingerprint:sha-256 1E:7F:B8:BA:1A:8D:76:BE:A9:A5:A3:9D:59:3E:CC:BD:1B:90:7B:89:EF:F0:03:B3:9A:CA:9C:07:02:97:53:6F\r\na=setup:actpass\r\na=mid:audio\r\na=extmap:1 urn:ietf:params:rtp-hdrext:ssrc-audio-level\r\na=extmap:3 http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time\r\na=sendrecv\r\na=rtcp-mux\r\na=rtpmap:111 opus/48000/2\r\na=fmtp:111 minptime=10\r\na=rtpmap:103 ISAC/16000\r\na=rtpmap:104 ISAC/32000\r\na=rtpmap:0 PCMU/8000\r\na=rtpmap:8 PCMA/8000\r\na=rtpmap:106 CN/32000\r\na=rtpmap:105 CN/16000\r\na=rtpmap:13 CN/8000\r\na=rtpmap:126 telephone-event/8000\r\na=maxptime:60\r\na=ssrc:777379316 cname:Dl+cb/nGYCzEcTvH\r\na=ssrc:777379316 msid:OfkjcHABgxUkHlk8mfJ8ayYZdCHqdpQGFSTM 0937b040-5691-4ae3-b533-dd9ce82c4393\r\na=ssrc:777379316 mslabel:OfkjcHABgxUkHlk8mfJ8ayYZdCHqdpQGFSTM\r\na=ssrc:777379316 label:0937b040-5691-4ae3-b533-dd9ce82c4393\r\nm=video 1 RTP/SAVPF 100 116 117 96\r\nc=IN IP4 0.0.0.0\r\na=rtcp:1 IN IP4 0.0.0.0\r\na=ice-ufrag:CF4q+RW54gQVPaz0\r\na=ice-pwd:hEIbgX4MME6cPkZKGih7bjQM\r\na=ice-options:google-ice\r\na=fingerprint:sha-256 1E:7F:B8:BA:1A:8D:76:BE:A9:A5:A3:9D:59:3E:CC:BD:1B:90:7B:89:EF:F0:03:B3:9A:CA:9C:07:02:97:53:6F\r\na=setup:actpass\r\na=mid:video\r\na=extmap:2 urn:ietf:params:rtp-hdrext:toffset\r\na=extmap:3 http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time\r\na=sendrecv\r\na=rtcp-mux\r\na=rtpmap:100 VP8/90000\r\na=rtcp-fb:100 ccm fir\r\na=rtcp-fb:100 nack\r\na=rtcp-fb:100 nack pli\r\na=rtcp-fb:100 goog-remb\r\na=rtpmap:116 red/90000\r\na=rtpmap:117 ulpfec/90000\r\na=rtpmap:96 rtx/90000\r\na=fmtp:96 apt=100\r\na=ssrc-group:FID 187598656 415229902\r\na=ssrc:187598656 cname:Dl+cb/nGYCzEcTvH\r\na=ssrc:187598656 msid:OfkjcHABgxUkHlk8mfJ8ayYZdCHqdpQGFSTM 02ab4641-6cd5-43be-b0fe-9952585642bf\r\na=ssrc:187598656 mslabel:OfkjcHABgxUkHlk8mfJ8ayYZdCHqdpQGFSTM\r\na=ssrc:187598656 label:02ab4641-6cd5-43be-b0fe-9952585642bf\r\na=ssrc:415229902 cname:Dl+cb/nGYCzEcTvH\r\na=ssrc:415229902 msid:OfkjcHABgxUkHlk8mfJ8ayYZdCHqdpQGFSTM 02ab4641-6cd5-43be-b0fe-9952585642bf\r\na=ssrc:415229902 mslabel:OfkjcHABgxUkHlk8mfJ8ayYZdCHqdpQGFSTM\r\na=ssrc:415229902 label:02ab4641-6cd5-43be-b0fe-9952585642bf\r\n"
},
"serverTime": 1431342100822
}
日志
libjingle: Ignored line: c=IN IP4 0.0.0.0
libjingle: Error(transport.cc:97): Answerer must use either active or passive value for setup attribute.
libjingle:Error(webrtcsession.cc:272): Failed to set remote answer sdp: Failed to push down transport description: Answerer must use either active or passive value for setup attribute.
**首先我创建报价并添加 localdescription 然后使用 emit 将其发送到服务器并且服务器 return 回调包含远程 sdp **
public void onCreateSuccess(SessionDescription arg0) {
// TODO Auto-generated method stub
try {
if(arg0.type.canonicalForm().equalsIgnoreCase("answer")){
peer.setRemoteDescription(this, sdp);
// mListener.onAddRemoteStream(localMS, 0);
}
else{
payload = new JSONObject();
payload.put("type", arg0.type.canonicalForm());
Log.d("offer", arg0.type.canonicalForm().toString());
payload.put("sdp", arg0.description);
sendMessage("rtcsid", arg0.type.canonicalForm(), payload);
peer.setLocalDescription(this, arg0);
}
} catch (JSONException e) {
e.printStackTrace();
}
IceCandidate:
public void onIceCandidate(IceCandidate arg0) {
// TODO Auto-generated method stub
Log.d("IceCandidate", arg0.toString());
JSONObject payload = new JSONObject();
try {
payload.put("type", arg0.sdpMLineIndex);
Log.d("sdpMLineIndex", Integer.toString(arg0.sdpMLineIndex));
payload.put("id", arg0.sdpMid);
Log.d("sdpMid", arg0.sdpMid.toString());
payload.put("type", arg0.sdp);
Log.d("candidate", arg0.sdp.toString());
sendMessage("easyrtcsid", "candidate", payload);
if(peer.getRemoteDescription()!=null){
IceCandidate candidate = new IceCandidate(
arg0.sdpMid,
arg0.sdpMLineIndex,
arg0.sdp.toString()
);
peer.addIceCandidate(candidate);
}
} catch (JSONException e) {
e.printStackTrace();
}
}
考生日志
{
05-11 14:59:28.495: I/libjingle(14672): Local and Remote descriptions must be applied to get SSL Role of the session.
05-11 14:59:28.495: I/libjingle(14672): Transport: audio, allocating candidates
05-11 14:59:28.495: D/IceGatheringChange(14672): GATHERING
05-11 14:59:28.495: I/libjingle(14672): Transport: audio, allocating candidates
05-11 14:59:28.495: D/IceGatheringChange(14672): GATHERING
05-11 14:59:28.495: I/libjingle(14672): Transport: video, allocating candidates
05-11 14:59:28.495: D/IceGatheringChange(14672): GATHERING
05-11 14:59:28.495: I/libjingle(14672): Transport: video, allocating candidates
05-11 14:59:28.495: D/IceGatheringChange(14672): GATHERING
05-11 14:59:28.495: I/libjingle(14672): Jingle:Net[wlan0:10.0.0.0/8:Unknown]: Allocation Phase=Udp
05-11 14:59:28.505: I/libjingle(14672): Jingle:Port[:1:0::Net[wlan0:10.0.0.0/8:Unknown]]: Port created
05-11 14:59:28.505: I/libjingle(14672): AllocationSequence: UDPPort will be handling the STUN candidate generation.
05-11 14:59:28.505: I/libjingle(14672): Adding allocated port for audio
05-11 14:59:28.505: I/libjingle(14672): Jingle:Port[audio:1:0::Net[wlan0:10.0.0.0/8:Unknown]]: Added port to allocator
05-11 14:59:28.525: D/IceCandidate(14672): audio:0:candidate:1281544012 1 udp 2122260223 10.0.0.112 49865 typ host generation 0
05-11 14:59:28.525: D/sdpMLineIndex(14672): 0
05-11 14:59:28.525: D/sdpMid(14672): audio
05-11 14:59:28.525: D/candidate(14672): candidate:1281544012 1 udp 2122260223 10.0.0.112 49865 typ host generation 0
05-11 14:59:28.525: I/libjingle(14672): Jingle:Net[wlan0:10.0.0.0/8:Unknown]: Allocation Phase=Udp
05-11 14:59:28.525: I/libjingle(14672): Jingle:Port[:1:0::Net[wlan0:10.0.0.0/8:Unknown]]: Port created
05-11 14:59:28.525: I/libjingle(14672): AllocationSequence: UDPPort will be handling the STUN candidate generation.
05-11 14:59:28.525: I/libjingle(14672): Adding allocated port for audio
05-11 14:59:28.525: I/libjingle(14672): Jingle:Port[audio:2:0::Net[wlan0:10.0.0.0/8:Unknown]]: Added port to allocator
05-11 14:59:28.555: D/IceCandidate(14672): audio:0:candidate:1281544012 2 udp 2122260222 10.0.0.112 36221 typ host generation 0
05-11 14:59:28.555: D/sdpMLineIndex(14672): 0
05-11 14:59:28.555: D/sdpMid(14672): audio
05-11 14:59:28.555: D/candidate(14672): candidate:1281544012 2 udp 2122260222 10.0.0.112 36221 typ host generation 0
05-11 14:59:28.555: I/libjingle(14672): Jingle:Net[wlan0:10.0.0.0/8:Unknown]: Allocation Phase=Udp
05-11 14:59:28.555: I/libjingle(14672): Jingle:Port[:1:0::Net[wlan0:10.0.0.0/8:Unknown]]: Port created
05-11 14:59:28.555: I/libjingle(14672): AllocationSequence: UDPPort will be handling the STUN candidate generation.
05-11 14:59:28.555: I/libjingle(14672): Adding allocated port for video
05-11 14:59:28.555: I/libjingle(14672): Jingle:Port[video:1:0::Net[wlan0:10.0.0.0/8:Unknown]]: Added port to allocator
05-11 14:59:28.565: D/IceCandidate(14672): video:1:candidate:1281544012 1 udp 2122260223 10.0.0.112 57380 typ host generation 0
05-11 14:59:28.565: D/sdpMLineIndex(14672): 1
05-11 14:59:28.565: D/sdpMid(14672): video
05-11 14:59:28.565: D/candidate(14672): candidate:1281544012 1 udp 2122260223 10.0.0.112 57380 typ host generation 0
05-11 14:59:28.575: I/libjingle(14672): Jingle:Net[wlan0:10.0.0.0/8:Unknown]: Allocation Phase=Udp
05-11 14:59:28.575: I/libjingle(14672): Jingle:Port[:1:0::Net[wlan0:10.0.0.0/8:Unknown]]: Port created
05-11 14:59:28.575: I/libjingle(14672): AllocationSequence: UDPPort will be handling the STUN candidate generation.
05-11 14:59:28.575: I/libjingle(14672): Adding allocated port for video
05-11 14:59:28.575: I/libjingle(14672): Jingle:Port[video:2:0::Net[wlan0:10.0.0.0/8:Unknown]]: Added port to allocator
05-11 14:59:28.605: D/IceCandidate(14672): video:1:candidate:1281544012 2 udp 2122260222 10.0.0.112 48445 typ host generation 0
05-11 14:59:28.605: D/sdpMLineIndex(14672): 1
05-11 14:59:28.605: D/sdpMid(14672): video
05-11 14:59:28.605: D/candidate(14672): candidate:1281544012 2 udp 2122260222 10.0.0.112 48445 typ host generation 0
05-11 14:59:28.625: W/libjingle(14672): Warning(thread.cc:320): Waiting for the thread to join, but blocking calls have been disallowed
05-11 14:59:28.625: W/libjingle(14672): Warning(thread.cc:320): Waiting for the thread to join, but blocking calls have been disallowed
05-11 14:59:28.625: W/libjingle(14672): Warning(thread.cc:320): Waiting for the thread to join, but blocking calls have been disallowed
05-11 14:59:28.625: W/libjingle(14672): Warning(thread.cc:320): Waiting for the thread to join, but blocking calls have been disallowed
05-11 14:59:28.625: W/libjingle(14672): Warning(thread.cc:320): Waiting for the thread to join, but blocking calls have been disallowed
05-11 14:59:28.625: W/libjingle(14672): Warning(thread.cc:320): Waiting for the thread to join, but blocking calls have been disallowed
05-11 14:59:28.625: W/libjingle(14672): Warning(thread.cc:320): Waiting for the thread to join, but blocking calls have been disallowed
05-11 14:59:28.625: W/libjingle(14672): Warning(thread.cc:320): Waiting for the thread to join, but blocking calls have been disallowed
05-11 14:59:28.625: W/libjingle(14672): Warning(thread.cc:320): Waiting for the thread to join, but blocking calls have been disallowed
05-11 14:59:28.625: W/libjingle(14672): Warning(thread.cc:320): Waiting for the thread to join, but blocking calls have been disallowed
05-11 14:59:28.625: I/libjingle(14672): Jingle:Net[wlan0:10.0.0.0/8:Unknown]: Allocation Phase=Relay
05-11 14:59:28.625: I/libjingle(14672): Jingle:Net[wlan0:10.0.0.0/8:Unknown]: Allocation Phase=Relay
05-11 14:59:28.635: W/libjingle(14672): Warning(thread.cc:320): Waiting for the thread to join, but blocking calls have been disallowed
05-11 14:59:28.635: I/libjingle(14672): Jingle:Net[wlan0:10.0.0.0/8:Unknown]: Allocation Phase=Relay
05-11 14:59:28.635: W/libjingle(14672): Warning(thread.cc:320): Waiting for the thread to join, but blocking calls have been disallowed
05-11 14:59:28.635: D/IceCandidate(14672): audio:0:candidate:2940422560 1 udp 1686052607 197.44.239.36 49865 typ srflx raddr 10.0.0.112 rport 49865 generation 0
05-11 14:59:28.635: D/sdpMLineIndex(14672): 0
05-11 14:59:28.635: D/sdpMid(14672): audio
05-11 14:59:28.635: D/candidate(14672): candidate:2940422560 1 udp 1686052607 197.44.239.36 49865 typ srflx raddr 10.0.0.112 rport 49865 generation 0
05-11 14:59:28.645: D/IceCandidate(14672): audio:0:candidate:2940422560 2 udp 1686052606 197.44.239.36 36221 typ srflx raddr 10.0.0.112 rport 36221 generation 0
05-11 14:59:28.645: D/sdpMLineIndex(14672): 0
05-11 14:59:28.645: D/sdpMid(14672): audio
05-11 14:59:28.645: D/candidate(14672): candidate:2940422560 2 udp 1686052606 197.44.239.36 36221 typ srflx raddr 10.0.0.112 rport 36221 generation 0
05-11 14:59:28.665: I/libjingle(14672): Jingle:Net[wlan0:10.0.0.0/8:Unknown]: Allocation Phase=Relay
05-11 14:59:28.675: D/IceCandidate(14672): video:1:candidate:2940422560 1 udp 1686052607 197.44.239.36 57380 typ srflx raddr 10.0.0.112 rport 57380 generation 0
05-11 14:59:28.675: D/sdpMLineIndex(14672): 1
05-11 14:59:28.675: D/sdpMid(14672): video
05-11 14:59:28.675: D/candidate(14672): candidate:2940422560 1 udp 1686052607 197.44.239.36 57380 typ srflx raddr 10.0.0.112 rport 57380 generation 0
05-11 14:59:28.685: I/libjingle(14672): Jingle:Net[wlan0:10.0.0.0/8:Unknown]: Allocation Phase=Tcp
05-11 14:59:28.685: I/libjingle(14672): Jingle:Port[:1:0:local:Net[wlan0:10.0.0.0/8:Unknown]]: Port created
05-11 14:59:28.685: I/libjingle(14672): Adding allocated port for audio
05-11 14:59:28.685: I/libjingle(14672): Jingle:Port[audio:1:0:local:Net[wlan0:10.0.0.0/8:Unknown]]: Added port to allocator
05-11 14:59:28.685: I/libjingle(14672): Jingle:Net[wlan0:10.0.0.0/8:Unknown]: Allocation Phase=Tcp
05-11 14:59:28.685: D/IceCandidate(14672): audio:0:candidate:48313276 1 tcp 1518280447 10.0.0.112 40627 typ host tcptype passive generation 0
05-11 14:59:28.685: D/sdpMLineIndex(14672): 0
05-11 14:59:28.685: D/sdpMid(14672): audio
05-11 14:59:28.685: D/candidate(14672): candidate:48313276 1 tcp 1518280447 10.0.0.112 40627 typ host tcptype passive generation 0
05-11 14:59:28.685: I/libjingle(14672): Jingle:Port[:1:0:local:Net[wlan0:10.0.0.0/8:Unknown]]: Port created
05-11 14:59:28.685: I/libjingle(14672): Adding allocated port for audio
05-11 14:59:28.685: I/libjingle(14672): Jingle:Port[audio:2:0:local:Net[wlan0:10.0.0.0/8:Unknown]]: Added port to allocator
05-11 14:59:28.685: I/libjingle(14672): Jingle:Net[wlan0:10.0.0.0/8:Unknown]: Allocation Phase=Tcp
05-11 14:59:28.685: D/IceCandidate(14672): audio:0:candidate:48313276 2 tcp 1518280446 10.0.0.112 48390 typ host tcptype passive generation 0
05-11 14:59:28.685: D/sdpMLineIndex(14672): 0
05-11 14:59:28.685: D/sdpMid(14672): audio
05-11 14:59:28.685: D/candidate(14672): candidate:48313276 2 tcp 1518280446 10.0.0.112 48390 typ host tcptype passive generation 0
05-11 14:59:28.695: I/libjingle(14672): Jingle:Port[:1:0:local:Net[wlan0:10.0.0.0/8:Unknown]]: Port created
05-11 14:59:28.695: I/libjingle(14672): Adding allocated port for video
05-11 14:59:28.695: I/libjingle(14672): Jingle:Port[video:1:0:local:Net[wlan0:10.0.0.0/8:Unknown]]: Added port to allocator
05-11 14:59:28.695: D/IceCandidate(14672): video:1:candidate:48313276 1 tcp 1518280447 10.0.0.112 60960 typ host tcptype passive generation 0
05-11 14:59:28.695: D/sdpMLineIndex(14672): 1
05-11 14:59:28.695: D/sdpMid(14672): video
05-11 14:59:28.695: D/candidate(14672): candidate:48313276 1 tcp 1518280447 10.0.0.112 60960 typ host tcptype passive generation 0
05-11 14:59:28.705: D/IceCandidate(14672): video:1:candidate:2940422560 2 udp 1686052606 197.44.239.36 48445 typ srflx raddr 10.0.0.112 rport 48445 generation 0
05-11 14:59:28.705: D/sdpMLineIndex(14672): 1
05-11 14:59:28.715: D/sdpMid(14672): video
05-11 14:59:28.715: D/candidate(14672): candidate:2940422560 2 udp 1686052606 197.44.239.36 48445 typ srflx raddr 10.0.0.112 rport 48445 generation 0
05-11 14:59:28.725: I/libjingle(14672): Jingle:Net[wlan0:10.0.0.0/8:Unknown]: Allocation Phase=Tcp
05-11 14:59:28.725: I/libjingle(14672): Jingle:Port[:1:0:local:Net[wlan0:10.0.0.0/8:Unknown]]: Port created
05-11 14:59:28.725: I/libjingle(14672): Adding allocated port for video
05-11 14:59:28.725: I/libjingle(14672): Jingle:Port[video:2:0:local:Net[wlan0:10.0.0.0/8:Unknown]]: Added port to allocator
05-11 14:59:28.725: D/IceCandidate(14672): video:1:candidate:48313276 2 tcp 1518280446 10.0.0.112 59723 typ host tcptype passive generation 0
05-11 14:59:28.725: D/sdpMLineIndex(14672): 1
05-11 14:59:28.725: D/sdpMid(14672): video
05-11 14:59:28.725: D/candidate(14672): candidate:48313276 2 tcp 1518280446 10.0.0.112 59723 typ host tcptype passive generation 0
05-11 14:59:28.735: I/libjingle(14672): Jingle:Net[wlan0:10.0.0.0/8:Unknown]: Allocation Phase=SslTcp
05-11 14:59:28.735: I/libjingle(14672): Jingle:Net[wlan0:10.0.0.0/8:Unknown]: Allocation Phase=SslTcp
05-11 14:59:28.735: I/libjingle(14672): All candidates gathered for audio:2:0
05-11 14:59:28.735: I/libjingle(14672): Transport: audio, component 2 allocation complete
05-11 14:59:28.745: I/libjingle(14672): Jingle:Net[wlan0:10.0.0.0/8:Unknown]: Allocation Phase=SslTcp
05-11 14:59:28.745: I/libjingle(14672): All candidates gathered for video:1:0
05-11 14:59:28.745: I/libjingle(14672): Transport: video, component 1 allocation complete
05-11 14:59:28.775: I/libjingle(14672): Jingle:Net[wlan0:10.0.0.0/8:Unknown]: Allocation Phase=SslTcp
05-11 14:59:28.775: I/libjingle(14672): All candidates gathered for video:2:0
05-11 14:59:28.775: I/libjingle(14672): Transport: video, component 2 allocation complete
05-11 14:59:28.775: I/libjingle(14672): Transport: video allocation complete
05-11 14:59:28.775: I/libjingle(14672): Candidate allocation not done for audio
05-11 14:59:28.795: I/libjingle(14672): All candidates gathered for audio:1:0
05-11 14:59:28.795: I/libjingle(14672): Transport: audio, component 1 allocation complete
05-11 14:59:28.795: I/libjingle(14672): Transport: audio allocation complete
05-11 14:59:28.795: I/libjingle(14672): Candidate gathering is complete.
05-11 14:59:28.795: D/IceGatheringChange(14672): COMPLETE
}
MediaConstraints
pcConstraints.mandatory.add(new MediaConstraints.KeyValuePair("OfferToReceiveAudio", "true"));
pcConstraints.mandatory.add(new MediaConstraints.KeyValuePair("OfferToReceiveVideo", "true"));
pcConstraints.optional.add(new MediaConstraints.KeyValuePair("DtlsSrtpKeyAgreement", "true"));
请记住,这是我自己的简陋代码,它可能并不完美,并且可能很难将所有内容复制到您自己的项目中。它适用于我,但这并不意味着它适用于其他人。
建立通话的过程如下(注意,这不是一成不变的):
有 2 台设备,A 和 B,都连接到某种信令服务器,以允许它们交换 SDP 和 ICE 候选者,以及互相邀请通话等...
A 开始通话,第一步可能是向 B 发送邀请。此时我还想使用以下代码初始化 peerconnection 对象:
//initialize the peerconnection factory
PeerConnectionFactory.initializeAndroidGlobals(MainActivity.context, true, true, true, parent.tex_remote);
factory = new PeerConnectionFactory();
//ice server initialization
ArrayList<PeerConnection.IceServer> iceServers = new ArrayList<>();
iceServers.add(new PeerConnection.IceServer("stun:stun.xxx.xxx:xxx"));
iceServers.add(new PeerConnection.IceServer("turn:turn.xxx.xxx:xxx", "xxx", "xxx"));
//create a new contraints object to configure the connection
MediaConstraints connectionConstraints = new MediaConstraints();
connectionConstraints.mandatory.add(new MediaConstraints.KeyValuePair("offerToReceiveAudio", "true"));
connectionConstraints.mandatory.add(new MediaConstraints.KeyValuePair("offerToReceiveVideo", "true"));
connectionConstraints.optional.add(new MediaConstraints.KeyValuePair("DtlsSrtpKeyAgreement", "true"));
//create a new peerconnection object
peerConnection = factory.createPeerConnection(iceServers, connectionConstraints, observer);
完成后,您有了 peerconnection 对象,您可以使用以下代码初始化本地媒体流:
//create a new audio and video source, this is the stream that will be sent to the remote
VideoSource videoSource = factory.createVideoSource(VideoCapturer.create("Camera 1, Facing front, Orientation 270"), new MediaConstraints());
AudioSource audioSource = factory.createAudioSource(new MediaConstraints());
//create a new audio and video track
VideoTrack videoTrack = factory.createVideoTrack("ARDAMSv0", videoSource);
AudioTrack audioTrack = factory.createAudioTrack("ARDAMSa0", audioSource);
//create a new media stream, this holds all local streams and their tracks
MediaStream lms = factory.createLocalMediaStream("ARDAMS");
//create a new video renderer and add it to the video track
VideoRenderer renderer = new VideoRenderer(parent);
videoTrack.addRenderer(renderer);
//add the video track to the stream
lms.addTrack(videoTrack);
//add the audio track to the stream
lms.addTrack(audioTrack);
//add the stream to the connection
peerConnection.addStream(lms);
同时,B 会收到来自信令服务器的呼叫邀请,并且必须向用户呈现某种来电视图。当用户决定接听电话时,B 向 A 发送一个接受信号。
当 A 收到此接受信号时,就该开始自己设置呼叫了。在 A 上调用 createOffer(),如果成功,库将调用 onCreateSuccess():
peerConnection.createOffer(observer, new MediaConstraints());
在onCreateSuccess()中,可以用新建的SDP调用setLocalDescription()。您还必须将此 SDP 发送给 B,因此您不妨在此处执行此操作:
peerConnection.setLocalDescription(this, sessionDescription);
//send this SDP to your remote peer
B 现在将收到 A 的报价,您必须通过调用 setRemoteDescription() 进行设置:
peerConnection.setRemoteDescription(observer, sdp);
如果成功,库将调用 onSetSuccess()。在 onSetSuccess() 中你可以调用 createAnswer():
peerConnection.createAnswer(observer, constraints);
因为您现在确定已设置初始报价 SDP。该库将为您再次调用 onCreateSuccess() 。与 A 的报价相同的事情现在发生在 B 的回答上。它会将答案设置为本地 SDP,并将其发送给 A:
peerConnection.setLocalDescription(this, sessionDescription);
//send this SDP to your remote peer
当所有这些都完成后,交换 SDP 就完成了。该库还会多次调用 onIceCandidate()。您只需将此 ICE 候选人发送给其他同行并在收到来自其他同行的 ICE 候选人时调用 peerConnection.addIceCandidate()。
pcConstraints.optional.add(new KeyValuePair("DtlsSrtpKeyAgreement", "true"));
pcConstraints.optional.add(new KeyValuePair("RtpDataChannels", "true"));