15d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved.
25d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// found in the LICENSE file.
45d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
55d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
65d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// The file runs a series of Media Source Entensions (MSE) operations on a
75d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// video tag.  The test takes several URL parameters described in
85d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)//loadTestParams() function.
95d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
10f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)(function() {
11f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  function getPerfTimestamp() {
12f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    return performance.now();
13f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
14f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
15f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  var pageStartTime = getPerfTimestamp();
16f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  var bodyLoadTime;
17f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  var pageEndTime;
18f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
19f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  function parseQueryParameters() {
20f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    var params = {};
21f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    var r = /([^&=]+)=?([^&]*)/g;
22f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
23f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    function d(s) { return decodeURIComponent(s.replace(/\+/g, ' ')); }
24f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
25f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    var match;
26f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    while (match = r.exec(window.location.search.substring(1)))
27f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      params[d(match[1])] = d(match[2]);
28f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
29f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    return params;
30f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
31f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
32f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  var testParams;
33f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  function loadTestParams() {
34f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    var queryParameters = parseQueryParameters();
35f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    testParams = {};
36f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    testParams.testType = queryParameters["testType"] || "AV";
37f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    testParams.useAppendStream = (queryParameters["useAppendStream"] == "true");
385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    testParams.doNotWaitForBodyOnLoad =
395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        (queryParameters["doNotWaitForBodyOnLoad"] == "true");
40f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    testParams.startOffset = 0;
41f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    testParams.appendSize = parseInt(queryParameters["appendSize"] || "65536");
425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    testParams.graphDuration =
435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        parseInt(queryParameters["graphDuration"] || "1000");
44f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
45f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
46f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  function plotTimestamps(timestamps, graphDuration, element) {
475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (!timestamps)
485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      return;
49f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    var c = document.getElementById('c');
50f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    var ctx = c.getContext('2d');
51f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
52f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    var bars = [
53f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      { label: 'Page Load Total',
54f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        start: pageStartTime,
55f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        end: pageEndTime,
56f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        color: '#404040' },
57f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      { label: 'body.onload Delay',
58f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        start: pageStartTime,
59f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        end: bodyLoadTime,
60f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        color: '#808080' },
61f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      { label: 'Test Total',
62f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        start: timestamps.testStartTime,
63f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        end: timestamps.testEndTime,
64f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        color: '#00FF00' },
65f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      { label: 'MediaSource opening',
66f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        start: timestamps.mediaSourceOpenStartTime,
67f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        end: timestamps.mediaSourceOpenEndTime,
68f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        color: '#008800' }
69f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    ];
70f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
71f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    var maxAppendEndTime = 0;
72f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    for (var i = 0; i < timestamps.appenders.length; ++i) {
73f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      var appender = timestamps.appenders[i];
74f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      bars.push({ label: 'XHR',
75f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                  start: appender.xhrStartTime,
76f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                  end: appender.xhrEndTime,
77f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                  color: '#0088FF' });
78f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      bars.push({ label: 'Append',
79f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                  start: appender.appendStartTime,
80f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                  end: appender.appendEndTime,
81f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                  color: '#00FFFF' });
82f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      if (appender.appendEndTime > maxAppendEndTime) {
83f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        maxAppendEndTime = appender.appendEndTime;
84f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      }
85f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    }
86f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    bars.push({
885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        label: 'Post Append Delay',
895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        start: maxAppendEndTime,
905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        end: timestamps.testEndTime,
915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        color: '#B0B0B0' });
92f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
93f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    var minTimestamp = Number.MAX_VALUE;
94f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    for (var i = 0; i < bars.length; ++i) {
95f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      minTimestamp = Math.min(minTimestamp, bars[i].start);
96f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    }
97f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
98f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    var graphWidth = c.width - 100;
99f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    function convertTimestampToX(t) {
100f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      return graphWidth * (t - minTimestamp) / graphDuration;
101f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    }
102f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    var y = 0;
103f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    var barThickness = 20;
104f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    c.height = bars.length * barThickness;
105f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    ctx.font = (0.75 * barThickness) + 'px arial';
106f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    for (var i = 0; i < bars.length; ++i) {
107f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      var bar = bars[i];
108f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      var xStart = convertTimestampToX(bar.start);
109f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      var xEnd = convertTimestampToX(bar.end);
110f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      ctx.fillStyle = bar.color;
111f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      ctx.fillRect(xStart, y, xEnd - xStart, barThickness);
112f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
113f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      ctx.fillStyle = 'black';
114f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      var text = bar.label + ' (' + (bar.end - bar.start).toFixed(3) + ' ms)';
115f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      ctx.fillText(text, xEnd + 10, y + (0.75 * barThickness));
116f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      y += barThickness;
117f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    }
118f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    reportTelemetryMediaMetrics(bars, element);
119f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
120f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
121f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  function displayResults(stats) {
122f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    var statsDiv = document.getElementById('stats');
123f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
124f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    if (!stats) {
125f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      statsDiv.innerHTML = "Test failed";
126f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      return;
127f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    }
128f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
129f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    var statsMarkup = "Test passed<br><table>";
130f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    for (var i in stats) {
1315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      statsMarkup += "<tr><td style=\"text-align:right\">" + i + ":</td><td>" +
1325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                     stats[i].toFixed(3) + " ms</td>";
133f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    }
134f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    statsMarkup += "</table>";
135f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    statsDiv.innerHTML = statsMarkup;
136f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
137f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
138f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  function reportTelemetryMediaMetrics(stats, element) {
1395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    var metrics = {};
140f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    for (var i = 0; i < stats.length; ++i) {
141f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      var bar = stats[i];
142f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      var label = bar.label.toLowerCase().replace(/\s+|\./g, '_');
143f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      var value =  (bar.end - bar.start).toFixed(3);
144f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      console.log("appending to telemetry " + label + " : "  + value);
1455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      _AppendMetric(metrics, label, value);
146f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    }
1475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    window.__testMetrics = {
1485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      "id": element.id,
1495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      "metrics": metrics
1505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    };
1515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
1525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  function _AppendMetric(metrics, metric, value) {
1545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (!metrics[metric])
1555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      metrics[metric] = [];
1565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    metrics[metric].push(value);
157f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
158f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
159f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  function updateControls(testParams) {
160f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    var testTypeElement = document.getElementById("testType");
161f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    for (var i in testTypeElement.options) {
162f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      var option = testTypeElement.options[i];
163f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      if (option.value == testParams.testType) {
164f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        testTypeElement.selectedIndex = option.index;
165f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      }
166f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    }
167f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
1685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    document.getElementById("useAppendStream").checked =
1695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        testParams.useAppendStream;
1705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    document.getElementById("doNotWaitForBodyOnLoad").checked =
1715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        testParams.doNotWaitForBodyOnLoad;
172f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    document.getElementById("appendSize").value = testParams.appendSize;
173f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    document.getElementById("graphDuration").value = testParams.graphDuration;
174f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
175f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
176f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  function BufferAppender(mimetype, url, id, startOffset, appendSize) {
177f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    this.mimetype = mimetype;
178f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    this.url = url;
179f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    this.id = id;
180f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    this.startOffset = startOffset;
181f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    this.appendSize = appendSize;
182f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    this.xhr = new XMLHttpRequest();
183f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    this.sourceBuffer = null;
184f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
185f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
186f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  BufferAppender.prototype.start = function() {
187f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    this.xhr.addEventListener('loadend', this.onLoadEnd.bind(this));
188f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    this.xhr.open('GET', this.url);
189f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    this.xhr.setRequestHeader('Range', 'bytes=' + this.startOffset + '-' +
190f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                              (this.startOffset + this.appendSize - 1));
191f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    this.xhr.responseType = 'arraybuffer';
192f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    this.xhr.send();
193f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
194f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    this.xhrStartTime = getPerfTimestamp();
195f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  };
196f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
197f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  BufferAppender.prototype.onLoadEnd = function() {
198f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    this.xhrEndTime = getPerfTimestamp();
199f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    this.attemptAppend();
200f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  };
201f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
202f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  BufferAppender.prototype.onSourceOpen = function(mediaSource) {
203f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    if (this.sourceBuffer)
204f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      return;
205f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    this.sourceBuffer = mediaSource.addSourceBuffer(this.mimetype);
206f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  };
207f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
208f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  BufferAppender.prototype.attemptAppend = function() {
209f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    if (!this.xhr.response || !this.sourceBuffer)
210f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      return;
211f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
212f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    this.appendStartTime = getPerfTimestamp();
213f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
214f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    if (this.sourceBuffer.appendBuffer) {
215f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      this.sourceBuffer.addEventListener('updateend',
216f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                                         this.onUpdateEnd.bind(this));
217f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      this.sourceBuffer.appendBuffer(this.xhr.response);
218f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    } else {
219f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      this.sourceBuffer.append(new Uint8Array(this.xhr.response));
220f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      this.appendEndTime = getPerfTimestamp();
221f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    }
222f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
223f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    this.xhr = null;
224f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  };
225f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
226f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  BufferAppender.prototype.onUpdateEnd = function() {
227f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    this.appendEndTime = getPerfTimestamp();
228f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  };
229f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
230f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  BufferAppender.prototype.onPlaybackStarted = function() {
231f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    var now = getPerfTimestamp();
232f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    this.playbackStartTime = now;
233f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    if (this.sourceBuffer.updating) {
234f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      // Still appending but playback has already started so just abort the XHR
235f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      // and append.
236f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      this.sourceBuffer.abort();
237f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      this.xhr.abort();
238f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    }
239f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  };
240f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
241f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  BufferAppender.prototype.getXHRLoadDuration = function() {
242f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    return this.xhrEndTime - this.xhrStartTime;
243f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  };
244f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
245f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  BufferAppender.prototype.getAppendDuration = function() {
246f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    return this.appendEndTime - this.appendStartTime;
247f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  };
248f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
249f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  function StreamAppender(mimetype, url, id, startOffset, appendSize) {
250f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    this.mimetype = mimetype;
251f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    this.url = url;
252f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    this.id = id;
253f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    this.startOffset = startOffset;
254f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    this.appendSize = appendSize;
255f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    this.xhr = new XMLHttpRequest();
256f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    this.sourceBuffer = null;
257f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    this.appendStarted = false;
258f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
259f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
260f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  StreamAppender.prototype.start = function() {
261f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    this.xhr.addEventListener('readystatechange',
262f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                              this.attemptAppend.bind(this));
263f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    this.xhr.addEventListener('loadend', this.onLoadEnd.bind(this));
264f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    this.xhr.open('GET', this.url);
265f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    this.xhr.setRequestHeader('Range', 'bytes=' + this.startOffset + '-' +
266f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                              (this.startOffset + this.appendSize - 1));
267f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    this.xhr.responseType = 'stream';
268f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    if (this.xhr.responseType != 'stream') {
2695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      EndTest("XHR does not support 'stream' responses.");
270f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    }
271f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    this.xhr.send();
272f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
273f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    this.xhrStartTime = getPerfTimestamp();
274f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  };
275f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
276f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  StreamAppender.prototype.onLoadEnd = function() {
277f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    this.xhrEndTime = getPerfTimestamp();
278f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    this.attemptAppend();
279f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  };
280f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
281f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  StreamAppender.prototype.onSourceOpen = function(mediaSource) {
282f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    if (this.sourceBuffer)
283f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      return;
284f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    this.sourceBuffer = mediaSource.addSourceBuffer(this.mimetype);
285f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  };
286f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
287f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  StreamAppender.prototype.attemptAppend = function() {
288f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    if (this.xhr.readyState < this.xhr.LOADING) {
289f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      return;
290f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    }
291f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
292f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    if (!this.xhr.response || !this.sourceBuffer || this.appendStarted)
293f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      return;
294f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
295f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    this.appendStartTime = getPerfTimestamp();
296f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    this.appendStarted = true;
297f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    this.sourceBuffer.addEventListener('updateend',
298f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                                       this.onUpdateEnd.bind(this));
299f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    this.sourceBuffer.appendStream(this.xhr.response);
300f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  };
301f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
302f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  StreamAppender.prototype.onUpdateEnd = function() {
303f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    this.appendEndTime = getPerfTimestamp();
304f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  };
305f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
306f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  StreamAppender.prototype.onPlaybackStarted = function() {
307f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    var now = getPerfTimestamp();
308f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    this.playbackStartTime = now;
309f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    if (this.sourceBuffer.updating) {
310f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      // Still appending but playback has already started so just abort the XHR
311f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      // and append.
312f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      this.sourceBuffer.abort();
313f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      this.xhr.abort();
314f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      if (!this.appendEndTime)
315f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        this.appendEndTime = now;
316f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
317f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      if (!this.xhrEndTime)
318f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        this.xhrEndTime = now;
319f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    }
320f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  };
321f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
322f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  StreamAppender.prototype.getXHRLoadDuration = function() {
323f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    return this.xhrEndTime - this.xhrStartTime;
324f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  };
325f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
326f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  StreamAppender.prototype.getAppendDuration = function() {
327f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    return this.appendEndTime - this.appendStartTime;
328f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  };
329f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
330f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // runAppendTest() sets testDone to true once all appends finish.
331f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  var testDone = false;
332f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  function runAppendTest(mediaElement, appenders, doneCallback) {
333f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    var testStartTime = getPerfTimestamp();
334f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    var mediaSourceOpenStartTime;
335f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    var mediaSourceOpenEndTime;
336f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
337f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    for (var i = 0; i < appenders.length; ++i) {
338f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      appenders[i].start();
339f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    }
340f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
341f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    function onSourceOpen(event) {
342f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      var mediaSource = event.target;
343f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
344f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      mediaSourceOpenEndTime = getPerfTimestamp();
345f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
346f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      for (var i = 0; i < appenders.length; ++i) {
347f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        appenders[i].onSourceOpen(mediaSource);
348f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      }
349f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
350f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      for (var i = 0; i < appenders.length; ++i) {
351f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        appenders[i].attemptAppend(mediaSource);
352f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      }
353f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
354f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      mediaElement.play();
355f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    }
356f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
357f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    var mediaSource;
358f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    if (window['MediaSource']) {
359f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      mediaSource = new window.MediaSource();
360f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      mediaSource.addEventListener('sourceopen', onSourceOpen);
361f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    } else {
362f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      mediaSource = new window.WebKitMediaSource();
363f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      mediaSource.addEventListener('webkitsourceopen', onSourceOpen);
364f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    }
365f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
366f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    var listener;
367f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    var timeout;
368f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    function checkForCurrentTimeChange() {
369f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      if (testDone)
370f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        return;
371f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
372f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      if (mediaElement.readyState < mediaElement.HAVE_METADATA ||
3730529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch          mediaElement.currentTime <= 0) {
3740529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch        listener = window.requestAnimationFrame(checkForCurrentTimeChange);
375f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        return;
3760529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      }
377f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
3785c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      var testEndTime = getPerfTimestamp();
379f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      for (var i = 0; i < appenders.length; ++i) {
380f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        appenders[i].onPlaybackStarted(mediaSource);
381f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      }
382f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
383f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      testDone = true;
384f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      window.clearInterval(listener);
385f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      window.clearTimeout(timeout);
386f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
387f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      var stats = {};
388f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      stats.total = testEndTime - testStartTime;
389f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      stats.sourceOpen = mediaSourceOpenEndTime - mediaSourceOpenStartTime;
390f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      stats.maxXHRLoadDuration = appenders[0].getXHRLoadDuration();
391f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      stats.maxAppendDuration = appenders[0].getAppendDuration();
392f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
393f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      var timestamps = {};
394f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      timestamps.testStartTime = testStartTime;
395f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      timestamps.testEndTime = testEndTime;
396f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      timestamps.mediaSourceOpenStartTime = mediaSourceOpenStartTime;
397f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      timestamps.mediaSourceOpenEndTime = mediaSourceOpenEndTime;
398f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      timestamps.appenders = [];
399f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
400f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      for (var i = 1; i < appenders.length; ++i) {
401f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        var appender = appenders[i];
402f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        var xhrLoadDuration = appender.getXHRLoadDuration();
403f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        var appendDuration = appender.getAppendDuration();
404f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
405f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        if (xhrLoadDuration > stats.maxXHRLoadDuration)
406f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)          stats.maxXHRLoadDuration = xhrLoadDuration;
407f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
408f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        if (appendDuration > stats.maxAppendDuration)
409f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)          stats.maxAppendDuration = appendDuration;
410f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      }
411f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
412f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      for (var i = 0; i < appenders.length; ++i) {
413f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        var appender = appenders[i];
414f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        var appenderTimestamps = {};
415f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        appenderTimestamps.xhrStartTime = appender.xhrStartTime;
416f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        appenderTimestamps.xhrEndTime = appender.xhrEndTime;
417f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        appenderTimestamps.appendStartTime = appender.appendStartTime;
418f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        appenderTimestamps.appendEndTime = appender.appendEndTime;
419f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        appenderTimestamps.playbackStartTime = appender.playbackStartTime;
420f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        timestamps.appenders.push(appenderTimestamps);
421f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      }
422f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
423f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      mediaElement.pause();
424f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
425f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      pageEndTime = getPerfTimestamp();
426f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      doneCallback(stats, timestamps);
427f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    };
428f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
4290529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    listener = window.requestAnimationFrame(checkForCurrentTimeChange);
430f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
431f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    timeout = setTimeout(function() {
432f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      if (testDone)
433f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        return;
434f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
435f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      testDone = true;
4360529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      window.cancelAnimationFrame(listener);
437f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
438f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      mediaElement.pause();
439f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      doneCallback(null);
4405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      EndTest("Test timed out.");
441f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    }, 10000);
442f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
443f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    mediaSourceOpenStartTime = getPerfTimestamp();
444f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    mediaElement.src = URL.createObjectURL(mediaSource);
445f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  };
446f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
447f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  function onBodyLoad() {
448f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    bodyLoadTime = getPerfTimestamp();
449f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
450f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    if (!testParams.doNotWaitForBodyOnLoad) {
451f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      startTest();
452f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    }
453f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
454f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
455f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  function startTest() {
456f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    updateControls(testParams);
457f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
458f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    var appenders = [];
459f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
4605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (testParams.useAppendStream && !window.MediaSource)
4615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      EndTest("Can't use appendStream() because the unprefixed MediaSource " +
4625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)              "object is not present.");
463f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
464f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    var Appender = testParams.useAppendStream ? StreamAppender : BufferAppender;
465f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
466f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    if (testParams.testType.indexOf("A") != -1) {
4675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      appenders.push(
4685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          new Appender("audio/mp4; codecs=\"mp4a.40.2\"",
4695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                       "audio.mp4",
4705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                       "a",
4715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                       testParams.startOffset,
4725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                       testParams.appendSize));
473f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    }
474f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
475f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    if (testParams.testType.indexOf("V") != -1) {
4765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      appenders.push(
4775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          new Appender("video/mp4; codecs=\"avc1.640028\"",
4785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                       "video.mp4",
4795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                       "v",
4805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                       testParams.startOffset,
4815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                       testParams.appendSize));
482f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    }
483f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
4845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    var video = document.getElementById("v");
4855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    video.addEventListener("error", function(e) {
4865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      console.log("video error!");
4875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      EndTest("Video error: " + video.error);
4885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    });
4895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
490f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    video.id = getTestID();
491f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    runAppendTest(video, appenders, function(stats, timestamps) {
492f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      displayResults(stats);
493f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      plotTimestamps(timestamps, testParams.graphDuration, video);
4945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      EndTest("Call back call done.");
495f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    });
496f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
497f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
4985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  function EndTest(msg) {
4995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    console.log("Ending test: " + msg);
5005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    window.__testDone = true;
5015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
5025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
503f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  function getTestID() {
504f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    var id = testParams.testType;
505f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    if (testParams.useAppendStream)
506f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      id += "_stream"
507f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    else
508f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      id += "_buffer"
509f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    if (testParams.doNotWaitForBodyOnLoad)
510f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      id += "_pre_load"
511f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    else
512f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      id += "_post_load"
513f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    return id;
514f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
515f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
516f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  function setupTest() {
517f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    loadTestParams();
518f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    document.body.onload = onBodyLoad;
519f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
520f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    if (testParams.doNotWaitForBodyOnLoad) {
521f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      startTest();
522f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    }
523f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
524f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
525f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  window["setupTest"] = setupTest;
526a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  window.__testDone = false;
5275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  window.__testMetrics = {};
528f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)})();
529