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:
NewTimestampIsLarger(const Packet * new_packet)28 explicit NewTimestampIsLarger(const Packet* new_packet)
29 : new_packet_(new_packet) {
30 }
operator ()(Packet * packet)31 bool operator()(Packet* packet) {
32 return (*new_packet_ >= *packet);
33 }
34
35 private:
36 const Packet* new_packet_;
37 };
38
PacketBuffer(size_t max_number_of_packets)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.
~PacketBuffer()43 PacketBuffer::~PacketBuffer() {
44 Flush();
45 }
46
47 // Flush the buffer. All packets in the buffer will be destroyed.
Flush()48 void PacketBuffer::Flush() {
49 DeleteAllPackets(&buffer_);
50 }
51
InsertPacket(Packet * packet)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
InsertPacketList(PacketList * packet_list,const DecoderDatabase & decoder_database,uint8_t * current_rtp_payload_type,uint8_t * current_cng_rtp_payload_type)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
NextTimestamp(uint32_t * next_timestamp) const119 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
NextHigherTimestamp(uint32_t timestamp,uint32_t * next_timestamp) const130 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
NextRtpHeader() const149 const RTPHeader* PacketBuffer::NextRtpHeader() const {
150 if (Empty()) {
151 return NULL;
152 }
153 return const_cast<const RTPHeader*>(&(buffer_.front()->header));
154 }
155
GetNextPacket(int * discard_count)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
DiscardNextPacket()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
DiscardOldPackets(uint32_t timestamp_limit)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
NumSamplesInBuffer(DecoderDatabase * decoder_database,int last_decoded_length) const207 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 if (packet->primary) {
221 duration =
222 decoder->PacketDuration(packet->payload, packet->payload_length);
223 } else {
224 continue;
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
IncrementWaitingTimes(int inc)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
DeleteFirstPacket(PacketList * packet_list)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
DeleteAllPackets(PacketList * packet_list)253 void PacketBuffer::DeleteAllPackets(PacketList* packet_list) {
254 while (DeleteFirstPacket(packet_list)) {
255 // Continue while the list is not empty.
256 }
257 }
258
BufferStat(int * num_packets,int * max_num_packets) const259 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
265