Update smoothed bitrate.
BUG=webrtc:6443 Review-Url: https://codereview.webrtc.org/2546493002 Cr-Commit-Position: refs/heads/master@{#16036}
This commit is contained in:
@ -706,6 +706,26 @@ if (rtc_include_tests) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
rtc_source_set("rtc_base_tests_main") {
|
||||||
|
testonly = true
|
||||||
|
sources = [
|
||||||
|
"unittest_main.cc",
|
||||||
|
]
|
||||||
|
public_configs = [ ":rtc_base_tests_utils_exported_config" ]
|
||||||
|
deps = [
|
||||||
|
":rtc_base_tests_utils",
|
||||||
|
]
|
||||||
|
public_deps = [
|
||||||
|
"//testing/gmock",
|
||||||
|
"//testing/gtest",
|
||||||
|
]
|
||||||
|
|
||||||
|
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_source_set("rtc_base_tests_utils") {
|
rtc_source_set("rtc_base_tests_utils") {
|
||||||
testonly = true
|
testonly = true
|
||||||
sources = [
|
sources = [
|
||||||
@ -731,7 +751,6 @@ if (rtc_include_tests) {
|
|||||||
"testechoserver.h",
|
"testechoserver.h",
|
||||||
"testutils.h",
|
"testutils.h",
|
||||||
"timedelta.h",
|
"timedelta.h",
|
||||||
"unittest_main.cc",
|
|
||||||
]
|
]
|
||||||
configs += [ ":rtc_base_tests_utils_warnings_config" ]
|
configs += [ ":rtc_base_tests_utils_warnings_config" ]
|
||||||
public_configs = [ ":rtc_base_tests_utils_exported_config" ]
|
public_configs = [ ":rtc_base_tests_utils_exported_config" ]
|
||||||
@ -763,7 +782,7 @@ if (rtc_include_tests) {
|
|||||||
]
|
]
|
||||||
deps = [
|
deps = [
|
||||||
":rtc_base",
|
":rtc_base",
|
||||||
":rtc_base_tests_utils",
|
":rtc_base_tests_main",
|
||||||
"//testing/gtest",
|
"//testing/gtest",
|
||||||
]
|
]
|
||||||
if (is_win) {
|
if (is_win) {
|
||||||
@ -818,7 +837,7 @@ if (rtc_include_tests) {
|
|||||||
]
|
]
|
||||||
deps = [
|
deps = [
|
||||||
":rtc_base_approved",
|
":rtc_base_approved",
|
||||||
":rtc_base_tests_utils",
|
":rtc_base_tests_main",
|
||||||
]
|
]
|
||||||
if (!build_with_chromium && is_clang) {
|
if (!build_with_chromium && is_clang) {
|
||||||
# Suppress warnings from the Chromium Clang plugin (bugs.webrtc.org/163).
|
# Suppress warnings from the Chromium Clang plugin (bugs.webrtc.org/163).
|
||||||
@ -834,7 +853,7 @@ if (rtc_include_tests) {
|
|||||||
"weak_ptr_unittest.cc",
|
"weak_ptr_unittest.cc",
|
||||||
]
|
]
|
||||||
deps = [
|
deps = [
|
||||||
":rtc_base_tests_utils",
|
":rtc_base_tests_main",
|
||||||
":rtc_task_queue",
|
":rtc_task_queue",
|
||||||
]
|
]
|
||||||
if (!build_with_chromium && is_clang) {
|
if (!build_with_chromium && is_clang) {
|
||||||
@ -851,7 +870,7 @@ if (rtc_include_tests) {
|
|||||||
]
|
]
|
||||||
deps = [
|
deps = [
|
||||||
":rtc_analytics",
|
":rtc_analytics",
|
||||||
":rtc_base_tests_utils",
|
":rtc_base_tests_main",
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -912,7 +931,7 @@ if (rtc_include_tests) {
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
deps = [
|
deps = [
|
||||||
":rtc_base_tests_utils",
|
":rtc_base_tests_main",
|
||||||
]
|
]
|
||||||
public_deps = [
|
public_deps = [
|
||||||
":rtc_base",
|
":rtc_base",
|
||||||
|
|||||||
@ -271,7 +271,7 @@ if (rtc_include_tests) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
deps += [
|
deps += [
|
||||||
"../base:rtc_base_tests_utils",
|
"../base:rtc_base_tests_main",
|
||||||
"//testing/gtest",
|
"//testing/gtest",
|
||||||
]
|
]
|
||||||
public_deps += [ "//testing/gmock" ]
|
public_deps += [ "//testing/gmock" ]
|
||||||
|
|||||||
@ -631,7 +631,7 @@ if (rtc_include_tests) {
|
|||||||
# TODO(jschuh): bugs.webrtc.org/1348: fix this warning.
|
# TODO(jschuh): bugs.webrtc.org/1348: fix this warning.
|
||||||
configs += [ "//build/config/compiler:no_size_t_to_int_warning" ]
|
configs += [ "//build/config/compiler:no_size_t_to_int_warning" ]
|
||||||
|
|
||||||
if (!build_with_chromium && is_clang) {
|
if ((!build_with_chromium || is_win) && is_clang) {
|
||||||
# Suppress warnings from the Chromium Clang plugin (bugs.webrtc.org/163).
|
# Suppress warnings from the Chromium Clang plugin (bugs.webrtc.org/163).
|
||||||
suppressed_configs += [ "//build/config/clang:find_bad_constructs" ]
|
suppressed_configs += [ "//build/config/clang:find_bad_constructs" ]
|
||||||
}
|
}
|
||||||
@ -648,9 +648,11 @@ if (rtc_include_tests) {
|
|||||||
"..:webrtc_common",
|
"..:webrtc_common",
|
||||||
"../api:transport_api",
|
"../api:transport_api",
|
||||||
"../base:rtc_base", # TODO(kjellander): Cleanup in bugs.webrtc.org/3806.
|
"../base:rtc_base", # TODO(kjellander): Cleanup in bugs.webrtc.org/3806.
|
||||||
|
"../base:rtc_base_tests_utils",
|
||||||
"../common_audio",
|
"../common_audio",
|
||||||
"../common_video",
|
"../common_video",
|
||||||
"../system_wrappers",
|
"../system_wrappers",
|
||||||
|
"../system_wrappers:metrics_default",
|
||||||
"../test:rtp_test_utils",
|
"../test:rtp_test_utils",
|
||||||
"../test:test_common",
|
"../test:test_common",
|
||||||
"../test:test_main",
|
"../test:test_main",
|
||||||
|
|||||||
@ -839,6 +839,7 @@ rtc_static_library("webrtc_opus") {
|
|||||||
"../..:webrtc_common",
|
"../..:webrtc_common",
|
||||||
"../../base:rtc_analytics",
|
"../../base:rtc_analytics",
|
||||||
"../../base:rtc_base_approved",
|
"../../base:rtc_base_approved",
|
||||||
|
"../../common_audio",
|
||||||
"../../system_wrappers",
|
"../../system_wrappers",
|
||||||
]
|
]
|
||||||
public_deps = [
|
public_deps = [
|
||||||
|
|||||||
@ -648,7 +648,8 @@ int AudioCodingModuleImpl::SendFrequency() const {
|
|||||||
void AudioCodingModuleImpl::SetBitRate(int bitrate_bps) {
|
void AudioCodingModuleImpl::SetBitRate(int bitrate_bps) {
|
||||||
rtc::CritScope lock(&acm_crit_sect_);
|
rtc::CritScope lock(&acm_crit_sect_);
|
||||||
if (encoder_stack_) {
|
if (encoder_stack_) {
|
||||||
encoder_stack_->OnReceivedTargetAudioBitrate(bitrate_bps);
|
encoder_stack_->OnReceivedUplinkBandwidth(bitrate_bps,
|
||||||
|
rtc::Optional<int64_t>());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -72,12 +72,16 @@ bool AudioEncoder::EnableAudioNetworkAdaptor(const std::string& config_string,
|
|||||||
|
|
||||||
void AudioEncoder::DisableAudioNetworkAdaptor() {}
|
void AudioEncoder::DisableAudioNetworkAdaptor() {}
|
||||||
|
|
||||||
void AudioEncoder::OnReceivedUplinkBandwidth(int uplink_bandwidth_bps) {}
|
|
||||||
|
|
||||||
void AudioEncoder::OnReceivedUplinkPacketLossFraction(
|
void AudioEncoder::OnReceivedUplinkPacketLossFraction(
|
||||||
float uplink_packet_loss_fraction) {}
|
float uplink_packet_loss_fraction) {}
|
||||||
|
|
||||||
void AudioEncoder::OnReceivedTargetAudioBitrate(int target_audio_bitrate_bps) {}
|
void AudioEncoder::OnReceivedTargetAudioBitrate(int target_audio_bitrate_bps) {
|
||||||
|
OnReceivedUplinkBandwidth(target_audio_bitrate_bps, rtc::Optional<int64_t>());
|
||||||
|
}
|
||||||
|
|
||||||
|
void AudioEncoder::OnReceivedUplinkBandwidth(
|
||||||
|
int target_audio_bitrate_bps,
|
||||||
|
rtc::Optional<int64_t> probing_interval_ms) {}
|
||||||
|
|
||||||
void AudioEncoder::OnReceivedRtt(int rtt_ms) {}
|
void AudioEncoder::OnReceivedRtt(int rtt_ms) {}
|
||||||
|
|
||||||
|
|||||||
@ -17,6 +17,7 @@
|
|||||||
#include "webrtc/base/array_view.h"
|
#include "webrtc/base/array_view.h"
|
||||||
#include "webrtc/base/buffer.h"
|
#include "webrtc/base/buffer.h"
|
||||||
#include "webrtc/base/deprecation.h"
|
#include "webrtc/base/deprecation.h"
|
||||||
|
#include "webrtc/base/optional.h"
|
||||||
#include "webrtc/typedefs.h"
|
#include "webrtc/typedefs.h"
|
||||||
|
|
||||||
namespace webrtc {
|
namespace webrtc {
|
||||||
@ -167,16 +168,19 @@ class AudioEncoder {
|
|||||||
// Disables audio network adaptor.
|
// Disables audio network adaptor.
|
||||||
virtual void DisableAudioNetworkAdaptor();
|
virtual void DisableAudioNetworkAdaptor();
|
||||||
|
|
||||||
// Provides uplink bandwidth to this encoder to allow it to adapt.
|
|
||||||
virtual void OnReceivedUplinkBandwidth(int uplink_bandwidth_bps);
|
|
||||||
|
|
||||||
// Provides uplink packet loss fraction to this encoder to allow it to adapt.
|
// Provides uplink packet loss fraction to this encoder to allow it to adapt.
|
||||||
// |uplink_packet_loss_fraction| is in the range [0.0, 1.0].
|
// |uplink_packet_loss_fraction| is in the range [0.0, 1.0].
|
||||||
virtual void OnReceivedUplinkPacketLossFraction(
|
virtual void OnReceivedUplinkPacketLossFraction(
|
||||||
float uplink_packet_loss_fraction);
|
float uplink_packet_loss_fraction);
|
||||||
|
|
||||||
// Provides target audio bitrate to this encoder to allow it to adapt.
|
// Provides target audio bitrate to this encoder to allow it to adapt.
|
||||||
virtual void OnReceivedTargetAudioBitrate(int target_audio_bitrate_bps);
|
virtual void OnReceivedTargetAudioBitrate(int target_bps);
|
||||||
|
|
||||||
|
// Provides target audio bitrate and corresponding probing interval of
|
||||||
|
// the bandwidth estimator to this encoder to allow it to adapt.
|
||||||
|
virtual void OnReceivedUplinkBandwidth(
|
||||||
|
int target_audio_bitrate_bps,
|
||||||
|
rtc::Optional<int64_t> probing_interval_ms);
|
||||||
|
|
||||||
// Provides RTT to this encoder to allow it to adapt.
|
// Provides RTT to this encoder to allow it to adapt.
|
||||||
virtual void OnReceivedRtt(int rtt_ms);
|
virtual void OnReceivedRtt(int rtt_ms);
|
||||||
|
|||||||
@ -190,9 +190,11 @@ void AudioEncoderCng::OnReceivedUplinkPacketLossFraction(
|
|||||||
uplink_packet_loss_fraction);
|
uplink_packet_loss_fraction);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AudioEncoderCng::OnReceivedTargetAudioBitrate(
|
void AudioEncoderCng::OnReceivedUplinkBandwidth(
|
||||||
int target_audio_bitrate_bps) {
|
int target_audio_bitrate_bps,
|
||||||
speech_encoder_->OnReceivedTargetAudioBitrate(target_audio_bitrate_bps);
|
rtc::Optional<int64_t> probing_interval_ms) {
|
||||||
|
speech_encoder_->OnReceivedUplinkBandwidth(target_audio_bitrate_bps,
|
||||||
|
probing_interval_ms);
|
||||||
}
|
}
|
||||||
|
|
||||||
AudioEncoder::EncodedInfo AudioEncoderCng::EncodePassive(
|
AudioEncoder::EncodedInfo AudioEncoderCng::EncodePassive(
|
||||||
|
|||||||
@ -65,7 +65,9 @@ class AudioEncoderCng final : public AudioEncoder {
|
|||||||
override;
|
override;
|
||||||
void OnReceivedUplinkPacketLossFraction(
|
void OnReceivedUplinkPacketLossFraction(
|
||||||
float uplink_packet_loss_fraction) override;
|
float uplink_packet_loss_fraction) override;
|
||||||
void OnReceivedTargetAudioBitrate(int target_audio_bitrate_bps) override;
|
void OnReceivedUplinkBandwidth(
|
||||||
|
int target_audio_bitrate_bps,
|
||||||
|
rtc::Optional<int64_t> probing_interval_ms) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
EncodedInfo EncodePassive(size_t frames_to_encode,
|
EncodedInfo EncodePassive(size_t frames_to_encode,
|
||||||
|
|||||||
@ -219,8 +219,9 @@ TEST_F(AudioEncoderCngTest, CheckFrameSizePropagation) {
|
|||||||
|
|
||||||
TEST_F(AudioEncoderCngTest, CheckTargetAudioBitratePropagation) {
|
TEST_F(AudioEncoderCngTest, CheckTargetAudioBitratePropagation) {
|
||||||
CreateCng(MakeCngConfig());
|
CreateCng(MakeCngConfig());
|
||||||
EXPECT_CALL(*mock_encoder_, OnReceivedTargetAudioBitrate(4711));
|
EXPECT_CALL(*mock_encoder_,
|
||||||
cng_->OnReceivedTargetAudioBitrate(4711);
|
OnReceivedUplinkBandwidth(4711, rtc::Optional<int64_t>()));
|
||||||
|
cng_->OnReceivedUplinkBandwidth(4711, rtc::Optional<int64_t>());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(AudioEncoderCngTest, CheckPacketLossFractionPropagation) {
|
TEST_F(AudioEncoderCngTest, CheckPacketLossFractionPropagation) {
|
||||||
|
|||||||
@ -41,8 +41,9 @@ class MockAudioEncoder : public AudioEncoder {
|
|||||||
MOCK_METHOD1(SetMaxPlaybackRate, void(int frequency_hz));
|
MOCK_METHOD1(SetMaxPlaybackRate, void(int frequency_hz));
|
||||||
MOCK_METHOD1(SetMaxBitrate, void(int max_bps));
|
MOCK_METHOD1(SetMaxBitrate, void(int max_bps));
|
||||||
MOCK_METHOD1(SetMaxPayloadSize, void(int max_payload_size_bytes));
|
MOCK_METHOD1(SetMaxPayloadSize, void(int max_payload_size_bytes));
|
||||||
MOCK_METHOD1(OnReceivedTargetAudioBitrate,
|
MOCK_METHOD2(OnReceivedUplinkBandwidth,
|
||||||
void(int target_audio_bitrate_bps));
|
void(int target_audio_bitrate_bps,
|
||||||
|
rtc::Optional<int64_t> probing_interval_ms));
|
||||||
MOCK_METHOD1(OnReceivedUplinkPacketLossFraction,
|
MOCK_METHOD1(OnReceivedUplinkPacketLossFraction,
|
||||||
void(float uplink_packet_loss_fraction));
|
void(float uplink_packet_loss_fraction));
|
||||||
|
|
||||||
|
|||||||
@ -17,11 +17,11 @@
|
|||||||
#include "webrtc/base/checks.h"
|
#include "webrtc/base/checks.h"
|
||||||
#include "webrtc/base/logging.h"
|
#include "webrtc/base/logging.h"
|
||||||
#include "webrtc/base/safe_conversions.h"
|
#include "webrtc/base/safe_conversions.h"
|
||||||
|
#include "webrtc/base/timeutils.h"
|
||||||
#include "webrtc/common_types.h"
|
#include "webrtc/common_types.h"
|
||||||
#include "webrtc/modules/audio_coding/audio_network_adaptor/audio_network_adaptor_impl.h"
|
#include "webrtc/modules/audio_coding/audio_network_adaptor/audio_network_adaptor_impl.h"
|
||||||
#include "webrtc/modules/audio_coding/audio_network_adaptor/controller_manager.h"
|
#include "webrtc/modules/audio_coding/audio_network_adaptor/controller_manager.h"
|
||||||
#include "webrtc/modules/audio_coding/codecs/opus/opus_interface.h"
|
#include "webrtc/modules/audio_coding/codecs/opus/opus_interface.h"
|
||||||
#include "webrtc/system_wrappers/include/clock.h"
|
|
||||||
#include "webrtc/system_wrappers/include/field_trial.h"
|
#include "webrtc/system_wrappers/include/field_trial.h"
|
||||||
|
|
||||||
namespace webrtc {
|
namespace webrtc {
|
||||||
@ -172,18 +172,23 @@ rtc::Optional<int> AudioEncoderOpus::Config::GetNewComplexity() const {
|
|||||||
|
|
||||||
AudioEncoderOpus::AudioEncoderOpus(
|
AudioEncoderOpus::AudioEncoderOpus(
|
||||||
const Config& config,
|
const Config& config,
|
||||||
AudioNetworkAdaptorCreator&& audio_network_adaptor_creator)
|
AudioNetworkAdaptorCreator&& audio_network_adaptor_creator,
|
||||||
|
std::unique_ptr<SmoothingFilter> bitrate_smoother)
|
||||||
: packet_loss_rate_(0.0),
|
: packet_loss_rate_(0.0),
|
||||||
inst_(nullptr),
|
inst_(nullptr),
|
||||||
packet_loss_fraction_smoother_(new PacketLossFractionSmoother(
|
packet_loss_fraction_smoother_(new PacketLossFractionSmoother(
|
||||||
config.clock ? config.clock : Clock::GetRealTimeClock())),
|
config.clock)),
|
||||||
audio_network_adaptor_creator_(
|
audio_network_adaptor_creator_(
|
||||||
audio_network_adaptor_creator
|
audio_network_adaptor_creator
|
||||||
? std::move(audio_network_adaptor_creator)
|
? std::move(audio_network_adaptor_creator)
|
||||||
: [this](const std::string& config_string, const Clock* clock) {
|
: [this](const std::string& config_string, const Clock* clock) {
|
||||||
return DefaultAudioNetworkAdaptorCreator(config_string,
|
return DefaultAudioNetworkAdaptorCreator(config_string,
|
||||||
clock);
|
clock);
|
||||||
}) {
|
}),
|
||||||
|
bitrate_smoother_(bitrate_smoother
|
||||||
|
? std::move(bitrate_smoother) : std::unique_ptr<SmoothingFilter>(
|
||||||
|
// We choose 5sec as initial time constant due to empirical data.
|
||||||
|
new SmoothingFilterImpl(5000, config.clock))) {
|
||||||
RTC_CHECK(RecreateEncoderInstance(config));
|
RTC_CHECK(RecreateEncoderInstance(config));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -272,13 +277,6 @@ void AudioEncoderOpus::DisableAudioNetworkAdaptor() {
|
|||||||
audio_network_adaptor_.reset(nullptr);
|
audio_network_adaptor_.reset(nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AudioEncoderOpus::OnReceivedUplinkBandwidth(int uplink_bandwidth_bps) {
|
|
||||||
if (!audio_network_adaptor_)
|
|
||||||
return;
|
|
||||||
audio_network_adaptor_->SetUplinkBandwidth(uplink_bandwidth_bps);
|
|
||||||
ApplyAudioNetworkAdaptor();
|
|
||||||
}
|
|
||||||
|
|
||||||
void AudioEncoderOpus::OnReceivedUplinkPacketLossFraction(
|
void AudioEncoderOpus::OnReceivedUplinkPacketLossFraction(
|
||||||
float uplink_packet_loss_fraction) {
|
float uplink_packet_loss_fraction) {
|
||||||
if (!audio_network_adaptor_) {
|
if (!audio_network_adaptor_) {
|
||||||
@ -291,10 +289,26 @@ void AudioEncoderOpus::OnReceivedUplinkPacketLossFraction(
|
|||||||
ApplyAudioNetworkAdaptor();
|
ApplyAudioNetworkAdaptor();
|
||||||
}
|
}
|
||||||
|
|
||||||
void AudioEncoderOpus::OnReceivedTargetAudioBitrate(
|
void AudioEncoderOpus::OnReceivedUplinkBandwidth(
|
||||||
int target_audio_bitrate_bps) {
|
int target_audio_bitrate_bps,
|
||||||
|
rtc::Optional<int64_t> probing_interval_ms) {
|
||||||
if (audio_network_adaptor_) {
|
if (audio_network_adaptor_) {
|
||||||
audio_network_adaptor_->SetTargetAudioBitrate(target_audio_bitrate_bps);
|
audio_network_adaptor_->SetTargetAudioBitrate(target_audio_bitrate_bps);
|
||||||
|
// We give smoothed bitrate allocation to audio network adaptor as
|
||||||
|
// the uplink bandwidth.
|
||||||
|
// The probing spikes should not affect the bitrate smoother more than 25%.
|
||||||
|
// To simplify the calculations we use a step response as input signal.
|
||||||
|
// The step response of an exponential filter is
|
||||||
|
// u(t) = 1 - e^(-t / time_constant).
|
||||||
|
// In order to limit the affect of a BWE spike within 25% of its value
|
||||||
|
// before
|
||||||
|
// the next probing, we would choose a time constant that fulfills
|
||||||
|
// 1 - e^(-probing_interval_ms / time_constant) < 0.25
|
||||||
|
// Then 4 * probing_interval_ms is a good choice.
|
||||||
|
if (probing_interval_ms)
|
||||||
|
bitrate_smoother_->SetTimeConstantMs(*probing_interval_ms * 4);
|
||||||
|
bitrate_smoother_->AddSample(target_audio_bitrate_bps);
|
||||||
|
|
||||||
ApplyAudioNetworkAdaptor();
|
ApplyAudioNetworkAdaptor();
|
||||||
} else if (webrtc::field_trial::FindFullName(
|
} else if (webrtc::field_trial::FindFullName(
|
||||||
"WebRTC-SendSideBwe-WithOverhead") == "Enabled") {
|
"WebRTC-SendSideBwe-WithOverhead") == "Enabled") {
|
||||||
@ -354,6 +368,7 @@ AudioEncoder::EncodedInfo AudioEncoderOpus::EncodeImpl(
|
|||||||
uint32_t rtp_timestamp,
|
uint32_t rtp_timestamp,
|
||||||
rtc::ArrayView<const int16_t> audio,
|
rtc::ArrayView<const int16_t> audio,
|
||||||
rtc::Buffer* encoded) {
|
rtc::Buffer* encoded) {
|
||||||
|
MaybeUpdateUplinkBandwidth();
|
||||||
|
|
||||||
if (input_buffer_.empty())
|
if (input_buffer_.empty())
|
||||||
first_timestamp_in_buffer_ = rtp_timestamp;
|
first_timestamp_in_buffer_ = rtp_timestamp;
|
||||||
@ -521,4 +536,18 @@ AudioEncoderOpus::DefaultAudioNetworkAdaptorCreator(
|
|||||||
GetTargetBitrate(), config_.fec_enabled, GetDtx(), clock)));
|
GetTargetBitrate(), config_.fec_enabled, GetDtx(), clock)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void AudioEncoderOpus::MaybeUpdateUplinkBandwidth() {
|
||||||
|
if (audio_network_adaptor_) {
|
||||||
|
int64_t now_ms = rtc::TimeMillis();
|
||||||
|
if (!bitrate_smoother_last_update_time_ ||
|
||||||
|
now_ms - *bitrate_smoother_last_update_time_ >=
|
||||||
|
config_.uplink_bandwidth_update_interval_ms) {
|
||||||
|
rtc::Optional<float> smoothed_bitrate = bitrate_smoother_->GetAverage();
|
||||||
|
if (smoothed_bitrate)
|
||||||
|
audio_network_adaptor_->SetUplinkBandwidth(*smoothed_bitrate);
|
||||||
|
bitrate_smoother_last_update_time_ = rtc::Optional<int64_t>(now_ms);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace webrtc
|
} // namespace webrtc
|
||||||
|
|||||||
@ -18,6 +18,7 @@
|
|||||||
|
|
||||||
#include "webrtc/base/constructormagic.h"
|
#include "webrtc/base/constructormagic.h"
|
||||||
#include "webrtc/base/optional.h"
|
#include "webrtc/base/optional.h"
|
||||||
|
#include "webrtc/common_audio/smoothing_filter.h"
|
||||||
#include "webrtc/modules/audio_coding/audio_network_adaptor/include/audio_network_adaptor.h"
|
#include "webrtc/modules/audio_coding/audio_network_adaptor/include/audio_network_adaptor.h"
|
||||||
#include "webrtc/modules/audio_coding/codecs/opus/opus_interface.h"
|
#include "webrtc/modules/audio_coding/codecs/opus/opus_interface.h"
|
||||||
#include "webrtc/modules/audio_coding/codecs/audio_encoder.h"
|
#include "webrtc/modules/audio_coding/codecs/audio_encoder.h"
|
||||||
@ -62,7 +63,8 @@ class AudioEncoderOpus final : public AudioEncoder {
|
|||||||
int complexity_threshold_window_bps = 1500;
|
int complexity_threshold_window_bps = 1500;
|
||||||
bool dtx_enabled = false;
|
bool dtx_enabled = false;
|
||||||
std::vector<int> supported_frame_lengths_ms;
|
std::vector<int> supported_frame_lengths_ms;
|
||||||
const Clock* clock = nullptr;
|
const Clock* clock = Clock::GetRealTimeClock();
|
||||||
|
int uplink_bandwidth_update_interval_ms = 200;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
#if defined(WEBRTC_ANDROID) || defined(WEBRTC_IOS) || defined(WEBRTC_ARCH_ARM)
|
#if defined(WEBRTC_ANDROID) || defined(WEBRTC_IOS) || defined(WEBRTC_ARCH_ARM)
|
||||||
@ -79,7 +81,8 @@ class AudioEncoderOpus final : public AudioEncoder {
|
|||||||
const Clock*)>;
|
const Clock*)>;
|
||||||
AudioEncoderOpus(
|
AudioEncoderOpus(
|
||||||
const Config& config,
|
const Config& config,
|
||||||
AudioNetworkAdaptorCreator&& audio_network_adaptor_creator = nullptr);
|
AudioNetworkAdaptorCreator&& audio_network_adaptor_creator = nullptr,
|
||||||
|
std::unique_ptr<SmoothingFilter> bitrate_smoother = nullptr);
|
||||||
|
|
||||||
explicit AudioEncoderOpus(const CodecInst& codec_inst);
|
explicit AudioEncoderOpus(const CodecInst& codec_inst);
|
||||||
|
|
||||||
@ -105,10 +108,11 @@ class AudioEncoderOpus final : public AudioEncoder {
|
|||||||
bool EnableAudioNetworkAdaptor(const std::string& config_string,
|
bool EnableAudioNetworkAdaptor(const std::string& config_string,
|
||||||
const Clock* clock) override;
|
const Clock* clock) override;
|
||||||
void DisableAudioNetworkAdaptor() override;
|
void DisableAudioNetworkAdaptor() override;
|
||||||
void OnReceivedUplinkBandwidth(int uplink_bandwidth_bps) override;
|
|
||||||
void OnReceivedUplinkPacketLossFraction(
|
void OnReceivedUplinkPacketLossFraction(
|
||||||
float uplink_packet_loss_fraction) override;
|
float uplink_packet_loss_fraction) override;
|
||||||
void OnReceivedTargetAudioBitrate(int target_audio_bitrate_bps) override;
|
void OnReceivedUplinkBandwidth(
|
||||||
|
int target_audio_bitrate_bps,
|
||||||
|
rtc::Optional<int64_t> probing_interval_ms) override;
|
||||||
void OnReceivedRtt(int rtt_ms) override;
|
void OnReceivedRtt(int rtt_ms) override;
|
||||||
void OnReceivedOverhead(size_t overhead_bytes_per_packet) override;
|
void OnReceivedOverhead(size_t overhead_bytes_per_packet) override;
|
||||||
void SetReceiverFrameLengthRange(int min_frame_length_ms,
|
void SetReceiverFrameLengthRange(int min_frame_length_ms,
|
||||||
@ -149,6 +153,8 @@ class AudioEncoderOpus final : public AudioEncoder {
|
|||||||
const std::string& config_string,
|
const std::string& config_string,
|
||||||
const Clock* clock) const;
|
const Clock* clock) const;
|
||||||
|
|
||||||
|
void MaybeUpdateUplinkBandwidth();
|
||||||
|
|
||||||
Config config_;
|
Config config_;
|
||||||
float packet_loss_rate_;
|
float packet_loss_rate_;
|
||||||
std::vector<int16_t> input_buffer_;
|
std::vector<int16_t> input_buffer_;
|
||||||
@ -161,6 +167,8 @@ class AudioEncoderOpus final : public AudioEncoder {
|
|||||||
AudioNetworkAdaptorCreator audio_network_adaptor_creator_;
|
AudioNetworkAdaptorCreator audio_network_adaptor_creator_;
|
||||||
std::unique_ptr<AudioNetworkAdaptor> audio_network_adaptor_;
|
std::unique_ptr<AudioNetworkAdaptor> audio_network_adaptor_;
|
||||||
rtc::Optional<size_t> overhead_bytes_per_packet_;
|
rtc::Optional<size_t> overhead_bytes_per_packet_;
|
||||||
|
const std::unique_ptr<SmoothingFilter> bitrate_smoother_;
|
||||||
|
rtc::Optional<int64_t> bitrate_smoother_last_update_time_;
|
||||||
|
|
||||||
RTC_DISALLOW_COPY_AND_ASSIGN(AudioEncoderOpus);
|
RTC_DISALLOW_COPY_AND_ASSIGN(AudioEncoderOpus);
|
||||||
};
|
};
|
||||||
|
|||||||
@ -8,9 +8,12 @@
|
|||||||
* be found in the AUTHORS file in the root of the source tree.
|
* be found in the AUTHORS file in the root of the source tree.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <array>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
#include "webrtc/base/checks.h"
|
#include "webrtc/base/checks.h"
|
||||||
|
#include "webrtc/base/fakeclock.h"
|
||||||
|
#include "webrtc/common_audio/mocks/mock_smoothing_filter.h"
|
||||||
#include "webrtc/common_types.h"
|
#include "webrtc/common_types.h"
|
||||||
#include "webrtc/modules/audio_coding/audio_network_adaptor/mock/mock_audio_network_adaptor.h"
|
#include "webrtc/modules/audio_coding/audio_network_adaptor/mock/mock_audio_network_adaptor.h"
|
||||||
#include "webrtc/modules/audio_coding/codecs/opus/audio_encoder_opus.h"
|
#include "webrtc/modules/audio_coding/codecs/opus/audio_encoder_opus.h"
|
||||||
@ -42,8 +45,10 @@ AudioEncoderOpus::Config CreateConfig(const CodecInst& codec_inst) {
|
|||||||
|
|
||||||
struct AudioEncoderOpusStates {
|
struct AudioEncoderOpusStates {
|
||||||
std::shared_ptr<MockAudioNetworkAdaptor*> mock_audio_network_adaptor;
|
std::shared_ptr<MockAudioNetworkAdaptor*> mock_audio_network_adaptor;
|
||||||
|
MockSmoothingFilter* mock_bitrate_smoother;
|
||||||
std::unique_ptr<AudioEncoderOpus> encoder;
|
std::unique_ptr<AudioEncoderOpus> encoder;
|
||||||
std::unique_ptr<SimulatedClock> simulated_clock;
|
std::unique_ptr<SimulatedClock> simulated_clock;
|
||||||
|
AudioEncoderOpus::Config config;
|
||||||
};
|
};
|
||||||
|
|
||||||
AudioEncoderOpusStates CreateCodec(size_t num_channels) {
|
AudioEncoderOpusStates CreateCodec(size_t num_channels) {
|
||||||
@ -68,11 +73,15 @@ AudioEncoderOpusStates CreateCodec(size_t num_channels) {
|
|||||||
|
|
||||||
CodecInst codec_inst = kDefaultOpusSettings;
|
CodecInst codec_inst = kDefaultOpusSettings;
|
||||||
codec_inst.channels = num_channels;
|
codec_inst.channels = num_channels;
|
||||||
auto config = CreateConfig(codec_inst);
|
states.config = CreateConfig(codec_inst);
|
||||||
|
std::unique_ptr<MockSmoothingFilter> bitrate_smoother(
|
||||||
|
new MockSmoothingFilter());
|
||||||
|
states.mock_bitrate_smoother = bitrate_smoother.get();
|
||||||
states.simulated_clock.reset(new SimulatedClock(kInitialTimeUs));
|
states.simulated_clock.reset(new SimulatedClock(kInitialTimeUs));
|
||||||
config.clock = states.simulated_clock.get();
|
states.config.clock = states.simulated_clock.get();
|
||||||
|
|
||||||
states.encoder.reset(new AudioEncoderOpus(config, std::move(creator)));
|
states.encoder.reset(new AudioEncoderOpus(states.config, std::move(creator),
|
||||||
|
std::move(bitrate_smoother)));
|
||||||
return states;
|
return states;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -153,26 +162,30 @@ TEST(AudioEncoderOpusTest, ToggleDtx) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
TEST(AudioEncoderOpusTest,
|
TEST(AudioEncoderOpusTest,
|
||||||
OnReceivedTargetAudioBitrateWithoutAudioNetworkAdaptor) {
|
OnReceivedUplinkBandwidthWithoutAudioNetworkAdaptor) {
|
||||||
auto states = CreateCodec(1);
|
auto states = CreateCodec(1);
|
||||||
// Constants are replicated from audio_states.encoderopus.cc.
|
// Constants are replicated from audio_states.encoderopus.cc.
|
||||||
const int kMinBitrateBps = 500;
|
const int kMinBitrateBps = 500;
|
||||||
const int kMaxBitrateBps = 512000;
|
const int kMaxBitrateBps = 512000;
|
||||||
// Set a too low bitrate.
|
// Set a too low bitrate.
|
||||||
states.encoder->OnReceivedTargetAudioBitrate(kMinBitrateBps - 1);
|
states.encoder->OnReceivedUplinkBandwidth(kMinBitrateBps - 1,
|
||||||
|
rtc::Optional<int64_t>());
|
||||||
EXPECT_EQ(kMinBitrateBps, states.encoder->GetTargetBitrate());
|
EXPECT_EQ(kMinBitrateBps, states.encoder->GetTargetBitrate());
|
||||||
// Set a too high bitrate.
|
// Set a too high bitrate.
|
||||||
states.encoder->OnReceivedTargetAudioBitrate(kMaxBitrateBps + 1);
|
states.encoder->OnReceivedUplinkBandwidth(kMaxBitrateBps + 1,
|
||||||
|
rtc::Optional<int64_t>());
|
||||||
EXPECT_EQ(kMaxBitrateBps, states.encoder->GetTargetBitrate());
|
EXPECT_EQ(kMaxBitrateBps, states.encoder->GetTargetBitrate());
|
||||||
// Set the minimum rate.
|
// Set the minimum rate.
|
||||||
states.encoder->OnReceivedTargetAudioBitrate(kMinBitrateBps);
|
states.encoder->OnReceivedUplinkBandwidth(kMinBitrateBps,
|
||||||
|
rtc::Optional<int64_t>());
|
||||||
EXPECT_EQ(kMinBitrateBps, states.encoder->GetTargetBitrate());
|
EXPECT_EQ(kMinBitrateBps, states.encoder->GetTargetBitrate());
|
||||||
// Set the maximum rate.
|
// Set the maximum rate.
|
||||||
states.encoder->OnReceivedTargetAudioBitrate(kMaxBitrateBps);
|
states.encoder->OnReceivedUplinkBandwidth(kMaxBitrateBps,
|
||||||
|
rtc::Optional<int64_t>());
|
||||||
EXPECT_EQ(kMaxBitrateBps, states.encoder->GetTargetBitrate());
|
EXPECT_EQ(kMaxBitrateBps, states.encoder->GetTargetBitrate());
|
||||||
// Set rates from 1000 up to 32000 bps.
|
// Set rates from 1000 up to 32000 bps.
|
||||||
for (int rate = 1000; rate <= 32000; rate += 1000) {
|
for (int rate = 1000; rate <= 32000; rate += 1000) {
|
||||||
states.encoder->OnReceivedTargetAudioBitrate(rate);
|
states.encoder->OnReceivedUplinkBandwidth(rate, rtc::Optional<int64_t>());
|
||||||
EXPECT_EQ(rate, states.encoder->GetTargetBitrate());
|
EXPECT_EQ(rate, states.encoder->GetTargetBitrate());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -250,23 +263,6 @@ TEST(AudioEncoderOpusTest, SetReceiverFrameLengthRange) {
|
|||||||
EXPECT_THAT(states.encoder->supported_frame_lengths_ms(), ElementsAre(20));
|
EXPECT_THAT(states.encoder->supported_frame_lengths_ms(), ElementsAre(20));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(AudioEncoderOpusTest, InvokeAudioNetworkAdaptorOnReceivedUplinkBandwidth) {
|
|
||||||
auto states = CreateCodec(2);
|
|
||||||
states.encoder->EnableAudioNetworkAdaptor("", nullptr);
|
|
||||||
|
|
||||||
auto config = CreateEncoderRuntimeConfig();
|
|
||||||
EXPECT_CALL(**states.mock_audio_network_adaptor, GetEncoderRuntimeConfig())
|
|
||||||
.WillOnce(Return(config));
|
|
||||||
|
|
||||||
// Since using mock audio network adaptor, any bandwidth value is fine.
|
|
||||||
constexpr int kUplinkBandwidth = 50000;
|
|
||||||
EXPECT_CALL(**states.mock_audio_network_adaptor,
|
|
||||||
SetUplinkBandwidth(kUplinkBandwidth));
|
|
||||||
states.encoder->OnReceivedUplinkBandwidth(kUplinkBandwidth);
|
|
||||||
|
|
||||||
CheckEncoderRuntimeConfig(states.encoder.get(), config);
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST(AudioEncoderOpusTest,
|
TEST(AudioEncoderOpusTest,
|
||||||
InvokeAudioNetworkAdaptorOnReceivedUplinkPacketLossFraction) {
|
InvokeAudioNetworkAdaptorOnReceivedUplinkPacketLossFraction) {
|
||||||
auto states = CreateCodec(2);
|
auto states = CreateCodec(2);
|
||||||
@ -285,8 +281,7 @@ TEST(AudioEncoderOpusTest,
|
|||||||
CheckEncoderRuntimeConfig(states.encoder.get(), config);
|
CheckEncoderRuntimeConfig(states.encoder.get(), config);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(AudioEncoderOpusTest,
|
TEST(AudioEncoderOpusTest, InvokeAudioNetworkAdaptorOnReceivedUplinkBandwidth) {
|
||||||
InvokeAudioNetworkAdaptorOnReceivedTargetAudioBitrate) {
|
|
||||||
auto states = CreateCodec(2);
|
auto states = CreateCodec(2);
|
||||||
states.encoder->EnableAudioNetworkAdaptor("", nullptr);
|
states.encoder->EnableAudioNetworkAdaptor("", nullptr);
|
||||||
|
|
||||||
@ -296,9 +291,14 @@ TEST(AudioEncoderOpusTest,
|
|||||||
|
|
||||||
// Since using mock audio network adaptor, any target audio bitrate is fine.
|
// Since using mock audio network adaptor, any target audio bitrate is fine.
|
||||||
constexpr int kTargetAudioBitrate = 30000;
|
constexpr int kTargetAudioBitrate = 30000;
|
||||||
|
constexpr int64_t kProbingIntervalMs = 3000;
|
||||||
EXPECT_CALL(**states.mock_audio_network_adaptor,
|
EXPECT_CALL(**states.mock_audio_network_adaptor,
|
||||||
SetTargetAudioBitrate(kTargetAudioBitrate));
|
SetTargetAudioBitrate(kTargetAudioBitrate));
|
||||||
states.encoder->OnReceivedTargetAudioBitrate(kTargetAudioBitrate);
|
EXPECT_CALL(*states.mock_bitrate_smoother,
|
||||||
|
SetTimeConstantMs(kProbingIntervalMs * 4));
|
||||||
|
EXPECT_CALL(*states.mock_bitrate_smoother, AddSample(kTargetAudioBitrate));
|
||||||
|
states.encoder->OnReceivedUplinkBandwidth(
|
||||||
|
kTargetAudioBitrate, rtc::Optional<int64_t>(kProbingIntervalMs));
|
||||||
|
|
||||||
CheckEncoderRuntimeConfig(states.encoder.get(), config);
|
CheckEncoderRuntimeConfig(states.encoder.get(), config);
|
||||||
}
|
}
|
||||||
@ -367,7 +367,8 @@ TEST(AudioEncoderOpusTest, DoNotInvokeSetTargetBitrateIfOverheadUnknown) {
|
|||||||
|
|
||||||
auto states = CreateCodec(2);
|
auto states = CreateCodec(2);
|
||||||
|
|
||||||
states.encoder->OnReceivedTargetAudioBitrate(kDefaultOpusSettings.rate * 2);
|
states.encoder->OnReceivedUplinkBandwidth(kDefaultOpusSettings.rate * 2,
|
||||||
|
rtc::Optional<int64_t>());
|
||||||
|
|
||||||
// Since |OnReceivedOverhead| has not been called, the codec bitrate should
|
// Since |OnReceivedOverhead| has not been called, the codec bitrate should
|
||||||
// not change.
|
// not change.
|
||||||
@ -384,7 +385,8 @@ TEST(AudioEncoderOpusTest, OverheadRemovedFromTargetAudioBitrate) {
|
|||||||
states.encoder->OnReceivedOverhead(kOverheadBytesPerPacket);
|
states.encoder->OnReceivedOverhead(kOverheadBytesPerPacket);
|
||||||
|
|
||||||
constexpr int kTargetBitrateBps = 40000;
|
constexpr int kTargetBitrateBps = 40000;
|
||||||
states.encoder->OnReceivedTargetAudioBitrate(kTargetBitrateBps);
|
states.encoder->OnReceivedUplinkBandwidth(kTargetBitrateBps,
|
||||||
|
rtc::Optional<int64_t>());
|
||||||
|
|
||||||
int packet_rate = rtc::CheckedDivExact(48000, kDefaultOpusSettings.pacsize);
|
int packet_rate = rtc::CheckedDivExact(48000, kDefaultOpusSettings.pacsize);
|
||||||
EXPECT_EQ(kTargetBitrateBps -
|
EXPECT_EQ(kTargetBitrateBps -
|
||||||
@ -410,14 +412,16 @@ TEST(AudioEncoderOpusTest, BitrateBounded) {
|
|||||||
// subtracted. The eventual codec rate should be bounded by |kMinBitrateBps|.
|
// subtracted. The eventual codec rate should be bounded by |kMinBitrateBps|.
|
||||||
int target_bitrate =
|
int target_bitrate =
|
||||||
kOverheadBytesPerPacket * 8 * packet_rate + kMinBitrateBps - 1;
|
kOverheadBytesPerPacket * 8 * packet_rate + kMinBitrateBps - 1;
|
||||||
states.encoder->OnReceivedTargetAudioBitrate(target_bitrate);
|
states.encoder->OnReceivedUplinkBandwidth(target_bitrate,
|
||||||
|
rtc::Optional<int64_t>());
|
||||||
EXPECT_EQ(kMinBitrateBps, states.encoder->GetTargetBitrate());
|
EXPECT_EQ(kMinBitrateBps, states.encoder->GetTargetBitrate());
|
||||||
|
|
||||||
// Set a target rate that is greater than |kMaxBitrateBps| when overhead is
|
// Set a target rate that is greater than |kMaxBitrateBps| when overhead is
|
||||||
// subtracted. The eventual codec rate should be bounded by |kMaxBitrateBps|.
|
// subtracted. The eventual codec rate should be bounded by |kMaxBitrateBps|.
|
||||||
target_bitrate =
|
target_bitrate =
|
||||||
kOverheadBytesPerPacket * 8 * packet_rate + kMaxBitrateBps + 1;
|
kOverheadBytesPerPacket * 8 * packet_rate + kMaxBitrateBps + 1;
|
||||||
states.encoder->OnReceivedTargetAudioBitrate(target_bitrate);
|
states.encoder->OnReceivedUplinkBandwidth(target_bitrate,
|
||||||
|
rtc::Optional<int64_t>());
|
||||||
EXPECT_EQ(kMaxBitrateBps, states.encoder->GetTargetBitrate());
|
EXPECT_EQ(kMaxBitrateBps, states.encoder->GetTargetBitrate());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -464,4 +468,35 @@ TEST(AudioEncoderOpusTest, EmptyConfigDoesNotAffectEncoderSettings) {
|
|||||||
CheckEncoderRuntimeConfig(states.encoder.get(), config);
|
CheckEncoderRuntimeConfig(states.encoder.get(), config);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(AudioEncoderOpusTest, UpdateUplinkBandwidthInAudioNetworkAdaptor) {
|
||||||
|
rtc::ScopedFakeClock fake_clock;
|
||||||
|
auto states = CreateCodec(2);
|
||||||
|
states.encoder->EnableAudioNetworkAdaptor("", nullptr);
|
||||||
|
std::array<int16_t, 480 * 2> audio;
|
||||||
|
audio.fill(0);
|
||||||
|
rtc::Buffer encoded;
|
||||||
|
EXPECT_CALL(*states.mock_bitrate_smoother, GetAverage())
|
||||||
|
.WillOnce(Return(rtc::Optional<float>(50000)));
|
||||||
|
EXPECT_CALL(**states.mock_audio_network_adaptor, SetUplinkBandwidth(50000));
|
||||||
|
states.encoder->Encode(
|
||||||
|
0, rtc::ArrayView<const int16_t>(audio.data(), audio.size()), &encoded);
|
||||||
|
|
||||||
|
// Repeat update uplink bandwidth tests.
|
||||||
|
for (int i = 0; i < 5; i++) {
|
||||||
|
// Don't update till it is time to update again.
|
||||||
|
fake_clock.AdvanceTime(rtc::TimeDelta::FromMilliseconds(
|
||||||
|
states.config.uplink_bandwidth_update_interval_ms - 1));
|
||||||
|
states.encoder->Encode(
|
||||||
|
0, rtc::ArrayView<const int16_t>(audio.data(), audio.size()), &encoded);
|
||||||
|
|
||||||
|
// Update when it is time to update.
|
||||||
|
EXPECT_CALL(*states.mock_bitrate_smoother, GetAverage())
|
||||||
|
.WillOnce(Return(rtc::Optional<float>(40000)));
|
||||||
|
EXPECT_CALL(**states.mock_audio_network_adaptor, SetUplinkBandwidth(40000));
|
||||||
|
fake_clock.AdvanceTime(rtc::TimeDelta::FromMilliseconds(1));
|
||||||
|
states.encoder->Encode(
|
||||||
|
0, rtc::ArrayView<const int16_t>(audio.data(), audio.size()), &encoded);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace webrtc
|
} // namespace webrtc
|
||||||
|
|||||||
@ -126,9 +126,11 @@ void AudioEncoderCopyRed::OnReceivedUplinkPacketLossFraction(
|
|||||||
uplink_packet_loss_fraction);
|
uplink_packet_loss_fraction);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AudioEncoderCopyRed::OnReceivedTargetAudioBitrate(
|
void AudioEncoderCopyRed::OnReceivedUplinkBandwidth(
|
||||||
int target_audio_bitrate_bps) {
|
int target_audio_bitrate_bps,
|
||||||
speech_encoder_->OnReceivedTargetAudioBitrate(target_audio_bitrate_bps);
|
rtc::Optional<int64_t> probing_interval_ms) {
|
||||||
|
speech_encoder_->OnReceivedUplinkBandwidth(target_audio_bitrate_bps,
|
||||||
|
probing_interval_ms);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace webrtc
|
} // namespace webrtc
|
||||||
|
|||||||
@ -53,7 +53,9 @@ class AudioEncoderCopyRed final : public AudioEncoder {
|
|||||||
override;
|
override;
|
||||||
void OnReceivedUplinkPacketLossFraction(
|
void OnReceivedUplinkPacketLossFraction(
|
||||||
float uplink_packet_loss_fraction) override;
|
float uplink_packet_loss_fraction) override;
|
||||||
void OnReceivedTargetAudioBitrate(int target_audio_bitrate_bps) override;
|
void OnReceivedUplinkBandwidth(
|
||||||
|
int target_audio_bitrate_bps,
|
||||||
|
rtc::Optional<int64_t> probing_interval_ms) override;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
EncodedInfo EncodeImpl(uint32_t rtp_timestamp,
|
EncodedInfo EncodeImpl(uint32_t rtp_timestamp,
|
||||||
|
|||||||
@ -98,8 +98,9 @@ TEST_F(AudioEncoderCopyRedTest, CheckMaxFrameSizePropagation) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(AudioEncoderCopyRedTest, CheckTargetAudioBitratePropagation) {
|
TEST_F(AudioEncoderCopyRedTest, CheckTargetAudioBitratePropagation) {
|
||||||
EXPECT_CALL(*mock_encoder_, OnReceivedTargetAudioBitrate(4711));
|
EXPECT_CALL(*mock_encoder_,
|
||||||
red_->OnReceivedTargetAudioBitrate(4711);
|
OnReceivedUplinkBandwidth(4711, rtc::Optional<int64_t>()));
|
||||||
|
red_->OnReceivedUplinkBandwidth(4711, rtc::Optional<int64_t>());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(AudioEncoderCopyRedTest, CheckPacketLossFractionPropagation) {
|
TEST_F(AudioEncoderCopyRedTest, CheckPacketLossFractionPropagation) {
|
||||||
|
|||||||
@ -469,7 +469,7 @@ TEST_F(AudioDecoderPcmUTest, EncodeDecode) {
|
|||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
int SetAndGetTargetBitrate(AudioEncoder* audio_encoder, int rate) {
|
int SetAndGetTargetBitrate(AudioEncoder* audio_encoder, int rate) {
|
||||||
audio_encoder->OnReceivedTargetAudioBitrate(rate);
|
audio_encoder->OnReceivedUplinkBandwidth(rate, rtc::Optional<int64_t>());
|
||||||
return audio_encoder->GetTargetBitrate();
|
return audio_encoder->GetTargetBitrate();
|
||||||
}
|
}
|
||||||
void TestSetAndGetTargetBitratesWithFixedCodec(AudioEncoder* audio_encoder,
|
void TestSetAndGetTargetBitratesWithFixedCodec(AudioEncoder* audio_encoder,
|
||||||
|
|||||||
@ -57,7 +57,7 @@ if (rtc_include_tests) {
|
|||||||
deps = [
|
deps = [
|
||||||
":rtc_stats",
|
":rtc_stats",
|
||||||
":rtc_stats_test_utils",
|
":rtc_stats_test_utils",
|
||||||
"../base:rtc_base_tests_utils",
|
"../base:rtc_base_tests_main",
|
||||||
"../system_wrappers:metrics_default",
|
"../system_wrappers:metrics_default",
|
||||||
"//testing/gmock",
|
"//testing/gmock",
|
||||||
]
|
]
|
||||||
|
|||||||
@ -926,10 +926,7 @@ Channel::Channel(int32_t channelId,
|
|||||||
rtp_packet_sender_proxy_(new RtpPacketSenderProxy()),
|
rtp_packet_sender_proxy_(new RtpPacketSenderProxy()),
|
||||||
retransmission_rate_limiter_(new RateLimiter(Clock::GetRealTimeClock(),
|
retransmission_rate_limiter_(new RateLimiter(Clock::GetRealTimeClock(),
|
||||||
kMaxRetransmissionWindowMs)),
|
kMaxRetransmissionWindowMs)),
|
||||||
decoder_factory_(config.acm_config.decoder_factory),
|
decoder_factory_(config.acm_config.decoder_factory) {
|
||||||
// Bitrate smoother can be initialized with arbitrary time constant
|
|
||||||
// (0 used here). The actual time constant will be set in SetBitRate.
|
|
||||||
bitrate_smoother_(0, Clock::GetRealTimeClock()) {
|
|
||||||
WEBRTC_TRACE(kTraceMemory, kTraceVoice, VoEId(_instanceId, _channelId),
|
WEBRTC_TRACE(kTraceMemory, kTraceVoice, VoEId(_instanceId, _channelId),
|
||||||
"Channel::Channel() - ctor");
|
"Channel::Channel() - ctor");
|
||||||
AudioCodingModule::Config acm_config(config.acm_config);
|
AudioCodingModule::Config acm_config(config.acm_config);
|
||||||
@ -1332,30 +1329,13 @@ int32_t Channel::SetSendCodec(const CodecInst& codec) {
|
|||||||
void Channel::SetBitRate(int bitrate_bps, int64_t probing_interval_ms) {
|
void Channel::SetBitRate(int bitrate_bps, int64_t probing_interval_ms) {
|
||||||
WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
|
WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
|
||||||
"Channel::SetBitRate(bitrate_bps=%d)", bitrate_bps);
|
"Channel::SetBitRate(bitrate_bps=%d)", bitrate_bps);
|
||||||
audio_coding_->ModifyEncoder([&](std::unique_ptr<AudioEncoder>* encoder) {
|
|
||||||
if (*encoder)
|
|
||||||
(*encoder)->OnReceivedTargetAudioBitrate(bitrate_bps);
|
|
||||||
});
|
|
||||||
retransmission_rate_limiter_->SetMaxRate(bitrate_bps);
|
|
||||||
|
|
||||||
// We give smoothed bitrate allocation to audio network adaptor as
|
|
||||||
// the uplink bandwidth.
|
|
||||||
// The probing spikes should not affect the bitrate smoother more than 25%.
|
|
||||||
// To simplify the calculations we use a step response as input signal.
|
|
||||||
// The step response of an exponential filter is
|
|
||||||
// u(t) = 1 - e^(-t / time_constant).
|
|
||||||
// In order to limit the affect of a BWE spike within 25% of its value before
|
|
||||||
// the next probing, we would choose a time constant that fulfills
|
|
||||||
// 1 - e^(-probing_interval_ms / time_constant) < 0.25
|
|
||||||
// Then 4 * probing_interval_ms is a good choice.
|
|
||||||
bitrate_smoother_.SetTimeConstantMs(probing_interval_ms * 4);
|
|
||||||
bitrate_smoother_.AddSample(bitrate_bps);
|
|
||||||
audio_coding_->ModifyEncoder([&](std::unique_ptr<AudioEncoder>* encoder) {
|
audio_coding_->ModifyEncoder([&](std::unique_ptr<AudioEncoder>* encoder) {
|
||||||
if (*encoder) {
|
if (*encoder) {
|
||||||
(*encoder)->OnReceivedUplinkBandwidth(
|
(*encoder)->OnReceivedUplinkBandwidth(
|
||||||
static_cast<int>(*bitrate_smoother_.GetAverage()));
|
bitrate_bps, rtc::Optional<int64_t>(probing_interval_ms));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
retransmission_rate_limiter_->SetMaxRate(bitrate_bps);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Channel::OnIncomingFractionLoss(int fraction_lost) {
|
void Channel::OnIncomingFractionLoss(int fraction_lost) {
|
||||||
|
|||||||
@ -17,7 +17,6 @@
|
|||||||
#include "webrtc/api/call/audio_sink.h"
|
#include "webrtc/api/call/audio_sink.h"
|
||||||
#include "webrtc/base/criticalsection.h"
|
#include "webrtc/base/criticalsection.h"
|
||||||
#include "webrtc/base/optional.h"
|
#include "webrtc/base/optional.h"
|
||||||
#include "webrtc/common_audio/smoothing_filter.h"
|
|
||||||
#include "webrtc/common_audio/resampler/include/push_resampler.h"
|
#include "webrtc/common_audio/resampler/include/push_resampler.h"
|
||||||
#include "webrtc/common_types.h"
|
#include "webrtc/common_types.h"
|
||||||
#include "webrtc/modules/audio_coding/acm2/codec_manager.h"
|
#include "webrtc/modules/audio_coding/acm2/codec_manager.h"
|
||||||
@ -554,8 +553,6 @@ class Channel
|
|||||||
|
|
||||||
// TODO(ossu): Remove once GetAudioDecoderFactory() is no longer needed.
|
// TODO(ossu): Remove once GetAudioDecoderFactory() is no longer needed.
|
||||||
rtc::scoped_refptr<AudioDecoderFactory> decoder_factory_;
|
rtc::scoped_refptr<AudioDecoderFactory> decoder_factory_;
|
||||||
|
|
||||||
SmoothingFilterImpl bitrate_smoother_;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace voe
|
} // namespace voe
|
||||||
|
|||||||
Reference in New Issue
Block a user