OLD | NEW |
---|---|
(Empty) | |
1 /* | |
2 * Copyright (c) 2015 The WebRTC project authors. All Rights Reserved. | |
3 * | |
4 * Use of this source code is governed by a BSD-style license | |
5 * that can be found in the LICENSE file in the root of the source | |
6 * tree. An additional intellectual property rights grant can be found | |
7 * in the file PATENTS. All contributing project authors may | |
8 * be found in the AUTHORS file in the root of the source tree. | |
9 */ | |
10 | |
11 #include "webrtc/modules/rtp_rtcp/source/packet_loss_stats.h" | |
12 | |
13 static const int kBufferSize = 100; | |
14 | |
15 namespace webrtc { | |
16 | |
17 PacketLossStats::PacketLossStats() | |
18 : single_loss_historic_count_(0), | |
19 multiple_loss_historic_event_count_(0), | |
20 multiple_loss_historic_packet_count_(0) { | |
21 } | |
22 | |
23 void PacketLossStats::AddLostPacket(uint16_t sequence_number) { | |
24 // Detect sequence number wrap around. | |
25 if (sequence_number < 0x4000 && !lost_packets_buffer_.empty() | |
26 && *(lost_packets_buffer_.begin()) > 0xC000) { | |
27 // The buffer contains large numbers and this is a small number. | |
28 lost_packets_wrapped_buffer_.insert(sequence_number); | |
29 } else { | |
30 lost_packets_buffer_.insert(sequence_number); | |
31 } | |
32 if (lost_packets_wrapped_buffer_.size() + lost_packets_buffer_.size() | |
33 > kBufferSize) { | |
34 PruneBuffer(); | |
35 } | |
36 } | |
37 | |
38 int PacketLossStats::GetSingleLossCount() const { | |
39 int single_loss_count, unused1, unused2; | |
40 ComputeLossCounts(&single_loss_count, &unused1, &unused2); | |
41 return single_loss_count; | |
42 } | |
43 | |
44 int PacketLossStats::GetMultipleLossEventCount() const { | |
45 int event_count, unused1, unused2; | |
46 ComputeLossCounts(&unused1, &event_count, &unused2); | |
47 return event_count; | |
48 } | |
49 | |
50 int PacketLossStats::GetMultipleLossPacketCount() const { | |
51 int packet_count, unused1, unused2; | |
52 ComputeLossCounts(&unused1, &unused2, &packet_count); | |
53 return packet_count; | |
54 } | |
55 | |
56 void PacketLossStats::ComputeLossCounts( | |
57 int* out_single_loss_count, | |
58 int* out_multiple_loss_event_count, | |
59 int* out_multiple_loss_packet_count) const { | |
60 *out_single_loss_count = single_loss_historic_count_; | |
61 *out_multiple_loss_event_count = multiple_loss_historic_event_count_; | |
62 *out_multiple_loss_packet_count = multiple_loss_historic_packet_count_; | |
63 if (lost_packets_buffer_.empty()) { | |
64 return; | |
65 } | |
66 uint16_t last_num = 0; | |
67 int sequential_count = 0; | |
68 const std::set<uint16_t>* buffer = &lost_packets_buffer_; | |
69 for (int i = 0; i < 2; ++i) { | |
70 for (auto it = buffer->begin(); it != buffer->end(); ++it) { | |
71 uint16_t next_num = *it; | |
72 if (sequential_count > 0 && next_num != ((last_num + 1) & 0xFFFF)) { | |
73 if (sequential_count == 1) { | |
74 (*out_single_loss_count)++; | |
75 } else if (sequential_count > 1) { | |
harryjin
2015/06/30 18:17:03
Just else is good enough? The else if condition is
bcornell
2015/06/30 19:47:46
Done.
| |
76 (*out_multiple_loss_event_count)++; | |
77 *out_multiple_loss_packet_count += sequential_count; | |
78 } | |
79 sequential_count = 0; | |
80 } | |
81 sequential_count++; | |
82 last_num = next_num; | |
83 } | |
84 buffer = &lost_packets_wrapped_buffer_; | |
85 } | |
86 if (sequential_count == 1) { | |
87 (*out_single_loss_count)++; | |
88 } else if (sequential_count > 1) { | |
89 (*out_multiple_loss_event_count)++; | |
90 *out_multiple_loss_packet_count += sequential_count; | |
91 } | |
92 } | |
93 | |
94 void PacketLossStats::PruneBuffer() { | |
95 // Remove the oldest lost packet and any contiguous packets and move them | |
96 // into the historic counts. | |
97 auto it = lost_packets_buffer_.begin(); | |
98 uint16_t last_removed = *it; | |
99 int remove_count = 1; | |
100 it = lost_packets_buffer_.erase(it); | |
101 while (!lost_packets_buffer_.empty() && *it == last_removed + 1) { | |
102 last_removed++; | |
103 remove_count++; | |
104 it = lost_packets_buffer_.erase(it); | |
105 } | |
106 // Continue counting if it is wrap around by swapping in the wrapped buffer | |
107 // and letting our value wrap as well. | |
108 if (lost_packets_buffer_.empty()) { | |
109 lost_packets_buffer_.swap(lost_packets_wrapped_buffer_); | |
110 it = lost_packets_buffer_.begin(); | |
111 while (!lost_packets_buffer_.empty() | |
112 && *it == ((last_removed + 1) & 0xFFFF)) { | |
113 last_removed = *it; | |
114 remove_count++; | |
115 it = lost_packets_buffer_.erase(it); | |
116 } | |
117 } | |
118 if (remove_count > 1) { | |
119 multiple_loss_historic_event_count_++; | |
120 multiple_loss_historic_packet_count_ += remove_count; | |
121 } else { | |
122 single_loss_historic_count_++; | |
123 } | |
124 } | |
125 | |
126 } // namespace webrtc | |
OLD | NEW |