summaryrefslogtreecommitdiffstats
path: root/tools/perf/metrics/media.py
blob: f26e715433773b11ca8353a033cd3b810478c598 (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
# Copyright 2013 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.
import logging
import os

from metrics import Metric
from telemetry.value import list_of_scalar_values
from telemetry.value import scalar


class MediaMetric(Metric):
  """MediaMetric class injects and calls JS responsible for recording metrics.

  Default media metrics are collected for every media element in the page,
  such as decoded_frame_count, dropped_frame_count, decoded_video_bytes, and
  decoded_audio_bytes.
  """

  def __init__(self, tab):
    super(MediaMetric, self).__init__()
    with open(os.path.join(os.path.dirname(__file__), 'media.js')) as f:
      js = f.read()
      tab.ExecuteJavaScript(js)
    self._results = None
    self._skip_basic_metrics = False

  def Start(self, page, tab):
    """Create the media metrics for all media elements in the document."""
    if hasattr(page, 'skip_basic_metrics'):
      self._skip_basic_metrics = page.skip_basic_metrics
    tab.ExecuteJavaScript('window.__createMediaMetricsForDocument()')

  def Stop(self, page, tab):
    self._results = tab.EvaluateJavaScript('window.__getAllMetrics()')

  def AddResults(self, tab, results):
    """Reports all recorded metrics as Telemetry perf results."""
    trace_names = []
    for media_metric in self._results:
      trace_names.append(self._AddResultsForMediaElement(media_metric, results))

    return '_'.join(trace_names) or tab.url

  def _AddResultsForMediaElement(self, media_metric, results):
    """Reports metrics for one media element.

    Media metrics contain an ID identifying the media element and values:
    media_metric = {
      'id': 'video_1',
      'metrics': {
          'time_to_play': 120,
          'decoded_bytes': 13233,
          ...
      }
    }
    """
    def AddOneResult(metric, unit):
      metrics = media_metric['metrics']
      for m in metrics:
        if m.startswith(metric):
          special_label = m[len(metric):]
          trace_name = '%s.%s%s' % (metric, trace, special_label)
          if isinstance(metrics[m], list):
            results.AddValue(list_of_scalar_values.ListOfScalarValues(
                results.current_page, trace_name, unit,
                values=[float(v) for v in metrics[m]],
                important=True))
          else:
            results.AddValue(scalar.ScalarValue(
                results.current_page, trace_name, unit, value=float(metrics[m]),
                important=True))

    trace = media_metric['id']
    if not trace:
      logging.error('Metrics ID is missing in results.')
      return

    if not self._skip_basic_metrics:
      AddOneResult('buffering_time', 'ms')
      AddOneResult('decoded_audio_bytes', 'bytes')
      AddOneResult('decoded_video_bytes', 'bytes')
      AddOneResult('decoded_frame_count', 'frames')
      AddOneResult('dropped_frame_count', 'frames')
      AddOneResult('time_to_play', 'ms')

    AddOneResult('avg_loop_time', 'ms')
    AddOneResult('seek', 'ms')
    return trace