• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1from __future__ import division
2
3from autotest_lib.client.common_lib.cros.cfm.metrics import (
4        media_info_metrics_extractor)
5
6MEDIA_TYPE = media_info_metrics_extractor.MediaType
7DIRECTION = media_info_metrics_extractor.Direction
8
9# Delta used to determine if floating point values are equal.
10FLOATING_POINT_COMPARISON_DELTA = 0.00001
11
12
13def _avg(l):
14    """
15    Returns the average of the list or 0 if the list is empty.
16    """
17    return sum(l)/len(l) if l else 0
18
19
20def _get_number_of_incoming_active_video_streams(extractor):
21    """
22    Calculates the number of incoming video streams.
23
24    @param extractor media_info_metrics_extractor.MediaInfoMetricsExtractor.
25
26    @returns List with (timestamp, number of incoming video streams) tuples.
27    """
28    # Get metrics of a kind we know exists and count the nuber of values
29    # for each data point.
30    fps_metrics = extractor.get_media_metric(
31            'fps', direction=DIRECTION.RECEIVER, media_type=MEDIA_TYPE.VIDEO)
32    return [(x, [len(y)]) for x, y in fps_metrics]
33
34
35ADAPTATION_CHANGES = 'adaptation_changes'
36ADAPTATION_REASON = 'adaptation_reason'
37AVG_ENCODE_MS = 'avg_encode_ms'
38BROWSER_CPU_PERCENT_OF_TOTAL = 'browser_cpu_percent'
39CPU_PERCENT_OF_TOTAL = 'cpu_percent'
40FRAMERATE_CAPTURED = 'framerate_catured'
41FRAMERATE_DECODED = 'framerate_decoded'
42FRAMERATE_ENCODED = 'framerate_encoded'
43FRAMERATE_TO_RENDERER = 'framerate_to_renderer'
44FRAMERATE_NETWORK_RECEIVED = 'framerate_network_received'
45GPU_PERCENT_OF_TOTAL = 'gpu_cpu_percent'
46NUMBER_OF_ACTIVE_INCOMING_VIDEO_STREAMS = 'num_active_vid_in_streams'
47PROCESS_JS_MEMORY_USED = 'process_js_memory_used'
48RENDERER_CPU_PERCENT_OF_TOTAL = 'renderer_cpu_percent'
49VIDEO_RECEIVED_FRAME_HEIGHT = 'video_received_frame_height'
50VIDEO_RECEIVED_FRAME_WIDTH = 'video_received_frame_width'
51VIDEO_SENT_FRAME_HEIGHT = 'video_sent_frame_height'
52VIDEO_SENT_FRAME_WIDTH = 'video_sent_frame_width'
53VIDEO_SENT_PACKETS = 'video_sent_packets'
54
55
56# Mapping between metric names and how to extract the named metric using the
57# MediaInfoMetricsExtractor.
58METRIC_NAME_TO_EXTRACTOR_FUNC_DICT = {
59    ADAPTATION_CHANGES:
60        lambda x: x.get_media_metric('adaptationChanges',
61                                     direction=DIRECTION.SENDER,
62                                     media_type=MEDIA_TYPE.VIDEO),
63    ADAPTATION_REASON:
64        lambda x: x.get_media_metric('adaptationReason',
65                                     direction=DIRECTION.SENDER,
66                                     media_type=MEDIA_TYPE.VIDEO),
67    AVG_ENCODE_MS:
68        lambda x: x.get_media_metric('avgEncodeMs',
69                                     direction=DIRECTION.SENDER,
70                                     media_type=MEDIA_TYPE.VIDEO),
71    BROWSER_CPU_PERCENT_OF_TOTAL:
72        lambda x: x.get_top_level_metric('browserProcessCpuUsage'),
73    CPU_PERCENT_OF_TOTAL:
74        lambda x: x.get_top_level_metric('systemcpuusage'),
75    FRAMERATE_CAPTURED:
76        lambda x: x.get_media_metric('fps',
77                                     direction=DIRECTION.SENDER,
78                                     media_type=MEDIA_TYPE.VIDEO),
79    FRAMERATE_DECODED:
80        lambda x: x.get_media_metric('fpsdecoded',
81                                     direction=DIRECTION.RECEIVER,
82                                     media_type=MEDIA_TYPE.VIDEO,
83                                     post_process_func=_avg),
84    FRAMERATE_ENCODED:
85       lambda x: x.get_media_metric('fpsnetwork',
86                                     direction=DIRECTION.SENDER,
87                                     media_type=MEDIA_TYPE.VIDEO),
88    FRAMERATE_NETWORK_RECEIVED:
89        lambda x: x.get_media_metric('fpsnetwork',
90                                     direction=DIRECTION.RECEIVER,
91                                     media_type=MEDIA_TYPE.VIDEO),
92    FRAMERATE_TO_RENDERER:
93        lambda x: x.get_media_metric('fps',
94                                     direction=DIRECTION.RECEIVER,
95                                     media_type=MEDIA_TYPE.VIDEO,
96                                     post_process_func=_avg),
97    GPU_PERCENT_OF_TOTAL:
98        lambda x: x.get_top_level_metric('gpuProcessCpuUsage'),
99    NUMBER_OF_ACTIVE_INCOMING_VIDEO_STREAMS:
100        _get_number_of_incoming_active_video_streams,
101    PROCESS_JS_MEMORY_USED:
102        lambda x: x.get_top_level_metric('processJsMemoryUsed'),
103    RENDERER_CPU_PERCENT_OF_TOTAL:
104        lambda x: x.get_top_level_metric('processcpuusage'),
105    VIDEO_RECEIVED_FRAME_WIDTH:
106        lambda x: x.get_media_metric('width',
107                                     direction=DIRECTION.RECEIVER,
108                                     media_type=MEDIA_TYPE.VIDEO,
109                                     post_process_func=_avg),
110    VIDEO_RECEIVED_FRAME_HEIGHT:
111        lambda x: x.get_media_metric('height',
112                                     direction=DIRECTION.RECEIVER,
113                                     media_type=MEDIA_TYPE.VIDEO,
114                                     post_process_func=_avg),
115    VIDEO_SENT_FRAME_HEIGHT:
116        lambda x: x.get_media_metric('height',
117                                     direction=DIRECTION.SENDER,
118                                     media_type=MEDIA_TYPE.VIDEO),
119    VIDEO_SENT_FRAME_WIDTH:
120        lambda x: x.get_media_metric('width',
121                                     direction=DIRECTION.SENDER,
122                                     media_type=MEDIA_TYPE.VIDEO),
123    VIDEO_SENT_PACKETS:
124        lambda x: x.get_media_metric('packetssent',
125                                     direction=DIRECTION.SENDER,
126                                     media_type=MEDIA_TYPE.VIDEO),
127}
128
129class MetricsCollector(object):
130    """Collects metrics for a test run."""
131
132    def __init__(self, data_point_collector):
133        """
134        Initializes.
135
136        @param data_point_collector
137        """
138        self._data_point_collector = data_point_collector
139        self._extractor = None
140
141    def collect_snapshot(self):
142        """
143        Stores new merics since the last call.
144
145        Metrics can then be retrieved by calling get_metric.
146        """
147        self._data_point_collector.collect_snapshot()
148        data_points = self._data_point_collector.get_data_points()
149        # Replace the extractor on each snapshot to always support
150        # getting metrics
151        self._extractor = (media_info_metrics_extractor
152                           .MediaInfoMetricsExtractor(data_points))
153
154    def get_metric(self, name):
155        """
156        Gets the metric with the specified name.
157
158        @param name The name of the metric
159        @returns a list with (timestamp, value_list) tuples
160        """
161        if self._extractor is None:
162            raise RuntimeError(
163                    'collect_snapshot() must be called at least once.')
164        return METRIC_NAME_TO_EXTRACTOR_FUNC_DICT[name](
165                self._extractor)
166
167
168class DataPointCollector(object):
169    """Collects data points."""
170
171    def __init__(self, cfm_facade):
172        """
173        Initializes.
174
175        @param cfm_facade The cfm facade to use for getting data points.
176        """
177        self._cfm_facade = cfm_facade
178        self._data_points = []
179
180    def collect_snapshot(self):
181        """
182        Collects any new datapoints since the last collection.
183        """
184        data_points = self._cfm_facade.get_media_info_data_points()
185        last_timestamp = (self._data_points[-1]['timestamp']
186                          if self._data_points else 0)
187        for data_point in data_points:
188            if (data_point['timestamp'] >
189                    last_timestamp + FLOATING_POINT_COMPARISON_DELTA):
190                self._data_points.append(data_point)
191
192    def get_data_points(self):
193        """
194        Gets all collected data points.
195        """
196        return self._data_points
197