Reregister of stereo receiver didn't work.

This CL takes care of the re-registration of codecs, and tests unregistering stereo codecs.

One bug fixed in Celt too.

TEST=audio_coding_module_test: TestStereo.

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

git-svn-id: http://webrtc.googlecode.com/svn/trunk@1859 4adac7df-926f-26a2-2b94-8c16560cd09d
This commit is contained in:
tina.legrand@webrtc.org 2012-03-08 13:23:18 +00:00
parent 50d9e26eea
commit f1befad273
6 changed files with 435 additions and 137 deletions

View File

@ -303,11 +303,21 @@ bool ACMCELT::IsTrueStereoCodec() {
int16_t ACMCELT::SetBitRateSafe(const int32_t rate) {
// Check that rate is in the valid range.
if ((rate >= 48000) && (rate <= 128000)) {
// Store new rate.
bitrate_ = rate;
return 0;
// Initiate encoder with new rate.
if (WebRtcCelt_EncoderInit(enc_inst_ptr_, channels_, bitrate_) >= 0) {
return 0;
} else {
WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, _uniqueID,
"SetBitRateSafe: Failed to initiate Celt with rate %d",
rate);
return -1;
}
} else {
WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, _uniqueID,
"SetBitRateSafe: Invalid rate Celt");
"SetBitRateSafe: Invalid rate Celt, %d", rate);
return -1;
}
}

View File

@ -50,9 +50,15 @@ AudioCodingModuleImpl::AudioCodingModuleImpl(
_id(id),
_lastTimestamp(0),
_lastInTimestamp(0),
_cng_nb_pltype(255),
_cng_wb_pltype(255),
_cng_swb_pltype(255),
_red_pltype(255),
_cng_reg_receiver(false),
_vadEnabled(false),
_dtxEnabled(false),
_vadMode(VADNormal),
_stereoReceiveRegistered(false),
_stereoSend(false),
_prev_received_channel(0),
_expected_channels(1),
@ -65,7 +71,6 @@ AudioCodingModuleImpl::AudioCodingModuleImpl(
_fecEnabled(false),
_fragmentation(NULL),
_lastFECTimestamp(0),
_redPayloadType(255),
_receiveREDPayloadType(255), // invalid value
_previousPayloadType(255),
_dummyRTPHeader(NULL),
@ -85,13 +90,6 @@ AudioCodingModuleImpl::AudioCodingModuleImpl(
strncpy(_sendCodecInst.plname, "noCodecRegistered", 31);
_sendCodecInst.pltype = -1;
// Nullify memory for CNG, DTMF and RED.
memset(&_cngNB, 0, sizeof(CodecInst));
memset(&_cngWB, 0, sizeof(CodecInst));
memset(&_cngSWB, 0, sizeof(CodecInst));
memset(&_RED, 0, sizeof(CodecInst));
memset(&_DTMF, 0, sizeof(CodecInst));
for (int i = 0; i < ACMCodecDB::kMaxNumCodecs; i++)
{
_codecs[i] = NULL;
@ -118,20 +116,23 @@ AudioCodingModuleImpl::AudioCodingModuleImpl(
{
if((STR_CASE_CMP(ACMCodecDB::database_[i].plname, "red") == 0))
{
_redPayloadType = ACMCodecDB::database_[i].pltype;
_red_pltype = static_cast<uint8_t>(ACMCodecDB::database_[i].pltype);
}
else if ((STR_CASE_CMP(ACMCodecDB::database_[i].plname, "CN") == 0))
{
if (ACMCodecDB::database_[i].plfreq == 8000)
{
memcpy(&_cngNB, &ACMCodecDB::database_[i], sizeof(_cngNB));
_cng_nb_pltype =
static_cast<uint8_t>(ACMCodecDB::database_[i].pltype);
}
else if (ACMCodecDB::database_[i].plfreq == 16000)
{
memcpy(&_cngWB, &ACMCodecDB::database_[i], sizeof(_cngWB));
_cng_wb_pltype =
static_cast<uint8_t>(ACMCodecDB::database_[i].pltype);
} else if (ACMCodecDB::database_[i].plfreq == 32000)
{
memcpy(&_cngSWB, &ACMCodecDB::database_[i], sizeof(_cngSWB));
_cng_swb_pltype =
static_cast<uint8_t>(ACMCodecDB::database_[i].pltype);
}
}
}
@ -384,21 +385,21 @@ AudioCodingModuleImpl::Process()
}
case kPassiveDTXNB:
{
currentPayloadType = (WebRtc_UWord8)_cngNB.pltype;
currentPayloadType = _cng_nb_pltype;
frameType = kAudioFrameCN;
_isFirstRED = true;
break;
}
case kPassiveDTXWB:
{
currentPayloadType = (WebRtc_UWord8)_cngWB.pltype;
currentPayloadType = _cng_wb_pltype;
frameType = kAudioFrameCN;
_isFirstRED = true;
break;
}
case kPassiveDTXSWB:
{
currentPayloadType = (WebRtc_UWord8)_cngSWB.pltype;
currentPayloadType = _cng_swb_pltype;
frameType = kAudioFrameCN;
_isFirstRED = true;
break;
@ -506,7 +507,7 @@ AudioCodingModuleImpl::Process()
_isFirstRED = false;
// Update payload type with RED payload type
currentPayloadType = _redPayloadType;
currentPayloadType = _red_pltype;
}
}
}
@ -681,6 +682,8 @@ mono codecs are supported, i.e. channels=1.", sendCodec.channels);
// payload type is used.
if(!STR_CASE_CMP(sendCodec.plname, "red"))
{
// TODO(tlegrand): Remove this check. Already taken care of in
// ACMCodecDB::CodecNumber().
// Check if the payload-type is valid
if(!ACMCodecDB::ValidPayloadType(sendCodec.pltype))
{
@ -690,12 +693,12 @@ mono codecs are supported, i.e. channels=1.", sendCodec.channels);
return -1;
}
// Set RED payload type
_redPayloadType = (WebRtc_UWord8)sendCodec.pltype;
_red_pltype = static_cast<uint8_t>(sendCodec.pltype);
return 0;
}
// CNG can be registered with other payload type. If not registered the
// default payload types will be used: CNNB=13 (fixed), CNWB=97, CNSWB=98
// default payload types from codec database will be used.
if(!STR_CASE_CMP(sendCodec.plname, "CN"))
{
// CNG is registered
@ -703,17 +706,17 @@ mono codecs are supported, i.e. channels=1.", sendCodec.channels);
{
case 8000:
{
memcpy(&_cngNB, &sendCodec, sizeof(_cngNB));
_cng_nb_pltype = static_cast<uint8_t>(sendCodec.pltype);
break;
}
case 16000:
{
memcpy(&_cngWB, &sendCodec, sizeof(_cngWB));
_cng_wb_pltype = static_cast<uint8_t>(sendCodec.pltype);
break;
}
case 32000:
{
memcpy(&_cngSWB, &sendCodec, sizeof(_cngSWB));
_cng_swb_pltype = static_cast<uint8_t>(sendCodec.pltype);
break;
}
default :
@ -727,6 +730,8 @@ mono codecs are supported, i.e. channels=1.", sendCodec.channels);
return 0;
}
// TODO(tlegrand): Remove this check. Already taken care of in
// ACMCodecDB::CodecNumber().
// Check if the payload-type is valid
if(!ACMCodecDB::ValidPayloadType(sendCodec.pltype))
{
@ -1406,6 +1411,7 @@ AudioCodingModuleImpl::InitializeReceiverSafe()
regInNeteq = 0;
}
}
_cng_reg_receiver = true;
_receiverInitialized = true;
return 0;
@ -1507,11 +1513,15 @@ AudioCodingModuleImpl::RegisterReceiveCodec(
}
}
// If codec already registered, start with unregistering
if(_registeredPlTypes[codecId] != -1)
{
if(UnregisterReceiveCodecSafe(codecId) < 0)
{
// If codec already registered, unregister. Except for CN where we only
// unregister if payload type is changing.
if ((_registeredPlTypes[codecId] == receiveCodec.pltype) &&
(STR_CASE_CMP(receiveCodec.plname, "CN") == 0)) {
// Codec already registered as receiver with this payload type. Nothing
// to be done.
return 0;
} else if (_registeredPlTypes[codecId] != -1) {
if(UnregisterReceiveCodecSafe(codecId) < 0) {
WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, _id,
"Cannot register master codec.");
return -1;
@ -1526,7 +1536,27 @@ AudioCodingModuleImpl::RegisterReceiveCodec(
return -1;
}
// If receive stereo, make sure we have two instances of NetEQ, one for each channel
// If CN is being registered in master, and we have at least one stereo
// codec registered in receiver, register CN in slave.
if (STR_CASE_CMP(receiveCodec.plname, "CN") == 0) {
_cng_reg_receiver = true;
if (_stereoReceiveRegistered) {
// At least one of the registered receivers is stereo, so go
// a head and add CN to the slave.
if(RegisterRecCodecMSSafe(receiveCodec, codecId, mirrorId,
ACMNetEQ::slaveJB) < 0) {
WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding,
_id, "Cannot register slave codec.");
return -1;
}
_stereoReceive[codecId] = true;
_registeredPlTypes[codecId] = receiveCodec.pltype;
return 0;
}
}
// If receive stereo, make sure we have two instances of NetEQ, one for each
// channel. Mark CN and RED as stereo.
if(receiveCodec.channels == 2)
{
if(_netEq.NumSlaves() < 1)
@ -1534,28 +1564,48 @@ AudioCodingModuleImpl::RegisterReceiveCodec(
if(_netEq.AddSlave(ACMCodecDB::NetEQDecoders(),
ACMCodecDB::kNumCodecs) < 0)
{
WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, _id,
"Cannot Add Slave jitter buffer to NetEQ.");
WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding,
_id, "Cannot Add Slave jitter buffer to NetEQ.");
return -1;
}
}
// Register RED and CN in slave.
// If this is the first time a stereo codec is registered, RED and CN
// should be register in slave, if they are registered in master.
if (!_stereoReceiveRegistered) {
bool reg_in_neteq = false;
for (int i = (ACMCodecDB::kNumCodecs - 1); i > -1; i--) {
if((STR_CASE_CMP(ACMCodecDB::database_[i].plname, "RED") == 0)) {
reg_in_neteq = true;
} else if ((STR_CASE_CMP(ACMCodecDB::database_[i].plname, "CN") == 0)) {
reg_in_neteq = true;
if (STR_CASE_CMP(ACMCodecDB::database_[i].plname, "RED") == 0) {
if (_registeredPlTypes[i] != -1) {
// Mark RED as stereo, since we have registered at least
// one stereo receive codec.
_stereoReceive[i] = true;
reg_in_neteq = true;
}
} else if (STR_CASE_CMP(ACMCodecDB::database_[i].plname, "CN")
== 0) {
if (_cng_reg_receiver) {
// Mark CN as stereo, since we have registered at least
// one stereo receive codec.
_stereoReceive[i] = true;
reg_in_neteq = true;
}
}
if (reg_in_neteq) {
if(RegisterRecCodecMSSafe(ACMCodecDB::database_[i], i, i,
ACMNetEQ::slaveJB) < 0) {
WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, _id,
"Cannot register slave codec.");
CodecInst tmp_codec;
memcpy(&tmp_codec, &ACMCodecDB::database_[i],
sizeof(CodecInst));
tmp_codec.pltype = _registeredPlTypes[i];
// Register RED of CN in slave, with the same payload type
// as in master.
if(RegisterRecCodecMSSafe(tmp_codec, i, i,
ACMNetEQ::slaveJB) < 0) {
WEBRTC_TRACE(webrtc::kTraceError,
webrtc::kTraceAudioCoding, _id,
"Cannot register slave codec.");
return -1;
}
_registeredPlTypes[i] = ACMCodecDB::database_[i].pltype;
reg_in_neteq = false;
}
}
@ -1569,12 +1619,15 @@ AudioCodingModuleImpl::RegisterReceiveCodec(
return -1;
}
// Last received payload type equal the current one, but was marked
// as mono. Reset to avoid problems.
if((_stereoReceive[codecId] == false) &&
(_lastRecvAudioCodecPlType == receiveCodec.pltype))
{
_lastRecvAudioCodecPlType = -1;
}
_stereoReceive[codecId] = true;
_stereoReceiveRegistered = true;
}
else
{
@ -1761,11 +1814,9 @@ AudioCodingModuleImpl::IncomingPacket(
myPayloadType = rtpInfo.header.payloadType;
}
// If payload is audio, check if received payload is different from previous
if((!rtpInfo.type.Audio.isCNG) &&
(myPayloadType != _cngNB.pltype) &&
(myPayloadType != _cngWB.pltype) &&
(myPayloadType != _cngSWB.pltype))
// If payload is audio, check if received payload is different from
// previous.
if(!rtpInfo.type.Audio.isCNG)
{
// This is Audio not CNG
@ -2554,12 +2605,16 @@ AudioCodingModuleImpl::UnregisterReceiveCodecSafe(
{
const WebRtcNetEQDecoder *neteqDecoder = ACMCodecDB::NetEQDecoders();
WebRtc_Word16 mirrorID = ACMCodecDB::MirrorID(codecID);
bool stereo_receiver = false;
if(_codecs[codecID] != NULL)
{
if(_registeredPlTypes[codecID] != -1)
{
// before deleting the decoder instance unregister
// from NetEQ.
// Store stereo information for future use.
stereo_receiver = _stereoReceive[codecID];
// Before deleting the decoder instance unregister from NetEQ.
if(_netEq.RemoveCodec(neteqDecoder[codecID], _stereoReceive[codecID]) < 0)
{
CodecInst codecInst;
@ -2575,6 +2630,8 @@ AudioCodingModuleImpl::UnregisterReceiveCodecSafe(
if(STR_CASE_CMP(ACMCodecDB::database_[codecID].plname, "CN") == 0)
{
// Search codecs nearby in the database to unregister all CN.
// TODO(tlegrand): do this search in a safe way. We can search
// outside the database.
for (int i=-2; i<3; i++)
{
if (STR_CASE_CMP(ACMCodecDB::database_[codecID+i].plname, "CN") == 0)
@ -2583,10 +2640,13 @@ AudioCodingModuleImpl::UnregisterReceiveCodecSafe(
if(_stereoReceive[codecID+i])
{
_slaveCodecs[codecID+i]->DestructDecoder();
_stereoReceive[codecID+i] = false;
}
_registeredPlTypes[codecID+i] = -1;
}
}
_cng_reg_receiver = false;
} else
{
if(codecID == mirrorID)
@ -2595,9 +2655,29 @@ AudioCodingModuleImpl::UnregisterReceiveCodecSafe(
if(_stereoReceive[codecID])
{
_slaveCodecs[codecID]->DestructDecoder();
_stereoReceive[codecID] = false;
}
}
}
// Check if this is the last registered stereo receive codec.
if (stereo_receiver) {
bool no_stereo = true;
for (int i = 0; i < ACMCodecDB::kNumCodecs; i++) {
if (_stereoReceive[i]) {
// We still have stereo codecs registered.
no_stereo = false;
break;
}
}
// If we don't have any stereo codecs left, change status.
if (no_stereo) {
_stereoReceiveRegistered = false;
}
}
}
}

View File

@ -311,11 +311,11 @@ private:
WebRtc_UWord32 _lastTimestamp;
WebRtc_UWord32 _lastInTimestamp;
CodecInst _sendCodecInst;
CodecInst _cngNB;
CodecInst _cngWB;
CodecInst _cngSWB;
CodecInst _RED;
CodecInst _DTMF;
uint8_t _cng_nb_pltype;
uint8_t _cng_wb_pltype;
uint8_t _cng_swb_pltype;
uint8_t _red_pltype;
bool _cng_reg_receiver;
bool _vadEnabled;
bool _dtxEnabled;
ACMVADMode _vadMode;
@ -323,6 +323,7 @@ private:
ACMGenericCodec* _slaveCodecs[ACMCodecDB::kMaxNumCodecs];
WebRtc_Word16 _mirrorCodecIdx[ACMCodecDB::kMaxNumCodecs];
bool _stereoReceive[ACMCodecDB::kMaxNumCodecs];
bool _stereoReceiveRegistered;
bool _stereoSend;
int _prev_received_channel;
int _expected_channels;
@ -341,7 +342,6 @@ private:
WebRtc_UWord8* _redBuffer;
RTPFragmentationHeader* _fragmentation;
WebRtc_UWord32 _lastFECTimestamp;
WebRtc_UWord8 _redPayloadType;
// if no RED is registered as receive codec this
// will have an invalid value.
WebRtc_UWord8 _receiveREDPayloadType;

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
* Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
@ -85,6 +85,9 @@ void Sender::Setup(AudioCodingModule *acm, RTPStream *rtpStream) {
}
acm->Codec(codecNo, sendCodec);
if (!strcmp(sendCodec.plname, "CELT")) {
sendCodec.channels = 1;
}
acm->RegisterSendCodec(sendCodec);
_packetization = new TestPacketization(rtpStream, sendCodec.plfreq);
if (acm->RegisterTransportCallback(_packetization) < 0) {
@ -146,6 +149,9 @@ void Receiver::Setup(AudioCodingModule *acm, RTPStream *rtpStream) {
noOfCodecs = acm->NumberOfCodecs();
for (int i = 0; i < noOfCodecs; i++) {
acm->Codec((WebRtc_UWord8) i, recvCodec);
if (!strcmp(recvCodec.plname, "CELT")) {
recvCodec.channels = 1;
}
if (acm->RegisterReceiveCodec(recvCodec) != 0) {
printf("Unable to register codec: for run: codecId: %d\n", codeId);
exit(1);

View File

@ -175,7 +175,17 @@ _channelA2B(NULL),
_testCntr(0),
_packSizeSamp(0),
_packSizeBytes(0),
_counter(0)
_counter(0),
g722_pltype_(0),
l16_8khz_pltype_(-1),
l16_16khz_pltype_(-1),
l16_32khz_pltype_(-1),
pcma_pltype_(-1),
pcmu_pltype_(-1),
celt_pltype_(-1),
cn_8khz_pltype_(-1),
cn_16khz_pltype_(-1),
cn_32khz_pltype_(-1)
{
// testMode = 0 for silent test (auto test)
_testMode = testMode;
@ -207,6 +217,7 @@ void TestStereo::Perform()
WebRtc_UWord16 frequencyHz;
int audio_channels;
int codec_channels;
int status;
if(_testMode == 0)
{
@ -233,23 +244,141 @@ void TestStereo::Perform()
WebRtc_UWord8 numEncoders = _acmA->NumberOfCodecs();
CodecInst myCodecParam;
// Register receiving codecs as stereo.
// Register receiving codecs, some of them as stereo.
for(WebRtc_UWord8 n = 0; n < numEncoders; n++) {
_acmB->Codec(n, myCodecParam);
if (!strcmp(myCodecParam.plname, "L16")) {
if (myCodecParam.plfreq == 8000) {
l16_8khz_pltype_ = myCodecParam.pltype;
} else if (myCodecParam.plfreq == 16000) {
l16_16khz_pltype_ = myCodecParam.pltype;
} else if (myCodecParam.plfreq == 32000) {
l16_32khz_pltype_ = myCodecParam.pltype;
}
myCodecParam.channels=2;
} else if (!strcmp(myCodecParam.plname, "PCMA")) {
pcma_pltype_ = myCodecParam.pltype;
myCodecParam.channels=2;
} else if (!strcmp(myCodecParam.plname, "PCMU")) {
pcmu_pltype_ = myCodecParam.pltype;
myCodecParam.channels=2;
} else if (!strcmp(myCodecParam.plname, "G722")) {
g722_pltype_ = myCodecParam.pltype;
myCodecParam.channels=2;
} else if (!strcmp(myCodecParam.plname, "CELT")) {
celt_pltype_ = myCodecParam.pltype;
myCodecParam.channels=2;
}
_acmB->RegisterReceiveCodec(myCodecParam);
}
// Test that unregister all receive codecs works for stereo.
for(WebRtc_UWord8 n = 0; n < numEncoders; n++)
{
_acmB->Codec(n, myCodecParam);
if(!strcmp(myCodecParam.plname, "L16") ||
!strcmp(myCodecParam.plname, "PCMA")||
!strcmp(myCodecParam.plname, "PCMU")||
!strcmp(myCodecParam.plname, "G722")||
!strcmp(myCodecParam.plname, "CELT"))
{
myCodecParam.channels=2;
_acmB->RegisterReceiveCodec(myCodecParam);
status = _acmB->Codec(n, myCodecParam);
if (status < 0) {
printf("Error in Codec(), no matching codec found");
}
status = _acmB->UnregisterReceiveCodec(myCodecParam.pltype);
if (status < 0) {
printf("Error in UnregisterReceiveCodec() for payload type %d",
myCodecParam.pltype);
}
}
// Register receiving mono codecs, except comfort noise.
for(WebRtc_UWord8 n = 0; n < numEncoders; n++)
{
status = _acmB->Codec(n, myCodecParam);
if (status < 0) {
printf("Error in Codec(), no matching codec found");
}
if(!strcmp(myCodecParam.plname, "L16") ||
!strcmp(myCodecParam.plname, "PCMA")||
!strcmp(myCodecParam.plname, "PCMU")||
!strcmp(myCodecParam.plname, "G722")||
!strcmp(myCodecParam.plname, "CELT")||
!strcmp(myCodecParam.plname, "CN")){
} else {
status = _acmB->RegisterReceiveCodec(myCodecParam);
if (status < 0) {
printf("Error in UnregisterReceiveCodec() for codec number %d",
n);
}
}
}
// TODO(tlegrand): Take care of return values of all function calls.
// Re-register all stereo codecs needed in the test, with new payload
// numbers.
g722_pltype_ = 117;
l16_8khz_pltype_ = 120;
l16_16khz_pltype_ = 121;
l16_32khz_pltype_ = 122;
pcma_pltype_ = 110;
pcmu_pltype_ = 118;
celt_pltype_ = 119;
cn_8khz_pltype_ = 123;
cn_16khz_pltype_ = 124;
cn_32khz_pltype_ = 125;
// Register all stereo codecs with new payload types.
#ifdef WEBRTC_CODEC_G722
// G722
_acmB->Codec("G722", myCodecParam, 16000);
myCodecParam.pltype = g722_pltype_;
myCodecParam.channels = 2;
_acmB->RegisterReceiveCodec(myCodecParam);
#endif
#ifdef WEBRTC_CODEC_PCM16
// L16
_acmB->Codec("L16", myCodecParam, 8000);
myCodecParam.pltype = l16_8khz_pltype_;
myCodecParam.channels = 2;
_acmB->RegisterReceiveCodec(myCodecParam);
_acmB->Codec("L16", myCodecParam, 16000);
myCodecParam.pltype = l16_16khz_pltype_;
myCodecParam.channels = 2;
_acmB->RegisterReceiveCodec(myCodecParam);
_acmB->Codec("L16", myCodecParam, 32000);
myCodecParam.pltype = l16_32khz_pltype_;
myCodecParam.channels = 2;
_acmB->RegisterReceiveCodec(myCodecParam);
#endif
// PCM Alaw and u-law
_acmB->Codec("PCMA", myCodecParam ,8000);
myCodecParam.pltype = pcma_pltype_;
myCodecParam.channels = 2;
_acmB->RegisterReceiveCodec(myCodecParam);
_acmB->Codec("PCMU", myCodecParam, 8000);
myCodecParam.pltype = pcmu_pltype_;
myCodecParam.channels = 2;
_acmB->RegisterReceiveCodec(myCodecParam);
#ifdef WEBRTC_CODEC_CELT
// Celt
_acmB->Codec("CELT", myCodecParam, 32000);
myCodecParam.pltype = celt_pltype_;
myCodecParam.channels = 2;
_acmB->RegisterReceiveCodec(myCodecParam);
#endif
// Register CNG with new payload type on both send and receive side.
_acmB->Codec("CN", myCodecParam, 8000);
myCodecParam.pltype = cn_8khz_pltype_;
_acmA->RegisterSendCodec(myCodecParam);
_acmB->RegisterReceiveCodec(myCodecParam);
_acmB->Codec("CN", myCodecParam, 16000);
myCodecParam.pltype = cn_16khz_pltype_;
_acmA->RegisterSendCodec(myCodecParam);
_acmB->RegisterReceiveCodec(myCodecParam);
_acmB->Codec("CN", myCodecParam, 32000);
myCodecParam.pltype = cn_32khz_pltype_;
_acmA->RegisterSendCodec(myCodecParam);
_acmB->RegisterReceiveCodec(myCodecParam);
// Create and connect the channel.
_channelA2B = new TestPackStereo;
_channelA2B = new TestPackStereo;
_acmA->RegisterTransportCallback(_channelA2B);
_channelA2B->RegisterReceiverACM(_acmB);
@ -272,20 +401,27 @@ void TestStereo::Perform()
_testCntr++;
OpenOutFile(_testCntr);
char codecG722[] = "G722";
RegisterSendCodec('A', codecG722, 16000, 64000, 160, codec_channels);
RegisterSendCodec('A', codecG722, 16000, 64000, 160, codec_channels,
g722_pltype_);
Run(_channelA2B, audio_channels, codec_channels);
RegisterSendCodec('A', codecG722, 16000, 64000, 320, codec_channels);
RegisterSendCodec('A', codecG722, 16000, 64000, 320, codec_channels,
g722_pltype_);
Run(_channelA2B, audio_channels, codec_channels);
RegisterSendCodec('A', codecG722, 16000, 64000, 480, codec_channels);
RegisterSendCodec('A', codecG722, 16000, 64000, 480, codec_channels,
g722_pltype_);
Run(_channelA2B, audio_channels, codec_channels);
RegisterSendCodec('A', codecG722, 16000, 64000, 640, codec_channels);
RegisterSendCodec('A', codecG722, 16000, 64000, 640, codec_channels,
g722_pltype_);
Run(_channelA2B, audio_channels, codec_channels);
RegisterSendCodec('A', codecG722, 16000, 64000, 800, codec_channels);
RegisterSendCodec('A', codecG722, 16000, 64000, 800, codec_channels,
g722_pltype_);
Run(_channelA2B, audio_channels, codec_channels);
RegisterSendCodec('A', codecG722, 16000, 64000, 960, codec_channels);
RegisterSendCodec('A', codecG722, 16000, 64000, 960, codec_channels,
g722_pltype_);
Run(_channelA2B, audio_channels, codec_channels);
_acmA->SetVAD(true, true, VADNormal);
RegisterSendCodec('A', codecG722, 16000, 64000, 320, codec_channels);
RegisterSendCodec('A', codecG722, 16000, 64000, 320, codec_channels,
g722_pltype_);
Run(_channelA2B, audio_channels, codec_channels);
_acmA->SetVAD(false, false, VADNormal);
_outFileB.Close();
@ -302,16 +438,21 @@ void TestStereo::Perform()
_testCntr++;
OpenOutFile(_testCntr);
char codecL16[] = "L16";
RegisterSendCodec('A', codecL16, 8000, 128000, 80, codec_channels);
RegisterSendCodec('A', codecL16, 8000, 128000, 80, codec_channels,
l16_8khz_pltype_);
Run(_channelA2B, audio_channels, codec_channels);
RegisterSendCodec('A', codecL16, 8000, 128000, 160, codec_channels);
RegisterSendCodec('A', codecL16, 8000, 128000, 160, codec_channels,
l16_8khz_pltype_);
Run(_channelA2B, audio_channels, codec_channels);
RegisterSendCodec('A', codecL16, 8000, 128000, 240, codec_channels);
RegisterSendCodec('A', codecL16, 8000, 128000, 240, codec_channels,
l16_8khz_pltype_);
Run(_channelA2B, audio_channels, codec_channels);
RegisterSendCodec('A', codecL16, 8000, 128000, 320, codec_channels);
RegisterSendCodec('A', codecL16, 8000, 128000, 320, codec_channels,
l16_8khz_pltype_);
Run(_channelA2B, audio_channels, codec_channels);
_acmA->SetVAD(true, true, VADNormal);
RegisterSendCodec('A', codecL16, 8000, 128000, 80, codec_channels);
RegisterSendCodec('A', codecL16, 8000, 128000, 80, codec_channels,
l16_8khz_pltype_);
Run(_channelA2B, audio_channels, codec_channels);
_acmA->SetVAD(false, false, VADNormal);
_outFileB.Close();
@ -325,16 +466,21 @@ void TestStereo::Perform()
}
_testCntr++;
OpenOutFile(_testCntr);
RegisterSendCodec('A', codecL16, 16000, 256000, 160, codec_channels);
RegisterSendCodec('A', codecL16, 16000, 256000, 160, codec_channels,
l16_16khz_pltype_);
Run(_channelA2B, audio_channels, codec_channels);
RegisterSendCodec('A', codecL16, 16000, 256000, 320, codec_channels);
RegisterSendCodec('A', codecL16, 16000, 256000, 320, codec_channels,
l16_16khz_pltype_);
Run(_channelA2B, audio_channels, codec_channels);
RegisterSendCodec('A', codecL16, 16000, 256000, 480, codec_channels);
RegisterSendCodec('A', codecL16, 16000, 256000, 480, codec_channels,
l16_16khz_pltype_);
Run(_channelA2B, audio_channels, codec_channels);
RegisterSendCodec('A', codecL16, 16000, 256000, 640, codec_channels);
RegisterSendCodec('A', codecL16, 16000, 256000, 640, codec_channels,
l16_16khz_pltype_);
Run(_channelA2B, audio_channels, codec_channels);
_acmA->SetVAD(true, true, VADNormal);
RegisterSendCodec('A', codecL16, 16000, 256000, 160, codec_channels);
RegisterSendCodec('A', codecL16, 16000, 256000, 160, codec_channels,
l16_16khz_pltype_);
Run(_channelA2B, audio_channels, codec_channels);
_acmA->SetVAD(false, false, VADNormal);
_outFileB.Close();
@ -348,12 +494,15 @@ void TestStereo::Perform()
}
_testCntr++;
OpenOutFile(_testCntr);
RegisterSendCodec('A', codecL16, 32000, 512000, 320, codec_channels);
RegisterSendCodec('A', codecL16, 32000, 512000, 320, codec_channels,
l16_32khz_pltype_);
Run(_channelA2B, audio_channels, codec_channels);
RegisterSendCodec('A', codecL16, 32000, 512000, 640, codec_channels);
RegisterSendCodec('A', codecL16, 32000, 512000, 640, codec_channels,
l16_32khz_pltype_);
Run(_channelA2B, audio_channels, codec_channels);
_acmA->SetVAD(true, true, VADNormal);
RegisterSendCodec('A', codecL16, 32000, 512000, 320, codec_channels);
RegisterSendCodec('A', codecL16, 32000, 512000, 320, codec_channels,
l16_32khz_pltype_);
Run(_channelA2B, audio_channels, codec_channels);
_acmA->SetVAD(false, false, VADNormal);
_outFileB.Close();
@ -373,20 +522,27 @@ void TestStereo::Perform()
_testCntr++;
OpenOutFile(_testCntr);
char codecPCMA[] = "PCMA";
RegisterSendCodec('A', codecPCMA, 8000, 64000, 80, codec_channels);
RegisterSendCodec('A', codecPCMA, 8000, 64000, 80, codec_channels,
pcma_pltype_);
Run(_channelA2B, audio_channels, codec_channels);
RegisterSendCodec('A', codecPCMA, 8000, 64000, 160, codec_channels);
RegisterSendCodec('A', codecPCMA, 8000, 64000, 160, codec_channels,
pcma_pltype_);
Run(_channelA2B, audio_channels, codec_channels);
RegisterSendCodec('A', codecPCMA, 8000, 64000, 240, codec_channels);
RegisterSendCodec('A', codecPCMA, 8000, 64000, 240, codec_channels,
pcma_pltype_);
Run(_channelA2B, audio_channels, codec_channels);
RegisterSendCodec('A', codecPCMA, 8000, 64000, 320, codec_channels);
RegisterSendCodec('A', codecPCMA, 8000, 64000, 320, codec_channels,
pcma_pltype_);
Run(_channelA2B, audio_channels, codec_channels);
RegisterSendCodec('A', codecPCMA, 8000, 64000, 400, codec_channels);
RegisterSendCodec('A', codecPCMA, 8000, 64000, 400, codec_channels,
pcma_pltype_);
Run(_channelA2B, audio_channels, codec_channels);
RegisterSendCodec('A', codecPCMA, 8000, 64000, 480, codec_channels);
RegisterSendCodec('A', codecPCMA, 8000, 64000, 480, codec_channels,
pcma_pltype_);
Run(_channelA2B, audio_channels, codec_channels);
_acmA->SetVAD(true, true, VADNormal);
RegisterSendCodec('A', codecPCMA, 8000, 64000, 80, codec_channels);
RegisterSendCodec('A', codecPCMA, 8000, 64000, 80, codec_channels,
pcma_pltype_);
Run(_channelA2B, audio_channels, codec_channels);
_acmA->SetVAD(false, false, VADNormal);
_outFileB.Close();
@ -400,20 +556,27 @@ void TestStereo::Perform()
_testCntr++;
OpenOutFile(_testCntr);
char codecPCMU[] = "PCMU";
RegisterSendCodec('A', codecPCMU, 8000, 64000, 80, codec_channels);
RegisterSendCodec('A', codecPCMU, 8000, 64000, 80, codec_channels,
pcmu_pltype_);
Run(_channelA2B, audio_channels, codec_channels);
RegisterSendCodec('A', codecPCMU, 8000, 64000, 160, codec_channels);
RegisterSendCodec('A', codecPCMU, 8000, 64000, 160, codec_channels,
pcmu_pltype_);
Run(_channelA2B, audio_channels, codec_channels);
RegisterSendCodec('A', codecPCMU, 8000, 64000, 240, codec_channels);
RegisterSendCodec('A', codecPCMU, 8000, 64000, 240, codec_channels,
pcmu_pltype_);
Run(_channelA2B, audio_channels, codec_channels);
RegisterSendCodec('A', codecPCMU, 8000, 64000, 320, codec_channels);
RegisterSendCodec('A', codecPCMU, 8000, 64000, 320, codec_channels,
pcmu_pltype_);
Run(_channelA2B, audio_channels, codec_channels);
RegisterSendCodec('A', codecPCMU, 8000, 64000, 400, codec_channels);
RegisterSendCodec('A', codecPCMU, 8000, 64000, 400, codec_channels,
pcmu_pltype_);
Run(_channelA2B, audio_channels, codec_channels);
RegisterSendCodec('A', codecPCMU, 8000, 64000, 480, codec_channels);
RegisterSendCodec('A', codecPCMU, 8000, 64000, 480, codec_channels,
pcmu_pltype_);
Run(_channelA2B, audio_channels, codec_channels);
_acmA->SetVAD(true, true, VADNormal);
RegisterSendCodec('A', codecPCMU, 8000, 64000, 80, codec_channels);
RegisterSendCodec('A', codecPCMU, 8000, 64000, 80, codec_channels,
pcmu_pltype_);
Run(_channelA2B, audio_channels, codec_channels);
_acmA->SetVAD(false, false, VADNormal);
_outFileB.Close();
@ -432,14 +595,18 @@ void TestStereo::Perform()
_testCntr++;
OpenOutFile(_testCntr);
char codecCELT[] = "CELT";
RegisterSendCodec('A', codecCELT, 32000, 48000, 320, codec_channels);
RegisterSendCodec('A', codecCELT, 32000, 48000, 320, codec_channels,
celt_pltype_);
Run(_channelA2B, audio_channels, codec_channels);
RegisterSendCodec('A', codecCELT, 32000, 64000, 320, codec_channels);
RegisterSendCodec('A', codecCELT, 32000, 64000, 320, codec_channels,
celt_pltype_);
Run(_channelA2B, audio_channels, codec_channels);
RegisterSendCodec('A', codecCELT, 32000, 128000, 320, codec_channels);
RegisterSendCodec('A', codecCELT, 32000, 128000, 320, codec_channels,
celt_pltype_);
Run(_channelA2B, audio_channels, codec_channels);
_acmA->SetVAD(true, true, VADNormal);
RegisterSendCodec('A', codecCELT, 32000, 48000, 320, codec_channels);
RegisterSendCodec('A', codecCELT, 32000, 48000, 320, codec_channels,
celt_pltype_);
Run(_channelA2B, audio_channels, codec_channels);
_acmA->SetVAD(false, false, VADNormal);
_outFileB.Close();
@ -459,7 +626,8 @@ void TestStereo::Perform()
_testCntr++;
_channelA2B->SetCodecType(3);
OpenOutFile(_testCntr);
RegisterSendCodec('A', codecG722, 16000, 64000, 160, codec_channels);
RegisterSendCodec('A', codecG722, 16000, 64000, 160, codec_channels,
g722_pltype_);
Run(_channelA2B, audio_channels, codec_channels);
_outFileB.Close();
#endif
@ -472,7 +640,8 @@ void TestStereo::Perform()
_testCntr++;
_channelA2B->SetCodecType(1);
OpenOutFile(_testCntr);
RegisterSendCodec('A', codecL16, 8000, 128000, 80, codec_channels);
RegisterSendCodec('A', codecL16, 8000, 128000, 80, codec_channels,
l16_8khz_pltype_);
Run(_channelA2B, audio_channels, codec_channels);
_outFileB.Close();
if(_testMode != 0) {
@ -482,7 +651,8 @@ void TestStereo::Perform()
}
_testCntr++;
OpenOutFile(_testCntr);
RegisterSendCodec('A', codecL16, 16000, 256000, 160, codec_channels);
RegisterSendCodec('A', codecL16, 16000, 256000, 160, codec_channels,
l16_16khz_pltype_);
Run(_channelA2B, audio_channels, codec_channels);
_outFileB.Close();
if(_testMode != 0) {
@ -492,7 +662,8 @@ void TestStereo::Perform()
}
_testCntr++;
OpenOutFile(_testCntr);
RegisterSendCodec('A', codecL16, 32000, 512000, 320, codec_channels);
RegisterSendCodec('A', codecL16, 32000, 512000, 320, codec_channels,
l16_32khz_pltype_);
Run(_channelA2B, audio_channels, codec_channels);
_outFileB.Close();
#endif
@ -505,9 +676,11 @@ void TestStereo::Perform()
_testCntr++;
_channelA2B->SetCodecType(0);
OpenOutFile(_testCntr);
RegisterSendCodec('A', codecPCMU, 8000, 64000, 80, codec_channels);
RegisterSendCodec('A', codecPCMU, 8000, 64000, 80, codec_channels,
pcmu_pltype_);
Run(_channelA2B, audio_channels, codec_channels);
RegisterSendCodec('A', codecPCMA, 8000, 64000, 80, codec_channels);
RegisterSendCodec('A', codecPCMA, 8000, 64000, 80, codec_channels,
pcma_pltype_);
Run(_channelA2B, audio_channels, codec_channels);
_outFileB.Close();
#endif
@ -520,7 +693,8 @@ void TestStereo::Perform()
_testCntr++;
_channelA2B->SetCodecType(4);
OpenOutFile(_testCntr);
RegisterSendCodec('A', codecCELT, 32000, 64000, 320, codec_channels);
RegisterSendCodec('A', codecCELT, 32000, 64000, 320, codec_channels,
celt_pltype_);
Run(_channelA2B, audio_channels, codec_channels);
_outFileB.Close();
#endif
@ -534,15 +708,26 @@ void TestStereo::Perform()
// Register receivers as mono.
for(WebRtc_UWord8 n = 0; n < numEncoders; n++) {
_acmB->Codec(n, myCodecParam);
if(!strcmp(myCodecParam.plname, "L16") ||
!strcmp(myCodecParam.plname, "PCMA")||
!strcmp(myCodecParam.plname, "PCMU")||
!strcmp(myCodecParam.plname, "G722")||
!strcmp(myCodecParam.plname, "CELT")) {
myCodecParam.channels = 1;
_acmB->Codec(n, myCodecParam);
if (!strcmp(myCodecParam.plname, "L16")) {
if (myCodecParam.plfreq == 8000) {
myCodecParam.pltype = l16_8khz_pltype_;
} else if (myCodecParam.plfreq == 16000) {
myCodecParam.pltype = l16_16khz_pltype_ ;
} else if (myCodecParam.plfreq == 32000) {
myCodecParam.pltype = l16_32khz_pltype_;
}
} else if (!strcmp(myCodecParam.plname, "PCMA")) {
myCodecParam.pltype = pcma_pltype_;
} else if (!strcmp(myCodecParam.plname, "PCMU")) {
myCodecParam.pltype = pcmu_pltype_;
} else if (!strcmp(myCodecParam.plname, "G722")) {
myCodecParam.pltype = g722_pltype_;
} else if (!strcmp(myCodecParam.plname, "CELT")) {
myCodecParam.pltype = celt_pltype_;
myCodecParam.channels = 1;
}
_acmB->RegisterReceiveCodec(myCodecParam);
}
}
#ifdef WEBRTC_CODEC_G722
// Run stereo audio and mono codec.
@ -553,7 +738,8 @@ void TestStereo::Perform()
}
_testCntr++;
OpenOutFile(_testCntr);
RegisterSendCodec('A', codecG722, 16000, 64000, 160, codec_channels);
RegisterSendCodec('A', codecG722, 16000, 64000, 160, codec_channels,
g722_pltype_);
Run(_channelA2B, audio_channels, codec_channels);
_outFileB.Close();
#endif
@ -565,7 +751,8 @@ void TestStereo::Perform()
}
_testCntr++;
OpenOutFile(_testCntr);
RegisterSendCodec('A', codecL16, 8000, 128000, 80, codec_channels);
RegisterSendCodec('A', codecL16, 8000, 128000, 80, codec_channels,
l16_8khz_pltype_);
Run(_channelA2B, audio_channels, codec_channels);
_outFileB.Close();
if(_testMode != 0) {
@ -575,7 +762,8 @@ void TestStereo::Perform()
}
_testCntr++;
OpenOutFile(_testCntr);
RegisterSendCodec('A', codecL16, 16000, 256000, 160, codec_channels);
RegisterSendCodec('A', codecL16, 16000, 256000, 160, codec_channels,
l16_16khz_pltype_);
Run(_channelA2B, audio_channels, codec_channels);
_outFileB.Close();
if(_testMode != 0) {
@ -585,7 +773,8 @@ void TestStereo::Perform()
}
_testCntr++;
OpenOutFile(_testCntr);
RegisterSendCodec('A', codecL16, 32000, 512000, 320, codec_channels);
RegisterSendCodec('A', codecL16, 32000, 512000, 320, codec_channels,
l16_32khz_pltype_);
Run(_channelA2B, audio_channels, codec_channels);
_outFileB.Close();
#endif
@ -597,9 +786,11 @@ void TestStereo::Perform()
}
_testCntr++;
OpenOutFile(_testCntr);
RegisterSendCodec('A', codecPCMU, 8000, 64000, 80, codec_channels);
RegisterSendCodec('A', codecPCMU, 8000, 64000, 80, codec_channels,
pcmu_pltype_);
Run(_channelA2B, audio_channels, codec_channels);
RegisterSendCodec('A', codecPCMA, 8000, 64000, 80, codec_channels);
RegisterSendCodec('A', codecPCMA, 8000, 64000, 80, codec_channels,
pcma_pltype_);
Run(_channelA2B, audio_channels, codec_channels);
_outFileB.Close();
#endif
@ -611,7 +802,8 @@ void TestStereo::Perform()
}
_testCntr++;
OpenOutFile(_testCntr);
RegisterSendCodec('A', codecCELT, 32000, 64000, 320, codec_channels);
RegisterSendCodec('A', codecCELT, 32000, 64000, 320, codec_channels,
celt_pltype_);
Run(_channelA2B, audio_channels, codec_channels);
_outFileB.Close();
#endif
@ -648,7 +840,8 @@ WebRtc_Word16 TestStereo::RegisterSendCodec(char side,
WebRtc_Word32 samplingFreqHz,
int rate,
int packSize,
int channels)
int channels,
int payload_type)
{
if(_testMode != 0) {
// Print out codec and settings
@ -691,14 +884,10 @@ WebRtc_Word16 TestStereo::RegisterSendCodec(char side,
CHECK_ERROR(AudioCodingModule::Codec(codecName, myCodecParam, samplingFreqHz));
myCodecParam.rate = rate;
myCodecParam.pacsize = packSize;
// Start with register codec as mono, to test that changing to stereo works.
myCodecParam.channels = 1;
myCodecParam.pltype = payload_type;
myCodecParam.channels = channels;
CHECK_ERROR(myACM->RegisterSendCodec(myCodecParam));
// Register codec as stereo.
if (channels == 2) {
myCodecParam.channels = 2;
CHECK_ERROR(myACM->RegisterSendCodec(myCodecParam));
}
// Initialization was successful.
return 0;
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
* Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
@ -66,7 +66,8 @@ private:
WebRtc_Word32 sampFreqHz,
int rate,
int packSize,
int channels);
int channels,
int payload_type);
void Run(TestPackStereo* channel, int in_channels, int out_channels);
void OpenOutFile(WebRtc_Word16 testNumber);
@ -95,6 +96,18 @@ private:
WebRtc_UWord16 _packSizeBytes;
int _counter;
int _codecType;
// Payload types for stereo codecs and CNG
int g722_pltype_;
int l16_8khz_pltype_;
int l16_16khz_pltype_;
int l16_32khz_pltype_;
int pcma_pltype_;
int pcmu_pltype_;
int celt_pltype_;
int cn_8khz_pltype_;
int cn_16khz_pltype_;
int cn_32khz_pltype_;
};
} // namespace webrtc