Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(206)

Side by Side Diff: tools/telemetry/telemetry/web_perf/metrics/webrtc_rendering_stats_unittest.py

Issue 1254023003: Telemetry Test for WebRTC Rendering. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Accomodate 'Serial' field definition change and minor fixes. Created 5 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 import unittest
2
3 import mock
4
5 import numpy
6
7 from telemetry.web_perf.metrics import webrtc_rendering_stats as stats_helper
8
9
10 class FakeEvent(object):
11 """Fake event class to mock rendering events."""
12
13 def __init__(self, **kwargs):
14 """Initializer for the fake WebMediaPlayerMS::UpdateCurrentFrame events.
15
16 The WebMediaPlayerMsRenderingStats only cares about actual render begin,
17 actual render end, ideal render instant and serial fields of the events.
18 So we only define these four fields here in this fake event class.
19 This method is written so as to take whatever valid parameters from the
20 event definition. It can also be used to craft incomplete events.
21
22 Args:
23 kwargs::= dict('actual_begin', 'actual_end', 'ideal_instant', 'serial').
24 """
25 self.args = {}
26 name_map = {
27 'Actual Render Begin': 'actual_begin',
28 'Actual Render End': 'actual_end',
29 'Ideal Render Instant': 'ideal_instant',
30 'Serial': 'serial'}
31 for internal_name, external_name in name_map.iteritems():
32 if external_name in kwargs:
33 self.args[internal_name] = kwargs[external_name]
34
35
36 class WebMediaPlayerMsRenderingStatsTest(unittest.TestCase):
37
38 def setUp(self):
39 # A local stream id always has an even number.
40 # A remote stream id always has an odd number.
41 self.local_stream = 136390988
42 self.remote_stream = 118626165
43
44 def testInitialization(self):
45 event_local_stream = FakeEvent(actual_begin=1655987203306,
46 actual_end=1655987219972, ideal_instant=1655987154324,
47 serial=self.local_stream)
48
49 event_remote_stream = FakeEvent(actual_begin=1655987203306,
50 actual_end=1655987219972, ideal_instant=1655987167999,
51 serial=self.remote_stream)
52
53 stats_parser = stats_helper.WebMediaPlayerMsRenderingStats(
54 [event_local_stream, event_remote_stream])
55
56 self.assertEqual(2, len(stats_parser.stream_to_events))
57
58 self.assertEqual(event_local_stream.args,
59 stats_parser.stream_to_events[self.local_stream][0].args)
60
61 self.assertEqual(event_remote_stream.args,
62 stats_parser.stream_to_events[self.remote_stream][0].args)
63
64 def testInvalidEvents(self):
65 event_missing_serial = FakeEvent(actual_begin=1655987244074,
66 actual_end=1655987260740, ideal_instant=1655987204839)
67
68 event_missing_actual_begin = FakeEvent(actual_end=1655987260740,
69 ideal_instant=1655987217999, serial=self.local_stream)
70
71 event_missing_actual_end = FakeEvent(actual_end=1655987260740,
72 ideal_instant=1655987217999, serial=self.remote_stream)
73
74 event_missing_ideal_instant = FakeEvent(actual_begin=1655987260740,
75 actual_end=1655987277406, serial=self.remote_stream)
76
77 stats_parser = stats_helper.WebMediaPlayerMsRenderingStats(
78 [event_missing_serial, event_missing_actual_begin,
79 event_missing_actual_end, event_missing_ideal_instant])
80
81 self.assertEqual(0, len(stats_parser.stream_to_events))
82
83 def _GetFakeEvents(self):
84 fake_events = [
85 FakeEvent(actual_begin=1663780195583, actual_end=1663780212249,
86 ideal_instant=1663780179998, serial=self.remote_stream),
87 FakeEvent(actual_begin=1663780212249, actual_end=1663780228915,
88 ideal_instant=1663780179998, serial=self.remote_stream),
89 FakeEvent(actual_begin=1663780228915, actual_end=1663780245581,
90 ideal_instant=1663780197998, serial=self.remote_stream),
91 FakeEvent(actual_begin=1663780245581, actual_end=1663780262247,
92 ideal_instant=1663780215998, serial=self.remote_stream),
93 FakeEvent(actual_begin=1663780262247, actual_end=1663780278913,
94 ideal_instant=1663780215998, serial=self.remote_stream),
95 FakeEvent(actual_begin=1663780278913, actual_end=1663780295579,
96 ideal_instant=1663780254998, serial=self.remote_stream),
97 FakeEvent(actual_begin=1663780295579, actual_end=1663780312245,
98 ideal_instant=1663780254998, serial=self.remote_stream),
99 FakeEvent(actual_begin=1663780312245, actual_end=1663780328911,
100 ideal_instant=1663780254998, serial=self.remote_stream),
101 FakeEvent(actual_begin=1663780328911, actual_end=1663780345577,
102 ideal_instant=1663780310998, serial=self.remote_stream),
103 FakeEvent(actual_begin=1663780345577, actual_end=1663780362243,
104 ideal_instant=1663780310998, serial=self.remote_stream),
105 FakeEvent(actual_begin=1663780362243, actual_end=1663780378909,
106 ideal_instant=1663780310998, serial=self.remote_stream),
107 FakeEvent(actual_begin=1663780378909, actual_end=1663780395575,
108 ideal_instant=1663780361998, serial=self.remote_stream),
109 FakeEvent(actual_begin=1663780395575, actual_end=1663780412241,
110 ideal_instant=1663780361998, serial=self.remote_stream),
111 FakeEvent(actual_begin=1663780412241, actual_end=1663780428907,
112 ideal_instant=1663780361998, serial=self.remote_stream),
113 FakeEvent(actual_begin=1663780428907, actual_end=1663780445573,
114 ideal_instant=1663780412998, serial=self.remote_stream)]
115
116 return fake_events
117
118 def testGetCadence(self):
119 fake_events = self._GetFakeEvents()
120 stats_parser = stats_helper.WebMediaPlayerMsRenderingStats(fake_events)
121 # The events defined in _GetFakeEvents above show that the first source
122 # framee of ideal_instant=1663780179998 is rendered twice, then
123 # the second source frame of ideal_instant=1663780197998 is rendered once
124 # the third source frame of ideal_instant=1663780215998 is rendered twice
125 # and so on. The expected cadence will therefore be [2 1 2 etc..]
126 expected_cadence = [2, 1, 2, 3, 3, 3, 1]
127 self.assertEqual(expected_cadence, stats_parser._GetCadence(fake_events))
128
129 def testGetSourceToOutputDistribution(self):
130 stats_parser = stats_helper.WebMediaPlayerMsRenderingStats([])
131 cadence = [2, 1, 2, 3, 3, 3, 1]
132 expected_frame_distribution = {1: 2, 2: 2, 3: 3}
133 self.assertEqual(expected_frame_distribution,
134 stats_parser._GetSourceToOutputDistribution(cadence))
135
136 def testGetFpsFromCadence(self):
137 frame_distribution = {1: 2, 2: 2, 3: 3}
138 stats_parser = stats_helper.WebMediaPlayerMsRenderingStats([])
139 expected_frame_rate = 28.0
140 self.assertEqual(expected_frame_rate,
141 stats_parser._GetFpsFromCadence(frame_distribution))
142
143 def testGetFrozenFramesReports(self):
144 frame_distribution = {1: 2, 2: 2, 3: 569, 6: 1}
145 expected_frozen_reports = [{'frozen_frames': 5, 'occurrences': 1}]
146 stats_parser = stats_helper.WebMediaPlayerMsRenderingStats([])
147 self.assertEqual(expected_frozen_reports,
148 stats_parser._GetFrozenFramesReports(frame_distribution))
149
150 def testIsRemoteStream(self):
151 stats_parser = stats_helper.WebMediaPlayerMsRenderingStats([])
152 self.assertTrue(stats_parser._IsRemoteStream(self.remote_stream))
153
154 def testGetDrifTimeStats(self):
155 fake_events = self._GetFakeEvents()
156 stats_parser = stats_helper.WebMediaPlayerMsRenderingStats([])
157 cadence = stats_parser._GetCadence(fake_events)
158 expected_drift_time = [15585, 30917, 29583, 23915, 17913, 16911, 15909]
159 expected_rendering_length_error = 29.613733905579398
160
161 self.assertEqual((expected_drift_time, expected_rendering_length_error),
162 stats_parser._GetDrifTimeStats(fake_events, cadence))
163
164 def testGetSmoothnessStats(self):
165 norm_drift_time = [5948.2857142857138, 9383.7142857142862,
166 8049.7142857142862, 2381.7142857142862, 3620.2857142857138,
167 4622.2857142857138, 5624.2857142857138]
168 stats_parser = stats_helper.WebMediaPlayerMsRenderingStats([])
169 expected_percent_badly_oos = 0.0
170 expected_percent_out_of_sync = 0.0
171 expected_smoothness_score = 100.0
172 expected_smoothness_stats = (expected_percent_badly_oos,
173 expected_percent_out_of_sync, expected_smoothness_score)
174
175 self.assertEqual(expected_smoothness_stats,
176 stats_parser._GetSmoothnessStats(norm_drift_time))
177
178 def testNegativeSmoothnessScoreChangedToZero(self):
179 norm_drift_time = [15948.285714285714, 9383.714285714286,
180 28049.714285714286, 72381.71428571429, 3620.2857142857138,
181 4622.285714285714, 35624.28571428572]
182 stats_parser = stats_helper.WebMediaPlayerMsRenderingStats([])
183 expected_percent_badly_oos = 28.571428571428573
184 expected_percent_out_of_sync = 42.857142857142854
185 expected_smoothness_score = 0.0
186 expected_smoothness_stats = (expected_percent_badly_oos,
187 expected_percent_out_of_sync, expected_smoothness_score)
188
189 self.assertEqual(expected_smoothness_stats,
190 stats_parser._GetSmoothnessStats(norm_drift_time))
191
192 def testGetFreezingScore(self):
193 frame_distribution = {1: 2, 2: 2, 3: 569, 6: 1}
194 stats_parser = stats_helper.WebMediaPlayerMsRenderingStats([])
195 expected_freezing_score = 99.94182664339732
196 self.assertEqual(expected_freezing_score,
197 stats_parser._GetFreezingScore(frame_distribution))
198
199 def testNegativeFrezingScoreChangedToZero(self):
200 frame_distribution = {1: 2, 2: 2, 3: 2, 8:100}
201 stats_parser = stats_helper.WebMediaPlayerMsRenderingStats([])
202 self.assertEqual(0.0, stats_parser._GetFreezingScore(frame_distribution))
203
204 def testGetTimeStats(self):
205 fake_events = self._GetFakeEvents()
206 expected_cadence = [2, 1, 2, 3, 3, 3, 1]
207 expected_frame_dist = {1: 2, 2: 2, 3: 569, 6: 1}
208 expected_frame_rate = 28.0
209 expected_drift_time = [15585, 30917, 29583, 23915, 17913, 16911, 15909]
210 expected_rendering_length_error = 29.613733905579398
211 expected_percent_badly_oos = 0.0
212 expected_percent_out_of_sync = 0.0
213 expected_smoothness_score = 100.0
214 expected_freezing_score = 99.94182664339732
215
216 stats_cls = stats_helper.WebMediaPlayerMsRenderingStats
217 stats_cls._GetCadence = mock.Mock()
218 stats_cls._GetCadence.return_value = expected_cadence
219 stats_cls._GetSourceToOutputDistribution = mock.Mock()
220 stats_cls._GetSourceToOutputDistribution.return_value = expected_frame_dist
221 stats_cls._GetFpsFromCadence = mock.Mock()
222 stats_cls._GetFpsFromCadence.return_value = expected_frame_rate
223 stats_cls._GetDrifTimeStats = mock.Mock()
224 stats_cls._GetDrifTimeStats.return_value = (expected_drift_time,
225 expected_rendering_length_error)
226 stats_cls._GetSmoothnessStats = mock.Mock()
227 stats_cls._GetSmoothnessStats.return_value = (expected_percent_badly_oos,
228 expected_percent_out_of_sync, expected_smoothness_score)
229 stats_cls._GetFreezingScore = mock.Mock()
230 stats_cls._GetFreezingScore.return_value = expected_freezing_score
231
232 stats_parser = stats_cls(fake_events)
233
234 expected_stats = {
235 'drift_time': expected_drift_time,
236 'mean_drift_time': numpy.mean(expected_drift_time),
237 'std_dev_drift_time': numpy.std(expected_drift_time),
238 'percent_badly_out_of_sync': expected_percent_badly_oos,
239 'percent_out_of_sync': expected_percent_out_of_sync,
240 'smoothness_score': expected_smoothness_score,
241 'freezing_score': expected_freezing_score,
242 'rendering_length_error': expected_rendering_length_error,
243 'fps': expected_frame_rate,
244 'frame_distribution': expected_frame_dist}
245
246 self.assertEqual(expected_stats, stats_parser.GetTimeStats())
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698