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: 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 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 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 265