LCOV - code coverage report
Current view: top level - media/webrtc/trunk/webrtc/modules/audio_coding/codecs/opus - audio_encoder_opus.cc (source / functions) Hit Total Coverage
Test: output.info Lines: 0 310 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 46 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :  *  Copyright (c) 2014 The WebRTC project authors. All Rights Reserved.
       3             :  *
       4             :  *  Use of this source code is governed by a BSD-style license
       5             :  *  that can be found in the LICENSE file in the root of the source
       6             :  *  tree. An additional intellectual property rights grant can be found
       7             :  *  in the file PATENTS.  All contributing project authors may
       8             :  *  be found in the AUTHORS file in the root of the source tree.
       9             :  */
      10             : 
      11             : #include "webrtc/modules/audio_coding/codecs/opus/audio_encoder_opus.h"
      12             : 
      13             : #include <algorithm>
      14             : #include <iterator>
      15             : 
      16             : #include "webrtc/base/checks.h"
      17             : #include "webrtc/base/logging.h"
      18             : #include "webrtc/base/numerics/exp_filter.h"
      19             : #include "webrtc/base/safe_conversions.h"
      20             : #include "webrtc/base/timeutils.h"
      21             : #include "webrtc/common_types.h"
      22             : #include "webrtc/modules/audio_coding/audio_network_adaptor/audio_network_adaptor_impl.h"
      23             : #include "webrtc/modules/audio_coding/audio_network_adaptor/controller_manager.h"
      24             : #include "webrtc/modules/audio_coding/codecs/opus/opus_interface.h"
      25             : #include "webrtc/system_wrappers/include/field_trial.h"
      26             : 
      27             : namespace webrtc {
      28             : 
      29             : namespace {
      30             : 
      31             : constexpr int kSampleRateHz = 48000;
      32             : constexpr int kMinBitrateBps = 500;
      33             : constexpr int kMaxBitrateBps = 512000;
      34             : constexpr int kSupportedFrameLengths[] = {20, 60};
      35             : 
      36             : // PacketLossFractionSmoother uses an exponential filter with a time constant
      37             : // of -1.0 / ln(0.9999) = 10000 ms.
      38             : constexpr float kAlphaForPacketLossFractionSmoother = 0.9999f;
      39             : 
      40           0 : AudioEncoderOpus::Config CreateConfig(const CodecInst& codec_inst) {
      41           0 :   AudioEncoderOpus::Config config;
      42           0 :   config.frame_size_ms = rtc::CheckedDivExact(codec_inst.pacsize, 48);
      43           0 :   config.num_channels = codec_inst.channels;
      44           0 :   config.bitrate_bps = rtc::Optional<int>(codec_inst.rate);
      45           0 :   config.payload_type = codec_inst.pltype;
      46           0 :   config.application = config.num_channels == 1 ? AudioEncoderOpus::kVoip
      47             :                                                 : AudioEncoderOpus::kAudio;
      48           0 :   config.supported_frame_lengths_ms.push_back(config.frame_size_ms);
      49             : #if WEBRTC_OPUS_VARIABLE_COMPLEXITY
      50             :   config.low_rate_complexity = 9;
      51             : #endif
      52           0 :   return config;
      53             : }
      54             : 
      55             : // Optimize the loss rate to configure Opus. Basically, optimized loss rate is
      56             : // the input loss rate rounded down to various levels, because a robustly good
      57             : // audio quality is achieved by lowering the packet loss down.
      58             : // Additionally, to prevent toggling, margins are used, i.e., when jumping to
      59             : // a loss rate from below, a higher threshold is used than jumping to the same
      60             : // level from above.
      61           0 : float OptimizePacketLossRate(float new_loss_rate, float old_loss_rate) {
      62           0 :   RTC_DCHECK_GE(new_loss_rate, 0.0f);
      63           0 :   RTC_DCHECK_LE(new_loss_rate, 1.0f);
      64           0 :   RTC_DCHECK_GE(old_loss_rate, 0.0f);
      65           0 :   RTC_DCHECK_LE(old_loss_rate, 1.0f);
      66           0 :   constexpr float kPacketLossRate20 = 0.20f;
      67           0 :   constexpr float kPacketLossRate10 = 0.10f;
      68           0 :   constexpr float kPacketLossRate5 = 0.05f;
      69           0 :   constexpr float kPacketLossRate1 = 0.01f;
      70           0 :   constexpr float kLossRate20Margin = 0.02f;
      71           0 :   constexpr float kLossRate10Margin = 0.01f;
      72           0 :   constexpr float kLossRate5Margin = 0.01f;
      73           0 :   if (new_loss_rate >=
      74           0 :       kPacketLossRate20 +
      75             :           kLossRate20Margin *
      76           0 :               (kPacketLossRate20 - old_loss_rate > 0 ? 1 : -1)) {
      77           0 :     return kPacketLossRate20;
      78           0 :   } else if (new_loss_rate >=
      79           0 :              kPacketLossRate10 +
      80             :                  kLossRate10Margin *
      81           0 :                      (kPacketLossRate10 - old_loss_rate > 0 ? 1 : -1)) {
      82           0 :     return kPacketLossRate10;
      83           0 :   } else if (new_loss_rate >=
      84           0 :              kPacketLossRate5 +
      85             :                  kLossRate5Margin *
      86           0 :                      (kPacketLossRate5 - old_loss_rate > 0 ? 1 : -1)) {
      87           0 :     return kPacketLossRate5;
      88           0 :   } else if (new_loss_rate >= kPacketLossRate1) {
      89           0 :     return kPacketLossRate1;
      90             :   } else {
      91           0 :     return 0.0f;
      92             :   }
      93             : }
      94             : 
      95             : }  // namespace
      96             : 
      97             : class AudioEncoderOpus::PacketLossFractionSmoother {
      98             :  public:
      99           0 :   explicit PacketLossFractionSmoother(const Clock* clock)
     100           0 :       : clock_(clock),
     101           0 :         last_sample_time_ms_(clock_->TimeInMilliseconds()),
     102           0 :         smoother_(kAlphaForPacketLossFractionSmoother) {}
     103             : 
     104             :   // Gets the smoothed packet loss fraction.
     105           0 :   float GetAverage() const {
     106           0 :     float value = smoother_.filtered();
     107           0 :     return (value == rtc::ExpFilter::kValueUndefined) ? 0.0f : value;
     108             :   }
     109             : 
     110             :   // Add new observation to the packet loss fraction smoother.
     111           0 :   void AddSample(float packet_loss_fraction) {
     112           0 :     int64_t now_ms = clock_->TimeInMilliseconds();
     113           0 :     smoother_.Apply(static_cast<float>(now_ms - last_sample_time_ms_),
     114           0 :                     packet_loss_fraction);
     115           0 :     last_sample_time_ms_ = now_ms;
     116           0 :   }
     117             : 
     118             :  private:
     119             :   const Clock* const clock_;
     120             :   int64_t last_sample_time_ms_;
     121             : 
     122             :   // An exponential filter is used to smooth the packet loss fraction.
     123             :   rtc::ExpFilter smoother_;
     124             : };
     125             : 
     126           0 : AudioEncoderOpus::Config::Config() {
     127             : #if WEBRTC_OPUS_VARIABLE_COMPLEXITY
     128             :   low_rate_complexity = 9;
     129             : #endif
     130           0 : }
     131             : AudioEncoderOpus::Config::Config(const Config&) = default;
     132             : AudioEncoderOpus::Config::~Config() = default;
     133             : auto AudioEncoderOpus::Config::operator=(const Config&) -> Config& = default;
     134             : 
     135           0 : bool AudioEncoderOpus::Config::IsOk() const {
     136           0 :   if (frame_size_ms <= 0 || frame_size_ms % 10 != 0)
     137           0 :     return false;
     138           0 :   if (num_channels != 1 && num_channels != 2)
     139           0 :     return false;
     140           0 :   if (bitrate_bps &&
     141           0 :       (*bitrate_bps < kMinBitrateBps || *bitrate_bps > kMaxBitrateBps))
     142           0 :     return false;
     143           0 :   if (complexity < 0 || complexity > 10)
     144           0 :     return false;
     145           0 :   if (low_rate_complexity < 0 || low_rate_complexity > 10)
     146           0 :     return false;
     147           0 :   return true;
     148             : }
     149             : 
     150           0 : int AudioEncoderOpus::Config::GetBitrateBps() const {
     151           0 :   RTC_DCHECK(IsOk());
     152           0 :   if (bitrate_bps)
     153           0 :     return *bitrate_bps;  // Explicitly set value.
     154             :   else
     155           0 :     return num_channels == 1 ? 32000 : 64000;  // Default value.
     156             : }
     157             : 
     158           0 : rtc::Optional<int> AudioEncoderOpus::Config::GetNewComplexity() const {
     159           0 :   RTC_DCHECK(IsOk());
     160           0 :   const int bitrate_bps = GetBitrateBps();
     161           0 :   if (bitrate_bps >=
     162           0 :           complexity_threshold_bps - complexity_threshold_window_bps &&
     163             :       bitrate_bps <=
     164           0 :           complexity_threshold_bps + complexity_threshold_window_bps) {
     165             :     // Within the hysteresis window; make no change.
     166           0 :     return rtc::Optional<int>();
     167             :   }
     168           0 :   return bitrate_bps <= complexity_threshold_bps
     169             :              ? rtc::Optional<int>(low_rate_complexity)
     170           0 :              : rtc::Optional<int>(complexity);
     171             : }
     172             : 
     173           0 : AudioEncoderOpus::AudioEncoderOpus(
     174             :     const Config& config,
     175             :     AudioNetworkAdaptorCreator&& audio_network_adaptor_creator,
     176           0 :     std::unique_ptr<SmoothingFilter> bitrate_smoother)
     177             :     : packet_loss_rate_(0.0),
     178             :       inst_(nullptr),
     179             :       packet_loss_fraction_smoother_(new PacketLossFractionSmoother(
     180           0 :           config.clock)),
     181             :       audio_network_adaptor_creator_(
     182             :           audio_network_adaptor_creator
     183           0 :               ? std::move(audio_network_adaptor_creator)
     184             :               : [this](const std::string& config_string,
     185             :                        RtcEventLog* event_log,
     186           0 :                        const Clock* clock) {
     187             :                   return DefaultAudioNetworkAdaptorCreator(config_string,
     188             :                                                            event_log, clock);
     189           0 :               }),
     190             :       bitrate_smoother_(bitrate_smoother
     191           0 :           ? std::move(bitrate_smoother) : std::unique_ptr<SmoothingFilter>(
     192             :               // We choose 5sec as initial time constant due to empirical data.
     193           0 :               new SmoothingFilterImpl(5000, config.clock))) {
     194           0 :   RTC_CHECK(RecreateEncoderInstance(config));
     195           0 : }
     196             : 
     197           0 : AudioEncoderOpus::AudioEncoderOpus(const CodecInst& codec_inst)
     198           0 :     : AudioEncoderOpus(CreateConfig(codec_inst), nullptr) {}
     199             : 
     200           0 : AudioEncoderOpus::~AudioEncoderOpus() {
     201           0 :   RTC_CHECK_EQ(0, WebRtcOpus_EncoderFree(inst_));
     202           0 : }
     203             : 
     204           0 : int AudioEncoderOpus::SampleRateHz() const {
     205           0 :   return kSampleRateHz;
     206             : }
     207             : 
     208           0 : size_t AudioEncoderOpus::NumChannels() const {
     209           0 :   return config_.num_channels;
     210             : }
     211             : 
     212           0 : size_t AudioEncoderOpus::Num10MsFramesInNextPacket() const {
     213           0 :   return Num10msFramesPerPacket();
     214             : }
     215             : 
     216           0 : size_t AudioEncoderOpus::Max10MsFramesInAPacket() const {
     217           0 :   return Num10msFramesPerPacket();
     218             : }
     219             : 
     220           0 : int AudioEncoderOpus::GetTargetBitrate() const {
     221           0 :   return config_.GetBitrateBps();
     222             : }
     223             : 
     224           0 : void AudioEncoderOpus::Reset() {
     225           0 :   RTC_CHECK(RecreateEncoderInstance(config_));
     226           0 : }
     227             : 
     228           0 : bool AudioEncoderOpus::SetFec(bool enable) {
     229           0 :   if (enable) {
     230           0 :     RTC_CHECK_EQ(0, WebRtcOpus_EnableFec(inst_));
     231             :   } else {
     232           0 :     RTC_CHECK_EQ(0, WebRtcOpus_DisableFec(inst_));
     233             :   }
     234           0 :   config_.fec_enabled = enable;
     235           0 :   return true;
     236             : }
     237             : 
     238           0 : bool AudioEncoderOpus::SetDtx(bool enable) {
     239           0 :   if (enable) {
     240           0 :     RTC_CHECK_EQ(0, WebRtcOpus_EnableDtx(inst_));
     241             :   } else {
     242           0 :     RTC_CHECK_EQ(0, WebRtcOpus_DisableDtx(inst_));
     243             :   }
     244           0 :   config_.dtx_enabled = enable;
     245           0 :   return true;
     246             : }
     247             : 
     248           0 : bool AudioEncoderOpus::GetDtx() const {
     249           0 :   return config_.dtx_enabled;
     250             : }
     251             : 
     252           0 : bool AudioEncoderOpus::SetApplication(Application application) {
     253           0 :   auto conf = config_;
     254           0 :   switch (application) {
     255             :     case Application::kSpeech:
     256           0 :       conf.application = AudioEncoderOpus::kVoip;
     257           0 :       break;
     258             :     case Application::kAudio:
     259           0 :       conf.application = AudioEncoderOpus::kAudio;
     260           0 :       break;
     261             :   }
     262           0 :   return RecreateEncoderInstance(conf);
     263             : }
     264             : 
     265           0 : void AudioEncoderOpus::SetMaxPlaybackRate(int frequency_hz) {
     266           0 :   auto conf = config_;
     267           0 :   conf.max_playback_rate_hz = frequency_hz;
     268           0 :   RTC_CHECK(RecreateEncoderInstance(conf));
     269           0 : }
     270             : 
     271           0 : bool AudioEncoderOpus::EnableAudioNetworkAdaptor(
     272             :     const std::string& config_string,
     273             :     RtcEventLog* event_log,
     274             :     const Clock* clock) {
     275             :   audio_network_adaptor_ =
     276           0 :       audio_network_adaptor_creator_(config_string, event_log, clock);
     277           0 :   return audio_network_adaptor_.get() != nullptr;
     278             : }
     279             : 
     280           0 : void AudioEncoderOpus::DisableAudioNetworkAdaptor() {
     281           0 :   audio_network_adaptor_.reset(nullptr);
     282           0 : }
     283             : 
     284           0 : void AudioEncoderOpus::OnReceivedUplinkPacketLossFraction(
     285             :     float uplink_packet_loss_fraction) {
     286           0 :   if (!audio_network_adaptor_) {
     287           0 :     packet_loss_fraction_smoother_->AddSample(uplink_packet_loss_fraction);
     288           0 :     float average_fraction_loss = packet_loss_fraction_smoother_->GetAverage();
     289           0 :     return SetProjectedPacketLossRate(average_fraction_loss);
     290             :   }
     291           0 :   audio_network_adaptor_->SetUplinkPacketLossFraction(
     292           0 :       uplink_packet_loss_fraction);
     293           0 :   ApplyAudioNetworkAdaptor();
     294             : }
     295             : 
     296           0 : void AudioEncoderOpus::OnReceivedUplinkBandwidth(
     297             :     int target_audio_bitrate_bps,
     298             :     rtc::Optional<int64_t> probing_interval_ms) {
     299           0 :   if (audio_network_adaptor_) {
     300           0 :     audio_network_adaptor_->SetTargetAudioBitrate(target_audio_bitrate_bps);
     301             :     // We give smoothed bitrate allocation to audio network adaptor as
     302             :     // the uplink bandwidth.
     303             :     // The probing spikes should not affect the bitrate smoother more than 25%.
     304             :     // To simplify the calculations we use a step response as input signal.
     305             :     // The step response of an exponential filter is
     306             :     // u(t) = 1 - e^(-t / time_constant).
     307             :     // In order to limit the affect of a BWE spike within 25% of its value
     308             :     // before
     309             :     // the next probing, we would choose a time constant that fulfills
     310             :     // 1 - e^(-probing_interval_ms / time_constant) < 0.25
     311             :     // Then 4 * probing_interval_ms is a good choice.
     312           0 :     if (probing_interval_ms)
     313           0 :       bitrate_smoother_->SetTimeConstantMs(*probing_interval_ms * 4);
     314           0 :     bitrate_smoother_->AddSample(target_audio_bitrate_bps);
     315             : 
     316           0 :     ApplyAudioNetworkAdaptor();
     317           0 :   } else if (webrtc::field_trial::FindFullName(
     318             :                  "WebRTC-SendSideBwe-WithOverhead") == "Enabled") {
     319           0 :     if (!overhead_bytes_per_packet_) {
     320           0 :       LOG(LS_INFO)
     321           0 :           << "AudioEncoderOpus: Overhead unknown, target audio bitrate "
     322           0 :           << target_audio_bitrate_bps << " bps is ignored.";
     323           0 :       return;
     324             :     }
     325             :     const int overhead_bps = static_cast<int>(
     326           0 :         *overhead_bytes_per_packet_ * 8 * 100 / Num10MsFramesInNextPacket());
     327           0 :     SetTargetBitrate(std::min(
     328             :         kMaxBitrateBps,
     329           0 :         std::max(kMinBitrateBps, target_audio_bitrate_bps - overhead_bps)));
     330             :   } else {
     331           0 :     SetTargetBitrate(target_audio_bitrate_bps);
     332             :   }
     333             : }
     334             : 
     335           0 : void AudioEncoderOpus::OnReceivedRtt(int rtt_ms) {
     336           0 :   if (!audio_network_adaptor_)
     337           0 :     return;
     338           0 :   audio_network_adaptor_->SetRtt(rtt_ms);
     339           0 :   ApplyAudioNetworkAdaptor();
     340             : }
     341             : 
     342           0 : void AudioEncoderOpus::OnReceivedOverhead(size_t overhead_bytes_per_packet) {
     343           0 :   if (audio_network_adaptor_) {
     344           0 :     audio_network_adaptor_->SetOverhead(overhead_bytes_per_packet);
     345           0 :     ApplyAudioNetworkAdaptor();
     346             :   } else {
     347             :     overhead_bytes_per_packet_ =
     348           0 :         rtc::Optional<size_t>(overhead_bytes_per_packet);
     349             :   }
     350           0 : }
     351             : 
     352           0 : void AudioEncoderOpus::SetReceiverFrameLengthRange(int min_frame_length_ms,
     353             :                                                    int max_frame_length_ms) {
     354             :   // Ensure that |SetReceiverFrameLengthRange| is called before
     355             :   // |EnableAudioNetworkAdaptor|, otherwise we need to recreate
     356             :   // |audio_network_adaptor_|, which is not a needed use case.
     357           0 :   RTC_DCHECK(!audio_network_adaptor_);
     358             : 
     359           0 :   config_.supported_frame_lengths_ms.clear();
     360             :   std::copy_if(std::begin(kSupportedFrameLengths),
     361             :                std::end(kSupportedFrameLengths),
     362             :                std::back_inserter(config_.supported_frame_lengths_ms),
     363           0 :                [&](int frame_length_ms) {
     364           0 :                  return frame_length_ms >= min_frame_length_ms &&
     365           0 :                         frame_length_ms <= max_frame_length_ms;
     366           0 :                });
     367           0 :   RTC_DCHECK(std::is_sorted(config_.supported_frame_lengths_ms.begin(),
     368           0 :                             config_.supported_frame_lengths_ms.end()));
     369           0 : }
     370             : 
     371           0 : AudioEncoder::EncodedInfo AudioEncoderOpus::EncodeImpl(
     372             :     uint32_t rtp_timestamp,
     373             :     rtc::ArrayView<const int16_t> audio,
     374             :     rtc::Buffer* encoded) {
     375           0 :   MaybeUpdateUplinkBandwidth();
     376             : 
     377           0 :   if (input_buffer_.empty())
     378           0 :     first_timestamp_in_buffer_ = rtp_timestamp;
     379             : 
     380           0 :   input_buffer_.insert(input_buffer_.end(), audio.cbegin(), audio.cend());
     381           0 :   if (input_buffer_.size() <
     382           0 :       (Num10msFramesPerPacket() * SamplesPer10msFrame())) {
     383           0 :     return EncodedInfo();
     384             :   }
     385           0 :   RTC_CHECK_EQ(input_buffer_.size(),
     386           0 :                Num10msFramesPerPacket() * SamplesPer10msFrame());
     387             : 
     388           0 :   const size_t max_encoded_bytes = SufficientOutputBufferSize();
     389           0 :   EncodedInfo info;
     390           0 :   info.encoded_bytes =
     391           0 :       encoded->AppendData(
     392           0 :           max_encoded_bytes, [&] (rtc::ArrayView<uint8_t> encoded) {
     393           0 :             int status = WebRtcOpus_Encode(
     394           0 :                 inst_, &input_buffer_[0],
     395             :                 rtc::CheckedDivExact(input_buffer_.size(),
     396             :                                      config_.num_channels),
     397           0 :                 rtc::saturated_cast<int16_t>(max_encoded_bytes),
     398           0 :                 encoded.data());
     399             : 
     400           0 :             RTC_CHECK_GE(status, 0);  // Fails only if fed invalid data.
     401             : 
     402           0 :             return static_cast<size_t>(status);
     403             :           });
     404           0 :   input_buffer_.clear();
     405             : 
     406             :   // Will use new packet size for next encoding.
     407           0 :   config_.frame_size_ms = next_frame_length_ms_;
     408             : 
     409           0 :   info.encoded_timestamp = first_timestamp_in_buffer_;
     410           0 :   info.payload_type = config_.payload_type;
     411           0 :   info.send_even_if_empty = true;  // Allows Opus to send empty packets.
     412           0 :   info.speech = (info.encoded_bytes > 0);
     413           0 :   info.encoder_type = CodecType::kOpus;
     414           0 :   return info;
     415             : }
     416             : 
     417           0 : size_t AudioEncoderOpus::Num10msFramesPerPacket() const {
     418           0 :   return static_cast<size_t>(rtc::CheckedDivExact(config_.frame_size_ms, 10));
     419             : }
     420             : 
     421           0 : size_t AudioEncoderOpus::SamplesPer10msFrame() const {
     422           0 :   return rtc::CheckedDivExact(kSampleRateHz, 100) * config_.num_channels;
     423             : }
     424             : 
     425           0 : size_t AudioEncoderOpus::SufficientOutputBufferSize() const {
     426             :   // Calculate the number of bytes we expect the encoder to produce,
     427             :   // then multiply by two to give a wide margin for error.
     428             :   const size_t bytes_per_millisecond =
     429           0 :       static_cast<size_t>(config_.GetBitrateBps() / (1000 * 8) + 1);
     430             :   const size_t approx_encoded_bytes =
     431           0 :       Num10msFramesPerPacket() * 10 * bytes_per_millisecond;
     432           0 :   return 2 * approx_encoded_bytes;
     433             : }
     434             : 
     435             : // If the given config is OK, recreate the Opus encoder instance with those
     436             : // settings, save the config, and return true. Otherwise, do nothing and return
     437             : // false.
     438           0 : bool AudioEncoderOpus::RecreateEncoderInstance(const Config& config) {
     439           0 :   if (!config.IsOk())
     440           0 :     return false;
     441           0 :   if (inst_)
     442           0 :     RTC_CHECK_EQ(0, WebRtcOpus_EncoderFree(inst_));
     443           0 :   input_buffer_.clear();
     444           0 :   input_buffer_.reserve(Num10msFramesPerPacket() * SamplesPer10msFrame());
     445           0 :   RTC_CHECK_EQ(0, WebRtcOpus_EncoderCreate(&inst_, config.num_channels,
     446           0 :                                            config.application));
     447           0 :   RTC_CHECK_EQ(0, WebRtcOpus_SetBitRate(inst_, config.GetBitrateBps()));
     448           0 :   if (config.fec_enabled) {
     449           0 :     RTC_CHECK_EQ(0, WebRtcOpus_EnableFec(inst_));
     450             :   } else {
     451           0 :     RTC_CHECK_EQ(0, WebRtcOpus_DisableFec(inst_));
     452             :   }
     453           0 :   RTC_CHECK_EQ(
     454           0 :       0, WebRtcOpus_SetMaxPlaybackRate(inst_, config.max_playback_rate_hz));
     455             :   // Use the default complexity if the start bitrate is within the hysteresis
     456             :   // window.
     457           0 :   complexity_ = config.GetNewComplexity().value_or(config.complexity);
     458           0 :   RTC_CHECK_EQ(0, WebRtcOpus_SetComplexity(inst_, complexity_));
     459           0 :   if (config.dtx_enabled) {
     460           0 :     RTC_CHECK_EQ(0, WebRtcOpus_EnableDtx(inst_));
     461             :   } else {
     462           0 :     RTC_CHECK_EQ(0, WebRtcOpus_DisableDtx(inst_));
     463             :   }
     464           0 :   RTC_CHECK_EQ(0,
     465             :                WebRtcOpus_SetPacketLossRate(
     466           0 :                    inst_, static_cast<int32_t>(packet_loss_rate_ * 100 + .5)));
     467           0 :   config_ = config;
     468             : 
     469           0 :   num_channels_to_encode_ = NumChannels();
     470           0 :   next_frame_length_ms_ = config_.frame_size_ms;
     471           0 :   return true;
     472             : }
     473             : 
     474           0 : void AudioEncoderOpus::SetFrameLength(int frame_length_ms) {
     475           0 :   next_frame_length_ms_ = frame_length_ms;
     476           0 : }
     477             : 
     478           0 : void AudioEncoderOpus::SetNumChannelsToEncode(size_t num_channels_to_encode) {
     479           0 :   RTC_DCHECK_GT(num_channels_to_encode, 0);
     480           0 :   RTC_DCHECK_LE(num_channels_to_encode, config_.num_channels);
     481             : 
     482           0 :   if (num_channels_to_encode_ == num_channels_to_encode)
     483           0 :     return;
     484             : 
     485           0 :   RTC_CHECK_EQ(0, WebRtcOpus_SetForceChannels(inst_, num_channels_to_encode));
     486           0 :   num_channels_to_encode_ = num_channels_to_encode;
     487             : }
     488             : 
     489           0 : void AudioEncoderOpus::SetProjectedPacketLossRate(float fraction) {
     490           0 :   float opt_loss_rate = OptimizePacketLossRate(fraction, packet_loss_rate_);
     491           0 :   if (packet_loss_rate_ != opt_loss_rate) {
     492           0 :     packet_loss_rate_ = opt_loss_rate;
     493           0 :     RTC_CHECK_EQ(
     494             :         0, WebRtcOpus_SetPacketLossRate(
     495           0 :                inst_, static_cast<int32_t>(packet_loss_rate_ * 100 + .5)));
     496             :   }
     497           0 : }
     498             : 
     499           0 : void AudioEncoderOpus::SetTargetBitrate(int bits_per_second) {
     500           0 :   config_.bitrate_bps = rtc::Optional<int>(
     501           0 :       std::max(std::min(bits_per_second, kMaxBitrateBps), kMinBitrateBps));
     502           0 :   RTC_DCHECK(config_.IsOk());
     503           0 :   RTC_CHECK_EQ(0, WebRtcOpus_SetBitRate(inst_, config_.GetBitrateBps()));
     504           0 :   const auto new_complexity = config_.GetNewComplexity();
     505           0 :   if (new_complexity && complexity_ != *new_complexity) {
     506           0 :     complexity_ = *new_complexity;
     507           0 :     RTC_CHECK_EQ(0, WebRtcOpus_SetComplexity(inst_, complexity_));
     508             :   }
     509           0 : }
     510             : 
     511           0 : void AudioEncoderOpus::ApplyAudioNetworkAdaptor() {
     512           0 :   auto config = audio_network_adaptor_->GetEncoderRuntimeConfig();
     513           0 :   RTC_DCHECK(!config.frame_length_ms || *config.frame_length_ms == 20 ||
     514           0 :              *config.frame_length_ms == 60);
     515             : 
     516           0 :   if (config.bitrate_bps)
     517           0 :     SetTargetBitrate(*config.bitrate_bps);
     518           0 :   if (config.frame_length_ms)
     519           0 :     SetFrameLength(*config.frame_length_ms);
     520           0 :   if (config.enable_fec)
     521           0 :     SetFec(*config.enable_fec);
     522           0 :   if (config.uplink_packet_loss_fraction)
     523           0 :     SetProjectedPacketLossRate(*config.uplink_packet_loss_fraction);
     524           0 :   if (config.enable_dtx)
     525           0 :     SetDtx(*config.enable_dtx);
     526           0 :   if (config.num_channels)
     527           0 :     SetNumChannelsToEncode(*config.num_channels);
     528           0 : }
     529             : 
     530             : std::unique_ptr<AudioNetworkAdaptor>
     531           0 : AudioEncoderOpus::DefaultAudioNetworkAdaptorCreator(
     532             :     const std::string& config_string,
     533             :     RtcEventLog* event_log,
     534             :     const Clock* clock) const {
     535           0 :   AudioNetworkAdaptorImpl::Config config;
     536           0 :   config.clock = clock;
     537           0 :   config.event_log = event_log;
     538             :   return std::unique_ptr<AudioNetworkAdaptor>(new AudioNetworkAdaptorImpl(
     539           0 :       config, ControllerManagerImpl::Create(
     540             :                   config_string, NumChannels(), supported_frame_lengths_ms(),
     541           0 :                   num_channels_to_encode_, next_frame_length_ms_,
     542           0 :                   GetTargetBitrate(), config_.fec_enabled, GetDtx(), clock)));
     543             : }
     544             : 
     545           0 : void AudioEncoderOpus::MaybeUpdateUplinkBandwidth() {
     546           0 :   if (audio_network_adaptor_) {
     547           0 :     int64_t now_ms = rtc::TimeMillis();
     548           0 :     if (!bitrate_smoother_last_update_time_ ||
     549           0 :         now_ms - *bitrate_smoother_last_update_time_ >=
     550           0 :             config_.uplink_bandwidth_update_interval_ms) {
     551           0 :       rtc::Optional<float> smoothed_bitrate = bitrate_smoother_->GetAverage();
     552           0 :       if (smoothed_bitrate)
     553           0 :         audio_network_adaptor_->SetUplinkBandwidth(*smoothed_bitrate);
     554           0 :       bitrate_smoother_last_update_time_ = rtc::Optional<int64_t>(now_ms);
     555             :     }
     556             :   }
     557           0 : }
     558             : 
     559             : }  // namespace webrtc

Generated by: LCOV version 1.13