• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1<!DOCTYPE html>
2<html>
3  <!--
4  Copyright (c) 2013 The Chromium Authors. All rights reserved.
5  Use of this source code is governed by a BSD-style license that can be
6  found in the LICENSE file.
7  -->
8<head>
9<title>Video Effects Demo</title>
10<style>
11video {
12  border:5px solid black;
13  width:480px;
14  height:360px;
15}
16button {
17  font: 18px sans-serif;
18  padding: 8px;
19}
20textarea {
21  font-family: monospace;
22  margin: 2px;
23  width:480px;
24  height:640px;
25}
26</style>
27</head>
28<body>
29<table>
30<tr>
31<td><video id="vidlocal" autoplay></video></td>
32<td><video id="vidprocessedlocal" autoplay></video></td>
33<td><video id="vidremote" autoplay></video></td>
34</tr>
35<tr>
36<td>Local Media Stream</td>
37<td>Local Media Stream After Effect</td>
38<td>Remote Media Stream</td>
39</tr>
40<tr>
41</table>
42<br>
43<button id="startButton" onclick="start()">Start</button>
44<button id="toggleEffectButton" onclick="toggleEffect()">Enable Effect</button>
45<button id="callButton" onclick="call()">Call</button>
46<button id="hangupButton" onclick="hangup()">Hang Up</button>
47<br>
48<embed id="plugin" type="application/x-ppapi-example-video-effects"
49    width="320" height="240"/>
50
51<script>
52var RTCPeerConnection = webkitRTCPeerConnection;
53var getUserMedia = navigator.webkitGetUserMedia.bind(navigator);
54var attachMediaStream = function(element, stream) {
55  element.src = URL.createObjectURL(stream);
56};
57var startButton = document.getElementById('startButton');
58var toggleEffectButton = document.getElementById('toggleEffectButton');
59var callButton = document.getElementById('callButton');
60var hangupButton = document.getElementById('hangupButton');
61
62callButton.disabled = true;
63hangupButton.disabled = true;
64toggleEffectButton.disabled = true;
65var pc1 = null;
66var pc2 = null;
67var localstream = null;
68var processedLocalstream = null;
69var effectsPlugin = null;
70var effectsEnabled = false;
71
72function trace(text) {
73  // This function is used for logging.
74  if (text[text.length - 1] == '\n') {
75    text = text.substring(0, text.length - 1);
76  }
77  console.log((performance.now() / 1000).toFixed(3) + ": " + text);
78}
79
80function gotStream(stream){
81  trace("Received local stream");
82  // Call the polyfill wrapper to attach the media stream to this element.
83  attachMediaStream(vidlocal, stream);
84  localstream = stream;
85  callButton.disabled = false;
86  initEffect();
87}
88
89function start() {
90  trace("Requesting local stream");
91  startButton.disabled = true;
92  // Call into getUserMedia via the polyfill (adapter.js).
93  getUserMedia({audio:false, video:true},
94                gotStream, function() {});
95}
96
97function onRegisterStreamDone() {
98  vidprocessedlocal.src = URL.createObjectURL(processedLocalstream);
99  toggleEffectButton.disabled = false;
100}
101
102function HandleMessage(message_event) {
103  if (message_event.data) {
104    if (message_event.data == 'DoneRegistering') {
105      onRegisterStreamDone();
106    } else {
107      trace(message_event.data);
108    }
109  }
110}
111
112function initEffect() {
113  var url = URL.createObjectURL(localstream);
114  processedLocalstream = new webkitMediaStream([]);
115  var processedStreamUrl = URL.createObjectURL(processedLocalstream);
116  effectsPlugin.postMessage(
117      'registerStream' + ' ' + url + ' ' + processedStreamUrl);
118}
119
120function toggleEffect() {
121  effectsEnabled = !effectsEnabled;
122  if (effectsEnabled) {
123    toggleEffectButton.innerHTML = 'Disable Effect';
124    effectsPlugin.postMessage('effectOn');
125  } else {
126    toggleEffectButton.innerHTML = 'Enable Effect';
127    effectsPlugin.postMessage('effectOff');
128  }
129}
130
131function call() {
132  callButton.disabled = true;
133  hangupButton.disabled = false;
134  trace("Starting call");
135  var servers = null;
136  pc1 = new RTCPeerConnection(servers);
137  trace("Created local peer connection object pc1");
138  pc1.onicecandidate = iceCallback1;
139  pc2 = new RTCPeerConnection(servers);
140  trace("Created remote peer connection object pc2");
141  pc2.onicecandidate = iceCallback2;
142  pc2.onaddstream = gotRemoteStream;
143
144  pc1.addStream(processedLocalstream);
145  trace("Adding Local Stream to peer connection");
146
147  pc1.createOffer(gotDescription1);
148}
149
150function gotDescription1(desc){
151  pc1.setLocalDescription(desc);
152  trace("Offer from pc1 \n" + desc.sdp);
153  pc2.setRemoteDescription(desc);
154  // Since the "remote" side has no media stream we need
155  // to pass in the right constraints in order for it to
156  // accept the incoming offer of audio and video.
157  var sdpConstraints = {'mandatory': {
158                        'OfferToReceiveAudio':true,
159                        'OfferToReceiveVideo':true }};
160  pc2.createAnswer(gotDescription2, null, sdpConstraints);
161}
162
163function gotDescription2(desc){
164  pc2.setLocalDescription(desc);
165  trace("Answer from pc2 \n" + desc.sdp);
166  pc1.setRemoteDescription(desc);
167}
168
169function hangup() {
170  trace("Ending call");
171  pc1.close();
172  pc2.close();
173  pc1 = null;
174  pc2 = null;
175  hangupButton.disabled = true;
176  callButton.disabled = false;
177}
178
179function gotRemoteStream(e){
180  vidremote.src = URL.createObjectURL(e.stream);
181  trace("Received remote stream");
182}
183
184function iceCallback1(event){
185  if (event.candidate) {
186    pc2.addIceCandidate(new RTCIceCandidate(event.candidate));
187    trace("Local ICE candidate: \n" + event.candidate.candidate);
188  }
189}
190
191function iceCallback2(event){
192  if (event.candidate) {
193    pc1.addIceCandidate(new RTCIceCandidate(event.candidate));
194    trace("Remote ICE candidate: \n " + event.candidate.candidate);
195  }
196}
197
198function InitializePlugin() {
199  effectsPlugin = document.getElementById('plugin');
200  effectsPlugin.addEventListener('message', HandleMessage, false);
201}
202
203document.addEventListener('DOMContentLoaded', InitializePlugin, false);
204</script>
205</body>
206</html>
207
208
209