1# Copyright 2015 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
5from telemetry.value import list_of_scalar_values
6from telemetry.value import scalar
7from telemetry.value import improvement_direction
8from telemetry.web_perf.metrics import timeline_based_metric
9from telemetry.web_perf.metrics import webrtc_rendering_stats as stats_helper
10
11WEB_MEDIA_PLAYER_MS_EVENT = 'WebMediaPlayerMS::UpdateCurrentFrame'
12
13
14class WebRtcRenderingTimelineMetric(timeline_based_metric.TimelineBasedMetric):
15  """WebrtcRenderingTimelineMetric calculates metric for WebMediaPlayerMS.
16
17  The following metrics are added to the results:
18    WebRTCRendering_drift_time us
19    WebRTCRendering_percent_badly_out_of_sync %
20    WebRTCRendering_percent_out_of_sync %
21    WebRTCRendering_fps FPS
22    WebRTCRendering_smoothness_score %
23    WebRTCRendering_freezing_score %
24    WebRTCRendering_rendering_length_error %
25  """
26
27  def __init__(self):
28    super(WebRtcRenderingTimelineMetric, self).__init__()
29
30  @staticmethod
31  def IsMediaPlayerMSEvent(event):
32    """Verify that the event is a webmediaplayerMS event."""
33    return event.name == WEB_MEDIA_PLAYER_MS_EVENT
34
35  def AddResults(self, model, renderer_thread, interactions, results):
36    """Adding metrics to the results."""
37    assert interactions
38    found_events = []
39    for event in renderer_thread.parent.IterAllEvents(
40        event_predicate=self.IsMediaPlayerMSEvent):
41      if timeline_based_metric.IsEventInInteractions(event, interactions):
42        found_events.append(event)
43    stats_parser = stats_helper.WebMediaPlayerMsRenderingStats(found_events)
44    rendering_stats = stats_parser.GetTimeStats()
45    none_reason = None
46    if not rendering_stats:
47      # Create a TimeStats object whose members have None values.
48      rendering_stats = stats_helper.TimeStats()
49      none_reason = 'No WebMediaPlayerMS::UpdateCurrentFrame event found'
50    elif rendering_stats.invalid_data:
51      # Throw away the data.
52      rendering_stats = stats_helper.TimeStats()
53      none_reason = 'WebMediaPlayerMS data is corrupted.'
54    results.AddValue(list_of_scalar_values.ListOfScalarValues(
55        results.current_page,
56        'WebRTCRendering_drift_time',
57        'us',
58        rendering_stats.drift_time,
59        important=True,
60        description='Drift time for a rendered frame',
61        tir_label=interactions[0].label,
62        improvement_direction=improvement_direction.DOWN,
63        none_value_reason=none_reason))
64
65    results.AddValue(scalar.ScalarValue(
66        results.current_page,
67        'WebRTCRendering_percent_badly_out_of_sync',
68        '%',
69        rendering_stats.percent_badly_out_of_sync,
70        important=True,
71        description='Percentage of frame which drifted more than 2 VSYNC',
72        tir_label=interactions[0].label,
73        improvement_direction=improvement_direction.DOWN,
74        none_value_reason=none_reason))
75
76    results.AddValue(scalar.ScalarValue(
77        results.current_page,
78        'WebRTCRendering_percent_out_of_sync',
79        '%',
80        rendering_stats.percent_out_of_sync,
81        important=True,
82        description='Percentage of frame which drifted more than 1 VSYNC',
83        tir_label=interactions[0].label,
84        improvement_direction=improvement_direction.DOWN,
85        none_value_reason=none_reason))
86
87    # I removed the frame distribution list from stats as it is not a metric,
88    # rather it is the underlying data. Also there is no sense of improvement
89    # direction for frame distribution.
90
91    results.AddValue(scalar.ScalarValue(
92        results.current_page,
93        'WebRTCRendering_fps',
94        'fps',
95        rendering_stats.fps,
96        important=True,
97        description='Calculated Frame Rate of video rendering',
98        tir_label=interactions[0].label,
99        improvement_direction=improvement_direction.UP,
100        none_value_reason=none_reason))
101
102    results.AddValue(scalar.ScalarValue(
103        results.current_page,
104        'WebRTCRendering_smoothness_score',
105        '%',
106        rendering_stats.smoothness_score,
107        important=True,
108        description='Smoothness score of rendering',
109        tir_label=interactions[0].label,
110        improvement_direction=improvement_direction.UP,
111        none_value_reason=none_reason))
112
113    results.AddValue(scalar.ScalarValue(
114        results.current_page,
115        'WebRTCRendering_freezing_score',
116        '%',
117        rendering_stats.freezing_score,
118        important=True,
119        description='Freezing score of rendering',
120        tir_label=interactions[0].label,
121        improvement_direction=improvement_direction.UP,
122        none_value_reason=none_reason))
123
124    results.AddValue(scalar.ScalarValue(
125        results.current_page,
126        'WebRTCRendering_rendering_length_error',
127        '%',
128        rendering_stats.rendering_length_error,
129        important=True,
130        description='Rendering length error rate',
131        tir_label=interactions[0].label,
132        improvement_direction=improvement_direction.DOWN,
133        none_value_reason=none_reason))
134