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}
diff --git a/webrtc/logging/BUILD.gn b/webrtc/logging/BUILD.gn
index a159455..fd0caca 100644
--- a/webrtc/logging/BUILD.gn
+++ b/webrtc/logging/BUILD.gn
@@ -42,6 +42,7 @@
":rtc_event_log_api",
"..:webrtc_common",
"../call:call_interfaces",
+ "../modules/audio_coding:audio_network_adaptor",
"../modules/rtp_rtcp",
]
diff --git a/webrtc/logging/rtc_event_log/DEPS b/webrtc/logging/rtc_event_log/DEPS
index 39d2020..e340150 100644
--- a/webrtc/logging/rtc_event_log/DEPS
+++ b/webrtc/logging/rtc_event_log/DEPS
@@ -1,6 +1,7 @@
include_rules = [
"+webrtc/base",
"+webrtc/call",
+ "+webrtc/modules/audio_coding/audio_network_adaptor",
"+webrtc/modules/rtp_rtcp",
"+webrtc/system_wrappers",
]
diff --git a/webrtc/logging/rtc_event_log/mock/mock_rtc_event_log.h b/webrtc/logging/rtc_event_log/mock/mock_rtc_event_log.h
index 315967b..4db33a1 100644
--- a/webrtc/logging/rtc_event_log/mock/mock_rtc_event_log.h
+++ b/webrtc/logging/rtc_event_log/mock/mock_rtc_event_log.h
@@ -58,6 +58,8 @@
void(int32_t bitrate,
uint8_t fraction_loss,
int32_t total_packets));
+ MOCK_METHOD1(LogAudioNetworkAdaptation,
+ void(const AudioNetworkAdaptor::EncoderRuntimeConfig& config));
};
} // namespace webrtc
diff --git a/webrtc/logging/rtc_event_log/rtc_event_log.cc b/webrtc/logging/rtc_event_log/rtc_event_log.cc
index 21ca5e1..65ee7d8 100644
--- a/webrtc/logging/rtc_event_log/rtc_event_log.cc
+++ b/webrtc/logging/rtc_event_log/rtc_event_log.cc
@@ -77,6 +77,8 @@
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 @@
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.";
diff --git a/webrtc/logging/rtc_event_log/rtc_event_log.h b/webrtc/logging/rtc_event_log/rtc_event_log.h
index ccf6094..5d221d4 100644
--- a/webrtc/logging/rtc_event_log/rtc_event_log.h
+++ b/webrtc/logging/rtc_event_log/rtc_event_log.h
@@ -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 @@
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 @@
void LogBwePacketLossEvent(int32_t bitrate,
uint8_t fraction_loss,
int32_t total_packets) override {}
+ void LogAudioNetworkAdaptation(
+ const AudioNetworkAdaptor::EncoderRuntimeConfig& config) override{};
};
} // namespace webrtc
diff --git a/webrtc/logging/rtc_event_log/rtc_event_log.proto b/webrtc/logging/rtc_event_log/rtc_event_log.proto
index a6d1695..e807722 100644
--- a/webrtc/logging/rtc_event_log/rtc_event_log.proto
+++ b/webrtc/logging/rtc_event_log/rtc_event_log.proto
@@ -37,6 +37,7 @@
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 @@
// 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 @@
// 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;
+}
\ No newline at end of file
diff --git a/webrtc/logging/rtc_event_log/rtc_event_log_parser.cc b/webrtc/logging/rtc_event_log/rtc_event_log_parser.cc
index ce55a4f..3b808b2 100644
--- a/webrtc/logging/rtc_event_log/rtc_event_log_parser.cc
+++ b/webrtc/logging/rtc_event_log/rtc_event_log_parser.cc
@@ -79,6 +79,8 @@
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::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
diff --git a/webrtc/logging/rtc_event_log/rtc_event_log_parser.h b/webrtc/logging/rtc_event_log/rtc_event_log_parser.h
index 2d66b90..8472668 100644
--- a/webrtc/logging/rtc_event_log/rtc_event_log_parser.h
+++ b/webrtc/logging/rtc_event_log/rtc_event_log_parser.h
@@ -47,7 +47,8 @@
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 @@
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_;
};
diff --git a/webrtc/logging/rtc_event_log/rtc_event_log_unittest.cc b/webrtc/logging/rtc_event_log/rtc_event_log_unittest.cc
index 1540466..f0ee973 100644
--- a/webrtc/logging/rtc_event_log/rtc_event_log_unittest.cc
+++ b/webrtc/logging/rtc_event_log/rtc_event_log_unittest.cc
@@ -228,6 +228,19 @@
}
}
+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 @@
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 @@
VideoSendConfigReadWriteTest test;
test.DoTest();
}
+
+TEST(RtcEventLogTest, LogAudioNetworkAdaptation) {
+ AudioNetworkAdaptationReadWriteTest test;
+ test.DoTest();
+}
+
} // namespace webrtc
diff --git a/webrtc/logging/rtc_event_log/rtc_event_log_unittest_helper.cc b/webrtc/logging/rtc_event_log/rtc_event_log_unittest_helper.cc
index fb60dbc..19ca8aa 100644
--- a/webrtc/logging/rtc_event_log/rtc_event_log_unittest_helper.cc
+++ b/webrtc/logging/rtc_event_log/rtc_event_log_unittest_helper.cc
@@ -461,6 +461,21 @@
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) {
diff --git a/webrtc/logging/rtc_event_log/rtc_event_log_unittest_helper.h b/webrtc/logging/rtc_event_log/rtc_event_log_unittest_helper.h
index 3f89e30..2f4e177 100644
--- a/webrtc/logging/rtc_event_log/rtc_event_log_unittest_helper.h
+++ b/webrtc/logging/rtc_event_log/rtc_event_log_unittest_helper.h
@@ -56,6 +56,11 @@
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,
diff --git a/webrtc/modules/audio_coding/BUILD.gn b/webrtc/modules/audio_coding/BUILD.gn
index 9c285c9..4046373 100644
--- a/webrtc/modules/audio_coding/BUILD.gn
+++ b/webrtc/modules/audio_coding/BUILD.gn
@@ -914,6 +914,8 @@
"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 @@
"../..:webrtc_common",
"../../base:rtc_base_approved",
"../../common_audio",
+ "../../logging:rtc_event_log_api",
"../../system_wrappers",
]
@@ -935,6 +938,11 @@
]
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 @@
"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",
diff --git a/webrtc/modules/audio_coding/audio_network_adaptor/audio_network_adaptor_impl.cc b/webrtc/modules/audio_coding/audio_network_adaptor/audio_network_adaptor_impl.cc
index 3b767d9..6ec92b0 100644
--- a/webrtc/modules/audio_coding/audio_network_adaptor/audio_network_adaptor_impl.cc
+++ b/webrtc/modules/audio_coding/audio_network_adaptor/audio_network_adaptor_impl.cc
@@ -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 @@
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 @@
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;
}
diff --git a/webrtc/modules/audio_coding/audio_network_adaptor/audio_network_adaptor_impl.h b/webrtc/modules/audio_coding/audio_network_adaptor/audio_network_adaptor_impl.h
index 801a9cc..9c47125 100644
--- a/webrtc/modules/audio_coding/audio_network_adaptor/audio_network_adaptor_impl.h
+++ b/webrtc/modules/audio_coding/audio_network_adaptor/audio_network_adaptor_impl.h
@@ -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 @@
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);
diff --git a/webrtc/modules/audio_coding/audio_network_adaptor/audio_network_adaptor_impl_unittest.cc b/webrtc/modules/audio_coding/audio_network_adaptor/audio_network_adaptor_impl_unittest.cc
index b26d2f5..9b608dc 100644
--- a/webrtc/modules/audio_coding/audio_network_adaptor/audio_network_adaptor_impl_unittest.cc
+++ b/webrtc/modules/audio_coding/audio_network_adaptor/audio_network_adaptor_impl_unittest.cc
@@ -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 @@
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 @@
.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 @@
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 @@
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
diff --git a/webrtc/modules/audio_coding/audio_network_adaptor/event_log_writer.cc b/webrtc/modules/audio_coding/audio_network_adaptor/event_log_writer.cc
new file mode 100644
index 0000000..619a247
--- /dev/null
+++ b/webrtc/modules/audio_coding/audio_network_adaptor/event_log_writer.cc
@@ -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
diff --git a/webrtc/modules/audio_coding/audio_network_adaptor/event_log_writer.h b/webrtc/modules/audio_coding/audio_network_adaptor/event_log_writer.h
new file mode 100644
index 0000000..740da8c
--- /dev/null
+++ b/webrtc/modules/audio_coding/audio_network_adaptor/event_log_writer.h
@@ -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_
diff --git a/webrtc/modules/audio_coding/audio_network_adaptor/event_log_writer_unittest.cc b/webrtc/modules/audio_coding/audio_network_adaptor/event_log_writer_unittest.cc
new file mode 100644
index 0000000..289b8e2
--- /dev/null
+++ b/webrtc/modules/audio_coding/audio_network_adaptor/event_log_writer_unittest.cc
@@ -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
diff --git a/webrtc/tools/BUILD.gn b/webrtc/tools/BUILD.gn
index d2992a4..46a0ede 100644
--- a/webrtc/tools/BUILD.gn
+++ b/webrtc/tools/BUILD.gn
@@ -205,6 +205,7 @@
"../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",
diff --git a/webrtc/tools/event_log_visualizer/analyzer.cc b/webrtc/tools/event_log_visualizer/analyzer.cc
index 89e516a..3fd2c25 100644
--- a/webrtc/tools/event_log_visualizer/analyzer.cc
+++ b/webrtc/tools/event_log_visualizer/analyzer.cc
@@ -423,6 +423,9 @@
bwe_loss_updates_.push_back(bwe_update);
break;
}
+ case ParsedRtcEventLog::AUDIO_NETWORK_ADAPTATION_EVENT: {
+ break;
+ }
case ParsedRtcEventLog::BWE_PACKET_DELAY_EVENT: {
break;
}
diff --git a/webrtc/voice_engine/channel.cc b/webrtc/voice_engine/channel.cc
index 5231691..2791f7f 100644
--- a/webrtc/voice_engine/channel.cc
+++ b/webrtc/voice_engine/channel.cc
@@ -140,6 +140,14 @@
}
}
+ 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;