1 # Copyright 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 import logging 5 import os 6 7 from metrics import Metric 8 from telemetry.value import list_of_scalar_values 9 from telemetry.value import scalar 10 11 12 class MediaMetric(Metric): 13 """MediaMetric class injects and calls JS responsible for recording metrics. 14 15 Default media metrics are collected for every media element in the page, 16 such as decoded_frame_count, dropped_frame_count, decoded_video_bytes, and 17 decoded_audio_bytes. 18 """ 19 20 def __init__(self, tab): 21 super(MediaMetric, self).__init__() 22 with open(os.path.join(os.path.dirname(__file__), 'media.js')) as f: 23 js = f.read() 24 tab.ExecuteJavaScript(js) 25 self._results = None 26 self._skip_basic_metrics = False 27 28 def Start(self, page, tab): 29 """Create the media metrics for all media elements in the document.""" 30 if hasattr(page, 'skip_basic_metrics'): 31 self._skip_basic_metrics = page.skip_basic_metrics 32 tab.ExecuteJavaScript('window.__createMediaMetricsForDocument()') 33 34 def Stop(self, page, tab): 35 self._results = tab.EvaluateJavaScript('window.__getAllMetrics()') 36 37 def AddResults(self, tab, results): 38 """Reports all recorded metrics as Telemetry perf results.""" 39 trace_names = [] 40 for media_metric in self._results: 41 trace_names.append(self._AddResultsForMediaElement(media_metric, results)) 42 43 return '_'.join(trace_names) or tab.url 44 45 def _AddResultsForMediaElement(self, media_metric, results): 46 """Reports metrics for one media element. 47 48 Media metrics contain an ID identifying the media element and values: 49 media_metric = { 50 'id': 'video_1', 51 'metrics': { 52 'time_to_play': 120, 53 'decoded_bytes': 13233, 54 ... 55 } 56 } 57 """ 58 def AddOneResult(metric, unit): 59 metrics = media_metric['metrics'] 60 for m in metrics: 61 if m.startswith(metric): 62 special_label = m[len(metric):] 63 trace_name = '%s.%s%s' % (metric, trace, special_label) 64 if isinstance(metrics[m], list): 65 results.AddValue(list_of_scalar_values.ListOfScalarValues( 66 results.current_page, trace_name, unit, 67 values=[float(v) for v in metrics[m]], 68 important=True)) 69 else: 70 results.AddValue(scalar.ScalarValue( 71 results.current_page, trace_name, unit, value=float(metrics[m]), 72 important=True)) 73 74 trace = media_metric['id'] 75 if not trace: 76 logging.error('Metrics ID is missing in results.') 77 return 78 79 if not self._skip_basic_metrics: 80 AddOneResult('buffering_time', 'ms') 81 AddOneResult('decoded_audio_bytes', 'bytes') 82 AddOneResult('decoded_video_bytes', 'bytes') 83 AddOneResult('decoded_frame_count', 'frames') 84 AddOneResult('dropped_frame_count', 'frames') 85 AddOneResult('time_to_play', 'ms') 86 87 AddOneResult('avg_loop_time', 'ms') 88 AddOneResult('seek', 'ms') 89 return trace 90