xref: /aosp_15_r20/external/webrtc/rtc_tools/network_tester/parse_packet_log.py (revision d9f758449e529ab9291ac668be2861e7a55c2422)
1#  Copyright (c) 2017 The WebRTC project authors. All Rights Reserved.
2#
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
5#  tree. An additional intellectual property rights grant can be found
6#  in the file PATENTS.  All contributing project authors may
7#  be found in the AUTHORS file in the root of the source tree.
8
9#  To run this script please copy "out/<build_name>/pyproto/webrtc/rtc_tools/
10#  network_tester/network_tester_packet_pb2.py" next to this script.
11#  The you can run this script with:
12#  "python parse_packet_log.py -f packet_log.dat"
13#  for more information call:
14#  "python parse_packet_log.py --help"
15
16from optparse import OptionParser
17import struct
18
19import matplotlib.pyplot as plt
20
21import network_tester_packet_pb2
22
23
24def GetSize(file_to_parse):
25    data = file_to_parse.read(1)
26    if data == '':
27        return 0
28    return struct.unpack('<b', data)[0]
29
30
31def ParsePacketLog(packet_log_file_to_parse):
32    packets = []
33    with open(packet_log_file_to_parse, 'rb') as file_to_parse:
34        while True:
35            size = GetSize(file_to_parse)
36            if size == 0:
37                break
38            try:
39                packet = network_tester_packet_pb2.NetworkTesterPacket()
40                packet.ParseFromString(file_to_parse.read(size))
41                packets.append(packet)
42            except IOError:
43                break
44    return packets
45
46
47def GetTimeAxis(packets):
48    first_arrival_time = packets[0].arrival_timestamp
49    return [(packet.arrival_timestamp - first_arrival_time) / 1000000.0
50            for packet in packets]
51
52
53def CreateSendTimeDiffPlot(packets, plot):
54    first_send_time_diff = (packets[0].arrival_timestamp -
55                            packets[0].send_timestamp)
56    y = [(packet.arrival_timestamp - packet.send_timestamp) -
57         first_send_time_diff for packet in packets]
58    plot.grid(True)
59    plot.set_title("SendTime difference [us]")
60    plot.plot(GetTimeAxis(packets), y)
61
62
63class MovingAverageBitrate(object):
64    def __init__(self):
65        self.packet_window = []
66        self.window_time = 1000000
67        self.bytes = 0
68        self.latest_packet_time = 0
69        self.send_interval = 0
70
71    def RemoveOldPackets(self):
72        for packet in self.packet_window:
73            if (self.latest_packet_time - packet.arrival_timestamp >
74                    self.window_time):
75                self.bytes = self.bytes - packet.packet_size
76                self.packet_window.remove(packet)
77
78    def AddPacket(self, packet):
79        """This functions returns bits / second"""
80        self.send_interval = packet.arrival_timestamp - self.latest_packet_time
81        self.latest_packet_time = packet.arrival_timestamp
82        self.RemoveOldPackets()
83        self.packet_window.append(packet)
84        self.bytes = self.bytes + packet.packet_size
85        return self.bytes * 8
86
87
88def CreateReceiveBiratePlot(packets, plot):
89    bitrate = MovingAverageBitrate()
90    y = [bitrate.AddPacket(packet) for packet in packets]
91    plot.grid(True)
92    plot.set_title("Receive birate [bps]")
93    plot.plot(GetTimeAxis(packets), y)
94
95
96def CreatePacketlossPlot(packets, plot):
97    packets_look_up = {}
98    first_sequence_number = packets[0].sequence_number
99    last_sequence_number = packets[-1].sequence_number
100    for packet in packets:
101        packets_look_up[packet.sequence_number] = packet
102    y = []
103    x = []
104    first_arrival_time = 0
105    last_arrival_time = 0
106    last_arrival_time_diff = 0
107    for sequence_number in range(first_sequence_number,
108                                 last_sequence_number + 1):
109        if sequence_number in packets_look_up:
110            y.append(0)
111            if first_arrival_time == 0:
112                first_arrival_time = packets_look_up[
113                    sequence_number].arrival_timestamp
114            x_time = (packets_look_up[sequence_number].arrival_timestamp -
115                      first_arrival_time)
116            if last_arrival_time != 0:
117                last_arrival_time_diff = x_time - last_arrival_time
118            last_arrival_time = x_time
119            x.append(x_time / 1000000.0)
120        else:
121            if last_arrival_time != 0 and last_arrival_time_diff != 0:
122                x.append(
123                    (last_arrival_time + last_arrival_time_diff) / 1000000.0)
124                y.append(1)
125    plot.grid(True)
126    plot.set_title("Lost packets [0/1]")
127    plot.plot(x, y)
128
129
130def main():
131    parser = OptionParser()
132    parser.add_option("-f",
133                      "--packet_log_file",
134                      dest="packet_log_file",
135                      help="packet_log file to parse")
136
137    options = parser.parse_args()[0]
138
139    packets = ParsePacketLog(options.packet_log_file)
140    f, plots = plt.subplots(3, sharex=True)
141    plt.xlabel('time [sec]')
142    CreateSendTimeDiffPlot(packets, plots[0])
143    CreateReceiveBiratePlot(packets, plots[1])
144    CreatePacketlossPlot(packets, plots[2])
145    f.subplots_adjust(hspace=0.3)
146    plt.show()
147
148
149if __name__ == "__main__":
150    main()
151