blob: 4c36684c8ecc2a8d13f4c8d6980d8db52eea990e [file] [log] [blame]
/*
* Copyright (c) 2017 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 <deque>
#include <limits>
#include <string>
#include "absl/memory/memory.h"
#include "logging/rtc_event_log/encoder/rtc_event_log_encoder_legacy.h"
#include "logging/rtc_event_log/events/rtc_event_alr_state.h"
#include "logging/rtc_event_log/events/rtc_event_audio_network_adaptation.h"
#include "logging/rtc_event_log/events/rtc_event_audio_playout.h"
#include "logging/rtc_event_log/events/rtc_event_audio_receive_stream_config.h"
#include "logging/rtc_event_log/events/rtc_event_audio_send_stream_config.h"
#include "logging/rtc_event_log/events/rtc_event_bwe_update_delay_based.h"
#include "logging/rtc_event_log/events/rtc_event_bwe_update_loss_based.h"
#include "logging/rtc_event_log/events/rtc_event_probe_cluster_created.h"
#include "logging/rtc_event_log/events/rtc_event_probe_result_failure.h"
#include "logging/rtc_event_log/events/rtc_event_probe_result_success.h"
#include "logging/rtc_event_log/events/rtc_event_rtcp_packet_incoming.h"
#include "logging/rtc_event_log/events/rtc_event_rtcp_packet_outgoing.h"
#include "logging/rtc_event_log/events/rtc_event_rtp_packet_incoming.h"
#include "logging/rtc_event_log/events/rtc_event_rtp_packet_outgoing.h"
#include "logging/rtc_event_log/events/rtc_event_video_receive_stream_config.h"
#include "logging/rtc_event_log/events/rtc_event_video_send_stream_config.h"
#include "logging/rtc_event_log/rtc_event_log_parser_new.h"
#include "logging/rtc_event_log/rtc_event_log_unittest_helper.h"
#include "modules/audio_coding/audio_network_adaptor/include/audio_network_adaptor_config.h"
#include "modules/remote_bitrate_estimator/include/bwe_defines.h"
#include "modules/rtp_rtcp/source/rtp_header_extensions.h"
#include "rtc_base/random.h"
#include "test/gtest.h"
namespace webrtc {
class RtcEventLogEncoderTest : public testing::TestWithParam<int> {
protected:
RtcEventLogEncoderTest()
: encoder_(new RtcEventLogEncoderLegacy),
seed_(GetParam()),
prng_(seed_),
gen_(seed_ * 880001UL) {}
~RtcEventLogEncoderTest() override = default;
// ANA events have some optional fields, so we want to make sure that we get
// correct behavior both when all of the values are there, as well as when
// only some.
void TestRtcEventAudioNetworkAdaptation(
std::unique_ptr<AudioEncoderRuntimeConfig> runtime_config);
std::deque<std::unique_ptr<RtcEvent>> history_;
// TODO(eladalon): Once we have more than one possible encoder, parameterize
// encoder selection.
std::unique_ptr<RtcEventLogEncoder> encoder_;
ParsedRtcEventLogNew parsed_log_;
const uint64_t seed_;
Random prng_;
test::EventGenerator gen_;
};
TEST_P(RtcEventLogEncoderTest, RtcEventAlrState) {
std::unique_ptr<RtcEventAlrState> event = gen_.NewAlrState();
history_.push_back(event->Copy());
std::string encoded = encoder_->EncodeBatch(history_.begin(), history_.end());
ASSERT_TRUE(parsed_log_.ParseString(encoded));
const auto& alr_state_events = parsed_log_.alr_state_events();
ASSERT_EQ(alr_state_events.size(), 1u);
test::VerifyLoggedAlrStateEvent(*event, alr_state_events[0]);
}
void RtcEventLogEncoderTest::TestRtcEventAudioNetworkAdaptation(
std::unique_ptr<AudioEncoderRuntimeConfig> runtime_config) {
// This function is called repeatedly. Clear state between calls.
history_.clear();
auto original_runtime_config = *runtime_config;
auto event = absl::make_unique<RtcEventAudioNetworkAdaptation>(
std::move(runtime_config));
const int64_t timestamp_us = event->timestamp_us_;
history_.push_back(std::move(event));
std::string encoded = encoder_->EncodeBatch(history_.begin(), history_.end());
ASSERT_TRUE(parsed_log_.ParseString(encoded));
const auto& ana_configs = parsed_log_.audio_network_adaptation_events();
ASSERT_EQ(ana_configs.size(), 1u);
EXPECT_EQ(ana_configs[0].timestamp_us, timestamp_us);
EXPECT_EQ(ana_configs[0].config, original_runtime_config);
}
TEST_P(RtcEventLogEncoderTest, RtcEventAudioNetworkAdaptationBitrate) {
auto runtime_config = absl::make_unique<AudioEncoderRuntimeConfig>();
const int bitrate_bps = rtc::checked_cast<int>(
prng_.Rand(0, std::numeric_limits<int32_t>::max()));
runtime_config->bitrate_bps = bitrate_bps;
TestRtcEventAudioNetworkAdaptation(std::move(runtime_config));
}
TEST_P(RtcEventLogEncoderTest, RtcEventAudioNetworkAdaptationFrameLength) {
auto runtime_config = absl::make_unique<AudioEncoderRuntimeConfig>();
const int frame_length_ms = prng_.Rand(1, 1000);
runtime_config->frame_length_ms = frame_length_ms;
TestRtcEventAudioNetworkAdaptation(std::move(runtime_config));
}
TEST_P(RtcEventLogEncoderTest, RtcEventAudioNetworkAdaptationPacketLoss) {
// To simplify the test, we just check powers of two.
const float plr = std::pow(0.5f, prng_.Rand(1, 8));
auto runtime_config = absl::make_unique<AudioEncoderRuntimeConfig>();
runtime_config->uplink_packet_loss_fraction = plr;
TestRtcEventAudioNetworkAdaptation(std::move(runtime_config));
}
TEST_P(RtcEventLogEncoderTest, RtcEventAudioNetworkAdaptationFec) {
// The test might be trivially passing for one of the two boolean values, so
// for safety's sake, we test both.
for (bool fec_enabled : {false, true}) {
auto runtime_config = absl::make_unique<AudioEncoderRuntimeConfig>();
runtime_config->enable_fec = fec_enabled;
TestRtcEventAudioNetworkAdaptation(std::move(runtime_config));
}
}
TEST_P(RtcEventLogEncoderTest, RtcEventAudioNetworkAdaptationDtx) {
// The test might be trivially passing for one of the two boolean values, so
// for safety's sake, we test both.
for (bool dtx_enabled : {false, true}) {
auto runtime_config = absl::make_unique<AudioEncoderRuntimeConfig>();
runtime_config->enable_dtx = dtx_enabled;
TestRtcEventAudioNetworkAdaptation(std::move(runtime_config));
}
}
TEST_P(RtcEventLogEncoderTest, RtcEventAudioNetworkAdaptationChannels) {
// The test might be trivially passing for one of the two possible values, so
// for safety's sake, we test both.
for (size_t channels : {1, 2}) {
auto runtime_config = absl::make_unique<AudioEncoderRuntimeConfig>();
runtime_config->num_channels = channels;
TestRtcEventAudioNetworkAdaptation(std::move(runtime_config));
}
}
TEST_P(RtcEventLogEncoderTest, RtcEventAudioNetworkAdaptationAll) {
const int bitrate_bps = rtc::checked_cast<int>(
prng_.Rand(0, std::numeric_limits<int32_t>::max()));
const int frame_length_ms = prng_.Rand(1, 1000);
const float plr = std::pow(0.5f, prng_.Rand(1, 8));
for (bool fec_enabled : {false, true}) {
for (bool dtx_enabled : {false, true}) {
for (size_t channels : {1, 2}) {
auto runtime_config = absl::make_unique<AudioEncoderRuntimeConfig>();
runtime_config->bitrate_bps = bitrate_bps;
runtime_config->frame_length_ms = frame_length_ms;
runtime_config->uplink_packet_loss_fraction = plr;
runtime_config->enable_fec = fec_enabled;
runtime_config->enable_dtx = dtx_enabled;
runtime_config->num_channels = channels;
TestRtcEventAudioNetworkAdaptation(std::move(runtime_config));
}
}
}
}
TEST_P(RtcEventLogEncoderTest, RtcEventAudioPlayout) {
uint32_t ssrc = prng_.Rand<uint32_t>();
std::unique_ptr<RtcEventAudioPlayout> event = gen_.NewAudioPlayout(ssrc);
history_.push_back(event->Copy());
std::string encoded = encoder_->EncodeBatch(history_.begin(), history_.end());
ASSERT_TRUE(parsed_log_.ParseString(encoded));
const auto& playout_events = parsed_log_.audio_playout_events();
ASSERT_EQ(playout_events.size(), 1u);
const auto playout_stream = playout_events.find(ssrc);
ASSERT_TRUE(playout_stream != playout_events.end());
ASSERT_EQ(playout_stream->second.size(), 1u);
LoggedAudioPlayoutEvent playout_event = playout_stream->second[0];
test::VerifyLoggedAudioPlayoutEvent(*event, playout_event);
}
TEST_P(RtcEventLogEncoderTest, RtcEventAudioReceiveStreamConfig) {
uint32_t ssrc = prng_.Rand<uint32_t>();
RtpHeaderExtensionMap extensions = gen_.NewRtpHeaderExtensionMap();
std::unique_ptr<RtcEventAudioReceiveStreamConfig> event =
gen_.NewAudioReceiveStreamConfig(ssrc, extensions);
history_.push_back(event->Copy());
std::string encoded = encoder_->EncodeBatch(history_.begin(), history_.end());
ASSERT_TRUE(parsed_log_.ParseString(encoded));
const auto& audio_recv_configs = parsed_log_.audio_recv_configs();
ASSERT_EQ(audio_recv_configs.size(), 1u);
test::VerifyLoggedAudioRecvConfig(*event, audio_recv_configs[0]);
}
TEST_P(RtcEventLogEncoderTest, RtcEventAudioSendStreamConfig) {
uint32_t ssrc = prng_.Rand<uint32_t>();
RtpHeaderExtensionMap extensions = gen_.NewRtpHeaderExtensionMap();
std::unique_ptr<RtcEventAudioSendStreamConfig> event =
gen_.NewAudioSendStreamConfig(ssrc, extensions);
history_.push_back(event->Copy());
std::string encoded = encoder_->EncodeBatch(history_.begin(), history_.end());
ASSERT_TRUE(parsed_log_.ParseString(encoded));
const auto& audio_send_configs = parsed_log_.audio_send_configs();
ASSERT_EQ(audio_send_configs.size(), 1u);
test::VerifyLoggedAudioSendConfig(*event, audio_send_configs[0]);
}
TEST_P(RtcEventLogEncoderTest, RtcEventBweUpdateDelayBased) {
std::unique_ptr<RtcEventBweUpdateDelayBased> event =
gen_.NewBweUpdateDelayBased();
history_.push_back(event->Copy());
std::string encoded = encoder_->EncodeBatch(history_.begin(), history_.end());
ASSERT_TRUE(parsed_log_.ParseString(encoded));
const auto& bwe_delay_updates = parsed_log_.bwe_delay_updates();
ASSERT_EQ(bwe_delay_updates.size(), 1u);
test::VerifyLoggedBweDelayBasedUpdate(*event, bwe_delay_updates[0]);
}
TEST_P(RtcEventLogEncoderTest, RtcEventBweUpdateLossBased) {
std::unique_ptr<RtcEventBweUpdateLossBased> event =
gen_.NewBweUpdateLossBased();
history_.push_back(event->Copy());
std::string encoded = encoder_->EncodeBatch(history_.begin(), history_.end());
ASSERT_TRUE(parsed_log_.ParseString(encoded));
const auto& bwe_loss_updates = parsed_log_.bwe_loss_updates();
ASSERT_EQ(bwe_loss_updates.size(), 1u);
test::VerifyLoggedBweLossBasedUpdate(*event, bwe_loss_updates[0]);
}
TEST_P(RtcEventLogEncoderTest, RtcEventIceCandidatePairConfig) {
std::unique_ptr<RtcEventIceCandidatePairConfig> event =
gen_.NewIceCandidatePairConfig();
history_.push_back(event->Copy());
std::string encoded = encoder_->EncodeBatch(history_.begin(), history_.end());
ASSERT_TRUE(parsed_log_.ParseString(encoded));
const auto& ice_candidate_pair_configs =
parsed_log_.ice_candidate_pair_configs();
ASSERT_EQ(ice_candidate_pair_configs.size(), 1u);
test::VerifyLoggedIceCandidatePairConfig(*event,
ice_candidate_pair_configs[0]);
}
TEST_P(RtcEventLogEncoderTest, RtcEventIceCandidatePair) {
std::unique_ptr<RtcEventIceCandidatePair> event = gen_.NewIceCandidatePair();
history_.push_back(event->Copy());
std::string encoded = encoder_->EncodeBatch(history_.begin(), history_.end());
ASSERT_TRUE(parsed_log_.ParseString(encoded));
const auto& ice_candidate_pair_events =
parsed_log_.ice_candidate_pair_events();
ASSERT_EQ(ice_candidate_pair_events.size(), 1u);
test::VerifyLoggedIceCandidatePairEvent(*event, ice_candidate_pair_events[0]);
}
TEST_P(RtcEventLogEncoderTest, RtcEventLoggingStarted) {
const int64_t timestamp_us = rtc::TimeMicros();
ASSERT_TRUE(parsed_log_.ParseString(encoder_->EncodeLogStart(timestamp_us)));
const auto& start_log_events = parsed_log_.start_log_events();
ASSERT_EQ(start_log_events.size(), 1u);
EXPECT_EQ(start_log_events[0].timestamp_us, timestamp_us);
}
TEST_P(RtcEventLogEncoderTest, RtcEventLoggingStopped) {
const int64_t timestamp_us = rtc::TimeMicros();
ASSERT_TRUE(parsed_log_.ParseString(encoder_->EncodeLogEnd(timestamp_us)));
const auto& stop_log_events = parsed_log_.stop_log_events();
ASSERT_EQ(stop_log_events.size(), 1u);
EXPECT_EQ(stop_log_events[0].timestamp_us, timestamp_us);
}
TEST_P(RtcEventLogEncoderTest, RtcEventProbeClusterCreated) {
std::unique_ptr<RtcEventProbeClusterCreated> event =
gen_.NewProbeClusterCreated();
history_.push_back(event->Copy());
std::string encoded = encoder_->EncodeBatch(history_.begin(), history_.end());
ASSERT_TRUE(parsed_log_.ParseString(encoded));
const auto& bwe_probe_cluster_created_events =
parsed_log_.bwe_probe_cluster_created_events();
ASSERT_EQ(bwe_probe_cluster_created_events.size(), 1u);
test::VerifyLoggedBweProbeClusterCreatedEvent(
*event, bwe_probe_cluster_created_events[0]);
}
TEST_P(RtcEventLogEncoderTest, RtcEventProbeResultFailure) {
std::unique_ptr<RtcEventProbeResultFailure> event =
gen_.NewProbeResultFailure();
history_.push_back(event->Copy());
std::string encoded = encoder_->EncodeBatch(history_.begin(), history_.end());
ASSERT_TRUE(parsed_log_.ParseString(encoded));
const auto& bwe_probe_failure_events = parsed_log_.bwe_probe_failure_events();
ASSERT_EQ(bwe_probe_failure_events.size(), 1u);
test::VerifyLoggedBweProbeFailureEvent(*event, bwe_probe_failure_events[0]);
}
TEST_P(RtcEventLogEncoderTest, RtcEventProbeResultSuccess) {
std::unique_ptr<RtcEventProbeResultSuccess> event =
gen_.NewProbeResultSuccess();
history_.push_back(event->Copy());
std::string encoded = encoder_->EncodeBatch(history_.begin(), history_.end());
ASSERT_TRUE(parsed_log_.ParseString(encoded));
const auto& bwe_probe_success_events = parsed_log_.bwe_probe_success_events();
ASSERT_EQ(bwe_probe_success_events.size(), 1u);
test::VerifyLoggedBweProbeSuccessEvent(*event, bwe_probe_success_events[0]);
}
TEST_P(RtcEventLogEncoderTest, RtcEventRtcpPacketIncoming) {
std::unique_ptr<RtcEventRtcpPacketIncoming> event =
gen_.NewRtcpPacketIncoming();
history_.push_back(event->Copy());
std::string encoded = encoder_->EncodeBatch(history_.begin(), history_.end());
ASSERT_TRUE(parsed_log_.ParseString(encoded));
const auto& incoming_rtcp_packets = parsed_log_.incoming_rtcp_packets();
ASSERT_EQ(incoming_rtcp_packets.size(), 1u);
test::VerifyLoggedRtcpPacketIncoming(*event, incoming_rtcp_packets[0]);
}
TEST_P(RtcEventLogEncoderTest, RtcEventRtcpPacketOutgoing) {
std::unique_ptr<RtcEventRtcpPacketOutgoing> event =
gen_.NewRtcpPacketOutgoing();
history_.push_back(event->Copy());
std::string encoded = encoder_->EncodeBatch(history_.begin(), history_.end());
ASSERT_TRUE(parsed_log_.ParseString(encoded));
const auto& outgoing_rtcp_packets = parsed_log_.outgoing_rtcp_packets();
ASSERT_EQ(outgoing_rtcp_packets.size(), 1u);
test::VerifyLoggedRtcpPacketOutgoing(*event, outgoing_rtcp_packets[0]);
}
TEST_P(RtcEventLogEncoderTest, RtcEventRtpPacketIncoming) {
uint32_t ssrc = prng_.Rand<uint32_t>();
RtpHeaderExtensionMap extension_map; // TODO(terelius): Test extensions too.
std::unique_ptr<RtcEventRtpPacketIncoming> event =
gen_.NewRtpPacketIncoming(ssrc, extension_map);
history_.push_back(event->Copy());
std::string encoded = encoder_->EncodeBatch(history_.begin(), history_.end());
ASSERT_TRUE(parsed_log_.ParseString(encoded));
const auto& incoming_rtp_packets_by_ssrc =
parsed_log_.incoming_rtp_packets_by_ssrc();
ASSERT_EQ(incoming_rtp_packets_by_ssrc.size(), 1u);
const auto& stream = incoming_rtp_packets_by_ssrc[0];
EXPECT_EQ(stream.ssrc, ssrc);
ASSERT_EQ(stream.incoming_packets.size(), 1u);
test::VerifyLoggedRtpPacketIncoming(*event, stream.incoming_packets[0]);
}
TEST_P(RtcEventLogEncoderTest, RtcEventRtpPacketOutgoing) {
uint32_t ssrc = prng_.Rand<uint32_t>();
RtpHeaderExtensionMap extension_map; // TODO(terelius): Test extensions too.
std::unique_ptr<RtcEventRtpPacketOutgoing> event =
gen_.NewRtpPacketOutgoing(ssrc, extension_map);
history_.push_back(event->Copy());
std::string encoded = encoder_->EncodeBatch(history_.begin(), history_.end());
ASSERT_TRUE(parsed_log_.ParseString(encoded));
const auto& outgoing_rtp_packets_by_ssrc =
parsed_log_.outgoing_rtp_packets_by_ssrc();
ASSERT_EQ(outgoing_rtp_packets_by_ssrc.size(), 1u);
const auto& stream = outgoing_rtp_packets_by_ssrc[0];
EXPECT_EQ(stream.ssrc, ssrc);
ASSERT_EQ(stream.outgoing_packets.size(), 1u);
test::VerifyLoggedRtpPacketOutgoing(*event, stream.outgoing_packets[0]);
}
TEST_P(RtcEventLogEncoderTest, RtcEventVideoReceiveStreamConfig) {
uint32_t ssrc = prng_.Rand<uint32_t>();
RtpHeaderExtensionMap extensions = gen_.NewRtpHeaderExtensionMap();
std::unique_ptr<RtcEventVideoReceiveStreamConfig> event =
gen_.NewVideoReceiveStreamConfig(ssrc, extensions);
history_.push_back(event->Copy());
std::string encoded = encoder_->EncodeBatch(history_.begin(), history_.end());
ASSERT_TRUE(parsed_log_.ParseString(encoded));
const auto& video_recv_configs = parsed_log_.video_recv_configs();
ASSERT_EQ(video_recv_configs.size(), 1u);
test::VerifyLoggedVideoRecvConfig(*event, video_recv_configs[0]);
}
TEST_P(RtcEventLogEncoderTest, RtcEventVideoSendStreamConfig) {
uint32_t ssrc = prng_.Rand<uint32_t>();
RtpHeaderExtensionMap extensions = gen_.NewRtpHeaderExtensionMap();
std::unique_ptr<RtcEventVideoSendStreamConfig> event =
gen_.NewVideoSendStreamConfig(ssrc, extensions);
history_.push_back(event->Copy());
std::string encoded = encoder_->EncodeBatch(history_.begin(), history_.end());
ASSERT_TRUE(parsed_log_.ParseString(encoded));
const auto& video_send_configs = parsed_log_.video_send_configs();
ASSERT_EQ(video_send_configs.size(), 1u);
test::VerifyLoggedVideoSendConfig(*event, video_send_configs[0]);
}
INSTANTIATE_TEST_CASE_P(RandomSeeds,
RtcEventLogEncoderTest,
::testing::Values(1, 2, 3, 4, 5));
} // namespace webrtc