Limit RED audio payload to narrow band.

In SDP, RED audio codec has its own sample rate. Currently, we offer RED/8000 (8 kHz). But the actual send codec can violate this sample rate. The way to solve it is to introduce more RED payload types, e.g., RED/16000, RED/32000.

As a first step towards that, we, in this CL, limit the current RED (RED/8000) to work only with 8 kHz codecs.

BUG=3619
R=henrik.lundin@webrtc.org

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

Cr-Commit-Position: refs/heads/master@{#8830}
git-svn-id: http://webrtc.googlecode.com/svn/trunk@8830 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 2fc4306..c472a4a 100644
--- a/webrtc/modules/audio_coding/main/acm2/acm_generic_codec.cc
+++ b/webrtc/modules/audio_coding/main/acm2/acm_generic_codec.cc
@@ -45,19 +45,19 @@
                  });
 }
 
-void SetCngPtInMap(std::map<int, int>* cng_pt_map,
-                   int sample_rate_hz,
-                   int payload_type) {
+void SetPtInMap(std::map<int, int>* pt_map,
+                int sample_rate_hz,
+                int payload_type) {
   if (payload_type == kInvalidPayloadType)
     return;
   CHECK_GE(payload_type, 0);
   CHECK_LT(payload_type, 128);
-  auto pt_iter = FindSampleRateInMap(cng_pt_map, sample_rate_hz);
-  if (pt_iter != cng_pt_map->end()) {
+  auto pt_iter = FindSampleRateInMap(pt_map, sample_rate_hz);
+  if (pt_iter != pt_map->end()) {
     // Remove item in map with sample_rate_hz.
-    cng_pt_map->erase(pt_iter);
+    pt_map->erase(pt_iter);
   }
-  (*cng_pt_map)[payload_type] = sample_rate_hz;
+  (*pt_map)[payload_type] = sample_rate_hz;
 }
 }  // namespace
 
@@ -83,7 +83,7 @@
                                  int cng_pt_swb,
                                  int cng_pt_fb,
                                  bool enable_red,
-                                 int red_payload_type)
+                                 int red_pt_nb)
     : has_internal_fec_(false),
       copy_red_enabled_(enable_red),
       encoder_(NULL),
@@ -96,16 +96,16 @@
       opus_dtx_enabled_(false),
       is_opus_(false),
       is_isac_(false),
-      red_payload_type_(red_payload_type),
       opus_application_set_(false) {
   acm_codec_params_.codec_inst = codec_inst;
   acm_codec_params_.enable_dtx = false;
   acm_codec_params_.enable_vad = false;
   acm_codec_params_.vad_mode = VADNormal;
-  SetCngPtInMap(&cng_pt_, 8000, cng_pt_nb);
-  SetCngPtInMap(&cng_pt_, 16000, cng_pt_wb);
-  SetCngPtInMap(&cng_pt_, 32000, cng_pt_swb);
-  SetCngPtInMap(&cng_pt_, 48000, cng_pt_fb);
+  SetPtInMap(&red_pt_, 8000, red_pt_nb);
+  SetPtInMap(&cng_pt_, 8000, cng_pt_nb);
+  SetPtInMap(&cng_pt_, 16000, cng_pt_wb);
+  SetPtInMap(&cng_pt_, 32000, cng_pt_swb);
+  SetPtInMap(&cng_pt_, 48000, cng_pt_fb);
   ResetAudioEncoder();
   CHECK(encoder_);
 }
@@ -348,20 +348,23 @@
   encoder_ = audio_encoder_.get();
 
   // Attach RED if needed.
-  if (copy_red_enabled_) {
-    CHECK_NE(red_payload_type_, kInvalidPayloadType);
+  auto pt_iter =
+      FindSampleRateInMap(&red_pt_, audio_encoder_->SampleRateHz());
+  if (copy_red_enabled_ && pt_iter != red_pt_.end()) {
+    CHECK_NE(pt_iter->first, kInvalidPayloadType);
     AudioEncoderCopyRed::Config config;
-    config.payload_type = red_payload_type_;
+    config.payload_type = pt_iter->first;
     config.speech_encoder = encoder_;
     red_encoder_.reset(new AudioEncoderCopyRed(config));
     encoder_ = red_encoder_.get();
   } else {
     red_encoder_.reset();
+    copy_red_enabled_ = false;
   }
 
   // Attach CNG if needed.
   // Reverse-lookup from sample rate to complete key-value pair.
-  auto pt_iter =
+  pt_iter =
       FindSampleRateInMap(&cng_pt_, audio_encoder_->SampleRateHz());
   if (acm_codec_params_.enable_dtx && pt_iter != cng_pt_.end()) {
     AudioEncoderCng::Config config;
@@ -434,7 +437,12 @@
 }
 
 void ACMGenericCodec::SetCngPt(int sample_rate_hz, int payload_type) {
-  SetCngPtInMap(&cng_pt_, sample_rate_hz, payload_type);
+  SetPtInMap(&cng_pt_, sample_rate_hz, payload_type);
+  ResetAudioEncoder();
+}
+
+void ACMGenericCodec::SetRedPt(int sample_rate_hz, int payload_type) {
+  SetPtInMap(&red_pt_, sample_rate_hz, payload_type);
   ResetAudioEncoder();
 }
 
@@ -522,10 +530,10 @@
   return 0;
 }
 
-void ACMGenericCodec::EnableCopyRed(bool enable, int red_payload_type) {
+int ACMGenericCodec::SetCopyRed(bool enable) {
   copy_red_enabled_ = enable;
-  red_payload_type_ = red_payload_type;
   ResetAudioEncoder();
+  return copy_red_enabled_ == enable ? 0 : -1;
 }
 
 AudioEncoder* ACMGenericCodec::GetAudioEncoder() {
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 cf07ea4..6a5a04a 100644
--- a/webrtc/modules/audio_coding/main/acm2/acm_generic_codec.h
+++ b/webrtc/modules/audio_coding/main/acm2/acm_generic_codec.h
@@ -88,7 +88,7 @@
                   int cng_pt_swb,
                   int cng_pt_fb,
                   bool enable_red,
-                  int red_payload_type);
+                  int red_pt_nb);
   ~ACMGenericCodec();
 
   ///////////////////////////////////////////////////////////////////////////
@@ -216,6 +216,9 @@
   // Registers comfort noise at |sample_rate_hz| to use |payload_type|.
   void SetCngPt(int sample_rate_hz, int payload_type);
 
+  // Registers RED at |sample_rate_hz| to use |payload_type|.
+  void SetRedPt(int sample_rate_hz, int payload_type);
+
   ///////////////////////////////////////////////////////////////////////////
   // UpdateEncoderSampFreq()
   // Call this function to update the encoder sampling frequency. This
@@ -395,8 +398,15 @@
   //
   int SetPacketLossRate(int /* loss_rate */);
 
-  // Sets if CopyRed should be enabled.
-  void EnableCopyRed(bool enable, int red_payload_type);
+  ///////////////////////////////////////////////////////////////////////////
+  // int SetCopyRed()
+  // Enable or disable copy RED. It fails if there is no RED payload that
+  // matches the codec, e.g., sample rate differs.
+  //
+  // Return value:
+  //   -1 if failed,
+  //    0 if succeeded.
+  int SetCopyRed(bool enable);
 
   AudioEncoder* GetAudioEncoder();
 
@@ -427,7 +437,8 @@
   bool is_isac_;
   // Map from payload type to CNG sample rate (Hz).
   std::map<int, int> cng_pt_;
-  int red_payload_type_;
+  // Map from payload type to RED sample rate (Hz).
+  std::map<int, int> red_pt_;
   OpusApplicationMode opus_application_;
   bool opus_application_set_;
 };
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 01a4249..d0bce92 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
@@ -131,7 +131,7 @@
       cng_wb_pltype_(255),
       cng_swb_pltype_(255),
       cng_fb_pltype_(255),
-      red_pltype_(255),
+      red_nb_pltype_(255),
       vad_enabled_(false),
       dtx_enabled_(false),
       vad_mode_(VADNormal),
@@ -163,8 +163,8 @@
   // Register the default payload type for RED and for CNG at sampling rates of
   // 8, 16, 32 and 48 kHz.
   for (int i = (ACMCodecDB::kNumCodecs - 1); i >= 0; i--) {
-    if (IsCodecRED(i)) {
-      red_pltype_ = static_cast<uint8_t>(ACMCodecDB::database_[i].pltype);
+    if (IsCodecRED(i) && ACMCodecDB::database_[i].plfreq == 8000) {
+      red_nb_pltype_ = static_cast<uint8_t>(ACMCodecDB::database_[i].pltype);
     } else if (IsCodecCN(i)) {
       if (ACMCodecDB::database_[i].plfreq == 8000) {
         cng_nb_pltype_ = static_cast<uint8_t>(ACMCodecDB::database_[i].pltype);
@@ -319,7 +319,7 @@
   CriticalSectionScoped lock(acm_crit_sect_);
   my_codec = ACMCodecDB::CreateCodecInstance(
       codec, cng_nb_pltype_, cng_wb_pltype_, cng_swb_pltype_, cng_fb_pltype_,
-      red_enabled_, red_pltype_);
+      red_enabled_, red_nb_pltype_);
   if (my_codec == NULL) {
     // Error, could not create the codec.
     WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, id_,
@@ -426,7 +426,15 @@
       return -1;
     }
     // Set RED payload type.
-    red_pltype_ = static_cast<uint8_t>(send_codec.pltype);
+    if (send_codec.plfreq == 8000) {
+      red_nb_pltype_ = static_cast<uint8_t>(send_codec.pltype);
+    } else {
+      WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, id_,
+                   "RegisterSendCodec() failed, invalid frequency for RED "
+                   "registration");
+      return -1;
+    }
+    SetRedPayloadType(send_codec.plfreq, send_codec.pltype);
     return 0;
   }
 
@@ -539,6 +547,13 @@
     if (send_codec_registered_) {
       // If we change codec we start fresh with RED.
       // This is not strictly required by the standard.
+
+      if(codec_ptr->SetCopyRed(red_enabled_) < 0) {
+        // We tried to preserve the old red status, if failed, it means the
+        // red status has to be flipped.
+        red_enabled_ = !red_enabled_;
+      }
+
       codec_ptr->SetVAD(&dtx_enabled_, &vad_enabled_, &vad_mode_);
 
       if (!codec_ptr->HasInternalFEC()) {
@@ -906,7 +921,14 @@
     return -1;
   }
 
-  EnableCopyRedForAllCodecs(enable_red);
+  // If a send codec is registered, set RED for the codec. We now only support
+  // copy red.
+  if (HaveValidEncoder("SetCopyRed") &&
+      codecs_[current_send_codec_idx_]->SetCopyRed(enable_red) < 0) {
+      WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, id_,
+                   "SetREDStatus failed");
+      return -1;
+  }
   red_enabled_ = enable_red;
   return 0;
 #else
@@ -1461,10 +1483,11 @@
   }
 }
 
-void AudioCodingModuleImpl::EnableCopyRedForAllCodecs(bool enable) {
+void AudioCodingModuleImpl::SetRedPayloadType(int sample_rate_hz,
+                                              int payload_type) {
   for (auto* codec : codecs_) {
     if (codec) {
-      codec->EnableCopyRed(enable, red_pltype_);
+      codec->SetRedPt(sample_rate_hz, payload_type);
     }
   }
 }
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 237d0ad..e41f857 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
@@ -297,7 +297,7 @@
   void SetCngPayloadType(int sample_rate_hz, int payload_type)
       EXCLUSIVE_LOCKS_REQUIRED(acm_crit_sect_);
 
-  void EnableCopyRedForAllCodecs(bool enable)
+  void SetRedPayloadType(int sample_rate_hz, int payload_type)
       EXCLUSIVE_LOCKS_REQUIRED(acm_crit_sect_);
 
   CriticalSectionWrapper* acm_crit_sect_;
@@ -311,7 +311,7 @@
   uint8_t cng_swb_pltype_ GUARDED_BY(acm_crit_sect_);
   uint8_t cng_fb_pltype_ GUARDED_BY(acm_crit_sect_);
 
-  uint8_t red_pltype_ GUARDED_BY(acm_crit_sect_);
+  uint8_t red_nb_pltype_ GUARDED_BY(acm_crit_sect_);
   bool vad_enabled_ GUARDED_BY(acm_crit_sect_);
   bool dtx_enabled_ GUARDED_BY(acm_crit_sect_);
   ACMVADMode vad_mode_ GUARDED_BY(acm_crit_sect_);
diff --git a/webrtc/modules/audio_coding/main/test/TestRedFec.cc b/webrtc/modules/audio_coding/main/test/TestRedFec.cc
index 8f6ef9d..6027a4d 100644
--- a/webrtc/modules/audio_coding/main/test/TestRedFec.cc
+++ b/webrtc/modules/audio_coding/main/test/TestRedFec.cc
@@ -20,8 +20,30 @@
 #include "webrtc/system_wrappers/interface/trace.h"
 #include "webrtc/test/testsupport/fileutils.h"
 
+#ifdef SUPPORT_RED_WB
+#undef SUPPORT_RED_WB
+#endif
+
+#ifdef SUPPORT_RED_SWB
+#undef SUPPORT_RED_SWB
+#endif
+
+#ifdef SUPPORT_RED_FB
+#undef SUPPORT_RED_FB
+#endif
+
 namespace webrtc {
 
+namespace {
+  const char kNameL16[] = "L16";
+  const char kNamePCMU[] = "PCMU";
+  const char kNameISAC[] = "ISAC";
+  const char kNameG722[] = "G722";
+  const char kNameOPUS[] = "opus";
+  const char kNameCN[] = "CN";
+  const char kNameRED[] = "RED";
+}
+
 TestRedFec::TestRedFec()
     : _acmA(AudioCodingModule::Create(0)),
       _acmB(AudioCodingModule::Create(1)),
@@ -60,32 +82,68 @@
   _acmA->RegisterTransportCallback(_channelA2B);
   _channelA2B->RegisterReceiverACM(_acmB.get());
 
+#ifndef WEBRTC_CODEC_PCM16
+  EXPECT_TRUE(false) << "PCM16 needs to be activated to run this test\n");
+  return;
+#endif
+  EXPECT_EQ(0, RegisterSendCodec('A', kNameL16, 8000));
+  EXPECT_EQ(0, RegisterSendCodec('A', kNameCN, 8000));
+  EXPECT_EQ(0, RegisterSendCodec('A', kNameRED));
+  EXPECT_EQ(0, SetVAD(true, true, VADAggr));
+  EXPECT_EQ(0, _acmA->SetREDStatus(true));
+  EXPECT_TRUE(_acmA->REDStatus());
+
+  OpenOutFile(_testCntr);
+  Run();
+  _outFileB.Close();
+
+  RegisterSendCodec('A', kNamePCMU, 8000);
+  // Switch to another 8 kHz codec, RED should remain switched on.
+  EXPECT_TRUE(_acmA->REDStatus());
+  OpenOutFile(_testCntr);
+  Run();
+  _outFileB.Close();
+
 #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));
+  EXPECT_EQ(0, RegisterSendCodec('A', kNameG722, 16000));
+  EXPECT_EQ(0, RegisterSendCodec('A', kNameCN, 16000));
+
+#ifdef SUPPORT_RED_WB
+  // Switch codec, RED should remain.
+  EXPECT_TRUE(_acmA->REDStatus());
+#else
+  // Switch to a 16 kHz codec, RED should have been switched off.
+  EXPECT_FALSE(_acmA->REDStatus());
+#endif
+
   OpenOutFile(_testCntr);
   EXPECT_EQ(0, SetVAD(true, true, VADAggr));
   EXPECT_EQ(0, _acmA->SetREDStatus(false));
   EXPECT_FALSE(_acmA->REDStatus());
   Run();
-  _outFileB.Close();
-
+#ifdef SUPPORT_RED_WB
   EXPECT_EQ(0, _acmA->SetREDStatus(true));
   EXPECT_TRUE(_acmA->REDStatus());
-  OpenOutFile(_testCntr);
+#else
+  EXPECT_EQ(-1, _acmA->SetREDStatus(true));
+  EXPECT_FALSE(_acmA->REDStatus());
+#endif
   Run();
   _outFileB.Close();
 
-  char nameISAC[] = "iSAC";
-  RegisterSendCodec('A', nameISAC, 16000);
+  RegisterSendCodec('A', kNameISAC, 16000);
+
+#ifdef SUPPORT_RED_WB
+  // Switch codec, RED should remain.
+  EXPECT_TRUE(_acmA->REDStatus());
+#else
+  EXPECT_FALSE(_acmA->REDStatus());
+#endif
+
   OpenOutFile(_testCntr);
   EXPECT_EQ(0, SetVAD(true, true, VADVeryAggr));
   EXPECT_EQ(0, _acmA->SetREDStatus(false));
@@ -93,13 +151,27 @@
   Run();
   _outFileB.Close();
 
+#ifdef SUPPORT_RED_WB
   EXPECT_EQ(0, _acmA->SetREDStatus(true));
   EXPECT_TRUE(_acmA->REDStatus());
+#else
+  EXPECT_EQ(-1, _acmA->SetREDStatus(true));
+  EXPECT_FALSE(_acmA->REDStatus());
+#endif
   OpenOutFile(_testCntr);
   Run();
   _outFileB.Close();
 
-  RegisterSendCodec('A', nameISAC, 32000);
+  RegisterSendCodec('A', kNameISAC, 32000);
+
+#if defined(SUPPORT_RED_SWB) && defined(SUPPORT_RED_WB)
+  // Switch codec, RED should remain.
+  EXPECT_TRUE(_acmA->REDStatus());
+#else
+  // Switch to a 32 kHz codec, RED should have been switched off.
+  EXPECT_FALSE(_acmA->REDStatus());
+#endif
+
   OpenOutFile(_testCntr);
   EXPECT_EQ(0, SetVAD(true, true, VADVeryAggr));
   EXPECT_EQ(0, _acmA->SetREDStatus(false));
@@ -107,36 +179,57 @@
   Run();
   _outFileB.Close();
 
+#ifdef SUPPORT_RED_SWB
   EXPECT_EQ(0, _acmA->SetREDStatus(true));
   EXPECT_TRUE(_acmA->REDStatus());
+#else
+  EXPECT_EQ(-1, _acmA->SetREDStatus(true));
+  EXPECT_FALSE(_acmA->REDStatus());
+#endif
   OpenOutFile(_testCntr);
   Run();
   _outFileB.Close();
 
-  RegisterSendCodec('A', nameISAC, 32000);
-  OpenOutFile(_testCntr);
+  RegisterSendCodec('A', kNameISAC, 32000);
   EXPECT_EQ(0, SetVAD(false, false, VADNormal));
+
+#if defined(SUPPORT_RED_SWB) && defined(SUPPORT_RED_WB)
+  OpenOutFile(_testCntr);
   EXPECT_EQ(0, _acmA->SetREDStatus(true));
   EXPECT_TRUE(_acmA->REDStatus());
   Run();
 
-  RegisterSendCodec('A', nameISAC, 16000);
+  RegisterSendCodec('A', kNameISAC, 16000);
   EXPECT_TRUE(_acmA->REDStatus());
   Run();
 
-  RegisterSendCodec('A', nameISAC, 32000);
+  RegisterSendCodec('A', kNameISAC, 32000);
   EXPECT_TRUE(_acmA->REDStatus());
   Run();
 
-  RegisterSendCodec('A', nameISAC, 16000);
+  RegisterSendCodec('A', kNameISAC, 16000);
   EXPECT_TRUE(_acmA->REDStatus());
   Run();
   _outFileB.Close();
+#else
+  EXPECT_EQ(-1, _acmA->SetREDStatus(true));
+  EXPECT_FALSE(_acmA->REDStatus());
+#endif
 
   _channelA2B->SetFECTestWithPacketLoss(true);
+  // Following tests are under packet losses.
 
-  EXPECT_EQ(0, RegisterSendCodec('A', nameG722));
-  EXPECT_EQ(0, RegisterSendCodec('A', nameCN, 16000));
+  EXPECT_EQ(0, RegisterSendCodec('A', kNameG722));
+  EXPECT_EQ(0, RegisterSendCodec('A', kNameCN, 16000));
+
+#if defined(SUPPORT_RED_WB) && defined(SUPPORT_RED_SWB)
+  // Switch codec, RED should remain.
+  EXPECT_TRUE(_acmA->REDStatus());
+#else
+  // Switch to a 16 kHz codec, RED should have been switched off.
+  EXPECT_FALSE(_acmA->REDStatus());
+#endif
+
   OpenOutFile(_testCntr);
   EXPECT_EQ(0, SetVAD(true, true, VADAggr));
   EXPECT_EQ(0, _acmA->SetREDStatus(false));
@@ -144,59 +237,93 @@
   Run();
   _outFileB.Close();
 
+#ifdef SUPPORT_RED_WB
   EXPECT_EQ(0, _acmA->SetREDStatus(true));
   EXPECT_TRUE(_acmA->REDStatus());
+#else
+  EXPECT_EQ(-1, _acmA->SetREDStatus(true));
+  EXPECT_FALSE(_acmA->REDStatus());
+#endif
   OpenOutFile(_testCntr);
   Run();
   _outFileB.Close();
 
-  RegisterSendCodec('A', nameISAC, 16000);
+  RegisterSendCodec('A', kNameISAC, 16000);
+
+#ifdef SUPPORT_RED_WB
+  // Switch codec, RED should remain.
+  EXPECT_TRUE(_acmA->REDStatus());
+#else
+  // Switch to a 16 kHz codec, RED should have been switched off.
+  EXPECT_FALSE(_acmA->REDStatus());
+#endif
+
   OpenOutFile(_testCntr);
   EXPECT_EQ(0, SetVAD(true, true, VADVeryAggr));
   EXPECT_EQ(0, _acmA->SetREDStatus(false));
   EXPECT_FALSE(_acmA->REDStatus());
   Run();
   _outFileB.Close();
-
+#ifdef SUPPORT_RED_WB
   EXPECT_EQ(0, _acmA->SetREDStatus(true));
   EXPECT_TRUE(_acmA->REDStatus());
+#else
+  EXPECT_EQ(-1, _acmA->SetREDStatus(true));
+  EXPECT_FALSE(_acmA->REDStatus());
+#endif
   OpenOutFile(_testCntr);
   Run();
   _outFileB.Close();
 
-  RegisterSendCodec('A', nameISAC, 32000);
+  RegisterSendCodec('A', kNameISAC, 32000);
+
+#if defined(SUPPORT_RED_SWB) && defined(SUPPORT_RED_WB)
+  // Switch codec, RED should remain.
+  EXPECT_TRUE(_acmA->REDStatus());
+#else
+  // Switch to a 32 kHz codec, RED should have been switched off.
+  EXPECT_FALSE(_acmA->REDStatus());
+#endif
+
   OpenOutFile(_testCntr);
   EXPECT_EQ(0, SetVAD(true, true, VADVeryAggr));
   EXPECT_EQ(0, _acmA->SetREDStatus(false));
   EXPECT_FALSE(_acmA->REDStatus());
-  Run();
-  _outFileB.Close();
-
+#ifdef SUPPORT_RED_SWB
   EXPECT_EQ(0, _acmA->SetREDStatus(true));
   EXPECT_TRUE(_acmA->REDStatus());
+#else
+  EXPECT_EQ(-1, _acmA->SetREDStatus(true));
+  EXPECT_FALSE(_acmA->REDStatus());
+#endif
   OpenOutFile(_testCntr);
   Run();
   _outFileB.Close();
 
-  RegisterSendCodec('A', nameISAC, 32000);
-  OpenOutFile(_testCntr);
+  RegisterSendCodec('A', kNameISAC, 32000);
   EXPECT_EQ(0, SetVAD(false, false, VADNormal));
+#if defined(SUPPORT_RED_SWB) && defined(SUPPORT_RED_WB)
+  OpenOutFile(_testCntr);
   EXPECT_EQ(0, _acmA->SetREDStatus(true));
   EXPECT_TRUE(_acmA->REDStatus());
   Run();
 
-  RegisterSendCodec('A', nameISAC, 16000);
+  RegisterSendCodec('A', kNameISAC, 16000);
   EXPECT_TRUE(_acmA->REDStatus());
   Run();
 
-  RegisterSendCodec('A', nameISAC, 32000);
+  RegisterSendCodec('A', kNameISAC, 32000);
   EXPECT_TRUE(_acmA->REDStatus());
   Run();
 
-  RegisterSendCodec('A', nameISAC, 16000);
+  RegisterSendCodec('A', kNameISAC, 16000);
   EXPECT_TRUE(_acmA->REDStatus());
   Run();
   _outFileB.Close();
+#else
+  EXPECT_EQ(-1, _acmA->SetREDStatus(true));
+  EXPECT_FALSE(_acmA->REDStatus());
+#endif
 
 #ifndef WEBRTC_CODEC_OPUS
   EXPECT_TRUE(false);
@@ -204,14 +331,22 @@
   return;
 #endif
 
-  char nameOpus[] = "opus";
-  RegisterSendCodec('A', nameOpus, 48000);
+  RegisterSendCodec('A', kNameOPUS, 48000);
 
+#if defined(SUPPORT_RED_FB) && defined(SUPPORT_RED_SWB) &&\
+  defined(SUPPORT_RED_WB)
+  // Switch to codec, RED should remain switched on.
   EXPECT_TRUE(_acmA->REDStatus());
+#else
+  EXPECT_FALSE(_acmA->REDStatus());
+#endif
 
   // _channelA2B imposes 25% packet loss rate.
   EXPECT_EQ(0, _acmA->SetPacketLossRate(25));
 
+#ifdef SUPPORT_RED_FB
+  EXPECT_EQ(0, _acmA->SetREDStatus(true));
+  EXPECT_TRUE(_acmA->REDStatus());
   // Codec FEC and RED are mutually exclusive.
   EXPECT_EQ(-1, _acmA->SetCodecFEC(true));
 
@@ -220,16 +355,21 @@
 
   // Codec FEC and RED are mutually exclusive.
   EXPECT_EQ(-1, _acmA->SetREDStatus(true));
+#else
+  EXPECT_EQ(-1, _acmA->SetREDStatus(true));
+  EXPECT_FALSE(_acmA->REDStatus());
+  EXPECT_EQ(0, _acmA->SetCodecFEC(true));
+#endif
 
   EXPECT_TRUE(_acmA->CodecFEC());
   OpenOutFile(_testCntr);
   Run();
 
-  // Switch to ISAC with RED.
-  RegisterSendCodec('A', nameISAC, 32000);
+  // Switch to L16 with RED.
+  RegisterSendCodec('A', kNameL16, 8000);
   EXPECT_EQ(0, SetVAD(false, false, VADNormal));
 
-  // ISAC does not support FEC, so FEC should be turned off automatically.
+  // L16 does not support FEC, so FEC should be turned off automatically.
   EXPECT_FALSE(_acmA->CodecFEC());
 
   EXPECT_EQ(0, _acmA->SetREDStatus(true));
@@ -237,32 +377,38 @@
   Run();
 
   // Switch to Opus again.
-  RegisterSendCodec('A', nameOpus, 48000);
-  EXPECT_EQ(0, _acmA->SetCodecFEC(false));
+  RegisterSendCodec('A', kNameOPUS, 48000);
+#ifdef SUPPORT_RED_FB
+  // Switch to codec, RED should remain switched on.
+  EXPECT_TRUE(_acmA->REDStatus());
+#else
+  EXPECT_FALSE(_acmA->REDStatus());
+#endif
   EXPECT_EQ(0, _acmA->SetREDStatus(false));
+  EXPECT_EQ(0, _acmA->SetCodecFEC(false));
   Run();
 
   EXPECT_EQ(0, _acmA->SetCodecFEC(true));
   _outFileB.Close();
 
   // Codecs does not support internal FEC, cannot enable FEC.
-  RegisterSendCodec('A', nameG722, 16000);
+  RegisterSendCodec('A', kNameG722, 16000);
   EXPECT_FALSE(_acmA->REDStatus());
   EXPECT_EQ(-1, _acmA->SetCodecFEC(true));
   EXPECT_FALSE(_acmA->CodecFEC());
 
-  RegisterSendCodec('A', nameISAC, 16000);
+  RegisterSendCodec('A', kNameISAC, 16000);
   EXPECT_FALSE(_acmA->REDStatus());
   EXPECT_EQ(-1, _acmA->SetCodecFEC(true));
   EXPECT_FALSE(_acmA->CodecFEC());
 
   // Codecs does not support internal FEC, disable FEC does not trigger failure.
-  RegisterSendCodec('A', nameG722, 16000);
+  RegisterSendCodec('A', kNameG722, 16000);
   EXPECT_FALSE(_acmA->REDStatus());
   EXPECT_EQ(0, _acmA->SetCodecFEC(false));
   EXPECT_FALSE(_acmA->CodecFEC());
 
-  RegisterSendCodec('A', nameISAC, 16000);
+  RegisterSendCodec('A', kNameISAC, 16000);
   EXPECT_FALSE(_acmA->REDStatus());
   EXPECT_EQ(0, _acmA->SetCodecFEC(false));
   EXPECT_FALSE(_acmA->CodecFEC());
@@ -272,7 +418,7 @@
   return _acmA->SetVAD(enableDTX, enableVAD, vadMode);
 }
 
-int16_t TestRedFec::RegisterSendCodec(char side, char* codecName,
+int16_t TestRedFec::RegisterSendCodec(char side, const char* codecName,
                                       int32_t samplingFreqHz) {
   std::cout << std::flush;
   AudioCodingModule* myACM;
@@ -304,9 +450,6 @@
 
 void TestRedFec::Run() {
   AudioFrame audioFrame;
-
-  uint16_t msecPassed = 0;
-  uint32_t secPassed = 0;
   int32_t outFreqHzB = _outFileB.SamplingFrequency();
 
   while (!_inFileA.EndOfFile()) {
@@ -314,18 +457,6 @@
     EXPECT_GE(_acmA->Add10MsData(audioFrame), 0);
     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();
 }
diff --git a/webrtc/modules/audio_coding/main/test/TestRedFec.h b/webrtc/modules/audio_coding/main/test/TestRedFec.h
index 57d9fe9..ac0b6cd 100644
--- a/webrtc/modules/audio_coding/main/test/TestRedFec.h
+++ b/webrtc/modules/audio_coding/main/test/TestRedFec.h
@@ -31,7 +31,7 @@
   // The default value of '-1' indicates that the registration is based only on
   // codec name and a sampling frequency matching is not required. This is
   // useful for codecs which support several sampling frequency.
-  int16_t RegisterSendCodec(char side, char* codecName,
+  int16_t RegisterSendCodec(char side, const char* codecName,
                             int32_t sampFreqHz = -1);
   void Run();
   void OpenOutFile(int16_t testNumber);