Line data Source code
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 : #include "webrtc/modules/audio_coding/neteq/tick_timer.h"
23 :
24 : namespace webrtc {
25 : namespace {
26 : // Predicate used when inserting packets in the buffer list.
27 : // Operator() returns true when |packet| goes before |new_packet|.
28 : class NewTimestampIsLarger {
29 : public:
30 0 : explicit NewTimestampIsLarger(const Packet& new_packet)
31 0 : : new_packet_(new_packet) {
32 0 : }
33 0 : bool operator()(const Packet& packet) {
34 0 : return (new_packet_ >= packet);
35 : }
36 :
37 : private:
38 : const Packet& new_packet_;
39 : };
40 :
41 : // Returns true if both payload types are known to the decoder database, and
42 : // have the same sample rate.
43 0 : bool EqualSampleRates(uint8_t pt1,
44 : uint8_t pt2,
45 : const DecoderDatabase& decoder_database) {
46 0 : auto di1 = decoder_database.GetDecoderInfo(pt1);
47 0 : auto di2 = decoder_database.GetDecoderInfo(pt2);
48 0 : return di1 && di2 && di1->SampleRateHz() == di2->SampleRateHz();
49 : }
50 : } // namespace
51 :
52 0 : PacketBuffer::PacketBuffer(size_t max_number_of_packets,
53 0 : const TickTimer* tick_timer)
54 0 : : max_number_of_packets_(max_number_of_packets), tick_timer_(tick_timer) {}
55 :
56 : // Destructor. All packets in the buffer will be destroyed.
57 0 : PacketBuffer::~PacketBuffer() {
58 0 : Flush();
59 0 : }
60 :
61 : // Flush the buffer. All packets in the buffer will be destroyed.
62 0 : void PacketBuffer::Flush() {
63 0 : buffer_.clear();
64 0 : }
65 :
66 0 : bool PacketBuffer::Empty() const {
67 0 : return buffer_.empty();
68 : }
69 :
70 0 : int PacketBuffer::InsertPacket(Packet&& packet) {
71 0 : if (packet.empty()) {
72 0 : LOG(LS_WARNING) << "InsertPacket invalid packet";
73 0 : return kInvalidPacket;
74 : }
75 :
76 0 : RTC_DCHECK_GE(packet.priority.codec_level, 0);
77 0 : RTC_DCHECK_GE(packet.priority.red_level, 0);
78 :
79 0 : int return_val = kOK;
80 :
81 0 : packet.waiting_time = tick_timer_->GetNewStopwatch();
82 :
83 0 : if (buffer_.size() >= max_number_of_packets_) {
84 : // Buffer is full. Flush it.
85 0 : Flush();
86 0 : LOG(LS_WARNING) << "Packet buffer flushed";
87 0 : return_val = kFlushed;
88 : }
89 :
90 : // Get an iterator pointing to the place in the buffer where the new packet
91 : // should be inserted. The list is searched from the back, since the most
92 : // likely case is that the new packet should be near the end of the list.
93 : PacketList::reverse_iterator rit = std::find_if(
94 0 : buffer_.rbegin(), buffer_.rend(),
95 0 : NewTimestampIsLarger(packet));
96 :
97 : // The new packet is to be inserted to the right of |rit|. If it has the same
98 : // timestamp as |rit|, which has a higher priority, do not insert the new
99 : // packet to list.
100 0 : if (rit != buffer_.rend() && packet.timestamp == rit->timestamp) {
101 0 : return return_val;
102 : }
103 :
104 : // The new packet is to be inserted to the left of |it|. If it has the same
105 : // timestamp as |it|, which has a lower priority, replace |it| with the new
106 : // packet.
107 0 : PacketList::iterator it = rit.base();
108 0 : if (it != buffer_.end() && packet.timestamp == it->timestamp) {
109 0 : it = buffer_.erase(it);
110 : }
111 0 : buffer_.insert(it, std::move(packet)); // Insert the packet at that position.
112 :
113 0 : return return_val;
114 : }
115 :
116 0 : int PacketBuffer::InsertPacketList(
117 : PacketList* packet_list,
118 : const DecoderDatabase& decoder_database,
119 : rtc::Optional<uint8_t>* current_rtp_payload_type,
120 : rtc::Optional<uint8_t>* current_cng_rtp_payload_type) {
121 0 : bool flushed = false;
122 0 : for (auto& packet : *packet_list) {
123 0 : if (decoder_database.IsComfortNoise(packet.payload_type)) {
124 0 : if (*current_cng_rtp_payload_type &&
125 0 : **current_cng_rtp_payload_type != packet.payload_type) {
126 : // New CNG payload type implies new codec type.
127 0 : *current_rtp_payload_type = rtc::Optional<uint8_t>();
128 0 : Flush();
129 0 : flushed = true;
130 : }
131 : *current_cng_rtp_payload_type =
132 0 : rtc::Optional<uint8_t>(packet.payload_type);
133 0 : } else if (!decoder_database.IsDtmf(packet.payload_type)) {
134 : // This must be speech.
135 0 : if ((*current_rtp_payload_type &&
136 0 : **current_rtp_payload_type != packet.payload_type) ||
137 0 : (*current_cng_rtp_payload_type &&
138 0 : !EqualSampleRates(packet.payload_type,
139 0 : **current_cng_rtp_payload_type,
140 0 : decoder_database))) {
141 0 : *current_cng_rtp_payload_type = rtc::Optional<uint8_t>();
142 0 : Flush();
143 0 : flushed = true;
144 : }
145 0 : *current_rtp_payload_type = rtc::Optional<uint8_t>(packet.payload_type);
146 : }
147 0 : int return_val = InsertPacket(std::move(packet));
148 0 : if (return_val == kFlushed) {
149 : // The buffer flushed, but this is not an error. We can still continue.
150 0 : flushed = true;
151 0 : } else if (return_val != kOK) {
152 : // An error occurred. Delete remaining packets in list and return.
153 0 : packet_list->clear();
154 0 : return return_val;
155 : }
156 : }
157 0 : packet_list->clear();
158 0 : return flushed ? kFlushed : kOK;
159 : }
160 :
161 0 : int PacketBuffer::NextTimestamp(uint32_t* next_timestamp) const {
162 0 : if (Empty()) {
163 0 : return kBufferEmpty;
164 : }
165 0 : if (!next_timestamp) {
166 0 : return kInvalidPointer;
167 : }
168 0 : *next_timestamp = buffer_.front().timestamp;
169 0 : return kOK;
170 : }
171 :
172 0 : int PacketBuffer::NextHigherTimestamp(uint32_t timestamp,
173 : uint32_t* next_timestamp) const {
174 0 : if (Empty()) {
175 0 : return kBufferEmpty;
176 : }
177 0 : if (!next_timestamp) {
178 0 : return kInvalidPointer;
179 : }
180 0 : PacketList::const_iterator it;
181 0 : for (it = buffer_.begin(); it != buffer_.end(); ++it) {
182 0 : if (it->timestamp >= timestamp) {
183 : // Found a packet matching the search.
184 0 : *next_timestamp = it->timestamp;
185 0 : return kOK;
186 : }
187 : }
188 0 : return kNotFound;
189 : }
190 :
191 0 : const Packet* PacketBuffer::PeekNextPacket() const {
192 0 : return buffer_.empty() ? nullptr : &buffer_.front();
193 : }
194 :
195 0 : rtc::Optional<Packet> PacketBuffer::GetNextPacket() {
196 0 : if (Empty()) {
197 : // Buffer is empty.
198 0 : return rtc::Optional<Packet>();
199 : }
200 :
201 0 : rtc::Optional<Packet> packet(std::move(buffer_.front()));
202 : // Assert that the packet sanity checks in InsertPacket method works.
203 0 : RTC_DCHECK(!packet->empty());
204 0 : buffer_.pop_front();
205 :
206 0 : return packet;
207 : }
208 :
209 0 : int PacketBuffer::DiscardNextPacket() {
210 0 : if (Empty()) {
211 0 : return kBufferEmpty;
212 : }
213 : // Assert that the packet sanity checks in InsertPacket method works.
214 0 : RTC_DCHECK(!buffer_.front().empty());
215 0 : buffer_.pop_front();
216 0 : return kOK;
217 : }
218 :
219 0 : int PacketBuffer::DiscardOldPackets(uint32_t timestamp_limit,
220 : uint32_t horizon_samples) {
221 0 : while (!Empty() && timestamp_limit != buffer_.front().timestamp &&
222 0 : IsObsoleteTimestamp(buffer_.front().timestamp, timestamp_limit,
223 : horizon_samples)) {
224 0 : if (DiscardNextPacket() != kOK) {
225 0 : assert(false); // Must be ok by design.
226 : }
227 : }
228 0 : return 0;
229 : }
230 :
231 0 : int PacketBuffer::DiscardAllOldPackets(uint32_t timestamp_limit) {
232 0 : return DiscardOldPackets(timestamp_limit, 0);
233 : }
234 :
235 0 : void PacketBuffer::DiscardPacketsWithPayloadType(uint8_t payload_type) {
236 0 : for (auto it = buffer_.begin(); it != buffer_.end(); /* */) {
237 0 : const Packet& packet = *it;
238 0 : if (packet.payload_type == payload_type) {
239 0 : it = buffer_.erase(it);
240 : } else {
241 0 : ++it;
242 : }
243 : }
244 0 : }
245 :
246 0 : size_t PacketBuffer::NumPacketsInBuffer() const {
247 0 : return buffer_.size();
248 : }
249 :
250 0 : size_t PacketBuffer::NumSamplesInBuffer(size_t last_decoded_length) const {
251 0 : size_t num_samples = 0;
252 0 : size_t last_duration = last_decoded_length;
253 0 : for (const Packet& packet : buffer_) {
254 0 : if (packet.frame) {
255 : // TODO(hlundin): Verify that it's fine to count all packets and remove
256 : // this check.
257 0 : if (packet.priority != Packet::Priority(0, 0)) {
258 0 : continue;
259 : }
260 0 : size_t duration = packet.frame->Duration();
261 0 : if (duration > 0) {
262 0 : last_duration = duration; // Save the most up-to-date (valid) duration.
263 : }
264 : }
265 0 : num_samples += last_duration;
266 : }
267 0 : return num_samples;
268 : }
269 :
270 0 : void PacketBuffer::BufferStat(int* num_packets, int* max_num_packets) const {
271 0 : *num_packets = static_cast<int>(buffer_.size());
272 0 : *max_num_packets = static_cast<int>(max_number_of_packets_);
273 0 : }
274 :
275 : } // namespace webrtc
|