Upstream version 7.36.149.0
[platform/framework/web/crosswalk.git] / src / third_party / webrtc / modules / rtp_rtcp / source / rtp_packet_history.cc
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
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
35 RTPPacketHistory::~RTPPacketHistory() {
36   {
37     CriticalSectionScoped cs(critsect_);
38     Free();
39   }
40   delete critsect_;
41 }
42
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
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
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
91 bool RTPPacketHistory::StorePackets() const {
92   CriticalSectionScoped cs(critsect_);
93   return store_;
94 }
95
96 // private, lock should already be taken
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
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
160 int32_t RTPPacketHistory::ReplaceRTPHeader(const uint8_t* packet,
161                                            uint16_t sequence_number,
162                                            uint16_t rtp_header_length) {
163   CriticalSectionScoped cs(critsect_);
164   if (!store_) {
165     return 0;
166   }
167
168   assert(packet);
169   assert(rtp_header_length > 3);
170   assert(rtp_header_length <= max_packet_length_);
171
172   int32_t index = 0;
173   bool found = FindSeqNum(sequence_number, &index);
174   if (!found) {
175     LOG(LS_WARNING)
176         << "Failed to replace RTP packet due to missing sequence number.";
177     return -1;
178   }
179
180   uint16_t length = stored_lengths_.at(index);
181   if (length == 0 || length > max_packet_length_) {
182     LOG(LS_WARNING) << "No match for getting seqNum " << sequence_number
183                     << ", len " << length;
184     return -1;
185   }
186   assert(stored_seq_nums_[index] == sequence_number);
187
188   // Update RTP header.
189   std::vector<std::vector<uint8_t> >::iterator it =
190       stored_packets_.begin() + index;
191   std::copy(packet, packet + rtp_header_length, it->begin());
192   return 0;
193 }
194
195 bool RTPPacketHistory::HasRTPPacket(uint16_t sequence_number) const {
196   CriticalSectionScoped cs(critsect_);
197   if (!store_) {
198     return false;
199   }
200
201   int32_t index = 0;
202   bool found = FindSeqNum(sequence_number, &index);
203   if (!found) {
204     return false;
205   }
206
207   uint16_t length = stored_lengths_.at(index);
208   if (length == 0 || length > max_packet_length_) {
209     // Invalid length.
210     return false;
211   }
212   return true;
213 }
214
215 bool RTPPacketHistory::GetPacketAndSetSendTime(uint16_t sequence_number,
216                                                uint32_t min_elapsed_time_ms,
217                                                bool retransmit,
218                                                uint8_t* packet,
219                                                uint16_t* packet_length,
220                                                int64_t* stored_time_ms) {
221   assert(*packet_length >= max_packet_length_);
222   CriticalSectionScoped cs(critsect_);
223   if (!store_) {
224     return false;
225   }
226
227   int32_t index = 0;
228   bool found = FindSeqNum(sequence_number, &index);
229   if (!found) {
230     LOG(LS_WARNING) << "No match for getting seqNum " << sequence_number;
231     return false;
232   }
233
234   uint16_t length = stored_lengths_.at(index);
235   assert(length <= max_packet_length_);
236   if (length == 0) {
237     LOG(LS_WARNING) << "No match for getting seqNum " << sequence_number
238                     << ", len " << length;
239     return false;
240   }
241
242   // Verify elapsed time since last retrieve.
243   int64_t now = clock_->TimeInMilliseconds();
244   if (min_elapsed_time_ms > 0 &&
245       ((now - stored_send_times_.at(index)) < min_elapsed_time_ms)) {
246     return false;
247   }
248
249   if (retransmit && stored_types_.at(index) == kDontRetransmit) {
250     // No bytes copied since this packet shouldn't be retransmitted or is
251     // of zero size.
252     return false;
253   }
254   stored_send_times_[index] = clock_->TimeInMilliseconds();
255   GetPacket(index, packet, packet_length, stored_time_ms);
256   return true;
257 }
258
259 void RTPPacketHistory::GetPacket(int index,
260                                  uint8_t* packet,
261                                  uint16_t* packet_length,
262                                  int64_t* stored_time_ms) const {
263   // Get packet.
264   uint16_t length = stored_lengths_.at(index);
265   std::vector<std::vector<uint8_t> >::const_iterator it_found_packet =
266       stored_packets_.begin() + index;
267   std::copy(it_found_packet->begin(), it_found_packet->begin() + length,
268             packet);
269   *packet_length = length;
270   *stored_time_ms = stored_times_.at(index);
271 }
272
273 bool RTPPacketHistory::GetBestFittingPacket(uint8_t* packet,
274                                             uint16_t* packet_length,
275                                             int64_t* stored_time_ms) {
276   CriticalSectionScoped cs(critsect_);
277   if (!store_)
278     return false;
279   int index = FindBestFittingPacket(*packet_length);
280   if (index < 0)
281     return false;
282   GetPacket(index, packet, packet_length, stored_time_ms);
283   return true;
284 }
285
286 // private, lock should already be taken
287 bool RTPPacketHistory::FindSeqNum(uint16_t sequence_number,
288                                   int32_t* index) const {
289   uint16_t temp_sequence_number = 0;
290   if (prev_index_ > 0) {
291     *index = prev_index_ - 1;
292     temp_sequence_number = stored_seq_nums_[*index];
293   } else {
294     *index = stored_seq_nums_.size() - 1;
295     temp_sequence_number = stored_seq_nums_[*index];  // wrap
296   }
297
298   int32_t idx = (prev_index_ - 1) - (temp_sequence_number - sequence_number);
299   if (idx >= 0 && idx < static_cast<int>(stored_seq_nums_.size())) {
300     *index = idx;
301     temp_sequence_number = stored_seq_nums_[*index];
302   }
303
304   if (temp_sequence_number != sequence_number) {
305     // We did not found a match, search all.
306     for (uint16_t m = 0; m < stored_seq_nums_.size(); m++) {
307       if (stored_seq_nums_[m] == sequence_number) {
308         *index = m;
309         temp_sequence_number = stored_seq_nums_[*index];
310         break;
311       }
312     }
313   }
314   if (temp_sequence_number == sequence_number) {
315     // We found a match.
316     return true;
317   }
318   return false;
319 }
320
321 int RTPPacketHistory::FindBestFittingPacket(uint16_t size) const {
322   if (size < kMinPacketRequestBytes || stored_lengths_.empty())
323     return -1;
324   int min_diff = -1;
325   size_t best_index = 0;
326   for (size_t i = 0; i < stored_lengths_.size(); ++i) {
327     if (stored_lengths_[i] == 0)
328       continue;
329     int diff = abs(stored_lengths_[i] - size);
330     if (min_diff < 0 || diff < min_diff) {
331       min_diff = diff;
332       best_index = i;
333     }
334   }
335   if (min_diff < 0)
336     return -1;
337   return best_index;
338 }
339 }  // namespace webrtc