Apprtc: not to start the call until we get Turn response.

BUG=1795
Test=Manual Test

R=fischman@webrtc.org, juberti@google.com

Review URL: https://webrtc-codereview.appspot.com/1528004

git-svn-id: http://webrtc.googlecode.com/svn/trunk@4144 4adac7df-926f-26a2-2b94-8c16560cd09d
This commit is contained in:
braveyao@webrtc.org 2013-05-31 06:29:41 +00:00
parent f9f39d59d4
commit 5ed7051799

View file

@ -10,23 +10,22 @@
var started = false; var started = false;
var turnDone = false; var turnDone = false;
var channelReady = false; var channelReady = false;
var signalingReady = false;
var msgQueue = [];
// Set up audio and video regardless of what devices are present. // Set up audio and video regardless of what devices are present.
var sdpConstraints = {'mandatory': { var sdpConstraints = {'mandatory': {
'OfferToReceiveAudio': true, 'OfferToReceiveAudio': true,
'OfferToReceiveVideo': true }}; 'OfferToReceiveVideo': true }};
var isVideoMuted = false; var isVideoMuted = false;
var isAudioMuted = false; var isAudioMuted = false;
var aspectRatio;
function initialize() { function initialize() {
console.log('Initializing; room=' + roomKey + '.'); console.log('Initializing; room=' + roomKey + '.');
card = document.getElementById('card'); card = document.getElementById('card');
localVideo = document.getElementById('localVideo'); localVideo = document.getElementById('localVideo');
// Reset localVideo display to center. // Reset localVideo display to center.
localVideo.addEventListener("loadedmetadata", function(){ localVideo.addEventListener('loadedmetadata', function(){
aspectRatio = this.videoWidth / this.videoHeight; window.onresize();});
window.onresize();
});
miniVideo = document.getElementById('miniVideo'); miniVideo = document.getElementById('miniVideo');
remoteVideo = document.getElementById('remoteVideo'); remoteVideo = document.getElementById('remoteVideo');
resetStatus(); resetStatus();
@ -35,6 +34,8 @@
openChannel(); openChannel();
maybeRequestTurn(); maybeRequestTurn();
doGetUserMedia(); doGetUserMedia();
// Caller is always ready to create peerConnection.
signalingReady = initiator;
} }
function openChannel() { function openChannel() {
@ -59,7 +60,7 @@
var currentDomain = document.domain; var currentDomain = document.domain;
if (currentDomain.search('localhost') === -1 && if (currentDomain.search('localhost') === -1 &&
currentDomain.search('apprtc.appspot.com') === -1) { currentDomain.search('apprtc') === -1) {
// Not authorized domain. Try with default STUN instead. // Not authorized domain. Try with default STUN instead.
turnDone = true; turnDone = true;
return; return;
@ -73,17 +74,21 @@
} }
function onTurnResult() { function onTurnResult() {
if (xmlhttp.readyState == 4 && xmlhttp.status == 200) { if (xmlhttp.readyState !== 4)
return;
if (xmlhttp.status === 200) {
var turnServer = JSON.parse(xmlhttp.responseText); var turnServer = JSON.parse(xmlhttp.responseText);
// Create a turnUri using the polyfill (adapter.js). // Create a turnUri using the polyfill (adapter.js).
var iceServer = createIceServer(turnServer.uris[0], turnServer.username, var iceServer = createIceServer(turnServer.uris[0], turnServer.username,
turnServer.password); turnServer.password);
pcConfig.iceServers.push(iceServer); pcConfig.iceServers.push(iceServer);
} else { } else {
console.log("Request for TURN server failed.") console.log('Request for TURN server failed.');
} }
// If TURN request failed, continue the call with default STUN. // If TURN request failed, continue the call with default STUN.
turnDone = true; turnDone = true;
maybeStart();
} }
function resetStatus() { function resetStatus() {
@ -127,18 +132,19 @@
} }
function maybeStart() { function maybeStart() {
if (!started && localStream && channelReady && turnDone) { if (!started && signalingReady &&
localStream && channelReady && turnDone) {
setStatus('Connecting...'); setStatus('Connecting...');
console.log('Creating PeerConnection.'); console.log('Creating PeerConnection.');
createPeerConnection(); createPeerConnection();
console.log('Adding local stream.'); console.log('Adding local stream.');
pc.addStream(localStream); pc.addStream(localStream);
started = true; started = true;
// Caller initiates offer to peer.
if (initiator) if (initiator)
doCall(); doCall();
} else { else
setTimeout(maybeStart, 100); calleeStart();
} }
} }
@ -153,6 +159,13 @@
pc.createOffer(setLocalAndSendMessage, null, constraints); pc.createOffer(setLocalAndSendMessage, null, constraints);
} }
function calleeStart() {
// Callee starts to process cached offer and other messages.
while (msgQueue.length > 0) {
processSignalingMessage(msgQueue.shift());
}
}
function doAnswer() { function doAnswer() {
console.log('Sending answer to peer.'); console.log('Sending answer to peer.');
pc.createAnswer(setLocalAndSendMessage, null, sdpConstraints); pc.createAnswer(setLocalAndSendMessage, null, sdpConstraints);
@ -186,27 +199,27 @@
} }
function processSignalingMessage(message) { function processSignalingMessage(message) {
var msg = JSON.parse(message); if (!started) {
console.log('peerConnection has not been created yet!');
return;
}
if (msg.type === 'offer') { if (message.type === 'offer') {
// Callee creates PeerConnection
if (!initiator && !started)
maybeStart();
// Set Opus in Stereo, if stereo enabled. // Set Opus in Stereo, if stereo enabled.
if (stereo) if (stereo)
msg.sdp = addStereo(msg.sdp); message.sdp = addStereo(message.sdp);
pc.setRemoteDescription(new RTCSessionDescription(msg)); pc.setRemoteDescription(new RTCSessionDescription(message));
doAnswer(); doAnswer();
} else if (msg.type === 'answer' && started) { } else if (message.type === 'answer') {
// Set Opus in Stereo, if stereo enabled. // Set Opus in Stereo, if stereo enabled.
if (stereo) if (stereo)
msg.sdp = addStereo(msg.sdp); message.sdp = addStereo(message.sdp);
pc.setRemoteDescription(new RTCSessionDescription(msg)); pc.setRemoteDescription(new RTCSessionDescription(message));
} else if (msg.type === 'candidate' && started) { } else if (message.type === 'candidate') {
var candidate = new RTCIceCandidate({sdpMLineIndex: msg.label, var candidate = new RTCIceCandidate({sdpMLineIndex: message.label,
candidate: msg.candidate}); candidate: message.candidate});
pc.addIceCandidate(candidate); pc.addIceCandidate(candidate);
} else if (msg.type === 'bye' && started) { } else if (message.type === 'bye') {
onRemoteHangup(); onRemoteHangup();
} }
} }
@ -214,10 +227,28 @@
function onChannelOpened() { function onChannelOpened() {
console.log('Channel opened.'); console.log('Channel opened.');
channelReady = true; channelReady = true;
maybeStart();
} }
function onChannelMessage(message) { function onChannelMessage(message) {
console.log('S->C: ' + message.data); console.log('S->C: ' + message.data);
processSignalingMessage(message.data); var msg = JSON.parse(message.data);
// Since the turn response is async and also GAE might disorder the
// Message delivery due to possible datastore query at server side,
// So callee needs to cache messages before peerConnection is created.
if (!initiator && !started) {
if (msg.type === 'offer') {
// Add offer to the beginning of msgQueue, since we can't handle
// Early candidates before offer at present.
msgQueue.unshift(msg);
// Callee creates PeerConnection
signalingReady = true;
maybeStart();
} else {
msgQueue.push(msg);
}
} else {
processSignalingMessage(msg);
}
} }
function onChannelError() { function onChannelError() {
console.log('Channel error.'); console.log('Channel error.');
@ -233,7 +264,7 @@
localVideo.style.opacity = 1; localVideo.style.opacity = 1;
localStream = stream; localStream = stream;
// Caller creates PeerConnection. // Caller creates PeerConnection.
if (initiator) maybeStart(); maybeStart();
} }
function onUserMediaError(error) { function onUserMediaError(error) {
@ -283,10 +314,12 @@
function stop() { function stop() {
started = false; started = false;
signalingReady = false;
isAudioMuted = false; isAudioMuted = false;
isVideoMuted = false; isVideoMuted = false;
pc.close(); pc.close();
pc = null; pc = null;
msgQueue.length = 0;
} }
function waitForRemoteVideo() { function waitForRemoteVideo() {
@ -519,6 +552,7 @@
// Set the video diplaying in the center of window. // Set the video diplaying in the center of window.
window.onresize = function(){ window.onresize = function(){
var aspectRatio;
if (remoteVideo.style.opacity === '1') { if (remoteVideo.style.opacity === '1') {
aspectRatio = remoteVideo.videoWidth/remoteVideo.videoHeight; aspectRatio = remoteVideo.videoWidth/remoteVideo.videoHeight;
} else if (localVideo.style.opacity === '1') { } else if (localVideo.style.opacity === '1') {
@ -533,9 +567,9 @@
innerWidth : aspectRatio * window.innerHeight; innerWidth : aspectRatio * window.innerHeight;
var videoHeight = innerHeight < window.innerWidth / aspectRatio ? var videoHeight = innerHeight < window.innerWidth / aspectRatio ?
innerHeight : window.innerWidth / aspectRatio; innerHeight : window.innerWidth / aspectRatio;
containerDiv = document.getElementById("container"); containerDiv = document.getElementById('container');
containerDiv.style.width = videoWidth + "px"; containerDiv.style.width = videoWidth + 'px';
containerDiv.style.height = videoHeight + "px"; containerDiv.style.height = videoHeight + 'px';
containerDiv.style.left = (innerWidth - videoWidth) / 2 + "px"; containerDiv.style.left = (innerWidth - videoWidth) / 2 + 'px';
containerDiv.style.top = (innerHeight - videoHeight) / 2 + "px"; containerDiv.style.top = (innerHeight - videoHeight) / 2 + 'px';
}; };