Adding BitrateController to audio network adaptor.

BUG=webrtc:6303

Review-Url: https://codereview.webrtc.org/2334613002
Cr-Commit-Position: refs/heads/master@{#14293}
This commit is contained in:
minyue 2016-09-19 09:56:35 -07:00 committed by Commit bot
parent 4bb04985c4
commit 26b039a137
8 changed files with 283 additions and 7 deletions

View File

@ -233,6 +233,30 @@ if (rtc_include_tests) {
}
}
rtc_source_set("audio_network_adaptor_unittests") {
# Put sources for unittests of audio network adaptor in a separate
# rtc_source_set to solve name collision on bitrate_controller_unittest.cc.
testonly = true
sources = [
"audio_coding/audio_network_adaptor/audio_network_adaptor_impl_unittest.cc",
"audio_coding/audio_network_adaptor/bitrate_controller_unittest.cc",
"audio_coding/audio_network_adaptor/channel_controller_unittest.cc",
"audio_coding/audio_network_adaptor/controller_manager_unittest.cc",
"audio_coding/audio_network_adaptor/dtx_controller_unittest.cc",
"audio_coding/audio_network_adaptor/mock/mock_controller.h",
"audio_coding/audio_network_adaptor/mock/mock_controller_manager.h",
]
deps = [
"audio_coding:audio_network_adaptor",
"//testing/gmock",
"//testing/gtest",
]
if (is_clang) {
# Suppress warnings from the Chromium Clang plugin (bugs.webrtc.org/163).
suppressed_configs += [ "//build/config/clang:find_bad_constructs" ]
}
}
rtc_test("modules_unittests") {
testonly = true
@ -245,12 +269,6 @@ if (rtc_include_tests) {
"audio_coding/acm2/codec_manager_unittest.cc",
"audio_coding/acm2/initial_delay_manager_unittest.cc",
"audio_coding/acm2/rent_a_codec_unittest.cc",
"audio_coding/audio_network_adaptor/audio_network_adaptor_impl_unittest.cc",
"audio_coding/audio_network_adaptor/channel_controller_unittest.cc",
"audio_coding/audio_network_adaptor/controller_manager_unittest.cc",
"audio_coding/audio_network_adaptor/dtx_controller_unittest.cc",
"audio_coding/audio_network_adaptor/mock/mock_controller.h",
"audio_coding/audio_network_adaptor/mock/mock_controller_manager.h",
"audio_coding/codecs/audio_decoder_factory_unittest.cc",
"audio_coding/codecs/cng/audio_encoder_cng_unittest.cc",
"audio_coding/codecs/cng/cng_unittest.cc",
@ -592,6 +610,7 @@ if (rtc_include_tests) {
}
deps += [
":audio_network_adaptor_unittests",
"..:webrtc_common",
"../base:rtc_base", # TODO(kjellander): Cleanup in bugs.webrtc.org/3806.
"../common_audio",
@ -605,7 +624,6 @@ if (rtc_include_tests) {
"audio_coding",
"audio_coding:acm_receive_test",
"audio_coding:acm_send_test",
"audio_coding:audio_network_adaptor",
"audio_coding:builtin_audio_decoder_factory",
"audio_coding:cng",
"audio_coding:isac_fix",

View File

@ -699,6 +699,8 @@ source_set("audio_network_adaptor") {
"audio_network_adaptor/audio_network_adaptor.cc",
"audio_network_adaptor/audio_network_adaptor_impl.cc",
"audio_network_adaptor/audio_network_adaptor_impl.h",
"audio_network_adaptor/bitrate_controller.cc",
"audio_network_adaptor/bitrate_controller.h",
"audio_network_adaptor/channel_controller.cc",
"audio_network_adaptor/channel_controller.h",
"audio_network_adaptor/controller.cc",

View File

@ -14,6 +14,8 @@
'audio_network_adaptor.cc',
'audio_network_adaptor_impl.cc',
'audio_network_adaptor_impl.h',
'bitrate_controller.h',
'bitrate_controller.cc',
'channel_controller.cc',
'channel_controller.h',
'controller.h',

View File

@ -28,6 +28,7 @@ constexpr size_t kNumControllers = 2;
MATCHER_P(NetworkMetricsIs, metric, "") {
return arg.uplink_bandwidth_bps == metric.uplink_bandwidth_bps &&
arg.target_audio_bitrate_bps == metric.target_audio_bitrate_bps &&
arg.uplink_packet_loss_fraction == metric.uplink_packet_loss_fraction;
}

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 "webrtc/modules/audio_coding/audio_network_adaptor/bitrate_controller.h"
#include <algorithm>
#include "webrtc/base/checks.h"
namespace webrtc {
namespace {
// TODO(minyue): consider passing this from a higher layer through
// SetConstraints().
// L2(14B) + IPv4(20B) + UDP(8B) + RTP(12B) + SRTP_AUTH(10B) = 64B = 512 bits
constexpr int kPacketOverheadBits = 512;
}
BitrateController::Config::Config(int initial_bitrate_bps,
int initial_frame_length_ms)
: initial_bitrate_bps(initial_bitrate_bps),
initial_frame_length_ms(initial_frame_length_ms) {}
BitrateController::Config::~Config() = default;
BitrateController::BitrateController(const Config& config)
: config_(config),
bitrate_bps_(config_.initial_bitrate_bps),
overhead_rate_bps_(kPacketOverheadBits * 1000 /
config_.initial_frame_length_ms) {
RTC_DCHECK_GT(bitrate_bps_, 0);
RTC_DCHECK_GT(overhead_rate_bps_, 0);
}
void BitrateController::MakeDecision(
const NetworkMetrics& metrics,
AudioNetworkAdaptor::EncoderRuntimeConfig* config) {
// Decision on |bitrate_bps| should not have been made.
RTC_DCHECK(!config->bitrate_bps);
if (metrics.target_audio_bitrate_bps) {
int overhead_rate =
config->frame_length_ms
? kPacketOverheadBits * 1000 / *config->frame_length_ms
: overhead_rate_bps_;
// If |metrics.target_audio_bitrate_bps| had included overhead, we would
// simply do:
// bitrate_bps_ = metrics.target_audio_bitrate_bps - overhead_rate;
// Follow https://bugs.chromium.org/p/webrtc/issues/detail?id=6315 to track
// progress regarding this.
// Now we assume that |metrics.target_audio_bitrate_bps| can handle the
// overhead of most recent packets.
bitrate_bps_ = std::max(0, *metrics.target_audio_bitrate_bps +
overhead_rate_bps_ - overhead_rate);
// TODO(minyue): apply a smoothing on the |overhead_rate_bps_|.
overhead_rate_bps_ = overhead_rate;
}
config->bitrate_bps = rtc::Optional<int>(bitrate_bps_);
}
} // namespace webrtc

View File

@ -0,0 +1,42 @@
/*
* 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_BITRATE_CONTROLLER_H_
#define WEBRTC_MODULES_AUDIO_CODING_AUDIO_NETWORK_ADAPTOR_BITRATE_CONTROLLER_H_
#include "webrtc/base/constructormagic.h"
#include "webrtc/modules/audio_coding/audio_network_adaptor/controller.h"
namespace webrtc {
class BitrateController final : public Controller {
public:
struct Config {
Config(int initial_bitrate_bps, int frame_length_ms);
~Config();
int initial_bitrate_bps;
int initial_frame_length_ms;
};
explicit BitrateController(const Config& config);
void MakeDecision(const NetworkMetrics& metrics,
AudioNetworkAdaptor::EncoderRuntimeConfig* config) override;
private:
const Config config_;
int bitrate_bps_;
int overhead_rate_bps_;
RTC_DISALLOW_COPY_AND_ASSIGN(BitrateController);
};
} // namespace webrtc
#endif // WEBRTC_MODULES_AUDIO_CODING_AUDIO_NETWORK_ADAPTOR_BITRATE_CONTROLLER_H_

View File

@ -0,0 +1,142 @@
/*
* 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 "testing/gtest/include/gtest/gtest.h"
#include "webrtc/modules/audio_coding/audio_network_adaptor/bitrate_controller.h"
namespace webrtc {
namespace {
// L2(14B) + IPv4(20B) + UDP(8B) + RTP(12B) + SRTP_AUTH(10B) = 64B = 512 bits
constexpr int kPacketOverheadBits = 512;
void CheckDecision(BitrateController* controller,
const rtc::Optional<int>& target_audio_bitrate_bps,
const rtc::Optional<int>& frame_length_ms,
int expected_bitrate_bps) {
Controller::NetworkMetrics metrics;
metrics.target_audio_bitrate_bps = target_audio_bitrate_bps;
AudioNetworkAdaptor::EncoderRuntimeConfig config;
config.frame_length_ms = frame_length_ms;
controller->MakeDecision(metrics, &config);
EXPECT_EQ(rtc::Optional<int>(expected_bitrate_bps), config.bitrate_bps);
}
} // namespace
// These tests are named AnaBitrateControllerTest to distinguish from
// BitrateControllerTest in
// modules/bitrate_controller/bitrate_controller_unittest.cc.
TEST(AnaBitrateControllerTest, OutputInitValueWhenTargetBitrateUnknown) {
constexpr int kInitialBitrateBps = 32000;
constexpr int kInitialFrameLengthMs = 20;
BitrateController controller(
BitrateController::Config(kInitialBitrateBps, kInitialFrameLengthMs));
CheckDecision(&controller, rtc::Optional<int>(),
rtc::Optional<int>(kInitialFrameLengthMs * 2),
kInitialBitrateBps);
}
TEST(AnaBitrateControllerTest, ChangeBitrateOnTargetBitrateChanged) {
constexpr int kInitialBitrateBps = 32000;
constexpr int kInitialFrameLengthMs = 20;
BitrateController controller(
BitrateController::Config(kInitialBitrateBps, kInitialFrameLengthMs));
constexpr int kTargetBitrateBps = 48000;
// Frame length unchanged, bitrate changes in accordance with
// |metrics.target_audio_bitrate_bps|
CheckDecision(&controller, rtc::Optional<int>(kTargetBitrateBps),
rtc::Optional<int>(kInitialFrameLengthMs), kTargetBitrateBps);
}
TEST(AnaBitrateControllerTest, TreatUnknownFrameLengthAsFrameLengthUnchanged) {
constexpr int kInitialBitrateBps = 32000;
constexpr int kInitialFrameLengthMs = 20;
BitrateController controller(
BitrateController::Config(kInitialBitrateBps, kInitialFrameLengthMs));
constexpr int kTargetBitrateBps = 48000;
CheckDecision(&controller, rtc::Optional<int>(kTargetBitrateBps),
rtc::Optional<int>(), kTargetBitrateBps);
}
TEST(AnaBitrateControllerTest, IncreaseBitrateOnFrameLengthIncreased) {
constexpr int kInitialBitrateBps = 32000;
constexpr int kInitialFrameLengthMs = 20;
BitrateController controller(
BitrateController::Config(kInitialBitrateBps, kInitialFrameLengthMs));
constexpr int kFrameLengthMs = 60;
constexpr int kPacketOverheadRateDiff =
kPacketOverheadBits * 1000 / kInitialFrameLengthMs -
kPacketOverheadBits * 1000 / kFrameLengthMs;
CheckDecision(&controller, rtc::Optional<int>(kInitialBitrateBps),
rtc::Optional<int>(kFrameLengthMs),
kInitialBitrateBps + kPacketOverheadRateDiff);
}
TEST(AnaBitrateControllerTest, DecreaseBitrateOnFrameLengthDecreased) {
constexpr int kInitialBitrateBps = 32000;
constexpr int kInitialFrameLengthMs = 60;
BitrateController controller(
BitrateController::Config(kInitialBitrateBps, kInitialFrameLengthMs));
constexpr int kFrameLengthMs = 20;
constexpr int kPacketOverheadRateDiff =
kPacketOverheadBits * 1000 / kInitialFrameLengthMs -
kPacketOverheadBits * 1000 / kFrameLengthMs;
CheckDecision(&controller, rtc::Optional<int>(kInitialBitrateBps),
rtc::Optional<int>(kFrameLengthMs),
kInitialBitrateBps + kPacketOverheadRateDiff);
}
TEST(AnaBitrateControllerTest, CheckBehaviorOnChangingCondition) {
constexpr int kInitialBitrateBps = 32000;
constexpr int kInitialFrameLengthMs = 20;
BitrateController controller(
BitrateController::Config(kInitialBitrateBps, kInitialFrameLengthMs));
int last_overhead_bitrate =
kPacketOverheadBits * 1000 / kInitialFrameLengthMs;
int current_overhead_bitrate = kPacketOverheadBits * 1000 / 20;
// Start from an arbitrary overall bitrate.
int overall_bitrate = 34567;
CheckDecision(
&controller, rtc::Optional<int>(overall_bitrate - last_overhead_bitrate),
rtc::Optional<int>(20), overall_bitrate - current_overhead_bitrate);
// Next: increase overall bitrate.
overall_bitrate += 100;
CheckDecision(
&controller, rtc::Optional<int>(overall_bitrate - last_overhead_bitrate),
rtc::Optional<int>(20), overall_bitrate - current_overhead_bitrate);
// Next: change frame length.
current_overhead_bitrate = kPacketOverheadBits * 1000 / 60;
CheckDecision(
&controller, rtc::Optional<int>(overall_bitrate - last_overhead_bitrate),
rtc::Optional<int>(60), overall_bitrate - current_overhead_bitrate);
last_overhead_bitrate = current_overhead_bitrate;
// Next: change frame length.
current_overhead_bitrate = kPacketOverheadBits * 1000 / 20;
CheckDecision(
&controller, rtc::Optional<int>(overall_bitrate - last_overhead_bitrate),
rtc::Optional<int>(20), overall_bitrate - current_overhead_bitrate);
last_overhead_bitrate = current_overhead_bitrate;
// Next: decrease overall bitrate and frame length.
overall_bitrate -= 100;
current_overhead_bitrate = kPacketOverheadBits * 1000 / 60;
CheckDecision(
&controller, rtc::Optional<int>(overall_bitrate - last_overhead_bitrate),
rtc::Optional<int>(60), overall_bitrate - current_overhead_bitrate);
}
} // namespace webrtc

View File

@ -23,6 +23,7 @@ class Controller {
~NetworkMetrics();
rtc::Optional<int> uplink_bandwidth_bps;
rtc::Optional<float> uplink_packet_loss_fraction;
rtc::Optional<int> target_audio_bitrate_bps;
};
struct Constraints {