Slide 45
Slide 45 text
Vanila JS
'use strict';
var startButton = document.getElementById('startButton');
var callButton = document.getElementById('callButton');
var hangupButton = document.getElementById('hangupButton');
callButton.disabled = true;
hangupButton.disabled = true;
startButton.onclick = start;
callButton.onclick = call;
hangupButton.onclick = hangup;
var startTime;
var localVideo = document.getElementById('localVideo');
var remoteVideo = document.getElementById('remoteVideo');
localVideo.addEventListener('loadedmetadata', function() {
trace('Local video videoWidth: ' + this.videoWidth +
'px, videoHeight: ' + this.videoHeight + 'px');
});
remoteVideo.addEventListener('loadedmetadata', function() {
trace('Remote video videoWidth: ' + this.videoWidth +
'px, videoHeight: ' + this.videoHeight + 'px');
});
remoteVideo.onresize = function() {
trace('Remote video size changed to ' +
remoteVideo.videoWidth + 'x' + remoteVideo.videoHeight);
// We'll use the first onsize callback as an indication that video has started
// playing out.
if (startTime) {
var elapsedTime = window.performance.now() - startTime;
trace('Setup time: ' + elapsedTime.toFixed(3) + 'ms');
startTime = null;
}
};
var localStream;
var pc1;
var pc2;
var offerOptions = {
offerToReceiveAudio: 1,
offerToReceiveVideo: 1
};
function getName(pc) {
return (pc === pc1) ? 'pc1' : 'pc2';
}
function getOtherPc(pc) {
return (pc === pc1) ? pc2 : pc1;
}
function gotStream(stream) {
trace('Received local stream');
localVideo.srcObject = stream;
localStream = stream;
callButton.disabled = false;
}
function start() {
trace('Requesting local stream');
startButton.disabled = true;
navigator.mediaDevices.getUserMedia({
audio: true,
video: true
})
.then(gotStream)
.catch(function(e) {
alert('getUserMedia() error: ' + e.name);
});
}
function call() {
callButton.disabled = true;
hangupButton.disabled = false;
trace('Starting call');
startTime = window.performance.now();
var videoTracks = localStream.getVideoTracks();
var audioTracks = localStream.getAudioTracks();
if (videoTracks.length > 0) {
trace('Using video device: ' + videoTracks[0].label);
}
if (audioTracks.length > 0) {
trace('Using audio device: ' + audioTracks[0].label);
}
var servers = null;
pc1 = new RTCPeerConnection(servers);
trace('Created local peer connection object pc1');
pc1.onicecandidate = function(e) {
onIceCandidate(pc1, e);
};
pc2 = new RTCPeerConnection(servers);
trace('Created remote peer connection object pc2');
pc2.onicecandidate = function(e) {
onIceCandidate(pc2, e);
};
pc1.oniceconnectionstatechange = function(e) {
onIceStateChange(pc1, e);
};
pc2.oniceconnectionstatechange = function(e) {
onIceStateChange(pc2, e);
};
pc2.onaddstream = gotRemoteStream;
pc1.addStream(localStream);
trace('Added local stream to pc1');
trace('pc1 createOffer start');
pc1.createOffer(onCreateOfferSuccess, onCreateSessionDescriptionError,
offerOptions);
}
209 lines of code
function onCreateSessionDescriptionError(error) {
trace('Failed to create session description: ' + error.toString());
}
function onCreateOfferSuccess(desc) {
trace('Offer from pc1\n' + desc.sdp);
trace('pc1 setLocalDescription start');
pc1.setLocalDescription(desc, function() {
onSetLocalSuccess(pc1);
}, onSetSessionDescriptionError);
trace('pc2 setRemoteDescription start');
pc2.setRemoteDescription(desc, function() {
onSetRemoteSuccess(pc2);
}, onSetSessionDescriptionError);
trace('pc2 createAnswer start');
// Since the 'remote' side has no media stream we need
// to pass in the right constraints in order for it to
// accept the incoming offer of audio and video.
pc2.createAnswer(onCreateAnswerSuccess, onCreateSessionDescriptionError);
}
function onSetLocalSuccess(pc) {
trace(getName(pc) + ' setLocalDescription complete');
}
function onSetRemoteSuccess(pc) {
trace(getName(pc) + ' setRemoteDescription complete');
}
function onSetSessionDescriptionError(error) {
trace('Failed to set session description: ' + error.toString());
}
function gotRemoteStream(e) {
remoteVideo.srcObject = e.stream;
trace('pc2 received remote stream');
}
function onCreateAnswerSuccess(desc) {
trace('Answer from pc2:\n' + desc.sdp);
trace('pc2 setLocalDescription start');
pc2.setLocalDescription(desc, function() {
onSetLocalSuccess(pc2);
}, onSetSessionDescriptionError);
trace('pc1 setRemoteDescription start');
pc1.setRemoteDescription(desc, function() {
onSetRemoteSuccess(pc1);
}, onSetSessionDescriptionError);
}
function onIceCandidate(pc, event) {
if (event.candidate) {
getOtherPc(pc).addIceCandidate(new RTCIceCandidate(event.candidate),
function() {
onAddIceCandidateSuccess(pc);
},
function(err) {
onAddIceCandidateError(pc, err);
}
);
trace(getName(pc) + ' ICE candidate: \n' + event.candidate.candidate);
}
}
function onAddIceCandidateSuccess(pc) {
trace(getName(pc) + ' addIceCandidate success');
}
function onAddIceCandidateError(pc, error) {
trace(getName(pc) + ' failed to add ICE Candidate: ' + error.toString());
}
function onIceStateChange(pc, event) {
if (pc) {
trace(getName(pc) + ' ICE state: ' + pc.iceConnectionState);
console.log('ICE state change event: ', event);
}
}
function hangup() {
trace('Ending call');
pc1.close();
pc2.close();
pc1 = null;
pc2 = null;
hangupButton.disabled = true;
callButton.disabled = false;
}
https://github.com/webrtc/samples/blob/gh-pages/src/content/peerconnection/pc1/js/main.js