blob: 242b77645650b66b63cd527530e83d33a3869f55 [file] [log] [blame]
// Copyright 2015 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.
// This script finds the first video element on a page and collect metrics
// for that element. This is based on src/tools/perf/metrics/media.js.
(function() {
// VideoWrapper attaches event listeners to collect metrics.
// The constructor starts playing the video.
function VideoWrapper(element) {
if (!(element instanceof HTMLVideoElement))
throw new Error('Unrecognized video element type ' + element);
metrics['ready'] = false;
this.element = element;
element.loop = false;
// Set the basic event handlers for this HTML5 video element.
this.element.addEventListener('loadedmetadata', this.onLoaded.bind(this));
this.element.addEventListener('canplay', this.onCanplay.bind(this));
this.element.addEventListener('ended', this.onEnded.bind(this));
this.playbackTimer = new Timer();
element.play()
}
VideoWrapper.prototype.onLoaded = function(e) {
if (this.element.readyState == HTMLMediaElement.HAVE_NOTHING) {
return
}
metrics['ready'] = true;
metrics['video_height'] = this.element.videoHeight;
metrics['video_width'] = this.element.videoWidth;
metrics['video_duration'] = this.element.duration;
window.__chromeProxyVideoLoaded = true;
};
VideoWrapper.prototype.onCanplay = function(event) {
metrics['time_to_play_ms'] = this.playbackTimer.stop();
};
VideoWrapper.prototype.onEnded = function(event) {
var time_to_end = this.playbackTimer.stop() - metrics['time_to_play_ms'];
metrics['buffering_time_ms'] = time_to_end - this.element.duration * 1000;
metrics['decoded_audio_bytes'] = this.element.webkitAudioDecodedByteCount;
metrics['decoded_video_bytes'] = this.element.webkitVideoDecodedByteCount;
metrics['decoded_frames'] = this.element.webkitDecodedFrameCount;
metrics['dropped_frames'] = this.element.webkitDroppedFrameCount;
window.__chromeProxyVideoEnded = true;
};
function MediaMetric(element) {
if (element instanceof HTMLMediaElement)
return new VideoWrapper(element);
throw new Error('Unrecognized media element type.');
}
function Timer() {
this.start();
}
Timer.prototype = {
start: function() {
this.start_ = getCurrentTime();
},
stop: function() {
// Return delta time since start in millisecs.
return Math.round((getCurrentTime() - this.start_) * 1000) / 1000;
}
};
function getCurrentTime() {
if (window.performance)
return (performance.now ||
performance.mozNow ||
performance.msNow ||
performance.oNow ||
performance.webkitNow).call(window.performance);
else
return Date.now();
}
function createVideoWrappersForDocument() {
var videos = document.querySelectorAll('video');
switch (videos.length) {
case 0:
throw new Error('Page has no videos.');
case 1:
break;
default:
throw new Error('Page too many videos: ' + videos.length.toString());
}
new VideoWrapper(videos[0])
}
metrics = {};
window.__chromeProxyCreateVideoWrappers = createVideoWrappersForDocument;
window.__chromeProxyVideoMetrics = metrics;
window.__chromeProxyVideoLoaded = false;
window.__chromeProxyVideoEnded = false;
})();