Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(149)

Side by Side Diff: tools/perf/perf_tools/media_metrics.js

Issue 16854013: Telemetry media_measurement plus play action and tests. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 7 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(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 // Media recorder class responsible for recording and performing actions on a
10 // media element. It attaches required event listeners in order to collect
11 // different metrics and allows the execution of different media actions.
12 function MediaRecorder(element) {
13 this.metrics = {};
14 this.info = {};
15 this.element = element;
16 this.isHTML5 = element instanceof HTMLMediaElement;
scherkus (not reviewing) 2013/06/14 20:50:45 when would we create a MediaRecorder for a non-med
shadi 2013/06/17 19:13:59 The plan is that we will add support for non HTML5
17 if (this.isHTML5)
18 this.initHTML5();
19 }
20
21 MediaRecorder.prototype.play = function() {
22 if (this.isHTML5) {
23 this.ttp_timer = new Timer();
24 this.element.play();
25 } else {
26 // How to raise an error? log?
27 Error('We can not automatically play this type of element');
28 }
29 };
30
31 MediaRecorder.prototype.initHTML5 = function() {
32 // Set the basic event handlers for HTML5 media element.
33 var recorder = this;
34 function onVideoLoad(event) {
35 // If a 'play' action is performed, then ttp_time != undefined.
36 if (recorder.ttp_timer == undefined)
37 recorder.ttp_timer = new Timer();
38 }
39 // For the cases where autoplay=true, and without a 'play' action, we want
scherkus (not reviewing) 2013/06/14 20:50:45 are we going to have tests w/ autoplay or should w
shadi 2013/06/17 19:13:59 Videostack tests won't have autoplay, but media me
40 // to start ttp_timer at 'play' or 'loadedmetadata' events.
41 this.element.addEventListener('play', onVideoLoad);
42 this.element.addEventListener('loadedmetadata', onVideoLoad);
43 this.element.addEventListener('playing', function(e) {
44 recorder.onPlaying(e);
45 });
46 this.element.addEventListener('ended', function(e) {
47 recorder.onEnded(e);
48 });
49 this.element.addEventListener('error', function(e) {
50 recorder.onError(e);
51 });
52 this.element.addEventListener('abort', function(e) {
53 recorder.onError(e);
54 });
55 };
56
57 MediaRecorder.prototype.onPlaying = function(event) {
58 this.playing = true;
59 this.metrics['ttp'] = [this.ttp_timer.stop(), 'sec'];
60 };
61
62 MediaRecorder.prototype.onEnded = function(event) {
63 this.ended = true;
64 this.metrics['playback_time'] = [this.ttp_timer.stop(), 'sec'];
65 };
66
67 MediaRecorder.prototype.onError = function(event) {
68 // TODO(shadi): communicate to Telemetry that an error has occured.
69 console.log('Media failed to play: ' + event.type);
70 };
71
72 MediaRecorder.prototype.getElementInfo = function() {
73 // Return information about the media element for this recorder.
74 if (this.element.id)
75 this.info['id'] = this.element.id;
76 if (this.isHTML5) {
77 // Add insteresting media specific tags.
78 if (this.element.src)
79 this.info['src'] = this.element.src;
80 }
81 return this.info;
82 };
83
84 MediaRecorder.prototype.getMetrics = function() {
85 // Returns all recorded metrics for the element
86 if (this.isHTML5) {
87 this.metrics['decoded_frame_count'] =
88 [this.element.webkitDecodedFrameCount, 'frames'];
89 this.metrics['dropped_frame_count'] =
90 [this.element.webkitDroppedFrameCount, 'frames'];
91 this.metrics['decoded_video_bytes'] =
92 [this.element.webkitVideoDecodedByteCount, 'bytes'];
93 this.metrics['decoded_audio_bytes'] =
94 [this.element.webkitAudioDecodedByteCount, 'bytes'];
95 }
96 return this.metrics;
97 };
98
99 MediaRecorder.prototype.getSummary = function() {
100 return {
101 'info': this.getElementInfo(),
102 'metrics': this.getMetrics()
103 };
104 };
105
106 MediaRecorder.prototype.hasEventCompleted = function(event_name) {
107 return this[event_name] == true;
108 };
109
110 function Timer() {
111 this.start_ = getCurrentTime();
112 this.times_ = [];
113 }
114
115 Timer.prototype = {
116 start: function() {
117 this.start_ = getCurrentTime();
118 },
119
120 stop: function() {
121 // Store time logs in secs.
122 var delta = (getCurrentTime() - this.start_) / 1000;
123 this.times_.push(delta);
124 return delta;
125 }
126 };
127
128 function CreateMediaRecorders() {
129 // Searches for all video and audio elements on the page and creates a
130 // corresponding media recorder instance for each.
131 var media = document.getElementsByTagName('video');
132 for (var i = 0; i < media.length; i++) {
133 mediaRecorders.push(new MediaRecorder(media[i]));
134 }
135 media = document.getElementsByTagName('audio');
136 for (var i = 0; i < media.length; i++) {
137 mediaRecorders.push(new MediaRecorder(media[i]));
138 }
139 }
140
141 function getCurrentTime() {
142 if (window.performance)
143 return (performance.now ||
144 performance.mozNow ||
145 performance.msNow ||
146 performance.oNow ||
147 performance.webkitNow).call(window.performance);
148 else
149 return Date().getTime();
150 }
151
152 function getAllMetrics() {
153 // Returns a summary (info + metrics) for all media recorders.
154 var metrics = [];
155 for (var i = 0; i < mediaRecorders.length; i++) {
156 metrics.push(mediaRecorders[i].getSummary());
157 }
158 return metrics;
159 }
160
161 function findMediaRecorders(selector) {
162 // Returns element matching the selector, otherwise returns the first video
163 // or audio tag element that can be found.
164 // If selector == 'all', returns all media recorders.
165 if (selector == 'all') {
166 return mediaRecorders;
167 }
168 var mediaElement = null;
169 if (selector) {
170 mediaElement = document.querySelector(selector);
171 } else {
172 var media = document.getElementsByTagName('video');
173 if (media.length > 0) {
174 mediaElement = media[0];
175 } else {
176 media = document.getElementsByTagName('audio');
177 if (media.length > 0) {
178 mediaElement = media[0];
179 }
180 }
181 }
182 if (mediaElement) {
183 for (var i = 0; i < mediaRecorders.length; i++) {
184 if (mediaElement == mediaRecorders[i].element)
185 return [mediaRecorders[i]];
186 }
187 }
188 return [];
189 }
190
191 function playMedia(selector) {
192 // Performs the "Play" action on media satisfying selector.
193 var recorders = findMediaRecorders(selector);
194 for (var i = 0; i < recorders.length; i++) {
195 recorders[i].play();
196 }
197 }
198
199 function hasEventCompleted(selector, event_name) {
200 // Return true if the event_name fired for media satisfying the selector.
201 var recorders = findMediaRecorders(selector);
202 for (var i = 0; i < recorders.length; i++) {
203 if (!recorders[i].hasEventCompleted(event_name))
204 return false;
205 }
206 return true;
207 }
208
209 // Stores recorders for all media elements on the page upon loading.
210 var mediaRecorders = [];
211 window.__mediaRecorders = mediaRecorders;
212 window.__getAllMetrics = getAllMetrics;
213 window.__playMedia = playMedia;
214 window.__hasEventCompleted = hasEventCompleted;
215 CreateMediaRecorders();
216 })();
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698