• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  *  Copyright (c) 2012 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/rtp_packet_history.h"
12 
13 #include <assert.h>
14 #include <stdlib.h>
15 #include <string.h>   // memset
16 #include <limits>
17 #include <set>
18 
19 #include "webrtc/modules/rtp_rtcp/source/rtp_utility.h"
20 #include "webrtc/system_wrappers/interface/critical_section_wrapper.h"
21 #include "webrtc/system_wrappers/interface/logging.h"
22 
23 namespace webrtc {
24 
25 enum { kMinPacketRequestBytes = 50 };
26 
RTPPacketHistory(Clock * clock)27 RTPPacketHistory::RTPPacketHistory(Clock* clock)
28   : clock_(clock),
29     critsect_(CriticalSectionWrapper::CreateCriticalSection()),
30     store_(false),
31     prev_index_(0),
32     max_packet_length_(0) {
33 }
34 
~RTPPacketHistory()35 RTPPacketHistory::~RTPPacketHistory() {
36   {
37     CriticalSectionScoped cs(critsect_);
38     Free();
39   }
40   delete critsect_;
41 }
42 
SetStorePacketsStatus(bool enable,uint16_t number_to_store)43 void RTPPacketHistory::SetStorePacketsStatus(bool enable,
44                                              uint16_t number_to_store) {
45   CriticalSectionScoped cs(critsect_);
46   if (enable) {
47     if (store_) {
48       LOG(LS_WARNING) << "Purging packet history in order to re-set status.";
49       Free();
50     }
51     Allocate(number_to_store);
52   } else {
53     Free();
54   }
55 }
56 
Allocate(uint16_t number_to_store)57 void RTPPacketHistory::Allocate(uint16_t number_to_store) {
58   assert(number_to_store > 0);
59   assert(!store_);
60   store_ = true;
61   stored_packets_.resize(number_to_store);
62   stored_seq_nums_.resize(number_to_store);
63   stored_lengths_.resize(number_to_store);
64   stored_times_.resize(number_to_store);
65   stored_send_times_.resize(number_to_store);
66   stored_types_.resize(number_to_store);
67 }
68 
Free()69 void RTPPacketHistory::Free() {
70   if (!store_) {
71     return;
72   }
73 
74   std::vector<std::vector<uint8_t> >::iterator it;
75   for (it = stored_packets_.begin(); it != stored_packets_.end(); ++it) {
76     it->clear();
77   }
78 
79   stored_packets_.clear();
80   stored_seq_nums_.clear();
81   stored_lengths_.clear();
82   stored_times_.clear();
83   stored_send_times_.clear();
84   stored_types_.clear();
85 
86   store_ = false;
87   prev_index_ = 0;
88   max_packet_length_ = 0;
89 }
90 
StorePackets() const91 bool RTPPacketHistory::StorePackets() const {
92   CriticalSectionScoped cs(critsect_);
93   return store_;
94 }
95 
96 // private, lock should already be taken
VerifyAndAllocatePacketLength(uint16_t packet_length)97 void RTPPacketHistory::VerifyAndAllocatePacketLength(uint16_t packet_length) {
98   assert(packet_length > 0);
99   if (!store_) {
100     return;
101   }
102 
103   if (packet_length <= max_packet_length_) {
104     return;
105   }
106 
107   std::vector<std::vector<uint8_t> >::iterator it;
108   for (it = stored_packets_.begin(); it != stored_packets_.end(); ++it) {
109     it->resize(packet_length);
110   }
111   max_packet_length_ = packet_length;
112 }
113 
PutRTPPacket(const uint8_t * packet,uint16_t packet_length,uint16_t max_packet_length,int64_t capture_time_ms,StorageType type)114 int32_t RTPPacketHistory::PutRTPPacket(const uint8_t* packet,
115                                        uint16_t packet_length,
116                                        uint16_t max_packet_length,
117                                        int64_t capture_time_ms,
118                                        StorageType type) {
119   if (type == kDontStore) {
120     return 0;
121   }
122 
123   CriticalSectionScoped cs(critsect_);
124   if (!store_) {
125     return 0;
126   }
127 
128   assert(packet);
129   assert(packet_length > 3);
130 
131   VerifyAndAllocatePacketLength(max_packet_length);
132 
133   if (packet_length > max_packet_length_) {
134     LOG(LS_WARNING) << "Failed to store RTP packet with length: "
135                     << packet_length;
136     return -1;
137   }
138 
139   const uint16_t seq_num = (packet[2] << 8) + packet[3];
140 
141   // Store packet
142   std::vector<std::vector<uint8_t> >::iterator it =
143       stored_packets_.begin() + prev_index_;
144   std::copy(packet, packet + packet_length, it->begin());
145 
146   stored_seq_nums_[prev_index_] = seq_num;
147   stored_lengths_[prev_index_] = packet_length;
148   stored_times_[prev_index_] = (capture_time_ms > 0) ? capture_time_ms :
149       clock_->TimeInMilliseconds();
150   stored_send_times_[prev_index_] = 0;  // Packet not sent.
151   stored_types_[prev_index_] = type;
152 
153   ++prev_index_;
154   if (prev_index_ >= stored_seq_nums_.size()) {
155     prev_index_ = 0;
156   }
157   return 0;
158 }
159 
HasRTPPacket(uint16_t sequence_number) const160 bool RTPPacketHistory::HasRTPPacket(uint16_t sequence_number) const {
161   CriticalSectionScoped cs(critsect_);
162   if (!store_) {
163     return false;
164   }
165 
166   int32_t index = 0;
167   bool found = FindSeqNum(sequence_number, &index);
168   if (!found) {
169     return false;
170   }
171 
172   uint16_t length = stored_lengths_.at(index);
173   if (length == 0 || length > max_packet_length_) {
174     // Invalid length.
175     return false;
176   }
177   return true;
178 }
179 
GetPacketAndSetSendTime(uint16_t sequence_number,uint32_t min_elapsed_time_ms,bool retransmit,uint8_t * packet,uint16_t * packet_length,int64_t * stored_time_ms)180 bool RTPPacketHistory::GetPacketAndSetSendTime(uint16_t sequence_number,
181                                                uint32_t min_elapsed_time_ms,
182                                                bool retransmit,
183                                                uint8_t* packet,
184                                                uint16_t* packet_length,
185                                                int64_t* stored_time_ms) {
186   assert(*packet_length >= max_packet_length_);
187   CriticalSectionScoped cs(critsect_);
188   if (!store_) {
189     return false;
190   }
191 
192   int32_t index = 0;
193   bool found = FindSeqNum(sequence_number, &index);
194   if (!found) {
195     LOG(LS_WARNING) << "No match for getting seqNum " << sequence_number;
196     return false;
197   }
198 
199   uint16_t length = stored_lengths_.at(index);
200   assert(length <= max_packet_length_);
201   if (length == 0) {
202     LOG(LS_WARNING) << "No match for getting seqNum " << sequence_number
203                     << ", len " << length;
204     return false;
205   }
206 
207   // Verify elapsed time since last retrieve.
208   int64_t now = clock_->TimeInMilliseconds();
209   if (min_elapsed_time_ms > 0 &&
210       ((now - stored_send_times_.at(index)) < min_elapsed_time_ms)) {
211     return false;
212   }
213 
214   if (retransmit && stored_types_.at(index) == kDontRetransmit) {
215     // No bytes copied since this packet shouldn't be retransmitted or is
216     // of zero size.
217     return false;
218   }
219   stored_send_times_[index] = clock_->TimeInMilliseconds();
220   GetPacket(index, packet, packet_length, stored_time_ms);
221   return true;
222 }
223 
GetPacket(int index,uint8_t * packet,uint16_t * packet_length,int64_t * stored_time_ms) const224 void RTPPacketHistory::GetPacket(int index,
225                                  uint8_t* packet,
226                                  uint16_t* packet_length,
227                                  int64_t* stored_time_ms) const {
228   // Get packet.
229   uint16_t length = stored_lengths_.at(index);
230   std::vector<std::vector<uint8_t> >::const_iterator it_found_packet =
231       stored_packets_.begin() + index;
232   std::copy(it_found_packet->begin(), it_found_packet->begin() + length,
233             packet);
234   *packet_length = length;
235   *stored_time_ms = stored_times_.at(index);
236 }
237 
GetBestFittingPacket(uint8_t * packet,uint16_t * packet_length,int64_t * stored_time_ms)238 bool RTPPacketHistory::GetBestFittingPacket(uint8_t* packet,
239                                             uint16_t* packet_length,
240                                             int64_t* stored_time_ms) {
241   CriticalSectionScoped cs(critsect_);
242   if (!store_)
243     return false;
244   int index = FindBestFittingPacket(*packet_length);
245   if (index < 0)
246     return false;
247   GetPacket(index, packet, packet_length, stored_time_ms);
248   return true;
249 }
250 
251 // private, lock should already be taken
FindSeqNum(uint16_t sequence_number,int32_t * index) const252 bool RTPPacketHistory::FindSeqNum(uint16_t sequence_number,
253                                   int32_t* index) const {
254   uint16_t temp_sequence_number = 0;
255   if (prev_index_ > 0) {
256     *index = prev_index_ - 1;
257     temp_sequence_number = stored_seq_nums_[*index];
258   } else {
259     *index = stored_seq_nums_.size() - 1;
260     temp_sequence_number = stored_seq_nums_[*index];  // wrap
261   }
262 
263   int32_t idx = (prev_index_ - 1) - (temp_sequence_number - sequence_number);
264   if (idx >= 0 && idx < static_cast<int>(stored_seq_nums_.size())) {
265     *index = idx;
266     temp_sequence_number = stored_seq_nums_[*index];
267   }
268 
269   if (temp_sequence_number != sequence_number) {
270     // We did not found a match, search all.
271     for (uint16_t m = 0; m < stored_seq_nums_.size(); m++) {
272       if (stored_seq_nums_[m] == sequence_number) {
273         *index = m;
274         temp_sequence_number = stored_seq_nums_[*index];
275         break;
276       }
277     }
278   }
279   if (temp_sequence_number == sequence_number) {
280     // We found a match.
281     return true;
282   }
283   return false;
284 }
285 
FindBestFittingPacket(uint16_t size) const286 int RTPPacketHistory::FindBestFittingPacket(uint16_t size) const {
287   if (size < kMinPacketRequestBytes || stored_lengths_.empty())
288     return -1;
289   int min_diff = -1;
290   size_t best_index = 0;
291   for (size_t i = 0; i < stored_lengths_.size(); ++i) {
292     if (stored_lengths_[i] == 0)
293       continue;
294     int diff = abs(stored_lengths_[i] - size);
295     if (min_diff < 0 || diff < min_diff) {
296       min_diff = diff;
297       best_index = i;
298     }
299   }
300   if (min_diff < 0)
301     return -1;
302   return best_index;
303 }
304 }  // namespace webrtc
305