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