Reland of "Log audio network adapter decisions in event log."

This was originally reviewed https://codereview.webrtc.org/2559953002/

It was reverted due to a bug in the original CL, see https://codereview.webrtc.org/2631703002/

This CL is to fix and reland.

BUG=webrtc:6845

Review-Url: https://codereview.webrtc.org/2644863002
Cr-Commit-Position: refs/heads/master@{#16242}
This commit is contained in:
minyue 2017-01-24 04:54:59 -08:00 committed by Commit bot
parent 35a32700fc
commit 4b7c952376
21 changed files with 592 additions and 3 deletions

View File

@ -42,6 +42,7 @@ rtc_static_library("rtc_event_log_impl") {
":rtc_event_log_api",
"..:webrtc_common",
"../call:call_interfaces",
"../modules/audio_coding:audio_network_adaptor",
"../modules/rtp_rtcp",
]

View File

@ -1,6 +1,7 @@
include_rules = [
"+webrtc/base",
"+webrtc/call",
"+webrtc/modules/audio_coding/audio_network_adaptor",
"+webrtc/modules/rtp_rtcp",
"+webrtc/system_wrappers",
]

View File

@ -58,6 +58,8 @@ class MockRtcEventLog : public RtcEventLog {
void(int32_t bitrate,
uint8_t fraction_loss,
int32_t total_packets));
MOCK_METHOD1(LogAudioNetworkAdaptation,
void(const AudioNetworkAdaptor::EncoderRuntimeConfig& config));
};
} // namespace webrtc

View File

@ -77,6 +77,8 @@ class RtcEventLogImpl final : public RtcEventLog {
void LogBwePacketLossEvent(int32_t bitrate,
uint8_t fraction_loss,
int32_t total_packets) override;
void LogAudioNetworkAdaptation(
const AudioNetworkAdaptor::EncoderRuntimeConfig& config) override;
private:
void StoreEvent(std::unique_ptr<rtclog::Event>* event);
@ -434,6 +436,29 @@ void RtcEventLogImpl::LogBwePacketLossEvent(int32_t bitrate,
StoreEvent(&event);
}
void RtcEventLogImpl::LogAudioNetworkAdaptation(
const AudioNetworkAdaptor::EncoderRuntimeConfig& config) {
std::unique_ptr<rtclog::Event> event(new rtclog::Event());
event->set_timestamp_us(rtc::TimeMicros());
event->set_type(rtclog::Event::AUDIO_NETWORK_ADAPTATION_EVENT);
auto audio_network_adaptation = event->mutable_audio_network_adaptation();
if (config.bitrate_bps)
audio_network_adaptation->set_bitrate_bps(*config.bitrate_bps);
if (config.frame_length_ms)
audio_network_adaptation->set_frame_length_ms(*config.frame_length_ms);
if (config.uplink_packet_loss_fraction) {
audio_network_adaptation->set_uplink_packet_loss_fraction(
*config.uplink_packet_loss_fraction);
}
if (config.enable_fec)
audio_network_adaptation->set_enable_fec(*config.enable_fec);
if (config.enable_dtx)
audio_network_adaptation->set_enable_dtx(*config.enable_dtx);
if (config.num_channels)
audio_network_adaptation->set_num_channels(*config.num_channels);
StoreEvent(&event);
}
void RtcEventLogImpl::StoreEvent(std::unique_ptr<rtclog::Event>* event) {
if (!event_queue_.Insert(event)) {
LOG(LS_ERROR) << "WebRTC event log queue full. Dropping event.";

View File

@ -17,6 +17,7 @@
#include "webrtc/base/platform_file.h"
#include "webrtc/call/audio_receive_stream.h"
#include "webrtc/call/audio_send_stream.h"
#include "webrtc/modules/audio_coding/audio_network_adaptor/include/audio_network_adaptor.h"
#include "webrtc/video_receive_stream.h"
#include "webrtc/video_send_stream.h"
@ -114,6 +115,10 @@ class RtcEventLog {
uint8_t fraction_loss,
int32_t total_packets) = 0;
// Logs audio encoder re-configuration driven by audio network adaptor.
virtual void LogAudioNetworkAdaptation(
const AudioNetworkAdaptor::EncoderRuntimeConfig& config) = 0;
// Reads an RtcEventLog file and returns true when reading was successful.
// The result is stored in the given EventStream object.
// The order of the events in the EventStream is implementation defined.
@ -155,6 +160,8 @@ class RtcEventLogNullImpl final : public RtcEventLog {
void LogBwePacketLossEvent(int32_t bitrate,
uint8_t fraction_loss,
int32_t total_packets) override {}
void LogAudioNetworkAdaptation(
const AudioNetworkAdaptor::EncoderRuntimeConfig& config) override{};
};
} // namespace webrtc

View File

@ -37,6 +37,7 @@ message Event {
VIDEO_SENDER_CONFIG_EVENT = 9;
AUDIO_RECEIVER_CONFIG_EVENT = 10;
AUDIO_SENDER_CONFIG_EVENT = 11;
AUDIO_NETWORK_ADAPTATION_EVENT = 16;
}
// required - Indicates the type of this event
@ -65,6 +66,9 @@ message Event {
// optional - but required if type == AUDIO_SENDER_CONFIG_EVENT
optional AudioSendConfig audio_sender_config = 11;
// optional - but required if type == AUDIO_NETWORK_ADAPTATION_EVENT
optional AudioNetworkAdaptation audio_network_adaptation = 16;
}
message RtpPacket {
@ -227,3 +231,24 @@ message AudioSendConfig {
// RTP header extensions used for the outgoing audio stream.
repeated RtpHeaderExtension header_extensions = 2;
}
message AudioNetworkAdaptation {
// Bit rate that the audio encoder is operating at.
optional int32 bitrate_bps = 1;
// Frame length that each encoded audio packet consists of.
optional int32 frame_length_ms = 2;
// Packet loss fraction that the encoder's forward error correction (FEC) is
// optimized for.
optional float uplink_packet_loss_fraction = 3;
// Whether forward error correction (FEC) is turned on or off.
optional bool enable_fec = 4;
// Whether discontinuous transmission (DTX) is turned on or off.
optional bool enable_dtx = 5;
// Number of audio channels that each encoded packet consists of.
optional uint32 num_channels = 6;
}

View File

@ -79,6 +79,8 @@ ParsedRtcEventLog::EventType GetRuntimeEventType(
return ParsedRtcEventLog::EventType::AUDIO_RECEIVER_CONFIG_EVENT;
case rtclog::Event::AUDIO_SENDER_CONFIG_EVENT:
return ParsedRtcEventLog::EventType::AUDIO_SENDER_CONFIG_EVENT;
case rtclog::Event::AUDIO_NETWORK_ADAPTATION_EVENT:
return ParsedRtcEventLog::EventType::AUDIO_NETWORK_ADAPTATION_EVENT;
}
RTC_NOTREACHED();
return ParsedRtcEventLog::EventType::UNKNOWN_EVENT;
@ -454,4 +456,29 @@ void ParsedRtcEventLog::GetBwePacketLossEvent(size_t index,
}
}
void ParsedRtcEventLog::GetAudioNetworkAdaptation(
size_t index,
AudioNetworkAdaptor::EncoderRuntimeConfig* config) const {
RTC_CHECK_LT(index, GetNumberOfEvents());
const rtclog::Event& event = events_[index];
RTC_CHECK(event.has_type());
RTC_CHECK_EQ(event.type(), rtclog::Event::AUDIO_NETWORK_ADAPTATION_EVENT);
RTC_CHECK(event.has_audio_network_adaptation());
const rtclog::AudioNetworkAdaptation& ana_event =
event.audio_network_adaptation();
if (ana_event.has_bitrate_bps())
config->bitrate_bps = rtc::Optional<int>(ana_event.bitrate_bps());
if (ana_event.has_enable_fec())
config->enable_fec = rtc::Optional<bool>(ana_event.enable_fec());
if (ana_event.has_enable_dtx())
config->enable_dtx = rtc::Optional<bool>(ana_event.enable_dtx());
if (ana_event.has_frame_length_ms())
config->frame_length_ms = rtc::Optional<int>(ana_event.frame_length_ms());
if (ana_event.has_num_channels())
config->num_channels = rtc::Optional<size_t>(ana_event.num_channels());
if (ana_event.has_uplink_packet_loss_fraction())
config->uplink_packet_loss_fraction =
rtc::Optional<float>(ana_event.uplink_packet_loss_fraction());
}
} // namespace webrtc

View File

@ -47,7 +47,8 @@ class ParsedRtcEventLog {
VIDEO_RECEIVER_CONFIG_EVENT = 8,
VIDEO_SENDER_CONFIG_EVENT = 9,
AUDIO_RECEIVER_CONFIG_EVENT = 10,
AUDIO_SENDER_CONFIG_EVENT = 11
AUDIO_SENDER_CONFIG_EVENT = 11,
AUDIO_NETWORK_ADAPTATION_EVENT = 16
};
// Reads an RtcEventLog file and returns true if parsing was successful.
@ -123,6 +124,13 @@ class ParsedRtcEventLog {
uint8_t* fraction_loss,
int32_t* total_packets) const;
// Reads a audio network adaptation event to a (non-NULL)
// AudioNetworkAdaptor::EncoderRuntimeConfig struct. Only the fields that are
// stored in the protobuf will be written.
void GetAudioNetworkAdaptation(
size_t index,
AudioNetworkAdaptor::EncoderRuntimeConfig* config) const;
private:
std::vector<rtclog::Event> events_;
};

View File

@ -228,6 +228,19 @@ void GenerateAudioSendConfig(uint32_t extensions_bitvector,
}
}
void GenerateAudioNetworkAdaptation(
uint32_t extensions_bitvector,
AudioNetworkAdaptor::EncoderRuntimeConfig* config,
Random* prng) {
config->bitrate_bps = rtc::Optional<int>(prng->Rand(0, 3000000));
config->enable_fec = rtc::Optional<bool>(prng->Rand<bool>());
config->enable_dtx = rtc::Optional<bool>(prng->Rand<bool>());
config->frame_length_ms = rtc::Optional<int>(prng->Rand(10, 120));
config->num_channels = rtc::Optional<size_t>(prng->Rand(1, 2));
config->uplink_packet_loss_fraction =
rtc::Optional<float>(prng->Rand<float>());
}
// Test for the RtcEventLog class. Dumps some RTP packets and other events
// to disk, then reads them back to see if they match.
void LogSessionAndReadBack(size_t rtp_count,
@ -604,6 +617,22 @@ class VideoSendConfigReadWriteTest : public ConfigReadWriteTest {
VideoSendStream::Config config;
};
class AudioNetworkAdaptationReadWriteTest : public ConfigReadWriteTest {
public:
void GenerateConfig(uint32_t extensions_bitvector) override {
GenerateAudioNetworkAdaptation(extensions_bitvector, &config, &prng);
}
void LogConfig(RtcEventLog* event_log) override {
event_log->LogAudioNetworkAdaptation(config);
}
void VerifyConfig(const ParsedRtcEventLog& parsed_log,
size_t index) override {
RtcEventLogTestHelper::VerifyAudioNetworkAdaptation(parsed_log, index,
config);
}
AudioNetworkAdaptor::EncoderRuntimeConfig config;
};
TEST(RtcEventLogTest, LogAudioReceiveConfig) {
AudioReceiveConfigReadWriteTest test;
test.DoTest();
@ -623,4 +652,10 @@ TEST(RtcEventLogTest, LogVideoSendConfig) {
VideoSendConfigReadWriteTest test;
test.DoTest();
}
TEST(RtcEventLogTest, LogAudioNetworkAdaptation) {
AudioNetworkAdaptationReadWriteTest test;
test.DoTest();
}
} // namespace webrtc

View File

@ -461,6 +461,21 @@ void RtcEventLogTestHelper::VerifyBweLossEvent(
EXPECT_EQ(total_packets, parsed_total_packets);
}
void RtcEventLogTestHelper::VerifyAudioNetworkAdaptation(
const ParsedRtcEventLog& parsed_log,
size_t index,
const AudioNetworkAdaptor::EncoderRuntimeConfig& config) {
AudioNetworkAdaptor::EncoderRuntimeConfig parsed_config;
parsed_log.GetAudioNetworkAdaptation(index, &parsed_config);
EXPECT_EQ(config.bitrate_bps, parsed_config.bitrate_bps);
EXPECT_EQ(config.enable_dtx, parsed_config.enable_dtx);
EXPECT_EQ(config.enable_fec, parsed_config.enable_fec);
EXPECT_EQ(config.frame_length_ms, parsed_config.frame_length_ms);
EXPECT_EQ(config.num_channels, parsed_config.num_channels);
EXPECT_EQ(config.uplink_packet_loss_fraction,
parsed_config.uplink_packet_loss_fraction);
}
void RtcEventLogTestHelper::VerifyLogStartEvent(
const ParsedRtcEventLog& parsed_log,
size_t index) {

View File

@ -56,6 +56,11 @@ class RtcEventLogTestHelper {
uint8_t fraction_loss,
int32_t total_packets);
static void VerifyAudioNetworkAdaptation(
const ParsedRtcEventLog& parsed_log,
size_t index,
const AudioNetworkAdaptor::EncoderRuntimeConfig& config);
static void VerifyLogStartEvent(const ParsedRtcEventLog& parsed_log,
size_t index);
static void VerifyLogEndEvent(const ParsedRtcEventLog& parsed_log,

View File

@ -914,6 +914,8 @@ rtc_static_library("audio_network_adaptor") {
"audio_network_adaptor/debug_dump_writer.h",
"audio_network_adaptor/dtx_controller.cc",
"audio_network_adaptor/dtx_controller.h",
"audio_network_adaptor/event_log_writer.cc",
"audio_network_adaptor/event_log_writer.h",
"audio_network_adaptor/fec_controller.cc",
"audio_network_adaptor/fec_controller.h",
"audio_network_adaptor/frame_length_controller.cc",
@ -925,6 +927,7 @@ rtc_static_library("audio_network_adaptor") {
"../..:webrtc_common",
"../../base:rtc_base_approved",
"../../common_audio",
"../../logging:rtc_event_log_api",
"../../system_wrappers",
]
@ -935,6 +938,11 @@ rtc_static_library("audio_network_adaptor") {
]
defines = [ "WEBRTC_AUDIO_NETWORK_ADAPTOR_DEBUG_DUMP" ]
}
if (!build_with_chromium && is_clang) {
# Suppress warnings from the Chromium Clang plugin (bugs.webrtc.org/163).
suppressed_configs += [ "//build/config/clang:find_bad_constructs" ]
}
}
rtc_static_library("neteq") {
@ -1935,6 +1943,7 @@ if (rtc_include_tests) {
"audio_network_adaptor/channel_controller_unittest.cc",
"audio_network_adaptor/controller_manager_unittest.cc",
"audio_network_adaptor/dtx_controller_unittest.cc",
"audio_network_adaptor/event_log_writer_unittest.cc",
"audio_network_adaptor/fec_controller_unittest.cc",
"audio_network_adaptor/frame_length_controller_unittest.cc",
"audio_network_adaptor/mock/mock_controller.h",

View File

@ -12,8 +12,16 @@
#include <utility>
#include "webrtc/base/logging.h"
namespace webrtc {
namespace {
constexpr int kEventLogMinBitrateChangeBps = 5000;
constexpr float kEventLogMinBitrateChangeFraction = 0.25;
constexpr float kEventLogMinPacketLossChangeFraction = 0.5;
} // namespace
AudioNetworkAdaptorImpl::Config::Config()
: event_log(nullptr), clock(nullptr){};
@ -25,7 +33,14 @@ AudioNetworkAdaptorImpl::AudioNetworkAdaptorImpl(
std::unique_ptr<DebugDumpWriter> debug_dump_writer)
: config_(config),
controller_manager_(std::move(controller_manager)),
debug_dump_writer_(std::move(debug_dump_writer)) {
debug_dump_writer_(std::move(debug_dump_writer)),
event_log_writer_(
config.event_log
? new EventLogWriter(config.event_log,
kEventLogMinBitrateChangeBps,
kEventLogMinBitrateChangeFraction,
kEventLogMinPacketLossChangeFraction)
: nullptr) {
RTC_DCHECK(controller_manager_);
}
@ -68,11 +83,13 @@ AudioNetworkAdaptorImpl::GetEncoderRuntimeConfig() {
controller_manager_->GetSortedControllers(last_metrics_))
controller->MakeDecision(last_metrics_, &config);
// TODO(minyue): Add debug dumping.
if (debug_dump_writer_)
debug_dump_writer_->DumpEncoderRuntimeConfig(
config, config_.clock->TimeInMilliseconds());
if (event_log_writer_)
event_log_writer_->MaybeLogEncoderConfig(config);
return config;
}

View File

@ -17,6 +17,7 @@
#include "webrtc/modules/audio_coding/audio_network_adaptor/controller.h"
#include "webrtc/modules/audio_coding/audio_network_adaptor/controller_manager.h"
#include "webrtc/modules/audio_coding/audio_network_adaptor/debug_dump_writer.h"
#include "webrtc/modules/audio_coding/audio_network_adaptor/event_log_writer.h"
#include "webrtc/modules/audio_coding/audio_network_adaptor/include/audio_network_adaptor.h"
#include "webrtc/system_wrappers/include/clock.h"
@ -65,6 +66,8 @@ class AudioNetworkAdaptorImpl final : public AudioNetworkAdaptor {
std::unique_ptr<DebugDumpWriter> debug_dump_writer_;
const std::unique_ptr<EventLogWriter> event_log_writer_;
Controller::NetworkMetrics last_metrics_;
RTC_DISALLOW_COPY_AND_ASSIGN(AudioNetworkAdaptorImpl);

View File

@ -11,6 +11,7 @@
#include <utility>
#include <vector>
#include "webrtc/logging/rtc_event_log/mock/mock_rtc_event_log.h"
#include "webrtc/modules/audio_coding/audio_network_adaptor/audio_network_adaptor_impl.h"
#include "webrtc/modules/audio_coding/audio_network_adaptor/mock/mock_controller.h"
#include "webrtc/modules/audio_coding/audio_network_adaptor/mock/mock_controller_manager.h"
@ -52,6 +53,7 @@ struct AudioNetworkAdaptorStates {
std::unique_ptr<AudioNetworkAdaptorImpl> audio_network_adaptor;
std::vector<std::unique_ptr<MockController>> mock_controllers;
std::unique_ptr<SimulatedClock> simulated_clock;
std::unique_ptr<MockRtcEventLog> event_log;
MockDebugDumpWriter* mock_debug_dump_writer;
};
@ -76,6 +78,7 @@ AudioNetworkAdaptorStates CreateAudioNetworkAdaptor() {
.WillRepeatedly(Return(controllers));
states.simulated_clock.reset(new SimulatedClock(kClockInitialTimeMs * 1000));
states.event_log.reset(new NiceMock<MockRtcEventLog>());
auto debug_dump_writer =
std::unique_ptr<MockDebugDumpWriter>(new NiceMock<MockDebugDumpWriter>());
@ -84,6 +87,7 @@ AudioNetworkAdaptorStates CreateAudioNetworkAdaptor() {
AudioNetworkAdaptorImpl::Config config;
config.clock = states.simulated_clock.get();
config.event_log = states.event_log.get();
// AudioNetworkAdaptorImpl governs the lifetime of controller manager.
states.audio_network_adaptor.reset(new AudioNetworkAdaptorImpl(
config,
@ -205,4 +209,20 @@ TEST(AudioNetworkAdaptorImplTest,
states.audio_network_adaptor->SetOverhead(kOverhead);
}
TEST(AudioNetworkAdaptorImplTest, LogRuntimeConfigOnGetEncoderRuntimeConfig) {
auto states = CreateAudioNetworkAdaptor();
AudioNetworkAdaptor::EncoderRuntimeConfig config;
config.bitrate_bps = rtc::Optional<int>(32000);
config.enable_fec = rtc::Optional<bool>(true);
EXPECT_CALL(*states.mock_controllers[0], MakeDecision(_, _))
.WillOnce(SetArgPointee<1>(config));
EXPECT_CALL(*states.event_log,
LogAudioNetworkAdaptation(EncoderRuntimeConfigIs(config)))
.Times(1);
states.audio_network_adaptor->GetEncoderRuntimeConfig();
}
} // namespace webrtc

View File

@ -0,0 +1,68 @@
/*
* Copyright (c) 2016 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 <math.h>
#include <algorithm>
#include "webrtc/logging/rtc_event_log/rtc_event_log.h"
#include "webrtc/modules/audio_coding/audio_network_adaptor/event_log_writer.h"
namespace webrtc {
EventLogWriter::EventLogWriter(RtcEventLog* event_log,
int min_bitrate_change_bps,
float min_bitrate_change_fraction,
float min_packet_loss_change_fraction)
: event_log_(event_log),
min_bitrate_change_bps_(min_bitrate_change_bps),
min_bitrate_change_fraction_(min_bitrate_change_fraction),
min_packet_loss_change_fraction_(min_packet_loss_change_fraction) {
RTC_DCHECK(event_log_);
}
EventLogWriter::~EventLogWriter() = default;
void EventLogWriter::MaybeLogEncoderConfig(
const AudioNetworkAdaptor::EncoderRuntimeConfig& config) {
if (last_logged_config_.num_channels != config.num_channels)
return LogEncoderConfig(config);
if (last_logged_config_.enable_dtx != config.enable_dtx)
return LogEncoderConfig(config);
if (last_logged_config_.enable_fec != config.enable_fec)
return LogEncoderConfig(config);
if (last_logged_config_.frame_length_ms != config.frame_length_ms)
return LogEncoderConfig(config);
if ((!last_logged_config_.bitrate_bps && config.bitrate_bps) ||
(last_logged_config_.bitrate_bps && config.bitrate_bps &&
std::abs(*last_logged_config_.bitrate_bps - *config.bitrate_bps) >=
std::min(static_cast<int>(*last_logged_config_.bitrate_bps *
min_bitrate_change_fraction_),
min_bitrate_change_bps_))) {
return LogEncoderConfig(config);
}
if ((!last_logged_config_.uplink_packet_loss_fraction &&
config.uplink_packet_loss_fraction) ||
(last_logged_config_.uplink_packet_loss_fraction &&
config.uplink_packet_loss_fraction &&
fabs(*last_logged_config_.uplink_packet_loss_fraction -
*config.uplink_packet_loss_fraction) >=
min_packet_loss_change_fraction_ *
*last_logged_config_.uplink_packet_loss_fraction)) {
return LogEncoderConfig(config);
}
}
void EventLogWriter::LogEncoderConfig(
const AudioNetworkAdaptor::EncoderRuntimeConfig& config) {
event_log_->LogAudioNetworkAdaptation(config);
last_logged_config_ = config;
}
} // namespace webrtc

View File

@ -0,0 +1,44 @@
/*
* Copyright (c) 2016 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.
*/
#ifndef WEBRTC_MODULES_AUDIO_CODING_AUDIO_NETWORK_ADAPTOR_EVENT_LOG_WRITER_H_
#define WEBRTC_MODULES_AUDIO_CODING_AUDIO_NETWORK_ADAPTOR_EVENT_LOG_WRITER_H_
#include "webrtc/base/constructormagic.h"
#include "webrtc/modules/audio_coding/audio_network_adaptor/include/audio_network_adaptor.h"
namespace webrtc {
class RtcEventLog;
class EventLogWriter final {
public:
EventLogWriter(RtcEventLog* event_log,
int min_bitrate_change_bps,
float min_bitrate_change_fraction,
float min_packet_loss_change_fraction);
~EventLogWriter();
void MaybeLogEncoderConfig(
const AudioNetworkAdaptor::EncoderRuntimeConfig& config);
private:
void LogEncoderConfig(
const AudioNetworkAdaptor::EncoderRuntimeConfig& config);
RtcEventLog* const event_log_;
const int min_bitrate_change_bps_;
const float min_bitrate_change_fraction_;
const float min_packet_loss_change_fraction_;
AudioNetworkAdaptor::EncoderRuntimeConfig last_logged_config_;
RTC_DISALLOW_COPY_AND_ASSIGN(EventLogWriter);
};
} // namespace webrtc
#endif // WEBRTC_MODULES_AUDIO_CODING_AUDIO_NETWORK_ADAPTOR_EVENT_LOG_WRITER_H_

View File

@ -0,0 +1,265 @@
/*
* Copyright (c) 2016 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 <memory>
#include "webrtc/logging/rtc_event_log/mock/mock_rtc_event_log.h"
#include "webrtc/modules/audio_coding/audio_network_adaptor/event_log_writer.h"
#include "webrtc/test/gtest.h"
namespace webrtc {
namespace {
constexpr int kMinBitrateChangeBps = 5000;
constexpr float kMinPacketLossChangeFraction = 0.5;
constexpr float kMinBitrateChangeFraction = 0.25;
constexpr int kHighBitrateBps = 70000;
constexpr int kLowBitrateBps = 10000;
constexpr int kFrameLengthMs = 60;
constexpr bool kEnableFec = true;
constexpr bool kEnableDtx = true;
constexpr float kPacketLossFraction = 0.05f;
constexpr size_t kNumChannels = 1;
MATCHER_P(EncoderRuntimeConfigIs, config, "") {
return arg.bitrate_bps == config.bitrate_bps &&
arg.frame_length_ms == config.frame_length_ms &&
arg.uplink_packet_loss_fraction ==
config.uplink_packet_loss_fraction &&
arg.enable_fec == config.enable_fec &&
arg.enable_dtx == config.enable_dtx &&
arg.num_channels == config.num_channels;
}
struct EventLogWriterStates {
std::unique_ptr<EventLogWriter> event_log_writer;
std::unique_ptr<testing::StrictMock<MockRtcEventLog>> event_log;
AudioNetworkAdaptor::EncoderRuntimeConfig runtime_config;
};
EventLogWriterStates CreateEventLogWriter() {
EventLogWriterStates state;
state.event_log.reset(new testing::StrictMock<MockRtcEventLog>());
state.event_log_writer.reset(new EventLogWriter(
state.event_log.get(), kMinBitrateChangeBps, kMinBitrateChangeFraction,
kMinPacketLossChangeFraction));
state.runtime_config.bitrate_bps = rtc::Optional<int>(kHighBitrateBps);
state.runtime_config.frame_length_ms = rtc::Optional<int>(kFrameLengthMs);
state.runtime_config.uplink_packet_loss_fraction =
rtc::Optional<float>(kPacketLossFraction);
state.runtime_config.enable_fec = rtc::Optional<bool>(kEnableFec);
state.runtime_config.enable_dtx = rtc::Optional<bool>(kEnableDtx);
state.runtime_config.num_channels = rtc::Optional<size_t>(kNumChannels);
return state;
}
} // namespace
TEST(EventLogWriterTest, FirstConfigIsLogged) {
auto state = CreateEventLogWriter();
EXPECT_CALL(
*state.event_log,
LogAudioNetworkAdaptation(EncoderRuntimeConfigIs(state.runtime_config)))
.Times(1);
state.event_log_writer->MaybeLogEncoderConfig(state.runtime_config);
}
TEST(EventLogWriterTest, SameConfigIsNotLogged) {
auto state = CreateEventLogWriter();
EXPECT_CALL(
*state.event_log,
LogAudioNetworkAdaptation(EncoderRuntimeConfigIs(state.runtime_config)))
.Times(1);
state.event_log_writer->MaybeLogEncoderConfig(state.runtime_config);
state.event_log_writer->MaybeLogEncoderConfig(state.runtime_config);
}
TEST(EventLogWriterTest, LogFecStateChange) {
auto state = CreateEventLogWriter();
EXPECT_CALL(
*state.event_log,
LogAudioNetworkAdaptation(EncoderRuntimeConfigIs(state.runtime_config)))
.Times(1);
state.event_log_writer->MaybeLogEncoderConfig(state.runtime_config);
state.runtime_config.enable_fec = rtc::Optional<bool>(!kEnableFec);
EXPECT_CALL(
*state.event_log,
LogAudioNetworkAdaptation(EncoderRuntimeConfigIs(state.runtime_config)))
.Times(1);
state.event_log_writer->MaybeLogEncoderConfig(state.runtime_config);
}
TEST(EventLogWriterTest, LogDtxStateChange) {
auto state = CreateEventLogWriter();
EXPECT_CALL(
*state.event_log,
LogAudioNetworkAdaptation(EncoderRuntimeConfigIs(state.runtime_config)))
.Times(1);
state.event_log_writer->MaybeLogEncoderConfig(state.runtime_config);
state.runtime_config.enable_dtx = rtc::Optional<bool>(!kEnableDtx);
EXPECT_CALL(
*state.event_log,
LogAudioNetworkAdaptation(EncoderRuntimeConfigIs(state.runtime_config)))
.Times(1);
state.event_log_writer->MaybeLogEncoderConfig(state.runtime_config);
}
TEST(EventLogWriterTest, LogChannelChange) {
auto state = CreateEventLogWriter();
EXPECT_CALL(
*state.event_log,
LogAudioNetworkAdaptation(EncoderRuntimeConfigIs(state.runtime_config)))
.Times(1);
state.event_log_writer->MaybeLogEncoderConfig(state.runtime_config);
state.runtime_config.num_channels = rtc::Optional<size_t>(kNumChannels + 1);
EXPECT_CALL(
*state.event_log,
LogAudioNetworkAdaptation(EncoderRuntimeConfigIs(state.runtime_config)))
.Times(1);
state.event_log_writer->MaybeLogEncoderConfig(state.runtime_config);
}
TEST(EventLogWriterTest, LogFrameLengthChange) {
auto state = CreateEventLogWriter();
EXPECT_CALL(
*state.event_log,
LogAudioNetworkAdaptation(EncoderRuntimeConfigIs(state.runtime_config)))
.Times(1);
state.event_log_writer->MaybeLogEncoderConfig(state.runtime_config);
state.runtime_config.frame_length_ms = rtc::Optional<int>(20);
EXPECT_CALL(
*state.event_log,
LogAudioNetworkAdaptation(EncoderRuntimeConfigIs(state.runtime_config)))
.Times(1);
state.event_log_writer->MaybeLogEncoderConfig(state.runtime_config);
}
TEST(EventLogWriterTest, DoNotLogSmallBitrateChange) {
auto state = CreateEventLogWriter();
EXPECT_CALL(
*state.event_log,
LogAudioNetworkAdaptation(EncoderRuntimeConfigIs(state.runtime_config)))
.Times(1);
state.event_log_writer->MaybeLogEncoderConfig(state.runtime_config);
state.runtime_config.bitrate_bps =
rtc::Optional<int>(kHighBitrateBps + kMinBitrateChangeBps - 1);
state.event_log_writer->MaybeLogEncoderConfig(state.runtime_config);
}
TEST(EventLogWriterTest, LogLargeBitrateChange) {
auto state = CreateEventLogWriter();
EXPECT_CALL(
*state.event_log,
LogAudioNetworkAdaptation(EncoderRuntimeConfigIs(state.runtime_config)))
.Times(1);
state.event_log_writer->MaybeLogEncoderConfig(state.runtime_config);
// At high bitrate, the min fraction rule requires a larger change than the
// min change rule. We make sure that the min change rule applies.
RTC_DCHECK_GT(kHighBitrateBps * kMinBitrateChangeFraction,
kMinBitrateChangeBps);
state.runtime_config.bitrate_bps =
rtc::Optional<int>(kHighBitrateBps + kMinBitrateChangeBps);
EXPECT_CALL(
*state.event_log,
LogAudioNetworkAdaptation(EncoderRuntimeConfigIs(state.runtime_config)))
.Times(1);
state.event_log_writer->MaybeLogEncoderConfig(state.runtime_config);
}
TEST(EventLogWriterTest, LogMinBitrateChangeFractionOnLowBitrateChange) {
auto state = CreateEventLogWriter();
state.runtime_config.bitrate_bps = rtc::Optional<int>(kLowBitrateBps);
EXPECT_CALL(
*state.event_log,
LogAudioNetworkAdaptation(EncoderRuntimeConfigIs(state.runtime_config)))
.Times(1);
state.event_log_writer->MaybeLogEncoderConfig(state.runtime_config);
// At high bitrate, the min change rule requires a larger change than the min
// fraction rule. We make sure that the min fraction rule applies.
state.runtime_config.bitrate_bps = rtc::Optional<int>(
kLowBitrateBps + kLowBitrateBps * kMinBitrateChangeFraction);
EXPECT_CALL(
*state.event_log,
LogAudioNetworkAdaptation(EncoderRuntimeConfigIs(state.runtime_config)))
.Times(1);
state.event_log_writer->MaybeLogEncoderConfig(state.runtime_config);
}
TEST(EventLogWriterTest, DoNotLogSmallPacketLossFractionChange) {
auto state = CreateEventLogWriter();
EXPECT_CALL(
*state.event_log,
LogAudioNetworkAdaptation(EncoderRuntimeConfigIs(state.runtime_config)))
.Times(1);
state.event_log_writer->MaybeLogEncoderConfig(state.runtime_config);
state.runtime_config.uplink_packet_loss_fraction = rtc::Optional<float>(
kPacketLossFraction + kMinPacketLossChangeFraction * kPacketLossFraction -
0.001f);
state.event_log_writer->MaybeLogEncoderConfig(state.runtime_config);
}
TEST(EventLogWriterTest, LogLargePacketLossFractionChange) {
auto state = CreateEventLogWriter();
EXPECT_CALL(
*state.event_log,
LogAudioNetworkAdaptation(EncoderRuntimeConfigIs(state.runtime_config)))
.Times(1);
state.event_log_writer->MaybeLogEncoderConfig(state.runtime_config);
state.runtime_config.uplink_packet_loss_fraction = rtc::Optional<float>(
kPacketLossFraction + kMinPacketLossChangeFraction * kPacketLossFraction);
EXPECT_CALL(
*state.event_log,
LogAudioNetworkAdaptation(EncoderRuntimeConfigIs(state.runtime_config)))
.Times(1);
state.event_log_writer->MaybeLogEncoderConfig(state.runtime_config);
}
TEST(EventLogWriterTest, LogJustOnceOnMultipleChanges) {
auto state = CreateEventLogWriter();
EXPECT_CALL(
*state.event_log,
LogAudioNetworkAdaptation(EncoderRuntimeConfigIs(state.runtime_config)))
.Times(1);
state.event_log_writer->MaybeLogEncoderConfig(state.runtime_config);
state.runtime_config.uplink_packet_loss_fraction = rtc::Optional<float>(
kPacketLossFraction + kMinPacketLossChangeFraction * kPacketLossFraction);
state.runtime_config.frame_length_ms = rtc::Optional<int>(20);
EXPECT_CALL(
*state.event_log,
LogAudioNetworkAdaptation(EncoderRuntimeConfigIs(state.runtime_config)))
.Times(1);
state.event_log_writer->MaybeLogEncoderConfig(state.runtime_config);
}
TEST(EventLogWriterTest, LogAfterGradualChange) {
auto state = CreateEventLogWriter();
EXPECT_CALL(
*state.event_log,
LogAudioNetworkAdaptation(EncoderRuntimeConfigIs(state.runtime_config)))
.Times(1);
state.event_log_writer->MaybeLogEncoderConfig(state.runtime_config);
state.runtime_config.bitrate_bps =
rtc::Optional<int>(kHighBitrateBps + kMinBitrateChangeBps);
EXPECT_CALL(
*state.event_log,
LogAudioNetworkAdaptation(EncoderRuntimeConfigIs(state.runtime_config)))
.Times(1);
for (int bitrate_bps = kHighBitrateBps;
bitrate_bps <= kHighBitrateBps + kMinBitrateChangeBps; bitrate_bps++) {
state.runtime_config.bitrate_bps = rtc::Optional<int>(bitrate_bps);
state.event_log_writer->MaybeLogEncoderConfig(state.runtime_config);
}
}
} // namespace webrtc

View File

@ -205,6 +205,7 @@ if (rtc_enable_protobuf) {
"../call:call_interfaces",
"../logging:rtc_event_log_impl",
"../logging:rtc_event_log_parser",
"../modules/audio_coding:ana_debug_dump_proto",
# TODO(kwiberg): Remove this dependency.
"../modules/audio_coding:audio_format",

View File

@ -423,6 +423,9 @@ EventLogAnalyzer::EventLogAnalyzer(const ParsedRtcEventLog& log)
bwe_loss_updates_.push_back(bwe_update);
break;
}
case ParsedRtcEventLog::AUDIO_NETWORK_ADAPTATION_EVENT: {
break;
}
case ParsedRtcEventLog::BWE_PACKET_DELAY_EVENT: {
break;
}

View File

@ -140,6 +140,14 @@ class RtcEventLogProxy final : public webrtc::RtcEventLog {
}
}
void LogAudioNetworkAdaptation(
const AudioNetworkAdaptor::EncoderRuntimeConfig& config) override {
rtc::CritScope lock(&crit_);
if (event_log_) {
event_log_->LogAudioNetworkAdaptation(config);
}
}
void SetEventLog(RtcEventLog* event_log) {
rtc::CritScope lock(&crit_);
event_log_ = event_log;