Chromium Code Reviews| 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 """Media measurement class gathers media related metrics on a page set. | |
| 6 | |
| 7 Default media metrics are collected for every media element in the page, such as | |
| 8 decoded_frame_count, dropped_frame_count, decoded_video_bytes, and | |
| 9 decoded_audio_bytes. | |
| 10 """ | |
| 11 | |
| 12 import logging | |
| 13 import os | |
| 14 | |
| 15 from telemetry.page import page_measurement | |
| 16 | |
| 17 | |
| 18 class MediaMeasurement(page_measurement.PageMeasurement): | |
| 19 """Provide general video and audio metrics.""" | |
| 20 | |
| 21 def __init__(self): | |
| 22 super(MediaMeasurement, self).__init__('media_metrics') | |
| 23 | |
| 24 def results_are_the_same_on_every_page(self): | |
| 25 """Results can vary from page to page based on media events taking place.""" | |
| 26 return False | |
| 27 | |
| 28 def ReportCollectedMetrics(self, tab, results): | |
| 29 """Reports all recorded metrics as Telemetry perf results. | |
| 30 | |
| 31 Metrics are recorded for each media element in the page. Each metric result | |
| 32 has media info + metric values as a map, for example: | |
| 33 Media metric = { | |
| 34 'info': { | |
| 35 'src': 'file.webm', | |
| 36 'id': 'video1', | |
| 37 ... | |
| 38 }, | |
| 39 'metrics': { | |
| 40 'ttp': [120, 'ms'], | |
| 41 'decoded_bytes': [13233, 'bytes'], | |
| 42 ... | |
| 43 } | |
| 44 } | |
| 45 """ | |
| 46 media_metrics = tab.EvaluateJavaScript('window.__getAllMetrics()') | |
|
nduca
2013/06/17 23:01:33
so you should make a MediaMetrics class that seals
shadi
2013/06/21 00:39:51
Done.
| |
| 47 for media_metric in media_metrics: | |
| 48 self.AddResult(media_metric, results) | |
| 49 | |
| 50 def AddResult(self, media_metric, results): | |
|
nduca
2013/06/17 23:01:33
looks like this doesn't have to be a class method.
shadi
2013/06/21 00:39:51
Done.
| |
| 51 """Adds the media metric result to global results, needed for graphing.""" | |
| 52 info = media_metric['info'] | |
| 53 metrics = media_metric['metrics'] | |
| 54 for metric in metrics: | |
| 55 value, units = GetValueUnit(metrics[metric]) | |
| 56 if not units: | |
| 57 logging.error('Missing units value for media metric %s.', metric) | |
| 58 continue | |
| 59 trace = GetTraceName(info) | |
| 60 results.Add(trace, units, value, chart_name=metric, | |
| 61 data_type='default') | |
| 62 | |
| 63 def LoadDepsJS(self, tab): | |
| 64 """Loads the JS files needed for media metrics, if not already loaded.""" | |
| 65 # Media actions could have already loaded the JS file. | |
| 66 deps_found = tab.EvaluateJavaScript('window.__mediaRecorders != undefined') | |
| 67 if not deps_found: | |
| 68 with open( | |
| 69 os.path.join(os.path.dirname(__file__), 'media_metrics.js')) as f: | |
| 70 js = f.read() | |
| 71 tab.ExecuteJavaScript(js) | |
| 72 | |
| 73 def MeasurePage(self, page, tab, results): | |
| 74 """Measure the page's performance.""" | |
| 75 self.LoadDepsJS(tab) | |
|
nduca
2013/06/17 23:01:33
how bout making this a start/stop pattern and do t
shadi
2013/06/18 00:30:01
I don't see how a start/stop pattern would work fo
| |
| 76 self.ReportCollectedMetrics(tab, results) | |
| 77 | |
| 78 | |
| 79 def GetValueUnit(metric): | |
| 80 """Returns a (value, units) pair stored in a metric if available.""" | |
| 81 if isinstance(metric, (list, tuple)): | |
| 82 if len(metric) > 1: | |
| 83 return (metric[0], metric[1]) | |
| 84 else: | |
| 85 return (metric[0], None) | |
| 86 return (metric, None) | |
| 87 | |
| 88 | |
| 89 def GetTraceName(info): | |
| 90 """Returns a media trace name based on the metric info map. | |
| 91 | |
| 92 In order, returns the first available: | |
| 93 - 'id' key value. | |
| 94 - file name based on 'src' key value. | |
| 95 - the first key value available. | |
| 96 - 'no_trace'. | |
| 97 """ | |
| 98 if 'id' in info: | |
| 99 return info['id'] | |
| 100 elif 'src' in info: | |
| 101 # Return only file name in src. | |
| 102 src = info['src'] | |
| 103 return src[src.rfind('/') + 1:] | |
| 104 else: | |
| 105 for key in info: | |
| 106 return info[key] | |
| 107 return 'no_trace' | |
| OLD | NEW |