packet_buffer.cc revision 7df9706a016aba9c10a117b530bcada9ceaa5ab9
1d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org/*
2d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org *  Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
3d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org *
4d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org *  Use of this source code is governed by a BSD-style license
5d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org *  that can be found in the LICENSE file in the root of the source
6d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org *  tree. An additional intellectual property rights grant can be found
7d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org *  in the file PATENTS.  All contributing project authors may
8d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org *  be found in the AUTHORS file in the root of the source tree.
9d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org */
10d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org
11d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org// This is the implementation of the PacketBuffer class. It is mostly based on
12d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org// an STL list. The list is kept sorted at all times so that the next packet to
13d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org// decode is at the beginning of the list.
14d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org
15d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org#include "webrtc/modules/audio_coding/neteq4/packet_buffer.h"
16d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org
17d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org#include <algorithm>  // find_if()
18d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org
19d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org#include "webrtc/modules/audio_coding/neteq4/decoder_database.h"
20d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org#include "webrtc/modules/audio_coding/neteq4/interface/audio_decoder.h"
21d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org
22d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.orgnamespace webrtc {
23d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org
24d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org// Predicate used when inserting packets in the buffer list.
25d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org// Operator() returns true when |packet| goes before |new_packet|.
26d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.orgclass NewTimestampIsLarger {
27d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org public:
28d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org  explicit NewTimestampIsLarger(const Packet* new_packet)
29d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org      : new_packet_(new_packet) {
30d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org  }
31d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org  bool operator()(Packet* packet) {
32d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org    return (*new_packet_ >= *packet);
33d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org  }
34d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org
35d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org private:
36d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org  const Packet* new_packet_;
37d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org};
38d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org
39d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org// Constructor. The arguments define the maximum number of slots and maximum
40d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org// payload memory (excluding RTP headers) that the buffer will accept.
41d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.orgPacketBuffer::PacketBuffer(size_t max_number_of_packets,
42d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org                           size_t max_memory_bytes)
43d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org    : max_number_of_packets_(max_number_of_packets),
44d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org      max_memory_bytes_(max_memory_bytes),
45d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org      current_memory_bytes_(0) {
46d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org}
47d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org
48d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org// Destructor. All packets in the buffer will be destroyed.
49d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.orgPacketBuffer::~PacketBuffer() {
50d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org  Flush();
51d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org}
52d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org
53d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org// Flush the buffer. All packets in the buffer will be destroyed.
54d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.orgvoid PacketBuffer::Flush() {
55d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org  DeleteAllPackets(&buffer_);
56d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org  current_memory_bytes_ = 0;
57d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org}
58d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org
59d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.orgint PacketBuffer::InsertPacket(Packet* packet) {
60d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org  if (!packet || !packet->payload) {
61d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org    if (packet) {
62d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org      delete packet;
63d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org    }
64d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org    return kInvalidPacket;
65d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org  }
66d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org
67d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org  int return_val = kOK;
68d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org
69d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org  if ((buffer_.size() >= max_number_of_packets_) ||
70d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org      (current_memory_bytes_ + packet->payload_length
71d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org          > static_cast<int>(max_memory_bytes_))) {
72d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org    // Buffer is full. Flush it.
73d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org    Flush();
74d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org    return_val = kFlushed;
75d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org    if ((buffer_.size() >= max_number_of_packets_) ||
76d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org        (current_memory_bytes_ + packet->payload_length
77d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org            > static_cast<int>(max_memory_bytes_))) {
78d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org      // Buffer is still too small for the packet. Either the buffer limits are
79d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org      // really small, or the packet is really large. Delete the packet and
80d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org      // return an error.
81d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org      delete [] packet->payload;
82d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org      delete packet;
83d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org      return kOversizePacket;
84d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org    }
85d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org  }
86d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org
87d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org  // Get an iterator pointing to the place in the buffer where the new packet
88d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org  // should be inserted. The list is searched from the back, since the most
89d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org  // likely case is that the new packet should be near the end of the list.
90d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org  PacketList::reverse_iterator rit = std::find_if(
91d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org      buffer_.rbegin(), buffer_.rend(),
92d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org      NewTimestampIsLarger(packet));
93d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org  buffer_.insert(rit.base(), packet);  // Insert the packet at that position.
94d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org  current_memory_bytes_ += packet->payload_length;
95d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org
96d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org  return return_val;
97d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org}
98d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org
99d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.orgint PacketBuffer::InsertPacketList(PacketList* packet_list,
100d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org                                   const DecoderDatabase& decoder_database,
101d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org                                   uint8_t* current_rtp_payload_type,
102d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org                                   uint8_t* current_cng_rtp_payload_type) {
103d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org  bool flushed = false;
104d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org  while (!packet_list->empty()) {
105d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org    Packet* packet = packet_list->front();
106d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org    if (decoder_database.IsComfortNoise(packet->header.payloadType)) {
107d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org      if (*current_cng_rtp_payload_type != 0xFF &&
108d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org          *current_cng_rtp_payload_type != packet->header.payloadType) {
109d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org        // New CNG payload type implies new codec type.
110d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org        *current_rtp_payload_type = 0xFF;
111d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org        Flush();
112d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org        flushed = true;
113d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org      }
114d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org      *current_cng_rtp_payload_type = packet->header.payloadType;
115d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org    } else if (!decoder_database.IsDtmf(packet->header.payloadType)) {
116d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org      // This must be speech.
117d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org      if (*current_rtp_payload_type != 0xFF &&
118d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org          *current_rtp_payload_type != packet->header.payloadType) {
119d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org        *current_cng_rtp_payload_type = 0xFF;
120d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org        Flush();
121d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org        flushed = true;
122d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org      }
123d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org      *current_rtp_payload_type = packet->header.payloadType;
124d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org    }
125d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org    int return_val = InsertPacket(packet);
126d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org    packet_list->pop_front();
127d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org    if (return_val == kFlushed) {
128d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org      // The buffer flushed, but this is not an error. We can still continue.
129d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org      flushed = true;
130d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org    } else if (return_val != kOK) {
131d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org      // An error occurred. Delete remaining packets in list and return.
132d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org      DeleteAllPackets(packet_list);
133d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org      return return_val;
134d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org    }
135d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org  }
136d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org  return flushed ? kFlushed : kOK;
137d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org}
138d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org
139d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.orgint PacketBuffer::NextTimestamp(uint32_t* next_timestamp) const {
140d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org  if (Empty()) {
141d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org    return kBufferEmpty;
142d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org  }
143d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org  if (!next_timestamp) {
144d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org    return kInvalidPointer;
145d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org  }
146d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org  *next_timestamp = buffer_.front()->header.timestamp;
147d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org  return kOK;
148d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org}
149d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org
150d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.orgint PacketBuffer::NextHigherTimestamp(uint32_t timestamp,
151d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org                                      uint32_t* next_timestamp) const {
152d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org  if (Empty()) {
153d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org    return kBufferEmpty;
154d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org  }
155d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org  if (!next_timestamp) {
156d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org    return kInvalidPointer;
157d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org  }
158d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org  PacketList::const_iterator it;
159d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org  for (it = buffer_.begin(); it != buffer_.end(); ++it) {
160d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org    if ((*it)->header.timestamp >= timestamp) {
161d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org      // Found a packet matching the search.
162d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org      *next_timestamp = (*it)->header.timestamp;
163d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org      return kOK;
164d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org    }
165d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org  }
166d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org  return kNotFound;
167d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org}
168d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org
169d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.orgconst RTPHeader* PacketBuffer::NextRtpHeader() const {
170d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org  if (Empty()) {
171d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org    return NULL;
172d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org  }
173d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org  return const_cast<const RTPHeader*>(&(buffer_.front()->header));
174d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org}
175d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org
176d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.orgPacket* PacketBuffer::GetNextPacket(int* discard_count) {
177d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org  if (Empty()) {
178d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org    // Buffer is empty.
179d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org    return NULL;
180d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org  }
181d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org
182d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org  Packet* packet = buffer_.front();
183d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org  // Assert that the packet sanity checks in InsertPacket method works.
184d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org  assert(packet && packet->payload);
185d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org  buffer_.pop_front();
186d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org  current_memory_bytes_ -= packet->payload_length;
187d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org  assert(current_memory_bytes_ >= 0);  // Assert bookkeeping is correct.
188d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org  // Discard other packets with the same timestamp. These are duplicates or
189d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org  // redundant payloads that should not be used.
190d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org  if (discard_count) {
191d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org    *discard_count = 0;
192d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org  }
193d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org  while (!Empty() &&
194d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org      buffer_.front()->header.timestamp == packet->header.timestamp) {
195d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org    if (DiscardNextPacket() != kOK) {
196d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org      assert(false);  // Must be ok by design.
197d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org    }
198d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org    if (discard_count) {
199d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org      ++(*discard_count);
200d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org    }
201d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org  }
202d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org  return packet;
203d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org}
204d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org
205d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.orgint PacketBuffer::DiscardNextPacket() {
206d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org  if (Empty()) {
207d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org    return kBufferEmpty;
208d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org  }
209d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org  Packet* temp_packet = buffer_.front();
210d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org  // Assert that the packet sanity checks in InsertPacket method works.
211d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org  assert(temp_packet && temp_packet->payload);
212d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org  current_memory_bytes_ -= temp_packet->payload_length;
213d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org  assert(current_memory_bytes_ >= 0);  // Assert bookkeeping is correct.
214d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org  DeleteFirstPacket(&buffer_);
215d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org  return kOK;
216d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org}
217d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org
218d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.orgint PacketBuffer::DiscardOldPackets(uint32_t timestamp_limit) {
219d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org  int discard_count = 0;
220d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org  while (!Empty() &&
221d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org      timestamp_limit != buffer_.front()->header.timestamp &&
222d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org      static_cast<uint32_t>(timestamp_limit
223d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org                            - buffer_.front()->header.timestamp) <
224d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org                            0xFFFFFFFF / 2) {
225d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org    if (DiscardNextPacket() != kOK) {
226d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org      assert(false);  // Must be ok by design.
227d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org    }
228d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org    ++discard_count;
229d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org  }
230d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org  return 0;
231d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org}
232d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org
233d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.orgint PacketBuffer::NumSamplesInBuffer(DecoderDatabase* decoder_database,
234d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org                                     int last_decoded_length) const {
235d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org  PacketList::const_iterator it;
236d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org  int num_samples = 0;
237d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org  for (it = buffer_.begin(); it != buffer_.end(); ++it) {
238d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org    Packet* packet = (*it);
239d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org    AudioDecoder* decoder =
240d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org        decoder_database->GetDecoder(packet->header.payloadType);
241d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org    if (decoder) {
242d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org      int duration = decoder->PacketDuration(packet->payload,
243d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org                                             packet->payload_length);
244d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org      if (duration >= 0) {
245d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org        num_samples += duration;
246d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org        continue;  // Go to next packet in loop.
247d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org      }
248d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org    }
249d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org    num_samples += last_decoded_length;
250d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org  }
251d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org  return num_samples;
252d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org}
253d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org
254d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.orgvoid PacketBuffer::IncrementWaitingTimes(int inc) {
255d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org  PacketList::iterator it;
256d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org  for (it = buffer_.begin(); it != buffer_.end(); ++it) {
257d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org    (*it)->waiting_time += inc;
258d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org  }
259d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org}
260d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org
261d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.orgbool PacketBuffer::DeleteFirstPacket(PacketList* packet_list) {
262d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org  if (packet_list->empty()) {
263d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org    return false;
264d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org  }
265d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org  Packet* first_packet = packet_list->front();
266d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org  delete [] first_packet->payload;
267d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org  delete first_packet;
268d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org  packet_list->pop_front();
269d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org  return true;
270d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org}
271d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org
272d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.orgvoid PacketBuffer::DeleteAllPackets(PacketList* packet_list) {
273d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org  while (DeleteFirstPacket(packet_list)) {
274d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org    // Continue while the list is not empty.
275d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org  }
276d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org}
277d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org
2787df9706a016aba9c10a117b530bcada9ceaa5ab9turaj@webrtc.orgvoid PacketBuffer::BufferStat(int* num_packest,
2797df9706a016aba9c10a117b530bcada9ceaa5ab9turaj@webrtc.org                              int* max_num_packets,
2807df9706a016aba9c10a117b530bcada9ceaa5ab9turaj@webrtc.org                              int* current_memory_bytes,
2817df9706a016aba9c10a117b530bcada9ceaa5ab9turaj@webrtc.org                              int* max_memory_bytes) const {
2827df9706a016aba9c10a117b530bcada9ceaa5ab9turaj@webrtc.org  *num_packest = buffer_.size();
2837df9706a016aba9c10a117b530bcada9ceaa5ab9turaj@webrtc.org  *max_num_packets = max_number_of_packets_;
2847df9706a016aba9c10a117b530bcada9ceaa5ab9turaj@webrtc.org  *current_memory_bytes = current_memory_bytes_;
2857df9706a016aba9c10a117b530bcada9ceaa5ab9turaj@webrtc.org  *max_memory_bytes = max_memory_bytes_;
2867df9706a016aba9c10a117b530bcada9ceaa5ab9turaj@webrtc.org}
2877df9706a016aba9c10a117b530bcada9ceaa5ab9turaj@webrtc.org
288d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org}  // namespace webrtc
289