Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / third_party / webrtc / modules / audio_coding / neteq / packet_buffer.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 // This is the implementation of the PacketBuffer class. It is mostly based on
12 // an STL list. The list is kept sorted at all times so that the next packet to
13 // decode is at the beginning of the list.
14
15 #include "webrtc/modules/audio_coding/neteq/packet_buffer.h"
16
17 #include <algorithm>  // find_if()
18
19 #include "webrtc/modules/audio_coding/neteq/decoder_database.h"
20 #include "webrtc/modules/audio_coding/neteq/interface/audio_decoder.h"
21
22 namespace webrtc {
23
24 // Predicate used when inserting packets in the buffer list.
25 // Operator() returns true when |packet| goes before |new_packet|.
26 class NewTimestampIsLarger {
27  public:
28   explicit NewTimestampIsLarger(const Packet* new_packet)
29       : new_packet_(new_packet) {
30   }
31   bool operator()(Packet* packet) {
32     return (*new_packet_ >= *packet);
33   }
34
35  private:
36   const Packet* new_packet_;
37 };
38
39 PacketBuffer::PacketBuffer(size_t max_number_of_packets)
40     : max_number_of_packets_(max_number_of_packets) {}
41
42 // Destructor. All packets in the buffer will be destroyed.
43 PacketBuffer::~PacketBuffer() {
44   Flush();
45 }
46
47 // Flush the buffer. All packets in the buffer will be destroyed.
48 void PacketBuffer::Flush() {
49   DeleteAllPackets(&buffer_);
50 }
51
52 int PacketBuffer::InsertPacket(Packet* packet) {
53   if (!packet || !packet->payload) {
54     if (packet) {
55       delete packet;
56     }
57     return kInvalidPacket;
58   }
59
60   int return_val = kOK;
61
62   if (buffer_.size() >= max_number_of_packets_) {
63     // Buffer is full. Flush it.
64     Flush();
65     return_val = kFlushed;
66   }
67
68   // Get an iterator pointing to the place in the buffer where the new packet
69   // should be inserted. The list is searched from the back, since the most
70   // likely case is that the new packet should be near the end of the list.
71   PacketList::reverse_iterator rit = std::find_if(
72       buffer_.rbegin(), buffer_.rend(),
73       NewTimestampIsLarger(packet));
74
75   // The new packet is to be inserted to the right of |rit|. If it has the same
76   // timestamp as |rit|, which has a higher priority, do not insert the new
77   // packet to list.
78   if (rit != buffer_.rend() &&
79       packet->header.timestamp == (*rit)->header.timestamp) {
80     delete [] packet->payload;
81     delete packet;
82     return return_val;
83   }
84
85   // The new packet is to be inserted to the left of |it|. If it has the same
86   // timestamp as |it|, which has a lower priority, replace |it| with the new
87   // packet.
88   PacketList::iterator it = rit.base();
89   if (it != buffer_.end() &&
90       packet->header.timestamp == (*it)->header.timestamp) {
91     delete [] (*it)->payload;
92     delete *it;
93     it = buffer_.erase(it);
94   }
95   buffer_.insert(it, packet);  // Insert the packet at that position.
96
97   return return_val;
98 }
99
100 int PacketBuffer::InsertPacketList(PacketList* packet_list,
101                                    const DecoderDatabase& decoder_database,
102                                    uint8_t* current_rtp_payload_type,
103                                    uint8_t* current_cng_rtp_payload_type) {
104   bool flushed = false;
105   while (!packet_list->empty()) {
106     Packet* packet = packet_list->front();
107     if (decoder_database.IsComfortNoise(packet->header.payloadType)) {
108       if (*current_cng_rtp_payload_type != 0xFF &&
109           *current_cng_rtp_payload_type != packet->header.payloadType) {
110         // New CNG payload type implies new codec type.
111         *current_rtp_payload_type = 0xFF;
112         Flush();
113         flushed = true;
114       }
115       *current_cng_rtp_payload_type = packet->header.payloadType;
116     } else if (!decoder_database.IsDtmf(packet->header.payloadType)) {
117       // This must be speech.
118       if (*current_rtp_payload_type != 0xFF &&
119           *current_rtp_payload_type != packet->header.payloadType) {
120         *current_cng_rtp_payload_type = 0xFF;
121         Flush();
122         flushed = true;
123       }
124       *current_rtp_payload_type = packet->header.payloadType;
125     }
126     int return_val = InsertPacket(packet);
127     packet_list->pop_front();
128     if (return_val == kFlushed) {
129       // The buffer flushed, but this is not an error. We can still continue.
130       flushed = true;
131     } else if (return_val != kOK) {
132       // An error occurred. Delete remaining packets in list and return.
133       DeleteAllPackets(packet_list);
134       return return_val;
135     }
136   }
137   return flushed ? kFlushed : kOK;
138 }
139
140 int PacketBuffer::NextTimestamp(uint32_t* next_timestamp) const {
141   if (Empty()) {
142     return kBufferEmpty;
143   }
144   if (!next_timestamp) {
145     return kInvalidPointer;
146   }
147   *next_timestamp = buffer_.front()->header.timestamp;
148   return kOK;
149 }
150
151 int PacketBuffer::NextHigherTimestamp(uint32_t timestamp,
152                                       uint32_t* next_timestamp) const {
153   if (Empty()) {
154     return kBufferEmpty;
155   }
156   if (!next_timestamp) {
157     return kInvalidPointer;
158   }
159   PacketList::const_iterator it;
160   for (it = buffer_.begin(); it != buffer_.end(); ++it) {
161     if ((*it)->header.timestamp >= timestamp) {
162       // Found a packet matching the search.
163       *next_timestamp = (*it)->header.timestamp;
164       return kOK;
165     }
166   }
167   return kNotFound;
168 }
169
170 const RTPHeader* PacketBuffer::NextRtpHeader() const {
171   if (Empty()) {
172     return NULL;
173   }
174   return const_cast<const RTPHeader*>(&(buffer_.front()->header));
175 }
176
177 Packet* PacketBuffer::GetNextPacket(int* discard_count) {
178   if (Empty()) {
179     // Buffer is empty.
180     return NULL;
181   }
182
183   Packet* packet = buffer_.front();
184   // Assert that the packet sanity checks in InsertPacket method works.
185   assert(packet && packet->payload);
186   buffer_.pop_front();
187
188   // Discard other packets with the same timestamp. These are duplicates or
189   // redundant payloads that should not be used.
190   int discards = 0;
191
192   while (!Empty() &&
193       buffer_.front()->header.timestamp == packet->header.timestamp) {
194     if (DiscardNextPacket() != kOK) {
195       assert(false);  // Must be ok by design.
196     }
197     ++discards;
198   }
199   // The way of inserting packet should not cause any packet discarding here.
200   // TODO(minyue): remove |discard_count|.
201   assert(discards == 0);
202   if (discard_count)
203     *discard_count = discards;
204
205   return packet;
206 }
207
208 int PacketBuffer::DiscardNextPacket() {
209   if (Empty()) {
210     return kBufferEmpty;
211   }
212   // Assert that the packet sanity checks in InsertPacket method works.
213   assert(buffer_.front());
214   assert(buffer_.front()->payload);
215   DeleteFirstPacket(&buffer_);
216   return kOK;
217 }
218
219 int PacketBuffer::DiscardOldPackets(uint32_t timestamp_limit,
220                                     uint32_t horizon_samples) {
221   while (!Empty() && timestamp_limit != buffer_.front()->header.timestamp &&
222          IsObsoleteTimestamp(buffer_.front()->header.timestamp,
223                              timestamp_limit,
224                              horizon_samples)) {
225     if (DiscardNextPacket() != kOK) {
226       assert(false);  // Must be ok by design.
227     }
228   }
229   return 0;
230 }
231
232 int PacketBuffer::NumSamplesInBuffer(DecoderDatabase* decoder_database,
233                                      int last_decoded_length) const {
234   PacketList::const_iterator it;
235   int num_samples = 0;
236   int last_duration = last_decoded_length;
237   for (it = buffer_.begin(); it != buffer_.end(); ++it) {
238     Packet* packet = (*it);
239     AudioDecoder* decoder =
240         decoder_database->GetDecoder(packet->header.payloadType);
241     if (decoder) {
242       int duration;
243       if (packet->sync_packet) {
244         duration = last_duration;
245       } else if (packet->primary) {
246         duration =
247             decoder->PacketDuration(packet->payload, packet->payload_length);
248       } else {
249         continue;
250       }
251       if (duration >= 0) {
252         last_duration = duration;  // Save the most up-to-date (valid) duration.
253       }
254     }
255     num_samples += last_duration;
256   }
257   return num_samples;
258 }
259
260 void PacketBuffer::IncrementWaitingTimes(int inc) {
261   PacketList::iterator it;
262   for (it = buffer_.begin(); it != buffer_.end(); ++it) {
263     (*it)->waiting_time += inc;
264   }
265 }
266
267 bool PacketBuffer::DeleteFirstPacket(PacketList* packet_list) {
268   if (packet_list->empty()) {
269     return false;
270   }
271   Packet* first_packet = packet_list->front();
272   delete [] first_packet->payload;
273   delete first_packet;
274   packet_list->pop_front();
275   return true;
276 }
277
278 void PacketBuffer::DeleteAllPackets(PacketList* packet_list) {
279   while (DeleteFirstPacket(packet_list)) {
280     // Continue while the list is not empty.
281   }
282 }
283
284 void PacketBuffer::BufferStat(int* num_packets, int* max_num_packets) const {
285   *num_packets = static_cast<int>(buffer_.size());
286   *max_num_packets = static_cast<int>(max_number_of_packets_);
287 }
288
289 }  // namespace webrtc