• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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