OLD | NEW |
1 /* | 1 /* |
2 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. | 2 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license | 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 | 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 | 6 * tree. An additional intellectual property rights grant can be found |
7 * in the file PATENTS. All contributing project authors may | 7 * in the file PATENTS. All contributing project authors may |
8 * be found in the AUTHORS file in the root of the source tree. | 8 * be found in the AUTHORS file in the root of the source tree. |
9 */ | 9 */ |
10 | 10 |
11 #include "webrtc/modules/rtp_rtcp/source/rtp_packet_history.h" | 11 #include "webrtc/modules/rtp_rtcp/source/rtp_packet_history.h" |
12 | 12 |
13 #include <assert.h> | |
14 #include <stdlib.h> | |
15 #include <string.h> // memset | |
16 | |
17 #include <algorithm> | 13 #include <algorithm> |
18 #include <limits> | 14 #include <limits> |
19 #include <set> | |
20 | 15 |
21 #include "webrtc/base/checks.h" | 16 #include "webrtc/base/checks.h" |
22 #include "webrtc/base/logging.h" | 17 #include "webrtc/base/logging.h" |
23 #include "webrtc/modules/rtp_rtcp/source/rtp_utility.h" | 18 #include "webrtc/modules/rtp_rtcp/source/rtp_packet_to_send.h" |
| 19 #include "webrtc/system_wrappers/include/clock.h" |
24 | 20 |
25 namespace webrtc { | 21 namespace webrtc { |
| 22 namespace { |
| 23 constexpr size_t kMinPacketRequestBytes = 50; |
| 24 } // namespace |
| 25 constexpr size_t RtpPacketHistory::kMaxCapacity; |
26 | 26 |
27 static const int kMinPacketRequestBytes = 50; | 27 RtpPacketHistory::RtpPacketHistory(Clock* clock) |
| 28 : clock_(clock), store_(false), prev_index_(0) {} |
28 | 29 |
29 RTPPacketHistory::RTPPacketHistory(Clock* clock) | 30 RtpPacketHistory::~RtpPacketHistory() {} |
30 : clock_(clock), | |
31 store_(false), | |
32 prev_index_(0) {} | |
33 | 31 |
34 RTPPacketHistory::~RTPPacketHistory() { | 32 void RtpPacketHistory::SetStorePacketsStatus(bool enable, |
35 } | |
36 | |
37 void RTPPacketHistory::SetStorePacketsStatus(bool enable, | |
38 uint16_t number_to_store) { | 33 uint16_t number_to_store) { |
39 rtc::CritScope cs(&critsect_); | 34 rtc::CritScope cs(&critsect_); |
40 if (enable) { | 35 if (enable) { |
41 if (store_) { | 36 if (store_) { |
42 LOG(LS_WARNING) << "Purging packet history in order to re-set status."; | 37 LOG(LS_WARNING) << "Purging packet history in order to re-set status."; |
43 Free(); | 38 Free(); |
44 } | 39 } |
45 assert(!store_); | 40 RTC_DCHECK(!store_); |
46 Allocate(number_to_store); | 41 Allocate(number_to_store); |
47 } else { | 42 } else { |
48 Free(); | 43 Free(); |
49 } | 44 } |
50 } | 45 } |
51 | 46 |
52 void RTPPacketHistory::Allocate(size_t number_to_store) { | 47 void RtpPacketHistory::Allocate(size_t number_to_store) { |
53 assert(number_to_store > 0); | 48 RTC_DCHECK_GT(number_to_store, 0u); |
54 assert(number_to_store <= kMaxHistoryCapacity); | 49 RTC_DCHECK_LE(number_to_store, kMaxCapacity); |
55 store_ = true; | 50 store_ = true; |
56 stored_packets_.resize(number_to_store); | 51 stored_packets_.resize(number_to_store); |
57 } | 52 } |
58 | 53 |
59 void RTPPacketHistory::Free() { | 54 void RtpPacketHistory::Free() { |
60 if (!store_) { | 55 if (!store_) { |
61 return; | 56 return; |
62 } | 57 } |
63 | 58 |
64 stored_packets_.clear(); | 59 stored_packets_.clear(); |
65 | 60 |
66 store_ = false; | 61 store_ = false; |
67 prev_index_ = 0; | 62 prev_index_ = 0; |
68 } | 63 } |
69 | 64 |
70 bool RTPPacketHistory::StorePackets() const { | 65 bool RtpPacketHistory::StorePackets() const { |
71 rtc::CritScope cs(&critsect_); | 66 rtc::CritScope cs(&critsect_); |
72 return store_; | 67 return store_; |
73 } | 68 } |
74 | 69 |
75 int32_t RTPPacketHistory::PutRTPPacket(const uint8_t* packet, | 70 void RtpPacketHistory::PutRtpPacket(std::unique_ptr<RtpPacketToSend> packet, |
76 size_t packet_length, | 71 StorageType type, |
77 int64_t capture_time_ms, | 72 bool sent) { |
78 StorageType type) { | 73 RTC_DCHECK(packet); |
79 rtc::CritScope cs(&critsect_); | 74 rtc::CritScope cs(&critsect_); |
80 if (!store_) { | 75 if (!store_) { |
81 return 0; | 76 return; |
82 } | 77 } |
83 | 78 |
84 assert(packet); | |
85 assert(packet_length > 3); | |
86 | |
87 if (packet_length > IP_PACKET_SIZE) { | |
88 LOG(LS_WARNING) << "Failed to store RTP packet with length: " | |
89 << packet_length; | |
90 return -1; | |
91 } | |
92 | |
93 const uint16_t seq_num = (packet[2] << 8) + packet[3]; | |
94 | |
95 // If index we're about to overwrite contains a packet that has not | 79 // If index we're about to overwrite contains a packet that has not |
96 // yet been sent (probably pending in paced sender), we need to expand | 80 // yet been sent (probably pending in paced sender), we need to expand |
97 // the buffer. | 81 // the buffer. |
98 if (stored_packets_[prev_index_].length > 0 && | 82 if (stored_packets_[prev_index_].packet && |
99 stored_packets_[prev_index_].send_time == 0) { | 83 stored_packets_[prev_index_].send_time == 0) { |
100 size_t current_size = static_cast<uint16_t>(stored_packets_.size()); | 84 size_t current_size = static_cast<uint16_t>(stored_packets_.size()); |
101 if (current_size < kMaxHistoryCapacity) { | 85 if (current_size < kMaxCapacity) { |
102 size_t expanded_size = std::max(current_size * 3 / 2, current_size + 1); | 86 size_t expanded_size = std::max(current_size * 3 / 2, current_size + 1); |
103 expanded_size = std::min(expanded_size, kMaxHistoryCapacity); | 87 expanded_size = std::min(expanded_size, kMaxCapacity); |
104 Allocate(expanded_size); | 88 Allocate(expanded_size); |
105 // Causes discontinuity, but that's OK-ish. FindSeqNum() will still work, | 89 // Causes discontinuity, but that's OK-ish. FindSeqNum() will still work, |
106 // but may be slower - at least until buffer has wrapped around once. | 90 // but may be slower - at least until buffer has wrapped around once. |
107 prev_index_ = current_size; | 91 prev_index_ = current_size; |
108 } | 92 } |
109 } | 93 } |
110 | 94 |
111 // Store packet | 95 // Store packet. |
112 // TODO(sprang): Overhaul this class and get rid of this copy step. | 96 if (packet->capture_time_ms() <= 0) |
113 // (Finally introduce the RtpPacket class?) | 97 packet->set_capture_time_ms(clock_->TimeInMilliseconds()); |
114 memcpy(stored_packets_[prev_index_].data, packet, packet_length); | 98 stored_packets_[prev_index_].sequence_number = packet->SequenceNumber(); |
115 stored_packets_[prev_index_].length = packet_length; | 99 stored_packets_[prev_index_].send_time = |
116 | 100 (sent ? clock_->TimeInMilliseconds() : 0); |
117 stored_packets_[prev_index_].sequence_number = seq_num; | |
118 stored_packets_[prev_index_].time_ms = | |
119 (capture_time_ms > 0) ? capture_time_ms : clock_->TimeInMilliseconds(); | |
120 stored_packets_[prev_index_].send_time = 0; // Packet not sent. | |
121 stored_packets_[prev_index_].storage_type = type; | 101 stored_packets_[prev_index_].storage_type = type; |
122 stored_packets_[prev_index_].has_been_retransmitted = false; | 102 stored_packets_[prev_index_].has_been_retransmitted = false; |
| 103 stored_packets_[prev_index_].packet = std::move(packet); |
123 | 104 |
124 ++prev_index_; | 105 ++prev_index_; |
125 if (prev_index_ >= stored_packets_.size()) { | 106 if (prev_index_ >= stored_packets_.size()) { |
126 prev_index_ = 0; | 107 prev_index_ = 0; |
127 } | 108 } |
128 return 0; | |
129 } | 109 } |
130 | 110 |
131 bool RTPPacketHistory::HasRTPPacket(uint16_t sequence_number) const { | 111 bool RtpPacketHistory::HasRtpPacket(uint16_t sequence_number) const { |
132 rtc::CritScope cs(&critsect_); | 112 rtc::CritScope cs(&critsect_); |
133 if (!store_) { | 113 if (!store_) { |
134 return false; | 114 return false; |
135 } | 115 } |
136 | 116 |
137 int32_t index = 0; | 117 int unused_index = 0; |
138 bool found = FindSeqNum(sequence_number, &index); | 118 return FindSeqNum(sequence_number, &unused_index); |
139 if (!found) { | 119 } |
140 return false; | 120 |
| 121 std::unique_ptr<RtpPacketToSend> RtpPacketHistory::GetPacketAndSetSendTime( |
| 122 uint16_t sequence_number, |
| 123 int64_t min_elapsed_time_ms, |
| 124 bool retransmit) { |
| 125 rtc::CritScope cs(&critsect_); |
| 126 if (!store_) { |
| 127 return nullptr; |
141 } | 128 } |
142 | 129 |
143 if (stored_packets_[index].length == 0) { | 130 int index = 0; |
144 // Invalid length. | 131 if (!FindSeqNum(sequence_number, &index)) { |
145 return false; | 132 LOG(LS_WARNING) << "No match for getting seqNum " << sequence_number; |
| 133 return nullptr; |
146 } | 134 } |
147 return true; | 135 RTC_DCHECK_EQ(sequence_number, |
148 } | 136 stored_packets_[index].packet->SequenceNumber()); |
149 | |
150 bool RTPPacketHistory::SetSent(uint16_t sequence_number) { | |
151 rtc::CritScope cs(&critsect_); | |
152 if (!store_) { | |
153 return false; | |
154 } | |
155 | |
156 int32_t index = 0; | |
157 bool found = FindSeqNum(sequence_number, &index); | |
158 if (!found) { | |
159 return false; | |
160 } | |
161 | |
162 // Send time already set. | |
163 if (stored_packets_[index].send_time != 0) { | |
164 return false; | |
165 } | |
166 | |
167 stored_packets_[index].send_time = clock_->TimeInMilliseconds(); | |
168 return true; | |
169 } | |
170 | |
171 bool RTPPacketHistory::GetPacketAndSetSendTime(uint16_t sequence_number, | |
172 int64_t min_elapsed_time_ms, | |
173 bool retransmit, | |
174 uint8_t* packet, | |
175 size_t* packet_length, | |
176 int64_t* stored_time_ms) { | |
177 rtc::CritScope cs(&critsect_); | |
178 RTC_CHECK_GE(*packet_length, static_cast<size_t>(IP_PACKET_SIZE)); | |
179 if (!store_) | |
180 return false; | |
181 | |
182 int32_t index = 0; | |
183 bool found = FindSeqNum(sequence_number, &index); | |
184 if (!found) { | |
185 LOG(LS_WARNING) << "No match for getting seqNum " << sequence_number; | |
186 return false; | |
187 } | |
188 | |
189 size_t length = stored_packets_[index].length; | |
190 assert(length <= IP_PACKET_SIZE); | |
191 if (length == 0) { | |
192 LOG(LS_WARNING) << "No match for getting seqNum " << sequence_number | |
193 << ", len " << length; | |
194 return false; | |
195 } | |
196 | 137 |
197 // Verify elapsed time since last retrieve, but only for retransmissions and | 138 // Verify elapsed time since last retrieve, but only for retransmissions and |
198 // always send packet upon first retransmission request. | 139 // always send packet upon first retransmission request. |
199 int64_t now = clock_->TimeInMilliseconds(); | 140 int64_t now = clock_->TimeInMilliseconds(); |
200 if (min_elapsed_time_ms > 0 && retransmit && | 141 if (min_elapsed_time_ms > 0 && retransmit && |
201 stored_packets_[index].has_been_retransmitted && | 142 stored_packets_[index].has_been_retransmitted && |
202 ((now - stored_packets_[index].send_time) < min_elapsed_time_ms)) { | 143 ((now - stored_packets_[index].send_time) < min_elapsed_time_ms)) { |
203 return false; | 144 return nullptr; |
204 } | 145 } |
205 | 146 |
206 if (retransmit) { | 147 if (retransmit) { |
207 if (stored_packets_[index].storage_type == kDontRetransmit) { | 148 if (stored_packets_[index].storage_type == kDontRetransmit) { |
208 // No bytes copied since this packet shouldn't be retransmitted or is | 149 // No bytes copied since this packet shouldn't be retransmitted. |
209 // of zero size. | 150 return nullptr; |
210 return false; | |
211 } | 151 } |
212 stored_packets_[index].has_been_retransmitted = true; | 152 stored_packets_[index].has_been_retransmitted = true; |
213 } | 153 } |
214 stored_packets_[index].send_time = clock_->TimeInMilliseconds(); | 154 stored_packets_[index].send_time = clock_->TimeInMilliseconds(); |
215 GetPacket(index, packet, packet_length, stored_time_ms); | 155 return GetPacket(index); |
216 return true; | |
217 } | 156 } |
218 | 157 |
219 void RTPPacketHistory::GetPacket(int index, | 158 std::unique_ptr<RtpPacketToSend> RtpPacketHistory::GetPacket(int index) const { |
220 uint8_t* packet, | 159 const RtpPacketToSend& stored = *stored_packets_[index].packet; |
221 size_t* packet_length, | 160 return std::unique_ptr<RtpPacketToSend>(new RtpPacketToSend(stored)); |
222 int64_t* stored_time_ms) const { | |
223 // Get packet. | |
224 size_t length = stored_packets_[index].length; | |
225 memcpy(packet, stored_packets_[index].data, length); | |
226 *packet_length = length; | |
227 *stored_time_ms = stored_packets_[index].time_ms; | |
228 } | 161 } |
229 | 162 |
230 bool RTPPacketHistory::GetBestFittingPacket(uint8_t* packet, | 163 std::unique_ptr<RtpPacketToSend> RtpPacketHistory::GetBestFittingPacket( |
231 size_t* packet_length, | 164 size_t packet_length) const { |
232 int64_t* stored_time_ms) { | |
233 rtc::CritScope cs(&critsect_); | 165 rtc::CritScope cs(&critsect_); |
234 if (!store_) | 166 if (!store_) |
235 return false; | 167 return nullptr; |
236 int index = FindBestFittingPacket(*packet_length); | 168 int index = FindBestFittingPacket(packet_length); |
237 if (index < 0) | 169 if (index < 0) |
238 return false; | 170 return nullptr; |
239 GetPacket(index, packet, packet_length, stored_time_ms); | 171 return GetPacket(index); |
240 return true; | |
241 } | 172 } |
242 | 173 |
243 // private, lock should already be taken | 174 bool RtpPacketHistory::FindSeqNum(uint16_t sequence_number, int* index) const { |
244 bool RTPPacketHistory::FindSeqNum(uint16_t sequence_number, | |
245 int32_t* index) const { | |
246 uint16_t temp_sequence_number = 0; | |
247 if (prev_index_ > 0) { | 175 if (prev_index_ > 0) { |
248 *index = prev_index_ - 1; | 176 *index = prev_index_ - 1; |
249 temp_sequence_number = stored_packets_[*index].sequence_number; | |
250 } else { | 177 } else { |
251 *index = stored_packets_.size() - 1; | 178 *index = stored_packets_.size() - 1; // Wrap. |
252 temp_sequence_number = stored_packets_[*index].sequence_number; // wrap | |
253 } | 179 } |
| 180 uint16_t temp_sequence_number = stored_packets_[*index].sequence_number; |
254 | 181 |
255 int32_t idx = (prev_index_ - 1) - (temp_sequence_number - sequence_number); | 182 int idx = *index - (temp_sequence_number - sequence_number); |
256 if (idx >= 0 && idx < static_cast<int>(stored_packets_.size())) { | 183 if (idx >= 0 && idx < static_cast<int>(stored_packets_.size())) { |
257 *index = idx; | 184 *index = idx; |
258 temp_sequence_number = stored_packets_[*index].sequence_number; | 185 temp_sequence_number = stored_packets_[*index].sequence_number; |
259 } | 186 } |
260 | 187 |
261 if (temp_sequence_number != sequence_number) { | 188 if (temp_sequence_number != sequence_number) { |
262 // We did not found a match, search all. | 189 // We did not found a match, search all. |
263 for (uint16_t m = 0; m < stored_packets_.size(); m++) { | 190 for (uint16_t m = 0; m < stored_packets_.size(); m++) { |
264 if (stored_packets_[m].sequence_number == sequence_number) { | 191 if (stored_packets_[m].sequence_number == sequence_number) { |
265 *index = m; | 192 *index = m; |
266 temp_sequence_number = stored_packets_[*index].sequence_number; | 193 temp_sequence_number = stored_packets_[*index].sequence_number; |
267 break; | 194 break; |
268 } | 195 } |
269 } | 196 } |
270 } | 197 } |
271 if (temp_sequence_number == sequence_number) { | 198 return temp_sequence_number == sequence_number && |
272 // We found a match. | 199 stored_packets_[*index].packet; |
273 return true; | |
274 } | |
275 return false; | |
276 } | 200 } |
277 | 201 |
278 int RTPPacketHistory::FindBestFittingPacket(size_t size) const { | 202 int RtpPacketHistory::FindBestFittingPacket(size_t size) const { |
279 if (size < kMinPacketRequestBytes || stored_packets_.empty()) | 203 if (size < kMinPacketRequestBytes || stored_packets_.empty()) |
280 return -1; | 204 return -1; |
281 size_t min_diff = std::numeric_limits<size_t>::max(); | 205 size_t min_diff = std::numeric_limits<size_t>::max(); |
282 int best_index = -1; // Returned unchanged if we don't find anything. | 206 int best_index = -1; // Returned unchanged if we don't find anything. |
283 for (size_t i = 0; i < stored_packets_.size(); ++i) { | 207 for (size_t i = 0; i < stored_packets_.size(); ++i) { |
284 if (stored_packets_[i].length == 0) | 208 if (!stored_packets_[i].packet) |
285 continue; | 209 continue; |
286 size_t diff = (stored_packets_[i].length > size) | 210 size_t stored_size = stored_packets_[i].packet->size(); |
287 ? (stored_packets_[i].length - size) | 211 size_t diff = |
288 : (size - stored_packets_[i].length); | 212 (stored_size > size) ? (stored_size - size) : (size - stored_size); |
289 if (diff < min_diff) { | 213 if (diff < min_diff) { |
290 min_diff = diff; | 214 min_diff = diff; |
291 best_index = static_cast<int>(i); | 215 best_index = static_cast<int>(i); |
292 } | 216 } |
293 } | 217 } |
294 return best_index; | 218 return best_index; |
295 } | 219 } |
296 | 220 |
297 RTPPacketHistory::StoredPacket::StoredPacket() {} | |
298 | |
299 } // namespace webrtc | 221 } // namespace webrtc |
OLD | NEW |