Opus integration

First patch = delivery from August 22, 2012.

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

git-svn-id: http://webrtc.googlecode.com/svn/trunk@2945 4adac7df-926f-26a2-2b94-8c16560cd09d
diff --git a/DEPS b/DEPS
index 46c3d2c..224e94b 100644
--- a/DEPS
+++ b/DEPS
@@ -57,6 +57,9 @@
   "third_party/libyuv":
     (Var("googlecode_url") % "libyuv") + "/trunk@389",
 
+  "third_party/opus/source":
+    "http://git.xiph.org/opus.git@v1.0.1",
+
   "third_party/protobuf":
     Var("chromium_trunk") + "/src/third_party/protobuf@" + Var("chromium_revision"),
 
diff --git a/src/build/common.gypi b/src/build/common.gypi
index 6d02f20..d57b265 100644
--- a/src/build/common.gypi
+++ b/src/build/common.gypi
@@ -85,6 +85,10 @@
 
         # Disable the use of protocol buffers in production code.
         'enable_protobuf%': 0,
+
+        # Disable Mozilla internal Opus version
+        'build_with_mozilla%': 0,
+
       }, {  # Settings for the standalone (not-in-Chromium) build.
         'include_pulse_audio%': 1,
         'include_internal_audio_device%': 1,
diff --git a/src/engine_configurations.h b/src/engine_configurations.h
index 35dec15..553aed4 100644
--- a/src/engine_configurations.h
+++ b/src/engine_configurations.h
@@ -27,19 +27,27 @@
 //  [Voice] Codec settings
 // ----------------------------------------------------------------------------
 
+// iSAC is not included in the Mozilla build, but in all other builds.
+#ifndef WEBRTC_MOZILLA_BUILD
 #ifdef WEBRTC_ARCH_ARM
-#define WEBRTC_CODEC_ISACFX     // fix-point iSAC implementation
+#define WEBRTC_CODEC_ISACFX  // Fix-point iSAC implementation.
 #else
-#define WEBRTC_CODEC_ISAC       // floating-point iSAC implementation (default)
-#endif
+#define WEBRTC_CODEC_ISAC  // Floating-point iSAC implementation (default).
+#endif  // WEBRTC_ARCH_ARM
+#endif  // !WEBRTC_MOZILLA_BUILD
+
+// AVT is included in all builds, along with G.711, NetEQ and CNG
+// (which are mandatory and don't have any defines).
 #define WEBRTC_CODEC_AVT
 
-#ifndef WEBRTC_CHROMIUM_BUILD
+// iLBC, G.722, PCM16B and Redundancy coding are excluded from Chromium and
+// Mozilla builds.
+#if !defined(WEBRTC_CHROMIUM_BUILD) && !defined(WEBRTC_MOZILLA_BUILD)
 #define WEBRTC_CODEC_ILBC
 #define WEBRTC_CODEC_G722
 #define WEBRTC_CODEC_PCM16
 #define WEBRTC_CODEC_RED
-#endif
+#endif  // !WEBRTC_CHROMIUM_BUILD && !WEBRTC_MOZILLA_BUILD
 
 // ----------------------------------------------------------------------------
 //  [Video] Codec settings
diff --git a/src/modules/audio_coding/codecs/cng/webrtc_cng.c b/src/modules/audio_coding/codecs/cng/webrtc_cng.c
index 7cc6cb9..28bfaae 100644
--- a/src/modules/audio_coding/codecs/cng/webrtc_cng.c
+++ b/src/modules/audio_coding/codecs/cng/webrtc_cng.c
@@ -36,7 +36,7 @@
 
 typedef struct WebRtcCngEncInst_t_ {
   int16_t enc_nrOfCoefs;
-  int16_t enc_sampfreq;
+  uint16_t enc_sampfreq;
   int16_t enc_interval;
   int16_t enc_msSinceSID;
   int32_t enc_Energy;
diff --git a/src/modules/audio_coding/codecs/opus/interface/opus_interface.h b/src/modules/audio_coding/codecs/opus/interface/opus_interface.h
new file mode 100644
index 0000000..dcfd87f
--- /dev/null
+++ b/src/modules/audio_coding/codecs/opus/interface/opus_interface.h
@@ -0,0 +1,123 @@
+/*
+ *  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_CODECS_OPUS_INTERFACE_OPUS_INTERFACE_H_
+#define WEBRTC_MODULES_AUDIO_CODING_CODECS_OPUS_INTERFACE_OPUS_INTERFACE_H_
+
+#include "typedefs.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// Opaque wrapper types for the codec state.
+typedef struct WebRtcOpusEncInst OpusEncInst;
+typedef struct WebRtcOpusDecInst OpusDecInst;
+
+int16_t WebRtcOpus_EncoderCreate(OpusEncInst** inst, int32_t channels);
+int16_t WebRtcOpus_EncoderFree(OpusEncInst* inst);
+
+/****************************************************************************
+ * WebRtcOpus_Encode(...)
+ *
+ * This function encodes audio as a series of Opus frames and inserts
+ * it into a packet. Input buffer can be any length.
+ *
+ * Input:
+ *      - inst                  : Encoder context
+ *      - audio_in              : Input speech data buffer
+ *      - samples               : Samples in audio_in
+ *      - length_encoded_buffer : Output buffer size
+ *
+ * Output:
+ *      - encoded               : Output compressed data buffer
+ *
+ * Return value                 : >0 - Length (in bytes) of coded data
+ *                                -1 - Error
+ */
+int16_t WebRtcOpus_Encode(OpusEncInst* inst, int16_t* audio_in, int16_t samples,
+                          int16_t length_encoded_buffer, uint8_t* encoded);
+
+/****************************************************************************
+ * WebRtcOpus_SetBitRate(...)
+ *
+ * This function adjusts the target bitrate of the encoder.
+ *
+ * Input:
+ *      - inst               : Encoder context
+ *      - rate               : New target bitrate
+ *
+ * Return value              :  0 - Success
+ *                             -1 - Error
+ */
+int16_t WebRtcOpus_SetBitRate(OpusEncInst* inst, int32_t rate);
+
+int16_t WebRtcOpus_DecoderCreate(OpusDecInst** inst, int channels);
+int16_t WebRtcOpus_DecoderFree(OpusDecInst* inst);
+
+/****************************************************************************
+ * WebRtcOpus_DecoderInit(...)
+ *
+ * This function resets state of the decoder.
+ *
+ * Input:
+ *      - inst               : Decoder context
+ *
+ * Return value              :  0 - Success
+ *                             -1 - Error
+ */
+int16_t WebRtcOpus_DecoderInit(OpusDecInst* inst);
+
+/****************************************************************************
+ * WebRtcOpus_Decode(...)
+ *
+ * This function decodes an Opus packet into one or more audio frames at the
+ * ACM interface's sampling rate (32 kHz).
+ *
+ * Input:
+ *      - inst               : Decoder context
+ *      - encoded            : Encoded data
+ *      - encoded_bytes      : Bytes in encoded vector
+ *
+ * Output:
+ *      - decoded            : The decoded vector
+ *      - audio_type         : 1 normal, 2 CNG (for Opus it should
+ *                             always return 1 since we're not using Opus's
+ *                             built-in DTX/CNG scheme)
+ *
+ * Return value              : >0 - Samples in decoded vector
+ *                             -1 - Error
+ */
+int16_t WebRtcOpus_Decode(OpusDecInst* inst, int16_t* encoded,
+                          int16_t encoded_bytes, int16_t* decoded,
+                          int16_t* audio_type);
+
+/****************************************************************************
+ * WebRtcOpus_DecodePlc(...)
+ *
+ * This function precesses PLC for opus frame(s).
+ * Input:
+ *        - inst                  : Decoder context
+ *        - number_of_lost_frames : Number of PLC frames to produce
+ *
+ * Output:
+ *        - decoded               : The decoded vector
+ *
+ * Return value                   : >0 - number of samples in decoded PLC vector
+ *                                  -1 - Error
+ */
+int16_t WebRtcOpus_DecodePlc(OpusDecInst* inst, int16_t* decoded,
+                             int16_t number_of_lost_frames);
+
+#ifdef __cplusplus
+}  // extern "C"
+#endif
+
+#endif  // WEBRTC_MODULES_AUDIO_CODING_CODECS_OPUS_INTERFACE_OPUS_INTERFACE_H_
diff --git a/src/modules/audio_coding/codecs/opus/opus.gypi b/src/modules/audio_coding/codecs/opus/opus.gypi
new file mode 100644
index 0000000..809068c
--- /dev/null
+++ b/src/modules/audio_coding/codecs/opus/opus.gypi
@@ -0,0 +1,44 @@
+# 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.
+
+{
+  'targets': [
+    {
+      'target_name': 'webrtc_opus',
+      'type': 'static_library',
+      'conditions': [
+        ['build_with_mozilla==1', {
+          # Mozilla provides its own build of the opus library.
+          'include_dirs': [
+            '$(DIST)/include/opus',
+           ]
+        }, {
+          'dependencies': [
+            '<(DEPTH)/third_party/opus/opus.gyp:opus'
+          ],
+          'include_dirs': [
+            '<(webrtc_root)/../third_party/opus/source/include',
+          ],
+        }],
+      ],
+      'direct_dependent_settings': {
+        'conditions': [
+          ['build_with_mozilla==1', {
+            'include_dirs': [
+              '$(DIST)/include/opus',
+            ],
+          }],
+        ],
+      },
+      'sources': [
+        'interface/opus_interface.h',
+        'opus_interface.c',
+      ],
+    },
+  ],
+}
diff --git a/src/modules/audio_coding/codecs/opus/opus_interface.c b/src/modules/audio_coding/codecs/opus/opus_interface.c
new file mode 100644
index 0000000..f61ecc5
--- /dev/null
+++ b/src/modules/audio_coding/codecs/opus/opus_interface.c
@@ -0,0 +1,181 @@
+/*
+ *  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 "modules/audio_coding/codecs/opus/interface/opus_interface.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "opus.h"
+
+#include "common_audio/signal_processing/resample_by_2_internal.h"
+#include "common_audio/signal_processing/include/signal_processing_library.h"
+
+enum {
+  /* We always produce 20ms frames. */
+  kWebRtcOpusMaxEncodeFrameSizeMs = 20,
+
+  /* The format allows up to 120ms frames. Since we
+   * don't control the other side, we must allow
+   * for packets that large. NetEq is currently
+   * limited to 60 ms on the receive side.
+   */
+  kWebRtcOpusMaxDecodeFrameSizeMs = 120,
+
+  /* Sample count is 48 kHz * samples per frame. */
+  kWebRtcOpusMaxFrameSize = 48 * kWebRtcOpusMaxDecodeFrameSizeMs,
+};
+
+struct WebRtcOpusEncInst {
+  OpusEncoder* encoder;
+};
+
+int16_t WebRtcOpus_EncoderCreate(OpusEncInst** inst, int32_t channels) {
+  OpusEncInst* state;
+  state = (OpusEncInst*) calloc(1, sizeof(OpusEncInst));
+  if (state) {
+    int error;
+    state->encoder = opus_encoder_create(48000, channels, OPUS_APPLICATION_VOIP,
+                                         &error);
+    if (error == OPUS_OK || state->encoder != NULL ) {
+      *inst = state;
+      return 0;
+    }
+    free(state);
+  }
+  return -1;
+}
+
+int16_t WebRtcOpus_EncoderFree(OpusEncInst* inst) {
+  opus_encoder_destroy(inst->encoder);
+  return 0;
+}
+
+int16_t WebRtcOpus_Encode(OpusEncInst* inst, int16_t* audio_in, int16_t samples,
+                          int16_t length_encoded_buffer, uint8_t* encoded) {
+  opus_int16* audio = (opus_int16*) audio_in;
+  unsigned char* coded = encoded;
+  int res;
+
+  if (samples > 48 * kWebRtcOpusMaxEncodeFrameSizeMs) {
+    return -1;
+  }
+
+  res = opus_encode(inst->encoder, audio, samples, coded,
+                    length_encoded_buffer);
+
+  if (res > 0) {
+    return res;
+  }
+  return -1;
+}
+
+int16_t WebRtcOpus_SetBitRate(OpusEncInst* inst, int32_t rate) {
+  return opus_encoder_ctl(inst->encoder, OPUS_SET_BITRATE(rate));
+}
+
+struct WebRtcOpusDecInst {
+  int16_t state_48_32[8];
+  OpusDecoder* decoder;
+};
+
+int16_t WebRtcOpus_DecoderCreate(OpusDecInst** inst, int channels) {
+  OpusDecInst* state;
+  state = (OpusDecInst*) calloc(1, sizeof(OpusDecInst));
+  if (state) {
+    int error;
+    // Always create a 48000 Hz Opus decoder.
+    state->decoder = opus_decoder_create(48000, channels, &error);
+    if (error == OPUS_OK && state->decoder != NULL ) {
+      *inst = state;
+      return 0;
+    }
+    free(state);
+    state = NULL;
+  }
+  return -1;
+}
+
+int16_t WebRtcOpus_DecoderFree(OpusDecInst* inst) {
+  opus_decoder_destroy(inst->decoder);
+  free(inst);
+  return 0;
+}
+
+int16_t WebRtcOpus_DecoderInit(OpusDecInst* inst) {
+  int error = opus_decoder_ctl(inst->decoder, OPUS_RESET_STATE);
+  if (error == OPUS_OK) {
+    memset(inst->state_48_32, 0, sizeof(inst->state_48_32));
+    return 0;
+  }
+  return -1;
+}
+
+static int DecodeNative(OpusDecInst* inst, int16_t* encoded,
+                        int16_t encoded_bytes, int16_t* decoded,
+                        int16_t* audio_type) {
+  unsigned char* coded = (unsigned char*) encoded;
+  opus_int16* audio = (opus_int16*) decoded;
+
+  int res = opus_decode(inst->decoder, coded, encoded_bytes, audio,
+                        kWebRtcOpusMaxFrameSize, 0);
+  /* TODO(tlegrand): set to DTX for zero-length packets? */
+  *audio_type = 0;
+
+  if (res > 0) {
+    return res;
+  }
+  return -1;
+}
+
+int16_t WebRtcOpus_Decode(OpusDecInst* inst, int16_t* encoded,
+                          int16_t encoded_bytes, int16_t* decoded,
+                          int16_t* audio_type) {
+  /* Enough for 120 ms (the largest Opus packet size) of mono audio at 48 kHz
+   * and resampler overlap. This will need to be enlarged for stereo decoding.
+   */
+  int16_t buffer16[kWebRtcOpusMaxFrameSize];
+  int32_t buffer32[kWebRtcOpusMaxFrameSize + 7];
+  int decoded_samples;
+  int blocks;
+  int16_t output_samples;
+  int i;
+
+  /* Decode to a temporary buffer. */
+  decoded_samples = DecodeNative(inst, encoded, encoded_bytes, buffer16,
+                                 audio_type);
+  if (decoded_samples < 0) {
+    return -1;
+  }
+  /* Resample from 48 kHz to 32 kHz. */
+  for (i = 0; i < 7; i++) {
+    buffer32[i] = inst->state_48_32[i];
+    inst->state_48_32[i] = buffer16[decoded_samples -7 + i];
+  }
+  for (i = 0; i < decoded_samples; i++) {
+    buffer32[7 + i] = buffer16[i];
+  }
+  /* Resampling 3 samples to 2. Function divides the input in |blocks| number
+   * of 3-sample groups, and output is |blocks| number of 2-sample groups. */
+  blocks = decoded_samples / 3;
+  WebRtcSpl_Resample48khzTo32khz(buffer32, buffer32, blocks);
+  output_samples = (int16_t) (blocks * 2);
+  WebRtcSpl_VectorBitShiftW32ToW16(decoded, output_samples, buffer32, 15);
+
+  return output_samples;
+}
+
+int16_t WebRtcOpus_DecodePlc(OpusDecInst* inst, int16_t* decoded,
+                             int16_t number_of_lost_frames) {
+  /* TODO(tlegrand): We can pass NULL to opus_decode to activate packet
+   * loss concealment, but I don't know how many samples
+   * number_of_lost_frames corresponds to. */
+  return -1;
+}
diff --git a/src/modules/audio_coding/main/source/acm_cng.cc b/src/modules/audio_coding/main/source/acm_cng.cc
index 2393346..4edfc05 100644
--- a/src/modules/audio_coding/main/source/acm_cng.cc
+++ b/src/modules/audio_coding/main/source/acm_cng.cc
@@ -81,7 +81,8 @@
   // Then return the structure back to NetEQ to add the codec to it's
   // database.
 
-  if (_sampFreqHz == 8000 || _sampFreqHz == 16000 || _sampFreqHz == 32000) {
+  if (_sampFreqHz == 8000 || _sampFreqHz == 16000 || _sampFreqHz == 32000 ||
+      _sampFreqHz == 48000) {
     SET_CODEC_PAR((codecDef), kDecoderCNG, codecInst.pltype,
         _decoderInstPtr, _sampFreqHz);
     SET_CNG_FUNCTIONS((codecDef));
diff --git a/src/modules/audio_coding/main/source/acm_cng.h b/src/modules/audio_coding/main/source/acm_cng.h
index 6276c44..d204d02 100644
--- a/src/modules/audio_coding/main/source/acm_cng.h
+++ b/src/modules/audio_coding/main/source/acm_cng.h
@@ -62,7 +62,7 @@
 
   WebRtcCngEncInst* _encoderInstPtr;
   WebRtcCngDecInst* _decoderInstPtr;
-  WebRtc_Word16 _sampFreqHz;
+  WebRtc_UWord16 _sampFreqHz;
 };
 
 } // namespace webrtc
diff --git a/src/modules/audio_coding/main/source/acm_codec_database.cc b/src/modules/audio_coding/main/source/acm_codec_database.cc
index b782194..2e3db19 100644
--- a/src/modules/audio_coding/main/source/acm_codec_database.cc
+++ b/src/modules/audio_coding/main/source/acm_codec_database.cc
@@ -86,6 +86,10 @@
     #include "acm_gsmfr.h"
     #include "gsmfr_interface.h"
 #endif
+#ifdef WEBRTC_CODEC_OPUS
+    #include "acm_opus.h"
+    #include "opus_interface.h"
+#endif
 #ifdef WEBRTC_CODEC_SPEEX
     #include "acm_speex.h"
     #include "speex_interface.h"
@@ -103,22 +107,20 @@
 // 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] = {
-  105, 107, 108, 109, 111, 112, 113, 114, 115, 116, 117, 120,
-  121, 122, 123, 124, 125, 126, 101, 100,  97,  96,  95,  94,
-   93,  92,  91,  90,  89,  88,  87,  86,  85,  84,  83,  82,
-   81,  80,  79,  78,  77,  76,  75,  74,  73,  72,  71,  70,
-   69,
+  105, 107, 108, 109, 111, 112, 113, 114, 115, 116, 117, 121,
+   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
 };
 
 // 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_PCM16) || \
-     defined(WEBRTC_CODEC_AMR) || defined(WEBRTC_CODEC_AMRWB) || \
-     defined(WEBRTC_CODEC_CELT) || defined(WEBRTC_CODEC_G729_1) || \
-     defined(WEBRTC_CODEC_SPEEX) || defined(WEBRTC_CODEC_G722_1) || \
-     defined(WEBRTC_CODEC_G722_1C))
+#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
 
@@ -186,14 +188,19 @@
 #ifdef WEBRTC_CODEC_GSMFR
   {3, "GSM", 8000, 160, 1, 13200},
 #endif
+#ifdef WEBRTC_CODEC_OPUS
+  // Opus supports 48, 24, 16, 12, 8 kHz.
+  {120, "opus", 48000, 960, 1, 32000},
+#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 three different sampling frequencies.
+  // 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
@@ -272,6 +279,11 @@
 #ifdef WEBRTC_CODEC_GSMFR
   {3, {160, 320, 480}, 160, 1},
 #endif
+#ifdef WEBRTC_CODEC_OPUS
+  // Opus supports frames shorter than 10ms,
+  // but it doesn't help us to use them.
+  {1, {960}, 0, 2},
+#endif
 #ifdef WEBRTC_CODEC_SPEEX
   {3, {160, 320, 480}, 0, 1},
   {3, {320, 640, 960}, 0, 1},
@@ -280,6 +292,7 @@
   {1, {240}, 240, 1},
   {1, {480}, 480, 1},
   {1, {960}, 960, 1},
+  {1, {1440}, 1440, 1},
 #ifdef WEBRTC_CODEC_AVT
   {1, {240}, 240, 1},
 #endif
@@ -355,6 +368,9 @@
 #ifdef WEBRTC_CODEC_GSMFR
   kDecoderGSMFR,
 #endif
+#ifdef WEBRTC_CODEC_OPUS
+  kDecoderOpus,
+#endif
 #ifdef WEBRTC_CODEC_SPEEX
   kDecoderSPEEX_8,
   kDecoderSPEEX_16,
@@ -363,6 +379,7 @@
   kDecoderCNG,
   kDecoderCNG,
   kDecoderCNG,
+  kDecoderCNG,
 #ifdef WEBRTC_CODEC_AVT
   kDecoderAVT,
 #endif
@@ -509,6 +526,9 @@
   } 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;
@@ -719,6 +739,10 @@
         codec_id = kCNSWB;
         break;
       }
+      case 48000: {
+        codec_id = kCNFB;
+        break;
+      }
       default: {
         return NULL;
       }
@@ -732,6 +756,10 @@
 #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;
@@ -766,6 +794,10 @@
         codec_id = kCNSWB;
         break;
       }
+      case 48000: {
+        codec_id = kCNFB;
+        break;
+      }
       default: {
         return NULL;
       }
@@ -928,6 +960,14 @@
   }
 }
 
+// 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)) {
diff --git a/src/modules/audio_coding/main/source/acm_codec_database.h b/src/modules/audio_coding/main/source/acm_codec_database.h
index 0fe3a5e..8baf24e 100644
--- a/src/modules/audio_coding/main/source/acm_codec_database.h
+++ b/src/modules/audio_coding/main/source/acm_codec_database.h
@@ -91,6 +91,9 @@
 #ifdef WEBRTC_CODEC_GSMFR
     , kGSMFR
 #endif
+#ifdef WEBRTC_CODEC_OPUS
+    , kOpus
+#endif
 #ifdef WEBRTC_CODEC_SPEEX
     , kSPEEX8
     , kSPEEX16
@@ -98,6 +101,7 @@
     , kCNNB
     , kCNWB
     , kCNSWB
+    , kCNFB
 #ifdef WEBRTC_CODEC_AVT
     , kAVT
 #endif
@@ -170,6 +174,9 @@
   enum {kSPEEX8 = -1};
   enum {kSPEEX16 = -1};
 #endif
+#ifndef WEBRTC_CODEC_OPUS
+  enum {kOpus = -1};
+#endif
 #ifndef WEBRTC_CODEC_AVT
   enum {kAVT = -1};
 #endif
@@ -298,6 +305,7 @@
   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
diff --git a/src/modules/audio_coding/main/source/acm_common_defs.h b/src/modules/audio_coding/main/source/acm_common_defs.h
index fd8dbd6..cdff1c1 100644
--- a/src/modules/audio_coding/main/source/acm_common_defs.h
+++ b/src/modules/audio_coding/main/source/acm_common_defs.h
@@ -63,14 +63,15 @@
 //   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
+  kPassiveDTXSWB,
+  kPassiveDTXFB
 };
 
 // A structure which contains codec parameters. For instance, used when
diff --git a/src/modules/audio_coding/main/source/acm_generic_codec.cc b/src/modules/audio_coding/main/source/acm_generic_codec.cc
index f9a6a3a..f98f260 100644
--- a/src/modules/audio_coding/main/source/acm_generic_codec.cc
+++ b/src/modules/audio_coding/main/source/acm_generic_codec.cc
@@ -58,6 +58,7 @@
       _numLPCParams(kNewCNGNumPLCParams),
       _sentCNPrevious(false),
       _isMaster(true),
+      _prev_frame_cng(0),
       _netEqDecodeLock(NULL),
       _codecWrapperLock(*RWLockWrapper::CreateRWLock()),
       _lastEncodedTimestamp(0),
@@ -294,6 +295,8 @@
                 *encodingType = kPassiveDTXWB;
             } else if (sampFreqHz == 32000) {
                 *encodingType = kPassiveDTXSWB;
+            } else if (sampFreqHz == 48000) {
+                *encodingType = kPassiveDTXFB;
             } else {
                 status = -1;
                 WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, _uniqueID,
@@ -1169,7 +1172,7 @@
         }
         WebRtc_UWord16 freqHz;
         EncoderSampFreq(freqHz);
-        if(WebRtcCng_InitEnc(_ptrDTXInst, (WebRtc_Word16)freqHz,
+        if(WebRtcCng_InitEnc(_ptrDTXInst, freqHz,
             ACM_SID_INTERVAL_MSEC, _numLPCParams) < 0)
         {
             // Couldn't initialize, has to return -1, and free the memory
@@ -1313,6 +1316,7 @@
         *samplesProcessed = 0;
         return 0;
     }
+
     WebRtc_UWord16 freqHz;
     EncoderSampFreq(freqHz);
 
@@ -1321,8 +1325,8 @@
     WebRtc_Word32 frameLenMsec = (((WebRtc_Word32)_frameLenSmpl * 1000) / freqHz);
     WebRtc_Word16 status;
 
-    // Vector for storing maximum 30 ms of mono audio at 32 kHz
-    WebRtc_Word16 audio[960];
+    // Vector for storing maximum 30 ms of mono audio at 48 kHz.
+    WebRtc_Word16 audio[1440];
 
     // Calculate number of VAD-blocks to process, and number of samples in each block.
     int noSamplesToProcess[2];
@@ -1378,25 +1382,33 @@
             *bitStreamLenByte = 0;
             for(WebRtc_Word16 n = 0; n < num10MsecFrames; n++)
             {
-                // This block is (passive) && (vad enabled)
-                status = WebRtcCng_Encode(_ptrDTXInst, &audio[n*samplesIn10Msec],
-                    samplesIn10Msec, bitStream, &bitStreamLen, 0);
+                // This block is (passive) && (vad enabled). If first CNG after
+                // speech, force SID by setting last parameter to "1".
+                status = WebRtcCng_Encode(_ptrDTXInst,
+                                          &audio[n*samplesIn10Msec],
+                                          samplesIn10Msec, bitStream,
+                                          &bitStreamLen, !_prev_frame_cng);
                 if (status < 0) {
                     return -1;
                 }
 
+                // Update previous frame was CNG.
+                _prev_frame_cng = 1;
+
                 *samplesProcessed += samplesIn10Msec*_noChannels;
 
                 // bitStreamLen will only be > 0 once per 100 ms
                 *bitStreamLenByte += bitStreamLen;
             }
 
-
             // Check if all samples got processed by the DTX
             if(*samplesProcessed != noSamplesToProcess[i]*_noChannels) {
                 // Set to zero since something went wrong. Shouldn't happen.
                 *samplesProcessed = 0;
             }
+        } else {
+            // Update previous frame was not CNG.
+            _prev_frame_cng = 0;
         }
 
         if(*samplesProcessed > 0)
diff --git a/src/modules/audio_coding/main/source/acm_generic_codec.h b/src/modules/audio_coding/main/source/acm_generic_codec.h
index c138ed9..29c882c 100644
--- a/src/modules/audio_coding/main/source/acm_generic_codec.h
+++ b/src/modules/audio_coding/main/source/acm_generic_codec.h
@@ -1310,6 +1310,7 @@
     WebRtc_UWord8         _numLPCParams;
     bool                  _sentCNPrevious;
     bool                  _isMaster;
+    int16_t               _prev_frame_cng;
 
     WebRtcACMCodecParams  _encoderParams;
     WebRtcACMCodecParams  _decoderParams;
diff --git a/src/modules/audio_coding/main/source/acm_opus.cc b/src/modules/audio_coding/main/source/acm_opus.cc
index 87bdd8b..034e57d 100644
--- a/src/modules/audio_coding/main/source/acm_opus.cc
+++ b/src/modules/audio_coding/main/source/acm_opus.cc
@@ -8,442 +8,256 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
+#include "acm_opus.h"
+
+#include "acm_codec_database.h"
 #include "acm_common_defs.h"
 #include "acm_neteq.h"
-#include "acm_opus.h"
 #include "trace.h"
 #include "webrtc_neteq.h"
 #include "webrtc_neteq_help_macros.h"
 
 #ifdef WEBRTC_CODEC_OPUS
-    // NOTE! Opus is not included in the open-source package. Modify this file or your codec
-    // API to match the function call and name of used Opus API file.
-    // #include "opus_interface.h"
+#include "opus_interface.h"
 #endif
 
-namespace webrtc
-{
+namespace webrtc {
 
 #ifndef WEBRTC_CODEC_OPUS
 
-ACMOPUS::ACMOPUS(WebRtc_Word16 /* codecID */)
+ACMOpus::ACMOpus(int16_t /* codecID */)
     : _encoderInstPtr(NULL),
       _decoderInstPtr(NULL),
-      _mySampFreq(0),
-      _myRate(0),
-      _opusMode(0),
-      _flagVBR(0) {
+      _sampleFreq(0),
+      _bitrate(0) {
   return;
 }
 
-
-ACMOPUS::~ACMOPUS()
-{
-    return;
+ACMOpus::~ACMOpus() {
+  return;
 }
 
-
-WebRtc_Word16
-ACMOPUS::InternalEncode(
-    WebRtc_UWord8* /* bitStream        */,
-    WebRtc_Word16* /* bitStreamLenByte */)
-{
-    return -1;
+int16_t ACMOpus::InternalEncode(uint8_t* /* bitStream */,
+                                int16_t* /* bitStreamLenByte */) {
+  return -1;
 }
 
-
-WebRtc_Word16
-ACMOPUS::DecodeSafe(
-    WebRtc_UWord8* /* bitStream        */,
-    WebRtc_Word16  /* bitStreamLenByte */,
-    WebRtc_Word16* /* audio            */,
-    WebRtc_Word16* /* audioSamples     */,
-    WebRtc_Word8*  /* speechType       */)
-{
-    return -1;
+int16_t ACMOpus::DecodeSafe(uint8_t* /* bitStream */,
+                            int16_t /* bitStreamLenByte */,
+                            int16_t* /* audio */,
+                            int16_t* /* audioSamples */,
+                            int8_t* /* speechType */) {
+  return -1;
 }
 
-
-WebRtc_Word16
-ACMOPUS::InternalInitEncoder(
-    WebRtcACMCodecParams* /* codecParams */)
-{
-    return -1;
+int16_t ACMOpus::InternalInitEncoder(WebRtcACMCodecParams* /* codecParams */) {
+  return -1;
 }
 
-
-WebRtc_Word16
-ACMOPUS::InternalInitDecoder(
-    WebRtcACMCodecParams* /* codecParams */)
-{
-    return -1;
+int16_t ACMOpus::InternalInitDecoder(WebRtcACMCodecParams* /* codecParams */) {
+  return -1;
 }
 
-
-WebRtc_Word32
-ACMOPUS::CodecDef(
-    WebRtcNetEQ_CodecDef& /* codecDef  */,
-    const CodecInst&      /* codecInst */)
-{
-    return -1;
+int32_t ACMOpus::CodecDef(WebRtcNetEQ_CodecDef& /* codecDef */,
+                          const CodecInst& /* codecInst */) {
+  return -1;
 }
 
-
-ACMGenericCodec*
-ACMOPUS::CreateInstance(void)
-{
-    return NULL;
+ACMGenericCodec* ACMOpus::CreateInstance(void) {
+  return NULL;
 }
 
-
-WebRtc_Word16
-ACMOPUS::InternalCreateEncoder()
-{
-    return -1;
+int16_t ACMOpus::InternalCreateEncoder() {
+  return -1;
 }
 
-
-void
-ACMOPUS::DestructEncoderSafe()
-{
-    return;
+void ACMOpus::DestructEncoderSafe() {
+  return;
 }
 
-
-WebRtc_Word16
-ACMOPUS::InternalCreateDecoder()
-{
-    return -1;
+int16_t ACMOpus::InternalCreateDecoder() {
+  return -1;
 }
 
-
-void
-ACMOPUS::DestructDecoderSafe()
-{
-    return;
+void ACMOpus::DestructDecoderSafe() {
+  return;
 }
 
-
-void
-ACMOPUS::InternalDestructEncoderInst(
-    void* /* ptrInst */)
-{
-    return;
+void ACMOpus::InternalDestructEncoderInst(void* /* ptrInst */) {
+  return;
 }
 
-WebRtc_Word16
-ACMOPUS::SetBitRateSafe(
-    const WebRtc_Word32 /*rate*/ )
-{
-    return -1;
+int16_t ACMOpus::SetBitRateSafe(const int32_t /*rate*/) {
+  return -1;
 }
 
-#else     //===================== Actual Implementation =======================
+#else  //===================== Actual Implementation =======================
 
-// Remove when integrating a real Opus wrapper
-extern WebRtc_Word16 WebRtcOpus_CreateEnc(OPUS_inst_t_** inst, WebRtc_Word16 samplFreq);
-extern WebRtc_Word16 WebRtcOpus_CreateDec(OPUS_inst_t_** inst, WebRtc_Word16 samplFreq);
-extern WebRtc_Word16 WebRtcOpus_FreeEnc(OPUS_inst_t_* inst);
-extern WebRtc_Word16 WebRtcOpus_FreeDec(OPUS_inst_t_* inst);
-extern WebRtc_Word16 WebRtcOpus_Encode(OPUS_inst_t_* encInst,
-                                       WebRtc_Word16* input,
-                                       WebRtc_Word16* output,
-                                       WebRtc_Word16 len,
-                                       WebRtc_Word16 byteLen);
-extern WebRtc_Word16 WebRtcOpus_EncoderInit(OPUS_inst_t_* encInst,
-                                            WebRtc_Word16 samplFreq,
-                                            WebRtc_Word16 mode,
-                                            WebRtc_Word16 vbrFlag);
-extern WebRtc_Word16 WebRtcOpus_Decode(OPUS_inst_t_* decInst);
-extern WebRtc_Word16 WebRtcOpus_DecodeBwe(OPUS_inst_t_* decInst, WebRtc_Word16* input);
-extern WebRtc_Word16 WebRtcOpus_DecodePlc(OPUS_inst_t_* decInst);
-extern WebRtc_Word16 WebRtcOpus_DecoderInit(OPUS_inst_t_* decInst);
-
-ACMOPUS::ACMOPUS(WebRtc_Word16 codecID)
+ACMOpus::ACMOpus(int16_t codecID)
     : _encoderInstPtr(NULL),
       _decoderInstPtr(NULL),
-      _mySampFreq(48000),  // Default sampling frequency.
-      _myRate(50000),  // Default rate.
-      _opusMode(1),  // Default mode is the hybrid mode.
-      _flagVBR(0) {  // Default VBR off.
+      _sampleFreq(32000),  // Default sampling frequency.
+      _bitrate(20000) {  // Default bit-rate.
   _codecID = codecID;
-
-  // Current implementation doesn't have DTX. That might change.
+  // Opus has internal DTX, but we dont use it for now.
   _hasInternalDTX = false;
 
+  if (_codecID != ACMCodecDB::kOpus) {
+    WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, _uniqueID,
+                 "Wrong codec id for Opus.");
+    _sampleFreq = -1;
+    _bitrate = -1;
+  }
   return;
 }
 
-ACMOPUS::~ACMOPUS()
-{
-    if(_encoderInstPtr != NULL)
-    {
-        WebRtcOpus_FreeEnc(_encoderInstPtr);
-        _encoderInstPtr = NULL;
-    }
-    if(_decoderInstPtr != NULL)
-    {
-        WebRtcOpus_FreeDec(_decoderInstPtr);
-        _decoderInstPtr = NULL;
-    }
-    return;
+ACMOpus::~ACMOpus() {
+  if (_encoderInstPtr != NULL) {
+    WebRtcOpus_EncoderFree(_encoderInstPtr);
+    _encoderInstPtr = NULL;
+  }
+  if (_decoderInstPtr != NULL) {
+    WebRtcOpus_DecoderFree(_decoderInstPtr);
+    _decoderInstPtr = NULL;
+  }
+  return;
 }
 
-
-WebRtc_Word16
-ACMOPUS::InternalEncode(
-    WebRtc_UWord8* bitStream,
-    WebRtc_Word16* bitStreamLenByte)
-{
-    WebRtc_Word16 noEncodedSamples = 0;
-    WebRtc_Word16 tmpLenByte = 0;
+int16_t ACMOpus::InternalEncode(uint8_t* bitStream, int16_t* bitStreamLenByte) {
+  // Call Encoder.
+  *bitStreamLenByte = WebRtcOpus_Encode(_encoderInstPtr,
+                                        &_inAudio[_inAudioIxRead],
+                                        _frameLenSmpl,
+                                        MAX_PAYLOAD_SIZE_BYTE,
+                                        bitStream);
+  // Check for error reported from encoder.
+  if (*bitStreamLenByte < 0) {
+    WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, _uniqueID,
+                 "InternalEncode: Encode error for Opus");
     *bitStreamLenByte = 0;
+    return -1;
+  }
 
-    WebRtc_Word16 byteLengthFrame = 0;
+  // Increment the read index. This tells the caller how far
+  // we have gone forward in reading the audio buffer.
+  _inAudioIxRead += _frameLenSmpl;
 
-    // Derive what byte-length is requested
-    byteLengthFrame = _myRate*_frameLenSmpl/(8*_mySampFreq);
-
-    // Call Encoder
-    *bitStreamLenByte = WebRtcOpus_Encode(_encoderInstPtr, &_inAudio[_inAudioIxRead],
-           (WebRtc_Word16*)bitStream, _frameLenSmpl, byteLengthFrame);
-
-    // increment the read index this tell the caller that how far
-    // we have gone forward in reading the audio buffer
-    _inAudioIxRead += _frameLenSmpl;
-
-    // sanity check
-    if(*bitStreamLenByte < 0)
-    {
-        // error has happened
-        WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, _uniqueID,
-            "InternalEncode: Encode error for Opus");
-            *bitStreamLenByte = 0;
-            return -1;
-    }
-
-    return *bitStreamLenByte;
+  return *bitStreamLenByte;
 }
 
+int16_t ACMOpus::DecodeSafe(uint8_t* bitStream, int16_t bitStreamLenByte,
+                            int16_t* audio, int16_t* audioSamples,
+                            int8_t* speechType) {
+  return 0;
+}
 
+int16_t ACMOpus::InternalInitEncoder(WebRtcACMCodecParams* codecParams) {
+  int16_t ret;
+  if (_encoderInstPtr != NULL) {
+    WebRtcOpus_EncoderFree(_encoderInstPtr);
+    _encoderInstPtr = NULL;
+  }
+  ret = WebRtcOpus_EncoderCreate(&_encoderInstPtr,
+                                 codecParams->codecInstant.channels);
+  if (ret < 0) {
+    WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, _uniqueID,
+                 "Encoder creation failed for Opus");
+    return ret;
+  }
+  ret = WebRtcOpus_SetBitRate(_encoderInstPtr, codecParams->codecInstant.rate);
+  if (ret < 0) {
+    WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, _uniqueID,
+                 "Setting initial bitrate failed for Opus");
+    return ret;
+  }
+  return 0;
+}
 
-WebRtc_Word16
-ACMOPUS::DecodeSafe(
-    WebRtc_UWord8* /* bitStream        */,
-    WebRtc_Word16  /* bitStreamLenByte */,
-    WebRtc_Word16* /* audio            */,
-    WebRtc_Word16* /* audioSamples     */,
-    WebRtc_Word8*  /* speechType       */)
-{
+int16_t ACMOpus::InternalInitDecoder(WebRtcACMCodecParams* codecParams) {
+  if (_decoderInstPtr != NULL) {
+    WebRtcOpus_DecoderFree(_decoderInstPtr);
+    _decoderInstPtr = NULL;
+  }
+  if (WebRtcOpus_DecoderCreate(&_decoderInstPtr,
+                               codecParams->codecInstant.channels) < 0) {
+    return -1;
+  }
+  return WebRtcOpus_DecoderInit(_decoderInstPtr);
+}
+
+int32_t ACMOpus::CodecDef(WebRtcNetEQ_CodecDef& codecDef,
+                          const CodecInst& codecInst) {
+  if (!_decoderInitialized) {
+    WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, _uniqueID,
+                 "CodeDef: Decoder uninitialized for Opus");
+    return -1;
+  }
+
+  // Fill up the structure by calling "SET_CODEC_PAR" & "SET_OPUS_FUNCTION."
+  // Then call NetEQ to add the codec to its database.
+  // TODO(tlegrand): Decoder is registered in NetEQ as a 32 kHz decoder, which
+  // is true until we have a full 48 kHz system, and remove the downsampling
+  // in the Opus decoder wrapper.
+  SET_CODEC_PAR((codecDef), kDecoderOpus, codecInst.pltype, _decoderInstPtr,
+                32000);
+  SET_OPUS_FUNCTIONS((codecDef));
+  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 (_encoderInstPtr) {
+    WebRtcOpus_EncoderFree(_encoderInstPtr);
+    _encoderInstPtr = NULL;
+  }
+}
+
+int16_t ACMOpus::InternalCreateDecoder() {
+  // Real decoder will be created in InternalInitDecoder
+  return 0;
+}
+
+void ACMOpus::DestructDecoderSafe() {
+  _decoderInitialized = false;
+  if (_decoderInstPtr) {
+    WebRtcOpus_DecoderFree(_decoderInstPtr);
+    _decoderInstPtr = NULL;
+  }
+}
+
+void ACMOpus::InternalDestructEncoderInst(void* ptrInst) {
+  if (ptrInst != NULL) {
+    WebRtcOpus_EncoderFree((OpusEncInst*) ptrInst);
+  }
+  return;
+}
+
+int16_t ACMOpus::SetBitRateSafe(const int32_t rate) {
+  if (rate < 6000 || rate > 510000) {
+    WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, _uniqueID,
+                 "SetBitRateSafe: Invalid rate Opus");
+    return -1;
+  }
+
+  _bitrate = rate;
+
+  // Ask the encoder for the new rate.
+  if (WebRtcOpus_SetBitRate(_encoderInstPtr, _bitrate) >= 0) {
+    _encoderParams.codecInstant.rate = _bitrate;
     return 0;
+  }
+
+  return -1;
 }
 
+#endif  // WEBRTC_CODEC_OPUS
 
-WebRtc_Word16
-ACMOPUS::InternalInitEncoder(
-    WebRtcACMCodecParams* codecParams)
-{
-    //set the bit rate and initialize
-    _myRate = codecParams->codecInstant.rate;
-    return SetBitRateSafe( (WebRtc_UWord32)_myRate);
-}
-
-
-WebRtc_Word16
-ACMOPUS::InternalInitDecoder(
-    WebRtcACMCodecParams* /* codecParams */)
-{
-    if (WebRtcOpus_DecoderInit(_decoderInstPtr) < 0)
-    {
-        WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, _uniqueID,
-                "InternalInitDecoder: init decoder failed for Opus");
-        return -1;
-    }
-    return 0;
-}
-
-
-WebRtc_Word32
-ACMOPUS::CodecDef(
-    WebRtcNetEQ_CodecDef& codecDef,
-    const CodecInst&      codecInst)
-{
-    if (!_decoderInitialized)
-    {
-        WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, _uniqueID,
-            "CodeDef: Decoder uninitialized for Opus");
-        return -1;
-    }
-
-    // Fill up the structure by calling
-    // "SET_CODEC_PAR" & "SET_G729_FUNCTION."
-    // Then call NetEQ to add the codec to it's
-    // database.
-    SET_CODEC_PAR((codecDef), kDecoderOpus, codecInst.pltype,
-        _decoderInstPtr, 16000);
-    SET_OPUS_FUNCTIONS((codecDef));
-    return 0;
-}
-
-
-ACMGenericCodec*
-ACMOPUS::CreateInstance(void)
-{
-    return NULL;
-}
-
-
-WebRtc_Word16
-ACMOPUS::InternalCreateEncoder()
-{
-    if (WebRtcOpus_CreateEnc(&_encoderInstPtr, _mySampFreq) < 0)
-    {
-        WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, _uniqueID,
-            "InternalCreateEncoder: create encoder failed for Opus");
-        return -1;
-    }
-    return 0;
-}
-
-
-void
-ACMOPUS::DestructEncoderSafe()
-{
-    _encoderExist = false;
-    _encoderInitialized = false;
-    if(_encoderInstPtr != NULL)
-    {
-        WebRtcOpus_FreeEnc(_encoderInstPtr);
-        _encoderInstPtr = NULL;
-    }
-}
-
-
-WebRtc_Word16
-ACMOPUS::InternalCreateDecoder()
-{
-   if (WebRtcOpus_CreateDec(&_decoderInstPtr, _mySampFreq) < 0)
-   {
-      WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, _uniqueID,
-        "InternalCreateDecoder: create decoder failed for Opus");
-       return -1;
-   }
-   return 0;
-}
-
-
-void
-ACMOPUS::DestructDecoderSafe()
-{
-    _decoderExist = false;
-    _decoderInitialized = false;
-    if(_decoderInstPtr != NULL)
-    {
-        WebRtcOpus_FreeDec(_decoderInstPtr);
-        _decoderInstPtr = NULL;
-    }
-}
-
-
-void
-ACMOPUS::InternalDestructEncoderInst(
-    void* ptrInst)
-{
-    if(ptrInst != NULL)
-    {
-        WebRtcOpus_FreeEnc((OPUS_inst_t*)ptrInst);
-    }
-    return;
-}
-
-WebRtc_Word16
-ACMOPUS::SetBitRateSafe(
-    const WebRtc_Word32 rate)
-{
-    //allowed rates: {8000, 12000, 14000, 16000, 18000, 20000,
-    //                22000, 24000, 26000, 28000, 30000, 32000};
-    switch(rate)
-    {
-    case 8000:
-        {
-            _myRate = 8000;
-            break;
-        }
-    case 12000:
-        {
-            _myRate = 12000;
-            break;
-        }
-    case 14000:
-        {
-            _myRate = 14000;
-            break;
-        }
-    case 16000:
-        {
-            _myRate = 16000;
-            break;
-        }
-    case 18000:
-        {
-            _myRate = 18000;
-            break;
-        }
-    case 20000:
-        {
-            _myRate = 20000;
-            break;
-        }
-    case 22000:
-        {
-            _myRate = 22000;
-            break;
-        }
-    case 24000:
-        {
-            _myRate = 24000;
-            break;
-        }
-    case 26000:
-        {
-            _myRate = 26000;
-            break;
-        }
-    case 28000:
-        {
-            _myRate = 28000;
-            break;
-        }
-    case 30000:
-        {
-            _myRate = 30000;
-            break;
-        }
-    case 32000:
-        {
-            _myRate = 32000;
-            break;
-        }
-    default:
-        {
-            WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, _uniqueID,
-                "SetBitRateSafe: Invalid rate Opus");
-            return -1;
-        }
-    }
-
-    // Re-init with new rate
-    if (WebRtcOpus_EncoderInit(_encoderInstPtr, _mySampFreq, _opusMode, _flagVBR) >= 0)
-    {
-        _encoderParams.codecInstant.rate = _myRate;
-        return 0;
-    }
-    else
-    {
-        return -1;
-    }
-}
-
-#endif
-
-} // namespace webrtc
+}  // namespace webrtc
diff --git a/src/modules/audio_coding/main/source/acm_opus.h b/src/modules/audio_coding/main/source/acm_opus.h
index c6832fa..d8baa30 100644
--- a/src/modules/audio_coding/main/source/acm_opus.h
+++ b/src/modules/audio_coding/main/source/acm_opus.h
@@ -12,68 +12,48 @@
 #define WEBRTC_MODULES_AUDIO_CODING_MAIN_SOURCE_ACM_OPUS_H_
 
 #include "acm_generic_codec.h"
+#include "opus_interface.h"
+#include "resampler.h"
 
-// forward declaration
-struct OPUS_inst_t_;
-struct OPUS_inst_t_;
+namespace webrtc {
 
-namespace webrtc
-{
+class ACMOpus : public ACMGenericCodec {
+ public:
+  ACMOpus(int16_t codecID);
+  ~ACMOpus();
 
-class ACMOPUS: public ACMGenericCodec
-{
-public:
-    ACMOPUS(WebRtc_Word16 codecID);
-    ~ACMOPUS();
-    // for FEC
-    ACMGenericCodec* CreateInstance(void);
+  ACMGenericCodec* CreateInstance(void);
 
-    WebRtc_Word16 InternalEncode(
-        WebRtc_UWord8* bitstream,
-        WebRtc_Word16* bitStreamLenByte);
+  int16_t InternalEncode(uint8_t* bitstream, int16_t* bitStreamLenByte);
 
-    WebRtc_Word16 InternalInitEncoder(
-        WebRtcACMCodecParams *codecParams);
+  int16_t InternalInitEncoder(WebRtcACMCodecParams *codecParams);
 
-    WebRtc_Word16 InternalInitDecoder(
-        WebRtcACMCodecParams *codecParams);
+  int16_t InternalInitDecoder(WebRtcACMCodecParams *codecParams);
 
-protected:
-    WebRtc_Word16 DecodeSafe(
-        WebRtc_UWord8* bitStream,
-        WebRtc_Word16  bitStreamLenByte,
-        WebRtc_Word16* audio,
-        WebRtc_Word16* audioSamples,
-        WebRtc_Word8*  speechType);
+ protected:
+  int16_t DecodeSafe(uint8_t* bitStream, int16_t bitStreamLenByte,
+                     int16_t* audio, int16_t* audioSamples, int8_t* speechType);
 
-    WebRtc_Word32 CodecDef(
-        WebRtcNetEQ_CodecDef& codecDef,
-        const CodecInst& codecInst);
+  int32_t CodecDef(WebRtcNetEQ_CodecDef& codecDef, const CodecInst& codecInst);
 
-    void DestructEncoderSafe();
+  void DestructEncoderSafe();
 
-    void DestructDecoderSafe();
+  void DestructDecoderSafe();
 
-    WebRtc_Word16 InternalCreateEncoder();
+  int16_t InternalCreateEncoder();
 
-    WebRtc_Word16 InternalCreateDecoder();
+  int16_t InternalCreateDecoder();
 
-    void InternalDestructEncoderInst(
-        void* ptrInst);
+  void InternalDestructEncoderInst(void* ptrInst);
 
-    WebRtc_Word16 SetBitRateSafe(
-        const WebRtc_Word32 rate);
+  int16_t SetBitRateSafe(const int32_t rate);
 
-    OPUS_inst_t_* _encoderInstPtr;
-    OPUS_inst_t_* _decoderInstPtr;
-
-    WebRtc_UWord16    _mySampFreq;
-    WebRtc_UWord16    _myRate;
-    WebRtc_Word16     _opusMode;
-    WebRtc_Word16     _flagVBR;
-
+  OpusEncInst* _encoderInstPtr;
+  OpusDecInst* _decoderInstPtr;
+  uint16_t _sampleFreq;
+  uint16_t _bitrate;
 };
 
-} // namespace webrtc
+}  // namespace webrtc
 
 #endif  // WEBRTC_MODULES_AUDIO_CODING_MAIN_SOURCE_ACM_OPUS_H_
diff --git a/src/modules/audio_coding/main/source/audio_coding_module.gypi b/src/modules/audio_coding/main/source/audio_coding_module.gypi
index bc9ea7d..f62ba36 100644
--- a/src/modules/audio_coding/main/source/audio_coding_module.gypi
+++ b/src/modules/audio_coding/main/source/audio_coding_module.gypi
@@ -15,6 +15,7 @@
       'iLBC',
       'iSAC',
       'iSACFix',
+      'webrtc_opus',
       'PCM16B',
       'NetEq',
       '<(webrtc_root)/common_audio/common_audio.gyp:resampler',
@@ -37,11 +38,13 @@
       'include_dirs': [
         '../interface',
         '../../../interface',
+        '../../codecs/opus/interface',
       ],
       'direct_dependent_settings': {
         'include_dirs': [
         '../interface',
         '../../../interface',
+        '../../codecs/opus/interface',
         ],
       },
       'sources': [
diff --git a/src/modules/audio_coding/main/source/audio_coding_module_impl.cc b/src/modules/audio_coding/main/source/audio_coding_module_impl.cc
index c1341b9..0a399ba 100644
--- a/src/modules/audio_coding/main/source/audio_coding_module_impl.cc
+++ b/src/modules/audio_coding/main/source/audio_coding_module_impl.cc
@@ -45,6 +45,7 @@
       _cng_nb_pltype(255),
       _cng_wb_pltype(255),
       _cng_swb_pltype(255),
+      _cng_fb_pltype(255),
       _red_pltype(255),
       _vadEnabled(false),
       _dtxEnabled(false),
@@ -112,6 +113,8 @@
         _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);
       }
     }
   }
@@ -320,6 +323,12 @@
           _isFirstRED = true;
           break;
         }
+        case kPassiveDTXFB: {
+          current_payload_type = _cng_fb_pltype;
+          frame_type = kAudioFrameCN;
+          _isFirstRED = true;
+          break;
+        }
       }
       has_data_to_send = true;
       _previousPayloadType = current_payload_type;
@@ -612,6 +621,10 @@
         _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 "
@@ -1254,6 +1267,9 @@
   CriticalSectionScoped lock(_acmCritSect);
   if (DecoderParamByPlType(_lastRecvAudioCodecPlType, codec_params) < 0) {
     return _netEq.CurrentSampFreqHz();
+  } else if (codec_params.codecInstant.plfreq == 48000) {
+    // TODO(tlegrand): Remove this option when we have full 48 kHz support.
+    return 32000;
   } else {
     return codec_params.codecInstant.plfreq;
   }
diff --git a/src/modules/audio_coding/main/source/audio_coding_module_impl.h b/src/modules/audio_coding/main/source/audio_coding_module_impl.h
index 145faf6..0e7f2f3 100644
--- a/src/modules/audio_coding/main/source/audio_coding_module_impl.h
+++ b/src/modules/audio_coding/main/source/audio_coding_module_impl.h
@@ -279,6 +279,7 @@
   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 _vadEnabled;
   bool _dtxEnabled;
diff --git a/src/modules/audio_coding/main/test/TestAllCodecs.cc b/src/modules/audio_coding/main/test/TestAllCodecs.cc
index b312390..89a9829 100644
--- a/src/modules/audio_coding/main/test/TestAllCodecs.cc
+++ b/src/modules/audio_coding/main/test/TestAllCodecs.cc
@@ -614,6 +614,28 @@
   Run(channel_a_to_b_);
   outfile_b_.Close();
 #endif
+#ifdef WEBRTC_CODEC_OPUS
+  if (test_mode_ != 0) {
+    printf("===============================================================\n");
+  }
+  test_count_++;
+  OpenOutFile(test_count_);
+  char codec_opus[] = "OPUS";
+  RegisterSendCodec('A', codec_opus, 48000, 6000, 960, -1);
+  Run(channel_a_to_b_);
+  RegisterSendCodec('A', codec_opus, 48000, 20000, 960, -1);
+  Run(channel_a_to_b_);
+  RegisterSendCodec('A', codec_opus, 48000, 32000, 960, -1);
+  Run(channel_a_to_b_);
+  RegisterSendCodec('A', codec_opus, 48000, 48000, 960, -1);
+  Run(channel_a_to_b_);
+  RegisterSendCodec('A', codec_opus, 48000, 64000, 960, -1);
+  Run(channel_a_to_b_);
+  RegisterSendCodec('A', codec_opus, 48000, 96000, 960, -1);
+  Run(channel_a_to_b_);
+  RegisterSendCodec('A', codec_opus, 48000, 500000, 960, -1);
+  Run(channel_a_to_b_);
+#endif
   if (test_mode_ != 0) {
     printf("===============================================================\n");
 
diff --git a/src/modules/audio_coding/main/test/TestVADDTX.cc b/src/modules/audio_coding/main/test/TestVADDTX.cc
index 793ab579..fcca374 100644
--- a/src/modules/audio_coding/main/test/TestVADDTX.cc
+++ b/src/modules/audio_coding/main/test/TestVADDTX.cc
@@ -138,6 +138,21 @@
     _outFileB.Close();
 
 #endif
+#ifdef WEBRTC_CODEC_OPUS
+    // Open outputfile
+    OpenOutFile(testCntr++);
+
+    // Register Opus as send codec
+    char nameOPUS[] = "opus";
+    RegisterSendCodec('A', nameOPUS);
+
+    // Run the five test cased
+    runTestCases();
+
+    // Close file
+    _outFileB.Close();
+
+#endif
     if(_testMode) {
         printf("Done!\n");
     }
diff --git a/src/modules/audio_coding/neteq/codec_db.c b/src/modules/audio_coding/neteq/codec_db.c
index 5369cfd..ebc9216 100644
--- a/src/modules/audio_coding/neteq/codec_db.c
+++ b/src/modules/audio_coding/neteq/codec_db.c
@@ -84,7 +84,7 @@
 #ifdef NETEQ_32KHZ_WIDEBAND
     &&(codec_fs!=32000)
 #endif
-#ifdef NETEQ_48KHZ_WIDEBAND
+#if defined(NETEQ_48KHZ_WIDEBAND) || defined(NETEQ_OPUS_CODEC)
     &&(codec_fs!=48000)
 #endif
     )
@@ -114,6 +114,9 @@
 #ifdef NETEQ_ISAC_SWB_CODEC
         case kDecoderISACswb :
 #endif
+#ifdef NETEQ_OPUS_CODEC
+        case kDecoderOpus :
+#endif
 #ifdef NETEQ_G722_CODEC
         case kDecoderG722 :
         case kDecoderG722_2ch :
@@ -458,6 +461,9 @@
 #ifdef NETEQ_ISAC_SWB_CODEC
         case kDecoderISACswb:
 #endif
+#ifdef NETEQ_OPUS_CODEC
+        case kDecoderOpus:
+#endif
 #ifdef NETEQ_ARBITRARY_CODEC
         case kDecoderArbitrary:
 #endif
diff --git a/src/modules/audio_coding/neteq/interface/webrtc_neteq.h b/src/modules/audio_coding/neteq/interface/webrtc_neteq.h
index 39f6595..9fc8297 100644
--- a/src/modules/audio_coding/neteq/interface/webrtc_neteq.h
+++ b/src/modules/audio_coding/neteq/interface/webrtc_neteq.h
@@ -62,6 +62,7 @@
     kDecoderG722_1C_24,
     kDecoderG722_1C_32,
     kDecoderG722_1C_48,
+    kDecoderOpus,
     kDecoderSPEEX_8,
     kDecoderSPEEX_16,
     kDecoderCELT_32,
diff --git a/src/modules/audio_coding/neteq/interface/webrtc_neteq_help_macros.h b/src/modules/audio_coding/neteq/interface/webrtc_neteq_help_macros.h
index c6f19bb..d885faa 100644
--- a/src/modules/audio_coding/neteq/interface/webrtc_neteq_help_macros.h
+++ b/src/modules/audio_coding/neteq/interface/webrtc_neteq_help_macros.h
@@ -151,7 +151,6 @@
                     inst.funcUpdBWEst=NULL; \
                     inst.funcGetErrorCode=NULL;
 
-
 #define SET_PCM16B_SWB48_FUNCTIONS(inst) \
                     inst.funcDecode=(WebRtcNetEQ_FuncDecode)WebRtcPcm16b_DecodeW16; \
                     inst.funcDecodeRCU=NULL; \
@@ -317,6 +316,17 @@
                     inst.funcUpdBWEst=NULL; \
                     inst.funcGetErrorCode=NULL;
 
+#define SET_OPUS_FUNCTIONS(inst) \
+                    inst.funcDecode=(WebRtcNetEQ_FuncDecode)WebRtcOpus_Decode; \
+                    inst.funcDecodeRCU=NULL; \
+                    inst.funcDecodePLC=NULL; \
+                    inst.funcDecodeInit=(WebRtcNetEQ_FuncDecodeInit)WebRtcOpus_DecoderInit; \
+                    inst.funcAddLatePkt=NULL; \
+                    inst.funcGetMDinfo=NULL; \
+                    inst.funcGetPitch=NULL; \
+                    inst.funcUpdBWEst=NULL; \
+                    inst.funcGetErrorCode=NULL;
+
 #define SET_SPEEX_FUNCTIONS(inst) \
                     inst.funcDecode=(WebRtcNetEQ_FuncDecode)WebRtcSpeex_Decode; \
                     inst.funcDecodeRCU=NULL; \
diff --git a/src/modules/audio_coding/neteq/neteq_defines.h b/src/modules/audio_coding/neteq/neteq_defines.h
index 318e6bb..79cb144 100644
--- a/src/modules/audio_coding/neteq/neteq_defines.h
+++ b/src/modules/audio_coding/neteq/neteq_defines.h
@@ -77,6 +77,8 @@
  *
  * NETEQ_G722_1C_CODEC            Enable G722.1 Annex C
  *
+ * NETEQ_OPUS_CODEC               Enable Opus
+ *
  * NETEQ_SPEEX_CODEC              Enable Speex (at 8 and 16 kHz sample rate)
  *
  * NETEQ_CELT_CODEC               Enable Celt (at 32 kHz sample rate)
@@ -244,6 +246,7 @@
     #define NETEQ_G729_CODEC
     #define NETEQ_G726_CODEC
     #define NETEQ_GSMFR_CODEC
+    #define NETEQ_OPUS_CODEC
     #define NETEQ_AMR_CODEC
 #endif
 
@@ -252,6 +255,7 @@
     #define NETEQ_G722_CODEC
     #define NETEQ_G722_1_CODEC
     #define NETEQ_G729_1_CODEC
+    #define NETEQ_OPUS_CODEC
     #define NETEQ_SPEEX_CODEC
     #define NETEQ_AMRWB_CODEC
     #define NETEQ_WIDEBAND
@@ -262,6 +266,7 @@
     #define NETEQ_32KHZ_WIDEBAND
     #define NETEQ_G722_1C_CODEC
     #define NETEQ_CELT_CODEC
+    #define NETEQ_OPUS_CODEC
 #endif
 
 #if (defined(NETEQ_VOICEENGINE_CODECS))
@@ -295,6 +300,8 @@
     #define NETEQ_G722_1C_CODEC
     #define NETEQ_CELT_CODEC
 
+    /* Fullband 48 kHz codecs */
+    #define NETEQ_OPUS_CODEC
 #endif 
 
 #if (defined(NETEQ_ALL_CODECS))
@@ -331,21 +338,26 @@
 
     /* Super wideband 48kHz codecs */
     #define NETEQ_48KHZ_WIDEBAND
+    #define NETEQ_OPUS_CODEC
 #endif
 
 /* Max output size from decoding one frame */
 #if defined(NETEQ_48KHZ_WIDEBAND)
-    #define NETEQ_MAX_FRAME_SIZE     2880    /* 60 ms super wideband */
-    #define NETEQ_MAX_OUTPUT_SIZE    3600    /* 60+15 ms super wideband (60 ms decoded + 15 ms for merge overlap) */
+    #define NETEQ_MAX_FRAME_SIZE 5760  /* 120 ms super wideband */
+    #define NETEQ_MAX_OUTPUT_SIZE 6480  /* 120+15 ms super wideband (120 ms
+                                         * decoded + 15 ms for merge overlap) */
 #elif defined(NETEQ_32KHZ_WIDEBAND)
-    #define NETEQ_MAX_FRAME_SIZE     1920    /* 60 ms super wideband */
-    #define NETEQ_MAX_OUTPUT_SIZE    2400    /* 60+15 ms super wideband (60 ms decoded + 15 ms for merge overlap) */
+    #define NETEQ_MAX_FRAME_SIZE 3840  /* 120 ms super wideband */
+    #define NETEQ_MAX_OUTPUT_SIZE 4320  /* 120+15 ms super wideband (120 ms
+                                         * decoded + 15 ms for merge overlap) */
 #elif defined(NETEQ_WIDEBAND)
-    #define NETEQ_MAX_FRAME_SIZE     960        /* 60 ms wideband */
-    #define NETEQ_MAX_OUTPUT_SIZE    1200    /* 60+15 ms wideband (60 ms decoded + 10 ms for merge overlap) */
+    #define NETEQ_MAX_FRAME_SIZE 1920  /* 120 ms wideband */
+    #define NETEQ_MAX_OUTPUT_SIZE 2160  /* 120+15 ms wideband (120 ms decoded +
+                                         * 15 ms for merge overlap) */
 #else
-    #define NETEQ_MAX_FRAME_SIZE     480        /* 60 ms narrowband */
-    #define NETEQ_MAX_OUTPUT_SIZE    600        /* 60+15 ms narrowband (60 ms decoded + 10 ms for merge overlap) */
+    #define NETEQ_MAX_FRAME_SIZE 960  /* 120 ms narrowband */
+    #define NETEQ_MAX_OUTPUT_SIZE 1080  /* 120+15 ms narrowband (120 ms decoded
+                                         * + 15 ms for merge overlap) */
 #endif
 
 
diff --git a/src/modules/audio_coding/neteq/packet_buffer.c b/src/modules/audio_coding/neteq/packet_buffer.c
index 8f09b07..7fbea58 100644
--- a/src/modules/audio_coding/neteq/packet_buffer.c
+++ b/src/modules/audio_coding/neteq/packet_buffer.c
@@ -578,6 +578,11 @@
             codecBytes = 1560; /* 240ms @ 52kbps (30ms frames) */
             codecBuffers = 8;
         }
+        else if (codecID[i] == kDecoderOpus)
+        {
+            codecBytes = 15300; /* 240ms @ 510kbps (60ms frames) */
+            codecBuffers = 30;  /* Replicating the value for PCMu/a */
+        }
         else if ((codecID[i] == kDecoderPCM16B) ||
             (codecID[i] == kDecoderPCM16B_2ch))
         {
diff --git a/src/modules/audio_coding/neteq/recin.c b/src/modules/audio_coding/neteq/recin.c
index bce7c48..399250d 100644
--- a/src/modules/audio_coding/neteq/recin.c
+++ b/src/modules/audio_coding/neteq/recin.c
@@ -202,6 +202,13 @@
             /* Get CNG sample rate */
             WebRtc_UWord16 fsCng = WebRtcNetEQ_DbGetSampleRate(&MCU_inst->codec_DB_inst,
                 RTPpacket[i_k].payloadType);
+
+            /* Force sampling frequency to 32000 Hz CNG 48000 Hz. */
+            /* TODO(tlegrand): remove limitation once ACM has full 48 kHz
+             * support. */
+            if (fsCng > 32000) {
+                fsCng = 32000;
+            }
             if ((fsCng != MCU_inst->fs) && (fsCng > 8000))
             {
                 /*
@@ -370,10 +377,29 @@
             MCU_inst->scalingFactor = kTSscalingTwo;
             break;
         }
+        case kDecoderOpus:
+        {
+            /* We resample Opus internally to 32 kHz, but timestamps
+             * are counted at 48 kHz. So there are two output samples
+             * per three RTP timestamp ticks. */
+            MCU_inst->scalingFactor = kTSscalingTwoThirds;
+            break;
+        }
+
         case kDecoderAVT:
         case kDecoderCNG:
         {
-            /* do not change the timestamp scaling settings */
+            /* TODO(tlegrand): remove scaling once ACM has full 48 kHz
+             * support. */
+            WebRtc_UWord16 sample_freq =
+                WebRtcNetEQ_DbGetSampleRate(&MCU_inst->codec_DB_inst,
+                                            rtpPayloadType);
+            if (sample_freq == 48000) {
+              MCU_inst->scalingFactor = kTSscalingTwoThirds;
+            }
+
+            /* For sample_freq <= 32 kHz, do not change the timestamp scaling
+             * settings. */
             break;
         }
         default:
diff --git a/src/modules/audio_coding/neteq/recout.c b/src/modules/audio_coding/neteq/recout.c
index eb80f2d..1f47945 100644
--- a/src/modules/audio_coding/neteq/recout.c
+++ b/src/modules/audio_coding/neteq/recout.c
@@ -41,8 +41,8 @@
 /* Scratch usage:
 
  Type           Name                            size             startpos      endpos
- WebRtc_Word16  pw16_NetEqAlgorithm_buffer      600*fs/8000      0             600*fs/8000-1
- struct         dspInfo                         6                600*fs/8000   605*fs/8000
+ WebRtc_Word16  pw16_NetEqAlgorithm_buffer      1080*fs/8000     0             1080*fs/8000-1
+ struct         dspInfo                         6                1080*fs/8000  1085*fs/8000
 
  func           WebRtcNetEQ_Normal              40+495*fs/8000   0             39+495*fs/8000
  func           WebRtcNetEQ_Merge               40+496*fs/8000   0             39+496*fs/8000
@@ -50,7 +50,7 @@
  func           WebRtcNetEQ_Accelerate          210              240*fs/8000   209+240*fs/8000
  func           WebRtcNetEQ_BGNUpdate           69               480*fs/8000   68+480*fs/8000
 
- Total:  605*fs/8000
+ Total:  1086*fs/8000
  */
 
 #define SCRATCH_ALGORITHM_BUFFER            0
@@ -58,35 +58,35 @@
 #define SCRATCH_NETEQ_MERGE                 0
 
 #if (defined(NETEQ_48KHZ_WIDEBAND)) 
-#define SCRATCH_DSP_INFO                     3600
+#define SCRATCH_DSP_INFO                     6480
 #define SCRATCH_NETEQ_ACCELERATE            1440
 #define SCRATCH_NETEQ_BGN_UPDATE            2880
 #define SCRATCH_NETEQ_EXPAND                756
 #elif (defined(NETEQ_32KHZ_WIDEBAND)) 
-#define SCRATCH_DSP_INFO                     2400
+#define SCRATCH_DSP_INFO                     4320
 #define SCRATCH_NETEQ_ACCELERATE            960
 #define SCRATCH_NETEQ_BGN_UPDATE            1920
 #define SCRATCH_NETEQ_EXPAND                504
 #elif (defined(NETEQ_WIDEBAND)) 
-#define SCRATCH_DSP_INFO                     1200
+#define SCRATCH_DSP_INFO                     2160
 #define SCRATCH_NETEQ_ACCELERATE            480
 #define SCRATCH_NETEQ_BGN_UPDATE            960
 #define SCRATCH_NETEQ_EXPAND                252
 #else    /* NB */
-#define SCRATCH_DSP_INFO                     600
+#define SCRATCH_DSP_INFO                     1080
 #define SCRATCH_NETEQ_ACCELERATE            240
 #define SCRATCH_NETEQ_BGN_UPDATE            480
 #define SCRATCH_NETEQ_EXPAND                126
 #endif
 
 #if (defined(NETEQ_48KHZ_WIDEBAND)) 
-#define SIZE_SCRATCH_BUFFER                 3636
+#define SIZE_SCRATCH_BUFFER                 6516
 #elif (defined(NETEQ_32KHZ_WIDEBAND)) 
-#define SIZE_SCRATCH_BUFFER                 2424
+#define SIZE_SCRATCH_BUFFER                 4344
 #elif (defined(NETEQ_WIDEBAND)) 
-#define SIZE_SCRATCH_BUFFER                 1212
+#define SIZE_SCRATCH_BUFFER                 2172
 #else    /* NB */
-#define SIZE_SCRATCH_BUFFER                 606
+#define SIZE_SCRATCH_BUFFER                 1086
 #endif
 
 #ifdef NETEQ_DELAY_LOGGING
@@ -110,13 +110,15 @@
 #ifdef SCRATCH
     char pw8_ScratchBuffer[((SIZE_SCRATCH_BUFFER + 1) * 2)];
     WebRtc_Word16 *pw16_scratchPtr = (WebRtc_Word16*) pw8_ScratchBuffer;
-    WebRtc_Word16 pw16_decoded_buffer[NETEQ_MAX_FRAME_SIZE];
+    /* pad with 240*fs_mult to match the overflow guard below */
+    WebRtc_Word16 pw16_decoded_buffer[NETEQ_MAX_FRAME_SIZE+240*6];
     WebRtc_Word16 *pw16_NetEqAlgorithm_buffer = pw16_scratchPtr
         + SCRATCH_ALGORITHM_BUFFER;
     DSP2MCU_info_t *dspInfo = (DSP2MCU_info_t*) (pw16_scratchPtr + SCRATCH_DSP_INFO);
 #else
-    WebRtc_Word16 pw16_decoded_buffer[NETEQ_MAX_FRAME_SIZE];
-    WebRtc_Word16 pw16_NetEqAlgorithm_buffer[NETEQ_MAX_OUTPUT_SIZE];
+    /* pad with 240*fs_mult to match the overflow guard below */
+    WebRtc_Word16 pw16_decoded_buffer[NETEQ_MAX_FRAME_SIZE+240*6];
+    WebRtc_Word16 pw16_NetEqAlgorithm_buffer[NETEQ_MAX_OUTPUT_SIZE+240*6];
     DSP2MCU_info_t dspInfoStruct;
     DSP2MCU_info_t *dspInfo = &dspInfoStruct;
 #endif
diff --git a/src/modules/audio_coding/neteq/signal_mcu.c b/src/modules/audio_coding/neteq/signal_mcu.c
index b28f39c..2cccf1a 100644
--- a/src/modules/audio_coding/neteq/signal_mcu.c
+++ b/src/modules/audio_coding/neteq/signal_mcu.c
@@ -319,7 +319,13 @@
                 WebRtc_UWord16 tempFs;
 
                 tempFs = WebRtcNetEQ_DbGetSampleRate(&inst->codec_DB_inst, payloadType);
-                if (tempFs > 0)
+                /* TODO(tlegrand): Remove this limitation once ACM has full
+                 * 48 kHz support. */
+                if (tempFs > 32000)
+                {
+                    inst->fs = 32000;
+                }
+                else if (tempFs > 0)
                 {
                     inst->fs = tempFs;
                 }
diff --git a/src/modules/audio_conference_mixer/interface/audio_conference_mixer.h b/src/modules/audio_conference_mixer/interface/audio_conference_mixer.h
index 4ece1bf..9ffac2d 100644
--- a/src/modules/audio_conference_mixer/interface/audio_conference_mixer.h
+++ b/src/modules/audio_conference_mixer/interface/audio_conference_mixer.h
@@ -30,6 +30,7 @@
         kNbInHz           = 8000,
         kWbInHz           = 16000,
         kSwbInHz          = 32000,
+        kFbInHz           = 48000,
         kLowestPossible   = -1,
         kDefaultFrequency = kWbInHz
     };
diff --git a/src/modules/audio_conference_mixer/source/audio_conference_mixer_impl.cc b/src/modules/audio_conference_mixer/source/audio_conference_mixer_impl.cc
index 851642c..1fdd9dc 100644
--- a/src/modules/audio_conference_mixer/source/audio_conference_mixer_impl.cc
+++ b/src/modules/audio_conference_mixer/source/audio_conference_mixer_impl.cc
@@ -282,6 +282,12 @@
                     SetOutputFrequency(kSwbInHz);
                 }
                 break;
+            case 48000:
+                if(OutputFrequency() != kFbInHz)
+                {
+                    SetOutputFrequency(kFbInHz);
+                }
+                break;
             default:
                 assert(false);
 
diff --git a/src/modules/modules.gyp b/src/modules/modules.gyp
index 089f538..a5b31c6 100644
--- a/src/modules/modules.gyp
+++ b/src/modules/modules.gyp
@@ -15,6 +15,7 @@
     'audio_coding/codecs/ilbc/ilbc.gypi',
     'audio_coding/codecs/isac/main/source/isac.gypi',
     'audio_coding/codecs/isac/fix/source/isacfix.gypi',
+    'audio_coding/codecs/opus/opus.gypi',
     'audio_coding/codecs/pcm16b/pcm16b.gypi',
     'audio_coding/main/source/audio_coding_module.gypi',
     'audio_coding/neteq/neteq.gypi',
diff --git a/src/modules/rtp_rtcp/source/rtp_receiver_audio.cc b/src/modules/rtp_rtcp/source/rtp_receiver_audio.cc
index a57da75..c9fd3df 100644
--- a/src/modules/rtp_rtcp/source/rtp_receiver_audio.cc
+++ b/src/modules/rtp_rtcp/source/rtp_receiver_audio.cc
@@ -27,6 +27,7 @@
     _cngNBPayloadType(-1),
     _cngWBPayloadType(-1),
     _cngSWBPayloadType(-1),
+    _cngFBPayloadType(-1),
     _cngPayloadType(-1),
     _G722PayloadType(-1),
     _lastReceivedG722(false),
@@ -94,7 +95,7 @@
 RTPReceiverAudio::CNGPayloadType(const WebRtc_Word8 payloadType,
                                  WebRtc_UWord32& frequency)
 {
-    //  we can have three CNG on 8000Hz, 16000Hz and 32000Hz
+    //  We can have four CNG on 8000Hz, 16000Hz, 32000Hz and 48000Hz.
     if(_cngNBPayloadType == payloadType)
     {
         frequency = 8000;
@@ -129,6 +130,15 @@
         }
         _cngPayloadType = _cngSWBPayloadType;
         return true;
+    }else if(_cngFBPayloadType == payloadType)
+    {
+        frequency = 48000;
+        if ((_cngPayloadType != -1) &&(_cngPayloadType !=_cngFBPayloadType))
+        {
+            ResetStatistics();
+        }
+        _cngPayloadType = _cngFBPayloadType;
+        return true;
     }else
     {
         //  not CNG
@@ -195,6 +205,8 @@
       _cngWBPayloadType = payloadType;
     } else if(frequency == 32000) {
       _cngSWBPayloadType = payloadType;
+    } else if(frequency == 48000) {
+      _cngFBPayloadType = payloadType;
     } else {
       assert(false);
       return NULL;
diff --git a/src/modules/rtp_rtcp/source/rtp_receiver_audio.h b/src/modules/rtp_rtcp/source/rtp_receiver_audio.h
index 0b0ba30..e256dd1 100644
--- a/src/modules/rtp_rtcp/source/rtp_receiver_audio.h
+++ b/src/modules/rtp_rtcp/source/rtp_receiver_audio.h
@@ -81,6 +81,7 @@
     WebRtc_Word8              _cngNBPayloadType;
     WebRtc_Word8              _cngWBPayloadType;
     WebRtc_Word8              _cngSWBPayloadType;
+    WebRtc_Word8              _cngFBPayloadType;
     WebRtc_Word8                _cngPayloadType;
 
     // G722 is special since it use the wrong number of RTP samples in timestamp VS. number of samples in the frame
diff --git a/src/modules/rtp_rtcp/source/rtp_sender_audio.cc b/src/modules/rtp_rtcp/source/rtp_sender_audio.cc
index 0f6f69f..0c422de 100644
--- a/src/modules/rtp_rtcp/source/rtp_sender_audio.cc
+++ b/src/modules/rtp_rtcp/source/rtp_sender_audio.cc
@@ -38,6 +38,7 @@
     _cngNBPayloadType(-1),
     _cngWBPayloadType(-1),
     _cngSWBPayloadType(-1),
+    _cngFBPayloadType(-1),
     _lastPayloadType(-1),
     _includeAudioLevelIndication(false),    // @TODO - reset at Init()?
     _audioLevelIndicationID(0),
@@ -101,6 +102,10 @@
 
     } else if (frequency == 32000) {
       _cngSWBPayloadType = payloadType;
+
+    } else if (frequency == 48000) {
+      _cngFBPayloadType = payloadType;
+
     } else {
       return -1;
     }
@@ -159,6 +164,15 @@
                 return false;
             }
         }
+        if(_cngFBPayloadType != -1)
+        {
+            // we have configured SWB CNG
+            if(_cngFBPayloadType == payloadType)
+            {
+                // only set a marker bit when we change payload type to a non CNG
+                return false;
+            }
+        }
         // payloadType differ
         if(_lastPayloadType == -1)
         {
diff --git a/src/modules/rtp_rtcp/source/rtp_sender_audio.h b/src/modules/rtp_rtcp/source/rtp_sender_audio.h
index 5974441..fe9a952 100644
--- a/src/modules/rtp_rtcp/source/rtp_sender_audio.h
+++ b/src/modules/rtp_rtcp/source/rtp_sender_audio.h
@@ -117,6 +117,7 @@
     WebRtc_Word8      _cngNBPayloadType;
     WebRtc_Word8      _cngWBPayloadType;
     WebRtc_Word8      _cngSWBPayloadType;
+    WebRtc_Word8      _cngFBPayloadType;
     WebRtc_Word8      _lastPayloadType;
 
     // Audio level indication (https://datatracker.ietf.org/doc/draft-lennox-avt-rtp-audio-level-exthdr/)
diff --git a/src/voice_engine/channel.cc b/src/voice_engine/channel.cc
index b4889e2..4370b74 100644
--- a/src/voice_engine/channel.cc
+++ b/src/voice_engine/channel.cc
@@ -6403,12 +6403,12 @@
     }
 
     WebRtc_Word32 playoutFrequency = _audioCodingModule.PlayoutFrequency();
-    if (_audioCodingModule.ReceiveCodec(currRecCodec) == 0)
-    {
-        if (STR_CASE_CMP("G722", currRecCodec.plname) == 0)
-        {
-            playoutFrequency = 8000;
-        }
+    if (_audioCodingModule.ReceiveCodec(currRecCodec) == 0) {
+      if (STR_CASE_CMP("G722", currRecCodec.plname) == 0) {
+        playoutFrequency = 8000;
+      } else if (STR_CASE_CMP("opus", currRecCodec.plname) == 0) {
+        playoutFrequency = 48000;
+      }
     }
     timestamp -= (delayMS * (playoutFrequency/1000));
 
@@ -6482,16 +6482,20 @@
     rtpReceiveFrequency = _audioCodingModule.ReceiveFrequency();
 
     CodecInst currRecCodec;
-    if (_audioCodingModule.ReceiveCodec(currRecCodec) == 0)
-    {
-        if (STR_CASE_CMP("G722", currRecCodec.plname) == 0)
-        {
-            // Even though the actual sampling rate for G.722 audio is
-            // 16,000 Hz, the RTP clock rate for the G722 payload format is
-            // 8,000 Hz because that value was erroneously assigned in
-            // RFC 1890 and must remain unchanged for backward compatibility.
-            rtpReceiveFrequency = 8000;
-        }
+    if (_audioCodingModule.ReceiveCodec(currRecCodec) == 0) {
+      if (STR_CASE_CMP("G722", currRecCodec.plname) == 0) {
+        // Even though the actual sampling rate for G.722 audio is
+        // 16,000 Hz, the RTP clock rate for the G722 payload format is
+        // 8,000 Hz because that value was erroneously assigned in
+        // RFC 1890 and must remain unchanged for backward compatibility.
+        rtpReceiveFrequency = 8000;
+      } else if (STR_CASE_CMP("opus", currRecCodec.plname) == 0) {
+        // We are resampling Opus internally to 32,000 Hz until all our
+        // DSP routines can operate at 48,000 Hz, but the RTP clock
+        // rate for the Opus payload format is standardized to 48,000 Hz,
+        // because that is the maximum supported decoding sampling rate.
+        rtpReceiveFrequency = 48000;
+      }
     }
 
     const WebRtc_UWord32 timeStampDiff = timestamp - _playoutTimeStampRTP;
@@ -6499,24 +6503,25 @@
 
     if (timeStampDiff > 0)
     {
-        switch (rtpReceiveFrequency)
-        {
-            case 8000:
-                timeStampDiffMs = timeStampDiff >> 3;
-                break;
-            case 16000:
-                timeStampDiffMs = timeStampDiff >> 4;
-                break;
-            case 32000:
-                timeStampDiffMs = timeStampDiff >> 5;
-                break;
-            default:
-                WEBRTC_TRACE(kTraceWarning, kTraceVoice,
-                             VoEId(_instanceId, _channelId),
-                             "Channel::UpdatePacketDelay() invalid sample "
-                             "rate");
-                timeStampDiffMs = 0;
-                return -1;
+        switch (rtpReceiveFrequency) {
+          case 8000:
+            timeStampDiffMs = static_cast<WebRtc_UWord32>(timeStampDiff >> 3);
+            break;
+          case 16000:
+            timeStampDiffMs = static_cast<WebRtc_UWord32>(timeStampDiff >> 4);
+            break;
+          case 32000:
+            timeStampDiffMs = static_cast<WebRtc_UWord32>(timeStampDiff >> 5);
+            break;
+          case 48000:
+            timeStampDiffMs = static_cast<WebRtc_UWord32>(timeStampDiff / 48);
+            break;
+          default:
+            WEBRTC_TRACE(kTraceWarning, kTraceVoice,
+                         VoEId(_instanceId, _channelId),
+                         "Channel::UpdatePacketDelay() invalid sample rate");
+            timeStampDiffMs = 0;
+            return -1;
         }
         if (timeStampDiffMs > 5000)
         {
@@ -6539,20 +6544,23 @@
         if (sequenceNumber - _previousSequenceNumber == 1)
         {
             WebRtc_UWord16 packetDelayMs = 0;
-            switch (rtpReceiveFrequency)
-            {
-            case 8000:
-                packetDelayMs = (WebRtc_UWord16)(
+            switch (rtpReceiveFrequency) {
+              case 8000:
+                packetDelayMs = static_cast<WebRtc_UWord16>(
                     (timestamp - _previousTimestamp) >> 3);
                 break;
-            case 16000:
-                packetDelayMs = (WebRtc_UWord16)(
+              case 16000:
+                packetDelayMs = static_cast<WebRtc_UWord16>(
                     (timestamp - _previousTimestamp) >> 4);
                 break;
-            case 32000:
-                packetDelayMs = (WebRtc_UWord16)(
+              case 32000:
+                packetDelayMs = static_cast<WebRtc_UWord16>(
                     (timestamp - _previousTimestamp) >> 5);
                 break;
+              case 48000:
+                packetDelayMs = static_cast<WebRtc_UWord16>(
+                    (timestamp - _previousTimestamp) / 48);
+                break;
             }
 
             if (packetDelayMs >= 10 && packetDelayMs <= 60)
diff --git a/src/voice_engine/transmit_mixer.cc b/src/voice_engine/transmit_mixer.cc
index 6153c5b..d987c4e 100644
--- a/src/voice_engine/transmit_mixer.cc
+++ b/src/voice_engine/transmit_mixer.cc
@@ -322,8 +322,14 @@
 
       if (codec.channels == 2)
         stereo_codec_ = true;
-      if (codec.plfreq > _mixingFrequency)
+
+      // TODO(tlegrand): Remove once we have full 48 kHz support in
+      // Audio Coding Module.
+      if (codec.plfreq > 32000) {
+        _mixingFrequency = 32000;
+      } else if (codec.plfreq > _mixingFrequency) {
         _mixingFrequency = codec.plfreq;
+      }
     }
     channel = sc.GetNextChannel(iterator);
   }
diff --git a/third_party/opus/opus.gyp b/third_party/opus/opus.gyp
new file mode 100644
index 0000000..88c826a
--- /dev/null
+++ b/third_party/opus/opus.gyp
@@ -0,0 +1,184 @@
+# 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.
+
+{
+  'targets': [
+    {
+      'target_name': 'opus',
+      'type': 'static_library',
+      'defines': [
+        'OPUS_BUILD',
+      ],
+      'conditions': [
+        ['OS=="linux"', {
+          'cflags': [
+            '-std=c99',
+          ],
+        }],
+        ['OS != "win"', {
+          'defines': [
+            'HAVE_LRINTF',
+            'VAR_ARRAYS',
+          ],
+        }],
+        ['OS == "win"', {
+          'defines': [
+            'USE_ALLOCA',
+            ['inline','__inline'],
+          ],
+          'msvs_disabled_warnings':[
+            4305, # Disable truncation warning in /source/celt/pitch.c[line 80]
+          ],
+        }],
+      ],
+      'include_dirs': [
+        'source/celt',
+        'source/include',
+        'source/silk',
+        'source/silk/float',
+        'source/src',
+      ],
+      'sources': [
+        # opus wrapper/glue
+        'source/src/opus.c',
+        'source/src/opus_decoder.c',
+        'source/src/opus_encoder.c',
+        'source/src/repacketizer.c',
+
+        # celt sub-codec
+        'source/celt/bands.c',
+        'source/celt/celt.c',
+        'source/celt/celt_lpc.c',
+        'source/celt/cwrs.c',
+        'source/celt/entcode.c',
+        'source/celt/entdec.c',
+        'source/celt/entenc.c',
+        'source/celt/kiss_fft.c',
+        'source/celt/laplace.c',
+        'source/celt/mathops.c',
+        'source/celt/mdct.c',
+        'source/celt/modes.c',
+        'source/celt/pitch.c',
+        'source/celt/quant_bands.c',
+        'source/celt/rate.c',
+        'source/celt/vq.c',
+
+        # silk sub-codec
+        'source/silk/A2NLSF.c',
+        'source/silk/ana_filt_bank_1.c',
+        'source/silk/biquad_alt.c',
+        'source/silk/bwexpander.c',
+        'source/silk/bwexpander_32.c',
+        'source/silk/check_control_input.c',
+        'source/silk/CNG.c',
+        'source/silk/code_signs.c',
+        'source/silk/control_audio_bandwidth.c',
+        'source/silk/control_codec.c',
+        'source/silk/control_SNR.c',
+        'source/silk/debug.c',
+        'source/silk/decode_core.c',
+        'source/silk/decode_frame.c',
+        'source/silk/decode_indices.c',
+        'source/silk/decode_parameters.c',
+        'source/silk/decode_pitch.c',
+        'source/silk/decode_pulses.c',
+        'source/silk/decoder_set_fs.c',
+        'source/silk/dec_API.c',
+        'source/silk/enc_API.c',
+        'source/silk/encode_indices.c',
+        'source/silk/encode_pulses.c',
+        'source/silk/gain_quant.c',
+        'source/silk/HP_variable_cutoff.c',
+        'source/silk/init_decoder.c',
+        'source/silk/init_encoder.c',
+        'source/silk/inner_prod_aligned.c',
+        'source/silk/interpolate.c',
+        'source/silk/lin2log.c',
+        'source/silk/log2lin.c',
+        'source/silk/LPC_analysis_filter.c',
+        'source/silk/LPC_inv_pred_gain.c',
+        'source/silk/LP_variable_cutoff.c',
+        'source/silk/NLSF2A.c',
+        'source/silk/NLSF_decode.c',
+        'source/silk/NLSF_encode.c',
+        'source/silk/NLSF_del_dec_quant.c',
+        'source/silk/NLSF_stabilize.c',
+        'source/silk/NLSF_unpack.c',
+        'source/silk/NLSF_VQ.c',
+        'source/silk/NLSF_VQ_weights_laroia.c',
+        'source/silk/NSQ.c',
+        'source/silk/NSQ_del_dec.c',
+        'source/silk/pitch_est_tables.c',
+        'source/silk/PLC.c',
+        'source/silk/process_NLSFs.c',
+        'source/silk/quant_LTP_gains.c',
+        'source/silk/resampler.c',
+        'source/silk/resampler_down2.c',
+        'source/silk/resampler_down2_3.c',
+        'source/silk/resampler_private_AR2.c',
+        'source/silk/resampler_private_down_FIR.c',
+        'source/silk/resampler_private_IIR_FIR.c',
+        'source/silk/resampler_private_up2_HQ.c',
+        'source/silk/resampler_rom.c',
+        'source/silk/shell_coder.c',
+        'source/silk/sigm_Q15.c',
+        'source/silk/sort.c',
+        'source/silk/stereo_decode_pred.c',
+        'source/silk/stereo_encode_pred.c',
+        'source/silk/stereo_find_predictor.c',
+        'source/silk/stereo_LR_to_MS.c',
+        'source/silk/stereo_MS_to_LR.c',
+        'source/silk/stereo_quant_pred.c',
+        'source/silk/sum_sqr_shift.c',
+        'source/silk/table_LSF_cos.c',
+        'source/silk/tables_gain.c',
+        'source/silk/tables_LTP.c',
+        'source/silk/tables_NLSF_CB_NB_MB.c',
+        'source/silk/tables_NLSF_CB_WB.c',
+        'source/silk/tables_other.c',
+        'source/silk/tables_pitch_lag.c',
+        'source/silk/tables_pulses_per_block.c',
+        'source/silk/VAD.c',
+        'source/silk/VQ_WMat_EC.c',
+
+        # silk floating point engine
+        'source/silk/float/apply_sine_window_FLP.c',
+        'source/silk/float/autocorrelation_FLP.c',
+        'source/silk/float/burg_modified_FLP.c',
+        'source/silk/float/bwexpander_FLP.c',
+        'source/silk/float/corrMatrix_FLP.c',
+        'source/silk/float/encode_frame_FLP.c',
+        'source/silk/float/energy_FLP.c',
+        'source/silk/float/find_LPC_FLP.c',
+        'source/silk/float/find_LTP_FLP.c',
+        'source/silk/float/find_pitch_lags_FLP.c',
+        'source/silk/float/find_pred_coefs_FLP.c',
+        'source/silk/float/inner_product_FLP.c',
+        'source/silk/float/k2a_FLP.c',
+        'source/silk/float/levinsondurbin_FLP.c',
+        'source/silk/float/LPC_analysis_filter_FLP.c',
+        'source/silk/float/LPC_inv_pred_gain_FLP.c',
+        'source/silk/float/LTP_analysis_filter_FLP.c',
+        'source/silk/float/LTP_scale_ctrl_FLP.c',
+        'source/silk/float/noise_shape_analysis_FLP.c',
+        'source/silk/float/pitch_analysis_core_FLP.c',
+        'source/silk/float/prefilter_FLP.c',
+        'source/silk/float/process_gains_FLP.c',
+        'source/silk/float/regularize_correlations_FLP.c',
+        'source/silk/float/residual_energy_FLP.c',
+        'source/silk/float/scale_copy_vector_FLP.c',
+        'source/silk/float/scale_vector_FLP.c',
+        'source/silk/float/schur_FLP.c',
+        'source/silk/float/solve_LS_FLP.c',
+        'source/silk/float/sort_FLP.c',
+        'source/silk/float/warped_autocorrelation_FLP.c',
+        'source/silk/float/wrappers_FLP.c',
+      ]
+    }
+  ]
+}
diff --git a/tools/create_supplement_gypi.py b/tools/create_supplement_gypi.py
index 7f996e7..f7b2696 100644
--- a/tools/create_supplement_gypi.py
+++ b/tools/create_supplement_gypi.py
@@ -15,6 +15,7 @@
 {
   'variables': {
     'build_with_chromium': 0,
+    'build_with_mozilla': 0,
   }
 }
 """