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.
9 <title>Video Effects Demo
</title>
12 border:
5px solid black;
17 font:
18px sans-serif;
21 font-family: monospace;
31 <td><video id=
"vidlocal" autoplay
></video></td>
32 <td><video id=
"vidprocessedlocal" autoplay
></video></td>
33 <td><video id=
"vidremote" autoplay
></video></td>
36 <td>Local Media Stream
</td>
37 <td>Local Media Stream After Effect
</td>
38 <td>Remote Media Stream
</td>
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>
48 <embed id=
"plugin" type=
"application/x-ppapi-example-video-effects"
49 width=
"320" height=
"240"/>
52 var RTCPeerConnection
= webkitRTCPeerConnection
;
53 var getUserMedia
= navigator
.webkitGetUserMedia
.bind(navigator
);
54 var attachMediaStream = function(element
, stream
) {
55 element
.src
= URL
.createObjectURL(stream
);
57 var startButton
= document
.getElementById('startButton');
58 var toggleEffectButton
= document
.getElementById('toggleEffectButton');
59 var callButton
= document
.getElementById('callButton');
60 var hangupButton
= document
.getElementById('hangupButton');
62 callButton
.disabled
= true;
63 hangupButton
.disabled
= true;
64 toggleEffectButton
.disabled
= true;
67 var localstream
= null;
68 var processedLocalstream
= null;
69 var effectsPlugin
= null;
70 var effectsEnabled
= false;
72 function trace(text
) {
73 // This function is used for logging.
74 if (text
[text
.length
- 1] == '\n') {
75 text
= text
.substring(0, text
.length
- 1);
77 console
.log((performance
.now() / 1000).toFixed(3) + ": " + text
);
80 function gotStream(stream
){
81 trace("Received local stream");
82 // Call the polyfill wrapper to attach the media stream to this element.
83 attachMediaStream(vidlocal
, stream
);
85 callButton
.disabled
= false;
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() {});
97 function onRegisterStreamDone() {
98 vidprocessedlocal
.src
= URL
.createObjectURL(processedLocalstream
);
99 toggleEffectButton
.disabled
= false;
102 function HandleMessage(message_event
) {
103 if (message_event
.data
) {
104 if (message_event
.data
== 'DoneRegistering') {
105 onRegisterStreamDone();
107 trace(message_event
.data
);
112 function initEffect() {
113 var url
= URL
.createObjectURL(localstream
);
114 processedLocalstream
= new webkitMediaStream([]);
115 var processedStreamUrl
= URL
.createObjectURL(processedLocalstream
);
116 effectsPlugin
.postMessage(
117 'registerStream' + ' ' + url
+ ' ' + processedStreamUrl
);
120 function toggleEffect() {
121 effectsEnabled
= !effectsEnabled
;
122 if (effectsEnabled
) {
123 toggleEffectButton
.innerHTML
= 'Disable Effect';
124 effectsPlugin
.postMessage('effectOn');
126 toggleEffectButton
.innerHTML
= 'Enable Effect';
127 effectsPlugin
.postMessage('effectOff');
132 callButton
.disabled
= true;
133 hangupButton
.disabled
= false;
134 trace("Starting call");
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
;
144 pc1
.addStream(processedLocalstream
);
145 trace("Adding Local Stream to peer connection");
147 pc1
.createOffer(gotDescription1
);
150 function 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
);
163 function gotDescription2(desc
){
164 pc2
.setLocalDescription(desc
);
165 trace("Answer from pc2 \n" + desc
.sdp
);
166 pc1
.setRemoteDescription(desc
);
170 trace("Ending call");
175 hangupButton
.disabled
= true;
176 callButton
.disabled
= false;
179 function gotRemoteStream(e
){
180 vidremote
.src
= URL
.createObjectURL(e
.stream
);
181 trace("Received remote stream");
184 function iceCallback1(event
){
185 if (event
.candidate
) {
186 pc2
.addIceCandidate(new RTCIceCandidate(event
.candidate
));
187 trace("Local ICE candidate: \n" + event
.candidate
.candidate
);
191 function iceCallback2(event
){
192 if (event
.candidate
) {
193 pc1
.addIceCandidate(new RTCIceCandidate(event
.candidate
));
194 trace("Remote ICE candidate: \n " + event
.candidate
.candidate
);
198 function InitializePlugin() {
199 effectsPlugin
= document
.getElementById('plugin');
200 effectsPlugin
.addEventListener('message', HandleMessage
, false);
203 document
.addEventListener('DOMContentLoaded', InitializePlugin
, false);