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

Side by Side Diff: webrtc/tools/py_event_log_analyzer/rtp_analyzer.py

Issue 2178973005: Improvements to bandwidth plot. See Monorail issue for comparison. (Closed) Base URL: https://chromium.googlesource.com/external/webrtc.git@master
Patch Set: Improved the delay plot. Created 4 years, 4 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
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 # Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. 1 # Copyright (c) 2016 The WebRTC project authors. All Rights Reserved.
2 # 2 #
3 # Use of this source code is governed by a BSD-style license 3 # Use of this source code is governed by a BSD-style license
4 # that can be found in the LICENSE file in the root of the source 4 # that can be found in the LICENSE file in the root of the source
5 # tree. An additional intellectual property rights grant can be found 5 # tree. An additional intellectual property rights grant can be found
6 # in the file PATENTS. All contributing project authors may 6 # in the file PATENTS. All contributing project authors may
7 # be found in the AUTHORS file in the root of the source tree. 7 # be found in the AUTHORS file in the root of the source tree.
8 8
9 """Displays statistics and plots graphs from RTC protobuf dump.""" 9 """Displays statistics and plots graphs from RTC protobuf dump."""
10 10
11 from __future__ import division 11 from __future__ import division
12 from __future__ import print_function 12 from __future__ import print_function
13 13
14 import collections 14 import collections
15 import optparse 15 import optparse
16 import sys 16 import sys
17 17
18 import matplotlib.pyplot as plt 18 import matplotlib.pyplot as plt
19 import numpy 19 import numpy
20 20
21 import misc 21 import misc
22 import pb_parse 22 import pb_parse
23 23
24 24
25 class RTPStatistics(object): 25 class RTPStatistics(object):
26 """Has methods for calculating and plotting RTP stream statistics.""" 26 """Has methods for calculating and plotting RTP stream statistics."""
27 27
28 BANDWIDTH_SMOOTHING_WINDOW_SIZE = 10 28 BANDWIDTH_SMOOTHING_WINDOW_SIZE = 10
29 PLOT_RESOLUTION_MS = 50
29 30
30 def __init__(self, data_points): 31 def __init__(self, data_points):
31 """Initializes object with data_points and computes simple statistics. 32 """Initializes object with data_points and computes simple statistics.
32 33
33 Computes percentages of number of packets and packet sizes by 34 Computes percentages of number of packets and packet sizes by
34 SSRC. 35 SSRC.
35 36
36 Args: 37 Args:
37 data_points: list of pb_parse.DataPoints on which statistics are 38 data_points: list of pb_parse.DataPoints on which statistics are
38 calculated. 39 calculated.
(...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after
163 if freq is None or always_query_sample_rate: 164 if freq is None or always_query_sample_rate:
164 if not always_query_sample_rate: 165 if not always_query_sample_rate:
165 print ("Frequency could not be guessed.", end=" ") 166 print ("Frequency could not be guessed.", end=" ")
166 freq = int(misc.get_input("Input frequency (in kHz)> ")) 167 freq = int(misc.get_input("Input frequency (in kHz)> "))
167 else: 168 else:
168 print("Guessed frequency: {}kHz".format(freq)) 169 print("Guessed frequency: {}kHz".format(freq))
169 170
170 for point in self.data_points: 171 for point in self.data_points:
171 point.real_send_time_ms = (point.timestamp - 172 point.real_send_time_ms = (point.timestamp -
172 self.data_points[0].timestamp) / freq 173 self.data_points[0].timestamp) / freq
173 point.delay = point.arrival_timestamp_ms -point.real_send_time_ms 174 point.delay = point.arrival_timestamp_ms - point.real_send_time_ms
174 175
175 def print_duration_statistics(self): 176 def print_duration_statistics(self):
176 """Prints delay, clock drift and bitrate statistics.""" 177 """Prints delay, clock drift and bitrate statistics."""
177 178
178 min_delay = min(point.delay for point in self.data_points) 179 min_delay = min(point.delay for point in self.data_points)
179 180
180 for point in self.data_points: 181 for point in self.data_points:
181 point.absdelay = point.delay - min_delay 182 point.absdelay = point.delay - min_delay
182 183
183 stream_duration_sender = self.data_points[-1].real_send_time_ms / 1000 184 stream_duration_sender = self.data_points[-1].real_send_time_ms / 1000
(...skipping 30 matching lines...) Expand all
214 last = point 215 last = point
215 self.data_points = data_points_ordered 216 self.data_points = data_points_ordered
216 217
217 def compute_bandwidth(self): 218 def compute_bandwidth(self):
218 """Computes bandwidth averaged over several consecutive packets. 219 """Computes bandwidth averaged over several consecutive packets.
219 220
220 The number of consecutive packets used in the average is 221 The number of consecutive packets used in the average is
221 BANDWIDTH_SMOOTHING_WINDOW_SIZE. Averaging is done with 222 BANDWIDTH_SMOOTHING_WINDOW_SIZE. Averaging is done with
222 numpy.correlate. 223 numpy.correlate.
223 """ 224 """
224 self.bandwidth_kbps = [] 225 start_ms = self.data_points[0].real_send_time_ms
225 for i in range(len(self.data_points) - 1): 226 stop_ms = self.data_points[-1].real_send_time_ms
226 self.bandwidth_kbps.append(self.data_points[i].size * 8 / 227 (self.bandwidth_kbps, _) = numpy.histogram(
227 (self.data_points[i + 228 [point.real_send_time_ms for point in self.data_points],
228 1].real_send_time_ms - 229 bins=numpy.arange(start_ms, stop_ms,
229 self.data_points[i].real_send_time_ms) 230 RTPStatistics.PLOT_RESOLUTION_MS),
230 ) 231 weights=[point.size * 8 / RTPStatistics.PLOT_RESOLUTION_MS
232 for point in self.data_points]
233 )
231 correlate_filter = (numpy.ones( 234 correlate_filter = (numpy.ones(
232 RTPStatistics.BANDWIDTH_SMOOTHING_WINDOW_SIZE) / 235 RTPStatistics.BANDWIDTH_SMOOTHING_WINDOW_SIZE) /
233 RTPStatistics.BANDWIDTH_SMOOTHING_WINDOW_SIZE) 236 RTPStatistics.BANDWIDTH_SMOOTHING_WINDOW_SIZE)
234 self.smooth_bw_kbps = numpy.correlate(self.bandwidth_kbps, correlate_filter) 237 self.smooth_bw_kbps = numpy.correlate(self.bandwidth_kbps, correlate_filter)
235 238
236 def plot_statistics(self): 239 def plot_statistics(self):
237 """Plots changes in delay and average bandwidth.""" 240 """Plots changes in delay and average bandwidth."""
241
242 start_ms = self.data_points[0].real_send_time_ms
243 stop_ms = self.data_points[-1].real_send_time_ms
244 time_axis = numpy.arange(start_ms / 1000, stop_ms / 1000,
245 RTPStatistics.PLOT_RESOLUTION_MS / 1000)
246
247 delay = calculate_delay(start_ms, stop_ms,
248 RTPStatistics.PLOT_RESOLUTION_MS,
phoglund 2016/07/28 06:28:55 Nit: indent
aleloi 2016/07/28 08:41:46 Done.
249 self.data_points)
250
238 plt.figure(1) 251 plt.figure(1)
239 plt.plot([f.real_send_time_ms / 1000 for f in self.data_points], 252 plt.plot(time_axis, delay)
240 [f.absdelay for f in self.data_points])
241 plt.xlabel("Send time [s]") 253 plt.xlabel("Send time [s]")
242 plt.ylabel("Relative transport delay [ms]") 254 plt.ylabel("Relative transport delay [ms]")
243 255
244 plt.figure(2) 256 plt.figure(2)
245 plt.plot([f.real_send_time_ms / 1000 for f in 257 plt.plot(time_axis[:len(self.smooth_bw_kbps)], self.smooth_bw_kbps)
246 self.data_points][:len(self.smooth_bw_kbps)],
247 self.smooth_bw_kbps[:len(self.data_points)])
248 plt.xlabel("Send time [s]") 258 plt.xlabel("Send time [s]")
249 plt.ylabel("Bandwidth [kbps]") 259 plt.ylabel("Bandwidth [kbps]")
250 260
251 plt.show() 261 plt.show()
252 262
253 263
264 def calculate_delay(start, stop, step, points):
265 """Regularizes the time coordinates for the delay.
266
267 Regularizes points by rounding the timestamps to the nearest point
phoglund 2016/07/28 06:28:55 Isn't this "quantizing"?
stefan-webrtc 2016/07/28 07:13:36 Perhaps you can use numpy's digitize instead? http
aleloi 2016/07/28 08:41:46 I'd rather not use that, I think. Based on the des
aleloi 2016/07/28 08:41:46 Wikipedia confirms that "quantizing" is the correc
268 in the time sequence start, start+step, start+2*step... Takes the
269 average of the delays of points rounded to the same. Returns
270 masked array, in which time points with no value are masked.
271 """
272 grouped_delays = [[] for _ in numpy.arange(start, stop, step)]
273 rounded_value_index = lambda x: int((x - start) / step)
274 for point in points:
275 grouped_delays[rounded_value_index(point.real_send_time_ms)
276 ].append(point.absdelay)
277 regularized_delays = [numpy.average(arr) if arr else None for arr in
278 grouped_delays]
279 return numpy.ma.masked_values(regularized_delays, None)
280
281
254 def main(): 282 def main():
255 usage = "Usage: %prog [options] <filename of rtc event log>" 283 usage = "Usage: %prog [options] <filename of rtc event log>"
256 parser = optparse.OptionParser(usage=usage) 284 parser = optparse.OptionParser(usage=usage)
257 parser.add_option("--dump_header_to_stdout", 285 parser.add_option("--dump_header_to_stdout",
258 default=False, action="store_true", 286 default=False, action="store_true",
259 help="print header info to stdout; similar to rtp_analyze") 287 help="print header info to stdout; similar to rtp_analyze")
260 parser.add_option("--query_sample_rate", 288 parser.add_option("--query_sample_rate",
261 default=False, action="store_true", 289 default=False, action="store_true",
262 help="always query user for real sample rate") 290 help="always query user for real sample rate")
263 291
(...skipping 19 matching lines...) Expand all
283 print("Statistics:") 311 print("Statistics:")
284 rtp_stats.print_sequence_number_statistics() 312 rtp_stats.print_sequence_number_statistics()
285 rtp_stats.estimate_frequency(options.query_sample_rate) 313 rtp_stats.estimate_frequency(options.query_sample_rate)
286 rtp_stats.print_duration_statistics() 314 rtp_stats.print_duration_statistics()
287 rtp_stats.remove_reordered() 315 rtp_stats.remove_reordered()
288 rtp_stats.compute_bandwidth() 316 rtp_stats.compute_bandwidth()
289 rtp_stats.plot_statistics() 317 rtp_stats.plot_statistics()
290 318
291 if __name__ == "__main__": 319 if __name__ == "__main__":
292 main() 320 main()
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698