| Index: webrtc/media/engine/webrtcvoiceengine.cc
 | 
| diff --git a/webrtc/media/engine/webrtcvoiceengine.cc b/webrtc/media/engine/webrtcvoiceengine.cc
 | 
| index f05c702c5b5a898278b11dbdd6b98d3db2eb5821..807dfe2ab8da2167aa7e7ff90fd92a9995395acd 100644
 | 
| --- a/webrtc/media/engine/webrtcvoiceengine.cc
 | 
| +++ b/webrtc/media/engine/webrtcvoiceengine.cc
 | 
| @@ -37,6 +37,7 @@
 | 
|  #include "webrtc/media/engine/webrtcmediaengine.h"
 | 
|  #include "webrtc/media/engine/webrtcvoe.h"
 | 
|  #include "webrtc/modules/audio_coding/acm2/rent_a_codec.h"
 | 
| +#include "webrtc/modules/audio_coding/codecs/builtin_audio_encoder_factory.h"
 | 
|  #include "webrtc/modules/audio_mixer/audio_mixer_impl.h"
 | 
|  #include "webrtc/modules/audio_processing/include/audio_processing.h"
 | 
|  #include "webrtc/system_wrappers/include/field_trial.h"
 | 
| @@ -77,27 +78,9 @@ constexpr int kNackRtpHistoryMs = 5000;
 | 
|  #error "Set WEBRTC_INTELLIGIBILITY_ENHANCER to either 0 or 1"
 | 
|  #endif
 | 
|  
 | 
| -// Codec parameters for Opus.
 | 
| -// draft-spittka-payload-rtp-opus-03
 | 
| -
 | 
| -// Recommended bitrates:
 | 
| -// 8-12 kb/s for NB speech,
 | 
| -// 16-20 kb/s for WB speech,
 | 
| -// 28-40 kb/s for FB speech,
 | 
| -// 48-64 kb/s for FB mono music, and
 | 
| -// 64-128 kb/s for FB stereo music.
 | 
| -// The current implementation applies the following values to mono signals,
 | 
| -// and multiplies them by 2 for stereo.
 | 
| -const int kOpusBitrateNbBps = 12000;
 | 
| -const int kOpusBitrateWbBps = 20000;
 | 
| -const int kOpusBitrateFbBps = 32000;
 | 
| -
 | 
| -// Opus bitrate should be in the range between 6000 and 510000.
 | 
| +// For SendSideBwe, Opus bitrate should be in the range between 6000 and 32000.
 | 
|  const int kOpusMinBitrateBps = 6000;
 | 
| -const int kOpusMaxBitrateBps = 510000;
 | 
| -
 | 
| -// iSAC bitrate should be <= 56000.
 | 
| -const int kIsacMaxBitrateBps = 56000;
 | 
| +const int kOpusBitrateFbBps = 32000;
 | 
|  
 | 
|  // Default audio dscp value.
 | 
|  // See http://tools.ietf.org/html/rfc2474 for details.
 | 
| @@ -138,8 +121,15 @@ bool ValidateStreamParams(const StreamParams& sp) {
 | 
|  // Dumps an AudioCodec in RFC 2327-ish format.
 | 
|  std::string ToString(const AudioCodec& codec) {
 | 
|    std::stringstream ss;
 | 
| -  ss << codec.name << "/" << codec.clockrate << "/" << codec.channels
 | 
| -     << " (" << codec.id << ")";
 | 
| +  ss << codec.name << "/" << codec.clockrate << "/" << codec.channels;
 | 
| +  if (!codec.params.empty()) {
 | 
| +    ss << " {";
 | 
| +    for (const auto& param : codec.params) {
 | 
| +      ss << " " << param.first << "=" << param.second;
 | 
| +    }
 | 
| +    ss << " }";
 | 
| +  }
 | 
| +  ss << " (" << codec.id << ")";
 | 
|    return ss.str();
 | 
|  }
 | 
|  
 | 
| @@ -185,12 +175,6 @@ bool VerifyUniquePayloadTypes(const std::vector<AudioCodec>& codecs) {
 | 
|    return it == payload_types.end();
 | 
|  }
 | 
|  
 | 
| -// Return true if codec.params[feature] == "1", false otherwise.
 | 
| -bool IsCodecFeatureEnabled(const AudioCodec& codec, const char* feature) {
 | 
| -  int value;
 | 
| -  return codec.GetParam(feature, &value) && value == 1;
 | 
| -}
 | 
| -
 | 
|  rtc::Optional<std::string> GetAudioNetworkAdaptorConfig(
 | 
|      const AudioOptions& options) {
 | 
|    if (options.audio_network_adaptor && *options.audio_network_adaptor &&
 | 
| @@ -202,85 +186,6 @@ rtc::Optional<std::string> GetAudioNetworkAdaptorConfig(
 | 
|    return rtc::Optional<std::string>();
 | 
|  }
 | 
|  
 | 
| -// Returns integer parameter params[feature] if it is defined. Returns
 | 
| -// |default_value| otherwise.
 | 
| -int GetCodecFeatureInt(const AudioCodec& codec,
 | 
| -                       const char* feature,
 | 
| -                       int default_value) {
 | 
| -  int value = 0;
 | 
| -  if (codec.GetParam(feature, &value)) {
 | 
| -    return value;
 | 
| -  }
 | 
| -  return default_value;
 | 
| -}
 | 
| -
 | 
| -// Use params[kCodecParamMaxAverageBitrate] if it is defined, use codec.bitrate
 | 
| -// otherwise. If the value (either from params or codec.bitrate) <=0, use the
 | 
| -// default configuration. If the value is beyond feasible bit rate of Opus,
 | 
| -// clamp it. Returns the Opus bit rate for operation.
 | 
| -int GetOpusBitrate(const AudioCodec& codec, int max_playback_rate) {
 | 
| -  int bitrate = 0;
 | 
| -  bool use_param = true;
 | 
| -  if (!codec.GetParam(kCodecParamMaxAverageBitrate, &bitrate)) {
 | 
| -    bitrate = codec.bitrate;
 | 
| -    use_param = false;
 | 
| -  }
 | 
| -  if (bitrate <= 0) {
 | 
| -    if (max_playback_rate <= 8000) {
 | 
| -      bitrate = kOpusBitrateNbBps;
 | 
| -    } else if (max_playback_rate <= 16000) {
 | 
| -      bitrate = kOpusBitrateWbBps;
 | 
| -    } else {
 | 
| -      bitrate = kOpusBitrateFbBps;
 | 
| -    }
 | 
| -
 | 
| -    if (IsCodecFeatureEnabled(codec, kCodecParamStereo)) {
 | 
| -      bitrate *= 2;
 | 
| -    }
 | 
| -  } else if (bitrate < kOpusMinBitrateBps || bitrate > kOpusMaxBitrateBps) {
 | 
| -    bitrate = (bitrate < kOpusMinBitrateBps) ? kOpusMinBitrateBps
 | 
| -                                             : kOpusMaxBitrateBps;
 | 
| -    std::string rate_source =
 | 
| -        use_param ? "Codec parameter \"maxaveragebitrate\"" :
 | 
| -            "Supplied Opus bitrate";
 | 
| -    LOG(LS_WARNING) << rate_source
 | 
| -                    << " is invalid and is replaced by: "
 | 
| -                    << bitrate;
 | 
| -  }
 | 
| -  return bitrate;
 | 
| -}
 | 
| -
 | 
| -void GetOpusConfig(const AudioCodec& codec,
 | 
| -                   webrtc::CodecInst* voe_codec,
 | 
| -                   bool* enable_codec_fec,
 | 
| -                   int* max_playback_rate,
 | 
| -                   bool* enable_codec_dtx,
 | 
| -                   int* min_ptime_ms,
 | 
| -                   int* max_ptime_ms) {
 | 
| -  *enable_codec_fec = IsCodecFeatureEnabled(codec, kCodecParamUseInbandFec);
 | 
| -  *enable_codec_dtx = IsCodecFeatureEnabled(codec, kCodecParamUseDtx);
 | 
| -  *max_playback_rate = GetCodecFeatureInt(codec, kCodecParamMaxPlaybackRate,
 | 
| -                                          kOpusDefaultMaxPlaybackRate);
 | 
| -  *max_ptime_ms =
 | 
| -      GetCodecFeatureInt(codec, kCodecParamMaxPTime, kOpusDefaultMaxPTime);
 | 
| -  *min_ptime_ms =
 | 
| -      GetCodecFeatureInt(codec, kCodecParamMinPTime, kOpusDefaultMinPTime);
 | 
| -  if (*max_ptime_ms < *min_ptime_ms) {
 | 
| -    // If min ptime or max ptime defined by codec parameter is wrong, we use
 | 
| -    // the default values.
 | 
| -    *max_ptime_ms = kOpusDefaultMaxPTime;
 | 
| -    *min_ptime_ms = kOpusDefaultMinPTime;
 | 
| -  }
 | 
| -
 | 
| -  // If OPUS, change what we send according to the "stereo" codec
 | 
| -  // parameter, and not the "channels" parameter.  We set
 | 
| -  // voe_codec.channels to 2 if "stereo=1" and 1 otherwise.  If
 | 
| -  // the bitrate is not specified, i.e. is <= zero, we set it to the
 | 
| -  // appropriate default value for mono or stereo Opus.
 | 
| -  voe_codec->channels = IsCodecFeatureEnabled(codec, kCodecParamStereo) ? 2 : 1;
 | 
| -  voe_codec->rate = GetOpusBitrate(codec, *max_playback_rate);
 | 
| -}
 | 
| -
 | 
|  webrtc::AudioState::Config MakeAudioStateConfig(
 | 
|      VoEWrapper* voe_wrapper,
 | 
|      rtc::scoped_refptr<webrtc::AudioMixer> audio_mixer) {
 | 
| @@ -296,67 +201,14 @@ webrtc::AudioState::Config MakeAudioStateConfig(
 | 
|  
 | 
|  class WebRtcVoiceCodecs final {
 | 
|   public:
 | 
| -  // TODO(solenberg): Do this filtering once off-line, add a simple AudioCodec
 | 
| -  // list and add a test which verifies VoE supports the listed codecs.
 | 
| -  static std::vector<AudioCodec> SupportedSendCodecs() {
 | 
| -    std::vector<AudioCodec> result;
 | 
| -    // Iterate first over our preferred codecs list, so that the results are
 | 
| -    // added in order of preference.
 | 
| -    for (size_t i = 0; i < arraysize(kCodecPrefs); ++i) {
 | 
| -      const CodecPref* pref = &kCodecPrefs[i];
 | 
| -      for (webrtc::CodecInst voe_codec : webrtc::acm2::RentACodec::Database()) {
 | 
| -        // Change the sample rate of G722 to 8000 to match SDP.
 | 
| -        MaybeFixupG722(&voe_codec, 8000);
 | 
| -        // Skip uncompressed formats.
 | 
| -        if (IsCodec(voe_codec, kL16CodecName)) {
 | 
| -          continue;
 | 
| -        }
 | 
| -
 | 
| -        if (!IsCodec(voe_codec, pref->name) ||
 | 
| -            pref->clockrate != voe_codec.plfreq ||
 | 
| -            pref->channels != voe_codec.channels) {
 | 
| -          // Not a match.
 | 
| -          continue;
 | 
| -        }
 | 
| -
 | 
| -        AudioCodec codec(pref->payload_type, voe_codec.plname, voe_codec.plfreq,
 | 
| -                         voe_codec.rate, voe_codec.channels);
 | 
| -        LOG(LS_INFO) << "Adding supported codec: " << ToString(codec);
 | 
| -        if (IsCodec(codec, kIsacCodecName)) {
 | 
| -          // Indicate auto-bitrate in signaling.
 | 
| -          codec.bitrate = 0;
 | 
| -        }
 | 
| -        if (IsCodec(codec, kOpusCodecName)) {
 | 
| -          // Only add fmtp parameters that differ from the spec.
 | 
| -          if (kPreferredMinPTime != kOpusDefaultMinPTime) {
 | 
| -            codec.params[kCodecParamMinPTime] =
 | 
| -                rtc::ToString(kPreferredMinPTime);
 | 
| -          }
 | 
| -          if (kPreferredMaxPTime != kOpusDefaultMaxPTime) {
 | 
| -            codec.params[kCodecParamMaxPTime] =
 | 
| -                rtc::ToString(kPreferredMaxPTime);
 | 
| -          }
 | 
| -          codec.SetParam(kCodecParamUseInbandFec, 1);
 | 
| -          codec.AddFeedbackParam(
 | 
| -              FeedbackParam(kRtcpFbParamTransportCc, kParamValueEmpty));
 | 
| -
 | 
| -          // TODO(hellner): Add ptime, sprop-stereo, and stereo
 | 
| -          // when they can be set to values other than the default.
 | 
| -        }
 | 
| -        result.push_back(codec);
 | 
| -      }
 | 
| -    }
 | 
| -    return result;
 | 
| -  }
 | 
| -
 | 
| -  static bool ToCodecInst(const AudioCodec& in,
 | 
| -                          webrtc::CodecInst* out) {
 | 
| +  static bool ToCodecInst(const AudioCodec& in, webrtc::CodecInst* out) {
 | 
|      for (webrtc::CodecInst voe_codec : webrtc::acm2::RentACodec::Database()) {
 | 
|        // Change the sample rate of G722 to 8000 to match SDP.
 | 
|        MaybeFixupG722(&voe_codec, 8000);
 | 
|        AudioCodec codec(voe_codec.pltype, voe_codec.plname, voe_codec.plfreq,
 | 
|                         voe_codec.rate, voe_codec.channels);
 | 
| -      bool multi_rate = IsCodecMultiRate(voe_codec);
 | 
| +      const bool multi_rate =
 | 
| +          IsCodec(codec, kIsacCodecName) || IsCodec(codec, kOpusCodecName);
 | 
|        // Allow arbitrary rates for ISAC to be specified.
 | 
|        if (multi_rate) {
 | 
|          // Set codec.bitrate to 0 so the check for codec.Matches() passes.
 | 
| @@ -383,112 +235,6 @@ class WebRtcVoiceCodecs final {
 | 
|      return false;
 | 
|    }
 | 
|  
 | 
| -  static bool IsCodecMultiRate(const webrtc::CodecInst& codec) {
 | 
| -    for (size_t i = 0; i < arraysize(kCodecPrefs); ++i) {
 | 
| -      if (IsCodec(codec, kCodecPrefs[i].name) &&
 | 
| -          kCodecPrefs[i].clockrate == codec.plfreq) {
 | 
| -        return kCodecPrefs[i].is_multi_rate;
 | 
| -      }
 | 
| -    }
 | 
| -    return false;
 | 
| -  }
 | 
| -
 | 
| -  static int MaxBitrateBps(const webrtc::CodecInst& codec) {
 | 
| -    for (size_t i = 0; i < arraysize(kCodecPrefs); ++i) {
 | 
| -      if (IsCodec(codec, kCodecPrefs[i].name) &&
 | 
| -          kCodecPrefs[i].clockrate == codec.plfreq) {
 | 
| -        return kCodecPrefs[i].max_bitrate_bps;
 | 
| -      }
 | 
| -    }
 | 
| -    return 0;
 | 
| -  }
 | 
| -
 | 
| -  static rtc::ArrayView<const int> GetPacketSizesMs(
 | 
| -      const webrtc::CodecInst& codec) {
 | 
| -    for (size_t i = 0; i < arraysize(kCodecPrefs); ++i) {
 | 
| -      if (IsCodec(codec, kCodecPrefs[i].name)) {
 | 
| -        size_t num_packet_sizes = kMaxNumPacketSize;
 | 
| -        for (int index = 0; index < kMaxNumPacketSize; index++) {
 | 
| -          if (kCodecPrefs[i].packet_sizes_ms[index] == 0) {
 | 
| -            num_packet_sizes = index;
 | 
| -            break;
 | 
| -          }
 | 
| -        }
 | 
| -        return rtc::ArrayView<const int>(kCodecPrefs[i].packet_sizes_ms,
 | 
| -                                         num_packet_sizes);
 | 
| -      }
 | 
| -    }
 | 
| -    return rtc::ArrayView<const int>();
 | 
| -  }
 | 
| -
 | 
| -  // If the AudioCodec param kCodecParamPTime is set, then we will set it to
 | 
| -  // codec pacsize if it's valid, or we will pick the next smallest value we
 | 
| -  // support.
 | 
| -  // TODO(Brave): Query supported packet sizes from ACM when the API is ready.
 | 
| -  static bool SetPTimeAsPacketSize(webrtc::CodecInst* codec, int ptime_ms) {
 | 
| -    for (const CodecPref& codec_pref : kCodecPrefs) {
 | 
| -      if ((IsCodec(*codec, codec_pref.name) &&
 | 
| -          codec_pref.clockrate == codec->plfreq) ||
 | 
| -          IsCodec(*codec, kG722CodecName)) {
 | 
| -        int packet_size_ms = SelectPacketSize(codec_pref, ptime_ms);
 | 
| -        if (packet_size_ms) {
 | 
| -          // Convert unit from milli-seconds to samples.
 | 
| -          codec->pacsize = (codec->plfreq / 1000) * packet_size_ms;
 | 
| -          return true;
 | 
| -        }
 | 
| -      }
 | 
| -    }
 | 
| -    return false;
 | 
| -  }
 | 
| -
 | 
| -  static const AudioCodec* GetPreferredCodec(
 | 
| -      const std::vector<AudioCodec>& codecs,
 | 
| -      webrtc::CodecInst* out) {
 | 
| -    RTC_DCHECK(out);
 | 
| -    // Select the preferred send codec (the first non-telephone-event/CN codec).
 | 
| -    for (const AudioCodec& codec : codecs) {
 | 
| -      if (IsCodec(codec, kDtmfCodecName) || IsCodec(codec, kCnCodecName)) {
 | 
| -        // Skip telephone-event/CN codecs - they will be handled later.
 | 
| -        continue;
 | 
| -      }
 | 
| -
 | 
| -      // We'll use the first codec in the list to actually send audio data.
 | 
| -      // Be sure to use the payload type requested by the remote side.
 | 
| -      // Ignore codecs we don't know about. The negotiation step should prevent
 | 
| -      // this, but double-check to be sure.
 | 
| -      if (!ToCodecInst(codec, out)) {
 | 
| -        LOG(LS_WARNING) << "Unknown codec " << ToString(codec);
 | 
| -        continue;
 | 
| -      }
 | 
| -      return &codec;
 | 
| -    }
 | 
| -    return nullptr;
 | 
| -  }
 | 
| -
 | 
| - private:
 | 
| -  static const int kMaxNumPacketSize = 6;
 | 
| -  struct CodecPref {
 | 
| -    const char* name;
 | 
| -    int clockrate;
 | 
| -    size_t channels;
 | 
| -    int payload_type;
 | 
| -    bool is_multi_rate;
 | 
| -    int packet_sizes_ms[kMaxNumPacketSize];
 | 
| -    int max_bitrate_bps;
 | 
| -  };
 | 
| -  // Note: keep the supported packet sizes in ascending order.
 | 
| -  static const CodecPref kCodecPrefs[14];
 | 
| -
 | 
| -  static int SelectPacketSize(const CodecPref& codec_pref, int ptime_ms) {
 | 
| -    int selected_packet_size_ms = codec_pref.packet_sizes_ms[0];
 | 
| -    for (int packet_size_ms : codec_pref.packet_sizes_ms) {
 | 
| -      if (packet_size_ms && packet_size_ms <= ptime_ms) {
 | 
| -        selected_packet_size_ms = packet_size_ms;
 | 
| -      }
 | 
| -    }
 | 
| -    return selected_packet_size_ms;
 | 
| -  }
 | 
| -
 | 
|    // Changes RTP timestamp rate of G722. This is due to the "bug" in the RFC
 | 
|    // which says that G722 should be advertised as 8 kHz although it is a 16 kHz
 | 
|    // codec.
 | 
| @@ -502,66 +248,37 @@ class WebRtcVoiceCodecs final {
 | 
|    }
 | 
|  };
 | 
|  
 | 
| -const WebRtcVoiceCodecs::CodecPref WebRtcVoiceCodecs::kCodecPrefs[14] = {
 | 
| -#if WEBRTC_OPUS_SUPPORT_120MS_PTIME
 | 
| -    {kOpusCodecName, 48000, 2, 111, true, {10, 20, 40, 60, 120},
 | 
| -     kOpusMaxBitrateBps},
 | 
| -#else
 | 
| -    {kOpusCodecName, 48000, 2, 111, true, {10, 20, 40, 60}, kOpusMaxBitrateBps},
 | 
| -#endif
 | 
| -    {kIsacCodecName, 16000, 1, 103, true, {30, 60}, kIsacMaxBitrateBps},
 | 
| -    {kIsacCodecName, 32000, 1, 104, true, {30}, kIsacMaxBitrateBps},
 | 
| -    // G722 should be advertised as 8000 Hz because of the RFC "bug".
 | 
| -    {kG722CodecName, 8000, 1, 9, false, {10, 20, 30, 40, 50, 60}},
 | 
| -    {kIlbcCodecName, 8000, 1, 102, false, {20, 30, 40, 60}},
 | 
| -    {kPcmuCodecName, 8000, 1, 0, false, {10, 20, 30, 40, 50, 60}},
 | 
| -    {kPcmaCodecName, 8000, 1, 8, false, {10, 20, 30, 40, 50, 60}},
 | 
| -    {kCnCodecName, 32000, 1, 106, false, {}},
 | 
| -    {kCnCodecName, 16000, 1, 105, false, {}},
 | 
| -    {kCnCodecName, 8000, 1, 13, false, {}},
 | 
| -    {kDtmfCodecName, 48000, 1, 110, false, {}},
 | 
| -    {kDtmfCodecName, 32000, 1, 112, false, {}},
 | 
| -    {kDtmfCodecName, 16000, 1, 113, false, {}},
 | 
| -    {kDtmfCodecName, 8000, 1, 126, false, {}}
 | 
| -};
 | 
| -
 | 
|  // |max_send_bitrate_bps| is the bitrate from "b=" in SDP.
 | 
|  // |rtp_max_bitrate_bps| is the bitrate from RtpSender::SetParameters.
 | 
|  rtc::Optional<int> ComputeSendBitrate(int max_send_bitrate_bps,
 | 
|                                        rtc::Optional<int> rtp_max_bitrate_bps,
 | 
| -                                      const webrtc::CodecInst& codec_inst) {
 | 
| +                                      const webrtc::AudioCodecSpec& spec) {
 | 
|    // If application-configured bitrate is set, take minimum of that and SDP
 | 
|    // bitrate.
 | 
|    const int bps = rtp_max_bitrate_bps
 | 
|                        ? MinPositive(max_send_bitrate_bps, *rtp_max_bitrate_bps)
 | 
|                        : max_send_bitrate_bps;
 | 
| -  const int codec_rate = codec_inst.rate;
 | 
| -
 | 
|    if (bps <= 0) {
 | 
| -    return rtc::Optional<int>(codec_rate);
 | 
| +    return rtc::Optional<int>(spec.info.default_bitrate_bps);
 | 
|    }
 | 
|  
 | 
| -  if (codec_inst.pltype == -1) {
 | 
| -    return rtc::Optional<int>(codec_rate);
 | 
| -    ;
 | 
| -  }
 | 
| -
 | 
| -  if (WebRtcVoiceCodecs::IsCodecMultiRate(codec_inst)) {
 | 
| -    // If codec is multi-rate then just set the bitrate.
 | 
| -    return rtc::Optional<int>(
 | 
| -        std::min(bps, WebRtcVoiceCodecs::MaxBitrateBps(codec_inst)));
 | 
| -  }
 | 
| -
 | 
| -  if (bps < codec_inst.rate) {
 | 
| +  if (bps < spec.info.min_bitrate_bps) {
 | 
|      // If codec is not multi-rate and |bps| is less than the fixed bitrate then
 | 
|      // fail. If codec is not multi-rate and |bps| exceeds or equal the fixed
 | 
|      // bitrate then ignore.
 | 
| -    LOG(LS_ERROR) << "Failed to set codec " << codec_inst.plname
 | 
| +    LOG(LS_ERROR) << "Failed to set codec " << spec.format.name
 | 
|                    << " to bitrate " << bps << " bps"
 | 
| -                  << ", requires at least " << codec_inst.rate << " bps.";
 | 
| +                  << ", requires at least " << spec.info.min_bitrate_bps
 | 
| +                  << " bps.";
 | 
|      return rtc::Optional<int>();
 | 
|    }
 | 
| -  return rtc::Optional<int>(codec_rate);
 | 
| +
 | 
| +  if (spec.info.HasFixedBitrate()) {
 | 
| +    return rtc::Optional<int>(spec.info.default_bitrate_bps);
 | 
| +  } else {
 | 
| +    // If codec is multi-rate then just set the bitrate.
 | 
| +    return rtc::Optional<int>(std::min(bps, spec.info.max_bitrate_bps));
 | 
| +  }
 | 
|  }
 | 
|  
 | 
|  }  // namespace
 | 
| @@ -585,7 +302,10 @@ WebRtcVoiceEngine::WebRtcVoiceEngine(
 | 
|      const rtc::scoped_refptr<webrtc::AudioDecoderFactory>& decoder_factory,
 | 
|      rtc::scoped_refptr<webrtc::AudioMixer> audio_mixer,
 | 
|      VoEWrapper* voe_wrapper)
 | 
| -    : adm_(adm), decoder_factory_(decoder_factory), voe_wrapper_(voe_wrapper) {
 | 
| +    : adm_(adm),
 | 
| +      encoder_factory_(webrtc::CreateBuiltinAudioEncoderFactory()),
 | 
| +      decoder_factory_(decoder_factory),
 | 
| +      voe_wrapper_(voe_wrapper) {
 | 
|    RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
 | 
|    LOG(LS_INFO) << "WebRtcVoiceEngine::WebRtcVoiceEngine";
 | 
|    RTC_DCHECK(voe_wrapper);
 | 
| @@ -595,13 +315,13 @@ WebRtcVoiceEngine::WebRtcVoiceEngine(
 | 
|  
 | 
|    // Load our audio codec list.
 | 
|    LOG(LS_INFO) << "Supported send codecs in order of preference:";
 | 
| -  send_codecs_ = WebRtcVoiceCodecs::SupportedSendCodecs();
 | 
| +  send_codecs_ = CollectCodecs(encoder_factory_->GetSupportedEncoders());
 | 
|    for (const AudioCodec& codec : send_codecs_) {
 | 
|      LOG(LS_INFO) << ToString(codec);
 | 
|    }
 | 
|  
 | 
|    LOG(LS_INFO) << "Supported recv codecs in order of preference:";
 | 
| -  recv_codecs_ = CollectRecvCodecs();
 | 
| +  recv_codecs_ = CollectCodecs(decoder_factory_->GetSupportedDecoders());
 | 
|    for (const AudioCodec& codec : recv_codecs_) {
 | 
|      LOG(LS_INFO) << ToString(codec);
 | 
|    }
 | 
| @@ -1104,11 +824,10 @@ webrtc::voe::TransmitMixer* WebRtcVoiceEngine::transmit_mixer() {
 | 
|    return transmit_mixer_;
 | 
|  }
 | 
|  
 | 
| -AudioCodecs WebRtcVoiceEngine::CollectRecvCodecs() const {
 | 
| +AudioCodecs WebRtcVoiceEngine::CollectCodecs(
 | 
| +    const std::vector<webrtc::AudioCodecSpec>& specs) const {
 | 
|    PayloadTypeMapper mapper;
 | 
|    AudioCodecs out;
 | 
| -  const std::vector<webrtc::AudioCodecSpec>& specs =
 | 
| -      decoder_factory_->GetSupportedDecoders();
 | 
|  
 | 
|    // Only generate CN payload types for these clockrates:
 | 
|    std::map<int, bool, std::greater<int>> generate_cn = {{ 8000,  false },
 | 
| @@ -1188,12 +907,14 @@ class WebRtcVoiceMediaChannel::WebRtcAudioSendStream
 | 
|        webrtc::AudioTransport* voe_audio_transport,
 | 
|        uint32_t ssrc,
 | 
|        const std::string& c_name,
 | 
| -      const webrtc::AudioSendStream::Config::SendCodecSpec& send_codec_spec,
 | 
| +      const rtc::Optional<webrtc::AudioSendStream::Config::SendCodecSpec>&
 | 
| +          send_codec_spec,
 | 
|        const std::vector<webrtc::RtpExtension>& extensions,
 | 
|        int max_send_bitrate_bps,
 | 
|        const rtc::Optional<std::string>& audio_network_adaptor_config,
 | 
|        webrtc::Call* call,
 | 
| -      webrtc::Transport* send_transport)
 | 
| +      webrtc::Transport* send_transport,
 | 
| +      const rtc::scoped_refptr<webrtc::AudioEncoderFactory>& encoder_factory)
 | 
|        : voe_audio_transport_(voe_audio_transport),
 | 
|          call_(call),
 | 
|          config_(send_transport),
 | 
| @@ -1205,13 +926,21 @@ class WebRtcVoiceMediaChannel::WebRtcAudioSendStream
 | 
|      // TODO(solenberg): Once we're not using FakeWebRtcVoiceEngine anymore:
 | 
|      // RTC_DCHECK(voe_audio_transport);
 | 
|      RTC_DCHECK(call);
 | 
| +    RTC_DCHECK(encoder_factory);
 | 
|      config_.rtp.ssrc = ssrc;
 | 
|      config_.rtp.c_name = c_name;
 | 
|      config_.voe_channel_id = ch;
 | 
|      config_.rtp.extensions = extensions;
 | 
|      config_.audio_network_adaptor_config = audio_network_adaptor_config;
 | 
| +    config_.encoder_factory = encoder_factory;
 | 
|      rtp_parameters_.encodings[0].ssrc = rtc::Optional<uint32_t>(ssrc);
 | 
| -    RecreateAudioSendStream(send_codec_spec);
 | 
| +
 | 
| +    UpdateAllowedBitrateRange();
 | 
| +    if (send_codec_spec) {
 | 
| +      UpdateSendCodecSpec(*send_codec_spec);
 | 
| +    }
 | 
| +
 | 
| +    CreateAudioSendStream();
 | 
|    }
 | 
|  
 | 
|    ~WebRtcAudioSendStream() override {
 | 
| @@ -1220,56 +949,45 @@ class WebRtcVoiceMediaChannel::WebRtcAudioSendStream
 | 
|      call_->DestroyAudioSendStream(stream_);
 | 
|    }
 | 
|  
 | 
| -  void RecreateAudioSendStream(
 | 
| +  void SetSendCodecSpec(
 | 
|        const webrtc::AudioSendStream::Config::SendCodecSpec& send_codec_spec) {
 | 
| -    RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
 | 
| -    send_codec_spec_ = send_codec_spec;
 | 
| -    config_.rtp.nack.rtp_history_ms =
 | 
| -        send_codec_spec_.nack_enabled ? kNackRtpHistoryMs : 0;
 | 
| -    config_.send_codec_spec = send_codec_spec_;
 | 
| -    auto send_rate = ComputeSendBitrate(
 | 
| -        max_send_bitrate_bps_, rtp_parameters_.encodings[0].max_bitrate_bps,
 | 
| -        send_codec_spec.codec_inst);
 | 
| -    if (send_rate) {
 | 
| -      // Apply a send rate that abides by |max_send_bitrate_bps_| and
 | 
| -      // |rtp_parameters_| when possible. Otherwise use the codec rate.
 | 
| -      config_.send_codec_spec.codec_inst.rate = *send_rate;
 | 
| -    }
 | 
| -    RecreateAudioSendStream();
 | 
| +    UpdateSendCodecSpec(send_codec_spec);
 | 
| +    ReconfigureAudioSendStream();
 | 
|    }
 | 
|  
 | 
| -  void RecreateAudioSendStream(
 | 
| -      const std::vector<webrtc::RtpExtension>& extensions) {
 | 
| +  void SetRtpExtensions(const std::vector<webrtc::RtpExtension>& extensions) {
 | 
|      RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
 | 
|      config_.rtp.extensions = extensions;
 | 
| -    RecreateAudioSendStream();
 | 
| +    ReconfigureAudioSendStream();
 | 
|    }
 | 
|  
 | 
| -  void RecreateAudioSendStream(
 | 
| +  void SetAudioNetworkAdaptorConfig(
 | 
|        const rtc::Optional<std::string>& audio_network_adaptor_config) {
 | 
|      RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
 | 
|      if (config_.audio_network_adaptor_config == audio_network_adaptor_config) {
 | 
|        return;
 | 
|      }
 | 
|      config_.audio_network_adaptor_config = audio_network_adaptor_config;
 | 
| -    RecreateAudioSendStream();
 | 
| +    UpdateAllowedBitrateRange();
 | 
| +    ReconfigureAudioSendStream();
 | 
|    }
 | 
|  
 | 
|    bool SetMaxSendBitrate(int bps) {
 | 
|      RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
 | 
| -    auto send_rate =
 | 
| -        ComputeSendBitrate(bps, rtp_parameters_.encodings[0].max_bitrate_bps,
 | 
| -                           send_codec_spec_.codec_inst);
 | 
| +    RTC_DCHECK(config_.send_codec_spec);
 | 
| +    RTC_DCHECK(audio_codec_spec_);
 | 
| +    auto send_rate = ComputeSendBitrate(
 | 
| +        bps, rtp_parameters_.encodings[0].max_bitrate_bps, *audio_codec_spec_);
 | 
| +
 | 
|      if (!send_rate) {
 | 
|        return false;
 | 
|      }
 | 
|  
 | 
|      max_send_bitrate_bps_ = bps;
 | 
|  
 | 
| -    if (config_.send_codec_spec.codec_inst.rate != *send_rate) {
 | 
| -      // Recreate AudioSendStream with new bit rate.
 | 
| -      config_.send_codec_spec.codec_inst.rate = *send_rate;
 | 
| -      RecreateAudioSendStream();
 | 
| +    if (send_rate != config_.send_codec_spec->target_bitrate_bps) {
 | 
| +      config_.send_codec_spec->target_bitrate_bps = send_rate;
 | 
| +      ReconfigureAudioSendStream();
 | 
|      }
 | 
|      return true;
 | 
|    }
 | 
| @@ -1385,20 +1103,24 @@ class WebRtcVoiceMediaChannel::WebRtcAudioSendStream
 | 
|      if (!ValidateRtpParameters(parameters)) {
 | 
|        return false;
 | 
|      }
 | 
| -    auto send_rate = ComputeSendBitrate(max_send_bitrate_bps_,
 | 
| -                                        parameters.encodings[0].max_bitrate_bps,
 | 
| -                                        send_codec_spec_.codec_inst);
 | 
| -    if (!send_rate) {
 | 
| -      return false;
 | 
| +
 | 
| +    rtc::Optional<int> send_rate;
 | 
| +    if (audio_codec_spec_) {
 | 
| +      send_rate = ComputeSendBitrate(max_send_bitrate_bps_,
 | 
| +                                     parameters.encodings[0].max_bitrate_bps,
 | 
| +                                     *audio_codec_spec_);
 | 
| +      if (!send_rate) {
 | 
| +        return false;
 | 
| +      }
 | 
|      }
 | 
|  
 | 
|      rtp_parameters_ = parameters;
 | 
|  
 | 
|      // parameters.encodings[0].encodings[0].max_bitrate_bps could have changed.
 | 
| -    if (config_.send_codec_spec.codec_inst.rate != *send_rate) {
 | 
| +    if (send_rate && send_rate != config_.send_codec_spec->target_bitrate_bps) {
 | 
|        // Recreate AudioSendStream with new bit rate.
 | 
| -      config_.send_codec_spec.codec_inst.rate = *send_rate;
 | 
| -      RecreateAudioSendStream();
 | 
| +      config_.send_codec_spec->target_bitrate_bps = send_rate;
 | 
| +      ReconfigureAudioSendStream();
 | 
|      } else {
 | 
|        // parameters.encodings[0].active could have changed.
 | 
|        UpdateSendState();
 | 
| @@ -1418,55 +1140,77 @@ class WebRtcVoiceMediaChannel::WebRtcAudioSendStream
 | 
|      }
 | 
|    }
 | 
|  
 | 
| -  void RecreateAudioSendStream() {
 | 
| +  void UpdateAllowedBitrateRange() {
 | 
|      RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
 | 
| -    if (stream_) {
 | 
| -      call_->DestroyAudioSendStream(stream_);
 | 
| -      stream_ = nullptr;
 | 
| -    }
 | 
| -    RTC_DCHECK(!stream_);
 | 
|      if (webrtc::field_trial::IsEnabled("WebRTC-Audio-SendSideBwe")) {
 | 
|        config_.min_bitrate_bps = kOpusMinBitrateBps;
 | 
|        config_.max_bitrate_bps = kOpusBitrateFbBps;
 | 
|        // TODO(mflodman): Keep testing this and set proper values.
 | 
|        // Note: This is an early experiment currently only supported by Opus.
 | 
|        if (send_side_bwe_with_overhead_) {
 | 
| -        auto packet_sizes_ms = WebRtcVoiceCodecs::GetPacketSizesMs(
 | 
| -            config_.send_codec_spec.codec_inst);
 | 
| -        if (!packet_sizes_ms.empty()) {
 | 
| -          int max_packet_size_ms =
 | 
| -              *std::max_element(packet_sizes_ms.begin(), packet_sizes_ms.end());
 | 
| -          int min_packet_size_ms =
 | 
| -              *std::min_element(packet_sizes_ms.begin(), packet_sizes_ms.end());
 | 
| -
 | 
| -          // Audio network adaptor will just use 20ms and 60ms frame lengths.
 | 
| -          // The adaptor will only be active for the Opus encoder.
 | 
| -          if (config_.audio_network_adaptor_config &&
 | 
| -              IsCodec(config_.send_codec_spec.codec_inst, kOpusCodecName)) {
 | 
| -#if WEBRTC_OPUS_SUPPORT_120MS_PTIME
 | 
| -            max_packet_size_ms = 120;
 | 
| -#else
 | 
| -            max_packet_size_ms = 60;
 | 
| -#endif
 | 
| -            min_packet_size_ms = 20;
 | 
| -          }
 | 
| -
 | 
| -          // OverheadPerPacket = Ipv4(20B) + UDP(8B) + SRTP(10B) + RTP(12)
 | 
| -          constexpr int kOverheadPerPacket = 20 + 8 + 10 + 12;
 | 
| -
 | 
| -          int min_overhead_bps =
 | 
| -              kOverheadPerPacket * 8 * 1000 / max_packet_size_ms;
 | 
| -
 | 
| -          int max_overhead_bps =
 | 
| -              kOverheadPerPacket * 8 * 1000 / min_packet_size_ms;
 | 
| -
 | 
| -          config_.min_bitrate_bps = kOpusMinBitrateBps + min_overhead_bps;
 | 
| -          config_.max_bitrate_bps = kOpusBitrateFbBps + max_overhead_bps;
 | 
| -        }
 | 
| +        const bool is_opus_with_ana =
 | 
| +            config_.audio_network_adaptor_config &&
 | 
| +            !STR_CASE_CMP(config_.send_codec_spec->format.name.c_str(),
 | 
| +                          kOpusCodecName);
 | 
| +        const int max_packet_size_ms =
 | 
| +            (is_opus_with_ana && WEBRTC_OPUS_SUPPORT_120MS_PTIME) ? 120 : 60;
 | 
| +        // Audio network adaptor will just use 20ms and 60ms frame lengths.
 | 
| +        // The adaptor will only be active for the Opus encoder.
 | 
| +        const int min_packet_size_ms = is_opus_with_ana ? 20 : 10;
 | 
| +
 | 
| +        // OverheadPerPacket = Ipv4(20B) + UDP(8B) + SRTP(10B) + RTP(12)
 | 
| +        constexpr int kOverheadPerPacket = 20 + 8 + 10 + 12;
 | 
| +
 | 
| +        int min_overhead_bps =
 | 
| +            kOverheadPerPacket * 8 * 1000 / max_packet_size_ms;
 | 
| +
 | 
| +        int max_overhead_bps =
 | 
| +            kOverheadPerPacket * 8 * 1000 / min_packet_size_ms;
 | 
| +
 | 
| +        config_.min_bitrate_bps = kOpusMinBitrateBps + min_overhead_bps;
 | 
| +        config_.max_bitrate_bps = kOpusBitrateFbBps + max_overhead_bps;
 | 
|        }
 | 
|      }
 | 
| +  }
 | 
| +
 | 
| +  void UpdateSendCodecSpec(
 | 
| +      const webrtc::AudioSendStream::Config::SendCodecSpec& send_codec_spec) {
 | 
| +    RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
 | 
| +    config_.rtp.nack.rtp_history_ms =
 | 
| +        send_codec_spec.nack_enabled ? kNackRtpHistoryMs : 0;
 | 
| +    config_.send_codec_spec =
 | 
| +        rtc::Optional<webrtc::AudioSendStream::Config::SendCodecSpec>(
 | 
| +            send_codec_spec);
 | 
| +    auto info =
 | 
| +        config_.encoder_factory->QueryAudioEncoder(send_codec_spec.format);
 | 
| +    RTC_DCHECK(info);
 | 
| +    // If a specific target bitrate has been set for the stream, use that as
 | 
| +    // the new default bitrate when computing send bitrate.
 | 
| +    if (send_codec_spec.target_bitrate_bps) {
 | 
| +      info->default_bitrate_bps = std::max(
 | 
| +          info->min_bitrate_bps,
 | 
| +          std::min(info->max_bitrate_bps, *send_codec_spec.target_bitrate_bps));
 | 
| +    }
 | 
| +
 | 
| +    audio_codec_spec_.emplace(
 | 
| +        webrtc::AudioCodecSpec{send_codec_spec.format, *info});
 | 
| +
 | 
| +    config_.send_codec_spec->target_bitrate_bps = ComputeSendBitrate(
 | 
| +        max_send_bitrate_bps_, rtp_parameters_.encodings[0].max_bitrate_bps,
 | 
| +        *audio_codec_spec_);
 | 
| +  }
 | 
| +
 | 
| +  void CreateAudioSendStream() {
 | 
| +    RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
 | 
| +    RTC_DCHECK(!stream_);
 | 
|      stream_ = call_->CreateAudioSendStream(config_);
 | 
|      RTC_CHECK(stream_);
 | 
| +  }
 | 
| +
 | 
| +  void ReconfigureAudioSendStream() {
 | 
| +    RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
 | 
| +    RTC_DCHECK(stream_);
 | 
| +    stream_->Reconfigure(config_);
 | 
|      UpdateSendState();
 | 
|    }
 | 
|  
 | 
| @@ -1488,7 +1232,7 @@ class WebRtcVoiceMediaChannel::WebRtcAudioSendStream
 | 
|    bool muted_ = false;
 | 
|    int max_send_bitrate_bps_;
 | 
|    webrtc::RtpParameters rtp_parameters_;
 | 
| -  webrtc::AudioSendStream::Config::SendCodecSpec send_codec_spec_;
 | 
| +  rtc::Optional<webrtc::AudioCodecSpec> audio_codec_spec_;
 | 
|  
 | 
|    RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(WebRtcAudioSendStream);
 | 
|  };
 | 
| @@ -1694,7 +1438,7 @@ bool WebRtcVoiceMediaChannel::SetSendParameters(
 | 
|    if (send_rtp_extensions_ != filtered_extensions) {
 | 
|      send_rtp_extensions_.swap(filtered_extensions);
 | 
|      for (auto& it : send_streams_) {
 | 
| -      it.second->RecreateAudioSendStream(send_rtp_extensions_);
 | 
| +      it.second->SetRtpExtensions(send_rtp_extensions_);
 | 
|      }
 | 
|    }
 | 
|  
 | 
| @@ -1839,10 +1583,10 @@ bool WebRtcVoiceMediaChannel::SetOptions(const AudioOptions& options) {
 | 
|      return false;
 | 
|    }
 | 
|  
 | 
| -  rtc::Optional<std::string> audio_network_adatptor_config =
 | 
| +  rtc::Optional<std::string> audio_network_adaptor_config =
 | 
|        GetAudioNetworkAdaptorConfig(options_);
 | 
|    for (auto& it : send_streams_) {
 | 
| -    it.second->RecreateAudioSendStream(audio_network_adatptor_config);
 | 
| +    it.second->SetAudioNetworkAdaptorConfig(audio_network_adaptor_config);
 | 
|    }
 | 
|  
 | 
|    LOG(LS_INFO) << "Set voice channel options. Current options: "
 | 
| @@ -1951,85 +1695,64 @@ bool WebRtcVoiceMediaChannel::SetSendCodecs(
 | 
|      }
 | 
|    }
 | 
|  
 | 
| -  // Scan through the list to figure out the codec to use for sending, along
 | 
| -  // with the proper configuration for VAD, CNG, NACK and Opus-specific
 | 
| -  // parameters.
 | 
| -  // TODO(solenberg): Refactor this logic once we create AudioEncoders here.
 | 
| -  webrtc::AudioSendStream::Config::SendCodecSpec send_codec_spec;
 | 
| -  {
 | 
| -    send_codec_spec.nack_enabled = send_codec_spec_.nack_enabled;
 | 
| -
 | 
| -    // Find send codec (the first non-telephone-event/CN codec).
 | 
| -    const AudioCodec* codec = WebRtcVoiceCodecs::GetPreferredCodec(
 | 
| -        codecs, &send_codec_spec.codec_inst);
 | 
| -    if (!codec) {
 | 
| -      LOG(LS_WARNING) << "Received empty list of codecs.";
 | 
| -      return false;
 | 
| -    }
 | 
| +  // Scan through the list to figure out the codec to use for sending.
 | 
| +  rtc::Optional<webrtc::AudioSendStream::Config::SendCodecSpec> send_codec_spec;
 | 
| +  rtc::Optional<webrtc::AudioCodecInfo> voice_codec_info;
 | 
| +  for (const AudioCodec& voice_codec : codecs) {
 | 
| +    if (!(IsCodec(voice_codec, kCnCodecName) ||
 | 
| +          IsCodec(voice_codec, kDtmfCodecName) ||
 | 
| +          IsCodec(voice_codec, kRedCodecName))) {
 | 
| +      webrtc::SdpAudioFormat format(voice_codec.name, voice_codec.clockrate,
 | 
| +                                    voice_codec.channels, voice_codec.params);
 | 
|  
 | 
| -    send_codec_spec.transport_cc_enabled = HasTransportCc(*codec);
 | 
| -    send_codec_spec.nack_enabled = HasNack(*codec);
 | 
| -    bitrate_config_ = GetBitrateConfigForCodec(*codec);
 | 
| -
 | 
| -    // For Opus as the send codec, we are to determine inband FEC, maximum
 | 
| -    // playback rate, and opus internal dtx.
 | 
| -    if (IsCodec(*codec, kOpusCodecName)) {
 | 
| -      GetOpusConfig(*codec, &send_codec_spec.codec_inst,
 | 
| -                    &send_codec_spec.enable_codec_fec,
 | 
| -                    &send_codec_spec.opus_max_playback_rate,
 | 
| -                    &send_codec_spec.enable_opus_dtx,
 | 
| -                    &send_codec_spec.min_ptime_ms,
 | 
| -                    &send_codec_spec.max_ptime_ms);
 | 
| -    }
 | 
| +      voice_codec_info = engine()->encoder_factory_->QueryAudioEncoder(format);
 | 
| +      if (!voice_codec_info) {
 | 
| +        LOG(LS_WARNING) << "Unknown codec " << ToString(voice_codec);
 | 
| +        continue;
 | 
| +      }
 | 
|  
 | 
| -    // Set packet size if the AudioCodec param kCodecParamPTime is set.
 | 
| -    int ptime_ms = 0;
 | 
| -    if (codec->GetParam(kCodecParamPTime, &ptime_ms)) {
 | 
| -      if (!WebRtcVoiceCodecs::SetPTimeAsPacketSize(
 | 
| -          &send_codec_spec.codec_inst, ptime_ms)) {
 | 
| -        LOG(LS_WARNING) << "Failed to set packet size for codec "
 | 
| -                        << send_codec_spec.codec_inst.plname;
 | 
| -        return false;
 | 
| +      send_codec_spec =
 | 
| +          rtc::Optional<webrtc::AudioSendStream::Config::SendCodecSpec>(
 | 
| +              {voice_codec.id, format});
 | 
| +      if (voice_codec.bitrate > 0) {
 | 
| +        send_codec_spec->target_bitrate_bps =
 | 
| +            rtc::Optional<int>(voice_codec.bitrate);
 | 
|        }
 | 
| +      send_codec_spec->transport_cc_enabled = HasTransportCc(voice_codec);
 | 
| +      send_codec_spec->nack_enabled = HasNack(voice_codec);
 | 
| +      bitrate_config_ = GetBitrateConfigForCodec(voice_codec);
 | 
| +      break;
 | 
|      }
 | 
| +  }
 | 
| +
 | 
| +  if (!send_codec_spec)
 | 
| +    return false;
 | 
|  
 | 
| +  RTC_DCHECK(voice_codec_info);
 | 
| +  if (voice_codec_info->allow_comfort_noise) {
 | 
|      // Loop through the codecs list again to find the CN codec.
 | 
|      // TODO(solenberg): Break out into a separate function?
 | 
|      for (const AudioCodec& cn_codec : codecs) {
 | 
| -      // Ignore codecs we don't know about. The negotiation step should prevent
 | 
| -      // this, but double-check to be sure.
 | 
| -      webrtc::CodecInst voe_codec = {0};
 | 
| -      if (!WebRtcVoiceEngine::ToCodecInst(cn_codec, &voe_codec)) {
 | 
| -        LOG(LS_WARNING) << "Unknown codec " << ToString(cn_codec);
 | 
| -        continue;
 | 
| -      }
 | 
| -
 | 
|        if (IsCodec(cn_codec, kCnCodecName) &&
 | 
| -          cn_codec.clockrate == codec->clockrate) {
 | 
| -        // Turn voice activity detection/comfort noise on if supported.
 | 
| -        // Set the wideband CN payload type appropriately.
 | 
| -        // (narrowband always uses the static payload type 13).
 | 
| -        int cng_plfreq = -1;
 | 
| +          cn_codec.clockrate == send_codec_spec->format.clockrate_hz) {
 | 
|          switch (cn_codec.clockrate) {
 | 
|            case 8000:
 | 
|            case 16000:
 | 
|            case 32000:
 | 
| -            cng_plfreq = cn_codec.clockrate;
 | 
| +            send_codec_spec->cng_payload_type = rtc::Optional<int>(cn_codec.id);
 | 
|              break;
 | 
|            default:
 | 
|              LOG(LS_WARNING) << "CN frequency " << cn_codec.clockrate
 | 
|                              << " not supported.";
 | 
| -            continue;
 | 
| +            break;
 | 
|          }
 | 
| -        send_codec_spec.cng_payload_type = cn_codec.id;
 | 
| -        send_codec_spec.cng_plfreq = cng_plfreq;
 | 
|          break;
 | 
|        }
 | 
|      }
 | 
|  
 | 
|      // Find the telephone-event PT exactly matching the preferred send codec.
 | 
|      for (const AudioCodec& dtmf_codec : dtmf_codecs) {
 | 
| -      if (dtmf_codec.clockrate == codec->clockrate) {
 | 
| +      if (dtmf_codec.clockrate == send_codec_spec->format.clockrate_hz) {
 | 
|          dtmf_payload_type_ = rtc::Optional<int>(dtmf_codec.id);
 | 
|          dtmf_payload_freq_ = dtmf_codec.clockrate;
 | 
|          break;
 | 
| @@ -2041,7 +1764,7 @@ bool WebRtcVoiceMediaChannel::SetSendCodecs(
 | 
|      send_codec_spec_ = std::move(send_codec_spec);
 | 
|      // Apply new settings to all streams.
 | 
|      for (const auto& kv : send_streams_) {
 | 
| -      kv.second->RecreateAudioSendStream(send_codec_spec_);
 | 
| +      kv.second->SetSendCodecSpec(*send_codec_spec_);
 | 
|      }
 | 
|    } else {
 | 
|      // If the codec isn't changing, set the start bitrate to -1 which means
 | 
| @@ -2051,12 +1774,12 @@ bool WebRtcVoiceMediaChannel::SetSendCodecs(
 | 
|  
 | 
|    // Check if the transport cc feedback or NACK status has changed on the
 | 
|    // preferred send codec, and in that case reconfigure all receive streams.
 | 
| -  if (recv_transport_cc_enabled_ != send_codec_spec_.transport_cc_enabled ||
 | 
| -      recv_nack_enabled_ != send_codec_spec_.nack_enabled) {
 | 
| +  if (recv_transport_cc_enabled_ != send_codec_spec_->transport_cc_enabled ||
 | 
| +      recv_nack_enabled_ != send_codec_spec_->nack_enabled) {
 | 
|      LOG(LS_INFO) << "Recreate all the receive streams because the send "
 | 
|                      "codec has changed.";
 | 
| -    recv_transport_cc_enabled_ = send_codec_spec_.transport_cc_enabled;
 | 
| -    recv_nack_enabled_ = send_codec_spec_.nack_enabled;
 | 
| +    recv_transport_cc_enabled_ = send_codec_spec_->transport_cc_enabled;
 | 
| +    recv_nack_enabled_ = send_codec_spec_->nack_enabled;
 | 
|      for (auto& kv : recv_streams_) {
 | 
|        kv.second->RecreateAudioReceiveStream(recv_transport_cc_enabled_,
 | 
|                                              recv_nack_enabled_);
 | 
| @@ -2179,7 +1902,7 @@ bool WebRtcVoiceMediaChannel::AddSendStream(const StreamParams& sp) {
 | 
|    WebRtcAudioSendStream* stream = new WebRtcAudioSendStream(
 | 
|        channel, audio_transport, ssrc, sp.cname, send_codec_spec_,
 | 
|        send_rtp_extensions_, max_send_bitrate_bps_, audio_network_adaptor_config,
 | 
| -      call_, this);
 | 
| +      call_, this, engine()->encoder_factory_);
 | 
|    send_streams_.insert(std::make_pair(ssrc, stream));
 | 
|  
 | 
|    // At this point the stream's local SSRC has been updated. If it is the first
 | 
| 
 |