Adding codec constraints page to webrtc.

Delete videoCall page to avoid duplication. 

Bug: webrtc:653087
Change-Id: If44bed19c4323231e9a4348814f19c9694c17a36
Reviewed-on: https://chromium-review.googlesource.com/616770
Commit-Queue: Charu Jain <charujain@google.com>
Reviewed-by: Ned Nguyen <nednguyen@google.com>
Cr-Original-Commit-Position: refs/heads/master@{#494835}
Cr-Mirrored-From: https://chromium.googlesource.com/chromium/src
Cr-Mirrored-Commit: 3d5fa21f1d6516eac36cc1bc963d3072df9d96d9
diff --git a/perf/page_sets/update_webrtc_cases b/perf/page_sets/update_webrtc_cases
index 01f55fe..b76cd38 100755
--- a/perf/page_sets/update_webrtc_cases
+++ b/perf/page_sets/update_webrtc_cases
@@ -21,16 +21,16 @@
     'test-pages': {
         'dirs': [
             'src/canvas-capture',
+            'src/codec_constraints',
             'src/multiple-peerconnections',
             'src/pause-play',
         ],
-        'revision': 'cbb12a3994692c63c9d885c95db0f67c5e3e3465',
+        'revision': '9f0ff9343a38dbf16199a964a18d7411d940c601',
     },
     'samples': {
         'dirs': [
             'src/content/datachannel/datatransfer',
             'src/content/getusermedia/resolution',
-            'src/content/peerconnection/constraints',
             'src/content/peerconnection/audio',
         ],
         'files': [
diff --git a/perf/page_sets/webrtc_cases.py b/perf/page_sets/webrtc_cases.py
index 66155b9..e462cb8 100644
--- a/perf/page_sets/webrtc_cases.py
+++ b/perf/page_sets/webrtc_cases.py
@@ -28,28 +28,6 @@
     action_runner.Wait(10)
 
 
-class VideoCall(WebrtcPage):
-  """Why: Sets up a local video-only WebRTC 720p call for 45 seconds."""
-
-  def __init__(self, page_set, tags):
-    super(VideoCall, self).__init__(
-        url='file://webrtc_cases/constraints.html',
-        name='720p_call_45s',
-        page_set=page_set, tags=tags)
-
-  def RunPageInteractions(self, action_runner):
-    with action_runner.CreateInteraction('Action_Create_PeerConnection',
-                                         repeatable=False):
-      action_runner.ExecuteJavaScript('minWidthInput.value = 1280')
-      action_runner.ExecuteJavaScript('maxWidthInput.value = 1280')
-      action_runner.ExecuteJavaScript('minHeightInput.value = 720')
-      action_runner.ExecuteJavaScript('maxHeightInput.value = 720')
-      action_runner.ClickElement('button[id="getMedia"]')
-      action_runner.Wait(2)
-      action_runner.ClickElement('button[id="connect"]')
-      action_runner.Wait(45)
-
-
 class DataChannel(WebrtcPage):
   """Why: Transfer as much data as possible through a data channel in 10s."""
 
@@ -96,6 +74,26 @@
       action_runner.Wait(10)
 
 
+class VideoCodecConstraints(WebrtcPage):
+  """Why: Sets up a video codec to a peer connection."""
+
+  def __init__(self, page_set, video_codec, tags):
+    super(VideoCodecConstraints, self).__init__(
+        url='file://webrtc_cases/codec_constraints.html',
+        name='codec_constraints_%s' % video_codec.lower(),
+        page_set=page_set, tags=tags)
+    self.video_codec = video_codec
+
+  def RunPageInteractions(self, action_runner):
+    with action_runner.CreateInteraction('Action_Codec_Constraints',
+                                         repeatable=False):
+      action_runner.ClickElement('input[id="%s"]' % self.video_codec)
+      action_runner.ClickElement('button[id="startButton"]')
+      action_runner.ClickElement('button[id="callButton"]')
+      action_runner.Wait(20)
+      action_runner.ClickElement('button[id="hangupButton"]')
+
+
 class MultiplePeerConnections(WebrtcPage):
   """Why: Sets up several peer connections in the same page."""
 
@@ -143,9 +141,11 @@
     self.AddStory(MultiplePeerConnections(self, tags=['stress']))
     self.AddStory(DataChannel(self, tags=['datachannel']))
     self.AddStory(GetUserMedia(self, tags=['getusermedia']))
-    self.AddStory(VideoCall(self, tags=['peerconnection', 'smoothness']))
     self.AddStory(CanvasCapturePeerConnection(self, tags=['smoothness']))
     self.AddStory(AudioCall(self, 'OPUS', tags=['audio']))
     self.AddStory(AudioCall(self, 'G772', tags=['audio']))
     self.AddStory(AudioCall(self, 'PCMU', tags=['audio']))
     self.AddStory(AudioCall(self, 'ISAC/1600', tags=['audio']))
+    self.AddStory(VideoCodecConstraints(self, 'H264', tags=['videoConstraints']))
+    self.AddStory(VideoCodecConstraints(self, 'VP8', tags=['videoConstraints']))
+    self.AddStory(VideoCodecConstraints(self, 'VP9', tags=['videoConstraints']))
diff --git a/perf/page_sets/webrtc_cases/codec_constraints.html b/perf/page_sets/webrtc_cases/codec_constraints.html
new file mode 100644
index 0000000..1e85c49
--- /dev/null
+++ b/perf/page_sets/webrtc_cases/codec_constraints.html
@@ -0,0 +1,56 @@
+<!DOCTYPE html>
+<!--
+ * Copyright 2017 The Chromium Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+-->
+<html>
+<head>
+
+
+  <base target="_blank">
+
+  <title>Video codec constraints</title>
+
+
+</head>
+
+<body>
+
+  <div id="container">
+
+    <div class="highlight">
+      <p>New codelab: <a href="https://codelabs.developers.google.com/codelabs/webrtc-web">Realtime communication with WebRTC</a></p>
+    </div>
+
+    <h1><a href="//webrtc.github.io/samples/" title="WebRTC samples homepage">WebRTC samples</a> <span>Peer connection with codec constraints</span></h1>
+
+    <video id="localVideo" autoplay muted></video>
+    <video id="remoteVideo" autoplay></video>
+
+    <div>
+       <h2>Video Codec Constraints</h2>
+       <input type="radio" id="H264" name="Codec" value="H264" checked>H264<br>
+       <input type="radio" id="VP8" name="Codec" value="VP8" checked>VP8<br>
+       <input type="radio" id="VP9" name="Codec" value="VP9" checked>VP9<br><br>
+    </div>
+    <div>
+      <button id="startButton">Start</button>
+      <button id="callButton">Call</button>
+      <button id="hangupButton">Hang Up</button>
+    </div>
+
+    <p>View the console to see logging. The <code>MediaStream</code> object <code>localStream</code>, and the <code>RTCPeerConnection</code> objects <code>pc1</code> and <code>pc2</code> are in global scope, so you can inspect them in the console as well.</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/peerconnection/codec_constraints" title="View source for this page on GitHub" id="viewSource">View source on GitHub</a>
+
+  </div>
+
+
+<script src="codec_constraints.js"></script>
+<script src="adapter.js"></script>
+<script src="common.js"></script>
+</body></html>
diff --git a/perf/page_sets/webrtc_cases/codec_constraints.js b/perf/page_sets/webrtc_cases/codec_constraints.js
new file mode 100644
index 0000000..1a1cf91
--- /dev/null
+++ b/perf/page_sets/webrtc_cases/codec_constraints.js
@@ -0,0 +1,417 @@
+/*
+ * Copyright 2017 The Chromium Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+'use strict';
+
+var startButton = document.getElementById('startButton');
+var callButton = document.getElementById('callButton');
+var hangupButton = document.getElementById('hangupButton');
+callButton.disabled = true;
+hangupButton.disabled = true;
+startButton.onclick = start;
+callButton.onclick = startTest;
+hangupButton.onclick = hangup;
+
+var startTime;
+var localVideo = document.getElementById('localVideo');
+var remoteVideo = document.getElementById('remoteVideo');
+
+function trace(arg) {
+  var now = (window.performance.now() / 1000).toFixed(3);
+  console.log(now + ': ', arg);
+}
+
+function getSelectedVideoCodec() {
+  var codec;
+  if (document.getElementById('H264').checked) {
+    codec = document.getElementById('H264').value;
+  } else if (document.getElementById('VP8').checked) {
+    codec = document.getElementById('VP8').value;
+  } else {
+    codec = document.getElementById('VP9').value;
+  }
+  return codec;
+}
+
+function Failure(message) {
+  this.message = message;
+  this.name = 'Failure';
+}
+
+localVideo.addEventListener('loadedmetadata', function() {
+  trace('Local video videoWidth: ' + this.videoWidth +
+    'px,  videoHeight: ' + this.videoHeight + 'px');
+});
+
+remoteVideo.addEventListener('loadedmetadata', function() {
+  trace('Remote video videoWidth: ' + this.videoWidth +
+    'px,  videoHeight: ' + this.videoHeight + 'px');
+});
+
+remoteVideo.onresize = function() {
+  trace('Remote video size changed to ' +
+    remoteVideo.videoWidth + 'x' + remoteVideo.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;
+  }
+};
+
+var localStream;
+var pc1;
+var pc2;
+var offerOptions = {
+  offerToReceiveAudio: 1,
+  offerToReceiveVideo: 1
+};
+
+function getName(pc) {
+  return (pc === pc1) ? 'pc1' : 'pc2';
+}
+
+function getOtherPc(pc) {
+  return (pc === pc1) ? pc2 : pc1;
+}
+
+function gotStream(stream) {
+  trace('Received local stream');
+  localVideo.srcObject = stream;
+  localStream = stream;
+  callButton.disabled = false;
+}
+
+function start() {
+  trace('Requesting local stream');
+  startButton.disabled = true;
+  navigator.mediaDevices.getUserMedia({
+    audio: true,
+    video: {
+      width: {exact: 1280},
+      height: {exact: 720},
+    },
+  })
+    .then(gotStream)
+    .catch(function(e) {
+      alert('getUserMedia() error: ' + e.name);
+    });
+}
+
+function call() {
+  callButton.disabled = true;
+  hangupButton.disabled = false;
+  trace('Starting call');
+  startTime = window.performance.now();
+  var videoTracks = localStream.getVideoTracks();
+  var audioTracks = localStream.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.ontrack = gotRemoteStream;
+
+  localStream.getTracks().forEach(
+    function(track) {
+      pc1.addTrack(
+        track,
+        localStream
+      );
+    }
+  );
+  trace('Added local stream to pc1');
+
+  trace('pc1 createOffer start');
+  pc1.createOffer(
+    offerOptions
+  ).then(
+    onCreateOfferSuccess,
+    onCreateSessionDescriptionError
+  );
+}
+
+function onCreateSessionDescriptionError(error) {
+  trace('Failed to create session description: ' + error.toString());
+}
+
+/**
+ * See |setSdpDefaultCodec|.
+ */
+function setSdpDefaultVideoCodec(sdp, codec, preferHwCodec) {
+  return setSdpDefaultCodec(sdp, 'video', codec, preferHwCodec);
+}
+
+/**
+ * Returns a modified version of |sdp| where the |codec| has been promoted to be
+ * the default codec, i.e. the codec whose ID is first in the list of codecs on
+ * the 'm=|type|' line, where |type| is 'audio' or 'video'. If |preferHwCodec|
+ * is true, it will select the last codec with the given name, and if false, it
+ * will select the first codec with the given name, because HW codecs are listed
+ * after SW codecs in the SDP list.
+ * @private
+ */
+function setSdpDefaultCodec(sdp, type, codec, preferHwCodec) {
+  var sdpLines = splitSdpLines(sdp);
+
+  // Find codec ID, e.g. 100 for 'VP8' if 'a=rtpmap:100 VP8/9000'.
+  var codecId = findRtpmapId(sdpLines, codec, preferHwCodec);
+  if (codecId === null) {
+    throw new Failure('setSdpDefaultCodec',
+      'Unknown ID for |codec| = \'' + codec + '\'.');
+  }
+
+  // Find 'm=|type|' line, e.g. 'm=video 9 UDP/TLS/RTP/SAVPF 100 101 107 116'.
+  var mLineNo = findLine(sdpLines, 'm=' + type);
+  if (mLineNo === null) {
+    throw new Failure('setSdpDefaultCodec',
+      '\'m=' + type + '\' line missing from |sdp|.');
+  }
+
+  // Modify video line to use the desired codec as the default.
+  sdpLines[mLineNo] = setMLineDefaultCodec(sdpLines[mLineNo], codecId);
+  return mergeSdpLines(sdpLines);
+}
+
+/**
+ * Searches through all |sdpLines| for the 'a=rtpmap:' line for the codec of
+ * the specified name, returning its ID as an int if found, or null otherwise.
+ * |codec| is the case-sensitive name of the codec. If |lastInstance|
+ * is true, it will return the last such ID, and if false, it will return the
+ * first such ID.
+ * For example, if |sdpLines| contains 'a=rtpmap:100 VP8/9000' and |codec| is
+ * 'VP8', this function returns 100.
+ * @private
+ */
+function findRtpmapId(sdpLines, codec, lastInstance) {
+  var lineNo = findRtpmapLine(sdpLines, codec, lastInstance);
+  if (lineNo === null) {
+    return null;
+  }
+  // Parse <id> from 'a=rtpmap:<id> <codec>/<rate>'.
+  var id = sdpLines[lineNo].substring(9, sdpLines[lineNo].indexOf(' '));
+  return parseInt(id);
+}
+
+/**
+ * Finds a 'a=rtpmap:' line from |sdpLines| that contains |contains| and returns
+ * its line index, or null if no such line was found. |contains| may be the
+ * codec ID, codec name or bitrate. If |lastInstance| is true, it will return
+ * the last such line index, and if false, it will return the first such line
+ * index.
+ * An 'a=rtpmap:' line looks like this: 'a=rtpmap:<id> <codec>/<rate>'.
+ */
+function findRtpmapLine(sdpLines, contains, lastInstance) {
+  if (lastInstance === true) {
+    for (var i = sdpLines.length - 1; i >= 0 ; i--) {
+      if (isRtpmapLine(sdpLines[i], contains)) {
+        return i;
+      }
+    }
+  } else {
+    for (i = 0; i < sdpLines.length; i++) {
+      if (isRtpmapLine(sdpLines[i], contains)) {
+        return i;
+      }
+    }
+  }
+  return null;
+}
+
+/**
+ * Returns true if |sdpLine| contains |contains| and is of pattern
+ * 'a=rtpmap:<id> <codec>/<rate>'.
+ */
+function isRtpmapLine(sdpLine, contains) {
+  // Is 'a=rtpmap:' line containing |contains| string?
+  if (sdpLine.startsWith('a=rtpmap:') &&
+      sdpLine.indexOf(contains) !== -1) {
+    // Expecting pattern 'a=rtpmap:<id> <codec>/<rate>'.
+    var pattern = new RegExp('a=rtpmap:(\\d+) \\w+\\/\\d+');
+    if (!sdpLine.match(pattern)) {
+      throw new Failure('isRtpmapLine', 'Unexpected "a=rtpmap:" pattern.');
+    }
+    return true;
+  }
+  return false;
+}
+
+/**
+ * Returns a modified version of |mLine| that has |codecId| first in the list of
+ * codec IDs. For example, setMLineDefaultCodec(
+ *     'm=video 9 UDP/TLS/RTP/SAVPF 100 101 107 116 117 96', 107)
+ * Returns:
+ *     'm=video 9 UDP/TLS/RTP/SAVPF 107 100 101 116 117 96'
+ * @private
+ */
+function setMLineDefaultCodec(mLine, codecId) {
+  var elements = mLine.split(' ');
+
+  // Copy first three elements, codec order starts on fourth.
+  var newLine = elements.slice(0, 3);
+
+  // Put target |codecId| first and copy the rest.
+  newLine.push(codecId);
+  for (var i = 3; i < elements.length; i++) {
+    if (elements[i] !== codecId) {
+      newLine.push(elements[i]);
+    }
+  }
+
+  return newLine.join(' ');
+}
+
+/** @private */
+function splitSdpLines(sdp) {
+  return sdp.split('\r\n');
+}
+
+/** @private */
+function mergeSdpLines(sdpLines) {
+  return sdpLines.join('\r\n');
+}
+
+/** @private */
+function findLine(lines, lineStartsWith, startingLine = 0) {
+  for (var i = startingLine; i < lines.length; i++) {
+    if (lines[i].startsWith(lineStartsWith)) {
+      return i;
+    }
+  }
+  return null;
+}
+
+function onCreateOfferSuccess(desc) {
+  var videoCodec = getSelectedVideoCodec();
+  desc.sdp = setSdpDefaultVideoCodec(desc.sdp, videoCodec, videoCodec);
+  trace('Offer from pc1\n' + desc.sdp);
+  trace('Ok-' + JSON.stringify(desc));
+  trace('pc1 setLocalDescription start');
+  pc1.setLocalDescription(desc).then(
+    function() {
+      onSetLocalSuccess(pc1);
+    },
+    onSetSessionDescriptionError
+  );
+  trace('pc2 setRemoteDescription start');
+  pc2.setRemoteDescription(desc).then(
+    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().then(
+    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 startTest() {
+  call();
+  setInterval(() => {
+    pc1.getStats((response) => {
+      trace(response);
+    });
+  }, 10 * 1000);
+}
+
+function gotRemoteStream(e) {
+  if (remoteVideo.srcObject !== e.streams[0]) {
+    remoteVideo.srcObject = e.streams[0];
+    trace('pc2 received remote stream');
+  }
+}
+
+function onCreateAnswerSuccess(desc) {
+  trace('Answer from pc2:\n' + desc.sdp);
+  trace('pc2 setLocalDescription start');
+  pc2.setLocalDescription(desc).then(
+    function() {
+      onSetLocalSuccess(pc2);
+    },
+    onSetSessionDescriptionError
+  );
+  trace('pc1 setRemoteDescription start');
+  pc1.setRemoteDescription(desc).then(
+    function() {
+      onSetRemoteSuccess(pc1);
+    },
+    onSetSessionDescriptionError
+  );
+}
+
+function onIceCandidate(pc, event) {
+  getOtherPc(pc).addIceCandidate(event.candidate)
+    .then(
+      function() {
+        onAddIceCandidateSuccess(pc);
+      },
+      function(err) {
+        onAddIceCandidateError(pc, err);
+      }
+    );
+  trace(getName(pc) + ' ICE candidate: \n' + (event.candidate ?
+    event.candidate.candidate : '(null)'));
+}
+
+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 hangup() {
+  trace('Ending call');
+  pc1.close();
+  pc2.close();
+  pc1 = null;
+  pc2 = null;
+  hangupButton.disabled = true;
+  callButton.disabled = false;
+}
diff --git a/perf/page_sets/webrtc_cases/constraints.html b/perf/page_sets/webrtc_cases/constraints.html
deleted file mode 100644
index e094ae6..0000000
--- a/perf/page_sets/webrtc_cases/constraints.html
+++ /dev/null
@@ -1,99 +0,0 @@
-<!DOCTYPE html>
-<!--
- * Copyright 2017 The Chromium Authors. All rights reserved.
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
--->
-<html>
-<head>
-
-
-  <base target="_blank">
-
-  <title>Constraints and statistics</title>
-
-
-</head>
-
-<body>
-
-  <div id="container">
-
-    <h1><a href="//webrtc.github.io/samples/" title="WebRTC samples homepage">WebRTC samples</a> <span>Constraints &amp; statistics</span></h1>
-
-    <section id="blurb">
-      <p>This demo shows ways to use constraints and statistics in WebRTC applications.</p>
-      <p>Set camera constraints, and click <strong>Get media</strong> to (re)open the camera with these included. Click <strong>Connect</strong> to create a (local) peer connection. The RTCPeerConnection objects <code>localPeerConnection</code> and <code>remotePeerConnection</code> can be inspected from the console.</p>
-      <p>Setting a value to zero will remove that constraint. </p>
-      <p>The lefthand video shows the output of <code>getUserMedia()</code>; on the right is the video after being passed through the peer connection. The transmission bitrate is displayed below the righthand video.</p>
-    </section>
-
-    <div>
-      <button id="getMedia">Get media</button>
-      <button id="connect" disabled>Connect</button>
-      <button id="hangup" disabled>Hang Up</button>
-    </div>
-
-
-    <section id="constraints">
-      <div id="getUserMedia">
-        <div class="input">
-          <h2>Camera constraints</h2>
-          <div id="minWidth">
-            <label>Min width <span>300</span>px:</label>
-            <input type="range" min="0" max="1920" value="300">
-          </div>
-          <div id="maxWidth">
-            <label>Max width <span>640</span>px:</label>
-            <input type="range" min="0" max="1920" value="640">
-          </div>
-          <div id="minHeight">
-            <label>Min height <span>200</span>px:</label>
-            <input type="range" min="0" max="1080" value="200">
-          </div>
-          <div id="maxHeight">
-            <label>Max height <span>480</span>px:</label>
-            <input type="range" min="0" max="1080" value="480">
-          </div>
-          <div id="minFramerate">
-            <label>Min frameRate <span>0</span>fps:</label>
-            <input type="range" min="0" max="60" value="0">
-          </div>
-          <div id="maxFramerate">
-            <label>Max frameRate <span>0</span>fps:</label>
-            <input type="range" min="0" max="60" value="0">
-          </div>
-        </div>
-        <div id="getUserMediaConstraints" class="output"></div>
-      </div>
-
-    </section>
-
-    <section id="video">
-      <div id="localVideo">
-        <video autoplay muted></video>
-        <div></div>
-      </div>
-      <div id="remoteVideo">
-        <video autoplay muted></video>
-        <div></div>
-        <div id="bitrate"></div>
-        <div id="peer"></div>
-      </div>
-    </section>
-
-    <section id="statistics">
-      <div id="senderStats"></div>
-      <div id="receiverStats"></div>
-    </section>
-
-    <a href="https://github.com/webrtc/samples/tree/gh-pages/src/content/peerconnection/constraints" title="View source for this page on GitHub" id="viewSource">View source on GitHub</a>
-
-  </div>
-
-
-
-<script src="constraints.js"></script>
-<script src="adapter.js"></script>
-<script src="common.js"></script>
-</body></html>
diff --git a/perf/page_sets/webrtc_cases/constraints.js b/perf/page_sets/webrtc_cases/constraints.js
deleted file mode 100644
index d19d212..0000000
--- a/perf/page_sets/webrtc_cases/constraints.js
+++ /dev/null
@@ -1,325 +0,0 @@
-/*
- * Copyright 2017 The Chromium Authors. All rights reserved.
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-'use strict';
-
-var getMediaButton = document.querySelector('button#getMedia');
-var connectButton = document.querySelector('button#connect');
-var hangupButton = document.querySelector('button#hangup');
-
-getMediaButton.onclick = getMedia;
-connectButton.onclick = createPeerConnection;
-hangupButton.onclick = hangup;
-
-var minWidthInput = document.querySelector('div#minWidth input');
-var maxWidthInput = document.querySelector('div#maxWidth input');
-var minHeightInput = document.querySelector('div#minHeight input');
-var maxHeightInput = document.querySelector('div#maxHeight input');
-var minFramerateInput = document.querySelector('div#minFramerate input');
-var maxFramerateInput = document.querySelector('div#maxFramerate input');
-
-minWidthInput.onchange = maxWidthInput.onchange =
-    minHeightInput.onchange = maxHeightInput.onchange =
-    minFramerateInput.onchange = maxFramerateInput.onchange = displayRangeValue;
-
-var getUserMediaConstraintsDiv =
-    document.querySelector('div#getUserMediaConstraints');
-var bitrateDiv = document.querySelector('div#bitrate');
-var peerDiv = document.querySelector('div#peer');
-var senderStatsDiv = document.querySelector('div#senderStats');
-var receiverStatsDiv = document.querySelector('div#receiverStats');
-
-var localVideo = document.querySelector('div#localVideo video');
-var remoteVideo = document.querySelector('div#remoteVideo video');
-var localVideoStatsDiv = document.querySelector('div#localVideo div');
-var remoteVideoStatsDiv = document.querySelector('div#remoteVideo div');
-
-var localPeerConnection;
-var remotePeerConnection;
-var localStream;
-var bytesPrev;
-var timestampPrev;
-
-main();
-
-function main() {
-  displayGetUserMediaConstraints();
-}
-
-function hangup() {
-  trace('Ending call');
-  localPeerConnection.close();
-  remotePeerConnection.close();
-  localPeerConnection = null;
-  remotePeerConnection = null;
-
-  localStream.getTracks().forEach(function(track) {
-    track.stop();
-  });
-  localStream = null;
-
-  hangupButton.disabled = true;
-  getMediaButton.disabled = false;
-}
-
-function getMedia() {
-  getMediaButton.disabled = true;
-  if (localStream) {
-    localStream.getTracks().forEach(function(track) {
-      track.stop();
-    });
-    var videoTracks = localStream.getVideoTracks();
-    for (var i = 0; i !== videoTracks.length; ++i) {
-      videoTracks[i].stop();
-    }
-  }
-  navigator.mediaDevices.getUserMedia(getUserMediaConstraints())
-  .then(gotStream)
-  .catch(function(e) {
-    var message = 'getUserMedia error: ' + e.name + '\n' +
-        'PermissionDeniedError may mean invalid constraints.';
-    alert(message);
-    console.log(message);
-    getMediaButton.disabled = false;
-  });
-}
-
-function gotStream(stream) {
-  connectButton.disabled = false;
-  console.log('GetUserMedia succeeded');
-  localStream = stream;
-  localVideo.srcObject = stream;
-}
-
-function getUserMediaConstraints() {
-  var constraints = {};
-  constraints.audio = true;
-  constraints.video = {};
-  if (minWidthInput.value !== '0') {
-    constraints.video.width = {};
-    constraints.video.width.min = minWidthInput.value;
-  }
-  if (maxWidthInput.value !== '0') {
-    constraints.video.width = constraints.video.width || {};
-    constraints.video.width.max = maxWidthInput.value;
-  }
-  if (minHeightInput.value !== '0') {
-    constraints.video.height = {};
-    constraints.video.height.min = minHeightInput.value;
-  }
-  if (maxHeightInput.value !== '0') {
-    constraints.video.height = constraints.video.height || {};
-    constraints.video.height.max = maxHeightInput.value;
-  }
-  if (minFramerateInput.value !== '0') {
-    constraints.video.frameRate = {};
-    constraints.video.frameRate.min = minFramerateInput.value;
-  }
-  if (maxFramerateInput.value !== '0') {
-    constraints.video.frameRate = constraints.video.frameRate || {};
-    constraints.video.frameRate.max = maxFramerateInput.value;
-  }
-
-  return constraints;
-}
-
-function displayGetUserMediaConstraints() {
-  var constraints = getUserMediaConstraints();
-  console.log('getUserMedia constraints', constraints);
-  getUserMediaConstraintsDiv.textContent =
-      JSON.stringify(constraints, null, '    ');
-}
-
-function createPeerConnection() {
-  connectButton.disabled = true;
-  hangupButton.disabled = false;
-
-  bytesPrev = 0;
-  timestampPrev = 0;
-  localPeerConnection = new RTCPeerConnection(null);
-  remotePeerConnection = new RTCPeerConnection(null);
-  localStream.getTracks().forEach(
-    function(track) {
-      localPeerConnection.addTrack(
-        track,
-        localStream
-      );
-    }
-  );
-  console.log('localPeerConnection creating offer');
-  localPeerConnection.onnegotiationeeded = function() {
-    console.log('Negotiation needed - localPeerConnection');
-  };
-  remotePeerConnection.onnegotiationeeded = function() {
-    console.log('Negotiation needed - remotePeerConnection');
-  };
-  localPeerConnection.onicecandidate = function(e) {
-    console.log('Candidate localPeerConnection');
-    remotePeerConnection.addIceCandidate(e.candidate)
-    .then(
-      onAddIceCandidateSuccess,
-      onAddIceCandidateError
-    );
-  };
-  remotePeerConnection.onicecandidate = function(e) {
-    console.log('Candidate remotePeerConnection');
-    localPeerConnection.addIceCandidate(e.candidate)
-    .then(
-      onAddIceCandidateSuccess,
-      onAddIceCandidateError
-    );
-  };
-  remotePeerConnection.ontrack = function(e) {
-    if (remoteVideo.srcObject !== e.streams[0]) {
-      console.log('remotePeerConnection got stream');
-      remoteVideo.srcObject = e.streams[0];
-    }
-  };
-  localPeerConnection.createOffer().then(
-    function(desc) {
-      console.log('localPeerConnection offering');
-      localPeerConnection.setLocalDescription(desc);
-      remotePeerConnection.setRemoteDescription(desc);
-      remotePeerConnection.createAnswer().then(
-        function(desc2) {
-          console.log('remotePeerConnection answering');
-          remotePeerConnection.setLocalDescription(desc2);
-          localPeerConnection.setRemoteDescription(desc2);
-        },
-        function(err) {
-          console.log(err);
-        }
-      );
-    },
-    function(err) {
-      console.log(err);
-    }
-  );
-}
-
-function onAddIceCandidateSuccess() {
-  trace('AddIceCandidate success.');
-}
-
-function onAddIceCandidateError(error) {
-  trace('Failed to add Ice Candidate: ' + error.toString());
-}
-
-// Display statistics
-setInterval(function() {
-  if (remotePeerConnection && remotePeerConnection.getRemoteStreams()[0]) {
-    remotePeerConnection.getStats(null)
-    .then(function(results) {
-      var statsString = dumpStats(results);
-      receiverStatsDiv.innerHTML = '<h2>Receiver stats</h2>' + statsString;
-      // calculate video bitrate
-      results.forEach(function(report) {
-        var now = report.timestamp;
-
-        var bitrate;
-        if (report.type === 'inboundrtp' && report.mediaType === 'video') {
-          // firefox calculates the bitrate for us
-          // https://bugzilla.mozilla.org/show_bug.cgi?id=951496
-          bitrate = Math.floor(report.bitrateMean / 1024);
-        } else if (report.type === 'ssrc' && report.bytesReceived &&
-             report.googFrameHeightReceived) {
-          // chrome does not so we need to do it ourselves
-          var bytes = report.bytesReceived;
-          if (timestampPrev) {
-            bitrate = 8 * (bytes - bytesPrev) / (now - timestampPrev);
-            bitrate = Math.floor(bitrate);
-          }
-          bytesPrev = bytes;
-          timestampPrev = now;
-        }
-        if (bitrate) {
-          bitrate += ' kbits/sec';
-          bitrateDiv.innerHTML = '<strong>Bitrate:</strong> ' + bitrate;
-        }
-      });
-
-      // figure out the peer's ip
-      var activeCandidatePair = null;
-      var remoteCandidate = null;
-
-      // Search for the candidate pair, spec-way first.
-      results.forEach(function(report) {
-        if (report.type === 'transport') {
-          activeCandidatePair = results.get(report.selectedCandidatePairId);
-        }
-      });
-      // Fallback for Firefox and Chrome legacy stats.
-      if (!activeCandidatePair) {
-        results.forEach(function(report) {
-          if (report.type === 'candidate-pair' && report.selected ||
-              report.type === 'googCandidatePair' &&
-              report.googActiveConnection === 'true') {
-            activeCandidatePair = report;
-          }
-        });
-      }
-      if (activeCandidatePair && activeCandidatePair.remoteCandidateId) {
-        remoteCandidate = results.get(activeCandidatePair.remoteCandidateId);
-      }
-      if (remoteCandidate) {
-        if (remoteCandidate.ip && remoteCandidate.port) {
-          peerDiv.innerHTML = '<strong>Connected to:</strong> ' +
-              remoteCandidate.ip + ':' + remoteCandidate.port;
-        } else if (remoteCandidate.ipAddress && remoteCandidate.portNumber) {
-          // Fall back to old names.
-          peerDiv.innerHTML = '<strong>Connected to:</strong> ' +
-              remoteCandidate.ipAddress +
-              ':' + remoteCandidate.portNumber;
-        }
-      }
-    }, function(err) {
-      console.log(err);
-    });
-    localPeerConnection.getStats(null)
-    .then(function(results) {
-      var statsString = dumpStats(results);
-      senderStatsDiv.innerHTML = '<h2>Sender stats</h2>' + statsString;
-    }, function(err) {
-      console.log(err);
-    });
-  } else {
-    console.log('Not connected yet');
-  }
-  // Collect some stats from the video tags.
-  if (localVideo.videoWidth) {
-    localVideoStatsDiv.innerHTML = '<strong>Video dimensions:</strong> ' +
-      localVideo.videoWidth + 'x' + localVideo.videoHeight + 'px';
-  }
-  if (remoteVideo.videoWidth) {
-    remoteVideoStatsDiv.innerHTML = '<strong>Video dimensions:</strong> ' +
-      remoteVideo.videoWidth + 'x' + remoteVideo.videoHeight + 'px';
-  }
-}, 1000);
-
-// Dumping a stats variable as a string.
-// might be named toString?
-function dumpStats(results) {
-  var statsString = '';
-  results.forEach(function(res) {
-    statsString += '<h3>Report type=';
-    statsString += res.type;
-    statsString += '</h3>\n';
-    statsString += 'id ' + res.id + '<br>\n';
-    statsString += 'time ' + res.timestamp + '<br>\n';
-    Object.keys(res).forEach(function(k) {
-      if (k !== 'timestamp' && k !== 'type' && k !== 'id') {
-        statsString += k + ': ' + res[k] + '<br>\n';
-      }
-    });
-  });
-  return statsString;
-}
-
-// Utility to show the value of a range in a sibling span element
-function displayRangeValue(e) {
-  var span = e.target.parentElement.querySelector('span');
-  span.textContent = e.target.value;
-  displayGetUserMediaConstraints();
-}