Skip to content

Commit

Permalink
Added captureStream to peer connection demo
Browse files Browse the repository at this point in the history
  • Loading branch information
samdutton committed May 10, 2016
1 parent 6530e9e commit 51b4e13
Show file tree
Hide file tree
Showing 22 changed files with 2,489 additions and 22 deletions.
2 changes: 1 addition & 1 deletion README.md
Expand Up @@ -46,7 +46,7 @@ Head over to [test/README.md](https://github.com/webrtc/samples/blob/gh-pages/te

[Stream from a canvas element to a video element](https://webrtc.github.io/samples/src/content/capture/canvas-video/)

<!-- [Stream from a canvas element to a peer connection](https://webrtc.github.io/samples/src/content/capture/canvas-pc/) -->
[Stream from a canvas element to a peer connection](https://webrtc.github.io/samples/src/content/capture/canvas-pc/)

<!-- [Record a stream from a canvas element](https://webrtc.github.io/samples/src/content/capture/canvas-record/) -->

Expand Down
8 changes: 4 additions & 4 deletions index.html
Expand Up @@ -102,7 +102,7 @@ <h3 id="capture">Stream capture</h3>

<p><a href="https://webrtc.github.io/samples/src/content/capture/canvas-video/">Stream from a canvas element to a video element</a></p>

<!-- <p><a href="https://webrtc.github.io/samples/src/content/capture/canvas-pc/">Stream from a canvas element to a peer connection</a></p> -->
<p><a href="https://webrtc.github.io/samples/src/content/capture/canvas-pc/">Stream from a canvas element to a peer connection</a></p>

<!-- <p><a href="https://webrtc.github.io/samples/src/content/capture/canvas-record/">Record a stream from a canvas element</a></p> -->

Expand Down Expand Up @@ -169,9 +169,9 @@ <h3 id="videoChat">Video chat</h3>
<script src="src/js/lib/ga.js"></script>
<script type="application/javascript">
// Redirect to HTTPS for Github Pages
if (window.location.protocol !== "https:"){
window.location.protocol = "https";
}
// if (window.location.protocol !== "https:"){
// window.location.protocol = "https";
// }
</script>

</body>
Expand Down
43 changes: 43 additions & 0 deletions src/content/capture/canvas-stream/css/main.css
@@ -0,0 +1,43 @@
/*
* Copyright (c) 2016 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree.
*/

canvas {
background-color: #ccc;
height: 231px;
margin: 0 20px 0 0;
vertical-align: top;
width: calc(50% - 12px);
}

video {
height: 231px;
margin: 0 0 20px 0;
object-fit: cover;
width: calc(50% - 12px);
}

@media screen and (max-width: 400px) {
canvas {
margin: 0 10px 0 0;
width: calc(50% - 7px);
}
video {
margin: 0 0 20px 0;
width: calc(50% - 7px);
}
}

@media screen and (max-width: 700px) {
canvas {
border: 1px solid #ccc;
width: calc(50% - 14px);
}
video {
object-fit: inherit;
}
}
71 changes: 71 additions & 0 deletions src/content/capture/canvas-stream/index.html
@@ -0,0 +1,71 @@
<!DOCTYPE html>
<!--
* Copyright (c) 2015 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree.
-->
<html>
<head>

<meta charset="utf-8">
<meta name="description" content="WebRTC code samples">
<meta name="viewport" content="width=device-width, user-scalable=yes, initial-scale=1, maximum-scale=1">
<meta itemprop="description" content="Client-side WebRTC code samples">
<meta itemprop="image" content="../../../images/webrtc-icon-192x192.png">
<meta itemprop="name" content="WebRTC code samples">
<meta name="mobile-web-app-capable" content="yes">
<meta id="theme-color" name="theme-color" content="#ffffff">

<base target="_blank">

<title>Canvas to peer connection</title>

<link rel="icon" sizes="192x192" href="../../../images/webrtc-icon-192x192.png">
<link href="//fonts.googleapis.com/css?family=Roboto:300,400,500,700" rel="stylesheet" type="text/css">
<link rel="stylesheet" href="../../../css/main.css" />
<link rel="stylesheet" href="css/main.css" />

</head>

<body>

<div id="container">

<h1><a href="//webrtc.github.io/samples/" title="WebRTC samples homepage">WebRTC samples</a> <span>Stream from canvas to peer connection</span></h1>

<canvas></canvas>
<video autoplay></video>

<p>Click and drag on the canvas element (on the left) to move the teapot.</p>

<p>This demo requires Firefox 43 or above, Chrome 51 or above, or Chrome 50 with <strong>Experimental Web Platform features</strong> enabled.</p>

<p>The teapot is drawn on the canvas element using WebGL. A stream is captured from the canvas using its <code>captureStream()</code> method and streamed via a peer connection to the video element on the right.</p>

<p>View the browser console to see logging.</p>

<p>Several variables are in global scope, so you can inspect them from the console: <code>canvas</code>, <code>video</code>, <code>localPeerConnection</code>, <code>remotePeerConnection</code> and <code>stream</code>.</p>

<p>For more information about RTCPeerConnection, see <a href="http://www.html5rocks.com/en/tutorials/webrtc/basics/" title="HTML5 Rocks article about WebRTC by Sam Dutton">Getting Started With WebRTC</a>.</p>

<a href="https://github.com/webrtc/samples/tree/gh-pages/src/content/capture/canvas-stream" title="View source for this page on GitHub" id="viewSource">View source on GitHub</a>

</div>

<!-- Teapot code -->
<script src="js/third_party/webgl-utils.js"></script>
<script src="js/third_party/webgl-debug.js"></script>
<script src="js/third_party/matrix4x4.js"></script>
<script src="js/third_party/cameracontroller.js"></script>
<script src="js/third_party/teapot-streams.js"></script>
<script src="js/third_party/demo.js"></script>

<script src="../../../js/adapter.js"></script>
<script src="../../../js/common.js"></script>
<script src="js/main.js"></script>

<script src="../../../js/lib/ga.js"></script>
</body>
</html>
173 changes: 173 additions & 0 deletions src/content/capture/canvas-stream/js/main.js
@@ -0,0 +1,173 @@
/*
* Copyright (c) 2015 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree.
*/

/* global main */

'use strict';

var canvas = document.querySelector('canvas');
var video = document.querySelector('video');

var pc1;
var pc2;
var offerOptions = {
offerToReceiveAudio: 1,
offerToReceiveVideo: 1
};

var startTime;

video.addEventListener('loadedmetadata', function() {
trace('Remote video videoWidth: ' + this.videoWidth +
'px, videoHeight: ' + this.videoHeight + 'px');
});

video.onresize = function() {
trace('Remote video size changed to ' +
video.videoWidth + 'x' + video.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;
}
};

// Call main() in demo.js
main();

var stream = canvas.captureStream();
trace('Got stream from canvas');

call();

function call() {
trace('Starting call');
startTime = window.performance.now();
var videoTracks = stream.getVideoTracks();
var audioTracks = stream.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(stream);
trace('Added local stream to pc1');

trace('pc1 createOffer start');
pc1.createOffer(onCreateOfferSuccess, onCreateSessionDescriptionError,
offerOptions);
}

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) {
video.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 getName(pc) {
return (pc === pc1) ? 'pc1' : 'pc2';
}

function getOtherPc(pc) {
return (pc === pc1) ? pc2 : pc1;
}
54 changes: 54 additions & 0 deletions src/content/capture/canvas-stream/js/test.js
@@ -0,0 +1,54 @@
/*
* Copyright (c) 2015 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree.
*/
/* eslint-env node */

'use strict';
// This is a basic test file for use with testling.
// The test script language comes from tape.
var test = require('tape');

var webdriver = require('selenium-webdriver');
var seleniumHelpers = require('webrtc-utilities').seleniumLib;

test('PeerConnection pc1 sample', function(t) {
var driver = seleniumHelpers.buildDriver();

driver.get('file://' + process.cwd() +
'/src/content/peerconnection/pc1/index.html')
.then(function() {
t.pass('page loaded');
return driver.findElement(webdriver.By.id('startButton')).click();
})
.then(function() {
t.pass('got media');
return driver.findElement(webdriver.By.id('callButton')).click();
})
.then(function() {
return driver.wait(function() {
return driver.executeScript(
'return pc2 && pc2.iceConnectionState === \'connected\';');
}, 30 * 1000);
})
.then(function() {
t.pass('pc2 ICE connected');
return driver.findElement(webdriver.By.id('hangupButton')).click();
})
.then(function() {
return driver.wait(function() {
return driver.executeScript('return pc1 === null');
}, 30 * 1000);
})
.then(function() {
t.pass('hangup');
t.end();
})
.then(null, function(err) {
t.fail(err);
t.end();
});
});

0 comments on commit 51b4e13

Please sign in to comment.