1. Make a clear distinction between codec internal FEC and RED, confusing mentioning of FEC in the old codes is replaced by RED

2. Add two new APIs to configure codec internal FEC

3. Add a test and listened to results. This is based modifying EncodeDecodeTest and deriving a new class from it.

New ACM gives good result.
Old ACM does not use NetEq 4, so FEC won't be decoded.

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

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

git-svn-id: http://webrtc.googlecode.com/svn/trunk@6233 4adac7df-926f-26a2-2b94-8c16560cd09d
diff --git a/webrtc/modules/audio_coding/main/acm2/acm_generic_codec.cc b/webrtc/modules/audio_coding/main/acm2/acm_generic_codec.cc
index aa8e8be..5043717 100644
--- a/webrtc/modules/audio_coding/main/acm2/acm_generic_codec.cc
+++ b/webrtc/modules/audio_coding/main/acm2/acm_generic_codec.cc
@@ -59,6 +59,7 @@
       num_lpc_params_(kNewCNGNumPLCParams),
       sent_cn_previous_(false),
       prev_frame_cng_(0),
+      has_internal_fec_(false),
       neteq_decode_lock_(NULL),
       codec_wrapper_lock_(*RWLockWrapper::CreateRWLock()),
       last_timestamp_(0xD87F3F9F),
diff --git a/webrtc/modules/audio_coding/main/acm2/acm_generic_codec.h b/webrtc/modules/audio_coding/main/acm2/acm_generic_codec.h
index d41580f..1ea61d0 100644
--- a/webrtc/modules/audio_coding/main/acm2/acm_generic_codec.h
+++ b/webrtc/modules/audio_coding/main/acm2/acm_generic_codec.h
@@ -560,6 +560,46 @@
   //
   virtual AudioDecoder* Decoder(int /* codec_id */) { return NULL; }
 
+  ///////////////////////////////////////////////////////////////////////////
+  // bool HasInternalFEC()
+  // Used to check if the codec has internal FEC.
+  //
+  // Return value:
+  //   true if the codec has an internal FEC, e.g. Opus.
+  //   false otherwise.
+  //
+  bool HasInternalFEC() const { return has_internal_fec_; }
+
+  ///////////////////////////////////////////////////////////////////////////
+  // int SetFEC();
+  // Sets the codec internal FEC. No effects on codecs that do not provide
+  // internal FEC.
+  //
+  // Input:
+  //   -enable_fec         : if true FEC will be enabled otherwise the FEC is
+  //                         disabled.
+  //
+  // Return value:
+  //   -1 if failed, or the codec does not support FEC
+  //    0 if succeeded.
+  //
+  virtual int SetFEC(bool /* enable_fec */) { return -1; }
+
+  ///////////////////////////////////////////////////////////////////////////
+  // int SetPacketLossRate()
+  // Sets expected packet loss rate for encoding. Some encoders provide packet
+  // loss gnostic encoding to make stream less sensitive to packet losses,
+  // through e.g., FEC. No effects on codecs that do not provide such encoding.
+  //
+  // Input:
+  //   -loss_rate          : expected packet loss rate (0 -- 100 inclusive).
+  //
+  // Return value:
+  //   -1 if failed, or codec does not support packet loss gnostic encoding,
+  //    0 if succeeded.
+  //
+  virtual int SetPacketLossRate(int /* loss_rate */) { return -1; }
+
  protected:
   ///////////////////////////////////////////////////////////////////////////
   // All the functions with FunctionNameSafe(...) contain the actual
@@ -899,6 +939,9 @@
   bool sent_cn_previous_;
   int16_t prev_frame_cng_;
 
+  // FEC.
+  bool has_internal_fec_;
+
   WebRtcACMCodecParams encoder_params_;
 
   // Used as a global lock for all available decoders
diff --git a/webrtc/modules/audio_coding/main/acm2/acm_opus.cc b/webrtc/modules/audio_coding/main/acm2/acm_opus.cc
index 5830f6b..544c932 100644
--- a/webrtc/modules/audio_coding/main/acm2/acm_opus.cc
+++ b/webrtc/modules/audio_coding/main/acm2/acm_opus.cc
@@ -75,6 +75,8 @@
   // Opus has internal DTX, but we dont use it for now.
   has_internal_dtx_ = false;
 
+  has_internal_fec_ = true;
+
   if (codec_id_ != ACMCodecDB::kOpus) {
     WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, unique_id_,
                  "Wrong codec id for Opus.");
@@ -198,6 +200,31 @@
   return -1;
 }
 
+int ACMOpus::SetFEC(bool enable_fec) {
+  // Ask the encoder to enable FEC.
+  if (enable_fec) {
+    if (WebRtcOpus_EnableFec(encoder_inst_ptr_) == 0) {
+      fec_enabled_ = true;
+      return 0;
+    }
+  } else {
+    if (WebRtcOpus_DisableFec(encoder_inst_ptr_) == 0) {
+      fec_enabled_ = false;
+      return 0;
+    }
+  }
+  return -1;
+}
+
+int ACMOpus::SetPacketLossRate(int loss_rate) {
+  // Ask the encoder to change the target packet loss rate.
+  if (WebRtcOpus_SetPacketLossRate(encoder_inst_ptr_, loss_rate) == 0) {
+    packet_loss_rate_ = loss_rate;
+    return 0;
+  }
+  return -1;
+}
+
 #endif  // WEBRTC_CODEC_OPUS
 
 }  // namespace acm2
diff --git a/webrtc/modules/audio_coding/main/acm2/acm_opus.h b/webrtc/modules/audio_coding/main/acm2/acm_opus.h
index a346e3c..7963ee9 100644
--- a/webrtc/modules/audio_coding/main/acm2/acm_opus.h
+++ b/webrtc/modules/audio_coding/main/acm2/acm_opus.h
@@ -32,6 +32,10 @@
 
   int16_t InternalInitEncoder(WebRtcACMCodecParams *codec_params);
 
+  virtual int SetFEC(bool enable_fec) OVERRIDE;
+
+  virtual int SetPacketLossRate(int loss_rate) OVERRIDE;
+
  protected:
   void DestructEncoderSafe();
 
@@ -45,6 +49,9 @@
   uint16_t sample_freq_;
   uint16_t bitrate_;
   int channels_;
+
+  bool fec_enabled_;
+  int packet_loss_rate_;
 };
 
 }  // namespace acm2
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
index 51aaeb8..ed4b086 100644
--- a/webrtc/modules/audio_coding/main/acm2/audio_coding_module_impl.cc
+++ b/webrtc/modules/audio_coding/main/acm2/audio_coding_module_impl.cc
@@ -39,11 +39,11 @@
   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.
+// Maximum number of payloads that can be packed in one RED packet. For
+// regular RED, we only pack two payloads. In case of dual-streaming, in worst
+// case we might pack 3 payloads in one RED packet.
 enum {
-  kNumFecFragmentationVectors = 2,
+  kNumRedFragmentationVectors = 2,
   kMaxNumFragmentationVectors = 3
 };
 
@@ -136,8 +136,9 @@
       acm_crit_sect_(CriticalSectionWrapper::CreateCriticalSection()),
       vad_callback_(NULL),
       is_first_red_(true),
-      fec_enabled_(false),
-      last_fec_timestamp_(0),
+      red_enabled_(false),
+      last_red_timestamp_(0),
+      codec_fec_enabled_(false),
       previous_pltype_(255),
       aux_rtp_header_(NULL),
       receiver_initialized_(false),
@@ -349,7 +350,7 @@
       int16_t len_bytes = MAX_PAYLOAD_SIZE_BYTE;
       WebRtcACMEncodingType encoding_type;
       if (secondary_encoder_->Encode(red_buffer_, &len_bytes,
-                                     &last_fec_timestamp_,
+                                     &last_red_timestamp_,
                                      &encoding_type) < 0) {
         WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, id_,
                      "ProcessDual(): Encoding of secondary encoder Failed");
@@ -372,7 +373,7 @@
       index_primary = secondary_ready_to_encode ?
           TimestampLessThan(primary_timestamp, secondary_timestamp) : 0;
       index_primary += has_previous_payload ?
-          TimestampLessThan(primary_timestamp, last_fec_timestamp_) : 0;
+          TimestampLessThan(primary_timestamp, last_red_timestamp_) : 0;
     }
 
     if (secondary_ready_to_encode) {
@@ -384,7 +385,7 @@
 
     if (has_previous_payload) {
       index_previous_secondary = primary_ready_to_encode ?
-          (1 - TimestampLessThan(primary_timestamp, last_fec_timestamp_)) : 0;
+          (1 - TimestampLessThan(primary_timestamp, last_red_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;
@@ -405,7 +406,7 @@
     } else if (index_secondary == 0) {
       current_timestamp = secondary_timestamp;
     } else {
-      current_timestamp = last_fec_timestamp_;
+      current_timestamp = last_red_timestamp_;
     }
 
     fragmentation_.fragmentationVectorSize = 0;
@@ -420,7 +421,7 @@
       fragmentation_.fragmentationPlType[index_previous_secondary] =
           secondary_send_codec_inst_.pltype;
       fragmentation_.fragmentationTimeDiff[index_previous_secondary] =
-          static_cast<uint16_t>(current_timestamp - last_fec_timestamp_);
+          static_cast<uint16_t>(current_timestamp - last_red_timestamp_);
       fragmentation_.fragmentationVectorSize++;
     }
 
@@ -462,7 +463,7 @@
   {
     CriticalSectionScoped lock(callback_crit_sect_);
     if (packetization_callback_ != NULL) {
-      // Callback with payload data, including redundant data (FEC/RED).
+      // Callback with payload data, including redundant data (RED).
       if (packetization_callback_->SendData(kAudioFrameSpeech,
                                             my_red_payload_type,
                                             current_timestamp, stream,
@@ -495,7 +496,7 @@
   FrameType frame_type = kAudioFrameSpeech;
   uint8_t current_payload_type = 0;
   bool has_data_to_send = false;
-  bool fec_active = false;
+  bool red_active = false;
   RTPFragmentationHeader my_fragmentation;
 
   // Keep the scope of the ACM critical section limited.
@@ -562,15 +563,15 @@
       // 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_) &&
+      if ((red_enabled_) &&
           ((encoding_type == kActiveNormalEncoded) ||
               (encoding_type == kPassiveNormalEncoded))) {
-        // FEC is enabled within this scope.
+        // RED 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):
+        // Summary of the RED 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
@@ -581,7 +582,7 @@
         //      - 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)
+        //        redundancy for packet #1 (old)
         //      - call GetRed_Payload() and store redundancy for packet #2 in
         //        second fragment of RED buffer
         //
@@ -604,19 +605,19 @@
         //
         //  Hence, even if every second packet is dropped, perfect
         //  reconstruction is possible.
-        fec_active = true;
+        red_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.
+          // Rearrange stream such that RED 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_);
+              rtp_timestamp - last_red_timestamp_);
 
           // Update fragmentation vectors.
           fragmentation_.fragmentationPlType[1] =
@@ -630,7 +631,7 @@
 
         // Insert new packet payload type.
         fragmentation_.fragmentationPlType[0] = current_payload_type;
-        last_fec_timestamp_ = rtp_timestamp;
+        last_red_timestamp_ = rtp_timestamp;
 
         // Can be modified by the GetRedPayload() call if iSAC is utilized.
         red_length_bytes = length_bytes;
@@ -650,7 +651,7 @@
         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).
+          // data instead (trivial RED scheme).
           memcpy(red_buffer_, stream, red_length_bytes);
         }
 
@@ -658,7 +659,7 @@
         // Update payload type with RED payload type.
         current_payload_type = red_pltype_;
         // We have packed 2 payloads.
-        fragmentation_.fragmentationVectorSize = kNumFecFragmentationVectors;
+        fragmentation_.fragmentationVectorSize = kNumRedFragmentationVectors;
 
         // Copy to local variable, as it will be used outside ACM lock.
         my_fragmentation.CopyFrom(fragmentation_);
@@ -672,8 +673,8 @@
     CriticalSectionScoped lock(callback_crit_sect_);
 
     if (packetization_callback_ != NULL) {
-      if (fec_active) {
-        // Callback with payload data, including redundant data (FEC/RED).
+      if (red_active) {
+        // Callback with payload data, including redundant data (RED).
         packetization_callback_->SendData(frame_type, current_payload_type,
                                           rtp_timestamp, stream, length_bytes,
                                           &my_fragmentation);
@@ -713,14 +714,14 @@
     }
   }
 
-  // Initialize FEC/RED.
+  // Initialize RED.
   is_first_red_ = true;
-  if (fec_enabled_ || secondary_encoder_.get() != NULL) {
+  if (red_enabled_ || secondary_encoder_.get() != NULL) {
     if (red_buffer_ != NULL) {
       memset(red_buffer_, 0, MAX_PAYLOAD_SIZE_BYTE);
     }
-    if (fec_enabled_) {
-      ResetFragmentation(kNumFecFragmentationVectors);
+    if (red_enabled_) {
+      ResetFragmentation(kNumRedFragmentationVectors);
     } else {
       ResetFragmentation(0);
     }
@@ -1031,10 +1032,20 @@
 
     // 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.
+      // If we change codec we start fresh with RED.
       // This is not strictly required by the standard.
       is_first_red_ = true;
       codec_ptr->SetVAD(&dtx_enabled_, &vad_enabled_, &vad_mode_);
+
+      if (!codec_ptr->HasInternalFEC()) {
+        codec_fec_enabled_ = false;
+      } else {
+        if (codec_ptr->SetFEC(codec_fec_enabled_) < 0) {
+          WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, id_,
+                       "Cannot set codec FEC");
+          return -1;
+        }
+      }
     }
 
     current_send_codec_idx_ = codec_id;
@@ -1120,8 +1131,18 @@
       }
       send_codec_inst_.rate = send_codec.rate;
     }
-    previous_pltype_ = send_codec_inst_.pltype;
 
+    if (!codecs_[codec_id]->HasInternalFEC()) {
+      codec_fec_enabled_ = false;
+    } else {
+      if (codecs_[codec_id]->SetFEC(codec_fec_enabled_) < 0) {
+        WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, id_,
+                     "Cannot set codec FEC");
+        return -1;
+      }
+    }
+
+    previous_pltype_ = send_codec_inst_.pltype;
     return 0;
   }
 }
@@ -1384,42 +1405,87 @@
 }
 
 /////////////////////////////////////////
-//   (FEC) Forward Error Correction
+//   (RED) Redundant Coding
 //
 
-bool AudioCodingModuleImpl::FECStatus() const {
+bool AudioCodingModuleImpl::REDStatus() const {
   CriticalSectionScoped lock(acm_crit_sect_);
-  return fec_enabled_;
+
+  return red_enabled_;
 }
 
-// Configure FEC status i.e on/off.
-int AudioCodingModuleImpl::SetFECStatus(
+// Configure RED status i.e on/off.
+int AudioCodingModuleImpl::SetREDStatus(
 #ifdef WEBRTC_CODEC_RED
-    bool enable_fec) {
+    bool enable_red) {
   CriticalSectionScoped lock(acm_crit_sect_);
 
-  if (fec_enabled_ != enable_fec) {
+  if (enable_red == true && codec_fec_enabled_ == true) {
+    WEBRTC_TRACE(webrtc::kTraceWarning, webrtc::kTraceAudioCoding, id_,
+                 "Codec internal FEC and RED cannot be co-enabled.");
+    return -1;
+  }
+
+  if (red_enabled_ != enable_red) {
     // Reset the RED buffer.
     memset(red_buffer_, 0, MAX_PAYLOAD_SIZE_BYTE);
 
     // Reset fragmentation buffers.
-    ResetFragmentation(kNumFecFragmentationVectors);
-    // Set fec_enabled_.
-    fec_enabled_ = enable_fec;
+    ResetFragmentation(kNumRedFragmentationVectors);
+    // Set red_enabled_.
+    red_enabled_ = enable_red;
   }
-  is_first_red_ = true;  // Make sure we restart FEC.
+  is_first_red_ = true;  // Make sure we restart RED.
   return 0;
 #else
-    bool /* enable_fec */) {
-  fec_enabled_ = false;
+    bool /* enable_red */) {
+  red_enabled_ = false;
   WEBRTC_TRACE(webrtc::kTraceWarning, webrtc::kTraceAudioCoding, id_,
-               "  WEBRTC_CODEC_RED is undefined => fec_enabled_ = %d",
-               fec_enabled_);
+               "  WEBRTC_CODEC_RED is undefined => red_enabled_ = %d",
+               red_enabled_);
   return -1;
 #endif
 }
 
 /////////////////////////////////////////
+//   (FEC) Forward Error Correction (codec internal)
+//
+
+bool AudioCodingModuleImpl::CodecFEC() const {
+  return codec_fec_enabled_;
+}
+
+int AudioCodingModuleImpl::SetCodecFEC(bool enable_codec_fec) {
+  CriticalSectionScoped lock(acm_crit_sect_);
+
+  if (enable_codec_fec == true && red_enabled_ == true) {
+    WEBRTC_TRACE(webrtc::kTraceWarning, webrtc::kTraceAudioCoding, id_,
+                 "Codec internal FEC and RED cannot be co-enabled.");
+    return -1;
+  }
+
+  // Set codec FEC.
+  if (HaveValidEncoder("SetCodecFEC") &&
+      codecs_[current_send_codec_idx_]->SetFEC(enable_codec_fec) < 0) {
+      WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, id_,
+                   "Set codec internal FEC failed.");
+    return -1;
+  }
+  codec_fec_enabled_ = enable_codec_fec;
+  return 0;
+}
+
+int AudioCodingModuleImpl::SetPacketLossRate(int loss_rate) {
+  if (HaveValidEncoder("SetPacketLossRate") &&
+      codecs_[current_send_codec_idx_]->SetPacketLossRate(loss_rate) < 0) {
+      WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, id_,
+                   "Set packet loss rate failed.");
+    return -1;
+  }
+  return 0;
+}
+
+/////////////////////////////////////////
 //   (VAD) Voice Activity Detection
 //
 int AudioCodingModuleImpl::SetVAD(bool enable_dtx,
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
index 157fc01..247aee7 100644
--- a/webrtc/modules/audio_coding/main/acm2/audio_coding_module_impl.h
+++ b/webrtc/modules/audio_coding/main/acm2/audio_coding_module_impl.h
@@ -92,14 +92,27 @@
   int Add10MsData(const AudioFrame& audio_frame);
 
   /////////////////////////////////////////
-  // (FEC) Forward Error Correction
+  // (RED) Redundant Coding
   //
 
-  // Configure FEC status i.e on/off.
-  int SetFECStatus(bool enable_fec);
+  // Configure RED status i.e. on/off.
+  int SetREDStatus(bool enable_red);
+
+  // Get RED status.
+  bool REDStatus() const;
+
+  /////////////////////////////////////////
+  // (FEC) Forward Error Correction (codec internal)
+  //
+
+  // Configure FEC status i.e. on/off.
+  int SetCodecFEC(bool enabled_codec_fec);
 
   // Get FEC status.
-  bool FECStatus() const;
+  bool CodecFEC() const;
+
+  // Set target packet loss rate
+  int SetPacketLossRate(int loss_rate);
 
   /////////////////////////////////////////
   //   (VAD) Voice Activity Detection
@@ -313,21 +326,24 @@
   CriticalSectionWrapper* acm_crit_sect_;
   ACMVADCallback* vad_callback_;
 
-  // RED/FEC.
+  // RED.
   bool is_first_red_;
-  bool fec_enabled_;
+  bool red_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.
+  // RED 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_;
+  uint32_t last_red_timestamp_;
+
+  // Codec internal FEC
+  bool codec_fec_enabled_;
 
   // This is to keep track of CN instances where we can send DTMFs.
   uint8_t previous_pltype_;
diff --git a/webrtc/modules/audio_coding/main/interface/audio_coding_module.h b/webrtc/modules/audio_coding/main/interface/audio_coding_module.h
index 9c7e562..1bfc0d3 100644
--- a/webrtc/modules/audio_coding/main/interface/audio_coding_module.h
+++ b/webrtc/modules/audio_coding/main/interface/audio_coding_module.h
@@ -373,12 +373,12 @@
   virtual int32_t Add10MsData(const AudioFrame& audio_frame) = 0;
 
   ///////////////////////////////////////////////////////////////////////////
-  // (FEC) Forward Error Correction
+  // (RED) Redundant Coding
   //
 
   ///////////////////////////////////////////////////////////////////////////
-  // int32_t SetFECStatus(const bool enable)
-  // configure FEC status i.e. on/off.
+  // int32_t SetREDStatus()
+  // configure RED status i.e. on/off.
   //
   // RFC 2198 describes a solution which has a single payload type which
   // signifies a packet with redundancy. That packet then becomes a container,
@@ -388,27 +388,69 @@
   // since each encapsulated payload must be preceded by a header indicating
   // the type of data enclosed.
   //
-  // This means that FEC is actually a RED scheme.
-  //
   // Input:
-  //   -enable_fec         : if true FEC is enabled, otherwise FEC is
+  //   -enable_red         : if true RED is enabled, otherwise RED is
   //                         disabled.
   //
   // Return value:
-  //   -1 if failed to set FEC status,
+  //   -1 if failed to set RED status,
   //    0 if succeeded.
   //
-  virtual int32_t SetFECStatus(const bool enable_fec) = 0;
+  virtual int32_t SetREDStatus(bool enable_red) = 0;
 
   ///////////////////////////////////////////////////////////////////////////
-  // bool FECStatus()
-  // Get FEC status
+  // bool REDStatus()
+  // Get RED status
   //
-  // Return value
+  // Return value:
+  //   true if RED is enabled,
+  //   false if RED is disabled.
+  //
+  virtual bool REDStatus() const = 0;
+
+  ///////////////////////////////////////////////////////////////////////////
+  // (FEC) Forward Error Correction (codec internal)
+  //
+
+  ///////////////////////////////////////////////////////////////////////////
+  // int32_t SetCodecFEC()
+  // Configures codec internal FEC status i.e. on/off. No effects on codecs that
+  // do not provide internal FEC.
+  //
+  // Input:
+  //   -enable_fec         : if true FEC will be enabled otherwise the FEC is
+  //                         disabled.
+  //
+  // Return value:
+  //   -1 if failed, or the codec does not support FEC
+  //    0 if succeeded.
+  //
+  virtual int SetCodecFEC(bool enable_codec_fec) = 0;
+
+  ///////////////////////////////////////////////////////////////////////////
+  // bool CodecFEC()
+  // Gets status of codec internal FEC.
+  //
+  // Return value:
   //   true if FEC is enabled,
   //   false if FEC is disabled.
   //
-  virtual bool FECStatus() const = 0;
+  virtual bool CodecFEC() const = 0;
+
+  ///////////////////////////////////////////////////////////////////////////
+  // int SetPacketLossRate()
+  // Sets expected packet loss rate for encoding. Some encoders provide packet
+  // loss gnostic encoding to make stream less sensitive to packet losses,
+  // through e.g., FEC. No effects on codecs that do not provide such encoding.
+  //
+  // Input:
+  //   -packet_loss_rate   : expected packet loss rate (0 -- 100 inclusive).
+  //
+  // Return value
+  //   -1 if failed to set packet loss rate,
+  //   0 if succeeded.
+  //
+  virtual int SetPacketLossRate(int packet_loss_rate) = 0;
 
   ///////////////////////////////////////////////////////////////////////////
   //   (VAD) Voice Activity Detection
diff --git a/webrtc/modules/audio_coding/main/test/EncodeDecodeTest.cc b/webrtc/modules/audio_coding/main/test/EncodeDecodeTest.cc
index 1ee6abc..d06cc07 100644
--- a/webrtc/modules/audio_coding/main/test/EncodeDecodeTest.cc
+++ b/webrtc/modules/audio_coding/main/test/EncodeDecodeTest.cc
@@ -10,12 +10,9 @@
 
 #include "webrtc/modules/audio_coding/main/test/EncodeDecodeTest.h"
 
+#include <sstream>
 #include <stdio.h>
 #include <stdlib.h>
-#include <string.h>
-
-#include <sstream>
-#include <string>
 
 #include "testing/gtest/include/gtest/gtest.h"
 #include "webrtc/common_types.h"
@@ -54,16 +51,19 @@
       _packetization(NULL) {
 }
 
-void Sender::Setup(AudioCodingModule *acm, RTPStream *rtpStream) {
+void Sender::Setup(AudioCodingModule *acm, RTPStream *rtpStream,
+                   std::string in_file_name, int sample_rate, int channels) {
   acm->InitializeSender();
   struct CodecInst sendCodec;
   int noOfCodecs = acm->NumberOfCodecs();
   int codecNo;
 
   // Open input file
-  const std::string file_name = webrtc::test::ResourcePath(
-      "audio_coding/testfile32kHz", "pcm");
-  _pcmFile.Open(file_name, 32000, "rb");
+  const std::string file_name = webrtc::test::ResourcePath(in_file_name, "pcm");
+  _pcmFile.Open(file_name, sample_rate, "rb");
+  if (channels == 2) {
+    _pcmFile.ReadStereo(true);
+  }
 
   // Set the codec for the current test.
   if ((testMode == 0) || (testMode == 1)) {
@@ -81,10 +81,8 @@
   }
 
   EXPECT_EQ(0, acm->Codec(codecNo, &sendCodec));
-  // Default number of channels is 2 for CELT, so we change to 1 in this test.
-  if (!strcmp(sendCodec.plname, "CELT")) {
-    sendCodec.channels = 1;
-  }
+
+  sendCodec.channels = channels;
 
   EXPECT_EQ(0, acm->RegisterSendCodec(sendCodec));
   _packetization = new TestPacketization(rtpStream, sendCodec.plfreq);
@@ -125,21 +123,28 @@
       _payloadSizeBytes(MAX_INCOMING_PAYLOAD) {
 }
 
-void Receiver::Setup(AudioCodingModule *acm, RTPStream *rtpStream) {
+void Receiver::Setup(AudioCodingModule *acm, RTPStream *rtpStream,
+                     std::string out_file_name, int channels) {
   struct CodecInst recvCodec;
   int noOfCodecs;
   EXPECT_EQ(0, acm->InitializeReceiver());
 
   noOfCodecs = acm->NumberOfCodecs();
   for (int i = 0; i < noOfCodecs; i++) {
-    EXPECT_EQ(0, acm->Codec(static_cast<uint8_t>(i), &recvCodec));
-    EXPECT_EQ(0, acm->RegisterReceiveCodec(recvCodec));
+    EXPECT_EQ(0, acm->Codec(i, &recvCodec));
+    if (recvCodec.channels == channels)
+      EXPECT_EQ(0, acm->RegisterReceiveCodec(recvCodec));
+    // Forces mono/stereo for Opus.
+    if (!strcmp(recvCodec.plname, "opus")) {
+      recvCodec.channels = channels;
+      EXPECT_EQ(0, acm->RegisterReceiveCodec(recvCodec));
+    }
   }
 
   int playSampFreq;
   std::string file_name;
   std::stringstream file_stream;
-  file_stream << webrtc::test::OutputPath() << "encodeDecode_out"
+  file_stream << webrtc::test::OutputPath() << out_file_name
       << static_cast<int>(codeId) << ".pcm";
   file_name = file_stream.str();
   _rtpStream = rtpStream;
@@ -156,7 +161,7 @@
     printf("which means output frequency equal to received signal frequency");
     printf("\n\nChoose output sampling frequency: ");
     ASSERT_GT(scanf("%d", &playSampFreq), 0);
-    file_name = webrtc::test::OutputPath() + "encodeDecode_out.pcm";
+    file_name = webrtc::test::OutputPath() + out_file_name + ".pcm";
     _pcmFile.Open(file_name, playSampFreq, "wb+");
   }
 
@@ -213,7 +218,8 @@
   if (_playoutLengthSmpls == 0) {
     return false;
   }
-  _pcmFile.Write10MsData(audioFrame.data_, audioFrame.samples_per_channel_);
+  _pcmFile.Write10MsData(audioFrame.data_,
+      audioFrame.samples_per_channel_ * audioFrame.num_channels_);
   return true;
 }
 
@@ -310,7 +316,7 @@
       _receiver.codeId = codeId;
 
       rtpFile.ReadHeader();
-      _receiver.Setup(acm.get(), &rtpFile);
+      _receiver.Setup(acm.get(), &rtpFile, "encodeDecode_out", 1);
       _receiver.Run();
       _receiver.Teardown();
       rtpFile.Close();
@@ -335,7 +341,7 @@
   _sender.testMode = testMode;
   _sender.codeId = codeId;
 
-  _sender.Setup(acm.get(), &rtpFile);
+  _sender.Setup(acm.get(), &rtpFile, "audio_coding/testfile32kHz", 32000, 1);
   struct CodecInst sendCodecInst;
   if (acm->SendCodec(&sendCodecInst) >= 0) {
     _sender.Run();
diff --git a/webrtc/modules/audio_coding/main/test/EncodeDecodeTest.h b/webrtc/modules/audio_coding/main/test/EncodeDecodeTest.h
index 4fdd943..dbe3f0c 100644
--- a/webrtc/modules/audio_coding/main/test/EncodeDecodeTest.h
+++ b/webrtc/modules/audio_coding/main/test/EncodeDecodeTest.h
@@ -12,6 +12,7 @@
 #define WEBRTC_MODULES_AUDIO_CODING_MAIN_TEST_ENCODEDECODETEST_H_
 
 #include <stdio.h>
+#include <string.h>
 
 #include "webrtc/modules/audio_coding/main/interface/audio_coding_module.h"
 #include "webrtc/modules/audio_coding/main/test/ACMTest.h"
@@ -44,7 +45,8 @@
 class Sender {
  public:
   Sender();
-  void Setup(AudioCodingModule *acm, RTPStream *rtpStream);
+  void Setup(AudioCodingModule *acm, RTPStream *rtpStream,
+             std::string in_file_name, int sample_rate, int channels);
   void Teardown();
   void Run();
   bool Add10MsData();
@@ -53,8 +55,10 @@
   uint8_t testMode;
   uint8_t codeId;
 
- private:
+ protected:
   AudioCodingModule* _acm;
+
+ private:
   PCMFile _pcmFile;
   AudioFrame _audioFrame;
   TestPacketization* _packetization;
@@ -63,10 +67,12 @@
 class Receiver {
  public:
   Receiver();
-  void Setup(AudioCodingModule *acm, RTPStream *rtpStream);
+  virtual ~Receiver() {};
+  void Setup(AudioCodingModule *acm, RTPStream *rtpStream,
+             std::string out_file_name, int channels);
   void Teardown();
   void Run();
-  bool IncomingPacket();
+  virtual bool IncomingPacket();
   bool PlayoutData();
 
   //for auto_test and logging
@@ -74,17 +80,19 @@
   uint8_t testMode;
 
  private:
-  AudioCodingModule* _acm;
-  RTPStream* _rtpStream;
   PCMFile _pcmFile;
   int16_t* _playoutBuffer;
   uint16_t _playoutLengthSmpls;
-  uint8_t _incomingPayload[MAX_INCOMING_PAYLOAD];
-  uint16_t _payloadSizeBytes;
-  uint16_t _realPayloadSizeBytes;
   int32_t _frequency;
   bool _firstTime;
+
+ protected:
+  AudioCodingModule* _acm;
+  uint8_t _incomingPayload[MAX_INCOMING_PAYLOAD];
+  RTPStream* _rtpStream;
   WebRtcRTPHeader _rtpInfo;
+  uint16_t _realPayloadSizeBytes;
+  uint16_t _payloadSizeBytes;
   uint32_t _nextTime;
 };
 
diff --git a/webrtc/modules/audio_coding/main/test/PacketLossTest.cc b/webrtc/modules/audio_coding/main/test/PacketLossTest.cc
new file mode 100644
index 0000000..e6ef392
--- /dev/null
+++ b/webrtc/modules/audio_coding/main/test/PacketLossTest.cc
@@ -0,0 +1,167 @@
+/*
+ *  Copyright (c) 2014 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/test/PacketLossTest.h"
+
+#include "testing/gtest/include/gtest/gtest.h"
+#include "webrtc/common.h"
+#include "webrtc/test/testsupport/fileutils.h"
+
+namespace webrtc {
+
+ReceiverWithPacketLoss::ReceiverWithPacketLoss()
+    : loss_rate_(0),
+      burst_length_(1),
+      packet_counter_(0),
+      lost_packet_counter_(0),
+      burst_lost_counter_(burst_length_) {
+}
+
+void ReceiverWithPacketLoss::Setup(AudioCodingModule *acm,
+                                   RTPStream *rtpStream,
+                                   std::string out_file_name,
+                                   int channels,
+                                   int loss_rate,
+                                   int burst_length) {
+  loss_rate_ = loss_rate;
+  burst_length_ = burst_length;
+  burst_lost_counter_ = burst_length_;  // To prevent first packet gets lost.
+  std::stringstream ss;
+  ss << out_file_name << "_" << loss_rate_ << "_" << burst_length_ << "_";
+  Receiver::Setup(acm, rtpStream, ss.str(), channels);
+}
+
+bool ReceiverWithPacketLoss::IncomingPacket() {
+  if (!_rtpStream->EndOfFile()) {
+    if (packet_counter_ == 0) {
+      _realPayloadSizeBytes = _rtpStream->Read(&_rtpInfo, _incomingPayload,
+                                               _payloadSizeBytes, &_nextTime);
+      if (_realPayloadSizeBytes == 0) {
+        if (_rtpStream->EndOfFile()) {
+          packet_counter_ = 0;
+          return true;
+        } else {
+          return false;
+        }
+      }
+    }
+
+    if (!PacketLost()) {
+      _acm->IncomingPacket(_incomingPayload, _realPayloadSizeBytes, _rtpInfo);
+    }
+    packet_counter_++;
+    _realPayloadSizeBytes = _rtpStream->Read(&_rtpInfo, _incomingPayload,
+                                             _payloadSizeBytes, &_nextTime);
+    if (_realPayloadSizeBytes == 0 && _rtpStream->EndOfFile()) {
+      packet_counter_ = 0;
+      lost_packet_counter_ = 0;
+    }
+  }
+  return true;
+}
+
+bool ReceiverWithPacketLoss::PacketLost() {
+  if (burst_lost_counter_ < burst_length_) {
+    lost_packet_counter_++;
+    burst_lost_counter_++;
+    return true;
+  }
+
+  if (lost_packet_counter_ * 100 < loss_rate_ * packet_counter_) {
+    lost_packet_counter_++;
+    burst_lost_counter_ = 1;
+    return true;
+  }
+  return false;
+}
+
+SenderWithFEC::SenderWithFEC()
+    : expected_loss_rate_(0) {
+}
+
+void SenderWithFEC::Setup(AudioCodingModule *acm, RTPStream *rtpStream,
+                          std::string in_file_name, int sample_rate,
+                          int channels, int expected_loss_rate) {
+  Sender::Setup(acm, rtpStream, in_file_name, sample_rate, channels);
+  EXPECT_TRUE(SetFEC(true));
+  EXPECT_TRUE(SetPacketLossRate(expected_loss_rate));
+}
+
+bool SenderWithFEC::SetFEC(bool enable_fec) {
+  if (_acm->SetCodecFEC(enable_fec) == 0) {
+    return true;
+  }
+  return false;
+}
+
+bool SenderWithFEC::SetPacketLossRate(int expected_loss_rate) {
+  if (_acm->SetPacketLossRate(expected_loss_rate) == 0) {
+    expected_loss_rate_ = expected_loss_rate;
+    return true;
+  }
+  return false;
+}
+
+PacketLossTest::PacketLossTest(int channels, int expected_loss_rate,
+                               int actual_loss_rate, int burst_length)
+    : channels_(channels),
+      in_file_name_(channels_ == 1 ? "audio_coding/testfile32kHz" :
+                    "audio_coding/teststereo32kHz"),
+      sample_rate_hz_(32000),
+      sender_(new SenderWithFEC),
+      receiver_(new ReceiverWithPacketLoss),
+      expected_loss_rate_(expected_loss_rate),
+      actual_loss_rate_(actual_loss_rate),
+      burst_length_(burst_length) {
+}
+
+void PacketLossTest::Perform() {
+#ifndef WEBRTC_CODEC_OPUS
+  return;
+#else
+  scoped_ptr<AudioCodingModule> acm(AudioCodingModule::Create(0));
+
+  int codec_id = acm->Codec("opus", 48000, channels_);
+
+  RTPFile rtpFile;
+  std::string fileName = webrtc::test::OutputPath() + "outFile.rtp";
+
+  // Encode to file
+  rtpFile.Open(fileName.c_str(), "wb+");
+  rtpFile.WriteHeader();
+
+  sender_->testMode = 0;
+  sender_->codeId = codec_id;
+
+  sender_->Setup(acm.get(), &rtpFile, in_file_name_, sample_rate_hz_, channels_,
+                 expected_loss_rate_);
+  struct CodecInst sendCodecInst;
+  if (acm->SendCodec(&sendCodecInst) >= 0) {
+    sender_->Run();
+  }
+  sender_->Teardown();
+  rtpFile.Close();
+
+  // Decode to file
+  rtpFile.Open(fileName.c_str(), "rb");
+  rtpFile.ReadHeader();
+
+  receiver_->testMode = 0;
+  receiver_->codeId = codec_id;
+
+  receiver_->Setup(acm.get(), &rtpFile, "packetLoss_out", channels_,
+                   actual_loss_rate_, burst_length_);
+  receiver_->Run();
+  receiver_->Teardown();
+  rtpFile.Close();
+#endif
+}
+
+}  // namespace webrtc
diff --git a/webrtc/modules/audio_coding/main/test/PacketLossTest.h b/webrtc/modules/audio_coding/main/test/PacketLossTest.h
new file mode 100644
index 0000000..e34da8c
--- /dev/null
+++ b/webrtc/modules/audio_coding/main/test/PacketLossTest.h
@@ -0,0 +1,66 @@
+/*
+ *  Copyright (c) 2014 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_TEST_PACKETLOSSTEST_H_
+#define WEBRTC_MODULES_AUDIO_CODING_MAIN_TEST_PACKETLOSSTEST_H_
+
+#include <string>
+#include "webrtc/modules/audio_coding/main/test/EncodeDecodeTest.h"
+#include "webrtc/system_wrappers/interface/scoped_ptr.h"
+
+namespace webrtc {
+
+class ReceiverWithPacketLoss : public Receiver {
+ public:
+  ReceiverWithPacketLoss();
+  void Setup(AudioCodingModule *acm, RTPStream *rtpStream,
+             std::string out_file_name, int channels, int loss_rate,
+             int burst_length);
+  bool IncomingPacket() OVERRIDE;
+ protected:
+  bool PacketLost();
+  int loss_rate_;
+  int burst_length_;
+  int packet_counter_;
+  int lost_packet_counter_;
+  int burst_lost_counter_;
+};
+
+class SenderWithFEC : public Sender {
+ public:
+  SenderWithFEC();
+  void Setup(AudioCodingModule *acm, RTPStream *rtpStream,
+             std::string in_file_name, int sample_rate, int channels,
+             int expected_loss_rate);
+  bool SetPacketLossRate(int expected_loss_rate);
+  bool SetFEC(bool enable_fec);
+ protected:
+  int expected_loss_rate_;
+};
+
+class PacketLossTest : public ACMTest {
+ public:
+  PacketLossTest(int channels, int expected_loss_rate_, int actual_loss_rate,
+                 int burst_length);
+  void Perform();
+ protected:
+  int channels_;
+  std::string in_file_name_;
+  int sample_rate_hz_;
+  scoped_ptr<SenderWithFEC> sender_;
+  scoped_ptr<ReceiverWithPacketLoss> receiver_;
+  int expected_loss_rate_;
+  int actual_loss_rate_;
+  int burst_length_;
+};
+
+}  // namespace webrtc
+
+#endif  // WEBRTC_MODULES_AUDIO_CODING_MAIN_TEST_PACKETLOSSTEST_H_
diff --git a/webrtc/modules/audio_coding/main/test/TestFEC.cc b/webrtc/modules/audio_coding/main/test/TestFEC.cc
deleted file mode 100644
index 76b6d4b..0000000
--- a/webrtc/modules/audio_coding/main/test/TestFEC.cc
+++ /dev/null
@@ -1,270 +0,0 @@
-/*
- *  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/test/TestFEC.h"
-
-#include <assert.h>
-#include <iostream>
-
-#include "webrtc/common_types.h"
-#include "webrtc/engine_configurations.h"
-#include "webrtc/modules/audio_coding/main/interface/audio_coding_module_typedefs.h"
-#include "webrtc/modules/audio_coding/main/test/utility.h"
-#include "webrtc/system_wrappers/interface/trace.h"
-#include "webrtc/test/testsupport/fileutils.h"
-
-namespace webrtc {
-
-TestFEC::TestFEC()
-    : _acmA(AudioCodingModule::Create(0)),
-      _acmB(AudioCodingModule::Create(1)),
-      _channelA2B(NULL),
-      _testCntr(0) {}
-
-TestFEC::~TestFEC() {
-  if (_channelA2B != NULL) {
-    delete _channelA2B;
-    _channelA2B = NULL;
-  }
-}
-
-void TestFEC::Perform() {
-  const std::string file_name = webrtc::test::ResourcePath(
-      "audio_coding/testfile32kHz", "pcm");
-  _inFileA.Open(file_name, 32000, "rb");
-
-  ASSERT_EQ(0, _acmA->InitializeReceiver());
-  ASSERT_EQ(0, _acmB->InitializeReceiver());
-
-  uint8_t numEncoders = _acmA->NumberOfCodecs();
-  CodecInst myCodecParam;
-  for (uint8_t n = 0; n < numEncoders; n++) {
-    EXPECT_EQ(0, _acmB->Codec(n, &myCodecParam));
-    EXPECT_EQ(0, _acmB->RegisterReceiveCodec(myCodecParam));
-  }
-
-  // Create and connect the channel
-  _channelA2B = new Channel;
-  _acmA->RegisterTransportCallback(_channelA2B);
-  _channelA2B->RegisterReceiverACM(_acmB.get());
-
-#ifndef WEBRTC_CODEC_G722
-  EXPECT_TRUE(false);
-  printf("G722 needs to be activated to run this test\n");
-  return;
-#endif
-  char nameG722[] = "G722";
-  EXPECT_EQ(0, RegisterSendCodec('A', nameG722, 16000));
-  char nameCN[] = "CN";
-  EXPECT_EQ(0, RegisterSendCodec('A', nameCN, 16000));
-  char nameRED[] = "RED";
-  EXPECT_EQ(0, RegisterSendCodec('A', nameRED));
-  OpenOutFile(_testCntr);
-  EXPECT_EQ(0, SetVAD(true, true, VADAggr));
-  EXPECT_EQ(0, _acmA->SetFECStatus(false));
-  EXPECT_FALSE(_acmA->FECStatus());
-  Run();
-  _outFileB.Close();
-
-  EXPECT_EQ(0, _acmA->SetFECStatus(true));
-  EXPECT_TRUE(_acmA->FECStatus());
-  OpenOutFile(_testCntr);
-  Run();
-  _outFileB.Close();
-
-  char nameISAC[] = "iSAC";
-  RegisterSendCodec('A', nameISAC, 16000);
-  OpenOutFile(_testCntr);
-  EXPECT_EQ(0, SetVAD(true, true, VADVeryAggr));
-  EXPECT_EQ(0, _acmA->SetFECStatus(false));
-  EXPECT_FALSE(_acmA->FECStatus());
-  Run();
-  _outFileB.Close();
-
-  EXPECT_EQ(0, _acmA->SetFECStatus(true));
-  EXPECT_TRUE(_acmA->FECStatus());
-  OpenOutFile(_testCntr);
-  Run();
-  _outFileB.Close();
-
-  RegisterSendCodec('A', nameISAC, 32000);
-  OpenOutFile(_testCntr);
-  EXPECT_EQ(0, SetVAD(true, true, VADVeryAggr));
-  EXPECT_EQ(0, _acmA->SetFECStatus(false));
-  EXPECT_FALSE(_acmA->FECStatus());
-  Run();
-  _outFileB.Close();
-
-  EXPECT_EQ(0, _acmA->SetFECStatus(true));
-  EXPECT_TRUE(_acmA->FECStatus());
-  OpenOutFile(_testCntr);
-  Run();
-  _outFileB.Close();
-
-  RegisterSendCodec('A', nameISAC, 32000);
-  OpenOutFile(_testCntr);
-  EXPECT_EQ(0, SetVAD(false, false, VADNormal));
-  EXPECT_EQ(0, _acmA->SetFECStatus(true));
-  EXPECT_TRUE(_acmA->FECStatus());
-  Run();
-
-  RegisterSendCodec('A', nameISAC, 16000);
-  EXPECT_TRUE(_acmA->FECStatus());
-  Run();
-
-  RegisterSendCodec('A', nameISAC, 32000);
-  EXPECT_TRUE(_acmA->FECStatus());
-  Run();
-
-  RegisterSendCodec('A', nameISAC, 16000);
-  EXPECT_TRUE(_acmA->FECStatus());
-  Run();
-  _outFileB.Close();
-
-  _channelA2B->SetFECTestWithPacketLoss(true);
-
-  EXPECT_EQ(0, RegisterSendCodec('A', nameG722));
-  EXPECT_EQ(0, RegisterSendCodec('A', nameCN, 16000));
-  OpenOutFile(_testCntr);
-  EXPECT_EQ(0, SetVAD(true, true, VADAggr));
-  EXPECT_EQ(0, _acmA->SetFECStatus(false));
-  EXPECT_FALSE(_acmA->FECStatus());
-  Run();
-  _outFileB.Close();
-
-  EXPECT_EQ(0, _acmA->SetFECStatus(true));
-  EXPECT_TRUE(_acmA->FECStatus());
-  OpenOutFile(_testCntr);
-  Run();
-  _outFileB.Close();
-
-  RegisterSendCodec('A', nameISAC, 16000);
-  OpenOutFile(_testCntr);
-  EXPECT_EQ(0, SetVAD(true, true, VADVeryAggr));
-  EXPECT_EQ(0, _acmA->SetFECStatus(false));
-  EXPECT_FALSE(_acmA->FECStatus());
-  Run();
-  _outFileB.Close();
-
-  EXPECT_EQ(0, _acmA->SetFECStatus(true));
-  EXPECT_TRUE(_acmA->FECStatus());
-  OpenOutFile(_testCntr);
-  Run();
-  _outFileB.Close();
-
-  RegisterSendCodec('A', nameISAC, 32000);
-  OpenOutFile(_testCntr);
-  EXPECT_EQ(0, SetVAD(true, true, VADVeryAggr));
-  EXPECT_EQ(0, _acmA->SetFECStatus(false));
-  EXPECT_FALSE(_acmA->FECStatus());
-  Run();
-  _outFileB.Close();
-
-  EXPECT_EQ(0, _acmA->SetFECStatus(true));
-  EXPECT_TRUE(_acmA->FECStatus());
-  OpenOutFile(_testCntr);
-  Run();
-  _outFileB.Close();
-
-  RegisterSendCodec('A', nameISAC, 32000);
-  OpenOutFile(_testCntr);
-  EXPECT_EQ(0, SetVAD(false, false, VADNormal));
-  EXPECT_EQ(0, _acmA->SetFECStatus(true));
-  EXPECT_TRUE(_acmA->FECStatus());
-  Run();
-
-  RegisterSendCodec('A', nameISAC, 16000);
-  EXPECT_TRUE(_acmA->FECStatus());
-  Run();
-
-  RegisterSendCodec('A', nameISAC, 32000);
-  EXPECT_TRUE(_acmA->FECStatus());
-  Run();
-
-  RegisterSendCodec('A', nameISAC, 16000);
-  EXPECT_TRUE(_acmA->FECStatus());
-  Run();
-  _outFileB.Close();
-}
-
-int32_t TestFEC::SetVAD(bool enableDTX, bool enableVAD, ACMVADMode vadMode) {
-  return _acmA->SetVAD(enableDTX, enableVAD, vadMode);
-}
-
-int16_t TestFEC::RegisterSendCodec(char side, char* codecName,
-                                   int32_t samplingFreqHz) {
-  std::cout << std::flush;
-  AudioCodingModule* myACM;
-  switch (side) {
-    case 'A': {
-      myACM = _acmA.get();
-      break;
-    }
-    case 'B': {
-      myACM = _acmB.get();
-      break;
-    }
-    default:
-      return -1;
-  }
-
-  if (myACM == NULL) {
-    assert(false);
-    return -1;
-  }
-  CodecInst myCodecParam;
-  EXPECT_GT(AudioCodingModule::Codec(codecName, &myCodecParam,
-                                     samplingFreqHz, 1), -1);
-  EXPECT_GT(myACM->RegisterSendCodec(myCodecParam), -1);
-
-  // Initialization was successful.
-  return 0;
-}
-
-void TestFEC::Run() {
-  AudioFrame audioFrame;
-
-  uint16_t msecPassed = 0;
-  uint32_t secPassed = 0;
-  int32_t outFreqHzB = _outFileB.SamplingFrequency();
-
-  while (!_inFileA.EndOfFile()) {
-    EXPECT_GT(_inFileA.Read10MsData(audioFrame), 0);
-    EXPECT_EQ(0, _acmA->Add10MsData(audioFrame));
-    EXPECT_GT(_acmA->Process(), -1);
-    EXPECT_EQ(0, _acmB->PlayoutData10Ms(outFreqHzB, &audioFrame));
-    _outFileB.Write10MsData(audioFrame.data_, audioFrame.samples_per_channel_);
-    msecPassed += 10;
-    if (msecPassed >= 1000) {
-      msecPassed = 0;
-      secPassed++;
-    }
-    // Test that toggling FEC on and off works.
-    if (((secPassed % 5) == 4) && (msecPassed == 0) && (_testCntr > 14)) {
-      EXPECT_EQ(0, _acmA->SetFECStatus(false));
-    }
-    if (((secPassed % 5) == 4) && (msecPassed >= 990) && (_testCntr > 14)) {
-      EXPECT_EQ(0, _acmA->SetFECStatus(true));
-    }
-  }
-  _inFileA.Rewind();
-}
-
-void TestFEC::OpenOutFile(int16_t test_number) {
-  std::string file_name;
-  std::stringstream file_stream;
-  file_stream << webrtc::test::OutputPath();
-  file_stream << "TestFEC_outFile_";
-  file_stream << test_number << ".pcm";
-  file_name = file_stream.str();
-  _outFileB.Open(file_name, 16000, "wb");
-}
-
-}  // namespace webrtc
diff --git a/webrtc/modules/audio_coding/main/test/TestRedFec.cc b/webrtc/modules/audio_coding/main/test/TestRedFec.cc
new file mode 100644
index 0000000..10498d8
--- /dev/null
+++ b/webrtc/modules/audio_coding/main/test/TestRedFec.cc
@@ -0,0 +1,333 @@
+/*
+ *  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/test/TestRedFec.h"
+
+#include <assert.h>
+
+#include "webrtc/common.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/modules/audio_coding/main/test/utility.h"
+#include "webrtc/system_wrappers/interface/trace.h"
+#include "webrtc/test/testsupport/fileutils.h"
+
+namespace webrtc {
+
+TestRedFec::TestRedFec()
+    : _acmA(AudioCodingModule::Create(0)),
+      _acmB(AudioCodingModule::Create(1)),
+      _channelA2B(NULL),
+      _testCntr(0) {
+}
+
+TestRedFec::~TestRedFec() {
+  if (_channelA2B != NULL) {
+    delete _channelA2B;
+    _channelA2B = NULL;
+  }
+}
+
+void TestRedFec::Perform() {
+  const std::string file_name = webrtc::test::ResourcePath(
+      "audio_coding/testfile32kHz", "pcm");
+  _inFileA.Open(file_name, 32000, "rb");
+
+  ASSERT_EQ(0, _acmA->InitializeReceiver());
+  ASSERT_EQ(0, _acmB->InitializeReceiver());
+
+  uint8_t numEncoders = _acmA->NumberOfCodecs();
+  CodecInst myCodecParam;
+  for (uint8_t n = 0; n < numEncoders; n++) {
+    EXPECT_EQ(0, _acmB->Codec(n, &myCodecParam));
+    // Default number of channels is 2 for opus, so we change to 1 in this test.
+    if (!strcmp(myCodecParam.plname, "opus")) {
+      myCodecParam.channels = 1;
+    }
+    EXPECT_EQ(0, _acmB->RegisterReceiveCodec(myCodecParam));
+  }
+
+  // Create and connect the channel
+  _channelA2B = new Channel;
+  _acmA->RegisterTransportCallback(_channelA2B);
+  _channelA2B->RegisterReceiverACM(_acmB.get());
+
+#ifndef WEBRTC_CODEC_G722
+  EXPECT_TRUE(false);
+  printf("G722 needs to be activated to run this test\n");
+  return;
+#endif
+  char nameG722[] = "G722";
+  EXPECT_EQ(0, RegisterSendCodec('A', nameG722, 16000));
+  char nameCN[] = "CN";
+  EXPECT_EQ(0, RegisterSendCodec('A', nameCN, 16000));
+  char nameRED[] = "RED";
+  EXPECT_EQ(0, RegisterSendCodec('A', nameRED));
+  OpenOutFile(_testCntr);
+  EXPECT_EQ(0, SetVAD(true, true, VADAggr));
+  EXPECT_EQ(0, _acmA->SetREDStatus(false));
+  EXPECT_FALSE(_acmA->REDStatus());
+  Run();
+  _outFileB.Close();
+
+  EXPECT_EQ(0, _acmA->SetREDStatus(true));
+  EXPECT_TRUE(_acmA->REDStatus());
+  OpenOutFile(_testCntr);
+  Run();
+  _outFileB.Close();
+
+  char nameISAC[] = "iSAC";
+  RegisterSendCodec('A', nameISAC, 16000);
+  OpenOutFile(_testCntr);
+  EXPECT_EQ(0, SetVAD(true, true, VADVeryAggr));
+  EXPECT_EQ(0, _acmA->SetREDStatus(false));
+  EXPECT_FALSE(_acmA->REDStatus());
+  Run();
+  _outFileB.Close();
+
+  EXPECT_EQ(0, _acmA->SetREDStatus(true));
+  EXPECT_TRUE(_acmA->REDStatus());
+  OpenOutFile(_testCntr);
+  Run();
+  _outFileB.Close();
+
+  RegisterSendCodec('A', nameISAC, 32000);
+  OpenOutFile(_testCntr);
+  EXPECT_EQ(0, SetVAD(true, true, VADVeryAggr));
+  EXPECT_EQ(0, _acmA->SetREDStatus(false));
+  EXPECT_FALSE(_acmA->REDStatus());
+  Run();
+  _outFileB.Close();
+
+  EXPECT_EQ(0, _acmA->SetREDStatus(true));
+  EXPECT_TRUE(_acmA->REDStatus());
+  OpenOutFile(_testCntr);
+  Run();
+  _outFileB.Close();
+
+  RegisterSendCodec('A', nameISAC, 32000);
+  OpenOutFile(_testCntr);
+  EXPECT_EQ(0, SetVAD(false, false, VADNormal));
+  EXPECT_EQ(0, _acmA->SetREDStatus(true));
+  EXPECT_TRUE(_acmA->REDStatus());
+  Run();
+
+  RegisterSendCodec('A', nameISAC, 16000);
+  EXPECT_TRUE(_acmA->REDStatus());
+  Run();
+
+  RegisterSendCodec('A', nameISAC, 32000);
+  EXPECT_TRUE(_acmA->REDStatus());
+  Run();
+
+  RegisterSendCodec('A', nameISAC, 16000);
+  EXPECT_TRUE(_acmA->REDStatus());
+  Run();
+  _outFileB.Close();
+
+  _channelA2B->SetFECTestWithPacketLoss(true);
+
+  EXPECT_EQ(0, RegisterSendCodec('A', nameG722));
+  EXPECT_EQ(0, RegisterSendCodec('A', nameCN, 16000));
+  OpenOutFile(_testCntr);
+  EXPECT_EQ(0, SetVAD(true, true, VADAggr));
+  EXPECT_EQ(0, _acmA->SetREDStatus(false));
+  EXPECT_FALSE(_acmA->REDStatus());
+  Run();
+  _outFileB.Close();
+
+  EXPECT_EQ(0, _acmA->SetREDStatus(true));
+  EXPECT_TRUE(_acmA->REDStatus());
+  OpenOutFile(_testCntr);
+  Run();
+  _outFileB.Close();
+
+  RegisterSendCodec('A', nameISAC, 16000);
+  OpenOutFile(_testCntr);
+  EXPECT_EQ(0, SetVAD(true, true, VADVeryAggr));
+  EXPECT_EQ(0, _acmA->SetREDStatus(false));
+  EXPECT_FALSE(_acmA->REDStatus());
+  Run();
+  _outFileB.Close();
+
+  EXPECT_EQ(0, _acmA->SetREDStatus(true));
+  EXPECT_TRUE(_acmA->REDStatus());
+  OpenOutFile(_testCntr);
+  Run();
+  _outFileB.Close();
+
+  RegisterSendCodec('A', nameISAC, 32000);
+  OpenOutFile(_testCntr);
+  EXPECT_EQ(0, SetVAD(true, true, VADVeryAggr));
+  EXPECT_EQ(0, _acmA->SetREDStatus(false));
+  EXPECT_FALSE(_acmA->REDStatus());
+  Run();
+  _outFileB.Close();
+
+  EXPECT_EQ(0, _acmA->SetREDStatus(true));
+  EXPECT_TRUE(_acmA->REDStatus());
+  OpenOutFile(_testCntr);
+  Run();
+  _outFileB.Close();
+
+  RegisterSendCodec('A', nameISAC, 32000);
+  OpenOutFile(_testCntr);
+  EXPECT_EQ(0, SetVAD(false, false, VADNormal));
+  EXPECT_EQ(0, _acmA->SetREDStatus(true));
+  EXPECT_TRUE(_acmA->REDStatus());
+  Run();
+
+  RegisterSendCodec('A', nameISAC, 16000);
+  EXPECT_TRUE(_acmA->REDStatus());
+  Run();
+
+  RegisterSendCodec('A', nameISAC, 32000);
+  EXPECT_TRUE(_acmA->REDStatus());
+  Run();
+
+  RegisterSendCodec('A', nameISAC, 16000);
+  EXPECT_TRUE(_acmA->REDStatus());
+  Run();
+  _outFileB.Close();
+
+#ifndef WEBRTC_CODEC_OPUS
+  EXPECT_TRUE(false);
+  printf("Opus needs to be activated to run this test\n");
+  return;
+#endif
+
+  char nameOpus[] = "opus";
+  RegisterSendCodec('A', nameOpus, 48000);
+
+  EXPECT_TRUE(_acmA->REDStatus());
+
+  // _channelA2B imposes 25% packet loss rate.
+  EXPECT_EQ(0, _acmA->SetPacketLossRate(25));
+
+  // Codec FEC and RED are mutually exclusive.
+  EXPECT_EQ(-1, _acmA->SetCodecFEC(true));
+
+  EXPECT_EQ(0, _acmA->SetREDStatus(false));
+  EXPECT_EQ(0, _acmA->SetCodecFEC(true));
+
+  // Codec FEC and RED are mutually exclusive.
+  EXPECT_EQ(-1, _acmA->SetREDStatus(true));
+
+  EXPECT_TRUE(_acmA->CodecFEC());
+  OpenOutFile(_testCntr);
+  Run();
+
+  // Switch to ISAC with RED.
+  RegisterSendCodec('A', nameISAC, 32000);
+  EXPECT_EQ(0, SetVAD(false, false, VADNormal));
+
+  // ISAC does not support FEC, so FEC should be turned off automatically.
+  EXPECT_FALSE(_acmA->CodecFEC());
+
+  EXPECT_EQ(0, _acmA->SetREDStatus(true));
+  EXPECT_TRUE(_acmA->REDStatus());
+  Run();
+
+  // Switch to Opus again.
+  RegisterSendCodec('A', nameOpus, 48000);
+  EXPECT_EQ(0, _acmA->SetCodecFEC(false));
+  EXPECT_EQ(0, _acmA->SetREDStatus(false));
+  Run();
+
+  EXPECT_EQ(0, _acmA->SetCodecFEC(true));
+  _outFileB.Close();
+
+  // Codecs does not support internal FEC.
+  RegisterSendCodec('A', nameG722, 16000);
+  EXPECT_FALSE(_acmA->REDStatus());
+  EXPECT_EQ(-1, _acmA->SetCodecFEC(true));
+  EXPECT_FALSE(_acmA->CodecFEC());
+
+  RegisterSendCodec('A', nameISAC, 16000);
+  EXPECT_FALSE(_acmA->REDStatus());
+  EXPECT_EQ(-1, _acmA->SetCodecFEC(true));
+  EXPECT_FALSE(_acmA->CodecFEC());
+}
+
+int32_t TestRedFec::SetVAD(bool enableDTX, bool enableVAD, ACMVADMode vadMode) {
+  return _acmA->SetVAD(enableDTX, enableVAD, vadMode);
+}
+
+int16_t TestRedFec::RegisterSendCodec(char side, char* codecName,
+                                      int32_t samplingFreqHz) {
+  std::cout << std::flush;
+  AudioCodingModule* myACM;
+  switch (side) {
+    case 'A': {
+      myACM = _acmA.get();
+      break;
+    }
+    case 'B': {
+      myACM = _acmB.get();
+      break;
+    }
+    default:
+      return -1;
+  }
+
+  if (myACM == NULL) {
+    assert(false);
+    return -1;
+  }
+  CodecInst myCodecParam;
+  EXPECT_GT(AudioCodingModule::Codec(codecName, &myCodecParam,
+                                     samplingFreqHz, 1), -1);
+  EXPECT_GT(myACM->RegisterSendCodec(myCodecParam), -1);
+
+  // Initialization was successful.
+  return 0;
+}
+
+void TestRedFec::Run() {
+  AudioFrame audioFrame;
+
+  uint16_t msecPassed = 0;
+  uint32_t secPassed = 0;
+  int32_t outFreqHzB = _outFileB.SamplingFrequency();
+
+  while (!_inFileA.EndOfFile()) {
+    EXPECT_GT(_inFileA.Read10MsData(audioFrame), 0);
+    EXPECT_EQ(0, _acmA->Add10MsData(audioFrame));
+    EXPECT_GT(_acmA->Process(), -1);
+    EXPECT_EQ(0, _acmB->PlayoutData10Ms(outFreqHzB, &audioFrame));
+    _outFileB.Write10MsData(audioFrame.data_, audioFrame.samples_per_channel_);
+    msecPassed += 10;
+    if (msecPassed >= 1000) {
+      msecPassed = 0;
+      secPassed++;
+    }
+    // Test that toggling RED on and off works.
+    if (((secPassed % 5) == 4) && (msecPassed == 0) && (_testCntr > 14)) {
+      EXPECT_EQ(0, _acmA->SetREDStatus(false));
+    }
+    if (((secPassed % 5) == 4) && (msecPassed >= 990) && (_testCntr > 14)) {
+      EXPECT_EQ(0, _acmA->SetREDStatus(true));
+    }
+  }
+  _inFileA.Rewind();
+}
+
+void TestRedFec::OpenOutFile(int16_t test_number) {
+  std::string file_name;
+  std::stringstream file_stream;
+  file_stream << webrtc::test::OutputPath();
+  file_stream << "TestRedFec_outFile_";
+  file_stream << test_number << ".pcm";
+  file_name = file_stream.str();
+  _outFileB.Open(file_name, 16000, "wb");
+}
+
+}  // namespace webrtc
diff --git a/webrtc/modules/audio_coding/main/test/TestFEC.h b/webrtc/modules/audio_coding/main/test/TestRedFec.h
similarity index 82%
rename from webrtc/modules/audio_coding/main/test/TestFEC.h
rename to webrtc/modules/audio_coding/main/test/TestRedFec.h
index d7a6223..30ced1e 100644
--- a/webrtc/modules/audio_coding/main/test/TestFEC.h
+++ b/webrtc/modules/audio_coding/main/test/TestRedFec.h
@@ -8,9 +8,10 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
-#ifndef WEBRTC_MODULES_AUDIO_CODING_MAIN_TESTFEC_H_
-#define WEBRTC_MODULES_AUDIO_CODING_MAIN_TESTFEC_H_
+#ifndef WEBRTC_MODULES_AUDIO_CODING_MAIN_TESTREDFEC_H_
+#define WEBRTC_MODULES_AUDIO_CODING_MAIN_TESTREDFEC_H_
 
+#include <string>
 #include "webrtc/modules/audio_coding/main/test/ACMTest.h"
 #include "webrtc/modules/audio_coding/main/test/Channel.h"
 #include "webrtc/modules/audio_coding/main/test/PCMFile.h"
@@ -18,10 +19,12 @@
 
 namespace webrtc {
 
-class TestFEC : public ACMTest {
+class Config;
+
+class TestRedFec : public ACMTest {
  public:
-  TestFEC();
-  ~TestFEC();
+  explicit TestRedFec();
+  ~TestRedFec();
 
   void Perform();
  private:
@@ -45,4 +48,4 @@
 
 }  // namespace webrtc
 
-#endif  // WEBRTC_MODULES_AUDIO_CODING_MAIN_TESTFEC_H_
+#endif  // WEBRTC_MODULES_AUDIO_CODING_MAIN_TESTREDFEC_H_
diff --git a/webrtc/modules/audio_coding/main/test/Tester.cc b/webrtc/modules/audio_coding/main/test/Tester.cc
index a89c9cd..b6a554b 100644
--- a/webrtc/modules/audio_coding/main/test/Tester.cc
+++ b/webrtc/modules/audio_coding/main/test/Tester.cc
@@ -18,8 +18,9 @@
 #include "webrtc/modules/audio_coding/main/test/EncodeDecodeTest.h"
 #include "webrtc/modules/audio_coding/main/test/iSACTest.h"
 #include "webrtc/modules/audio_coding/main/test/opus_test.h"
+#include "webrtc/modules/audio_coding/main/test/PacketLossTest.h"
 #include "webrtc/modules/audio_coding/main/test/TestAllCodecs.h"
-#include "webrtc/modules/audio_coding/main/test/TestFEC.h"
+#include "webrtc/modules/audio_coding/main/test/TestRedFec.h"
 #include "webrtc/modules/audio_coding/main/test/TestStereo.h"
 #include "webrtc/modules/audio_coding/main/test/TestVADDTX.h"
 #include "webrtc/modules/audio_coding/main/test/TwoWayCommunication.h"
@@ -49,11 +50,11 @@
   Trace::ReturnTrace();
 }
 
-TEST(AudioCodingModuleTest, DISABLED_ON_ANDROID(TestFEC)) {
+TEST(AudioCodingModuleTest, DISABLED_ON_ANDROID(TestRedFec)) {
   Trace::CreateTrace();
   Trace::SetTraceFile((webrtc::test::OutputPath() +
       "acm_fec_trace.txt").c_str());
-  webrtc::TestFEC().Perform();
+  webrtc::TestRedFec().Perform();
   Trace::ReturnTrace();
 }
 
@@ -97,6 +98,38 @@
   Trace::ReturnTrace();
 }
 
+TEST(AudioCodingModuleTest, TestPacketLoss) {
+  Trace::CreateTrace();
+  Trace::SetTraceFile((webrtc::test::OutputPath() +
+      "acm_packetloss_trace.txt").c_str());
+  webrtc::PacketLossTest(1, 10, 10, 1).Perform();
+  Trace::ReturnTrace();
+}
+
+TEST(AudioCodingModuleTest, TestPacketLossBurst) {
+  Trace::CreateTrace();
+  Trace::SetTraceFile((webrtc::test::OutputPath() +
+      "acm_packetloss_burst_trace.txt").c_str());
+  webrtc::PacketLossTest(1, 10, 10, 2).Perform();
+  Trace::ReturnTrace();
+}
+
+TEST(AudioCodingModuleTest, TestPacketLossStereo) {
+  Trace::CreateTrace();
+  Trace::SetTraceFile((webrtc::test::OutputPath() +
+      "acm_packetloss_trace.txt").c_str());
+  webrtc::PacketLossTest(2, 10, 10, 1).Perform();
+  Trace::ReturnTrace();
+}
+
+TEST(AudioCodingModuleTest, TestPacketLossStereoBurst) {
+  Trace::CreateTrace();
+  Trace::SetTraceFile((webrtc::test::OutputPath() +
+      "acm_packetloss_burst_trace.txt").c_str());
+  webrtc::PacketLossTest(2, 10, 10, 2).Perform();
+  Trace::ReturnTrace();
+}
+
 // The full API test is too long to run automatically on bots, but can be used
 // for offline testing. User interaction is needed.
 #ifdef ACM_TEST_FULL_API
diff --git a/webrtc/modules/audio_coding/main/test/delay_test.cc b/webrtc/modules/audio_coding/main/test/delay_test.cc
index ba81507..2e75472 100644
--- a/webrtc/modules/audio_coding/main/test/delay_test.cc
+++ b/webrtc/modules/audio_coding/main/test/delay_test.cc
@@ -161,8 +161,8 @@
   void ConfigAcm(const AcmSettings& config) {
     ASSERT_EQ(0, acm_a_->SetVAD(config.dtx, config.dtx, VADAggr)) <<
         "Failed to set VAD.\n";
-    ASSERT_EQ(0, acm_a_->SetFECStatus(config.fec)) <<
-        "Failed to set FEC.\n";
+    ASSERT_EQ(0, acm_a_->SetREDStatus(config.fec)) <<
+        "Failed to set RED.\n";
   }
 
   void ConfigChannel(bool packet_loss) {
diff --git a/webrtc/modules/modules.gyp b/webrtc/modules/modules.gyp
index ff9761d..47e0a74 100644
--- a/webrtc/modules/modules.gyp
+++ b/webrtc/modules/modules.gyp
@@ -336,13 +336,14 @@
             'audio_coding/main/test/EncodeDecodeTest.cc',
             'audio_coding/main/test/iSACTest.cc',
             'audio_coding/main/test/opus_test.cc',
+            'audio_coding/main/test/PacketLossTest.cc',
             'audio_coding/main/test/PCMFile.cc',
             'audio_coding/main/test/RTPFile.cc',
             'audio_coding/main/test/SpatialAudio.cc',
             'audio_coding/main/test/TestAllCodecs.cc',
             'audio_coding/main/test/target_delay_unittest.cc',
             'audio_coding/main/test/Tester.cc',
-            'audio_coding/main/test/TestFEC.cc',
+            'audio_coding/main/test/TestRedFec.cc',
             'audio_coding/main/test/TestStereo.cc',
             'audio_coding/main/test/TestVADDTX.cc',
             'audio_coding/main/test/TimedTrace.cc',
diff --git a/webrtc/voice_engine/channel.cc b/webrtc/voice_engine/channel.cc
index 700f5d6..37ec4d7 100644
--- a/webrtc/voice_engine/channel.cc
+++ b/webrtc/voice_engine/channel.cc
@@ -3528,10 +3528,10 @@
     }
   }
 
-  if (audio_coding_->SetFECStatus(enable) != 0) {
+  if (audio_coding_->SetREDStatus(enable) != 0) {
     _engineStatisticsPtr->SetLastError(
         VE_AUDIO_CODING_MODULE_ERROR, kTraceError,
-        "SetFECStatus() failed to set FEC state in the ACM");
+        "SetREDStatus() failed to set RED state in the ACM");
     return -1;
   }
   return 0;
@@ -3540,7 +3540,7 @@
 int
 Channel::GetFECStatus(bool& enabled, int& redPayloadtype)
 {
-    enabled = audio_coding_->FECStatus();
+    enabled = audio_coding_->REDStatus();
     if (enabled)
     {
         int8_t payloadType(0);