Home | History | Annotate | Download | only in video_effects
      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>
     11 video {
     12   border:5px solid black;
     13   width:480px;
     14   height:360px;
     15 }
     16 button {
     17   font: 18px sans-serif;
     18   padding: 8px;
     19 }
     20 textarea {
     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>
     52 var RTCPeerConnection = webkitRTCPeerConnection;
     53 var getUserMedia = navigator.webkitGetUserMedia.bind(navigator);
     54 var attachMediaStream = function(element, stream) {
     55   element.src = webkitURL.createObjectURL(stream);
     56 };
     57 var startButton = document.getElementById('startButton');
     58 var toggleEffectButton = document.getElementById('toggleEffectButton');
     59 var callButton = document.getElementById('callButton');
     60 var hangupButton = document.getElementById('hangupButton');
     61 
     62 callButton.disabled = true;
     63 hangupButton.disabled = true;
     64 toggleEffectButton.disabled = true;
     65 var pc1 = null;
     66 var pc2 = null;
     67 var localstream = null;
     68 var processedLocalstream = null;
     69 var effectsPlugin = null;
     70 var effectsEnabled = false;
     71 
     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);
     76   }
     77   console.log((performance.now() / 1000).toFixed(3) + ": " + text);
     78 }
     79 
     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);
     84   localstream = stream;
     85   callButton.disabled = false;
     86   initEffect();
     87 }
     88 
     89 function 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 
     97 function onRegisterStreamDone() {
     98   vidprocessedlocal.src = webkitURL.createObjectURL(processedLocalstream);
     99   toggleEffectButton.disabled = false;
    100 }
    101 
    102 function 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 
    112 function initEffect() {
    113   var url = webkitURL.createObjectURL(localstream);
    114   processedLocalstream = new webkitMediaStream([]);
    115   var processedStreamUrl = webkitURL.createObjectURL(processedLocalstream);
    116   effectsPlugin.postMessage(
    117       'registerStream' + ' ' + url + ' ' + processedStreamUrl);
    118 }
    119 
    120 function 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     
    131 function 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 
    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);
    161 }
    162 
    163 function gotDescription2(desc){
    164   pc2.setLocalDescription(desc);
    165   trace("Answer from pc2 \n" + desc.sdp);
    166   pc1.setRemoteDescription(desc);
    167 }
    168 
    169 function 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 
    179 function gotRemoteStream(e){
    180   vidremote.src = webkitURL.createObjectURL(e.stream);
    181   trace("Received remote stream");
    182 }
    183 
    184 function 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       
    191 function 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 
    198 function InitializePlugin() {
    199   effectsPlugin = document.getElementById('plugin');
    200   effectsPlugin.addEventListener('message', HandleMessage, false);
    201 }
    202 
    203 document.addEventListener('DOMContentLoaded', InitializePlugin, false);
    204 </script>
    205 </body>
    206 </html>
    207 
    208 
    209