Create a joint encoder/decoder wrapper for iSAC in ACM

This CL extends the ACMISAC wrapper class to inherit from AudioDecoder
as well (the type of object that NetEq uses). The class has it's own
lock protecting the iSAC instance. This way, we can remove the
neteq_decode_lock_ (a.k.a. decoder_lock_) in a later CL.

The old AcmAudioDecoderIsac class is deleted.

R=kwiberg@webrtc.org, tina.legrand@webrtc.org, turaj@webrtc.org

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

git-svn-id: http://webrtc.googlecode.com/svn/trunk@6377 4adac7df-926f-26a2-2b94-8c16560cd09d
diff --git a/webrtc/modules/audio_coding/main/acm2/acm_isac.cc b/webrtc/modules/audio_coding/main/acm2/acm_isac.cc
index d7be971..9fbcdd4 100644
--- a/webrtc/modules/audio_coding/main/acm2/acm_isac.cc
+++ b/webrtc/modules/audio_coding/main/acm2/acm_isac.cc
@@ -15,6 +15,7 @@
 #include "webrtc/modules/audio_coding/main/acm2/acm_codec_database.h"
 #include "webrtc/modules/audio_coding/main/acm2/acm_common_defs.h"
 #include "webrtc/modules/audio_coding/neteq/interface/audio_decoder.h"
+#include "webrtc/system_wrappers/interface/critical_section_wrapper.h"
 #include "webrtc/system_wrappers/interface/trace.h"
 
 #ifdef WEBRTC_CODEC_ISAC
@@ -59,14 +60,15 @@
 #if (!defined(WEBRTC_CODEC_ISAC) && !defined(WEBRTC_CODEC_ISACFX))
 
 ACMISAC::ACMISAC(int16_t /* codec_id */)
-    : codec_inst_ptr_(NULL),
+    : codec_inst_crit_sect_(CriticalSectionWrapper::CreateCriticalSection()),
+      codec_inst_ptr_(NULL),
       is_enc_initialized_(false),
       isac_coding_mode_(CHANNEL_INDEPENDENT),
       enforce_frame_size_(false),
       isac_currentBN_(32000),
       samples_in10MsAudio_(160),  // Initiates to 16 kHz mode.
-      audio_decoder_(NULL),
-      decoder_initialized_(false) {}
+      decoder_initialized_(false) {
+}
 
 ACMISAC::~ACMISAC() {
   return;
@@ -261,81 +263,14 @@
 
 #endif
 
-// Decoder class to be injected into NetEq.
-class AcmAudioDecoderIsac : public AudioDecoder {
- public:
-  AcmAudioDecoderIsac(int codec_id, void* state)
-      : AudioDecoder(ACMCodecDB::neteq_decoders_[codec_id]) {
-    state_ = state;
-  }
-
-  // ACMISAC is the owner of the object where |state_| is pointing to.
-  // Therefore, it should not be deleted in this destructor.
-  virtual ~AcmAudioDecoderIsac() {}
-
-  virtual int Decode(const uint8_t* encoded, size_t encoded_len,
-                     int16_t* decoded, SpeechType* speech_type) {
-    int16_t temp_type;
-    int ret = ACM_ISAC_DECODE_B(static_cast<ACM_ISAC_STRUCT*>(state_),
-                                reinterpret_cast<const uint16_t*>(encoded),
-                                static_cast<int16_t>(encoded_len), decoded,
-                                &temp_type);
-    *speech_type = ConvertSpeechType(temp_type);
-    return ret;
-  }
-
-  virtual bool HasDecodePlc() const { return true; }
-
-  virtual int DecodePlc(int num_frames, int16_t* decoded) {
-    return ACM_ISAC_DECODEPLC(static_cast<ACM_ISAC_STRUCT*>(state_),
-                              decoded, static_cast<int16_t>(num_frames));
-  }
-
-  virtual int Init() {
-    return 0;  // We expect that the initialized instance is injected in the
-               // constructor.
-  }
-
-  virtual int IncomingPacket(const uint8_t* payload,
-                             size_t payload_len,
-                             uint16_t rtp_sequence_number,
-                             uint32_t rtp_timestamp,
-                             uint32_t arrival_timestamp) {
-    return ACM_ISAC_DECODE_BWE(static_cast<ACM_ISAC_STRUCT*>(state_),
-                               reinterpret_cast<const uint16_t*>(payload),
-                               static_cast<uint32_t>(payload_len),
-                               rtp_sequence_number,
-                               rtp_timestamp,
-                               arrival_timestamp);
-  }
-
-  virtual int DecodeRedundant(const uint8_t* encoded,
-                              size_t encoded_len, int16_t* decoded,
-                              SpeechType* speech_type) {
-    int16_t temp_type = 1;  // Default is speech.
-    int16_t ret = ACM_ISAC_DECODERCU(static_cast<ACM_ISAC_STRUCT*>(state_),
-                                     reinterpret_cast<const uint16_t*>(encoded),
-                                     static_cast<int16_t>(encoded_len), decoded,
-                                     &temp_type);
-    *speech_type = ConvertSpeechType(temp_type);
-    return ret;
-  }
-
-  virtual int ErrorCode() {
-    return ACM_ISAC_GETERRORCODE(static_cast<ACM_ISAC_STRUCT*>(state_));
-  }
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(AcmAudioDecoderIsac);
-};
-
 ACMISAC::ACMISAC(int16_t codec_id)
-    : is_enc_initialized_(false),
+    : AudioDecoder(ACMCodecDB::neteq_decoders_[codec_id]),
+      codec_inst_crit_sect_(CriticalSectionWrapper::CreateCriticalSection()),
+      is_enc_initialized_(false),
       isac_coding_mode_(CHANNEL_INDEPENDENT),
       enforce_frame_size_(false),
       isac_current_bn_(32000),
       samples_in_10ms_audio_(160),  // Initiates to 16 kHz mode.
-      audio_decoder_(NULL),
       decoder_initialized_(false) {
   codec_id_ = codec_id;
 
@@ -345,14 +280,10 @@
     return;
   }
   codec_inst_ptr_->inst = NULL;
+  state_ = codec_inst_ptr_;
 }
 
 ACMISAC::~ACMISAC() {
-  if (audio_decoder_ != NULL) {
-    delete audio_decoder_;
-    audio_decoder_ = NULL;
-  }
-
   if (codec_inst_ptr_ != NULL) {
     if (codec_inst_ptr_->inst != NULL) {
       ACM_ISAC_FREE(codec_inst_ptr_->inst);
@@ -364,6 +295,34 @@
   return;
 }
 
+int16_t ACMISAC::InternalInitDecoder(WebRtcACMCodecParams* codec_params) {
+  // set decoder sampling frequency.
+  if (codec_params->codec_inst.plfreq == 32000 ||
+      codec_params->codec_inst.plfreq == 48000) {
+    UpdateDecoderSampFreq(ACMCodecDB::kISACSWB);
+  } else {
+    UpdateDecoderSampFreq(ACMCodecDB::kISAC);
+  }
+
+  // in a one-way communication we may never register send-codec.
+  // However we like that the BWE to work properly so it has to
+  // be initialized. The BWE is initialized when iSAC encoder is initialized.
+  // Therefore, we need this.
+  if (!encoder_initialized_) {
+    // Since we don't require a valid rate or a valid packet size when
+    // initializing the decoder, we set valid values before initializing encoder
+    codec_params->codec_inst.rate = kIsacWbDefaultRate;
+    codec_params->codec_inst.pacsize = kIsacPacSize960;
+    if (InternalInitEncoder(codec_params) < 0) {
+      return -1;
+    }
+    encoder_initialized_ = true;
+  }
+
+  CriticalSectionScoped lock(codec_inst_crit_sect_.get());
+  return ACM_ISAC_DECODERINIT(codec_inst_ptr_->inst);
+}
+
 ACMGenericCodec* ACMISAC::CreateInstance(void) { return NULL; }
 
 int16_t ACMISAC::InternalEncode(uint8_t* bitstream,
@@ -375,6 +334,7 @@
   // at the first 10ms pushed in to iSAC if the bit-rate is low, this is
   // sort of a bug in iSAC. to address this we treat iSAC as the
   // following.
+  CriticalSectionScoped lock(codec_inst_crit_sect_.get());
   if (codec_inst_ptr_ == NULL) {
     return -1;
   }
@@ -428,6 +388,7 @@
   if (UpdateEncoderSampFreq((uint16_t)codec_params->codec_inst.plfreq) < 0) {
     return -1;
   }
+  CriticalSectionScoped lock(codec_inst_crit_sect_.get());
   if (ACM_ISAC_ENCODERINIT(codec_inst_ptr_->inst, isac_coding_mode_) < 0) {
     return -1;
   }
@@ -450,38 +411,8 @@
   return 0;
 }
 
-int16_t ACMISAC::InternalInitDecoder(WebRtcACMCodecParams* codec_params) {
-  if (codec_inst_ptr_ == NULL) {
-    return -1;
-  }
-
-  // set decoder sampling frequency.
-  if (codec_params->codec_inst.plfreq == 32000 ||
-      codec_params->codec_inst.plfreq == 48000) {
-    UpdateDecoderSampFreq(ACMCodecDB::kISACSWB);
-  } else {
-    UpdateDecoderSampFreq(ACMCodecDB::kISAC);
-  }
-
-  // in a one-way communication we may never register send-codec.
-  // However we like that the BWE to work properly so it has to
-  // be initialized. The BWE is initialized when iSAC encoder is initialized.
-  // Therefore, we need this.
-  if (!encoder_initialized_) {
-    // Since we don't require a valid rate or a valid packet size when
-    // initializing the decoder, we set valid values before initializing encoder
-    codec_params->codec_inst.rate = kIsacWbDefaultRate;
-    codec_params->codec_inst.pacsize = kIsacPacSize960;
-    if (InternalInitEncoder(codec_params) < 0) {
-      return -1;
-    }
-    encoder_initialized_ = true;
-  }
-
-  return ACM_ISAC_DECODERINIT(codec_inst_ptr_->inst);
-}
-
 int16_t ACMISAC::InternalCreateEncoder() {
+  CriticalSectionScoped lock(codec_inst_crit_sect_.get());
   if (codec_inst_ptr_ == NULL) {
     return -1;
   }
@@ -493,19 +424,6 @@
   return status;
 }
 
-void ACMISAC::DestructEncoderSafe() {
-  // codec with shared instance cannot delete.
-  encoder_initialized_ = false;
-  return;
-}
-
-void ACMISAC::InternalDestructEncoderInst(void* ptr_inst) {
-  if (ptr_inst != NULL) {
-    ACM_ISAC_FREE(static_cast<ACM_ISAC_STRUCT *>(ptr_inst));
-  }
-  return;
-}
-
 int16_t ACMISAC::Transcode(uint8_t* bitstream,
                            int16_t* bitstream_len_byte,
                            int16_t q_bwe,
@@ -513,6 +431,7 @@
                            bool is_red) {
   int16_t jitter_info = 0;
   // transcode from a higher rate to lower rate sanity check
+  CriticalSectionScoped lock(codec_inst_crit_sect_.get());
   if (codec_inst_ptr_ == NULL) {
     return -1;
   }
@@ -530,7 +449,27 @@
   }
 }
 
+void ACMISAC::UpdateFrameLen() {
+  CriticalSectionScoped lock(codec_inst_crit_sect_.get());
+  frame_len_smpl_ = ACM_ISAC_GETNEWFRAMELEN(codec_inst_ptr_->inst);
+  encoder_params_.codec_inst.pacsize = frame_len_smpl_;
+}
+
+void ACMISAC::DestructEncoderSafe() {
+  // codec with shared instance cannot delete.
+  encoder_initialized_ = false;
+  return;
+}
+
+void ACMISAC::InternalDestructEncoderInst(void* ptr_inst) {
+  if (ptr_inst != NULL) {
+    ACM_ISAC_FREE(static_cast<ACM_ISAC_STRUCT *>(ptr_inst));
+  }
+  return;
+}
+
 int16_t ACMISAC::SetBitRateSafe(int32_t bit_rate) {
+  CriticalSectionScoped lock(codec_inst_crit_sect_.get());
   if (codec_inst_ptr_ == NULL) {
     return -1;
   }
@@ -594,6 +533,7 @@
   int samp_rate;
 
   // Get bandwidth information
+  CriticalSectionScoped lock(codec_inst_crit_sect_.get());
   ACM_ISAC_GETSENDBWE(codec_inst_ptr_->inst, &bandwidth_index, &delay_index);
 
   // Validy check of index
@@ -615,6 +555,7 @@
   int16_t bandwidth_index;
 
   // Check sample frequency and choose appropriate table
+  CriticalSectionScoped lock(codec_inst_crit_sect_.get());
   samp_rate = ACM_ISAC_GETENCSAMPRATE(codec_inst_ptr_->inst);
 
   if (samp_rate == 16000) {
@@ -657,6 +598,7 @@
   return -1;
 #else
     uint8_t* red_payload, int16_t* payload_bytes) {
+  CriticalSectionScoped lock(codec_inst_crit_sect_.get());
   int16_t bytes =
       WebRtcIsac_GetRedPayload(
           codec_inst_ptr_->inst, reinterpret_cast<int16_t*>(red_payload));
@@ -672,6 +614,7 @@
 #ifdef WEBRTC_CODEC_ISAC
     int16_t codec_id) {
     // The decoder supports only wideband and super-wideband.
+  CriticalSectionScoped lock(codec_inst_crit_sect_.get());
   if (ACMCodecDB::kISAC == codec_id) {
     return WebRtcIsac_SetDecSampRate(codec_inst_ptr_->inst, 16000);
   } else if (ACMCodecDB::kISACSWB == codec_id ||
@@ -700,6 +643,7 @@
       in_audio_ix_read_ = 0;
       in_audio_ix_write_ = 0;
       in_timestamp_ix_write_ = 0;
+      CriticalSectionScoped lock(codec_inst_crit_sect_.get());
       if (WebRtcIsac_SetEncSampRate(codec_inst_ptr_->inst,
                                     encoder_samp_freq_hz) < 0) {
         return -1;
@@ -718,6 +662,7 @@
 }
 
 int16_t ACMISAC::EncoderSampFreq(uint16_t* samp_freq_hz) {
+  CriticalSectionScoped lock(codec_inst_crit_sect_.get());
   *samp_freq_hz = ACM_ISAC_GETENCSAMPRATE(codec_inst_ptr_->inst);
   return 0;
 }
@@ -730,6 +675,7 @@
   {
     uint16_t samp_freq_hz;
     EncoderSampFreq(&samp_freq_hz);
+    CriticalSectionScoped lock(codec_inst_crit_sect_.get());
     // TODO(turajs): at 32kHz we hardcode calling with 30ms and enforce
     // the frame-size otherwise we might get error. Revise if
     // control-bwe is changed.
@@ -749,26 +695,25 @@
     return -1;
   }
   UpdateFrameLen();
+  CriticalSectionScoped lock(codec_inst_crit_sect_.get());
   ACM_ISAC_GETSENDBITRATE(codec_inst_ptr_->inst, &isac_current_bn_);
   return 0;
 }
 
 int32_t ACMISAC::SetISACMaxPayloadSize(const uint16_t max_payload_len_bytes) {
+  CriticalSectionScoped lock(codec_inst_crit_sect_.get());
   return ACM_ISAC_SETMAXPAYLOADSIZE(codec_inst_ptr_->inst,
                                     max_payload_len_bytes);
 }
 
 int32_t ACMISAC::SetISACMaxRate(const uint32_t max_rate_bit_per_sec) {
+  CriticalSectionScoped lock(codec_inst_crit_sect_.get());
   return ACM_ISAC_SETMAXRATE(codec_inst_ptr_->inst, max_rate_bit_per_sec);
 }
 
-void ACMISAC::UpdateFrameLen() {
-  frame_len_smpl_ = ACM_ISAC_GETNEWFRAMELEN(codec_inst_ptr_->inst);
-  encoder_params_.codec_inst.pacsize = frame_len_smpl_;
-}
-
 void ACMISAC::CurrentRate(int32_t* rate_bit_per_sec) {
   if (isac_coding_mode_ == ADAPTIVE) {
+    CriticalSectionScoped lock(codec_inst_crit_sect_.get());
     ACM_ISAC_GETSENDBITRATE(codec_inst_ptr_->inst, rate_bit_per_sec);
   }
 }
@@ -784,12 +729,71 @@
   return status;
 }
 
-AudioDecoder* ACMISAC::Decoder(int codec_id) {
-  if (audio_decoder_)
-    return audio_decoder_;
+int ACMISAC::Decode(const uint8_t* encoded,
+                    size_t encoded_len,
+                    int16_t* decoded,
+                    SpeechType* speech_type) {
+  int16_t temp_type;
+  CriticalSectionScoped lock(codec_inst_crit_sect_.get());
+  int ret =
+      ACM_ISAC_DECODE_B(static_cast<ACM_ISAC_STRUCT*>(codec_inst_ptr_->inst),
+                        reinterpret_cast<const uint16_t*>(encoded),
+                        static_cast<int16_t>(encoded_len),
+                        decoded,
+                        &temp_type);
+  *speech_type = ConvertSpeechType(temp_type);
+  return ret;
+}
 
+int ACMISAC::DecodePlc(int num_frames, int16_t* decoded) {
+  CriticalSectionScoped lock(codec_inst_crit_sect_.get());
+  return ACM_ISAC_DECODEPLC(
+      static_cast<ACM_ISAC_STRUCT*>(codec_inst_ptr_->inst),
+      decoded,
+      static_cast<int16_t>(num_frames));
+}
+
+int ACMISAC::IncomingPacket(const uint8_t* payload,
+                            size_t payload_len,
+                            uint16_t rtp_sequence_number,
+                            uint32_t rtp_timestamp,
+                            uint32_t arrival_timestamp) {
+  CriticalSectionScoped lock(codec_inst_crit_sect_.get());
+  return ACM_ISAC_DECODE_BWE(
+      static_cast<ACM_ISAC_STRUCT*>(codec_inst_ptr_->inst),
+      reinterpret_cast<const uint16_t*>(payload),
+      static_cast<uint32_t>(payload_len),
+      rtp_sequence_number,
+      rtp_timestamp,
+      arrival_timestamp);
+}
+
+int ACMISAC::DecodeRedundant(const uint8_t* encoded,
+                             size_t encoded_len,
+                             int16_t* decoded,
+                             SpeechType* speech_type) {
+  int16_t temp_type = 1;  // Default is speech.
+  CriticalSectionScoped lock(codec_inst_crit_sect_.get());
+  int16_t ret =
+      ACM_ISAC_DECODERCU(static_cast<ACM_ISAC_STRUCT*>(codec_inst_ptr_->inst),
+                         reinterpret_cast<const uint16_t*>(encoded),
+                         static_cast<int16_t>(encoded_len),
+                         decoded,
+                         &temp_type);
+  *speech_type = ConvertSpeechType(temp_type);
+  return ret;
+}
+
+int ACMISAC::ErrorCode() {
+  CriticalSectionScoped lock(codec_inst_crit_sect_.get());
+  return ACM_ISAC_GETERRORCODE(
+      static_cast<ACM_ISAC_STRUCT*>(codec_inst_ptr_->inst));
+}
+
+AudioDecoder* ACMISAC::Decoder(int codec_id) {
   // Create iSAC instance if it does not exist.
   if (!encoder_exist_) {
+    CriticalSectionScoped lock(codec_inst_crit_sect_.get());
     assert(codec_inst_ptr_->inst == NULL);
     encoder_initialized_ = false;
     decoder_initialized_ = false;
@@ -822,8 +826,7 @@
     decoder_initialized_ = true;
   }
 
-  audio_decoder_ = new AcmAudioDecoderIsac(codec_id, codec_inst_ptr_->inst);
-  return audio_decoder_;
+  return this;
 }
 
 #endif
diff --git a/webrtc/modules/audio_coding/main/acm2/acm_isac.h b/webrtc/modules/audio_coding/main/acm2/acm_isac.h
index a3227d5..3249526 100644
--- a/webrtc/modules/audio_coding/main/acm2/acm_isac.h
+++ b/webrtc/modules/audio_coding/main/acm2/acm_isac.h
@@ -12,86 +12,119 @@
 #define WEBRTC_MODULES_AUDIO_CODING_MAIN_ACM2_ACM_ISAC_H_
 
 #include "webrtc/modules/audio_coding/main/acm2/acm_generic_codec.h"
+#include "webrtc/modules/audio_coding/neteq/interface/audio_decoder.h"
+#include "webrtc/system_wrappers/interface/scoped_ptr.h"
+#include "webrtc/system_wrappers/interface/thread_annotations.h"
 
 namespace webrtc {
 
+class CriticalSectionWrapper;
+
 namespace acm2 {
 
 struct ACMISACInst;
-class AcmAudioDecoderIsac;
 
 enum IsacCodingMode {
   ADAPTIVE,
   CHANNEL_INDEPENDENT
 };
 
-class ACMISAC : public ACMGenericCodec {
+class ACMISAC : public ACMGenericCodec, AudioDecoder {
  public:
   explicit ACMISAC(int16_t codec_id);
   ~ACMISAC();
 
-  // for FEC
-  ACMGenericCodec* CreateInstance(void);
-
-  int16_t InternalEncode(uint8_t* bitstream, int16_t* bitstream_len_byte);
-
-  int16_t InternalInitEncoder(WebRtcACMCodecParams* codec_params);
-
   int16_t InternalInitDecoder(WebRtcACMCodecParams* codec_params);
 
-  int16_t UpdateDecoderSampFreq(int16_t codec_id);
+  // Methods below are inherited from ACMGenericCodec.
+  ACMGenericCodec* CreateInstance(void) OVERRIDE;
 
-  int16_t UpdateEncoderSampFreq(uint16_t samp_freq_hz);
+  int16_t InternalEncode(uint8_t* bitstream,
+                         int16_t* bitstream_len_byte) OVERRIDE;
 
-  int16_t EncoderSampFreq(uint16_t* samp_freq_hz);
+  int16_t InternalInitEncoder(WebRtcACMCodecParams* codec_params) OVERRIDE;
+
+  int16_t UpdateDecoderSampFreq(int16_t codec_id) OVERRIDE;
+
+  int16_t UpdateEncoderSampFreq(uint16_t samp_freq_hz) OVERRIDE;
+
+  int16_t EncoderSampFreq(uint16_t* samp_freq_hz) OVERRIDE;
 
   int32_t ConfigISACBandwidthEstimator(const uint8_t init_frame_size_msec,
                                        const uint16_t init_rate_bit_per_sec,
-                                       const bool enforce_frame_size);
+                                       const bool enforce_frame_size) OVERRIDE;
 
-  int32_t SetISACMaxPayloadSize(const uint16_t max_payload_len_bytes);
+  int32_t SetISACMaxPayloadSize(const uint16_t max_payload_len_bytes) OVERRIDE;
 
-  int32_t SetISACMaxRate(const uint32_t max_rate_bit_per_sec);
+  int32_t SetISACMaxRate(const uint32_t max_rate_bit_per_sec) OVERRIDE;
 
   int16_t REDPayloadISAC(const int32_t isac_rate,
                          const int16_t isac_bw_estimate,
                          uint8_t* payload,
-                         int16_t* payload_len_bytes);
+                         int16_t* payload_len_bytes) OVERRIDE;
+
+  // Methods below are inherited from AudioDecoder.
+  virtual int Decode(const uint8_t* encoded,
+                     size_t encoded_len,
+                     int16_t* decoded,
+                     SpeechType* speech_type) OVERRIDE;
+
+  virtual bool HasDecodePlc() const OVERRIDE { return true; }
+
+  virtual int DecodePlc(int num_frames, int16_t* decoded) OVERRIDE;
+
+  virtual int Init() OVERRIDE { return 0; }
+
+  virtual int IncomingPacket(const uint8_t* payload,
+                             size_t payload_len,
+                             uint16_t rtp_sequence_number,
+                             uint32_t rtp_timestamp,
+                             uint32_t arrival_timestamp) OVERRIDE;
+
+  virtual int DecodeRedundant(const uint8_t* encoded,
+                              size_t encoded_len,
+                              int16_t* decoded,
+                              SpeechType* speech_type) OVERRIDE;
+
+  virtual int ErrorCode() OVERRIDE;
 
  protected:
-  void DestructEncoderSafe();
-
-  int16_t SetBitRateSafe(const int32_t bit_rate);
-
-  int32_t GetEstimatedBandwidthSafe();
-
-  int32_t SetEstimatedBandwidthSafe(int32_t estimated_bandwidth);
-
-  int32_t GetRedPayloadSafe(uint8_t* red_payload, int16_t* payload_bytes);
-
-  int16_t InternalCreateEncoder();
-
-  void InternalDestructEncoderInst(void* ptr_inst);
-
   int16_t Transcode(uint8_t* bitstream,
                     int16_t* bitstream_len_byte,
                     int16_t q_bwe,
                     int32_t rate,
                     bool is_red);
 
-  void CurrentRate(int32_t* rate_bit_per_sec);
-
   void UpdateFrameLen();
 
-  virtual AudioDecoder* Decoder(int codec_id);
+  // Methods below are inherited from ACMGenericCodec.
+  void DestructEncoderSafe() OVERRIDE;
 
-  ACMISACInst* codec_inst_ptr_;
+  int16_t SetBitRateSafe(const int32_t bit_rate) OVERRIDE;
+
+  int32_t GetEstimatedBandwidthSafe() OVERRIDE;
+
+  int32_t SetEstimatedBandwidthSafe(int32_t estimated_bandwidth) OVERRIDE;
+
+  int32_t GetRedPayloadSafe(uint8_t* red_payload,
+                            int16_t* payload_bytes) OVERRIDE;
+
+  int16_t InternalCreateEncoder() OVERRIDE;
+
+  void InternalDestructEncoderInst(void* ptr_inst) OVERRIDE;
+
+  void CurrentRate(int32_t* rate_bit_per_sec) OVERRIDE;
+
+  virtual AudioDecoder* Decoder(int codec_id) OVERRIDE;
+
+  // |codec_inst_crit_sect_| protects |codec_inst_ptr_|.
+  const scoped_ptr<CriticalSectionWrapper> codec_inst_crit_sect_;
+  ACMISACInst* codec_inst_ptr_ GUARDED_BY(codec_inst_crit_sect_);
   bool is_enc_initialized_;
   IsacCodingMode isac_coding_mode_;
   bool enforce_frame_size_;
   int32_t isac_current_bn_;
   uint16_t samples_in_10ms_audio_;
-  AcmAudioDecoderIsac* audio_decoder_;
   bool decoder_initialized_;
 };