Index: webrtc/modules/audio_coding/codecs/opus/audio_encoder_opus.cc |
diff --git a/webrtc/modules/audio_coding/codecs/opus/audio_encoder_opus.cc b/webrtc/modules/audio_coding/codecs/opus/audio_encoder_opus.cc |
index d03f2d3cc2440c3d5fa029e91c4dd037fcf54c96..ae9dae2fbea4bc9e66d6a8b6826236258cc2ecab 100644 |
--- a/webrtc/modules/audio_coding/codecs/opus/audio_encoder_opus.cc |
+++ b/webrtc/modules/audio_coding/codecs/opus/audio_encoder_opus.cc |
@@ -15,7 +15,10 @@ |
#include "webrtc/base/checks.h" |
#include "webrtc/base/safe_conversions.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/controller_manager.h" |
#include "webrtc/modules/audio_coding/codecs/opus/opus_interface.h" |
+#include "webrtc/system_wrappers/include/clock.h" |
namespace webrtc { |
@@ -24,6 +27,7 @@ namespace { |
const int kSampleRateHz = 48000; |
const int kMinBitrateBps = 500; |
const int kMaxBitrateBps = 512000; |
+constexpr int kSupportedFrameLengths[] = {20, 60}; |
AudioEncoderOpus::Config CreateConfig(const CodecInst& codec_inst) { |
AudioEncoderOpus::Config config; |
@@ -104,13 +108,23 @@ int AudioEncoderOpus::Config::GetBitrateBps() const { |
return num_channels == 1 ? 32000 : 64000; // Default value. |
} |
-AudioEncoderOpus::AudioEncoderOpus(const Config& config) |
- : packet_loss_rate_(0.0), inst_(nullptr) { |
+AudioEncoderOpus::AudioEncoderOpus( |
+ const Config& config, |
+ AudioNetworkAdaptorCreator&& audio_network_adaptor_creator) |
+ : packet_loss_rate_(0.0), |
+ inst_(nullptr), |
+ audio_network_adaptor_creator_( |
+ audio_network_adaptor_creator |
+ ? audio_network_adaptor_creator |
+ : [this](const std::string& config_string, const Clock* clock) { |
+ return DefaultAudioNetworkAdaptorCreator(config_string, |
+ clock); |
+ }) { |
RTC_CHECK(RecreateEncoderInstance(config)); |
} |
AudioEncoderOpus::AudioEncoderOpus(const CodecInst& codec_inst) |
- : AudioEncoderOpus(CreateConfig(codec_inst)) {} |
+ : AudioEncoderOpus(CreateConfig(codec_inst), nullptr) {} |
AudioEncoderOpus::~AudioEncoderOpus() { |
RTC_CHECK_EQ(0, WebRtcOpus_EncoderFree(inst_)); |
@@ -141,15 +155,23 @@ void AudioEncoderOpus::Reset() { |
} |
bool AudioEncoderOpus::SetFec(bool enable) { |
- auto conf = config_; |
- conf.fec_enabled = enable; |
- return RecreateEncoderInstance(conf); |
+ if (enable) { |
+ RTC_CHECK_EQ(0, WebRtcOpus_EnableFec(inst_)); |
+ } else { |
+ RTC_CHECK_EQ(0, WebRtcOpus_DisableFec(inst_)); |
+ } |
+ config_.fec_enabled = enable; |
+ return true; |
} |
bool AudioEncoderOpus::SetDtx(bool enable) { |
- auto conf = config_; |
- conf.dtx_enabled = enable; |
- return RecreateEncoderInstance(conf); |
+ if (enable) { |
+ RTC_CHECK_EQ(0, WebRtcOpus_EnableDtx(inst_)); |
+ } else { |
+ RTC_CHECK_EQ(0, WebRtcOpus_DisableDtx(inst_)); |
+ } |
+ config_.dtx_enabled = enable; |
+ return true; |
} |
bool AudioEncoderOpus::GetDtx() const { |
@@ -192,6 +214,57 @@ void AudioEncoderOpus::SetTargetBitrate(int bits_per_second) { |
RTC_CHECK_EQ(0, WebRtcOpus_SetBitRate(inst_, config_.GetBitrateBps())); |
} |
+bool AudioEncoderOpus::EnableAudioNetworkAdaptor( |
+ const std::string& config_string, |
+ const Clock* clock) { |
+ audio_network_adaptor_ = audio_network_adaptor_creator_(config_string, clock); |
+ return audio_network_adaptor_.get() != nullptr; |
+} |
+ |
+void AudioEncoderOpus::DisableAudioNetworkAdaptor() { |
+ 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( |
+ float uplink_packet_loss_fraction) { |
+ if (!audio_network_adaptor_) |
+ return; |
+ audio_network_adaptor_->SetUplinkPacketLossFraction( |
+ uplink_packet_loss_fraction); |
+ ApplyAudioNetworkAdaptor(); |
+} |
+ |
+void AudioEncoderOpus::OnReceivedTargetAudioBitrate( |
+ int target_audio_bitrate_bps) { |
+ if (!audio_network_adaptor_) |
+ return; |
+ audio_network_adaptor_->SetTargetAudioBitrate(target_audio_bitrate_bps); |
+ ApplyAudioNetworkAdaptor(); |
+} |
+ |
+void AudioEncoderOpus::OnReceivedRtt(int rtt_ms) { |
+ if (!audio_network_adaptor_) |
+ return; |
+ audio_network_adaptor_->SetRtt(rtt_ms); |
+ ApplyAudioNetworkAdaptor(); |
+} |
+ |
+void AudioEncoderOpus::SetReceiverFrameLengthRange(int min_frame_length_ms, |
+ int max_frame_length_ms) { |
+ if (!audio_network_adaptor_) |
+ return; |
+ audio_network_adaptor_->SetReceiverFrameLengthRange(min_frame_length_ms, |
+ max_frame_length_ms); |
+ ApplyAudioNetworkAdaptor(); |
+} |
+ |
AudioEncoder::EncodedInfo AudioEncoderOpus::EncodeImpl( |
uint32_t rtp_timestamp, |
rtc::ArrayView<const int16_t> audio, |
@@ -226,6 +299,9 @@ AudioEncoder::EncodedInfo AudioEncoderOpus::EncodeImpl( |
}); |
input_buffer_.clear(); |
+ // Will use new packet size for next encoding. |
+ config_.frame_size_ms = next_frame_length_ms_; |
+ |
info.encoded_timestamp = first_timestamp_in_buffer_; |
info.payload_type = config_.payload_type; |
info.send_even_if_empty = true; // Allows Opus to send empty packets. |
@@ -282,7 +358,59 @@ bool AudioEncoderOpus::RecreateEncoderInstance(const Config& config) { |
WebRtcOpus_SetPacketLossRate( |
inst_, static_cast<int32_t>(packet_loss_rate_ * 100 + .5))); |
config_ = config; |
+ |
+ num_channels_to_encode_ = NumChannels(); |
+ next_frame_length_ms_ = config_.frame_size_ms; |
return true; |
} |
+void AudioEncoderOpus::SetFrameLength(int frame_length_ms) { |
+ next_frame_length_ms_ = frame_length_ms; |
+} |
+ |
+void AudioEncoderOpus::SetNumChannelsToEncode(size_t num_channels_to_encode) { |
+ RTC_DCHECK_GT(num_channels_to_encode, 0u); |
+ RTC_DCHECK_LE(num_channels_to_encode, config_.num_channels); |
+ |
+ if (num_channels_to_encode_ == num_channels_to_encode) |
+ return; |
+ |
+ RTC_CHECK_EQ(0, WebRtcOpus_SetForceChannels(inst_, num_channels_to_encode)); |
+ num_channels_to_encode_ = num_channels_to_encode; |
+} |
+ |
+void AudioEncoderOpus::ApplyAudioNetworkAdaptor() { |
+ auto config = audio_network_adaptor_->GetEncoderRuntimeConfig(); |
+ // |audio_network_adaptor_| is supposed to be configured to output all |
+ // following parameters. |
+ RTC_DCHECK(config.bitrate_bps); |
+ RTC_DCHECK(config.frame_length_ms); |
+ RTC_DCHECK(config.uplink_packet_loss_fraction); |
+ RTC_DCHECK(config.enable_fec); |
+ RTC_DCHECK(config.enable_dtx); |
+ RTC_DCHECK(config.num_channels); |
+ |
+ RTC_DCHECK(*config.frame_length_ms == 20 || *config.frame_length_ms == 60); |
+ |
+ SetTargetBitrate(*config.bitrate_bps); |
+ SetFrameLength(*config.frame_length_ms); |
+ SetFec(*config.enable_fec); |
+ SetProjectedPacketLossRate(*config.uplink_packet_loss_fraction); |
+ SetDtx(*config.enable_dtx); |
+ SetNumChannelsToEncode(*config.num_channels); |
+} |
+ |
+std::unique_ptr<AudioNetworkAdaptor> |
+AudioEncoderOpus::DefaultAudioNetworkAdaptorCreator( |
+ const std::string& config_string, |
+ const Clock* clock) const { |
+ AudioNetworkAdaptorImpl::Config config; |
+ config.clock = clock; |
+ return std::unique_ptr<AudioNetworkAdaptor>(new AudioNetworkAdaptorImpl( |
+ config, ControllerManagerImpl::Create( |
+ config_string, NumChannels(), kSupportedFrameLengths, |
+ num_channels_to_encode_, next_frame_length_ms_, |
+ GetTargetBitrate(), config_.fec_enabled, GetDtx(), clock))); |
+} |
+ |
} // namespace webrtc |