2 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
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.
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.
15 #include "webrtc/modules/audio_coding/neteq4/packet_buffer.h"
17 #include <algorithm> // find_if()
19 #include "webrtc/modules/audio_coding/neteq4/decoder_database.h"
20 #include "webrtc/modules/audio_coding/neteq4/interface/audio_decoder.h"
24 // Predicate used when inserting packets in the buffer list.
25 // Operator() returns true when |packet| goes before |new_packet|.
26 class NewTimestampIsLarger {
28 explicit NewTimestampIsLarger(const Packet* new_packet)
29 : new_packet_(new_packet) {
31 bool operator()(Packet* packet) {
32 return (*new_packet_ >= *packet);
36 const Packet* new_packet_;
39 PacketBuffer::PacketBuffer(size_t max_number_of_packets)
40 : max_number_of_packets_(max_number_of_packets) {}
42 // Destructor. All packets in the buffer will be destroyed.
43 PacketBuffer::~PacketBuffer() {
47 // Flush the buffer. All packets in the buffer will be destroyed.
48 void PacketBuffer::Flush() {
49 DeleteAllPackets(&buffer_);
52 int PacketBuffer::InsertPacket(Packet* packet) {
53 if (!packet || !packet->payload) {
57 return kInvalidPacket;
62 if (buffer_.size() >= max_number_of_packets_) {
63 // Buffer is full. Flush it.
65 return_val = kFlushed;
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.
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) {
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;
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;
103 *current_rtp_payload_type = packet->header.payloadType;
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.
110 } else if (return_val != kOK) {
111 // An error occurred. Delete remaining packets in list and return.
112 DeleteAllPackets(packet_list);
116 return flushed ? kFlushed : kOK;
119 int PacketBuffer::NextTimestamp(uint32_t* next_timestamp) const {
123 if (!next_timestamp) {
124 return kInvalidPointer;
126 *next_timestamp = buffer_.front()->header.timestamp;
130 int PacketBuffer::NextHigherTimestamp(uint32_t timestamp,
131 uint32_t* next_timestamp) const {
135 if (!next_timestamp) {
136 return kInvalidPointer;
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;
149 const RTPHeader* PacketBuffer::NextRtpHeader() const {
153 return const_cast<const RTPHeader*>(&(buffer_.front()->header));
156 Packet* PacketBuffer::GetNextPacket(int* discard_count) {
162 Packet* packet = buffer_.front();
163 // Assert that the packet sanity checks in InsertPacket method works.
164 assert(packet && packet->payload);
166 // Discard other packets with the same timestamp. These are duplicates or
167 // redundant payloads that should not be used.
172 buffer_.front()->header.timestamp == packet->header.timestamp) {
173 if (DiscardNextPacket() != kOK) {
174 assert(false); // Must be ok by design.
183 int PacketBuffer::DiscardNextPacket() {
187 // Assert that the packet sanity checks in InsertPacket method works.
188 assert(buffer_.front());
189 assert(buffer_.front()->payload);
190 DeleteFirstPacket(&buffer_);
194 int PacketBuffer::DiscardOldPackets(uint32_t timestamp_limit) {
196 timestamp_limit != buffer_.front()->header.timestamp &&
197 static_cast<uint32_t>(timestamp_limit
198 - buffer_.front()->header.timestamp) <
200 if (DiscardNextPacket() != kOK) {
201 assert(false); // Must be ok by design.
207 int PacketBuffer::NumSamplesInBuffer(DecoderDatabase* decoder_database,
208 int last_decoded_length) const {
209 PacketList::const_iterator it;
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);
218 if (packet->sync_packet) {
219 duration = last_duration;
221 duration = packet->primary ?
222 decoder->PacketDuration(packet->payload, packet->payload_length) :
223 decoder->PacketDurationRedundant(packet->payload,
224 packet->payload_length);
227 last_duration = duration; // Save the most up-to-date (valid) duration.
230 num_samples += last_duration;
235 void PacketBuffer::IncrementWaitingTimes(int inc) {
236 PacketList::iterator it;
237 for (it = buffer_.begin(); it != buffer_.end(); ++it) {
238 (*it)->waiting_time += inc;
242 bool PacketBuffer::DeleteFirstPacket(PacketList* packet_list) {
243 if (packet_list->empty()) {
246 Packet* first_packet = packet_list->front();
247 delete [] first_packet->payload;
249 packet_list->pop_front();
253 void PacketBuffer::DeleteAllPackets(PacketList* packet_list) {
254 while (DeleteFirstPacket(packet_list)) {
255 // Continue while the list is not empty.
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_);
264 } // namespace webrtc