canvas_demo.html (200 lines of code) (raw):
<html><head>
<meta http-equiv="content-type" content="text/html; charset=ISO-8859-1">
<title>Canvas RTCPeerConnection Demo</title>
<style>
#video-container {
padding: 15px;
-moz-column-count: 2;
}
#canvas {
height:500px;
}
#video {
height:500px;
}
#mycanvas1 {
}
#pc2video {
height:auto;
width:100%;
max-height:480px;
}
#thebutton {
}
.hidden
{
display: none;
}
</style>
</head>
<body>
<center>
<a href="index.html">Main webrtc demo page</a><br>
<h2>Canvas PeerConnection Demo</h2>
<b>NOTE: You need Firefox 41, and set canvas.capturestream.enabled to true in about:config!</b><br>
</center>
<div id="startstopbutton">
<button id="thebutton" onclick="xstart();">Start!</button>
</div>
<div id="video-container">
<div id="canvas">
<h3>Canvas</h3>
<canvas id="mycanvas1" width="640" height="480"></canvas>
</div>
<div id="video">
<h3>Remote Video</h3>
<video id="pc2video" controls="controls" muted autoplay></video>
</div>
</div>
<div id="log"></div>
<script type="text/javascript" src="jquery.js"></script>
<script type="text/javascript" src="Cloth.js"></script>
<script type="application/javascript">
let pc2video = document.getElementById("pc2video");
let canvas0 = document.getElementById("canvas");
let canvas1 = document.getElementById("mycanvas1");
let thebutton = document.getElementById("thebutton");
let logarea = document.getElementById("log");
let pc1;
let pc2;
let pc1_offer;
let pc2_answer;
let offer_constraints = { offerToReceiveVideo: false,
offerToReceiveAudio: false };
let answer_constraints = { offerToReceiveVideo: true,
offerToReceiveAudio: true };
let canvas_stream;
var senders1 = [ ];
function log(msg) {
logarea.innerHTML = "<p>" + msg + "</p>" + logarea.innerHTML;
}
function failed(code) {
log("Failure callback: " + JSON.stringify(code));
}
function logReset() {
logarea.innerHTML = "";
}
// pc1.createOffer finished, call pc1.setLocal
function step1(offer) {
log("Offer: " + sdpPrettyPrint(offer.sdp));
pc1_offer = offer;
pc1.setLocalDescription(offer, step2, failed);
}
// replace CR NL with HTML breaks
function sdpPrettyPrint(sdp) {
return sdp.replace(/[\r\n]+/g, '<br>');
}
// pc1.setLocal finished, call pc2.setRemote
function step2() {
pc1.onicecandidate = function(obj) {
if (obj.candidate) {
log("pc1 found ICE candidate: " + JSON.stringify(obj.candidate));
pc2.addIceCandidate(obj.candidate);
} else {
log("pc1 got end-of-candidates signal");
}
}
pc2.setRemoteDescription(pc1_offer, step3, failed);
};
// pc2.setRemote finished, call pc2.createAnswer
function step3() {
pc2.didSetRemote = true;
while (pc2.ice_queued.length > 0) {
pc2.addIceCandidate(pc2.ice_queued.shift());
}
pc2.createAnswer(step4, failed, answer_constraints);
}
// pc2.createAnswer finished, call pc2.setLocal
function step4(answer) {
log("Answer: " + sdpPrettyPrint(answer.sdp));
pc2_answer = answer;
pc2.setLocalDescription(answer, step5, failed);
}
// pc2.setLocal finished, call pc1.setRemote
function step5() {
pc2.onicecandidate = function(obj) {
if (obj.candidate) {
log("pc2 found ICE candidate: " + JSON.stringify(obj.candidate));
pc1.addIceCandidate(obj.candidate);
} else {
log("pc2 got end-of-candidates signal");
}
}
pc1.setRemoteDescription(pc2_answer, step6, failed);
}
// pc1.setRemote finished, media should be running!
function step6() {
pc1.didSetRemote = true;
while (pc1.ice_queued.length > 0) {
pc1.addIceCandidate(pc1.ice_queued.shift());
}
log("Offer/Answer finished");
}
function xstart() {
thebutton.innerHTML = "Stop!";
thebutton.onclick = stop;
pc1 = new RTCPeerConnection();
pc2 = new RTCPeerConnection();
pc1.didSetRemote = false;
pc2.didSetRemote = false;
pc1.ice_queued = [];
pc2.ice_queued = [];
pc2.onicecandidate = function(obj) {
if (obj.candidate) {
log("pc2 found ICE candidate: " + JSON.stringify(obj.candidate));
if (pc1.didSetRemote) {
pc1.addIceCandidate(obj.candidate);
} else {
pc1.ice_queued.push(obj.candidate);
}
} else {
log("pc2 got end-of-candidates signal");
}
}
pc1.onicecandidate = function(obj) {
if (obj.candidate) {
log("pc1 found ICE candidate: " + JSON.stringify(obj.candidate));
if (pc2.didSetRemote) {
pc2.addIceCandidate(obj.candidate);
} else {
pc2.ice_queued.push(obj.candidate);
}
} else {
log("pc1 got end-of-candidates signal");
}
}
pc2.onaddstream = function(obj) {
log("pc2 got remote stream from pc1 " + obj.type);
pc2video.srcObject = obj.stream;
}
if (!canvas1.captureStream) {
canvas0.innerHTML = canvas0.innerHTML + "<p></p><h2>Missing canvas.captureStream() support</h2>";
return;
}
$('#mycanvas1').show();
start_cloth(canvas1);
canvas_stream = canvas1.captureStream(15);
canvas_stream.getTracks().forEach(function(track) {
senders1[track.kind] = pc1.addTrack(track, canvas_stream);
});
pc1.createOffer(step1, failed, offer_constraints);
}
function stop() {
$('#mycanvas1').hide();
pc2video.pause();
pc2video.srcObject = null;
canvas_stream.getTracks().forEach(function(track) {
track.stop();
});
canvas_stream = null;
pc1.close();
pc2.close();
pc1 = null;
pc2 = null;
senders1 = [];
thebutton.innerHTML = "Start!";
thebutton.onclick = xstart;
logReset();
}
</script>
</body></html>