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> | 13 #include <assert.h> |
14 #include <stdlib.h> | 14 #include <stdlib.h> |
15 #include <string.h> // memset | 15 #include <string.h> // memset |
16 #include <limits> | 16 #include <limits> |
17 #include <set> | 17 #include <set> |
18 | 18 |
19 #include "webrtc/modules/rtp_rtcp/source/rtp_utility.h" | 19 #include "webrtc/modules/rtp_rtcp/source/rtp_utility.h" |
20 #include "webrtc/system_wrappers/interface/critical_section_wrapper.h" | 20 #include "webrtc/system_wrappers/interface/critical_section_wrapper.h" |
21 #include "webrtc/system_wrappers/interface/logging.h" | 21 #include "webrtc/system_wrappers/interface/logging.h" |
22 | 22 |
23 namespace webrtc { | 23 namespace webrtc { |
24 | 24 |
25 static const int kMinPacketRequestBytes = 50; | 25 static const int kMinPacketRequestBytes = 50; |
26 | 26 |
27 RTPPacketHistory::RTPPacketHistory(Clock* clock) | 27 RTPPacketHistory::RTPPacketHistory(Clock* clock) |
28 : clock_(clock), | 28 : clock_(clock), |
29 critsect_(CriticalSectionWrapper::CreateCriticalSection()), | 29 critsect_(CriticalSectionWrapper::CreateCriticalSection()), |
30 store_(false), | 30 store_(false), |
31 prev_index_(0), | 31 prev_index_(0) {} |
32 max_packet_length_(0) { | |
33 } | |
34 | 32 |
35 RTPPacketHistory::~RTPPacketHistory() { | 33 RTPPacketHistory::~RTPPacketHistory() { |
36 } | 34 } |
37 | 35 |
38 void RTPPacketHistory::SetStorePacketsStatus(bool enable, | 36 void RTPPacketHistory::SetStorePacketsStatus(bool enable, |
39 uint16_t number_to_store) { | 37 uint16_t number_to_store) { |
40 CriticalSectionScoped cs(critsect_.get()); | 38 CriticalSectionScoped cs(critsect_.get()); |
41 if (enable) { | 39 if (enable) { |
42 if (store_) { | 40 if (store_) { |
43 LOG(LS_WARNING) << "Purging packet history in order to re-set status."; | 41 LOG(LS_WARNING) << "Purging packet history in order to re-set status."; |
44 Free(); | 42 Free(); |
45 } | 43 } |
46 assert(!store_); | 44 assert(!store_); |
47 Allocate(number_to_store); | 45 Allocate(number_to_store); |
48 } else { | 46 } else { |
49 Free(); | 47 Free(); |
50 } | 48 } |
51 } | 49 } |
52 | 50 |
53 void RTPPacketHistory::Allocate(size_t number_to_store) { | 51 void RTPPacketHistory::Allocate(size_t number_to_store) { |
54 assert(number_to_store > 0); | 52 assert(number_to_store > 0); |
55 assert(number_to_store <= kMaxHistoryCapacity); | 53 assert(number_to_store <= kMaxHistoryCapacity); |
56 store_ = true; | 54 store_ = true; |
57 stored_packets_.resize(number_to_store); | 55 stored_packets_.resize(number_to_store); |
58 stored_seq_nums_.resize(number_to_store); | |
59 stored_lengths_.resize(number_to_store); | |
60 stored_times_.resize(number_to_store); | |
61 stored_send_times_.resize(number_to_store); | |
62 stored_types_.resize(number_to_store); | |
63 } | 56 } |
64 | 57 |
65 void RTPPacketHistory::Free() { | 58 void RTPPacketHistory::Free() { |
66 if (!store_) { | 59 if (!store_) { |
67 return; | 60 return; |
68 } | 61 } |
69 | 62 |
70 std::vector<std::vector<uint8_t> >::iterator it; | |
71 for (it = stored_packets_.begin(); it != stored_packets_.end(); ++it) { | |
72 it->clear(); | |
73 } | |
74 | |
75 stored_packets_.clear(); | 63 stored_packets_.clear(); |
76 stored_seq_nums_.clear(); | |
77 stored_lengths_.clear(); | |
78 stored_times_.clear(); | |
79 stored_send_times_.clear(); | |
80 stored_types_.clear(); | |
81 | 64 |
82 store_ = false; | 65 store_ = false; |
83 prev_index_ = 0; | 66 prev_index_ = 0; |
84 max_packet_length_ = 0; | |
85 } | 67 } |
86 | 68 |
87 bool RTPPacketHistory::StorePackets() const { | 69 bool RTPPacketHistory::StorePackets() const { |
88 CriticalSectionScoped cs(critsect_.get()); | 70 CriticalSectionScoped cs(critsect_.get()); |
89 return store_; | 71 return store_; |
90 } | 72 } |
91 | 73 |
92 void RTPPacketHistory::VerifyAndAllocatePacketLength(size_t packet_length, | |
93 uint32_t start_index) { | |
94 assert(packet_length > 0); | |
95 if (!store_) { | |
96 return; | |
97 } | |
98 | |
99 // If start_index > 0 this is a resize and we must check any new (empty) | |
100 // packets created during the resize. | |
101 if (start_index == 0 && packet_length <= max_packet_length_) { | |
102 return; | |
103 } | |
104 | |
105 max_packet_length_ = std::max(packet_length, max_packet_length_); | |
106 | |
107 std::vector<std::vector<uint8_t> >::iterator it; | |
108 for (it = stored_packets_.begin() + start_index; it != stored_packets_.end(); | |
109 ++it) { | |
110 it->resize(max_packet_length_); | |
111 } | |
112 } | |
113 | |
114 int32_t RTPPacketHistory::PutRTPPacket(const uint8_t* packet, | 74 int32_t RTPPacketHistory::PutRTPPacket(const uint8_t* packet, |
115 size_t packet_length, | 75 size_t packet_length, |
116 size_t max_packet_length, | |
117 int64_t capture_time_ms, | 76 int64_t capture_time_ms, |
118 StorageType type) { | 77 StorageType type) { |
119 if (type == kDontStore) { | 78 if (type == kDontStore) { |
120 return 0; | 79 return 0; |
121 } | 80 } |
122 | 81 |
123 CriticalSectionScoped cs(critsect_.get()); | 82 CriticalSectionScoped cs(critsect_.get()); |
124 if (!store_) { | 83 if (!store_) { |
125 return 0; | 84 return 0; |
126 } | 85 } |
127 | 86 |
128 assert(packet); | 87 assert(packet); |
129 assert(packet_length > 3); | 88 assert(packet_length > 3); |
130 | 89 |
131 VerifyAndAllocatePacketLength(max_packet_length, 0); | 90 if (packet_length > IP_PACKET_SIZE) { |
132 | |
133 if (packet_length > max_packet_length_) { | |
134 LOG(LS_WARNING) << "Failed to store RTP packet with length: " | 91 LOG(LS_WARNING) << "Failed to store RTP packet with length: " |
135 << packet_length; | 92 << packet_length; |
136 return -1; | 93 return -1; |
137 } | 94 } |
138 | 95 |
139 const uint16_t seq_num = (packet[2] << 8) + packet[3]; | 96 const uint16_t seq_num = (packet[2] << 8) + packet[3]; |
140 | 97 |
141 // If index we're about to overwrite contains a packet that has not | 98 // If index we're about to overwrite contains a packet that has not |
142 // yet been sent (probably pending in paced sender), we need to expand | 99 // yet been sent (probably pending in paced sender), we need to expand |
143 // the buffer. | 100 // the buffer. |
144 if (stored_lengths_[prev_index_] > 0 && | 101 if (stored_packets_[prev_index_].length > 0 && |
145 stored_send_times_[prev_index_] == 0) { | 102 stored_packets_[prev_index_].send_time == 0) { |
146 size_t current_size = static_cast<uint16_t>(stored_packets_.size()); | 103 size_t current_size = static_cast<uint16_t>(stored_packets_.size()); |
147 if (current_size < kMaxHistoryCapacity) { | 104 if (current_size < kMaxHistoryCapacity) { |
148 size_t expanded_size = std::max(current_size * 3 / 2, current_size + 1); | 105 size_t expanded_size = std::max(current_size * 3 / 2, current_size + 1); |
149 expanded_size = std::min(expanded_size, kMaxHistoryCapacity); | 106 expanded_size = std::min(expanded_size, kMaxHistoryCapacity); |
150 Allocate(expanded_size); | 107 Allocate(expanded_size); |
151 VerifyAndAllocatePacketLength(max_packet_length, current_size); | |
152 // Causes discontinuity, but that's OK-ish. FindSeqNum() will still work, | 108 // Causes discontinuity, but that's OK-ish. FindSeqNum() will still work, |
153 // but may be slower - at least until buffer has wrapped around once. | 109 // but may be slower - at least until buffer has wrapped around once. |
154 prev_index_ = current_size; | 110 prev_index_ = current_size; |
155 } | 111 } |
156 } | 112 } |
157 | 113 |
158 // Store packet | 114 // Store packet |
159 std::vector<std::vector<uint8_t> >::iterator it = | |
160 stored_packets_.begin() + prev_index_; | |
161 // TODO(sprang): Overhaul this class and get rid of this copy step. | 115 // TODO(sprang): Overhaul this class and get rid of this copy step. |
162 // (Finally introduce the RtpPacket class?) | 116 // (Finally introduce the RtpPacket class?) |
163 std::copy(packet, packet + packet_length, it->begin()); | 117 memcpy(stored_packets_[prev_index_].data, packet, packet_length); |
| 118 stored_packets_[prev_index_].length = packet_length; |
164 | 119 |
165 stored_seq_nums_[prev_index_] = seq_num; | 120 stored_packets_[prev_index_].sequence_number = seq_num; |
166 stored_lengths_[prev_index_] = packet_length; | 121 stored_packets_[prev_index_].time_ms = |
167 stored_times_[prev_index_] = (capture_time_ms > 0) ? capture_time_ms : | 122 (capture_time_ms > 0) ? capture_time_ms : clock_->TimeInMilliseconds(); |
168 clock_->TimeInMilliseconds(); | 123 stored_packets_[prev_index_].send_time = 0; // Packet not sent. |
169 stored_send_times_[prev_index_] = 0; // Packet not sent. | 124 stored_packets_[prev_index_].storage_type = type; |
170 stored_types_[prev_index_] = type; | |
171 | 125 |
172 ++prev_index_; | 126 ++prev_index_; |
173 if (prev_index_ >= stored_seq_nums_.size()) { | 127 if (prev_index_ >= stored_packets_.size()) { |
174 prev_index_ = 0; | 128 prev_index_ = 0; |
175 } | 129 } |
176 return 0; | 130 return 0; |
177 } | 131 } |
178 | 132 |
179 bool RTPPacketHistory::HasRTPPacket(uint16_t sequence_number) const { | 133 bool RTPPacketHistory::HasRTPPacket(uint16_t sequence_number) const { |
180 CriticalSectionScoped cs(critsect_.get()); | 134 CriticalSectionScoped cs(critsect_.get()); |
181 if (!store_) { | 135 if (!store_) { |
182 return false; | 136 return false; |
183 } | 137 } |
184 | 138 |
185 int32_t index = 0; | 139 int32_t index = 0; |
186 bool found = FindSeqNum(sequence_number, &index); | 140 bool found = FindSeqNum(sequence_number, &index); |
187 if (!found) { | 141 if (!found) { |
188 return false; | 142 return false; |
189 } | 143 } |
190 | 144 |
191 size_t length = stored_lengths_.at(index); | 145 if (stored_packets_[index].length == 0) { |
192 if (length == 0 || length > max_packet_length_) { | |
193 // Invalid length. | 146 // Invalid length. |
194 return false; | 147 return false; |
195 } | 148 } |
196 return true; | 149 return true; |
197 } | 150 } |
198 | 151 |
199 bool RTPPacketHistory::SetSent(uint16_t sequence_number) { | 152 bool RTPPacketHistory::SetSent(uint16_t sequence_number) { |
200 CriticalSectionScoped cs(critsect_.get()); | 153 CriticalSectionScoped cs(critsect_.get()); |
201 if (!store_) { | 154 if (!store_) { |
202 return false; | 155 return false; |
203 } | 156 } |
204 | 157 |
205 int32_t index = 0; | 158 int32_t index = 0; |
206 bool found = FindSeqNum(sequence_number, &index); | 159 bool found = FindSeqNum(sequence_number, &index); |
207 if (!found) { | 160 if (!found) { |
208 return false; | 161 return false; |
209 } | 162 } |
210 | 163 |
211 // Send time already set. | 164 // Send time already set. |
212 if (stored_send_times_[index] != 0) { | 165 if (stored_packets_[index].send_time != 0) { |
213 return false; | 166 return false; |
214 } | 167 } |
215 | 168 |
216 stored_send_times_[index] = clock_->TimeInMilliseconds(); | 169 stored_packets_[index].send_time = clock_->TimeInMilliseconds(); |
217 return true; | 170 return true; |
218 } | 171 } |
219 | 172 |
220 bool RTPPacketHistory::GetPacketAndSetSendTime(uint16_t sequence_number, | 173 bool RTPPacketHistory::GetPacketAndSetSendTime(uint16_t sequence_number, |
221 int64_t min_elapsed_time_ms, | 174 int64_t min_elapsed_time_ms, |
222 bool retransmit, | 175 bool retransmit, |
223 uint8_t* packet, | 176 uint8_t* packet, |
224 size_t* packet_length, | 177 size_t* packet_length, |
225 int64_t* stored_time_ms) { | 178 int64_t* stored_time_ms) { |
226 CriticalSectionScoped cs(critsect_.get()); | 179 CriticalSectionScoped cs(critsect_.get()); |
227 assert(*packet_length >= max_packet_length_); | 180 assert(*packet_length >= IP_PACKET_SIZE); |
228 if (!store_) { | 181 if (!store_) { |
229 return false; | 182 return false; |
230 } | 183 } |
231 | 184 |
232 int32_t index = 0; | 185 int32_t index = 0; |
233 bool found = FindSeqNum(sequence_number, &index); | 186 bool found = FindSeqNum(sequence_number, &index); |
234 if (!found) { | 187 if (!found) { |
235 LOG(LS_WARNING) << "No match for getting seqNum " << sequence_number; | 188 LOG(LS_WARNING) << "No match for getting seqNum " << sequence_number; |
236 return false; | 189 return false; |
237 } | 190 } |
238 | 191 |
239 size_t length = stored_lengths_.at(index); | 192 size_t length = stored_packets_[index].length; |
240 assert(length <= max_packet_length_); | 193 assert(length <= IP_PACKET_SIZE); |
241 if (length == 0) { | 194 if (length == 0) { |
242 LOG(LS_WARNING) << "No match for getting seqNum " << sequence_number | 195 LOG(LS_WARNING) << "No match for getting seqNum " << sequence_number |
243 << ", len " << length; | 196 << ", len " << length; |
244 return false; | 197 return false; |
245 } | 198 } |
246 | 199 |
247 // Verify elapsed time since last retrieve. | 200 // Verify elapsed time since last retrieve. |
248 int64_t now = clock_->TimeInMilliseconds(); | 201 int64_t now = clock_->TimeInMilliseconds(); |
249 if (min_elapsed_time_ms > 0 && | 202 if (min_elapsed_time_ms > 0 && |
250 ((now - stored_send_times_.at(index)) < min_elapsed_time_ms)) { | 203 ((now - stored_packets_[index].send_time) < min_elapsed_time_ms)) { |
251 return false; | 204 return false; |
252 } | 205 } |
253 | 206 |
254 if (retransmit && stored_types_.at(index) == kDontRetransmit) { | 207 if (retransmit && stored_packets_[index].storage_type == kDontRetransmit) { |
255 // No bytes copied since this packet shouldn't be retransmitted or is | 208 // No bytes copied since this packet shouldn't be retransmitted or is |
256 // of zero size. | 209 // of zero size. |
257 return false; | 210 return false; |
258 } | 211 } |
259 stored_send_times_[index] = clock_->TimeInMilliseconds(); | 212 stored_packets_[index].send_time = clock_->TimeInMilliseconds(); |
260 GetPacket(index, packet, packet_length, stored_time_ms); | 213 GetPacket(index, packet, packet_length, stored_time_ms); |
261 return true; | 214 return true; |
262 } | 215 } |
263 | 216 |
264 void RTPPacketHistory::GetPacket(int index, | 217 void RTPPacketHistory::GetPacket(int index, |
265 uint8_t* packet, | 218 uint8_t* packet, |
266 size_t* packet_length, | 219 size_t* packet_length, |
267 int64_t* stored_time_ms) const { | 220 int64_t* stored_time_ms) const { |
268 // Get packet. | 221 // Get packet. |
269 size_t length = stored_lengths_.at(index); | 222 size_t length = stored_packets_[index].length; |
270 std::vector<std::vector<uint8_t> >::const_iterator it_found_packet = | 223 memcpy(packet, stored_packets_[index].data, length); |
271 stored_packets_.begin() + index; | |
272 std::copy(it_found_packet->begin(), it_found_packet->begin() + length, | |
273 packet); | |
274 *packet_length = length; | 224 *packet_length = length; |
275 *stored_time_ms = stored_times_.at(index); | 225 *stored_time_ms = stored_packets_[index].time_ms; |
276 } | 226 } |
277 | 227 |
278 bool RTPPacketHistory::GetBestFittingPacket(uint8_t* packet, | 228 bool RTPPacketHistory::GetBestFittingPacket(uint8_t* packet, |
279 size_t* packet_length, | 229 size_t* packet_length, |
280 int64_t* stored_time_ms) { | 230 int64_t* stored_time_ms) { |
281 CriticalSectionScoped cs(critsect_.get()); | 231 CriticalSectionScoped cs(critsect_.get()); |
282 if (!store_) | 232 if (!store_) |
283 return false; | 233 return false; |
284 int index = FindBestFittingPacket(*packet_length); | 234 int index = FindBestFittingPacket(*packet_length); |
285 if (index < 0) | 235 if (index < 0) |
286 return false; | 236 return false; |
287 GetPacket(index, packet, packet_length, stored_time_ms); | 237 GetPacket(index, packet, packet_length, stored_time_ms); |
288 return true; | 238 return true; |
289 } | 239 } |
290 | 240 |
291 // private, lock should already be taken | 241 // private, lock should already be taken |
292 bool RTPPacketHistory::FindSeqNum(uint16_t sequence_number, | 242 bool RTPPacketHistory::FindSeqNum(uint16_t sequence_number, |
293 int32_t* index) const { | 243 int32_t* index) const { |
294 uint16_t temp_sequence_number = 0; | 244 uint16_t temp_sequence_number = 0; |
295 if (prev_index_ > 0) { | 245 if (prev_index_ > 0) { |
296 *index = prev_index_ - 1; | 246 *index = prev_index_ - 1; |
297 temp_sequence_number = stored_seq_nums_[*index]; | 247 temp_sequence_number = stored_packets_[*index].sequence_number; |
298 } else { | 248 } else { |
299 *index = stored_seq_nums_.size() - 1; | 249 *index = stored_packets_.size() - 1; |
300 temp_sequence_number = stored_seq_nums_[*index]; // wrap | 250 temp_sequence_number = stored_packets_[*index].sequence_number; // wrap |
301 } | 251 } |
302 | 252 |
303 int32_t idx = (prev_index_ - 1) - (temp_sequence_number - sequence_number); | 253 int32_t idx = (prev_index_ - 1) - (temp_sequence_number - sequence_number); |
304 if (idx >= 0 && idx < static_cast<int>(stored_seq_nums_.size())) { | 254 if (idx >= 0 && idx < static_cast<int>(stored_packets_.size())) { |
305 *index = idx; | 255 *index = idx; |
306 temp_sequence_number = stored_seq_nums_[*index]; | 256 temp_sequence_number = stored_packets_[*index].sequence_number; |
307 } | 257 } |
308 | 258 |
309 if (temp_sequence_number != sequence_number) { | 259 if (temp_sequence_number != sequence_number) { |
310 // We did not found a match, search all. | 260 // We did not found a match, search all. |
311 for (uint16_t m = 0; m < stored_seq_nums_.size(); m++) { | 261 for (uint16_t m = 0; m < stored_packets_.size(); m++) { |
312 if (stored_seq_nums_[m] == sequence_number) { | 262 if (stored_packets_[m].sequence_number == sequence_number) { |
313 *index = m; | 263 *index = m; |
314 temp_sequence_number = stored_seq_nums_[*index]; | 264 temp_sequence_number = stored_packets_[*index].sequence_number; |
315 break; | 265 break; |
316 } | 266 } |
317 } | 267 } |
318 } | 268 } |
319 if (temp_sequence_number == sequence_number) { | 269 if (temp_sequence_number == sequence_number) { |
320 // We found a match. | 270 // We found a match. |
321 return true; | 271 return true; |
322 } | 272 } |
323 return false; | 273 return false; |
324 } | 274 } |
325 | 275 |
326 int RTPPacketHistory::FindBestFittingPacket(size_t size) const { | 276 int RTPPacketHistory::FindBestFittingPacket(size_t size) const { |
327 if (size < kMinPacketRequestBytes || stored_lengths_.empty()) | 277 if (size < kMinPacketRequestBytes || stored_packets_.empty()) |
328 return -1; | 278 return -1; |
329 size_t min_diff = std::numeric_limits<size_t>::max(); | 279 size_t min_diff = std::numeric_limits<size_t>::max(); |
330 int best_index = -1; // Returned unchanged if we don't find anything. | 280 int best_index = -1; // Returned unchanged if we don't find anything. |
331 for (size_t i = 0; i < stored_lengths_.size(); ++i) { | 281 for (size_t i = 0; i < stored_packets_.size(); ++i) { |
332 if (stored_lengths_[i] == 0) | 282 if (stored_packets_[i].length == 0) |
333 continue; | 283 continue; |
334 size_t diff = (stored_lengths_[i] > size) ? | 284 size_t diff = (stored_packets_[i].length > size) |
335 (stored_lengths_[i] - size) : (size - stored_lengths_[i]); | 285 ? (stored_packets_[i].length - size) |
| 286 : (size - stored_packets_[i].length); |
336 if (diff < min_diff) { | 287 if (diff < min_diff) { |
337 min_diff = diff; | 288 min_diff = diff; |
338 best_index = static_cast<int>(i); | 289 best_index = static_cast<int>(i); |
339 } | 290 } |
340 } | 291 } |
341 return best_index; | 292 return best_index; |
342 } | 293 } |
| 294 |
| 295 RTPPacketHistory::StoredPacket::StoredPacket() {} |
| 296 |
343 } // namespace webrtc | 297 } // namespace webrtc |
OLD | NEW |