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:
@ -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);
|
||||
|
||||
Reference in New Issue
Block a user