Adding packet overhead to audio network adaptor.

BUG=webrtc:6303, webrtc:6762

Review-Url: https://codereview.webrtc.org/2530653003
Cr-Commit-Position: refs/heads/master@{#15305}
This commit is contained in:
minyue
2016-11-29 13:00:28 -08:00
committed by Commit bot
parent 821dc7aa66
commit c9e80eee51
9 changed files with 178 additions and 88 deletions

View File

@ -42,6 +42,11 @@ void AudioNetworkAdaptorImpl::SetUplinkPacketLossFraction(
DumpNetworkMetrics();
}
void AudioNetworkAdaptorImpl::SetRtt(int rtt_ms) {
last_metrics_.rtt_ms = rtc::Optional<int>(rtt_ms);
DumpNetworkMetrics();
}
void AudioNetworkAdaptorImpl::SetTargetAudioBitrate(
int target_audio_bitrate_bps) {
last_metrics_.target_audio_bitrate_bps =
@ -49,8 +54,9 @@ void AudioNetworkAdaptorImpl::SetTargetAudioBitrate(
DumpNetworkMetrics();
}
void AudioNetworkAdaptorImpl::SetRtt(int rtt_ms) {
last_metrics_.rtt_ms = rtc::Optional<int>(rtt_ms);
void AudioNetworkAdaptorImpl::SetOverhead(size_t overhead_bytes_per_packet) {
last_metrics_.overhead_bytes_per_packet =
rtc::Optional<size_t>(overhead_bytes_per_packet);
DumpNetworkMetrics();
}

View File

@ -45,6 +45,8 @@ class AudioNetworkAdaptorImpl final : public AudioNetworkAdaptor {
void SetTargetAudioBitrate(int target_audio_bitrate_bps) override;
void SetOverhead(size_t overhead_bytes_per_packet) override;
EncoderRuntimeConfig GetEncoderRuntimeConfig() override;
void StartDebugDump(FILE* file_handle) override;

View File

@ -34,16 +34,10 @@ MATCHER_P(NetworkMetricsIs, metric, "") {
return arg.uplink_bandwidth_bps == metric.uplink_bandwidth_bps &&
arg.target_audio_bitrate_bps == metric.target_audio_bitrate_bps &&
arg.rtt_ms == metric.rtt_ms &&
arg.overhead_bytes_per_packet == metric.overhead_bytes_per_packet &&
arg.uplink_packet_loss_fraction == metric.uplink_packet_loss_fraction;
}
MATCHER_P(ConstraintsReceiverFrameLengthRangeIs, frame_length_range, "") {
return arg.receiver_frame_length_range->min_frame_length_ms ==
frame_length_range.min_frame_length_ms &&
arg.receiver_frame_length_range->max_frame_length_ms ==
frame_length_range.max_frame_length_ms;
}
MATCHER_P(EncoderRuntimeConfigIs, config, "") {
return arg.bitrate_bps == config.bitrate_bps &&
arg.frame_length_ms == config.frame_length_ms &&
@ -108,6 +102,7 @@ TEST(AudioNetworkAdaptorImplTest,
constexpr float kPacketLoss = 0.7f;
constexpr int kRtt = 100;
constexpr int kTargetAudioBitrate = 15000;
constexpr size_t kOverhead = 64;
Controller::NetworkMetrics check;
check.uplink_bandwidth_bps = rtc::Optional<int>(kBandwidth);
@ -137,6 +132,13 @@ TEST(AudioNetworkAdaptorImplTest,
}
states.audio_network_adaptor->SetTargetAudioBitrate(kTargetAudioBitrate);
states.audio_network_adaptor->GetEncoderRuntimeConfig();
check.overhead_bytes_per_packet = rtc::Optional<size_t>(kOverhead);
for (auto& mock_controller : states.mock_controllers) {
EXPECT_CALL(*mock_controller, MakeDecision(NetworkMetricsIs(check), _));
}
states.audio_network_adaptor->SetOverhead(kOverhead);
states.audio_network_adaptor->GetEncoderRuntimeConfig();
}
TEST(AudioNetworkAdaptorImplTest,
@ -164,6 +166,7 @@ TEST(AudioNetworkAdaptorImplTest,
constexpr float kPacketLoss = 0.7f;
constexpr int kRtt = 100;
constexpr int kTargetAudioBitrate = 15000;
constexpr size_t kOverhead = 64;
Controller::NetworkMetrics check;
check.uplink_bandwidth_bps = rtc::Optional<int>(kBandwidth);
@ -193,6 +196,13 @@ TEST(AudioNetworkAdaptorImplTest,
EXPECT_CALL(*states.mock_debug_dump_writer,
DumpNetworkMetrics(NetworkMetricsIs(check), timestamp_check));
states.audio_network_adaptor->SetTargetAudioBitrate(kTargetAudioBitrate);
states.simulated_clock->AdvanceTimeMilliseconds(50);
timestamp_check += 50;
check.overhead_bytes_per_packet = rtc::Optional<size_t>(kOverhead);
EXPECT_CALL(*states.mock_debug_dump_writer,
DumpNetworkMetrics(NetworkMetricsIs(check), timestamp_check));
states.audio_network_adaptor->SetOverhead(kOverhead);
}
} // namespace webrtc

View File

@ -13,17 +13,11 @@
#include <algorithm>
#include "webrtc/base/checks.h"
#include "webrtc/system_wrappers/include/field_trial.h"
namespace webrtc {
namespace audio_network_adaptor {
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),
@ -34,10 +28,9 @@ 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) {
frame_length_ms_(config_.initial_frame_length_ms) {
RTC_DCHECK_GT(bitrate_bps_, 0);
RTC_DCHECK_GT(overhead_rate_bps_, 0);
RTC_DCHECK_GT(frame_length_ms_, 0);
}
void BitrateController::MakeDecision(
@ -45,23 +38,18 @@ void BitrateController::MakeDecision(
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;
if (metrics.target_audio_bitrate_bps && metrics.overhead_bytes_per_packet) {
// Current implementation of BitrateController can only work when
// |metrics.target_audio_bitrate_bps| includes overhead is enabled. This is
// currently governed by the following field trial.
RTC_DCHECK_EQ("Enabled", webrtc::field_trial::FindFullName(
"WebRTC-SendSideBwe-WithOverhead"));
if (config->frame_length_ms)
frame_length_ms_ = *config->frame_length_ms;
int overhead_rate_bps =
*metrics.overhead_bytes_per_packet * 8 * 1000 / frame_length_ms_;
bitrate_bps_ =
std::max(0, *metrics.target_audio_bitrate_bps - overhead_rate_bps);
}
config->bitrate_bps = rtc::Optional<int>(bitrate_bps_);
}

View File

@ -34,7 +34,7 @@ class BitrateController final : public Controller {
private:
const Config config_;
int bitrate_bps_;
int overhead_rate_bps_;
int frame_length_ms_;
RTC_DISALLOW_COPY_AND_ASSIGN(BitrateController);
};

View File

@ -9,6 +9,7 @@
*/
#include "webrtc/modules/audio_coding/audio_network_adaptor/bitrate_controller.h"
#include "webrtc/test/field_trial.h"
#include "webrtc/test/gtest.h"
namespace webrtc {
@ -16,15 +17,14 @@ namespace audio_network_adaptor {
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<size_t>& overhead_bytes_per_packet,
const rtc::Optional<int>& frame_length_ms,
int expected_bitrate_bps) {
Controller::NetworkMetrics metrics;
metrics.target_audio_bitrate_bps = target_audio_bitrate_bps;
metrics.overhead_bytes_per_packet = overhead_bytes_per_packet;
AudioNetworkAdaptor::EncoderRuntimeConfig config;
config.frame_length_ms = frame_length_ms;
controller->MakeDecision(metrics, &config);
@ -40,104 +40,183 @@ void CheckDecision(BitrateController* controller,
TEST(AnaBitrateControllerTest, OutputInitValueWhenTargetBitrateUnknown) {
constexpr int kInitialBitrateBps = 32000;
constexpr int kInitialFrameLengthMs = 20;
constexpr size_t kOverheadBytesPerPacket = 64;
BitrateController controller(
BitrateController::Config(kInitialBitrateBps, kInitialFrameLengthMs));
CheckDecision(&controller, rtc::Optional<int>(),
rtc::Optional<size_t>(kOverheadBytesPerPacket),
rtc::Optional<int>(kInitialFrameLengthMs * 2),
kInitialBitrateBps);
}
TEST(AnaBitrateControllerTest, OutputInitValueWhenOverheadUnknown) {
constexpr int kInitialBitrateBps = 32000;
constexpr int kInitialFrameLengthMs = 20;
constexpr int kTargetBitrateBps = 48000;
BitrateController controller(
BitrateController::Config(kInitialBitrateBps, kInitialFrameLengthMs));
CheckDecision(&controller, rtc::Optional<int>(kTargetBitrateBps),
rtc::Optional<size_t>(),
rtc::Optional<int>(kInitialFrameLengthMs * 2),
kInitialBitrateBps);
}
TEST(AnaBitrateControllerTest, ChangeBitrateOnTargetBitrateChanged) {
constexpr int kInitialBitrateBps = 32000;
test::ScopedFieldTrials override_field_trials(
"WebRTC-SendSideBwe-WithOverhead/Enabled/");
constexpr int kInitialFrameLengthMs = 20;
BitrateController controller(
BitrateController::Config(kInitialBitrateBps, kInitialFrameLengthMs));
BitrateController::Config(32000, kInitialFrameLengthMs));
constexpr int kTargetBitrateBps = 48000;
constexpr size_t kOverheadBytesPerPacket = 64;
constexpr int kBitrateBps =
kTargetBitrateBps -
kOverheadBytesPerPacket * 8 * 1000 / kInitialFrameLengthMs;
// Frame length unchanged, bitrate changes in accordance with
// |metrics.target_audio_bitrate_bps|
// |metrics.target_audio_bitrate_bps| and |metrics.overhead_bytes_per_packet|.
CheckDecision(&controller, rtc::Optional<int>(kTargetBitrateBps),
rtc::Optional<int>(kInitialFrameLengthMs), kTargetBitrateBps);
rtc::Optional<size_t>(kOverheadBytesPerPacket),
rtc::Optional<int>(kInitialFrameLengthMs), kBitrateBps);
}
TEST(AnaBitrateControllerTest, TreatUnknownFrameLengthAsFrameLengthUnchanged) {
constexpr int kInitialBitrateBps = 32000;
test::ScopedFieldTrials override_field_trials(
"WebRTC-SendSideBwe-WithOverhead/Enabled/");
constexpr int kInitialFrameLengthMs = 20;
BitrateController controller(
BitrateController::Config(kInitialBitrateBps, kInitialFrameLengthMs));
BitrateController::Config(32000, kInitialFrameLengthMs));
constexpr int kTargetBitrateBps = 48000;
constexpr size_t kOverheadBytesPerPacket = 64;
constexpr int kBitrateBps =
kTargetBitrateBps -
kOverheadBytesPerPacket * 8 * 1000 / kInitialFrameLengthMs;
CheckDecision(&controller, rtc::Optional<int>(kTargetBitrateBps),
rtc::Optional<int>(), kTargetBitrateBps);
rtc::Optional<size_t>(kOverheadBytesPerPacket),
rtc::Optional<int>(), kBitrateBps);
}
TEST(AnaBitrateControllerTest, IncreaseBitrateOnFrameLengthIncreased) {
constexpr int kInitialBitrateBps = 32000;
test::ScopedFieldTrials override_field_trials(
"WebRTC-SendSideBwe-WithOverhead/Enabled/");
constexpr int kInitialFrameLengthMs = 20;
BitrateController controller(
BitrateController::Config(kInitialBitrateBps, kInitialFrameLengthMs));
BitrateController::Config(32000, kInitialFrameLengthMs));
constexpr int kTargetBitrateBps = 48000;
constexpr size_t kOverheadBytesPerPacket = 64;
constexpr int kBitrateBps =
kTargetBitrateBps -
kOverheadBytesPerPacket * 8 * 1000 / kInitialFrameLengthMs;
CheckDecision(&controller, rtc::Optional<int>(kTargetBitrateBps),
rtc::Optional<size_t>(kOverheadBytesPerPacket),
rtc::Optional<int>(), kBitrateBps);
constexpr int kFrameLengthMs = 60;
constexpr int kPacketOverheadRateDiff =
kPacketOverheadBits * 1000 / kInitialFrameLengthMs -
kPacketOverheadBits * 1000 / kFrameLengthMs;
CheckDecision(&controller, rtc::Optional<int>(kInitialBitrateBps),
constexpr size_t kPacketOverheadRateDiff =
kOverheadBytesPerPacket * 8 * 1000 / 20 -
kOverheadBytesPerPacket * 8 * 1000 / 60;
CheckDecision(&controller, rtc::Optional<int>(kTargetBitrateBps),
rtc::Optional<size_t>(kOverheadBytesPerPacket),
rtc::Optional<int>(kFrameLengthMs),
kInitialBitrateBps + kPacketOverheadRateDiff);
kBitrateBps + kPacketOverheadRateDiff);
}
TEST(AnaBitrateControllerTest, DecreaseBitrateOnFrameLengthDecreased) {
constexpr int kInitialBitrateBps = 32000;
test::ScopedFieldTrials override_field_trials(
"WebRTC-SendSideBwe-WithOverhead/Enabled/");
constexpr int kInitialFrameLengthMs = 60;
BitrateController controller(
BitrateController::Config(kInitialBitrateBps, kInitialFrameLengthMs));
BitrateController::Config(32000, kInitialFrameLengthMs));
constexpr int kTargetBitrateBps = 48000;
constexpr size_t kOverheadBytesPerPacket = 64;
constexpr int kBitrateBps =
kTargetBitrateBps -
kOverheadBytesPerPacket * 8 * 1000 / kInitialFrameLengthMs;
CheckDecision(&controller, rtc::Optional<int>(kTargetBitrateBps),
rtc::Optional<size_t>(kOverheadBytesPerPacket),
rtc::Optional<int>(), kBitrateBps);
constexpr int kFrameLengthMs = 20;
constexpr int kPacketOverheadRateDiff =
kPacketOverheadBits * 1000 / kInitialFrameLengthMs -
kPacketOverheadBits * 1000 / kFrameLengthMs;
CheckDecision(&controller, rtc::Optional<int>(kInitialBitrateBps),
constexpr size_t kPacketOverheadRateDiff =
kOverheadBytesPerPacket * 8 * 1000 / 20 -
kOverheadBytesPerPacket * 8 * 1000 / 60;
CheckDecision(&controller, rtc::Optional<int>(kTargetBitrateBps),
rtc::Optional<size_t>(kOverheadBytesPerPacket),
rtc::Optional<int>(kFrameLengthMs),
kInitialBitrateBps + kPacketOverheadRateDiff);
kBitrateBps - kPacketOverheadRateDiff);
}
TEST(AnaBitrateControllerTest, BitrateNeverBecomesNegative) {
test::ScopedFieldTrials override_field_trials(
"WebRTC-SendSideBwe-WithOverhead/Enabled/");
BitrateController controller(BitrateController::Config(32000, 20));
constexpr size_t kOverheadBytesPerPacket = 64;
constexpr int kFrameLengthMs = 60;
// Set a target rate smaller than overhead rate, the bitrate is bounded by 0.
constexpr int kTargetBitrateBps =
kOverheadBytesPerPacket * 8 * 1000 / kFrameLengthMs - 1;
CheckDecision(&controller, rtc::Optional<int>(kTargetBitrateBps),
rtc::Optional<size_t>(kOverheadBytesPerPacket),
rtc::Optional<int>(kFrameLengthMs), 0);
}
TEST(AnaBitrateControllerTest, CheckBehaviorOnChangingCondition) {
constexpr int kInitialBitrateBps = 32000;
constexpr int kInitialFrameLengthMs = 20;
BitrateController controller(
BitrateController::Config(kInitialBitrateBps, kInitialFrameLengthMs));
test::ScopedFieldTrials override_field_trials(
"WebRTC-SendSideBwe-WithOverhead/Enabled/");
BitrateController controller(BitrateController::Config(32000, 20));
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);
size_t overhead_bytes_per_packet = 64;
int frame_length_ms = 20;
int current_bitrate =
overall_bitrate - overhead_bytes_per_packet * 8 * 1000 / frame_length_ms;
CheckDecision(&controller, rtc::Optional<int>(overall_bitrate),
rtc::Optional<size_t>(overhead_bytes_per_packet),
rtc::Optional<int>(frame_length_ms), current_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);
current_bitrate += 100;
CheckDecision(&controller, rtc::Optional<int>(overall_bitrate),
rtc::Optional<size_t>(overhead_bytes_per_packet),
rtc::Optional<int>(frame_length_ms), current_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;
frame_length_ms = 60;
current_bitrate += overhead_bytes_per_packet * 8 * 1000 / 20 -
overhead_bytes_per_packet * 8 * 1000 / 60;
CheckDecision(&controller, rtc::Optional<int>(overall_bitrate),
rtc::Optional<size_t>(overhead_bytes_per_packet),
rtc::Optional<int>(frame_length_ms), current_bitrate);
// Next: change overhead.
overhead_bytes_per_packet -= 30;
current_bitrate += 30 * 8 * 1000 / frame_length_ms;
CheckDecision(&controller, rtc::Optional<int>(overall_bitrate),
rtc::Optional<size_t>(overhead_bytes_per_packet),
rtc::Optional<int>(frame_length_ms), current_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;
frame_length_ms = 20;
current_bitrate -= overhead_bytes_per_packet * 8 * 1000 / 20 -
overhead_bytes_per_packet * 8 * 1000 / 60;
CheckDecision(&controller, rtc::Optional<int>(overall_bitrate),
rtc::Optional<size_t>(overhead_bytes_per_packet),
rtc::Optional<int>(frame_length_ms), current_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);
current_bitrate -= 100;
frame_length_ms = 60;
current_bitrate += overhead_bytes_per_packet * 8 * 1000 / 20 -
overhead_bytes_per_packet * 8 * 1000 / 60;
CheckDecision(&controller, rtc::Optional<int>(overall_bitrate),
rtc::Optional<size_t>(overhead_bytes_per_packet),
rtc::Optional<int>(frame_length_ms), current_bitrate);
}
} // namespace audio_network_adaptor

View File

@ -25,6 +25,7 @@ class Controller {
rtc::Optional<float> uplink_packet_loss_fraction;
rtc::Optional<int> target_audio_bitrate_bps;
rtc::Optional<int> rtt_ms;
rtc::Optional<size_t> overhead_bytes_per_packet;
};
virtual ~Controller() = default;

View File

@ -47,6 +47,8 @@ class AudioNetworkAdaptor {
virtual void SetTargetAudioBitrate(int target_audio_bitrate_bps) = 0;
virtual void SetOverhead(size_t overhead_bytes_per_packet) = 0;
virtual EncoderRuntimeConfig GetEncoderRuntimeConfig() = 0;
virtual void StartDebugDump(FILE* file_handle) = 0;

View File

@ -30,6 +30,8 @@ class MockAudioNetworkAdaptor : public AudioNetworkAdaptor {
MOCK_METHOD1(SetTargetAudioBitrate, void(int target_audio_bitrate_bps));
MOCK_METHOD1(SetOverhead, void(size_t overhead_bytes_per_packet));
MOCK_METHOD0(GetEncoderRuntimeConfig, EncoderRuntimeConfig());
MOCK_METHOD1(StartDebugDump, void(FILE* file_handle));