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
159c55f0f957534144d2b8a64154f0a479249b34behenrik.lundin@webrtc.org#include "webrtc/modules/audio_coding/neteq/packet_buffer.h"
16d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org
17d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org#include <algorithm>  // find_if()
18d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org
19d67a219bec0c4cde149014984d5dfe168fe0a346Henrik Lundin#include "webrtc/base/logging.h"
20e04a93bcf5e1b608c798a6a3148224b8035f0119kwiberg@webrtc.org#include "webrtc/modules/audio_coding/codecs/audio_decoder.h"
219c55f0f957534144d2b8a64154f0a479249b34behenrik.lundin@webrtc.org#include "webrtc/modules/audio_coding/neteq/decoder_database.h"
22d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org
23d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.orgnamespace webrtc {
24d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org
25d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org// Predicate used when inserting packets in the buffer list.
26d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org// Operator() returns true when |packet| goes before |new_packet|.
27d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.orgclass NewTimestampIsLarger {
28d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org public:
29d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org  explicit NewTimestampIsLarger(const Packet* new_packet)
30d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org      : new_packet_(new_packet) {
31d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org  }
32d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org  bool operator()(Packet* packet) {
33d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org    return (*new_packet_ >= *packet);
34d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org  }
35d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org
36d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org private:
37d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org  const Packet* new_packet_;
38d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org};
39d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org
40116ed1d4f0445fdf215cffa2d9d0946a1cdab3ebhenrik.lundin@webrtc.orgPacketBuffer::PacketBuffer(size_t max_number_of_packets)
41116ed1d4f0445fdf215cffa2d9d0946a1cdab3ebhenrik.lundin@webrtc.org    : max_number_of_packets_(max_number_of_packets) {}
42d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org
43d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org// Destructor. All packets in the buffer will be destroyed.
44d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.orgPacketBuffer::~PacketBuffer() {
45d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org  Flush();
46d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org}
47d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org
48d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org// Flush the buffer. All packets in the buffer will be destroyed.
49d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.orgvoid PacketBuffer::Flush() {
50d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org  DeleteAllPackets(&buffer_);
51d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org}
52d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org
537f6c4d42a2605d1da39af3f957a46cf57b043b84Karl Wibergbool PacketBuffer::Empty() const {
547f6c4d42a2605d1da39af3f957a46cf57b043b84Karl Wiberg  return buffer_.empty();
557f6c4d42a2605d1da39af3f957a46cf57b043b84Karl Wiberg}
567f6c4d42a2605d1da39af3f957a46cf57b043b84Karl Wiberg
57d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.orgint PacketBuffer::InsertPacket(Packet* packet) {
58d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org  if (!packet || !packet->payload) {
59d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org    if (packet) {
60d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org      delete packet;
61d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org    }
62d67a219bec0c4cde149014984d5dfe168fe0a346Henrik Lundin    LOG(LS_WARNING) << "InsertPacket invalid packet";
63d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org    return kInvalidPacket;
64d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org  }
65d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org
66d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org  int return_val = kOK;
67d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org
68116ed1d4f0445fdf215cffa2d9d0946a1cdab3ebhenrik.lundin@webrtc.org  if (buffer_.size() >= max_number_of_packets_) {
69d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org    // Buffer is full. Flush it.
70d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org    Flush();
71d67a219bec0c4cde149014984d5dfe168fe0a346Henrik Lundin    LOG(LS_WARNING) << "Packet buffer flushed";
72d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org    return_val = kFlushed;
73d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org  }
74d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org
75d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org  // Get an iterator pointing to the place in the buffer where the new packet
76d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org  // should be inserted. The list is searched from the back, since the most
77d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org  // likely case is that the new packet should be near the end of the list.
78d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org  PacketList::reverse_iterator rit = std::find_if(
79d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org      buffer_.rbegin(), buffer_.rend(),
80d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org      NewTimestampIsLarger(packet));
81c803907d874971faabe790af1604c8ca6d8a1daeminyue@webrtc.org
82c803907d874971faabe790af1604c8ca6d8a1daeminyue@webrtc.org  // The new packet is to be inserted to the right of |rit|. If it has the same
83c803907d874971faabe790af1604c8ca6d8a1daeminyue@webrtc.org  // timestamp as |rit|, which has a higher priority, do not insert the new
84c803907d874971faabe790af1604c8ca6d8a1daeminyue@webrtc.org  // packet to list.
85c803907d874971faabe790af1604c8ca6d8a1daeminyue@webrtc.org  if (rit != buffer_.rend() &&
86c803907d874971faabe790af1604c8ca6d8a1daeminyue@webrtc.org      packet->header.timestamp == (*rit)->header.timestamp) {
87c803907d874971faabe790af1604c8ca6d8a1daeminyue@webrtc.org    delete [] packet->payload;
88c803907d874971faabe790af1604c8ca6d8a1daeminyue@webrtc.org    delete packet;
89c803907d874971faabe790af1604c8ca6d8a1daeminyue@webrtc.org    return return_val;
90c803907d874971faabe790af1604c8ca6d8a1daeminyue@webrtc.org  }
91c803907d874971faabe790af1604c8ca6d8a1daeminyue@webrtc.org
92c803907d874971faabe790af1604c8ca6d8a1daeminyue@webrtc.org  // The new packet is to be inserted to the left of |it|. If it has the same
93c803907d874971faabe790af1604c8ca6d8a1daeminyue@webrtc.org  // timestamp as |it|, which has a lower priority, replace |it| with the new
94c803907d874971faabe790af1604c8ca6d8a1daeminyue@webrtc.org  // packet.
95c803907d874971faabe790af1604c8ca6d8a1daeminyue@webrtc.org  PacketList::iterator it = rit.base();
96c803907d874971faabe790af1604c8ca6d8a1daeminyue@webrtc.org  if (it != buffer_.end() &&
97c803907d874971faabe790af1604c8ca6d8a1daeminyue@webrtc.org      packet->header.timestamp == (*it)->header.timestamp) {
98c803907d874971faabe790af1604c8ca6d8a1daeminyue@webrtc.org    delete [] (*it)->payload;
99c803907d874971faabe790af1604c8ca6d8a1daeminyue@webrtc.org    delete *it;
100c803907d874971faabe790af1604c8ca6d8a1daeminyue@webrtc.org    it = buffer_.erase(it);
101c803907d874971faabe790af1604c8ca6d8a1daeminyue@webrtc.org  }
102c803907d874971faabe790af1604c8ca6d8a1daeminyue@webrtc.org  buffer_.insert(it, packet);  // Insert the packet at that position.
103d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org
104d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org  return return_val;
105d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org}
106d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org
107d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.orgint PacketBuffer::InsertPacketList(PacketList* packet_list,
108d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org                                   const DecoderDatabase& decoder_database,
109d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org                                   uint8_t* current_rtp_payload_type,
110d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org                                   uint8_t* current_cng_rtp_payload_type) {
111d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org  bool flushed = false;
112d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org  while (!packet_list->empty()) {
113d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org    Packet* packet = packet_list->front();
114d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org    if (decoder_database.IsComfortNoise(packet->header.payloadType)) {
115d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org      if (*current_cng_rtp_payload_type != 0xFF &&
116d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org          *current_cng_rtp_payload_type != packet->header.payloadType) {
117d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org        // New CNG payload type implies new codec type.
118d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org        *current_rtp_payload_type = 0xFF;
119d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org        Flush();
120d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org        flushed = true;
121d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org      }
122d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org      *current_cng_rtp_payload_type = packet->header.payloadType;
123d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org    } else if (!decoder_database.IsDtmf(packet->header.payloadType)) {
124d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org      // This must be speech.
125d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org      if (*current_rtp_payload_type != 0xFF &&
126d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org          *current_rtp_payload_type != packet->header.payloadType) {
127d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org        *current_cng_rtp_payload_type = 0xFF;
128d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org        Flush();
129d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org        flushed = true;
130d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org      }
131d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org      *current_rtp_payload_type = packet->header.payloadType;
132d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org    }
133d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org    int return_val = InsertPacket(packet);
134d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org    packet_list->pop_front();
135d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org    if (return_val == kFlushed) {
136d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org      // The buffer flushed, but this is not an error. We can still continue.
137d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org      flushed = true;
138d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org    } else if (return_val != kOK) {
139d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org      // An error occurred. Delete remaining packets in list and return.
140d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org      DeleteAllPackets(packet_list);
141d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org      return return_val;
142d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org    }
143d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org  }
144d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org  return flushed ? kFlushed : kOK;
145d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org}
146d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org
147d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.orgint PacketBuffer::NextTimestamp(uint32_t* next_timestamp) const {
148d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org  if (Empty()) {
149d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org    return kBufferEmpty;
150d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org  }
151d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org  if (!next_timestamp) {
152d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org    return kInvalidPointer;
153d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org  }
154d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org  *next_timestamp = buffer_.front()->header.timestamp;
155d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org  return kOK;
156d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org}
157d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org
158d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.orgint PacketBuffer::NextHigherTimestamp(uint32_t timestamp,
159d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org                                      uint32_t* next_timestamp) const {
160d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org  if (Empty()) {
161d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org    return kBufferEmpty;
162d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org  }
163d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org  if (!next_timestamp) {
164d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org    return kInvalidPointer;
165d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org  }
166d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org  PacketList::const_iterator it;
167d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org  for (it = buffer_.begin(); it != buffer_.end(); ++it) {
168d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org    if ((*it)->header.timestamp >= timestamp) {
169d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org      // Found a packet matching the search.
170d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org      *next_timestamp = (*it)->header.timestamp;
171d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org      return kOK;
172d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org    }
173d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org  }
174d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org  return kNotFound;
175d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org}
176d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org
177d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.orgconst RTPHeader* PacketBuffer::NextRtpHeader() const {
178d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org  if (Empty()) {
179d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org    return NULL;
180d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org  }
181d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org  return const_cast<const RTPHeader*>(&(buffer_.front()->header));
182d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org}
183d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org
184dce40cf804019a9898b6ab8d8262466b697c56e0Peter KastingPacket* PacketBuffer::GetNextPacket(size_t* discard_count) {
185d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org  if (Empty()) {
186d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org    // Buffer is empty.
187d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org    return NULL;
188d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org  }
189d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org
190d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org  Packet* packet = buffer_.front();
191d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org  // Assert that the packet sanity checks in InsertPacket method works.
192d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org  assert(packet && packet->payload);
193d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org  buffer_.pop_front();
194c803907d874971faabe790af1604c8ca6d8a1daeminyue@webrtc.org
195d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org  // Discard other packets with the same timestamp. These are duplicates or
196d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org  // redundant payloads that should not be used.
197dce40cf804019a9898b6ab8d8262466b697c56e0Peter Kasting  size_t discards = 0;
198c803907d874971faabe790af1604c8ca6d8a1daeminyue@webrtc.org
199d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org  while (!Empty() &&
200d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org      buffer_.front()->header.timestamp == packet->header.timestamp) {
201d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org    if (DiscardNextPacket() != kOK) {
202d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org      assert(false);  // Must be ok by design.
203d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org    }
204c803907d874971faabe790af1604c8ca6d8a1daeminyue@webrtc.org    ++discards;
205d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org  }
206c803907d874971faabe790af1604c8ca6d8a1daeminyue@webrtc.org  // The way of inserting packet should not cause any packet discarding here.
207c803907d874971faabe790af1604c8ca6d8a1daeminyue@webrtc.org  // TODO(minyue): remove |discard_count|.
208c803907d874971faabe790af1604c8ca6d8a1daeminyue@webrtc.org  assert(discards == 0);
209c803907d874971faabe790af1604c8ca6d8a1daeminyue@webrtc.org  if (discard_count)
210c803907d874971faabe790af1604c8ca6d8a1daeminyue@webrtc.org    *discard_count = discards;
211c803907d874971faabe790af1604c8ca6d8a1daeminyue@webrtc.org
212d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org  return packet;
213d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org}
214d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org
215d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.orgint PacketBuffer::DiscardNextPacket() {
216d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org  if (Empty()) {
217d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org    return kBufferEmpty;
218d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org  }
219d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org  // Assert that the packet sanity checks in InsertPacket method works.
22012a34247a448fa76ba7e13cef3e8b3561d168909henrik.lundin@webrtc.org  assert(buffer_.front());
22112a34247a448fa76ba7e13cef3e8b3561d168909henrik.lundin@webrtc.org  assert(buffer_.front()->payload);
222d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org  DeleteFirstPacket(&buffer_);
223d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org  return kOK;
224d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org}
225d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org
22652b42cb069a035f10e951195c28cf6d05d1fd91chenrik.lundin@webrtc.orgint PacketBuffer::DiscardOldPackets(uint32_t timestamp_limit,
22752b42cb069a035f10e951195c28cf6d05d1fd91chenrik.lundin@webrtc.org                                    uint32_t horizon_samples) {
22852b42cb069a035f10e951195c28cf6d05d1fd91chenrik.lundin@webrtc.org  while (!Empty() && timestamp_limit != buffer_.front()->header.timestamp &&
22952b42cb069a035f10e951195c28cf6d05d1fd91chenrik.lundin@webrtc.org         IsObsoleteTimestamp(buffer_.front()->header.timestamp,
23052b42cb069a035f10e951195c28cf6d05d1fd91chenrik.lundin@webrtc.org                             timestamp_limit,
23152b42cb069a035f10e951195c28cf6d05d1fd91chenrik.lundin@webrtc.org                             horizon_samples)) {
232d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org    if (DiscardNextPacket() != kOK) {
233d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org      assert(false);  // Must be ok by design.
234d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org    }
235d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org  }
236d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org  return 0;
237d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org}
238d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org
2397f6c4d42a2605d1da39af3f957a46cf57b043b84Karl Wibergint PacketBuffer::DiscardAllOldPackets(uint32_t timestamp_limit) {
2407f6c4d42a2605d1da39af3f957a46cf57b043b84Karl Wiberg  return DiscardOldPackets(timestamp_limit, 0);
2417f6c4d42a2605d1da39af3f957a46cf57b043b84Karl Wiberg}
2427f6c4d42a2605d1da39af3f957a46cf57b043b84Karl Wiberg
243dce40cf804019a9898b6ab8d8262466b697c56e0Peter Kastingsize_t PacketBuffer::NumPacketsInBuffer() const {
244dce40cf804019a9898b6ab8d8262466b697c56e0Peter Kasting  return buffer_.size();
2457f6c4d42a2605d1da39af3f957a46cf57b043b84Karl Wiberg}
2467f6c4d42a2605d1da39af3f957a46cf57b043b84Karl Wiberg
247dce40cf804019a9898b6ab8d8262466b697c56e0Peter Kastingsize_t PacketBuffer::NumSamplesInBuffer(DecoderDatabase* decoder_database,
248dce40cf804019a9898b6ab8d8262466b697c56e0Peter Kasting                                        size_t last_decoded_length) const {
249d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org  PacketList::const_iterator it;
250dce40cf804019a9898b6ab8d8262466b697c56e0Peter Kasting  size_t num_samples = 0;
251dce40cf804019a9898b6ab8d8262466b697c56e0Peter Kasting  size_t last_duration = last_decoded_length;
252d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org  for (it = buffer_.begin(); it != buffer_.end(); ++it) {
253d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org    Packet* packet = (*it);
254d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org    AudioDecoder* decoder =
255d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org        decoder_database->GetDecoder(packet->header.payloadType);
256728d9037c016c01295177fa700fc7927f0bb80bbPeter Kasting    if (decoder && !packet->sync_packet) {
257728d9037c016c01295177fa700fc7927f0bb80bbPeter Kasting      if (!packet->primary) {
2580aa3ee661c11eda7babdd92fd8a3f25c8d7a1fd0minyue@webrtc.org        continue;
259b28bfa7efcffa3800f64ebd6aeb54face45c180dminyue@webrtc.org      }
260728d9037c016c01295177fa700fc7927f0bb80bbPeter Kasting      int duration =
261b297c5a01f88219da26cffe433804963d1b70f0fpkasting          decoder->PacketDuration(packet->payload, packet->payload_length);
262d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org      if (duration >= 0) {
2637b75ac6756a594d81ae88e8f798b0376886b69f5turaj@webrtc.org        last_duration = duration;  // Save the most up-to-date (valid) duration.
264d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org      }
265d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org    }
2667b75ac6756a594d81ae88e8f798b0376886b69f5turaj@webrtc.org    num_samples += last_duration;
267d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org  }
268d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org  return num_samples;
269d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org}
270d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org
271d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.orgvoid PacketBuffer::IncrementWaitingTimes(int inc) {
272d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org  PacketList::iterator it;
273d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org  for (it = buffer_.begin(); it != buffer_.end(); ++it) {
274d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org    (*it)->waiting_time += inc;
275d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org  }
276d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org}
277d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org
278d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.orgbool PacketBuffer::DeleteFirstPacket(PacketList* packet_list) {
279d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org  if (packet_list->empty()) {
280d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org    return false;
281d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org  }
282d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org  Packet* first_packet = packet_list->front();
283d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org  delete [] first_packet->payload;
284d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org  delete first_packet;
285d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org  packet_list->pop_front();
286d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org  return true;
287d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org}
288d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org
289d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.orgvoid PacketBuffer::DeleteAllPackets(PacketList* packet_list) {
290d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org  while (DeleteFirstPacket(packet_list)) {
291d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org    // Continue while the list is not empty.
292d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org  }
293d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org}
294d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org
295116ed1d4f0445fdf215cffa2d9d0946a1cdab3ebhenrik.lundin@webrtc.orgvoid PacketBuffer::BufferStat(int* num_packets, int* max_num_packets) const {
296362a55e7b0852a7be95f0d627321503258152551turaj@webrtc.org  *num_packets = static_cast<int>(buffer_.size());
297362a55e7b0852a7be95f0d627321503258152551turaj@webrtc.org  *max_num_packets = static_cast<int>(max_number_of_packets_);
2987df9706a016aba9c10a117b530bcada9ceaa5ab9turaj@webrtc.org}
2997df9706a016aba9c10a117b530bcada9ceaa5ab9turaj@webrtc.org
300d94659dc279b86376c1a6470dc326fd342caaa93henrik.lundin@webrtc.org}  // namespace webrtc
301