blob: 12af99909fa0ed3831dc7cf78f5d31dd6fb13cfd [file] [log] [blame]
from __future__ import division
from autotest_lib.client.common_lib.cros.cfm.metrics import (
media_info_metrics_extractor)
MEDIA_TYPE = media_info_metrics_extractor.MediaType
DIRECTION = media_info_metrics_extractor.Direction
# Delta used to determine if floating point values are equal.
FLOATING_POINT_COMPARISON_DELTA = 0.00001
def _avg(l):
"""
Returns the average of the list or 0 if the list is empty.
"""
return sum(l)/len(l) if l else 0
def _get_number_of_incoming_active_video_streams(extractor):
"""
Calculates the number of incoming video streams.
@param extractor media_info_metrics_extractor.MediaInfoMetricsExtractor.
@returns List with (timestamp, number of incoming video streams) tuples.
"""
# Get metrics of a kind we know exists and count the nuber of values
# for each data point.
fps_metrics = extractor.get_media_metric(
'fps', direction=DIRECTION.RECEIVER, media_type=MEDIA_TYPE.VIDEO)
return [(x, [len(y)]) for x, y in fps_metrics]
ADAPTATION_CHANGES = 'adaptation_changes'
ADAPTATION_REASON = 'adaptation_reason'
AVG_ENCODE_MS = 'avg_encode_ms'
BROWSER_CPU_PERCENT_OF_TOTAL = 'browser_cpu_percent'
CPU_PERCENT_OF_TOTAL = 'cpu_percent'
FRAMERATE_CAPTURED = 'framerate_catured'
FRAMERATE_DECODED = 'framerate_decoded'
FRAMERATE_ENCODED = 'framerate_encoded'
FRAMERATE_TO_RENDERER = 'framerate_to_renderer'
FRAMERATE_NETWORK_RECEIVED = 'framerate_network_received'
GPU_PERCENT_OF_TOTAL = 'gpu_cpu_percent'
NUMBER_OF_ACTIVE_INCOMING_VIDEO_STREAMS = 'num_active_vid_in_streams'
PROCESS_JS_MEMORY_USED = 'process_js_memory_used'
RENDERER_CPU_PERCENT_OF_TOTAL = 'renderer_cpu_percent'
VIDEO_RECEIVED_FRAME_HEIGHT = 'video_received_frame_height'
VIDEO_RECEIVED_FRAME_WIDTH = 'video_received_frame_width'
VIDEO_SENT_FRAME_HEIGHT = 'video_sent_frame_height'
VIDEO_SENT_FRAME_WIDTH = 'video_sent_frame_width'
VIDEO_SENT_PACKETS = 'video_sent_packets'
# Mapping between metric names and how to extract the named metric using the
# MediaInfoMetricsExtractor.
METRIC_NAME_TO_EXTRACTOR_FUNC_DICT = {
ADAPTATION_CHANGES:
lambda x: x.get_media_metric('adaptationChanges',
direction=DIRECTION.SENDER,
media_type=MEDIA_TYPE.VIDEO),
ADAPTATION_REASON:
lambda x: x.get_media_metric('adaptationReason',
direction=DIRECTION.SENDER,
media_type=MEDIA_TYPE.VIDEO),
AVG_ENCODE_MS:
lambda x: x.get_media_metric('avgEncodeMs',
direction=DIRECTION.SENDER,
media_type=MEDIA_TYPE.VIDEO),
BROWSER_CPU_PERCENT_OF_TOTAL:
lambda x: x.get_top_level_metric('browserProcessCpuUsage'),
CPU_PERCENT_OF_TOTAL:
lambda x: x.get_top_level_metric('systemcpuusage'),
FRAMERATE_CAPTURED:
lambda x: x.get_media_metric('fps',
direction=DIRECTION.SENDER,
media_type=MEDIA_TYPE.VIDEO),
FRAMERATE_DECODED:
lambda x: x.get_media_metric('fpsdecoded',
direction=DIRECTION.RECEIVER,
media_type=MEDIA_TYPE.VIDEO,
post_process_func=_avg),
FRAMERATE_ENCODED:
lambda x: x.get_media_metric('fpsnetwork',
direction=DIRECTION.SENDER,
media_type=MEDIA_TYPE.VIDEO),
FRAMERATE_NETWORK_RECEIVED:
lambda x: x.get_media_metric('fpsnetwork',
direction=DIRECTION.RECEIVER,
media_type=MEDIA_TYPE.VIDEO),
FRAMERATE_TO_RENDERER:
lambda x: x.get_media_metric('fps',
direction=DIRECTION.RECEIVER,
media_type=MEDIA_TYPE.VIDEO,
post_process_func=_avg),
GPU_PERCENT_OF_TOTAL:
lambda x: x.get_top_level_metric('gpuProcessCpuUsage'),
NUMBER_OF_ACTIVE_INCOMING_VIDEO_STREAMS:
_get_number_of_incoming_active_video_streams,
PROCESS_JS_MEMORY_USED:
lambda x: x.get_top_level_metric('processJsMemoryUsed'),
RENDERER_CPU_PERCENT_OF_TOTAL:
lambda x: x.get_top_level_metric('processcpuusage'),
VIDEO_RECEIVED_FRAME_WIDTH:
lambda x: x.get_media_metric('width',
direction=DIRECTION.RECEIVER,
media_type=MEDIA_TYPE.VIDEO,
post_process_func=_avg),
VIDEO_RECEIVED_FRAME_HEIGHT:
lambda x: x.get_media_metric('height',
direction=DIRECTION.RECEIVER,
media_type=MEDIA_TYPE.VIDEO,
post_process_func=_avg),
VIDEO_SENT_FRAME_HEIGHT:
lambda x: x.get_media_metric('height',
direction=DIRECTION.SENDER,
media_type=MEDIA_TYPE.VIDEO),
VIDEO_SENT_FRAME_WIDTH:
lambda x: x.get_media_metric('width',
direction=DIRECTION.SENDER,
media_type=MEDIA_TYPE.VIDEO),
VIDEO_SENT_PACKETS:
lambda x: x.get_media_metric('packetssent',
direction=DIRECTION.SENDER,
media_type=MEDIA_TYPE.VIDEO),
}
class MetricsCollector(object):
"""Collects metrics for a test run."""
def __init__(self, data_point_collector):
"""
Initializes.
@param data_point_collector
"""
self._data_point_collector = data_point_collector
self._extractor = None
def collect_snapshot(self):
"""
Stores new merics since the last call.
Metrics can then be retrieved by calling get_metric.
"""
self._data_point_collector.collect_snapshot()
data_points = self._data_point_collector.get_data_points()
# Replace the extractor on each snapshot to always support
# getting metrics
self._extractor = (media_info_metrics_extractor
.MediaInfoMetricsExtractor(data_points))
def get_metric(self, name):
"""
Gets the metric with the specified name.
@param name The name of the metric
@returns a list with (timestamp, value_list) tuples
"""
if self._extractor is None:
raise RuntimeError(
'collect_snapshot() must be called at least once.')
return METRIC_NAME_TO_EXTRACTOR_FUNC_DICT[name](
self._extractor)
class DataPointCollector(object):
"""Collects data points."""
def __init__(self, cfm_facade):
"""
Initializes.
@param cfm_facade The cfm facade to use for getting data points.
"""
self._cfm_facade = cfm_facade
self._data_points = []
def collect_snapshot(self):
"""
Collects any new datapoints since the last collection.
"""
data_points = self._cfm_facade.get_media_info_data_points()
last_timestamp = (self._data_points[-1]['timestamp']
if self._data_points else 0)
for data_point in data_points:
if (data_point['timestamp'] >
last_timestamp + FLOATING_POINT_COMPARISON_DELTA):
self._data_points.append(data_point)
def get_data_points(self):
"""
Gets all collected data points.
"""
return self._data_points