Upstream version 7.36.149.0
[platform/framework/web/crosswalk.git] / src / third_party / webrtc / modules / audio_coding / neteq4 / 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/neteq4/packet_buffer.h"
16
17 #include <algorithm>  // find_if()
18
19 #include "webrtc/modules/audio_coding/neteq4/decoder_database.h"
20 #include "webrtc/modules/audio_coding/neteq4/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   buffer_.insert(rit.base(), packet);  // Insert the packet at that position.
75
76   return return_val;
77 }
78
79 int PacketBuffer::InsertPacketList(PacketList* packet_list,
80                                    const DecoderDatabase& decoder_database,
81                                    uint8_t* current_rtp_payload_type,
82                                    uint8_t* current_cng_rtp_payload_type) {
83   bool flushed = false;
84   while (!packet_list->empty()) {
85     Packet* packet = packet_list->front();
86     if (decoder_database.IsComfortNoise(packet->header.payloadType)) {
87       if (*current_cng_rtp_payload_type != 0xFF &&
88           *current_cng_rtp_payload_type != packet->header.payloadType) {
89         // New CNG payload type implies new codec type.
90         *current_rtp_payload_type = 0xFF;
91         Flush();
92         flushed = true;
93       }
94       *current_cng_rtp_payload_type = packet->header.payloadType;
95     } else if (!decoder_database.IsDtmf(packet->header.payloadType)) {
96       // This must be speech.
97       if (*current_rtp_payload_type != 0xFF &&
98           *current_rtp_payload_type != packet->header.payloadType) {
99         *current_cng_rtp_payload_type = 0xFF;
100         Flush();
101         flushed = true;
102       }
103       *current_rtp_payload_type = packet->header.payloadType;
104     }
105     int return_val = InsertPacket(packet);
106     packet_list->pop_front();
107     if (return_val == kFlushed) {
108       // The buffer flushed, but this is not an error. We can still continue.
109       flushed = true;
110     } else if (return_val != kOK) {
111       // An error occurred. Delete remaining packets in list and return.
112       DeleteAllPackets(packet_list);
113       return return_val;
114     }
115   }
116   return flushed ? kFlushed : kOK;
117 }
118
119 int PacketBuffer::NextTimestamp(uint32_t* next_timestamp) const {
120   if (Empty()) {
121     return kBufferEmpty;
122   }
123   if (!next_timestamp) {
124     return kInvalidPointer;
125   }
126   *next_timestamp = buffer_.front()->header.timestamp;
127   return kOK;
128 }
129
130 int PacketBuffer::NextHigherTimestamp(uint32_t timestamp,
131                                       uint32_t* next_timestamp) const {
132   if (Empty()) {
133     return kBufferEmpty;
134   }
135   if (!next_timestamp) {
136     return kInvalidPointer;
137   }
138   PacketList::const_iterator it;
139   for (it = buffer_.begin(); it != buffer_.end(); ++it) {
140     if ((*it)->header.timestamp >= timestamp) {
141       // Found a packet matching the search.
142       *next_timestamp = (*it)->header.timestamp;
143       return kOK;
144     }
145   }
146   return kNotFound;
147 }
148
149 const RTPHeader* PacketBuffer::NextRtpHeader() const {
150   if (Empty()) {
151     return NULL;
152   }
153   return const_cast<const RTPHeader*>(&(buffer_.front()->header));
154 }
155
156 Packet* PacketBuffer::GetNextPacket(int* discard_count) {
157   if (Empty()) {
158     // Buffer is empty.
159     return NULL;
160   }
161
162   Packet* packet = buffer_.front();
163   // Assert that the packet sanity checks in InsertPacket method works.
164   assert(packet && packet->payload);
165   buffer_.pop_front();
166   // Discard other packets with the same timestamp. These are duplicates or
167   // redundant payloads that should not be used.
168   if (discard_count) {
169     *discard_count = 0;
170   }
171   while (!Empty() &&
172       buffer_.front()->header.timestamp == packet->header.timestamp) {
173     if (DiscardNextPacket() != kOK) {
174       assert(false);  // Must be ok by design.
175     }
176     if (discard_count) {
177       ++(*discard_count);
178     }
179   }
180   return packet;
181 }
182
183 int PacketBuffer::DiscardNextPacket() {
184   if (Empty()) {
185     return kBufferEmpty;
186   }
187   // Assert that the packet sanity checks in InsertPacket method works.
188   assert(buffer_.front());
189   assert(buffer_.front()->payload);
190   DeleteFirstPacket(&buffer_);
191   return kOK;
192 }
193
194 int PacketBuffer::DiscardOldPackets(uint32_t timestamp_limit) {
195   while (!Empty() &&
196       timestamp_limit != buffer_.front()->header.timestamp &&
197       static_cast<uint32_t>(timestamp_limit
198                             - buffer_.front()->header.timestamp) <
199                             0xFFFFFFFF / 2) {
200     if (DiscardNextPacket() != kOK) {
201       assert(false);  // Must be ok by design.
202     }
203   }
204   return 0;
205 }
206
207 int PacketBuffer::NumSamplesInBuffer(DecoderDatabase* decoder_database,
208                                      int last_decoded_length) const {
209   PacketList::const_iterator it;
210   int num_samples = 0;
211   int last_duration = last_decoded_length;
212   for (it = buffer_.begin(); it != buffer_.end(); ++it) {
213     Packet* packet = (*it);
214     AudioDecoder* decoder =
215         decoder_database->GetDecoder(packet->header.payloadType);
216     if (decoder) {
217       int duration;
218       if (packet->sync_packet) {
219         duration = last_duration;
220       } else {
221         duration = packet->primary ?
222             decoder->PacketDuration(packet->payload, packet->payload_length) :
223             decoder->PacketDurationRedundant(packet->payload,
224                                              packet->payload_length);
225       }
226       if (duration >= 0) {
227         last_duration = duration;  // Save the most up-to-date (valid) duration.
228       }
229     }
230     num_samples += last_duration;
231   }
232   return num_samples;
233 }
234
235 void PacketBuffer::IncrementWaitingTimes(int inc) {
236   PacketList::iterator it;
237   for (it = buffer_.begin(); it != buffer_.end(); ++it) {
238     (*it)->waiting_time += inc;
239   }
240 }
241
242 bool PacketBuffer::DeleteFirstPacket(PacketList* packet_list) {
243   if (packet_list->empty()) {
244     return false;
245   }
246   Packet* first_packet = packet_list->front();
247   delete [] first_packet->payload;
248   delete first_packet;
249   packet_list->pop_front();
250   return true;
251 }
252
253 void PacketBuffer::DeleteAllPackets(PacketList* packet_list) {
254   while (DeleteFirstPacket(packet_list)) {
255     // Continue while the list is not empty.
256   }
257 }
258
259 void PacketBuffer::BufferStat(int* num_packets, int* max_num_packets) const {
260   *num_packets = static_cast<int>(buffer_.size());
261   *max_num_packets = static_cast<int>(max_number_of_packets_);
262 }
263
264 }  // namespace webrtc