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
This commit is contained in:
parent
1596a4f88b
commit
41d2befe9f
@ -45,19 +45,19 @@ std::map<int, int>::iterator FindSampleRateInMap(std::map<int, int>* cng_pt_map,
|
||||
});
|
||||
}
|
||||
|
||||
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 @@ 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() {
|
||||
|
@ -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<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_;
|
||||
};
|
||||
|
@ -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<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 @@ 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<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 @@ 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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_);
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user