From ae1c4547eeea63fffd2c1da0d16b4f47921b6611 Mon Sep 17 00:00:00 2001 From: "tina.legrand@webrtc.org" Date: Mon, 12 Mar 2012 08:41:30 +0000 Subject: [PATCH] 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@1871 4adac7df-926f-26a2-2b94-8c16560cd09d --- .../audio_coding/main/source/acm_celt.cc | 14 +- .../main/source/audio_coding_module_impl.cc | 177 ++++++--- .../main/source/audio_coding_module_impl.h | 12 +- .../main/test/EncodeDecodeTest.cc | 8 +- .../audio_coding/main/test/TestStereo.cc | 349 ++++++++++++++---- .../audio_coding/main/test/TestStereo.h | 17 +- 6 files changed, 436 insertions(+), 141 deletions(-) diff --git a/src/modules/audio_coding/main/source/acm_celt.cc b/src/modules/audio_coding/main/source/acm_celt.cc index 5b12f3249..c6a9efa0b 100644 --- a/src/modules/audio_coding/main/source/acm_celt.cc +++ b/src/modules/audio_coding/main/source/acm_celt.cc @@ -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; } } diff --git a/src/modules/audio_coding/main/source/audio_coding_module_impl.cc b/src/modules/audio_coding/main/source/audio_coding_module_impl.cc index 39e390bfa..5f60ce965 100644 --- a/src/modules/audio_coding/main/source/audio_coding_module_impl.cc +++ b/src/modules/audio_coding/main/source/audio_coding_module_impl.cc @@ -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(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(ACMCodecDB::database_[i].pltype); } else if (ACMCodecDB::database_[i].plfreq == 16000) { - memcpy(&_cngWB, &ACMCodecDB::database_[i], sizeof(_cngWB)); + _cng_wb_pltype = + static_cast(ACMCodecDB::database_[i].pltype); } else if (ACMCodecDB::database_[i].plfreq == 32000) { - memcpy(&_cngSWB, &ACMCodecDB::database_[i], sizeof(_cngSWB)); + _cng_swb_pltype = + static_cast(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(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(sendCodec.pltype); break; } case 16000: { - memcpy(&_cngWB, &sendCodec, sizeof(_cngWB)); + _cng_wb_pltype = static_cast(sendCodec.pltype); break; } case 32000: { - memcpy(&_cngSWB, &sendCodec, sizeof(_cngSWB)); + _cng_swb_pltype = static_cast(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; @@ -2570,23 +2625,25 @@ AudioCodingModuleImpl::UnregisterReceiveCodecSafe( return -1; } - // CN is a special case for NetEQ, all three sampling frequencies are - // deletad if one is deleted + // CN is a special case for NetEQ, all three sampling frequencies + // are unregistered if one is deleted 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) { - _codecs[codecID+i]->DestructDecoder(); 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 +2652,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; + } + } } } diff --git a/src/modules/audio_coding/main/source/audio_coding_module_impl.h b/src/modules/audio_coding/main/source/audio_coding_module_impl.h index 422b22e64..788dd9482 100644 --- a/src/modules/audio_coding/main/source/audio_coding_module_impl.h +++ b/src/modules/audio_coding/main/source/audio_coding_module_impl.h @@ -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; diff --git a/src/modules/audio_coding/main/test/EncodeDecodeTest.cc b/src/modules/audio_coding/main/test/EncodeDecodeTest.cc index 74bb84ca4..3a70a2692 100644 --- a/src/modules/audio_coding/main/test/EncodeDecodeTest.cc +++ b/src/modules/audio_coding/main/test/EncodeDecodeTest.cc @@ -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); diff --git a/src/modules/audio_coding/main/test/TestStereo.cc b/src/modules/audio_coding/main/test/TestStereo.cc index 2105d36fe..4b1f107f0 100644 --- a/src/modules/audio_coding/main/test/TestStereo.cc +++ b/src/modules/audio_coding/main/test/TestStereo.cc @@ -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; } diff --git a/src/modules/audio_coding/main/test/TestStereo.h b/src/modules/audio_coding/main/test/TestStereo.h index 94a0c564d..0172c28f4 100644 --- a/src/modules/audio_coding/main/test/TestStereo.h +++ b/src/modules/audio_coding/main/test/TestStereo.h @@ -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