OLD | NEW |
---|---|
(Empty) | |
1 // Copyright (c) 2013 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 file contains common utilities to find video/audio elements on a page | |
6 // and collect metrics for each. | |
7 | |
8 (function() { | |
9 // MediaMetric class responsible for collecting metrics on a media element. | |
10 // It attaches required event listeners in order to collect different metrics. | |
11 function MediaMetric(element) { | |
nduca
2013/07/09 23:07:19
should a MediaMetricBase base class, a HTML5Media
shadi
2013/07/11 00:49:13
PTAL. I kept all fields common to any media metric
| |
12 this.metrics = {}; | |
13 this.info = {}; | |
14 this.element = element; | |
15 this.isHTML5 = element instanceof HTMLMediaElement; | |
nduca
2013/07/09 23:07:19
this could be a getter on MediaMetric.
shadi
2013/07/11 00:49:13
This is avoided with subclasses.
| |
16 // Listen to when a Telemetry 'Play' action gets called. | |
17 this.element.addEventListener('willPlay', this.onWillPlay, false); | |
18 if (this.isHTML5) | |
19 this.initHTML5(); | |
nduca
2013/07/09 23:07:19
what happens if you accidentally bind a media metr
shadi
2013/07/11 00:49:13
Done.
| |
20 } | |
nduca
2013/07/09 23:07:19
should you explode if this isnt' html5?
shadi
2013/07/11 00:49:13
not really. If there are no html5 elements in the
| |
21 | |
22 MediaMetric.prototype.onWillPlay = function() { | |
23 this.ttp_timer = new Timer(); | |
nduca
2013/07/09 23:07:19
name this fully
shadi
2013/07/11 00:49:13
Done.
| |
24 }; | |
25 | |
26 MediaMetric.prototype.initHTML5 = function() { | |
27 // Set the basic event handlers for HTML5 media element. | |
28 var metric = this; | |
29 function onVideoLoad(event) { | |
30 // If a 'Play' action is performed, then ttp_time != undefined. | |
31 if (metric.ttp_timer == undefined) | |
32 metric.ttp_timer = new Timer(); | |
33 } | |
34 // For the cases where autoplay=true, and without a 'play' action, we want | |
35 // to start ttp_timer at 'play' or 'loadedmetadata' events. | |
36 this.element.addEventListener('play', onVideoLoad); | |
37 this.element.addEventListener('loadedmetadata', onVideoLoad); | |
38 this.element.addEventListener('playing', function(e) { | |
39 metric.onPlaying(e); | |
40 }); | |
41 this.element.addEventListener('ended', function(e) { | |
42 metric.onEnded(e); | |
43 }); | |
44 }; | |
45 | |
46 MediaMetric.prototype.onPlaying = function(event) { | |
47 // Playing event can fire more than once if seeking. | |
48 if (!this.metrics['ttp']) | |
49 this.metrics['ttp'] = [this.ttp_timer.stop(), 'sec']; | |
50 }; | |
51 | |
52 MediaMetric.prototype.onEnded = function(event) { | |
53 this.metrics['playback_time'] = [this.ttp_timer.stop(), 'sec']; | |
54 }; | |
55 | |
56 MediaMetric.prototype.getElementInfo = function() { | |
57 // Return information about the media element for this metric. | |
58 if (this.element.id) | |
59 this.info['id'] = this.element.id; | |
60 if (this.isHTML5) { | |
61 // Add interesting media specific tags. | |
62 if (this.element.src) | |
63 this.info['src'] = this.element.src; | |
64 } | |
65 return this.info; | |
66 }; | |
67 | |
68 MediaMetric.prototype.getMetrics = function() { | |
69 // Returns all collected metrics for the element | |
70 if (this.isHTML5) { | |
71 this.metrics['decoded_frame_count'] = | |
72 [this.element.webkitDecodedFrameCount, 'frames']; | |
73 this.metrics['dropped_frame_count'] = | |
74 [this.element.webkitDroppedFrameCount, 'frames']; | |
75 this.metrics['decoded_video_bytes'] = | |
76 [this.element.webkitVideoDecodedByteCount, 'bytes']; | |
77 this.metrics['decoded_audio_bytes'] = | |
78 [this.element.webkitAudioDecodedByteCount, 'bytes']; | |
79 } | |
80 return this.metrics; | |
81 }; | |
82 | |
83 MediaMetric.prototype.getSummary = function() { | |
84 return { | |
85 'info': this.getElementInfo(), | |
86 'metrics': this.getMetrics() | |
87 }; | |
88 }; | |
89 | |
90 function Timer() { | |
nduca
2013/07/09 23:07:19
why does this not call start()?
and why not just
shadi
2013/07/11 00:49:13
It is usually the case where you need to start the
| |
91 this.start_ = getCurrentTime(); | |
92 this.times_ = []; | |
93 } | |
94 | |
95 Timer.prototype = { | |
96 start: function() { | |
97 this.start_ = getCurrentTime(); | |
98 }, | |
99 | |
100 stop: function() { | |
101 // Store time logs in secs. | |
102 var delta = (getCurrentTime() - this.start_) / 1000; | |
103 this.times_.push(delta); | |
104 return delta; | |
105 } | |
106 }; | |
107 | |
108 function LoadMediaMetrics() { | |
nduca
2013/07/09 23:07:19
This isn't really loading. createMediaMetricsForDo
shadi
2013/07/11 00:49:13
Done.
| |
109 // Searches for all video and audio elements on the page and creates a | |
110 // corresponding media metric instance for each. | |
111 var media = document.querySelectorAll('video, audio'); | |
nduca
2013/07/09 23:07:19
mediaElements
shadi
2013/07/11 00:49:13
Done.
| |
112 for (var i = 0; i < media.length; i++) { | |
nduca
2013/07/09 23:07:19
one liners dont get {}
shadi
2013/07/11 00:49:13
Done.
| |
113 mediaMetrics.push(new MediaMetric(media[i])); | |
nduca
2013/07/09 23:07:19
explicitly say window.__mediaMetrics perhaps inste
shadi
2013/07/11 00:49:13
Done.
| |
114 } | |
115 } | |
116 | |
117 function getCurrentTime() { | |
118 if (window.performance) | |
119 return (performance.now || | |
120 performance.mozNow || | |
121 performance.msNow || | |
122 performance.oNow || | |
123 performance.webkitNow).call(window.performance); | |
124 else | |
125 return Date().getTime(); | |
nduca
2013/07/09 23:07:19
Date.now()? does't create garbage...
shadi
2013/07/11 00:49:13
Done.
| |
126 } | |
127 | |
128 function getAllMetrics() { | |
129 // Returns a summary (info + metrics) for all media metrics. | |
130 var metrics = []; | |
131 for (var i = 0; i < mediaMetrics.length; i++) { | |
nduca
2013/07/09 23:07:19
one line fors get no bracez
shadi
2013/07/11 00:49:13
Done.
| |
132 metrics.push(mediaMetrics[i].getSummary()); | |
133 } | |
134 return metrics; | |
135 } | |
136 | |
137 // Stores metrics for all media elements on the page upon loading. | |
138 var mediaMetrics = []; | |
139 window.__mediaMetrics = mediaMetrics; | |
140 window.__getAllMetrics = getAllMetrics; | |
141 LoadMediaMetrics(); | |
nduca
2013/07/09 23:07:19
you should keep injection of the script separate f
shadi
2013/07/11 00:49:13
Is there a good reason for this? Is there a case w
| |
142 })(); | |
OLD | NEW |