From 41d2befe9f34ba8706dbf0d2d3ede54af761b5bf Mon Sep 17 00:00:00 2001 From: "minyue@webrtc.org" Date: Mon, 23 Mar 2015 12:57:45 +0000 Subject: [PATCH] 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 --- .../main/acm2/acm_generic_codec.cc | 48 ++-- .../main/acm2/acm_generic_codec.h | 19 +- .../main/acm2/audio_coding_module_impl.cc | 39 ++- .../main/acm2/audio_coding_module_impl.h | 4 +- .../audio_coding/main/test/TestRedFec.cc | 245 ++++++++++++++---- .../audio_coding/main/test/TestRedFec.h | 2 +- 6 files changed, 265 insertions(+), 92 deletions(-) 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 2fc43061e9..c472a4a116 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 @@ std::map::iterator FindSampleRateInMap(std::map* cng_pt_map, }); } -void SetCngPtInMap(std::map* cng_pt_map, - int sample_rate_hz, - int payload_type) { +void SetPtInMap(std::map* 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 @@ ACMGenericCodec::ACMGenericCodec(const CodecInst& codec_inst, 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 @@ ACMGenericCodec::ACMGenericCodec(const CodecInst& codec_inst, 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 @@ void ACMGenericCodec::ResetAudioEncoder() { 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 @@ int16_t ACMGenericCodec::SetVAD(bool* enable_dtx, } 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 @@ int ACMGenericCodec::SetPacketLossRate(int loss_rate) { 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 cf07ea4dbe..6a5a04a07a 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 @@ class ACMGenericCodec { int cng_pt_swb, int cng_pt_fb, bool enable_red, - int red_payload_type); + int red_pt_nb); ~ACMGenericCodec(); /////////////////////////////////////////////////////////////////////////// @@ -216,6 +216,9 @@ class ACMGenericCodec { // 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 @@ class ACMGenericCodec { // 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 @@ class ACMGenericCodec { bool is_isac_; // Map from payload type to CNG sample rate (Hz). std::map cng_pt_; - int red_payload_type_; + // Map from payload type to RED sample rate (Hz). + std::map 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 01a4249588..d0bce92329 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 @@ AudioCodingModuleImpl::AudioCodingModuleImpl( 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 @@ AudioCodingModuleImpl::AudioCodingModuleImpl( // 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(ACMCodecDB::database_[i].pltype); + if (IsCodecRED(i) && ACMCodecDB::database_[i].plfreq == 8000) { + red_nb_pltype_ = static_cast(ACMCodecDB::database_[i].pltype); } else if (IsCodecCN(i)) { if (ACMCodecDB::database_[i].plfreq == 8000) { cng_nb_pltype_ = static_cast(ACMCodecDB::database_[i].pltype); @@ -319,7 +319,7 @@ ACMGenericCodec* AudioCodingModuleImpl::CreateCodec(const CodecInst& codec) { 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 @@ int AudioCodingModuleImpl::RegisterSendCodec(const CodecInst& send_codec) { return -1; } // Set RED payload type. - red_pltype_ = static_cast(send_codec.pltype); + if (send_codec.plfreq == 8000) { + red_nb_pltype_ = static_cast(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 @@ int AudioCodingModuleImpl::RegisterSendCodec(const CodecInst& send_codec) { 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 @@ int AudioCodingModuleImpl::SetREDStatus( 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::SetCngPayloadType(int sample_rate_hz, } } -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 237d0ade0f..e41f857f95 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 @@ class AudioCodingModuleImpl : public AudioCodingModule { 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 @@ class AudioCodingModuleImpl : public AudioCodingModule { 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 8f6ef9d89c..6027a4d0e1 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 @@ void TestRedFec::Perform() { _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 @@ void TestRedFec::Perform() { 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 @@ void TestRedFec::Perform() { 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', 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 - 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)); @@ -144,59 +237,93 @@ void TestRedFec::Perform() { 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 @@ void TestRedFec::Perform() { 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 @@ void TestRedFec::Perform() { // 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 @@ void TestRedFec::Perform() { 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 @@ int32_t TestRedFec::SetVAD(bool enableDTX, bool enableVAD, ACMVADMode vadMode) { 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 @@ int16_t TestRedFec::RegisterSendCodec(char side, char* codecName, 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 @@ void TestRedFec::Run() { 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 57d9fe96c8..ac0b6cdfc7 100644 --- a/webrtc/modules/audio_coding/main/test/TestRedFec.h +++ b/webrtc/modules/audio_coding/main/test/TestRedFec.h @@ -31,7 +31,7 @@ class TestRedFec : public ACMTest { // 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);