Add RtpEncodingParameters.adaptive_ptime.

When enabled:
- Creates an audio network adapter config that is passed to audio send
stream.
- Configures a lower default min bitrate.

All parameters can be configured via a field trial that can also force
enable the audio network adaptor (this is mainly intended for testing).

Bug: chromium:1086942
Change-Id: I48dfcca1ee2948084199352abed6212a6c78eb6c
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/177840
Reviewed-by: Harald Alvestrand <hta@webrtc.org>
Reviewed-by: Minyue Li <minyue@webrtc.org>
Reviewed-by: Sam Zackrisson <saza@webrtc.org>
Commit-Queue: Jakob Ivarsson <jakobi@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#31565}
This commit is contained in:
Jakob Ivarsson 2020-06-25 14:09:58 +02:00 committed by Commit Bot
parent 118d01ac35
commit 39adce1498
5 changed files with 133 additions and 7 deletions

View File

@ -75,6 +75,8 @@ struct RTC_EXPORT AudioOptions {
// and check if any other AudioOptions members are unused.
absl::optional<bool> combined_audio_video_bwe;
// Enable audio network adaptor.
// TODO(webrtc:11717): Remove this API in favor of adaptivePtime in
// RtpEncodingParameters.
absl::optional<bool> audio_network_adaptor;
// Config string for audio network adaptor.
absl::optional<std::string> audio_network_adaptor_config;

View File

@ -473,6 +473,10 @@ struct RTC_EXPORT RtpEncodingParameters {
// Called "encodingId" in ORTC.
std::string rid;
// Allow dynamic frame length changes for audio:
// https://w3c.github.io/webrtc-extensions/#dom-rtcrtpencodingparameters-adaptiveptime
bool adaptive_ptime = false;
bool operator==(const RtpEncodingParameters& o) const {
return ssrc == o.ssrc && bitrate_priority == o.bitrate_priority &&
network_priority == o.network_priority &&
@ -481,7 +485,8 @@ struct RTC_EXPORT RtpEncodingParameters {
max_framerate == o.max_framerate &&
num_temporal_layers == o.num_temporal_layers &&
scale_resolution_down_by == o.scale_resolution_down_by &&
active == o.active && rid == o.rid;
active == o.active && rid == o.rid &&
adaptive_ptime == o.adaptive_ptime;
}
bool operator!=(const RtpEncodingParameters& o) const {
return !(*this == o);

View File

@ -317,6 +317,7 @@ rtc_library("rtc_audio_video") {
"../rtc_base",
"../rtc_base:audio_format_to_string",
"../rtc_base:checks",
"../rtc_base:ignore_wundef",
"../rtc_base:rtc_task_queue",
"../rtc_base:stringutils",
"../rtc_base/experiments:field_trial_parser",
@ -359,7 +360,10 @@ rtc_library("rtc_audio_video") {
deps += [ "../modules/video_capture:video_capture_internal_impl" ]
}
if (rtc_enable_protobuf) {
deps += [ "../modules/audio_processing/aec_dump:aec_dump_impl" ]
deps += [
"../modules/audio_coding:ana_config_proto",
"../modules/audio_processing/aec_dump:aec_dump_impl",
]
} else {
deps += [ "../modules/audio_processing/aec_dump:null_aec_dump_factory" ]
}

View File

@ -36,7 +36,9 @@
#include "rtc_base/constructor_magic.h"
#include "rtc_base/experiments/field_trial_parser.h"
#include "rtc_base/experiments/field_trial_units.h"
#include "rtc_base/experiments/struct_parameters_parser.h"
#include "rtc_base/helpers.h"
#include "rtc_base/ignore_wundef.h"
#include "rtc_base/logging.h"
#include "rtc_base/race_checker.h"
#include "rtc_base/strings/audio_format_to_string.h"
@ -46,6 +48,16 @@
#include "system_wrappers/include/field_trial.h"
#include "system_wrappers/include/metrics.h"
#if WEBRTC_ENABLE_PROTOBUF
RTC_PUSH_IGNORING_WUNDEF()
#ifdef WEBRTC_ANDROID_PLATFORM_BUILD
#include "external/webrtc/webrtc/modules/audio_coding/audio_network_adaptor/config.pb.h"
#else
#include "modules/audio_coding/audio_network_adaptor/config.pb.h"
#endif
RTC_POP_IGNORING_WUNDEF()
#endif
namespace cricket {
namespace {
@ -191,6 +203,38 @@ absl::optional<int> ComputeSendBitrate(int max_send_bitrate_bps,
}
}
struct AdaptivePtimeConfig {
bool enabled = false;
webrtc::DataRate min_payload_bitrate = webrtc::DataRate::KilobitsPerSec(16);
webrtc::DataRate min_encoder_bitrate = webrtc::DataRate::KilobitsPerSec(12);
bool use_slow_adaptation = true;
absl::optional<std::string> audio_network_adaptor_config;
std::unique_ptr<webrtc::StructParametersParser> Parser() {
return webrtc::StructParametersParser::Create( //
"enabled", &enabled, //
"min_payload_bitrate", &min_payload_bitrate, //
"min_encoder_bitrate", &min_encoder_bitrate, //
"use_slow_adaptation", &use_slow_adaptation);
}
AdaptivePtimeConfig() {
Parser()->Parse(
webrtc::field_trial::FindFullName("WebRTC-Audio-AdaptivePtime"));
#if WEBRTC_ENABLE_PROTOBUF
webrtc::audio_network_adaptor::config::ControllerManager config;
auto* frame_length_controller =
config.add_controllers()->mutable_frame_length_controller_v2();
frame_length_controller->set_min_payload_bitrate_bps(
min_payload_bitrate.bps());
frame_length_controller->set_use_slow_adaptation(use_slow_adaptation);
config.add_controllers()->mutable_bitrate_controller();
audio_network_adaptor_config = config.SerializeAsString();
#endif
}
};
} // namespace
WebRtcVoiceEngine::WebRtcVoiceEngine(
@ -737,7 +781,6 @@ class WebRtcVoiceMediaChannel::WebRtcAudioSendStream
config_.rtp.extensions = extensions;
config_.has_dscp =
rtp_parameters_.encodings[0].network_priority != webrtc::Priority::kLow;
config_.audio_network_adaptor_config = audio_network_adaptor_config;
config_.encoder_factory = encoder_factory;
config_.codec_pair_id = codec_pair_id;
config_.track_id = track_id;
@ -748,6 +791,9 @@ class WebRtcVoiceMediaChannel::WebRtcAudioSendStream
rtp_parameters_.rtcp.cname = c_name;
rtp_parameters_.header_extensions = extensions;
audio_network_adaptor_config_from_options_ = audio_network_adaptor_config;
UpdateAudioNetworkAdaptorConfig();
if (send_codec_spec) {
UpdateSendCodecSpec(*send_codec_spec);
}
@ -798,10 +844,12 @@ class WebRtcVoiceMediaChannel::WebRtcAudioSendStream
void SetAudioNetworkAdaptorConfig(
const absl::optional<std::string>& audio_network_adaptor_config) {
RTC_DCHECK(worker_thread_checker_.IsCurrent());
if (config_.audio_network_adaptor_config == audio_network_adaptor_config) {
if (audio_network_adaptor_config_from_options_ ==
audio_network_adaptor_config) {
return;
}
config_.audio_network_adaptor_config = audio_network_adaptor_config;
audio_network_adaptor_config_from_options_ = audio_network_adaptor_config;
UpdateAudioNetworkAdaptorConfig();
UpdateAllowedBitrateRange();
ReconfigureAudioSendStream();
}
@ -948,6 +996,7 @@ class WebRtcVoiceMediaChannel::WebRtcAudioSendStream
rtp_parameters_.encodings[0].max_bitrate_bps;
double old_priority = rtp_parameters_.encodings[0].bitrate_priority;
webrtc::Priority old_dscp = rtp_parameters_.encodings[0].network_priority;
bool old_adaptive_ptime = rtp_parameters_.encodings[0].adaptive_ptime;
rtp_parameters_ = parameters;
config_.bitrate_priority = rtp_parameters_.encodings[0].bitrate_priority;
config_.has_dscp = (rtp_parameters_.encodings[0].network_priority !=
@ -956,15 +1005,19 @@ class WebRtcVoiceMediaChannel::WebRtcAudioSendStream
bool reconfigure_send_stream =
(rtp_parameters_.encodings[0].max_bitrate_bps != old_rtp_max_bitrate) ||
(rtp_parameters_.encodings[0].bitrate_priority != old_priority) ||
(rtp_parameters_.encodings[0].network_priority != old_dscp);
(rtp_parameters_.encodings[0].network_priority != old_dscp) ||
(rtp_parameters_.encodings[0].adaptive_ptime != old_adaptive_ptime);
if (rtp_parameters_.encodings[0].max_bitrate_bps != old_rtp_max_bitrate) {
// Update the bitrate range.
if (send_rate) {
config_.send_codec_spec->target_bitrate_bps = send_rate;
}
UpdateAllowedBitrateRange();
}
if (reconfigure_send_stream) {
// Changing adaptive_ptime may update the audio network adaptor config
// used.
UpdateAudioNetworkAdaptorConfig();
UpdateAllowedBitrateRange();
ReconfigureAudioSendStream();
}
@ -1000,6 +1053,7 @@ class WebRtcVoiceMediaChannel::WebRtcAudioSendStream
// The order of precedence, from lowest to highest is:
// - a reasonable default of 32kbps min/max
// - fixed target bitrate from codec spec
// - lower min bitrate if adaptive ptime is enabled
// - bitrate configured in the rtp_parameter encodings settings
const int kDefaultBitrateBps = 32000;
config_.min_bitrate_bps = kDefaultBitrateBps;
@ -1011,6 +1065,12 @@ class WebRtcVoiceMediaChannel::WebRtcAudioSendStream
config_.max_bitrate_bps = *config_.send_codec_spec->target_bitrate_bps;
}
if (rtp_parameters_.encodings[0].adaptive_ptime) {
config_.min_bitrate_bps = std::min(
config_.min_bitrate_bps,
static_cast<int>(adaptive_ptime_config_.min_encoder_bitrate.bps()));
}
if (rtp_parameters_.encodings[0].min_bitrate_bps) {
config_.min_bitrate_bps = *rtp_parameters_.encodings[0].min_bitrate_bps;
}
@ -1044,12 +1104,24 @@ class WebRtcVoiceMediaChannel::WebRtcAudioSendStream
UpdateAllowedBitrateRange();
}
void UpdateAudioNetworkAdaptorConfig() {
if (adaptive_ptime_config_.enabled ||
rtp_parameters_.encodings[0].adaptive_ptime) {
config_.audio_network_adaptor_config =
adaptive_ptime_config_.audio_network_adaptor_config;
return;
}
config_.audio_network_adaptor_config =
audio_network_adaptor_config_from_options_;
}
void ReconfigureAudioSendStream() {
RTC_DCHECK(worker_thread_checker_.IsCurrent());
RTC_DCHECK(stream_);
stream_->Reconfigure(config_);
}
const AdaptivePtimeConfig adaptive_ptime_config_;
rtc::ThreadChecker worker_thread_checker_;
rtc::RaceChecker audio_capture_race_checker_;
webrtc::Call* call_ = nullptr;
@ -1067,6 +1139,9 @@ class WebRtcVoiceMediaChannel::WebRtcAudioSendStream
int max_send_bitrate_bps_;
webrtc::RtpParameters rtp_parameters_;
absl::optional<webrtc::AudioCodecSpec> audio_codec_spec_;
// TODO(webrtc:11717): Remove this once audio_network_adaptor in AudioOptions
// has been removed.
absl::optional<std::string> audio_network_adaptor_config_from_options_;
RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(WebRtcAudioSendStream);
};

View File

@ -1219,6 +1219,46 @@ TEST_P(WebRtcVoiceEngineTestFake, SetRtpParametersEncodingsActive) {
EXPECT_TRUE(GetSendStream(kSsrcX).IsSending());
}
TEST_P(WebRtcVoiceEngineTestFake, SetRtpParametersAdaptivePtime) {
EXPECT_TRUE(SetupSendStream());
// Get current parameters and change "adaptive_ptime" to true.
webrtc::RtpParameters parameters = channel_->GetRtpSendParameters(kSsrcX);
ASSERT_EQ(1u, parameters.encodings.size());
ASSERT_FALSE(parameters.encodings[0].adaptive_ptime);
parameters.encodings[0].adaptive_ptime = true;
EXPECT_TRUE(channel_->SetRtpSendParameters(kSsrcX, parameters).ok());
EXPECT_TRUE(GetAudioNetworkAdaptorConfig(kSsrcX));
EXPECT_EQ(12000, GetSendStreamConfig(kSsrcX).min_bitrate_bps);
parameters.encodings[0].adaptive_ptime = false;
EXPECT_TRUE(channel_->SetRtpSendParameters(kSsrcX, parameters).ok());
EXPECT_FALSE(GetAudioNetworkAdaptorConfig(kSsrcX));
EXPECT_EQ(32000, GetSendStreamConfig(kSsrcX).min_bitrate_bps);
}
TEST_P(WebRtcVoiceEngineTestFake,
DisablingAdaptivePtimeDoesNotRemoveAudioNetworkAdaptorFromOptions) {
EXPECT_TRUE(SetupSendStream());
send_parameters_.options.audio_network_adaptor = true;
send_parameters_.options.audio_network_adaptor_config = {"1234"};
SetSendParameters(send_parameters_);
EXPECT_EQ(send_parameters_.options.audio_network_adaptor_config,
GetAudioNetworkAdaptorConfig(kSsrcX));
webrtc::RtpParameters parameters = channel_->GetRtpSendParameters(kSsrcX);
parameters.encodings[0].adaptive_ptime = false;
EXPECT_TRUE(channel_->SetRtpSendParameters(kSsrcX, parameters).ok());
EXPECT_EQ(send_parameters_.options.audio_network_adaptor_config,
GetAudioNetworkAdaptorConfig(kSsrcX));
}
TEST_P(WebRtcVoiceEngineTestFake, AdaptivePtimeFieldTrial) {
webrtc::test::ScopedFieldTrials override_field_trials(
"WebRTC-Audio-AdaptivePtime/enabled:true/");
EXPECT_TRUE(SetupSendStream());
EXPECT_TRUE(GetAudioNetworkAdaptorConfig(kSsrcX));
}
// Test that SetRtpSendParameters configures the correct encoding channel for
// each SSRC.
TEST_P(WebRtcVoiceEngineTestFake, RtpParametersArePerStream) {