blob: 839c179ba4b04cc27a2b010ca6551823bd6c5024 [file] [log] [blame]
henrik.lundin@webrtc.org9a400812013-01-29 12:09:21 +00001/*
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
22namespace webrtc {
23
24// Predicate used when inserting packets in the buffer list.
25// Operator() returns true when |packet| goes before |new_packet|.
26class 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// Constructor. The arguments define the maximum number of slots and maximum
40// payload memory (excluding RTP headers) that the buffer will accept.
41PacketBuffer::PacketBuffer(size_t max_number_of_packets,
42 size_t max_memory_bytes)
43 : max_number_of_packets_(max_number_of_packets),
44 max_memory_bytes_(max_memory_bytes),
45 current_memory_bytes_(0) {
46}
47
48// Destructor. All packets in the buffer will be destroyed.
49PacketBuffer::~PacketBuffer() {
50 Flush();
51}
52
53// Flush the buffer. All packets in the buffer will be destroyed.
54void PacketBuffer::Flush() {
55 DeleteAllPackets(&buffer_);
56 current_memory_bytes_ = 0;
57}
58
59int PacketBuffer::InsertPacket(Packet* packet) {
60 if (!packet || !packet->payload) {
61 if (packet) {
62 delete packet;
63 }
64 return kInvalidPacket;
65 }
66
67 int return_val = kOK;
68
69 if ((buffer_.size() >= max_number_of_packets_) ||
70 (current_memory_bytes_ + packet->payload_length
71 > static_cast<int>(max_memory_bytes_))) {
72 // Buffer is full. Flush it.
73 Flush();
74 return_val = kFlushed;
75 if ((buffer_.size() >= max_number_of_packets_) ||
76 (current_memory_bytes_ + packet->payload_length
77 > static_cast<int>(max_memory_bytes_))) {
78 // Buffer is still too small for the packet. Either the buffer limits are
79 // really small, or the packet is really large. Delete the packet and
80 // return an error.
81 delete [] packet->payload;
82 delete packet;
83 return kOversizePacket;
84 }
85 }
86
87 // Get an iterator pointing to the place in the buffer where the new packet
88 // should be inserted. The list is searched from the back, since the most
89 // likely case is that the new packet should be near the end of the list.
90 PacketList::reverse_iterator rit = std::find_if(
91 buffer_.rbegin(), buffer_.rend(),
92 NewTimestampIsLarger(packet));
93 buffer_.insert(rit.base(), packet); // Insert the packet at that position.
94 current_memory_bytes_ += packet->payload_length;
95
96 return return_val;
97}
98
99int PacketBuffer::InsertPacketList(PacketList* packet_list,
100 const DecoderDatabase& decoder_database,
101 uint8_t* current_rtp_payload_type,
102 uint8_t* current_cng_rtp_payload_type) {
103 bool flushed = false;
104 while (!packet_list->empty()) {
105 Packet* packet = packet_list->front();
106 if (decoder_database.IsComfortNoise(packet->header.payloadType)) {
107 if (*current_cng_rtp_payload_type != 0xFF &&
108 *current_cng_rtp_payload_type != packet->header.payloadType) {
109 // New CNG payload type implies new codec type.
110 *current_rtp_payload_type = 0xFF;
111 Flush();
112 flushed = true;
113 }
114 *current_cng_rtp_payload_type = packet->header.payloadType;
115 } else if (!decoder_database.IsDtmf(packet->header.payloadType)) {
116 // This must be speech.
117 if (*current_rtp_payload_type != 0xFF &&
118 *current_rtp_payload_type != packet->header.payloadType) {
119 *current_cng_rtp_payload_type = 0xFF;
120 Flush();
121 flushed = true;
122 }
123 *current_rtp_payload_type = packet->header.payloadType;
124 }
125 int return_val = InsertPacket(packet);
126 packet_list->pop_front();
127 if (return_val == kFlushed) {
128 // The buffer flushed, but this is not an error. We can still continue.
129 flushed = true;
130 } else if (return_val != kOK) {
131 // An error occurred. Delete remaining packets in list and return.
132 DeleteAllPackets(packet_list);
133 return return_val;
134 }
135 }
136 return flushed ? kFlushed : kOK;
137}
138
139int PacketBuffer::NextTimestamp(uint32_t* next_timestamp) const {
140 if (Empty()) {
141 return kBufferEmpty;
142 }
143 if (!next_timestamp) {
144 return kInvalidPointer;
145 }
146 *next_timestamp = buffer_.front()->header.timestamp;
147 return kOK;
148}
149
150int PacketBuffer::NextHigherTimestamp(uint32_t timestamp,
151 uint32_t* next_timestamp) const {
152 if (Empty()) {
153 return kBufferEmpty;
154 }
155 if (!next_timestamp) {
156 return kInvalidPointer;
157 }
158 PacketList::const_iterator it;
159 for (it = buffer_.begin(); it != buffer_.end(); ++it) {
160 if ((*it)->header.timestamp >= timestamp) {
161 // Found a packet matching the search.
162 *next_timestamp = (*it)->header.timestamp;
163 return kOK;
164 }
165 }
166 return kNotFound;
167}
168
169const RTPHeader* PacketBuffer::NextRtpHeader() const {
170 if (Empty()) {
171 return NULL;
172 }
173 return const_cast<const RTPHeader*>(&(buffer_.front()->header));
174}
175
176Packet* PacketBuffer::GetNextPacket(int* discard_count) {
177 if (Empty()) {
178 // Buffer is empty.
179 return NULL;
180 }
181
182 Packet* packet = buffer_.front();
183 // Assert that the packet sanity checks in InsertPacket method works.
184 assert(packet && packet->payload);
185 buffer_.pop_front();
186 current_memory_bytes_ -= packet->payload_length;
187 assert(current_memory_bytes_ >= 0); // Assert bookkeeping is correct.
188 // Discard other packets with the same timestamp. These are duplicates or
189 // redundant payloads that should not be used.
190 if (discard_count) {
191 *discard_count = 0;
192 }
193 while (!Empty() &&
194 buffer_.front()->header.timestamp == packet->header.timestamp) {
195 if (DiscardNextPacket() != kOK) {
196 assert(false); // Must be ok by design.
197 }
198 if (discard_count) {
199 ++(*discard_count);
200 }
201 }
202 return packet;
203}
204
205int PacketBuffer::DiscardNextPacket() {
206 if (Empty()) {
207 return kBufferEmpty;
208 }
209 Packet* temp_packet = buffer_.front();
210 // Assert that the packet sanity checks in InsertPacket method works.
211 assert(temp_packet && temp_packet->payload);
212 current_memory_bytes_ -= temp_packet->payload_length;
213 assert(current_memory_bytes_ >= 0); // Assert bookkeeping is correct.
214 DeleteFirstPacket(&buffer_);
215 return kOK;
216}
217
218int PacketBuffer::DiscardOldPackets(uint32_t timestamp_limit) {
219 int discard_count = 0;
220 while (!Empty() &&
221 timestamp_limit != buffer_.front()->header.timestamp &&
222 static_cast<uint32_t>(timestamp_limit
223 - buffer_.front()->header.timestamp) <
224 0xFFFFFFFF / 2) {
225 if (DiscardNextPacket() != kOK) {
226 assert(false); // Must be ok by design.
227 }
228 ++discard_count;
229 }
230 return 0;
231}
232
233int PacketBuffer::NumSamplesInBuffer(DecoderDatabase* decoder_database,
234 int last_decoded_length) const {
235 PacketList::const_iterator it;
236 int num_samples = 0;
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 = decoder->PacketDuration(packet->payload,
243 packet->payload_length);
244 if (duration >= 0) {
245 num_samples += duration;
246 continue; // Go to next packet in loop.
247 }
248 }
249 num_samples += last_decoded_length;
250 }
251 return num_samples;
252}
253
254void PacketBuffer::IncrementWaitingTimes(int inc) {
255 PacketList::iterator it;
256 for (it = buffer_.begin(); it != buffer_.end(); ++it) {
257 (*it)->waiting_time += inc;
258 }
259}
260
261bool PacketBuffer::DeleteFirstPacket(PacketList* packet_list) {
262 if (packet_list->empty()) {
263 return false;
264 }
265 Packet* first_packet = packet_list->front();
266 delete [] first_packet->payload;
267 delete first_packet;
268 packet_list->pop_front();
269 return true;
270}
271
272void PacketBuffer::DeleteAllPackets(PacketList* packet_list) {
273 while (DeleteFirstPacket(packet_list)) {
274 // Continue while the list is not empty.
275 }
276}
277
turaj@webrtc.org4b8077b2013-08-02 18:07:13 +0000278void PacketBuffer::BufferStat(int* num_packest,
279 int* max_num_packets,
280 int* current_memory_bytes,
281 int* max_memory_bytes) const {
282 *num_packest = buffer_.size();
283 *max_num_packets = max_number_of_packets_;
284 *current_memory_bytes = current_memory_bytes_;
285 *max_memory_bytes = max_memory_bytes_;
286}
287
henrik.lundin@webrtc.org9a400812013-01-29 12:09:21 +0000288} // namespace webrtc