ACM2 integration with NetEq 4.

nack{.cc, .h, _unittest.cc} are basically copies from main/source/ folder, with cpplint warning cleaned up.

BUG=
R=andrew@webrtc.org

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

git-svn-id: http://webrtc.googlecode.com/svn/trunk@4736 4adac7df-926f-26a2-2b94-8c16560cd09d
diff --git a/webrtc/modules/audio_coding/main/acm2/acm_amr.cc b/webrtc/modules/audio_coding/main/acm2/acm_amr.cc
new file mode 100644
index 0000000..75430f1
--- /dev/null
+++ b/webrtc/modules/audio_coding/main/acm2/acm_amr.cc
@@ -0,0 +1,310 @@
+/*
+ *  Copyright (c) 2012 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 "webrtc/modules/audio_coding/main/source/acm_amr.h"
+
+#ifdef WEBRTC_CODEC_AMR
+// NOTE! GSM AMR is not included in the open-source package. The following
+// interface file is needed:
+#include "webrtc/modules/audio_coding/main/codecs/amr/interface/amr_interface.h"
+#include "webrtc/modules/audio_coding/main/interface/audio_coding_module_typedefs.h"
+#include "webrtc/modules/audio_coding/main/source/acm_common_defs.h"
+#include "webrtc/system_wrappers/interface/rw_lock_wrapper.h"
+#include "webrtc/system_wrappers/interface/trace.h"
+
+// The API in the header file should match the one below.
+//
+// int16_t WebRtcAmr_CreateEnc(AMR_encinst_t_** enc_inst);
+// int16_t WebRtcAmr_CreateDec(AMR_decinst_t_** dec_inst);
+// int16_t WebRtcAmr_FreeEnc(AMR_encinst_t_* enc_inst);
+// int16_t WebRtcAmr_FreeDec(AMR_decinst_t_* dec_inst);
+// int16_t WebRtcAmr_Encode(AMR_encinst_t_* enc_inst,
+//                          int16_t* input,
+//                          int16_t len,
+//                          int16_t*output,
+//                          int16_t mode);
+//  int16_t WebRtcAmr_EncoderInit(AMR_encinst_t_* enc_inst,
+//                               int16_t dtx_mode);
+// int16_t WebRtcAmr_EncodeBitmode(AMR_encinst_t_* enc_inst,
+//                                 int format);
+// int16_t WebRtcAmr_Decode(AMR_decinst_t_* dec_inst);
+// int16_t WebRtcAmr_DecodePlc(AMR_decinst_t_* dec_inst);
+// int16_t WebRtcAmr_DecoderInit(AMR_decinst_t_* dec_inst);
+// int16_t WebRtcAmr_DecodeBitmode(AMR_decinst_t_* dec_inst,
+//                                 int format);
+#endif
+
+namespace webrtc {
+
+#ifndef WEBRTC_CODEC_AMR
+ACMAMR::ACMAMR(int16_t /* codec_id */)
+    : encoder_inst_ptr_(NULL),
+      encoding_mode_(-1),  // Invalid value.
+      encoding_rate_(0),   // Invalid value.
+      encoder_packing_format_(AMRBandwidthEfficient) {
+  return;
+}
+
+ACMAMR::~ACMAMR() { return; }
+
+int16_t ACMAMR::InternalEncode(uint8_t* /* bitstream */,
+                               int16_t* /* bitstream_len_byte */) {
+  return -1;
+}
+
+int16_t ACMAMR::EnableDTX() { return -1; }
+
+int16_t ACMAMR::DisableDTX() { return -1; }
+
+int16_t ACMAMR::InternalInitEncoder(WebRtcACMCodecParams* /* codec_params */) {
+  return -1;
+}
+
+ACMGenericCodec* ACMAMR::CreateInstance(void) { return NULL; }
+
+int16_t ACMAMR::InternalCreateEncoder() { return -1; }
+
+void ACMAMR::DestructEncoderSafe() { return; }
+
+int16_t ACMAMR::SetBitRateSafe(const int32_t /* rate */) { return -1; }
+
+void ACMAMR::InternalDestructEncoderInst(void* /* ptr_inst */) { return; }
+
+int16_t ACMAMR::SetAMREncoderPackingFormat(
+    ACMAMRPackingFormat /* packing_format */) {
+  return -1;
+}
+
+ACMAMRPackingFormat ACMAMR::AMREncoderPackingFormat() const {
+  return AMRUndefined;
+}
+
+int16_t ACMAMR::SetAMRDecoderPackingFormat(
+    ACMAMRPackingFormat /* packing_format */) {
+  return -1;
+}
+
+ACMAMRPackingFormat ACMAMR::AMRDecoderPackingFormat() const {
+  return AMRUndefined;
+}
+
+#else     //===================== Actual Implementation =======================
+
+#define WEBRTC_AMR_MR475 0
+#define WEBRTC_AMR_MR515 1
+#define WEBRTC_AMR_MR59 2
+#define WEBRTC_AMR_MR67 3
+#define WEBRTC_AMR_MR74 4
+#define WEBRTC_AMR_MR795 5
+#define WEBRTC_AMR_MR102 6
+#define WEBRTC_AMR_MR122 7
+
+ACMAMR::ACMAMR(int16_t codec_id)
+    : encoder_inst_ptr_(NULL),
+      encoding_mode_(-1),  // invalid value
+      encoding_rate_(0) {  // invalid value
+  codec_id_ = codec_id;
+  has_internal_dtx_ = true;
+  encoder_packing_format_ = AMRBandwidthEfficient;
+  return;
+}
+
+ACMAMR::~ACMAMR() {
+  if (encoder_inst_ptr_ != NULL) {
+    WebRtcAmr_FreeEnc(encoder_inst_ptr_);
+    encoder_inst_ptr_ = NULL;
+  }
+  return;
+}
+
+int16_t ACMAMR::InternalEncode(uint8_t* bitstream,
+                               int16_t* bitstream_len_byte) {
+  int16_t vad_decision = 1;
+  // sanity check, if the rate is set correctly. we might skip this
+  // sanity check. if rate is not set correctly, initialization flag
+  // should be false and should not be here.
+  if ((encoding_mode_ < WEBRTC_AMR_MR475) ||
+      (encoding_mode_ > WEBRTC_AMR_MR122)) {
+    *bitstream_len_byte = 0;
+    return -1;
+  }
+  *bitstream_len_byte = WebRtcAmr_Encode(encoder_inst_ptr_,
+                                         &in_audio_[in_audio_ix_read_],
+                                         frame_len_smpl_,
+                                         reinterpret_cast<int16_t*>(bitstream),
+                                         encoding_mode_);
+
+  // Update VAD, if internal DTX is used
+  if (has_internal_dtx_ && dtx_enabled_) {
+    if (*bitstream_len_byte <= (7 * frame_len_smpl_ / 160)) {
+      vad_decision = 0;
+    }
+    for (int16_t n = 0; n < MAX_FRAME_SIZE_10MSEC; n++) {
+      vad_label_[n] = vad_decision;
+    }
+  }
+  // increment the read index
+  in_audio_ix_read_ += frame_len_smpl_;
+  return *bitstream_len_byte;
+}
+
+int16_t ACMAMR::EnableDTX() {
+  if (dtx_enabled_) {
+    return 0;
+  } else if (encoder_exist_) {  // check if encoder exist
+    // enable DTX
+    if (WebRtcAmr_EncoderInit(encoder_inst_ptr_, 1) < 0) {
+      return -1;
+    }
+    dtx_enabled_ = true;
+    return 0;
+  } else {
+    return -1;
+  }
+}
+
+int16_t ACMAMR::DisableDTX() {
+  if (!dtx_enabled_) {
+    return 0;
+  } else if (encoder_exist_) {  // check if encoder exist
+    // disable DTX
+    if (WebRtcAmr_EncoderInit(encoder_inst_ptr_, 0) < 0) {
+      return -1;
+    }
+    dtx_enabled_ = false;
+    return 0;
+  } else {
+    // encoder doesn't exists, therefore disabling is harmless
+    return 0;
+  }
+}
+
+int16_t ACMAMR::InternalInitEncoder(WebRtcACMCodecParams* codec_params) {
+  int16_t status = SetBitRateSafe((codec_params->codec_inst).rate);
+  status += (WebRtcAmr_EncoderInit(encoder_inst_ptr_,
+                                   ((codec_params->enable_dtx) ? 1 : 0)) < 0)
+                ? -1
+                : 0;
+  status +=
+      (WebRtcAmr_EncodeBitmode(encoder_inst_ptr_, encoder_packing_format_) < 0)
+          ? -1
+          : 0;
+  return (status < 0) ? -1 : 0;
+}
+
+ACMGenericCodec* ACMAMR::CreateInstance(void) { return NULL; }
+
+int16_t ACMAMR::InternalCreateEncoder() {
+  return WebRtcAmr_CreateEnc(&encoder_inst_ptr_);
+}
+
+void ACMAMR::DestructEncoderSafe() {
+  if (encoder_inst_ptr_ != NULL) {
+    WebRtcAmr_FreeEnc(encoder_inst_ptr_);
+    encoder_inst_ptr_ = NULL;
+  }
+  // there is no encoder set the following
+  encoder_exist_ = false;
+  encoder_initialized_ = false;
+  encoding_mode_ = -1;  // invalid value
+  encoding_rate_ = 0;   // invalid value
+}
+
+int16_t ACMAMR::SetBitRateSafe(const int32_t rate) {
+  switch (rate) {
+    case 4750: {
+      encoding_mode_ = WEBRTC_AMR_MR475;
+      encoding_rate_ = 4750;
+      break;
+    }
+    case 5150: {
+      encoding_mode_ = WEBRTC_AMR_MR515;
+      encoding_rate_ = 5150;
+      break;
+    }
+    case 5900: {
+      encoding_mode_ = WEBRTC_AMR_MR59;
+      encoding_rate_ = 5900;
+      break;
+    }
+    case 6700: {
+      encoding_mode_ = WEBRTC_AMR_MR67;
+      encoding_rate_ = 6700;
+      break;
+    }
+    case 7400: {
+      encoding_mode_ = WEBRTC_AMR_MR74;
+      encoding_rate_ = 7400;
+      break;
+    }
+    case 7950: {
+      encoding_mode_ = WEBRTC_AMR_MR795;
+      encoding_rate_ = 7950;
+      break;
+    }
+    case 10200: {
+      encoding_mode_ = WEBRTC_AMR_MR102;
+      encoding_rate_ = 10200;
+      break;
+    }
+    case 12200: {
+      encoding_mode_ = WEBRTC_AMR_MR122;
+      encoding_rate_ = 12200;
+      break;
+    }
+    default: {
+      return -1;
+    }
+  }
+  return 0;
+}
+
+void ACMAMR::InternalDestructEncoderInst(void* ptr_inst) {
+  // Free the memory where ptr_inst is pointing to
+  if (ptr_inst != NULL) {
+    WebRtcAmr_FreeEnc(static_cast<AMR_encinst_t_*>(ptr_inst));
+  }
+  return;
+}
+
+int16_t ACMAMR::SetAMREncoderPackingFormat(ACMAMRPackingFormat packing_format) {
+  if ((packing_format != AMRBandwidthEfficient) &&
+      (packing_format != AMROctetAlligned) &&
+      (packing_format != AMRFileStorage)) {
+    WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, unique_id_,
+                 "Invalid AMR Encoder packing-format.");
+    return -1;
+  } else {
+    if (WebRtcAmr_EncodeBitmode(encoder_inst_ptr_, packing_format) < 0) {
+      return -1;
+    } else {
+      encoder_packing_format_ = packing_format;
+      return 0;
+    }
+  }
+}
+
+ACMAMRPackingFormat ACMAMR::AMREncoderPackingFormat() const {
+  return encoder_packing_format_;
+}
+
+int16_t ACMAMR::SetAMRDecoderPackingFormat(
+    ACMAMRPackingFormat /* packing_format */) {
+  // Not implemented.
+  return -1;
+}
+
+ACMAMRPackingFormat ACMAMR::AMRDecoderPackingFormat() const {
+  // Not implemented.
+  return AMRUndefined;
+}
+
+#endif
+}  // namespace webrtc
diff --git a/webrtc/modules/audio_coding/main/acm2/acm_amr.h b/webrtc/modules/audio_coding/main/acm2/acm_amr.h
new file mode 100644
index 0000000..c58b511
--- /dev/null
+++ b/webrtc/modules/audio_coding/main/acm2/acm_amr.h
@@ -0,0 +1,65 @@
+/*
+ *  Copyright (c) 2012 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_MAIN_SOURCE_ACM_AMR_H_
+#define WEBRTC_MODULES_AUDIO_CODING_MAIN_SOURCE_ACM_AMR_H_
+
+#include "webrtc/modules/audio_coding/main/source/acm_generic_codec.h"
+
+// forward declaration
+struct AMR_encinst_t_;
+struct AMR_decinst_t_;
+
+namespace webrtc {
+
+enum ACMAMRPackingFormat;
+
+class ACMAMR : public ACMGenericCodec {
+ public:
+  explicit ACMAMR(int16_t codec_id);
+  ~ACMAMR();
+
+  // for FEC
+  ACMGenericCodec* CreateInstance(void);
+
+  int16_t InternalEncode(uint8_t* bitstream, int16_t* bitstream_len_byte);
+
+  int16_t InternalInitEncoder(WebRtcACMCodecParams* codec_params);
+
+  int16_t SetAMREncoderPackingFormat(const ACMAMRPackingFormat packing_format);
+
+  ACMAMRPackingFormat AMREncoderPackingFormat() const;
+
+  int16_t SetAMRDecoderPackingFormat(const ACMAMRPackingFormat packing_format);
+
+  ACMAMRPackingFormat AMRDecoderPackingFormat() const;
+
+ protected:
+  void DestructEncoderSafe();
+
+  int16_t InternalCreateEncoder();
+
+  void InternalDestructEncoderInst(void* ptr_inst);
+
+  int16_t SetBitRateSafe(const int32_t rate);
+
+  int16_t EnableDTX();
+
+  int16_t DisableDTX();
+
+  AMR_encinst_t_* encoder_inst_ptr_;
+  int16_t encoding_mode_;
+  int16_t encoding_rate_;
+  ACMAMRPackingFormat encoder_packing_format_;
+};
+
+}  // namespace webrtc
+
+#endif  // WEBRTC_MODULES_AUDIO_CODING_MAIN_SOURCE_ACM_AMR_H_
diff --git a/webrtc/modules/audio_coding/main/acm2/acm_amrwb.cc b/webrtc/modules/audio_coding/main/acm2/acm_amrwb.cc
new file mode 100644
index 0000000..1b82674
--- /dev/null
+++ b/webrtc/modules/audio_coding/main/acm2/acm_amrwb.cc
@@ -0,0 +1,316 @@
+/*
+ *  Copyright (c) 2012 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 "webrtc/modules/audio_coding/main/source/acm_amrwb.h"
+
+#ifdef WEBRTC_CODEC_AMRWB
+// NOTE! GSM AMR-wb is not included in the open-source package. The
+// following interface file is needed:
+#include "webrtc/modules/audio_coding/main/codecs/amrwb/interface/amrwb_interface.h"
+#include "webrtc/modules/audio_coding/main/interface/audio_coding_module_typedefs.h"
+#include "webrtc/modules/audio_coding/main/source/acm_common_defs.h"
+#include "webrtc/system_wrappers/interface/rw_lock_wrapper.h"
+#include "webrtc/system_wrappers/interface/trace.h"
+
+// The API in the header file should match the one below.
+//
+// int16_t WebRtcAmrWb_CreateEnc(AMRWB_encinst_t_** enc_inst);
+// int16_t WebRtcAmrWb_CreateDec(AMRWB_decinst_t_** dec_inst);
+// int16_t WebRtcAmrWb_FreeEnc(AMRWB_encinst_t_* enc_inst);
+// int16_t WebRtcAmrWb_FreeDec(AMRWB_decinst_t_* dec_inst);
+// int16_t WebRtcAmrWb_Encode(AMRWB_encinst_t_* enc_inst, int16_t* input,
+//                            int16_t len, int16_t* output, int16_t mode);
+// int16_t WebRtcAmrWb_EncoderInit(AMRWB_encinst_t_* enc_inst,
+//                                 int16_t dtx_mode);
+// int16_t WebRtcAmrWb_EncodeBitmode(AMRWB_encinst_t_* enc_inst,
+//                                    int format);
+// int16_t WebRtcAmrWb_Decode(AMRWB_decinst_t_* dec_inst);
+// int16_t WebRtcAmrWb_DecodePlc(AMRWB_decinst_t_* dec_inst);
+// int16_t WebRtcAmrWb_DecoderInit(AMRWB_decinst_t_* dec_inst);
+// int16_t WebRtcAmrWb_DecodeBitmode(AMRWB_decinst_t_* dec_inst,
+//                                   int format);
+#endif
+
+namespace webrtc {
+
+#ifndef WEBRTC_CODEC_AMRWB
+ACMAMRwb::ACMAMRwb(int16_t /* codec_id */)
+    : encoder_inst_ptr_(NULL),
+      encoding_mode_(-1),  // invalid value
+      encoding_rate_(0),   // invalid value
+      encoder_packing_format_(AMRBandwidthEfficient) {}
+
+ACMAMRwb::~ACMAMRwb() {}
+
+int16_t ACMAMRwb::InternalEncode(uint8_t* /* bitstream */,
+                                 int16_t* /* bitstream_len_byte */) {
+  return -1;
+}
+
+int16_t ACMAMRwb::EnableDTX() { return -1; }
+
+int16_t ACMAMRwb::DisableDTX() { return -1; }
+
+int16_t ACMAMRwb::InternalInitEncoder(
+    WebRtcACMCodecParams* /* codec_params */) {
+  return -1;
+}
+
+ACMGenericCodec* ACMAMRwb::CreateInstance(void) { return NULL; }
+
+int16_t ACMAMRwb::InternalCreateEncoder() { return -1; }
+
+void ACMAMRwb::DestructEncoderSafe() { return; }
+
+int16_t ACMAMRwb::SetBitRateSafe(const int32_t /* rate */) { return -1; }
+
+void ACMAMRwb::InternalDestructEncoderInst(void* /* ptr_inst */) { return; }
+
+int16_t ACMAMRwb::SetAMRwbEncoderPackingFormat(
+    ACMAMRPackingFormat /* packing_format */) {
+  return -1;
+}
+
+ACMAMRPackingFormat ACMAMRwb::AMRwbEncoderPackingFormat() const {
+  return AMRUndefined;
+}
+
+int16_t ACMAMRwb::SetAMRwbDecoderPackingFormat(
+    ACMAMRPackingFormat /* packing_format */) {
+  return -1;
+}
+
+ACMAMRPackingFormat ACMAMRwb::AMRwbDecoderPackingFormat() const {
+  return AMRUndefined;
+}
+
+#else     //===================== Actual Implementation =======================
+
+#define AMRWB_MODE_7k 0
+#define AMRWB_MODE_9k 1
+#define AMRWB_MODE_12k 2
+#define AMRWB_MODE_14k 3
+#define AMRWB_MODE_16k 4
+#define AMRWB_MODE_18k 5
+#define AMRWB_MODE_20k 6
+#define AMRWB_MODE_23k 7
+#define AMRWB_MODE_24k 8
+
+ACMAMRwb::ACMAMRwb(int16_t codec_id)
+    : encoder_inst_ptr_(NULL),
+      encoding_mode_(-1),  // invalid value
+      encoding_rate_(0) {  // invalid value
+  codec_id_ = codec_id;
+  has_internal_dtx_ = true;
+  encoder_packing_format_ = AMRBandwidthEfficient;
+  return;
+}
+
+ACMAMRwb::~ACMAMRwb() {
+  if (encoder_inst_ptr_ != NULL) {
+    WebRtcAmrWb_FreeEnc(encoder_inst_ptr_);
+    encoder_inst_ptr_ = NULL;
+  }
+  return;
+}
+
+int16_t ACMAMRwb::InternalEncode(uint8_t* bitstream,
+                                 int16_t* bitstream_len_byte) {
+  int16_t vad_decision = 1;
+  // sanity check, if the rate is set correctly. we might skip this
+  // sanity check. if rate is not set correctly, initialization flag
+  // should be false and should not be here.
+  if ((encoding_mode_ < AMRWB_MODE_7k) || (encoding_mode_ > AMRWB_MODE_24k)) {
+    *bitstream_len_byte = 0;
+    return -1;
+  }
+  *bitstream_len_byte = WebRtcAmrWb_Encode(
+      encoder_inst_ptr_, &in_audio_[in_audio_ix_read_], frame_len_smpl_,
+      reinterpret_cast<int16_t*>(bitstream), encoding_mode_);
+
+  // Update VAD, if internal DTX is used
+  if (has_internal_dtx_ && dtx_enabled_) {
+    if (*bitstream_len_byte <= (7 * frame_len_smpl_ / 160)) {
+      vad_decision = 0;
+    }
+    for (int16_t n = 0; n < MAX_FRAME_SIZE_10MSEC; n++) {
+      vad_label_[n] = vad_decision;
+    }
+  }
+  // increment the read index this tell the caller that how far
+  // we have gone forward in reading the audio buffer
+  in_audio_ix_read_ += frame_len_smpl_;
+  return *bitstream_len_byte;
+}
+
+int16_t ACMAMRwb::EnableDTX() {
+  if (dtx_enabled_) {
+    return 0;
+  } else if (encoder_exist_) {  // check if encoder exist
+    // enable DTX
+    if (WebRtcAmrWb_EncoderInit(encoder_inst_ptr_, 1) < 0) {
+      return -1;
+    }
+    dtx_enabled_ = true;
+    return 0;
+  } else {
+    return -1;
+  }
+}
+
+int16_t ACMAMRwb::DisableDTX() {
+  if (!dtx_enabled_) {
+    return 0;
+  } else if (encoder_exist_) {  // check if encoder exist
+    // disable DTX
+    if (WebRtcAmrWb_EncoderInit(encoder_inst_ptr_, 0) < 0) {
+      return -1;
+    }
+    dtx_enabled_ = false;
+    return 0;
+  } else {
+    // encoder doesn't exists, therefore disabling is harmless
+    return 0;
+  }
+}
+
+int16_t ACMAMRwb::InternalInitEncoder(WebRtcACMCodecParams* codec_params) {
+  // sanity check
+  if (encoder_inst_ptr_ == NULL) {
+    return -1;
+  }
+
+  int16_t status = SetBitRateSafe((codec_params->codec_inst).rate);
+  status += (WebRtcAmrWb_EncoderInit(encoder_inst_ptr_,
+                                     ((codec_params->enable_dtx) ? 1 : 0)) < 0)
+                ? -1
+                : 0;
+  status += (WebRtcAmrWb_EncodeBitmode(encoder_inst_ptr_,
+                                       encoder_packing_format_) < 0)
+                ? -1
+                : 0;
+  return (status < 0) ? -1 : 0;
+}
+
+ACMGenericCodec* ACMAMRwb::CreateInstance(void) { return NULL; }
+
+int16_t ACMAMRwb::InternalCreateEncoder() {
+  return WebRtcAmrWb_CreateEnc(&encoder_inst_ptr_);
+}
+
+void ACMAMRwb::DestructEncoderSafe() {
+  if (encoder_inst_ptr_ != NULL) {
+    WebRtcAmrWb_FreeEnc(encoder_inst_ptr_);
+    encoder_inst_ptr_ = NULL;
+  }
+  // there is no encoder set the following
+  encoder_exist_ = false;
+  encoder_initialized_ = false;
+  encoding_mode_ = -1;  // invalid value
+  encoding_rate_ = 0;
+}
+
+int16_t ACMAMRwb::SetBitRateSafe(const int32_t rate) {
+  switch (rate) {
+    case 7000: {
+      encoding_mode_ = AMRWB_MODE_7k;
+      encoding_rate_ = 7000;
+      break;
+    }
+    case 9000: {
+      encoding_mode_ = AMRWB_MODE_9k;
+      encoding_rate_ = 9000;
+      break;
+    }
+    case 12000: {
+      encoding_mode_ = AMRWB_MODE_12k;
+      encoding_rate_ = 12000;
+      break;
+    }
+    case 14000: {
+      encoding_mode_ = AMRWB_MODE_14k;
+      encoding_rate_ = 14000;
+      break;
+    }
+    case 16000: {
+      encoding_mode_ = AMRWB_MODE_16k;
+      encoding_rate_ = 16000;
+      break;
+    }
+    case 18000: {
+      encoding_mode_ = AMRWB_MODE_18k;
+      encoding_rate_ = 18000;
+      break;
+    }
+    case 20000: {
+      encoding_mode_ = AMRWB_MODE_20k;
+      encoding_rate_ = 20000;
+      break;
+    }
+    case 23000: {
+      encoding_mode_ = AMRWB_MODE_23k;
+      encoding_rate_ = 23000;
+      break;
+    }
+    case 24000: {
+      encoding_mode_ = AMRWB_MODE_24k;
+      encoding_rate_ = 24000;
+      break;
+    }
+    default: {
+      return -1;
+    }
+  }
+  return 0;
+}
+
+void ACMAMRwb::InternalDestructEncoderInst(void* ptr_inst) {
+  if (ptr_inst != NULL) {
+    WebRtcAmrWb_FreeEnc(static_cast<AMRWB_encinst_t_*>(ptr_inst));
+  }
+  return;
+}
+
+int16_t ACMAMRwb::SetAMRwbEncoderPackingFormat(
+    ACMAMRPackingFormat packing_format) {
+  if ((packing_format != AMRBandwidthEfficient) &&
+      (packing_format != AMROctetAlligned) &&
+      (packing_format != AMRFileStorage)) {
+    WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, unique_id_,
+                 "Invalid AMRwb encoder packing-format.");
+    return -1;
+  } else {
+    if (WebRtcAmrWb_EncodeBitmode(encoder_inst_ptr_, packing_format) < 0) {
+      return -1;
+    } else {
+      encoder_packing_format_ = packing_format;
+      return 0;
+    }
+  }
+}
+
+ACMAMRPackingFormat ACMAMRwb::AMRwbEncoderPackingFormat() const {
+  return encoder_packing_format_;
+}
+
+int16_t ACMAMRwb::SetAMRwbDecoderPackingFormat(
+    ACMAMRPackingFormat packing_format) {
+  // Not implemented.
+  return -1;
+}
+
+ACMAMRPackingFormat ACMAMRwb::AMRwbDecoderPackingFormat() const {
+  // Not implemented.
+  return AMRUndefined;
+}
+
+#endif
+
+}  // namespace webrtc
diff --git a/webrtc/modules/audio_coding/main/acm2/acm_amrwb.h b/webrtc/modules/audio_coding/main/acm2/acm_amrwb.h
new file mode 100644
index 0000000..550bab2
--- /dev/null
+++ b/webrtc/modules/audio_coding/main/acm2/acm_amrwb.h
@@ -0,0 +1,66 @@
+/*
+ *  Copyright (c) 2012 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_MAIN_SOURCE_ACM_AMRWB_H_
+#define WEBRTC_MODULES_AUDIO_CODING_MAIN_SOURCE_ACM_AMRWB_H_
+
+#include "webrtc/modules/audio_coding/main/source/acm_generic_codec.h"
+
+// forward declaration
+struct AMRWB_encinst_t_;
+struct AMRWB_decinst_t_;
+
+namespace webrtc {
+
+class ACMAMRwb : public ACMGenericCodec {
+ public:
+  explicit ACMAMRwb(int16_t codec_id);
+  ~ACMAMRwb();
+
+  // for FEC
+  ACMGenericCodec* CreateInstance(void);
+
+  int16_t InternalEncode(uint8_t* bitstream, int16_t* bitstream_len_byte);
+
+  int16_t InternalInitEncoder(WebRtcACMCodecParams* codec_params);
+
+  int16_t SetAMRwbEncoderPackingFormat(
+      const ACMAMRPackingFormat packing_format);
+
+  ACMAMRPackingFormat AMRwbEncoderPackingFormat() const;
+
+  int16_t SetAMRwbDecoderPackingFormat(
+      const ACMAMRPackingFormat packing_format);
+
+  ACMAMRPackingFormat AMRwbDecoderPackingFormat() const;
+
+ protected:
+  void DestructEncoderSafe();
+
+  int16_t InternalCreateEncoder();
+
+  void InternalDestructEncoderInst(void* ptr_inst);
+
+  int16_t SetBitRateSafe(const int32_t rate);
+
+  int16_t EnableDTX();
+
+  int16_t DisableDTX();
+
+  AMRWB_encinst_t_* encoder_inst_ptr_;
+
+  int16_t encoding_mode_;
+  int16_t encoding_rate_;
+  ACMAMRPackingFormat encoder_packing_format_;
+};
+
+}  // namespace webrtc
+
+#endif  // WEBRTC_MODULES_AUDIO_CODING_MAIN_SOURCE_ACM_AMRWB_H_
diff --git a/webrtc/modules/audio_coding/main/acm2/acm_celt.cc b/webrtc/modules/audio_coding/main/acm2/acm_celt.cc
new file mode 100644
index 0000000..6f2c807
--- /dev/null
+++ b/webrtc/modules/audio_coding/main/acm2/acm_celt.cc
@@ -0,0 +1,191 @@
+/*
+ *  Copyright (c) 2012 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 "webrtc/modules/audio_coding/main/source/acm_celt.h"
+
+#ifdef WEBRTC_CODEC_CELT
+// NOTE! Celt is not included in the open-source package. Modify this file or
+// your codec API to match the function call and name of used CELT API file.
+#include "webrtc/modules/audio_coding/codecs/celt/include/celt_interface.h"
+#include "webrtc/modules/audio_coding/main/source/acm_common_defs.h"
+#include "webrtc/system_wrappers/interface/trace.h"
+#endif
+
+namespace webrtc {
+
+#ifndef WEBRTC_CODEC_CELT
+
+ACMCELT::ACMCELT(int16_t /* codec_id */)
+    : enc_inst_ptr_(NULL),
+      sampling_freq_(0),
+      bitrate_(0),
+      channels_(1) {
+  return;
+}
+
+ACMCELT::~ACMCELT() {
+  return;
+}
+
+int16_t ACMCELT::InternalEncode(uint8_t* /* bitstream */,
+                                int16_t* /* bitstream_len_byte */) {
+  return -1;
+}
+
+int16_t ACMCELT::InternalInitEncoder(WebRtcACMCodecParams* /* codec_params */) {
+  return -1;
+}
+
+ACMGenericCodec* ACMCELT::CreateInstance(void) {
+  return NULL;
+}
+
+int16_t ACMCELT::InternalCreateEncoder() {
+  return -1;
+}
+
+void ACMCELT::DestructEncoderSafe() {
+  return;
+}
+
+void ACMCELT::InternalDestructEncoderInst(void* /* ptr_inst */) {
+  return;
+}
+
+int16_t ACMCELT::SetBitRateSafe(const int32_t /*rate*/) {
+  return -1;
+}
+
+#else  //===================== Actual Implementation =======================
+
+ACMCELT::ACMCELT(int16_t codec_id)
+    : enc_inst_ptr_(NULL),
+      sampling_freq_(32000),  // Default sampling frequency.
+      bitrate_(64000),  // Default rate.
+      channels_(1) {  // Default send mono.
+  // TODO(tlegrand): remove later when ACMGenericCodec has a new constructor.
+  codec_id_ = codec_id;
+
+  return;
+}
+
+ACMCELT::~ACMCELT() {
+  if (enc_inst_ptr_ != NULL) {
+    WebRtcCelt_FreeEnc(enc_inst_ptr_);
+    enc_inst_ptr_ = NULL;
+  }
+  return;
+}
+
+int16_t ACMCELT::InternalEncode(uint8_t* bitstream,
+                                int16_t* bitstream_len_byte) {
+  *bitstream_len_byte = 0;
+
+  // Call Encoder.
+  *bitstream_len_byte = WebRtcCelt_Encode(enc_inst_ptr_,
+                                          &in_audio_[in_audio_ix_read_],
+                                          bitstream);
+
+  // Increment the read index this tell the caller that how far
+  // we have gone forward in reading the audio buffer.
+  in_audio_ix_read_ += frame_len_smpl_ * channels_;
+
+  if (*bitstream_len_byte < 0) {
+    // Error reported from the encoder.
+    WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, unique_id_,
+                 "InternalEncode: Encode error for Celt");
+    *bitstream_len_byte = 0;
+    return -1;
+  }
+
+  return *bitstream_len_byte;
+}
+
+int16_t ACMCELT::InternalInitEncoder(WebRtcACMCodecParams* codec_params) {
+  // Set bitrate and check that it is within the valid range.
+  int16_t status = SetBitRateSafe((codec_params->codec_inst).rate);
+  if (status < 0) {
+    return -1;
+  }
+
+  // If number of channels changed we need to re-create memory.
+  if (codec_params->codec_inst.channels != channels_) {
+    WebRtcCelt_FreeEnc(enc_inst_ptr_);
+    enc_inst_ptr_ = NULL;
+    // Store new number of channels.
+    channels_ = codec_params->codec_inst.channels;
+    if (WebRtcCelt_CreateEnc(&enc_inst_ptr_, channels_) < 0) {
+      return -1;
+    }
+  }
+
+  // Initiate encoder.
+  if (WebRtcCelt_EncoderInit(enc_inst_ptr_, channels_, bitrate_) >= 0) {
+    return 0;
+  } else {
+    return -1;
+  }
+}
+
+ACMGenericCodec* ACMCELT::CreateInstance(void) {
+  return NULL;
+}
+
+int16_t ACMCELT::InternalCreateEncoder() {
+  if (WebRtcCelt_CreateEnc(&enc_inst_ptr_, num_channels_) < 0) {
+    WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, unique_id_,
+                 "InternalCreateEncoder: create encoder failed for Celt");
+    return -1;
+  }
+  channels_ = num_channels_;
+  return 0;
+}
+
+void ACMCELT::DestructEncoderSafe() {
+  encoder_exist_ = false;
+  encoder_initialized_ = false;
+  if (enc_inst_ptr_ != NULL) {
+    WebRtcCelt_FreeEnc(enc_inst_ptr_);
+    enc_inst_ptr_ = NULL;
+  }
+}
+
+void ACMCELT::InternalDestructEncoderInst(void* ptr_inst) {
+  if (ptr_inst != NULL) {
+    WebRtcCelt_FreeEnc(static_cast<CELT_encinst_t*>(ptr_inst));
+  }
+  return;
+}
+
+int16_t ACMCELT::SetBitRateSafe(const int32_t rate) {
+  // Check that rate is in the valid range.
+  if ((rate >= 48000) && (rate <= 128000)) {
+    // Store new rate.
+    bitrate_ = rate;
+
+    // Initiate encoder with new rate.
+    if (WebRtcCelt_EncoderInit(enc_inst_ptr_, channels_, bitrate_) >= 0) {
+      return 0;
+    } else {
+      WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, unique_id_,
+                   "SetBitRateSafe: Failed to initiate Celt with rate %d",
+                   rate);
+      return -1;
+    }
+  } else {
+    WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, unique_id_,
+                 "SetBitRateSafe: Invalid rate Celt, %d", rate);
+    return -1;
+  }
+}
+
+#endif
+
+}  // namespace webrtc
diff --git a/webrtc/modules/audio_coding/main/acm2/acm_celt.h b/webrtc/modules/audio_coding/main/acm2/acm_celt.h
new file mode 100644
index 0000000..b90a4e8
--- /dev/null
+++ b/webrtc/modules/audio_coding/main/acm2/acm_celt.h
@@ -0,0 +1,50 @@
+/*
+ *  Copyright (c) 2012 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_MAIN_SOURCE_ACM_CELT_H_
+#define WEBRTC_MODULES_AUDIO_CODING_MAIN_SOURCE_ACM_CELT_H_
+
+#include "webrtc/modules/audio_coding/main/source/acm_generic_codec.h"
+
+// forward declaration
+struct CELT_encinst_t_;
+struct CELT_decinst_t_;
+
+namespace webrtc {
+
+class ACMCELT : public ACMGenericCodec {
+ public:
+  explicit ACMCELT(int16_t codec_id);
+  ~ACMCELT();
+
+  ACMGenericCodec* CreateInstance(void);
+
+  int16_t InternalEncode(uint8_t* bitstream, int16_t* bitstream_len_byte);
+
+  int16_t InternalInitEncoder(WebRtcACMCodecParams *codec_params);
+
+ protected:
+  void DestructEncoderSafe();
+
+  int16_t InternalCreateEncoder();
+
+  void InternalDestructEncoderInst(void* ptr_inst);
+
+  int16_t SetBitRateSafe(const int32_t rate);
+
+  CELT_encinst_t_* enc_inst_ptr_;
+  uint16_t sampling_freq_;
+  int32_t bitrate_;
+  uint16_t channels_;
+};
+
+}  // namespace webrtc
+
+#endif  // WEBRTC_MODULES_AUDIO_CODING_MAIN_SOURCE_ACM_CELT_H_
diff --git a/webrtc/modules/audio_coding/main/acm2/acm_cng.cc b/webrtc/modules/audio_coding/main/acm2/acm_cng.cc
new file mode 100644
index 0000000..b04fd6a
--- /dev/null
+++ b/webrtc/modules/audio_coding/main/acm2/acm_cng.cc
@@ -0,0 +1,79 @@
+/*
+ *  Copyright (c) 2012 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 "webrtc/modules/audio_coding/main/source/acm_cng.h"
+
+#include "webrtc/modules/audio_coding/codecs/cng/include/webrtc_cng.h"
+#include "webrtc/modules/audio_coding/main/source/acm_codec_database.h"
+#include "webrtc/modules/audio_coding/main/source/acm_common_defs.h"
+#include "webrtc/system_wrappers/interface/trace.h"
+
+namespace webrtc {
+
+ACMCNG::ACMCNG(int16_t codec_id) {
+  encoder_inst_ptr_ = NULL;
+  codec_id_ = codec_id;
+  samp_freq_hz_ = ACMCodecDB::CodecFreq(codec_id_);
+  return;
+}
+
+ACMCNG::~ACMCNG() {
+  if (encoder_inst_ptr_ != NULL) {
+    WebRtcCng_FreeEnc(encoder_inst_ptr_);
+    encoder_inst_ptr_ = NULL;
+  }
+  return;
+}
+
+// CNG is not like a regular encoder, this function
+// should not be called normally
+// instead the following function is called from inside
+// ACMGenericCodec::ProcessFrameVADDTX
+int16_t ACMCNG::InternalEncode(uint8_t* /* bitstream */,
+                               int16_t* /* bitstream_len_byte */) {
+  return -1;
+}
+
+// CNG is not like a regular encoder,
+// this function should not be called normally
+// instead the following function is called from inside
+// ACMGenericCodec::ProcessFrameVADDTX
+int16_t ACMCNG::InternalInitEncoder(WebRtcACMCodecParams* /* codec_params */) {
+  return -1;
+}
+
+ACMGenericCodec* ACMCNG::CreateInstance(void) { return NULL; }
+
+int16_t ACMCNG::InternalCreateEncoder() {
+  if (WebRtcCng_CreateEnc(&encoder_inst_ptr_) < 0) {
+    encoder_inst_ptr_ = NULL;
+    return -1;
+  } else {
+    return 0;
+  }
+}
+
+void ACMCNG::DestructEncoderSafe() {
+  if (encoder_inst_ptr_ != NULL) {
+    WebRtcCng_FreeEnc(encoder_inst_ptr_);
+    encoder_inst_ptr_ = NULL;
+  }
+  encoder_exist_ = false;
+  encoder_initialized_ = false;
+}
+
+void ACMCNG::InternalDestructEncoderInst(void* ptr_inst) {
+  if (ptr_inst != NULL) {
+    WebRtcCng_FreeEnc(static_cast<CNG_enc_inst*>(ptr_inst));
+  }
+  return;
+}
+
+}  // namespace webrtc
diff --git a/webrtc/modules/audio_coding/main/acm2/acm_cng.h b/webrtc/modules/audio_coding/main/acm2/acm_cng.h
new file mode 100644
index 0000000..2ea4f02
--- /dev/null
+++ b/webrtc/modules/audio_coding/main/acm2/acm_cng.h
@@ -0,0 +1,56 @@
+/*
+ *  Copyright (c) 2012 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_MAIN_SOURCE_ACM_CNG_H_
+#define WEBRTC_MODULES_AUDIO_CODING_MAIN_SOURCE_ACM_CNG_H_
+
+#include "webrtc/modules/audio_coding/main/source/acm_generic_codec.h"
+
+// forward declaration
+struct WebRtcCngEncInst;
+struct WebRtcCngDecInst;
+
+namespace webrtc {
+
+class ACMCNG: public ACMGenericCodec {
+ public:
+  explicit ACMCNG(int16_t codec_id);
+  ~ACMCNG();
+
+  // for FEC
+  ACMGenericCodec* CreateInstance(void);
+
+  int16_t InternalEncode(uint8_t* bitstream,
+                         int16_t* bitstream_len_byte);
+
+  int16_t InternalInitEncoder(WebRtcACMCodecParams *codec_params);
+
+ protected:
+  void DestructEncoderSafe();
+
+  int16_t InternalCreateEncoder();
+
+  void InternalDestructEncoderInst(void* ptr_inst);
+
+  int16_t EnableDTX() {
+    return -1;
+  }
+
+  int16_t DisableDTX() {
+    return -1;
+  }
+
+  WebRtcCngEncInst* encoder_inst_ptr_;
+  uint16_t samp_freq_hz_;
+};
+
+}  // namespace webrtc
+
+#endif  // WEBRTC_MODULES_AUDIO_CODING_MAIN_SOURCE_ACM_CNG_H_
diff --git a/webrtc/modules/audio_coding/main/acm2/acm_codec_database.cc b/webrtc/modules/audio_coding/main/acm2/acm_codec_database.cc
new file mode 100644
index 0000000..08080d1
--- /dev/null
+++ b/webrtc/modules/audio_coding/main/acm2/acm_codec_database.cc
@@ -0,0 +1,964 @@
+/*
+ *  Copyright (c) 2012 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.
+ */
+
+/*
+ * This file generates databases with information about all supported audio
+ * codecs.
+ */
+
+// TODO(tlegrand): Change constant input pointers in all functions to constant
+// references, where appropriate.
+#include "webrtc/modules/audio_coding/main/source/acm_codec_database.h"
+
+#include <assert.h>
+
+#include "webrtc/modules/audio_coding/main/source/acm_common_defs.h"
+#include "webrtc/modules/audio_coding/neteq4/interface/audio_decoder.h"
+#include "webrtc/system_wrappers/interface/trace.h"
+
+// Includes needed to create the codecs.
+// G711, PCM mu-law and A-law
+#include "webrtc/modules/audio_coding/main/source/acm_pcma.h"
+#include "webrtc/modules/audio_coding/main/source/acm_pcmu.h"
+#include "webrtc/modules/audio_coding/codecs/g711/include/g711_interface.h"
+// CNG
+#include "webrtc/modules/audio_coding/codecs/cng/include/webrtc_cng.h"
+#include "webrtc/modules/audio_coding/main/source/acm_cng.h"
+#ifdef WEBRTC_CODEC_ISAC
+#include "webrtc/modules/audio_coding/codecs/isac/main/interface/isac.h"
+#endif
+#ifdef WEBRTC_CODEC_ISACFX
+#include "webrtc/modules/audio_coding/codecs/isac/fix/interface/isacfix.h"
+#endif
+#if (defined WEBRTC_CODEC_ISACFX) || (defined WEBRTC_CODEC_ISAC)
+#include "webrtc/modules/audio_coding/main/source/acm_isac.h"
+#include "webrtc/modules/audio_coding/main/source/acm_isac_macros.h"
+#endif
+#ifdef WEBRTC_CODEC_PCM16
+#include "webrtc/modules/audio_coding/codecs/pcm16b/include/pcm16b.h"
+#include "webrtc/modules/audio_coding/main/source/acm_pcm16b.h"
+#endif
+#ifdef WEBRTC_CODEC_ILBC
+#include "webrtc/modules/audio_coding/codecs/ilbc/interface/ilbc.h"
+#include "webrtc/modules/audio_coding/main/source/acm_ilbc.h"
+#endif
+#ifdef WEBRTC_CODEC_AMR
+#include "webrtc/modules/audio_coding/codecs/amr/include/amr_interface.h"
+#include "webrtc/modules/audio_coding/main/source/acm_amr.h"
+#endif
+#ifdef WEBRTC_CODEC_AMRWB
+#include "webrtc/modules/audio_coding/codecs/amrwb/include/amrwb_interface.h"
+#include "webrtc/modules/audio_coding/main/source/acm_amrwb.h"
+#endif
+#ifdef WEBRTC_CODEC_CELT
+#include "webrtc/modules/audio_coding/codecs/celt/include/celt_interface.h"
+#include "webrtc/modules/audio_coding/main/source/acm_celt.h"
+#endif
+#ifdef WEBRTC_CODEC_G722
+#include "webrtc/modules/audio_coding/codecs/g722/include/g722_interface.h"
+#include "webrtc/modules/audio_coding/main/source/acm_g722.h"
+#endif
+#ifdef WEBRTC_CODEC_G722_1
+#include "webrtc/modules/audio_coding/codecs/g7221/include/g7221_interface.h"
+#include "webrtc/modules/audio_coding/main/source/acm_g7221.h"
+#endif
+#ifdef WEBRTC_CODEC_G722_1C
+#include "webrtc/modules/audio_coding/codecs/g7221c/include/g7221c_interface.h"
+#include "webrtc/modules/audio_coding/main/source/acm_g7221c.h"
+#endif
+#ifdef WEBRTC_CODEC_G729
+#include "webrtc/modules/audio_coding/codecs/g729/include/g729_interface.h"
+#include "webrtc/modules/audio_coding/main/source/acm_g729.h"
+#endif
+#ifdef WEBRTC_CODEC_G729_1
+#include "webrtc/modules/audio_coding/codecs/g7291/include/g7291_interface.h"
+#include "webrtc/modules/audio_coding/main/source/acm_g7291.h"
+#endif
+#ifdef WEBRTC_CODEC_GSMFR
+#include "webrtc/modules/audio_coding/codecs/gsmfr/include/gsmfr_interface.h"
+#include "webrtc/modules/audio_coding/main/source/acm_gsmfr.h"
+#endif
+#ifdef WEBRTC_CODEC_OPUS
+#include "webrtc/modules/audio_coding/codecs/opus/interface/opus_interface.h"
+#include "webrtc/modules/audio_coding/main/source/acm_opus.h"
+#endif
+#ifdef WEBRTC_CODEC_SPEEX
+#include "webrtc/modules/audio_coding/codecs/speex/include/speex_interface.h"
+#include "webrtc/modules/audio_coding/main/source/acm_speex.h"
+#endif
+#ifdef WEBRTC_CODEC_AVT
+#include "webrtc/modules/audio_coding/main/source/acm_dtmf_playout.h"
+#endif
+#ifdef WEBRTC_CODEC_RED
+#include "webrtc/modules/audio_coding/main/source/acm_red.h"
+#endif
+
+namespace webrtc {
+
+// We dynamically allocate some of the dynamic payload types to the defined
+// codecs. Note! There are a limited number of payload types. If more codecs
+// are defined they will receive reserved fixed payload types (values 69-95).
+const int kDynamicPayloadtypes[ACMCodecDB::kMaxNumCodecs] = {
+  107, 108, 109, 111, 112, 113, 114, 115, 116, 117, 92,
+  91,  90,  89,  88,  87,  86,  85,  84,  83,  82,  81, 80,
+  79,  78,  77,  76,  75,  74,  73,  72,  71,  70,  69, 68,
+  67, 66, 65
+};
+
+// Creates database with all supported codecs at compile time.
+// Each entry needs the following parameters in the given order:
+// payload type, name, sampling frequency, packet size in samples,
+// number of channels, and default rate.
+#if (defined(WEBRTC_CODEC_AMR) || defined(WEBRTC_CODEC_AMRWB) || \
+    defined(WEBRTC_CODEC_CELT) || defined(WEBRTC_CODEC_G722_1) || \
+    defined(WEBRTC_CODEC_G722_1C) || defined(WEBRTC_CODEC_G729_1) || \
+    defined(WEBRTC_CODEC_PCM16) || defined(WEBRTC_CODEC_SPEEX))
+static int count_database = 0;
+#endif
+
+const CodecInst ACMCodecDB::database_[] = {
+#if (defined(WEBRTC_CODEC_ISAC) || defined(WEBRTC_CODEC_ISACFX))
+  {103, "ISAC", 16000, kIsacPacSize480, 1, kIsacWbDefaultRate},
+# if (defined(WEBRTC_CODEC_ISAC))
+  {104, "ISAC", 32000, kIsacPacSize960, 1, kIsacSwbDefaultRate},
+  {105, "ISAC", 48000, kIsacPacSize1440, 1, kIsacSwbDefaultRate},
+# endif
+#endif
+#ifdef WEBRTC_CODEC_PCM16
+  // Mono
+  {kDynamicPayloadtypes[count_database++], "L16", 8000, 80, 1, 128000},
+  {kDynamicPayloadtypes[count_database++], "L16", 16000, 160, 1, 256000},
+  {kDynamicPayloadtypes[count_database++], "L16", 32000, 320, 1, 512000},
+  // Stereo
+  {kDynamicPayloadtypes[count_database++], "L16", 8000, 80, 2, 128000},
+  {kDynamicPayloadtypes[count_database++], "L16", 16000, 160, 2, 256000},
+  {kDynamicPayloadtypes[count_database++], "L16", 32000, 320, 2, 512000},
+#endif
+  // G.711, PCM mu-law and A-law.
+  // Mono
+  {0, "PCMU", 8000, 160, 1, 64000},
+  {8, "PCMA", 8000, 160, 1, 64000},
+  // Stereo
+  {110, "PCMU", 8000, 160, 2, 64000},
+  {118, "PCMA", 8000, 160, 2, 64000},
+#ifdef WEBRTC_CODEC_ILBC
+  {102, "ILBC", 8000, 240, 1, 13300},
+#endif
+#ifdef WEBRTC_CODEC_AMR
+  {kDynamicPayloadtypes[count_database++], "AMR", 8000, 160, 1, 12200},
+#endif
+#ifdef WEBRTC_CODEC_AMRWB
+  {kDynamicPayloadtypes[count_database++], "AMR-WB", 16000, 320, 1, 20000},
+#endif
+#ifdef WEBRTC_CODEC_CELT
+  // Mono
+  {kDynamicPayloadtypes[count_database++], "CELT", 32000, 640, 1, 64000},
+  // Stereo
+  {kDynamicPayloadtypes[count_database++], "CELT", 32000, 640, 2, 64000},
+#endif
+#ifdef WEBRTC_CODEC_G722
+  // Mono
+  {9, "G722", 16000, 320, 1, 64000},
+  // Stereo
+  {119, "G722", 16000, 320, 2, 64000},
+#endif
+#ifdef WEBRTC_CODEC_G722_1
+  {kDynamicPayloadtypes[count_database++], "G7221", 16000, 320, 1, 32000},
+  {kDynamicPayloadtypes[count_database++], "G7221", 16000, 320, 1, 24000},
+  {kDynamicPayloadtypes[count_database++], "G7221", 16000, 320, 1, 16000},
+#endif
+#ifdef WEBRTC_CODEC_G722_1C
+  {kDynamicPayloadtypes[count_database++], "G7221", 32000, 640, 1, 48000},
+  {kDynamicPayloadtypes[count_database++], "G7221", 32000, 640, 1, 32000},
+  {kDynamicPayloadtypes[count_database++], "G7221", 32000, 640, 1, 24000},
+#endif
+#ifdef WEBRTC_CODEC_G729
+  {18, "G729", 8000, 240, 1, 8000},
+#endif
+#ifdef WEBRTC_CODEC_G729_1
+  {kDynamicPayloadtypes[count_database++], "G7291", 16000, 320, 1, 32000},
+#endif
+#ifdef WEBRTC_CODEC_GSMFR
+  {3, "GSM", 8000, 160, 1, 13200},
+#endif
+#ifdef WEBRTC_CODEC_OPUS
+  // Opus internally supports 48, 24, 16, 12, 8 kHz.
+  // Mono and stereo.
+  {120, "opus", 48000, 960, 2, 64000},
+#endif
+#ifdef WEBRTC_CODEC_SPEEX
+  {kDynamicPayloadtypes[count_database++], "speex", 8000, 160, 1, 11000},
+  {kDynamicPayloadtypes[count_database++], "speex", 16000, 320, 1, 22000},
+#endif
+  // Comfort noise for four different sampling frequencies.
+  {13, "CN", 8000, 240, 1, 0},
+  {98, "CN", 16000, 480, 1, 0},
+  {99, "CN", 32000, 960, 1, 0},
+  {100, "CN", 48000, 1440, 1, 0},
+#ifdef WEBRTC_CODEC_AVT
+  {106, "telephone-event", 8000, 240, 1, 0},
+#endif
+#ifdef WEBRTC_CODEC_RED
+  {127, "red", 8000, 0, 1, 0},
+#endif
+  // To prevent compile errors due to trailing commas.
+  {-1, "Null", -1, -1, -1, -1}
+};
+
+// Create database with all codec settings at compile time.
+// Each entry needs the following parameters in the given order:
+// Number of allowed packet sizes, a vector with the allowed packet sizes,
+// Basic block samples, max number of channels that are supported.
+const ACMCodecDB::CodecSettings ACMCodecDB::codec_settings_[] = {
+#if (defined(WEBRTC_CODEC_ISAC) || defined(WEBRTC_CODEC_ISACFX))
+    {2, {kIsacPacSize480, kIsacPacSize960}, 0, 1, true},
+# if (defined(WEBRTC_CODEC_ISAC))
+    {1, {kIsacPacSize960}, 0, 1, false},
+    {1, {kIsacPacSize1440}, 0, 1, true},
+# endif
+#endif
+#ifdef WEBRTC_CODEC_PCM16
+    // Mono
+    {4, {80, 160, 240, 320}, 0, 2, false},
+    {4, {160, 320, 480, 640}, 0, 2, false},
+    {2, {320, 640}, 0, 2, false},
+    // Stereo
+    {4, {80, 160, 240, 320}, 0, 2, false},
+    {4, {160, 320, 480, 640}, 0, 2, false},
+    {2, {320, 640}, 0, 2},
+#endif
+    // G.711, PCM mu-law and A-law.
+    // Mono
+    {6, {80, 160, 240, 320, 400, 480}, 0, 2, false},
+    {6, {80, 160, 240, 320, 400, 480}, 0, 2, false},
+    // Stereo
+    {6, {80, 160, 240, 320, 400, 480}, 0, 2, false},
+    {6, {80, 160, 240, 320, 400, 480}, 0, 2, false},
+#ifdef WEBRTC_CODEC_ILBC
+    {4, {160, 240, 320, 480}, 0, 1, false},
+#endif
+#ifdef WEBRTC_CODEC_AMR
+    {3, {160, 320, 480}, 0, 1, true},
+#endif
+#ifdef WEBRTC_CODEC_AMRWB
+    {3, {320, 640, 960}, 0, 1, true},
+#endif
+#ifdef WEBRTC_CODEC_CELT
+    // Mono
+    {1, {640}, 0, 2, false},
+    // Stereo
+    {1, {640}, 0, 2, false},
+#endif
+#ifdef WEBRTC_CODEC_G722
+    // Mono
+    {6, {160, 320, 480, 640, 800, 960}, 0, 2, false},
+    // Stereo
+    {6, {160, 320, 480, 640, 800, 960}, 0, 2, false},
+#endif
+#ifdef WEBRTC_CODEC_G722_1
+    {1, {320}, 320, 1, false},
+    {1, {320}, 320, 1, false},
+    {1, {320}, 320, 1, false},
+#endif
+#ifdef WEBRTC_CODEC_G722_1C
+    {1, {640}, 640, 1, false},
+    {1, {640}, 640, 1, false},
+    {1, {640}, 640, 1, false},
+#endif
+#ifdef WEBRTC_CODEC_G729
+    {6, {80, 160, 240, 320, 400, 480}, 0, 1, false},
+#endif
+#ifdef WEBRTC_CODEC_G729_1
+    {3, {320, 640, 960}, 0, 1, false},
+#endif
+#ifdef WEBRTC_CODEC_GSMFR
+    {3, {160, 320, 480}, 160, 1, false},
+#endif
+#ifdef WEBRTC_CODEC_OPUS
+    // Opus supports frames shorter than 10ms,
+    // but it doesn't help us to use them.
+    // Mono and stereo.
+    {1, {960}, 0, 2, false},
+#endif
+#ifdef WEBRTC_CODEC_SPEEX
+    {3, {160, 320, 480}, 0, 1, false},
+    {3, {320, 640, 960}, 0, 1, false},
+#endif
+    // Comfort noise for three different sampling frequencies.
+    {1, {240}, 240, 1, false},
+    {1, {480}, 480, 1, false},
+    {1, {960}, 960, 1, false},
+    {1, {1440}, 1440, 1, false},
+#ifdef WEBRTC_CODEC_AVT
+    {1, {240}, 240, 1, false},
+#endif
+#ifdef WEBRTC_CODEC_RED
+    {1, {0}, 0, 1, false},
+#endif
+    // To prevent compile errors due to trailing commas.
+    {-1, {-1}, -1, -1, false}
+};
+
+// Create a database of all NetEQ decoders at compile time.
+const NetEqDecoder ACMCodecDB::neteq_decoders_[] = {
+#if (defined(WEBRTC_CODEC_ISAC) || defined(WEBRTC_CODEC_ISACFX))
+    kDecoderISAC,
+# if (defined(WEBRTC_CODEC_ISAC))
+    kDecoderISACswb,
+    kDecoderISACfb,
+# endif
+#endif
+#ifdef WEBRTC_CODEC_PCM16
+    // Mono
+    kDecoderPCM16B,
+    kDecoderPCM16Bwb,
+    kDecoderPCM16Bswb32kHz,
+    // Stereo
+    kDecoderPCM16B_2ch,
+    kDecoderPCM16Bwb_2ch,
+    kDecoderPCM16Bswb32kHz_2ch,
+#endif
+    // G.711, PCM mu-las and A-law.
+    // Mono
+    kDecoderPCMu,
+    kDecoderPCMa,
+    // Stereo
+    kDecoderPCMu_2ch,
+    kDecoderPCMa_2ch,
+#ifdef WEBRTC_CODEC_ILBC
+    kDecoderILBC,
+#endif
+#ifdef WEBRTC_CODEC_AMR
+    kDecoderAMR,
+#endif
+#ifdef WEBRTC_CODEC_AMRWB
+    kDecoderAMRWB,
+#endif
+#ifdef WEBRTC_CODEC_CELT
+    // Mono
+    kDecoderCELT_32,
+    // Stereo
+    kDecoderCELT_32_2ch,
+#endif
+#ifdef WEBRTC_CODEC_G722
+    // Mono
+    kDecoderG722,
+    // Stereo
+    kDecoderG722_2ch,
+#endif
+#ifdef WEBRTC_CODEC_G722_1
+    kDecoderG722_1_32,
+    kDecoderG722_1_24,
+    kDecoderG722_1_16,
+#endif
+#ifdef WEBRTC_CODEC_G722_1C
+    kDecoderG722_1C_48,
+    kDecoderG722_1C_32,
+    kDecoderG722_1C_24,
+#endif
+#ifdef WEBRTC_CODEC_G729
+    kDecoderG729,
+#endif
+#ifdef WEBRTC_CODEC_G729_1
+    kDecoderG729_1,
+#endif
+#ifdef WEBRTC_CODEC_GSMFR
+    kDecoderGSMFR,
+#endif
+#ifdef WEBRTC_CODEC_OPUS
+    // Mono and stereo.
+    kDecoderOpus,
+#endif
+#ifdef WEBRTC_CODEC_SPEEX
+    kDecoderSPEEX_8,
+    kDecoderSPEEX_16,
+#endif
+    // Comfort noise for three different sampling frequencies.
+    kDecoderCNGnb,
+    kDecoderCNGwb,
+    kDecoderCNGswb32kHz,
+    kDecoderCNGswb48kHz
+#ifdef WEBRTC_CODEC_AVT
+    , kDecoderAVT
+#endif
+#ifdef WEBRTC_CODEC_RED
+    , kDecoderRED
+#endif
+};
+
+// Get codec information from database.
+// TODO(tlegrand): replace memcpy with a pointer to the data base memory.
+int ACMCodecDB::Codec(int codec_id, CodecInst* codec_inst) {
+  // Error check to see that codec_id is not out of bounds.
+  if ((codec_id < 0) || (codec_id >= kNumCodecs)) {
+    return -1;
+  }
+
+  // Copy database information for the codec to the output.
+  memcpy(codec_inst, &database_[codec_id], sizeof(CodecInst));
+
+  return 0;
+}
+
+// Enumerator for error codes when asking for codec database id.
+enum {
+  kInvalidCodec = -10,
+  kInvalidPayloadtype = -30,
+  kInvalidPacketSize = -40,
+  kInvalidRate = -50
+};
+
+// Gets the codec id number from the database. If there is some mismatch in
+// the codec settings, the function will return an error code.
+// NOTE! The first mismatch found will generate the return value.
+int ACMCodecDB::CodecNumber(const CodecInst& codec_inst, int* mirror_id) {
+  // Look for a matching codec in the database.
+  int codec_id = CodecId(codec_inst);
+
+  // Checks if we found a matching codec.
+  if (codec_id == -1) {
+    return kInvalidCodec;
+  }
+
+  // Checks the validity of payload type
+  if (!ValidPayloadType(codec_inst.pltype)) {
+    return kInvalidPayloadtype;
+  }
+
+  // Comfort Noise is special case, packet-size & rate is not checked.
+  if (STR_CASE_CMP(database_[codec_id].plname, "CN") == 0) {
+    *mirror_id = codec_id;
+    return codec_id;
+  }
+
+  // RED is special case, packet-size & rate is not checked.
+  if (STR_CASE_CMP(database_[codec_id].plname, "red") == 0) {
+    *mirror_id = codec_id;
+    return codec_id;
+  }
+
+  // Checks the validity of packet size.
+  if (codec_settings_[codec_id].num_packet_sizes > 0) {
+    bool packet_size_ok = false;
+    int i;
+    int packet_size_samples;
+    for (i = 0; i < codec_settings_[codec_id].num_packet_sizes; i++) {
+      packet_size_samples =
+          codec_settings_[codec_id].packet_sizes_samples[i];
+      if (codec_inst.pacsize == packet_size_samples) {
+        packet_size_ok = true;
+        break;
+      }
+    }
+
+    if (!packet_size_ok) {
+      return kInvalidPacketSize;
+    }
+  }
+
+  if (codec_inst.pacsize < 1) {
+    return kInvalidPacketSize;
+  }
+
+  // Check the validity of rate. Codecs with multiple rates have their own
+  // function for this.
+  *mirror_id = codec_id;
+  if (STR_CASE_CMP("isac", codec_inst.plname) == 0) {
+    if (IsISACRateValid(codec_inst.rate)) {
+      // Set mirrorID to iSAC WB which is only created once to be used both for
+      // iSAC WB and SWB, because they need to share struct.
+      *mirror_id = kISAC;
+      return  codec_id;
+    } else {
+      return kInvalidRate;
+    }
+  } else if (STR_CASE_CMP("ilbc", codec_inst.plname) == 0) {
+    return IsILBCRateValid(codec_inst.rate, codec_inst.pacsize)
+        ? codec_id : kInvalidRate;
+  } else if (STR_CASE_CMP("amr", codec_inst.plname) == 0) {
+    return IsAMRRateValid(codec_inst.rate)
+        ? codec_id : kInvalidRate;
+  } else if (STR_CASE_CMP("amr-wb", codec_inst.plname) == 0) {
+    return IsAMRwbRateValid(codec_inst.rate)
+        ? codec_id : kInvalidRate;
+  } else if (STR_CASE_CMP("g7291", codec_inst.plname) == 0) {
+    return IsG7291RateValid(codec_inst.rate)
+        ? codec_id : kInvalidRate;
+  } else if (STR_CASE_CMP("opus", codec_inst.plname) == 0) {
+    return IsOpusRateValid(codec_inst.rate)
+        ? codec_id : kInvalidRate;
+  } else if (STR_CASE_CMP("speex", codec_inst.plname) == 0) {
+    return IsSpeexRateValid(codec_inst.rate)
+        ? codec_id : kInvalidRate;
+  } else if (STR_CASE_CMP("celt", codec_inst.plname) == 0) {
+    return IsCeltRateValid(codec_inst.rate)
+        ? codec_id : kInvalidRate;
+  }
+
+  return IsRateValid(codec_id, codec_inst.rate) ?
+      codec_id : kInvalidRate;
+}
+
+// Looks for a matching payload name, frequency, and channels in the
+// codec list. Need to check all three since some codecs have several codec
+// entries with different frequencies and/or channels.
+// Does not check other codec settings, such as payload type and packet size.
+// Returns the id of the codec, or -1 if no match is found.
+int ACMCodecDB::CodecId(const CodecInst& codec_inst) {
+  return (CodecId(codec_inst.plname, codec_inst.plfreq,
+                  codec_inst.channels));
+}
+
+int ACMCodecDB::CodecId(const char* payload_name, int frequency, int channels) {
+  for (int id = 0; id < kNumCodecs; id++) {
+    bool name_match = false;
+    bool frequency_match = false;
+    bool channels_match = false;
+
+    // Payload name, sampling frequency and number of channels need to match.
+    // NOTE! If |frequency| is -1, the frequency is not applicable, and is
+    // always treated as true, like for RED.
+    name_match = (STR_CASE_CMP(database_[id].plname, payload_name) == 0);
+    frequency_match = (frequency == database_[id].plfreq) || (frequency == -1);
+    // The number of channels must match for all codecs but Opus.
+    if (STR_CASE_CMP(payload_name, "opus") != 0) {
+      channels_match = (channels == database_[id].channels);
+    } else {
+      // For opus we just check that number of channels is valid.
+      channels_match = (channels == 1 || channels == 2);
+    }
+
+    if (name_match && frequency_match && channels_match) {
+      // We have found a matching codec in the list.
+      return id;
+    }
+  }
+
+  // We didn't find a matching codec.
+  return -1;
+}
+// Gets codec id number, and mirror id, from database for the receiver.
+int ACMCodecDB::ReceiverCodecNumber(const CodecInst& codec_inst,
+                                    int* mirror_id) {
+  // Look for a matching codec in the database.
+  int codec_id = CodecId(codec_inst);
+
+  // Set |mirror_id| to |codec_id|, except for iSAC. In case of iSAC we always
+  // set |mirror_id| to iSAC WB (kISAC) which is only created once to be used
+  // both for iSAC WB and SWB, because they need to share struct.
+  if (STR_CASE_CMP(codec_inst.plname, "ISAC") != 0) {
+    *mirror_id = codec_id;
+  } else {
+    *mirror_id = kISAC;
+  }
+
+  return codec_id;
+}
+
+// Returns the codec sampling frequency for codec with id = "codec_id" in
+// database.
+int ACMCodecDB::CodecFreq(int codec_id) {
+  // Error check to see that codec_id is not out of bounds.
+  if (codec_id < 0 || codec_id >= kNumCodecs) {
+    return -1;
+  }
+
+  return database_[codec_id].plfreq;
+}
+
+// Returns the codec's basic coding block size in samples.
+int ACMCodecDB::BasicCodingBlock(int codec_id) {
+  // Error check to see that codec_id is not out of bounds.
+  if (codec_id < 0 || codec_id >= kNumCodecs) {
+    return -1;
+  }
+
+  return codec_settings_[codec_id].basic_block_samples;
+}
+
+// Returns the NetEQ decoder database.
+const NetEqDecoder* ACMCodecDB::NetEQDecoders() {
+  return neteq_decoders_;
+}
+
+// Gets mirror id. The Id is used for codecs sharing struct for settings that
+// need different payload types.
+int ACMCodecDB::MirrorID(int codec_id) {
+  if (STR_CASE_CMP(database_[codec_id].plname, "isac") == 0) {
+    return kISAC;
+  } else {
+    return codec_id;
+  }
+}
+
+// Creates memory/instance for storing codec state.
+ACMGenericCodec* ACMCodecDB::CreateCodecInstance(const CodecInst& codec_inst) {
+  // All we have support for right now.
+  if (!STR_CASE_CMP(codec_inst.plname, "ISAC")) {
+#if (defined(WEBRTC_CODEC_ISAC) || defined(WEBRTC_CODEC_ISACFX))
+    return new ACMISAC(kISAC);
+#endif
+  } else if (!STR_CASE_CMP(codec_inst.plname, "PCMU")) {
+    if (codec_inst.channels == 1) {
+      return new ACMPCMU(kPCMU);
+    } else {
+      return new ACMPCMU(kPCMU_2ch);
+    }
+  } else if (!STR_CASE_CMP(codec_inst.plname, "PCMA")) {
+    if (codec_inst.channels == 1) {
+      return new ACMPCMA(kPCMA);
+    } else {
+      return new ACMPCMA(kPCMA_2ch);
+    }
+  } else if (!STR_CASE_CMP(codec_inst.plname, "ILBC")) {
+#ifdef WEBRTC_CODEC_ILBC
+    return new ACMILBC(kILBC);
+#endif
+  } else if (!STR_CASE_CMP(codec_inst.plname, "AMR")) {
+#ifdef WEBRTC_CODEC_AMR
+    return new ACMAMR(kGSMAMR);
+#endif
+  } else if (!STR_CASE_CMP(codec_inst.plname, "AMR-WB")) {
+#ifdef WEBRTC_CODEC_AMRWB
+    return new ACMAMRwb(kGSMAMRWB);
+#endif
+  } else if (!STR_CASE_CMP(codec_inst.plname, "CELT")) {
+#ifdef WEBRTC_CODEC_CELT
+    if (codec_inst.channels == 1) {
+      return new ACMCELT(kCELT32);
+    } else {
+      return new ACMCELT(kCELT32_2ch);
+    }
+#endif
+  } else if (!STR_CASE_CMP(codec_inst.plname, "G722")) {
+#ifdef WEBRTC_CODEC_G722
+    if (codec_inst.channels == 1) {
+      return new ACMG722(kG722);
+    } else {
+      return new ACMG722(kG722_2ch);
+    }
+#endif
+  } else if (!STR_CASE_CMP(codec_inst.plname, "G7221")) {
+    switch (codec_inst.plfreq) {
+      case 16000: {
+#ifdef WEBRTC_CODEC_G722_1
+        int codec_id;
+        switch (codec_inst->rate) {
+          case 16000 : {
+            codec_id = kG722_1_16;
+            break;
+          }
+          case 24000 : {
+            codec_id = kG722_1_24;
+            break;
+          }
+          case 32000 : {
+            codec_id = kG722_1_32;
+            break;
+          }
+          default: {
+            return NULL;
+          }
+          return new ACMG722_1(codec_id);
+        }
+#endif
+      }
+      case 32000: {
+#ifdef WEBRTC_CODEC_G722_1C
+        int codec_id;
+        switch (codec_inst->rate) {
+          case 24000 : {
+            codec_id = kG722_1C_24;
+            break;
+          }
+          case 32000 : {
+            codec_id = kG722_1C_32;
+            break;
+          }
+          case 48000 : {
+            codec_id = kG722_1C_48;
+            break;
+          }
+          default: {
+            return NULL;
+          }
+          return new ACMG722_1C(codec_id);
+        }
+#endif
+      }
+    }
+  } else if (!STR_CASE_CMP(codec_inst.plname, "CN")) {
+    // For CN we need to check sampling frequency to know what codec to create.
+    int codec_id;
+    switch (codec_inst.plfreq) {
+      case 8000: {
+        codec_id = kCNNB;
+        break;
+      }
+      case 16000: {
+        codec_id = kCNWB;
+        break;
+      }
+      case 32000: {
+        codec_id = kCNSWB;
+        break;
+      }
+      case 48000: {
+        codec_id = kCNFB;
+        break;
+      }
+      default: {
+        return NULL;
+      }
+    }
+    return new ACMCNG(codec_id);
+  } else if (!STR_CASE_CMP(codec_inst.plname, "G729")) {
+#ifdef WEBRTC_CODEC_G729
+    return new ACMG729(kG729);
+#endif
+  } else if (!STR_CASE_CMP(codec_inst.plname, "G7291")) {
+#ifdef WEBRTC_CODEC_G729_1
+    return new ACMG729_1(kG729_1);
+#endif
+  } else if (!STR_CASE_CMP(codec_inst.plname, "opus")) {
+#ifdef WEBRTC_CODEC_OPUS
+    return new ACMOpus(kOpus);
+#endif
+  } else if (!STR_CASE_CMP(codec_inst.plname, "speex")) {
+#ifdef WEBRTC_CODEC_SPEEX
+    int codec_id;
+    switch (codec_inst->plfreq) {
+      case 8000: {
+        codec_id = kSPEEX8;
+        break;
+      }
+      case 16000: {
+        codec_id = kSPEEX16;
+        break;
+      }
+      default: {
+        return NULL;
+      }
+    }
+    return new ACMSPEEX(codec_id);
+#endif
+  } else if (!STR_CASE_CMP(codec_inst.plname, "CN")) {
+    // For CN we need to check sampling frequency to know what codec to create.
+    int codec_id;
+    switch (codec_inst.plfreq) {
+      case 8000: {
+        codec_id = kCNNB;
+        break;
+      }
+      case 16000: {
+        codec_id = kCNWB;
+        break;
+      }
+      case 32000: {
+        codec_id = kCNSWB;
+        break;
+      }
+      case 48000: {
+        codec_id = kCNFB;
+        break;
+      }
+      default: {
+        return NULL;
+      }
+    }
+    return new ACMCNG(codec_id);
+  } else if (!STR_CASE_CMP(codec_inst.plname, "L16")) {
+#ifdef WEBRTC_CODEC_PCM16
+    // For L16 we need to check sampling frequency to know what codec to create.
+    int codec_id;
+    if (codec_inst.channels == 1) {
+      switch (codec_inst.plfreq) {
+        case 8000: {
+          codec_id = kPCM16B;
+          break;
+        }
+        case 16000: {
+          codec_id = kPCM16Bwb;
+          break;
+        }
+        case 32000: {
+          codec_id = kPCM16Bswb32kHz;
+          break;
+        }
+        default: {
+          return NULL;
+        }
+      }
+    } else {
+      switch (codec_inst.plfreq) {
+        case 8000: {
+          codec_id = kPCM16B_2ch;
+          break;
+        }
+        case 16000: {
+          codec_id = kPCM16Bwb_2ch;
+          break;
+        }
+        case 32000: {
+          codec_id = kPCM16Bswb32kHz_2ch;
+          break;
+        }
+        default: {
+          return NULL;
+        }
+      }
+    }
+    return new ACMPCM16B(codec_id);
+#endif
+  } else if (!STR_CASE_CMP(codec_inst.plname, "telephone-event")) {
+#ifdef WEBRTC_CODEC_AVT
+    return new ACMDTMFPlayout(kAVT);
+#endif
+  } else if (!STR_CASE_CMP(codec_inst.plname, "red")) {
+#ifdef WEBRTC_CODEC_RED
+    return new ACMRED(kRED);
+#endif
+  }
+  return NULL;
+}
+
+// Checks if the bitrate is valid for the codec.
+bool ACMCodecDB::IsRateValid(int codec_id, int rate) {
+  if (database_[codec_id].rate == rate) {
+    return true;
+  } else {
+    return false;
+  }
+}
+
+// Checks if the bitrate is valid for iSAC.
+bool ACMCodecDB::IsISACRateValid(int rate) {
+  if ((rate == -1) || ((rate <= 56000) && (rate >= 10000))) {
+    return true;
+  } else {
+    return false;
+  }
+}
+
+// Checks if the bitrate is valid for iLBC.
+bool ACMCodecDB::IsILBCRateValid(int rate, int frame_size_samples) {
+  if (((frame_size_samples == 240) || (frame_size_samples == 480)) &&
+      (rate == 13300)) {
+    return true;
+  } else if (((frame_size_samples == 160) || (frame_size_samples == 320)) &&
+      (rate == 15200)) {
+    return true;
+  } else {
+    return false;
+  }
+}
+
+// Check if the bitrate is valid for the GSM-AMR.
+bool ACMCodecDB::IsAMRRateValid(int rate) {
+  switch (rate) {
+    case 4750:
+    case 5150:
+    case 5900:
+    case 6700:
+    case 7400:
+    case 7950:
+    case 10200:
+    case 12200: {
+      return true;
+    }
+    default: {
+      return false;
+    }
+  }
+}
+
+// Check if the bitrate is valid for GSM-AMR-WB.
+bool ACMCodecDB::IsAMRwbRateValid(int rate) {
+  switch (rate) {
+    case 7000:
+    case 9000:
+    case 12000:
+    case 14000:
+    case 16000:
+    case 18000:
+    case 20000:
+    case 23000:
+    case 24000: {
+      return true;
+    }
+    default: {
+      return false;
+    }
+  }
+}
+
+// Check if the bitrate is valid for G.729.1.
+bool ACMCodecDB::IsG7291RateValid(int rate) {
+  switch (rate) {
+    case 8000:
+    case 12000:
+    case 14000:
+    case 16000:
+    case 18000:
+    case 20000:
+    case 22000:
+    case 24000:
+    case 26000:
+    case 28000:
+    case 30000:
+    case 32000: {
+      return true;
+    }
+    default: {
+      return false;
+    }
+  }
+}
+
+// Checks if the bitrate is valid for Speex.
+bool ACMCodecDB::IsSpeexRateValid(int rate) {
+  if (rate > 2000) {
+    return true;
+  } else {
+    return false;
+  }
+}
+
+// Checks if the bitrate is valid for Opus.
+bool ACMCodecDB::IsOpusRateValid(int rate) {
+  if ((rate < 6000) || (rate > 510000)) {
+    return false;
+  }
+  return true;
+}
+
+// Checks if the bitrate is valid for Celt.
+bool ACMCodecDB::IsCeltRateValid(int rate) {
+  if ((rate >= 48000) && (rate <= 128000)) {
+    return true;
+  } else {
+    return false;
+  }
+}
+
+// Checks if the payload type is in the valid range.
+bool ACMCodecDB::ValidPayloadType(int payload_type) {
+  if ((payload_type < 0) || (payload_type > 127)) {
+    return false;
+  }
+  return true;
+}
+
+bool ACMCodecDB::OwnsDecoder(int codec_id) {
+  assert(codec_id >= 0 && codec_id < ACMCodecDB::kNumCodecs);
+  return ACMCodecDB::codec_settings_[codec_id].owns_decoder;
+}
+
+}  // namespace webrtc
diff --git a/webrtc/modules/audio_coding/main/acm2/acm_codec_database.h b/webrtc/modules/audio_coding/main/acm2/acm_codec_database.h
new file mode 100644
index 0000000..fb5cb9a
--- /dev/null
+++ b/webrtc/modules/audio_coding/main/acm2/acm_codec_database.h
@@ -0,0 +1,350 @@
+/*
+ *  Copyright (c) 2012 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.
+ */
+
+/*
+ * This file generates databases with information about all supported audio
+ * codecs.
+ */
+
+#ifndef WEBRTC_MODULES_AUDIO_CODING_MAIN_SOURCE_ACM_CODEC_DATABASE_H_
+#define WEBRTC_MODULES_AUDIO_CODING_MAIN_SOURCE_ACM_CODEC_DATABASE_H_
+
+#include "webrtc/common_types.h"
+#include "webrtc/modules/audio_coding/main/source/acm_generic_codec.h"
+#include "webrtc/modules/audio_coding/neteq4/interface/neteq.h"
+
+namespace webrtc {
+
+// TODO(tlegrand): replace class ACMCodecDB with a namespace.
+class ACMCodecDB {
+ public:
+  // Enum with array indexes for the supported codecs. NOTE! The order MUST
+  // be the same as when creating the database in acm_codec_database.cc.
+  enum {
+    kNone = -1
+#if (defined(WEBRTC_CODEC_ISAC) || defined(WEBRTC_CODEC_ISACFX))
+    , kISAC
+# if (defined(WEBRTC_CODEC_ISAC))
+    , kISACSWB
+    , kISACFB
+# endif
+#endif
+#ifdef WEBRTC_CODEC_PCM16
+    // Mono
+    , kPCM16B
+    , kPCM16Bwb
+    , kPCM16Bswb32kHz
+    // Stereo
+    , kPCM16B_2ch
+    , kPCM16Bwb_2ch
+    , kPCM16Bswb32kHz_2ch
+#endif
+    // Mono
+    , kPCMU
+    , kPCMA
+    // Stereo
+    , kPCMU_2ch
+    , kPCMA_2ch
+#ifdef WEBRTC_CODEC_ILBC
+    , kILBC
+#endif
+#ifdef WEBRTC_CODEC_AMR
+    , kGSMAMR
+#endif
+#ifdef WEBRTC_CODEC_AMRWB
+    , kGSMAMRWB
+#endif
+#ifdef WEBRTC_CODEC_CELT
+    // Mono
+    , kCELT32
+    // Stereo
+    , kCELT32_2ch
+#endif
+#ifdef WEBRTC_CODEC_G722
+    // Mono
+    , kG722
+    // Stereo
+    , kG722_2ch
+#endif
+#ifdef WEBRTC_CODEC_G722_1
+    , kG722_1_32
+    , kG722_1_24
+    , kG722_1_16
+#endif
+#ifdef WEBRTC_CODEC_G722_1C
+    , kG722_1C_48
+    , kG722_1C_32
+    , kG722_1C_24
+#endif
+#ifdef WEBRTC_CODEC_G729
+    , kG729
+#endif
+#ifdef WEBRTC_CODEC_G729_1
+    , kG729_1
+#endif
+#ifdef WEBRTC_CODEC_GSMFR
+    , kGSMFR
+#endif
+#ifdef WEBRTC_CODEC_OPUS
+    // Mono and stereo
+    , kOpus
+#endif
+#ifdef WEBRTC_CODEC_SPEEX
+    , kSPEEX8
+    , kSPEEX16
+#endif
+    , kCNNB
+    , kCNWB
+    , kCNSWB
+    , kCNFB
+#ifdef WEBRTC_CODEC_AVT
+    , kAVT
+#endif
+#ifdef WEBRTC_CODEC_RED
+    , kRED
+#endif
+    , kNumCodecs
+  };
+
+  // Set unsupported codecs to -1
+#ifndef WEBRTC_CODEC_ISAC
+  enum {kISACSWB = -1};
+  enum {kISACFB = -1};
+# ifndef WEBRTC_CODEC_ISACFX
+  enum {kISAC = -1};
+# endif
+#endif
+#ifndef WEBRTC_CODEC_PCM16
+  // Mono
+  enum {kPCM16B = -1};
+  enum {kPCM16Bwb = -1};
+  enum {kPCM16Bswb32kHz = -1};
+  // Stereo
+  enum {kPCM16B_2ch = -1};
+  enum {kPCM16Bwb_2ch = -1};
+  enum {kPCM16Bswb32kHz_2ch = -1};
+#endif
+  // 48 kHz not supported, always set to -1.
+  enum {kPCM16Bswb48kHz = -1};
+#ifndef WEBRTC_CODEC_ILBC
+  enum {kILBC = -1};
+#endif
+#ifndef WEBRTC_CODEC_AMR
+  enum {kGSMAMR = -1};
+#endif
+#ifndef WEBRTC_CODEC_AMRWB
+  enum {kGSMAMRWB = -1};
+#endif
+#ifndef WEBRTC_CODEC_CELT
+  // Mono
+  enum {kCELT32 = -1};
+  // Stereo
+  enum {kCELT32_2ch = -1};
+#endif
+#ifndef WEBRTC_CODEC_G722
+  // Mono
+  enum {kG722 = -1};
+  // Stereo
+  enum {kG722_2ch = -1};
+#endif
+#ifndef WEBRTC_CODEC_G722_1
+  enum {kG722_1_32 = -1};
+  enum {kG722_1_24 = -1};
+  enum {kG722_1_16 = -1};
+#endif
+#ifndef WEBRTC_CODEC_G722_1C
+  enum {kG722_1C_48 = -1};
+  enum {kG722_1C_32 = -1};
+  enum {kG722_1C_24 = -1};
+#endif
+#ifndef WEBRTC_CODEC_G729
+  enum {kG729 = -1};
+#endif
+#ifndef WEBRTC_CODEC_G729_1
+  enum {kG729_1 = -1};
+#endif
+#ifndef WEBRTC_CODEC_GSMFR
+  enum {kGSMFR = -1};
+#endif
+#ifndef WEBRTC_CODEC_SPEEX
+  enum {kSPEEX8 = -1};
+  enum {kSPEEX16 = -1};
+#endif
+#ifndef WEBRTC_CODEC_OPUS
+  // Mono and stereo
+  enum {kOpus = -1};
+#endif
+#ifndef WEBRTC_CODEC_AVT
+  enum {kAVT = -1};
+#endif
+#ifndef WEBRTC_CODEC_RED
+  enum {kRED = -1};
+#endif
+
+  // kMaxNumCodecs - Maximum number of codecs that can be activated in one
+  //                 build.
+  // kMaxNumPacketSize - Maximum number of allowed packet sizes for one codec.
+  // These might need to be increased if adding a new codec to the database
+  static const int kMaxNumCodecs =  50;
+  static const int kMaxNumPacketSize = 6;
+
+  // Codec specific settings
+  //
+  // num_packet_sizes     - number of allowed packet sizes.
+  // packet_sizes_samples - list of the allowed packet sizes.
+  // basic_block_samples  - assigned a value different from 0 if the codec
+  //                        requires to be fed with a specific number of samples
+  //                        that can be different from packet size.
+  // channel_support      - number of channels supported to encode;
+  //                        1 = mono, 2 = stereo, etc.
+  // owns_decoder         - if true, it means that the codec should own the
+  //                        decoder instance. In this case, the codec should
+  //                        implement ACMGenericCodec::Decoder(), which returns
+  //                        a pointer to AudioDecoder. This pointer is injected
+  //                        into NetEq when this codec is registered as receive
+  //                        codec.
+  struct CodecSettings {
+    int num_packet_sizes;
+    int packet_sizes_samples[kMaxNumPacketSize];
+    int basic_block_samples;
+    int channel_support;
+    bool owns_decoder;
+  };
+
+  // Gets codec information from database at the position in database given by
+  // [codec_id].
+  // Input:
+  //   [codec_id] - number that specifies at what position in the database to
+  //                get the information.
+  // Output:
+  //   [codec_inst] - filled with information about the codec.
+  // Return:
+  //   0 if successful, otherwise -1.
+  static int Codec(int codec_id, CodecInst* codec_inst);
+
+  // Returns codec id and mirror id from database, given the information
+  // received in the input [codec_inst]. Mirror id is a number that tells
+  // where to find the codec's memory (instance). The number is either the
+  // same as codec id (most common), or a number pointing at a different
+  // entry in the database, if the codec has several entries with different
+  // payload types. This is used for codecs that must share one struct even if
+  // the payload type differs.
+  // One example is the codec iSAC which has the same struct for both 16 and
+  // 32 khz, but they have different entries in the database. Let's say the
+  // function is called with iSAC 32kHz. The function will return 1 as that is
+  // the entry in the data base, and [mirror_id] = 0, as that is the entry for
+  // iSAC 16 kHz, which holds the shared memory.
+  // Input:
+  //   [codec_inst] - Information about the codec for which we require the
+  //                  database id.
+  // Output:
+  //   [mirror_id] - mirror id, which most often is the same as the return
+  //                 value, see above.
+  //   [err_message] - if present, in the event of a mismatch found between the
+  //                   input and the database, a descriptive error message is
+  //                   written here.
+  //   [err_message] - if present, the length of error message is returned here.
+  // Return:
+  //   codec id if successful, otherwise < 0.
+  static int CodecNumber(const CodecInst& codec_inst, int* mirror_id,
+                         char* err_message, int max_message_len_byte);
+  static int CodecNumber(const CodecInst& codec_inst, int* mirror_id);
+  static int CodecId(const CodecInst& codec_inst);
+  static int CodecId(const char* payload_name, int frequency, int channels);
+  static int ReceiverCodecNumber(const CodecInst& codec_inst, int* mirror_id);
+
+  // Returns the codec sampling frequency for codec with id = "codec_id" in
+  // database.
+  // TODO(tlegrand): Check if function is needed, or if we can change
+  // to access database directly.
+  // Input:
+  //   [codec_id] - number that specifies at what position in the database to
+  //                get the information.
+  // Return:
+  //   codec sampling frequency if successful, otherwise -1.
+  static int CodecFreq(int codec_id);
+
+  // Return the codec's basic coding block size in samples.
+  // TODO(tlegrand): Check if function is needed, or if we can change
+  // to access database directly.
+  // Input:
+  //   [codec_id] - number that specifies at what position in the database to
+  //                get the information.
+  // Return:
+  //   codec basic block size if successful, otherwise -1.
+  static int BasicCodingBlock(int codec_id);
+
+  // Returns the NetEQ decoder database.
+  static const NetEqDecoder* NetEQDecoders();
+
+  // Returns mirror id, which is a number that tells where to find the codec's
+  // memory (instance). It is either the same as codec id (most common), or a
+  // number pointing at a different entry in the database, if the codec have
+  // several entries with different payload types. This is used for codecs that
+  // must share struct even if the payload type differs.
+  // TODO(tlegrand): Check if function is needed, or if we can change
+  // to access database directly.
+  // Input:
+  //   [codec_id] - number that specifies codec's position in the database.
+  // Return:
+  //   Mirror id on success, otherwise -1.
+  static int MirrorID(int codec_id);
+
+  // Create memory/instance for storing codec state.
+  // Input:
+  //   [codec_inst] - information about codec. Only name of codec, "plname", is
+  //                  used in this function.
+  static ACMGenericCodec* CreateCodecInstance(const CodecInst& codec_inst);
+
+  // Specifies if the codec specified by |codec_id| MUST own its own decoder.
+  // This is the case for codecs which *should* share a single codec instance
+  // between encoder and decoder. Or for codecs which ACM should have control
+  // over the decoder. For instance iSAC is such a codec that encoder and
+  // decoder share the same codec instance.
+  static bool OwnsDecoder(int codec_id);
+
+  // Checks if the bitrate is valid for the codec.
+  // Input:
+  //   [codec_id] - number that specifies codec's position in the database.
+  //   [rate] - bitrate to check.
+  //   [frame_size_samples] - (used for iLBC) specifies which frame size to go
+  //                          with the rate.
+  static bool IsRateValid(int codec_id, int rate);
+  static bool IsISACRateValid(int rate);
+  static bool IsILBCRateValid(int rate, int frame_size_samples);
+  static bool IsAMRRateValid(int rate);
+  static bool IsAMRwbRateValid(int rate);
+  static bool IsG7291RateValid(int rate);
+  static bool IsSpeexRateValid(int rate);
+  static bool IsOpusRateValid(int rate);
+  static bool IsCeltRateValid(int rate);
+
+  // Check if the payload type is valid, meaning that it is in the valid range
+  // of 0 to 127.
+  // Input:
+  //   [payload_type] - payload type.
+  static bool ValidPayloadType(int payload_type);
+
+  // Databases with information about the supported codecs
+  // database_ - stored information about all codecs: payload type, name,
+  //             sampling frequency, packet size in samples, default channel
+  //             support, and default rate.
+  // codec_settings_ - stored codec settings: number of allowed packet sizes,
+  //                   a vector with the allowed packet sizes, basic block
+  //                   samples, and max number of channels that are supported.
+  // neteq_decoders_ - list of supported decoders in NetEQ.
+  static const CodecInst database_[kMaxNumCodecs];
+  static const CodecSettings codec_settings_[kMaxNumCodecs];
+  static const NetEqDecoder neteq_decoders_[kMaxNumCodecs];
+};
+
+}  // namespace webrtc
+
+#endif  // WEBRTC_MODULES_AUDIO_CODING_MAIN_SOURCE_ACM_CODEC_DATABASE_H_
diff --git a/webrtc/modules/audio_coding/main/acm2/acm_common_defs.h b/webrtc/modules/audio_coding/main/acm2/acm_common_defs.h
new file mode 100644
index 0000000..b27256a
--- /dev/null
+++ b/webrtc/modules/audio_coding/main/acm2/acm_common_defs.h
@@ -0,0 +1,98 @@
+/*
+ *  Copyright (c) 2011 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_MAIN_SOURCE_ACM_COMMON_DEFS_H_
+#define WEBRTC_MODULES_AUDIO_CODING_MAIN_SOURCE_ACM_COMMON_DEFS_H_
+
+#include <string.h>
+
+#include "webrtc/common_types.h"
+#include "webrtc/engine_configurations.h"
+#include "webrtc/modules/audio_coding/main/interface/audio_coding_module_typedefs.h"
+#include "webrtc/typedefs.h"
+
+// Checks for enabled codecs, we prevent enabling codecs which are not
+// compatible.
+#if ((defined WEBRTC_CODEC_ISAC) && (defined WEBRTC_CODEC_ISACFX))
+#error iSAC and iSACFX codecs cannot be enabled at the same time
+#endif
+
+#ifndef STR_CASE_CMP
+#ifdef WIN32
+// OS-dependent case-insensitive string comparison
+#define STR_CASE_CMP(x, y) ::_stricmp(x, y)
+#else
+// OS-dependent case-insensitive string comparison
+#define STR_CASE_CMP(x, y) ::strcasecmp(x, y)
+#endif
+#endif
+
+namespace webrtc {
+
+// 60 ms is the maximum block size we support. An extra 20 ms is considered
+// for safety if process() method is not called when it should be, i.e. we
+// accept 20 ms of jitter. 80 ms @ 32 kHz (super wide-band) is 2560 samples.
+#define AUDIO_BUFFER_SIZE_W16  2560
+
+// There is one timestamp per each 10 ms of audio
+// the audio buffer, at max, may contain 32 blocks of 10ms
+// audio if the sampling frequency is 8000 Hz (80 samples per block).
+// Therefore, The size of the buffer where we keep timestamps
+// is defined as follows
+#define TIMESTAMP_BUFFER_SIZE_W32  (AUDIO_BUFFER_SIZE_W16/80)
+
+// The maximum size of a payload, that is 60 ms of PCM-16 @ 32 kHz stereo
+#define MAX_PAYLOAD_SIZE_BYTE   7680
+
+// General codec specific defines
+const int kIsacWbDefaultRate = 32000;
+const int kIsacSwbDefaultRate = 56000;
+const int kIsacPacSize480 = 480;
+const int kIsacPacSize960 = 960;
+const int kIsacPacSize1440 = 1440;
+
+// An encoded bit-stream is labeled by one of the following enumerators.
+//
+//   kNoEncoding              : There has been no encoding.
+//   kActiveNormalEncoded     : Active audio frame coded by the codec.
+//   kPassiveNormalEncoded    : Passive audio frame coded by the codec.
+//   kPassiveDTXNB            : Passive audio frame coded by narrow-band CN.
+//   kPassiveDTXWB            : Passive audio frame coded by wide-band CN.
+//   kPassiveDTXSWB           : Passive audio frame coded by super-wide-band CN.
+//   kPassiveDTXFB            : Passive audio frame coded by full-band CN.
+enum WebRtcACMEncodingType {
+  kNoEncoding,
+  kActiveNormalEncoded,
+  kPassiveNormalEncoded,
+  kPassiveDTXNB,
+  kPassiveDTXWB,
+  kPassiveDTXSWB,
+  kPassiveDTXFB
+};
+
+// A structure which contains codec parameters. For instance, used when
+// initializing encoder and decoder.
+//
+//   codec_inst: c.f. common_types.h
+//   enable_dtx: set true to enable DTX. If codec does not have
+//               internal DTX, this will enable VAD.
+//   enable_vad: set true to enable VAD.
+//   vad_mode: VAD mode, c.f. audio_coding_module_typedefs.h
+//             for possible values.
+struct WebRtcACMCodecParams {
+  CodecInst codec_inst;
+  bool enable_dtx;
+  bool enable_vad;
+  ACMVADMode vad_mode;
+};
+
+}  // namespace webrtc
+
+#endif  // WEBRTC_MODULES_AUDIO_CODING_MAIN_SOURCE_ACM_COMMON_DEFS_H_
diff --git a/webrtc/modules/audio_coding/main/acm2/acm_dtmf_playout.cc b/webrtc/modules/audio_coding/main/acm2/acm_dtmf_playout.cc
new file mode 100644
index 0000000..b6b9102
--- /dev/null
+++ b/webrtc/modules/audio_coding/main/acm2/acm_dtmf_playout.cc
@@ -0,0 +1,86 @@
+/*
+ *  Copyright (c) 2012 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 "webrtc/modules/audio_coding/main/source/acm_dtmf_playout.h"
+
+#ifdef WEBRTC_CODEC_AVT
+#include "webrtc/modules/audio_coding/main/source/acm_common_defs.h"
+#include "webrtc/modules/audio_coding/main/source/acm_receiver.h"
+#include "webrtc/system_wrappers/interface/trace.h"
+#endif
+
+namespace webrtc {
+
+#ifndef WEBRTC_CODEC_AVT
+
+ACMDTMFPlayout::ACMDTMFPlayout(int16_t /* codec_id */) { return; }
+
+ACMDTMFPlayout::~ACMDTMFPlayout() { return; }
+
+int16_t ACMDTMFPlayout::InternalEncode(uint8_t* /* bitstream */,
+                                       int16_t* /* bitstream_len_byte */) {
+  return -1;
+}
+
+int16_t ACMDTMFPlayout::InternalInitEncoder(
+    WebRtcACMCodecParams* /* codec_params */) {
+  return -1;
+}
+
+ACMGenericCodec* ACMDTMFPlayout::CreateInstance(void) { return NULL; }
+
+int16_t ACMDTMFPlayout::InternalCreateEncoder() { return -1; }
+
+void ACMDTMFPlayout::InternalDestructEncoderInst(void* /* ptr_inst */) {
+  return;
+}
+
+void ACMDTMFPlayout::DestructEncoderSafe() {
+  return;
+}
+
+#else  //===================== Actual Implementation =======================
+
+ACMDTMFPlayout::ACMDTMFPlayout(int16_t codec_id) { codec_id_ = codec_id; }
+
+ACMDTMFPlayout::~ACMDTMFPlayout() { return; }
+
+int16_t ACMDTMFPlayout::InternalEncode(uint8_t* /* bitstream */,
+                                       int16_t* /* bitstream_len_byte */) {
+  return 0;
+}
+
+int16_t ACMDTMFPlayout::InternalInitEncoder(
+    WebRtcACMCodecParams* /* codec_params */) {
+  // This codec does not need initialization,
+  // DTMFPlayout has no instance
+  return 0;
+}
+
+ACMGenericCodec* ACMDTMFPlayout::CreateInstance(void) { return NULL; }
+
+int16_t ACMDTMFPlayout::InternalCreateEncoder() {
+  // DTMFPlayout has no instance
+  return 0;
+}
+
+void ACMDTMFPlayout::InternalDestructEncoderInst(void* /* ptr_inst */) {
+  // DTMFPlayout has no instance
+  return;
+}
+
+void ACMDTMFPlayout::DestructEncoderSafe() {
+  // DTMFPlayout has no instance
+  return;
+}
+
+#endif
+
+}  // namespace webrtc
diff --git a/webrtc/modules/audio_coding/main/acm2/acm_dtmf_playout.h b/webrtc/modules/audio_coding/main/acm2/acm_dtmf_playout.h
new file mode 100644
index 0000000..e16653c
--- /dev/null
+++ b/webrtc/modules/audio_coding/main/acm2/acm_dtmf_playout.h
@@ -0,0 +1,40 @@
+/*
+ *  Copyright (c) 2012 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_MAIN_SOURCE_ACM_DTMF_PLAYOUT_H_
+#define WEBRTC_MODULES_AUDIO_CODING_MAIN_SOURCE_ACM_DTMF_PLAYOUT_H_
+
+#include "webrtc/modules/audio_coding/main/source/acm_generic_codec.h"
+
+namespace webrtc {
+
+class ACMDTMFPlayout : public ACMGenericCodec {
+ public:
+  explicit ACMDTMFPlayout(int16_t codec_id);
+  ~ACMDTMFPlayout();
+
+  // for FEC
+  ACMGenericCodec* CreateInstance(void);
+
+  int16_t InternalEncode(uint8_t* bitstream, int16_t* bitstream_len_byte);
+
+  int16_t InternalInitEncoder(WebRtcACMCodecParams* codec_params);
+
+ protected:
+  void DestructEncoderSafe();
+
+  int16_t InternalCreateEncoder();
+
+  void InternalDestructEncoderInst(void* ptr_inst);
+};
+
+}  // namespace webrtc
+
+#endif  // WEBRTC_MODULES_AUDIO_CODING_MAIN_SOURCE_ACM_DTMF_PLAYOUT_H_
diff --git a/webrtc/modules/audio_coding/main/acm2/acm_g722.cc b/webrtc/modules/audio_coding/main/acm2/acm_g722.cc
new file mode 100644
index 0000000..6ba0d7b
--- /dev/null
+++ b/webrtc/modules/audio_coding/main/acm2/acm_g722.cc
@@ -0,0 +1,197 @@
+/*
+ *  Copyright (c) 2012 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 "webrtc/modules/audio_coding/main/source/acm_g722.h"
+
+#ifdef WEBRTC_CODEC_G722
+#include "webrtc/modules/audio_coding/codecs/g722/include/g722_interface.h"
+#include "webrtc/modules/audio_coding/main/source/acm_codec_database.h"
+#include "webrtc/modules/audio_coding/main/source/acm_common_defs.h"
+#include "webrtc/system_wrappers/interface/trace.h"
+#endif
+
+namespace webrtc {
+
+#ifndef WEBRTC_CODEC_G722
+
+ACMG722::ACMG722(int16_t /* codec_id */)
+    : ptr_enc_str_(NULL),
+      encoder_inst_ptr_(NULL),
+      encoder_inst_ptr_right_(NULL) {}
+
+ACMG722::~ACMG722() {}
+
+int32_t ACMG722::Add10MsDataSafe(const uint32_t /* timestamp */,
+                                 const int16_t* /* data */,
+                                 const uint16_t /* length_smpl */,
+                                 const uint8_t /* audio_channel */) {
+  return -1;
+}
+
+int16_t ACMG722::InternalEncode(uint8_t* /* bitstream */,
+                                int16_t* /* bitstream_len_byte */) {
+  return -1;
+}
+
+int16_t ACMG722::InternalInitEncoder(WebRtcACMCodecParams* /* codec_params */) {
+  return -1;
+}
+
+ACMGenericCodec* ACMG722::CreateInstance(void) { return NULL; }
+
+int16_t ACMG722::InternalCreateEncoder() { return -1; }
+
+void ACMG722::DestructEncoderSafe() { return; }
+
+void ACMG722::InternalDestructEncoderInst(void* /* ptr_inst */) { return; }
+
+#else     //===================== Actual Implementation =======================
+
+// Encoder and decoder memory
+struct ACMG722EncStr {
+  G722EncInst* inst;  // instance for left channel in case of stereo
+  G722EncInst* inst_right;  // instance for right channel in case of stereo
+};
+struct ACMG722DecStr {
+  G722DecInst* inst;  // instance for left channel in case of stereo
+  G722DecInst* inst_right;  // instance for right channel in case of stereo
+};
+
+ACMG722::ACMG722(int16_t codec_id)
+    : encoder_inst_ptr_(NULL), encoder_inst_ptr_right_(NULL) {
+  ptr_enc_str_ = new ACMG722EncStr;
+  if (ptr_enc_str_ != NULL) {
+    ptr_enc_str_->inst = NULL;
+    ptr_enc_str_->inst_right = NULL;
+  }
+  codec_id_ = codec_id;
+  return;
+}
+
+ACMG722::~ACMG722() {
+  // Encoder
+  if (ptr_enc_str_ != NULL) {
+    if (ptr_enc_str_->inst != NULL) {
+      WebRtcG722_FreeEncoder(ptr_enc_str_->inst);
+      ptr_enc_str_->inst = NULL;
+    }
+    if (ptr_enc_str_->inst_right != NULL) {
+      WebRtcG722_FreeEncoder(ptr_enc_str_->inst_right);
+      ptr_enc_str_->inst_right = NULL;
+    }
+    delete ptr_enc_str_;
+    ptr_enc_str_ = NULL;
+  }
+  return;
+}
+
+int32_t ACMG722::Add10MsDataSafe(const uint32_t timestamp,
+                                 const int16_t* data,
+                                 const uint16_t length_smpl,
+                                 const uint8_t audio_channel) {
+  return ACMGenericCodec::Add10MsDataSafe(
+      (timestamp >> 1), data, length_smpl, audio_channel);
+}
+
+int16_t ACMG722::InternalEncode(uint8_t* bitstream,
+                                int16_t* bitstream_len_byte) {
+  // If stereo, split input signal in left and right channel before encoding
+  if (num_channels_ == 2) {
+    int16_t left_channel[960];
+    int16_t right_channel[960];
+    uint8_t out_left[480];
+    uint8_t out_right[480];
+    int16_t len_in_bytes;
+    for (int i = 0, j = 0; i < frame_len_smpl_ * 2; i += 2, j++) {
+      left_channel[j] = in_audio_[in_audio_ix_read_ + i];
+      right_channel[j] = in_audio_[in_audio_ix_read_ + i + 1];
+    }
+    len_in_bytes = WebRtcG722_Encode(
+        encoder_inst_ptr_, left_channel, frame_len_smpl_,
+        reinterpret_cast<int16_t*>(out_left));
+    len_in_bytes += WebRtcG722_Encode(encoder_inst_ptr_right_,
+                                      right_channel,
+                                      frame_len_smpl_,
+                                      reinterpret_cast<int16_t*>(out_right));
+    *bitstream_len_byte = len_in_bytes;
+
+    // Interleave the 4 bits per sample from left and right channel
+    for (int i = 0, j = 0; i < len_in_bytes; i += 2, j++) {
+      bitstream[i] = (out_left[j] & 0xF0) + (out_right[j] >> 4);
+      bitstream[i + 1] = ((out_left[j] & 0x0F) << 4) + (out_right[j] & 0x0F);
+    }
+  } else {
+    *bitstream_len_byte = WebRtcG722_Encode(
+        encoder_inst_ptr_, &in_audio_[in_audio_ix_read_], frame_len_smpl_,
+        reinterpret_cast<int16_t*>(bitstream));
+  }
+
+  // increment the read index this tell the caller how far
+  // we have gone forward in reading the audio buffer
+  in_audio_ix_read_ += frame_len_smpl_ * num_channels_;
+  return *bitstream_len_byte;
+}
+
+int16_t ACMG722::InternalInitEncoder(WebRtcACMCodecParams* codec_params) {
+  if (codec_params->codec_inst.channels == 2) {
+    // Create codec struct for right channel
+    if (ptr_enc_str_->inst_right == NULL) {
+      WebRtcG722_CreateEncoder(&ptr_enc_str_->inst_right);
+      if (ptr_enc_str_->inst_right == NULL) {
+        return -1;
+      }
+    }
+    encoder_inst_ptr_right_ = ptr_enc_str_->inst_right;
+    if (WebRtcG722_EncoderInit(encoder_inst_ptr_right_) < 0) {
+      return -1;
+    }
+  }
+
+  return WebRtcG722_EncoderInit(encoder_inst_ptr_);
+}
+
+ACMGenericCodec* ACMG722::CreateInstance(void) { return NULL; }
+
+int16_t ACMG722::InternalCreateEncoder() {
+  if (ptr_enc_str_ == NULL) {
+    // this structure must be created at the costructor
+    // if it is still NULL then there is a probelm and
+    // we dont continue
+    return -1;
+  }
+  WebRtcG722_CreateEncoder(&ptr_enc_str_->inst);
+  if (ptr_enc_str_->inst == NULL) {
+    return -1;
+  }
+  encoder_inst_ptr_ = ptr_enc_str_->inst;
+  return 0;
+}
+
+void ACMG722::DestructEncoderSafe() {
+  if (ptr_enc_str_ != NULL) {
+    if (ptr_enc_str_->inst != NULL) {
+      WebRtcG722_FreeEncoder(ptr_enc_str_->inst);
+      ptr_enc_str_->inst = NULL;
+    }
+  }
+  encoder_exist_ = false;
+  encoder_initialized_ = false;
+}
+
+void ACMG722::InternalDestructEncoderInst(void* ptr_inst) {
+  if (ptr_inst != NULL) {
+    WebRtcG722_FreeEncoder(static_cast<G722EncInst*>(ptr_inst));
+  }
+  return;
+}
+
+#endif
+
+}  // namespace webrtc
diff --git a/webrtc/modules/audio_coding/main/acm2/acm_g722.h b/webrtc/modules/audio_coding/main/acm2/acm_g722.h
new file mode 100644
index 0000000..21a0fdb
--- /dev/null
+++ b/webrtc/modules/audio_coding/main/acm2/acm_g722.h
@@ -0,0 +1,57 @@
+/*
+ *  Copyright (c) 2012 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_MAIN_SOURCE_ACM_G722_H_
+#define WEBRTC_MODULES_AUDIO_CODING_MAIN_SOURCE_ACM_G722_H_
+
+#include "webrtc/modules/audio_coding/main/source/acm_generic_codec.h"
+
+typedef struct WebRtcG722EncInst G722EncInst;
+typedef struct WebRtcG722DecInst G722DecInst;
+
+namespace webrtc {
+
+// Forward declaration.
+struct ACMG722EncStr;
+struct ACMG722DecStr;
+
+class ACMG722 : public ACMGenericCodec {
+ public:
+  explicit ACMG722(int16_t codec_id);
+  ~ACMG722();
+
+  // For FEC.
+  ACMGenericCodec* CreateInstance(void);
+
+  int16_t InternalEncode(uint8_t* bitstream, int16_t* bitstream_len_byte);
+
+  int16_t InternalInitEncoder(WebRtcACMCodecParams* codec_params);
+
+ protected:
+  int32_t Add10MsDataSafe(const uint32_t timestamp,
+                          const int16_t* data,
+                          const uint16_t length_smpl,
+                          const uint8_t audio_channel);
+
+  void DestructEncoderSafe();
+
+  int16_t InternalCreateEncoder();
+
+  void InternalDestructEncoderInst(void* ptr_inst);
+
+  ACMG722EncStr* ptr_enc_str_;
+
+  G722EncInst* encoder_inst_ptr_;
+  G722EncInst* encoder_inst_ptr_right_;  // Prepared for stereo
+};
+
+}  // namespace webrtc
+
+#endif  // WEBRTC_MODULES_AUDIO_CODING_MAIN_SOURCE_ACM_G722_H_
diff --git a/webrtc/modules/audio_coding/main/acm2/acm_g7221.cc b/webrtc/modules/audio_coding/main/acm2/acm_g7221.cc
new file mode 100644
index 0000000..65b34b0
--- /dev/null
+++ b/webrtc/modules/audio_coding/main/acm2/acm_g7221.cc
@@ -0,0 +1,326 @@
+/*
+ *  Copyright (c) 2012 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 "webrtc/modules/audio_coding/main/source/acm_g7221.h"
+
+#ifdef WEBRTC_CODEC_G722_1
+// NOTE! G.722.1 is not included in the open-source package. The following
+// interface file is needed:
+#include "webrtc/modules/audio_coding/main/codecs/g7221/interface/g7221_interface.h"
+#include "webrtc/modules/audio_coding/main/source/acm_codec_database.h"
+#include "webrtc/modules/audio_coding/main/source/acm_common_defs.h"
+#include "webrtc/system_wrappers/interface/trace.h"
+
+// The API in the header file should match the one below.
+//
+// int16_t WebRtcG7221_CreateEnc16(G722_1_16_encinst_t_** enc_inst);
+// int16_t WebRtcG7221_CreateEnc24(G722_1_24_encinst_t_** enc_inst);
+// int16_t WebRtcG7221_CreateEnc32(G722_1_32_encinst_t_** enc_inst);
+// int16_t WebRtcG7221_CreateDec16(G722_1_16_decinst_t_** dec_inst);
+// int16_t WebRtcG7221_CreateDec24(G722_1_24_decinst_t_** dec_inst);
+// int16_t WebRtcG7221_CreateDec32(G722_1_32_decinst_t_** dec_inst);
+//
+// int16_t WebRtcG7221_FreeEnc16(G722_1_16_encinst_t_** enc_inst);
+// int16_t WebRtcG7221_FreeEnc24(G722_1_24_encinst_t_** enc_inst);
+// int16_t WebRtcG7221_FreeEnc32(G722_1_32_encinst_t_** enc_inst);
+// int16_t WebRtcG7221_FreeDec16(G722_1_16_decinst_t_** dec_inst);
+// int16_t WebRtcG7221_FreeDec24(G722_1_24_decinst_t_** dec_inst);
+// int16_t WebRtcG7221_FreeDec32(G722_1_32_decinst_t_** dec_inst);
+//
+// int16_t WebRtcG7221_EncoderInit16(G722_1_16_encinst_t_* enc_inst);
+// int16_t WebRtcG7221_EncoderInit24(G722_1_24_encinst_t_* enc_inst);
+// int16_t WebRtcG7221_EncoderInit32(G722_1_32_encinst_t_* enc_inst);
+// int16_t WebRtcG7221_DecoderInit16(G722_1_16_decinst_t_* dec_inst);
+// int16_t WebRtcG7221_DecoderInit24(G722_1_24_decinst_t_* dec_inst);
+// int16_t WebRtcG7221_DecoderInit32(G722_1_32_decinst_t_* dec_inst);
+//
+// int16_t WebRtcG7221_Encode16(G722_1_16_encinst_t_* enc_inst,
+//                              int16_t* input,
+//                              int16_t len,
+//                              int16_t* output);
+// int16_t WebRtcG7221_Encode24(G722_1_24_encinst_t_* enc_inst,
+//                              int16_t* input,
+//                              int16_t len,
+//                              int16_t* output);
+// int16_t WebRtcG7221_Encode32(G722_1_32_encinst_t_* enc_inst,
+//                              int16_t* input,
+//                              int16_t len,
+//                              int16_t* output);
+//
+// int16_t WebRtcG7221_Decode16(G722_1_16_decinst_t_* dec_inst,
+//                              int16_t* bitstream,
+//                              int16_t len,
+//                              int16_t* output);
+// int16_t WebRtcG7221_Decode24(G722_1_24_decinst_t_* dec_inst,
+//                              int16_t* bitstream,
+//                              int16_t len,
+//                              int16_t* output);
+// int16_t WebRtcG7221_Decode32(G722_1_32_decinst_t_* dec_inst,
+//                              int16_t* bitstream,
+//                              int16_t len,
+//                              int16_t* output);
+//
+// int16_t WebRtcG7221_DecodePlc16(G722_1_16_decinst_t_* dec_inst,
+//                                 int16_t* output,
+//                                 int16_t nr_lost_frames);
+// int16_t WebRtcG7221_DecodePlc24(G722_1_24_decinst_t_* dec_inst,
+//                                 int16_t* output,
+//                                 int16_t nr_lost_frames);
+// int16_t WebRtcG7221_DecodePlc32(G722_1_32_decinst_t_* dec_inst,
+//                                 int16_t* output,
+//                                 int16_t nr_lost_frames);
+#endif
+
+namespace webrtc {
+
+#ifndef WEBRTC_CODEC_G722_1
+
+ACMG722_1::ACMG722_1(int16_t /* codec_id */)
+    : operational_rate_(-1),
+      encoder_inst_ptr_(NULL),
+      encoder_inst_ptr_right_(NULL),
+      encoder_inst16_ptr_(NULL),
+      encoder_inst16_ptr_right_(NULL),
+      encoder_inst24_ptr_(NULL),
+      encoder_inst24_ptr_right_(NULL),
+      encoder_inst32_ptr_(NULL),
+      encoder_inst32_ptr_right_(NULL) {
+  return;
+}
+
+ACMG722_1::~ACMG722_1() { return; }
+
+int16_t ACMG722_1::InternalEncode(uint8_t* /* bitstream */,
+                                  int16_t* /* bitstream_len_byte */) {
+  return -1;
+}
+
+int16_t ACMG722_1::InternalInitEncoder(
+    WebRtcACMCodecParams* /* codec_params */) {
+  return -1;
+}
+
+ACMGenericCodec* ACMG722_1::CreateInstance(void) { return NULL; }
+
+int16_t ACMG722_1::InternalCreateEncoder() { return -1; }
+
+void ACMG722_1::DestructEncoderSafe() { return; }
+
+void ACMG722_1::InternalDestructEncoderInst(void* /* ptr_inst */) { return; }
+
+#else  //===================== Actual Implementation =======================
+ACMG722_1::ACMG722_1(int16_t codec_id)
+    : encoder_inst_ptr_(NULL),
+      encoder_inst_ptr_right_(NULL),
+      encoder_inst16_ptr_(NULL),
+      encoder_inst16_ptr_right_(NULL),
+      encoder_inst24_ptr_(NULL),
+      encoder_inst24_ptr_right_(NULL),
+      encoder_inst32_ptr_(NULL),
+      encoder_inst32_ptr_right_(NULL) {
+  codec_id_ = codec_id;
+  if (codec_id_ == ACMCodecDB::kG722_1_16) {
+    operational_rate_ = 16000;
+  } else if (codec_id_ == ACMCodecDB::kG722_1_24) {
+    operational_rate_ = 24000;
+  } else if (codec_id_ == ACMCodecDB::kG722_1_32) {
+    operational_rate_ = 32000;
+  } else {
+    operational_rate_ = -1;
+  }
+  return;
+}
+
+ACMG722_1::~ACMG722_1() {
+  if (encoder_inst_ptr_ != NULL) {
+    delete encoder_inst_ptr_;
+    encoder_inst_ptr_ = NULL;
+  }
+  if (encoder_inst_ptr_right_ != NULL) {
+    delete encoder_inst_ptr_right_;
+    encoder_inst_ptr_right_ = NULL;
+  }
+
+  switch (operational_rate_) {
+    case 16000: {
+      encoder_inst16_ptr_ = NULL;
+      encoder_inst16_ptr_right_ = NULL;
+      break;
+    }
+    case 24000: {
+      encoder_inst24_ptr_ = NULL;
+      encoder_inst24_ptr_right_ = NULL;
+      break;
+    }
+    case 32000: {
+      encoder_inst32_ptr_ = NULL;
+      encoder_inst32_ptr_right_ = NULL;
+      break;
+    }
+    default: {
+      break;
+    }
+  }
+  return;
+}
+
+int16_t ACMG722_1::InternalEncode(uint8_t* bitstream,
+                                  int16_t* bitstream_len_byte) {
+  int16_t left_channel[320];
+  int16_t right_channel[320];
+  int16_t len_in_bytes;
+  int16_t out_bits[160];
+
+  // If stereo, split input signal in left and right channel before encoding
+  if (num_channels_ == 2) {
+    for (int i = 0, j = 0; i < frame_len_smpl_ * 2; i += 2, j++) {
+      left_channel[j] = in_audio_[in_audio_ix_read_ + i];
+      right_channel[j] = in_audio_[in_audio_ix_read_ + i + 1];
+    }
+  } else {
+    memcpy(left_channel, &in_audio_[in_audio_ix_read_], 320);
+  }
+
+  switch (operational_rate_) {
+    case 16000: {
+      len_in_bytes = WebRtcG7221_Encode16(encoder_inst16_ptr_, left_channel,
+                                               320, &out_bits[0]);
+      if (num_channels_ == 2) {
+        len_in_bytes += WebRtcG7221_Encode16(encoder_inst16_ptr_right_,
+                                             right_channel, 320,
+                                             &out_bits[len_in_bytes / 2]);
+      }
+      break;
+    }
+    case 24000: {
+      len_in_bytes = WebRtcG7221_Encode24(encoder_inst24_ptr_, left_channel,
+                                          320, &out_bits[0]);
+      if (num_channels_ == 2) {
+        len_in_bytes += WebRtcG7221_Encode24(encoder_inst24_ptr_right_,
+                                             right_channel, 320,
+                                             &out_bits[len_in_bytes / 2]);
+      }
+      break;
+    }
+    case 32000: {
+      len_in_bytes = WebRtcG7221_Encode32(encoder_inst32_ptr_, left_channel,
+                                          320, &out_bits[0]);
+      if (num_channels_ == 2) {
+        len_in_bytes += WebRtcG7221_Encode32(encoder_inst32_ptr_right_,
+                                             right_channel, 320,
+                                             &out_bits[len_in_bytes / 2]);
+      }
+      break;
+    }
+    default: {
+      WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, unique_id_,
+                   "InternalInitEncode: Wrong rate for G722_1.");
+      return -1;
+    }
+  }
+  memcpy(bitstream, out_bits, len_in_bytes);
+  *bitstream_len_byte = len_in_bytes;
+
+  // increment the read index this tell the caller that how far
+  // we have gone forward in reading the audio buffer
+  in_audio_ix_read_ += 320 * num_channels_;
+  return *bitstream_len_byte;
+}
+
+int16_t ACMG722_1::InternalInitEncoder(WebRtcACMCodecParams* codec_params) {
+  int16_t ret;
+
+  switch (operational_rate_) {
+    case 16000: {
+      ret = WebRtcG7221_EncoderInit16(encoder_inst16_ptr_right_);
+      if (ret < 0) {
+        return ret;
+      }
+      return WebRtcG7221_EncoderInit16(encoder_inst16_ptr_);
+    }
+    case 24000: {
+      ret = WebRtcG7221_EncoderInit24(encoder_inst24_ptr_right_);
+      if (ret < 0) {
+        return ret;
+      }
+      return WebRtcG7221_EncoderInit24(encoder_inst24_ptr_);
+    }
+    case 32000: {
+      ret = WebRtcG7221_EncoderInit32(encoder_inst32_ptr_right_);
+      if (ret < 0) {
+        return ret;
+      }
+      return WebRtcG7221_EncoderInit32(encoder_inst32_ptr_);
+    }
+    default: {
+      WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding,
+                   unique_id_, "InternalInitEncoder: Wrong rate for G722_1.");
+      return -1;
+    }
+  }
+}
+
+ACMGenericCodec* ACMG722_1::CreateInstance(void) { return NULL; }
+
+int16_t ACMG722_1::InternalCreateEncoder() {
+  if ((encoder_inst_ptr_ == NULL) || (encoder_inst_ptr_right_ == NULL)) {
+    return -1;
+  }
+  switch (operational_rate_) {
+    case 16000: {
+      WebRtcG7221_CreateEnc16(&encoder_inst16_ptr_);
+      WebRtcG7221_CreateEnc16(&encoder_inst16_ptr_right_);
+      break;
+    }
+    case 24000: {
+      WebRtcG7221_CreateEnc24(&encoder_inst24_ptr_);
+      WebRtcG7221_CreateEnc24(&encoder_inst24_ptr_right_);
+      break;
+    }
+    case 32000: {
+      WebRtcG7221_CreateEnc32(&encoder_inst32_ptr_);
+      WebRtcG7221_CreateEnc32(&encoder_inst32_ptr_right_);
+      break;
+    }
+    default: {
+      WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, unique_id_,
+                   "InternalCreateEncoder: Wrong rate for G722_1.");
+      return -1;
+    }
+  }
+  return 0;
+}
+
+void ACMG722_1::DestructEncoderSafe() {
+  encoder_exist_ = false;
+  encoder_initialized_ = false;
+  if (encoder_inst_ptr_ != NULL) {
+    delete encoder_inst_ptr_;
+    encoder_inst_ptr_ = NULL;
+  }
+  if (encoder_inst_ptr_right_ != NULL) {
+    delete encoder_inst_ptr_right_;
+    encoder_inst_ptr_right_ = NULL;
+  }
+  encoder_inst16_ptr_ = NULL;
+  encoder_inst24_ptr_ = NULL;
+  encoder_inst32_ptr_ = NULL;
+}
+
+void ACMG722_1::InternalDestructEncoderInst(void* ptr_inst) {
+  if (ptr_inst != NULL) {
+    delete ptr_inst;
+  }
+  return;
+}
+
+#endif
+
+}  // namespace webrtc
diff --git a/webrtc/modules/audio_coding/main/acm2/acm_g7221.h b/webrtc/modules/audio_coding/main/acm2/acm_g7221.h
new file mode 100644
index 0000000..2b532db9
--- /dev/null
+++ b/webrtc/modules/audio_coding/main/acm2/acm_g7221.h
@@ -0,0 +1,62 @@
+/*
+ *  Copyright (c) 2012 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_MAIN_SOURCE_ACM_G7221_H_
+#define WEBRTC_MODULES_AUDIO_CODING_MAIN_SOURCE_ACM_G7221_H_
+
+#include "webrtc/modules/audio_coding/main/source/acm_generic_codec.h"
+
+// forward declaration
+struct G722_1_16_encinst_t_;
+struct G722_1_16_decinst_t_;
+struct G722_1_24_encinst_t_;
+struct G722_1_24_decinst_t_;
+struct G722_1_32_encinst_t_;
+struct G722_1_32_decinst_t_;
+struct G722_1_Inst_t_;
+
+namespace webrtc {
+
+class ACMG722_1 : public ACMGenericCodec {
+ public:
+  explicit ACMG722_1(int16_t codec_id);
+  ~ACMG722_1();
+
+  // for FEC
+  ACMGenericCodec* CreateInstance(void);
+
+  int16_t InternalEncode(uint8_t* bitstream, int16_t* bitstream_len_byte);
+
+  int16_t InternalInitEncoder(WebRtcACMCodecParams* codec_params);
+
+ protected:
+  void DestructEncoderSafe();
+
+  int16_t InternalCreateEncoder();
+
+  void InternalDestructEncoderInst(void* ptr_inst);
+
+  int32_t operational_rate_;
+
+  G722_1_Inst_t_* encoder_inst_ptr_;
+  G722_1_Inst_t_* encoder_inst_ptr_right_;  // Used in stereo mode
+
+  // Only one set of these pointer is valid at any instance
+  G722_1_16_encinst_t_* encoder_inst16_ptr_;
+  G722_1_16_encinst_t_* encoder_inst16_ptr_right_;
+  G722_1_24_encinst_t_* encoder_inst24_ptr_;
+  G722_1_24_encinst_t_* encoder_inst24_ptr_right_;
+  G722_1_32_encinst_t_* encoder_inst32_ptr_;
+  G722_1_32_encinst_t_* encoder_inst32_ptr_right_;
+};
+
+}  // namespace webrtc
+
+#endif  // WEBRTC_MODULES_AUDIO_CODING_MAIN_SOURCE_ACM_G7221_H_
diff --git a/webrtc/modules/audio_coding/main/acm2/acm_g7221c.cc b/webrtc/modules/audio_coding/main/acm2/acm_g7221c.cc
new file mode 100644
index 0000000..b426d1f
--- /dev/null
+++ b/webrtc/modules/audio_coding/main/acm2/acm_g7221c.cc
@@ -0,0 +1,332 @@
+/*
+ *  Copyright (c) 2012 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 "webrtc/modules/audio_coding/main/source/acm_g7221c.h"
+
+#ifdef WEBRTC_CODEC_G722_1C
+// NOTE! G.722.1C is not included in the open-source package. The following
+// interface file is needed:
+#include "webrtc/modules/audio_coding/main/codecs/g7221c/interface/g7221c_interface.h"
+#include "webrtc/modules/audio_coding/main/source/acm_codec_database.h"
+#include "webrtc/modules/audio_coding/main/source/acm_common_defs.h"
+#include "webrtc/system_wrappers/interface/trace.h"
+
+// The API in the header file should match the one below.
+//
+// int16_t WebRtcG7221C_CreateEnc24(G722_1C_24_encinst_t_** enc_inst);
+// int16_t WebRtcG7221C_CreateEnc32(G722_1C_32_encinst_t_** enc_inst);
+// int16_t WebRtcG7221C_CreateEnc48(G722_1C_48_encinst_t_** enc_inst);
+// int16_t WebRtcG7221C_CreateDec24(G722_1C_24_decinst_t_** dec_inst);
+// int16_t WebRtcG7221C_CreateDec32(G722_1C_32_decinst_t_** dec_inst);
+// int16_t WebRtcG7221C_CreateDec48(G722_1C_48_decinst_t_** dec_inst);
+//
+// int16_t WebRtcG7221C_FreeEnc24(G722_1C_24_encinst_t_** enc_inst);
+// int16_t WebRtcG7221C_FreeEnc32(G722_1C_32_encinst_t_** enc_inst);
+// int16_t WebRtcG7221C_FreeEnc48(G722_1C_48_encinst_t_** enc_inst);
+// int16_t WebRtcG7221C_FreeDec24(G722_1C_24_decinst_t_** dec_inst);
+// int16_t WebRtcG7221C_FreeDec32(G722_1C_32_decinst_t_** dec_inst);
+// int16_t WebRtcG7221C_FreeDec48(G722_1C_48_decinst_t_** dec_inst);
+//
+// int16_t WebRtcG7221C_EncoderInit24(G722_1C_24_encinst_t_* enc_inst);
+// int16_t WebRtcG7221C_EncoderInit32(G722_1C_32_encinst_t_* enc_inst);
+// int16_t WebRtcG7221C_EncoderInit48(G722_1C_48_encinst_t_* enc_inst);
+// int16_t WebRtcG7221C_DecoderInit24(G722_1C_24_decinst_t_* dec_inst);
+// int16_t WebRtcG7221C_DecoderInit32(G722_1C_32_decinst_t_* dec_inst);
+// int16_t WebRtcG7221C_DecoderInit48(G722_1C_48_decinst_t_* dec_inst);
+//
+// int16_t WebRtcG7221C_Encode24(G722_1C_24_encinst_t_* enc_inst,
+//                               int16_t* input,
+//                               int16_t len,
+//                               int16_t* output);
+// int16_t WebRtcG7221C_Encode32(G722_1C_32_encinst_t_* enc_inst,
+//                               int16_t* input,
+//                               int16_t len,
+//                               int16_t* output);
+// int16_t WebRtcG7221C_Encode48(G722_1C_48_encinst_t_* enc_inst,
+//                               int16_t* input,
+//                               int16_t len,
+//                               int16_t* output);
+//
+// int16_t WebRtcG7221C_Decode24(G722_1C_24_decinst_t_* dec_inst,
+//                               int16_t* bitstream,
+//                               int16_t len,
+//                               int16_t* output);
+// int16_t WebRtcG7221C_Decode32(G722_1C_32_decinst_t_* dec_inst,
+//                               int16_t* bitstream,
+//                               int16_t len,
+//                               int16_t* output);
+// int16_t WebRtcG7221C_Decode48(G722_1C_48_decinst_t_* dec_inst,
+//                               int16_t* bitstream,
+//                               int16_t len,
+//                               int16_t* output);
+//
+// int16_t WebRtcG7221C_DecodePlc24(G722_1C_24_decinst_t_* dec_inst,
+//                                  int16_t* output,
+//                                  int16_t nr_lost_frames);
+// int16_t WebRtcG7221C_DecodePlc32(G722_1C_32_decinst_t_* dec_inst,
+//                                  int16_t* output,
+//                                  int16_t nr_lost_frames);
+// int16_t WebRtcG7221C_DecodePlc48(G722_1C_48_decinst_t_* dec_inst,
+//                                  int16_t* output,
+//                                  int16_t nr_lost_frames);
+#endif
+
+namespace webrtc {
+
+#ifndef WEBRTC_CODEC_G722_1C
+
+ACMG722_1C::ACMG722_1C(int16_t /* codec_id */)
+    : operational_rate_(-1),
+      encoder_inst_ptr_(NULL),
+      encoder_inst_ptr_right_(NULL),
+      encoder_inst24_ptr_(NULL),
+      encoder_inst24_ptr_right_(NULL),
+      encoder_inst32_ptr_(NULL),
+      encoder_inst32_ptr_right_(NULL),
+      encoder_inst48_ptr_(NULL),
+      encoder_inst48_ptr_right_(NULL) {
+  return;
+}
+
+ACMG722_1C::~ACMG722_1C() { return; }
+
+int16_t ACMG722_1C::InternalEncode(uint8_t* /* bitstream */,
+                                   int16_t* /* bitstream_len_byte */) {
+  return -1;
+}
+
+int16_t ACMG722_1C::InternalInitEncoder(
+    WebRtcACMCodecParams* /* codec_params */) {
+  return -1;
+}
+
+ACMGenericCodec* ACMG722_1C::CreateInstance(void) { return NULL; }
+
+int16_t ACMG722_1C::InternalCreateEncoder() { return -1; }
+
+void ACMG722_1C::DestructEncoderSafe() { return; }
+
+void ACMG722_1C::InternalDestructEncoderInst(void* /* ptr_inst */) { return; }
+
+#else  //===================== Actual Implementation =======================
+ACMG722_1C::ACMG722_1C(int16_t codec_id)
+    : encoder_inst_ptr_(NULL),
+      encoder_inst_ptr_right_(NULL),
+      encoder_inst24_ptr_(NULL),
+      encoder_inst24_ptr_right_(NULL),
+      encoder_inst32_ptr_(NULL),
+      encoder_inst32_ptr_right_(NULL),
+      encoder_inst48_ptr_(NULL),
+      encoder_inst48_ptr_right_(NULL) {
+  codec_id_ = codec_id;
+  if (codec_id_ == ACMCodecDB::kG722_1C_24) {
+    operational_rate_ = 24000;
+  } else if (codec_id_ == ACMCodecDB::kG722_1C_32) {
+    operational_rate_ = 32000;
+  } else if (codec_id_ == ACMCodecDB::kG722_1C_48) {
+    operational_rate_ = 48000;
+  } else {
+    WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, unique_id_,
+                 "Wrong codec id for G722_1c.");
+    operational_rate_ = -1;
+  }
+  return;
+}
+
+ACMG722_1C::~ACMG722_1C() {
+  if (encoder_inst_ptr_ != NULL) {
+    delete encoder_inst_ptr_;
+    encoder_inst_ptr_ = NULL;
+  }
+  if (encoder_inst_ptr_right_ != NULL) {
+    delete encoder_inst_ptr_right_;
+    encoder_inst_ptr_right_ = NULL;
+  }
+
+  switch (operational_rate_) {
+    case 24000: {
+      encoder_inst24_ptr_ = NULL;
+      encoder_inst24_ptr_right_ = NULL;
+      break;
+    }
+    case 32000: {
+      encoder_inst32_ptr_ = NULL;
+      encoder_inst32_ptr_right_ = NULL;
+      break;
+    }
+    case 48000: {
+      encoder_inst48_ptr_ = NULL;
+      encoder_inst48_ptr_right_ = NULL;
+      break;
+    }
+    default: {
+      WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, unique_id_,
+                   "Wrong rate for G722_1c.");
+      break;
+    }
+  }
+  return;
+}
+
+int16_t ACMG722_1C::InternalEncode(uint8_t* bitstream,
+                                   int16_t* bitstream_len_byte) {
+  int16_t left_channel[640];
+  int16_t right_channel[640];
+  int16_t len_in_bytes;
+  int16_t out_bits[240];
+
+  // If stereo, split input signal in left and right channel before encoding
+  if (num_channels_ == 2) {
+    for (int i = 0, j = 0; i < frame_len_smpl_ * 2; i += 2, j++) {
+      left_channel[j] = in_audio_[in_audio_ix_read_ + i];
+      right_channel[j] = in_audio_[in_audio_ix_read_ + i + 1];
+    }
+  } else {
+    memcpy(left_channel, &in_audio_[in_audio_ix_read_], 640);
+  }
+
+  switch (operational_rate_) {
+    case 24000: {
+      len_in_bytes = WebRtcG7221C_Encode24(encoder_inst24_ptr_, left_channel,
+                                           640, &out_bits[0]);
+      if (num_channels_ == 2) {
+        len_in_bytes += WebRtcG7221C_Encode24(encoder_inst24_ptr_right_,
+                                              right_channel, 640,
+                                              &out_bits[len_in_bytes / 2]);
+      }
+      break;
+    }
+    case 32000: {
+      len_in_bytes = WebRtcG7221C_Encode32(encoder_inst32_ptr_, left_channel,
+                                           640, &out_bits[0]);
+      if (num_channels_ == 2) {
+        len_in_bytes += WebRtcG7221C_Encode32(encoder_inst32_ptr_right_,
+                                              right_channel, 640,
+                                              &out_bits[len_in_bytes / 2]);
+      }
+      break;
+    }
+    case 48000: {
+      len_in_bytes = WebRtcG7221C_Encode48(encoder_inst48_ptr_, left_channel,
+                                           640, &out_bits[0]);
+      if (num_channels_ == 2) {
+        len_in_bytes += WebRtcG7221C_Encode48(encoder_inst48_ptr_right_,
+                                              right_channel, 640,
+                                              &out_bits[len_in_bytes / 2]);
+      }
+      break;
+    }
+    default: {
+      WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, unique_id_,
+                   "InternalEncode: Wrong rate for G722_1c.");
+      return -1;
+    }
+  }
+
+  memcpy(bitstream, out_bits, len_in_bytes);
+  *bitstream_len_byte = len_in_bytes;
+
+  // increment the read index this tell the caller that how far
+  // we have gone forward in reading the audio buffer
+  in_audio_ix_read_ += 640 * num_channels_;
+
+  return *bitstream_len_byte;
+}
+
+int16_t ACMG722_1C::InternalInitEncoder(WebRtcACMCodecParams* codec_params) {
+  int16_t ret;
+
+  switch (operational_rate_) {
+    case 24000: {
+      ret = WebRtcG7221C_EncoderInit24(encoder_inst24_ptr_right_);
+      if (ret < 0) {
+        return ret;
+      }
+      return WebRtcG7221C_EncoderInit24(encoder_inst24_ptr_);
+    }
+    case 32000: {
+      ret = WebRtcG7221C_EncoderInit32(encoder_inst32_ptr_right_);
+      if (ret < 0) {
+        return ret;
+      }
+      return WebRtcG7221C_EncoderInit32(encoder_inst32_ptr_);
+    }
+    case 48000: {
+      ret = WebRtcG7221C_EncoderInit48(encoder_inst48_ptr_right_);
+      if (ret < 0) {
+        return ret;
+      }
+      return WebRtcG7221C_EncoderInit48(encoder_inst48_ptr_);
+    }
+    default: {
+      WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, unique_id_,
+                   "InternalInitEncode: Wrong rate for G722_1c.");
+      return -1;
+    }
+  }
+}
+
+ACMGenericCodec* ACMG722_1C::CreateInstance(void) { return NULL; }
+
+int16_t ACMG722_1C::InternalCreateEncoder() {
+  if ((encoder_inst_ptr_ == NULL) || (encoder_inst_ptr_right_ == NULL)) {
+    return -1;
+  }
+  switch (operational_rate_) {
+    case 24000: {
+      WebRtcG7221C_CreateEnc24(&encoder_inst24_ptr_);
+      WebRtcG7221C_CreateEnc24(&encoder_inst24_ptr_right_);
+      break;
+    }
+    case 32000: {
+      WebRtcG7221C_CreateEnc32(&encoder_inst32_ptr_);
+      WebRtcG7221C_CreateEnc32(&encoder_inst32_ptr_right_);
+      break;
+    }
+    case 48000: {
+      WebRtcG7221C_CreateEnc48(&encoder_inst48_ptr_);
+      WebRtcG7221C_CreateEnc48(&encoder_inst48_ptr_right_);
+      break;
+    }
+    default: {
+      WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, unique_id_,
+                   "InternalCreateEncoder: Wrong rate for G722_1c.");
+      return -1;
+    }
+  }
+  return 0;
+}
+
+void ACMG722_1C::DestructEncoderSafe() {
+  encoder_exist_ = false;
+  encoder_initialized_ = false;
+  if (encoder_inst_ptr_ != NULL) {
+    delete encoder_inst_ptr_;
+    encoder_inst_ptr_ = NULL;
+  }
+  if (encoder_inst_ptr_right_ != NULL) {
+    delete encoder_inst_ptr_right_;
+    encoder_inst_ptr_right_ = NULL;
+  }
+  encoder_inst24_ptr_ = NULL;
+  encoder_inst32_ptr_ = NULL;
+  encoder_inst48_ptr_ = NULL;
+}
+
+void ACMG722_1C::InternalDestructEncoderInst(void* ptr_inst) {
+  if (ptr_inst != NULL) {
+    delete ptr_inst;
+  }
+  return;
+}
+
+#endif
+
+}  // namespace webrtc
diff --git a/webrtc/modules/audio_coding/main/acm2/acm_g7221c.h b/webrtc/modules/audio_coding/main/acm2/acm_g7221c.h
new file mode 100644
index 0000000..d051b28
--- /dev/null
+++ b/webrtc/modules/audio_coding/main/acm2/acm_g7221c.h
@@ -0,0 +1,62 @@
+/*
+ *  Copyright (c) 2012 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_MAIN_SOURCE_ACM_G7221C_H_
+#define WEBRTC_MODULES_AUDIO_CODING_MAIN_SOURCE_ACM_G7221C_H_
+
+#include "webrtc/modules/audio_coding/main/source/acm_generic_codec.h"
+
+// forward declaration
+struct G722_1C_24_encinst_t_;
+struct G722_1C_24_decinst_t_;
+struct G722_1C_32_encinst_t_;
+struct G722_1C_32_decinst_t_;
+struct G722_1C_48_encinst_t_;
+struct G722_1C_48_decinst_t_;
+struct G722_1_Inst_t_;
+
+namespace webrtc {
+
+class ACMG722_1C : public ACMGenericCodec {
+ public:
+  explicit ACMG722_1C(int16_t codec_id);
+  ~ACMG722_1C();
+
+  // for FEC
+  ACMGenericCodec* CreateInstance(void);
+
+  int16_t InternalEncode(uint8_t* bitstream, int16_t* bitstream_len_byte);
+
+  int16_t InternalInitEncoder(WebRtcACMCodecParams* codec_params);
+
+ protected:
+  void DestructEncoderSafe();
+
+  int16_t InternalCreateEncoder();
+
+  void InternalDestructEncoderInst(void* ptr_inst);
+
+  int32_t operational_rate_;
+
+  G722_1_Inst_t_* encoder_inst_ptr_;
+  G722_1_Inst_t_* encoder_inst_ptr_right_;  // Used in stereo mode
+
+  // Only one set of these pointer is valid at any instance
+  G722_1C_24_encinst_t_* encoder_inst24_ptr_;
+  G722_1C_24_encinst_t_* encoder_inst24_ptr_right_;
+  G722_1C_32_encinst_t_* encoder_inst32_ptr_;
+  G722_1C_32_encinst_t_* encoder_inst32_ptr_right_;
+  G722_1C_48_encinst_t_* encoder_inst48_ptr_;
+  G722_1C_48_encinst_t_* encoder_inst48_ptr_right_;
+};
+
+}  // namespace webrtc
+
+#endif  // WEBRTC_MODULES_AUDIO_CODING_MAIN_SOURCE_ACM_G7221C_H_
diff --git a/webrtc/modules/audio_coding/main/acm2/acm_g729.cc b/webrtc/modules/audio_coding/main/acm2/acm_g729.cc
new file mode 100644
index 0000000..a2349ce
--- /dev/null
+++ b/webrtc/modules/audio_coding/main/acm2/acm_g729.cc
@@ -0,0 +1,255 @@
+/*
+ *  Copyright (c) 2012 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 "webrtc/modules/audio_coding/main/source/acm_g729.h"
+
+#ifdef WEBRTC_CODEC_G729
+// NOTE! G.729 is not included in the open-source package. Modify this file
+// or your codec API to match the function calls and names of used G.729 API
+// file.
+#include "webrtc/modules/audio_coding/main/codecs/g729/interface/g729_interface.h"
+#include "webrtc/modules/audio_coding/main/source/acm_common_defs.h"
+#include "webrtc/modules/audio_coding/main/source/acm_receiver.h"
+#include "webrtc/system_wrappers/interface/trace.h"
+#endif
+
+namespace webrtc {
+
+#ifndef WEBRTC_CODEC_G729
+
+ACMG729::ACMG729(int16_t /* codec_id */) : encoder_inst_ptr_(NULL) {}
+
+ACMG729::~ACMG729() { return; }
+
+int16_t ACMG729::InternalEncode(uint8_t* /* bitstream */,
+                                int16_t* /* bitstream_len_byte */) {
+  return -1;
+}
+
+int16_t ACMG729::EnableDTX() { return -1; }
+
+int16_t ACMG729::DisableDTX() { return -1; }
+
+int32_t ACMG729::ReplaceInternalDTXSafe(const bool /*replace_internal_dtx */) {
+  return -1;
+}
+
+int32_t ACMG729::IsInternalDTXReplacedSafe(bool* /* internal_dtx_replaced */) {
+  return -1;
+}
+
+int16_t ACMG729::InternalInitEncoder(WebRtcACMCodecParams* /* codec_params */) {
+  return -1;
+}
+
+ACMGenericCodec* ACMG729::CreateInstance(void) { return NULL; }
+
+int16_t ACMG729::InternalCreateEncoder() { return -1; }
+
+void ACMG729::DestructEncoderSafe() { return; }
+
+void ACMG729::InternalDestructEncoderInst(void* /* ptr_inst */) { return; }
+
+#else  //===================== Actual Implementation =======================
+ACMG729::ACMG729(int16_t codec_id)
+    : codec_id_(codec_id),
+      has_internal_dtx_(),
+      encoder_inst_ptr_(NULL) {}
+
+ACMG729::~ACMG729() {
+  if (encoder_inst_ptr_ != NULL) {
+    // Delete encoder memory
+    WebRtcG729_FreeEnc(encoder_inst_ptr_);
+    encoder_inst_ptr_ = NULL;
+  }
+  return;
+}
+
+int16_t ACMG729::InternalEncode(uint8_t* bitstream,
+                                int16_t* bitstream_len_byte) {
+  // Initialize before entering the loop
+  int16_t num_encoded_samples = 0;
+  int16_t tmp_len_byte = 0;
+  int16_t vad_decision = 0;
+  *bitstream_len_byte = 0;
+  while (num_encoded_samples < frame_len_smpl_) {
+    // Call G.729 encoder with pointer to encoder memory, input
+    // audio, number of samples and bitsream
+    tmp_len_byte = WebRtcG729_Encode(
+        encoder_inst_ptr_, &in_audio_[in_audio_ix_read_], 80,
+        reinterpret_cast<int16_t*>(&(bitstream[*bitstream_len_byte])));
+
+    // increment the read index this tell the caller that how far
+    // we have gone forward in reading the audio buffer
+    in_audio_ix_read_ += 80;
+
+    // sanity check
+    if (tmp_len_byte < 0) {
+      // error has happened
+      *bitstream_len_byte = 0;
+      return -1;
+    }
+
+    // increment number of written bytes
+    *bitstream_len_byte += tmp_len_byte;
+    switch (tmp_len_byte) {
+      case 0: {
+        if (0 == num_encoded_samples) {
+          // this is the first 10 ms in this packet and there is
+          // no data generated, perhaps DTX is enabled and the
+          // codec is not generating any bit-stream for this 10 ms.
+          // we do not continue encoding this frame.
+          return 0;
+        }
+        break;
+      }
+      case 2: {
+        // check if G.729 internal DTX is enabled
+        if (has_internal_dtx_ && dtx_enabled_) {
+          vad_decision = 0;
+          for (int16_t n = 0; n < MAX_FRAME_SIZE_10MSEC; n++) {
+            vad_label_[n] = vad_decision;
+          }
+        }
+        // we got a SID and have to send out this packet no matter
+        // how much audio we have encoded
+        return *bitstream_len_byte;
+      }
+      case 10: {
+        vad_decision = 1;
+        // this is a valid length just continue encoding
+        break;
+      }
+      default: {
+        return -1;
+      }
+    }
+
+    // update number of encoded samples
+    num_encoded_samples += 80;
+  }
+
+  // update VAD decision vector
+  if (has_internal_dtx_ && !vad_decision && dtx_enabled_) {
+    for (int16_t n = 0; n < MAX_FRAME_SIZE_10MSEC; n++) {
+      vad_label_[n] = vad_decision;
+    }
+  }
+
+  // done encoding, return number of encoded bytes
+  return *bitstream_len_byte;
+}
+
+int16_t ACMG729::EnableDTX() {
+  if (dtx_enabled_) {
+    // DTX already enabled, do nothing
+    return 0;
+  } else if (encoder_exist_) {
+    // Re-init the G.729 encoder to turn on DTX
+    if (WebRtcG729_EncoderInit(encoder_inst_ptr_, 1) < 0) {
+      return -1;
+    }
+    dtx_enabled_ = true;
+    return 0;
+  } else {
+    return -1;
+  }
+}
+
+int16_t ACMG729::DisableDTX() {
+  if (!dtx_enabled_) {
+    // DTX already dissabled, do nothing
+    return 0;
+  } else if (encoder_exist_) {
+    // Re-init the G.729 decoder to turn off DTX
+    if (WebRtcG729_EncoderInit(encoder_inst_ptr_, 0) < 0) {
+      return -1;
+    }
+    dtx_enabled_ = false;
+    return 0;
+  } else {
+    // encoder doesn't exists, therefore disabling is harmless
+    return 0;
+  }
+}
+
+int32_t ACMG729::ReplaceInternalDTXSafe(const bool replace_internal_dtx) {
+  // This function is used to disable the G.729 built in DTX and use an
+  // external instead.
+
+  if (replace_internal_dtx == has_internal_dtx_) {
+    // Make sure we keep the DTX/VAD setting if possible
+    bool old_enable_dtx = dtx_enabled_;
+    bool old_enable_vad = vad_enabled_;
+    ACMVADMode old_mode = vad_mode_;
+    if (replace_internal_dtx) {
+      // Disable internal DTX before enabling external DTX
+      DisableDTX();
+    } else {
+      // Disable external DTX before enabling internal
+      ACMGenericCodec::DisableDTX();
+    }
+    has_internal_dtx_ = !replace_internal_dtx;
+    int16_t status = SetVADSafe(old_enable_dtx, old_enable_vad, old_mode);
+    // Check if VAD status has changed from inactive to active, or if error was
+    // reported
+    if (status == 1) {
+      vad_enabled_ = true;
+      return status;
+    } else if (status < 0) {
+      has_internal_dtx_ = replace_internal_dtx;
+      return -1;
+    }
+  }
+  return 0;
+}
+
+int32_t ACMG729::IsInternalDTXReplacedSafe(bool* internal_dtx_replaced) {
+  // Get status of wether DTX is replaced or not
+  *internal_dtx_replaced = !has_internal_dtx_;
+  return 0;
+}
+
+int16_t ACMG729::InternalInitEncoder(WebRtcACMCodecParams* codec_params) {
+  // Init G.729 encoder
+  return WebRtcG729_EncoderInit(encoder_inst_ptr_,
+                                ((codec_params->enable_dtx) ? 1 : 0));
+}
+
+ACMGenericCodec* ACMG729::CreateInstance(void) {
+  // Function not used
+  return NULL;
+}
+
+int16_t ACMG729::InternalCreateEncoder() {
+  // Create encoder memory
+  return WebRtcG729_CreateEnc(&encoder_inst_ptr_);
+}
+
+void ACMG729::DestructEncoderSafe() {
+  // Free encoder memory
+  encoder_exist_ = false;
+  encoder_initialized_ = false;
+  if (encoder_inst_ptr_ != NULL) {
+    WebRtcG729_FreeEnc(encoder_inst_ptr_);
+    encoder_inst_ptr_ = NULL;
+  }
+}
+
+void ACMG729::InternalDestructEncoderInst(void* ptr_inst) {
+  if (ptr_inst != NULL) {
+    WebRtcG729_FreeEnc(static_cast<G729_encinst_t_*>(ptr_inst));
+  }
+  return;
+}
+
+#endif
+
+}  // namespace webrtc
diff --git a/webrtc/modules/audio_coding/main/acm2/acm_g729.h b/webrtc/modules/audio_coding/main/acm2/acm_g729.h
new file mode 100644
index 0000000..3b35f3b
--- /dev/null
+++ b/webrtc/modules/audio_coding/main/acm2/acm_g729.h
@@ -0,0 +1,54 @@
+/*
+ *  Copyright (c) 2012 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_MAIN_SOURCE_ACM_G729_H_
+#define WEBRTC_MODULES_AUDIO_CODING_MAIN_SOURCE_ACM_G729_H_
+
+#include "webrtc/modules/audio_coding/main/source/acm_generic_codec.h"
+
+// forward declaration
+struct G729_encinst_t_;
+struct G729_decinst_t_;
+
+namespace webrtc {
+
+class ACMG729 : public ACMGenericCodec {
+ public:
+  explicit ACMG729(int16_t codec_id);
+  ~ACMG729();
+
+  // for FEC
+  ACMGenericCodec* CreateInstance(void);
+
+  int16_t InternalEncode(uint8_t* bitstream, int16_t* bitstream_len_byte);
+
+  int16_t InternalInitEncoder(WebRtcACMCodecParams* codec_params);
+
+ protected:
+  void DestructEncoderSafe();
+
+  int16_t InternalCreateEncoder();
+
+  void InternalDestructEncoderInst(void* ptr_inst);
+
+  int16_t EnableDTX();
+
+  int16_t DisableDTX();
+
+  int32_t ReplaceInternalDTXSafe(const bool replace_internal_dtx);
+
+  int32_t IsInternalDTXReplacedSafe(bool* internal_dtx_replaced);
+
+  G729_encinst_t_* encoder_inst_ptr_;
+};
+
+}  // namespace webrtc
+
+#endif  // WEBRTC_MODULES_AUDIO_CODING_MAIN_SOURCE_ACM_G729_H_
diff --git a/webrtc/modules/audio_coding/main/acm2/acm_g7291.cc b/webrtc/modules/audio_coding/main/acm2/acm_g7291.cc
new file mode 100644
index 0000000..1c661c1
--- /dev/null
+++ b/webrtc/modules/audio_coding/main/acm2/acm_g7291.cc
@@ -0,0 +1,240 @@
+/*
+ *  Copyright (c) 2012 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 "webrtc/modules/audio_coding/main/source/acm_g7291.h"
+
+#ifdef WEBRTC_CODEC_G729_1
+// NOTE! G.729.1 is not included in the open-source package. Modify this file
+// or your codec API to match the function calls and names of used G.729.1 API
+// file.
+#include "webrtc/modules/audio_coding/main/codecs/g7291/interface/g7291_interface.h"
+#include "webrtc/modules/audio_coding/main/source/acm_common_defs.h"
+#include "webrtc/system_wrappers/interface/trace.h"
+#endif
+
+namespace webrtc {
+
+#ifndef WEBRTC_CODEC_G729_1
+
+ACMG729_1::ACMG729_1(int16_t /* codec_id */)
+    : encoder_inst_ptr_(NULL),
+      my_rate_(32000),
+      flag_8khz_(0),
+      flag_g729_mode_(0) {
+  return;
+}
+
+ACMG729_1::~ACMG729_1() { return; }
+
+int16_t ACMG729_1::InternalEncode(uint8_t* /* bitstream */,
+                                  int16_t* /* bitstream_len_byte */) {
+  return -1;
+}
+
+int16_t ACMG729_1::InternalInitEncoder(
+    WebRtcACMCodecParams* /* codec_params */) {
+  return -1;
+}
+
+ACMGenericCodec* ACMG729_1::CreateInstance(void) { return NULL; }
+
+int16_t ACMG729_1::InternalCreateEncoder() { return -1; }
+
+void ACMG729_1::DestructEncoderSafe() { return; }
+
+void ACMG729_1::InternalDestructEncoderInst(void* /* ptr_inst */) { return; }
+
+int16_t ACMG729_1::SetBitRateSafe(const int32_t /*rate*/) { return -1; }
+
+#else  //===================== Actual Implementation =======================
+
+struct G729_1_inst_t_;
+
+ACMG729_1::ACMG729_1(int16_t codec_id)
+    : encoder_inst_ptr_(NULL),
+      my_rate_(32000),  // Default rate.
+      flag_8khz_(0),
+      flag_g729_mode_(0) {
+  // TODO(tlegrand): We should add codec_id as a input variable to the
+  // constructor of ACMGenericCodec.
+  codec_id_ = codec_id;
+  return;
+}
+
+ACMG729_1::~ACMG729_1() {
+  if (encoder_inst_ptr_ != NULL) {
+    WebRtcG7291_Free(encoder_inst_ptr_);
+    encoder_inst_ptr_ = NULL;
+  }
+  return;
+}
+
+int16_t ACMG729_1::InternalEncode(uint8_t* bitstream,
+                                  int16_t* bitstream_len_byte) {
+  // Initialize before entering the loop
+  int16_t num_encoded_samples = 0;
+  *bitstream_len_byte = 0;
+
+  int16_t byte_length_frame = 0;
+
+  // Derive number of 20ms frames per encoded packet.
+  // [1,2,3] <=> [20,40,60]ms <=> [320,640,960] samples
+  int16_t num_20ms_frames = (frame_len_smpl_ / 320);
+  // Byte length for the frame. +1 is for rate information.
+  byte_length_frame =
+      my_rate_ / (8 * 50) * num_20ms_frames + (1 - flag_g729_mode_);
+
+  // The following might be revised if we have G729.1 Annex C (support for DTX);
+  do {
+    *bitstream_len_byte = WebRtcG7291_Encode(
+        encoder_inst_ptr_, &in_audio_[in_audio_ix_read_],
+        reinterpret_cast<int16_t*>(bitstream), my_rate_, num_20ms_frames);
+
+    // increment the read index this tell the caller that how far
+    // we have gone forward in reading the audio buffer
+    in_audio_ix_read_ += 160;
+
+    // sanity check
+    if (*bitstream_len_byte < 0) {
+      // error has happened
+      WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, unique_id_,
+                   "InternalEncode: Encode error for G729_1");
+      *bitstream_len_byte = 0;
+      return -1;
+    }
+
+    num_encoded_samples += 160;
+  } while (*bitstream_len_byte == 0);
+
+  // This criteria will change if we have Annex C.
+  if (*bitstream_len_byte != byte_length_frame) {
+    WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, unique_id_,
+                 "InternalEncode: Encode error for G729_1");
+    *bitstream_len_byte = 0;
+    return -1;
+  }
+
+  if (num_encoded_samples != frame_len_smpl_) {
+    *bitstream_len_byte = 0;
+    return -1;
+  }
+
+  return *bitstream_len_byte;
+}
+
+int16_t ACMG729_1::InternalInitEncoder(WebRtcACMCodecParams* codec_params) {
+  // set the bit rate and initialize
+  my_rate_ = codec_params->codec_inst.rate;
+  return SetBitRateSafe((uint32_t)my_rate_);
+}
+
+ACMGenericCodec* ACMG729_1::CreateInstance(void) { return NULL; }
+
+int16_t ACMG729_1::InternalCreateEncoder() {
+  if (WebRtcG7291_Create(&encoder_inst_ptr_) < 0) {
+    WEBRTC_TRACE(webrtc::kTraceError,
+                 webrtc::kTraceAudioCoding,
+                 unique_id_,
+                 "InternalCreateEncoder: create encoder failed for G729_1");
+    return -1;
+  }
+  return 0;
+}
+
+void ACMG729_1::DestructEncoderSafe() {
+  encoder_exist_ = false;
+  encoder_initialized_ = false;
+  if (encoder_inst_ptr_ != NULL) {
+    WebRtcG7291_Free(encoder_inst_ptr_);
+    encoder_inst_ptr_ = NULL;
+  }
+}
+
+void ACMG729_1::InternalDestructEncoderInst(void* ptr_inst) {
+  if (ptr_inst != NULL) {
+    // WebRtcG7291_Free((G729_1_inst_t*)ptrInst);
+  }
+  return;
+}
+
+int16_t ACMG729_1::SetBitRateSafe(const int32_t rate) {
+  // allowed rates: { 8000, 12000, 14000, 16000, 18000, 20000,
+  //                22000, 24000, 26000, 28000, 30000, 32000};
+  // TODO(tlegrand): This check exists in one other place two. Should be
+  // possible to reuse code.
+  switch (rate) {
+    case 8000: {
+      my_rate_ = 8000;
+      break;
+    }
+    case 12000: {
+      my_rate_ = 12000;
+      break;
+    }
+    case 14000: {
+      my_rate_ = 14000;
+      break;
+    }
+    case 16000: {
+      my_rate_ = 16000;
+      break;
+    }
+    case 18000: {
+      my_rate_ = 18000;
+      break;
+    }
+    case 20000: {
+      my_rate_ = 20000;
+      break;
+    }
+    case 22000: {
+      my_rate_ = 22000;
+      break;
+    }
+    case 24000: {
+      my_rate_ = 24000;
+      break;
+    }
+    case 26000: {
+      my_rate_ = 26000;
+      break;
+    }
+    case 28000: {
+      my_rate_ = 28000;
+      break;
+    }
+    case 30000: {
+      my_rate_ = 30000;
+      break;
+    }
+    case 32000: {
+      my_rate_ = 32000;
+      break;
+    }
+    default: {
+      WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, unique_id_,
+                   "SetBitRateSafe: Invalid rate G729_1");
+      return -1;
+    }
+  }
+
+  // Re-init with new rate
+  if (WebRtcG7291_EncoderInit(encoder_inst_ptr_, my_rate_, flag_8khz_,
+                              flag_g729_mode_) >= 0) {
+    encoder_params_.codec_inst.rate = my_rate_;
+    return 0;
+  } else {
+    return -1;
+  }
+}
+
+#endif
+
+}  // namespace webrtc
diff --git a/webrtc/modules/audio_coding/main/acm2/acm_g7291.h b/webrtc/modules/audio_coding/main/acm2/acm_g7291.h
new file mode 100644
index 0000000..97601ea
--- /dev/null
+++ b/webrtc/modules/audio_coding/main/acm2/acm_g7291.h
@@ -0,0 +1,52 @@
+/*
+ *  Copyright (c) 2012 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_MAIN_SOURCE_ACM_G7291_H_
+#define WEBRTC_MODULES_AUDIO_CODING_MAIN_SOURCE_ACM_G7291_H_
+
+#include "webrtc/modules/audio_coding/main/source/acm_generic_codec.h"
+
+// forward declaration
+struct G729_1_inst_t_;
+struct G729_1_inst_t_;
+
+namespace webrtc {
+
+class ACMG729_1 : public ACMGenericCodec {
+ public:
+  explicit ACMG729_1(int16_t codec_id);
+  ~ACMG729_1();
+
+  // for FEC
+  ACMGenericCodec* CreateInstance(void);
+
+  int16_t InternalEncode(uint8_t* bitstream, int16_t* bitstream_len_byte);
+
+  int16_t InternalInitEncoder(WebRtcACMCodecParams* codec_params);
+
+ protected:
+  void DestructEncoderSafe();
+
+  int16_t InternalCreateEncoder();
+
+  void InternalDestructEncoderInst(void* ptr_inst);
+
+  int16_t SetBitRateSafe(const int32_t rate);
+
+  G729_1_inst_t_* encoder_inst_ptr_;
+
+  uint16_t my_rate_;
+  int16_t flag_8khz_;
+  int16_t flag_g729_mode_;
+};
+
+}  // namespace webrtc
+
+#endif  // WEBRTC_MODULES_AUDIO_CODING_MAIN_SOURCE_ACM_G7291_H_
diff --git a/webrtc/modules/audio_coding/main/acm2/acm_generic_codec.cc b/webrtc/modules/audio_coding/main/acm2/acm_generic_codec.cc
new file mode 100644
index 0000000..5e210ef
--- /dev/null
+++ b/webrtc/modules/audio_coding/main/acm2/acm_generic_codec.cc
@@ -0,0 +1,995 @@
+/*
+ *  Copyright (c) 2012 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 "webrtc/modules/audio_coding/main/source/acm_generic_codec.h"
+
+#include <assert.h>
+#include <string.h>
+
+#include "webrtc/common_audio/vad/include/webrtc_vad.h"
+#include "webrtc/modules/audio_coding/codecs/cng/include/webrtc_cng.h"
+#include "webrtc/modules/audio_coding/main/source/acm_codec_database.h"
+#include "webrtc/modules/audio_coding/main/source/acm_common_defs.h"
+#include "webrtc/system_wrappers/interface/trace.h"
+
+namespace webrtc {
+
+// Enum for CNG
+enum {
+  kMaxPLCParamsCNG = WEBRTC_CNG_MAX_LPC_ORDER,
+  kNewCNGNumPLCParams = 8
+};
+
+// Interval for sending new CNG parameters (SID frames) is 100 msec.
+enum {
+  kCngSidIntervalMsec = 100
+};
+
+// We set some of the variables to invalid values as a check point
+// if a proper initialization has happened. Another approach is
+// to initialize to a default codec that we are sure is always included.
+ACMGenericCodec::ACMGenericCodec()
+    : in_audio_ix_write_(0),
+      in_audio_ix_read_(0),
+      in_timestamp_ix_write_(0),
+      in_audio_(NULL),
+      in_timestamp_(NULL),
+      frame_len_smpl_(-1),  // invalid value
+      num_channels_(1),
+      codec_id_(-1),  // invalid value
+      num_missed_samples_(0),
+      encoder_exist_(false),
+      encoder_initialized_(false),
+      registered_in_neteq_(false),
+      has_internal_dtx_(false),
+      ptr_vad_inst_(NULL),
+      vad_enabled_(false),
+      vad_mode_(VADNormal),
+      dtx_enabled_(false),
+      ptr_dtx_inst_(NULL),
+      num_lpc_params_(kNewCNGNumPLCParams),
+      sent_cn_previous_(false),
+      prev_frame_cng_(0),
+      neteq_decode_lock_(NULL),
+      codec_wrapper_lock_(*RWLockWrapper::CreateRWLock()),
+      last_timestamp_(0xD87F3F9F),
+      unique_id_(0) {
+  // Initialize VAD vector.
+  for (int i = 0; i < MAX_FRAME_SIZE_10MSEC; i++) {
+    vad_label_[i] = 0;
+  }
+  // Nullify memory for encoder and decoder, and set payload type to an
+  // invalid value.
+  memset(&encoder_params_, 0, sizeof(WebRtcACMCodecParams));
+  encoder_params_.codec_inst.pltype = -1;
+}
+
+ACMGenericCodec::~ACMGenericCodec() {
+  // Check all the members which are pointers, and if they are not NULL
+  // delete/free them.
+  if (ptr_vad_inst_ != NULL) {
+    WebRtcVad_Free(ptr_vad_inst_);
+    ptr_vad_inst_ = NULL;
+  }
+  if (in_audio_ != NULL) {
+    delete[] in_audio_;
+    in_audio_ = NULL;
+  }
+  if (in_timestamp_ != NULL) {
+    delete[] in_timestamp_;
+    in_timestamp_ = NULL;
+  }
+  if (ptr_dtx_inst_ != NULL) {
+    WebRtcCng_FreeEnc(ptr_dtx_inst_);
+    ptr_dtx_inst_ = NULL;
+  }
+  delete &codec_wrapper_lock_;
+}
+
+int32_t ACMGenericCodec::Add10MsData(const uint32_t timestamp,
+                                     const int16_t* data,
+                                     const uint16_t length_smpl,
+                                     const uint8_t audio_channel) {
+  WriteLockScoped wl(codec_wrapper_lock_);
+  return Add10MsDataSafe(timestamp, data, length_smpl, audio_channel);
+}
+
+int32_t ACMGenericCodec::Add10MsDataSafe(const uint32_t timestamp,
+                                         const int16_t* data,
+                                         const uint16_t length_smpl,
+                                         const uint8_t audio_channel) {
+  // The codec expects to get data in correct sampling rate. Get the sampling
+  // frequency of the codec.
+  uint16_t plfreq_hz;
+  if (EncoderSampFreq(&plfreq_hz) < 0) {
+    return -1;
+  }
+
+  // Sanity check to make sure the length of the input corresponds to 10 ms.
+  if ((plfreq_hz / 100) != length_smpl) {
+    // This is not 10 ms of audio, given the sampling frequency of the codec.
+    return -1;
+  }
+
+  if (last_timestamp_ == timestamp) {
+    // Same timestamp as the last time, overwrite.
+    if ((in_audio_ix_write_ >= length_smpl * audio_channel) &&
+        (in_timestamp_ix_write_ > 0)) {
+      in_audio_ix_write_ -= length_smpl * audio_channel;
+      in_timestamp_ix_write_--;
+      WEBRTC_TRACE(webrtc::kTraceDebug, webrtc::kTraceAudioCoding, unique_id_,
+                   "Adding 10ms with previous timestamp, overwriting the "
+                   "previous 10ms");
+    } else {
+      WEBRTC_TRACE(webrtc::kTraceDebug, webrtc::kTraceAudioCoding, unique_id_,
+                   "Adding 10ms with previous timestamp, this will sound bad");
+    }
+  }
+
+  last_timestamp_ = timestamp;
+
+  // If the data exceeds the buffer size, we throw away the oldest data and
+  // add the newly received 10 msec at the end.
+  if ((in_audio_ix_write_ + length_smpl * audio_channel) >
+      AUDIO_BUFFER_SIZE_W16) {
+    // Get the number of samples to be overwritten.
+    int16_t missed_samples = in_audio_ix_write_ + length_smpl * audio_channel -
+        AUDIO_BUFFER_SIZE_W16;
+
+    // Move the data (overwrite the old data).
+    memmove(in_audio_, in_audio_ + missed_samples,
+            (AUDIO_BUFFER_SIZE_W16 - length_smpl * audio_channel) *
+            sizeof(int16_t));
+
+    // Copy the new data.
+    memcpy(in_audio_ + (AUDIO_BUFFER_SIZE_W16 - length_smpl * audio_channel),
+           data, length_smpl * audio_channel * sizeof(int16_t));
+
+    // Get the number of 10 ms blocks which are overwritten.
+    int16_t missed_10ms_blocks =static_cast<int16_t>(
+        (missed_samples / audio_channel * 100) / plfreq_hz);
+
+    // Move the timestamps.
+    memmove(in_timestamp_, in_timestamp_ + missed_10ms_blocks,
+            (in_timestamp_ix_write_ - missed_10ms_blocks) * sizeof(uint32_t));
+    in_timestamp_ix_write_ -= missed_10ms_blocks;
+    in_timestamp_[in_timestamp_ix_write_] = timestamp;
+    in_timestamp_ix_write_++;
+
+    // Buffer is full.
+    in_audio_ix_write_ = AUDIO_BUFFER_SIZE_W16;
+    IncreaseNoMissedSamples(missed_samples);
+    return -missed_samples;
+  }
+
+  // Store the input data in our data buffer.
+  memcpy(in_audio_ + in_audio_ix_write_, data,
+         length_smpl * audio_channel * sizeof(int16_t));
+  in_audio_ix_write_ += length_smpl * audio_channel;
+
+  assert(in_timestamp_ix_write_ < TIMESTAMP_BUFFER_SIZE_W32);
+  assert(in_timestamp_ix_write_ >= 0);
+
+  in_timestamp_[in_timestamp_ix_write_] = timestamp;
+  in_timestamp_ix_write_++;
+  return 0;
+}
+
+bool ACMGenericCodec::HasFrameToEncode() const {
+  ReadLockScoped lockCodec(codec_wrapper_lock_);
+  if (in_audio_ix_write_ < frame_len_smpl_ * num_channels_)
+    return false;
+  return true;
+}
+
+int16_t ACMGenericCodec::Encode(uint8_t* bitstream,
+                                int16_t* bitstream_len_byte,
+                                uint32_t* timestamp,
+                                WebRtcACMEncodingType* encoding_type) {
+  if (!HasFrameToEncode()) {
+    // There is not enough audio
+    *timestamp = 0;
+    *bitstream_len_byte = 0;
+    // Doesn't really matter what this parameter set to
+    *encoding_type = kNoEncoding;
+    return 0;
+  }
+  WriteLockScoped lockCodec(codec_wrapper_lock_);
+  ReadLockScoped lockNetEq(*neteq_decode_lock_);
+
+  // Not all codecs accept the whole frame to be pushed into encoder at once.
+  // Some codecs needs to be feed with a specific number of samples different
+  // from the frame size. If this is the case, |myBasicCodingBlockSmpl| will
+  // report a number different from 0, and we will loop over calls to encoder
+  // further down, until we have encode a complete frame.
+  const int16_t my_basic_coding_block_smpl =
+      ACMCodecDB::BasicCodingBlock(codec_id_);
+  if (my_basic_coding_block_smpl < 0 || !encoder_initialized_ ||
+      !encoder_exist_) {
+    // This should not happen, but in case it does, report no encoding done.
+    *timestamp = 0;
+    *bitstream_len_byte = 0;
+    *encoding_type = kNoEncoding;
+    WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, unique_id_,
+                 "EncodeSafe: error, basic coding sample block is negative");
+    return -1;
+  }
+  // This makes the internal encoder read from the beginning of the buffer.
+  in_audio_ix_read_ = 0;
+  *timestamp = in_timestamp_[0];
+
+  // Process the audio through VAD. The function will set |_vad_labels|.
+  // If VAD is disabled all entries in |_vad_labels| are set to ONE (active).
+  int16_t status = 0;
+  int16_t dtx_processed_samples = 0;
+  status = ProcessFrameVADDTX(bitstream, bitstream_len_byte,
+                              &dtx_processed_samples);
+  if (status < 0) {
+    *timestamp = 0;
+    *bitstream_len_byte = 0;
+    *encoding_type = kNoEncoding;
+  } else {
+    if (dtx_processed_samples > 0) {
+      // Dtx have processed some samples, and even if a bit-stream is generated
+      // we should not do any encoding (normally there won't be enough data).
+
+      // Setting the following makes sure that the move of audio data and
+      // timestamps done correctly.
+      in_audio_ix_read_ = dtx_processed_samples;
+      // This will let the owner of ACMGenericCodec to know that the
+      // generated bit-stream is DTX to use correct payload type.
+      uint16_t samp_freq_hz;
+      EncoderSampFreq(&samp_freq_hz);
+      if (samp_freq_hz == 8000) {
+        *encoding_type = kPassiveDTXNB;
+      } else if (samp_freq_hz == 16000) {
+        *encoding_type = kPassiveDTXWB;
+      } else if (samp_freq_hz == 32000) {
+        *encoding_type = kPassiveDTXSWB;
+      } else if (samp_freq_hz == 48000) {
+        *encoding_type = kPassiveDTXFB;
+      } else {
+        status = -1;
+        WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, unique_id_,
+                     "EncodeSafe: Wrong sampling frequency for DTX.");
+      }
+
+      // Transport empty frame if we have an empty bitstream.
+      if ((*bitstream_len_byte == 0) &&
+          (sent_cn_previous_ ||
+          ((in_audio_ix_write_ - in_audio_ix_read_) <= 0))) {
+        // Makes sure we transmit an empty frame.
+        *bitstream_len_byte = 1;
+        *encoding_type = kNoEncoding;
+      }
+      sent_cn_previous_ = true;
+    } else {
+      // We should encode the audio frame. Either VAD and/or DTX is off, or the
+      // audio was considered "active".
+
+      sent_cn_previous_ = false;
+      if (my_basic_coding_block_smpl == 0) {
+        // This codec can handle all allowed frame sizes as basic coding block.
+        status = InternalEncode(bitstream, bitstream_len_byte);
+        if (status < 0) {
+          // TODO(tlegrand): Maybe reseting the encoder to be fresh for the next
+          // frame.
+          WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding,
+                       unique_id_, "EncodeSafe: error in internal_encode");
+          *bitstream_len_byte = 0;
+          *encoding_type = kNoEncoding;
+        }
+      } else {
+        // A basic-coding-block for this codec is defined so we loop over the
+        // audio with the steps of the basic-coding-block.
+        int16_t tmp_bitstream_len_byte;
+
+        // Reset the variables which will be incremented in the loop.
+        *bitstream_len_byte = 0;
+        bool done = false;
+        while (!done) {
+          status = InternalEncode(&bitstream[*bitstream_len_byte],
+                                  &tmp_bitstream_len_byte);
+          *bitstream_len_byte += tmp_bitstream_len_byte;
+
+          // Guard Against errors and too large payloads.
+          if ((status < 0) || (*bitstream_len_byte > MAX_PAYLOAD_SIZE_BYTE)) {
+            // Error has happened, and even if we are in the middle of a full
+            // frame we have to exit. Before exiting, whatever bits are in the
+            // buffer are probably corrupted, so we ignore them.
+            *bitstream_len_byte = 0;
+            *encoding_type = kNoEncoding;
+            // We might have come here because of the second condition.
+            status = -1;
+            WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding,
+                         unique_id_, "EncodeSafe: error in InternalEncode");
+            // break from the loop
+            break;
+          }
+
+          // TODO(andrew): This should be multiplied by the number of
+          //               channels, right?
+          // http://code.google.com/p/webrtc/issues/detail?id=714
+          done = in_audio_ix_read_ >= frame_len_smpl_;
+        }
+      }
+      if (status >= 0) {
+        *encoding_type = (vad_label_[0] == 1) ? kActiveNormalEncoded :
+            kPassiveNormalEncoded;
+        // Transport empty frame if we have an empty bitstream.
+        if ((*bitstream_len_byte == 0) &&
+            ((in_audio_ix_write_ - in_audio_ix_read_) <= 0)) {
+          // Makes sure we transmit an empty frame.
+          *bitstream_len_byte = 1;
+          *encoding_type = kNoEncoding;
+        }
+      }
+    }
+  }
+
+  // Move the timestamp buffer according to the number of 10 ms blocks
+  // which are read.
+  uint16_t samp_freq_hz;
+  EncoderSampFreq(&samp_freq_hz);
+  int16_t num_10ms_blocks = static_cast<int16_t>(
+      (in_audio_ix_read_ / num_channels_ * 100) / samp_freq_hz);
+  if (in_timestamp_ix_write_ > num_10ms_blocks) {
+    memmove(in_timestamp_, in_timestamp_ + num_10ms_blocks,
+            (in_timestamp_ix_write_ - num_10ms_blocks) * sizeof(int32_t));
+  }
+  in_timestamp_ix_write_ -= num_10ms_blocks;
+
+  // Remove encoded audio and move next audio to be encoded to the beginning
+  // of the buffer. Accordingly, adjust the read and write indices.
+  if (in_audio_ix_read_ < in_audio_ix_write_) {
+    memmove(in_audio_, &in_audio_[in_audio_ix_read_],
+            (in_audio_ix_write_ - in_audio_ix_read_) * sizeof(int16_t));
+  }
+  in_audio_ix_write_ -= in_audio_ix_read_;
+  in_audio_ix_read_ = 0;
+  return (status < 0) ? (-1) : (*bitstream_len_byte);
+}
+
+bool ACMGenericCodec::EncoderInitialized() {
+  ReadLockScoped rl(codec_wrapper_lock_);
+  return encoder_initialized_;
+}
+
+int16_t ACMGenericCodec::EncoderParams(WebRtcACMCodecParams* enc_params) {
+  ReadLockScoped rl(codec_wrapper_lock_);
+  return EncoderParamsSafe(enc_params);
+}
+
+int16_t ACMGenericCodec::EncoderParamsSafe(WebRtcACMCodecParams* enc_params) {
+  // Codec parameters are valid only if the encoder is initialized.
+  if (encoder_initialized_) {
+    int32_t current_rate;
+    memcpy(enc_params, &encoder_params_, sizeof(WebRtcACMCodecParams));
+    current_rate = enc_params->codec_inst.rate;
+    CurrentRate(&current_rate);
+    enc_params->codec_inst.rate = current_rate;
+    return 0;
+  } else {
+    enc_params->codec_inst.plname[0] = '\0';
+    enc_params->codec_inst.pltype = -1;
+    enc_params->codec_inst.pacsize = 0;
+    enc_params->codec_inst.rate = 0;
+    WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, unique_id_,
+                 "EncoderParamsSafe: error, encoder not initialized");
+    return -1;
+  }
+}
+
+int16_t ACMGenericCodec::ResetEncoder() {
+  WriteLockScoped lockCodec(codec_wrapper_lock_);
+  ReadLockScoped lockNetEq(*neteq_decode_lock_);
+  return ResetEncoderSafe();
+}
+
+int16_t ACMGenericCodec::ResetEncoderSafe() {
+  if (!encoder_exist_ || !encoder_initialized_) {
+    // We don't reset if encoder doesn't exists or isn't initialized yet.
+    return 0;
+  }
+
+  in_audio_ix_write_ = 0;
+  in_audio_ix_read_ = 0;
+  in_timestamp_ix_write_ = 0;
+  num_missed_samples_ = 0;
+  memset(in_audio_, 0, AUDIO_BUFFER_SIZE_W16 * sizeof(int16_t));
+  memset(in_timestamp_, 0, TIMESTAMP_BUFFER_SIZE_W32 * sizeof(int32_t));
+
+  // Store DTX/VAD parameters.
+  bool enable_vad = vad_enabled_;
+  bool enable_dtx = dtx_enabled_;
+  ACMVADMode mode = vad_mode_;
+
+  // Reset the encoder.
+  if (InternalResetEncoder() < 0) {
+    WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, unique_id_,
+                 "ResetEncoderSafe: error in reset encoder");
+    return -1;
+  }
+
+  // Disable DTX & VAD to delete the states and have a fresh start.
+  DisableDTX();
+  DisableVAD();
+
+  // Set DTX/VAD.
+  return SetVADSafe(enable_dtx, enable_vad, mode);
+}
+
+int16_t ACMGenericCodec::InternalResetEncoder() {
+  // Call the codecs internal encoder initialization/reset function.
+  return InternalInitEncoder(&encoder_params_);
+}
+
+int16_t ACMGenericCodec::InitEncoder(WebRtcACMCodecParams* codec_params,
+                                     bool force_initialization) {
+  WriteLockScoped lockCodec(codec_wrapper_lock_);
+  ReadLockScoped lockNetEq(*neteq_decode_lock_);
+  return InitEncoderSafe(codec_params, force_initialization);
+}
+
+int16_t ACMGenericCodec::InitEncoderSafe(WebRtcACMCodecParams* codec_params,
+                                         bool force_initialization) {
+  // Check if we got a valid set of parameters.
+  int mirrorID;
+  int codec_number = ACMCodecDB::CodecNumber(codec_params->codec_inst,
+                                             &mirrorID);
+  if (codec_number < 0) {
+    WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, unique_id_,
+                 "InitEncoderSafe: error, codec number negative");
+    return -1;
+  }
+  // Check if the parameters are for this codec.
+  if ((codec_id_ >= 0) && (codec_id_ != codec_number) &&
+      (codec_id_ != mirrorID)) {
+    // The current codec is not the same as the one given by codec_params.
+    WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, unique_id_,
+                 "InitEncoderSafe: current codec is not the same as the one "
+                 "given by codec_params");
+    return -1;
+  }
+
+  if (encoder_initialized_ && !force_initialization) {
+    // The encoder is already initialized, and we don't want to force
+    // initialization.
+    return 0;
+  }
+  int16_t status;
+  if (!encoder_exist_) {
+    // New encoder, start with creating.
+    encoder_initialized_ = false;
+    status = CreateEncoder();
+    if (status < 0) {
+      WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, unique_id_,
+                   "InitEncoderSafe: cannot create encoder");
+      return -1;
+    } else {
+      encoder_exist_ = true;
+    }
+  }
+  frame_len_smpl_ = (codec_params->codec_inst).pacsize;
+  num_channels_ = codec_params->codec_inst.channels;
+  status = InternalInitEncoder(codec_params);
+  if (status < 0) {
+    WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, unique_id_,
+                 "InitEncoderSafe: error in init encoder");
+    encoder_initialized_ = false;
+    return -1;
+  } else {
+    // Store encoder parameters.
+    memcpy(&encoder_params_, codec_params, sizeof(WebRtcACMCodecParams));
+    encoder_initialized_ = true;
+    if (in_audio_ == NULL) {
+      in_audio_ = new int16_t[AUDIO_BUFFER_SIZE_W16];
+      if (in_audio_ == NULL) {
+        return -1;
+      }
+      memset(in_audio_, 0, AUDIO_BUFFER_SIZE_W16 * sizeof(int16_t));
+    }
+    if (in_timestamp_ == NULL) {
+      in_timestamp_ = new uint32_t[TIMESTAMP_BUFFER_SIZE_W32];
+      if (in_timestamp_ == NULL) {
+        return -1;
+      }
+      memset(in_timestamp_, 0, sizeof(uint32_t) * TIMESTAMP_BUFFER_SIZE_W32);
+    }
+  }
+  status = SetVADSafe(codec_params->enable_dtx, codec_params->enable_vad,
+                      codec_params->vad_mode);
+
+  return status;
+}
+
+void ACMGenericCodec::ResetNoMissedSamples() {
+  WriteLockScoped cs(codec_wrapper_lock_);
+  num_missed_samples_ = 0;
+}
+
+void ACMGenericCodec::IncreaseNoMissedSamples(const int16_t num_samples) {
+  num_missed_samples_ += num_samples;
+}
+
+// Get the number of missed samples, this can be public.
+uint32_t ACMGenericCodec::NoMissedSamples() const {
+  ReadLockScoped cs(codec_wrapper_lock_);
+  return num_missed_samples_;
+}
+
+void ACMGenericCodec::DestructEncoder() {
+  WriteLockScoped wl(codec_wrapper_lock_);
+
+  // Disable VAD and delete the instance.
+  if (ptr_vad_inst_ != NULL) {
+    WebRtcVad_Free(ptr_vad_inst_);
+    ptr_vad_inst_ = NULL;
+  }
+  vad_enabled_ = false;
+  vad_mode_ = VADNormal;
+
+  // Disable DTX and delete the instance.
+  dtx_enabled_ = false;
+  if (ptr_dtx_inst_ != NULL) {
+    WebRtcCng_FreeEnc(ptr_dtx_inst_);
+    ptr_dtx_inst_ = NULL;
+  }
+  num_lpc_params_ = kNewCNGNumPLCParams;
+
+  DestructEncoderSafe();
+}
+
+int16_t ACMGenericCodec::SetBitRate(const int32_t bitrate_bps) {
+  WriteLockScoped wl(codec_wrapper_lock_);
+  return SetBitRateSafe(bitrate_bps);
+}
+
+int16_t ACMGenericCodec::SetBitRateSafe(const int32_t bitrate_bps) {
+  // If the codec can change the bit-rate this function is overloaded.
+  // Otherwise the only acceptable value is the one that is in the database.
+  CodecInst codec_params;
+  if (ACMCodecDB::Codec(codec_id_, &codec_params) < 0) {
+    WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, unique_id_,
+                 "SetBitRateSafe: error in ACMCodecDB::Codec");
+    return -1;
+  }
+  if (codec_params.rate != bitrate_bps) {
+    WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, unique_id_,
+                 "SetBitRateSafe: rate value is not acceptable");
+    return -1;
+  } else {
+    return 0;
+  }
+}
+
+// iSAC specific functions:
+int32_t ACMGenericCodec::GetEstimatedBandwidth() {
+  WriteLockScoped wl(codec_wrapper_lock_);
+  return GetEstimatedBandwidthSafe();
+}
+
+int32_t ACMGenericCodec::GetEstimatedBandwidthSafe() {
+  // All codecs but iSAC will return -1.
+  return -1;
+}
+
+int32_t ACMGenericCodec::SetEstimatedBandwidth(int32_t estimated_bandwidth) {
+  WriteLockScoped wl(codec_wrapper_lock_);
+  return SetEstimatedBandwidthSafe(estimated_bandwidth);
+}
+
+int32_t ACMGenericCodec::SetEstimatedBandwidthSafe(
+    int32_t /*estimated_bandwidth*/) {
+  // All codecs but iSAC will return -1.
+  return -1;
+}
+// End of iSAC specific functions.
+
+int32_t ACMGenericCodec::GetRedPayload(uint8_t* red_payload,
+                                       int16_t* payload_bytes) {
+  WriteLockScoped wl(codec_wrapper_lock_);
+  return GetRedPayloadSafe(red_payload, payload_bytes);
+}
+
+int32_t ACMGenericCodec::GetRedPayloadSafe(uint8_t* /* red_payload */,
+                                           int16_t* /* payload_bytes */) {
+  return -1;  // Do nothing by default.
+}
+
+int16_t ACMGenericCodec::CreateEncoder() {
+  int16_t status = 0;
+  if (!encoder_exist_) {
+    status = InternalCreateEncoder();
+    // We just created the codec and obviously it is not initialized.
+    encoder_initialized_ = false;
+  }
+  if (status < 0) {
+    WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, unique_id_,
+                 "CreateEncoder: error in internal create encoder");
+    encoder_exist_ = false;
+  } else {
+    encoder_exist_ = true;
+  }
+  return status;
+}
+
+void ACMGenericCodec::DestructEncoderInst(void* ptr_inst) {
+  if (ptr_inst != NULL) {
+    WriteLockScoped lockCodec(codec_wrapper_lock_);
+    ReadLockScoped lockNetEq(*neteq_decode_lock_);
+    InternalDestructEncoderInst(ptr_inst);
+  }
+}
+
+uint32_t ACMGenericCodec::EarliestTimestamp() const {
+  ReadLockScoped cs(codec_wrapper_lock_);
+  return in_timestamp_[0];
+}
+
+int16_t ACMGenericCodec::SetVAD(const bool enable_dtx,
+                                const bool enable_vad,
+                                const ACMVADMode mode) {
+  WriteLockScoped cs(codec_wrapper_lock_);
+  return SetVADSafe(enable_dtx, enable_vad, mode);
+}
+
+int16_t ACMGenericCodec::SetVADSafe(const bool enable_dtx,
+                                    const bool enable_vad,
+                                    const ACMVADMode mode) {
+  if (enable_dtx) {
+    // Make G729 AnnexB a special case.
+    if (!STR_CASE_CMP(encoder_params_.codec_inst.plname, "G729")
+        && !has_internal_dtx_) {
+      if (ACMGenericCodec::EnableDTX() < 0) {
+        WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, unique_id_,
+                     "SetVADSafe: error in enable DTX");
+        return -1;
+      }
+    } else {
+      if (EnableDTX() < 0) {
+        WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, unique_id_,
+                     "SetVADSafe: error in enable DTX");
+        return -1;
+      }
+    }
+
+    if (has_internal_dtx_) {
+      // Codec has internal DTX, practically we don't need WebRtc VAD, however,
+      // we let the user to turn it on if they need call-backs on silence.
+      // Store VAD mode for future even if VAD is off.
+      vad_mode_ = mode;
+      return (enable_vad) ? EnableVAD(mode) : DisableVAD();
+    } else {
+      // Codec does not have internal DTX so enabling DTX requires an active
+      // VAD. 'enable_dtx == true' overwrites VAD status.
+      if (EnableVAD(mode) < 0) {
+        // If we cannot create VAD we have to disable DTX.
+        if (!vad_enabled_) {
+          DisableDTX();
+        }
+        WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, unique_id_,
+                     "SetVADSafe: error in enable VAD");
+        return -1;
+      }
+
+      // Return '1', to let the caller know VAD was turned on, even if the
+      // function was called with VAD='false'.
+      if (enable_vad == false) {
+        return 1;
+      } else {
+        return 0;
+      }
+    }
+  } else {
+    // Make G729 AnnexB a special case.
+    if (!STR_CASE_CMP(encoder_params_.codec_inst.plname, "G729")
+        && !has_internal_dtx_) {
+      ACMGenericCodec::DisableDTX();
+    } else {
+      DisableDTX();
+    }
+    return (enable_vad) ? EnableVAD(mode) : DisableVAD();
+  }
+}
+
+int16_t ACMGenericCodec::EnableDTX() {
+  if (has_internal_dtx_) {
+    // We should not be here if we have internal DTX this function should be
+    // overloaded by the derived class in this case.
+    return -1;
+  }
+  if (!dtx_enabled_) {
+    if (WebRtcCng_CreateEnc(&ptr_dtx_inst_) < 0) {
+      ptr_dtx_inst_ = NULL;
+      return -1;
+    }
+    uint16_t freq_hz;
+    EncoderSampFreq(&freq_hz);
+    if (WebRtcCng_InitEnc(ptr_dtx_inst_, freq_hz, kCngSidIntervalMsec,
+                          num_lpc_params_) < 0) {
+      // Couldn't initialize, has to return -1, and free the memory.
+      WebRtcCng_FreeEnc(ptr_dtx_inst_);
+      ptr_dtx_inst_ = NULL;
+      return -1;
+    }
+    dtx_enabled_ = true;
+  }
+  return 0;
+}
+
+int16_t ACMGenericCodec::DisableDTX() {
+  if (has_internal_dtx_) {
+    // We should not be here if we have internal DTX this function should be
+    // overloaded by the derived class in this case.
+    return -1;
+  }
+  if (ptr_dtx_inst_ != NULL) {
+    WebRtcCng_FreeEnc(ptr_dtx_inst_);
+    ptr_dtx_inst_ = NULL;
+  }
+  dtx_enabled_ = false;
+  return 0;
+}
+
+int16_t ACMGenericCodec::EnableVAD(ACMVADMode mode) {
+  if ((mode < VADNormal) || (mode > VADVeryAggr)) {
+    WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, unique_id_,
+                 "EnableVAD: error in VAD mode range");
+    return -1;
+  }
+
+  if (!vad_enabled_) {
+    if (WebRtcVad_Create(&ptr_vad_inst_) < 0) {
+      ptr_vad_inst_ = NULL;
+      WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, unique_id_,
+                   "EnableVAD: error in create VAD");
+      return -1;
+    }
+    if (WebRtcVad_Init(ptr_vad_inst_) < 0) {
+      WebRtcVad_Free(ptr_vad_inst_);
+      ptr_vad_inst_ = NULL;
+      WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, unique_id_,
+                   "EnableVAD: error in init VAD");
+      return -1;
+    }
+  }
+
+  // Set the VAD mode to the given value.
+  if (WebRtcVad_set_mode(ptr_vad_inst_, mode) < 0) {
+    // We failed to set the mode and we have to return -1. If we already have a
+    // working VAD (vad_enabled_ == true) then we leave it to work. Otherwise,
+    // the following will be executed.
+    if (!vad_enabled_) {
+      // We just created the instance but cannot set the mode we have to free
+      // the memory.
+      WebRtcVad_Free(ptr_vad_inst_);
+      ptr_vad_inst_ = NULL;
+    }
+    WEBRTC_TRACE(webrtc::kTraceDebug, webrtc::kTraceAudioCoding, unique_id_,
+                 "EnableVAD: failed to set the VAD mode");
+    return -1;
+  }
+  vad_mode_ = mode;
+  vad_enabled_ = true;
+  return 0;
+}
+
+int16_t ACMGenericCodec::DisableVAD() {
+  if (ptr_vad_inst_ != NULL) {
+    WebRtcVad_Free(ptr_vad_inst_);
+    ptr_vad_inst_ = NULL;
+  }
+  vad_enabled_ = false;
+  return 0;
+}
+
+int32_t ACMGenericCodec::ReplaceInternalDTX(const bool replace_internal_dtx) {
+  WriteLockScoped cs(codec_wrapper_lock_);
+  return ReplaceInternalDTXSafe(replace_internal_dtx);
+}
+
+int32_t ACMGenericCodec::ReplaceInternalDTXSafe(
+    const bool /* replace_internal_dtx */) {
+  return -1;
+}
+
+int32_t ACMGenericCodec::IsInternalDTXReplaced(bool* internal_dtx_replaced) {
+  WriteLockScoped cs(codec_wrapper_lock_);
+  return IsInternalDTXReplacedSafe(internal_dtx_replaced);
+}
+
+int32_t ACMGenericCodec::IsInternalDTXReplacedSafe(
+    bool* internal_dtx_replaced) {
+  *internal_dtx_replaced = false;
+  return 0;
+}
+
+int16_t ACMGenericCodec::ProcessFrameVADDTX(uint8_t* bitstream,
+                                            int16_t* bitstream_len_byte,
+                                            int16_t* samples_processed) {
+  if (!vad_enabled_) {
+    // VAD not enabled, set all |vad_lable_[]| to 1 (speech detected).
+    for (int n = 0; n < MAX_FRAME_SIZE_10MSEC; n++) {
+      vad_label_[n] = 1;
+    }
+    *samples_processed = 0;
+    return 0;
+  }
+
+  uint16_t freq_hz;
+  EncoderSampFreq(&freq_hz);
+
+  // Calculate number of samples in 10 ms blocks, and number ms in one frame.
+  int16_t samples_in_10ms = static_cast<int16_t>(freq_hz / 100);
+  int32_t frame_len_ms = static_cast<int32_t>(frame_len_smpl_) * 1000 / freq_hz;
+  int16_t status;
+
+  // Vector for storing maximum 30 ms of mono audio at 48 kHz.
+  int16_t audio[1440];
+
+  // Calculate number of VAD-blocks to process, and number of samples in each
+  // block.
+  int num_samples_to_process[2];
+  if (frame_len_ms == 40) {
+    // 20 ms in each VAD block.
+    num_samples_to_process[0] = num_samples_to_process[1] = 2 * samples_in_10ms;
+  } else {
+    // For 10-30 ms framesizes, second VAD block will be size zero ms,
+    // for 50 and 60 ms first VAD block will be 30 ms.
+    num_samples_to_process[0] =
+        (frame_len_ms > 30) ? 3 * samples_in_10ms : frame_len_smpl_;
+    num_samples_to_process[1] = frame_len_smpl_ - num_samples_to_process[0];
+  }
+
+  int offset = 0;
+  int loops = (num_samples_to_process[1] > 0) ? 2 : 1;
+  for (int i = 0; i < loops; i++) {
+    // TODO(turajs): Do we need to care about VAD together with stereo?
+    // If stereo, calculate mean of the two channels.
+    if (num_channels_ == 2) {
+      for (int j = 0; j < num_samples_to_process[i]; j++) {
+        audio[j] = (in_audio_[(offset + j) * 2] +
+            in_audio_[(offset + j) * 2 + 1]) / 2;
+      }
+      offset = num_samples_to_process[0];
+    } else {
+      // Mono, copy data from in_audio_ to continue work on.
+      memcpy(audio, in_audio_, sizeof(int16_t) * num_samples_to_process[i]);
+    }
+
+    // Call VAD.
+    status = static_cast<int16_t>(WebRtcVad_Process(ptr_vad_inst_,
+                                                    static_cast<int>(freq_hz),
+                                                    audio,
+                                                    num_samples_to_process[i]));
+    vad_label_[i] = status;
+
+    if (status < 0) {
+      // This will force that the data be removed from the buffer.
+      *samples_processed += num_samples_to_process[i];
+      return -1;
+    }
+
+    // If VAD decision non-active, update DTX. NOTE! We only do this if the
+    // first part of a frame gets the VAD decision "inactive". Otherwise DTX
+    // might say it is time to transmit SID frame, but we will encode the whole
+    // frame, because the first part is active.
+    *samples_processed = 0;
+    if ((status == 0) && (i == 0) && dtx_enabled_ && !has_internal_dtx_) {
+      int16_t bitstream_len;
+      int num_10ms_frames = num_samples_to_process[i] / samples_in_10ms;
+      *bitstream_len_byte = 0;
+      for (int n = 0; n < num_10ms_frames; n++) {
+        // This block is (passive) && (vad enabled). If first CNG after
+        // speech, force SID by setting last parameter to "1".
+        status = WebRtcCng_Encode(ptr_dtx_inst_, &audio[n * samples_in_10ms],
+                                  samples_in_10ms, bitstream, &bitstream_len,
+                                  !prev_frame_cng_);
+        if (status < 0) {
+          return -1;
+        }
+
+        // Update previous frame was CNG.
+        prev_frame_cng_ = 1;
+
+        *samples_processed += samples_in_10ms * num_channels_;
+
+        // |bitstream_len_byte| will only be > 0 once per 100 ms.
+        *bitstream_len_byte += bitstream_len;
+      }
+
+      // Check if all samples got processed by the DTX.
+      if (*samples_processed != num_samples_to_process[i] * num_channels_) {
+        // Set to zero since something went wrong. Shouldn't happen.
+        *samples_processed = 0;
+      }
+    } else {
+      // Update previous frame was not CNG.
+      prev_frame_cng_ = 0;
+    }
+
+    if (*samples_processed > 0) {
+      // The block contains inactive speech, and is processed by DTX.
+      // Discontinue running VAD.
+      break;
+    }
+  }
+
+  return status;
+}
+
+int16_t ACMGenericCodec::SamplesLeftToEncode() {
+  ReadLockScoped rl(codec_wrapper_lock_);
+  return (frame_len_smpl_ <= in_audio_ix_write_) ? 0 :
+      (frame_len_smpl_ - in_audio_ix_write_);
+}
+
+void ACMGenericCodec::SetUniqueID(const uint32_t id) {
+  unique_id_ = id;
+}
+
+// This function is replaced by codec specific functions for some codecs.
+int16_t ACMGenericCodec::EncoderSampFreq(uint16_t* samp_freq_hz) {
+  int32_t f;
+  f = ACMCodecDB::CodecFreq(codec_id_);
+  if (f < 0) {
+    WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, unique_id_,
+                 "EncoderSampFreq: codec frequency is negative");
+    return -1;
+  } else {
+    *samp_freq_hz = static_cast<uint16_t>(f);
+    return 0;
+  }
+}
+
+int32_t ACMGenericCodec::ConfigISACBandwidthEstimator(
+    const uint8_t /* init_frame_size_msec */,
+    const uint16_t /* init_rate_bit_per_sec */,
+    const bool /* enforce_frame_size  */) {
+  WEBRTC_TRACE(webrtc::kTraceWarning, webrtc::kTraceAudioCoding, unique_id_,
+               "The send-codec is not iSAC, failed to config iSAC bandwidth "
+               "estimator.");
+  return -1;
+}
+
+int32_t ACMGenericCodec::SetISACMaxRate(
+    const uint32_t /* max_rate_bit_per_sec */) {
+  WEBRTC_TRACE(webrtc::kTraceWarning, webrtc::kTraceAudioCoding, unique_id_,
+               "The send-codec is not iSAC, failed to set iSAC max rate.");
+  return -1;
+}
+
+int32_t ACMGenericCodec::SetISACMaxPayloadSize(
+    const uint16_t /* max_payload_len_bytes */) {
+  WEBRTC_TRACE(webrtc::kTraceWarning, webrtc::kTraceAudioCoding, unique_id_,
+               "The send-codec is not iSAC, failed to set iSAC max "
+               "payload-size.");
+  return -1;
+}
+
+int16_t ACMGenericCodec::UpdateEncoderSampFreq(
+    uint16_t /* samp_freq_hz */) {
+  WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, unique_id_,
+               "It is asked for a change in smapling frequency while the "
+               "current  send-codec supports only one sampling rate.");
+  return -1;
+}
+
+int16_t ACMGenericCodec::REDPayloadISAC(const int32_t /* isac_rate */,
+                                        const int16_t /* isac_bw_estimate */,
+                                        uint8_t* /* payload */,
+                                        int16_t* /* payload_len_bytes */) {
+  WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, unique_id_,
+               "Error: REDPayloadISAC is an iSAC specific function");
+  return -1;
+}
+
+}  // namespace webrtc
diff --git a/webrtc/modules/audio_coding/main/acm2/acm_generic_codec.h b/webrtc/modules/audio_coding/main/acm2/acm_generic_codec.h
new file mode 100644
index 0000000..cde2e42
--- /dev/null
+++ b/webrtc/modules/audio_coding/main/acm2/acm_generic_codec.h
@@ -0,0 +1,918 @@
+/*
+ *  Copyright (c) 2012 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_MAIN_SOURCE_ACM_GENERIC_CODEC_H_
+#define WEBRTC_MODULES_AUDIO_CODING_MAIN_SOURCE_ACM_GENERIC_CODEC_H_
+
+#include "webrtc/modules/audio_coding/main/interface/audio_coding_module_typedefs.h"
+#include "webrtc/modules/audio_coding/main/source/acm_common_defs.h"
+#include "webrtc/modules/audio_coding/neteq4/interface/neteq.h"
+#include "webrtc/modules/audio_coding/neteq4/interface/audio_decoder.h"
+#include "webrtc/system_wrappers/interface/rw_lock_wrapper.h"
+#include "webrtc/system_wrappers/interface/trace.h"
+
+#define MAX_FRAME_SIZE_10MSEC 6
+
+// forward declaration
+struct WebRtcVadInst;
+struct WebRtcCngEncInst;
+
+namespace webrtc {
+
+// forward declaration
+struct CodecInst;
+class AcmReceiver;
+
+class ACMGenericCodec {
+ public:
+  ///////////////////////////////////////////////////////////////////////////
+  // Constructor of the class
+  //
+  ACMGenericCodec();
+
+  ///////////////////////////////////////////////////////////////////////////
+  // Destructor of the class.
+  //
+  virtual ~ACMGenericCodec();
+
+  ///////////////////////////////////////////////////////////////////////////
+  // ACMGenericCodec* CreateInstance();
+  // The function will be used for FEC. It is not implemented yet.
+  //
+  virtual ACMGenericCodec* CreateInstance() = 0;
+
+  ///////////////////////////////////////////////////////////////////////////
+  // int16_t Encode()
+  // The function is called to perform an encoding of the audio stored in
+  // audio buffer. An encoding is performed only if enough audio, i.e. equal
+  // to the frame-size of the codec, exist. The audio frame will be processed
+  // by VAD and CN/DTX if required. There are few different cases.
+  //
+  // A) Neither VAD nor DTX is active; the frame is encoded by the encoder.
+  //
+  // B) VAD is enabled but not DTX; in this case the audio is processed by VAD
+  //    and encoded by the encoder. The "*encoding_type" will be either
+  //    "kActiveNormalEncode" or "kPassiveNormalEncode" if frame is active or
+  //    passive, respectively.
+  //
+  // C) DTX is enabled; if the codec has internal VAD/DTX we just encode the
+  //    frame by the encoder. Otherwise, the frame is passed through VAD and
+  //    if identified as passive, then it will be processed by CN/DTX. If the
+  //    frame is active it will be encoded by the encoder.
+  //
+  // This function acquires the appropriate locks and calls EncodeSafe() for
+  // the actual processing.
+  //
+  // Outputs:
+  //   -bitstream          : a buffer where bit-stream will be written to.
+  //   -bitstream_len_byte : contains the length of the bit-stream in
+  //                         bytes.
+  //   -timestamp          : contains the RTP timestamp, this is the
+  //                         sampling time of the first sample encoded
+  //                         (measured in number of samples).
+  //   -encoding_type       : contains the type of encoding applied on the
+  //                         audio samples. The alternatives are
+  //                         (c.f. acm_common_types.h)
+  //                         -kNoEncoding:
+  //                            there was not enough data to encode. or
+  //                            some error has happened that we could
+  //                            not do encoding.
+  //                         -kActiveNormalEncoded:
+  //                            the audio frame is active and encoded by
+  //                            the given codec.
+  //                         -kPassiveNormalEncoded:
+  //                            the audio frame is passive but coded with
+  //                            the given codec (NO DTX).
+  //                         -kPassiveDTXWB:
+  //                            The audio frame is passive and used
+  //                            wide-band CN to encode.
+  //                         -kPassiveDTXNB:
+  //                            The audio frame is passive and used
+  //                            narrow-band CN to encode.
+  //
+  // Return value:
+  //   -1 if error is occurred, otherwise the length of the bit-stream in
+  //      bytes.
+  //
+  int16_t Encode(uint8_t* bitstream,
+                 int16_t* bitstream_len_byte,
+                 uint32_t* timestamp,
+                 WebRtcACMEncodingType* encoding_type);
+
+  ///////////////////////////////////////////////////////////////////////////
+  // bool EncoderInitialized();
+  //
+  // Return value:
+  //   True if the encoder is successfully initialized,
+  //   false otherwise.
+  //
+  bool EncoderInitialized();
+
+  ///////////////////////////////////////////////////////////////////////////
+  // int16_t EncoderParams()
+  // It is called to get encoder parameters. It will call
+  // EncoderParamsSafe() in turn.
+  //
+  // Output:
+  //   -enc_params         : a buffer where the encoder parameters is
+  //                         written to. If the encoder is not
+  //                         initialized this buffer is filled with
+  //                         invalid values
+  // Return value:
+  //   -1 if the encoder is not initialized,
+  //    0 otherwise.
+  //
+  int16_t EncoderParams(WebRtcACMCodecParams* enc_params);
+
+  ///////////////////////////////////////////////////////////////////////////
+  // int16_t InitEncoder(...)
+  // This function is called to initialize the encoder with the given
+  // parameters.
+  //
+  // Input:
+  //   -codec_params        : parameters of encoder.
+  //   -force_initialization: if false the initialization is invoked only if
+  //                          the encoder is not initialized. If true the
+  //                          encoder is forced to (re)initialize.
+  //
+  // Return value:
+  //   0 if could initialize successfully,
+  //  -1 if failed to initialize.
+  //
+  //
+  int16_t InitEncoder(WebRtcACMCodecParams* codec_params,
+                      bool force_initialization);
+
+  ///////////////////////////////////////////////////////////////////////////
+  // int32_t Add10MsData(...)
+  // This function is called to add 10 ms of audio to the audio buffer of
+  // the codec.
+  //
+  // Inputs:
+  //   -timestamp          : the timestamp of the 10 ms audio. the timestamp
+  //                         is the sampling time of the
+  //                         first sample measured in number of samples.
+  //   -data               : a buffer that contains the audio. The codec
+  //                         expects to get the audio in correct sampling
+  //                         frequency
+  //   -length             : the length of the audio buffer
+  //   -audio_channel      : 0 for mono, 1 for stereo (not supported yet)
+  //
+  // Return values:
+  //   -1 if failed
+  //    0 otherwise.
+  //
+  int32_t Add10MsData(const uint32_t timestamp,
+                      const int16_t* data,
+                      const uint16_t length,
+                      const uint8_t audio_channel);
+
+  ///////////////////////////////////////////////////////////////////////////
+  // uint32_t NoMissedSamples()
+  // This function returns the number of samples which are overwritten in
+  // the audio buffer. The audio samples are overwritten if the input audio
+  // buffer is full, but Add10MsData() is called. (We might remove this
+  // function if it is not used)
+  //
+  // Return Value:
+  //   Number of samples which are overwritten.
+  //
+  uint32_t NoMissedSamples() const;
+
+  ///////////////////////////////////////////////////////////////////////////
+  // void ResetNoMissedSamples()
+  // This function resets the number of overwritten samples to zero.
+  // (We might remove this function if we remove NoMissedSamples())
+  //
+  void ResetNoMissedSamples();
+
+  ///////////////////////////////////////////////////////////////////////////
+  // int16_t SetBitRate()
+  // The function is called to set the encoding rate.
+  //
+  // Input:
+  //   -bitrate_bps        : encoding rate in bits per second
+  //
+  // Return value:
+  //   -1 if failed to set the rate, due to invalid input or given
+  //      codec is not rate-adjustable.
+  //    0 if the rate is adjusted successfully
+  //
+  int16_t SetBitRate(const int32_t bitrate_bps);
+
+  ///////////////////////////////////////////////////////////////////////////
+  // DestructEncoderInst()
+  // This API is used in conferencing. It will free the memory that is pointed
+  // by |ptr_inst|. |ptr_inst| is a pointer to encoder instance, created and
+  // filled up by calling EncoderInst(...).
+  //
+  // Inputs:
+  //   -ptr_inst            : pointer to an encoder instance to be deleted.
+  //
+  //
+  void DestructEncoderInst(void* ptr_inst);
+
+  ///////////////////////////////////////////////////////////////////////////
+  // uint32_t EarliestTimestamp()
+  // Returns the timestamp of the first 10 ms in audio buffer. This is used
+  // to identify if a synchronization of two encoders is required.
+  //
+  // Return value:
+  //   timestamp of the first 10 ms audio in the audio buffer.
+  //
+  uint32_t EarliestTimestamp() const;
+
+  ///////////////////////////////////////////////////////////////////////////
+  // int16_t SetVAD()
+  // This is called to set VAD & DTX. If the codec has internal DTX that will
+  // be used. If DTX is enabled and the codec does not have internal DTX,
+  // WebRtc-VAD will be used to decide if the frame is active. If DTX is
+  // disabled but VAD is enabled. The audio is passed through VAD to label it
+  // as active or passive, but the frame is  encoded normally. However the
+  // bit-stream is labeled properly so that ACM::Process() can use this
+  // information. In case of failure, the previous states of the VAD & DTX
+  // are kept.
+  //
+  // Inputs:
+  //   -enable_dtx         : if true DTX will be enabled otherwise the DTX is
+  //                         disabled. If codec has internal DTX that will be
+  //                         used, otherwise WebRtc-CNG is used. In the latter
+  //                         case VAD is automatically activated.
+  //   -enable_vad         : if true WebRtc-VAD is enabled, otherwise VAD is
+  //                         disabled, except for the case that DTX is enabled
+  //                         but codec doesn't have internal DTX. In this case
+  //                         VAD is enabled regardless of the value of
+  //                         |enable_vad|.
+  //   -mode               : this specifies the aggressiveness of VAD.
+  //
+  // Return value
+  //   -1 if failed to set DTX & VAD as specified,
+  //    0 if succeeded.
+  //
+  int16_t SetVAD(const bool enable_dtx = true,
+                 const bool enable_vad = false,
+                 const ACMVADMode mode = VADNormal);
+
+  ///////////////////////////////////////////////////////////////////////////
+  // int32_t ReplaceInternalDTX()
+  // This is called to replace the codec internal DTX with WebRtc DTX.
+  // This is only valid for G729 where the user has possibility to replace
+  // AnnexB with WebRtc DTX. For other codecs this function has no effect.
+  //
+  // Input:
+  //   -replace_internal_dtx : if true the internal DTX is replaced with WebRtc.
+  //
+  // Return value
+  //   -1 if failed to replace internal DTX,
+  //    0 if succeeded.
+  //
+  int32_t ReplaceInternalDTX(const bool replace_internal_dtx);
+
+  ///////////////////////////////////////////////////////////////////////////
+  // int32_t IsInternalDTXReplaced()
+  // This is called to check if the codec internal DTX is replaced by WebRtc
+  // DTX. This is only valid for G729 where the user has possibility to replace
+  // AnnexB with WebRtc DTX. For other codecs this function has no effect.
+  //
+  // Output:
+  //   -internal_dtx_replaced: if true the internal DTX is replaced with WebRtc.
+  //
+  // Return value
+  //   -1 if failed to check
+  //    0 if succeeded.
+  //
+  int32_t IsInternalDTXReplaced(bool* internal_dtx_replaced);
+
+  ///////////////////////////////////////////////////////////////////////////
+  // void SetNetEqDecodeLock()
+  // Passes the NetEq lock to the codec.
+  //
+  // Input:
+  //   -neteq_decode_lock  : pointer to the lock associated with NetEQ of ACM.
+  //
+  void SetNetEqDecodeLock(RWLockWrapper* neteq_decode_lock) {
+    neteq_decode_lock_ = neteq_decode_lock;
+  }
+
+  ///////////////////////////////////////////////////////////////////////////
+  // bool HasInternalDTX()
+  // Used to check if the codec has internal DTX.
+  //
+  // Return value:
+  //   true if the codec has an internal DTX, e.g. G729,
+  //   false otherwise.
+  //
+  bool HasInternalDTX() const { return has_internal_dtx_; }
+
+  ///////////////////////////////////////////////////////////////////////////
+  // int32_t GetEstimatedBandwidth()
+  // Used to get decoder estimated bandwidth. Only iSAC will provide a value.
+  //
+  //
+  // Return value:
+  //   -1 if fails to get decoder estimated bandwidth,
+  //    >0 estimated bandwidth in bits/sec.
+  //
+  int32_t GetEstimatedBandwidth();
+
+  ///////////////////////////////////////////////////////////////////////////
+  // int32_t SetEstimatedBandwidth()
+  // Used to set estiamted bandwidth sent out of band from other side. Only
+  // iSAC will have use for the value.
+  //
+  // Input:
+  //       -estimated_bandwidth:    estimated bandwidth in bits/sec
+  //
+  // Return value:
+  //   -1 if fails to set estimated bandwidth,
+  //    0 on success.
+  //
+  int32_t SetEstimatedBandwidth(int32_t estimated_bandwidth);
+
+  ///////////////////////////////////////////////////////////////////////////
+  // int32_t GetRedPayload()
+  // Used to get codec specific RED payload (if such is implemented).
+  // Currently only done in iSAC.
+  //
+  // Outputs:
+  //   -red_payload       : a pointer to the data for RED payload.
+  //   -payload_bytes     : number of bytes in RED payload.
+  //
+  // Return value:
+  //   -1 if fails to get codec specific RED,
+  //    0 if succeeded.
+  //
+  int32_t GetRedPayload(uint8_t* red_payload, int16_t* payload_bytes);
+
+  ///////////////////////////////////////////////////////////////////////////
+  // int16_t ResetEncoder()
+  // By calling this function you would re-initialize the encoder with the
+  // current parameters. All the settings, e.g. VAD/DTX, frame-size... should
+  // remain unchanged. (In case of iSAC we don't want to lose BWE history.)
+  //
+  // Return value
+  //   -1 if failed,
+  //    0 if succeeded.
+  //
+  int16_t ResetEncoder();
+
+  ///////////////////////////////////////////////////////////////////////////
+  // void DestructEncoder()
+  // This function is called to delete the encoder instance, if possible, to
+  // have a fresh start. For codecs where encoder and decoder share the same
+  // instance we cannot delete the encoder and instead we will initialize the
+  // encoder. We also delete VAD and DTX if they have been created.
+  //
+  void DestructEncoder();
+
+  ///////////////////////////////////////////////////////////////////////////
+  // int16_t SamplesLeftToEncode()
+  // Returns the number of samples required to be able to do encoding.
+  //
+  // Return value:
+  //   Number of samples.
+  //
+  int16_t SamplesLeftToEncode();
+
+  ///////////////////////////////////////////////////////////////////////////
+  // SetUniqueID()
+  // Set a unique ID for the codec to be used for tracing and debugging
+  //
+  // Input
+  //   -id                 : A number to identify the codec.
+  //
+  void SetUniqueID(const uint32_t id);
+
+  ///////////////////////////////////////////////////////////////////////////
+  // UpdateDecoderSampFreq()
+  // For most of the codecs this function does nothing. It must be
+  // implemented for those codecs that one codec instance serves as the
+  // decoder for different flavors of the codec. One example is iSAC. there,
+  // iSAC 16 kHz and iSAC 32 kHz are treated as two different codecs with
+  // different payload types, however, there is only one iSAC instance to
+  // decode. The reason for that is we would like to decode and encode with
+  // the same codec instance for bandwidth estimator to work.
+  //
+  // Each time that we receive a new payload type, we call this function to
+  // prepare the decoder associated with the new payload. Normally, decoders
+  // doesn't have to do anything. For iSAC the decoder has to change it's
+  // sampling rate. The input parameter specifies the current flavor of the
+  // codec in codec database. For instance, if we just got a SWB payload then
+  // the input parameter is ACMCodecDB::isacswb.
+  //
+  // Input:
+  //   -codec_id           : the ID of the codec associated with the
+  //                         payload type that we just received.
+  //
+  // Return value:
+  //    0 if succeeded in updating the decoder.
+  //   -1 if failed to update.
+  //
+  virtual int16_t UpdateDecoderSampFreq(int16_t /* codec_id */) { return 0; }
+
+  ///////////////////////////////////////////////////////////////////////////
+  // UpdateEncoderSampFreq()
+  // Call this function to update the encoder sampling frequency. This
+  // is for codecs where one payload-name supports several encoder sampling
+  // frequencies. Otherwise, to change the sampling frequency we need to
+  // register new codec. ACM will consider that as registration of a new
+  // codec, not a change in parameter. For iSAC, switching from WB to SWB
+  // is treated as a change in parameter. Therefore, we need this function.
+  //
+  // Input:
+  //   -samp_freq_hz        : encoder sampling frequency.
+  //
+  // Return value:
+  //   -1 if failed, or if this is meaningless for the given codec.
+  //    0 if succeeded.
+  //
+  virtual int16_t UpdateEncoderSampFreq(uint16_t samp_freq_hz);
+
+  ///////////////////////////////////////////////////////////////////////////
+  // EncoderSampFreq()
+  // Get the sampling frequency that the encoder (WebRtc wrapper) expects.
+  //
+  // Output:
+  //   -samp_freq_hz       : sampling frequency, in Hertz, which the encoder
+  //                         should be fed with.
+  //
+  // Return value:
+  //   -1 if failed to output sampling rate.
+  //    0 if the sample rate is returned successfully.
+  //
+  virtual int16_t EncoderSampFreq(uint16_t* samp_freq_hz);
+
+  ///////////////////////////////////////////////////////////////////////////
+  // int32_t ConfigISACBandwidthEstimator()
+  // Call this function to configure the bandwidth estimator of ISAC.
+  // During the adaptation of bit-rate, iSAC automatically adjusts the
+  // frame-size (either 30 or 60 ms) to save on RTP header. The initial
+  // frame-size can be specified by the first argument. The configuration also
+  // regards the initial estimate of bandwidths. The estimator starts from
+  // this point and converges to the actual bottleneck. This is given by the
+  // second parameter. Furthermore, it is also possible to control the
+  // adaptation of frame-size. This is specified by the last parameter.
+  //
+  // Input:
+  //   -init_frame_fize_ms : initial frame-size in milliseconds. For iSAC-wb
+  //                         30 ms and 60 ms (default) are acceptable values,
+  //                         and for iSAC-swb 30 ms is the only acceptable
+  //                         value. Zero indicates default value.
+  //   -init_rate_bps      : initial estimate of the bandwidth. Values
+  //                         between 10000 and 58000 are acceptable.
+  //   -enforce_frame_size : if true, the frame-size will not be adapted.
+  //
+  // Return value:
+  //   -1 if failed to configure the bandwidth estimator,
+  //    0 if the configuration was successfully applied.
+  //
+  virtual int32_t ConfigISACBandwidthEstimator(
+      const uint8_t init_frame_size_msec,
+      const uint16_t init_rate_bps,
+      const bool enforce_frame_size);
+
+  ///////////////////////////////////////////////////////////////////////////
+  // SetISACMaxPayloadSize()
+  // Set the maximum payload size of iSAC packets. No iSAC payload,
+  // regardless of its frame-size, may exceed the given limit. For
+  // an iSAC payload of size B bits and frame-size T sec we have;
+  // (B < max_payload_len_bytes * 8) and (B/T < max_rate_bit_per_sec), c.f.
+  // SetISACMaxRate().
+  //
+  // Input:
+  //   -max_payload_len_bytes : maximum payload size in bytes.
+  //
+  // Return value:
+  //   -1 if failed to set the maximum  payload-size.
+  //    0 if the given length is set successfully.
+  //
+  virtual int32_t SetISACMaxPayloadSize(const uint16_t max_payload_len_bytes);
+
+  ///////////////////////////////////////////////////////////////////////////
+  // SetISACMaxRate()
+  // Set the maximum instantaneous rate of iSAC. For a payload of B bits
+  // with a frame-size of T sec the instantaneous rate is B/T bits per
+  // second. Therefore, (B/T < max_rate_bit_per_sec) and
+  // (B < max_payload_len_bytes * 8) are always satisfied for iSAC payloads,
+  // c.f SetISACMaxPayloadSize().
+  //
+  // Input:
+  //   -max_rate_bps       : maximum instantaneous bit-rate given in bits/sec.
+  //
+  // Return value:
+  //   -1 if failed to set the maximum rate.
+  //    0 if the maximum rate is set successfully.
+  //
+  virtual int32_t SetISACMaxRate(const uint32_t max_rate_bps);
+
+  int32_t FrameSize() { return frame_len_smpl_; }
+
+  ///////////////////////////////////////////////////////////////////////////
+  // REDPayloadISAC()
+  // This is an iSAC-specific function. The function is called to get RED
+  // payload from a default-encoder.
+  //
+  // Inputs:
+  //   -isac_rate          : the target rate of the main payload. A RED
+  //                         payload is generated according to the rate of
+  //                         main payload. Note that we are not specifying the
+  //                         rate of RED payload, but the main payload.
+  //   -isac_bw_estimate   : bandwidth information should be inserted in
+  //                         RED payload.
+  //
+  // Output:
+  //   -payload            : pointer to a buffer where the RED payload will
+  //                         written to.
+  //   -payload_len_bytes  : a place-holder to write the length of the RED
+  //                         payload in Bytes.
+  //
+  // Return value:
+  //   -1 if an error occurs, otherwise the length of the payload (in Bytes)
+  //   is returned.
+  //
+  virtual int16_t REDPayloadISAC(const int32_t isac_rate,
+                                 const int16_t isac_bw_estimate,
+                                 uint8_t* payload,
+                                 int16_t* payload_len_bytes);
+
+  ///////////////////////////////////////////////////////////////////////////
+  // HasFrameToEncode()
+  // Returns true if there is enough audio buffered for encoding, such that
+  // calling Encode() will return a payload.
+  //
+  bool HasFrameToEncode() const;
+
+  //
+  // Returns pointer to the AudioDecoder class of this codec. A codec which
+  // should own its own decoder (e.g. iSAC which need same instance for encoding
+  // and decoding, or a codec which should access decoder instance for specific
+  // decoder setting) should implement this method. This method is called if
+  // and only if the ACMCodecDB::codec_settings[codec_id].owns_decoder is true.
+  //
+  virtual AudioDecoder* Decoder(int /* codec_id */) { return NULL; }
+
+ protected:
+  ///////////////////////////////////////////////////////////////////////////
+  // All the functions with FunctionNameSafe(...) contain the actual
+  // implementation of FunctionName(...). FunctionName() acquires an
+  // appropriate lock and calls FunctionNameSafe() to do the actual work.
+  // Therefore, for the description of functionality, input/output arguments
+  // and return value we refer to FunctionName()
+  //
+
+  ///////////////////////////////////////////////////////////////////////////
+  // See Add10MsSafe() for the description of function, input(s)/output(s)
+  // and return value.
+  //
+  virtual int32_t Add10MsDataSafe(const uint32_t timestamp,
+                                  const int16_t* data,
+                                  const uint16_t length,
+                                  const uint8_t audio_channel);
+
+  ///////////////////////////////////////////////////////////////////////////
+  // See EncoderParam() for the description of function, input(s)/output(s)
+  // and return value.
+  //
+  int16_t EncoderParamsSafe(WebRtcACMCodecParams* enc_params);
+
+  ///////////////////////////////////////////////////////////////////////////
+  // See ResetEncoder() for the description of function, input(s)/output(s)
+  // and return value.
+  //
+  int16_t ResetEncoderSafe();
+
+  ///////////////////////////////////////////////////////////////////////////
+  // See InitEncoder() for the description of function, input(s)/output(s)
+  // and return value.
+  //
+  int16_t InitEncoderSafe(WebRtcACMCodecParams* codec_params,
+                          bool force_initialization);
+
+  ///////////////////////////////////////////////////////////////////////////
+  // See InitDecoder() for the description of function, input(s)/output(s)
+  // and return value.
+  //
+  int16_t InitDecoderSafe(WebRtcACMCodecParams* codec_params,
+                          bool force_initialization);
+
+  ///////////////////////////////////////////////////////////////////////////
+  // See DestructEncoder() for the description of function,
+  // input(s)/output(s) and return value.
+  //
+  virtual void DestructEncoderSafe() = 0;
+
+  ///////////////////////////////////////////////////////////////////////////
+  // See SetBitRate() for the description of function, input(s)/output(s)
+  // and return value.
+  //
+  // Any codec that can change the bit-rate has to implement this.
+  //
+  virtual int16_t SetBitRateSafe(const int32_t bitrate_bps);
+
+  ///////////////////////////////////////////////////////////////////////////
+  // See GetEstimatedBandwidth() for the description of function,
+  // input(s)/output(s) and return value.
+  //
+  virtual int32_t GetEstimatedBandwidthSafe();
+
+  ///////////////////////////////////////////////////////////////////////////
+  // See SetEstimatedBandwidth() for the description of function,
+  // input(s)/output(s) and return value.
+  //
+  virtual int32_t SetEstimatedBandwidthSafe(int32_t estimated_bandwidth);
+
+  ///////////////////////////////////////////////////////////////////////////
+  // See GetRedPayload() for the description of function, input(s)/output(s)
+  // and return value.
+  //
+  virtual int32_t GetRedPayloadSafe(uint8_t* red_payload,
+                                    int16_t* payload_bytes);
+
+  ///////////////////////////////////////////////////////////////////////////
+  // See SetVAD() for the description of function, input(s)/output(s) and
+  // return value.
+  //
+  int16_t SetVADSafe(const bool enable_dtx = true,
+                     const bool enable_vad = false,
+                     const ACMVADMode mode = VADNormal);
+
+  ///////////////////////////////////////////////////////////////////////////
+  // See ReplaceInternalDTX() for the description of function, input and
+  // return value.
+  //
+  virtual int32_t ReplaceInternalDTXSafe(const bool replace_internal_dtx);
+
+  ///////////////////////////////////////////////////////////////////////////
+  // See IsInternalDTXReplaced() for the description of function, input and
+  // return value.
+  //
+  virtual int32_t IsInternalDTXReplacedSafe(bool* internal_dtx_replaced);
+
+  ///////////////////////////////////////////////////////////////////////////
+  // int16_t CreateEncoder()
+  // Creates the encoder instance.
+  //
+  // Return value:
+  //   -1 if failed,
+  //    0 if succeeded.
+  //
+  int16_t CreateEncoder();
+
+  ///////////////////////////////////////////////////////////////////////////
+  // int16_t EnableVAD();
+  // Enables VAD with the given mode. The VAD instance will be created if
+  // it does not exists.
+  //
+  // Input:
+  //   -mode               : VAD mode c.f. audio_coding_module_typedefs.h for
+  //                         the options.
+  //
+  // Return value:
+  //   -1 if failed,
+  //    0 if succeeded.
+  //
+  int16_t EnableVAD(ACMVADMode mode);
+
+  ///////////////////////////////////////////////////////////////////////////
+  // int16_t DisableVAD()
+  // Disables VAD.
+  //
+  // Return value:
+  //   -1 if failed,
+  //    0 if succeeded.
+  //
+  int16_t DisableVAD();
+
+  ///////////////////////////////////////////////////////////////////////////
+  // int16_t EnableDTX()
+  // Enables DTX. This method should be overwritten for codecs which have
+  // internal DTX.
+  //
+  // Return value:
+  //   -1 if failed,
+  //    0 if succeeded.
+  //
+  virtual int16_t EnableDTX();
+
+  ///////////////////////////////////////////////////////////////////////////
+  // int16_t DisableDTX()
+  // Disables usage of DTX. This method should be overwritten for codecs which
+  // have internal DTX.
+  //
+  // Return value:
+  //   -1 if failed,
+  //    0 if succeeded.
+  //
+  virtual int16_t DisableDTX();
+
+  ///////////////////////////////////////////////////////////////////////////
+  // int16_t InternalEncode()
+  // This is a codec-specific function called in EncodeSafe() to actually
+  // encode a frame of audio.
+  //
+  // Outputs:
+  //   -bitstream          : pointer to a buffer where the bit-stream is
+  //                         written to.
+  //   -bitstream_len_byte : the length of the bit-stream in bytes,
+  //                         a negative value indicates error.
+  //
+  // Return value:
+  //   -1 if failed,
+  //   otherwise the length of the bit-stream is returned.
+  //
+  virtual int16_t InternalEncode(uint8_t* bitstream,
+                                 int16_t* bitstream_len_byte) = 0;
+
+  ///////////////////////////////////////////////////////////////////////////
+  // int16_t InternalInitEncoder()
+  // This is a codec-specific function called in InitEncoderSafe(), it has to
+  // do all codec-specific operation to initialize the encoder given the
+  // encoder parameters.
+  //
+  // Input:
+  //   -codec_params       : pointer to a structure that contains parameters to
+  //                         initialize encoder.
+  //                         Set codec_params->codec_inst.rate to -1 for
+  //                         iSAC to operate in adaptive mode.
+  //                         (to do: if frame-length is -1 frame-length will be
+  //                         automatically adjusted, otherwise, given
+  //                         frame-length is forced)
+  //
+  // Return value:
+  //   -1 if failed,
+  //    0 if succeeded.
+  //
+  virtual int16_t InternalInitEncoder(WebRtcACMCodecParams* codec_params) = 0;
+
+  ///////////////////////////////////////////////////////////////////////////
+  // void IncreaseNoMissedSamples()
+  // This method is called to increase the number of samples that are
+  // overwritten in the audio buffer.
+  //
+  // Input:
+  //   -num_samples        : the number of overwritten samples is incremented
+  //                         by this value.
+  //
+  void IncreaseNoMissedSamples(const int16_t num_samples);
+
+  ///////////////////////////////////////////////////////////////////////////
+  // int16_t InternalCreateEncoder()
+  // This is a codec-specific method called in CreateEncoderSafe() it is
+  // supposed to perform all codec-specific operations to create encoder
+  // instance.
+  //
+  // Return value:
+  //   -1 if failed,
+  //    0 if succeeded.
+  //
+  virtual int16_t InternalCreateEncoder() = 0;
+
+  ///////////////////////////////////////////////////////////////////////////
+  // void InternalDestructEncoderInst()
+  // This is a codec-specific method, used in conferencing, called from
+  // DestructEncoderInst(). The input argument is pointer to encoder instance
+  // (codec instance for codecs that encoder and decoder share the same
+  // instance). This method is called to free the memory that |ptr_inst| is
+  // pointing to.
+  //
+  // Input:
+  //   -ptr_inst           : pointer to encoder instance.
+  //
+  // Return value:
+  //   -1 if failed,
+  //    0 if succeeded.
+  //
+  virtual void InternalDestructEncoderInst(void* ptr_inst) = 0;
+
+  ///////////////////////////////////////////////////////////////////////////
+  // int16_t InternalResetEncoder()
+  // This method is called to reset the states of encoder. However, the
+  // current parameters, e.g. frame-length, should remain as they are. For
+  // most of the codecs a re-initialization of the encoder is what needs to
+  // be down. But for iSAC we like to keep the BWE history so we cannot
+  // re-initialize. As soon as such an API is implemented in iSAC this method
+  // has to be overwritten in ACMISAC class.
+  //
+  // Return value:
+  //   -1 if failed,
+  //    0 if succeeded.
+  //
+  virtual int16_t InternalResetEncoder();
+
+  ///////////////////////////////////////////////////////////////////////////
+  // int16_t ProcessFrameVADDTX()
+  // This function is called when a full frame of audio is available. It will
+  // break the audio frame into blocks such that each block could be processed
+  // by VAD & CN/DTX. If a frame is divided into two blocks then there are two
+  // cases. First, the first block is active, the second block will not be
+  // processed by CN/DTX but only by VAD and return to caller with
+  // '*samples_processed' set to zero. There, the audio frame will be encoded
+  // by the encoder. Second, the first block is inactive and is processed by
+  // CN/DTX, then we stop processing the next block and return to the caller
+  // which is EncodeSafe(), with "*samples_processed" equal to the number of
+  // samples in first block.
+  //
+  // Output:
+  //   -bitstream          : pointer to a buffer where DTX frame, if
+  //                         generated, will be written to.
+  //   -bitstream_len_byte : contains the length of bit-stream in bytes, if
+  //                         generated. Zero if no bit-stream is generated.
+  //   -samples_processed  : contains no of samples that actually CN has
+  //                         processed. Those samples processed by CN will not
+  //                         be encoded by the encoder, obviously. If
+  //                         contains zero, it means that the frame has been
+  //                         identified as active by VAD. Note that
+  //                         "*samples_processed" might be non-zero but
+  //                         "*bitstream_len_byte" be zero.
+  //
+  // Return value:
+  //   -1 if failed,
+  //    0 if succeeded.
+  //
+  int16_t ProcessFrameVADDTX(uint8_t* bitstream,
+                             int16_t* bitstream_len_byte,
+                             int16_t* samples_processed);
+
+  ///////////////////////////////////////////////////////////////////////////
+  // CurrentRate()
+  // Call to get the current encoding rate of the encoder. This function
+  // should be overwritten for codecs which automatically change their
+  // target rate. One example is iSAC. The output of the function is the
+  // current target rate.
+  //
+  // Output:
+  //   -rate_bps           : the current target rate of the codec.
+  //
+  virtual void CurrentRate(int32_t* /* rate_bps */) {}
+
+  // &in_audio_[in_audio_ix_write_] always point to where new audio can be
+  // written to
+  int16_t in_audio_ix_write_;
+
+  // &in_audio_[in_audio_ix_read_] points to where audio has to be read from
+  int16_t in_audio_ix_read_;
+
+  int16_t in_timestamp_ix_write_;
+
+  // Where the audio is stored before encoding,
+  // To save memory the following buffer can be allocated
+  // dynamically for 80 ms depending on the sampling frequency
+  // of the codec.
+  int16_t* in_audio_;
+  uint32_t* in_timestamp_;
+
+  int16_t frame_len_smpl_;
+  uint16_t num_channels_;
+
+  // This will point to a static database of the supported codecs
+  int16_t codec_id_;
+
+  // This will account for the number of samples  were not encoded
+  // the case is rare, either samples are missed due to overwrite
+  // at input buffer or due to encoding error
+  uint32_t num_missed_samples_;
+
+  // True if the encoder instance created
+  bool encoder_exist_;
+
+  // True if the encoder instance initialized
+  bool encoder_initialized_;
+
+  bool registered_in_neteq_;
+
+  // VAD/DTX
+  bool has_internal_dtx_;
+  WebRtcVadInst* ptr_vad_inst_;
+  bool vad_enabled_;
+  ACMVADMode vad_mode_;
+  int16_t vad_label_[MAX_FRAME_SIZE_10MSEC];
+  bool dtx_enabled_;
+  WebRtcCngEncInst* ptr_dtx_inst_;
+  uint8_t num_lpc_params_;
+  bool sent_cn_previous_;
+  int16_t prev_frame_cng_;
+
+  WebRtcACMCodecParams encoder_params_;
+
+  // Used as a global lock for all available decoders
+  // so that no decoder is used when NetEQ decodes.
+  RWLockWrapper* neteq_decode_lock_;
+
+  // Used to lock wrapper internal data
+  // such as buffers and state variables.
+  RWLockWrapper& codec_wrapper_lock_;
+
+  uint32_t last_timestamp_;
+  uint32_t unique_id_;
+};
+
+}  // namespace webrtc
+
+#endif  // WEBRTC_MODULES_AUDIO_CODING_MAIN_SOURCE_ACM_GENERIC_CODEC_H_
diff --git a/webrtc/modules/audio_coding/main/acm2/acm_gsmfr.cc b/webrtc/modules/audio_coding/main/acm2/acm_gsmfr.cc
new file mode 100644
index 0000000..9fd097c
--- /dev/null
+++ b/webrtc/modules/audio_coding/main/acm2/acm_gsmfr.cc
@@ -0,0 +1,157 @@
+/*
+ *  Copyright (c) 2012 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 "webrtc/modules/audio_coding/main/source/acm_gsmfr.h"
+
+#ifdef WEBRTC_CODEC_GSMFR
+// NOTE! GSM-FR is not included in the open-source package. Modify this file
+// or your codec API to match the function calls and names of used GSM-FR API
+// file.
+#include "webrtc/modules/audio_coding/main/codecs/gsmfr/interface/gsmfr_interface.h"
+#include "webrtc/modules/audio_coding/main/source/acm_common_defs.h"
+#include "webrtc/system_wrappers/interface/trace.h"
+#endif
+
+namespace webrtc {
+
+#ifndef WEBRTC_CODEC_GSMFR
+
+ACMGSMFR::ACMGSMFR(int16_t /* codec_id */) : encoder_inst_ptr_(NULL) {}
+
+ACMGSMFR::~ACMGSMFR() { return; }
+
+int16_t ACMGSMFR::InternalEncode(uint8_t* /* bitstream */,
+                                 int16_t* /* bitstream_len_byte */) {
+  return -1;
+}
+
+int16_t ACMGSMFR::EnableDTX() { return -1; }
+
+int16_t ACMGSMFR::DisableDTX() { return -1; }
+
+int16_t ACMGSMFR::InternalInitEncoder(
+    WebRtcACMCodecParams* /* codec_params */) {
+  return -1;
+}
+
+ACMGenericCodec* ACMGSMFR::CreateInstance(void) { return NULL; }
+
+int16_t ACMGSMFR::InternalCreateEncoder() { return -1; }
+
+void ACMGSMFR::DestructEncoderSafe() { return; }
+
+void ACMGSMFR::InternalDestructEncoderInst(void* /* ptr_inst */) {
+  return;
+}
+
+#else  //===================== Actual Implementation =======================
+
+ACMGSMFR::ACMGSMFR(int16_t codec_id)
+    : codec_id_(codec_id),
+      has_internal_dtx_(true),
+      encoder_inst_ptr_(NULL) {}
+
+ACMGSMFR::~ACMGSMFR() {
+  if (encoder_inst_ptr_ != NULL) {
+    WebRtcGSMFR_FreeEnc(encoder_inst_ptr_);
+    encoder_inst_ptr_ = NULL;
+  }
+  return;
+}
+
+int16_t ACMGSMFR::InternalEncode(uint8_t* bitstream,
+                                 int16_t* bitstream_len_byte) {
+  *bitstream_len_byte = WebRtcGSMFR_Encode(
+      encoder_inst_ptr_, &in_audio_[in_audio_ix_read_], frame_len_smpl_,
+      reinterpret_cast<int16_t*>(bitstream));
+
+  // increment the read index this tell the caller that how far
+  // we have gone forward in reading the audio buffer
+  in_audio_ix_read_ += frame_len_smpl_;
+  return *bitstream_len_byte;
+}
+
+int16_t ACMGSMFR::EnableDTX() {
+  if (dtx_enabled_) {
+    return 0;
+  } else if (encoder_exist_) {
+    if (WebRtcGSMFR_EncoderInit(encoder_inst_ptr_, 1) < 0) {
+      WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, unique_id_,
+                   "EnableDTX: cannot init encoder for GSMFR");
+      return -1;
+    }
+    dtx_enabled_ = true;
+    return 0;
+  } else {
+    return -1;
+  }
+}
+
+int16_t ACMGSMFR::DisableDTX() {
+  if (!dtx_enabled_) {
+    return 0;
+  } else if (encoder_exist_) {
+    if (WebRtcGSMFR_EncoderInit(encoder_inst_ptr_, 0) < 0) {
+      WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, unique_id_,
+                   "DisableDTX: cannot init encoder for GSMFR");
+      return -1;
+    }
+    dtx_enabled_ = false;
+    return 0;
+  } else {
+    // encoder doesn't exists, therefore disabling is harmless
+    return 0;
+  }
+}
+
+int16_t ACMGSMFR::InternalInitEncoder(WebRtcACMCodecParams* codec_params) {
+  if (WebRtcGSMFR_EncoderInit(encoder_inst_ptr_,
+                              ((codec_params->enable_dtx) ? 1 : 0)) < 0) {
+    WEBRTC_TRACE(webrtc::kTraceError,
+                 webrtc::kTraceAudioCoding,
+                 unique_id_,
+                 "InternalInitEncoder: cannot init encoder for GSMFR");
+  }
+  return 0;
+}
+
+ACMGenericCodec* ACMGSMFR::CreateInstance(void) { return NULL; }
+
+int16_t ACMGSMFR::InternalCreateEncoder() {
+  if (WebRtcGSMFR_CreateEnc(&encoder_inst_ptr_) < 0) {
+    WEBRTC_TRACE(webrtc::kTraceError,
+                 webrtc::kTraceAudioCoding,
+                 unique_id_,
+                 "InternalCreateEncoder: cannot create instance for GSMFR "
+                 "encoder");
+    return -1;
+  }
+  return 0;
+}
+
+void ACMGSMFR::DestructEncoderSafe() {
+  if (encoder_inst_ptr_ != NULL) {
+    WebRtcGSMFR_FreeEnc(encoder_inst_ptr_);
+    encoder_inst_ptr_ = NULL;
+  }
+  encoder_exist_ = false;
+  encoder_initialized_ = false;
+}
+
+void ACMGSMFR::InternalDestructEncoderInst(void* ptr_inst) {
+  if (ptr_inst != NULL) {
+    WebRtcGSMFR_FreeEnc(static_cast<GSMFR_encinst_t_*>(ptr_inst));
+  }
+  return;
+}
+
+#endif
+
+}  // namespace webrtc
diff --git a/webrtc/modules/audio_coding/main/acm2/acm_gsmfr.h b/webrtc/modules/audio_coding/main/acm2/acm_gsmfr.h
new file mode 100644
index 0000000..935ac44
--- /dev/null
+++ b/webrtc/modules/audio_coding/main/acm2/acm_gsmfr.h
@@ -0,0 +1,50 @@
+/*
+ *  Copyright (c) 2012 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_MAIN_SOURCE_ACM_GSMFR_H_
+#define WEBRTC_MODULES_AUDIO_CODING_MAIN_SOURCE_ACM_GSMFR_H_
+
+#include "webrtc/modules/audio_coding/main/source/acm_generic_codec.h"
+
+// forward declaration
+struct GSMFR_encinst_t_;
+struct GSMFR_decinst_t_;
+
+namespace webrtc {
+
+class ACMGSMFR : public ACMGenericCodec {
+ public:
+  explicit ACMGSMFR(int16_t codec_id);
+  ~ACMGSMFR();
+
+  // for FEC
+  ACMGenericCodec* CreateInstance(void);
+
+  int16_t InternalEncode(uint8_t* bitstream, int16_t* bitstream_len_byte);
+
+  int16_t InternalInitEncoder(WebRtcACMCodecParams* codec_params);
+
+ protected:
+  void DestructEncoderSafe();
+
+  int16_t InternalCreateEncoder();
+
+  void InternalDestructEncoderInst(void* ptr_inst);
+
+  int16_t EnableDTX();
+
+  int16_t DisableDTX();
+
+  GSMFR_encinst_t_* encoder_inst_ptr_;
+};
+
+}  // namespace webrtc
+
+#endif  // WEBRTC_MODULES_AUDIO_CODING_MAIN_SOURCE_ACM_GSMFR_H_
diff --git a/webrtc/modules/audio_coding/main/acm2/acm_ilbc.cc b/webrtc/modules/audio_coding/main/acm2/acm_ilbc.cc
new file mode 100644
index 0000000..204e1e9
--- /dev/null
+++ b/webrtc/modules/audio_coding/main/acm2/acm_ilbc.cc
@@ -0,0 +1,141 @@
+/*
+ *  Copyright (c) 2012 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 "webrtc/modules/audio_coding/main/source/acm_ilbc.h"
+
+#ifdef WEBRTC_CODEC_ILBC
+#include "webrtc/modules/audio_coding/codecs/ilbc/interface/ilbc.h"
+#include "webrtc/modules/audio_coding/main/source/acm_common_defs.h"
+#include "webrtc/system_wrappers/interface/trace.h"
+#endif
+
+namespace webrtc {
+
+#ifndef WEBRTC_CODEC_ILBC
+
+ACMILBC::ACMILBC(int16_t /* codec_id */) : encoder_inst_ptr_(NULL) {}
+
+ACMILBC::~ACMILBC() { return; }
+
+int16_t ACMILBC::InternalEncode(uint8_t* /* bitstream */,
+                                int16_t* /* bitstream_len_byte */) {
+  return -1;
+}
+
+int16_t ACMILBC::InternalInitEncoder(WebRtcACMCodecParams* /* codec_params */) {
+  return -1;
+}
+
+ACMGenericCodec* ACMILBC::CreateInstance(void) { return NULL; }
+
+int16_t ACMILBC::InternalCreateEncoder() { return -1; }
+
+void ACMILBC::DestructEncoderSafe() { return; }
+
+void ACMILBC::InternalDestructEncoderInst(void* /* ptr_inst */) { return; }
+
+int16_t ACMILBC::SetBitRateSafe(const int32_t /* rate */) { return -1; }
+
+#else  //===================== Actual Implementation =======================
+
+ACMILBC::ACMILBC(int16_t codec_id) : encoder_inst_ptr_(NULL) {
+  codec_id_ = codec_id;
+  return;
+}
+
+ACMILBC::~ACMILBC() {
+  if (encoder_inst_ptr_ != NULL) {
+    WebRtcIlbcfix_EncoderFree(encoder_inst_ptr_);
+    encoder_inst_ptr_ = NULL;
+  }
+  return;
+}
+
+int16_t ACMILBC::InternalEncode(uint8_t* bitstream,
+                                int16_t* bitstream_len_byte) {
+  *bitstream_len_byte = WebRtcIlbcfix_Encode(
+      encoder_inst_ptr_, &in_audio_[in_audio_ix_read_], frame_len_smpl_,
+      reinterpret_cast<int16_t*>(bitstream));
+  if (*bitstream_len_byte < 0) {
+    WEBRTC_TRACE(webrtc::kTraceError,
+                 webrtc::kTraceAudioCoding,
+                 unique_id_,
+                 "InternalEncode: error in encode for ILBC");
+    return -1;
+  }
+  // increment the read index this tell the caller that how far
+  // we have gone forward in reading the audio buffer
+  in_audio_ix_read_ += frame_len_smpl_;
+  return *bitstream_len_byte;
+}
+
+int16_t ACMILBC::InternalInitEncoder(WebRtcACMCodecParams* codec_params) {
+  // initialize with a correct processing block length
+  if ((160 == (codec_params->codec_inst).pacsize) ||
+      (320 == (codec_params->codec_inst).pacsize)) {
+    // processing block of 20ms
+    return WebRtcIlbcfix_EncoderInit(encoder_inst_ptr_, 20);
+  } else if ((240 == (codec_params->codec_inst).pacsize) ||
+      (480 == (codec_params->codec_inst).pacsize)) {
+    // processing block of 30ms
+    return WebRtcIlbcfix_EncoderInit(encoder_inst_ptr_, 30);
+  } else {
+    WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, unique_id_,
+                 "InternalInitEncoder: invalid processing block");
+    return -1;
+  }
+}
+
+ACMGenericCodec* ACMILBC::CreateInstance(void) { return NULL; }
+
+int16_t ACMILBC::InternalCreateEncoder() {
+  if (WebRtcIlbcfix_EncoderCreate(&encoder_inst_ptr_) < 0) {
+    WEBRTC_TRACE(webrtc::kTraceError,
+                 webrtc::kTraceAudioCoding,
+                 unique_id_,
+                 "InternalCreateEncoder: cannot create instance for ILBC "
+                 "encoder");
+    return -1;
+  }
+  return 0;
+}
+
+void ACMILBC::DestructEncoderSafe() {
+  encoder_initialized_ = false;
+  encoder_exist_ = false;
+  if (encoder_inst_ptr_ != NULL) {
+    WebRtcIlbcfix_EncoderFree(encoder_inst_ptr_);
+    encoder_inst_ptr_ = NULL;
+  }
+}
+
+void ACMILBC::InternalDestructEncoderInst(void* ptr_inst) {
+  if (ptr_inst != NULL) {
+    WebRtcIlbcfix_EncoderFree(static_cast<iLBC_encinst_t_*>(ptr_inst));
+  }
+  return;
+}
+
+int16_t ACMILBC::SetBitRateSafe(const int32_t rate) {
+  // Check that rate is valid. No need to store the value
+  if (rate == 13300) {
+    WebRtcIlbcfix_EncoderInit(encoder_inst_ptr_, 30);
+  } else if (rate == 15200) {
+    WebRtcIlbcfix_EncoderInit(encoder_inst_ptr_, 20);
+  } else {
+    return -1;
+  }
+  encoder_params_.codec_inst.rate = rate;
+
+  return 0;
+}
+
+#endif
+
+}  // namespace webrtc
diff --git a/webrtc/modules/audio_coding/main/acm2/acm_ilbc.h b/webrtc/modules/audio_coding/main/acm2/acm_ilbc.h
new file mode 100644
index 0000000..11e759c
--- /dev/null
+++ b/webrtc/modules/audio_coding/main/acm2/acm_ilbc.h
@@ -0,0 +1,48 @@
+/*
+ *  Copyright (c) 2012 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_MAIN_SOURCE_ACM_ILBC_H_
+#define WEBRTC_MODULES_AUDIO_CODING_MAIN_SOURCE_ACM_ILBC_H_
+
+#include "webrtc/modules/audio_coding/main/source/acm_generic_codec.h"
+
+// forward declaration
+struct iLBC_encinst_t_;
+struct iLBC_decinst_t_;
+
+namespace webrtc {
+
+class ACMILBC : public ACMGenericCodec {
+ public:
+  explicit ACMILBC(int16_t codec_id);
+  ~ACMILBC();
+
+  // for FEC
+  ACMGenericCodec* CreateInstance(void);
+
+  int16_t InternalEncode(uint8_t* bitstream, int16_t* bitstream_len_byte);
+
+  int16_t InternalInitEncoder(WebRtcACMCodecParams* codec_params);
+
+ protected:
+  int16_t SetBitRateSafe(const int32_t rate);
+
+  void DestructEncoderSafe();
+
+  int16_t InternalCreateEncoder();
+
+  void InternalDestructEncoderInst(void* ptr_inst);
+
+  iLBC_encinst_t_* encoder_inst_ptr_;
+};
+
+}  // namespace webrtc
+
+#endif  // WEBRTC_MODULES_AUDIO_CODING_MAIN_SOURCE_ACM_ILBC_H_
diff --git a/webrtc/modules/audio_coding/main/acm2/acm_isac.cc b/webrtc/modules/audio_coding/main/acm2/acm_isac.cc
new file mode 100644
index 0000000..1c7e8b3
--- /dev/null
+++ b/webrtc/modules/audio_coding/main/acm2/acm_isac.cc
@@ -0,0 +1,829 @@
+/*
+ *  Copyright (c) 2012 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 "webrtc/modules/audio_coding/main/source/acm_isac.h"
+
+#include <assert.h>
+
+#include "webrtc/modules/audio_coding/main/interface/audio_coding_module_typedefs.h"
+#include "webrtc/modules/audio_coding/main/source/acm_codec_database.h"
+#include "webrtc/modules/audio_coding/main/source/acm_common_defs.h"
+#include "webrtc/modules/audio_coding/neteq4/interface/audio_decoder.h"
+#include "webrtc/system_wrappers/interface/trace.h"
+
+#ifdef WEBRTC_CODEC_ISAC
+#include "webrtc/modules/audio_coding/codecs/isac/main/interface/isac.h"
+#endif
+
+#ifdef WEBRTC_CODEC_ISACFX
+#include "webrtc/modules/audio_coding/codecs/isac/fix/interface/isacfix.h"
+#endif
+
+#if defined (WEBRTC_CODEC_ISAC) || defined (WEBRTC_CODEC_ISACFX)
+#include "webrtc/modules/audio_coding/main/source/acm_isac_macros.h"
+#endif
+
+namespace webrtc {
+
+// we need this otherwise we cannot use forward declaration
+// in the header file
+#if (defined(WEBRTC_CODEC_ISAC) || defined(WEBRTC_CODEC_ISACFX))
+struct ACMISACInst {
+  ACM_ISAC_STRUCT* inst;
+};
+#endif
+
+#define ISAC_MIN_RATE 10000
+#define ISAC_MAX_RATE 56000
+
+// Tables for bandwidth estimates
+#define NR_ISAC_BANDWIDTHS 24
+static const int32_t kIsacRatesWb[NR_ISAC_BANDWIDTHS] = {
+    10000, 11100, 12300, 13700, 15200, 16900, 18800, 20900, 23300, 25900, 28700,
+    31900, 10100, 11200, 12400, 13800, 15300, 17000, 18900, 21000, 23400, 26000,
+    28800, 32000};
+
+static const int32_t kIsacRatesSwb[NR_ISAC_BANDWIDTHS] = {
+    10000, 11000, 12400, 13800, 15300, 17000, 18900, 21000, 23200, 25400, 27600,
+    29800, 32000, 34100, 36300, 38500, 40700, 42900, 45100, 47300, 49500, 51700,
+    53900, 56000 };
+
+#if (!defined(WEBRTC_CODEC_ISAC) && !defined(WEBRTC_CODEC_ISACFX))
+
+ACMISAC::ACMISAC(int16_t /* codec_id */)
+    : 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) {}
+
+ACMISAC::~ACMISAC() {
+  return;
+}
+
+ACMGenericCodec* ACMISAC::CreateInstance(void) { return NULL; }
+
+int16_t ACMISAC::InternalEncode(uint8_t* /* bitstream */,
+                                int16_t* /* bitstream_len_byte */) {
+  return -1;
+}
+
+int16_t ACMISAC::InternalInitEncoder(WebRtcACMCodecParams* /* codec_params */) {
+  return -1;
+}
+
+int16_t ACMISAC::InternalInitDecoder(WebRtcACMCodecParams* /* codec_params */) {
+  return -1;
+}
+
+int16_t ACMISAC::InternalCreateEncoder() { return -1; }
+
+void ACMISAC::DestructEncoderSafe() { return; }
+
+void ACMISAC::InternalDestructEncoderInst(void* /* ptr_inst */) { return; }
+
+int16_t ACMISAC::Transcode(uint8_t* /* bitstream */,
+                           int16_t* /* bitstream_len_byte */,
+                           int16_t /* q_bwe */,
+                           int32_t /* scale */,
+                           bool /* is_red */) {
+  return -1;
+}
+
+int16_t ACMISAC::SetBitRateSafe(int32_t /* bit_rate */) { return -1; }
+
+int32_t ACMISAC::GetEstimatedBandwidthSafe() { return -1; }
+
+int32_t ACMISAC::SetEstimatedBandwidthSafe(int32_t /* estimated_bandwidth */) {
+  return -1;
+}
+
+int32_t ACMISAC::GetRedPayloadSafe(uint8_t* /* red_payload */,
+                                   int16_t* /* payload_bytes */) {
+  return -1;
+}
+
+int16_t ACMISAC::UpdateDecoderSampFreq(int16_t /* codec_id */) { return -1; }
+
+int16_t ACMISAC::UpdateEncoderSampFreq(uint16_t /* encoder_samp_freq_hz */) {
+  return -1;
+}
+
+int16_t ACMISAC::EncoderSampFreq(uint16_t* /* samp_freq_hz */) { return -1; }
+
+int32_t ACMISAC::ConfigISACBandwidthEstimator(
+    const uint8_t /* init_frame_size_msec */,
+    const uint16_t /* init_rate_bit_per_sec */,
+    const bool /* enforce_frame_size  */) {
+  return -1;
+}
+
+int32_t ACMISAC::SetISACMaxPayloadSize(
+    const uint16_t /* max_payload_len_bytes */) {
+  return -1;
+}
+
+int32_t ACMISAC::SetISACMaxRate(const uint32_t /* max_rate_bit_per_sec */) {
+  return -1;
+}
+
+void ACMISAC::UpdateFrameLen() { return; }
+
+void ACMISAC::CurrentRate(int32_t* /*rate_bit_per_sec */) { return; }
+
+bool ACMISAC::DecoderParamsSafe(WebRtcACMCodecParams* /* dec_params */,
+                                const uint8_t /* payload_type */) {
+  return false;
+}
+
+int16_t ACMISAC::REDPayloadISAC(const int32_t /* isac_rate */,
+                                const int16_t /* isac_bw_estimate */,
+                                uint8_t* /* payload */,
+                                int16_t* /* payload_len_bytes */) {
+  return -1;
+}
+
+AudioDecoder* ACMISAC::Decoder(int /* codec_id */) { return NULL; }
+
+#else     //===================== Actual Implementation =======================
+
+#ifdef WEBRTC_CODEC_ISACFX
+
+// How the scaling is computed. iSAC computes a gain based on the
+// bottleneck. It follows the following expression for that
+//
+// G(BN_kbps) = pow(10, (a + b * BN_kbps + c * BN_kbps * BN_kbps) / 20.0)
+//              / 3.4641;
+//
+// Where for 30 ms framelength we have,
+//
+// a = -23; b = 0.48; c = 0;
+//
+// As the default encoder is operating at 32kbps we have the scale as
+//
+// S(BN_kbps) = G(BN_kbps) / G(32);
+
+#define ISAC_NUM_SUPPORTED_RATES 9
+
+static const uint16_t kIsacSuportedRates[ISAC_NUM_SUPPORTED_RATES] = {
+    32000, 30000, 26000, 23000, 21000, 19000, 17000, 15000, 12000};
+
+static const float kIsacScale[ISAC_NUM_SUPPORTED_RATES] = {
+    1.0f,    0.8954f,  0.7178f, 0.6081f, 0.5445f,
+    0.4875f, 0.4365f,  0.3908f, 0.3311f
+};
+
+enum IsacSamplingRate {
+  kIsacWideband = 16,
+  kIsacSuperWideband = 32
+};
+
+static float ACMISACFixTranscodingScale(uint16_t rate) {
+  // find the scale for transcoding, the scale is rounded
+  // downward
+  float scale = -1;
+  for (int16_t n = 0; n < ISAC_NUM_SUPPORTED_RATES; n++) {
+    if (rate >= kIsacSuportedRates[n]) {
+      scale = kIsacScale[n];
+      break;
+    }
+  }
+  return scale;
+}
+
+static void ACMISACFixGetSendBitrate(ACM_ISAC_STRUCT* inst,
+                                     int32_t* bottleneck) {
+  *bottleneck = WebRtcIsacfix_GetUplinkBw(inst);
+}
+
+static int16_t ACMISACFixGetNewBitstream(ACM_ISAC_STRUCT* inst,
+                                         int16_t bwe_index,
+                                         int16_t /* jitter_index */,
+                                         int32_t rate,
+                                         int16_t* bitstream,
+                                         bool is_red) {
+  if (is_red) {
+    // RED not supported with iSACFIX
+    return -1;
+  }
+  float scale = ACMISACFixTranscodingScale((uint16_t)rate);
+  return WebRtcIsacfix_GetNewBitStream(inst, bwe_index, scale, bitstream);
+}
+
+static int16_t ACMISACFixGetSendBWE(ACM_ISAC_STRUCT* inst,
+                                    int16_t* rate_index,
+                                    int16_t* /* dummy */) {
+  int16_t local_rate_index;
+  int16_t status = WebRtcIsacfix_GetDownLinkBwIndex(inst, &local_rate_index);
+  if (status < 0) {
+    return -1;
+  } else {
+    *rate_index = local_rate_index;
+    return 0;
+  }
+}
+
+static int16_t ACMISACFixControlBWE(ACM_ISAC_STRUCT* inst,
+                                    int32_t rate_bps,
+                                    int16_t frame_size_ms,
+                                    int16_t enforce_frame_size) {
+  return WebRtcIsacfix_ControlBwe(
+      inst, (int16_t)rate_bps, frame_size_ms, enforce_frame_size);
+}
+
+static int16_t ACMISACFixControl(ACM_ISAC_STRUCT* inst,
+                                 int32_t rate_bps,
+                                 int16_t frame_size_ms) {
+  return WebRtcIsacfix_Control(inst, (int16_t)rate_bps, frame_size_ms);
+}
+
+// The following two function should have the same signature as their counter
+// part in iSAC floating-point, i.e. WebRtcIsac_EncSampRate &
+// WebRtcIsac_DecSampRate.
+static uint16_t ACMISACFixGetEncSampRate(ACM_ISAC_STRUCT* /* inst */) {
+  return 16000;
+}
+
+static uint16_t ACMISACFixGetDecSampRate(ACM_ISAC_STRUCT* /* inst */) {
+  return 16000;
+}
+
+#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),
+                               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<ISACStruct*>(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),
+      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;
+
+  // Create codec instance.
+  codec_inst_ptr_ = new ACMISACInst;
+  if (codec_inst_ptr_ == NULL) {
+    return;
+  }
+  codec_inst_ptr_->inst = NULL;
+}
+
+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);
+      codec_inst_ptr_->inst = NULL;
+    }
+    delete codec_inst_ptr_;
+    codec_inst_ptr_ = NULL;
+  }
+  return;
+}
+
+ACMGenericCodec* ACMISAC::CreateInstance(void) { return NULL; }
+
+int16_t ACMISAC::InternalEncode(uint8_t* bitstream,
+                                int16_t* bitstream_len_byte) {
+  // ISAC takes 10ms audio every time we call encoder, therefore,
+  // it should be treated like codecs with 'basic coding block'
+  // non-zero, and the following 'while-loop' should not be necessary.
+  // However, due to a mistake in the codec the frame-size might change
+  // 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.
+  if (codec_inst_ptr_ == NULL) {
+    return -1;
+  }
+  *bitstream_len_byte = 0;
+  while ((*bitstream_len_byte == 0) && (in_audio_ix_read_ < frame_len_smpl_)) {
+    if (in_audio_ix_read_ > in_audio_ix_write_) {
+      // something is wrong.
+      WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, unique_id_,
+                   "The actual frame-size of iSAC appears to be larger that "
+                   "expected. All audio pushed in but no bit-stream is "
+                   "generated.");
+      return -1;
+    }
+    *bitstream_len_byte = ACM_ISAC_ENCODE(
+        codec_inst_ptr_->inst, &in_audio_[in_audio_ix_read_],
+        reinterpret_cast<int16_t*>(bitstream));
+    // increment the read index this tell the caller that how far
+    // we have gone forward in reading the audio buffer
+    in_audio_ix_read_ += samples_in_10ms_audio_;
+  }
+  if (*bitstream_len_byte == 0) {
+    WEBRTC_TRACE(webrtc::kTraceWarning, webrtc::kTraceAudioCoding, unique_id_,
+                 "ISAC Has encoded the whole frame but no bit-stream is "
+                 "generated.");
+  }
+
+  // a packet is generated iSAC, is set in adaptive mode may change
+  // the frame length and we like to update the bottleneck value as
+  // well, although updating bottleneck is not crucial
+  if ((*bitstream_len_byte > 0) && (isac_coding_mode_ == ADAPTIVE)) {
+    ACM_ISAC_GETSENDBITRATE(codec_inst_ptr_->inst, &isac_current_bn_);
+  }
+  UpdateFrameLen();
+  return *bitstream_len_byte;
+}
+
+int16_t ACMISAC::InternalInitEncoder(WebRtcACMCodecParams* codec_params) {
+  // if rate is set to -1 then iSAC has to be in adaptive mode
+  if (codec_params->codec_inst.rate == -1) {
+    isac_coding_mode_ = ADAPTIVE;
+  } else if ((codec_params->codec_inst.rate >= ISAC_MIN_RATE) &&
+             (codec_params->codec_inst.rate <= ISAC_MAX_RATE)) {
+    // sanity check that rate is in acceptable range
+    isac_coding_mode_ = CHANNEL_INDEPENDENT;
+    isac_current_bn_ = codec_params->codec_inst.rate;
+  } else {
+    return -1;
+  }
+
+  // we need to set the encoder sampling frequency.
+  if (UpdateEncoderSampFreq((uint16_t)codec_params->codec_inst.plfreq) < 0) {
+    return -1;
+  }
+  if (ACM_ISAC_ENCODERINIT(codec_inst_ptr_->inst, isac_coding_mode_) < 0) {
+    return -1;
+  }
+
+  // apply the frame-size and rate if operating in
+  // channel-independent mode
+  if (isac_coding_mode_ == CHANNEL_INDEPENDENT) {
+    if (ACM_ISAC_CONTROL(codec_inst_ptr_->inst,
+                         codec_params->codec_inst.rate,
+                         codec_params->codec_inst.pacsize /
+                         (codec_params->codec_inst.plfreq / 1000)) < 0) {
+      return -1;
+    }
+  } else {
+    // We need this for adaptive case and has to be called
+    // after initialization
+    ACM_ISAC_GETSENDBITRATE(codec_inst_ptr_->inst, &isac_current_bn_);
+  }
+  frame_len_smpl_ = ACM_ISAC_GETNEWFRAMELEN(codec_inst_ptr_->inst);
+  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() {
+  if (codec_inst_ptr_ == NULL) {
+    return -1;
+  }
+  decoder_initialized_ = false;
+  int16_t status = ACM_ISAC_CREATE(&(codec_inst_ptr_->inst));
+
+  if (status < 0)
+    codec_inst_ptr_->inst = NULL;
+  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,
+                           int32_t rate,
+                           bool is_red) {
+  int16_t jitter_info = 0;
+  // transcode from a higher rate to lower rate sanity check
+  if (codec_inst_ptr_ == NULL) {
+    return -1;
+  }
+
+  *bitstream_len_byte = ACM_ISAC_GETNEWBITSTREAM(
+      codec_inst_ptr_->inst, q_bwe, jitter_info, rate,
+      reinterpret_cast<int16_t*>(bitstream), (is_red) ? 1 : 0);
+
+  if (*bitstream_len_byte < 0) {
+    // error happened
+    *bitstream_len_byte = 0;
+    return -1;
+  } else {
+    return *bitstream_len_byte;
+  }
+}
+
+int16_t ACMISAC::SetBitRateSafe(int32_t bit_rate) {
+  if (codec_inst_ptr_ == NULL) {
+    return -1;
+  }
+  uint16_t encoder_samp_freq;
+  EncoderSampFreq(&encoder_samp_freq);
+  bool reinit = false;
+  // change the BN of iSAC
+  if (bit_rate == -1) {
+    // ADAPTIVE MODE
+    // Check if it was already in adaptive mode
+    if (isac_coding_mode_ != ADAPTIVE) {
+      // was not in adaptive, then set the mode to adaptive
+      // and flag for re-initialization
+      isac_coding_mode_ = ADAPTIVE;
+      reinit = true;
+    }
+  } else if ((bit_rate >= ISAC_MIN_RATE) && (bit_rate <= ISAC_MAX_RATE)) {
+    // Sanity check if the rate valid
+    // check if it was in channel-independent mode before
+    if (isac_coding_mode_ != CHANNEL_INDEPENDENT) {
+      // was not in channel independent, set the mode to
+      // channel-independent and flag for re-initialization
+      isac_coding_mode_ = CHANNEL_INDEPENDENT;
+      reinit = true;
+    }
+    // store the bottleneck
+    isac_current_bn_ = (uint16_t)bit_rate;
+  } else {
+    // invlaid rate
+    return -1;
+  }
+
+  int16_t status = 0;
+  if (reinit) {
+    // initialize and check if it is successful
+    if (ACM_ISAC_ENCODERINIT(codec_inst_ptr_->inst, isac_coding_mode_) < 0) {
+      // failed initialization
+      return -1;
+    }
+  }
+  if (isac_coding_mode_ == CHANNEL_INDEPENDENT) {
+    status = ACM_ISAC_CONTROL(
+        codec_inst_ptr_->inst, isac_current_bn_,
+        (encoder_samp_freq == 32000 || encoder_samp_freq == 48000) ? 30 :
+            (frame_len_smpl_ / 16));
+    if (status < 0) {
+      status = -1;
+    }
+  }
+
+  // Update encoder parameters
+  encoder_params_.codec_inst.rate = bit_rate;
+
+  UpdateFrameLen();
+  return status;
+}
+
+int32_t ACMISAC::GetEstimatedBandwidthSafe() {
+  int16_t bandwidth_index = 0;
+  int16_t delay_index = 0;
+  int samp_rate;
+
+  // Get bandwidth information
+  ACM_ISAC_GETSENDBWE(codec_inst_ptr_->inst, &bandwidth_index, &delay_index);
+
+  // Validy check of index
+  if ((bandwidth_index < 0) || (bandwidth_index >= NR_ISAC_BANDWIDTHS)) {
+    return -1;
+  }
+
+  // Check sample frequency
+  samp_rate = ACM_ISAC_GETDECSAMPRATE(codec_inst_ptr_->inst);
+  if (samp_rate == 16000) {
+    return kIsacRatesWb[bandwidth_index];
+  } else {
+    return kIsacRatesSwb[bandwidth_index];
+  }
+}
+
+int32_t ACMISAC::SetEstimatedBandwidthSafe(int32_t estimated_bandwidth) {
+  int samp_rate;
+  int16_t bandwidth_index;
+
+  // Check sample frequency and choose appropriate table
+  samp_rate = ACM_ISAC_GETENCSAMPRATE(codec_inst_ptr_->inst);
+
+  if (samp_rate == 16000) {
+    // Search through the WB rate table to find the index
+    bandwidth_index = NR_ISAC_BANDWIDTHS / 2 - 1;
+    for (int i = 0; i < (NR_ISAC_BANDWIDTHS / 2); i++) {
+      if (estimated_bandwidth == kIsacRatesWb[i]) {
+        bandwidth_index = i;
+        break;
+      } else if (estimated_bandwidth
+          == kIsacRatesWb[i + NR_ISAC_BANDWIDTHS / 2]) {
+        bandwidth_index = i + NR_ISAC_BANDWIDTHS / 2;
+        break;
+      } else if (estimated_bandwidth < kIsacRatesWb[i]) {
+        bandwidth_index = i;
+        break;
+      }
+    }
+  } else {
+    // Search through the SWB rate table to find the index
+    bandwidth_index = NR_ISAC_BANDWIDTHS - 1;
+    for (int i = 0; i < NR_ISAC_BANDWIDTHS; i++) {
+      if (estimated_bandwidth <= kIsacRatesSwb[i]) {
+        bandwidth_index = i;
+        break;
+      }
+    }
+  }
+
+  // Set iSAC Bandwidth Estimate
+  ACM_ISAC_SETBWE(codec_inst_ptr_->inst, bandwidth_index);
+
+  return 0;
+}
+
+int32_t ACMISAC::GetRedPayloadSafe(
+#if (!defined(WEBRTC_CODEC_ISAC))
+    uint8_t* /* red_payload */,
+    int16_t* /* payload_bytes */) {
+  return -1;
+#else
+    uint8_t* red_payload, int16_t* payload_bytes) {
+  int16_t bytes =
+      WebRtcIsac_GetRedPayload(
+          codec_inst_ptr_->inst, reinterpret_cast<int16_t*>(red_payload));
+  if (bytes < 0) {
+    return -1;
+  }
+  *payload_bytes = bytes;
+  return 0;
+#endif
+}
+
+int16_t ACMISAC::UpdateDecoderSampFreq(
+#ifdef WEBRTC_CODEC_ISAC
+    int16_t codec_id) {
+    // The decoder supports only wideband and super-wideband.
+  if (ACMCodecDB::kISAC == codec_id) {
+    return WebRtcIsac_SetDecSampRate(codec_inst_ptr_->inst, 16000);
+  } else if (ACMCodecDB::kISACSWB == codec_id ||
+             ACMCodecDB::kISACFB == codec_id) {
+    return WebRtcIsac_SetDecSampRate(codec_inst_ptr_->inst, 32000);
+  } else {
+    return -1;
+  }
+#else
+    int16_t /* codec_id */) {
+  return 0;
+#endif
+}
+
+int16_t ACMISAC::UpdateEncoderSampFreq(
+#ifdef WEBRTC_CODEC_ISAC
+    uint16_t encoder_samp_freq_hz) {
+  uint16_t current_samp_rate_hz;
+  EncoderSampFreq(&current_samp_rate_hz);
+
+  if (current_samp_rate_hz != encoder_samp_freq_hz) {
+    if ((encoder_samp_freq_hz != 16000) && (encoder_samp_freq_hz != 32000) &&
+        (encoder_samp_freq_hz != 48000)) {
+      return -1;
+    } else {
+      in_audio_ix_read_ = 0;
+      in_audio_ix_write_ = 0;
+      in_timestamp_ix_write_ = 0;
+      if (WebRtcIsac_SetEncSampRate(codec_inst_ptr_->inst,
+                                    encoder_samp_freq_hz) < 0) {
+        return -1;
+      }
+      samples_in_10ms_audio_ = encoder_samp_freq_hz / 100;
+      frame_len_smpl_ = ACM_ISAC_GETNEWFRAMELEN(codec_inst_ptr_->inst);
+      encoder_params_.codec_inst.pacsize = frame_len_smpl_;
+      encoder_params_.codec_inst.plfreq = encoder_samp_freq_hz;
+      return 0;
+    }
+  }
+#else
+    uint16_t /* codec_id */) {
+#endif
+  return 0;
+}
+
+int16_t ACMISAC::EncoderSampFreq(uint16_t* samp_freq_hz) {
+  *samp_freq_hz = ACM_ISAC_GETENCSAMPRATE(codec_inst_ptr_->inst);
+  return 0;
+}
+
+int32_t ACMISAC::ConfigISACBandwidthEstimator(
+    const uint8_t init_frame_size_msec,
+    const uint16_t init_rate_bit_per_sec,
+    const bool enforce_frame_size) {
+  int16_t status;
+  {
+    uint16_t samp_freq_hz;
+    EncoderSampFreq(&samp_freq_hz);
+    // 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.
+    if (samp_freq_hz == 32000 || samp_freq_hz == 48000) {
+      status = ACM_ISAC_CONTROL_BWE(codec_inst_ptr_->inst,
+                                    init_rate_bit_per_sec, 30, 1);
+    } else {
+      status = ACM_ISAC_CONTROL_BWE(codec_inst_ptr_->inst,
+                                    init_rate_bit_per_sec,
+                                    init_frame_size_msec,
+                                    enforce_frame_size ? 1 : 0);
+    }
+  }
+  if (status < 0) {
+    WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, unique_id_,
+                 "Couldn't config iSAC BWE.");
+    return -1;
+  }
+  UpdateFrameLen();
+  ACM_ISAC_GETSENDBITRATE(codec_inst_ptr_->inst, &isac_current_bn_);
+  return 0;
+}
+
+int32_t ACMISAC::SetISACMaxPayloadSize(const uint16_t max_payload_len_bytes) {
+  return ACM_ISAC_SETMAXPAYLOADSIZE(codec_inst_ptr_->inst,
+                                    max_payload_len_bytes);
+}
+
+int32_t ACMISAC::SetISACMaxRate(const uint32_t max_rate_bit_per_sec) {
+  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) {
+    ACM_ISAC_GETSENDBITRATE(codec_inst_ptr_->inst, rate_bit_per_sec);
+  }
+}
+
+int16_t ACMISAC::REDPayloadISAC(const int32_t isac_rate,
+                                const int16_t isac_bw_estimate,
+                                uint8_t* payload,
+                                int16_t* payload_len_bytes) {
+  int16_t status;
+  ReadLockScoped rl(codec_wrapper_lock_);
+  status =
+      Transcode(payload, payload_len_bytes, isac_bw_estimate, isac_rate, true);
+  return status;
+}
+
+AudioDecoder* ACMISAC::Decoder(int codec_id) {
+  if (audio_decoder_)
+    return audio_decoder_;
+
+  // Create iSAC instance if it does not exist.
+  if (!encoder_exist_) {
+    assert(codec_inst_ptr_->inst == NULL);
+    encoder_initialized_ = false;
+    decoder_initialized_ = false;
+    if (ACM_ISAC_CREATE(&(codec_inst_ptr_->inst)) < 0) {
+      codec_inst_ptr_->inst = NULL;
+      return NULL;
+    }
+    encoder_exist_ = true;
+  }
+
+  WebRtcACMCodecParams codec_params;
+  if (!encoder_initialized_ || !decoder_initialized_) {
+    ACMCodecDB::Codec(codec_id, &codec_params.codec_inst);
+    // The following three values are not used but we set them to valid values.
+    codec_params.enable_dtx = false;
+    codec_params.enable_vad = false;
+    codec_params.vad_mode = VADNormal;
+  }
+
+  if (!encoder_initialized_) {
+    // Initialize encoder to make sure bandwidth estimator works.
+    if (InternalInitEncoder(&codec_params) < 0)
+      return NULL;
+    encoder_initialized_ = true;
+  }
+
+  if (!decoder_initialized_) {
+    if (InternalInitDecoder(&codec_params) < 0)
+      return NULL;
+    decoder_initialized_ = true;
+  }
+
+  audio_decoder_ = new AcmAudioDecoderIsac(codec_id, codec_inst_ptr_->inst);
+  return audio_decoder_;
+}
+
+#endif
+
+}  // namespace webrtc
diff --git a/webrtc/modules/audio_coding/main/acm2/acm_isac.h b/webrtc/modules/audio_coding/main/acm2/acm_isac.h
new file mode 100644
index 0000000..f4cf1a6
--- /dev/null
+++ b/webrtc/modules/audio_coding/main/acm2/acm_isac.h
@@ -0,0 +1,98 @@
+/*
+ *  Copyright (c) 2012 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_MAIN_SOURCE_ACM_ISAC_H_
+#define WEBRTC_MODULES_AUDIO_CODING_MAIN_SOURCE_ACM_ISAC_H_
+
+#include "webrtc/modules/audio_coding/main/source/acm_generic_codec.h"
+
+namespace webrtc {
+
+struct ACMISACInst;
+class AcmAudioDecoderIsac;
+
+enum IsacCodingMode {
+  ADAPTIVE,
+  CHANNEL_INDEPENDENT
+};
+
+class ACMISAC : public ACMGenericCodec {
+ 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);
+
+  int16_t UpdateEncoderSampFreq(uint16_t samp_freq_hz);
+
+  int16_t EncoderSampFreq(uint16_t* samp_freq_hz);
+
+  int32_t ConfigISACBandwidthEstimator(const uint8_t init_frame_size_msec,
+                                       const uint16_t init_rate_bit_per_sec,
+                                       const bool enforce_frame_size);
+
+  int32_t SetISACMaxPayloadSize(const uint16_t max_payload_len_bytes);
+
+  int32_t SetISACMaxRate(const uint32_t max_rate_bit_per_sec);
+
+  int16_t REDPayloadISAC(const int32_t isac_rate,
+                         const int16_t isac_bw_estimate,
+                         uint8_t* payload,
+                         int16_t* payload_len_bytes);
+
+ 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);
+
+  ACMISACInst* codec_inst_ptr_;
+  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_;
+};
+
+}  // namespace webrtc
+
+#endif  // WEBRTC_MODULES_AUDIO_CODING_MAIN_SOURCE_ACM_ISAC_H_
diff --git a/webrtc/modules/audio_coding/main/acm2/acm_isac_macros.h b/webrtc/modules/audio_coding/main/acm2/acm_isac_macros.h
new file mode 100644
index 0000000..646b3cc
--- /dev/null
+++ b/webrtc/modules/audio_coding/main/acm2/acm_isac_macros.h
@@ -0,0 +1,76 @@
+/*
+ *  Copyright (c) 2012 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_MAIN_SOURCE_ACM_ISAC_MACROS_H_
+#define WEBRTC_MODULES_AUDIO_CODING_MAIN_SOURCE_ACM_ISAC_MACROS_H_
+
+#include "webrtc/engine_configurations.h"
+
+namespace webrtc {
+
+#ifdef WEBRTC_CODEC_ISAC
+#define ACM_ISAC_CREATE            WebRtcIsac_Create
+#define ACM_ISAC_FREE              WebRtcIsac_Free
+#define ACM_ISAC_ENCODERINIT       WebRtcIsac_EncoderInit
+#define ACM_ISAC_ENCODE            WebRtcIsac_Encode
+#define ACM_ISAC_DECODERINIT       WebRtcIsac_DecoderInit
+#define ACM_ISAC_DECODE_BWE        WebRtcIsac_UpdateBwEstimate
+#define ACM_ISAC_DECODE_B          WebRtcIsac_Decode
+#define ACM_ISAC_DECODEPLC         WebRtcIsac_DecodePlc
+#define ACM_ISAC_CONTROL           WebRtcIsac_Control
+#define ACM_ISAC_CONTROL_BWE       WebRtcIsac_ControlBwe
+#define ACM_ISAC_GETFRAMELEN       WebRtcIsac_ReadFrameLen
+#define ACM_ISAC_GETERRORCODE      WebRtcIsac_GetErrorCode
+#define ACM_ISAC_GETSENDBITRATE    WebRtcIsac_GetUplinkBw
+#define ACM_ISAC_SETMAXPAYLOADSIZE WebRtcIsac_SetMaxPayloadSize
+#define ACM_ISAC_SETMAXRATE        WebRtcIsac_SetMaxRate
+#define ACM_ISAC_GETNEWBITSTREAM   WebRtcIsac_GetNewBitStream
+#define ACM_ISAC_GETSENDBWE        WebRtcIsac_GetDownLinkBwIndex
+#define ACM_ISAC_SETBWE            WebRtcIsac_UpdateUplinkBw
+#define ACM_ISAC_GETBWE            WebRtcIsac_ReadBwIndex
+#define ACM_ISAC_GETNEWFRAMELEN    WebRtcIsac_GetNewFrameLen
+#define ACM_ISAC_STRUCT            ISACStruct
+#define ACM_ISAC_GETENCSAMPRATE    WebRtcIsac_EncSampRate
+#define ACM_ISAC_GETDECSAMPRATE    WebRtcIsac_DecSampRate
+#define ACM_ISAC_DECODERCU         WebRtcIsac_DecodeRcu
+#endif
+
+#ifdef WEBRTC_CODEC_ISACFX
+#define ACM_ISAC_CREATE            WebRtcIsacfix_Create
+#define ACM_ISAC_FREE              WebRtcIsacfix_Free
+#define ACM_ISAC_ENCODERINIT       WebRtcIsacfix_EncoderInit
+#define ACM_ISAC_ENCODE            WebRtcIsacfix_Encode
+#define ACM_ISAC_DECODERINIT       WebRtcIsacfix_DecoderInit
+#define ACM_ISAC_DECODE_BWE        WebRtcIsacfix_UpdateBwEstimate
+#define ACM_ISAC_DECODE_B          WebRtcIsacfix_Decode
+#define ACM_ISAC_DECODEPLC         WebRtcIsacfix_DecodePlc
+#define ACM_ISAC_CONTROL           ACMISACFixControl  // Local Impl
+#define ACM_ISAC_CONTROL_BWE       ACMISACFixControlBWE  // Local Impl
+#define ACM_ISAC_GETFRAMELEN       WebRtcIsacfix_ReadFrameLen
+#define ACM_ISAC_GETERRORCODE      WebRtcIsacfix_GetErrorCode
+#define ACM_ISAC_GETSENDBITRATE    ACMISACFixGetSendBitrate  // Local Impl
+#define ACM_ISAC_SETMAXPAYLOADSIZE WebRtcIsacfix_SetMaxPayloadSize
+#define ACM_ISAC_SETMAXRATE        WebRtcIsacfix_SetMaxRate
+#define ACM_ISAC_GETNEWBITSTREAM   ACMISACFixGetNewBitstream  // Local Impl
+#define ACM_ISAC_GETSENDBWE        ACMISACFixGetSendBWE  // Local Impl
+#define ACM_ISAC_SETBWE            WebRtcIsacfix_UpdateUplinkBw
+#define ACM_ISAC_GETBWE            WebRtcIsacfix_ReadBwIndex
+#define ACM_ISAC_GETNEWFRAMELEN    WebRtcIsacfix_GetNewFrameLen
+#define ACM_ISAC_STRUCT            ISACFIX_MainStruct
+#define ACM_ISAC_GETENCSAMPRATE    ACMISACFixGetEncSampRate  // Local Impl
+#define ACM_ISAC_GETDECSAMPRATE    ACMISACFixGetDecSampRate  // Local Impl
+#define ACM_ISAC_DECODERCU         WebRtcIsacfix_Decode  // No special RCU
+                                                         // decoder
+#endif
+
+}  // namespace webrtc
+
+#endif  // WEBRTC_MODULES_AUDIO_CODING_MAIN_SOURCE_ACM_ISAC_MACROS_H_
+
diff --git a/webrtc/modules/audio_coding/main/acm2/acm_neteq_unittest.cc b/webrtc/modules/audio_coding/main/acm2/acm_neteq_unittest.cc
new file mode 100644
index 0000000..3f5a200
--- /dev/null
+++ b/webrtc/modules/audio_coding/main/acm2/acm_neteq_unittest.cc
@@ -0,0 +1,13 @@
+/*
+ *  Copyright (c) 2012 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.
+ */
+
+// This file contains unit tests for ACM's NetEQ wrapper (class ACMNetEQ).
+
+namespace webrtc {}  // namespace
diff --git a/webrtc/modules/audio_coding/main/acm2/acm_opus.cc b/webrtc/modules/audio_coding/main/acm2/acm_opus.cc
new file mode 100644
index 0000000..a738085
--- /dev/null
+++ b/webrtc/modules/audio_coding/main/acm2/acm_opus.cc
@@ -0,0 +1,187 @@
+/*
+ *  Copyright (c) 2012 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 "webrtc/modules/audio_coding/main/source/acm_opus.h"
+
+#ifdef WEBRTC_CODEC_OPUS
+#include "webrtc/modules/audio_coding/codecs/opus/interface/opus_interface.h"
+#include "webrtc/modules/audio_coding/main/source/acm_codec_database.h"
+#include "webrtc/modules/audio_coding/main/source/acm_common_defs.h"
+#include "webrtc/system_wrappers/interface/trace.h"
+#endif
+
+namespace webrtc {
+
+#ifndef WEBRTC_CODEC_OPUS
+
+ACMOpus::ACMOpus(int16_t /* codec_id */)
+    : encoder_inst_ptr_(NULL),
+      sample_freq_(0),
+      bitrate_(0),
+      channels_(1) {
+  return;
+}
+
+ACMOpus::~ACMOpus() {
+  return;
+}
+
+int16_t ACMOpus::InternalEncode(uint8_t* /* bitstream */,
+                                int16_t* /* bitstream_len_byte */) {
+  return -1;
+}
+
+int16_t ACMOpus::InternalInitEncoder(WebRtcACMCodecParams* /* codec_params */) {
+  return -1;
+}
+
+ACMGenericCodec* ACMOpus::CreateInstance(void) {
+  return NULL;
+}
+
+int16_t ACMOpus::InternalCreateEncoder() {
+  return -1;
+}
+
+void ACMOpus::DestructEncoderSafe() {
+  return;
+}
+
+void ACMOpus::InternalDestructEncoderInst(void* /* ptr_inst */) {
+  return;
+}
+
+int16_t ACMOpus::SetBitRateSafe(const int32_t /*rate*/) {
+  return -1;
+}
+
+#else  //===================== Actual Implementation =======================
+
+ACMOpus::ACMOpus(int16_t codec_id)
+    : encoder_inst_ptr_(NULL),
+      sample_freq_(32000),  // Default sampling frequency.
+      bitrate_(20000),  // Default bit-rate.
+      channels_(1) {  // Default mono
+  codec_id_ = codec_id;
+  // Opus has internal DTX, but we dont use it for now.
+  has_internal_dtx_ = false;
+
+  if (codec_id_ != ACMCodecDB::kOpus) {
+    WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, unique_id_,
+                 "Wrong codec id for Opus.");
+    sample_freq_ = -1;
+    bitrate_ = -1;
+  }
+  return;
+}
+
+ACMOpus::~ACMOpus() {
+  if (encoder_inst_ptr_ != NULL) {
+    WebRtcOpus_EncoderFree(encoder_inst_ptr_);
+    encoder_inst_ptr_ = NULL;
+  }
+}
+
+int16_t ACMOpus::InternalEncode(uint8_t* bitstream,
+                                int16_t* bitstream_len_byte) {
+  // Call Encoder.
+  *bitstream_len_byte = WebRtcOpus_Encode(encoder_inst_ptr_,
+                                          &in_audio_[in_audio_ix_read_],
+                                          frame_len_smpl_,
+                                          MAX_PAYLOAD_SIZE_BYTE, bitstream);
+  // Check for error reported from encoder.
+  if (*bitstream_len_byte < 0) {
+    WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, unique_id_,
+                 "InternalEncode: Encode error for Opus");
+    *bitstream_len_byte = 0;
+    return -1;
+  }
+
+  // Increment the read index. This tells the caller how far
+  // we have gone forward in reading the audio buffer.
+  in_audio_ix_read_ += frame_len_smpl_ * channels_;
+
+  return *bitstream_len_byte;
+}
+
+int16_t ACMOpus::InternalInitEncoder(WebRtcACMCodecParams* codec_params) {
+  int16_t ret;
+  if (encoder_inst_ptr_ != NULL) {
+    WebRtcOpus_EncoderFree(encoder_inst_ptr_);
+    encoder_inst_ptr_ = NULL;
+  }
+  ret = WebRtcOpus_EncoderCreate(&encoder_inst_ptr_,
+                                 codec_params->codec_inst.channels);
+  // Store number of channels.
+  channels_ = codec_params->codec_inst.channels;
+
+  if (ret < 0) {
+    WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, unique_id_,
+                 "Encoder creation failed for Opus");
+    return ret;
+  }
+  ret = WebRtcOpus_SetBitRate(encoder_inst_ptr_,
+                              codec_params->codec_inst.rate);
+  if (ret < 0) {
+    WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, unique_id_,
+                 "Setting initial bitrate failed for Opus");
+    return ret;
+  }
+
+  // Store bitrate.
+  bitrate_ = codec_params->codec_inst.rate;
+
+  return 0;
+}
+
+ACMGenericCodec* ACMOpus::CreateInstance(void) {
+  return NULL;
+}
+
+int16_t ACMOpus::InternalCreateEncoder() {
+  // Real encoder will be created in InternalInitEncoder.
+  return 0;
+}
+
+void ACMOpus::DestructEncoderSafe() {
+  if (encoder_inst_ptr_) {
+    WebRtcOpus_EncoderFree(encoder_inst_ptr_);
+    encoder_inst_ptr_ = NULL;
+  }
+}
+
+void ACMOpus::InternalDestructEncoderInst(void* ptr_inst) {
+  if (ptr_inst != NULL) {
+    WebRtcOpus_EncoderFree(static_cast<OpusEncInst*>(ptr_inst));
+  }
+  return;
+}
+
+int16_t ACMOpus::SetBitRateSafe(const int32_t rate) {
+  if (rate < 6000 || rate > 510000) {
+    WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, unique_id_,
+                 "SetBitRateSafe: Invalid rate Opus");
+    return -1;
+  }
+
+  bitrate_ = rate;
+
+  // Ask the encoder for the new rate.
+  if (WebRtcOpus_SetBitRate(encoder_inst_ptr_, bitrate_) >= 0) {
+    encoder_params_.codec_inst.rate = bitrate_;
+    return 0;
+  }
+
+  return -1;
+}
+
+#endif  // WEBRTC_CODEC_OPUS
+
+}  // namespace webrtc
diff --git a/webrtc/modules/audio_coding/main/acm2/acm_opus.h b/webrtc/modules/audio_coding/main/acm2/acm_opus.h
new file mode 100644
index 0000000..28b08b6
--- /dev/null
+++ b/webrtc/modules/audio_coding/main/acm2/acm_opus.h
@@ -0,0 +1,50 @@
+/*
+ *  Copyright (c) 2012 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_MAIN_SOURCE_ACM_OPUS_H_
+#define WEBRTC_MODULES_AUDIO_CODING_MAIN_SOURCE_ACM_OPUS_H_
+
+#include "webrtc/common_audio/resampler/include/resampler.h"
+#include "webrtc/modules/audio_coding/main/source/acm_generic_codec.h"
+
+struct WebRtcOpusEncInst;
+struct WebRtcOpusDecInst;
+
+namespace webrtc {
+
+class ACMOpus : public ACMGenericCodec {
+ public:
+  explicit ACMOpus(int16_t codec_id);
+  ~ACMOpus();
+
+  ACMGenericCodec* CreateInstance(void);
+
+  int16_t InternalEncode(uint8_t* bitstream, int16_t* bitstream_len_byte);
+
+  int16_t InternalInitEncoder(WebRtcACMCodecParams *codec_params);
+
+ protected:
+  void DestructEncoderSafe();
+
+  int16_t InternalCreateEncoder();
+
+  void InternalDestructEncoderInst(void* ptr_inst);
+
+  int16_t SetBitRateSafe(const int32_t rate);
+
+  WebRtcOpusEncInst* encoder_inst_ptr_;
+  uint16_t sample_freq_;
+  uint16_t bitrate_;
+  int channels_;
+};
+
+}  // namespace webrtc
+
+#endif  // WEBRTC_MODULES_AUDIO_CODING_MAIN_SOURCE_ACM_OPUS_H_
diff --git a/webrtc/modules/audio_coding/main/acm2/acm_pcm16b.cc b/webrtc/modules/audio_coding/main/acm2/acm_pcm16b.cc
new file mode 100644
index 0000000..3bc9642
--- /dev/null
+++ b/webrtc/modules/audio_coding/main/acm2/acm_pcm16b.cc
@@ -0,0 +1,92 @@
+/*
+ *  Copyright (c) 2012 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 "webrtc/modules/audio_coding/main/source/acm_pcm16b.h"
+
+#ifdef WEBRTC_CODEC_PCM16
+#include "webrtc/modules/audio_coding/codecs/pcm16b/include/pcm16b.h"
+#include "webrtc/modules/audio_coding/main/source/acm_codec_database.h"
+#include "webrtc/modules/audio_coding/main/source/acm_common_defs.h"
+#include "webrtc/system_wrappers/interface/trace.h"
+#endif
+
+namespace webrtc {
+
+#ifndef WEBRTC_CODEC_PCM16
+
+ACMPCM16B::ACMPCM16B(int16_t /* codec_id */) { return; }
+
+ACMPCM16B::~ACMPCM16B() { return; }
+
+int16_t ACMPCM16B::InternalEncode(uint8_t* /* bitstream */,
+                                  int16_t* /* bitstream_len_byte */) {
+  return -1;
+}
+
+int16_t ACMPCM16B::InternalInitEncoder(
+    WebRtcACMCodecParams* /* codec_params */) {
+  return -1;
+}
+
+ACMGenericCodec* ACMPCM16B::CreateInstance(void) { return NULL; }
+
+int16_t ACMPCM16B::InternalCreateEncoder() { return -1; }
+
+void ACMPCM16B::InternalDestructEncoderInst(void* /* ptr_inst */) { return; }
+
+void ACMPCM16B::DestructEncoderSafe() { return; }
+
+#else  //===================== Actual Implementation =======================
+ACMPCM16B::ACMPCM16B(int16_t codec_id) {
+  codec_id_ = codec_id;
+  sampling_freq_hz_ = ACMCodecDB::CodecFreq(codec_id_);
+}
+
+ACMPCM16B::~ACMPCM16B() { return; }
+
+int16_t ACMPCM16B::InternalEncode(uint8_t* bitstream,
+                                  int16_t* bitstream_len_byte) {
+  *bitstream_len_byte = WebRtcPcm16b_Encode(&in_audio_[in_audio_ix_read_],
+                                            frame_len_smpl_ * num_channels_,
+                                            bitstream);
+  // Increment the read index to tell the caller that how far
+  // we have gone forward in reading the audio buffer.
+  in_audio_ix_read_ += frame_len_smpl_ * num_channels_;
+  return *bitstream_len_byte;
+}
+
+int16_t ACMPCM16B::InternalInitEncoder(
+    WebRtcACMCodecParams* /* codec_params */) {
+  // This codec does not need initialization, PCM has no instance.
+  return 0;
+}
+
+ACMGenericCodec* ACMPCM16B::CreateInstance(void) { return NULL; }
+
+int16_t ACMPCM16B::InternalCreateEncoder() {
+  // PCM has no instance.
+  return 0;
+}
+
+void ACMPCM16B::InternalDestructEncoderInst(void* /* ptr_inst */) {
+  // PCM has no instance.
+  return;
+}
+
+void ACMPCM16B::DestructEncoderSafe() {
+  // PCM has no instance.
+  encoder_exist_ = false;
+  encoder_initialized_ = false;
+  return;
+}
+
+#endif
+
+}  // namespace webrtc
diff --git a/webrtc/modules/audio_coding/main/acm2/acm_pcm16b.h b/webrtc/modules/audio_coding/main/acm2/acm_pcm16b.h
new file mode 100644
index 0000000..a7fff0f
--- /dev/null
+++ b/webrtc/modules/audio_coding/main/acm2/acm_pcm16b.h
@@ -0,0 +1,42 @@
+/*
+ *  Copyright (c) 2012 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_MAIN_SOURCE_ACM_PCM16B_H_
+#define WEBRTC_MODULES_AUDIO_CODING_MAIN_SOURCE_ACM_PCM16B_H_
+
+#include "webrtc/modules/audio_coding/main/source/acm_generic_codec.h"
+
+namespace webrtc {
+
+class ACMPCM16B : public ACMGenericCodec {
+ public:
+  explicit ACMPCM16B(int16_t codec_id);
+  ~ACMPCM16B();
+
+  // For FEC.
+  ACMGenericCodec* CreateInstance(void);
+
+  int16_t InternalEncode(uint8_t* bitstream, int16_t* bitstream_len_byte);
+
+  int16_t InternalInitEncoder(WebRtcACMCodecParams* codec_params);
+
+ protected:
+  void DestructEncoderSafe();
+
+  int16_t InternalCreateEncoder();
+
+  void InternalDestructEncoderInst(void* ptr_inst);
+
+  int32_t sampling_freq_hz_;
+};
+
+}  // namespace webrtc
+
+#endif  // WEBRTC_MODULES_AUDIO_CODING_MAIN_SOURCE_ACM_PCM16B_H_
diff --git a/webrtc/modules/audio_coding/main/acm2/acm_pcma.cc b/webrtc/modules/audio_coding/main/acm2/acm_pcma.cc
new file mode 100644
index 0000000..0d574fe
--- /dev/null
+++ b/webrtc/modules/audio_coding/main/acm2/acm_pcma.cc
@@ -0,0 +1,58 @@
+/*
+ *  Copyright (c) 2012 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 "webrtc/modules/audio_coding/main/source/acm_pcma.h"
+
+#include "webrtc/modules/audio_coding/codecs/g711/include/g711_interface.h"
+#include "webrtc/modules/audio_coding/main/source/acm_common_defs.h"
+#include "webrtc/system_wrappers/interface/trace.h"
+
+// Codec interface
+
+namespace webrtc {
+
+ACMPCMA::ACMPCMA(int16_t codec_id) { codec_id_ = codec_id; }
+
+ACMPCMA::~ACMPCMA() { return; }
+
+int16_t ACMPCMA::InternalEncode(uint8_t* bitstream,
+                                int16_t* bitstream_len_byte) {
+  *bitstream_len_byte = WebRtcG711_EncodeA(
+      NULL, &in_audio_[in_audio_ix_read_], frame_len_smpl_ * num_channels_,
+      reinterpret_cast<int16_t*>(bitstream));
+  // Increment the read index this tell the caller that how far
+  // we have gone forward in reading the audio buffer.
+  in_audio_ix_read_ += frame_len_smpl_ * num_channels_;
+  return *bitstream_len_byte;
+}
+
+int16_t ACMPCMA::InternalInitEncoder(WebRtcACMCodecParams* /* codec_params */) {
+  // This codec does not need initialization, PCM has no instance.
+  return 0;
+}
+
+ACMGenericCodec* ACMPCMA::CreateInstance(void) { return NULL; }
+
+int16_t ACMPCMA::InternalCreateEncoder() {
+  // PCM has no instance.
+  return 0;
+}
+
+void ACMPCMA::InternalDestructEncoderInst(void* /* ptr_inst */) {
+  // PCM has no instance.
+  return;
+}
+
+void ACMPCMA::DestructEncoderSafe() {
+  // PCM has no instance.
+  return;
+}
+
+}  // namespace webrtc
diff --git a/webrtc/modules/audio_coding/main/acm2/acm_pcma.h b/webrtc/modules/audio_coding/main/acm2/acm_pcma.h
new file mode 100644
index 0000000..61386d3
--- /dev/null
+++ b/webrtc/modules/audio_coding/main/acm2/acm_pcma.h
@@ -0,0 +1,40 @@
+/*
+ *  Copyright (c) 2012 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_MAIN_SOURCE_ACM_PCMA_H_
+#define WEBRTC_MODULES_AUDIO_CODING_MAIN_SOURCE_ACM_PCMA_H_
+
+#include "webrtc/modules/audio_coding/main/source/acm_generic_codec.h"
+
+namespace webrtc {
+
+class ACMPCMA : public ACMGenericCodec {
+ public:
+  explicit ACMPCMA(int16_t codec_id);
+  ~ACMPCMA();
+
+  // For FEC.
+  ACMGenericCodec* CreateInstance(void);
+
+  int16_t InternalEncode(uint8_t* bitstream, int16_t* bitstream_len_byte);
+
+  int16_t InternalInitEncoder(WebRtcACMCodecParams* codec_params);
+
+ protected:
+  void DestructEncoderSafe();
+
+  int16_t InternalCreateEncoder();
+
+  void InternalDestructEncoderInst(void* ptr_inst);
+};
+
+}  // namespace webrtc
+
+#endif  // WEBRTC_MODULES_AUDIO_CODING_MAIN_SOURCE_ACM_PCMA_H_
diff --git a/webrtc/modules/audio_coding/main/acm2/acm_pcmu.cc b/webrtc/modules/audio_coding/main/acm2/acm_pcmu.cc
new file mode 100644
index 0000000..441e3dd
--- /dev/null
+++ b/webrtc/modules/audio_coding/main/acm2/acm_pcmu.cc
@@ -0,0 +1,59 @@
+/*
+ *  Copyright (c) 2012 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 "webrtc/modules/audio_coding/main/source/acm_pcmu.h"
+
+#include "webrtc/modules/audio_coding/codecs/g711/include/g711_interface.h"
+#include "webrtc/modules/audio_coding/main/source/acm_common_defs.h"
+#include "webrtc/system_wrappers/interface/trace.h"
+
+// Codec interface.
+
+namespace webrtc {
+
+ACMPCMU::ACMPCMU(int16_t codec_id) { codec_id_ = codec_id; }
+
+ACMPCMU::~ACMPCMU() {}
+
+int16_t ACMPCMU::InternalEncode(uint8_t* bitstream,
+                                int16_t* bitstream_len_byte) {
+  *bitstream_len_byte = WebRtcG711_EncodeU(
+      NULL, &in_audio_[in_audio_ix_read_], frame_len_smpl_ * num_channels_,
+      reinterpret_cast<int16_t*>(bitstream));
+
+  // Increment the read index this tell the caller that how far
+  // we have gone forward in reading the audio buffer.
+  in_audio_ix_read_ += frame_len_smpl_ * num_channels_;
+  return *bitstream_len_byte;
+}
+
+int16_t ACMPCMU::InternalInitEncoder(WebRtcACMCodecParams* /* codec_params */) {
+  // This codec does not need initialization, PCM has no instance.
+  return 0;
+}
+
+ACMGenericCodec* ACMPCMU::CreateInstance(void) { return NULL; }
+
+int16_t ACMPCMU::InternalCreateEncoder() {
+  // PCM has no instance.
+  return 0;
+}
+
+void ACMPCMU::InternalDestructEncoderInst(void* /* ptr_inst */) {
+  // PCM has no instance.
+}
+
+void ACMPCMU::DestructEncoderSafe() {
+  // PCM has no instance.
+  encoder_exist_ = false;
+  encoder_initialized_ = false;
+}
+
+}  // namespace webrtc
diff --git a/webrtc/modules/audio_coding/main/acm2/acm_pcmu.h b/webrtc/modules/audio_coding/main/acm2/acm_pcmu.h
new file mode 100644
index 0000000..832a00d
--- /dev/null
+++ b/webrtc/modules/audio_coding/main/acm2/acm_pcmu.h
@@ -0,0 +1,40 @@
+/*
+ *  Copyright (c) 2012 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_MAIN_SOURCE_ACM_PCMU_H_
+#define WEBRTC_MODULES_AUDIO_CODING_MAIN_SOURCE_ACM_PCMU_H_
+
+#include "webrtc/modules/audio_coding/main/source/acm_generic_codec.h"
+
+namespace webrtc {
+
+class ACMPCMU : public ACMGenericCodec {
+ public:
+  explicit ACMPCMU(int16_t codec_id);
+  ~ACMPCMU();
+
+  // For FEC.
+  ACMGenericCodec* CreateInstance(void);
+
+  int16_t InternalEncode(uint8_t* bitstream, int16_t* bitstream_len_byte);
+
+  int16_t InternalInitEncoder(WebRtcACMCodecParams* codec_params);
+
+ protected:
+  void DestructEncoderSafe();
+
+  int16_t InternalCreateEncoder();
+
+  void InternalDestructEncoderInst(void* ptr_inst);
+};
+
+}  // namespace webrtc
+
+#endif  // WEBRTC_MODULES_AUDIO_CODING_MAIN_SOURCE_ACM_PCMU_H_
diff --git a/webrtc/modules/audio_coding/main/acm2/acm_receiver.cc b/webrtc/modules/audio_coding/main/acm2/acm_receiver.cc
new file mode 100644
index 0000000..fb3fe3e
--- /dev/null
+++ b/webrtc/modules/audio_coding/main/acm2/acm_receiver.cc
@@ -0,0 +1,827 @@
+/*
+ *  Copyright (c) 2013 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 "webrtc/modules/audio_coding/main/source/acm_receiver.h"
+
+#include <stdlib.h>  // malloc
+
+#include <algorithm>  // sort
+#include <vector>
+
+#include "webrtc/common_audio/signal_processing/include/signal_processing_library.h"
+#include "webrtc/common_types.h"
+#include "webrtc/modules/audio_coding/main/source/acm_common_defs.h"
+#include "webrtc/modules/audio_coding/main/source/acm_resampler.h"
+#include "webrtc/modules/audio_coding/main/source/nack.h"
+#include "webrtc/modules/audio_coding/neteq4/interface/audio_decoder.h"
+#include "webrtc/modules/audio_coding/neteq4/interface/neteq.h"
+#include "webrtc/system_wrappers/interface/critical_section_wrapper.h"
+#include "webrtc/system_wrappers/interface/logging.h"
+#include "webrtc/system_wrappers/interface/rw_lock_wrapper.h"
+#include "webrtc/system_wrappers/interface/tick_util.h"
+#include "webrtc/system_wrappers/interface/trace.h"
+
+namespace webrtc {
+
+namespace {
+
+const int kRtpHeaderSize = 12;
+const int kNeteqInitSampleRateHz = 16000;
+const int kNackThresholdPackets = 2;
+
+// |vad_activity_| field of |audio_frame| is set to |previous_audio_activity_|
+// before the call to this function.
+void SetAudioFrameActivityAndType(bool vad_enabled,
+                                  NetEqOutputType type,
+                                  AudioFrame* audio_frame) {
+  if (vad_enabled) {
+    switch (type) {
+      case kOutputNormal: {
+        audio_frame->vad_activity_ = AudioFrame::kVadActive;
+        audio_frame->speech_type_ = AudioFrame::kNormalSpeech;
+        break;
+      }
+      case kOutputVADPassive: {
+        audio_frame->vad_activity_ = AudioFrame::kVadPassive;
+        audio_frame->speech_type_ = AudioFrame::kNormalSpeech;
+        break;
+      }
+      case kOutputCNG: {
+        audio_frame->vad_activity_ = AudioFrame::kVadPassive;
+        audio_frame->speech_type_ = AudioFrame::kCNG;
+        break;
+      }
+      case kOutputPLC: {
+        // Don't change |audio_frame->vad_activity_|, it should be the same as
+        // |previous_audio_activity_|.
+        audio_frame->speech_type_ = AudioFrame::kPLC;
+        break;
+      }
+      case kOutputPLCtoCNG: {
+        audio_frame->vad_activity_ = AudioFrame::kVadPassive;
+        audio_frame->speech_type_ = AudioFrame::kPLCCNG;
+        break;
+      }
+      default:
+        assert(false);
+    }
+  } else {
+    // Always return kVadUnknown when receive VAD is inactive
+    audio_frame->vad_activity_ = AudioFrame::kVadUnknown;
+    switch (type) {
+      case kOutputNormal: {
+        audio_frame->speech_type_ = AudioFrame::kNormalSpeech;
+        break;
+      }
+      case kOutputCNG: {
+        audio_frame->speech_type_ = AudioFrame::kCNG;
+        break;
+      }
+      case kOutputPLC: {
+        audio_frame->speech_type_ = AudioFrame::kPLC;
+        break;
+      }
+      case kOutputPLCtoCNG: {
+        audio_frame->speech_type_ = AudioFrame::kPLCCNG;
+        break;
+      }
+      case kOutputVADPassive: {
+        // Normally, we should no get any VAD decision if post-decoding VAD is
+        // not active. However, if post-decoding VAD has been active then
+        // disabled, we might be here for couple of frames.
+        audio_frame->speech_type_ = AudioFrame::kNormalSpeech;
+        LOG_F(LS_WARNING) << "Post-decoding VAD is disabled but output is "
+            << "labeled VAD-passive";
+        break;
+      }
+      default:
+        assert(false);
+    }
+  }
+}
+
+// Is the given codec a CNG codec?
+bool IsCng(int codec_id) {
+  return (codec_id == ACMCodecDB::kCNNB || codec_id == ACMCodecDB::kCNWB ||
+      codec_id == ACMCodecDB::kCNSWB || codec_id == ACMCodecDB::kCNFB);
+}
+
+}  // namespace
+
+AcmReceiver::AcmReceiver()
+    : id_(0),
+      neteq_(NetEq::Create(kNeteqInitSampleRateHz)),
+      last_audio_decoder_(-1),  // Invalid value.
+      decode_lock_(RWLockWrapper::CreateRWLock()),
+      neteq_crit_sect_(CriticalSectionWrapper::CreateCriticalSection()),
+      vad_enabled_(false),
+      previous_audio_activity_(AudioFrame::kVadUnknown),
+      current_sample_rate_hz_(kNeteqInitSampleRateHz),
+      nack_(),
+      nack_enabled_(false),
+      av_sync_(false),
+      initial_delay_manager_(),
+      missing_packets_sync_stream_(),
+      late_packets_sync_stream_() {
+  for (int n = 0; n < ACMCodecDB::kMaxNumCodecs; ++n) {
+    decoders_[n].registered = false;
+  }
+
+  // Make sure we are on the same page as NetEq, although the default behavior
+  // for NetEq has been VAD disabled.
+  if (vad_enabled_)
+    neteq_->EnableVad();
+  else
+    neteq_->DisableVad();
+}
+
+AcmReceiver::~AcmReceiver() {
+  delete neteq_;
+  delete decode_lock_;
+  delete neteq_crit_sect_;
+}
+
+int AcmReceiver::SetMinimumDelay(int delay_ms) {
+  if (neteq_->SetMinimumDelay(delay_ms))
+    return 0;
+  LOG_FERR1(LS_ERROR, "AcmReceiver::SetExtraDelay", delay_ms);
+  return -1;
+}
+
+int AcmReceiver::SetInitialDelay(int delay_ms) {
+  if (delay_ms < 0 || delay_ms > 10000) {
+    return -1;
+  }
+  CriticalSectionScoped lock(neteq_crit_sect_);
+
+  if (delay_ms == 0) {
+    av_sync_ = false;
+    initial_delay_manager_.reset();
+    missing_packets_sync_stream_.reset();
+    late_packets_sync_stream_.reset();
+    neteq_->SetMinimumDelay(0);
+    return 0;
+  }
+
+  if (av_sync_ && initial_delay_manager_->PacketBuffered()) {
+    // Too late for this API. Only works before a call is started.
+    return -1;
+  }
+
+  // Most of places NetEq calls are not within AcmReceiver's critical section to
+  // improve performance. Here, this call has to be placed before the following
+  // block, therefore, we keep it inside critical section. Otherwise, we have to
+  // release |neteq_crit_sect_| and acquire it again, which seems an overkill.
+  if (neteq_->SetMinimumDelay(delay_ms) < 0)
+    return -1;
+
+  const int kLatePacketThreshold = 5;
+  av_sync_ = true;
+  initial_delay_manager_.reset(new InitialDelayManager(delay_ms,
+                                                       kLatePacketThreshold));
+  missing_packets_sync_stream_.reset(new InitialDelayManager::SyncStream);
+  late_packets_sync_stream_.reset(new InitialDelayManager::SyncStream);
+  return 0;
+}
+
+int AcmReceiver::SetMaximumDelay(int delay_ms) {
+  if (neteq_->SetMaximumDelay(delay_ms))
+    return 0;
+  LOG_FERR1(LS_ERROR, "AcmReceiver::SetExtraDelay", delay_ms);
+  return -1;
+}
+
+int AcmReceiver::LeastRequiredDelayMs() const {
+  return neteq_->LeastRequiredDelayMs();
+}
+
+int AcmReceiver::current_sample_rate_hz() const {
+  CriticalSectionScoped lock(neteq_crit_sect_);
+  return current_sample_rate_hz_;
+}
+
+// TODO(turajs): use one set of enumerators, e.g. the one defined in
+// common_types.h
+void AcmReceiver::SetPlayoutMode(AudioPlayoutMode mode) {
+  enum NetEqPlayoutMode playout_mode = kPlayoutOn;
+  enum NetEqBackgroundNoiseMode bgn_mode = kBgnOn;
+  switch (mode) {
+    case voice:
+      playout_mode = kPlayoutOn;
+      bgn_mode = kBgnOn;
+      break;
+    case fax:  // No change to background noise mode.
+      playout_mode = kPlayoutFax;
+      bgn_mode = neteq_->BackgroundNoiseMode();
+      break;
+    case streaming:
+      playout_mode = kPlayoutStreaming;
+      bgn_mode = kBgnOff;
+      break;
+    case off:
+      playout_mode = kPlayoutOff;
+      bgn_mode = kBgnOff;
+      break;
+  }
+  neteq_->SetPlayoutMode(playout_mode);
+  neteq_->SetBackgroundNoiseMode(bgn_mode);
+}
+
+AudioPlayoutMode AcmReceiver::PlayoutMode() const {
+  AudioPlayoutMode acm_mode = voice;
+  NetEqPlayoutMode mode = neteq_->PlayoutMode();
+  switch (mode) {
+    case kPlayoutOn:
+      acm_mode = voice;
+      break;
+    case kPlayoutOff:
+      acm_mode = off;
+      break;
+    case kPlayoutFax:
+      acm_mode = fax;
+      break;
+    case kPlayoutStreaming:
+      acm_mode = streaming;
+      break;
+    default:
+      assert(false);
+  }
+  return acm_mode;
+}
+
+int AcmReceiver::InsertPacket(const WebRtcRTPHeader& rtp_header,
+                              const uint8_t* incoming_payload,
+                              int length_payload) {
+  uint32_t receive_timestamp = 0;
+  InitialDelayManager::PacketType packet_type =
+      InitialDelayManager::kUndefinedPacket;
+  bool new_codec = false;
+  const RTPHeader* header = &rtp_header.header;  // Just a shorthand.
+
+  {
+    CriticalSectionScoped lock(neteq_crit_sect_);
+
+    int codec_id = RtpHeaderToCodecIndex(*header, incoming_payload);
+    if (codec_id < 0) {
+      LOG_F(LS_ERROR) << "Payload-type " << header->payloadType
+          << " is not registered.";
+      return -1;
+    }
+    assert(codec_id < ACMCodecDB::kMaxNumCodecs);
+    const int sample_rate_hz = ACMCodecDB::CodecFreq(codec_id);
+    receive_timestamp = NowInTimestamp(sample_rate_hz);
+
+    if (IsCng(codec_id)) {
+      // If this is a CNG while the audio codec is not mono skip pushing in
+      // packets into NetEq.
+      if (last_audio_decoder_ >= 0 &&
+        decoders_[last_audio_decoder_].channels > 1)
+        return 0;
+      packet_type = InitialDelayManager::kCngPacket;
+    } else if (codec_id == ACMCodecDB::kAVT) {
+      packet_type = InitialDelayManager::kAvtPacket;
+    } else {
+      if (codec_id != last_audio_decoder_) {
+        // This is either the first audio packet or send codec is changed.
+        // Therefore, either NetEq buffer is empty or will be flushed when this
+        // packet inserted. Note that |last_audio_decoder_| is initialized to
+        // an invalid value (-1), hence, the above condition is true for the
+        // very first audio packet.
+        new_codec = true;
+
+        // Updating NACK'sampling rate is required, either first packet is
+        // received or codec is changed. Furthermore, reset is required if codec
+        // is changed (NetEq flushes its buffer so NACK should reset its list).
+        if (nack_enabled_) {
+          assert(nack_.get());
+          nack_->Reset();
+          nack_->UpdateSampleRate(sample_rate_hz);
+        }
+        last_audio_decoder_ = codec_id;
+      }
+      packet_type = InitialDelayManager::kAudioPacket;
+    }
+
+    if (nack_enabled_) {
+      assert(nack_.get());
+      nack_->UpdateLastReceivedPacket(header->sequenceNumber,
+                                      header->timestamp);
+    }
+
+    if (av_sync_) {
+      assert(initial_delay_manager_.get());
+      assert(missing_packets_sync_stream_.get());
+      // This updates |initial_delay_manager_| and specifies an stream of
+      // sync-packets, if required to be inserted. We insert the sync-packets
+      // when AcmReceiver lock is released and |decoder_lock_| is acquired.
+      initial_delay_manager_->UpdateLastReceivedPacket(
+          rtp_header, receive_timestamp, packet_type, new_codec, sample_rate_hz,
+          missing_packets_sync_stream_.get());
+    }
+  }
+
+  {
+    WriteLockScoped lock_codecs(*decode_lock_);  // Lock to prevent an encoding.
+
+    // If |missing_packets_sync_stream_| is allocated then we are in AV-sync and
+    // we may need to insert sync-packets. We don't check |av_sync_| as we are
+    // outside AcmReceiver's critical section.
+    if (missing_packets_sync_stream_.get()) {
+      InsertStreamOfSyncPackets(missing_packets_sync_stream_.get());
+    }
+
+    if (neteq_->InsertPacket(rtp_header, incoming_payload, length_payload,
+                             receive_timestamp) < 0) {
+      LOG_FERR1(LS_ERROR, "AcmReceiver::InsertPacket", header->payloadType) <<
+          " Failed to insert packet";
+      return -1;
+    }
+  }
+  return 0;
+}
+
+int AcmReceiver::GetAudio(int desired_freq_hz, AudioFrame* audio_frame) {
+  enum NetEqOutputType type;
+  int16_t* ptr_audio_buffer = audio_frame->data_;
+  int samples_per_channel;
+  int num_channels;
+  bool return_silence = false;
+
+  {
+    // Accessing members, take the lock.
+    CriticalSectionScoped lock(neteq_crit_sect_);
+
+    if (av_sync_) {
+      assert(initial_delay_manager_.get());
+      assert(late_packets_sync_stream_.get());
+      return_silence = GetSilence(desired_freq_hz, audio_frame);
+      uint32_t timestamp_now = NowInTimestamp(current_sample_rate_hz_);
+      initial_delay_manager_->LatePackets(timestamp_now,
+                                          late_packets_sync_stream_.get());
+    }
+
+    if (!return_silence) {
+      // This is our initial guess regarding whether a resampling will be
+      // required. It is based on previous sample rate of netEq. Most often,
+      // this is a correct guess, however, in case that incoming payload changes
+      // the resampling might might be needed. By doing so, we avoid an
+      // unnecessary memcpy().
+      if (desired_freq_hz != -1 &&
+          current_sample_rate_hz_ != desired_freq_hz) {
+        ptr_audio_buffer = audio_buffer_;
+      }
+    }
+  }
+
+  {
+    WriteLockScoped lock_codecs(*decode_lock_);  // Lock to prevent an encoding.
+
+    // If |late_packets_sync_stream_| is allocated then we have been in AV-sync
+    // mode and we might have to insert sync-packets.
+    if (late_packets_sync_stream_.get()) {
+      InsertStreamOfSyncPackets(late_packets_sync_stream_.get());
+      if (return_silence)  // Silence generated, don't pull from NetEq.
+        return 0;
+    }
+
+    if (neteq_->GetAudio(AudioFrame::kMaxDataSizeSamples,
+                         ptr_audio_buffer,
+                         &samples_per_channel,
+                         &num_channels, &type) != NetEq::kOK) {
+      LOG_FERR0(LS_ERROR, "AcmReceiver::GetAudio") << "NetEq Failed.";
+      return -1;
+    }
+  }
+
+  // Accessing members, take the lock.
+  CriticalSectionScoped lock(neteq_crit_sect_);
+
+  // Update NACK.
+  int decoded_sequence_num = 0;
+  uint32_t decoded_timestamp = 0;
+  bool update_nack = nack_enabled_ &&  // Update NACK only if it is enabled.
+      neteq_->DecodedRtpInfo(&decoded_sequence_num, &decoded_timestamp);
+  if (update_nack) {
+    assert(nack_.get());
+    nack_->UpdateLastDecodedPacket(decoded_sequence_num, decoded_timestamp);
+  }
+
+  // NetEq always returns 10 ms of audio.
+  current_sample_rate_hz_ = samples_per_channel * 100;
+
+  // Update if resampling is required.
+  bool need_resampling = (desired_freq_hz != -1) &&
+      (current_sample_rate_hz_ != desired_freq_hz);
+
+  if (ptr_audio_buffer == audio_buffer_) {
+    // Data is written to local buffer.
+    if (need_resampling) {
+      samples_per_channel = resampler_.Resample10Msec(
+          audio_buffer_, current_sample_rate_hz_, desired_freq_hz,
+          num_channels, audio_frame->data_);
+      if (samples_per_channel < 0) {
+        LOG_FERR0(LS_ERROR, "AcmReceiver::GetAudio") << "Resampler Failed.";
+        return -1;
+      }
+    } else {
+      // We might end up here ONLY if codec is changed.
+      memcpy(audio_frame->data_, audio_buffer_, samples_per_channel *
+             num_channels * sizeof(int16_t));
+    }
+  } else {
+    // Data is written into |audio_frame|.
+    if (need_resampling) {
+      // We might end up here ONLY if codec is changed.
+      samples_per_channel = resampler_.Resample10Msec(
+          audio_frame->data_, current_sample_rate_hz_, desired_freq_hz,
+          num_channels, audio_buffer_);
+      if (samples_per_channel < 0) {
+        LOG_FERR0(LS_ERROR, "AcmReceiver::GetAudio") << "Resampler Failed.";
+        return -1;
+      }
+      memcpy(audio_frame->data_, audio_buffer_, samples_per_channel *
+             num_channels * sizeof(int16_t));
+    }
+  }
+
+  audio_frame->num_channels_ = num_channels;
+  audio_frame->samples_per_channel_ = samples_per_channel;
+  audio_frame->sample_rate_hz_ = samples_per_channel * 100;
+
+  // Should set |vad_activity| before calling SetAudioFrameActivityAndType().
+  audio_frame->vad_activity_ = previous_audio_activity_;
+  SetAudioFrameActivityAndType(vad_enabled_, type, audio_frame);
+  previous_audio_activity_ = audio_frame->vad_activity_;
+  return 0;
+}
+
+int32_t AcmReceiver::AddCodec(int acm_codec_id,
+                              uint8_t payload_type,
+                              int channels,
+                              AudioDecoder* audio_decoder) {
+  assert(acm_codec_id >= 0 && acm_codec_id < ACMCodecDB::kMaxNumCodecs);
+  NetEqDecoder neteq_decoder = ACMCodecDB::neteq_decoders_[acm_codec_id];
+
+  CriticalSectionScoped lock(neteq_crit_sect_);
+
+  // The corresponding NetEq decoder ID.
+  // If this coder has been registered before.
+  if (decoders_[acm_codec_id].registered) {
+    if (decoders_[acm_codec_id].payload_type == payload_type) {
+      // Re-registering the same codec with the same payload-type. Do nothing
+      // and return.
+      return 0;
+    }
+
+    // Changing the payload-type of this codec. First unregister. Then register
+    // with new payload-type.
+    if (neteq_->RemovePayloadType(decoders_[acm_codec_id].payload_type) !=
+        NetEq::kOK) {
+      LOG_F(LS_ERROR) << "Cannot remover payload "
+          << decoders_[acm_codec_id].payload_type;
+      return -1;
+    }
+  }
+
+  int ret_val;
+  if (!audio_decoder) {
+    ret_val = neteq_->RegisterPayloadType(neteq_decoder, payload_type);
+  } else {
+    ret_val = neteq_->RegisterExternalDecoder(
+        audio_decoder, neteq_decoder,
+        ACMCodecDB::database_[acm_codec_id].plfreq, payload_type);
+  }
+  if (ret_val != NetEq::kOK) {
+    LOG_FERR3(LS_ERROR, "AcmReceiver::AddCodec", acm_codec_id, payload_type,
+              channels);
+    // Registration failed, delete the allocated space and set the pointer to
+    // NULL, for the record.
+    decoders_[acm_codec_id].registered = false;
+    return -1;
+  }
+
+  decoders_[acm_codec_id].registered = true;
+  decoders_[acm_codec_id].payload_type = payload_type;
+  decoders_[acm_codec_id].channels = channels;
+  return 0;
+}
+
+void AcmReceiver::EnableVad() {
+  neteq_->EnableVad();
+  CriticalSectionScoped lock(neteq_crit_sect_);
+  vad_enabled_ = true;
+}
+
+void AcmReceiver::DisableVad() {
+  neteq_->DisableVad();
+  CriticalSectionScoped lock(neteq_crit_sect_);
+  vad_enabled_ = false;
+}
+
+void AcmReceiver::FlushBuffers() {
+  neteq_->FlushBuffers();
+}
+
+// If failed in removing one of the codecs, this method continues to remove as
+// many as it can.
+int AcmReceiver::RemoveAllCodecs() {
+  int ret_val = 0;
+  CriticalSectionScoped lock(neteq_crit_sect_);
+  for (int n = 0; n < ACMCodecDB::kMaxNumCodecs; ++n) {
+    if (decoders_[n].registered) {
+      if (neteq_->RemovePayloadType(decoders_[n].payload_type) == 0) {
+        decoders_[n].registered = false;
+      } else {
+        LOG_F(LS_ERROR) << "Cannot remove payload "
+            << decoders_[n].payload_type;
+        ret_val = -1;
+      }
+    }
+  }
+  return ret_val;
+}
+
+int AcmReceiver::RemoveCodec(uint8_t payload_type) {
+  int codec_index = PayloadType2CodecIndex(payload_type);
+  if (codec_index < 0) {  // Such a payload-type is not registered.
+    LOG(LS_ERROR) << "payload_type " << payload_type << " is not registered"
+        " to be removed.";
+    return -1;
+  }
+  if (neteq_->RemovePayloadType(payload_type) != NetEq::kOK) {
+    LOG_FERR1(LS_ERROR, "AcmReceiver::RemoveCodec", payload_type);
+    return -1;
+  }
+  CriticalSectionScoped lock(neteq_crit_sect_);
+  decoders_[codec_index].registered = false;
+  return 0;
+}
+
+void AcmReceiver::set_id(int id) {
+  CriticalSectionScoped lock(neteq_crit_sect_);
+  id_ = id;
+}
+
+uint32_t AcmReceiver::PlayoutTimestamp() {
+  if (av_sync_) {
+    assert(initial_delay_manager_.get());
+    if (initial_delay_manager_->buffering())
+      return initial_delay_manager_->playout_timestamp();
+  }
+  return neteq_->PlayoutTimestamp();
+}
+
+int AcmReceiver::last_audio_codec_id() const {
+  CriticalSectionScoped lock(neteq_crit_sect_);
+  return last_audio_decoder_;
+}
+
+int AcmReceiver::last_audio_payload_type() const {
+  CriticalSectionScoped lock(neteq_crit_sect_);
+  if (last_audio_decoder_ < 0)
+    return -1;
+  assert(decoders_[last_audio_decoder_].registered);
+  return decoders_[last_audio_decoder_].payload_type;
+}
+
+int AcmReceiver::RedPayloadType() const {
+  CriticalSectionScoped lock(neteq_crit_sect_);
+  if (!decoders_[ACMCodecDB::kRED].registered) {
+    LOG_F(LS_WARNING) << "RED is not registered.";
+    return -1;
+  }
+  return decoders_[ACMCodecDB::kRED].payload_type;
+}
+
+int AcmReceiver::LastAudioCodec(CodecInst* codec) const {
+  CriticalSectionScoped lock(neteq_crit_sect_);
+  if (last_audio_decoder_ < 0) {
+    LOG_F(LS_WARNING) << "No audio payload is received, yet.";
+    return -1;
+  }
+  assert(decoders_[last_audio_decoder_].registered);
+  memcpy(codec, &ACMCodecDB::database_[last_audio_decoder_], sizeof(CodecInst));
+  codec->pltype = decoders_[last_audio_decoder_].payload_type;
+  codec->channels = decoders_[last_audio_decoder_].channels;
+  return 0;
+}
+
+void AcmReceiver::NetworkStatistics(ACMNetworkStatistics* acm_stat) {
+  NetEqNetworkStatistics neteq_stat;
+  // NetEq function always returns zero, so we don't check the return value.
+  neteq_->NetworkStatistics(&neteq_stat);
+
+  acm_stat->currentBufferSize = neteq_stat.current_buffer_size_ms;
+  acm_stat->preferredBufferSize = neteq_stat.preferred_buffer_size_ms;
+  acm_stat->jitterPeaksFound = neteq_stat.jitter_peaks_found;
+  acm_stat->currentPacketLossRate = neteq_stat.packet_loss_rate;
+  acm_stat->currentDiscardRate = neteq_stat.packet_discard_rate;
+  acm_stat->currentExpandRate = neteq_stat.expand_rate;
+  acm_stat->currentPreemptiveRate = neteq_stat.preemptive_rate;
+  acm_stat->currentAccelerateRate = neteq_stat.accelerate_rate;
+  acm_stat->clockDriftPPM = neteq_stat.clockdrift_ppm;
+
+  std::vector<int> waiting_times;
+  neteq_->WaitingTimes(&waiting_times);
+  size_t size = waiting_times.size();
+  if (size == 0) {
+    acm_stat->meanWaitingTimeMs = -1;
+    acm_stat->medianWaitingTimeMs = -1;
+    acm_stat->minWaitingTimeMs = -1;
+    acm_stat->maxWaitingTimeMs = -1;
+  } else {
+    std::sort(waiting_times.begin(), waiting_times.end());
+    if ((size & 0x1) == 0) {
+      acm_stat->medianWaitingTimeMs = (waiting_times[size / 2 - 1] +
+          waiting_times[size / 2]) / 2;
+    } else {
+      acm_stat->medianWaitingTimeMs = waiting_times[size / 2];
+    }
+    acm_stat->minWaitingTimeMs = waiting_times.front();
+    acm_stat->maxWaitingTimeMs = waiting_times.back();
+    double sum = 0;
+    for (size_t i = 0; i < size; ++i) {
+      sum += waiting_times[i];
+    }
+    acm_stat->meanWaitingTimeMs = static_cast<int>(sum / size);
+  }
+}
+
+int AcmReceiver::DecoderByPayloadType(uint8_t payload_type,
+                                      CodecInst* codec) const {
+  CriticalSectionScoped lock(neteq_crit_sect_);
+  int codec_index = PayloadType2CodecIndex(payload_type);
+  if (codec_index < 0) {
+    LOG_FERR1(LS_ERROR, "AcmReceiver::DecoderByPayloadType", payload_type);
+    return -1;
+  }
+  memcpy(codec, &ACMCodecDB::database_[codec_index], sizeof(CodecInst));
+  codec->pltype = decoders_[codec_index].payload_type;
+  codec->channels = decoders_[codec_index].channels;
+  return 0;
+}
+
+int AcmReceiver::PayloadType2CodecIndex(uint8_t payload_type) const {
+  for (int n = 0; n < ACMCodecDB::kMaxNumCodecs; ++n) {
+    if (decoders_[n].registered && decoders_[n].payload_type == payload_type) {
+      return n;
+    }
+  }
+  return -1;
+}
+
+int AcmReceiver::EnableNack(size_t max_nack_list_size) {
+  // Don't do anything if |max_nack_list_size| is out of range.
+  if (max_nack_list_size == 0 || max_nack_list_size > Nack::kNackListSizeLimit)
+    return -1;
+
+  CriticalSectionScoped lock(neteq_crit_sect_);
+  if (!nack_enabled_) {
+    nack_.reset(Nack::Create(kNackThresholdPackets));
+    nack_enabled_ = true;
+
+    // Sampling rate might need to be updated if we change from disable to
+    // enable. Do it if the receive codec is valid.
+    if (last_audio_decoder_ >= 0) {
+      nack_->UpdateSampleRate(
+          ACMCodecDB::database_[last_audio_decoder_].plfreq);
+    }
+  }
+  return nack_->SetMaxNackListSize(max_nack_list_size);
+}
+
+void AcmReceiver::DisableNack() {
+  CriticalSectionScoped lock(neteq_crit_sect_);
+  nack_.reset();  // Memory is released.
+  nack_enabled_ = false;
+}
+
+std::vector<uint16_t> AcmReceiver::GetNackList(
+    int round_trip_time_ms) const {
+  CriticalSectionScoped lock(neteq_crit_sect_);
+  if (round_trip_time_ms < 0) {
+    WEBRTC_TRACE(webrtc::kTraceWarning, webrtc::kTraceAudioCoding, id_,
+                 "GetNackList: round trip time cannot be negative."
+                 " round_trip_time_ms=%d", round_trip_time_ms);
+  }
+  if (nack_enabled_ && round_trip_time_ms >= 0) {
+    assert(nack_.get());
+    return nack_->GetNackList(round_trip_time_ms);
+  }
+  std::vector<uint16_t> empty_list;
+  return empty_list;
+}
+
+void AcmReceiver::ResetInitialDelay() {
+  {
+    CriticalSectionScoped lock(neteq_crit_sect_);
+    av_sync_ = false;
+    initial_delay_manager_.reset(NULL);
+    missing_packets_sync_stream_.reset(NULL);
+    late_packets_sync_stream_.reset(NULL);
+  }
+  neteq_->SetMinimumDelay(0);
+  // TODO(turajs): Should NetEq Buffer be flushed?
+}
+
+// This function is called within critical section, no need to acquire a lock.
+bool AcmReceiver::GetSilence(int desired_sample_rate_hz, AudioFrame* frame) {
+  assert(av_sync_);
+  assert(initial_delay_manager_.get());
+  if (!initial_delay_manager_->buffering()) {
+    return false;
+  }
+
+  // We stop accumulating packets, if the number of packets or the total size
+  // exceeds a threshold.
+  int num_packets;
+  int max_num_packets;
+  int buffer_size_byte;
+  int max_buffer_size_byte;
+  const float kBufferingThresholdScale = 0.9;
+  neteq_->PacketBufferStatistics(&num_packets, &max_num_packets,
+                                 &buffer_size_byte, &max_buffer_size_byte);
+  if (num_packets > max_num_packets * kBufferingThresholdScale ||
+      buffer_size_byte > max_buffer_size_byte * kBufferingThresholdScale) {
+    initial_delay_manager_->DisableBuffering();
+    return false;
+  }
+
+  // Set the values if already got a packet, otherwise set to default values.
+  if (last_audio_decoder_ >= 0) {
+    current_sample_rate_hz_ = ACMCodecDB::database_[last_audio_decoder_].plfreq;
+    frame->num_channels_ = decoders_[last_audio_decoder_].channels;
+  } else {
+    current_sample_rate_hz_ = kNeteqInitSampleRateHz;
+    frame->num_channels_ = 1;
+  }
+
+  // Set the audio frame's sampling frequency.
+  if (desired_sample_rate_hz > 0) {
+    frame->sample_rate_hz_ = desired_sample_rate_hz;
+  } else {
+    frame->sample_rate_hz_ = current_sample_rate_hz_;
+  }
+
+  frame->samples_per_channel_ = frame->sample_rate_hz_ / 100;  // Always 10 ms.
+  frame->speech_type_ = AudioFrame::kCNG;
+  frame->vad_activity_ = AudioFrame::kVadPassive;
+  frame->energy_ = 0;
+  int samples = frame->samples_per_channel_ * frame->num_channels_;
+  memset(frame->data_, 0, samples * sizeof(int16_t));
+  return true;
+}
+
+NetEqBackgroundNoiseMode AcmReceiver::BackgroundNoiseModeForTest() const {
+  return neteq_->BackgroundNoiseMode();
+}
+
+int AcmReceiver::RtpHeaderToCodecIndex(
+    const RTPHeader &rtp_header, const uint8_t* payload) const {
+  uint8_t payload_type = rtp_header.payloadType;
+  if (decoders_[ACMCodecDB::kRED].registered &&
+      payload_type == decoders_[ACMCodecDB::kRED].payload_type) {
+    // This is a RED packet, get the payload of the audio codec.
+    payload_type = payload[0] & 0x7F;
+  }
+
+  // Check if the payload is registered.
+  return PayloadType2CodecIndex(payload_type);
+}
+
+uint32_t AcmReceiver::NowInTimestamp(int decoder_sampling_rate) const {
+  // Down-cast the time to (32-6)-bit since we only care about
+  // the least significant bits. (32-6) bits cover 2^(32-6) = 67108864 ms.
+  // We masked 6 most significant bits of 32-bit so there is no overflow in
+  // the conversion from milliseconds to timestamp.
+  const uint32_t now_in_ms = static_cast<uint32_t>(
+      TickTime::MillisecondTimestamp() & 0x03ffffff);
+  return static_cast<uint32_t>(
+      (decoder_sampling_rate / 1000) * now_in_ms);
+}
+
+// This function only interacts with |neteq_|, therefore, it does not have to
+// be within critical section of AcmReceiver. It is inserting packets
+// into NetEq, so we call it when |decode_lock_| is acquired. However, this is
+// not essential as sync-packets do not interact with codecs (especially BWE).
+void AcmReceiver::InsertStreamOfSyncPackets(
+    InitialDelayManager::SyncStream* sync_stream) {
+  assert(sync_stream);
+  assert(av_sync_);
+  for (int n = 0; n < sync_stream->num_sync_packets; ++n) {
+    neteq_->InsertSyncPacket(sync_stream->rtp_info,
+                             sync_stream->receive_timestamp);
+    ++sync_stream->rtp_info.header.sequenceNumber;
+    sync_stream->rtp_info.header.timestamp += sync_stream->timestamp_step;
+    sync_stream->receive_timestamp += sync_stream->timestamp_step;
+  }
+}
+
+}  // namespace webrtc
diff --git a/webrtc/modules/audio_coding/main/acm2/acm_receiver.h b/webrtc/modules/audio_coding/main/acm2/acm_receiver.h
new file mode 100644
index 0000000..344e1c9
--- /dev/null
+++ b/webrtc/modules/audio_coding/main/acm2/acm_receiver.h
@@ -0,0 +1,365 @@
+/*
+ *  Copyright (c) 2013 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_MAIN_SOURCE_ACM_RECEIVER_H_
+#define WEBRTC_MODULES_AUDIO_CODING_MAIN_SOURCE_ACM_RECEIVER_H_
+
+#include <vector>
+
+#include "webrtc/common_audio/vad/include/webrtc_vad.h"
+#include "webrtc/engine_configurations.h"
+#include "webrtc/modules/audio_coding/main/interface/audio_coding_module.h"
+#include "webrtc/modules/audio_coding/main/source/acm_codec_database.h"
+#include "webrtc/modules/audio_coding/main/source/acm_resampler.h"
+#include "webrtc/modules/audio_coding/main/source/initial_delay_manager.h"
+#include "webrtc/modules/audio_coding/neteq4/interface/neteq.h"
+#include "webrtc/modules/interface/module_common_types.h"
+#include "webrtc/system_wrappers/interface/scoped_ptr.h"
+#include "webrtc/typedefs.h"
+
+namespace webrtc {
+
+class CriticalSectionWrapper;
+class RWLockWrapper;
+class NetEq;
+class Nack;
+struct CodecInst;
+
+class AcmReceiver {
+ public:
+  struct Decoder {
+    bool registered;
+    uint8_t payload_type;
+    // This field is meaningful for codecs where both mono and
+    // stereo versions are registered under the same ID.
+    int channels;
+  };
+
+  // Constructor of the class
+  AcmReceiver();
+
+  explicit AcmReceiver(NetEq* neteq);
+
+  // Destructor of the class.
+  ~AcmReceiver();
+
+  //
+  // Inserts a payload with its associated RTP-header into NetEq.
+  //
+  // Input:
+  //   - rtp_header           : RTP header for the incoming payload containing
+  //                            information about payload type, sequence number,
+  //                            timestamp, SSRC and marker bit.
+  //   - incoming_payload     : Incoming audio payload.
+  //   - length_payload       : Length of incoming audio payload in bytes.
+  //
+  // Return value             : 0 if OK.
+  //                           <0 if NetEq returned an error.
+  //
+  int InsertPacket(const WebRtcRTPHeader& rtp_header,
+                   const uint8_t* incoming_payload,
+                   int length_payload);
+
+  //
+  // Asks NetEq for 10 milliseconds of decoded audio.
+  //
+  // Input:
+  //   -desired_freq_hz       : specifies the sampling rate [Hz] of the output
+  //                            audio. If set -1 indicates to resampling is
+  //                            is required and the audio returned at the
+  //                            sampling rate of the decoder.
+  //
+  // Output:
+  //   -audio_frame           : an audio frame were output data and
+  //                            associated parameters are written to.
+  //
+  // Return value             : 0 if OK.
+  //                           -1 if NetEq returned an error.
+  //
+  int GetAudio(int desired_freq_hz, AudioFrame* audio_frame);
+
+  //
+  // Adds a new codec to the NetEq codec database.
+  //
+  // Input:
+  //   - acm_codec_id        : ACM codec ID.
+  //   - payload_type        : payload type.
+  //   - audio_decoder       : pointer to a decoder object. If it is NULL
+  //                           then NetEq will internally create the decoder
+  //                           object. Otherwise, NetEq will store this pointer
+  //                           as the decoder corresponding with the given
+  //                           payload type. NetEq won't acquire the ownership
+  //                           of this pointer. It is up to the client of this
+  //                           class (ACM) to delete it. By providing
+  //                           |audio_decoder| ACM will have control over the
+  //                           decoder instance of the codec. This is essential
+  //                           for a codec like iSAC which encoder/decoder
+  //                           encoder has to know about decoder (bandwidth
+  //                           estimator that is updated at decoding time).
+  //
+  // Return value             : 0 if OK.
+  //                           <0 if NetEq returned an error.
+  //
+  int AddCodec(int acm_codec_id,
+               uint8_t payload_type,
+               int channels,
+               AudioDecoder* audio_decoder);
+
+  //
+  // Sets a minimum delay for packet buffer. The given delay is maintained,
+  // unless channel condition dictates a higher delay.
+  //
+  // Input:
+  //   - delay_ms             : minimum delay in milliseconds.
+  //
+  // Return value             : 0 if OK.
+  //                           <0 if NetEq returned an error.
+  //
+  int SetMinimumDelay(int delay_ms);
+
+  //
+  // Sets a maximum delay [ms] for the packet buffer. The target delay does not
+  // exceed the given value, even if channel condition requires so.
+  //
+  // Input:
+  //   - delay_ms             : maximum delay in milliseconds.
+  //
+  // Return value             : 0 if OK.
+  //                           <0 if NetEq returned an error.
+  //
+  int SetMaximumDelay(int delay_ms);
+
+  //
+  // Get least required delay computed based on channel conditions. Note that
+  // this is before applying any user-defined limits (specified by calling
+  // (SetMinimumDelay() and/or SetMaximumDelay()).
+  //
+  int LeastRequiredDelayMs() const;
+
+  //
+  // Sets an initial delay of |delay_ms| milliseconds. This introduces a playout
+  // delay. Silence (zero signal) is played out until equivalent of |delay_ms|
+  // millisecond of audio is buffered. Then, NetEq maintains the delay.
+  //
+  // Input:
+  //   - delay_ms             : initial delay in milliseconds.
+  //
+  // Return value             : 0 if OK.
+  //                           <0 if NetEq returned an error.
+  //
+  int SetInitialDelay(int delay_ms);
+
+  //
+  // Resets the initial delay to zero.
+  //
+  void ResetInitialDelay();
+
+  //
+  // Get the current sampling frequency in Hz.
+  //
+  // Return value             : Sampling frequency in Hz.
+  //
+  int current_sample_rate_hz() const;
+
+  //
+  // Sets the playout mode.
+  //
+  // Input:
+  //   - mode                 : an enumerator specifying the playout mode.
+  //
+  void SetPlayoutMode(AudioPlayoutMode mode);
+
+  //
+  // Get the current playout mode.
+  //
+  // Return value             : The current playout mode.
+  //
+  AudioPlayoutMode PlayoutMode() const;
+
+  //
+  // Get the current network statistics from NetEq.
+  //
+  // Output:
+  //   - statistics           : The current network statistics.
+  //
+  void NetworkStatistics(ACMNetworkStatistics* statistics);
+
+  //
+  // Enable post-decoding VAD.
+  //
+  void EnableVad();
+
+  //
+  // Disable post-decoding VAD.
+  //
+  void DisableVad();
+
+  //
+  // Returns whether post-decoding VAD is enabled (true) or disabled (false).
+  //
+  bool vad_enabled() const { return vad_enabled_; }
+
+  //
+  // Get the decode lock used to protect decoder instances while decoding.
+  //
+  // Return value             : Pointer to the decode lock.
+  //
+  RWLockWrapper* DecodeLock() const { return decode_lock_; }
+
+  //
+  // Flushes the NetEq packet and speech buffers.
+  //
+  void FlushBuffers();
+
+  //
+  // Removes a payload-type from the NetEq codec database.
+  //
+  // Input:
+  //   - payload_type         : the payload-type to be removed.
+  //
+  // Return value             : 0 if OK.
+  //                           -1 if an error occurred.
+  //
+  int RemoveCodec(uint8_t payload_type);
+
+  //
+  // Remove all registered codecs.
+  //
+  int RemoveAllCodecs();
+
+  //
+  // Set ID.
+  //
+  void set_id(int id);  // TODO(turajs): can be inline.
+
+  //
+  // Returns the RTP timestamp of the last sample delivered by GetAudio().
+  //
+  uint32_t PlayoutTimestamp();
+
+  //
+  // Return the index of the codec associated with the last non-CNG/non-DTMF
+  // received payload. If no non-CNG/non-DTMF payload is received -1 is
+  // returned.
+  //
+  int last_audio_codec_id() const;  // TODO(turajs): can be inline.
+
+  //
+  // Return the payload-type of the last non-CNG/non-DTMF RTP packet. If no
+  // non-CNG/non-DTMF packet is received -1 is returned.
+  //
+  int last_audio_payload_type() const;  // TODO(turajs): can be inline.
+
+  //
+  // Get the audio codec associated with the last non-CNG/non-DTMF received
+  // payload. If no non-CNG/non-DTMF packet is received -1 is returned,
+  // otherwise return 0.
+  //
+  int LastAudioCodec(CodecInst* codec) const;
+
+  //
+  // Return payload type of RED if it is registered, otherwise return -1;
+  //
+  int RedPayloadType() const;
+
+  //
+  // Get a decoder given its registered payload-type.
+  //
+  // Input:
+  //    -payload_type         : the payload-type of the codec to be retrieved.
+  //
+  // Output:
+  //    -codec                : codec associated with the given payload-type.
+  //
+  // Return value             : 0 if succeeded.
+  //                           -1 if failed, e.g. given payload-type is not
+  //                              registered.
+  //
+  int DecoderByPayloadType(uint8_t payload_type,
+                           CodecInst* codec) const;
+
+  //
+  // Enable NACK and set the maximum size of the NACK list. If NACK is already
+  // enabled then the maximum NACK list size is modified accordingly.
+  //
+  // Input:
+  //    -max_nack_list_size  : maximum NACK list size
+  //                           should be positive (none zero) and less than or
+  //                           equal to |Nack::kNackListSizeLimit|
+  // Return value
+  //                         : 0 if succeeded.
+  //                          -1 if failed
+  //
+  int EnableNack(size_t max_nack_list_size);
+
+  // Disable NACK.
+  void DisableNack();
+
+  //
+  // Get a list of packets to be retransmitted.
+  //
+  // Input:
+  //    -round_trip_time_ms : estimate of the round-trip-time (in milliseconds).
+  // Return value           : list of packets to be retransmitted.
+  //
+  std::vector<uint16_t> GetNackList(int round_trip_time_ms) const;
+
+  //
+  // Returns the background noise mode. This is only for testing and ACM is not
+  // calling this function. Used in acm_receiver_unittest.cc.
+  //
+  NetEqBackgroundNoiseMode BackgroundNoiseModeForTest() const;
+
+ private:
+  int PayloadType2CodecIndex(uint8_t payload_type) const;
+
+  bool GetSilence(int desired_sample_rate_hz, AudioFrame* frame);
+
+  int GetNumSyncPacketToInsert(uint16_t received_squence_number);
+
+  int RtpHeaderToCodecIndex(
+      const RTPHeader& rtp_header, const uint8_t* payload) const;
+
+  uint32_t NowInTimestamp(int decoder_sampling_rate) const;
+
+  void InsertStreamOfSyncPackets(InitialDelayManager::SyncStream* sync_stream);
+
+  int id_;
+  NetEq* neteq_;
+  Decoder decoders_[ACMCodecDB::kMaxNumCodecs];
+  int last_audio_decoder_;
+  RWLockWrapper* decode_lock_;
+  CriticalSectionWrapper* neteq_crit_sect_;
+  bool vad_enabled_;
+  AudioFrame::VADActivity previous_audio_activity_;
+  int current_sample_rate_hz_;
+  ACMResampler resampler_;
+  // Used in GetAudio, declared as member to avoid allocating every 10ms.
+  int16_t audio_buffer_[AudioFrame::kMaxDataSizeSamples];
+  scoped_ptr<Nack> nack_;
+  bool nack_enabled_;
+
+  // Indicates if a non-zero initial delay is set, and the receiver is in
+  // AV-sync mode.
+  bool av_sync_;
+  scoped_ptr<InitialDelayManager> initial_delay_manager_;
+
+  // The following are defined as members to avoid creating them in every
+  // iteration. |missing_packets_sync_stream_| is *ONLY* used in InsertPacket().
+  // |late_packets_sync_stream_| is only used in GetAudio(). Both of these
+  // member variables are allocated only when we AV-sync is enabled, i.e.
+  // initial delay is set.
+  scoped_ptr<InitialDelayManager::SyncStream> missing_packets_sync_stream_;
+  scoped_ptr<InitialDelayManager::SyncStream> late_packets_sync_stream_;
+};
+
+}  // namespace webrtc
+
+#endif  // WEBRTC_MODULES_AUDIO_CODING_MAIN_SOURCE_ACM_RECEIVER_H_
diff --git a/webrtc/modules/audio_coding/main/acm2/acm_receiver_unittest.cc b/webrtc/modules/audio_coding/main/acm2/acm_receiver_unittest.cc
new file mode 100644
index 0000000..ab652cf
--- /dev/null
+++ b/webrtc/modules/audio_coding/main/acm2/acm_receiver_unittest.cc
@@ -0,0 +1,419 @@
+/*
+ *  Copyright (c) 2013 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 "webrtc/modules/audio_coding/main/source/acm_receiver.h"
+
+#include <algorithm>  // std::min
+
+#include "gtest/gtest.h"
+#include "webrtc/modules/audio_coding/main/interface/audio_coding_module.h"
+#include "webrtc/modules/audio_coding/main/source/acm_codec_database.h"
+#include "webrtc/modules/audio_coding/neteq4/tools/rtp_generator.h"
+#include "webrtc/system_wrappers/interface/scoped_ptr.h"
+#include "webrtc/test/test_suite.h"
+#include "webrtc/test/testsupport/fileutils.h"
+
+namespace webrtc {
+namespace {
+
+bool CodecsEqual(const CodecInst& codec_a, const CodecInst& codec_b) {
+    if (strcmp(codec_a.plname, codec_b.plname) != 0 ||
+        codec_a.plfreq != codec_b.plfreq ||
+        codec_a.pltype != codec_b.pltype ||
+        codec_b.channels != codec_a.channels)
+      return false;
+    return true;
+}
+
+}  // namespace
+
+class AcmReceiverTest : public AudioPacketizationCallback,
+                        public ::testing::Test {
+ protected:
+  AcmReceiverTest()
+      : receiver_(new AcmReceiver),
+        acm_(AudioCodingModule::Create(0)),
+        timestamp_(0),
+        packet_sent_(false),
+        last_packet_send_timestamp_(timestamp_),
+        last_frame_type_(kFrameEmpty) {}
+
+  ~AcmReceiverTest() {}
+
+  void SetUp() {
+    ASSERT_TRUE(receiver_.get() != NULL);
+    ASSERT_TRUE(acm_ != NULL);
+    for (int n = 0; n < ACMCodecDB::kNumCodecs; n++) {
+      ASSERT_EQ(0, ACMCodecDB::Codec(n, &codecs_[n]));
+    }
+
+    acm_->InitializeReceiver();
+    acm_->InitializeSender();
+    acm_->RegisterTransportCallback(this);
+
+    rtp_header_.header.sequenceNumber = 0;
+    rtp_header_.header.timestamp = 0;
+    rtp_header_.header.markerBit = false;
+    rtp_header_.header.ssrc = 0x12345678;  // Arbitrary.
+    rtp_header_.header.numCSRCs = 0;
+    rtp_header_.header.payloadType = 0;
+    rtp_header_.frameType = kAudioFrameSpeech;
+    rtp_header_.type.Audio.isCNG = false;
+  }
+
+  void TearDown() {
+    AudioCodingModule::Destroy(acm_);
+  }
+
+  void InsertOnePacketOfSilence(int codec_id) {
+    CodecInst codec;
+    ACMCodecDB::Codec(codec_id, &codec);
+    if (timestamp_ == 0) {  // This is the first time inserting audio.
+      ASSERT_EQ(0, acm_->RegisterSendCodec(codec));
+    } else {
+      CodecInst current_codec;
+      ASSERT_EQ(0, acm_->SendCodec(&current_codec));
+      if (!CodecsEqual(codec, current_codec))
+        ASSERT_EQ(0, acm_->RegisterSendCodec(codec));
+    }
+    AudioFrame frame;
+    // Frame setup according to the codec.
+    frame.sample_rate_hz_ = codec.plfreq;
+    frame.samples_per_channel_ = codec.plfreq / 100;  // 10 ms.
+    frame.num_channels_ = codec.channels;
+    memset(frame.data_, 0, frame.samples_per_channel_ * frame.num_channels_ *
+           sizeof(int16_t));
+    int num_bytes = 0;
+    packet_sent_ = false;
+    last_packet_send_timestamp_ = timestamp_;
+    while (num_bytes == 0) {
+      frame.timestamp_ = timestamp_;
+      timestamp_ += frame.samples_per_channel_;
+      ASSERT_EQ(0, acm_->Add10MsData(frame));
+      num_bytes = acm_->Process();
+      ASSERT_GE(num_bytes, 0);
+    }
+    ASSERT_TRUE(packet_sent_);  // Sanity check.
+  }
+
+  // Last element of id should be negative.
+  void AddSetOfCodecs(const int* id) {
+    int n = 0;
+    while (id[n] >= 0) {
+      ASSERT_EQ(0, receiver_->AddCodec(id[n], codecs_[id[n]].pltype,
+                                       codecs_[id[n]].channels, NULL));
+      ++n;
+    }
+  }
+
+  virtual int SendData(
+      FrameType frame_type,
+      uint8_t payload_type,
+      uint32_t timestamp,
+      const uint8_t* payload_data,
+      uint16_t payload_len_bytes,
+      const RTPFragmentationHeader* fragmentation) {
+    if (frame_type == kFrameEmpty)
+      return 0;
+
+    rtp_header_.header.payloadType = payload_type;
+    rtp_header_.frameType = frame_type;
+    if (frame_type == kAudioFrameSpeech)
+      rtp_header_.type.Audio.isCNG = false;
+    else
+      rtp_header_.type.Audio.isCNG = true;
+    rtp_header_.header.timestamp = timestamp;
+
+    int ret_val = receiver_->InsertPacket(rtp_header_, payload_data,
+                                          payload_len_bytes);
+    if (ret_val < 0) {
+      assert(false);
+      return -1;
+    }
+    rtp_header_.header.sequenceNumber++;
+    packet_sent_ = true;
+    last_frame_type_ = frame_type;
+    return 0;
+  }
+
+  scoped_ptr<AcmReceiver> receiver_;
+  CodecInst codecs_[ACMCodecDB::kMaxNumCodecs];
+  AudioCodingModule* acm_;
+  WebRtcRTPHeader rtp_header_;
+  uint32_t timestamp_;
+  bool packet_sent_;  // Set when SendData is called reset when inserting audio.
+  uint32_t last_packet_send_timestamp_;
+  FrameType last_frame_type_;
+};
+
+TEST_F(AcmReceiverTest, AddCodecGetCodec) {
+  // Add codec.
+  for (int n = 0; n < ACMCodecDB::kNumCodecs; ++n) {
+    if (n & 0x1)  // Just add codecs with odd index.
+      EXPECT_EQ(0, receiver_->AddCodec(n, codecs_[n].pltype,
+                                       codecs_[n].channels, NULL));
+  }
+  // Get codec and compare.
+  for (int n = 0; n < ACMCodecDB::kNumCodecs; ++n) {
+    CodecInst my_codec;
+    if (n & 0x1) {
+      // Codecs with odd index should match the reference.
+      EXPECT_EQ(0, receiver_->DecoderByPayloadType(codecs_[n].pltype,
+                                                   &my_codec));
+      EXPECT_TRUE(CodecsEqual(codecs_[n], my_codec));
+    } else {
+      // Codecs with even index are not registered.
+      EXPECT_EQ(-1, receiver_->DecoderByPayloadType(codecs_[n].pltype,
+                                                    &my_codec));
+    }
+  }
+}
+
+TEST_F(AcmReceiverTest, AddCodecChangePayloadType) {
+  CodecInst ref_codec;
+  const int codec_id = ACMCodecDB::kPCMA;
+  EXPECT_EQ(0, ACMCodecDB::Codec(codec_id, &ref_codec));
+  const int payload_type = ref_codec.pltype;
+  EXPECT_EQ(0, receiver_->AddCodec(codec_id, ref_codec.pltype,
+                                   ref_codec.channels, NULL));
+  CodecInst test_codec;
+  EXPECT_EQ(0, receiver_->DecoderByPayloadType(payload_type, &test_codec));
+  EXPECT_EQ(true, CodecsEqual(ref_codec, test_codec));
+
+  // Re-register the same codec with different payload.
+  ref_codec.pltype = payload_type + 1;
+  EXPECT_EQ(0, receiver_->AddCodec(codec_id, ref_codec.pltype,
+                                   ref_codec.channels, NULL));
+
+  // Payload type |payload_type| should not exist.
+  EXPECT_EQ(-1, receiver_->DecoderByPayloadType(payload_type, &test_codec));
+
+  // Payload type |payload_type + 1| should exist.
+  EXPECT_EQ(0, receiver_->DecoderByPayloadType(payload_type + 1, &test_codec));
+  EXPECT_TRUE(CodecsEqual(test_codec, ref_codec));
+}
+
+TEST_F(AcmReceiverTest, AddCodecRemoveCodec) {
+  CodecInst codec;
+  const int codec_id = ACMCodecDB::kPCMA;
+  EXPECT_EQ(0, ACMCodecDB::Codec(codec_id, &codec));
+  const int payload_type = codec.pltype;
+  EXPECT_EQ(0, receiver_->AddCodec(codec_id, codec.pltype,
+                                   codec.channels, NULL));
+
+  // Remove non-existing codec, must fail.
+  EXPECT_EQ(-1, receiver_->RemoveCodec(payload_type + 1));
+
+  // Remove an existing codec.
+  EXPECT_EQ(0, receiver_->RemoveCodec(payload_type));
+
+  // Ask for the removed codec, must fail.
+  EXPECT_EQ(-1, receiver_->DecoderByPayloadType(payload_type, &codec));
+}
+
+TEST_F(AcmReceiverTest, SampleRate) {
+  const int kCodecId[] = {
+      ACMCodecDB::kISAC, ACMCodecDB::kISACSWB, ACMCodecDB::kISACFB,
+      -1  // Terminator.
+  };
+  AddSetOfCodecs(kCodecId);
+
+  AudioFrame frame;
+  const int kOutSampleRateHz = 8000;  // Different than codec sample rate.
+  int n = 0;
+  while (kCodecId[n] >= 0) {
+    const int num_10ms_frames = codecs_[kCodecId[n]].pacsize /
+        (codecs_[kCodecId[n]].plfreq / 100);
+    InsertOnePacketOfSilence(kCodecId[n]);
+    for (int k = 0; k < num_10ms_frames; ++k) {
+      EXPECT_EQ(0, receiver_->GetAudio(kOutSampleRateHz, &frame));
+    }
+    EXPECT_EQ(std::min(32000, codecs_[kCodecId[n]].plfreq),
+              receiver_->current_sample_rate_hz());
+    ++n;
+  }
+}
+
+// Changing playout mode to FAX should not change the background noise mode.
+TEST_F(AcmReceiverTest, PlayoutModeAndBackgroundNoiseMode) {
+  EXPECT_EQ(kBgnOn, receiver_->BackgroundNoiseModeForTest());  // Default
+
+  receiver_->SetPlayoutMode(voice);
+  EXPECT_EQ(voice, receiver_->PlayoutMode());
+  EXPECT_EQ(kBgnOn, receiver_->BackgroundNoiseModeForTest());
+
+  receiver_->SetPlayoutMode(streaming);
+  EXPECT_EQ(streaming, receiver_->PlayoutMode());
+  EXPECT_EQ(kBgnOff, receiver_->BackgroundNoiseModeForTest());
+
+  receiver_->SetPlayoutMode(fax);
+  EXPECT_EQ(fax, receiver_->PlayoutMode());
+  EXPECT_EQ(kBgnOff, receiver_->BackgroundNoiseModeForTest());
+
+  receiver_->SetPlayoutMode(off);
+  EXPECT_EQ(off, receiver_->PlayoutMode());
+  EXPECT_EQ(kBgnOff, receiver_->BackgroundNoiseModeForTest());
+
+  // Change to voice then to FAX.
+  receiver_->SetPlayoutMode(voice);
+  EXPECT_EQ(voice, receiver_->PlayoutMode());
+  EXPECT_EQ(kBgnOn, receiver_->BackgroundNoiseModeForTest());
+  receiver_->SetPlayoutMode(fax);
+  EXPECT_EQ(fax, receiver_->PlayoutMode());
+  EXPECT_EQ(kBgnOn, receiver_->BackgroundNoiseModeForTest());
+}
+
+TEST_F(AcmReceiverTest, PostdecodingVad) {
+  receiver_->EnableVad();
+  EXPECT_TRUE(receiver_->vad_enabled());
+
+  const int id = ACMCodecDB::kPCM16Bwb;
+  ASSERT_EQ(0, receiver_->AddCodec(id, codecs_[id].pltype, codecs_[id].channels,
+                                   NULL));
+  const int kNumPackets = 5;
+  const int num_10ms_frames = codecs_[id].pacsize / (codecs_[id].plfreq / 100);
+  AudioFrame frame;
+  for (int n = 0; n < kNumPackets; ++n) {
+    InsertOnePacketOfSilence(id);
+    for (int k = 0; k < num_10ms_frames; ++k)
+      ASSERT_EQ(0, receiver_->GetAudio(codecs_[id].plfreq, &frame));
+  }
+  EXPECT_EQ(AudioFrame::kVadPassive, frame.vad_activity_);
+
+  receiver_->DisableVad();
+  EXPECT_FALSE(receiver_->vad_enabled());
+
+  for (int n = 0; n < kNumPackets; ++n) {
+    InsertOnePacketOfSilence(id);
+    for (int k = 0; k < num_10ms_frames; ++k)
+      ASSERT_EQ(0, receiver_->GetAudio(codecs_[id].plfreq, &frame));
+  }
+  EXPECT_EQ(AudioFrame::kVadUnknown, frame.vad_activity_);
+}
+
+TEST_F(AcmReceiverTest, FlushBuffer) {
+  const int id = ACMCodecDB::kISAC;
+  EXPECT_EQ(0, receiver_->AddCodec(id, codecs_[id].pltype, codecs_[id].channels,
+                                   NULL));
+  const int kNumPackets = 5;
+  const int num_10ms_frames = codecs_[id].pacsize / (codecs_[id].plfreq / 100);
+  for (int n = 0; n < kNumPackets; ++n)
+     InsertOnePacketOfSilence(id);
+  ACMNetworkStatistics statistics;
+  receiver_->NetworkStatistics(&statistics);
+  ASSERT_EQ(num_10ms_frames * kNumPackets * 10, statistics.currentBufferSize);
+
+  receiver_->FlushBuffers();
+  receiver_->NetworkStatistics(&statistics);
+  ASSERT_EQ(0, statistics.currentBufferSize);
+}
+
+TEST_F(AcmReceiverTest, PlayoutTimestamp) {
+  const int id = ACMCodecDB::kPCM16Bwb;
+  EXPECT_EQ(0, receiver_->AddCodec(id, codecs_[id].pltype, codecs_[id].channels,
+                                   NULL));
+  receiver_->SetPlayoutMode(fax);
+  const int kNumPackets = 5;
+  const int num_10ms_frames = codecs_[id].pacsize / (codecs_[id].plfreq / 100);
+  uint32_t expected_timestamp;
+  AudioFrame frame;
+  int ts_offset = 0;
+  bool first_audio_frame = true;
+  for (int n = 0; n < kNumPackets; ++n) {
+    packet_sent_ = false;
+    InsertOnePacketOfSilence(id);
+    ASSERT_TRUE(packet_sent_);
+    expected_timestamp = last_packet_send_timestamp_;
+    for (int k = 0; k < num_10ms_frames; ++k) {
+      ASSERT_EQ(0, receiver_->GetAudio(codecs_[id].plfreq, &frame));
+      if (first_audio_frame) {
+        // There is an offset in playout timestamps. Perhaps, it is related to
+        // initial delay that NetEq applies
+        ts_offset =  receiver_->PlayoutTimestamp() - expected_timestamp;
+        first_audio_frame = false;
+      } else {
+        EXPECT_EQ(expected_timestamp + ts_offset,
+                  receiver_->PlayoutTimestamp());
+      }
+      expected_timestamp += codecs_[id].plfreq / 100;  // Increment by 10 ms.
+    }
+  }
+}
+
+TEST_F(AcmReceiverTest, LastAudioCodec) {
+  const int kCodecId[] = {
+      ACMCodecDB::kISAC, ACMCodecDB::kPCMA, ACMCodecDB::kISACSWB,
+      ACMCodecDB::kPCM16Bswb32kHz, ACMCodecDB::kG722_1C_48,
+      -1  // Terminator.
+  };
+  AddSetOfCodecs(kCodecId);
+
+  const int kCngId[] = {  // Not including full-band.
+      ACMCodecDB::kCNNB, ACMCodecDB::kCNWB, ACMCodecDB::kCNSWB,
+      -1  // Terminator.
+  };
+  AddSetOfCodecs(kCngId);
+
+  // Register CNG at sender side.
+  int n = 0;
+  while (kCngId[n] > 0) {
+    ASSERT_EQ(0, acm_->RegisterSendCodec(codecs_[kCngId[n]]));
+    ++n;
+  }
+
+  CodecInst codec;
+  // No audio payload is received.
+  EXPECT_EQ(-1, receiver_->LastAudioCodec(&codec));
+
+  // Start with sending DTX.
+  ASSERT_EQ(0, acm_->SetVAD(true, true, VADVeryAggr));
+  packet_sent_ = false;
+  InsertOnePacketOfSilence(kCodecId[0]);  // Enough to test with one codec.
+  ASSERT_TRUE(packet_sent_);
+  EXPECT_EQ(kAudioFrameCN, last_frame_type_);
+
+  // Has received, only, DTX. Last Audio codec is undefined.
+  EXPECT_EQ(-1, receiver_->LastAudioCodec(&codec));
+  EXPECT_EQ(-1, receiver_->last_audio_codec_id());
+  EXPECT_EQ(-1, receiver_->last_audio_payload_type());
+
+  n = 0;
+  while (kCodecId[n] >= 0) {  // Loop over codecs.
+    // Set DTX off to send audio payload.
+    acm_->SetVAD(false, false, VADAggr);
+    packet_sent_ = false;
+    InsertOnePacketOfSilence(kCodecId[n]);
+
+    // Sanity check if Actually an audio payload received, and it should be
+    // of type "speech."
+    ASSERT_TRUE(packet_sent_);
+    ASSERT_EQ(kAudioFrameSpeech, last_frame_type_);
+    EXPECT_EQ(kCodecId[n], receiver_->last_audio_codec_id());
+
+    // Set VAD on to send DTX. Then check if the "Last Audio codec" returns
+    // the expected codec.
+    acm_->SetVAD(true, true, VADAggr);
+
+    // Do as many encoding until a DTX is sent.
+    while (last_frame_type_ != kAudioFrameCN) {
+      packet_sent_ = false;
+      InsertOnePacketOfSilence(kCodecId[n]);
+      ASSERT_TRUE(packet_sent_);
+    }
+    EXPECT_EQ(kCodecId[n], receiver_->last_audio_codec_id());
+    EXPECT_EQ(codecs_[kCodecId[n]].pltype,
+              receiver_->last_audio_payload_type());
+    EXPECT_EQ(0, receiver_->LastAudioCodec(&codec));
+    EXPECT_TRUE(CodecsEqual(codecs_[kCodecId[n]], codec));
+    ++n;
+  }
+}
+
+}  // namespace webrtc
diff --git a/webrtc/modules/audio_coding/main/acm2/acm_red.cc b/webrtc/modules/audio_coding/main/acm2/acm_red.cc
new file mode 100644
index 0000000..5b5b16f
--- /dev/null
+++ b/webrtc/modules/audio_coding/main/acm2/acm_red.cc
@@ -0,0 +1,50 @@
+/*
+ *  Copyright (c) 2012 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 "webrtc/modules/audio_coding/main/source/acm_red.h"
+
+#include "webrtc/modules/audio_coding/main/source/acm_common_defs.h"
+#include "webrtc/system_wrappers/interface/trace.h"
+
+namespace webrtc {
+
+ACMRED::ACMRED(int16_t codec_id) { codec_id_ = codec_id; }
+
+ACMRED::~ACMRED() {}
+
+int16_t ACMRED::InternalEncode(uint8_t* /* bitstream */,
+                               int16_t* /* bitstream_len_byte */) {
+  // RED is never used as an encoder
+  // RED has no instance
+  return 0;
+}
+
+int16_t ACMRED::InternalInitEncoder(WebRtcACMCodecParams* /* codec_params */) {
+  // This codec does not need initialization,
+  // RED has no instance
+  return 0;
+}
+
+ACMGenericCodec* ACMRED::CreateInstance(void) { return NULL; }
+
+int16_t ACMRED::InternalCreateEncoder() {
+  // RED has no instance
+  return 0;
+}
+
+void ACMRED::InternalDestructEncoderInst(void* /* ptr_inst */) {
+  // RED has no instance
+}
+
+void ACMRED::DestructEncoderSafe() {
+  // RED has no instance
+}
+
+}  // namespace webrtc
diff --git a/webrtc/modules/audio_coding/main/acm2/acm_red.h b/webrtc/modules/audio_coding/main/acm2/acm_red.h
new file mode 100644
index 0000000..c8023db
--- /dev/null
+++ b/webrtc/modules/audio_coding/main/acm2/acm_red.h
@@ -0,0 +1,40 @@
+/*
+ *  Copyright (c) 2012 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_MAIN_SOURCE_ACM_RED_H_
+#define WEBRTC_MODULES_AUDIO_CODING_MAIN_SOURCE_ACM_RED_H_
+
+#include "webrtc/modules/audio_coding/main/source/acm_generic_codec.h"
+
+namespace webrtc {
+
+class ACMRED : public ACMGenericCodec {
+ public:
+  explicit ACMRED(int16_t codec_id);
+  ~ACMRED();
+
+  // For FEC.
+  ACMGenericCodec* CreateInstance(void);
+
+  int16_t InternalEncode(uint8_t* bitstream, int16_t* bitstream_len_byte);
+
+  int16_t InternalInitEncoder(WebRtcACMCodecParams* codec_params);
+
+ protected:
+  void DestructEncoderSafe();
+
+  int16_t InternalCreateEncoder();
+
+  void InternalDestructEncoderInst(void* ptr_inst);
+};
+
+}  // namespace webrtc
+
+#endif  // WEBRTC_MODULES_AUDIO_CODING_MAIN_SOURCE_ACM_RED_H_
diff --git a/webrtc/modules/audio_coding/main/acm2/acm_resampler.cc b/webrtc/modules/audio_coding/main/acm2/acm_resampler.cc
new file mode 100644
index 0000000..d399cee
--- /dev/null
+++ b/webrtc/modules/audio_coding/main/acm2/acm_resampler.cc
@@ -0,0 +1,66 @@
+/*
+ *  Copyright (c) 2012 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 "webrtc/modules/audio_coding/main/source/acm_resampler.h"
+
+#include <string.h>
+
+#include "webrtc/common_audio/resampler/include/resampler.h"
+#include "webrtc/common_audio/signal_processing/include/signal_processing_library.h"
+#include "webrtc/system_wrappers/interface/critical_section_wrapper.h"
+#include "webrtc/system_wrappers/interface/trace.h"
+
+namespace webrtc {
+
+ACMResampler::ACMResampler()
+    : resampler_crit_sect_(CriticalSectionWrapper::CreateCriticalSection()) {
+}
+
+ACMResampler::~ACMResampler() {
+  delete resampler_crit_sect_;
+}
+
+int ACMResampler::Resample10Msec(const int16_t* in_audio,
+                                 int in_freq_hz,
+                                 int out_freq_hz,
+                                 int num_audio_channels,
+                                 int16_t* out_audio) {
+  CriticalSectionScoped cs(resampler_crit_sect_);
+
+  if (in_freq_hz == out_freq_hz) {
+    size_t length = static_cast<size_t>(in_freq_hz * num_audio_channels / 100);
+    memcpy(out_audio, in_audio, length * sizeof(int16_t));
+    return static_cast<int16_t>(in_freq_hz / 100);
+  }
+
+  // |maxLen| is maximum number of samples for 10ms at 48kHz.
+  int max_len = 480 * num_audio_channels;
+  int length_in = (in_freq_hz / 100) * num_audio_channels;
+  int out_len;
+
+  ResamplerType type = (num_audio_channels == 1) ? kResamplerSynchronous :
+      kResamplerSynchronousStereo;
+
+  if (resampler_.ResetIfNeeded(in_freq_hz, out_freq_hz, type) < 0) {
+    WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, 0,
+                 "Error in reset of resampler");
+    return -1;
+  }
+
+  if (resampler_.Push(in_audio, length_in, out_audio, max_len, out_len) < 0) {
+    WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, 0,
+                 "Error in resampler: resampler.Push");
+    return -1;
+  }
+
+  return out_len / num_audio_channels;
+}
+
+}  // namespace webrtc
diff --git a/webrtc/modules/audio_coding/main/acm2/acm_resampler.h b/webrtc/modules/audio_coding/main/acm2/acm_resampler.h
new file mode 100644
index 0000000..c44fbc4
--- /dev/null
+++ b/webrtc/modules/audio_coding/main/acm2/acm_resampler.h
@@ -0,0 +1,40 @@
+/*
+ *  Copyright (c) 2012 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_MAIN_SOURCE_ACM_RESAMPLER_H_
+#define WEBRTC_MODULES_AUDIO_CODING_MAIN_SOURCE_ACM_RESAMPLER_H_
+
+#include "webrtc/common_audio/resampler/include/resampler.h"
+#include "webrtc/typedefs.h"
+
+namespace webrtc {
+
+class CriticalSectionWrapper;
+
+class ACMResampler {
+ public:
+  ACMResampler();
+  ~ACMResampler();
+
+  int Resample10Msec(const int16_t* in_audio,
+                     int in_freq_hz,
+                     int out_freq_hz,
+                     int num_audio_channels,
+                     int16_t* out_audio);
+
+ private:
+  // Use the Resampler class.
+  Resampler resampler_;
+  CriticalSectionWrapper* resampler_crit_sect_;
+};
+
+}  // namespace webrtc
+
+#endif  // WEBRTC_MODULES_AUDIO_CODING_MAIN_SOURCE_ACM_RESAMPLER_H_
diff --git a/webrtc/modules/audio_coding/main/acm2/acm_speex.cc b/webrtc/modules/audio_coding/main/acm2/acm_speex.cc
new file mode 100644
index 0000000..80dcf5c2
--- /dev/null
+++ b/webrtc/modules/audio_coding/main/acm2/acm_speex.cc
@@ -0,0 +1,329 @@
+/*
+ *  Copyright (c) 2012 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 "webrtc/modules/audio_coding/main/source/acm_speex.h"
+
+#ifdef WEBRTC_CODEC_SPEEX
+// NOTE! Speex is not included in the open-source package. Modify this file or
+// your codec API to match the function calls and names of used Speex API file.
+#include "webrtc/modules/audio_coding/main/codecs/speex/interface/speex_interface.h"
+#include "webrtc/modules/audio_coding/main/source/acm_codec_database.h"
+#include "webrtc/modules/audio_coding/main/source/acm_common_defs.h"
+#include "webrtc/system_wrappers/interface/trace.h"
+#endif
+
+namespace webrtc {
+
+#ifndef WEBRTC_CODEC_SPEEX
+ACMSPEEX::ACMSPEEX(int16_t /* codec_id */)
+    : encoder_inst_ptr_(NULL),
+      compl_mode_(0),
+      vbr_enabled_(false),
+      encoding_rate_(-1),
+      sampling_frequency_(-1),
+      samples_in_20ms_audio_(-1) {
+  return;
+}
+
+ACMSPEEX::~ACMSPEEX() { return; }
+
+int16_t ACMSPEEX::InternalEncode(uint8_t* /* bitstream */,
+                                 int16_t* /* bitstream_len_byte */) {
+  return -1;
+}
+
+int16_t ACMSPEEX::EnableDTX() { return -1; }
+
+int16_t ACMSPEEX::DisableDTX() { return -1; }
+
+int16_t ACMSPEEX::InternalInitEncoder(
+    WebRtcACMCodecParams* /* codec_params */) {
+  return -1;
+}
+
+ACMGenericCodec* ACMSPEEX::CreateInstance(void) { return NULL; }
+
+int16_t ACMSPEEX::InternalCreateEncoder() { return -1; }
+
+void ACMSPEEX::DestructEncoderSafe() { return; }
+
+int16_t ACMSPEEX::SetBitRateSafe(const int32_t /* rate */) { return -1; }
+
+void ACMSPEEX::InternalDestructEncoderInst(void* /* ptr_inst */) { return; }
+
+#ifdef UNUSEDSPEEX
+int16_t ACMSPEEX::EnableVBR() { return -1; }
+
+int16_t ACMSPEEX::DisableVBR() { return -1; }
+
+int16_t ACMSPEEX::SetComplMode(int16_t mode) { return -1; }
+#endif
+
+#else  //===================== Actual Implementation =======================
+
+ACMSPEEX::ACMSPEEX(int16_t codec_id) : encoder_inst_ptr_(NULL) {
+  codec_id_ = codec_id;
+
+  // Set sampling frequency, frame size and rate Speex
+  if (codec_id_ == ACMCodecDB::kSPEEX8) {
+    sampling_frequency_ = 8000;
+    samples_in_20ms_audio_ = 160;
+    encoding_rate_ = 11000;
+  } else if (codec_id_ == ACMCodecDB::kSPEEX16) {
+    sampling_frequency_ = 16000;
+    samples_in_20ms_audio_ = 320;
+    encoding_rate_ = 22000;
+  } else {
+    WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, unique_id_,
+                 "Wrong codec id for Speex.");
+
+    sampling_frequency_ = -1;
+    samples_in_20ms_audio_ = -1;
+    encoding_rate_ = -1;
+  }
+
+  has_internal_dtx_ = true;
+  dtx_enabled_ = false;
+  vbr_enabled_ = false;
+  compl_mode_ = 3;  // default complexity value
+
+  return;
+}
+
+ACMSPEEX::~ACMSPEEX() {
+  if (encoder_inst_ptr_ != NULL) {
+    WebRtcSpeex_FreeEnc(encoder_inst_ptr_);
+    encoder_inst_ptr_ = NULL;
+  }
+  return;
+}
+
+int16_t ACMSPEEX::InternalEncode(uint8_t* bitstream,
+                                 int16_t* bitstream_len_byte) {
+  int16_t status;
+  int16_t num_encoded_samples = 0;
+  int16_t n = 0;
+
+  while (num_encoded_samples < frame_len_smpl_) {
+    status = WebRtcSpeex_Encode(
+        encoder_inst_ptr_, &in_audio_[in_audio_ix_read_], encoding_rate_);
+
+    // increment the read index this tell the caller that how far
+    // we have gone forward in reading the audio buffer
+    in_audio_ix_read_ += samples_in_20ms_audio_;
+    num_encoded_samples += samples_in_20ms_audio_;
+
+    if (status < 0) {
+      WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, unique_id_,
+                   "Error in Speex encoder");
+      return status;
+    }
+
+    // Update VAD, if internal DTX is used
+    if (has_internal_dtx_ && dtx_enabled_) {
+      vad_label_[n++] = status;
+      vad_label_[n++] = status;
+    }
+
+    if (status == 0) {
+      // This frame is detected as inactive. We need send whatever
+      // encoded so far.
+      *bitstream_len_byte = WebRtcSpeex_GetBitstream(
+              encoder_inst_ptr_, reinterpret_cast<int16_t*>(bitstream));
+      return *bitstream_len_byte;
+    }
+  }
+
+  *bitstream_len_byte = WebRtcSpeex_GetBitstream(
+      encoder_inst_ptr_, reinterpret_cast<int16_t*>(bitstream));
+  return *bitstream_len_byte;
+}
+
+int16_t ACMSPEEX::EnableDTX() {
+  if (dtx_enabled_) {
+    return 0;
+  } else if (encoder_exist_) {  // check if encoder exist
+    // enable DTX
+    if (WebRtcSpeex_EncoderInit(encoder_inst_ptr_, vbr_enabled_ ? 1 : 0,
+                                compl_mode_, 1) < 0) {
+      WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, unique_id_,
+                   "Cannot enable DTX for Speex");
+      return -1;
+    }
+    dtx_enabled_ = true;
+    return 0;
+  } else {
+    return -1;
+  }
+
+  return 0;
+}
+
+int16_t ACMSPEEX::DisableDTX() {
+  if (!dtx_enabled_) {
+    return 0;
+  } else if (encoder_exist_) {  // check if encoder exist
+    // disable DTX
+    if (WebRtcSpeex_EncoderInit(encoder_inst_ptr_, (vbr_enabled_ ? 1 : 0),
+                                compl_mode_, 0) < 0) {
+      WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, unique_id_,
+                   "Cannot disable DTX for Speex");
+      return -1;
+    }
+    dtx_enabled_ = false;
+    return 0;
+  } else {
+    // encoder doesn't exists, therefore disabling is harmless
+    return 0;
+  }
+
+  return 0;
+}
+
+int16_t ACMSPEEX::InternalInitEncoder(WebRtcACMCodecParams* codec_params) {
+  // sanity check
+  if (encoder_inst_ptr_ == NULL) {
+    WEBRTC_TRACE(webrtc::kTraceError,
+                 webrtc::kTraceAudioCoding,
+                 unique_id_,
+                 "Cannot initialize Speex encoder, instance does not exist");
+    return -1;
+  }
+
+  int16_t status = SetBitRateSafe((codec_params->codecInstant).rate);
+  status += (WebRtcSpeex_EncoderInit(encoder_inst_ptr_,
+                                     vbr_enabled_,
+                                     compl_mode_,
+                                     ((codec_params->enable_dtx) ? 1 : 0)) < 0)
+                ? -1
+                : 0;
+
+  if (status >= 0) {
+    return 0;
+  } else {
+    WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, unique_id_,
+                 "Error in initialization of Speex encoder");
+    return -1;
+  }
+}
+
+ACMGenericCodec* ACMSPEEX::CreateInstance(void) { return NULL; }
+
+int16_t ACMSPEEX::InternalCreateEncoder() {
+  return WebRtcSpeex_CreateEnc(&encoder_inst_ptr_, sampling_frequency_);
+}
+
+void ACMSPEEX::DestructEncoderSafe() {
+  if (encoder_inst_ptr_ != NULL) {
+    WebRtcSpeex_FreeEnc(encoder_inst_ptr_);
+    encoder_inst_ptr_ = NULL;
+  }
+  // there is no encoder set the following
+  encoder_exist_ = false;
+  encoder_initialized_ = false;
+  encoding_rate_ = 0;
+}
+
+int16_t ACMSPEEX::SetBitRateSafe(const int32_t rate) {
+  // Check if changed rate
+  if (rate == encoding_rate_) {
+    return 0;
+  } else if (rate > 2000) {
+    encoding_rate_ = rate;
+    encoder_params_.codecInstant.rate = rate;
+  } else {
+    WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, unique_id_,
+                 "Unsupported encoding rate for Speex");
+
+    return -1;
+  }
+
+  return 0;
+}
+
+void ACMSPEEX::InternalDestructEncoderInst(void* ptr_inst) {
+  if (ptr_inst != NULL) {
+    WebRtcSpeex_FreeEnc(static_cast<SPEEX_encinst_t_*>(ptr_inst));
+  }
+  return;
+}
+
+#ifdef UNUSEDSPEEX
+
+// This API is currently not in use. If requested to be able to enable/disable
+// VBR an ACM API need to be added.
+int16_t ACMSPEEX::EnableVBR() {
+  if (vbr_enabled_) {
+    return 0;
+  } else if (encoder_exist_) {  // check if encoder exist
+    // enable Variable Bit Rate (VBR)
+    if (WebRtcSpeex_EncoderInit(encoder_inst_ptr_, 1, compl_mode_,
+                                (dtx_enabled_ ? 1 : 0)) < 0) {
+      WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, unique_id_,
+                   "Cannot enable VBR mode for Speex");
+
+      return -1;
+    }
+    vbr_enabled_ = true;
+    return 0;
+  } else {
+    return -1;
+  }
+}
+
+// This API is currently not in use. If requested to be able to enable/disable
+// VBR an ACM API need to be added.
+int16_t ACMSPEEX::DisableVBR() {
+  if (!vbr_enabled_) {
+    return 0;
+  } else if (encoder_exist_) {  // check if encoder exist
+    // disable DTX
+    if (WebRtcSpeex_EncoderInit(encoder_inst_ptr_, 0, compl_mode_,
+                                (dtx_enabled_ ? 1 : 0)) < 0) {
+      WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, unique_id_,
+                   "Cannot disable DTX for Speex");
+
+      return -1;
+    }
+    vbr_enabled_ = false;
+    return 0;
+  } else {
+    // encoder doesn't exists, therefore disabling is harmless
+    return 0;
+  }
+}
+
+// This API is currently not in use. If requested to be able to set complexity
+// an ACM API need to be added.
+int16_t ACMSPEEX::SetComplMode(int16_t mode) {
+  // Check if new mode
+  if (mode == compl_mode_) {
+    return 0;
+  } else if (encoder_exist_) {  // check if encoder exist
+    // Set new mode
+    if (WebRtcSpeex_EncoderInit(encoder_inst_ptr_, 0, mode,
+                                (dtx_enabled_ ? 1 : 0)) < 0) {
+      WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, unique_id_,
+                   "Error in complexity mode for Speex");
+      return -1;
+    }
+    compl_mode_ = mode;
+    return 0;
+  } else {
+    // encoder doesn't exists, therefore disabling is harmless
+    return 0;
+  }
+}
+
+#endif
+
+#endif
+
+}  // namespace webrtc
diff --git a/webrtc/modules/audio_coding/main/acm2/acm_speex.h b/webrtc/modules/audio_coding/main/acm2/acm_speex.h
new file mode 100644
index 0000000..68953a8
--- /dev/null
+++ b/webrtc/modules/audio_coding/main/acm2/acm_speex.h
@@ -0,0 +1,65 @@
+/*
+ *  Copyright (c) 2012 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_MAIN_SOURCE_ACM_SPEEX_H_
+#define WEBRTC_MODULES_AUDIO_CODING_MAIN_SOURCE_ACM_SPEEX_H_
+
+#include "webrtc/modules/audio_coding/main/source/acm_generic_codec.h"
+
+// forward declaration
+struct SPEEX_encinst_t_;
+struct SPEEX_decinst_t_;
+
+namespace webrtc {
+
+class ACMSPEEX : public ACMGenericCodec {
+ public:
+  explicit ACMSPEEX(int16_t codec_id);
+  ~ACMSPEEX();
+
+  // For FEC.
+  ACMGenericCodec* CreateInstance(void);
+
+  int16_t InternalEncode(uint8_t* bitstream, int16_t* bitstream_len_byte);
+
+  int16_t InternalInitEncoder(WebRtcACMCodecParams* codec_params);
+
+ protected:
+  void DestructEncoderSafe();
+
+  int16_t InternalCreateEncoder();
+
+  void InternalDestructEncoderInst(void* ptr_inst);
+
+  int16_t SetBitRateSafe(const int32_t rate);
+
+  int16_t EnableDTX();
+
+  int16_t DisableDTX();
+
+#ifdef UNUSEDSPEEX
+  int16_t EnableVBR();
+
+  int16_t DisableVBR();
+
+  int16_t SetComplMode(int16_t mode);
+#endif
+
+  SPEEX_encinst_t_* encoder_inst_ptr_;
+  int16_t compl_mode_;
+  bool vbr_enabled_;
+  int32_t encoding_rate_;
+  int16_t sampling_frequency_;
+  uint16_t samples_in_20ms_audio_;
+};
+
+}  // namespace webrtc
+
+#endif  // WEBRTC_MODULES_AUDIO_CODING_MAIN_SOURCE_ACM_SPEEX_H_
diff --git a/webrtc/modules/audio_coding/main/acm2/audio_coding_module.cc b/webrtc/modules/audio_coding/main/acm2/audio_coding_module.cc
new file mode 100644
index 0000000..97d5d46
--- /dev/null
+++ b/webrtc/modules/audio_coding/main/acm2/audio_coding_module.cc
@@ -0,0 +1,101 @@
+/*
+ *  Copyright (c) 2012 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 "webrtc/modules/audio_coding/main/interface/audio_coding_module.h"
+
+#include "webrtc/common_types.h"
+#include "webrtc/modules/audio_coding/main/source/acm_codec_database.h"
+#include "webrtc/modules/audio_coding/main/source/audio_coding_module_impl.h"
+#include "webrtc/system_wrappers/interface/trace.h"
+
+namespace webrtc {
+
+// Create module
+AudioCodingModule* AudioCodingModule::Create(int id) {
+  return new AudioCodingModuleImpl(id);
+}
+
+// Destroy module
+void AudioCodingModule::Destroy(AudioCodingModule* module) {
+  delete static_cast<AudioCodingModuleImpl*>(module);
+}
+
+// Get number of supported codecs
+int AudioCodingModule::NumberOfCodecs() {
+  return ACMCodecDB::kNumCodecs;
+}
+
+// Get supported codec parameters with id
+int AudioCodingModule::Codec(int list_id, CodecInst* codec) {
+  // Get the codec settings for the codec with the given list ID
+  return ACMCodecDB::Codec(list_id, codec);
+}
+
+// Get supported codec parameters with name, frequency and number of channels.
+int AudioCodingModule::Codec(const char* payload_name,
+                             CodecInst* codec,
+                             int sampling_freq_hz,
+                             int channels) {
+  int codec_id;
+
+  // Get the id of the codec from the database.
+  codec_id = ACMCodecDB::CodecId(payload_name, sampling_freq_hz, channels);
+  if (codec_id < 0) {
+    // We couldn't find a matching codec, set the parameters to unacceptable
+    // values and return.
+    codec->plname[0] = '\0';
+    codec->pltype = -1;
+    codec->pacsize = 0;
+    codec->rate = 0;
+    codec->plfreq = 0;
+    return -1;
+  }
+
+  // Get default codec settings.
+  ACMCodecDB::Codec(codec_id, codec);
+
+  // Keep the number of channels from the function call. For most codecs it
+  // will be the same value as in default codec settings, but not for all.
+  codec->channels = channels;
+
+  return 0;
+}
+
+// Get supported codec Index with name, frequency and number of channels.
+int AudioCodingModule::Codec(const char* payload_name,
+                             int sampling_freq_hz,
+                             int channels) {
+  return ACMCodecDB::CodecId(payload_name, sampling_freq_hz, channels);
+}
+
+// Checks the validity of the parameters of the given codec
+bool AudioCodingModule::IsCodecValid(const CodecInst& codec) {
+  int mirror_id;
+
+  int codec_number = ACMCodecDB::CodecNumber(codec, &mirror_id);
+
+  if (codec_number < 0) {
+    WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, -1,
+                 "Invalid codec setting");
+    return false;
+  } else {
+    return true;
+  }
+}
+
+AudioCodingModule* AudioCodingModuleFactory::Create(const int32_t id) const {
+  return NULL;
+}
+
+AudioCodingModule* NewAudioCodingModuleFactory::Create(const int32_t id) const {
+  return new AudioCodingModuleImpl(id);
+}
+
+}  // namespace webrtc
diff --git a/webrtc/modules/audio_coding/main/acm2/audio_coding_module.gypi b/webrtc/modules/audio_coding/main/acm2/audio_coding_module.gypi
new file mode 100644
index 0000000..8b0fbe1
--- /dev/null
+++ b/webrtc/modules/audio_coding/main/acm2/audio_coding_module.gypi
@@ -0,0 +1,190 @@
+# Copyright (c) 2012 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.
+
+{
+  'variables': {
+    'audio_coding_dependencies': [
+      'CNG',
+      'G711',
+      'G722',
+      'iLBC',
+      'iSAC',
+      'iSACFix',
+      'PCM16B',
+      'NetEq4',
+      '<(webrtc_root)/common_audio/common_audio.gyp:common_audio',
+      '<(webrtc_root)/system_wrappers/source/system_wrappers.gyp:system_wrappers',
+    ],
+    'audio_coding_defines': [],
+    'conditions': [
+      ['include_opus==1', {
+        'audio_coding_dependencies': ['webrtc_opus',],
+        'audio_coding_defines': ['WEBRTC_CODEC_OPUS',],
+      }],
+    ],
+  },
+  'targets': [
+    {
+      'target_name': 'audio_coding_module',
+      'type': 'static_library',
+      'defines': [
+        '<@(audio_coding_defines)',
+      ],
+      'dependencies': [
+        '<@(audio_coding_dependencies)',
+      ],
+      'include_dirs': [
+        '../interface',
+        '../../../interface',
+      ],
+      'direct_dependent_settings': {
+        'include_dirs': [
+          '../interface',
+          '../../../interface',
+        ],
+      },
+      'sources': [
+        '../interface/audio_coding_module.h',
+        '../interface/audio_coding_module_typedefs.h',
+        'acm_amr.cc',
+        'acm_amr.h',
+        'acm_amrwb.cc',
+        'acm_amrwb.h',
+        'acm_celt.cc',
+        'acm_celt.h',
+        'acm_cng.cc',
+        'acm_cng.h',
+        'acm_codec_database.cc',
+        'acm_codec_database.h',
+        'acm_dtmf_playout.cc',
+        'acm_dtmf_playout.h',
+        'acm_g722.cc',
+        'acm_g722.h',
+        'acm_g7221.cc',
+        'acm_g7221.h',
+        'acm_g7221c.cc',
+        'acm_g7221c.h',
+        'acm_g729.cc',
+        'acm_g729.h',
+        'acm_g7291.cc',
+        'acm_g7291.h',
+        'acm_generic_codec.cc',
+        'acm_generic_codec.h',
+        'acm_gsmfr.cc',
+        'acm_gsmfr.h',
+        'acm_ilbc.cc',
+        'acm_ilbc.h',
+        'acm_isac.cc',
+        'acm_isac.h',
+        'acm_isac_macros.h',
+        'acm_opus.cc',
+        'acm_opus.h',
+        'acm_speex.cc',
+        'acm_speex.h',
+        'acm_pcm16b.cc',
+        'acm_pcm16b.h',
+        'acm_pcma.cc',
+        'acm_pcma.h',
+        'acm_pcmu.cc',
+        'acm_pcmu.h',
+        'acm_red.cc',
+        'acm_red.h',
+        'acm_receiver.cc',
+        'acm_receiver.h',
+        'acm_resampler.cc',
+        'acm_resampler.h',
+        'audio_coding_module.cc',
+        'audio_coding_module_impl.cc',
+        'audio_coding_module_impl.h',
+        'initial_delay_manager.cc',
+        'initial_delay_manager.h',
+        'nack.cc',
+        'nack.h',
+      ],
+    },
+  ],
+  'conditions': [
+    ['include_tests==1', {
+      'targets': [
+        {
+          'target_name': 'delay_test',
+          'type': 'executable',
+          'dependencies': [
+            'audio_coding_module',
+            '<(DEPTH)/testing/gtest.gyp:gtest',
+            '<(webrtc_root)/test/test.gyp:test_support_main',
+            '<(webrtc_root)/system_wrappers/source/system_wrappers.gyp:system_wrappers',
+            '<(DEPTH)/third_party/gflags/gflags.gyp:gflags',
+          ],
+          'sources': [
+             '../test/delay_test.cc',
+             '../test/Channel.cc',
+             '../test/PCMFile.cc',
+          ],
+        }, # delay_test  
+        {
+          # This is handy for testing codecs with different settings. I like to
+          # keep it while we are developing ACM 2. Not sure if we keep it
+          # forever, though I don't have strong reason to remove it.
+          'target_name': 'codec_test',
+          'type': 'executable',
+          'dependencies': [
+            'audio_coding_module',
+            '<(DEPTH)/testing/gtest.gyp:gtest',
+            '<(webrtc_root)/test/test.gyp:test_support_main',
+            '<(webrtc_root)/system_wrappers/source/system_wrappers.gyp:system_wrappers',
+            '<(DEPTH)/third_party/gflags/gflags.gyp:gflags',
+          ],
+          'sources': [
+             '../test/codec_test.cc',
+             '../test/Channel.cc',
+             '../test/PCMFile.cc',
+           ],
+        }, # codec_test
+# TODO(turajs): Add this target.        
+#        {
+#          'target_name': 'insert_packet_with_timing',
+#          'type': 'executable',
+#          'dependencies': [
+#            'audio_coding_module',
+#            '<(DEPTH)/testing/gtest.gyp:gtest',
+#            '<(webrtc_root)/test/test.gyp:test_support_main',
+#            '<(webrtc_root)/system_wrappers/source/system_wrappers.gyp:system_wrappers',
+#            '<(DEPTH)/third_party/gflags/gflags.gyp:gflags',
+#          ],
+#          'sources': [
+#             'acm_receiver_unittest.cc',
+#             '../test/Channel.cc',
+#             '../test/PCMFile.cc',
+#           ],
+#        }, # insert_packet_with_timing
+         {
+          # TODO(turajs): This test will be included in module.gyp when ACM 2 is in 
+          # public repository.
+           'target_name': 'acm2_unittests',
+           'type': 'executable',
+           'defines': [
+             '<@(audio_coding_defines)',
+           ],
+           'dependencies': [
+             'audio_coding_module',
+             '<(DEPTH)/testing/gtest.gyp:gtest',
+             '<(webrtc_root)/test/test.gyp:test_support_main',
+             #'<(webrtc_root)/system_wrappers/source/system_wrappers.gyp:system_wrappers',
+             '<(DEPTH)/third_party/gflags/gflags.gyp:gflags',
+           ],
+           'sources': [
+              'nack_unittest.cc',
+              'acm_receiver_unittest.cc',
+              'initial_delay_manager_unittest.cc',
+            ],
+         }, # acm2_unittests
+     ],
+    }],
+  ],
+}
diff --git a/webrtc/modules/audio_coding/main/acm2/audio_coding_module_impl.cc b/webrtc/modules/audio_coding/main/acm2/audio_coding_module_impl.cc
new file mode 100644
index 0000000..f5fac73
--- /dev/null
+++ b/webrtc/modules/audio_coding/main/acm2/audio_coding_module_impl.cc
@@ -0,0 +1,1990 @@
+/*
+ *  Copyright (c) 2012 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 "webrtc/modules/audio_coding/main/source/audio_coding_module_impl.h"
+
+#include <assert.h>
+#include <stdlib.h>
+#include <vector>
+
+#include "webrtc/engine_configurations.h"
+#include "webrtc/modules/audio_coding/main/interface/audio_coding_module_typedefs.h"
+#include "webrtc/modules/audio_coding/main/source/acm_codec_database.h"
+#include "webrtc/modules/audio_coding/main/source/acm_common_defs.h"
+#include "webrtc/modules/audio_coding/main/source/acm_generic_codec.h"
+#include "webrtc/modules/audio_coding/main/source/acm_resampler.h"
+#include "webrtc/system_wrappers/interface/critical_section_wrapper.h"
+#include "webrtc/system_wrappers/interface/rw_lock_wrapper.h"
+#include "webrtc/system_wrappers/interface/trace.h"
+#include "webrtc/typedefs.h"
+
+namespace webrtc {
+
+enum {
+  kACMToneEnd = 999
+};
+
+// Maximum number of bytes in one packet (PCM16B, 20 ms packets, stereo).
+enum {
+  kMaxPacketSize = 2560
+};
+
+// Maximum number of payloads that can be packed in one RED payload. For
+// regular FEC, we only pack two payloads. In case of dual-streaming, in worst
+// case we might pack 3 payloads in one RED payload.
+enum {
+  kNumFecFragmentationVectors = 2,
+  kMaxNumFragmentationVectors = 3
+};
+
+// If packet N is arrived all packets prior to N - |kNackThresholdPackets| which
+// are not received are considered as lost, and appear in NACK list.
+enum {
+  kNackThresholdPackets = 2
+};
+
+namespace {
+
+// TODO(turajs): the same functionality is used in NetEq. If both classes
+// need them, make it a static function in ACMCodecDB.
+bool IsCodecRED(const CodecInst* codec) {
+  return (STR_CASE_CMP(codec->plname, "RED") == 0);
+}
+
+bool IsCodecRED(int index) {
+  return (IsCodecRED(&ACMCodecDB::database_[index]));
+}
+
+bool IsCodecCN(const CodecInst* codec) {
+  return (STR_CASE_CMP(codec->plname, "CN") == 0);
+}
+
+bool IsCodecCN(int index) {
+  return (IsCodecCN(&ACMCodecDB::database_[index]));
+}
+
+// Stereo-to-mono can be used as in-place.
+int DownMix(const AudioFrame& frame, int length_out_buff, int16_t* out_buff) {
+  if (length_out_buff < frame.samples_per_channel_) {
+    return -1;
+  }
+  for (int n = 0; n < frame.samples_per_channel_; ++n)
+    out_buff[n] = (frame.data_[2 * n] + frame.data_[2 * n + 1]) >> 1;
+  return 0;
+}
+
+// Mono-to-stereo can be used as in-place.
+int UpMix(const AudioFrame& frame, int length_out_buff, int16_t* out_buff) {
+  if (length_out_buff < frame.samples_per_channel_) {
+    return -1;
+  }
+  for (int n = frame.samples_per_channel_ - 1; n >= 0; --n) {
+    out_buff[2 * n + 1] = frame.data_[n];
+    out_buff[2 * n] = frame.data_[n];
+  }
+  return 0;
+}
+
+// Return 1 if timestamp t1 is less than timestamp t2, while compensating for
+// wrap-around.
+static int TimestampLessThan(uint32_t t1, uint32_t t2) {
+  uint32_t kHalfFullRange = static_cast<uint32_t>(0xFFFFFFFF) / 2;
+  if (t1 == t2) {
+    return 0;
+  } else if (t1 < t2) {
+    if (t2 - t1 < kHalfFullRange)
+      return 1;
+    return 0;
+  } else {
+    if (t1 - t2 < kHalfFullRange)
+      return 0;
+    return 1;
+  }
+}
+
+}  // namespace
+
+AudioCodingModuleImpl::AudioCodingModuleImpl(int id)
+    : packetization_callback_(NULL),
+      id_(id),
+      expected_codec_ts_(0xD87F3F9F),
+      expected_in_ts_(0xD87F3F9F),
+      send_codec_inst_(),
+      cng_nb_pltype_(255),
+      cng_wb_pltype_(255),
+      cng_swb_pltype_(255),
+      cng_fb_pltype_(255),
+      red_pltype_(255),
+      vad_enabled_(false),
+      dtx_enabled_(false),
+      vad_mode_(VADNormal),
+      stereo_send_(false),
+      current_send_codec_idx_(-1),
+      send_codec_registered_(false),
+      acm_crit_sect_(CriticalSectionWrapper::CreateCriticalSection()),
+      vad_callback_(NULL),
+      is_first_red_(true),
+      fec_enabled_(false),
+      last_fec_timestamp_(0),
+      previous_pltype_(255),
+      aux_rtp_header_(NULL),
+      receiver_initialized_(false),
+      callback_crit_sect_(CriticalSectionWrapper::CreateCriticalSection()),
+      secondary_send_codec_inst_(),
+      secondary_encoder_(NULL),
+      codec_timestamp_(expected_codec_ts_),
+      first_10ms_data_(false) {
+
+  // Nullify send codec memory, set payload type and set codec name to
+  // invalid values.
+  const char no_name[] = "noCodecRegistered";
+  strncpy(send_codec_inst_.plname, no_name, RTP_PAYLOAD_NAME_SIZE - 1);
+  send_codec_inst_.pltype = -1;
+
+  strncpy(secondary_send_codec_inst_.plname, no_name,
+          RTP_PAYLOAD_NAME_SIZE - 1);
+  secondary_send_codec_inst_.pltype = -1;
+
+  for (int i = 0; i < ACMCodecDB::kMaxNumCodecs; i++) {
+    codecs_[i] = NULL;
+    mirror_codec_idx_[i] = -1;
+  }
+
+  receiver_.set_id(id_);
+
+  // Allocate memory for RED.
+  red_buffer_ = new uint8_t[MAX_PAYLOAD_SIZE_BYTE];
+
+  // TODO(turajs): This might not be exactly how this class is supposed to work.
+  // The external usage might be that |fragmentationVectorSize| has to match
+  // the allocated space for the member-arrays, while here, we allocate
+  // according to the maximum number of fragmentations and change
+  // |fragmentationVectorSize| on-the-fly based on actual number of
+  // fragmentations. However, due to copying to local variable before calling
+  // SendData, the RTP module receives a "valid" fragmentation, where allocated
+  // space matches |fragmentationVectorSize|, therefore, this should not cause
+  // any problem. A better approach is not using RTPFragmentationHeader as
+  // member variable, instead, use an ACM-specific structure to hold RED-related
+  // data. See module_common_type.h for the definition of
+  // RTPFragmentationHeader.
+  fragmentation_.VerifyAndAllocateFragmentationHeader(
+      kMaxNumFragmentationVectors);
+
+  // Register the default payload type for RED and for CNG at sampling rates of
+  // 8, 16, 32 and 48 kHz.
+  for (int i = (ACMCodecDB::kNumCodecs - 1); i >= 0; i--) {
+    if (IsCodecRED(i)) {
+      red_pltype_ = static_cast<uint8_t>(ACMCodecDB::database_[i].pltype);
+    } else if (IsCodecCN(i)) {
+      if (ACMCodecDB::database_[i].plfreq == 8000) {
+        cng_nb_pltype_ = static_cast<uint8_t>(ACMCodecDB::database_[i].pltype);
+      } else if (ACMCodecDB::database_[i].plfreq == 16000) {
+        cng_wb_pltype_ = static_cast<uint8_t>(ACMCodecDB::database_[i].pltype);
+      } else if (ACMCodecDB::database_[i].plfreq == 32000) {
+        cng_swb_pltype_ = static_cast<uint8_t>(ACMCodecDB::database_[i].pltype);
+      } else if (ACMCodecDB::database_[i].plfreq == 48000) {
+        cng_fb_pltype_ = static_cast<uint8_t>(ACMCodecDB::database_[i].pltype);
+      }
+    }
+  }
+
+  if (InitializeReceiverSafe() < 0) {
+    WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, id_,
+                 "Cannot initialize receiver");
+  }
+  WEBRTC_TRACE(webrtc::kTraceMemory, webrtc::kTraceAudioCoding, id, "Created");
+}
+
+AudioCodingModuleImpl::~AudioCodingModuleImpl() {
+  {
+    CriticalSectionScoped lock(acm_crit_sect_);
+    current_send_codec_idx_ = -1;
+
+    for (int i = 0; i < ACMCodecDB::kMaxNumCodecs; i++) {
+      if (codecs_[i] != NULL) {
+        // Mirror index holds the address of the codec memory.
+        assert(mirror_codec_idx_[i] > -1);
+        if (codecs_[mirror_codec_idx_[i]] != NULL) {
+          delete codecs_[mirror_codec_idx_[i]];
+          codecs_[mirror_codec_idx_[i]] = NULL;
+        }
+
+        codecs_[i] = NULL;
+      }
+    }
+
+    if (red_buffer_ != NULL) {
+      delete[] red_buffer_;
+      red_buffer_ = NULL;
+    }
+  }
+
+  if (aux_rtp_header_ != NULL) {
+    delete aux_rtp_header_;
+    aux_rtp_header_ = NULL;
+  }
+
+  delete callback_crit_sect_;
+  callback_crit_sect_ = NULL;
+
+  delete acm_crit_sect_;
+  acm_crit_sect_ = NULL;
+  WEBRTC_TRACE(webrtc::kTraceMemory, webrtc::kTraceAudioCoding, id_,
+               "Destroyed");
+}
+
+int32_t AudioCodingModuleImpl::ChangeUniqueId(const int32_t id) {
+  {
+    CriticalSectionScoped lock(acm_crit_sect_);
+    id_ = id;
+
+    for (int i = 0; i < ACMCodecDB::kMaxNumCodecs; i++) {
+      if (codecs_[i] != NULL) {
+        codecs_[i]->SetUniqueID(id);
+      }
+    }
+  }
+
+  receiver_.set_id(id_);
+  return 0;
+}
+
+// Returns the number of milliseconds until the module want a
+// worker thread to call Process.
+int32_t AudioCodingModuleImpl::TimeUntilNextProcess() {
+  CriticalSectionScoped lock(acm_crit_sect_);
+
+  if (!HaveValidEncoder("TimeUntilNextProcess")) {
+    return -1;
+  }
+  return codecs_[current_send_codec_idx_]->SamplesLeftToEncode() /
+      (send_codec_inst_.plfreq / 1000);
+}
+
+int32_t AudioCodingModuleImpl::Process() {
+  bool dual_stream;
+  {
+    CriticalSectionScoped lock(acm_crit_sect_);
+    dual_stream = (secondary_encoder_.get() != NULL);
+  }
+  if (dual_stream) {
+    return ProcessDualStream();
+  }
+  return ProcessSingleStream();
+}
+
+int AudioCodingModuleImpl::EncodeFragmentation(int fragmentation_index,
+                                               int payload_type,
+                                               uint32_t current_timestamp,
+                                               ACMGenericCodec* encoder,
+                                               uint8_t* stream) {
+  int16_t len_bytes = MAX_PAYLOAD_SIZE_BYTE;
+  uint32_t rtp_timestamp;
+  WebRtcACMEncodingType encoding_type;
+  if (encoder->Encode(stream, &len_bytes, &rtp_timestamp, &encoding_type) < 0) {
+    return -1;
+  }
+  assert(encoding_type == kActiveNormalEncoded);
+  assert(len_bytes > 0);
+
+  fragmentation_.fragmentationLength[fragmentation_index] = len_bytes;
+  fragmentation_.fragmentationPlType[fragmentation_index] = payload_type;
+  fragmentation_.fragmentationTimeDiff[fragmentation_index] =
+      static_cast<uint16_t>(current_timestamp - rtp_timestamp);
+  fragmentation_.fragmentationVectorSize++;
+  return len_bytes;
+}
+
+// Primary payloads are sent immediately, whereas a single secondary payload is
+// buffered to be combined with "the next payload."
+// Normally "the next payload" would be a primary payload. In case two
+// consecutive secondary payloads are generated with no primary payload in
+// between, then two secondary payloads are packed in one RED.
+int AudioCodingModuleImpl::ProcessDualStream() {
+  uint8_t stream[kMaxNumFragmentationVectors * MAX_PAYLOAD_SIZE_BYTE];
+  uint32_t current_timestamp;
+  int16_t length_bytes = 0;
+  RTPFragmentationHeader my_fragmentation;
+
+  uint8_t my_red_payload_type;
+
+  {
+    CriticalSectionScoped lock(acm_crit_sect_);
+    // Check if there is an encoder before.
+    if (!HaveValidEncoder("ProcessDualStream") ||
+        secondary_encoder_.get() == NULL) {
+      return -1;
+    }
+    ACMGenericCodec* primary_encoder = codecs_[current_send_codec_idx_];
+    // If primary encoder has a full frame of audio to generate payload.
+    bool primary_ready_to_encode = primary_encoder->HasFrameToEncode();
+    // If the secondary encoder has a frame of audio to generate a payload.
+    bool secondary_ready_to_encode = secondary_encoder_->HasFrameToEncode();
+
+    if (!primary_ready_to_encode && !secondary_ready_to_encode) {
+      // Nothing to send.
+      return 0;
+    }
+    int len_bytes_previous_secondary = static_cast<int>(
+        fragmentation_.fragmentationLength[2]);
+    assert(len_bytes_previous_secondary <= MAX_PAYLOAD_SIZE_BYTE);
+    bool has_previous_payload = len_bytes_previous_secondary > 0;
+
+    uint32_t primary_timestamp = primary_encoder->EarliestTimestamp();
+    uint32_t secondary_timestamp = secondary_encoder_->EarliestTimestamp();
+
+    if (!has_previous_payload && !primary_ready_to_encode &&
+        secondary_ready_to_encode) {
+      // Secondary payload will be the ONLY bit-stream. Encode by secondary
+      // encoder, store the payload, and return. No packet is sent.
+      int16_t len_bytes = MAX_PAYLOAD_SIZE_BYTE;
+      WebRtcACMEncodingType encoding_type;
+      if (secondary_encoder_->Encode(red_buffer_, &len_bytes,
+                                     &last_fec_timestamp_,
+                                     &encoding_type) < 0) {
+        WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, id_,
+                     "ProcessDual(): Encoding of secondary encoder Failed");
+        return -1;
+      }
+      assert(len_bytes > 0);
+      assert(encoding_type == kActiveNormalEncoded);
+      assert(len_bytes <= MAX_PAYLOAD_SIZE_BYTE);
+      fragmentation_.fragmentationLength[2] = len_bytes;
+      return 0;
+    }
+
+    // Initialize with invalid but different values, so later can have sanity
+    // check if they are different.
+    int index_primary = -1;
+    int index_secondary = -2;
+    int index_previous_secondary = -3;
+
+    if (primary_ready_to_encode) {
+      index_primary = secondary_ready_to_encode ?
+          TimestampLessThan(primary_timestamp, secondary_timestamp) : 0;
+      index_primary += has_previous_payload ?
+          TimestampLessThan(primary_timestamp, last_fec_timestamp_) : 0;
+    }
+
+    if (secondary_ready_to_encode) {
+      // Timestamp of secondary payload can only be less than primary payload,
+      // but is always larger than the timestamp of previous secondary payload.
+      index_secondary = primary_ready_to_encode ?
+          (1 - TimestampLessThan(primary_timestamp, secondary_timestamp)) : 0;
+    }
+
+    if (has_previous_payload) {
+      index_previous_secondary = primary_ready_to_encode ?
+          (1 - TimestampLessThan(primary_timestamp, last_fec_timestamp_)) : 0;
+      // If secondary is ready it always have a timestamp larger than previous
+      // secondary. So the index is either 0 or 1.
+      index_previous_secondary += secondary_ready_to_encode ? 1 : 0;
+    }
+
+    // Indices must not be equal.
+    assert(index_primary != index_secondary);
+    assert(index_primary != index_previous_secondary);
+    assert(index_secondary != index_previous_secondary);
+
+    // One of the payloads has to be at position zero.
+    assert(index_primary == 0 || index_secondary == 0 ||
+           index_previous_secondary == 0);
+
+    // Timestamp of the RED payload.
+    if (index_primary == 0) {
+      current_timestamp = primary_timestamp;
+    } else if (index_secondary == 0) {
+      current_timestamp = secondary_timestamp;
+    } else {
+      current_timestamp = last_fec_timestamp_;
+    }
+
+    fragmentation_.fragmentationVectorSize = 0;
+    if (has_previous_payload) {
+      assert(index_previous_secondary >= 0 &&
+             index_previous_secondary < kMaxNumFragmentationVectors);
+      assert(len_bytes_previous_secondary <= MAX_PAYLOAD_SIZE_BYTE);
+      memcpy(&stream[index_previous_secondary * MAX_PAYLOAD_SIZE_BYTE],
+             red_buffer_, sizeof(stream[0]) * len_bytes_previous_secondary);
+      fragmentation_.fragmentationLength[index_previous_secondary] =
+          len_bytes_previous_secondary;
+      fragmentation_.fragmentationPlType[index_previous_secondary] =
+          secondary_send_codec_inst_.pltype;
+      fragmentation_.fragmentationTimeDiff[index_previous_secondary] =
+          static_cast<uint16_t>(current_timestamp - last_fec_timestamp_);
+      fragmentation_.fragmentationVectorSize++;
+    }
+
+    if (primary_ready_to_encode) {
+      assert(index_primary >= 0 && index_primary < kMaxNumFragmentationVectors);
+      int i = index_primary * MAX_PAYLOAD_SIZE_BYTE;
+      if (EncodeFragmentation(index_primary, send_codec_inst_.pltype,
+                              current_timestamp, primary_encoder,
+                              &stream[i]) < 0) {
+        WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, id_,
+                     "ProcessDualStream(): Encoding of primary encoder Failed");
+        return -1;
+      }
+    }
+
+    if (secondary_ready_to_encode) {
+      assert(index_secondary >= 0 &&
+             index_secondary < kMaxNumFragmentationVectors - 1);
+      int i = index_secondary * MAX_PAYLOAD_SIZE_BYTE;
+      if (EncodeFragmentation(index_secondary,
+                              secondary_send_codec_inst_.pltype,
+                              current_timestamp, secondary_encoder_.get(),
+                              &stream[i]) < 0) {
+        WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, id_,
+                     "ProcessDualStream(): Encoding of secondary encoder "
+                     "Failed");
+        return -1;
+      }
+    }
+    // Copy to local variable, as it will be used outside the ACM lock.
+    my_fragmentation.CopyFrom(fragmentation_);
+    my_red_payload_type = red_pltype_;
+    length_bytes = 0;
+    for (int n = 0; n < fragmentation_.fragmentationVectorSize; n++) {
+      length_bytes += fragmentation_.fragmentationLength[n];
+    }
+  }
+
+  {
+    CriticalSectionScoped lock(callback_crit_sect_);
+    if (packetization_callback_ != NULL) {
+      // Callback with payload data, including redundant data (FEC/RED).
+      if (packetization_callback_->SendData(kAudioFrameSpeech,
+                                            my_red_payload_type,
+                                            current_timestamp, stream,
+                                            length_bytes,
+                                            &my_fragmentation) < 0) {
+        return -1;
+      }
+    }
+  }
+
+  {
+    CriticalSectionScoped lock(acm_crit_sect_);
+    // Now that data is sent, clean up fragmentation.
+    ResetFragmentation(0);
+  }
+  return 0;
+}
+
+// Process any pending tasks such as timeouts.
+int AudioCodingModuleImpl::ProcessSingleStream() {
+  // Make room for 1 RED payload.
+  uint8_t stream[2 * MAX_PAYLOAD_SIZE_BYTE];
+  // TODO(turajs): |length_bytes| & |red_length_bytes| can be of type int if
+  // ACMGenericCodec::Encode() & ACMGenericCodec::GetRedPayload() allows.
+  int16_t length_bytes = 2 * MAX_PAYLOAD_SIZE_BYTE;
+  int16_t red_length_bytes = length_bytes;
+  uint32_t rtp_timestamp;
+  int status;
+  WebRtcACMEncodingType encoding_type;
+  FrameType frame_type = kAudioFrameSpeech;
+  uint8_t current_payload_type = 0;
+  bool has_data_to_send = false;
+  bool fec_active = false;
+  RTPFragmentationHeader my_fragmentation;
+
+  // Keep the scope of the ACM critical section limited.
+  {
+    CriticalSectionScoped lock(acm_crit_sect_);
+    // Check if there is an encoder before.
+    if (!HaveValidEncoder("ProcessSingleStream")) {
+      return -1;
+    }
+    status = codecs_[current_send_codec_idx_]->Encode(stream, &length_bytes,
+                                                      &rtp_timestamp,
+                                                      &encoding_type);
+    if (status < 0) {
+      // Encode failed.
+      WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, id_,
+                   "ProcessSingleStream(): Encoding Failed");
+      length_bytes = 0;
+      return -1;
+    } else if (status == 0) {
+      // Not enough data.
+      return 0;
+    } else {
+      switch (encoding_type) {
+        case kNoEncoding: {
+          current_payload_type = previous_pltype_;
+          frame_type = kFrameEmpty;
+          length_bytes = 0;
+          break;
+        }
+        case kActiveNormalEncoded:
+        case kPassiveNormalEncoded: {
+          current_payload_type = (uint8_t)send_codec_inst_.pltype;
+          frame_type = kAudioFrameSpeech;
+          break;
+        }
+        case kPassiveDTXNB: {
+          current_payload_type = cng_nb_pltype_;
+          frame_type = kAudioFrameCN;
+          is_first_red_ = true;
+          break;
+        }
+        case kPassiveDTXWB: {
+          current_payload_type = cng_wb_pltype_;
+          frame_type = kAudioFrameCN;
+          is_first_red_ = true;
+          break;
+        }
+        case kPassiveDTXSWB: {
+          current_payload_type = cng_swb_pltype_;
+          frame_type = kAudioFrameCN;
+          is_first_red_ = true;
+          break;
+        }
+        case kPassiveDTXFB: {
+          current_payload_type = cng_fb_pltype_;
+          frame_type = kAudioFrameCN;
+          is_first_red_ = true;
+          break;
+        }
+      }
+      has_data_to_send = true;
+      previous_pltype_ = current_payload_type;
+
+      // Redundancy encode is done here. The two bitstreams packetized into
+      // one RTP packet and the fragmentation points are set.
+      // Only apply RED on speech data.
+      if ((fec_enabled_) &&
+          ((encoding_type == kActiveNormalEncoded) ||
+              (encoding_type == kPassiveNormalEncoded))) {
+        // FEC is enabled within this scope.
+        //
+        // Note that, a special solution exists for iSAC since it is the only
+        // codec for which GetRedPayload has a non-empty implementation.
+        //
+        // Summary of the FEC scheme below (use iSAC as example):
+        //
+        //  1st (is_first_red_ is true) encoded iSAC frame (primary #1) =>
+        //      - call GetRedPayload() and store redundancy for packet #1 in
+        //        second fragment of RED buffer (old data)
+        //      - drop the primary iSAC frame
+        //      - don't call SendData
+        //  2nd (is_first_red_ is false) encoded iSAC frame (primary #2) =>
+        //      - store primary #2 in 1st fragment of RED buffer and send the
+        //        combined packet
+        //      - the transmitted packet contains primary #2 (new) and
+        //        reduncancy for packet #1 (old)
+        //      - call GetRed_Payload() and store redundancy for packet #2 in
+        //        second fragment of RED buffer
+        //
+        //  ...
+        //
+        //  Nth encoded iSAC frame (primary #N) =>
+        //      - store primary #N in 1st fragment of RED buffer and send the
+        //        combined packet
+        //      - the transmitted packet contains primary #N (new) and
+        //        reduncancy for packet #(N-1) (old)
+        //      - call GetRedPayload() and store redundancy for packet #N in
+        //        second fragment of RED buffer
+        //
+        //  For all other codecs, GetRedPayload does nothing and returns -1 =>
+        //  redundant data is only a copy.
+        //
+        //  First combined packet contains : #2 (new) and #1 (old)
+        //  Second combined packet contains: #3 (new) and #2 (old)
+        //  Third combined packet contains : #4 (new) and #3 (old)
+        //
+        //  Hence, even if every second packet is dropped, perfect
+        //  reconstruction is possible.
+        fec_active = true;
+
+        has_data_to_send = false;
+        // Skip the following part for the first packet in a RED session.
+        if (!is_first_red_) {
+          // Rearrange stream such that FEC packets are included.
+          // Replace stream now that we have stored current stream.
+          memcpy(stream + fragmentation_.fragmentationOffset[1], red_buffer_,
+                 fragmentation_.fragmentationLength[1]);
+          // Update the fragmentation time difference vector, in number of
+          // timestamps.
+          uint16_t time_since_last = static_cast<uint16_t>(
+              rtp_timestamp - last_fec_timestamp_);
+
+          // Update fragmentation vectors.
+          fragmentation_.fragmentationPlType[1] =
+              fragmentation_.fragmentationPlType[0];
+          fragmentation_.fragmentationTimeDiff[1] = time_since_last;
+          has_data_to_send = true;
+        }
+
+        // Insert new packet length.
+        fragmentation_.fragmentationLength[0] = length_bytes;
+
+        // Insert new packet payload type.
+        fragmentation_.fragmentationPlType[0] = current_payload_type;
+        last_fec_timestamp_ = rtp_timestamp;
+
+        // Can be modified by the GetRedPayload() call if iSAC is utilized.
+        red_length_bytes = length_bytes;
+
+        // A fragmentation header is provided => packetization according to
+        // RFC 2198 (RTP Payload for Redundant Audio Data) will be used.
+        // First fragment is the current data (new).
+        // Second fragment is the previous data (old).
+        length_bytes = static_cast<int16_t>(
+            fragmentation_.fragmentationLength[0] +
+            fragmentation_.fragmentationLength[1]);
+
+        // Get, and store, redundant data from the encoder based on the recently
+        // encoded frame.
+        // NOTE - only iSAC contains an implementation; all other codecs does
+        // nothing and returns -1.
+        if (codecs_[current_send_codec_idx_]->GetRedPayload(
+            red_buffer_, &red_length_bytes) == -1) {
+          // The codec was not iSAC => use current encoder output as redundant
+          // data instead (trivial FEC scheme).
+          memcpy(red_buffer_, stream, red_length_bytes);
+        }
+
+        is_first_red_ = false;
+        // Update payload type with RED payload type.
+        current_payload_type = red_pltype_;
+        // We have packed 2 payloads.
+        fragmentation_.fragmentationVectorSize = kNumFecFragmentationVectors;
+
+        // Copy to local variable, as it will be used outside ACM lock.
+        my_fragmentation.CopyFrom(fragmentation_);
+        // Store RED length.
+        fragmentation_.fragmentationLength[1] = red_length_bytes;
+      }
+    }
+  }
+
+  if (has_data_to_send) {
+    CriticalSectionScoped lock(callback_crit_sect_);
+
+    if (packetization_callback_ != NULL) {
+      if (fec_active) {
+        // Callback with payload data, including redundant data (FEC/RED).
+        packetization_callback_->SendData(frame_type, current_payload_type,
+                                          rtp_timestamp, stream, length_bytes,
+                                          &my_fragmentation);
+      } else {
+        // Callback with payload data.
+        packetization_callback_->SendData(frame_type, current_payload_type,
+                                          rtp_timestamp, stream, length_bytes,
+                                          NULL);
+      }
+    }
+
+    if (vad_callback_ != NULL) {
+      // Callback with VAD decision.
+      vad_callback_->InFrameType(((int16_t)encoding_type));
+    }
+  }
+  return length_bytes;
+}
+
+/////////////////////////////////////////
+//   Sender
+//
+
+// Initialize send codec.
+int AudioCodingModuleImpl::InitializeSender() {
+  CriticalSectionScoped lock(acm_crit_sect_);
+
+  // Start with invalid values.
+  send_codec_registered_ = false;
+  current_send_codec_idx_ = -1;
+  send_codec_inst_.plname[0] = '\0';
+
+  // Delete all encoders to start fresh.
+  for (int id = 0; id < ACMCodecDB::kMaxNumCodecs; id++) {
+    if (codecs_[id] != NULL) {
+      codecs_[id]->DestructEncoder();
+    }
+  }
+
+  // Initialize FEC/RED.
+  is_first_red_ = true;
+  if (fec_enabled_ || secondary_encoder_.get() != NULL) {
+    if (red_buffer_ != NULL) {
+      memset(red_buffer_, 0, MAX_PAYLOAD_SIZE_BYTE);
+    }
+    if (fec_enabled_) {
+      ResetFragmentation(kNumFecFragmentationVectors);
+    } else {
+      ResetFragmentation(0);
+    }
+  }
+
+  return 0;
+}
+
+int AudioCodingModuleImpl::ResetEncoder() {
+  CriticalSectionScoped lock(acm_crit_sect_);
+  if (!HaveValidEncoder("ResetEncoder")) {
+    return -1;
+  }
+  return codecs_[current_send_codec_idx_]->ResetEncoder();
+}
+
+ACMGenericCodec* AudioCodingModuleImpl::CreateCodec(const CodecInst& codec) {
+  ACMGenericCodec* my_codec = NULL;
+
+  my_codec = ACMCodecDB::CreateCodecInstance(codec);
+  if (my_codec == NULL) {
+    // Error, could not create the codec.
+    WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, id_,
+                 "ACMCodecDB::CreateCodecInstance() failed in CreateCodec()");
+    return my_codec;
+  }
+  my_codec->SetUniqueID(id_);
+  my_codec->SetNetEqDecodeLock(receiver_.DecodeLock());
+
+  return my_codec;
+}
+
+// Check if the given codec is a valid to be registered as send codec.
+static int IsValidSendCodec(const CodecInst& send_codec,
+                            bool is_primary_encoder,
+                            int acm_id,
+                            int* mirror_id) {
+  if ((send_codec.channels != 1) && (send_codec.channels != 2)) {
+    WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, acm_id,
+                 "Wrong number of channels (%d, only mono and stereo are "
+                 "supported) for %s encoder", send_codec.channels,
+                 is_primary_encoder ? "primary" : "secondary");
+    return -1;
+  }
+
+  int codec_id = ACMCodecDB::CodecNumber(send_codec, mirror_id);
+  if (codec_id < 0) {
+    WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, acm_id,
+                 "Invalid codec setting for the send codec.");
+    return -1;
+  }
+
+  // TODO(tlegrand): Remove this check. Already taken care of in
+  // ACMCodecDB::CodecNumber().
+  // Check if the payload-type is valid
+  if (!ACMCodecDB::ValidPayloadType(send_codec.pltype)) {
+    WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, acm_id,
+                 "Invalid payload-type %d for %s.", send_codec.pltype,
+                 send_codec.plname);
+    return -1;
+  }
+
+  // Telephone-event cannot be a send codec.
+  if (!STR_CASE_CMP(send_codec.plname, "telephone-event")) {
+    WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, acm_id,
+                 "telephone-event cannot be a send codec");
+    *mirror_id = -1;
+    return -1;
+  }
+
+  if (ACMCodecDB::codec_settings_[codec_id].channel_support
+      < send_codec.channels) {
+    WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, acm_id,
+                 "%d number of channels not supportedn for %s.",
+                 send_codec.channels, send_codec.plname);
+    *mirror_id = -1;
+    return -1;
+  }
+
+  if (!is_primary_encoder) {
+    // If registering the secondary encoder, then RED and CN are not valid
+    // choices as encoder.
+    if (IsCodecRED(&send_codec)) {
+      WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, acm_id,
+                   "RED cannot be secondary codec");
+      *mirror_id = -1;
+      return -1;
+    }
+
+    if (IsCodecCN(&send_codec)) {
+      WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, acm_id,
+                   "DTX cannot be secondary codec");
+      *mirror_id = -1;
+      return -1;
+    }
+  }
+  return codec_id;
+}
+
+int AudioCodingModuleImpl::RegisterSecondarySendCodec(
+    const CodecInst& send_codec) {
+  CriticalSectionScoped lock(acm_crit_sect_);
+  if (!send_codec_registered_) {
+    return -1;
+  }
+  // Primary and Secondary codecs should have the same sampling rates.
+  if (send_codec.plfreq != send_codec_inst_.plfreq) {
+    return -1;
+  }
+  int mirror_id;
+  int codec_id = IsValidSendCodec(send_codec, false, id_, &mirror_id);
+  if (codec_id < 0) {
+    return -1;
+  }
+  ACMGenericCodec* encoder = CreateCodec(send_codec);
+  WebRtcACMCodecParams codec_params;
+  // Initialize the codec before registering. For secondary codec VAD & DTX are
+  // disabled.
+  memcpy(&(codec_params.codec_inst), &send_codec, sizeof(CodecInst));
+  codec_params.enable_vad = false;
+  codec_params.enable_dtx = false;
+  codec_params.vad_mode = VADNormal;
+  // Force initialization.
+  if (encoder->InitEncoder(&codec_params, true) < 0) {
+    // Could not initialize, therefore cannot be registered.
+    delete encoder;
+    return -1;
+  }
+  secondary_encoder_.reset(encoder);
+  memcpy(&secondary_send_codec_inst_, &send_codec, sizeof(send_codec));
+
+  // Disable VAD & DTX.
+  SetVADSafe(false, false, VADNormal);
+
+  // Cleaning.
+  if (red_buffer_) {
+    memset(red_buffer_, 0, MAX_PAYLOAD_SIZE_BYTE);
+  }
+  ResetFragmentation(0);
+  return 0;
+}
+
+void AudioCodingModuleImpl::UnregisterSecondarySendCodec() {
+  CriticalSectionScoped lock(acm_crit_sect_);
+  if (secondary_encoder_.get() == NULL) {
+    return;
+  }
+  secondary_encoder_.reset();
+  ResetFragmentation(0);
+}
+
+int AudioCodingModuleImpl::SecondarySendCodec(
+    CodecInst* secondary_codec) const {
+  CriticalSectionScoped lock(acm_crit_sect_);
+  if (secondary_encoder_.get() == NULL) {
+    return -1;
+  }
+  memcpy(secondary_codec, &secondary_send_codec_inst_,
+         sizeof(secondary_send_codec_inst_));
+  return 0;
+}
+
+// Can be called multiple times for Codec, CNG, RED.
+int AudioCodingModuleImpl::RegisterSendCodec(const CodecInst& send_codec) {
+  int mirror_id;
+  int codec_id = IsValidSendCodec(send_codec, true, id_, &mirror_id);
+
+  CriticalSectionScoped lock(acm_crit_sect_);
+
+  // Check for reported errors from function IsValidSendCodec().
+  if (codec_id < 0) {
+    if (!send_codec_registered_) {
+      // This values has to be NULL if there is no codec registered.
+      current_send_codec_idx_ = -1;
+    }
+    return -1;
+  }
+
+  // RED can be registered with other payload type. If not registered a default
+  // payload type is used.
+  if (IsCodecRED(&send_codec)) {
+    // TODO(tlegrand): Remove this check. Already taken care of in
+    // ACMCodecDB::CodecNumber().
+    // Check if the payload-type is valid
+    if (!ACMCodecDB::ValidPayloadType(send_codec.pltype)) {
+      WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, id_,
+                   "Invalid payload-type %d for %s.", send_codec.pltype,
+                   send_codec.plname);
+      return -1;
+    }
+    // Set RED payload type.
+    red_pltype_ = static_cast<uint8_t>(send_codec.pltype);
+    return 0;
+  }
+
+  // CNG can be registered with other payload type. If not registered the
+  // default payload types from codec database will be used.
+  if (IsCodecCN(&send_codec)) {
+    // CNG is registered.
+    switch (send_codec.plfreq) {
+      case 8000: {
+        cng_nb_pltype_ = static_cast<uint8_t>(send_codec.pltype);
+        break;
+      }
+      case 16000: {
+        cng_wb_pltype_ = static_cast<uint8_t>(send_codec.pltype);
+        break;
+      }
+      case 32000: {
+        cng_swb_pltype_ = static_cast<uint8_t>(send_codec.pltype);
+        break;
+      }
+      case 48000: {
+        cng_fb_pltype_ = static_cast<uint8_t>(send_codec.pltype);
+        break;
+      }
+      default: {
+        WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, id_,
+                     "RegisterSendCodec() failed, invalid frequency for CNG "
+                     "registration");
+        return -1;
+      }
+    }
+    return 0;
+  }
+
+  // Set Stereo, and make sure VAD and DTX is turned off.
+  if (send_codec.channels == 2) {
+    stereo_send_ = true;
+    if (vad_enabled_ || dtx_enabled_) {
+      WEBRTC_TRACE(webrtc::kTraceWarning, webrtc::kTraceAudioCoding, id_,
+                   "VAD/DTX is turned off, not supported when sending stereo.");
+    }
+    vad_enabled_ = false;
+    dtx_enabled_ = false;
+  } else {
+    stereo_send_ = false;
+  }
+
+  // Check if the codec is already registered as send codec.
+  bool is_send_codec;
+  if (send_codec_registered_) {
+    int send_codec_mirror_id;
+    int send_codec_id = ACMCodecDB::CodecNumber(send_codec_inst_,
+                                                &send_codec_mirror_id);
+    assert(send_codec_id >= 0);
+    is_send_codec = (send_codec_id == codec_id) ||
+        (mirror_id == send_codec_mirror_id);
+  } else {
+    is_send_codec = false;
+  }
+
+  // If there is secondary codec registered and the new send codec has a
+  // sampling rate different than that of secondary codec, then unregister the
+  // secondary codec.
+  if (secondary_encoder_.get() != NULL &&
+      secondary_send_codec_inst_.plfreq != send_codec.plfreq) {
+    secondary_encoder_.reset();
+    ResetFragmentation(0);
+  }
+
+  // If new codec, or new settings, register.
+  if (!is_send_codec) {
+    if (codecs_[mirror_id] == NULL) {
+      codecs_[mirror_id] = CreateCodec(send_codec);
+      if (codecs_[mirror_id] == NULL) {
+        WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, id_,
+                     "Cannot Create the codec");
+        return -1;
+      }
+      mirror_codec_idx_[mirror_id] = mirror_id;
+    }
+
+    if (mirror_id != codec_id) {
+      codecs_[codec_id] = codecs_[mirror_id];
+      mirror_codec_idx_[codec_id] = mirror_id;
+    }
+
+    ACMGenericCodec* codec_ptr = codecs_[codec_id];
+    int status;
+    WebRtcACMCodecParams codec_params;
+
+    memcpy(&(codec_params.codec_inst), &send_codec, sizeof(CodecInst));
+    codec_params.enable_vad = vad_enabled_;
+    codec_params.enable_dtx = dtx_enabled_;
+    codec_params.vad_mode = vad_mode_;
+    // Force initialization.
+    status = codec_ptr->InitEncoder(&codec_params, true);
+
+    // Check if VAD was turned on, or if error is reported.
+    if (status == 1) {
+      vad_enabled_ = true;
+    } else if (status < 0) {
+      // Could not initialize the encoder.
+
+      // Check if already have a registered codec.
+      // Depending on that different messages are logged.
+      if (!send_codec_registered_) {
+        current_send_codec_idx_ = -1;
+        WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, id_,
+                     "Cannot Initialize the encoder No Encoder is registered");
+      } else {
+        WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, id_,
+                     "Cannot Initialize the encoder, continue encoding with "
+                     "the previously registered codec");
+      }
+      return -1;
+    }
+
+    // Everything is fine so we can replace the previous codec with this one.
+    if (send_codec_registered_) {
+      // If we change codec we start fresh with FEC.
+      // This is not strictly required by the standard.
+      is_first_red_ = true;
+
+      if (codec_ptr->SetVAD(dtx_enabled_, vad_enabled_, vad_mode_) < 0) {
+        // SetVAD failed.
+        vad_enabled_ = false;
+        dtx_enabled_ = false;
+      }
+    }
+
+    current_send_codec_idx_ = codec_id;
+    send_codec_registered_ = true;
+    memcpy(&send_codec_inst_, &send_codec, sizeof(CodecInst));
+    previous_pltype_ = send_codec_inst_.pltype;
+    return 0;
+  } else {
+    // If codec is the same as already registered check if any parameters
+    // has changed compared to the current values.
+    // If any parameter is valid then apply it and record.
+    bool force_init = false;
+
+    if (mirror_id != codec_id) {
+      codecs_[codec_id] = codecs_[mirror_id];
+      mirror_codec_idx_[codec_id] = mirror_id;
+    }
+
+    // Check the payload type.
+    if (send_codec.pltype != send_codec_inst_.pltype) {
+      // At this point check if the given payload type is valid.
+      // Record it later when the sampling frequency is changed
+      // successfully.
+      if (!ACMCodecDB::ValidPayloadType(send_codec.pltype)) {
+        WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, id_,
+                     "Out of range payload type");
+        return -1;
+      }
+    }
+
+    // If there is a codec that ONE instance of codec supports multiple
+    // sampling frequencies, then we need to take care of it here.
+    // one such a codec is iSAC. Both WB and SWB are encoded and decoded
+    // with one iSAC instance. Therefore, we need to update the encoder
+    // frequency if required.
+    if (send_codec_inst_.plfreq != send_codec.plfreq) {
+      force_init = true;
+
+      // If sampling frequency is changed we have to start fresh with RED.
+      is_first_red_ = true;
+    }
+
+    // If packet size or number of channels has changed, we need to
+    // re-initialize the encoder.
+    if (send_codec_inst_.pacsize != send_codec.pacsize) {
+      force_init = true;
+    }
+    if (send_codec_inst_.channels != send_codec.channels) {
+      force_init = true;
+    }
+
+    if (force_init) {
+      WebRtcACMCodecParams codec_params;
+
+      memcpy(&(codec_params.codec_inst), &send_codec, sizeof(CodecInst));
+      codec_params.enable_vad = vad_enabled_;
+      codec_params.enable_dtx = dtx_enabled_;
+      codec_params.vad_mode = vad_mode_;
+
+      // Force initialization.
+      if (codecs_[current_send_codec_idx_]->InitEncoder(&codec_params,
+                                                        true) < 0) {
+        WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, id_,
+                     "Could not change the codec packet-size.");
+        return -1;
+      }
+
+      send_codec_inst_.plfreq = send_codec.plfreq;
+      send_codec_inst_.pacsize = send_codec.pacsize;
+      send_codec_inst_.channels = send_codec.channels;
+    }
+
+    // If the change of sampling frequency has been successful then
+    // we store the payload-type.
+    send_codec_inst_.pltype = send_codec.pltype;
+
+    // Check if a change in Rate is required.
+    if (send_codec.rate != send_codec_inst_.rate) {
+      if (codecs_[codec_id]->SetBitRate(send_codec.rate) < 0) {
+        WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, id_,
+                     "Could not change the codec rate.");
+        return -1;
+      }
+      send_codec_inst_.rate = send_codec.rate;
+    }
+    previous_pltype_ = send_codec_inst_.pltype;
+
+    return 0;
+  }
+}
+
+// Get current send codec.
+int AudioCodingModuleImpl::SendCodec(
+    CodecInst* current_codec) const {
+  WEBRTC_TRACE(webrtc::kTraceStream, webrtc::kTraceAudioCoding, id_,
+               "SendCodec()");
+  CriticalSectionScoped lock(acm_crit_sect_);
+
+  if (!send_codec_registered_) {
+    WEBRTC_TRACE(webrtc::kTraceStream, webrtc::kTraceAudioCoding, id_,
+                 "SendCodec Failed, no codec is registered");
+    return -1;
+  }
+  WebRtcACMCodecParams encoder_param;
+  codecs_[current_send_codec_idx_]->EncoderParams(&encoder_param);
+  encoder_param.codec_inst.pltype = send_codec_inst_.pltype;
+  memcpy(current_codec, &(encoder_param.codec_inst), sizeof(CodecInst));
+
+  return 0;
+}
+
+// Get current send frequency.
+int AudioCodingModuleImpl::SendFrequency() const {
+  WEBRTC_TRACE(webrtc::kTraceStream, webrtc::kTraceAudioCoding, id_,
+               "SendFrequency()");
+  CriticalSectionScoped lock(acm_crit_sect_);
+
+  if (!send_codec_registered_) {
+    WEBRTC_TRACE(webrtc::kTraceStream, webrtc::kTraceAudioCoding, id_,
+                 "SendFrequency Failed, no codec is registered");
+    return -1;
+  }
+
+  return send_codec_inst_.plfreq;
+}
+
+// Get encode bitrate.
+// Adaptive rate codecs return their current encode target rate, while other
+// codecs return there longterm avarage or their fixed rate.
+int AudioCodingModuleImpl::SendBitrate() const {
+  CriticalSectionScoped lock(acm_crit_sect_);
+
+  if (!send_codec_registered_) {
+    WEBRTC_TRACE(webrtc::kTraceStream, webrtc::kTraceAudioCoding, id_,
+                 "SendBitrate Failed, no codec is registered");
+    return -1;
+  }
+
+  WebRtcACMCodecParams encoder_param;
+  codecs_[current_send_codec_idx_]->EncoderParams(&encoder_param);
+
+  return encoder_param.codec_inst.rate;
+}
+
+// Set available bandwidth, inform the encoder about the estimated bandwidth
+// received from the remote party.
+int AudioCodingModuleImpl::SetReceivedEstimatedBandwidth(int bw) {
+  return codecs_[current_send_codec_idx_]->SetEstimatedBandwidth(bw);
+}
+
+// Register a transport callback which will be called to deliver
+// the encoded buffers.
+int AudioCodingModuleImpl::RegisterTransportCallback(
+    AudioPacketizationCallback* transport) {
+  CriticalSectionScoped lock(callback_crit_sect_);
+  packetization_callback_ = transport;
+  return 0;
+}
+
+// Add 10MS of raw (PCM) audio data to the encoder.
+int AudioCodingModuleImpl::Add10MsData(
+    const AudioFrame& audio_frame) {
+  if (audio_frame.samples_per_channel_ <= 0) {
+    assert(false);
+    WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, id_,
+                 "Cannot Add 10 ms audio, payload length is negative or "
+                 "zero");
+    return -1;
+  }
+
+  // Allow for 8, 16, 32 and 48kHz input audio.
+  if ((audio_frame.sample_rate_hz_ != 8000)
+      && (audio_frame.sample_rate_hz_ != 16000)
+      && (audio_frame.sample_rate_hz_ != 32000)
+      && (audio_frame.sample_rate_hz_ != 48000)) {
+    assert(false);
+    WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, id_,
+                 "Cannot Add 10 ms audio, input frequency not valid");
+    return -1;
+  }
+
+  // If the length and frequency matches. We currently just support raw PCM.
+  if ((audio_frame.sample_rate_hz_ / 100)
+      != audio_frame.samples_per_channel_) {
+    WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, id_,
+                 "Cannot Add 10 ms audio, input frequency and length doesn't"
+                 " match");
+    return -1;
+  }
+
+  if (audio_frame.num_channels_ != 1 && audio_frame.num_channels_ != 2) {
+    WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, id_,
+                 "Cannot Add 10 ms audio, invalid number of channels.");
+    return -1;
+  }
+
+  CriticalSectionScoped lock(acm_crit_sect_);
+  // Do we have a codec registered?
+  if (!HaveValidEncoder("Add10MsData")) {
+    return -1;
+  }
+
+  const AudioFrame* ptr_frame;
+  // Perform a resampling, also down-mix if it is required and can be
+  // performed before resampling (a down mix prior to resampling will take
+  // place if both primary and secondary encoders are mono and input is in
+  // stereo).
+  if (PreprocessToAddData(audio_frame, &ptr_frame) < 0) {
+    return -1;
+  }
+
+  // Check whether we need an up-mix or down-mix?
+  bool remix = ptr_frame->num_channels_ != send_codec_inst_.channels;
+  if (secondary_encoder_.get() != NULL) {
+    remix = remix ||
+        (ptr_frame->num_channels_ != secondary_send_codec_inst_.channels);
+  }
+
+  // If a re-mix is required (up or down), this buffer will store re-mixed
+  // version of the input.
+  int16_t buffer[WEBRTC_10MS_PCM_AUDIO];
+  if (remix) {
+    if (ptr_frame->num_channels_ == 1) {
+      if (UpMix(*ptr_frame, WEBRTC_10MS_PCM_AUDIO, buffer) < 0)
+        return -1;
+    } else {
+      if (DownMix(*ptr_frame, WEBRTC_10MS_PCM_AUDIO, buffer) < 0)
+        return -1;
+    }
+  }
+
+  // When adding data to encoders this pointer is pointing to an audio buffer
+  // with correct number of channels.
+  const int16_t* ptr_audio = ptr_frame->data_;
+
+  // For pushing data to primary, point the |ptr_audio| to correct buffer.
+  if (send_codec_inst_.channels != ptr_frame->num_channels_)
+    ptr_audio = buffer;
+
+  if (codecs_[current_send_codec_idx_]->Add10MsData(
+      ptr_frame->timestamp_, ptr_audio, ptr_frame->samples_per_channel_,
+      send_codec_inst_.channels) < 0)
+    return -1;
+
+  if (secondary_encoder_.get() != NULL) {
+    // For pushing data to secondary, point the |ptr_audio| to correct buffer.
+    ptr_audio = ptr_frame->data_;
+    if (secondary_send_codec_inst_.channels != ptr_frame->num_channels_)
+      ptr_audio = buffer;
+
+    if (secondary_encoder_->Add10MsData(
+        ptr_frame->timestamp_, ptr_audio, ptr_frame->samples_per_channel_,
+        secondary_send_codec_inst_.channels) < 0)
+      return -1;
+  }
+
+  return 0;
+}
+
+// Perform a resampling and down-mix if required. We down-mix only if
+// encoder is mono and input is stereo. In case of dual-streaming, both
+// encoders has to be mono for down-mix to take place.
+// |*ptr_out| will point to the pre-processed audio-frame. If no pre-processing
+// is required, |*ptr_out| points to |in_frame|.
+int AudioCodingModuleImpl::PreprocessToAddData(const AudioFrame& in_frame,
+                                               const AudioFrame** ptr_out) {
+  // Primary and secondary (if exists) should have the same sampling rate.
+  assert((secondary_encoder_.get() != NULL) ?
+      secondary_send_codec_inst_.plfreq == send_codec_inst_.plfreq : true);
+
+  bool resample = (in_frame.sample_rate_hz_ != send_codec_inst_.plfreq);
+
+  // This variable is true if primary codec and secondary codec (if exists)
+  // are both mono and input is stereo.
+  bool down_mix;
+  if (secondary_encoder_.get() != NULL) {
+    down_mix = (in_frame.num_channels_ == 2) &&
+        (send_codec_inst_.channels == 1) &&
+        (secondary_send_codec_inst_.channels == 1);
+  } else {
+    down_mix = (in_frame.num_channels_ == 2) &&
+        (send_codec_inst_.channels == 1);
+  }
+
+  if (!first_10ms_data_) {
+    expected_in_ts_ = in_frame.timestamp_;
+    expected_codec_ts_ = in_frame.timestamp_;
+    first_10ms_data_ = true;
+  } else if (in_frame.timestamp_ != expected_in_ts_) {
+    // TODO(turajs): Do we need a warning here.
+    expected_codec_ts_ += (in_frame.timestamp_ - expected_in_ts_) *
+        static_cast<uint32_t>((static_cast<double>(send_codec_inst_.plfreq) /
+                    static_cast<double>(in_frame.sample_rate_hz_)));
+    expected_in_ts_ = in_frame.timestamp_;
+  }
+
+
+  if (!down_mix && !resample) {
+    // No pre-processing is required.
+    expected_in_ts_ += in_frame.samples_per_channel_;
+    expected_codec_ts_ += in_frame.samples_per_channel_;
+    *ptr_out = &in_frame;
+    return 0;
+  }
+
+  *ptr_out = &preprocess_frame_;
+  preprocess_frame_.num_channels_ = in_frame.num_channels_;
+  int16_t audio[WEBRTC_10MS_PCM_AUDIO];
+  const int16_t* src_ptr_audio = in_frame.data_;
+  int16_t* dest_ptr_audio = preprocess_frame_.data_;
+  if (down_mix) {
+    // If a resampling is required the output of a down-mix is written into a
+    // local buffer, otherwise, it will be written to the output frame.
+    if (resample)
+      dest_ptr_audio = audio;
+    if (DownMix(in_frame, WEBRTC_10MS_PCM_AUDIO, dest_ptr_audio) < 0)
+      return -1;
+    preprocess_frame_.num_channels_ = 1;
+    // Set the input of the resampler is the down-mixed signal.
+    src_ptr_audio = audio;
+  }
+
+  preprocess_frame_.timestamp_ = expected_codec_ts_;
+  preprocess_frame_.samples_per_channel_ = in_frame.samples_per_channel_;
+  preprocess_frame_.sample_rate_hz_ = in_frame.sample_rate_hz_;
+  // If it is required, we have to do a resampling.
+  if (resample) {
+    // The result of the resampler is written to output frame.
+    dest_ptr_audio = preprocess_frame_.data_;
+
+    preprocess_frame_.samples_per_channel_ = resampler_.Resample10Msec(
+        src_ptr_audio, in_frame.sample_rate_hz_, send_codec_inst_.plfreq,
+        preprocess_frame_.num_channels_, dest_ptr_audio);
+
+    if (preprocess_frame_.samples_per_channel_ < 0) {
+      WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, id_,
+                   "Cannot add 10 ms audio, resmapling failed");
+      return -1;
+    }
+    preprocess_frame_.sample_rate_hz_ = send_codec_inst_.plfreq;
+  }
+
+  expected_codec_ts_ += preprocess_frame_.samples_per_channel_;
+  expected_in_ts_ += in_frame.samples_per_channel_;
+
+  return 0;
+}
+
+/////////////////////////////////////////
+//   (FEC) Forward Error Correction
+//
+
+bool AudioCodingModuleImpl::FECStatus() const {
+  CriticalSectionScoped lock(acm_crit_sect_);
+  return fec_enabled_;
+}
+
+// Configure FEC status i.e on/off.
+int AudioCodingModuleImpl::SetFECStatus(
+#ifdef WEBRTC_CODEC_RED
+    bool enable_fec) {
+  CriticalSectionScoped lock(acm_crit_sect_);
+
+  if (fec_enabled_ != enable_fec) {
+    // Reset the RED buffer.
+    memset(red_buffer_, 0, MAX_PAYLOAD_SIZE_BYTE);
+
+    // Reset fragmentation buffers.
+    ResetFragmentation(kNumFecFragmentationVectors);
+    // Set fec_enabled_.
+    fec_enabled_ = enable_fec;
+  }
+  is_first_red_ = true;  // Make sure we restart FEC.
+  return 0;
+#else
+    bool /* enable_fec */) {
+  fec_enabled_ = false;
+  WEBRTC_TRACE(webrtc::kTraceWarning, webrtc::kTraceAudioCoding, id_,
+               "  WEBRTC_CODEC_RED is undefined => fec_enabled_ = %d",
+               fec_enabled_);
+  return -1;
+#endif
+}
+
+/////////////////////////////////////////
+//   (VAD) Voice Activity Detection
+//
+int AudioCodingModuleImpl::SetVAD(bool enable_dtx,
+                                  bool enable_vad,
+                                  ACMVADMode mode) {
+  CriticalSectionScoped lock(acm_crit_sect_);
+  return SetVADSafe(enable_dtx, enable_vad, mode);
+}
+
+int AudioCodingModuleImpl::SetVADSafe(bool enable_dtx,
+                                      bool enable_vad,
+                                      ACMVADMode mode) {
+  // Sanity check of the mode.
+  if ((mode != VADNormal) && (mode != VADLowBitrate)
+      && (mode != VADAggr) && (mode != VADVeryAggr)) {
+    WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, id_,
+                 "Invalid VAD Mode %d, no change is made to VAD/DTX status",
+                 mode);
+    return -1;
+  }
+
+  // Check that the send codec is mono. We don't support VAD/DTX for stereo
+  // sending.
+  if ((enable_dtx || enable_vad) && stereo_send_) {
+    WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, id_,
+                 "VAD/DTX not supported for stereo sending");
+    return -1;
+  }
+
+  // We don't support VAD/DTX when dual-streaming is enabled, i.e.
+  // secondary-encoder is registered.
+  if ((enable_dtx || enable_vad) && secondary_encoder_.get() != NULL) {
+    WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, id_,
+                 "VAD/DTX not supported when dual-streaming is enabled.");
+    return -1;
+  }
+
+  // If a send codec is registered, set VAD/DTX for the codec.
+  if (HaveValidEncoder("SetVAD")) {
+    int status = codecs_[current_send_codec_idx_]->SetVAD(enable_dtx,
+                                                          enable_vad,
+                                                          mode);
+    if (status == 1) {
+      // Vad was enabled.
+      vad_enabled_ = true;
+      dtx_enabled_ = enable_dtx;
+      vad_mode_ = mode;
+
+      return 0;
+    } else if (status < 0) {
+      // SetVAD failed.
+      WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, id_,
+                   "SetVAD failed");
+
+      vad_enabled_ = false;
+      dtx_enabled_ = false;
+
+      return -1;
+    }
+  }
+
+  vad_enabled_ = enable_vad;
+  dtx_enabled_ = enable_dtx;
+  vad_mode_ = mode;
+
+  return 0;
+}
+
+// Get VAD/DTX settings.
+int AudioCodingModuleImpl::VAD(bool* dtx_enabled, bool* vad_enabled,
+                               ACMVADMode* mode) const {
+  CriticalSectionScoped lock(acm_crit_sect_);
+
+  *dtx_enabled = dtx_enabled_;
+  *vad_enabled = vad_enabled_;
+  *mode = vad_mode_;
+
+  return 0;
+}
+
+/////////////////////////////////////////
+//   Receiver
+//
+
+int AudioCodingModuleImpl::InitializeReceiver() {
+  CriticalSectionScoped lock(acm_crit_sect_);
+  return InitializeReceiverSafe();
+}
+
+// Initialize receiver, resets codec database etc.
+int AudioCodingModuleImpl::InitializeReceiverSafe() {
+  // If the receiver is already initialized then we want to destroy any
+  // existing decoders. After a call to this function, we should have a clean
+  // start-up.
+  if (receiver_initialized_) {
+    if (receiver_.RemoveAllCodecs() < 0)
+      return -1;
+  }
+  receiver_.set_id(id_);
+  receiver_.ResetInitialDelay();
+  receiver_.SetMinimumDelay(0);
+  receiver_.SetMaximumDelay(0);
+  receiver_.FlushBuffers();
+
+  // Register RED and CN.
+  for (int i = 0; i < ACMCodecDB::kNumCodecs; i++) {
+    if (IsCodecRED(i) || IsCodecCN(i)) {
+      uint8_t pl_type = static_cast<uint8_t>(ACMCodecDB::database_[i].pltype);
+      if (receiver_.AddCodec(i, pl_type, 1, NULL) < 0) {
+        WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, id_,
+                     "Cannot register master codec.");
+        return -1;
+      }
+    }
+  }
+  receiver_initialized_ = true;
+  return 0;
+}
+
+// TODO(turajs): If NetEq opens an API for reseting the state of decoders then
+// implement this method. Otherwise it should be removed. I might be that by
+// removing and registering a decoder we can achieve the effect of resetting.
+// Reset the decoder state.
+int AudioCodingModuleImpl::ResetDecoder() {
+  CriticalSectionScoped lock(acm_crit_sect_);
+  return -1;
+}
+
+// Get current receive frequency.
+int AudioCodingModuleImpl::ReceiveFrequency() const {
+  WEBRTC_TRACE(webrtc::kTraceStream, webrtc::kTraceAudioCoding, id_,
+               "ReceiveFrequency()");
+
+  CriticalSectionScoped lock(acm_crit_sect_);
+
+  int codec_id = receiver_.last_audio_codec_id();
+
+  int sample_rate_hz;
+  if (codec_id < 0)
+    sample_rate_hz = receiver_.current_sample_rate_hz();
+  else
+    sample_rate_hz = ACMCodecDB::database_[codec_id].plfreq;
+
+  // TODO(tlegrand): Remove this option when we have full 48 kHz support.
+  return (sample_rate_hz > 32000) ? 32000 : sample_rate_hz;
+}
+
+// Get current playout frequency.
+int AudioCodingModuleImpl::PlayoutFrequency() const {
+  WEBRTC_TRACE(webrtc::kTraceStream, webrtc::kTraceAudioCoding, id_,
+               "PlayoutFrequency()");
+
+  CriticalSectionScoped lock(acm_crit_sect_);
+
+  return receiver_.current_sample_rate_hz();
+}
+
+// Register possible receive codecs, can be called multiple times,
+// for codecs, CNG (NB, WB and SWB), DTMF, RED.
+int AudioCodingModuleImpl::RegisterReceiveCodec(const CodecInst& codec) {
+  CriticalSectionScoped lock(acm_crit_sect_);
+
+  if (codec.channels > 2 || codec.channels < 0) {
+    WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, id_,
+                 "Unsupported number of channels, %d.", codec.channels);
+    return -1;
+  }
+
+  // TODO(turajs) do we need this for NetEq 4?
+  if (!receiver_initialized_) {
+    if (InitializeReceiverSafe() < 0) {
+      WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, id_,
+                   "Cannot initialize receiver, failed registering codec.");
+      return -1;
+    }
+  }
+
+  int mirror_id;
+  int codec_id = ACMCodecDB::ReceiverCodecNumber(codec, &mirror_id);
+
+  if (codec_id < 0 || codec_id >= ACMCodecDB::kNumCodecs) {
+    WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, id_,
+                 "Wrong codec params to be registered as receive codec");
+    return -1;
+  }
+
+  // Check if the payload-type is valid.
+  if (!ACMCodecDB::ValidPayloadType(codec.pltype)) {
+    WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, id_,
+                 "Invalid payload-type %d for %s.", codec.pltype,
+                 codec.plname);
+    return -1;
+  }
+
+  AudioDecoder* decoder = NULL;
+  // Get |decoder| associated with |codec|. |decoder| can be NULL if |codec|
+  // does not own its decoder.
+  if (GetAudioDecoder(codec, codec_id, mirror_id, &decoder) < 0) {
+    WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, id_,
+                 "Wrong codec params to be registered as receive codec");
+    return -1;
+  }
+  uint8_t payload_type = static_cast<uint8_t>(codec.pltype);
+  return receiver_.AddCodec(codec_id, payload_type, codec.channels, decoder);
+}
+
+// Get current received codec.
+int AudioCodingModuleImpl::ReceiveCodec(CodecInst* current_codec) const {
+  return receiver_.LastAudioCodec(current_codec);
+}
+
+// Incoming packet from network parsed and ready for decode.
+int AudioCodingModuleImpl::IncomingPacket(const uint8_t* incoming_payload,
+                                          const int payload_length,
+                                          const WebRtcRTPHeader& rtp_header) {
+  if (payload_length < 0) {
+    WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, id_,
+                 "IncomingPacket() Error, payload-length cannot be negative");
+    return -1;
+  }
+  int last_audio_pltype = receiver_.last_audio_payload_type();
+  if (receiver_.InsertPacket(rtp_header, incoming_payload, payload_length) <
+      0) {
+    return -1;
+  }
+  if (receiver_.last_audio_payload_type() != last_audio_pltype) {
+    int index = receiver_.last_audio_codec_id();
+    assert(index >= 0);
+    CriticalSectionScoped lock(acm_crit_sect_);
+
+    // |codec_[index]| might not be even created, simply because it is not
+    // yet registered as send codec. Even if it is registered, unless the
+    // codec shares same instance for encoder and decoder, this call is
+    // useless.
+    if (codecs_[index] != NULL)
+      codecs_[index]->UpdateDecoderSampFreq(index);
+  }
+  return 0;
+}
+
+// Minimum playout delay (Used for lip-sync).
+int AudioCodingModuleImpl::SetMinimumPlayoutDelay(int time_ms) {
+  if ((time_ms < 0) || (time_ms > 10000)) {
+    WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, id_,
+                 "Delay must be in the range of 0-1000 milliseconds.");
+    return -1;
+  }
+  return receiver_.SetMinimumDelay(time_ms);
+}
+
+int AudioCodingModuleImpl::SetMaximumPlayoutDelay(int time_ms) {
+  if ((time_ms < 0) || (time_ms > 10000)) {
+    WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, id_,
+                 "Delay must be in the range of 0-1000 milliseconds.");
+    return -1;
+  }
+  return receiver_.SetMaximumDelay(time_ms);
+}
+
+// Estimate the Bandwidth based on the incoming stream, needed for one way
+// audio where the RTCP send the BW estimate.
+// This is also done in the RTP module.
+int AudioCodingModuleImpl::DecoderEstimatedBandwidth() const {
+  // We can estimate far-end to near-end bandwidth if the iSAC are sent. Check
+  // if the last received packets were iSAC packet then retrieve the bandwidth.
+  int last_audio_codec_id = receiver_.last_audio_codec_id();
+  if (last_audio_codec_id >= 0 &&
+      STR_CASE_CMP("ISAC", ACMCodecDB::database_[last_audio_codec_id].plname)) {
+    CriticalSectionScoped lock(acm_crit_sect_);
+    return codecs_[last_audio_codec_id]->GetEstimatedBandwidth();
+  }
+  return -1;
+}
+
+// Set playout mode for: voice, fax, streaming or off.
+int AudioCodingModuleImpl::SetPlayoutMode(AudioPlayoutMode mode) {
+  receiver_.SetPlayoutMode(mode);
+  return 0;  // TODO(turajs): return value is for backward compatibility.
+}
+
+// Get playout mode voice, fax, streaming or off.
+AudioPlayoutMode AudioCodingModuleImpl::PlayoutMode() const {
+  return receiver_.PlayoutMode();
+}
+
+// Get 10 milliseconds of raw audio data to play out.
+// Automatic resample to the requested frequency.
+int AudioCodingModuleImpl::PlayoutData10Ms(int desired_freq_hz,
+                                           AudioFrame* audio_frame) {
+  // GetAudio always returns 10 ms, at the requested sample rate.
+  if (receiver_.GetAudio(desired_freq_hz, audio_frame) != 0) {
+    WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, id_,
+                 "PlayoutData failed, RecOut Failed");
+    return -1;
+  }
+
+  audio_frame->id_ = id_;
+  audio_frame->energy_ = 0;
+  audio_frame->timestamp_ = 0;
+  return 0;
+}
+
+/////////////////////////////////////////
+//   Statistics
+//
+
+// TODO(turajs) change the return value to void. Also change the corresponding
+// NetEq function.
+int AudioCodingModuleImpl::NetworkStatistics(ACMNetworkStatistics* statistics) {
+  receiver_.NetworkStatistics(statistics);
+  return 0;
+}
+
+void AudioCodingModuleImpl::DestructEncoderInst(void* inst) {
+  CriticalSectionScoped lock(acm_crit_sect_);
+  WEBRTC_TRACE(webrtc::kTraceDebug, webrtc::kTraceAudioCoding, id_,
+               "DestructEncoderInst()");
+  if (!HaveValidEncoder("DestructEncoderInst"))
+    return;
+  codecs_[current_send_codec_idx_]->DestructEncoderInst(inst);
+}
+
+int AudioCodingModuleImpl::RegisterVADCallback(ACMVADCallback* vad_callback) {
+  WEBRTC_TRACE(webrtc::kTraceDebug, webrtc::kTraceAudioCoding, id_,
+               "RegisterVADCallback()");
+  CriticalSectionScoped lock(callback_crit_sect_);
+  vad_callback_ = vad_callback;
+  return 0;
+}
+
+// TODO(tlegrand): Modify this function to work for stereo, and add tests.
+int AudioCodingModuleImpl::IncomingPayload(const uint8_t* incoming_payload,
+                                           int payload_length,
+                                           uint8_t payload_type,
+                                           uint32_t timestamp) {
+  if (payload_length < 0) {
+    // Log error in trace file.
+    WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, id_,
+                 "IncomingPacket() Error, payload-length cannot be negative");
+    return -1;
+  }
+
+  // We are not acquiring any lock when interacting with |aux_rtp_header_| no
+  // other method uses this member variable.
+  if (aux_rtp_header_ == NULL) {
+    // This is the first time that we are using |dummy_rtp_header_|
+    // so we have to create it.
+    aux_rtp_header_ = new WebRtcRTPHeader;
+    aux_rtp_header_->header.payloadType = payload_type;
+    // Don't matter in this case.
+    aux_rtp_header_->header.ssrc = 0;
+    aux_rtp_header_->header.markerBit = false;
+    // Start with random numbers.
+    aux_rtp_header_->header.sequenceNumber = 0x1234;  // Arbitrary.
+    aux_rtp_header_->type.Audio.channel = 1;
+  }
+
+  IncomingPacket(incoming_payload, payload_length, *aux_rtp_header_);
+  // Get ready for the next payload.
+  aux_rtp_header_->header.sequenceNumber++;
+  return 0;
+}
+
+int AudioCodingModuleImpl::ReplaceInternalDTXWithWebRtc(bool use_webrtc_dtx) {
+  CriticalSectionScoped lock(acm_crit_sect_);
+
+  if (!HaveValidEncoder("ReplaceInternalDTXWithWebRtc")) {
+    WEBRTC_TRACE(
+        webrtc::kTraceError, webrtc::kTraceAudioCoding, id_,
+        "Cannot replace codec internal DTX when no send codec is registered.");
+    return -1;
+  }
+
+  int res = codecs_[current_send_codec_idx_]->ReplaceInternalDTX(
+      use_webrtc_dtx);
+  // Check if VAD is turned on, or if there is any error.
+  if (res == 1) {
+    vad_enabled_ = true;
+  } else if (res < 0) {
+    WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, id_,
+                 "Failed to set ReplaceInternalDTXWithWebRtc(%d)",
+                 use_webrtc_dtx);
+    return res;
+  }
+
+  return 0;
+}
+
+int AudioCodingModuleImpl::IsInternalDTXReplacedWithWebRtc(
+    bool* uses_webrtc_dtx) {
+  CriticalSectionScoped lock(acm_crit_sect_);
+
+  if (!HaveValidEncoder("IsInternalDTXReplacedWithWebRtc")) {
+    return -1;
+  }
+  if (codecs_[current_send_codec_idx_]->IsInternalDTXReplaced(uses_webrtc_dtx)
+      < 0) {
+    return -1;
+  }
+  return 0;
+}
+
+int AudioCodingModuleImpl::SetISACMaxRate(int max_bit_per_sec) {
+  CriticalSectionScoped lock(acm_crit_sect_);
+
+  if (!HaveValidEncoder("SetISACMaxRate")) {
+    return -1;
+  }
+
+  return codecs_[current_send_codec_idx_]->SetISACMaxRate(max_bit_per_sec);
+}
+
+int AudioCodingModuleImpl::SetISACMaxPayloadSize(int max_size_bytes) {
+  CriticalSectionScoped lock(acm_crit_sect_);
+
+  if (!HaveValidEncoder("SetISACMaxPayloadSize")) {
+    return -1;
+  }
+
+  return codecs_[current_send_codec_idx_]->SetISACMaxPayloadSize(
+      max_size_bytes);
+}
+
+int AudioCodingModuleImpl::ConfigISACBandwidthEstimator(
+    int frame_size_ms,
+    int rate_bit_per_sec,
+    bool enforce_frame_size) {
+  CriticalSectionScoped lock(acm_crit_sect_);
+
+  if (!HaveValidEncoder("ConfigISACBandwidthEstimator")) {
+    return -1;
+  }
+
+  return codecs_[current_send_codec_idx_]->ConfigISACBandwidthEstimator(
+      frame_size_ms, rate_bit_per_sec, enforce_frame_size);
+}
+
+int AudioCodingModuleImpl::PlayoutTimestamp(uint32_t* timestamp) {
+  *timestamp = receiver_.PlayoutTimestamp();
+  return 0;
+}
+
+bool AudioCodingModuleImpl::HaveValidEncoder(const char* caller_name) const {
+  if ((!send_codec_registered_) || (current_send_codec_idx_ < 0) ||
+      (current_send_codec_idx_ >= ACMCodecDB::kNumCodecs)) {
+    WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, id_,
+                 "%s failed: No send codec is registered.", caller_name);
+    return false;
+  }
+  if ((current_send_codec_idx_ < 0) ||
+      (current_send_codec_idx_ >= ACMCodecDB::kNumCodecs)) {
+    WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, id_,
+                 "%s failed: Send codec index out of range.", caller_name);
+    return false;
+  }
+  if (codecs_[current_send_codec_idx_] == NULL) {
+    WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, id_,
+                 "%s failed: Send codec is NULL pointer.", caller_name);
+    return false;
+  }
+  return true;
+}
+
+int AudioCodingModuleImpl::UnregisterReceiveCodec(uint8_t payload_type) {
+  return receiver_.RemoveCodec(payload_type);
+}
+
+// TODO(turajs): correct the type of |length_bytes| when it is corrected in
+// GenericCodec.
+int AudioCodingModuleImpl::REDPayloadISAC(int isac_rate,
+                                          int isac_bw_estimate,
+                                          uint8_t* payload,
+                                          int16_t* length_bytes) {
+  if (!HaveValidEncoder("EncodeData")) {
+    return -1;
+  }
+  int status;
+  status = codecs_[current_send_codec_idx_]->REDPayloadISAC(isac_rate,
+                                                            isac_bw_estimate,
+                                                            payload,
+                                                            length_bytes);
+  return status;
+}
+
+void AudioCodingModuleImpl::ResetFragmentation(int vector_size) {
+  for (int n = 0; n < kMaxNumFragmentationVectors; n++) {
+    fragmentation_.fragmentationOffset[n] = n * MAX_PAYLOAD_SIZE_BYTE;
+  }
+  memset(fragmentation_.fragmentationLength, 0, kMaxNumFragmentationVectors *
+         sizeof(fragmentation_.fragmentationLength[0]));
+  memset(fragmentation_.fragmentationTimeDiff, 0, kMaxNumFragmentationVectors *
+         sizeof(fragmentation_.fragmentationTimeDiff[0]));
+  memset(fragmentation_.fragmentationPlType,
+         0,
+         kMaxNumFragmentationVectors *
+             sizeof(fragmentation_.fragmentationPlType[0]));
+  fragmentation_.fragmentationVectorSize = static_cast<uint16_t>(vector_size);
+}
+
+int AudioCodingModuleImpl::GetAudioDecoder(const CodecInst& codec, int codec_id,
+                                           int mirror_id,
+                                           AudioDecoder** decoder) {
+  if (ACMCodecDB::OwnsDecoder(codec_id)) {
+    // This codec has to own its own decoder. Therefore, it should create the
+    // corresponding AudioDecoder class and insert it into NetEq. If the codec
+    // does not exist create it.
+    //
+    // TODO(turajs): this part of the code is common with RegisterSendCodec(),
+    //               make a method for it.
+    if (codecs_[mirror_id] == NULL) {
+      codecs_[mirror_id] = CreateCodec(codec);
+      if (codecs_[mirror_id] == NULL) {
+        WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, id_,
+                     "Cannot Create the codec");
+        return -1;
+      }
+      mirror_codec_idx_[mirror_id] = mirror_id;
+    }
+
+    if (mirror_id != codec_id) {
+      codecs_[codec_id] = codecs_[mirror_id];
+      mirror_codec_idx_[codec_id] = mirror_id;
+    }
+    *decoder = codecs_[codec_id]->Decoder(codec_id);
+    if (!*decoder) {
+      assert(false);
+      return -1;
+    }
+  } else {
+    *decoder = NULL;
+  }
+
+  return 0;
+}
+
+int AudioCodingModuleImpl::SetInitialPlayoutDelay(int delay_ms) {
+  {
+    CriticalSectionScoped lock(acm_crit_sect_);
+    // Initialize receiver, if it is not initialized. Otherwise, initial delay
+    // is reset upon initialization of the receiver.
+    if (!receiver_initialized_)
+      InitializeReceiverSafe();
+  }
+  return receiver_.SetInitialDelay(delay_ms);
+}
+
+int AudioCodingModuleImpl::EnableNack(size_t max_nack_list_size) {
+  return receiver_.EnableNack(max_nack_list_size);
+}
+
+void AudioCodingModuleImpl::DisableNack() {
+  receiver_.DisableNack();
+}
+
+std::vector<uint16_t> AudioCodingModuleImpl::GetNackList(
+    int round_trip_time_ms) const {
+  return receiver_.GetNackList(round_trip_time_ms);
+}
+
+int AudioCodingModuleImpl::LeastRequiredDelayMs() const {
+  return receiver_.LeastRequiredDelayMs();
+}
+
+}  // namespace webrtc
diff --git a/webrtc/modules/audio_coding/main/acm2/audio_coding_module_impl.h b/webrtc/modules/audio_coding/main/acm2/audio_coding_module_impl.h
new file mode 100644
index 0000000..b9c70e9
--- /dev/null
+++ b/webrtc/modules/audio_coding/main/acm2/audio_coding_module_impl.h
@@ -0,0 +1,354 @@
+/*
+ *  Copyright (c) 2012 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_MAIN_SOURCE_AUDIO_CODING_MODULE_IMPL_H_
+#define WEBRTC_MODULES_AUDIO_CODING_MAIN_SOURCE_AUDIO_CODING_MODULE_IMPL_H_
+
+#include <vector>
+
+#include "webrtc/common_types.h"
+#include "webrtc/engine_configurations.h"
+#include "webrtc/modules/audio_coding/main/source/acm_codec_database.h"
+#include "webrtc/modules/audio_coding/main/source/acm_receiver.h"
+#include "webrtc/modules/audio_coding/main/source/acm_resampler.h"
+#include "webrtc/system_wrappers/interface/scoped_ptr.h"
+
+namespace webrtc {
+
+class ACMDTMFDetection;
+class ACMGenericCodec;
+class CriticalSectionWrapper;
+class RWLockWrapper;
+
+class AudioCodingModuleImpl : public AudioCodingModule {
+ public:
+  // Constructor
+  explicit AudioCodingModuleImpl(int id);
+
+  // Destructor
+  ~AudioCodingModuleImpl();
+
+  // Change the unique identifier of this object.
+  virtual int32_t ChangeUniqueId(const int32_t id);
+
+  // Returns the number of milliseconds until the module want a worker thread
+  // to call Process.
+  int32_t TimeUntilNextProcess();
+
+  // Process any pending tasks such as timeouts.
+  int32_t Process();
+
+  /////////////////////////////////////////
+  //   Sender
+  //
+
+  // Initialize send codec.
+  int InitializeSender();
+
+  // Reset send codec.
+  int ResetEncoder();
+
+  // Can be called multiple times for Codec, CNG, RED.
+  int RegisterSendCodec(const CodecInst& send_codec);
+
+  // Register Secondary codec for dual-streaming. Dual-streaming is activated
+  // right after the secondary codec is registered.
+  int RegisterSecondarySendCodec(const CodecInst& send_codec);
+
+  // Unregister the secondary codec. Dual-streaming is deactivated right after
+  // deregistering secondary codec.
+  void UnregisterSecondarySendCodec();
+
+  // Get the secondary codec.
+  int SecondarySendCodec(CodecInst* secondary_codec) const;
+
+  // Get current send codec.
+  int SendCodec(CodecInst* current_codec) const;
+
+  // Get current send frequency.
+  int SendFrequency() const;
+
+  // Get encode bit-rate.
+  // Adaptive rate codecs return their current encode target rate, while other
+  // codecs return there long-term average or their fixed rate.
+  int SendBitrate() const;
+
+  // Set available bandwidth, inform the encoder about the
+  // estimated bandwidth received from the remote party.
+  virtual int SetReceivedEstimatedBandwidth(int bw);
+
+  // Register a transport callback which will be
+  // called to deliver the encoded buffers.
+  int RegisterTransportCallback(AudioPacketizationCallback* transport);
+
+  // Add 10 ms of raw (PCM) audio data to the encoder.
+  int Add10MsData(const AudioFrame& audio_frame);
+
+  /////////////////////////////////////////
+  // (FEC) Forward Error Correction
+  //
+
+  // Configure FEC status i.e on/off.
+  int SetFECStatus(bool enable_fec);
+
+  // Get FEC status.
+  bool FECStatus() const;
+
+  /////////////////////////////////////////
+  //   (VAD) Voice Activity Detection
+  //   and
+  //   (CNG) Comfort Noise Generation
+  //
+
+  int SetVAD(bool enable_dtx = true,
+             bool enable_vad = false,
+             ACMVADMode mode = VADNormal);
+
+  int VAD(bool* dtx_enabled, bool* vad_enabled, ACMVADMode* mode) const;
+
+  int RegisterVADCallback(ACMVADCallback* vad_callback);
+
+  /////////////////////////////////////////
+  //   Receiver
+  //
+
+  // Initialize receiver, resets codec database etc.
+  int InitializeReceiver();
+
+  // Reset the decoder state.
+  int ResetDecoder();
+
+  // Get current receive frequency.
+  int ReceiveFrequency() const;
+
+  // Get current playout frequency.
+  int PlayoutFrequency() const;
+
+  // Register possible receive codecs, can be called multiple times,
+  // for codecs, CNG, DTMF, RED.
+  int RegisterReceiveCodec(const CodecInst& receive_codec);
+
+  // Get current received codec.
+  int ReceiveCodec(CodecInst* current_codec) const;
+
+  // Incoming packet from network parsed and ready for decode.
+  int IncomingPacket(const uint8_t* incoming_payload,
+                     int payload_length,
+                     const WebRtcRTPHeader& rtp_info);
+
+  // Incoming payloads, without rtp-info, the rtp-info will be created in ACM.
+  // One usage for this API is when pre-encoded files are pushed in ACM.
+  int IncomingPayload(const uint8_t* incoming_payload,
+                      int payload_length,
+                      uint8_t payload_type,
+                      uint32_t timestamp);
+
+  // Minimum playout delay.
+  int SetMinimumPlayoutDelay(int time_ms);
+
+  // Maximum playout delay.
+  int SetMaximumPlayoutDelay(int time_ms);
+
+  // Smallest latency NetEq will maintain.
+  int LeastRequiredDelayMs() const;
+
+  // Impose an initial delay on playout. ACM plays silence until |delay_ms|
+  // audio is accumulated in NetEq buffer, then starts decoding payloads.
+  int SetInitialPlayoutDelay(int delay_ms);
+
+  // TODO(turajs): DTMF playout is always activated in NetEq these APIs should
+  // be removed, as well as all VoE related APIs and methods.
+  //
+  // Configure Dtmf playout status i.e on/off playout the incoming outband Dtmf
+  // tone.
+  int SetDtmfPlayoutStatus(bool enable) { return 0; }
+
+  // Get Dtmf playout status.
+  bool DtmfPlayoutStatus() const { return true; }
+
+  // Estimate the Bandwidth based on the incoming stream, needed
+  // for one way audio where the RTCP send the BW estimate.
+  // This is also done in the RTP module .
+  int DecoderEstimatedBandwidth() const;
+
+  // Set playout mode voice, fax.
+  int SetPlayoutMode(AudioPlayoutMode mode);
+
+  // Get playout mode voice, fax.
+  AudioPlayoutMode PlayoutMode() const;
+
+  // Get playout timestamp.
+  int PlayoutTimestamp(uint32_t* timestamp);
+
+  // Get 10 milliseconds of raw audio data to play out, and
+  // automatic resample to the requested frequency if > 0.
+  int PlayoutData10Ms(int desired_freq_hz, AudioFrame* audio_frame);
+
+  /////////////////////////////////////////
+  //   Statistics
+  //
+
+  int NetworkStatistics(ACMNetworkStatistics* statistics);
+
+  void DestructEncoderInst(void* inst);
+
+  // GET RED payload for iSAC. The method id called when 'this' ACM is
+  // the default ACM.
+  int REDPayloadISAC(int isac_rate,
+                     int isac_bw_estimate,
+                     uint8_t* payload,
+                     int16_t* length_bytes);
+
+  int ReplaceInternalDTXWithWebRtc(bool use_webrtc_dtx);
+
+  int IsInternalDTXReplacedWithWebRtc(bool* uses_webrtc_dtx);
+
+  int SetISACMaxRate(int max_bit_per_sec);
+
+  int SetISACMaxPayloadSize(int max_size_bytes);
+
+  int ConfigISACBandwidthEstimator(int frame_size_ms,
+                                   int rate_bit_per_sec,
+                                   bool enforce_frame_size = false);
+
+  int UnregisterReceiveCodec(uint8_t payload_type);
+
+  int EnableNack(size_t max_nack_list_size);
+
+  void DisableNack();
+
+  std::vector<uint16_t> GetNackList(int round_trip_time_ms) const;
+
+ private:
+  int UnregisterReceiveCodecSafe(int payload_type);
+
+  ACMGenericCodec* CreateCodec(const CodecInst& codec);
+
+  int InitializeReceiverSafe();
+
+  bool HaveValidEncoder(const char* caller_name) const;
+
+  // Set VAD/DTX status. This function does not acquire a lock, and it is
+  // created to be called only from inside a critical section.
+  int SetVADSafe(bool enable_dtx, bool enable_vad, ACMVADMode mode);
+
+  // Process buffered audio when dual-streaming is not enabled (When RED is
+  // enabled still this function is used.)
+  int ProcessSingleStream();
+
+  // Process buffered audio when dual-streaming is enabled, i.e. secondary send
+  // codec is registered.
+  int ProcessDualStream();
+
+  // Preprocessing of input audio, including resampling and down-mixing if
+  // required, before pushing audio into encoder's buffer.
+  //
+  // in_frame: input audio-frame
+  // ptr_out: pointer to output audio_frame. If no preprocessing is required
+  //          |ptr_out| will be pointing to |in_frame|, otherwise pointing to
+  //          |preprocess_frame_|.
+  //
+  // Return value:
+  //   -1: if encountering an error.
+  //    0: otherwise.
+  int PreprocessToAddData(const AudioFrame& in_frame,
+                          const AudioFrame** ptr_out);
+
+  // Change required states after starting to receive the codec corresponding
+  // to |index|.
+  int UpdateUponReceivingCodec(int index);
+
+  int EncodeFragmentation(int fragmentation_index, int payload_type,
+                          uint32_t current_timestamp,
+                          ACMGenericCodec* encoder,
+                          uint8_t* stream);
+
+  void ResetFragmentation(int vector_size);
+
+  // Get a pointer to AudioDecoder of the given codec. For some codecs, e.g.
+  // iSAC, encoding and decoding have to be performed on a shared
+  // codec-instance. By calling this method, we get the codec-instance that ACM
+  // owns, then pass that to NetEq. This way, we perform both encoding and
+  // decoding on the same codec-instance. Furthermore, ACM would have control
+  // over decoder functionality if required. If |codec| does not share an
+  // instance between encoder and decoder, the |*decoder| is set NULL.
+  // The field ACMCodecDB::CodecSettings.owns_decoder indicates that if a
+  // codec owns the decoder-instance. For such codecs |*decoder| should be a
+  // valid pointer, otherwise it will be NULL.
+  int GetAudioDecoder(const CodecInst& codec, int codec_id,
+                      int mirror_id, AudioDecoder** decoder);
+
+  AudioPacketizationCallback* packetization_callback_;
+
+  int id_;
+  uint32_t expected_codec_ts_;
+  uint32_t expected_in_ts_;
+  CodecInst send_codec_inst_;
+
+  uint8_t cng_nb_pltype_;
+  uint8_t cng_wb_pltype_;
+  uint8_t cng_swb_pltype_;
+  uint8_t cng_fb_pltype_;
+
+  uint8_t red_pltype_;
+  bool vad_enabled_;
+  bool dtx_enabled_;
+  ACMVADMode vad_mode_;
+  ACMGenericCodec* codecs_[ACMCodecDB::kMaxNumCodecs];
+  int mirror_codec_idx_[ACMCodecDB::kMaxNumCodecs];
+  bool stereo_send_;
+  int current_send_codec_idx_;
+  bool send_codec_registered_;
+  ACMResampler resampler_;
+  AcmReceiver receiver_;
+  CriticalSectionWrapper* acm_crit_sect_;
+  ACMVADCallback* vad_callback_;
+
+  // RED/FEC.
+  bool is_first_red_;
+  bool fec_enabled_;
+
+  // TODO(turajs): |red_buffer_| is allocated in constructor, why having them
+  // as pointers and not an array. If concerned about the memory, then make a
+  // set-up function to allocate them only when they are going to be used, i.e.
+  // FEC or Dual-streaming is enabled.
+  uint8_t* red_buffer_;
+
+  // TODO(turajs): we actually don't need |fragmentation_| as a member variable.
+  // It is sufficient to keep the length & payload type of previous payload in
+  // member variables.
+  RTPFragmentationHeader fragmentation_;
+  uint32_t last_fec_timestamp_;
+
+  // This is to keep track of CN instances where we can send DTMFs.
+  uint8_t previous_pltype_;
+
+  // Used when payloads are pushed into ACM without any RTP info
+  // One example is when pre-encoded bit-stream is pushed from
+  // a file.
+  // IMPORTANT: this variable is only used in IncomingPayload(), therefore,
+  // no lock acquired when interacting with this variable. If it is going to
+  // be used in other methods, locks need to be taken.
+  WebRtcRTPHeader* aux_rtp_header_;
+
+  bool receiver_initialized_;
+
+  CriticalSectionWrapper* callback_crit_sect_;
+
+  AudioFrame preprocess_frame_;
+  CodecInst secondary_send_codec_inst_;
+  scoped_ptr<ACMGenericCodec> secondary_encoder_;
+  uint32_t codec_timestamp_;
+  bool first_10ms_data_;
+};
+
+}  // namespace webrtc
+
+#endif  // WEBRTC_MODULES_AUDIO_CODING_MAIN_SOURCE_AUDIO_CODING_MODULE_IMPL_H_
diff --git a/webrtc/modules/audio_coding/main/acm2/initial_delay_manager.cc b/webrtc/modules/audio_coding/main/acm2/initial_delay_manager.cc
new file mode 100644
index 0000000..dffed64
--- /dev/null
+++ b/webrtc/modules/audio_coding/main/acm2/initial_delay_manager.cc
@@ -0,0 +1,224 @@
+/*
+ *  Copyright (c) 2013 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 "webrtc/modules/audio_coding/main/source/initial_delay_manager.h"
+
+namespace webrtc {
+
+InitialDelayManager::InitialDelayManager(int initial_delay_ms,
+                                         int late_packet_threshold)
+    : last_packet_type_(kUndefinedPacket),
+      last_receive_timestamp_(0),
+      timestamp_step_(0),
+      audio_payload_type_(kInvalidPayloadType),
+      initial_delay_ms_(initial_delay_ms),
+      buffered_audio_ms_(0),
+      buffering_(true),
+      playout_timestamp_(0),
+      late_packet_threshold_(late_packet_threshold) {}
+
+void InitialDelayManager::UpdateLastReceivedPacket(
+    const WebRtcRTPHeader& rtp_info,
+    uint32_t receive_timestamp,
+    PacketType type,
+    bool new_codec,
+    int sample_rate_hz,
+    SyncStream* sync_stream) {
+  assert(sync_stream);
+
+  // If payload of audio packets is changing |new_codec| has to be true.
+  assert(!(!new_codec && type == kAudioPacket &&
+         rtp_info.header.payloadType != audio_payload_type_));
+
+  // Just shorthands.
+  const RTPHeader* current_header = &rtp_info.header;
+  RTPHeader* last_header = &last_packet_rtp_info_.header;
+
+  // Don't do anything if getting DTMF. The chance of DTMF in applications where
+  // initial delay is required is very low (we don't know of any). This avoids a
+  // lot of corner cases. The effect of ignoring DTMF packet is minimal. Note
+  // that DTMFs are inserted into NetEq just not accounted here.
+  if (type == kAvtPacket ||
+      (last_packet_type_ != kUndefinedPacket &&
+      !IsNewerSequenceNumber(current_header->sequenceNumber,
+                             last_header->sequenceNumber))) {
+    sync_stream->num_sync_packets = 0;
+    return;
+  }
+
+  if (new_codec) {
+    timestamp_step_ = 0;
+    if (type == kAudioPacket)
+      audio_payload_type_ = rtp_info.header.payloadType;
+    else
+      audio_payload_type_ = kInvalidPayloadType;  // Invalid.
+
+    RecordLastPacket(rtp_info, receive_timestamp, type);
+    sync_stream->num_sync_packets = 0;
+    buffered_audio_ms_ = 0;
+    buffering_ = true;
+
+    // If |buffering_| is set then |playout_timestamp_| should have correct
+    // value.
+    UpdatePlayoutTimestamp(*current_header, sample_rate_hz);
+    return;
+  }
+
+  uint32_t timestamp_increase = current_header->timestamp -
+      last_header->timestamp;
+
+  // |timestamp_increase| is invalid if this is the first packet. The effect is
+  // that |buffered_audio_ms_| is not increased.
+  if (last_packet_type_ == kUndefinedPacket) {
+    timestamp_increase = 0;
+  }
+
+  if (buffering_) {
+    buffered_audio_ms_ += timestamp_increase * 1000 / sample_rate_hz;
+
+    // A timestamp that reflects the initial delay, while buffering.
+    UpdatePlayoutTimestamp(*current_header, sample_rate_hz);
+
+    if (buffered_audio_ms_ >= initial_delay_ms_)
+      buffering_ = false;
+  }
+
+  if (current_header->sequenceNumber == last_header->sequenceNumber + 1) {
+    // Two consecutive audio packets, the previous packet-type is audio, so we
+    // can update |timestamp_step_|.
+    if (last_packet_type_ == kAudioPacket)
+      timestamp_step_ = timestamp_increase;
+    RecordLastPacket(rtp_info, receive_timestamp, type);
+    sync_stream->num_sync_packets = 0;
+    return;
+  }
+
+  uint16_t packet_gap = current_header->sequenceNumber -
+      last_header->sequenceNumber - 1;
+
+  // For smooth transitions leave a gap between audio and sync packets.
+  sync_stream->num_sync_packets = last_packet_type_ == kSyncPacket ?
+      packet_gap - 1 : packet_gap - 2;
+
+  // Do nothing if we haven't received any audio packet.
+  if (sync_stream->num_sync_packets > 0 &&
+      audio_payload_type_ != kInvalidPayloadType) {
+    if (timestamp_step_ == 0) {
+      // Make an estimate for |timestamp_step_| if it is not updated, yet.
+      assert(packet_gap > 0);
+      timestamp_step_ = timestamp_increase / (packet_gap + 1);
+    }
+    sync_stream->timestamp_step = timestamp_step_;
+
+    // Build the first sync-packet based on the current received packet.
+    memcpy(&sync_stream->rtp_info, &rtp_info, sizeof(rtp_info));
+    sync_stream->rtp_info.header.payloadType = audio_payload_type_;
+
+    uint16_t sequence_number_update = sync_stream->num_sync_packets + 1;
+    uint32_t timestamp_update = timestamp_step_ * sequence_number_update;
+
+    // Rewind sequence number and timestamps. This will give a more accurate
+    // description of the missing packets.
+    //
+    // Note that we leave a gap between the last packet in sync-stream and the
+    // current received packet, so it should be compensated for in the following
+    // computation of timestamps and sequence number.
+    sync_stream->rtp_info.header.sequenceNumber -= sequence_number_update;
+    sync_stream->receive_timestamp = receive_timestamp - timestamp_update;
+    sync_stream->rtp_info.header.timestamp -= timestamp_update;
+    sync_stream->rtp_info.header.payloadType = audio_payload_type_;
+  } else {
+    sync_stream->num_sync_packets = 0;
+  }
+
+  RecordLastPacket(rtp_info, receive_timestamp, type);
+  return;
+}
+
+void InitialDelayManager::RecordLastPacket(const WebRtcRTPHeader& rtp_info,
+                                           uint32_t receive_timestamp,
+                                           PacketType type) {
+  last_packet_type_ = type;
+  last_receive_timestamp_ = receive_timestamp;
+  memcpy(&last_packet_rtp_info_, &rtp_info, sizeof(rtp_info));
+}
+
+void InitialDelayManager::LatePackets(
+    uint32_t timestamp_now, SyncStream* sync_stream) {
+  assert(sync_stream);
+  const int kLateThreshold = 5;
+  sync_stream->num_sync_packets = 0;
+
+  // If there is no estimate of timestamp increment, |timestamp_step_|, then
+  // we cannot estimate the number of late packets.
+  // If the last packet has been CNG, estimating late packets is not meaningful,
+  // as a CNG packet is on unknown length.
+  // We can set a higher threshold if the last packet is CNG and continue
+  // execution, but this is how ACM1 code was written.
+  if (timestamp_step_ <= 0 ||
+      last_packet_type_ == kCngPacket ||
+      last_packet_type_ == kUndefinedPacket ||
+      audio_payload_type_ == kInvalidPayloadType)  // No audio packet received.
+    return;
+
+  int num_late_packets = (timestamp_now - last_receive_timestamp_) /
+      timestamp_step_;
+
+  if (num_late_packets < kLateThreshold)
+    return;
+
+  int sync_offset = 1;  // One gap at the end of the sync-stream.
+  if (last_packet_type_ != kSyncPacket) {
+    ++sync_offset;  // One more gap at the beginning of the sync-stream.
+    --num_late_packets;
+  }
+  uint32_t timestamp_update = sync_offset * timestamp_step_;
+
+  sync_stream->num_sync_packets = num_late_packets;
+  if (num_late_packets == 0)
+    return;
+
+  // Build the first sync-packet in the sync-stream.
+  memcpy(&sync_stream->rtp_info, &last_packet_rtp_info_,
+         sizeof(last_packet_rtp_info_));
+
+  // Increase sequence number and timestamps.
+  sync_stream->rtp_info.header.sequenceNumber += sync_offset;
+  sync_stream->rtp_info.header.timestamp += timestamp_update;
+  sync_stream->receive_timestamp = last_receive_timestamp_ + timestamp_update;
+  sync_stream->timestamp_step = timestamp_step_;
+
+  // Sync-packets have audio payload-type.
+  sync_stream->rtp_info.header.payloadType = audio_payload_type_;
+
+  uint16_t sequence_number_update = num_late_packets + sync_offset - 1;
+  timestamp_update = sequence_number_update * timestamp_step_;
+
+  // Fake the last RTP, assuming the caller will inject the whole sync-stream.
+  last_packet_rtp_info_.header.timestamp += timestamp_update;
+  last_packet_rtp_info_.header.sequenceNumber += sequence_number_update;
+  last_packet_rtp_info_.header.payloadType = audio_payload_type_;
+  last_receive_timestamp_ += timestamp_update;
+
+  last_packet_type_ = kSyncPacket;
+  return;
+}
+
+void InitialDelayManager::DisableBuffering() {
+  buffering_ = false;
+}
+
+void InitialDelayManager::UpdatePlayoutTimestamp(
+    const RTPHeader& current_header, int sample_rate_hz) {
+  playout_timestamp_ = current_header.timestamp - static_cast<uint32_t>(
+      initial_delay_ms_ * sample_rate_hz / 1000);
+}
+
+}  // namespace webrtc
diff --git a/webrtc/modules/audio_coding/main/acm2/initial_delay_manager.h b/webrtc/modules/audio_coding/main/acm2/initial_delay_manager.h
new file mode 100644
index 0000000..5c8ae18
--- /dev/null
+++ b/webrtc/modules/audio_coding/main/acm2/initial_delay_manager.h
@@ -0,0 +1,115 @@
+/*
+ *  Copyright (c) 2013 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_MAIN_SOURCE_INITIAL_DELAY_MANAGER_H_
+#define WEBRTC_MODULES_AUDIO_CODING_MAIN_SOURCE_INITIAL_DELAY_MANAGER_H_
+
+#include "webrtc/modules/interface/module_common_types.h"
+#include "webrtc/system_wrappers/interface/scoped_ptr.h"
+
+namespace webrtc {
+
+class InitialDelayManager {
+ public:
+  enum PacketType {
+    kUndefinedPacket, kCngPacket, kAvtPacket, kAudioPacket, kSyncPacket };
+
+  // Specifies a stream of sync-packets.
+  struct SyncStream {
+    SyncStream()
+        : num_sync_packets(0),
+          receive_timestamp(0),
+          timestamp_step(0) {
+      memset(&rtp_info, 0, sizeof(rtp_info));
+    }
+
+    int num_sync_packets;
+
+    // RTP header of the first sync-packet in the sequence.
+    WebRtcRTPHeader rtp_info;
+
+    // Received timestamp of the first sync-packet in the sequence.
+    uint32_t receive_timestamp;
+
+    // Samples per packet.
+    uint32_t timestamp_step;
+  };
+
+  InitialDelayManager(int initial_delay_ms, int late_packet_threshold);
+
+  // Update with the last received RTP header, |header|, and received timestamp,
+  // |received_timestamp|. |type| indicates the packet type. If codec is changed
+  // since the last time |new_codec| should be true. |sample_rate_hz| is the
+  // decoder's sampling rate in Hz. |header| has a field to store sampling rate
+  // but we are not sure if that is properly set at the send side, and |header|
+  // is declared constant in the caller of this function
+  // (AcmReceiver::InsertPacket()). |sync_stream| contains information required
+  // to generate a stream of sync packets.
+  void UpdateLastReceivedPacket(const WebRtcRTPHeader& header,
+                                uint32_t receive_timestamp,
+                                PacketType type,
+                                bool new_codec,
+                                int sample_rate_hz,
+                                SyncStream* sync_stream);
+
+  // Based on the last received timestamp and given the current timestamp,
+  // sequence of late (or perhaps missing) packets is computed.
+  void LatePackets(uint32_t timestamp_now, SyncStream* sync_stream);
+
+  // Playout timestamp, valid when buffering.
+  uint32_t playout_timestamp() { return playout_timestamp_; }
+
+  // True if buffered audio is less than the given initial delay (specified at
+  // the constructor). Buffering might be disabled by the client of this class.
+  bool buffering() { return buffering_; }
+
+  // Disable buffering in the class.
+  void DisableBuffering();
+
+  // True if any packet received for buffering.
+  bool PacketBuffered() { return last_packet_type_ != kUndefinedPacket; }
+
+ private:
+  static const uint8_t kInvalidPayloadType = 0xFF;
+
+  // Update playout timestamps. While buffering, this is about
+  // |initial_delay_ms| millisecond behind the latest received timestamp.
+  void UpdatePlayoutTimestamp(const RTPHeader& current_header,
+                              int sample_rate_hz);
+
+  // Record an RTP headr and related parameter
+  void RecordLastPacket(const WebRtcRTPHeader& rtp_info,
+                        uint32_t receive_timestamp,
+                        PacketType type);
+
+  PacketType last_packet_type_;
+  WebRtcRTPHeader last_packet_rtp_info_;
+  uint32_t last_receive_timestamp_;
+  uint32_t timestamp_step_;
+  uint8_t audio_payload_type_;
+  const int initial_delay_ms_;
+  int buffered_audio_ms_;
+  bool buffering_;
+
+  // During the initial phase where packets are being accumulated and silence
+  // is played out, |playout_ts| is a timestamp which is equal to
+  // |initial_delay_ms_| milliseconds earlier than the most recently received
+  // RTP timestamp.
+  uint32_t playout_timestamp_;
+
+  // If the number of late packets exceed this value (computed based on current
+  // timestamp and last received timestamp), sequence of sync-packets is
+  // specified.
+  const int late_packet_threshold_;
+};
+
+}  // namespace webrtc
+
+#endif  // WEBRTC_MODULES_AUDIO_CODING_MAIN_SOURCE_INITIAL_DELAY_MANAGER_H_
diff --git a/webrtc/modules/audio_coding/main/acm2/initial_delay_manager_unittest.cc b/webrtc/modules/audio_coding/main/acm2/initial_delay_manager_unittest.cc
new file mode 100644
index 0000000..9d96d17
--- /dev/null
+++ b/webrtc/modules/audio_coding/main/acm2/initial_delay_manager_unittest.cc
@@ -0,0 +1,371 @@
+/*
+ *  Copyright (c) 2013 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 <cstring>
+
+#include "gtest/gtest.h"
+#include "webrtc/modules/audio_coding/main/source/initial_delay_manager.h"
+
+namespace webrtc {
+
+namespace {
+
+const uint8_t kAudioPayloadType = 0;
+const uint8_t kCngPayloadType = 1;
+const uint8_t kAvtPayloadType = 2;
+
+const int kSamplingRateHz = 16000;
+const int kInitDelayMs = 200;
+const int kFrameSizeMs = 20;
+const uint32_t kTimestampStep = kFrameSizeMs * kSamplingRateHz / 1000;
+const int kLatePacketThreshold = 5;
+
+void InitRtpInfo(WebRtcRTPHeader* rtp_info) {
+  memset(rtp_info, 0, sizeof(*rtp_info));
+  rtp_info->header.markerBit = false;
+  rtp_info->header.payloadType = kAudioPayloadType;
+  rtp_info->header.sequenceNumber = 1234;
+  rtp_info->header.timestamp = 0xFFFFFFFD;  // Close to wrap around.
+  rtp_info->header.ssrc = 0x87654321;  // Arbitrary.
+  rtp_info->header.numCSRCs = 0;  // Arbitrary.
+  rtp_info->header.paddingLength = 0;
+  rtp_info->header.headerLength = sizeof(RTPHeader);
+  rtp_info->header.payload_type_frequency = kSamplingRateHz;
+  rtp_info->header.extension.absoluteSendTime = 0;
+  rtp_info->header.extension.transmissionTimeOffset = 0;
+  rtp_info->frameType = kAudioFrameSpeech;
+}
+
+void ForwardRtpHeader(int n,
+                      WebRtcRTPHeader* rtp_info,
+                      uint32_t* rtp_receive_timestamp) {
+  rtp_info->header.sequenceNumber += n;
+  rtp_info->header.timestamp += n * kTimestampStep;
+  *rtp_receive_timestamp += n * kTimestampStep;
+}
+
+void NextRtpHeader(WebRtcRTPHeader* rtp_info,
+                   uint32_t* rtp_receive_timestamp) {
+  ForwardRtpHeader(1, rtp_info, rtp_receive_timestamp);
+}
+
+}  // namespace
+
+class InitialDelayManagerTest : public ::testing::Test {
+ protected:
+  InitialDelayManagerTest()
+      : manager_(new InitialDelayManager(kInitDelayMs, kLatePacketThreshold)),
+        rtp_receive_timestamp_(1111) { }  // Arbitrary starting point.
+
+  virtual void SetUp() {
+    ASSERT_TRUE(manager_.get() != NULL);
+    InitRtpInfo(&rtp_info_);
+  }
+
+  void GetNextRtpHeader(WebRtcRTPHeader* rtp_info,
+                        uint32_t* rtp_receive_timestamp) const {
+    memcpy(rtp_info, &rtp_info_, sizeof(*rtp_info));
+    *rtp_receive_timestamp = rtp_receive_timestamp_;
+    NextRtpHeader(rtp_info, rtp_receive_timestamp);
+  }
+
+  scoped_ptr<InitialDelayManager> manager_;
+  WebRtcRTPHeader rtp_info_;
+  uint32_t rtp_receive_timestamp_;
+};
+
+TEST_F(InitialDelayManagerTest, Init) {
+  EXPECT_TRUE(manager_->buffering());
+  EXPECT_FALSE(manager_->PacketBuffered());
+  manager_->DisableBuffering();
+  EXPECT_FALSE(manager_->buffering());
+  InitialDelayManager::SyncStream sync_stream;
+
+  // Call before any packet inserted.
+  manager_->LatePackets(0x6789ABCD, &sync_stream);  // Arbitrary but large
+                                                    // receive timestamp.
+  EXPECT_EQ(0, sync_stream.num_sync_packets);
+
+  // Insert non-audio packets, a CNG and DTMF.
+  rtp_info_.header.payloadType = kCngPayloadType;
+  manager_->UpdateLastReceivedPacket(rtp_info_, rtp_receive_timestamp_,
+                                     InitialDelayManager::kCngPacket, false,
+                                     kSamplingRateHz, &sync_stream);
+  EXPECT_EQ(0, sync_stream.num_sync_packets);
+  ForwardRtpHeader(5, &rtp_info_, &rtp_receive_timestamp_);
+  rtp_info_.header.payloadType = kAvtPayloadType;
+  manager_->UpdateLastReceivedPacket(rtp_info_, rtp_receive_timestamp_,
+                                     InitialDelayManager::kAvtPacket, false,
+                                     kSamplingRateHz, &sync_stream);
+  // Gap in sequence numbers but no audio received, sync-stream should be empty.
+  EXPECT_EQ(0, sync_stream.num_sync_packets);
+  manager_->LatePackets(0x45678987, &sync_stream);  // Large arbitrary receive
+                                                    // timestamp.
+  // |manager_| has no estimate of timestamp-step and has not received any
+  // audio packet.
+  EXPECT_EQ(0, sync_stream.num_sync_packets);
+
+
+  NextRtpHeader(&rtp_info_, &rtp_receive_timestamp_);
+  rtp_info_.header.payloadType = kAudioPayloadType;
+  // First packet.
+  manager_->UpdateLastReceivedPacket(rtp_info_, rtp_receive_timestamp_,
+                                     InitialDelayManager::kAudioPacket, true,
+                                     kSamplingRateHz, &sync_stream);
+  EXPECT_EQ(0, sync_stream.num_sync_packets);
+
+  // Call LatePAcket() after only one packet inserted.
+  manager_->LatePackets(0x6789ABCD, &sync_stream);  // Arbitrary but large
+                                                    // receive timestamp.
+  EXPECT_EQ(0, sync_stream.num_sync_packets);
+
+  // Gap in timestamp, but this packet is also flagged as "new," therefore,
+  // expecting empty sync-stream.
+  ForwardRtpHeader(5, &rtp_info_, &rtp_receive_timestamp_);
+  manager_->UpdateLastReceivedPacket(rtp_info_, rtp_receive_timestamp_,
+                                     InitialDelayManager::kAudioPacket, true,
+                                     kSamplingRateHz, &sync_stream);
+}
+
+TEST_F(InitialDelayManagerTest, MissingPacket) {
+  InitialDelayManager::SyncStream sync_stream;
+  // First packet.
+  manager_->UpdateLastReceivedPacket(rtp_info_, rtp_receive_timestamp_,
+                                     InitialDelayManager::kAudioPacket, true,
+                                     kSamplingRateHz, &sync_stream);
+  ASSERT_EQ(0, sync_stream.num_sync_packets);
+
+  // Second packet.
+  NextRtpHeader(&rtp_info_, &rtp_receive_timestamp_);
+  manager_->UpdateLastReceivedPacket(rtp_info_, rtp_receive_timestamp_,
+                                     InitialDelayManager::kAudioPacket, false,
+                                     kSamplingRateHz, &sync_stream);
+  ASSERT_EQ(0, sync_stream.num_sync_packets);
+
+  // Third packet, missing packets start from here.
+  NextRtpHeader(&rtp_info_, &rtp_receive_timestamp_);
+
+  // First sync-packet in sync-stream is one after the above packet.
+  WebRtcRTPHeader expected_rtp_info;
+  uint32_t expected_receive_timestamp;
+  GetNextRtpHeader(&expected_rtp_info, &expected_receive_timestamp);
+
+  const int kNumMissingPackets = 10;
+  ForwardRtpHeader(kNumMissingPackets, &rtp_info_, &rtp_receive_timestamp_);
+  manager_->UpdateLastReceivedPacket(rtp_info_, rtp_receive_timestamp_,
+                                     InitialDelayManager::kAudioPacket, false,
+                                     kSamplingRateHz, &sync_stream);
+  EXPECT_EQ(kNumMissingPackets - 2, sync_stream.num_sync_packets);
+  EXPECT_EQ(0, memcmp(&expected_rtp_info, &sync_stream.rtp_info,
+                      sizeof(expected_rtp_info)));
+  EXPECT_EQ(kTimestampStep, sync_stream.timestamp_step);
+  EXPECT_EQ(expected_receive_timestamp, sync_stream.receive_timestamp);
+}
+
+// There hasn't been any consecutive packets to estimate timestamp-step.
+TEST_F(InitialDelayManagerTest, MissingPacketEstimateTimestamp) {
+  InitialDelayManager::SyncStream sync_stream;
+  // First packet.
+  manager_->UpdateLastReceivedPacket(rtp_info_, rtp_receive_timestamp_,
+                                     InitialDelayManager::kAudioPacket, true,
+                                     kSamplingRateHz, &sync_stream);
+  ASSERT_EQ(0, sync_stream.num_sync_packets);
+
+  // Second packet, missing packets start here.
+  NextRtpHeader(&rtp_info_, &rtp_receive_timestamp_);
+
+  // First sync-packet in sync-stream is one after the above.
+  WebRtcRTPHeader expected_rtp_info;
+  uint32_t expected_receive_timestamp;
+  GetNextRtpHeader(&expected_rtp_info, &expected_receive_timestamp);
+
+  const int kNumMissingPackets = 10;
+  ForwardRtpHeader(kNumMissingPackets, &rtp_info_, &rtp_receive_timestamp_);
+  manager_->UpdateLastReceivedPacket(rtp_info_, rtp_receive_timestamp_,
+                                     InitialDelayManager::kAudioPacket, false,
+                                     kSamplingRateHz, &sync_stream);
+  EXPECT_EQ(kNumMissingPackets - 2, sync_stream.num_sync_packets);
+  EXPECT_EQ(0, memcmp(&expected_rtp_info, &sync_stream.rtp_info,
+                      sizeof(expected_rtp_info)));
+}
+
+TEST_F(InitialDelayManagerTest, MissingPacketWithCng) {
+  InitialDelayManager::SyncStream sync_stream;
+
+  // First packet.
+  manager_->UpdateLastReceivedPacket(rtp_info_, rtp_receive_timestamp_,
+                                     InitialDelayManager::kAudioPacket, true,
+                                     kSamplingRateHz, &sync_stream);
+  ASSERT_EQ(0, sync_stream.num_sync_packets);
+
+  // Second packet as CNG.
+  NextRtpHeader(&rtp_info_, &rtp_receive_timestamp_);
+  rtp_info_.header.payloadType = kCngPayloadType;
+  manager_->UpdateLastReceivedPacket(rtp_info_, rtp_receive_timestamp_,
+                                     InitialDelayManager::kCngPacket, false,
+                                     kSamplingRateHz, &sync_stream);
+  ASSERT_EQ(0, sync_stream.num_sync_packets);
+
+  // Audio packet after CNG. Missing packets start from this packet.
+  rtp_info_.header.payloadType = kAudioPayloadType;
+  NextRtpHeader(&rtp_info_, &rtp_receive_timestamp_);
+
+  // Timestamps are increased higher than regular packet.
+  const uint32_t kCngTimestampStep = 5 * kTimestampStep;
+  rtp_info_.header.timestamp += kCngTimestampStep;
+  rtp_receive_timestamp_ += kCngTimestampStep;
+
+  // First sync-packet in sync-stream is the one after the above packet.
+  WebRtcRTPHeader expected_rtp_info;
+  uint32_t expected_receive_timestamp;
+  GetNextRtpHeader(&expected_rtp_info, &expected_receive_timestamp);
+
+  const int kNumMissingPackets = 10;
+  ForwardRtpHeader(kNumMissingPackets, &rtp_info_, &rtp_receive_timestamp_);
+  manager_->UpdateLastReceivedPacket(rtp_info_, rtp_receive_timestamp_,
+                                     InitialDelayManager::kAudioPacket, false,
+                                     kSamplingRateHz, &sync_stream);
+  EXPECT_EQ(kNumMissingPackets - 2, sync_stream.num_sync_packets);
+  EXPECT_EQ(0, memcmp(&expected_rtp_info, &sync_stream.rtp_info,
+                      sizeof(expected_rtp_info)));
+  EXPECT_EQ(kTimestampStep, sync_stream.timestamp_step);
+  EXPECT_EQ(expected_receive_timestamp, sync_stream.receive_timestamp);
+}
+
+TEST_F(InitialDelayManagerTest, LatePacket) {
+  InitialDelayManager::SyncStream sync_stream;
+  // First packet.
+  manager_->UpdateLastReceivedPacket(rtp_info_, rtp_receive_timestamp_,
+                                     InitialDelayManager::kAudioPacket, true,
+                                     kSamplingRateHz, &sync_stream);
+  ASSERT_EQ(0, sync_stream.num_sync_packets);
+
+  // Second packet.
+  NextRtpHeader(&rtp_info_, &rtp_receive_timestamp_);
+  manager_->UpdateLastReceivedPacket(rtp_info_, rtp_receive_timestamp_,
+                                     InitialDelayManager::kAudioPacket, false,
+                                     kSamplingRateHz, &sync_stream);
+  ASSERT_EQ(0, sync_stream.num_sync_packets);
+
+  // Timestamp increment for 10ms;
+  const uint32_t kTimestampStep10Ms = kSamplingRateHz / 100;
+
+  // 10 ms after the second packet is inserted.
+  uint32_t timestamp_now = rtp_receive_timestamp_ + kTimestampStep10Ms;
+
+  // Third packet, late packets start from this packet.
+  NextRtpHeader(&rtp_info_, &rtp_receive_timestamp_);
+
+  // First sync-packet in sync-stream, which is one after the above packet.
+  WebRtcRTPHeader expected_rtp_info;
+  uint32_t expected_receive_timestamp;
+  GetNextRtpHeader(&expected_rtp_info, &expected_receive_timestamp);
+
+  const int kLatePacketThreshold = 5;
+
+  int expected_num_late_packets = kLatePacketThreshold - 1;
+  for (int k = 0; k < 2; ++k) {
+    for (int n = 1; n < kLatePacketThreshold * kFrameSizeMs / 10; ++n) {
+      manager_->LatePackets(timestamp_now, &sync_stream);
+      EXPECT_EQ(0, sync_stream.num_sync_packets) <<
+          "try " << k << " loop number " << n;
+      timestamp_now += kTimestampStep10Ms;
+    }
+    manager_->LatePackets(timestamp_now, &sync_stream);
+
+    EXPECT_EQ(expected_num_late_packets, sync_stream.num_sync_packets) <<
+        "try " << k;
+    EXPECT_EQ(kTimestampStep, sync_stream.timestamp_step) <<
+        "try " << k;
+    EXPECT_EQ(expected_receive_timestamp, sync_stream.receive_timestamp) <<
+        "try " << k;
+    EXPECT_EQ(0, memcmp(&expected_rtp_info, &sync_stream.rtp_info,
+                        sizeof(expected_rtp_info)));
+
+    timestamp_now += kTimestampStep10Ms;
+
+    // |manger_| assumes the |sync_stream| obtained by LatePacket() is fully
+    // injected. The last injected packet is sync-packet, therefore, there will
+    // not be any gap between sync stream of this and the next iteration.
+    ForwardRtpHeader(sync_stream.num_sync_packets, &expected_rtp_info,
+        &expected_receive_timestamp);
+    expected_num_late_packets = kLatePacketThreshold;
+  }
+
+  // Test "no-gap" for missing packet after late packet.
+  // |expected_rtp_info| is the expected sync-packet if any packet is missing.
+  memcpy(&rtp_info_, &expected_rtp_info, sizeof(rtp_info_));
+  rtp_receive_timestamp_ = expected_receive_timestamp;
+
+  int kNumMissingPackets = 3;  // Arbitrary.
+  ForwardRtpHeader(kNumMissingPackets, &rtp_info_, &rtp_receive_timestamp_);
+  manager_->UpdateLastReceivedPacket(rtp_info_, rtp_receive_timestamp_,
+                                     InitialDelayManager::kAudioPacket, false,
+                                     kSamplingRateHz, &sync_stream);
+
+  // Note that there is one packet gap between the last sync-packet and the
+  // latest inserted packet.
+  EXPECT_EQ(kNumMissingPackets - 1, sync_stream.num_sync_packets);
+  EXPECT_EQ(kTimestampStep, sync_stream.timestamp_step);
+  EXPECT_EQ(expected_receive_timestamp, sync_stream.receive_timestamp);
+  EXPECT_EQ(0, memcmp(&expected_rtp_info, &sync_stream.rtp_info,
+                      sizeof(expected_rtp_info)));
+}
+
+TEST_F(InitialDelayManagerTest, NoLatePacketAfterCng) {
+  InitialDelayManager::SyncStream sync_stream;
+
+  // First packet.
+  manager_->UpdateLastReceivedPacket(rtp_info_, rtp_receive_timestamp_,
+                                     InitialDelayManager::kAudioPacket, true,
+                                     kSamplingRateHz, &sync_stream);
+  ASSERT_EQ(0, sync_stream.num_sync_packets);
+
+  // Second packet as CNG.
+  NextRtpHeader(&rtp_info_, &rtp_receive_timestamp_);
+  const uint8_t kCngPayloadType = 1;  // Arbitrary.
+  rtp_info_.header.payloadType = kCngPayloadType;
+  manager_->UpdateLastReceivedPacket(rtp_info_, rtp_receive_timestamp_,
+                                     InitialDelayManager::kCngPacket, false,
+                                     kSamplingRateHz, &sync_stream);
+  ASSERT_EQ(0, sync_stream.num_sync_packets);
+
+  // Forward the time more then |kLatePacketThreshold| packets.
+  uint32_t timestamp_now = rtp_receive_timestamp_ + kTimestampStep * (3 +
+      kLatePacketThreshold);
+
+  manager_->LatePackets(timestamp_now, &sync_stream);
+  EXPECT_EQ(0, sync_stream.num_sync_packets);
+}
+
+TEST_F(InitialDelayManagerTest, BufferingAudio) {
+  InitialDelayManager::SyncStream sync_stream;
+
+  // Very first packet is not counted in calculation of buffered audio.
+  for (int n = 0; n < kInitDelayMs / kFrameSizeMs; ++n) {
+    manager_->UpdateLastReceivedPacket(rtp_info_, rtp_receive_timestamp_,
+                                       InitialDelayManager::kAudioPacket,
+                                       n == 0, kSamplingRateHz, &sync_stream);
+    EXPECT_EQ(0, sync_stream.num_sync_packets);
+    EXPECT_TRUE(manager_->buffering());
+    const uint32_t expected_playout_timestamp = rtp_info_.header.timestamp -
+        kInitDelayMs * kSamplingRateHz / 1000;
+    EXPECT_EQ(expected_playout_timestamp, manager_->playout_timestamp());
+    NextRtpHeader(&rtp_info_, &rtp_receive_timestamp_);
+  }
+
+  manager_->UpdateLastReceivedPacket(rtp_info_, rtp_receive_timestamp_,
+                                     InitialDelayManager::kAudioPacket,
+                                     false, kSamplingRateHz, &sync_stream);
+  EXPECT_EQ(0, sync_stream.num_sync_packets);
+  EXPECT_FALSE(manager_->buffering());
+}
+
+}  // namespace webrtc
diff --git a/webrtc/modules/audio_coding/main/acm2/nack.cc b/webrtc/modules/audio_coding/main/acm2/nack.cc
new file mode 100644
index 0000000..d4d0c3b
--- /dev/null
+++ b/webrtc/modules/audio_coding/main/acm2/nack.cc
@@ -0,0 +1,225 @@
+/*
+ *  Copyright (c) 2013 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 "webrtc/modules/audio_coding/main/source/nack.h"
+
+#include <assert.h>  // For assert.
+
+#include <algorithm>  // For std::max.
+
+#include "webrtc/modules/interface/module_common_types.h"
+#include "webrtc/system_wrappers/interface/logging.h"
+
+namespace webrtc {
+
+namespace {
+
+const int kDefaultSampleRateKhz = 48;
+const int kDefaultPacketSizeMs = 20;
+
+}  // namespace
+
+Nack::Nack(int nack_threshold_packets)
+    : nack_threshold_packets_(nack_threshold_packets),
+      sequence_num_last_received_rtp_(0),
+      timestamp_last_received_rtp_(0),
+      any_rtp_received_(false),
+      sequence_num_last_decoded_rtp_(0),
+      timestamp_last_decoded_rtp_(0),
+      any_rtp_decoded_(false),
+      sample_rate_khz_(kDefaultSampleRateKhz),
+      samples_per_packet_(sample_rate_khz_ * kDefaultPacketSizeMs),
+      max_nack_list_size_(kNackListSizeLimit) {}
+
+Nack* Nack::Create(int nack_threshold_packets) {
+  return new Nack(nack_threshold_packets);
+}
+
+void Nack::UpdateSampleRate(int sample_rate_hz) {
+  assert(sample_rate_hz > 0);
+  sample_rate_khz_ = sample_rate_hz / 1000;
+}
+
+void Nack::UpdateLastReceivedPacket(uint16_t sequence_number,
+                                    uint32_t timestamp) {
+  // Just record the value of sequence number and timestamp if this is the
+  // first packet.
+  if (!any_rtp_received_) {
+    sequence_num_last_received_rtp_ = sequence_number;
+    timestamp_last_received_rtp_ = timestamp;
+    any_rtp_received_ = true;
+    // If no packet is decoded, to have a reasonable estimate of time-to-play
+    // use the given values.
+    if (!any_rtp_decoded_) {
+      sequence_num_last_decoded_rtp_ = sequence_number;
+      timestamp_last_decoded_rtp_ = timestamp;
+    }
+    return;
+  }
+
+  if (sequence_number == sequence_num_last_received_rtp_)
+    return;
+
+  // Received RTP should not be in the list.
+  nack_list_.erase(sequence_number);
+
+  // If this is an old sequence number, no more action is required, return.
+  if (IsNewerSequenceNumber(sequence_num_last_received_rtp_, sequence_number))
+    return;
+
+  UpdateSamplesPerPacket(sequence_number, timestamp);
+
+  UpdateList(sequence_number);
+
+  sequence_num_last_received_rtp_ = sequence_number;
+  timestamp_last_received_rtp_ = timestamp;
+  LimitNackListSize();
+}
+
+void Nack::UpdateSamplesPerPacket(uint16_t sequence_number_current_received_rtp,
+                                  uint32_t timestamp_current_received_rtp) {
+  uint32_t timestamp_increase = timestamp_current_received_rtp -
+      timestamp_last_received_rtp_;
+  uint16_t sequence_num_increase = sequence_number_current_received_rtp -
+      sequence_num_last_received_rtp_;
+
+  samples_per_packet_ = timestamp_increase / sequence_num_increase;
+}
+
+void Nack::UpdateList(uint16_t sequence_number_current_received_rtp) {
+  // Some of the packets which were considered late, now are considered missing.
+  ChangeFromLateToMissing(sequence_number_current_received_rtp);
+
+  if (IsNewerSequenceNumber(sequence_number_current_received_rtp,
+                            sequence_num_last_received_rtp_ + 1))
+    AddToList(sequence_number_current_received_rtp);
+}
+
+void Nack::ChangeFromLateToMissing(
+    uint16_t sequence_number_current_received_rtp) {
+  NackList::const_iterator lower_bound = nack_list_.lower_bound(
+      static_cast<uint16_t>(sequence_number_current_received_rtp -
+                            nack_threshold_packets_));
+
+  for (NackList::iterator it = nack_list_.begin(); it != lower_bound; ++it)
+    it->second.is_missing = true;
+}
+
+uint32_t Nack::EstimateTimestamp(uint16_t sequence_num) {
+  uint16_t sequence_num_diff = sequence_num - sequence_num_last_received_rtp_;
+  return sequence_num_diff * samples_per_packet_ + timestamp_last_received_rtp_;
+}
+
+void Nack::AddToList(uint16_t sequence_number_current_received_rtp) {
+  assert(!any_rtp_decoded_ || IsNewerSequenceNumber(
+      sequence_number_current_received_rtp, sequence_num_last_decoded_rtp_));
+
+  // Packets with sequence numbers older than |upper_bound_missing| are
+  // considered missing, and the rest are considered late.
+  uint16_t upper_bound_missing = sequence_number_current_received_rtp -
+      nack_threshold_packets_;
+
+  for (uint16_t n = sequence_num_last_received_rtp_ + 1;
+      IsNewerSequenceNumber(sequence_number_current_received_rtp, n); ++n) {
+    bool is_missing = IsNewerSequenceNumber(upper_bound_missing, n);
+    uint32_t timestamp = EstimateTimestamp(n);
+    NackElement nack_element(TimeToPlay(timestamp), timestamp, is_missing);
+    nack_list_.insert(nack_list_.end(), std::make_pair(n, nack_element));
+  }
+}
+
+void Nack::UpdateEstimatedPlayoutTimeBy10ms() {
+  while (!nack_list_.empty() &&
+      nack_list_.begin()->second.time_to_play_ms <= 10)
+    nack_list_.erase(nack_list_.begin());
+
+  for (NackList::iterator it = nack_list_.begin(); it != nack_list_.end(); ++it)
+    it->second.time_to_play_ms -= 10;
+}
+
+void Nack::UpdateLastDecodedPacket(uint16_t sequence_number,
+                                   uint32_t timestamp) {
+  if (IsNewerSequenceNumber(sequence_number, sequence_num_last_decoded_rtp_) ||
+      !any_rtp_decoded_) {
+    sequence_num_last_decoded_rtp_ = sequence_number;
+    timestamp_last_decoded_rtp_ = timestamp;
+    // Packets in the list with sequence numbers less than the
+    // sequence number of the decoded RTP should be removed from the lists.
+    // They will be discarded by the jitter buffer if they arrive.
+    nack_list_.erase(nack_list_.begin(), nack_list_.upper_bound(
+        sequence_num_last_decoded_rtp_));
+
+    // Update estimated time-to-play.
+    for (NackList::iterator it = nack_list_.begin(); it != nack_list_.end();
+        ++it)
+      it->second.time_to_play_ms = TimeToPlay(it->second.estimated_timestamp);
+  } else {
+    assert(sequence_number == sequence_num_last_decoded_rtp_);
+
+    // Same sequence number as before. 10 ms is elapsed, update estimations for
+    // time-to-play.
+    UpdateEstimatedPlayoutTimeBy10ms();
+
+    // Update timestamp for better estimate of time-to-play, for packets which
+    // are added to NACK list later on.
+    timestamp_last_decoded_rtp_ += sample_rate_khz_ * 10;
+  }
+  any_rtp_decoded_ = true;
+}
+
+Nack::NackList Nack::GetNackList() const {
+  return nack_list_;
+}
+
+void Nack::Reset() {
+  nack_list_.clear();
+
+  sequence_num_last_received_rtp_ = 0;
+  timestamp_last_received_rtp_ = 0;
+  any_rtp_received_ = false;
+  sequence_num_last_decoded_rtp_ = 0;
+  timestamp_last_decoded_rtp_ = 0;
+  any_rtp_decoded_ = false;
+  sample_rate_khz_ = kDefaultSampleRateKhz;
+  samples_per_packet_ = sample_rate_khz_ * kDefaultPacketSizeMs;
+}
+
+int Nack::SetMaxNackListSize(size_t max_nack_list_size) {
+  if (max_nack_list_size == 0 || max_nack_list_size > kNackListSizeLimit)
+    return -1;
+  max_nack_list_size_ = max_nack_list_size;
+  LimitNackListSize();
+  return 0;
+}
+
+void Nack::LimitNackListSize() {
+  uint16_t limit = sequence_num_last_received_rtp_ -
+      static_cast<uint16_t>(max_nack_list_size_) - 1;
+  nack_list_.erase(nack_list_.begin(), nack_list_.upper_bound(limit));
+}
+
+int Nack::TimeToPlay(uint32_t timestamp) const {
+  uint32_t timestamp_increase = timestamp - timestamp_last_decoded_rtp_;
+  return timestamp_increase / sample_rate_khz_;
+}
+
+// We don't erase elements with time-to-play shorter than round-trip-time.
+std::vector<uint16_t> Nack::GetNackList(int round_trip_time_ms) const {
+  std::vector<uint16_t> sequence_numbers;
+  for (NackList::const_iterator it = nack_list_.begin(); it != nack_list_.end();
+      ++it) {
+    if (it->second.is_missing &&
+        it->second.time_to_play_ms > round_trip_time_ms)
+      sequence_numbers.push_back(it->first);
+  }
+  return sequence_numbers;
+}
+
+}  // namespace webrtc
diff --git a/webrtc/modules/audio_coding/main/acm2/nack.h b/webrtc/modules/audio_coding/main/acm2/nack.h
new file mode 100644
index 0000000..ddafbcd
--- /dev/null
+++ b/webrtc/modules/audio_coding/main/acm2/nack.h
@@ -0,0 +1,209 @@
+/*
+ *  Copyright (c) 2013 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_MAIN_SOURCE_NACK_H_
+#define WEBRTC_MODULES_AUDIO_CODING_MAIN_SOURCE_NACK_H_
+
+#include <vector>
+#include <map>
+
+#include "webrtc/modules/audio_coding/main/interface/audio_coding_module_typedefs.h"
+#include "webrtc/system_wrappers/interface/scoped_ptr.h"
+#include "webrtc/test/testsupport/gtest_prod_util.h"
+
+//
+// The Nack class keeps track of the lost packets, an estimate of time-to-play
+// for each packet is also given.
+//
+// Every time a packet is pushed into NetEq, LastReceivedPacket() has to be
+// called to update the NACK list.
+//
+// Every time 10ms audio is pulled from NetEq LastDecodedPacket() should be
+// called, and time-to-play is updated at that moment.
+//
+// If packet N is received, any packet prior to |N - NackThreshold| which is not
+// arrived is considered lost, and should be labeled as "missing" (the size of
+// the list might be limited and older packet eliminated from the list). Packets
+// |N - NackThreshold|, |N - NackThreshold + 1|, ..., |N - 1| are considered
+// "late." A "late" packet with sequence number K is changed to "missing" any
+// time a packet with sequence number newer than |K + NackList| is arrived.
+//
+// The Nack class has to know about the sample rate of the packets to compute
+// time-to-play. So sample rate should be set as soon as the first packet is
+// received. If there is a change in the receive codec (sender changes codec)
+// then Nack should be reset. This is because NetEQ would flush its buffer and
+// re-transmission is meaning less for old packet. Therefore, in that case,
+// after reset the sampling rate has to be updated.
+//
+// Thread Safety
+// =============
+// Please note that this class in not thread safe. The class must be protected
+// if different APIs are called from different threads.
+//
+namespace webrtc {
+
+class Nack {
+ public:
+  // A limit for the size of the NACK list.
+  static const size_t kNackListSizeLimit = 500;  // 10 seconds for 20 ms frame
+                                                 // packets.
+  // Factory method.
+  static Nack* Create(int nack_threshold_packets);
+
+  ~Nack() {}
+
+  // Set a maximum for the size of the NACK list. If the last received packet
+  // has sequence number of N, then NACK list will not contain any element
+  // with sequence number earlier than N - |max_nack_list_size|.
+  //
+  // The largest maximum size is defined by |kNackListSizeLimit|
+  int SetMaxNackListSize(size_t max_nack_list_size);
+
+  // Set the sampling rate.
+  //
+  // If associated sampling rate of the received packets is changed, call this
+  // function to update sampling rate. Note that if there is any change in
+  // received codec then NetEq will flush its buffer and NACK has to be reset.
+  // After Reset() is called sampling rate has to be set.
+  void UpdateSampleRate(int sample_rate_hz);
+
+  // Update the sequence number and the timestamp of the last decoded RTP. This
+  // API should be called every time 10 ms audio is pulled from NetEq.
+  void UpdateLastDecodedPacket(uint16_t sequence_number, uint32_t timestamp);
+
+  // Update the sequence number and the timestamp of the last received RTP. This
+  // API should be called every time a packet pushed into ACM.
+  void UpdateLastReceivedPacket(uint16_t sequence_number, uint32_t timestamp);
+
+  // Get a list of "missing" packets which have expected time-to-play larger
+  // than the given round-trip-time (in milliseconds).
+  // Note: Late packets are not included.
+  std::vector<uint16_t> GetNackList(int round_trip_time_ms) const;
+
+  // Reset to default values. The NACK list is cleared.
+  // |nack_threshold_packets_| & |max_nack_list_size_| preserve their values.
+  void Reset();
+
+ private:
+  // This test need to access the private method GetNackList().
+  FRIEND_TEST_ALL_PREFIXES(NackTest, EstimateTimestampAndTimeToPlay);
+
+  struct NackElement {
+    NackElement(int initial_time_to_play_ms,
+                uint32_t initial_timestamp,
+                bool missing)
+        : time_to_play_ms(initial_time_to_play_ms),
+          estimated_timestamp(initial_timestamp),
+          is_missing(missing) {}
+
+    // Estimated time (ms) left for this packet to be decoded. This estimate is
+    // updated every time jitter buffer decodes a packet.
+    int time_to_play_ms;
+
+    // A guess about the timestamp of the missing packet, it is used for
+    // estimation of |time_to_play_ms|. The estimate might be slightly wrong if
+    // there has been frame-size change since the last received packet and the
+    // missing packet. However, the risk of this is low, and in case of such
+    // errors, there will be a minor misestimation in time-to-play of missing
+    // packets. This will have a very minor effect on NACK performance.
+    uint32_t estimated_timestamp;
+
+    // True if the packet is considered missing. Otherwise indicates packet is
+    // late.
+    bool is_missing;
+  };
+
+  class NackListCompare {
+   public:
+    bool operator() (uint16_t sequence_number_old,
+                     uint16_t sequence_number_new) const {
+      return IsNewerSequenceNumber(sequence_number_new, sequence_number_old);
+    }
+  };
+
+  typedef std::map<uint16_t, NackElement, NackListCompare> NackList;
+
+  // Constructor.
+  explicit Nack(int nack_threshold_packets);
+
+  // This API is used only for testing to assess whether time-to-play is
+  // computed correctly.
+  NackList GetNackList() const;
+
+  // Given the |sequence_number_current_received_rtp| of currently received RTP,
+  // recognize packets which are not arrive and add to the list.
+  void AddToList(uint16_t sequence_number_current_received_rtp);
+
+  // This function subtracts 10 ms of time-to-play for all packets in NACK list.
+  // This is called when 10 ms elapsed with no new RTP packet decoded.
+  void UpdateEstimatedPlayoutTimeBy10ms();
+
+  // Given the |sequence_number_current_received_rtp| and
+  // |timestamp_current_received_rtp| of currently received RTP update number
+  // of samples per packet.
+  void UpdateSamplesPerPacket(uint16_t sequence_number_current_received_rtp,
+                              uint32_t timestamp_current_received_rtp);
+
+  // Given the |sequence_number_current_received_rtp| of currently received RTP
+  // update the list. That is; some packets will change from late to missing,
+  // some packets are inserted as missing and some inserted as late.
+  void UpdateList(uint16_t sequence_number_current_received_rtp);
+
+  // Packets which are considered late for too long (according to
+  // |nack_threshold_packets_|) are flagged as missing.
+  void ChangeFromLateToMissing(uint16_t sequence_number_current_received_rtp);
+
+  // Packets which have sequence number older that
+  // |sequence_num_last_received_rtp_| - |max_nack_list_size_| are removed
+  // from the NACK list.
+  void LimitNackListSize();
+
+  // Estimate timestamp of a missing packet given its sequence number.
+  uint32_t EstimateTimestamp(uint16_t sequence_number);
+
+  // Compute time-to-play given a timestamp.
+  int TimeToPlay(uint32_t timestamp) const;
+
+  // If packet N is arrived, any packet prior to N - |nack_threshold_packets_|
+  // which is not arrived is considered missing, and should be in NACK list.
+  // Also any packet in the range of N-1 and N - |nack_threshold_packets_|,
+  // exclusive, which is not arrived is considered late, and should should be
+  // in the list of late packets.
+  const int nack_threshold_packets_;
+
+  // Valid if a packet is received.
+  uint16_t sequence_num_last_received_rtp_;
+  uint32_t timestamp_last_received_rtp_;
+  bool any_rtp_received_;  // If any packet received.
+
+  // Valid if a packet is decoded.
+  uint16_t sequence_num_last_decoded_rtp_;
+  uint32_t timestamp_last_decoded_rtp_;
+  bool any_rtp_decoded_;  // If any packet decoded.
+
+  int sample_rate_khz_;  // Sample rate in kHz.
+
+  // Number of samples per packet. We update this every time we receive a
+  // packet, not only for consecutive packets.
+  int samples_per_packet_;
+
+  // A list of missing packets to be retransmitted. Components of the list
+  // contain the sequence number of missing packets and the estimated time that
+  // each pack is going to be played out.
+  NackList nack_list_;
+
+  // NACK list will not keep track of missing packets prior to
+  // |sequence_num_last_received_rtp_| - |max_nack_list_size_|.
+  size_t max_nack_list_size_;
+};
+
+}  // namespace webrtc
+
+#endif  // WEBRTC_MODULES_AUDIO_CODING_MAIN_SOURCE_NACK_H_
diff --git a/webrtc/modules/audio_coding/main/acm2/nack_unittest.cc b/webrtc/modules/audio_coding/main/acm2/nack_unittest.cc
new file mode 100644
index 0000000..b84211d
--- /dev/null
+++ b/webrtc/modules/audio_coding/main/acm2/nack_unittest.cc
@@ -0,0 +1,482 @@
+/*
+ *  Copyright (c) 2013 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 "webrtc/modules/audio_coding/main/source/nack.h"
+
+#include <stdint.h>
+
+#include <algorithm>
+
+#include "gtest/gtest.h"
+#include "webrtc/typedefs.h"
+#include "webrtc/modules/audio_coding/main/interface/audio_coding_module_typedefs.h"
+#include "webrtc/system_wrappers/interface/scoped_ptr.h"
+
+namespace webrtc {
+
+namespace {
+
+const int kNackThreshold = 3;
+const int kSampleRateHz = 16000;
+const int kPacketSizeMs = 30;
+const uint32_t kTimestampIncrement = 480;  // 30 ms.
+const int kShortRoundTripTimeMs = 1;
+
+bool IsNackListCorrect(const std::vector<uint16_t>& nack_list,
+                       const uint16_t* lost_sequence_numbers,
+                       size_t num_lost_packets) {
+  if (nack_list.size() != num_lost_packets)
+    return false;
+
+  if (num_lost_packets == 0)
+    return true;
+
+  for (size_t k = 0; k < nack_list.size(); ++k) {
+    int seq_num = nack_list[k];
+    bool seq_num_matched = false;
+    for (size_t n = 0; n < num_lost_packets; ++n) {
+      if (seq_num == lost_sequence_numbers[n]) {
+        seq_num_matched = true;
+        break;
+      }
+    }
+    if (!seq_num_matched)
+      return false;
+  }
+  return true;
+}
+
+}  // namespace
+
+TEST(NackTest, EmptyListWhenNoPacketLoss) {
+  scoped_ptr<Nack> nack(Nack::Create(kNackThreshold));
+  nack->UpdateSampleRate(kSampleRateHz);
+
+  int seq_num = 1;
+  uint32_t timestamp = 0;
+
+  std::vector<uint16_t> nack_list;
+  for (int n = 0; n < 100; n++) {
+    nack->UpdateLastReceivedPacket(seq_num, timestamp);
+    nack_list = nack->GetNackList(kShortRoundTripTimeMs);
+    seq_num++;
+    timestamp += kTimestampIncrement;
+    nack_list = nack->GetNackList(kShortRoundTripTimeMs);
+    EXPECT_TRUE(nack_list.empty());
+  }
+}
+
+TEST(NackTest, NoNackIfReorderWithinNackThreshold) {
+  scoped_ptr<Nack> nack(Nack::Create(kNackThreshold));
+  nack->UpdateSampleRate(kSampleRateHz);
+
+  int seq_num = 1;
+  uint32_t timestamp = 0;
+  std::vector<uint16_t> nack_list;
+
+  nack->UpdateLastReceivedPacket(seq_num, timestamp);
+  nack_list = nack->GetNackList(kShortRoundTripTimeMs);
+  EXPECT_TRUE(nack_list.empty());
+  int num_late_packets = kNackThreshold + 1;
+
+  // Push in reverse order
+  while (num_late_packets > 0) {
+    nack->UpdateLastReceivedPacket(seq_num + num_late_packets, timestamp +
+                            num_late_packets * kTimestampIncrement);
+    nack_list = nack->GetNackList(kShortRoundTripTimeMs);
+    EXPECT_TRUE(nack_list.empty());
+    num_late_packets--;
+  }
+}
+
+TEST(NackTest, LatePacketsMovedToNackThenNackListDoesNotChange) {
+  const uint16_t kSequenceNumberLostPackets[] = { 2, 3, 4, 5, 6, 7, 8, 9 };
+  static const int kNumAllLostPackets = sizeof(kSequenceNumberLostPackets) /
+      sizeof(kSequenceNumberLostPackets[0]);
+
+  for (int k = 0; k < 2; k++) {  // Two iteration with/without wrap around.
+    scoped_ptr<Nack> nack(Nack::Create(kNackThreshold));
+    nack->UpdateSampleRate(kSampleRateHz);
+
+    uint16_t sequence_num_lost_packets[kNumAllLostPackets];
+    for (int n = 0; n < kNumAllLostPackets; n++) {
+      sequence_num_lost_packets[n] = kSequenceNumberLostPackets[n] + k *
+          65531;  // Have wrap around in sequence numbers for |k == 1|.
+    }
+    uint16_t seq_num = sequence_num_lost_packets[0] - 1;
+
+    uint32_t timestamp = 0;
+    std::vector<uint16_t> nack_list;
+
+    nack->UpdateLastReceivedPacket(seq_num, timestamp);
+    nack_list = nack->GetNackList(kShortRoundTripTimeMs);
+    EXPECT_TRUE(nack_list.empty());
+
+    seq_num = sequence_num_lost_packets[kNumAllLostPackets - 1] + 1;
+    timestamp += kTimestampIncrement * (kNumAllLostPackets + 1);
+    int num_lost_packets = std::max(0, kNumAllLostPackets - kNackThreshold);
+
+    for (int n = 0; n < kNackThreshold + 1; ++n) {
+      nack->UpdateLastReceivedPacket(seq_num, timestamp);
+      nack_list = nack->GetNackList(kShortRoundTripTimeMs);
+      EXPECT_TRUE(IsNackListCorrect(nack_list, sequence_num_lost_packets,
+                                    num_lost_packets));
+      seq_num++;
+      timestamp += kTimestampIncrement;
+      num_lost_packets++;
+    }
+
+    for (int n = 0; n < 100; ++n) {
+      nack->UpdateLastReceivedPacket(seq_num, timestamp);
+      nack_list = nack->GetNackList(kShortRoundTripTimeMs);
+      EXPECT_TRUE(IsNackListCorrect(nack_list, sequence_num_lost_packets,
+                                    kNumAllLostPackets));
+      seq_num++;
+      timestamp += kTimestampIncrement;
+    }
+  }
+}
+
+TEST(NackTest, ArrivedPacketsAreRemovedFromNackList) {
+  const uint16_t kSequenceNumberLostPackets[] = { 2, 3, 4, 5, 6, 7, 8, 9 };
+  static const int kNumAllLostPackets = sizeof(kSequenceNumberLostPackets) /
+      sizeof(kSequenceNumberLostPackets[0]);
+
+  for (int k = 0; k < 2; ++k) {  // Two iteration with/without wrap around.
+    scoped_ptr<Nack> nack(Nack::Create(kNackThreshold));
+    nack->UpdateSampleRate(kSampleRateHz);
+
+    uint16_t sequence_num_lost_packets[kNumAllLostPackets];
+    for (int n = 0; n < kNumAllLostPackets; ++n) {
+      sequence_num_lost_packets[n] = kSequenceNumberLostPackets[n] + k *
+          65531;  // Wrap around for |k == 1|.
+    }
+
+    uint16_t seq_num = sequence_num_lost_packets[0] - 1;
+    uint32_t timestamp = 0;
+
+    nack->UpdateLastReceivedPacket(seq_num, timestamp);
+    std::vector<uint16_t> nack_list = nack->GetNackList(kShortRoundTripTimeMs);
+    EXPECT_TRUE(nack_list.empty());
+
+    size_t index_retransmitted_rtp = 0;
+    uint32_t timestamp_retransmitted_rtp = timestamp + kTimestampIncrement;
+
+    seq_num = sequence_num_lost_packets[kNumAllLostPackets - 1] + 1;
+    timestamp += kTimestampIncrement * (kNumAllLostPackets + 1);
+    size_t num_lost_packets = std::max(0, kNumAllLostPackets - kNackThreshold);
+    for (int n = 0; n < kNumAllLostPackets; ++n) {
+      // Number of lost packets does not change for the first
+      // |kNackThreshold + 1| packets, one is added to the list and one is
+      // removed. Thereafter, the list shrinks every iteration.
+      if (n >= kNackThreshold + 1)
+        num_lost_packets--;
+
+      nack->UpdateLastReceivedPacket(seq_num, timestamp);
+      nack_list = nack->GetNackList(kShortRoundTripTimeMs);
+      EXPECT_TRUE(IsNackListCorrect(
+          nack_list, &sequence_num_lost_packets[index_retransmitted_rtp],
+          num_lost_packets));
+      seq_num++;
+      timestamp += kTimestampIncrement;
+
+      // Retransmission of a lost RTP.
+      nack->UpdateLastReceivedPacket(
+          sequence_num_lost_packets[index_retransmitted_rtp],
+          timestamp_retransmitted_rtp);
+      index_retransmitted_rtp++;
+      timestamp_retransmitted_rtp += kTimestampIncrement;
+
+      nack_list = nack->GetNackList(kShortRoundTripTimeMs);
+      EXPECT_TRUE(IsNackListCorrect(
+          nack_list, &sequence_num_lost_packets[index_retransmitted_rtp],
+          num_lost_packets - 1));  // One less lost packet in the list.
+    }
+    ASSERT_TRUE(nack_list.empty());
+  }
+}
+
+// Assess if estimation of timestamps and time-to-play is correct. Introduce all
+// combinations that timestamps and sequence numbers might have wrap around.
+TEST(NackTest, EstimateTimestampAndTimeToPlay) {
+  const uint16_t kLostPackets[] = { 2, 3, 4, 5, 6, 7, 8, 9, 10,
+      11, 12, 13, 14, 15 };
+  static const int kNumAllLostPackets = sizeof(kLostPackets) /
+      sizeof(kLostPackets[0]);
+
+
+  for (int k = 0; k < 4; ++k) {
+    scoped_ptr<Nack> nack(Nack::Create(kNackThreshold));
+    nack->UpdateSampleRate(kSampleRateHz);
+
+    // Sequence number wrap around if |k| is 2 or 3;
+    int seq_num_offset = (k < 2) ? 0 : 65531;
+
+    // Timestamp wrap around if |k| is 1 or 3.
+    uint32_t timestamp_offset = (k & 0x1) ?
+        static_cast<uint32_t>(0xffffffff) - 6 : 0;
+
+    uint32_t timestamp_lost_packets[kNumAllLostPackets];
+    uint16_t seq_num_lost_packets[kNumAllLostPackets];
+    for (int n = 0; n < kNumAllLostPackets; ++n) {
+      timestamp_lost_packets[n] = timestamp_offset + kLostPackets[n] *
+          kTimestampIncrement;
+      seq_num_lost_packets[n] = seq_num_offset + kLostPackets[n];
+    }
+
+    // We and to push two packets before lost burst starts.
+    uint16_t seq_num = seq_num_lost_packets[0] - 2;
+    uint32_t timestamp = timestamp_lost_packets[0] - 2 * kTimestampIncrement;
+
+    const uint16_t first_seq_num = seq_num;
+    const uint32_t first_timestamp = timestamp;
+
+    // Two consecutive packets to have a correct estimate of timestamp increase.
+    nack->UpdateLastReceivedPacket(seq_num, timestamp);
+    seq_num++;
+    timestamp += kTimestampIncrement;
+    nack->UpdateLastReceivedPacket(seq_num, timestamp);
+
+    // A packet after the last one which is supposed to be lost.
+    seq_num = seq_num_lost_packets[kNumAllLostPackets - 1] + 1;
+    timestamp = timestamp_lost_packets[kNumAllLostPackets - 1] +
+        kTimestampIncrement;
+    nack->UpdateLastReceivedPacket(seq_num, timestamp);
+
+    Nack::NackList nack_list = nack->GetNackList();
+    EXPECT_EQ(static_cast<size_t>(kNumAllLostPackets), nack_list.size());
+
+    // Pretend the first packet is decoded.
+    nack->UpdateLastDecodedPacket(first_seq_num, first_timestamp);
+    nack_list = nack->GetNackList();
+
+    Nack::NackList::iterator it = nack_list.begin();
+    while (it != nack_list.end()) {
+      seq_num = it->first - seq_num_offset;
+      int index = seq_num - kLostPackets[0];
+      EXPECT_EQ(timestamp_lost_packets[index], it->second.estimated_timestamp);
+      EXPECT_EQ((index + 2) * kPacketSizeMs, it->second.time_to_play_ms);
+      ++it;
+    }
+
+    // Pretend 10 ms is passed, and we had pulled audio from NetEq, it still
+    // reports the same sequence number as decoded, time-to-play should be
+    // updated by 10 ms.
+    nack->UpdateLastDecodedPacket(first_seq_num, first_timestamp);
+    nack_list = nack->GetNackList();
+    it = nack_list.begin();
+    while (it != nack_list.end()) {
+      seq_num = it->first - seq_num_offset;
+      int index = seq_num - kLostPackets[0];
+      EXPECT_EQ((index + 2) * kPacketSizeMs - 10, it->second.time_to_play_ms);
+      ++it;
+    }
+  }
+}
+
+TEST(NackTest, MissingPacketsPriorToLastDecodedRtpShouldNotBeInNackList) {
+  for (int m = 0; m < 2; ++m) {
+    uint16_t seq_num_offset = (m == 0) ? 0 : 65531;  // Wrap around if |m| is 1.
+    scoped_ptr<Nack> nack(Nack::Create(kNackThreshold));
+    nack->UpdateSampleRate(kSampleRateHz);
+
+    // Two consecutive packets to have a correct estimate of timestamp increase.
+    uint16_t seq_num = 0;
+    nack->UpdateLastReceivedPacket(seq_num_offset + seq_num,
+      seq_num * kTimestampIncrement);
+    seq_num++;
+    nack->UpdateLastReceivedPacket(seq_num_offset + seq_num,
+      seq_num * kTimestampIncrement);
+
+    // Skip 10 packets (larger than NACK threshold).
+    const int kNumLostPackets = 10;
+    seq_num += kNumLostPackets + 1;
+    nack->UpdateLastReceivedPacket(seq_num_offset + seq_num,
+      seq_num * kTimestampIncrement);
+
+    const size_t kExpectedListSize = kNumLostPackets - kNackThreshold;
+    std::vector<uint16_t> nack_list = nack->GetNackList(kShortRoundTripTimeMs);
+    EXPECT_EQ(kExpectedListSize, nack_list.size());
+
+    for (int k = 0; k < 2; ++k) {
+      // Decoding of the first and the second arrived packets.
+      for (int n = 0; n < kPacketSizeMs / 10; ++n) {
+        nack->UpdateLastDecodedPacket(seq_num_offset + k,
+                                      k * kTimestampIncrement);
+        nack_list = nack->GetNackList(kShortRoundTripTimeMs);
+        EXPECT_EQ(kExpectedListSize, nack_list.size());
+      }
+    }
+
+    // Decoding of the last received packet.
+    nack->UpdateLastDecodedPacket(seq_num + seq_num_offset,
+      seq_num * kTimestampIncrement);
+    nack_list = nack->GetNackList(kShortRoundTripTimeMs);
+    EXPECT_TRUE(nack_list.empty());
+
+    // Make sure list of late packets is also empty. To check that, push few
+    // packets, if the late list is not empty its content will pop up in NACK
+    // list.
+    for (int n = 0; n < kNackThreshold + 10; ++n) {
+      seq_num++;
+      nack->UpdateLastReceivedPacket(seq_num_offset + seq_num,
+       seq_num * kTimestampIncrement);
+      nack_list = nack->GetNackList(kShortRoundTripTimeMs);
+      EXPECT_TRUE(nack_list.empty());
+    }
+  }
+}
+
+TEST(NackTest, Reset) {
+  scoped_ptr<Nack> nack(Nack::Create(kNackThreshold));
+  nack->UpdateSampleRate(kSampleRateHz);
+
+  // Two consecutive packets to have a correct estimate of timestamp increase.
+  uint16_t seq_num = 0;
+  nack->UpdateLastReceivedPacket(seq_num, seq_num * kTimestampIncrement);
+  seq_num++;
+  nack->UpdateLastReceivedPacket(seq_num, seq_num * kTimestampIncrement);
+
+  // Skip 10 packets (larger than NACK threshold).
+  const int kNumLostPackets = 10;
+  seq_num += kNumLostPackets + 1;
+  nack->UpdateLastReceivedPacket(seq_num, seq_num * kTimestampIncrement);
+
+  const size_t kExpectedListSize = kNumLostPackets - kNackThreshold;
+  std::vector<uint16_t> nack_list = nack->GetNackList(kShortRoundTripTimeMs);
+  EXPECT_EQ(kExpectedListSize, nack_list.size());
+
+  nack->Reset();
+  nack_list = nack->GetNackList(kShortRoundTripTimeMs);
+  EXPECT_TRUE(nack_list.empty());
+}
+
+TEST(NackTest, ListSizeAppliedFromBeginning) {
+  const size_t kNackListSize = 10;
+  for (int m = 0; m < 2; ++m) {
+    uint16_t seq_num_offset = (m == 0) ? 0 : 65525;  // Wrap around if |m| is 1.
+    scoped_ptr<Nack> nack(Nack::Create(kNackThreshold));
+    nack->UpdateSampleRate(kSampleRateHz);
+    nack->SetMaxNackListSize(kNackListSize);
+
+    uint16_t seq_num = seq_num_offset;
+    uint32_t timestamp = 0x12345678;
+    nack->UpdateLastReceivedPacket(seq_num, timestamp);
+
+    // Packet lost more than NACK-list size limit.
+    uint16_t num_lost_packets = kNackThreshold + kNackListSize + 5;
+
+    seq_num += num_lost_packets + 1;
+    timestamp += (num_lost_packets + 1) * kTimestampIncrement;
+    nack->UpdateLastReceivedPacket(seq_num, timestamp);
+
+    std::vector<uint16_t> nack_list = nack->GetNackList(kShortRoundTripTimeMs);
+    EXPECT_EQ(kNackListSize - kNackThreshold, nack_list.size());
+  }
+}
+
+TEST(NackTest, ChangeOfListSizeAppliedAndOldElementsRemoved) {
+  const size_t kNackListSize = 10;
+  for (int m = 0; m < 2; ++m) {
+    uint16_t seq_num_offset = (m == 0) ? 0 : 65525;  // Wrap around if |m| is 1.
+    scoped_ptr<Nack> nack(Nack::Create(kNackThreshold));
+    nack->UpdateSampleRate(kSampleRateHz);
+
+    uint16_t seq_num = seq_num_offset;
+    uint32_t timestamp = 0x87654321;
+    nack->UpdateLastReceivedPacket(seq_num, timestamp);
+
+    // Packet lost more than NACK-list size limit.
+    uint16_t num_lost_packets = kNackThreshold + kNackListSize + 5;
+
+    scoped_array<uint16_t> seq_num_lost(new uint16_t[num_lost_packets]);
+    for (int n = 0; n < num_lost_packets; ++n) {
+      seq_num_lost[n] = ++seq_num;
+    }
+
+    ++seq_num;
+    timestamp += (num_lost_packets + 1) * kTimestampIncrement;
+    nack->UpdateLastReceivedPacket(seq_num, timestamp);
+    size_t expected_size = num_lost_packets - kNackThreshold;
+
+    std::vector<uint16_t> nack_list = nack->GetNackList(kShortRoundTripTimeMs);
+    EXPECT_EQ(expected_size, nack_list.size());
+
+    nack->SetMaxNackListSize(kNackListSize);
+    expected_size = kNackListSize - kNackThreshold;
+    nack_list = nack->GetNackList(kShortRoundTripTimeMs);
+    EXPECT_TRUE(IsNackListCorrect(
+        nack_list, &seq_num_lost[num_lost_packets - kNackListSize],
+        expected_size));
+
+    // NACK list does not change size but the content is changing. The oldest
+    // element is removed and one from late list is inserted.
+    size_t n;
+    for (n = 1; n <= static_cast<size_t>(kNackThreshold); ++n) {
+      ++seq_num;
+      timestamp += kTimestampIncrement;
+      nack->UpdateLastReceivedPacket(seq_num, timestamp);
+      nack_list = nack->GetNackList(kShortRoundTripTimeMs);
+      EXPECT_TRUE(IsNackListCorrect(
+          nack_list, &seq_num_lost[num_lost_packets - kNackListSize + n],
+          expected_size));
+    }
+
+    // NACK list should shrink.
+    for (; n < kNackListSize; ++n) {
+      ++seq_num;
+      timestamp += kTimestampIncrement;
+      nack->UpdateLastReceivedPacket(seq_num, timestamp);
+      --expected_size;
+      nack_list = nack->GetNackList(kShortRoundTripTimeMs);
+      EXPECT_TRUE(IsNackListCorrect(
+          nack_list, &seq_num_lost[num_lost_packets - kNackListSize + n],
+          expected_size));
+    }
+
+    // After this packet, NACK list should be empty.
+    ++seq_num;
+    timestamp += kTimestampIncrement;
+    nack->UpdateLastReceivedPacket(seq_num, timestamp);
+    nack_list = nack->GetNackList(kShortRoundTripTimeMs);
+    EXPECT_TRUE(nack_list.empty());
+  }
+}
+
+TEST(NackTest, RoudTripTimeIsApplied) {
+  const int kNackListSize = 200;
+  scoped_ptr<Nack> nack(Nack::Create(kNackThreshold));
+  nack->UpdateSampleRate(kSampleRateHz);
+  nack->SetMaxNackListSize(kNackListSize);
+
+  uint16_t seq_num = 0;
+  uint32_t timestamp = 0x87654321;
+  nack->UpdateLastReceivedPacket(seq_num, timestamp);
+
+  // Packet lost more than NACK-list size limit.
+  uint16_t kNumLostPackets = kNackThreshold + 5;
+
+  seq_num += (1 + kNumLostPackets);
+  timestamp += (1 + kNumLostPackets) * kTimestampIncrement;
+  nack->UpdateLastReceivedPacket(seq_num, timestamp);
+
+  // Expected time-to-play are:
+  // kPacketSizeMs - 10, 2*kPacketSizeMs - 10, 3*kPacketSizeMs - 10, ...
+  //
+  // sequence number:  1,  2,  3,   4,   5
+  // time-to-play:    20, 50, 80, 110, 140
+  //
+  std::vector<uint16_t> nack_list = nack->GetNackList(100);
+  ASSERT_EQ(2u, nack_list.size());
+  EXPECT_EQ(4, nack_list[0]);
+  EXPECT_EQ(5, nack_list[1]);
+}
+
+}  // namespace webrtc