blob: d42a31b7d97d3b6efc86fb46f6669f204430e79f [file] [log] [blame]
/*
* Copyright (c) 2018 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.
*/
#include "modules/audio_coding/neteq/tools/neteq_event_log_input.h"
#include <limits>
#include <memory>
#include "absl/strings/string_view.h"
#include "rtc_base/checks.h"
namespace webrtc {
namespace test {
namespace {
class NetEqEventLogInput : public NetEqInput {
public:
NetEqEventLogInput(const std::vector<LoggedRtpPacketIncoming>& packet_stream,
const std::vector<LoggedAudioPlayoutEvent>& output_events,
const std::vector<LoggedNetEqSetMinimumDelayEvent>&
neteq_set_minimum_delay_events,
std::optional<int64_t> end_time_ms)
: packet_stream_(packet_stream),
packet_stream_it_(packet_stream_.begin()),
output_events_(output_events),
output_events_it_(output_events_.begin()),
neteq_set_minimum_delay_events_(neteq_set_minimum_delay_events),
neteq_set_minimum_delay_events_it_(
neteq_set_minimum_delay_events_.begin()),
end_time_ms_(end_time_ms) {
// Ignore all output events before the first packet.
while (output_events_it_ != output_events_.end() &&
output_events_it_->log_time_ms() <
packet_stream_it_->log_time_ms()) {
++output_events_it_;
}
}
std::optional<int64_t> NextPacketTime() const override {
if (packet_stream_it_ == packet_stream_.end()) {
return std::nullopt;
}
if (end_time_ms_ && packet_stream_it_->rtp.log_time_ms() > *end_time_ms_) {
return std::nullopt;
}
return packet_stream_it_->rtp.log_time_ms();
}
std::optional<int64_t> NextOutputEventTime() const override {
if (output_events_it_ == output_events_.end()) {
return std::nullopt;
}
if (end_time_ms_ && output_events_it_->log_time_ms() > *end_time_ms_) {
return std::nullopt;
}
return output_events_it_->log_time_ms();
}
std::optional<SetMinimumDelayInfo> NextSetMinimumDelayInfo() const override {
if (neteq_set_minimum_delay_events_it_ ==
neteq_set_minimum_delay_events_.end()) {
return std::nullopt;
}
if (end_time_ms_ &&
neteq_set_minimum_delay_events_it_->log_time_ms() > *end_time_ms_) {
return std::nullopt;
}
return SetMinimumDelayInfo(
neteq_set_minimum_delay_events_it_->log_time_ms(),
neteq_set_minimum_delay_events_it_->minimum_delay_ms);
}
std::unique_ptr<PacketData> PopPacket() override {
if (packet_stream_it_ == packet_stream_.end()) {
return nullptr;
}
auto packet_data = std::make_unique<PacketData>();
packet_data->header = packet_stream_it_->rtp.header;
packet_data->time_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.
packet_data->payload.SetSize(packet_stream_it_->rtp.total_length -
packet_stream_it_->rtp.header_length);
std::fill_n(packet_data->payload.data(), packet_data->payload.size(), 0);
++packet_stream_it_;
return packet_data;
}
void AdvanceOutputEvent() override {
if (output_events_it_ != output_events_.end()) {
++output_events_it_;
}
}
void AdvanceSetMinimumDelay() override {
if (neteq_set_minimum_delay_events_it_ !=
neteq_set_minimum_delay_events_.end()) {
++neteq_set_minimum_delay_events_it_;
}
}
bool ended() const override { return !NextEventTime(); }
std::optional<RTPHeader> NextHeader() const override {
if (packet_stream_it_ == packet_stream_.end()) {
return std::nullopt;
}
return packet_stream_it_->rtp.header;
}
private:
const std::vector<LoggedRtpPacketIncoming> packet_stream_;
std::vector<LoggedRtpPacketIncoming>::const_iterator packet_stream_it_;
const std::vector<LoggedAudioPlayoutEvent> output_events_;
std::vector<LoggedAudioPlayoutEvent>::const_iterator output_events_it_;
const std::vector<LoggedNetEqSetMinimumDelayEvent>
neteq_set_minimum_delay_events_;
std::vector<LoggedNetEqSetMinimumDelayEvent>::const_iterator
neteq_set_minimum_delay_events_it_;
const std::optional<int64_t> end_time_ms_;
};
} // namespace
std::unique_ptr<NetEqInput> CreateNetEqEventLogInput(
const ParsedRtcEventLog& parsed_log,
std::optional<uint32_t> ssrc) {
if (parsed_log.incoming_audio_ssrcs().empty()) {
return nullptr;
}
// Pick the first SSRC if none was provided.
ssrc = ssrc.value_or(*parsed_log.incoming_audio_ssrcs().begin());
auto streams = parsed_log.incoming_rtp_packets_by_ssrc();
auto stream =
std::find_if(streams.begin(), streams.end(),
[ssrc](auto stream) { return stream.ssrc == ssrc; });
if (stream == streams.end()) {
return nullptr;
}
auto output_events_it = parsed_log.audio_playout_events().find(*ssrc);
if (output_events_it == parsed_log.audio_playout_events().end()) {
return nullptr;
}
std::vector<LoggedNetEqSetMinimumDelayEvent> neteq_set_minimum_delay_events;
auto neteq_set_minimum_delay_events_it =
parsed_log.neteq_set_minimum_delay_events().find(*ssrc);
if (neteq_set_minimum_delay_events_it !=
parsed_log.neteq_set_minimum_delay_events().end()) {
neteq_set_minimum_delay_events = neteq_set_minimum_delay_events_it->second;
}
int64_t end_time_ms = parsed_log.first_log_segment().stop_time_ms();
return std::make_unique<NetEqEventLogInput>(
stream->incoming_packets, output_events_it->second,
neteq_set_minimum_delay_events, end_time_ms);
}
} // namespace test
} // namespace webrtc