summaryrefslogtreecommitdiffstats
path: root/chrome/browser/resources/media_internals/metrics.js
blob: 2c40f4a51a4ef9c84a9ee1e6a804c89c626d1699 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
// Copyright (c) 2011 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.

cr.define('media', function() {
  'use strict';

  // A set of parameter names. An entry of 'abc' allows metrics to specify
  // events with specific values of 'abc'.
  var metricProperties = {
    'pipeline_state': true,
  };

  // A set of metrics to measure. The user will see the most recent and average
  // measurement of the time between each metric's start and end events.
  var metrics = {
    'seek': {
      'start': 'SEEK',
      'end': 'pipeline_state=started'
    },
    'first frame': {
      'start': 'WEBMEDIAPLAYER_CREATED',
      'end': 'pipeline_state=started'
    },
  };

  /**
   * This class measures times between the events specified above. It inherits
   * <li> and contains a table that displays the measurements.
   */
  var Metrics = cr.ui.define('li');

  Metrics.prototype = {
    __proto__: HTMLLIElement.prototype,

    /**
     * Decorate this <li> as a Metrics.
     */
    decorate: function() {
      this.table_ = document.createElement('table');
      var details = document.createElement('details');
      var summary = media.makeElement('summary', 'Metrics:');
      details.appendChild(summary);
      details.appendChild(this.table_);
      this.appendChild(details);

      var hRow = document.createElement('tr');
      hRow.appendChild(media.makeElement('th', 'Metric:'));
      hRow.appendChild(media.makeElement('th', 'Last Measure:'));
      hRow.appendChild(media.makeElement('th', 'Average:'));
      var header = document.createElement('thead');
      header.appendChild(hRow);
      this.table_.appendChild(header);

      for (var metric in metrics) {
        var last = document.createElement('td');
        var avg = document.createElement('td');
        this[metric] = {
          count: 0,
          total: 0,
          start: null,
          last: last,
          avg: avg
        };
        var row = document.createElement('tr');
        row.appendChild(media.makeElement('td', metric + ':'));
        row.appendChild(last);
        row.appendChild(avg);
        this.table_.appendChild(row);
      }
    },

    /**
     * An event has occurred. Update any metrics that refer to this type
     * of event. Can be called multiple times by addEvent below if the metrics
     * refer to specific parameters.
     * @param {Object} event The MediaLogEvent that has occurred.
     * @param {string} type The type of event.
     */
    addEventInternal: function(event, type) {
      var timeInMs = event.time * 1000;  // Work with milliseconds.

      for (var metric in metrics) {
        var m = this[metric];
        if (type == metrics[metric].start && !m.start) {
          m.start = timeInMs;
        } else if (type == metrics[metric].end && m.start != null) {
          var last = timeInMs - m.start;
          m.last.textContent = last.toFixed(1);
          m.total += last;
          m.count++;
          if (m.count > 1)
            m.avg.textContent = (m.total / m.count).toFixed(1);
          m.start = null;
        }
      }
    },

    /**
     * An event has occurred. Update any metrics that refer to events of this
     * type or with this event's parameters.
     * @param {Object} event The MediaLogEvent that has occurred.
     */
    addEvent: function(event) {
      this.addEventInternal(event, event.type);
      for (var p in event.params) {
        if (p in metricProperties) {
          var type = p + '=' + event.params[p];
          this.addEventInternal(event, type);
        }
      }
    },
  };

  return {
      Metrics: Metrics,
  };
});