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

Side by Side Diff: webrtc/modules/rtp_rtcp/source/rtp_packet_history.cc

Issue 1340573002: Refactor RTPPacketHistory to use a packet struct. (Closed) Base URL: https://chromium.googlesource.com/external/webrtc.git@master
Patch Set: remove max packet size as a parameter Created 5 years, 3 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
OLDNEW
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
OLDNEW
« no previous file with comments | « webrtc/modules/rtp_rtcp/source/rtp_packet_history.h ('k') | webrtc/modules/rtp_rtcp/source/rtp_packet_history_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698