mirror of
https://github.com/mollyim/webrtc.git
synced 2025-05-13 05:40:42 +01:00
Unifying the handling of the events in NetEqInput.
Bug: webrtc:14763 Change-Id: I9615a9ce41c9b577c4ebd4cdcc9885bfbc5dac48 Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/293040 Reviewed-by: Sam Zackrisson <saza@webrtc.org> Commit-Queue: Jesus de Vicente Pena <devicentepena@webrtc.org> Reviewed-by: Björn Terelius <terelius@webrtc.org> Reviewed-by: Jakob Ivarsson <jakobi@webrtc.org> Cr-Commit-Position: refs/heads/main@{#39706}
This commit is contained in:
parent
58b049373e
commit
d93b7b91e0
22 changed files with 484 additions and 492 deletions
|
@ -119,34 +119,26 @@ class LossyInput : public NetEqInput {
|
|||
burst_length_(burst_length),
|
||||
input_(std::move(input)) {}
|
||||
|
||||
absl::optional<int64_t> NextPacketTime() const override {
|
||||
return input_->NextPacketTime();
|
||||
absl::optional<int64_t> NextEventTime() const {
|
||||
return input_->NextEventTime();
|
||||
}
|
||||
|
||||
absl::optional<int64_t> NextOutputEventTime() const override {
|
||||
return input_->NextOutputEventTime();
|
||||
std::unique_ptr<Event> PopEvent() override {
|
||||
std::unique_ptr<Event> event = input_->PopEvent();
|
||||
if (event == nullptr || event->type() != Event::Type::kPacketData) {
|
||||
return event;
|
||||
}
|
||||
|
||||
absl::optional<SetMinimumDelayInfo> NextSetMinimumDelayInfo() const override {
|
||||
return input_->NextSetMinimumDelayInfo();
|
||||
}
|
||||
|
||||
std::unique_ptr<PacketData> PopPacket() override {
|
||||
if (loss_cadence_ != 0 && (++count_ % loss_cadence_) == 0) {
|
||||
if (loss_cadence_ != 0 && remaining_losses_ == 0 &&
|
||||
(++count_ % loss_cadence_) == 0) {
|
||||
// Pop `burst_length_` packets to create the loss.
|
||||
auto packet_to_return = input_->PopPacket();
|
||||
for (int i = 0; i < burst_length_; i++) {
|
||||
input_->PopPacket();
|
||||
remaining_losses_ = burst_length_;
|
||||
} else {
|
||||
if (remaining_losses_ != 0) {
|
||||
remaining_losses_--;
|
||||
return PopEvent();
|
||||
}
|
||||
return packet_to_return;
|
||||
}
|
||||
return input_->PopPacket();
|
||||
}
|
||||
|
||||
void AdvanceOutputEvent() override { return input_->AdvanceOutputEvent(); }
|
||||
|
||||
void AdvanceSetMinimumDelay() override {
|
||||
return input_->AdvanceSetMinimumDelay();
|
||||
return event;
|
||||
}
|
||||
|
||||
bool ended() const override { return input_->ended(); }
|
||||
|
@ -158,6 +150,7 @@ class LossyInput : public NetEqInput {
|
|||
private:
|
||||
const int loss_cadence_;
|
||||
const int burst_length_;
|
||||
int remaining_losses_ = 0;
|
||||
int count_ = 0;
|
||||
const std::unique_ptr<NetEqInput> input_;
|
||||
};
|
||||
|
|
|
@ -988,9 +988,9 @@ TEST(NetEqNoTimeStretchingMode, RunTest) {
|
|||
{5, kRtpExtensionTransportSequenceNumber},
|
||||
{7, kRtpExtensionVideoContentType},
|
||||
{8, kRtpExtensionVideoTiming}};
|
||||
std::unique_ptr<NetEqInput> input(new NetEqRtpDumpInput(
|
||||
std::unique_ptr<NetEqInput> input = std::make_unique<NetEqPacketSourceInput>(
|
||||
webrtc::test::ResourcePath("audio_coding/neteq_universal_new", "rtp"),
|
||||
rtp_ext_map, absl::nullopt /*No SSRC filter*/));
|
||||
rtp_ext_map, absl::nullopt /*No SSRC filter*/);
|
||||
std::unique_ptr<TimeLimitedNetEqInput> input_time_limit(
|
||||
new TimeLimitedNetEqInput(std::move(input), 20000));
|
||||
std::unique_ptr<AudioSink> output(new VoidAudioSink);
|
||||
|
|
|
@ -24,36 +24,19 @@ EncodeNetEqInput::EncodeNetEqInput(std::unique_ptr<Generator> generator,
|
|||
: generator_(std::move(generator)),
|
||||
encoder_(std::move(encoder)),
|
||||
input_duration_ms_(input_duration_ms) {
|
||||
CreatePacket();
|
||||
event_ = GetNextEvent();
|
||||
}
|
||||
|
||||
EncodeNetEqInput::~EncodeNetEqInput() = default;
|
||||
|
||||
absl::optional<int64_t> EncodeNetEqInput::NextPacketTime() const {
|
||||
RTC_DCHECK(packet_data_);
|
||||
return static_cast<int64_t>(packet_data_->time_ms);
|
||||
}
|
||||
|
||||
absl::optional<int64_t> EncodeNetEqInput::NextOutputEventTime() const {
|
||||
return next_output_event_ms_;
|
||||
}
|
||||
|
||||
std::unique_ptr<NetEqInput::PacketData> EncodeNetEqInput::PopPacket() {
|
||||
RTC_DCHECK(packet_data_);
|
||||
// Grab the packet to return...
|
||||
std::unique_ptr<PacketData> packet_to_return = std::move(packet_data_);
|
||||
// ... and line up the next packet for future use.
|
||||
CreatePacket();
|
||||
|
||||
return packet_to_return;
|
||||
}
|
||||
|
||||
void EncodeNetEqInput::AdvanceOutputEvent() {
|
||||
next_output_event_ms_ += kOutputPeriodMs;
|
||||
std::unique_ptr<NetEqInput::Event> EncodeNetEqInput::PopEvent() {
|
||||
std::unique_ptr<NetEqInput::Event> event_to_return = std::move(event_);
|
||||
event_ = GetNextEvent();
|
||||
return event_to_return;
|
||||
}
|
||||
|
||||
bool EncodeNetEqInput::ended() const {
|
||||
return next_output_event_ms_ > input_duration_ms_;
|
||||
return next_output_event_ms_ > input_duration_ms_ + kOutputPeriodMs;
|
||||
}
|
||||
|
||||
absl::optional<RTPHeader> EncodeNetEqInput::NextHeader() const {
|
||||
|
@ -61,9 +44,23 @@ absl::optional<RTPHeader> EncodeNetEqInput::NextHeader() const {
|
|||
return packet_data_->header;
|
||||
}
|
||||
|
||||
std::unique_ptr<NetEqInput::Event> EncodeNetEqInput::GetNextEvent() {
|
||||
std::unique_ptr<NetEqInput::Event> event;
|
||||
if (packet_data_ == nullptr) {
|
||||
CreatePacket();
|
||||
}
|
||||
if (next_output_event_ms_ < packet_data_->timestamp_ms_) {
|
||||
event = std::make_unique<GetAudio>(next_output_event_ms_);
|
||||
next_output_event_ms_ += kOutputPeriodMs;
|
||||
return event;
|
||||
}
|
||||
event = std::move(packet_data_);
|
||||
CreatePacket();
|
||||
return event;
|
||||
}
|
||||
|
||||
void EncodeNetEqInput::CreatePacket() {
|
||||
// Create a new PacketData object.
|
||||
RTC_DCHECK(!packet_data_);
|
||||
packet_data_.reset(new NetEqInput::PacketData);
|
||||
RTC_DCHECK_EQ(packet_data_->payload.size(), 0);
|
||||
|
||||
|
@ -86,7 +83,7 @@ void EncodeNetEqInput::CreatePacket() {
|
|||
packet_data_->header.timestamp = info.encoded_timestamp;
|
||||
packet_data_->header.payloadType = info.payload_type;
|
||||
packet_data_->header.sequenceNumber = sequence_number_++;
|
||||
packet_data_->time_ms = next_packet_time_ms_;
|
||||
packet_data_->timestamp_ms_ = next_packet_time_ms_;
|
||||
next_packet_time_ms_ += num_blocks * kOutputPeriodMs;
|
||||
}
|
||||
|
||||
|
|
|
@ -37,28 +37,24 @@ class EncodeNetEqInput : public NetEqInput {
|
|||
int64_t input_duration_ms);
|
||||
~EncodeNetEqInput() override;
|
||||
|
||||
absl::optional<int64_t> NextPacketTime() const override;
|
||||
|
||||
absl::optional<int64_t> NextOutputEventTime() const override;
|
||||
|
||||
absl::optional<SetMinimumDelayInfo> NextSetMinimumDelayInfo() const override {
|
||||
return absl::nullopt;
|
||||
}
|
||||
|
||||
std::unique_ptr<PacketData> PopPacket() override;
|
||||
|
||||
void AdvanceOutputEvent() override;
|
||||
|
||||
void AdvanceSetMinimumDelay() override {}
|
||||
std::unique_ptr<Event> PopEvent() override;
|
||||
|
||||
bool ended() const override;
|
||||
|
||||
absl::optional<RTPHeader> NextHeader() const override;
|
||||
|
||||
absl::optional<int64_t> NextEventTime() const override {
|
||||
if (event_) {
|
||||
return event_->timestamp_ms();
|
||||
}
|
||||
return absl::nullopt;
|
||||
}
|
||||
|
||||
private:
|
||||
static constexpr int64_t kOutputPeriodMs = 10;
|
||||
|
||||
void CreatePacket();
|
||||
std::unique_ptr<Event> GetNextEvent();
|
||||
|
||||
std::unique_ptr<Generator> generator_;
|
||||
std::unique_ptr<AudioEncoder> encoder_;
|
||||
|
@ -68,6 +64,7 @@ class EncodeNetEqInput : public NetEqInput {
|
|||
int64_t next_packet_time_ms_ = 0;
|
||||
int64_t next_output_event_ms_ = 0;
|
||||
const int64_t input_duration_ms_;
|
||||
std::unique_ptr<Event> event_;
|
||||
};
|
||||
|
||||
} // namespace test
|
||||
|
|
|
@ -27,37 +27,27 @@ InitialPacketInserterNetEqInput::InitialPacketInserterNetEqInput(
|
|||
packets_to_insert_(number_of_initial_packets),
|
||||
sample_rate_hz_(sample_rate_hz) {}
|
||||
|
||||
absl::optional<int64_t> InitialPacketInserterNetEqInput::NextPacketTime()
|
||||
const {
|
||||
return source_->NextPacketTime();
|
||||
absl::optional<int64_t> InitialPacketInserterNetEqInput::NextEventTime() const {
|
||||
return source_->NextEventTime();
|
||||
}
|
||||
|
||||
absl::optional<int64_t> InitialPacketInserterNetEqInput::NextOutputEventTime()
|
||||
const {
|
||||
return source_->NextOutputEventTime();
|
||||
}
|
||||
|
||||
absl::optional<NetEqInput::SetMinimumDelayInfo>
|
||||
InitialPacketInserterNetEqInput::NextSetMinimumDelayInfo() const {
|
||||
return source_->NextSetMinimumDelayInfo();
|
||||
}
|
||||
|
||||
std::unique_ptr<InitialPacketInserterNetEqInput::PacketData>
|
||||
InitialPacketInserterNetEqInput::PopPacket() {
|
||||
std::unique_ptr<NetEqInput::Event> InitialPacketInserterNetEqInput::PopEvent() {
|
||||
std::unique_ptr<NetEqInput::Event> event;
|
||||
if (!first_packet_) {
|
||||
first_packet_ = source_->PopPacket();
|
||||
if (!first_packet_) {
|
||||
// The source has no packets, so we should not insert any dummy packets.
|
||||
packets_to_insert_ = 0;
|
||||
event = source_->PopEvent();
|
||||
if (event == nullptr || event->type() != Event::Type::kPacketData) {
|
||||
return event;
|
||||
}
|
||||
first_packet_ = std::move(event);
|
||||
}
|
||||
if (packets_to_insert_ > 0) {
|
||||
RTC_CHECK(first_packet_);
|
||||
auto dummy_packet = std::unique_ptr<PacketData>(new PacketData());
|
||||
dummy_packet->header = first_packet_->header;
|
||||
dummy_packet->payload = rtc::Buffer(first_packet_->payload.data(),
|
||||
first_packet_->payload.size());
|
||||
dummy_packet->time_ms = first_packet_->time_ms;
|
||||
std::unique_ptr<PacketData> dummy_packet = std::make_unique<PacketData>();
|
||||
PacketData& first_packet = static_cast<PacketData&>(*first_packet_);
|
||||
dummy_packet->header = first_packet.header;
|
||||
dummy_packet->payload =
|
||||
rtc::Buffer(first_packet.payload.data(), first_packet.payload.size());
|
||||
dummy_packet->timestamp_ms_ = first_packet.timestamp_ms_;
|
||||
dummy_packet->header.sequenceNumber -= packets_to_insert_;
|
||||
// This assumes 20ms per packet.
|
||||
dummy_packet->header.timestamp -=
|
||||
|
@ -65,15 +55,7 @@ InitialPacketInserterNetEqInput::PopPacket() {
|
|||
packets_to_insert_--;
|
||||
return dummy_packet;
|
||||
}
|
||||
return source_->PopPacket();
|
||||
}
|
||||
|
||||
void InitialPacketInserterNetEqInput::AdvanceSetMinimumDelay() {
|
||||
source_->AdvanceSetMinimumDelay();
|
||||
}
|
||||
|
||||
void InitialPacketInserterNetEqInput::AdvanceOutputEvent() {
|
||||
source_->AdvanceOutputEvent();
|
||||
return source_->PopEvent();
|
||||
}
|
||||
|
||||
bool InitialPacketInserterNetEqInput::ended() const {
|
||||
|
|
|
@ -27,20 +27,16 @@ class InitialPacketInserterNetEqInput final : public NetEqInput {
|
|||
InitialPacketInserterNetEqInput(std::unique_ptr<NetEqInput> source,
|
||||
int number_of_initial_packets,
|
||||
int sample_rate_hz);
|
||||
absl::optional<int64_t> NextPacketTime() const override;
|
||||
absl::optional<int64_t> NextOutputEventTime() const override;
|
||||
absl::optional<SetMinimumDelayInfo> NextSetMinimumDelayInfo() const override;
|
||||
std::unique_ptr<PacketData> PopPacket() override;
|
||||
void AdvanceOutputEvent() override;
|
||||
void AdvanceSetMinimumDelay() override;
|
||||
std::unique_ptr<Event> PopEvent() override;
|
||||
bool ended() const override;
|
||||
absl::optional<RTPHeader> NextHeader() const override;
|
||||
absl::optional<int64_t> NextEventTime() const override;
|
||||
|
||||
private:
|
||||
const std::unique_ptr<NetEqInput> source_;
|
||||
int packets_to_insert_;
|
||||
const int sample_rate_hz_;
|
||||
std::unique_ptr<PacketData> first_packet_;
|
||||
std::unique_ptr<Event> first_packet_;
|
||||
};
|
||||
|
||||
} // namespace test
|
||||
|
|
|
@ -87,8 +87,8 @@ void PrintDelays(const NetEqDelayAnalyzer::Delays& delays,
|
|||
void NetEqDelayAnalyzer::AfterInsertPacket(
|
||||
const test::NetEqInput::PacketData& packet,
|
||||
NetEq* neteq) {
|
||||
data_.insert(
|
||||
std::make_pair(packet.header.timestamp, TimingData(packet.time_ms)));
|
||||
data_.insert(std::make_pair(packet.header.timestamp,
|
||||
TimingData(packet.timestamp_ms())));
|
||||
ssrcs_.insert(packet.header.ssrc);
|
||||
payload_types_.insert(packet.header.payloadType);
|
||||
}
|
||||
|
|
|
@ -42,36 +42,88 @@ NetEqEventLogInput* NetEqEventLogInput::CreateFromString(
|
|||
return new NetEqEventLogInput(std::move(event_log_src));
|
||||
}
|
||||
|
||||
absl::optional<int64_t> NetEqEventLogInput::NextOutputEventTime() const {
|
||||
return next_output_event_ms_;
|
||||
std::unique_ptr<NetEqInput::Event> NetEqEventLogInput::PopEvent() {
|
||||
std::unique_ptr<NetEqInput::Event> event_to_return = std::move(event_);
|
||||
event_ = GetNextEvent();
|
||||
return event_to_return;
|
||||
}
|
||||
|
||||
absl::optional<NetEqInput::SetMinimumDelayInfo>
|
||||
NetEqEventLogInput::NextSetMinimumDelayInfo() const {
|
||||
return next_minimum_delay_event_info_;
|
||||
absl::optional<RTPHeader> NetEqEventLogInput::NextHeader() const {
|
||||
return packet_ ? absl::optional<RTPHeader>(packet_->header()) : absl::nullopt;
|
||||
}
|
||||
|
||||
void NetEqEventLogInput::AdvanceOutputEvent() {
|
||||
next_output_event_ms_ = source_->NextAudioOutputEventMs();
|
||||
if (*next_output_event_ms_ == std::numeric_limits<int64_t>::max()) {
|
||||
next_output_event_ms_ = absl::nullopt;
|
||||
absl::optional<int64_t> NetEqEventLogInput::NextOutputEventTime() {
|
||||
absl::optional<int64_t> next_output_event_ms;
|
||||
next_output_event_ms = source_->NextAudioOutputEventMs();
|
||||
if (*next_output_event_ms == std::numeric_limits<int64_t>::max()) {
|
||||
next_output_event_ms = absl::nullopt;
|
||||
}
|
||||
return next_output_event_ms;
|
||||
}
|
||||
|
||||
void NetEqEventLogInput::AdvanceSetMinimumDelay() {
|
||||
next_minimum_delay_event_info_ = source_->NextSetMinimumDelayEvent();
|
||||
std::unique_ptr<NetEqInput::Event> NetEqEventLogInput::CreatePacketEvent() {
|
||||
std::unique_ptr<PacketData> packet_data = std::make_unique<PacketData>();
|
||||
packet_data->header = packet_->header();
|
||||
if (packet_->payload_length_bytes() == 0 &&
|
||||
packet_->virtual_payload_length_bytes() > 0) {
|
||||
// This is a header-only "dummy" packet. Set the payload to all zeros, with
|
||||
// length according to the virtual length.
|
||||
packet_data->payload.SetSize(packet_->virtual_payload_length_bytes());
|
||||
std::fill_n(packet_data->payload.data(), packet_data->payload.size(), 0);
|
||||
} else {
|
||||
packet_data->payload.SetData(packet_->payload(),
|
||||
packet_->payload_length_bytes());
|
||||
}
|
||||
packet_data->timestamp_ms_ = packet_->time_ms();
|
||||
packet_ = source_->NextPacket();
|
||||
return packet_data;
|
||||
}
|
||||
|
||||
PacketSource* NetEqEventLogInput::source() {
|
||||
return source_.get();
|
||||
std::unique_ptr<NetEqInput::Event> NetEqEventLogInput::CreateOutputEvent() {
|
||||
std::unique_ptr<NetEqInput::Event> event =
|
||||
std::make_unique<NetEqInput::GetAudio>(next_output_event_ms_.value());
|
||||
next_output_event_ms_ = NextOutputEventTime();
|
||||
return event;
|
||||
}
|
||||
|
||||
std::unique_ptr<NetEqInput::Event>
|
||||
NetEqEventLogInput::CreateSetMinimumDelayEvent() {
|
||||
std::unique_ptr<NetEqInput::Event> event =
|
||||
std::make_unique<NetEqInput::SetMinimumDelay>(
|
||||
next_minimum_delay_event_.value());
|
||||
next_minimum_delay_event_ = source_->NextSetMinimumDelayEvent();
|
||||
return event;
|
||||
}
|
||||
|
||||
std::unique_ptr<NetEqInput::Event> NetEqEventLogInput::GetNextEvent() {
|
||||
std::unique_ptr<NetEqInput::Event> event;
|
||||
int64_t packet_time_ms = packet_ ? static_cast<int64_t>(packet_->time_ms())
|
||||
: std::numeric_limits<int64_t>::max();
|
||||
int64_t output_time_ms = next_output_event_ms_.has_value()
|
||||
? next_output_event_ms_.value()
|
||||
: std::numeric_limits<int64_t>::max();
|
||||
int64_t minimum_delay_ms = next_minimum_delay_event_.has_value()
|
||||
? next_minimum_delay_event_->timestamp_ms()
|
||||
: std::numeric_limits<int64_t>::max();
|
||||
if (packet_ && packet_time_ms <= minimum_delay_ms &&
|
||||
packet_time_ms <= output_time_ms) {
|
||||
event = CreatePacketEvent();
|
||||
} else if (next_minimum_delay_event_.has_value() &&
|
||||
minimum_delay_ms <= output_time_ms) {
|
||||
event = CreateSetMinimumDelayEvent();
|
||||
} else if (next_output_event_ms_.has_value()) {
|
||||
event = CreateOutputEvent();
|
||||
}
|
||||
return event;
|
||||
}
|
||||
|
||||
NetEqEventLogInput::NetEqEventLogInput(
|
||||
std::unique_ptr<RtcEventLogSource> source)
|
||||
: source_(std::move(source)) {
|
||||
LoadNextPacket();
|
||||
AdvanceOutputEvent();
|
||||
AdvanceSetMinimumDelay();
|
||||
packet_ = source_->NextPacket();
|
||||
next_minimum_delay_event_ = source_->NextSetMinimumDelayEvent();
|
||||
next_output_event_ms_ = NextOutputEventTime();
|
||||
event_ = GetNextEvent();
|
||||
}
|
||||
|
||||
} // namespace test
|
||||
|
|
|
@ -24,9 +24,8 @@ namespace test {
|
|||
|
||||
class RtcEventLogSource;
|
||||
|
||||
// Implementation of NetEqPacketSourceInput to be used with an
|
||||
// RtcEventLogSource.
|
||||
class NetEqEventLogInput final : public NetEqPacketSourceInput {
|
||||
// Implementation of a NetEqInput from an RtcEventLogSource.
|
||||
class NetEqEventLogInput final : public NetEqInput {
|
||||
public:
|
||||
static NetEqEventLogInput* CreateFromFile(
|
||||
absl::string_view file_name,
|
||||
|
@ -35,18 +34,31 @@ class NetEqEventLogInput final : public NetEqPacketSourceInput {
|
|||
absl::string_view file_contents,
|
||||
absl::optional<uint32_t> ssrc_filter);
|
||||
|
||||
absl::optional<int64_t> NextOutputEventTime() const override;
|
||||
absl::optional<SetMinimumDelayInfo> NextSetMinimumDelayInfo() const override;
|
||||
void AdvanceOutputEvent() override;
|
||||
void AdvanceSetMinimumDelay() override;
|
||||
|
||||
protected:
|
||||
PacketSource* source() override;
|
||||
absl::optional<int64_t> NextEventTime() const override {
|
||||
if (event_) {
|
||||
return event_->timestamp_ms();
|
||||
}
|
||||
return absl::nullopt;
|
||||
}
|
||||
std::unique_ptr<Event> PopEvent() override;
|
||||
absl::optional<RTPHeader> NextHeader() const override;
|
||||
bool ended() const override {
|
||||
return !next_output_event_ms_ || packet_ == nullptr;
|
||||
}
|
||||
|
||||
private:
|
||||
NetEqEventLogInput(std::unique_ptr<RtcEventLogSource> source);
|
||||
std::unique_ptr<Event> GetNextEvent();
|
||||
std::unique_ptr<Event> CreatePacketEvent();
|
||||
std::unique_ptr<Event> CreateOutputEvent();
|
||||
std::unique_ptr<Event> CreateSetMinimumDelayEvent();
|
||||
absl::optional<int64_t> NextOutputEventTime();
|
||||
|
||||
std::unique_ptr<RtcEventLogSource> source_;
|
||||
absl::optional<SetMinimumDelayInfo> next_minimum_delay_event_info_;
|
||||
std::unique_ptr<Packet> packet_;
|
||||
absl::optional<int64_t> next_output_event_ms_;
|
||||
absl::optional<SetMinimumDelay> next_minimum_delay_event_;
|
||||
std::unique_ptr<Event> event_;
|
||||
};
|
||||
|
||||
} // namespace test
|
||||
|
|
|
@ -22,7 +22,7 @@ std::string NetEqInput::PacketData::ToString() const {
|
|||
rtc::StringBuilder ss;
|
||||
ss << "{"
|
||||
"time_ms: "
|
||||
<< static_cast<int64_t>(time_ms)
|
||||
<< static_cast<int64_t>(timestamp_ms_)
|
||||
<< ", "
|
||||
"header: {"
|
||||
"pt: "
|
||||
|
@ -50,46 +50,24 @@ TimeLimitedNetEqInput::TimeLimitedNetEqInput(std::unique_ptr<NetEqInput> input,
|
|||
|
||||
TimeLimitedNetEqInput::~TimeLimitedNetEqInput() = default;
|
||||
|
||||
absl::optional<int64_t> TimeLimitedNetEqInput::NextPacketTime() const {
|
||||
return ended_ ? absl::nullopt : input_->NextPacketTime();
|
||||
}
|
||||
|
||||
absl::optional<int64_t> TimeLimitedNetEqInput::NextOutputEventTime() const {
|
||||
return ended_ ? absl::nullopt : input_->NextOutputEventTime();
|
||||
}
|
||||
|
||||
absl::optional<NetEqInput::SetMinimumDelayInfo>
|
||||
TimeLimitedNetEqInput::NextSetMinimumDelayInfo() const {
|
||||
return ended_ ? absl::nullopt : input_->NextSetMinimumDelayInfo();
|
||||
}
|
||||
|
||||
std::unique_ptr<NetEqInput::PacketData> TimeLimitedNetEqInput::PopPacket() {
|
||||
std::unique_ptr<NetEqInput::Event> TimeLimitedNetEqInput::PopEvent() {
|
||||
std::unique_ptr<Event> event;
|
||||
if (ended_) {
|
||||
return std::unique_ptr<PacketData>();
|
||||
return event;
|
||||
}
|
||||
auto packet = input_->PopPacket();
|
||||
event = input_->PopEvent();
|
||||
MaybeSetEnded();
|
||||
return packet;
|
||||
}
|
||||
|
||||
void TimeLimitedNetEqInput::AdvanceOutputEvent() {
|
||||
if (!ended_) {
|
||||
input_->AdvanceOutputEvent();
|
||||
MaybeSetEnded();
|
||||
}
|
||||
}
|
||||
|
||||
void TimeLimitedNetEqInput::AdvanceSetMinimumDelay() {
|
||||
if (!ended_) {
|
||||
input_->AdvanceSetMinimumDelay();
|
||||
MaybeSetEnded();
|
||||
}
|
||||
return event;
|
||||
}
|
||||
|
||||
bool TimeLimitedNetEqInput::ended() const {
|
||||
return ended_ || input_->ended();
|
||||
}
|
||||
|
||||
absl::optional<int64_t> TimeLimitedNetEqInput::NextEventTime() const {
|
||||
return input_->NextEventTime();
|
||||
}
|
||||
|
||||
absl::optional<RTPHeader> TimeLimitedNetEqInput::NextHeader() const {
|
||||
return ended_ ? absl::nullopt : input_->NextHeader();
|
||||
}
|
||||
|
|
|
@ -26,74 +26,53 @@ namespace test {
|
|||
// Interface class for input to the NetEqTest class.
|
||||
class NetEqInput {
|
||||
public:
|
||||
struct PacketData {
|
||||
PacketData();
|
||||
~PacketData();
|
||||
std::string ToString() const;
|
||||
|
||||
RTPHeader header;
|
||||
rtc::Buffer payload;
|
||||
int64_t time_ms;
|
||||
class Event {
|
||||
public:
|
||||
enum class Type { kPacketData, kGetAudio, kSetMinimumDelay };
|
||||
virtual Type type() = 0;
|
||||
virtual int64_t timestamp_ms() const = 0;
|
||||
virtual ~Event() = default;
|
||||
};
|
||||
|
||||
struct SetMinimumDelayInfo {
|
||||
SetMinimumDelayInfo(int64_t timestamp_ms_in, int delay_ms_in)
|
||||
: timestamp_ms(timestamp_ms_in), delay_ms(delay_ms_in) {}
|
||||
int64_t timestamp_ms;
|
||||
int delay_ms;
|
||||
class PacketData : public Event {
|
||||
public:
|
||||
PacketData();
|
||||
~PacketData();
|
||||
Type type() override { return Type::kPacketData; }
|
||||
int64_t timestamp_ms() const override { return timestamp_ms_; }
|
||||
std::string ToString() const;
|
||||
RTPHeader header;
|
||||
rtc::Buffer payload;
|
||||
int64_t timestamp_ms_;
|
||||
};
|
||||
|
||||
class SetMinimumDelay : public Event {
|
||||
public:
|
||||
SetMinimumDelay(int64_t timestamp_ms_in, int delay_ms_in)
|
||||
: timestamp_ms_(timestamp_ms_in), delay_ms_(delay_ms_in) {}
|
||||
Type type() override { return Type::kSetMinimumDelay; }
|
||||
int64_t timestamp_ms() const override { return timestamp_ms_; }
|
||||
int delay_ms() { return delay_ms_; }
|
||||
|
||||
private:
|
||||
int64_t timestamp_ms_;
|
||||
int delay_ms_;
|
||||
};
|
||||
|
||||
class GetAudio : public Event {
|
||||
public:
|
||||
explicit GetAudio(int64_t timestamp_ms_in)
|
||||
: timestamp_ms_(timestamp_ms_in) {}
|
||||
Type type() override { return Type::kGetAudio; }
|
||||
int64_t timestamp_ms() const override { return timestamp_ms_; }
|
||||
|
||||
private:
|
||||
int64_t timestamp_ms_;
|
||||
};
|
||||
|
||||
virtual ~NetEqInput() = default;
|
||||
|
||||
// Returns at what time (in ms) NetEq::InsertPacket should be called next, or
|
||||
// empty if the source is out of packets.
|
||||
virtual absl::optional<int64_t> NextPacketTime() const = 0;
|
||||
|
||||
// Returns at what time (in ms) NetEq::GetAudio should be called next, or
|
||||
// empty if no more output events are available.
|
||||
virtual absl::optional<int64_t> NextOutputEventTime() const = 0;
|
||||
|
||||
// Returns the information related to the next NetEq set minimum delay event
|
||||
// if available.
|
||||
virtual absl::optional<SetMinimumDelayInfo> NextSetMinimumDelayInfo()
|
||||
const = 0;
|
||||
|
||||
// Returns the time (in ms) for the next event (packet, output or set minimum
|
||||
// delay event) or empty if there are no more events.
|
||||
absl::optional<int64_t> NextEventTime() const {
|
||||
absl::optional<int64_t> next_event_time = NextPacketTime();
|
||||
const auto next_output_time = NextOutputEventTime();
|
||||
// Return the minimum of non-empty `a` and `b`, or empty if both are empty.
|
||||
if (next_output_time) {
|
||||
next_event_time = next_event_time ? std::min(next_event_time.value(),
|
||||
next_output_time.value())
|
||||
: next_output_time;
|
||||
}
|
||||
const auto next_neteq_minimum_delay = NextSetMinimumDelayInfo();
|
||||
if (next_neteq_minimum_delay) {
|
||||
next_event_time =
|
||||
next_event_time
|
||||
? std::min(next_event_time.value(),
|
||||
next_neteq_minimum_delay.value().timestamp_ms)
|
||||
: next_neteq_minimum_delay.value().timestamp_ms;
|
||||
}
|
||||
return next_event_time;
|
||||
}
|
||||
|
||||
// Returns the next packet to be inserted into NetEq. The packet following the
|
||||
// returned one is pre-fetched in the NetEqInput object, such that future
|
||||
// calls to NextPacketTime() or NextHeader() will return information from that
|
||||
// packet.
|
||||
virtual std::unique_ptr<PacketData> PopPacket() = 0;
|
||||
|
||||
// Move to the next output event. This will make NextOutputEventTime() return
|
||||
// a new value (potentially the same if several output events share the same
|
||||
// time).
|
||||
virtual void AdvanceOutputEvent() = 0;
|
||||
|
||||
// Move to the next NetEq set minimum delay. This will make
|
||||
// `NextSetMinimumDelayInfo` return a new value.
|
||||
virtual void AdvanceSetMinimumDelay() = 0;
|
||||
virtual std::unique_ptr<Event> PopEvent() = 0;
|
||||
|
||||
// Returns true if the source has come to an end. An implementation must
|
||||
// eventually return true from this method, or the test will end up in an
|
||||
|
@ -103,6 +82,10 @@ class NetEqInput {
|
|||
// Returns the RTP header for the next packet, i.e., the packet that will be
|
||||
// delivered next by PopPacket().
|
||||
virtual absl::optional<RTPHeader> NextHeader() const = 0;
|
||||
|
||||
// Returns the time (in ms) for the next event, or empty if both are out of
|
||||
// events.
|
||||
virtual absl::optional<int64_t> NextEventTime() const = 0;
|
||||
};
|
||||
|
||||
// Wrapper class to impose a time limit on a NetEqInput object, typically
|
||||
|
@ -112,12 +95,8 @@ class TimeLimitedNetEqInput : public NetEqInput {
|
|||
public:
|
||||
TimeLimitedNetEqInput(std::unique_ptr<NetEqInput> input, int64_t duration_ms);
|
||||
~TimeLimitedNetEqInput() override;
|
||||
absl::optional<int64_t> NextPacketTime() const override;
|
||||
absl::optional<int64_t> NextOutputEventTime() const override;
|
||||
absl::optional<SetMinimumDelayInfo> NextSetMinimumDelayInfo() const override;
|
||||
std::unique_ptr<PacketData> PopPacket() override;
|
||||
void AdvanceOutputEvent() override;
|
||||
void AdvanceSetMinimumDelay() override;
|
||||
absl::optional<int64_t> NextEventTime() const override;
|
||||
std::unique_ptr<Event> PopEvent() override;
|
||||
bool ended() const override;
|
||||
absl::optional<RTPHeader> NextHeader() const override;
|
||||
|
||||
|
|
|
@ -20,27 +20,45 @@
|
|||
namespace webrtc {
|
||||
namespace test {
|
||||
|
||||
NetEqPacketSourceInput::NetEqPacketSourceInput() : next_output_event_ms_(0) {}
|
||||
NetEqPacketSourceInput::NetEqPacketSourceInput(
|
||||
absl::string_view file_name,
|
||||
const NetEqPacketSourceInput::RtpHeaderExtensionMap& hdr_ext_map,
|
||||
absl::optional<uint32_t> ssrc_filter)
|
||||
: next_output_event_ms_(0) {
|
||||
std::unique_ptr<RtpFileSource> source(
|
||||
RtpFileSource::Create(file_name, ssrc_filter));
|
||||
for (const auto& ext_pair : hdr_ext_map) {
|
||||
source->RegisterRtpHeaderExtension(ext_pair.second, ext_pair.first);
|
||||
}
|
||||
packet_source_ = std::move(source);
|
||||
packet_ = packet_source_->NextPacket();
|
||||
event_ = GetNextEvent();
|
||||
}
|
||||
|
||||
absl::optional<int64_t> NetEqPacketSourceInput::NextPacketTime() const {
|
||||
return packet_
|
||||
? absl::optional<int64_t>(static_cast<int64_t>(packet_->time_ms()))
|
||||
: absl::nullopt;
|
||||
std::unique_ptr<NetEqInput::Event> NetEqPacketSourceInput::PopEvent() {
|
||||
std::unique_ptr<Event> event_to_return = std::move(event_);
|
||||
event_ = GetNextEvent();
|
||||
return event_to_return;
|
||||
}
|
||||
|
||||
absl::optional<RTPHeader> NetEqPacketSourceInput::NextHeader() const {
|
||||
return packet_ ? absl::optional<RTPHeader>(packet_->header()) : absl::nullopt;
|
||||
if (packet_) {
|
||||
return packet_->header();
|
||||
}
|
||||
return absl::nullopt;
|
||||
}
|
||||
|
||||
void NetEqPacketSourceInput::LoadNextPacket() {
|
||||
packet_ = source()->NextPacket();
|
||||
}
|
||||
|
||||
std::unique_ptr<NetEqInput::PacketData> NetEqPacketSourceInput::PopPacket() {
|
||||
std::unique_ptr<NetEqInput::Event> NetEqPacketSourceInput::GetNextEvent() {
|
||||
if (!packet_) {
|
||||
return std::unique_ptr<PacketData>();
|
||||
return nullptr;
|
||||
}
|
||||
std::unique_ptr<PacketData> packet_data(new PacketData);
|
||||
if (packet_->time_ms() > next_output_event_ms_) {
|
||||
std::unique_ptr<NetEqInput::GetAudio> event =
|
||||
std::make_unique<NetEqInput::GetAudio>(next_output_event_ms_);
|
||||
next_output_event_ms_ += kOutputPeriodMs;
|
||||
return event;
|
||||
}
|
||||
std::unique_ptr<PacketData> packet_data = std::make_unique<PacketData>();
|
||||
packet_data->header = packet_->header();
|
||||
if (packet_->payload_length_bytes() == 0 &&
|
||||
packet_->virtual_payload_length_bytes() > 0) {
|
||||
|
@ -52,39 +70,10 @@ std::unique_ptr<NetEqInput::PacketData> NetEqPacketSourceInput::PopPacket() {
|
|||
packet_data->payload.SetData(packet_->payload(),
|
||||
packet_->payload_length_bytes());
|
||||
}
|
||||
packet_data->time_ms = packet_->time_ms();
|
||||
|
||||
LoadNextPacket();
|
||||
|
||||
packet_data->timestamp_ms_ = packet_->time_ms();
|
||||
packet_ = packet_source_->NextPacket();
|
||||
return packet_data;
|
||||
}
|
||||
|
||||
NetEqRtpDumpInput::NetEqRtpDumpInput(absl::string_view file_name,
|
||||
const RtpHeaderExtensionMap& hdr_ext_map,
|
||||
absl::optional<uint32_t> ssrc_filter)
|
||||
: source_(RtpFileSource::Create(file_name, ssrc_filter)) {
|
||||
for (const auto& ext_pair : hdr_ext_map) {
|
||||
source_->RegisterRtpHeaderExtension(ext_pair.second, ext_pair.first);
|
||||
}
|
||||
LoadNextPacket();
|
||||
}
|
||||
|
||||
absl::optional<int64_t> NetEqRtpDumpInput::NextOutputEventTime() const {
|
||||
return next_output_event_ms_;
|
||||
}
|
||||
|
||||
void NetEqRtpDumpInput::AdvanceOutputEvent() {
|
||||
if (next_output_event_ms_) {
|
||||
*next_output_event_ms_ += kOutputPeriodMs;
|
||||
}
|
||||
if (!NextPacketTime()) {
|
||||
next_output_event_ms_ = absl::nullopt;
|
||||
}
|
||||
}
|
||||
|
||||
PacketSource* NetEqRtpDumpInput::source() {
|
||||
return source_.get();
|
||||
}
|
||||
|
||||
} // namespace test
|
||||
} // namespace webrtc
|
||||
|
|
|
@ -30,43 +30,29 @@ class NetEqPacketSourceInput : public NetEqInput {
|
|||
public:
|
||||
using RtpHeaderExtensionMap = std::map<int, webrtc::RTPExtensionType>;
|
||||
|
||||
NetEqPacketSourceInput();
|
||||
absl::optional<int64_t> NextPacketTime() const override;
|
||||
std::unique_ptr<PacketData> PopPacket() override;
|
||||
absl::optional<RTPHeader> NextHeader() const override;
|
||||
bool ended() const override { return !next_output_event_ms_; }
|
||||
|
||||
protected:
|
||||
virtual PacketSource* source() = 0;
|
||||
void LoadNextPacket();
|
||||
|
||||
absl::optional<int64_t> next_output_event_ms_;
|
||||
|
||||
private:
|
||||
std::unique_ptr<Packet> packet_;
|
||||
};
|
||||
|
||||
// Implementation of NetEqPacketSourceInput to be used with an RtpFileSource.
|
||||
class NetEqRtpDumpInput final : public NetEqPacketSourceInput {
|
||||
public:
|
||||
NetEqRtpDumpInput(absl::string_view file_name,
|
||||
const RtpHeaderExtensionMap& hdr_ext_map,
|
||||
NetEqPacketSourceInput(
|
||||
absl::string_view file_name,
|
||||
const NetEqPacketSourceInput::RtpHeaderExtensionMap& hdr_ext_map,
|
||||
absl::optional<uint32_t> ssrc_filter);
|
||||
|
||||
absl::optional<int64_t> NextOutputEventTime() const override;
|
||||
absl::optional<SetMinimumDelayInfo> NextSetMinimumDelayInfo() const override {
|
||||
absl::optional<int64_t> NextEventTime() const override {
|
||||
if (event_) {
|
||||
return event_->timestamp_ms();
|
||||
}
|
||||
return absl::nullopt;
|
||||
}
|
||||
void AdvanceOutputEvent() override;
|
||||
void AdvanceSetMinimumDelay() override {}
|
||||
|
||||
protected:
|
||||
PacketSource* source() override;
|
||||
std::unique_ptr<Event> PopEvent() override;
|
||||
absl::optional<RTPHeader> NextHeader() const override;
|
||||
bool ended() const override { return event_ == nullptr; }
|
||||
|
||||
private:
|
||||
static constexpr int64_t kOutputPeriodMs = 10;
|
||||
std::unique_ptr<Event> GetNextEvent();
|
||||
|
||||
std::unique_ptr<RtpFileSource> source_;
|
||||
std::unique_ptr<Packet> packet_;
|
||||
std::unique_ptr<PacketSource> packet_source_;
|
||||
int64_t next_output_event_ms_;
|
||||
std::unique_ptr<Event> event_;
|
||||
};
|
||||
|
||||
} // namespace test
|
||||
|
|
|
@ -26,46 +26,25 @@ NetEqReplacementInput::NetEqReplacementInput(
|
|||
comfort_noise_types_(comfort_noise_types),
|
||||
forbidden_types_(forbidden_types) {
|
||||
RTC_CHECK(source_);
|
||||
packet_ = source_->PopPacket();
|
||||
ReplacePacket();
|
||||
event_ = source_->PopEvent();
|
||||
ReplaceIfPacketEvent();
|
||||
}
|
||||
|
||||
absl::optional<int64_t> NetEqReplacementInput::NextPacketTime() const {
|
||||
return packet_
|
||||
? absl::optional<int64_t>(static_cast<int64_t>(packet_->time_ms))
|
||||
: absl::nullopt;
|
||||
}
|
||||
|
||||
absl::optional<int64_t> NetEqReplacementInput::NextOutputEventTime() const {
|
||||
return source_->NextOutputEventTime();
|
||||
}
|
||||
|
||||
absl::optional<NetEqInput::SetMinimumDelayInfo>
|
||||
NetEqReplacementInput::NextSetMinimumDelayInfo() const {
|
||||
return source_->NextSetMinimumDelayInfo();
|
||||
}
|
||||
|
||||
std::unique_ptr<NetEqInput::PacketData> NetEqReplacementInput::PopPacket() {
|
||||
std::unique_ptr<PacketData> to_return = std::move(packet_);
|
||||
std::unique_ptr<NetEqInput::Event> NetEqReplacementInput::PopEvent() {
|
||||
std::unique_ptr<NetEqInput::Event> event_to_return = std::move(event_);
|
||||
while (true) {
|
||||
packet_ = source_->PopPacket();
|
||||
if (!packet_)
|
||||
event_ = source_->PopEvent();
|
||||
if (event_ == nullptr || event_->type() != Event::Type::kPacketData) {
|
||||
break;
|
||||
if (packet_->payload.size() > packet_->header.paddingLength) {
|
||||
}
|
||||
PacketData& packet = static_cast<PacketData&>(*event_);
|
||||
if (packet.payload.size() > packet.header.paddingLength) {
|
||||
// Not padding only. Good to go. Skip this packet otherwise.
|
||||
break;
|
||||
}
|
||||
}
|
||||
ReplacePacket();
|
||||
return to_return;
|
||||
}
|
||||
|
||||
void NetEqReplacementInput::AdvanceOutputEvent() {
|
||||
source_->AdvanceOutputEvent();
|
||||
}
|
||||
|
||||
void NetEqReplacementInput::AdvanceSetMinimumDelay() {
|
||||
source_->AdvanceSetMinimumDelay();
|
||||
ReplaceIfPacketEvent();
|
||||
return event_to_return;
|
||||
}
|
||||
|
||||
bool NetEqReplacementInput::ended() const {
|
||||
|
@ -76,36 +55,38 @@ absl::optional<RTPHeader> NetEqReplacementInput::NextHeader() const {
|
|||
return source_->NextHeader();
|
||||
}
|
||||
|
||||
void NetEqReplacementInput::ReplacePacket() {
|
||||
if (!source_->NextPacketTime()) {
|
||||
// End of input. Cannot do proper replacement on the very last packet, so we
|
||||
// delete it instead.
|
||||
packet_.reset();
|
||||
void NetEqReplacementInput::ReplaceIfPacketEvent() {
|
||||
if (event_ == nullptr || event_->type() != Event::Type::kPacketData) {
|
||||
return;
|
||||
}
|
||||
|
||||
RTC_DCHECK(packet_);
|
||||
PacketData& packet = static_cast<PacketData&>(*event_);
|
||||
|
||||
RTC_CHECK_EQ(forbidden_types_.count(packet_->header.payloadType), 0)
|
||||
<< "Payload type " << static_cast<int>(packet_->header.payloadType)
|
||||
RTC_CHECK_EQ(forbidden_types_.count(packet.header.payloadType), 0)
|
||||
<< "Payload type " << static_cast<int>(packet.header.payloadType)
|
||||
<< " is forbidden.";
|
||||
|
||||
// Check if this packet is comfort noise.
|
||||
if (comfort_noise_types_.count(packet_->header.payloadType) != 0) {
|
||||
if (comfort_noise_types_.count(packet.header.payloadType) != 0) {
|
||||
// If CNG, simply insert a zero-energy one-byte payload.
|
||||
uint8_t cng_payload[1] = {127}; // Max attenuation of CNG.
|
||||
packet_->payload.SetData(cng_payload);
|
||||
packet.payload.SetData(cng_payload);
|
||||
return;
|
||||
}
|
||||
|
||||
absl::optional<RTPHeader> next_hdr = source_->NextHeader();
|
||||
if (!next_hdr) {
|
||||
// End of input. Cannot do proper replacement on the very last packet, so we
|
||||
// delete it instead.
|
||||
event_ = nullptr;
|
||||
return;
|
||||
}
|
||||
RTC_DCHECK(next_hdr);
|
||||
uint8_t payload[12];
|
||||
RTC_DCHECK_LE(last_frame_size_timestamps_, 120 * 48);
|
||||
uint32_t input_frame_size_timestamps = last_frame_size_timestamps_;
|
||||
const uint32_t timestamp_diff =
|
||||
next_hdr->timestamp - packet_->header.timestamp;
|
||||
if (next_hdr->sequenceNumber == packet_->header.sequenceNumber + 1 &&
|
||||
const uint32_t timestamp_diff = next_hdr->timestamp - packet.header.timestamp;
|
||||
if (next_hdr->sequenceNumber == packet.header.sequenceNumber + 1 &&
|
||||
timestamp_diff <= 120 * 48) {
|
||||
// Packets are in order and the timestamp diff is less than 5760 samples.
|
||||
// Accept the timestamp diff as a valid frame size.
|
||||
|
@ -113,11 +94,11 @@ void NetEqReplacementInput::ReplacePacket() {
|
|||
last_frame_size_timestamps_ = input_frame_size_timestamps;
|
||||
}
|
||||
RTC_DCHECK_LE(input_frame_size_timestamps, 120 * 48);
|
||||
FakeDecodeFromFile::PrepareEncoded(packet_->header.timestamp,
|
||||
FakeDecodeFromFile::PrepareEncoded(packet.header.timestamp,
|
||||
input_frame_size_timestamps,
|
||||
packet_->payload.size(), payload);
|
||||
packet_->payload.SetData(payload);
|
||||
packet_->header.payloadType = replacement_payload_type_;
|
||||
packet.payload.size(), payload);
|
||||
packet.payload.SetData(payload);
|
||||
packet.header.payloadType = replacement_payload_type_;
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -28,23 +28,24 @@ class NetEqReplacementInput : public NetEqInput {
|
|||
const std::set<uint8_t>& comfort_noise_types,
|
||||
const std::set<uint8_t>& forbidden_types);
|
||||
|
||||
absl::optional<int64_t> NextPacketTime() const override;
|
||||
absl::optional<int64_t> NextOutputEventTime() const override;
|
||||
absl::optional<SetMinimumDelayInfo> NextSetMinimumDelayInfo() const override;
|
||||
std::unique_ptr<PacketData> PopPacket() override;
|
||||
void AdvanceOutputEvent() override;
|
||||
void AdvanceSetMinimumDelay() override;
|
||||
absl::optional<int64_t> NextEventTime() const override {
|
||||
if (event_) {
|
||||
return event_->timestamp_ms();
|
||||
}
|
||||
return absl::nullopt;
|
||||
}
|
||||
std::unique_ptr<Event> PopEvent() override;
|
||||
bool ended() const override;
|
||||
absl::optional<RTPHeader> NextHeader() const override;
|
||||
|
||||
private:
|
||||
void ReplacePacket();
|
||||
void ReplaceIfPacketEvent();
|
||||
|
||||
std::unique_ptr<NetEqInput> source_;
|
||||
const uint8_t replacement_payload_type_;
|
||||
const std::set<uint8_t> comfort_noise_types_;
|
||||
const std::set<uint8_t> forbidden_types_;
|
||||
std::unique_ptr<PacketData> packet_; // The next packet to deliver.
|
||||
std::unique_ptr<Event> event_; // The next event to deliver.
|
||||
uint32_t last_frame_size_timestamps_ = 960; // Initial guess: 20 ms @ 48 kHz.
|
||||
};
|
||||
|
||||
|
|
|
@ -107,25 +107,27 @@ NetEqTest::SimulationStepResult NetEqTest::RunToNextGetAudio() {
|
|||
RTC_DCHECK(input_->NextEventTime());
|
||||
clock_.AdvanceTimeMilliseconds(*input_->NextEventTime() - time_now_ms);
|
||||
time_now_ms = *input_->NextEventTime();
|
||||
std::unique_ptr<NetEqInput::Event> event = input_->PopEvent();
|
||||
// Check if it is time to insert packet.
|
||||
if (input_->NextPacketTime() && time_now_ms >= *input_->NextPacketTime()) {
|
||||
std::unique_ptr<NetEqInput::PacketData> packet_data = input_->PopPacket();
|
||||
RTC_CHECK(packet_data);
|
||||
RTC_CHECK(event);
|
||||
if (event->type() == NetEqInput::Event::Type::kPacketData) {
|
||||
NetEqInput::PacketData& packet_data =
|
||||
static_cast<NetEqInput::PacketData&>(*event);
|
||||
const size_t payload_data_length =
|
||||
packet_data->payload.size() - packet_data->header.paddingLength;
|
||||
packet_data.payload.size() - packet_data.header.paddingLength;
|
||||
if (payload_data_length != 0) {
|
||||
int error = neteq_->InsertPacket(
|
||||
packet_data->header,
|
||||
rtc::ArrayView<const uint8_t>(packet_data->payload));
|
||||
packet_data.header,
|
||||
rtc::ArrayView<const uint8_t>(packet_data.payload));
|
||||
if (error != NetEq::kOK && callbacks_.error_callback) {
|
||||
callbacks_.error_callback->OnInsertPacketError(*packet_data);
|
||||
callbacks_.error_callback->OnInsertPacketError(packet_data);
|
||||
}
|
||||
if (callbacks_.post_insert_packet) {
|
||||
callbacks_.post_insert_packet->AfterInsertPacket(*packet_data,
|
||||
callbacks_.post_insert_packet->AfterInsertPacket(packet_data,
|
||||
neteq_.get());
|
||||
}
|
||||
} else {
|
||||
neteq_->InsertEmptyPacket(packet_data->header);
|
||||
neteq_->InsertEmptyPacket(packet_data.header);
|
||||
}
|
||||
if (last_packet_time_ms_) {
|
||||
current_state_.packet_iat_ms.push_back(time_now_ms -
|
||||
|
@ -137,20 +139,20 @@ NetEqTest::SimulationStepResult NetEqTest::RunToNextGetAudio() {
|
|||
last_packet_time_ms_ ? (time_now_ms - *last_packet_time_ms_) : -1;
|
||||
const auto delta_timestamp =
|
||||
last_packet_timestamp_
|
||||
? (static_cast<int64_t>(packet_data->header.timestamp) -
|
||||
? (static_cast<int64_t>(packet_data.header.timestamp) -
|
||||
*last_packet_timestamp_) *
|
||||
1000 / sample_rate_hz_
|
||||
: -1;
|
||||
const auto packet_size_bytes =
|
||||
packet_data->payload.size() == 12
|
||||
packet_data.payload.size() == 12
|
||||
? ByteReader<uint32_t>::ReadLittleEndian(
|
||||
&packet_data->payload[8])
|
||||
&packet_data.payload[8])
|
||||
: -1;
|
||||
*text_log_ << "Packet - wallclock: " << std::setw(5) << time_now_ms
|
||||
<< ", delta wc: " << std::setw(4) << delta_wallclock
|
||||
<< ", seq_no: " << packet_data->header.sequenceNumber
|
||||
<< ", seq_no: " << packet_data.header.sequenceNumber
|
||||
<< ", timestamp: " << std::setw(10)
|
||||
<< packet_data->header.timestamp
|
||||
<< packet_data.header.timestamp
|
||||
<< ", delta ts: " << std::setw(4) << delta_timestamp
|
||||
<< ", size: " << std::setw(5) << packet_size_bytes
|
||||
<< ", frame size: " << std::setw(3)
|
||||
|
@ -160,19 +162,16 @@ NetEqTest::SimulationStepResult NetEqTest::RunToNextGetAudio() {
|
|||
}
|
||||
last_packet_time_ms_ = absl::make_optional<int>(time_now_ms);
|
||||
last_packet_timestamp_ =
|
||||
absl::make_optional<uint32_t>(packet_data->header.timestamp);
|
||||
absl::make_optional<uint32_t>(packet_data.header.timestamp);
|
||||
}
|
||||
|
||||
if (input_->NextSetMinimumDelayInfo().has_value() &&
|
||||
time_now_ms >= input_->NextSetMinimumDelayInfo().value().timestamp_ms) {
|
||||
if (event->type() == NetEqInput::Event::Type::kSetMinimumDelay) {
|
||||
neteq_->SetBaseMinimumDelayMs(
|
||||
input_->NextSetMinimumDelayInfo().value().delay_ms);
|
||||
input_->AdvanceSetMinimumDelay();
|
||||
static_cast<NetEqInput::SetMinimumDelay&>(*event).delay_ms());
|
||||
}
|
||||
|
||||
// Check if it is time to get output audio.
|
||||
if (input_->NextOutputEventTime() &&
|
||||
time_now_ms >= *input_->NextOutputEventTime()) {
|
||||
if (event->type() == NetEqInput::Event::Type::kGetAudio) {
|
||||
if (callbacks_.get_audio_callback) {
|
||||
callbacks_.get_audio_callback->BeforeGetAudio(neteq_.get());
|
||||
}
|
||||
|
@ -200,7 +199,6 @@ NetEqTest::SimulationStepResult NetEqTest::RunToNextGetAudio() {
|
|||
out_frame.samples_per_channel_ * out_frame.num_channels_));
|
||||
}
|
||||
|
||||
input_->AdvanceOutputEvent();
|
||||
result.simulation_step_ms =
|
||||
input_->NextEventTime().value_or(time_now_ms) - start_time_ms;
|
||||
const auto operations_state = neteq_->GetOperationsAndState();
|
||||
|
@ -271,8 +269,8 @@ NetEqTest::SimulationStepResult NetEqTest::RunToNextGetAudio() {
|
|||
}
|
||||
}
|
||||
prev_lifetime_stats_ = lifetime_stats;
|
||||
const bool no_more_packets_to_decode =
|
||||
!input_->NextPacketTime() && !operations_state.next_packet_available;
|
||||
const bool no_more_events =
|
||||
!input_->NextEventTime() && !operations_state.next_packet_available;
|
||||
// End the simulation if the gap is too large. This indicates an issue
|
||||
// with the event log file.
|
||||
const bool simulation_step_too_large = result.simulation_step_ms > 1000;
|
||||
|
@ -281,9 +279,8 @@ NetEqTest::SimulationStepResult NetEqTest::RunToNextGetAudio() {
|
|||
// the simulation time, which can be a large distortion.
|
||||
result.simulation_step_ms = 10;
|
||||
}
|
||||
result.is_simulation_finished = simulation_step_too_large ||
|
||||
no_more_packets_to_decode ||
|
||||
input_->ended();
|
||||
result.is_simulation_finished =
|
||||
simulation_step_too_large || no_more_events || input_->ended();
|
||||
prev_ops_state_ = operations_state;
|
||||
return result;
|
||||
}
|
||||
|
|
|
@ -136,8 +136,8 @@ std::unique_ptr<NetEqTest> NetEqTestFactory::InitializeTestFromFile(
|
|||
std::unique_ptr<NetEqInput> input;
|
||||
if (RtpFileSource::ValidRtpDump(input_file_name) ||
|
||||
RtpFileSource::ValidPcap(input_file_name)) {
|
||||
input.reset(new NetEqRtpDumpInput(input_file_name, rtp_ext_map,
|
||||
config.ssrc_filter));
|
||||
input = std::make_unique<NetEqPacketSourceInput>(
|
||||
input_file_name, rtp_ext_map, config.ssrc_filter);
|
||||
} else {
|
||||
input.reset(NetEqEventLogInput::CreateFromFile(input_file_name,
|
||||
config.ssrc_filter));
|
||||
|
@ -169,21 +169,17 @@ std::unique_ptr<NetEqTest> NetEqTestFactory::InitializeTest(
|
|||
if (config.skip_get_audio_events > 0) {
|
||||
std::cout << "Skipping " << config.skip_get_audio_events
|
||||
<< " get_audio events" << std::endl;
|
||||
if (!input->NextPacketTime() || !input->NextOutputEventTime()) {
|
||||
if (!input->NextEventTime()) {
|
||||
std::cerr << "No events found" << std::endl;
|
||||
return nullptr;
|
||||
}
|
||||
for (int i = 0; i < config.skip_get_audio_events; i++) {
|
||||
input->AdvanceOutputEvent();
|
||||
if (!input->NextOutputEventTime()) {
|
||||
std::cerr << "Not enough get_audio events found" << std::endl;
|
||||
return nullptr;
|
||||
std::unique_ptr<NetEqInput::Event> event = input->PopEvent();
|
||||
while (event && event->type() != NetEqInput::Event::Type::kGetAudio) {
|
||||
event = input->PopEvent();
|
||||
}
|
||||
}
|
||||
while (*input->NextPacketTime() < *input->NextOutputEventTime()) {
|
||||
input->PopPacket();
|
||||
if (!input->NextPacketTime()) {
|
||||
std::cerr << "Not enough incoming packets found" << std::endl;
|
||||
if (event == nullptr) {
|
||||
std::cerr << "Not enough events found" << std::endl;
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
@ -212,7 +208,10 @@ std::unique_ptr<NetEqTest> NetEqTestFactory::InitializeTest(
|
|||
// types and SSRCs.
|
||||
discarded_pt_and_ssrc.emplace(first_rtp_header->payloadType,
|
||||
first_rtp_header->ssrc);
|
||||
input->PopPacket();
|
||||
std::unique_ptr<NetEqInput::Event> event = input->PopEvent();
|
||||
while (event && event->type() != NetEqInput::Event::Type::kPacketData) {
|
||||
event = input->PopEvent();
|
||||
}
|
||||
}
|
||||
if (!discarded_pt_and_ssrc.empty()) {
|
||||
std::cout << "Discarded initial packets with the following payload types "
|
||||
|
|
|
@ -95,7 +95,7 @@ int64_t RtcEventLogSource::NextAudioOutputEventMs() {
|
|||
return output_time_ms;
|
||||
}
|
||||
|
||||
absl::optional<NetEqInput::SetMinimumDelayInfo>
|
||||
absl::optional<NetEqInput::SetMinimumDelay>
|
||||
RtcEventLogSource::NextSetMinimumDelayEvent() {
|
||||
if (minimum_delay_index_ >= minimum_delay_.size()) {
|
||||
return absl::nullopt;
|
||||
|
|
|
@ -55,7 +55,7 @@ class RtcEventLogSource : public PacketSource {
|
|||
int64_t NextAudioOutputEventMs();
|
||||
|
||||
// Returns the next NetEq set minimum delay event if available.
|
||||
absl::optional<NetEqInput::SetMinimumDelayInfo> NextSetMinimumDelayEvent();
|
||||
absl::optional<NetEqInput::SetMinimumDelay> NextSetMinimumDelayEvent();
|
||||
|
||||
private:
|
||||
RtcEventLogSource();
|
||||
|
@ -67,7 +67,7 @@ class RtcEventLogSource : public PacketSource {
|
|||
size_t rtp_packet_index_ = 0;
|
||||
std::vector<int64_t> audio_outputs_;
|
||||
size_t audio_output_index_ = 0;
|
||||
std::vector<NetEqInput::SetMinimumDelayInfo> minimum_delay_;
|
||||
std::vector<NetEqInput::SetMinimumDelay> minimum_delay_;
|
||||
size_t minimum_delay_index_ = 0;
|
||||
};
|
||||
|
||||
|
|
|
@ -196,9 +196,52 @@ class NetEqStreamInput : public test::NetEqInput {
|
|||
end_time_ms_(end_time_ms) {
|
||||
RTC_DCHECK(packet_stream);
|
||||
RTC_DCHECK(output_events);
|
||||
event_ = GetNextEvent();
|
||||
}
|
||||
|
||||
absl::optional<int64_t> NextPacketTime() const override {
|
||||
absl::optional<int64_t> NextEventTime() const override {
|
||||
if (event_) {
|
||||
return event_->timestamp_ms();
|
||||
}
|
||||
return absl::nullopt;
|
||||
}
|
||||
|
||||
std::unique_ptr<Event> PopEvent() override {
|
||||
std::unique_ptr<Event> return_event = std::move(event_);
|
||||
event_ = GetNextEvent();
|
||||
return return_event;
|
||||
}
|
||||
|
||||
std::unique_ptr<Event> GetNextEvent() {
|
||||
absl::optional<int64_t> next_time;
|
||||
absl::optional<int64_t> next_packet_time = NextPacketTime();
|
||||
absl::optional<int64_t> next_output_time = NextOutputEventTime();
|
||||
absl::optional<int64_t> next_set_minimum_delay_time =
|
||||
NextSetMinimumDelayTime();
|
||||
for (auto time :
|
||||
{next_packet_time, next_output_time, next_set_minimum_delay_time}) {
|
||||
if (time) {
|
||||
if (next_time) {
|
||||
next_time = time.value() < next_time.value() ? time : next_time;
|
||||
} else {
|
||||
next_time = time;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (next_packet_time && next_packet_time.value() == next_time.value()) {
|
||||
return PopPacket();
|
||||
}
|
||||
if (next_output_time && next_output_time.value() == next_time.value()) {
|
||||
return PopGetAudio();
|
||||
}
|
||||
if (next_set_minimum_delay_time &&
|
||||
next_set_minimum_delay_time.value() == next_time.value()) {
|
||||
return PopNetEqSetMinimumDelay();
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
absl::optional<int64_t> NextPacketTime() const {
|
||||
if (packet_stream_it_ == packet_stream_.end()) {
|
||||
return absl::nullopt;
|
||||
}
|
||||
|
@ -208,7 +251,7 @@ class NetEqStreamInput : public test::NetEqInput {
|
|||
return packet_stream_it_->rtp.log_time_ms();
|
||||
}
|
||||
|
||||
absl::optional<int64_t> NextOutputEventTime() const override {
|
||||
absl::optional<int64_t> NextOutputEventTime() const {
|
||||
if (output_events_it_ == output_events_end_) {
|
||||
return absl::nullopt;
|
||||
}
|
||||
|
@ -218,7 +261,7 @@ class NetEqStreamInput : public test::NetEqInput {
|
|||
return output_events_it_->log_time_ms();
|
||||
}
|
||||
|
||||
absl::optional<SetMinimumDelayInfo> NextSetMinimumDelayInfo() const override {
|
||||
absl::optional<int64_t> NextSetMinimumDelayTime() const {
|
||||
if (neteq_set_minimum_delay_events_it_ ==
|
||||
neteq_set_minimum_delay_events_end_) {
|
||||
return absl::nullopt;
|
||||
|
@ -227,18 +270,16 @@ class NetEqStreamInput : public test::NetEqInput {
|
|||
neteq_set_minimum_delay_events_it_->log_time_ms() > *end_time_ms_) {
|
||||
return absl::nullopt;
|
||||
}
|
||||
return SetMinimumDelayInfo(
|
||||
neteq_set_minimum_delay_events_it_->log_time_ms(),
|
||||
neteq_set_minimum_delay_events_it_->minimum_delay_ms);
|
||||
return neteq_set_minimum_delay_events_it_->log_time_ms();
|
||||
}
|
||||
|
||||
std::unique_ptr<PacketData> PopPacket() override {
|
||||
std::unique_ptr<PacketData> PopPacket() {
|
||||
if (packet_stream_it_ == packet_stream_.end()) {
|
||||
return std::unique_ptr<PacketData>();
|
||||
}
|
||||
std::unique_ptr<PacketData> packet_data(new PacketData());
|
||||
packet_data->header = packet_stream_it_->rtp.header;
|
||||
packet_data->time_ms = packet_stream_it_->rtp.log_time_ms();
|
||||
packet_data->timestamp_ms_ = packet_stream_it_->rtp.log_time_ms();
|
||||
|
||||
// This is a header-only "dummy" packet. Set the payload to all zeros, with
|
||||
// length according to the virtual length.
|
||||
|
@ -250,17 +291,26 @@ class NetEqStreamInput : public test::NetEqInput {
|
|||
return packet_data;
|
||||
}
|
||||
|
||||
void AdvanceOutputEvent() override {
|
||||
std::unique_ptr<GetAudio> PopGetAudio() {
|
||||
std::unique_ptr<GetAudio> get_audio;
|
||||
if (output_events_it_ != output_events_end_) {
|
||||
get_audio = std::make_unique<GetAudio>(output_events_it_->log_time_ms());
|
||||
++output_events_it_;
|
||||
}
|
||||
return get_audio;
|
||||
}
|
||||
|
||||
void AdvanceSetMinimumDelay() override {
|
||||
std::unique_ptr<SetMinimumDelay> PopNetEqSetMinimumDelay() {
|
||||
std::unique_ptr<SetMinimumDelay> net_eq_set_minimum_delay;
|
||||
if (neteq_set_minimum_delay_events_it_ !=
|
||||
neteq_set_minimum_delay_events_end_) {
|
||||
net_eq_set_minimum_delay = std::make_unique<SetMinimumDelay>(
|
||||
neteq_set_minimum_delay_events_it_->log_time_ms(),
|
||||
neteq_set_minimum_delay_events_it_->minimum_delay_ms);
|
||||
|
||||
++neteq_set_minimum_delay_events_it_;
|
||||
}
|
||||
return net_eq_set_minimum_delay;
|
||||
}
|
||||
|
||||
bool ended() const override { return !NextEventTime(); }
|
||||
|
@ -282,6 +332,7 @@ class NetEqStreamInput : public test::NetEqInput {
|
|||
const std::vector<LoggedNetEqSetMinimumDelayEvent>::const_iterator
|
||||
neteq_set_minimum_delay_events_end_;
|
||||
const absl::optional<int64_t> end_time_ms_;
|
||||
std::unique_ptr<Event> event_;
|
||||
};
|
||||
|
||||
namespace {
|
||||
|
|
|
@ -64,71 +64,65 @@ class FuzzRtpInput : public NetEqInput {
|
|||
new SineGenerator(config.sample_rate_hz));
|
||||
input_.reset(new EncodeNetEqInput(std::move(generator), std::move(encoder),
|
||||
std::numeric_limits<int64_t>::max()));
|
||||
packet_ = input_->PopPacket();
|
||||
FuzzHeader();
|
||||
MaybeFuzzPayload();
|
||||
// We pop the first event so we have information about the timing of such
|
||||
// first event.
|
||||
event_ = input_->PopEvent();
|
||||
if (event_ && event_->type() == Event::Type::kPacketData) {
|
||||
FuzzPacket(static_cast<PacketData*>(event_.get()));
|
||||
}
|
||||
}
|
||||
|
||||
absl::optional<int64_t> NextPacketTime() const override {
|
||||
return packet_->time_ms;
|
||||
std::unique_ptr<Event> PopEvent() override {
|
||||
std::unique_ptr<Event> event_to_return = std::move(event_);
|
||||
event_ = input_->PopEvent();
|
||||
if (event_ && event_->type() == Event::Type::kPacketData) {
|
||||
FuzzPacket(static_cast<PacketData*>(event_.get()));
|
||||
}
|
||||
|
||||
absl::optional<int64_t> NextOutputEventTime() const override {
|
||||
return input_->NextOutputEventTime();
|
||||
}
|
||||
|
||||
absl::optional<SetMinimumDelayInfo> NextSetMinimumDelayInfo() const override {
|
||||
return input_->NextSetMinimumDelayInfo();
|
||||
}
|
||||
|
||||
std::unique_ptr<PacketData> PopPacket() override {
|
||||
RTC_DCHECK(packet_);
|
||||
std::unique_ptr<PacketData> packet_to_return = std::move(packet_);
|
||||
packet_ = input_->PopPacket();
|
||||
FuzzHeader();
|
||||
MaybeFuzzPayload();
|
||||
return packet_to_return;
|
||||
}
|
||||
|
||||
void AdvanceOutputEvent() override { return input_->AdvanceOutputEvent(); }
|
||||
|
||||
void AdvanceSetMinimumDelay() override {
|
||||
return input_->AdvanceSetMinimumDelay();
|
||||
return event_to_return;
|
||||
}
|
||||
|
||||
bool ended() const override { return ended_; }
|
||||
|
||||
absl::optional<RTPHeader> NextHeader() const override {
|
||||
RTC_DCHECK(packet_);
|
||||
return packet_->header;
|
||||
RTC_DCHECK(event_ && event_->type() == Event::Type::kPacketData);
|
||||
return static_cast<PacketData&>(*event_).header;
|
||||
}
|
||||
|
||||
absl::optional<int64_t> NextEventTime() const override {
|
||||
if (event_) {
|
||||
return event_->timestamp_ms();
|
||||
}
|
||||
return absl::nullopt;
|
||||
}
|
||||
|
||||
private:
|
||||
void FuzzHeader() {
|
||||
void FuzzPacket(PacketData* packet_data) {
|
||||
FuzzHeader(packet_data->header);
|
||||
MaybeFuzzPayload(packet_data->payload);
|
||||
}
|
||||
|
||||
void FuzzHeader(RTPHeader& header) {
|
||||
constexpr size_t kNumBytesToFuzz = 11;
|
||||
if (data_ix_ + kNumBytesToFuzz > data_.size()) {
|
||||
ended_ = true;
|
||||
return;
|
||||
}
|
||||
RTC_DCHECK(packet_);
|
||||
const size_t start_ix = data_ix_;
|
||||
packet_->header.payloadType =
|
||||
header.payloadType =
|
||||
ByteReader<uint8_t>::ReadLittleEndian(&data_[data_ix_]);
|
||||
packet_->header.payloadType &= 0x7F;
|
||||
header.payloadType &= 0x7F;
|
||||
data_ix_ += sizeof(uint8_t);
|
||||
packet_->header.sequenceNumber =
|
||||
header.sequenceNumber =
|
||||
ByteReader<uint16_t>::ReadLittleEndian(&data_[data_ix_]);
|
||||
data_ix_ += sizeof(uint16_t);
|
||||
packet_->header.timestamp =
|
||||
ByteReader<uint32_t>::ReadLittleEndian(&data_[data_ix_]);
|
||||
header.timestamp = ByteReader<uint32_t>::ReadLittleEndian(&data_[data_ix_]);
|
||||
data_ix_ += sizeof(uint32_t);
|
||||
packet_->header.ssrc =
|
||||
ByteReader<uint32_t>::ReadLittleEndian(&data_[data_ix_]);
|
||||
header.ssrc = ByteReader<uint32_t>::ReadLittleEndian(&data_[data_ix_]);
|
||||
data_ix_ += sizeof(uint32_t);
|
||||
RTC_CHECK_EQ(data_ix_ - start_ix, kNumBytesToFuzz);
|
||||
}
|
||||
|
||||
void MaybeFuzzPayload() {
|
||||
void MaybeFuzzPayload(rtc::Buffer& payload) {
|
||||
// Read one byte of fuzz data to determine how many payload bytes to fuzz.
|
||||
if (data_ix_ + 1 > data_.size()) {
|
||||
ended_ = true;
|
||||
|
@ -138,7 +132,7 @@ class FuzzRtpInput : public NetEqInput {
|
|||
|
||||
// Restrict number of bytes to fuzz to 16; a reasonably low number enough to
|
||||
// cover a few RED headers. Also don't write outside the payload length.
|
||||
bytes_to_fuzz = std::min(bytes_to_fuzz % 16, packet_->payload.size());
|
||||
bytes_to_fuzz = std::min(bytes_to_fuzz % 16, payload.size());
|
||||
|
||||
if (bytes_to_fuzz == 0)
|
||||
return;
|
||||
|
@ -148,7 +142,7 @@ class FuzzRtpInput : public NetEqInput {
|
|||
return;
|
||||
}
|
||||
|
||||
std::memcpy(packet_->payload.data(), &data_[data_ix_], bytes_to_fuzz);
|
||||
std::memcpy(payload.data(), &data_[data_ix_], bytes_to_fuzz);
|
||||
data_ix_ += bytes_to_fuzz;
|
||||
}
|
||||
|
||||
|
@ -156,7 +150,7 @@ class FuzzRtpInput : public NetEqInput {
|
|||
rtc::ArrayView<const uint8_t> data_;
|
||||
size_t data_ix_ = 0;
|
||||
std::unique_ptr<EncodeNetEqInput> input_;
|
||||
std::unique_ptr<PacketData> packet_;
|
||||
std::unique_ptr<Event> event_;
|
||||
};
|
||||
} // namespace
|
||||
|
||||
|
|
|
@ -80,8 +80,10 @@ class FuzzSignalInput : public NetEqInput {
|
|||
new SineAndNoiseGenerator(config.sample_rate_hz, fuzz_data));
|
||||
input_.reset(new EncodeNetEqInput(std::move(generator), std::move(encoder),
|
||||
std::numeric_limits<int64_t>::max()));
|
||||
packet_ = input_->PopPacket();
|
||||
|
||||
// We pop the first event so we have information about the timing of such
|
||||
// first event.
|
||||
PopPacket();
|
||||
PopEvent();
|
||||
// Select an output event period. This is how long time we wait between each
|
||||
// call to NetEq::GetAudio. 10 ms is nominal, 9 and 11 ms will both lead to
|
||||
// clock drift (in different directions).
|
||||
|
@ -89,32 +91,45 @@ class FuzzSignalInput : public NetEqInput {
|
|||
output_event_period_ms_ = fuzz_data_.SelectOneOf(output_event_periods);
|
||||
}
|
||||
|
||||
absl::optional<int64_t> NextPacketTime() const override {
|
||||
return packet_->time_ms;
|
||||
std::unique_ptr<Event> PopEvent() override {
|
||||
std::unique_ptr<Event> event_to_return = std::move(event_);
|
||||
if (packet_ && packet_->timestamp_ms() <= next_output_event_ms_) {
|
||||
event_ = PopPacket();
|
||||
} else {
|
||||
event_ = std::make_unique<GetAudio>(next_output_event_ms_);
|
||||
next_output_event_ms_ += output_event_period_ms_;
|
||||
}
|
||||
return event_to_return;
|
||||
}
|
||||
|
||||
absl::optional<int64_t> NextOutputEventTime() const override {
|
||||
return next_output_event_ms_;
|
||||
absl::optional<int64_t> NextEventTime() const override {
|
||||
if (event_) {
|
||||
return event_->timestamp_ms();
|
||||
}
|
||||
return absl::nullopt;
|
||||
}
|
||||
|
||||
absl::optional<SetMinimumDelayInfo> NextSetMinimumDelayInfo() const override {
|
||||
return input_->NextSetMinimumDelayInfo();
|
||||
}
|
||||
|
||||
std::unique_ptr<PacketData> PopPacket() override {
|
||||
RTC_DCHECK(packet_);
|
||||
std::unique_ptr<PacketData> packet_to_return = std::move(packet_);
|
||||
std::unique_ptr<Event> PopPacket() {
|
||||
std::unique_ptr<Event> packet_to_return = std::move(packet_);
|
||||
int64_t packet_to_return_time_ms =
|
||||
packet_to_return ? packet_to_return->timestamp_ms() : 0;
|
||||
PacketData* packet_data = nullptr;
|
||||
do {
|
||||
packet_ = input_->PopPacket();
|
||||
std::unique_ptr<Event> event = input_->PopEvent();
|
||||
while (event && event->type() != Event::Type::kPacketData) {
|
||||
event = input_->PopEvent();
|
||||
}
|
||||
packet_data = static_cast<PacketData*>(event.get());
|
||||
// If the next value from the fuzzer input is 0, the packet is discarded
|
||||
// and the next one is pulled from the source.
|
||||
} while (fuzz_data_.CanReadBytes(1) && fuzz_data_.Read<uint8_t>() == 0);
|
||||
if (fuzz_data_.CanReadBytes(1)) {
|
||||
if (fuzz_data_.CanReadBytes(1) && packet_data) {
|
||||
// Generate jitter by setting an offset for the arrival time.
|
||||
const int8_t arrival_time_offset_ms = fuzz_data_.Read<int8_t>();
|
||||
// The arrival time can not be before the previous packets.
|
||||
packet_->time_ms = std::max(packet_to_return->time_ms,
|
||||
packet_->time_ms + arrival_time_offset_ms);
|
||||
packet_data->timestamp_ms_ =
|
||||
std::max(packet_to_return_time_ms,
|
||||
packet_data->timestamp_ms_ + arrival_time_offset_ms);
|
||||
} else {
|
||||
// Mark that we are at the end of the test. However, the current packet is
|
||||
// still valid (but it may not have been fuzzed as expected).
|
||||
|
@ -123,28 +138,21 @@ class FuzzSignalInput : public NetEqInput {
|
|||
return packet_to_return;
|
||||
}
|
||||
|
||||
void AdvanceOutputEvent() override {
|
||||
next_output_event_ms_ += output_event_period_ms_;
|
||||
}
|
||||
|
||||
void AdvanceSetMinimumDelay() override {
|
||||
return input_->AdvanceSetMinimumDelay();
|
||||
}
|
||||
|
||||
bool ended() const override { return ended_; }
|
||||
|
||||
absl::optional<RTPHeader> NextHeader() const override {
|
||||
RTC_DCHECK(packet_);
|
||||
return packet_->header;
|
||||
return static_cast<PacketData&>(*packet_).header;
|
||||
}
|
||||
|
||||
private:
|
||||
bool ended_ = false;
|
||||
FuzzDataHelper& fuzz_data_;
|
||||
std::unique_ptr<EncodeNetEqInput> input_;
|
||||
std::unique_ptr<PacketData> packet_;
|
||||
std::unique_ptr<Event> packet_;
|
||||
int64_t next_output_event_ms_ = 0;
|
||||
int64_t output_event_period_ms_ = 10;
|
||||
int64_t output_event_period_ms_;
|
||||
std::unique_ptr<Event> event_;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
|
|
Loading…
Reference in a new issue