Home | History | Annotate | Download | only in neteq
      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