2013-01-29 12:09:21 +00:00
|
|
|
/*
|
|
|
|
|
* Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
|
|
|
|
|
*
|
|
|
|
|
* Use of this source code is governed by a BSD-style license
|
|
|
|
|
* that can be found in the LICENSE file in the root of the source
|
|
|
|
|
* tree. An additional intellectual property rights grant can be found
|
|
|
|
|
* in the file PATENTS. All contributing project authors may
|
|
|
|
|
* be found in the AUTHORS file in the root of the source tree.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
// This is the implementation of the PacketBuffer class. It is mostly based on
|
|
|
|
|
// an STL list. The list is kept sorted at all times so that the next packet to
|
|
|
|
|
// decode is at the beginning of the list.
|
|
|
|
|
|
2017-09-15 06:47:31 +02:00
|
|
|
#include "modules/audio_coding/neteq/packet_buffer.h"
|
2013-01-29 12:09:21 +00:00
|
|
|
|
2018-10-23 12:03:01 +02:00
|
|
|
#include <algorithm>
|
|
|
|
|
#include <list>
|
|
|
|
|
#include <memory>
|
|
|
|
|
#include <type_traits>
|
|
|
|
|
#include <utility>
|
2013-01-29 12:09:21 +00:00
|
|
|
|
2017-09-15 06:47:31 +02:00
|
|
|
#include "api/audio_codecs/audio_decoder.h"
|
2019-10-31 14:38:11 +01:00
|
|
|
#include "api/neteq/tick_timer.h"
|
2017-09-15 06:47:31 +02:00
|
|
|
#include "modules/audio_coding/neteq/decoder_database.h"
|
|
|
|
|
#include "modules/audio_coding/neteq/statistics_calculator.h"
|
2018-10-23 12:03:01 +02:00
|
|
|
#include "rtc_base/checks.h"
|
2020-11-25 11:32:40 +01:00
|
|
|
#include "rtc_base/experiments/struct_parameters_parser.h"
|
2017-09-15 06:47:31 +02:00
|
|
|
#include "rtc_base/logging.h"
|
2019-07-03 16:00:30 +02:00
|
|
|
#include "rtc_base/numerics/safe_conversions.h"
|
2013-01-29 12:09:21 +00:00
|
|
|
|
|
|
|
|
namespace webrtc {
|
2016-09-01 23:19:05 -07:00
|
|
|
namespace {
|
2013-01-29 12:09:21 +00:00
|
|
|
// Predicate used when inserting packets in the buffer list.
|
2021-07-28 20:00:17 +02:00
|
|
|
// Operator() returns true when `packet` goes before `new_packet`.
|
2013-01-29 12:09:21 +00:00
|
|
|
class NewTimestampIsLarger {
|
|
|
|
|
public:
|
2016-10-24 08:25:28 -07:00
|
|
|
explicit NewTimestampIsLarger(const Packet& new_packet)
|
2013-01-29 12:09:21 +00:00
|
|
|
: new_packet_(new_packet) {}
|
2016-10-24 08:25:28 -07:00
|
|
|
bool operator()(const Packet& packet) { return (new_packet_ >= packet); }
|
2013-01-29 12:09:21 +00:00
|
|
|
|
|
|
|
|
private:
|
2016-10-24 08:25:28 -07:00
|
|
|
const Packet& new_packet_;
|
2013-01-29 12:09:21 +00:00
|
|
|
};
|
|
|
|
|
|
2016-09-01 23:19:05 -07:00
|
|
|
} // namespace
|
|
|
|
|
|
2016-04-26 07:45:16 -07:00
|
|
|
PacketBuffer::PacketBuffer(size_t max_number_of_packets,
|
2023-11-07 10:10:47 +01:00
|
|
|
const TickTimer* tick_timer,
|
|
|
|
|
StatisticsCalculator* stats)
|
|
|
|
|
: max_number_of_packets_(max_number_of_packets),
|
|
|
|
|
tick_timer_(tick_timer),
|
|
|
|
|
stats_(stats) {}
|
2013-01-29 12:09:21 +00:00
|
|
|
|
|
|
|
|
// Destructor. All packets in the buffer will be destroyed.
|
|
|
|
|
PacketBuffer::~PacketBuffer() {
|
2020-11-25 11:32:40 +01:00
|
|
|
buffer_.clear();
|
2013-01-29 12:09:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Flush the buffer. All packets in the buffer will be destroyed.
|
2023-11-07 10:10:47 +01:00
|
|
|
void PacketBuffer::Flush() {
|
2020-11-25 11:32:40 +01:00
|
|
|
for (auto& p : buffer_) {
|
2023-11-07 10:10:47 +01:00
|
|
|
LogPacketDiscarded(p.priority.codec_level);
|
2020-11-25 11:32:40 +01:00
|
|
|
}
|
2016-10-24 08:25:28 -07:00
|
|
|
buffer_.clear();
|
2023-11-07 10:10:47 +01:00
|
|
|
stats_->FlushedPacketBuffer();
|
2020-11-25 11:32:40 +01:00
|
|
|
}
|
|
|
|
|
|
2015-04-09 15:44:22 +02:00
|
|
|
bool PacketBuffer::Empty() const {
|
|
|
|
|
return buffer_.empty();
|
|
|
|
|
}
|
|
|
|
|
|
2023-11-07 10:10:47 +01:00
|
|
|
int PacketBuffer::InsertPacket(Packet&& packet) {
|
2016-10-24 08:25:28 -07:00
|
|
|
if (packet.empty()) {
|
2017-11-09 11:09:25 +01:00
|
|
|
RTC_LOG(LS_WARNING) << "InsertPacket invalid packet";
|
2013-01-29 12:09:21 +00:00
|
|
|
return kInvalidPacket;
|
|
|
|
|
}
|
|
|
|
|
|
2016-10-24 08:25:28 -07:00
|
|
|
RTC_DCHECK_GE(packet.priority.codec_level, 0);
|
|
|
|
|
RTC_DCHECK_GE(packet.priority.red_level, 0);
|
2016-09-22 02:06:28 -07:00
|
|
|
|
2013-01-29 12:09:21 +00:00
|
|
|
int return_val = kOK;
|
|
|
|
|
|
2016-10-24 08:25:28 -07:00
|
|
|
packet.waiting_time = tick_timer_->GetNewStopwatch();
|
2016-04-26 07:45:16 -07:00
|
|
|
|
2023-11-02 13:45:35 +01:00
|
|
|
if (buffer_.size() >= max_number_of_packets_) {
|
|
|
|
|
// Buffer is full.
|
2023-11-07 10:10:47 +01:00
|
|
|
Flush();
|
2023-11-02 13:45:35 +01:00
|
|
|
return_val = kFlushed;
|
|
|
|
|
RTC_LOG(LS_WARNING) << "Packet buffer flushed.";
|
2013-01-29 12:09:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Get an iterator pointing to the place in the buffer where the new packet
|
|
|
|
|
// should be inserted. The list is searched from the back, since the most
|
|
|
|
|
// likely case is that the new packet should be near the end of the list.
|
|
|
|
|
PacketList::reverse_iterator rit = std::find_if(
|
|
|
|
|
buffer_.rbegin(), buffer_.rend(), NewTimestampIsLarger(packet));
|
2014-10-09 10:49:54 +00:00
|
|
|
|
2021-07-28 20:00:17 +02:00
|
|
|
// The new packet is to be inserted to the right of `rit`. If it has the same
|
|
|
|
|
// timestamp as `rit`, which has a higher priority, do not insert the new
|
2014-10-09 10:49:54 +00:00
|
|
|
// packet to list.
|
2016-10-24 08:25:28 -07:00
|
|
|
if (rit != buffer_.rend() && packet.timestamp == rit->timestamp) {
|
2023-11-07 10:10:47 +01:00
|
|
|
LogPacketDiscarded(packet.priority.codec_level);
|
2014-10-09 10:49:54 +00:00
|
|
|
return return_val;
|
|
|
|
|
}
|
|
|
|
|
|
2021-07-28 20:00:17 +02:00
|
|
|
// The new packet is to be inserted to the left of `it`. If it has the same
|
|
|
|
|
// timestamp as `it`, which has a lower priority, replace `it` with the new
|
2014-10-09 10:49:54 +00:00
|
|
|
// packet.
|
|
|
|
|
PacketList::iterator it = rit.base();
|
2016-10-24 08:25:28 -07:00
|
|
|
if (it != buffer_.end() && packet.timestamp == it->timestamp) {
|
2023-11-07 10:10:47 +01:00
|
|
|
LogPacketDiscarded(it->priority.codec_level);
|
2014-10-09 10:49:54 +00:00
|
|
|
it = buffer_.erase(it);
|
|
|
|
|
}
|
2016-10-24 08:25:28 -07:00
|
|
|
buffer_.insert(it, std::move(packet)); // Insert the packet at that position.
|
2013-01-29 12:09:21 +00:00
|
|
|
|
|
|
|
|
return return_val;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int PacketBuffer::NextTimestamp(uint32_t* next_timestamp) const {
|
|
|
|
|
if (Empty()) {
|
|
|
|
|
return kBufferEmpty;
|
|
|
|
|
}
|
|
|
|
|
if (!next_timestamp) {
|
|
|
|
|
return kInvalidPointer;
|
|
|
|
|
}
|
2016-10-24 08:25:28 -07:00
|
|
|
*next_timestamp = buffer_.front().timestamp;
|
2013-01-29 12:09:21 +00:00
|
|
|
return kOK;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int PacketBuffer::NextHigherTimestamp(uint32_t timestamp,
|
|
|
|
|
uint32_t* next_timestamp) const {
|
|
|
|
|
if (Empty()) {
|
|
|
|
|
return kBufferEmpty;
|
|
|
|
|
}
|
|
|
|
|
if (!next_timestamp) {
|
|
|
|
|
return kInvalidPointer;
|
|
|
|
|
}
|
|
|
|
|
PacketList::const_iterator it;
|
|
|
|
|
for (it = buffer_.begin(); it != buffer_.end(); ++it) {
|
2016-10-24 08:25:28 -07:00
|
|
|
if (it->timestamp >= timestamp) {
|
2013-01-29 12:09:21 +00:00
|
|
|
// Found a packet matching the search.
|
2016-10-24 08:25:28 -07:00
|
|
|
*next_timestamp = it->timestamp;
|
2013-01-29 12:09:21 +00:00
|
|
|
return kOK;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return kNotFound;
|
|
|
|
|
}
|
|
|
|
|
|
2016-10-18 04:06:13 -07:00
|
|
|
const Packet* PacketBuffer::PeekNextPacket() const {
|
2016-10-24 08:25:28 -07:00
|
|
|
return buffer_.empty() ? nullptr : &buffer_.front();
|
2013-01-29 12:09:21 +00:00
|
|
|
}
|
|
|
|
|
|
2018-06-19 13:26:36 +02:00
|
|
|
absl::optional<Packet> PacketBuffer::GetNextPacket() {
|
2013-01-29 12:09:21 +00:00
|
|
|
if (Empty()) {
|
|
|
|
|
// Buffer is empty.
|
2018-06-19 13:26:36 +02:00
|
|
|
return absl::nullopt;
|
2013-01-29 12:09:21 +00:00
|
|
|
}
|
|
|
|
|
|
2018-06-19 13:26:36 +02:00
|
|
|
absl::optional<Packet> packet(std::move(buffer_.front()));
|
2013-01-29 12:09:21 +00:00
|
|
|
// Assert that the packet sanity checks in InsertPacket method works.
|
2016-10-24 08:25:28 -07:00
|
|
|
RTC_DCHECK(!packet->empty());
|
2013-01-29 12:09:21 +00:00
|
|
|
buffer_.pop_front();
|
2014-10-09 10:49:54 +00:00
|
|
|
|
2013-01-29 12:09:21 +00:00
|
|
|
return packet;
|
|
|
|
|
}
|
|
|
|
|
|
2023-11-07 10:10:47 +01:00
|
|
|
int PacketBuffer::DiscardNextPacket() {
|
2013-01-29 12:09:21 +00:00
|
|
|
if (Empty()) {
|
|
|
|
|
return kBufferEmpty;
|
|
|
|
|
}
|
|
|
|
|
// Assert that the packet sanity checks in InsertPacket method works.
|
2017-08-23 15:59:38 +02:00
|
|
|
const Packet& packet = buffer_.front();
|
|
|
|
|
RTC_DCHECK(!packet.empty());
|
2023-11-07 10:10:47 +01:00
|
|
|
LogPacketDiscarded(packet.priority.codec_level);
|
2016-10-24 08:25:28 -07:00
|
|
|
buffer_.pop_front();
|
2013-01-29 12:09:21 +00:00
|
|
|
return kOK;
|
|
|
|
|
}
|
|
|
|
|
|
2017-07-05 11:17:40 +02:00
|
|
|
void PacketBuffer::DiscardOldPackets(uint32_t timestamp_limit,
|
2023-11-07 10:10:47 +01:00
|
|
|
uint32_t horizon_samples) {
|
|
|
|
|
buffer_.remove_if([this, timestamp_limit, horizon_samples](const Packet& p) {
|
2017-08-23 15:59:38 +02:00
|
|
|
if (timestamp_limit == p.timestamp ||
|
|
|
|
|
!IsObsoleteTimestamp(p.timestamp, timestamp_limit, horizon_samples)) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
2023-11-07 10:10:47 +01:00
|
|
|
LogPacketDiscarded(p.priority.codec_level);
|
2017-08-23 15:59:38 +02:00
|
|
|
return true;
|
2017-07-05 07:03:34 -07:00
|
|
|
});
|
2013-01-29 12:09:21 +00:00
|
|
|
}
|
|
|
|
|
|
2023-11-07 10:10:47 +01:00
|
|
|
void PacketBuffer::DiscardAllOldPackets(uint32_t timestamp_limit) {
|
|
|
|
|
DiscardOldPackets(timestamp_limit, 0);
|
2015-04-09 15:44:22 +02:00
|
|
|
}
|
|
|
|
|
|
2023-11-07 10:10:47 +01:00
|
|
|
void PacketBuffer::DiscardPacketsWithPayloadType(uint8_t payload_type) {
|
|
|
|
|
buffer_.remove_if([this, payload_type](const Packet& p) {
|
2017-08-23 15:59:38 +02:00
|
|
|
if (p.payload_type != payload_type) {
|
|
|
|
|
return false;
|
2016-09-20 01:38:00 -07:00
|
|
|
}
|
2023-11-07 10:10:47 +01:00
|
|
|
LogPacketDiscarded(p.priority.codec_level);
|
2017-08-23 15:59:38 +02:00
|
|
|
return true;
|
|
|
|
|
});
|
2016-09-20 01:38:00 -07:00
|
|
|
}
|
|
|
|
|
|
Update a ton of audio code to use size_t more correctly and in general reduce
use of int16_t/uint16_t.
This is the upshot of a recommendation by henrik.lundin and kwiberg on an original small change ( https://webrtc-codereview.appspot.com/42569004/#ps1 ) to stop using int16_t just because values could fit in it, and is similar in nature to a previous "mass change to use size_t more" ( https://webrtc-codereview.appspot.com/23129004/ ) which also needed to be split up for review but to land all at once, since, like adding "const", such changes tend to cause a lot of transitive effects.
This was be reviewed and approved in pieces:
https://codereview.webrtc.org/1224093003
https://codereview.webrtc.org/1224123002
https://codereview.webrtc.org/1224163002
https://codereview.webrtc.org/1225133003
https://codereview.webrtc.org/1225173002
https://codereview.webrtc.org/1227163003
https://codereview.webrtc.org/1227203003
https://codereview.webrtc.org/1227213002
https://codereview.webrtc.org/1227893002
https://codereview.webrtc.org/1228793004
https://codereview.webrtc.org/1228803003
https://codereview.webrtc.org/1228823002
https://codereview.webrtc.org/1228823003
https://codereview.webrtc.org/1228843002
https://codereview.webrtc.org/1230693002
https://codereview.webrtc.org/1231713002
The change is being landed as TBR to all the folks who reviewed the above.
BUG=chromium:81439
TEST=none
R=andrew@webrtc.org, pbos@webrtc.org
TBR=aluebs, andrew, asapersson, henrika, hlundin, jan.skoglund, kwiberg, minyue, pbos, pthatcher
Review URL: https://codereview.webrtc.org/1230503003 .
Cr-Commit-Position: refs/heads/master@{#9768}
2015-08-24 14:52:23 -07:00
|
|
|
size_t PacketBuffer::NumPacketsInBuffer() const {
|
|
|
|
|
return buffer_.size();
|
2015-04-09 15:44:22 +02:00
|
|
|
}
|
|
|
|
|
|
2016-09-20 01:38:00 -07:00
|
|
|
size_t PacketBuffer::NumSamplesInBuffer(size_t last_decoded_length) const {
|
Update a ton of audio code to use size_t more correctly and in general reduce
use of int16_t/uint16_t.
This is the upshot of a recommendation by henrik.lundin and kwiberg on an original small change ( https://webrtc-codereview.appspot.com/42569004/#ps1 ) to stop using int16_t just because values could fit in it, and is similar in nature to a previous "mass change to use size_t more" ( https://webrtc-codereview.appspot.com/23129004/ ) which also needed to be split up for review but to land all at once, since, like adding "const", such changes tend to cause a lot of transitive effects.
This was be reviewed and approved in pieces:
https://codereview.webrtc.org/1224093003
https://codereview.webrtc.org/1224123002
https://codereview.webrtc.org/1224163002
https://codereview.webrtc.org/1225133003
https://codereview.webrtc.org/1225173002
https://codereview.webrtc.org/1227163003
https://codereview.webrtc.org/1227203003
https://codereview.webrtc.org/1227213002
https://codereview.webrtc.org/1227893002
https://codereview.webrtc.org/1228793004
https://codereview.webrtc.org/1228803003
https://codereview.webrtc.org/1228823002
https://codereview.webrtc.org/1228823003
https://codereview.webrtc.org/1228843002
https://codereview.webrtc.org/1230693002
https://codereview.webrtc.org/1231713002
The change is being landed as TBR to all the folks who reviewed the above.
BUG=chromium:81439
TEST=none
R=andrew@webrtc.org, pbos@webrtc.org
TBR=aluebs, andrew, asapersson, henrika, hlundin, jan.skoglund, kwiberg, minyue, pbos, pthatcher
Review URL: https://codereview.webrtc.org/1230503003 .
Cr-Commit-Position: refs/heads/master@{#9768}
2015-08-24 14:52:23 -07:00
|
|
|
size_t num_samples = 0;
|
|
|
|
|
size_t last_duration = last_decoded_length;
|
2016-10-24 08:25:28 -07:00
|
|
|
for (const Packet& packet : buffer_) {
|
|
|
|
|
if (packet.frame) {
|
2016-09-22 02:06:28 -07:00
|
|
|
// TODO(hlundin): Verify that it's fine to count all packets and remove
|
|
|
|
|
// this check.
|
2016-10-24 08:25:28 -07:00
|
|
|
if (packet.priority != Packet::Priority(0, 0)) {
|
2014-05-28 07:48:01 +00:00
|
|
|
continue;
|
2014-03-21 12:07:40 +00:00
|
|
|
}
|
2016-10-24 08:25:28 -07:00
|
|
|
size_t duration = packet.frame->Duration();
|
2016-09-20 01:38:00 -07:00
|
|
|
if (duration > 0) {
|
2013-09-26 00:27:56 +00:00
|
|
|
last_duration = duration; // Save the most up-to-date (valid) duration.
|
2013-01-29 12:09:21 +00:00
|
|
|
}
|
|
|
|
|
}
|
2013-09-26 00:27:56 +00:00
|
|
|
num_samples += last_duration;
|
2013-01-29 12:09:21 +00:00
|
|
|
}
|
|
|
|
|
return num_samples;
|
|
|
|
|
}
|
|
|
|
|
|
2019-07-03 16:00:30 +02:00
|
|
|
size_t PacketBuffer::GetSpanSamples(size_t last_decoded_length,
|
|
|
|
|
size_t sample_rate,
|
2023-03-23 21:51:27 +01:00
|
|
|
bool count_waiting_time) const {
|
2019-03-12 15:12:08 +01:00
|
|
|
if (buffer_.size() == 0) {
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
size_t span = buffer_.back().timestamp - buffer_.front().timestamp;
|
2023-03-23 21:51:27 +01:00
|
|
|
size_t waiting_time_samples = rtc::dchecked_cast<size_t>(
|
|
|
|
|
buffer_.back().waiting_time->ElapsedMs() * (sample_rate / 1000));
|
|
|
|
|
if (count_waiting_time) {
|
|
|
|
|
span += waiting_time_samples;
|
|
|
|
|
} else if (buffer_.back().frame && buffer_.back().frame->Duration() > 0) {
|
2019-07-03 16:00:30 +02:00
|
|
|
size_t duration = buffer_.back().frame->Duration();
|
2023-03-23 21:51:27 +01:00
|
|
|
if (buffer_.back().frame->IsDtxPacket()) {
|
2019-07-03 16:00:30 +02:00
|
|
|
duration = std::max(duration, waiting_time_samples);
|
|
|
|
|
}
|
|
|
|
|
span += duration;
|
2019-03-12 15:12:08 +01:00
|
|
|
} else {
|
|
|
|
|
span += last_decoded_length;
|
|
|
|
|
}
|
|
|
|
|
return span;
|
|
|
|
|
}
|
|
|
|
|
|
2018-05-22 13:21:01 +02:00
|
|
|
bool PacketBuffer::ContainsDtxOrCngPacket(
|
|
|
|
|
const DecoderDatabase* decoder_database) const {
|
|
|
|
|
RTC_DCHECK(decoder_database);
|
|
|
|
|
for (const Packet& packet : buffer_) {
|
|
|
|
|
if ((packet.frame && packet.frame->IsDtxPacket()) ||
|
|
|
|
|
decoder_database->IsComfortNoise(packet.payload_type)) {
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2023-11-07 10:10:47 +01:00
|
|
|
void PacketBuffer::LogPacketDiscarded(int codec_level) {
|
|
|
|
|
if (codec_level > 0) {
|
|
|
|
|
stats_->SecondaryPacketsDiscarded(1);
|
|
|
|
|
} else {
|
|
|
|
|
stats_->PacketsDiscarded(1);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2013-01-29 12:09:21 +00:00
|
|
|
} // namespace webrtc
|