New interface: AudioEncoderMutable

With implementations for all codecs. It has no users yet. This new
interface is the same as AudioEncoder (in fact it is a subclass) but
it allows changing some parameters after construction.

COAUTHOR=henrik.lundin@webrtc.org
BUG=4228
R=jmarusic@webrtc.org, minyue@webrtc.org

Review URL: https://webrtc-codereview.appspot.com/51679004

Cr-Commit-Position: refs/heads/master@{#9149}
diff --git a/webrtc/modules/audio_coding/codecs/audio_encoder.h b/webrtc/modules/audio_coding/codecs/audio_encoder.h
index e8a2c6e..b5cf827 100644
--- a/webrtc/modules/audio_coding/codecs/audio_encoder.h
+++ b/webrtc/modules/audio_coding/codecs/audio_encoder.h
@@ -105,12 +105,45 @@
   // coding efforts, such as FEC.
   virtual void SetProjectedPacketLossRate(double fraction) {}
 
- protected:
+  // This is the encode function that the inherited classes must implement. It
+  // is called from Encode in the base class.
   virtual EncodedInfo EncodeInternal(uint32_t rtp_timestamp,
                                      const int16_t* audio,
                                      size_t max_encoded_bytes,
                                      uint8_t* encoded) = 0;
 };
 
+class AudioEncoderMutable : public AudioEncoder {
+ public:
+  enum Application { kApplicationSpeech, kApplicationAudio };
+
+  // Discards unprocessed audio data.
+  virtual void Reset() = 0;
+
+  // Enables codec-internal FEC, if the implementation supports it.
+  virtual bool SetFec(bool enable) = 0;
+
+  // Enables or disables codec-internal VAD/DTX, if the implementation supports
+  // it. Otherwise, false is returned. If |force| is true, other configurations
+  // may be changed to allow the operation.
+  virtual bool SetDtx(bool enable, bool force) = 0;
+
+  // Sets the application mode. The implementation is free to disregard this
+  // setting. If |force| is true, other configurations may be changed to allow
+  // the operation.
+  virtual bool SetApplication(Application application, bool force) = 0;
+
+  // Sets an upper limit on the payload size produced by the encoder. The
+  // implementation is free to disregard this setting.
+  virtual void SetMaxPayloadSize(int max_payload_size_bytes) = 0;
+
+  // Sets the maximum rate which the codec may not exceed for any packet.
+  virtual void SetMaxRate(int max_rate_bps) = 0;
+
+  // Informs the encoder about the maximum sample rate which the decoder will
+  // use when decoding the bitstream. The implementation is free to disregard
+  // this hint.
+  virtual bool SetMaxPlaybackRate(int frequency_hz) = 0;
+};
 }  // namespace webrtc
 #endif  // WEBRTC_MODULES_AUDIO_CODING_CODECS_AUDIO_ENCODER_H_
diff --git a/webrtc/modules/audio_coding/codecs/audio_encoder_mutable_impl.h b/webrtc/modules/audio_coding/codecs/audio_encoder_mutable_impl.h
new file mode 100644
index 0000000..3de4046
--- /dev/null
+++ b/webrtc/modules/audio_coding/codecs/audio_encoder_mutable_impl.h
@@ -0,0 +1,96 @@
+/*
+ *  Copyright (c) 2015 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+#ifndef WEBRTC_MODULES_AUDIO_CODING_CODECS_AUDIO_ENCODER_MUTABLE_IMPL_H_
+#define WEBRTC_MODULES_AUDIO_CODING_CODECS_AUDIO_ENCODER_MUTABLE_IMPL_H_
+
+#include "webrtc/base/scoped_ptr.h"
+#include "webrtc/modules/audio_coding/codecs/audio_encoder.h"
+
+namespace webrtc {
+
+// This is a convenient base class for implementations of AudioEncoderMutable.
+// T is the type of the encoder state; it has to look like an AudioEncoder
+// subclass whose constructor takes a single T::Config parameter. If P is
+// given, this class will inherit from it instead of directly from
+// AudioEncoderMutable.
+template <typename T, typename P = AudioEncoderMutable>
+class AudioEncoderMutableImpl : public P {
+ public:
+  void Reset() override { Reconstruct(config_); }
+
+  bool SetFec(bool enable) override { return false; }
+
+  bool SetDtx(bool enable, bool force) override { return false; }
+
+  bool SetApplication(AudioEncoderMutable::Application application,
+                      bool force) override {
+    return false;
+  }
+
+  void SetMaxPayloadSize(int max_payload_size_bytes) override {}
+
+  void SetMaxRate(int max_rate_bps) override {}
+
+  bool SetMaxPlaybackRate(int frequency_hz) override { return false; }
+
+  AudioEncoderMutable::EncodedInfo EncodeInternal(uint32_t rtp_timestamp,
+                                                  const int16_t* audio,
+                                                  size_t max_encoded_bytes,
+                                                  uint8_t* encoded) override {
+    return encoder_->EncodeInternal(rtp_timestamp, audio, max_encoded_bytes,
+                                    encoded);
+  }
+  int SampleRateHz() const override { return encoder_->SampleRateHz(); }
+  int NumChannels() const override { return encoder_->NumChannels(); }
+  size_t MaxEncodedBytes() const override {
+    return encoder_->MaxEncodedBytes();
+  }
+  int RtpTimestampRateHz() const override {
+    return encoder_->RtpTimestampRateHz();
+  }
+  int Num10MsFramesInNextPacket() const override {
+    return encoder_->Num10MsFramesInNextPacket();
+  }
+  int Max10MsFramesInAPacket() const override {
+    return encoder_->Max10MsFramesInAPacket();
+  }
+  void SetTargetBitrate(int bits_per_second) override {
+    encoder_->SetTargetBitrate(bits_per_second);
+  }
+  void SetProjectedPacketLossRate(double fraction) override {
+    encoder_->SetProjectedPacketLossRate(fraction);
+  }
+
+ protected:
+  explicit AudioEncoderMutableImpl(const typename T::Config& config) {
+    Reconstruct(config);
+  }
+
+  bool Reconstruct(const typename T::Config& config) {
+    if (!config.IsOk())
+      return false;
+    config_ = config;
+    encoder_.reset(new T(config_));
+    return true;
+  }
+
+  const typename T::Config& config() const { return config_; }
+  T* encoder() { return encoder_.get(); }
+  const T* encoder() const { return encoder_.get(); }
+
+ private:
+  rtc::scoped_ptr<T> encoder_;
+  typename T::Config config_;
+};
+
+}  // namespace webrtc
+
+#endif  // WEBRTC_MODULES_AUDIO_CODING_CODECS_AUDIO_ENCODER_MUTABLE_IMPL_H_
diff --git a/webrtc/modules/audio_coding/codecs/cng/include/audio_encoder_cng.h b/webrtc/modules/audio_coding/codecs/cng/include/audio_encoder_cng.h
index daecd51..831758b 100644
--- a/webrtc/modules/audio_coding/codecs/cng/include/audio_encoder_cng.h
+++ b/webrtc/modules/audio_coding/codecs/cng/include/audio_encoder_cng.h
@@ -54,8 +54,6 @@
   int Max10MsFramesInAPacket() const override;
   void SetTargetBitrate(int bits_per_second) override;
   void SetProjectedPacketLossRate(double fraction) override;
-
- protected:
   EncodedInfo EncodeInternal(uint32_t rtp_timestamp,
                              const int16_t* audio,
                              size_t max_encoded_bytes,
diff --git a/webrtc/modules/audio_coding/codecs/g711/audio_encoder_pcm.cc b/webrtc/modules/audio_coding/codecs/g711/audio_encoder_pcm.cc
index 5c45fa5..0a3a639 100644
--- a/webrtc/modules/audio_coding/codecs/g711/audio_encoder_pcm.cc
+++ b/webrtc/modules/audio_coding/codecs/g711/audio_encoder_pcm.cc
@@ -13,6 +13,7 @@
 #include <limits>
 
 #include "webrtc/base/checks.h"
+#include "webrtc/common_types.h"
 #include "webrtc/modules/audio_coding/codecs/g711/include/g711_interface.h"
 
 namespace webrtc {
@@ -28,6 +29,10 @@
 }
 }  // namespace
 
+bool AudioEncoderPcm::Config::IsOk() const {
+  return (frame_size_ms % 10 == 0) && (num_channels >= 1);
+}
+
 AudioEncoderPcm::AudioEncoderPcm(const Config& config, int sample_rate_hz)
     : sample_rate_hz_(sample_rate_hz),
       num_channels_(config.num_channels),
@@ -105,4 +110,25 @@
   return WebRtcG711_EncodeU(audio, static_cast<int16_t>(input_len), encoded);
 }
 
+namespace {
+template <typename T>
+typename T::Config CreateConfig(const CodecInst& codec_inst) {
+  typename T::Config config;
+  config.frame_size_ms = codec_inst.pacsize / 8;
+  config.num_channels = codec_inst.channels;
+  config.payload_type = codec_inst.pltype;
+  return config;
+}
+}  // namespace
+
+AudioEncoderMutablePcmU::AudioEncoderMutablePcmU(const CodecInst& codec_inst)
+    : AudioEncoderMutableImpl<AudioEncoderPcmU>(
+          CreateConfig<AudioEncoderPcmU>(codec_inst)) {
+}
+
+AudioEncoderMutablePcmA::AudioEncoderMutablePcmA(const CodecInst& codec_inst)
+    : AudioEncoderMutableImpl<AudioEncoderPcmA>(
+          CreateConfig<AudioEncoderPcmA>(codec_inst)) {
+}
+
 }  // namespace webrtc
diff --git a/webrtc/modules/audio_coding/codecs/g711/include/audio_encoder_pcm.h b/webrtc/modules/audio_coding/codecs/g711/include/audio_encoder_pcm.h
index 6e588ec..870b4dd 100644
--- a/webrtc/modules/audio_coding/codecs/g711/include/audio_encoder_pcm.h
+++ b/webrtc/modules/audio_coding/codecs/g711/include/audio_encoder_pcm.h
@@ -13,7 +13,9 @@
 
 #include <vector>
 
+#include "webrtc/base/scoped_ptr.h"
 #include "webrtc/modules/audio_coding/codecs/audio_encoder.h"
+#include "webrtc/modules/audio_coding/codecs/audio_encoder_mutable_impl.h"
 
 namespace webrtc {
 
@@ -21,6 +23,8 @@
  public:
   struct Config {
    public:
+    bool IsOk() const;
+
     int frame_size_ms;
     int num_channels;
     int payload_type;
@@ -37,15 +41,14 @@
   size_t MaxEncodedBytes() const override;
   int Num10MsFramesInNextPacket() const override;
   int Max10MsFramesInAPacket() const override;
-
- protected:
-  AudioEncoderPcm(const Config& config, int sample_rate_hz);
-
   EncodedInfo EncodeInternal(uint32_t rtp_timestamp,
                              const int16_t* audio,
                              size_t max_encoded_bytes,
                              uint8_t* encoded) override;
 
+ protected:
+  AudioEncoderPcm(const Config& config, int sample_rate_hz);
+
   virtual int16_t EncodeCall(const int16_t* audio,
                              size_t input_len,
                              uint8_t* encoded) = 0;
@@ -96,5 +99,19 @@
   static const int kSampleRateHz = 8000;
 };
 
+struct CodecInst;
+
+class AudioEncoderMutablePcmU
+    : public AudioEncoderMutableImpl<AudioEncoderPcmU> {
+ public:
+  explicit AudioEncoderMutablePcmU(const CodecInst& codec_inst);
+};
+
+class AudioEncoderMutablePcmA
+    : public AudioEncoderMutableImpl<AudioEncoderPcmA> {
+ public:
+  explicit AudioEncoderMutablePcmA(const CodecInst& codec_inst);
+};
+
 }  // namespace webrtc
 #endif  // WEBRTC_MODULES_AUDIO_CODING_CODECS_G711_INCLUDE_AUDIO_ENCODER_PCM_H_
diff --git a/webrtc/modules/audio_coding/codecs/g722/audio_encoder_g722.cc b/webrtc/modules/audio_coding/codecs/g722/audio_encoder_g722.cc
index a9fa25f..effb405 100644
--- a/webrtc/modules/audio_coding/codecs/g722/audio_encoder_g722.cc
+++ b/webrtc/modules/audio_coding/codecs/g722/audio_encoder_g722.cc
@@ -12,6 +12,7 @@
 
 #include <limits>
 #include "webrtc/base/checks.h"
+#include "webrtc/common_types.h"
 #include "webrtc/modules/audio_coding/codecs/g722/include/g722_interface.h"
 
 namespace webrtc {
@@ -22,6 +23,10 @@
 
 }  // namespace
 
+bool AudioEncoderG722::Config::IsOk() const {
+  return (frame_size_ms % 10 == 0) && (num_channels >= 1);
+}
+
 AudioEncoderG722::EncoderState::EncoderState() {
   CHECK_EQ(0, WebRtcG722_CreateEncoder(&encoder));
   CHECK_EQ(0, WebRtcG722_EncoderInit(encoder));
@@ -39,8 +44,7 @@
       first_timestamp_in_buffer_(0),
       encoders_(new EncoderState[num_channels_]),
       interleave_buffer_(2 * num_channels_) {
-  CHECK_EQ(config.frame_size_ms % 10, 0)
-      << "Frame size must be an integer multiple of 10 ms.";
+  CHECK(config.IsOk());
   const int samples_per_channel =
       kSampleRateHz / 100 * num_10ms_frames_per_packet_;
   for (int i = 0; i < num_channels_; ++i) {
@@ -134,4 +138,18 @@
   return kSampleRateHz / 100 * num_10ms_frames_per_packet_;
 }
 
+namespace {
+AudioEncoderG722::Config CreateConfig(const CodecInst& codec_inst) {
+  AudioEncoderG722::Config config;
+  config.num_channels = codec_inst.channels;
+  config.frame_size_ms = codec_inst.pacsize / 16;
+  config.payload_type = codec_inst.pltype;
+  return config;
+}
+}  // namespace
+
+AudioEncoderMutableG722::AudioEncoderMutableG722(const CodecInst& codec_inst)
+    : AudioEncoderMutableImpl<AudioEncoderG722>(CreateConfig(codec_inst)) {
+}
+
 }  // namespace webrtc
diff --git a/webrtc/modules/audio_coding/codecs/g722/include/audio_encoder_g722.h b/webrtc/modules/audio_coding/codecs/g722/include/audio_encoder_g722.h
index ba6e5dd..f5e0a98 100644
--- a/webrtc/modules/audio_coding/codecs/g722/include/audio_encoder_g722.h
+++ b/webrtc/modules/audio_coding/codecs/g722/include/audio_encoder_g722.h
@@ -14,6 +14,7 @@
 #include "webrtc/base/buffer.h"
 #include "webrtc/base/scoped_ptr.h"
 #include "webrtc/modules/audio_coding/codecs/audio_encoder.h"
+#include "webrtc/modules/audio_coding/codecs/audio_encoder_mutable_impl.h"
 #include "webrtc/modules/audio_coding/codecs/g722/include/g722_interface.h"
 
 namespace webrtc {
@@ -22,6 +23,7 @@
  public:
   struct Config {
     Config() : payload_type(9), frame_size_ms(20), num_channels(1) {}
+    bool IsOk() const;
 
     int payload_type;
     int frame_size_ms;
@@ -37,8 +39,6 @@
   int RtpTimestampRateHz() const override;
   int Num10MsFramesInNextPacket() const override;
   int Max10MsFramesInAPacket() const override;
-
- protected:
   EncodedInfo EncodeInternal(uint32_t rtp_timestamp,
                              const int16_t* audio,
                              size_t max_encoded_bytes,
@@ -65,5 +65,13 @@
   rtc::Buffer interleave_buffer_;
 };
 
+struct CodecInst;
+
+class AudioEncoderMutableG722
+    : public AudioEncoderMutableImpl<AudioEncoderG722> {
+ public:
+  explicit AudioEncoderMutableG722(const CodecInst& codec_inst);
+};
+
 }  // namespace webrtc
 #endif  // WEBRTC_MODULES_AUDIO_CODING_CODECS_G722_INCLUDE_AUDIO_ENCODER_G722_H_
diff --git a/webrtc/modules/audio_coding/codecs/ilbc/audio_encoder_ilbc.cc b/webrtc/modules/audio_coding/codecs/ilbc/audio_encoder_ilbc.cc
index fad531f..4fea44b 100644
--- a/webrtc/modules/audio_coding/codecs/ilbc/audio_encoder_ilbc.cc
+++ b/webrtc/modules/audio_coding/codecs/ilbc/audio_encoder_ilbc.cc
@@ -13,6 +13,7 @@
 #include <cstring>
 #include <limits>
 #include "webrtc/base/checks.h"
+#include "webrtc/common_types.h"
 #include "webrtc/modules/audio_coding/codecs/ilbc/interface/ilbc.h"
 
 namespace webrtc {
@@ -23,15 +24,20 @@
 
 }  // namespace
 
+bool AudioEncoderIlbc::Config::IsOk() const {
+  if (!(frame_size_ms == 20 || frame_size_ms == 30 || frame_size_ms == 40 ||
+        frame_size_ms == 60))
+    return false;
+  if (kSampleRateHz / 100 * (frame_size_ms / 10) > kMaxSamplesPerPacket)
+    return false;
+  return true;
+}
+
 AudioEncoderIlbc::AudioEncoderIlbc(const Config& config)
     : payload_type_(config.payload_type),
       num_10ms_frames_per_packet_(config.frame_size_ms / 10),
       num_10ms_frames_buffered_(0) {
-  CHECK(config.frame_size_ms == 20 || config.frame_size_ms == 30 ||
-        config.frame_size_ms == 40 || config.frame_size_ms == 60)
-      << "Frame size must be 20, 30, 40, or 60 ms.";
-  DCHECK_LE(kSampleRateHz / 100 * num_10ms_frames_per_packet_,
-            kMaxSamplesPerPacket);
+  CHECK(config.IsOk());
   CHECK_EQ(0, WebRtcIlbcfix_EncoderCreate(&encoder_));
   const int encoder_frame_size_ms = config.frame_size_ms > 30
                                         ? config.frame_size_ms / 2
@@ -112,4 +118,17 @@
   }
 }
 
+namespace {
+AudioEncoderIlbc::Config CreateConfig(const CodecInst& codec_inst) {
+  AudioEncoderIlbc::Config config;
+  config.frame_size_ms = codec_inst.pacsize / 8;
+  config.payload_type = codec_inst.pltype;
+  return config;
+}
+}  // namespace
+
+AudioEncoderMutableIlbc::AudioEncoderMutableIlbc(const CodecInst& codec_inst)
+    : AudioEncoderMutableImpl<AudioEncoderIlbc>(CreateConfig(codec_inst)) {
+}
+
 }  // namespace webrtc
diff --git a/webrtc/modules/audio_coding/codecs/ilbc/interface/audio_encoder_ilbc.h b/webrtc/modules/audio_coding/codecs/ilbc/interface/audio_encoder_ilbc.h
index 91d17b4..c172db1 100644
--- a/webrtc/modules/audio_coding/codecs/ilbc/interface/audio_encoder_ilbc.h
+++ b/webrtc/modules/audio_coding/codecs/ilbc/interface/audio_encoder_ilbc.h
@@ -13,6 +13,7 @@
 
 #include "webrtc/base/scoped_ptr.h"
 #include "webrtc/modules/audio_coding/codecs/audio_encoder.h"
+#include "webrtc/modules/audio_coding/codecs/audio_encoder_mutable_impl.h"
 #include "webrtc/modules/audio_coding/codecs/ilbc/interface/ilbc.h"
 
 namespace webrtc {
@@ -21,6 +22,7 @@
  public:
   struct Config {
     Config() : payload_type(102), frame_size_ms(30) {}
+    bool IsOk() const;
 
     int payload_type;
     int frame_size_ms;  // Valid values are 20, 30, 40, and 60 ms.
@@ -36,8 +38,6 @@
   size_t MaxEncodedBytes() const override;
   int Num10MsFramesInNextPacket() const override;
   int Max10MsFramesInAPacket() const override;
-
- protected:
   EncodedInfo EncodeInternal(uint32_t rtp_timestamp,
                              const int16_t* audio,
                              size_t max_encoded_bytes,
@@ -55,5 +55,13 @@
   IlbcEncoderInstance* encoder_;
 };
 
+struct CodecInst;
+
+class AudioEncoderMutableIlbc
+    : public AudioEncoderMutableImpl<AudioEncoderIlbc> {
+ public:
+  explicit AudioEncoderMutableIlbc(const CodecInst& codec_inst);
+};
+
 }  // namespace webrtc
 #endif  // WEBRTC_MODULES_AUDIO_CODING_CODECS_ILBC_INTERFACE_AUDIO_ENCODER_ILBC_H_
diff --git a/webrtc/modules/audio_coding/codecs/isac/audio_encoder_isac_t.h b/webrtc/modules/audio_coding/codecs/isac/audio_encoder_isac_t.h
index ad53166..b67a9b0 100644
--- a/webrtc/modules/audio_coding/codecs/isac/audio_encoder_isac_t.h
+++ b/webrtc/modules/audio_coding/codecs/isac/audio_encoder_isac_t.h
@@ -72,7 +72,6 @@
   int ErrorCode() override;
   size_t Channels() const override { return 1; }
 
- protected:
   // AudioEncoder protected method.
   EncodedInfo EncodeInternal(uint32_t rtp_timestamp,
                              const int16_t* audio,
@@ -117,5 +116,13 @@
   DISALLOW_COPY_AND_ASSIGN(AudioEncoderDecoderIsacT);
 };
 
+struct CodecInst;
+
+class AudioEncoderDecoderMutableIsac : public AudioEncoderMutable,
+                                       public AudioDecoder {
+ public:
+  virtual void UpdateSettings(const CodecInst& codec_inst) = 0;
+};
+
 }  // namespace webrtc
 #endif  // WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_AUDIO_ENCODER_ISAC_T_H_
diff --git a/webrtc/modules/audio_coding/codecs/isac/fix/interface/audio_encoder_isacfix.h b/webrtc/modules/audio_coding/codecs/isac/fix/interface/audio_encoder_isacfix.h
index d12c167..bf9f875 100644
--- a/webrtc/modules/audio_coding/codecs/isac/fix/interface/audio_encoder_isacfix.h
+++ b/webrtc/modules/audio_coding/codecs/isac/fix/interface/audio_encoder_isacfix.h
@@ -12,6 +12,8 @@
 #define WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_FIX_INTERFACE_AUDIO_ENCODER_ISACFIX_H_
 
 #include "webrtc/base/checks.h"
+#include "webrtc/base/scoped_ptr.h"
+#include "webrtc/modules/audio_coding/codecs/audio_encoder_mutable_impl.h"
 #include "webrtc/modules/audio_coding/codecs/isac/audio_encoder_isac_t.h"
 #include "webrtc/modules/audio_coding/codecs/isac/fix/interface/isacfix.h"
 
@@ -104,5 +106,45 @@
 
 typedef AudioEncoderDecoderIsacT<IsacFix> AudioEncoderDecoderIsacFix;
 
+struct CodecInst;
+
+class AudioEncoderDecoderMutableIsacFix
+    : public AudioEncoderMutableImpl<AudioEncoderDecoderIsacFix,
+                                     AudioEncoderDecoderMutableIsac> {
+ public:
+  explicit AudioEncoderDecoderMutableIsacFix(const CodecInst& codec_inst);
+  void UpdateSettings(const CodecInst& codec_inst) override;
+  void SetMaxPayloadSize(int max_payload_size_bytes) override;
+  void SetMaxRate(int max_rate_bps) override;
+
+  // From AudioDecoder.
+  int Decode(const uint8_t* encoded,
+             size_t encoded_len,
+             int sample_rate_hz,
+             size_t max_decoded_bytes,
+             int16_t* decoded,
+             SpeechType* speech_type) override;
+  int DecodeRedundant(const uint8_t* encoded,
+                      size_t encoded_len,
+                      int sample_rate_hz,
+                      size_t max_decoded_bytes,
+                      int16_t* decoded,
+                      SpeechType* speech_type) override;
+  bool HasDecodePlc() const override;
+  int DecodePlc(int num_frames, int16_t* decoded) override;
+  int Init() override;
+  int IncomingPacket(const uint8_t* payload,
+                     size_t payload_len,
+                     uint16_t rtp_sequence_number,
+                     uint32_t rtp_timestamp,
+                     uint32_t arrival_timestamp) override;
+  int ErrorCode() override;
+  int PacketDuration(const uint8_t* encoded, size_t encoded_len) const override;
+  int PacketDurationRedundant(const uint8_t* encoded,
+                              size_t encoded_len) const override;
+  bool PacketHasFec(const uint8_t* encoded, size_t encoded_len) const override;
+  size_t Channels() const override;
+};
+
 }  // namespace webrtc
 #endif  // WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_FIX_INTERFACE_AUDIO_ENCODER_ISACFIX_H_
diff --git a/webrtc/modules/audio_coding/codecs/isac/fix/source/audio_encoder_isacfix.cc b/webrtc/modules/audio_coding/codecs/isac/fix/source/audio_encoder_isacfix.cc
index d0aea26..4003b26 100644
--- a/webrtc/modules/audio_coding/codecs/isac/fix/source/audio_encoder_isacfix.cc
+++ b/webrtc/modules/audio_coding/codecs/isac/fix/source/audio_encoder_isacfix.cc
@@ -10,6 +10,7 @@
 
 #include "webrtc/modules/audio_coding/codecs/isac/fix/interface/audio_encoder_isacfix.h"
 
+#include "webrtc/common_types.h"
 #include "webrtc/modules/audio_coding/codecs/isac/audio_encoder_isac_t_impl.h"
 
 namespace webrtc {
@@ -20,4 +21,113 @@
 // AudioEncoderDecoderIsacFix.
 template class AudioEncoderDecoderIsacT<IsacFix>;
 
+namespace {
+AudioEncoderDecoderIsacFix::Config CreateConfig(const CodecInst& codec_inst) {
+  AudioEncoderDecoderIsacFix::Config config;
+  config.payload_type = codec_inst.pltype;
+  config.sample_rate_hz = codec_inst.plfreq;
+  config.frame_size_ms =
+      rtc::CheckedDivExact(1000 * codec_inst.pacsize, config.sample_rate_hz);
+  if (codec_inst.rate != -1)
+    config.bit_rate = codec_inst.rate;
+  config.adaptive_mode = (codec_inst.rate == -1);
+  return config;
+}
+}  // namespace
+
+AudioEncoderDecoderMutableIsacFix::AudioEncoderDecoderMutableIsacFix(
+    const CodecInst& codec_inst)
+    : AudioEncoderMutableImpl<AudioEncoderDecoderIsacFix,
+                              AudioEncoderDecoderMutableIsac>(
+          CreateConfig(codec_inst)) {
+}
+
+void AudioEncoderDecoderMutableIsacFix::UpdateSettings(
+    const CodecInst& codec_inst) {
+  bool success = Reconstruct(CreateConfig(codec_inst));
+  DCHECK(success);
+}
+
+void AudioEncoderDecoderMutableIsacFix::SetMaxPayloadSize(
+    int max_payload_size_bytes) {
+  auto conf = config();
+  conf.max_payload_size_bytes = max_payload_size_bytes;
+  Reconstruct(conf);
+}
+
+void AudioEncoderDecoderMutableIsacFix::SetMaxRate(int max_rate_bps) {
+  auto conf = config();
+  conf.max_bit_rate = max_rate_bps;
+  Reconstruct(conf);
+}
+
+int AudioEncoderDecoderMutableIsacFix::Decode(const uint8_t* encoded,
+                                              size_t encoded_len,
+                                              int sample_rate_hz,
+                                              size_t max_decoded_bytes,
+                                              int16_t* decoded,
+                                              SpeechType* speech_type) {
+  return encoder()->Decode(encoded, encoded_len, sample_rate_hz,
+                           max_decoded_bytes, decoded, speech_type);
+}
+
+int AudioEncoderDecoderMutableIsacFix::DecodeRedundant(
+    const uint8_t* encoded,
+    size_t encoded_len,
+    int sample_rate_hz,
+    size_t max_decoded_bytes,
+    int16_t* decoded,
+    SpeechType* speech_type) {
+  return encoder()->DecodeRedundant(encoded, encoded_len, sample_rate_hz,
+                                    max_decoded_bytes, decoded, speech_type);
+}
+
+bool AudioEncoderDecoderMutableIsacFix::HasDecodePlc() const {
+  return encoder()->HasDecodePlc();
+}
+
+int AudioEncoderDecoderMutableIsacFix::DecodePlc(int num_frames,
+                                                 int16_t* decoded) {
+  return encoder()->DecodePlc(num_frames, decoded);
+}
+
+int AudioEncoderDecoderMutableIsacFix::Init() {
+  return encoder()->Init();
+}
+
+int AudioEncoderDecoderMutableIsacFix::IncomingPacket(
+    const uint8_t* payload,
+    size_t payload_len,
+    uint16_t rtp_sequence_number,
+    uint32_t rtp_timestamp,
+    uint32_t arrival_timestamp) {
+  return encoder()->IncomingPacket(payload, payload_len, rtp_sequence_number,
+                                   rtp_timestamp, arrival_timestamp);
+}
+
+int AudioEncoderDecoderMutableIsacFix::ErrorCode() {
+  return encoder()->ErrorCode();
+}
+
+int AudioEncoderDecoderMutableIsacFix::PacketDuration(
+    const uint8_t* encoded,
+    size_t encoded_len) const {
+  return encoder()->PacketDuration(encoded, encoded_len);
+}
+
+int AudioEncoderDecoderMutableIsacFix::PacketDurationRedundant(
+    const uint8_t* encoded,
+    size_t encoded_len) const {
+  return encoder()->PacketDurationRedundant(encoded, encoded_len);
+}
+
+bool AudioEncoderDecoderMutableIsacFix::PacketHasFec(const uint8_t* encoded,
+                                                     size_t encoded_len) const {
+  return encoder()->PacketHasFec(encoded, encoded_len);
+}
+
+size_t AudioEncoderDecoderMutableIsacFix::Channels() const {
+  return encoder()->Channels();
+}
+
 }  // namespace webrtc
diff --git a/webrtc/modules/audio_coding/codecs/isac/main/interface/audio_encoder_isac.h b/webrtc/modules/audio_coding/codecs/isac/main/interface/audio_encoder_isac.h
index 7d8ac79..5a75807 100644
--- a/webrtc/modules/audio_coding/codecs/isac/main/interface/audio_encoder_isac.h
+++ b/webrtc/modules/audio_coding/codecs/isac/main/interface/audio_encoder_isac.h
@@ -12,6 +12,8 @@
 #define WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_INTERFACE_AUDIO_ENCODER_ISAC_H_
 
 #include "webrtc/base/checks.h"
+#include "webrtc/base/scoped_ptr.h"
+#include "webrtc/modules/audio_coding/codecs/audio_encoder_mutable_impl.h"
 #include "webrtc/modules/audio_coding/codecs/isac/audio_encoder_isac_t.h"
 #include "webrtc/modules/audio_coding/codecs/isac/main/interface/isac.h"
 
@@ -102,5 +104,45 @@
 
 typedef AudioEncoderDecoderIsacT<IsacFloat> AudioEncoderDecoderIsac;
 
+struct CodecInst;
+
+class AudioEncoderDecoderMutableIsacFloat
+    : public AudioEncoderMutableImpl<AudioEncoderDecoderIsac,
+                                     AudioEncoderDecoderMutableIsac> {
+ public:
+  explicit AudioEncoderDecoderMutableIsacFloat(const CodecInst& codec_inst);
+  void UpdateSettings(const CodecInst& codec_inst) override;
+  void SetMaxPayloadSize(int max_payload_size_bytes) override;
+  void SetMaxRate(int max_rate_bps) override;
+
+  // From AudioDecoder.
+  int Decode(const uint8_t* encoded,
+             size_t encoded_len,
+             int sample_rate_hz,
+             size_t max_decoded_bytes,
+             int16_t* decoded,
+             SpeechType* speech_type) override;
+  int DecodeRedundant(const uint8_t* encoded,
+                      size_t encoded_len,
+                      int sample_rate_hz,
+                      size_t max_decoded_bytes,
+                      int16_t* decoded,
+                      SpeechType* speech_type) override;
+  bool HasDecodePlc() const override;
+  int DecodePlc(int num_frames, int16_t* decoded) override;
+  int Init() override;
+  int IncomingPacket(const uint8_t* payload,
+                     size_t payload_len,
+                     uint16_t rtp_sequence_number,
+                     uint32_t rtp_timestamp,
+                     uint32_t arrival_timestamp) override;
+  int ErrorCode() override;
+  int PacketDuration(const uint8_t* encoded, size_t encoded_len) const override;
+  int PacketDurationRedundant(const uint8_t* encoded,
+                              size_t encoded_len) const override;
+  bool PacketHasFec(const uint8_t* encoded, size_t encoded_len) const override;
+  size_t Channels() const override;
+};
+
 }  // namespace webrtc
 #endif  // WEBRTC_MODULES_AUDIO_CODING_CODECS_ISAC_MAIN_INTERFACE_AUDIO_ENCODER_ISAC_H_
diff --git a/webrtc/modules/audio_coding/codecs/isac/main/source/audio_encoder_isac.cc b/webrtc/modules/audio_coding/codecs/isac/main/source/audio_encoder_isac.cc
index ba08603..b2c1241 100644
--- a/webrtc/modules/audio_coding/codecs/isac/main/source/audio_encoder_isac.cc
+++ b/webrtc/modules/audio_coding/codecs/isac/main/source/audio_encoder_isac.cc
@@ -10,6 +10,7 @@
 
 #include "webrtc/modules/audio_coding/codecs/isac/main/interface/audio_encoder_isac.h"
 
+#include "webrtc/common_types.h"
 #include "webrtc/modules/audio_coding/codecs/isac/audio_encoder_isac_t_impl.h"
 
 namespace webrtc {
@@ -18,4 +19,114 @@
 // AudioEncoderDecoderIsac.
 template class AudioEncoderDecoderIsacT<IsacFloat>;
 
+namespace {
+AudioEncoderDecoderIsac::Config CreateConfig(const CodecInst& codec_inst) {
+  AudioEncoderDecoderIsac::Config config;
+  config.payload_type = codec_inst.pltype;
+  config.sample_rate_hz = codec_inst.plfreq;
+  config.frame_size_ms =
+      rtc::CheckedDivExact(1000 * codec_inst.pacsize, config.sample_rate_hz);
+  if (codec_inst.rate != -1)
+    config.bit_rate = codec_inst.rate;
+  config.adaptive_mode = (codec_inst.rate == -1);
+  return config;
+}
+}  // namespace
+
+AudioEncoderDecoderMutableIsacFloat::AudioEncoderDecoderMutableIsacFloat(
+    const CodecInst& codec_inst)
+    : AudioEncoderMutableImpl<AudioEncoderDecoderIsac,
+                              AudioEncoderDecoderMutableIsac>(
+          CreateConfig(codec_inst)) {
+}
+
+void AudioEncoderDecoderMutableIsacFloat::UpdateSettings(
+    const CodecInst& codec_inst) {
+  bool success = Reconstruct(CreateConfig(codec_inst));
+  DCHECK(success);
+}
+
+void AudioEncoderDecoderMutableIsacFloat::SetMaxPayloadSize(
+    int max_payload_size_bytes) {
+  auto conf = config();
+  conf.max_payload_size_bytes = max_payload_size_bytes;
+  Reconstruct(conf);
+}
+
+void AudioEncoderDecoderMutableIsacFloat::SetMaxRate(int max_rate_bps) {
+  auto conf = config();
+  conf.max_bit_rate = max_rate_bps;
+  Reconstruct(conf);
+}
+
+int AudioEncoderDecoderMutableIsacFloat::Decode(const uint8_t* encoded,
+                                                size_t encoded_len,
+                                                int sample_rate_hz,
+                                                size_t max_decoded_bytes,
+                                                int16_t* decoded,
+                                                SpeechType* speech_type) {
+  return encoder()->Decode(encoded, encoded_len, sample_rate_hz,
+                           max_decoded_bytes, decoded, speech_type);
+}
+
+int AudioEncoderDecoderMutableIsacFloat::DecodeRedundant(
+    const uint8_t* encoded,
+    size_t encoded_len,
+    int sample_rate_hz,
+    size_t max_decoded_bytes,
+    int16_t* decoded,
+    SpeechType* speech_type) {
+  return encoder()->DecodeRedundant(encoded, encoded_len, sample_rate_hz,
+                                    max_decoded_bytes, decoded, speech_type);
+}
+
+bool AudioEncoderDecoderMutableIsacFloat::HasDecodePlc() const {
+  return encoder()->HasDecodePlc();
+}
+
+int AudioEncoderDecoderMutableIsacFloat::DecodePlc(int num_frames,
+                                                   int16_t* decoded) {
+  return encoder()->DecodePlc(num_frames, decoded);
+}
+
+int AudioEncoderDecoderMutableIsacFloat::Init() {
+  return encoder()->Init();
+}
+
+int AudioEncoderDecoderMutableIsacFloat::IncomingPacket(
+    const uint8_t* payload,
+    size_t payload_len,
+    uint16_t rtp_sequence_number,
+    uint32_t rtp_timestamp,
+    uint32_t arrival_timestamp) {
+  return encoder()->IncomingPacket(payload, payload_len, rtp_sequence_number,
+                                   rtp_timestamp, arrival_timestamp);
+}
+
+int AudioEncoderDecoderMutableIsacFloat::ErrorCode() {
+  return encoder()->ErrorCode();
+}
+
+int AudioEncoderDecoderMutableIsacFloat::PacketDuration(
+    const uint8_t* encoded,
+    size_t encoded_len) const {
+  return encoder()->PacketDuration(encoded, encoded_len);
+}
+
+int AudioEncoderDecoderMutableIsacFloat::PacketDurationRedundant(
+    const uint8_t* encoded,
+    size_t encoded_len) const {
+  return encoder()->PacketDurationRedundant(encoded, encoded_len);
+}
+
+bool AudioEncoderDecoderMutableIsacFloat::PacketHasFec(
+    const uint8_t* encoded,
+    size_t encoded_len) const {
+  return encoder()->PacketHasFec(encoded, encoded_len);
+}
+
+size_t AudioEncoderDecoderMutableIsacFloat::Channels() const {
+  return encoder()->Channels();
+}
+
 }  // namespace webrtc
diff --git a/webrtc/modules/audio_coding/codecs/opus/audio_encoder_mutable_opus_test.cc b/webrtc/modules/audio_coding/codecs/opus/audio_encoder_mutable_opus_test.cc
new file mode 100644
index 0000000..ddb5f1e
--- /dev/null
+++ b/webrtc/modules/audio_coding/codecs/opus/audio_encoder_mutable_opus_test.cc
@@ -0,0 +1,114 @@
+/*
+ *  Copyright (c) 2015 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "testing/gtest/include/gtest/gtest.h"
+#include "webrtc/common_types.h"
+#include "webrtc/modules/audio_coding/codecs/opus/interface/audio_encoder_opus.h"
+
+namespace webrtc {
+namespace acm2 {
+
+#ifdef WEBRTC_CODEC_OPUS
+namespace {
+const CodecInst kDefaultOpusCodecInst = {105, "opus", 48000, 960, 1, 32000};
+}  // namespace
+
+class AudioEncoderMutableOpusTest : public ::testing::Test {
+ protected:
+  AudioEncoderMutableOpusTest() : codec_inst_(kDefaultOpusCodecInst) {}
+
+  void CreateCodec(int num_channels) {
+    codec_inst_.channels = num_channels;
+    encoder_.reset(new AudioEncoderMutableOpus(codec_inst_));
+    auto expected_app =
+        num_channels == 1 ? AudioEncoderOpus::kVoip : AudioEncoderOpus::kAudio;
+    EXPECT_EQ(expected_app, encoder_->application());
+  }
+
+  CodecInst codec_inst_;
+  rtc::scoped_ptr<AudioEncoderMutableOpus> encoder_;
+};
+
+TEST_F(AudioEncoderMutableOpusTest, DefaultApplicationModeMono) {
+  CreateCodec(1);
+}
+
+TEST_F(AudioEncoderMutableOpusTest, DefaultApplicationModeStereo) {
+  CreateCodec(2);
+}
+
+TEST_F(AudioEncoderMutableOpusTest, ChangeApplicationMode) {
+  CreateCodec(2);
+  EXPECT_TRUE(
+      encoder_->SetApplication(AudioEncoderMutable::kApplicationSpeech, false));
+  EXPECT_EQ(AudioEncoderOpus::kVoip, encoder_->application());
+}
+
+TEST_F(AudioEncoderMutableOpusTest, ResetWontChangeApplicationMode) {
+  CreateCodec(2);
+
+  // Trigger a reset.
+  encoder_->Reset();
+  // Verify that the mode is still kAudio.
+  EXPECT_EQ(AudioEncoderOpus::kAudio, encoder_->application());
+
+  // Now change to kVoip.
+  EXPECT_TRUE(
+      encoder_->SetApplication(AudioEncoderMutable::kApplicationSpeech, false));
+  EXPECT_EQ(AudioEncoderOpus::kVoip, encoder_->application());
+
+  // Trigger a reset again.
+  encoder_->Reset();
+  // Verify that the mode is still kVoip.
+  EXPECT_EQ(AudioEncoderOpus::kVoip, encoder_->application());
+}
+
+TEST_F(AudioEncoderMutableOpusTest, ToggleDtx) {
+  CreateCodec(2);
+
+  // DTX is not allowed in audio mode, if mode forcing flag is false.
+  EXPECT_FALSE(encoder_->SetDtx(true, false));
+  EXPECT_EQ(AudioEncoderOpus::kAudio, encoder_->application());
+
+  // DTX will be on, if mode forcing flag is true. Then application mode is
+  // switched to kVoip.
+  EXPECT_TRUE(encoder_->SetDtx(true, true));
+  EXPECT_EQ(AudioEncoderOpus::kVoip, encoder_->application());
+
+  // Audio mode is not allowed when DTX is on, and DTX forcing flag is false.
+  EXPECT_FALSE(
+      encoder_->SetApplication(AudioEncoderMutable::kApplicationAudio, false));
+  EXPECT_TRUE(encoder_->dtx_enabled());
+
+  // Audio mode will be set, if DTX forcing flag is true. Then DTX is switched
+  // off.
+  EXPECT_TRUE(
+      encoder_->SetApplication(AudioEncoderMutable::kApplicationAudio, true));
+  EXPECT_FALSE(encoder_->dtx_enabled());
+
+  // Now we set VOIP mode. The DTX forcing flag has no effect.
+  EXPECT_TRUE(
+      encoder_->SetApplication(AudioEncoderMutable::kApplicationSpeech, true));
+  EXPECT_FALSE(encoder_->dtx_enabled());
+
+  // In VOIP mode, we can enable DTX with mode forcing flag being false.
+  EXPECT_TRUE(encoder_->SetDtx(true, false));
+
+  // Turn off DTX.
+  EXPECT_TRUE(encoder_->SetDtx(false, false));
+
+  // When DTX is off, we can set Audio mode with DTX forcing flag being false.
+  EXPECT_TRUE(
+      encoder_->SetApplication(AudioEncoderMutable::kApplicationAudio, false));
+}
+#endif  // WEBRTC_CODEC_OPUS
+
+}  // namespace acm2
+}  // namespace webrtc
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 941e635..a3a34bf 100644
--- a/webrtc/modules/audio_coding/codecs/opus/audio_encoder_opus.cc
+++ b/webrtc/modules/audio_coding/codecs/opus/audio_encoder_opus.cc
@@ -11,6 +11,7 @@
 #include "webrtc/modules/audio_coding/codecs/opus/interface/audio_encoder_opus.h"
 
 #include "webrtc/base/checks.h"
+#include "webrtc/common_types.h"
 #include "webrtc/modules/audio_coding/codecs/opus/interface/opus_interface.h"
 
 namespace webrtc {
@@ -199,20 +200,73 @@
   CHECK_EQ(input_buffer_.size(),
            static_cast<size_t>(num_10ms_frames_per_packet_) *
            samples_per_10ms_frame_);
-  int16_t r = WebRtcOpus_Encode(
+  int16_t status = WebRtcOpus_Encode(
       inst_, &input_buffer_[0],
       rtc::CheckedDivExact(CastInt16(input_buffer_.size()),
                            static_cast<int16_t>(num_channels_)),
       ClampInt16(max_encoded_bytes), encoded);
-  CHECK_GE(r, 0);  // Fails only if fed invalid data.
+  CHECK_GE(status, 0);  // Fails only if fed invalid data.
   input_buffer_.clear();
   EncodedInfo info;
-  info.encoded_bytes = r;
+  info.encoded_bytes = status;
   info.encoded_timestamp = first_timestamp_in_buffer_;
   info.payload_type = payload_type_;
   info.send_even_if_empty = true;  // Allows Opus to send empty packets.
-  info.speech = r > 0;
+  info.speech = (status > 0);
   return info;
 }
 
+namespace {
+AudioEncoderOpus::Config CreateConfig(const CodecInst& codec_inst) {
+  AudioEncoderOpus::Config config;
+  config.frame_size_ms = rtc::CheckedDivExact(codec_inst.pacsize, 48);
+  config.num_channels = codec_inst.channels;
+  config.bitrate_bps = codec_inst.rate;
+  config.payload_type = codec_inst.pltype;
+  config.application = (config.num_channels == 1 ? AudioEncoderOpus::kVoip
+                                                 : AudioEncoderOpus::kAudio);
+  return config;
+}
+}  // namespace
+
+AudioEncoderMutableOpus::AudioEncoderMutableOpus(const CodecInst& codec_inst)
+    : AudioEncoderMutableImpl<AudioEncoderOpus>(CreateConfig(codec_inst)) {
+}
+
+bool AudioEncoderMutableOpus::SetFec(bool enable) {
+  auto conf = config();
+  conf.fec_enabled = enable;
+  return Reconstruct(conf);
+}
+
+bool AudioEncoderMutableOpus::SetDtx(bool enable, bool force) {
+  auto conf = config();
+  if (enable && force)
+    conf.application = AudioEncoderOpus::kVoip;
+  conf.dtx_enabled = enable;
+  return Reconstruct(conf);
+}
+
+bool AudioEncoderMutableOpus::SetApplication(Application application,
+                                             bool force) {
+  auto conf = config();
+  switch (application) {
+    case kApplicationSpeech:
+      conf.application = AudioEncoderOpus::kVoip;
+      break;
+    case kApplicationAudio:
+      if (force)
+        conf.dtx_enabled = false;
+      conf.application = AudioEncoderOpus::kAudio;
+      break;
+  }
+  return Reconstruct(conf);
+}
+
+bool AudioEncoderMutableOpus::SetMaxPlaybackRate(int frequency_hz) {
+  auto conf = config();
+  conf.max_playback_rate_hz = frequency_hz;
+  return Reconstruct(conf);
+}
+
 }  // namespace webrtc
diff --git a/webrtc/modules/audio_coding/codecs/opus/interface/audio_encoder_opus.h b/webrtc/modules/audio_coding/codecs/opus/interface/audio_encoder_opus.h
index bd76b49..8d123a9 100644
--- a/webrtc/modules/audio_coding/codecs/opus/interface/audio_encoder_opus.h
+++ b/webrtc/modules/audio_coding/codecs/opus/interface/audio_encoder_opus.h
@@ -13,6 +13,8 @@
 
 #include <vector>
 
+#include "webrtc/base/scoped_ptr.h"
+#include "webrtc/modules/audio_coding/codecs/audio_encoder_mutable_impl.h"
 #include "webrtc/modules/audio_coding/codecs/opus/interface/opus_interface.h"
 #include "webrtc/modules/audio_coding/codecs/audio_encoder.h"
 
@@ -56,8 +58,6 @@
   double packet_loss_rate() const { return packet_loss_rate_; }
   ApplicationMode application() const { return application_; }
   bool dtx_enabled() const { return dtx_enabled_; }
-
- protected:
   EncodedInfo EncodeInternal(uint32_t rtp_timestamp,
                              const int16_t* audio,
                              size_t max_encoded_bytes,
@@ -77,5 +77,22 @@
   double packet_loss_rate_;
 };
 
+struct CodecInst;
+
+class AudioEncoderMutableOpus
+    : public AudioEncoderMutableImpl<AudioEncoderOpus> {
+ public:
+  explicit AudioEncoderMutableOpus(const CodecInst& codec_inst);
+  bool SetFec(bool enable) override;
+  bool SetDtx(bool enable, bool force) override;
+  bool SetApplication(Application application, bool force) override;
+  bool SetMaxPlaybackRate(int frequency_hz) override;
+  AudioEncoderOpus::ApplicationMode application() const {
+    return encoder()->application();
+  }
+  double packet_loss_rate() const { return encoder()->packet_loss_rate(); }
+  bool dtx_enabled() const { return encoder()->dtx_enabled(); }
+};
+
 }  // namespace webrtc
 #endif  // WEBRTC_MODULES_AUDIO_CODING_CODECS_OPUS_INTERFACE_AUDIO_ENCODER_OPUS_H_
diff --git a/webrtc/modules/audio_coding/codecs/pcm16b/audio_encoder_pcm16b.cc b/webrtc/modules/audio_coding/codecs/pcm16b/audio_encoder_pcm16b.cc
index f761922..491fdfd 100644
--- a/webrtc/modules/audio_coding/codecs/pcm16b/audio_encoder_pcm16b.cc
+++ b/webrtc/modules/audio_coding/codecs/pcm16b/audio_encoder_pcm16b.cc
@@ -9,14 +9,41 @@
  */
 
 #include "webrtc/modules/audio_coding/codecs/pcm16b/include/audio_encoder_pcm16b.h"
+
+#include "webrtc/base/checks.h"
+#include "webrtc/common_types.h"
 #include "webrtc/modules/audio_coding/codecs/pcm16b/include/pcm16b.h"
 
 namespace webrtc {
 
+bool AudioEncoderPcm16B::Config::IsOk() const {
+  if ((sample_rate_hz != 8000) && (sample_rate_hz != 16000) &&
+      (sample_rate_hz != 32000) && (sample_rate_hz != 48000))
+    return false;
+  return AudioEncoderPcm::Config::IsOk();
+}
+
 int16_t AudioEncoderPcm16B::EncodeCall(const int16_t* audio,
                                        size_t input_len,
                                        uint8_t* encoded) {
   return WebRtcPcm16b_Encode(audio, static_cast<int16_t>(input_len), encoded);
 }
 
+namespace {
+AudioEncoderPcm16B::Config CreateConfig(const CodecInst& codec_inst) {
+  AudioEncoderPcm16B::Config config;
+  config.num_channels = codec_inst.channels;
+  config.sample_rate_hz = codec_inst.plfreq;
+  config.frame_size_ms = rtc::CheckedDivExact(
+      codec_inst.pacsize, rtc::CheckedDivExact(config.sample_rate_hz, 1000));
+  config.payload_type = codec_inst.pltype;
+  return config;
+}
+}  // namespace
+
+AudioEncoderMutablePcm16B::AudioEncoderMutablePcm16B(
+    const CodecInst& codec_inst)
+    : AudioEncoderMutableImpl<AudioEncoderPcm16B>(CreateConfig(codec_inst)) {
+}
+
 }  // namespace webrtc
diff --git a/webrtc/modules/audio_coding/codecs/pcm16b/include/audio_encoder_pcm16b.h b/webrtc/modules/audio_coding/codecs/pcm16b/include/audio_encoder_pcm16b.h
index 99ecd24..f1e1c51d 100644
--- a/webrtc/modules/audio_coding/codecs/pcm16b/include/audio_encoder_pcm16b.h
+++ b/webrtc/modules/audio_coding/codecs/pcm16b/include/audio_encoder_pcm16b.h
@@ -11,6 +11,8 @@
 #ifndef WEBRTC_MODULES_AUDIO_CODING_CODECS_PCM16B_INCLUDE_AUDIO_ENCODER_PCM16B_H_
 #define WEBRTC_MODULES_AUDIO_CODING_CODECS_PCM16B_INCLUDE_AUDIO_ENCODER_PCM16B_H_
 
+#include "webrtc/base/scoped_ptr.h"
+#include "webrtc/modules/audio_coding/codecs/audio_encoder_mutable_impl.h"
 #include "webrtc/modules/audio_coding/codecs/g711/include/audio_encoder_pcm.h"
 
 namespace webrtc {
@@ -20,6 +22,7 @@
   struct Config : public AudioEncoderPcm::Config {
    public:
     Config() : AudioEncoderPcm::Config(107), sample_rate_hz(8000) {}
+    bool IsOk() const;
 
     int sample_rate_hz;
   };
@@ -33,5 +36,13 @@
                      uint8_t* encoded) override;
 };
 
+struct CodecInst;
+
+class AudioEncoderMutablePcm16B
+    : public AudioEncoderMutableImpl<AudioEncoderPcm16B> {
+ public:
+  explicit AudioEncoderMutablePcm16B(const CodecInst& codec_inst);
+};
+
 }  // namespace webrtc
 #endif  // WEBRTC_MODULES_AUDIO_CODING_CODECS_PCM16B_INCLUDE_AUDIO_ENCODER_PCM16B_H_
diff --git a/webrtc/modules/audio_coding/codecs/red/audio_encoder_copy_red.h b/webrtc/modules/audio_coding/codecs/red/audio_encoder_copy_red.h
index 99e5ee2..49ab948 100644
--- a/webrtc/modules/audio_coding/codecs/red/audio_encoder_copy_red.h
+++ b/webrtc/modules/audio_coding/codecs/red/audio_encoder_copy_red.h
@@ -44,8 +44,6 @@
   int Max10MsFramesInAPacket() const override;
   void SetTargetBitrate(int bits_per_second) override;
   void SetProjectedPacketLossRate(double fraction) override;
-
- protected:
   EncodedInfo EncodeInternal(uint32_t rtp_timestamp,
                              const int16_t* audio,
                              size_t max_encoded_bytes,
diff --git a/webrtc/modules/modules.gyp b/webrtc/modules/modules.gyp
index 5fbd501..e97d852 100644
--- a/webrtc/modules/modules.gyp
+++ b/webrtc/modules/modules.gyp
@@ -96,6 +96,7 @@
             'audio_coding/codecs/cng/audio_encoder_cng_unittest.cc',
             'audio_coding/main/acm2/acm_generic_codec_test.cc',
             'audio_coding/main/acm2/acm_generic_codec_opus_test.cc',
+            'audio_coding/codecs/opus/audio_encoder_mutable_opus_test.cc',
             'audio_coding/main/acm2/acm_receiver_unittest.cc',
             'audio_coding/main/acm2/acm_receiver_unittest_oldapi.cc',
             'audio_coding/main/acm2/audio_coding_module_unittest.cc',