OLD | NEW |
(Empty) | |
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. |
| 4 |
| 5 // This script finds the first video element on a page and collect metrics |
| 6 // for that element. This is based on src/tools/perf/metrics/media.js. |
| 7 |
| 8 (function() { |
| 9 // VideoWrapper attaches event listeners to collect metrics. |
| 10 // The constructor starts playing the video. |
| 11 function VideoWrapper(element) { |
| 12 if (!(element instanceof HTMLVideoElement)) |
| 13 throw new Error('Unrecognized video element type ' + element); |
| 14 metrics['ready'] = false; |
| 15 this.element = element; |
| 16 element.loop = false; |
| 17 // Set the basic event handlers for this HTML5 video element. |
| 18 this.element.addEventListener('loadedmetadata', this.onLoaded.bind(this)); |
| 19 this.element.addEventListener('canplay', this.onCanplay.bind(this)); |
| 20 this.element.addEventListener('ended', this.onEnded.bind(this)); |
| 21 this.playbackTimer = new Timer(); |
| 22 element.play() |
| 23 } |
| 24 |
| 25 VideoWrapper.prototype.onLoaded = function(e) { |
| 26 if (this.element.readyState == HTMLMediaElement.HAVE_NOTHING) { |
| 27 return |
| 28 } |
| 29 metrics['ready'] = true; |
| 30 metrics['video_height'] = this.element.videoHeight; |
| 31 metrics['video_width'] = this.element.videoWidth; |
| 32 metrics['video_duration'] = this.element.duration; |
| 33 window.__chromeProxyVideoLoaded = true; |
| 34 }; |
| 35 |
| 36 VideoWrapper.prototype.onCanplay = function(event) { |
| 37 metrics['time_to_play_ms'] = this.playbackTimer.stop(); |
| 38 }; |
| 39 |
| 40 VideoWrapper.prototype.onEnded = function(event) { |
| 41 var time_to_end = this.playbackTimer.stop() - metrics['time_to_play_ms']; |
| 42 metrics['buffering_time_ms'] = time_to_end - this.element.duration * 1000; |
| 43 metrics['decoded_audio_bytes'] = this.element.webkitAudioDecodedByteCount; |
| 44 metrics['decoded_video_bytes'] = this.element.webkitVideoDecodedByteCount; |
| 45 metrics['decoded_frames'] = this.element.webkitDecodedFrameCount; |
| 46 metrics['dropped_frames'] = this.element.webkitDroppedFrameCount; |
| 47 window.__chromeProxyVideoEnded = true; |
| 48 }; |
| 49 |
| 50 function MediaMetric(element) { |
| 51 if (element instanceof HTMLMediaElement) |
| 52 return new VideoWrapper(element); |
| 53 throw new Error('Unrecognized media element type.'); |
| 54 } |
| 55 |
| 56 function Timer() { |
| 57 this.start(); |
| 58 } |
| 59 |
| 60 Timer.prototype = { |
| 61 start: function() { |
| 62 this.start_ = getCurrentTime(); |
| 63 }, |
| 64 |
| 65 stop: function() { |
| 66 // Return delta time since start in millisecs. |
| 67 return Math.round((getCurrentTime() - this.start_) * 1000) / 1000; |
| 68 } |
| 69 }; |
| 70 |
| 71 function getCurrentTime() { |
| 72 if (window.performance) |
| 73 return (performance.now || |
| 74 performance.mozNow || |
| 75 performance.msNow || |
| 76 performance.oNow || |
| 77 performance.webkitNow).call(window.performance); |
| 78 else |
| 79 return Date.now(); |
| 80 } |
| 81 |
| 82 function createVideoWrappersForDocument() { |
| 83 var videos = document.querySelectorAll('video'); |
| 84 switch (videos.length) { |
| 85 case 0: |
| 86 throw new Error('Page has no videos.'); |
| 87 case 1: |
| 88 break; |
| 89 default: |
| 90 throw new Error('Page too many videos: ' + videos.length.toString()); |
| 91 } |
| 92 new VideoWrapper(videos[0]) |
| 93 } |
| 94 |
| 95 metrics = {}; |
| 96 window.__chromeProxyCreateVideoWrappers = createVideoWrappersForDocument; |
| 97 window.__chromeProxyVideoMetrics = metrics; |
| 98 window.__chromeProxyVideoLoaded = false; |
| 99 window.__chromeProxyVideoEnded = false; |
| 100 })(); |
OLD | NEW |