diff --git a/src/modules/audio_coding/main/source/acm_celt.cc b/src/modules/audio_coding/main/source/acm_celt.cc new file mode 100644 index 000000000..1e467fe89 --- /dev/null +++ b/src/modules/audio_coding/main/source/acm_celt.cc @@ -0,0 +1,317 @@ +/* + * 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 + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#include "acm_common_defs.h" +#include "acm_neteq.h" +#include "acm_celt.h" +#include "trace.h" +#include "webrtc_neteq.h" +#include "webrtc_neteq_help_macros.h" +// TODO(tlegrand): Add full paths. + +#ifdef WEBRTC_CODEC_CELT +// NOTE! Celt is not included in the open-source package. Modify this file or +// your codec API to match the function call and name of used Celt API file. +#include "celt_interface.h" +#endif + +namespace webrtc { + +#ifndef WEBRTC_CODEC_CELT + +ACMCELT::ACMCELT(int16_t /* codecID */) + : enc_inst_ptr_(NULL), + dec_inst_ptr_(NULL), + sampling_freq_(0), + bitrate_(0), + channels_(1), + dec_channels_(1) { + return; +} + +ACMCELT::~ACMCELT() { + return; +} + +int16_t ACMCELT::InternalEncode(uint8_t* /* bitStream */, + int16_t* /* bitStreamLenByte */) { + return -1; +} + +int16_t ACMCELT::DecodeSafe(uint8_t* /* bitStream */, + int16_t /* bitStreamLenByte */, + int16_t* /* audio */, + int16_t* /* audioSamples */, + char* /* speechType */) { + return -1; +} + +int16_t ACMCELT::InternalInitEncoder(WebRtcACMCodecParams* /* codecParams */) { + return -1; +} + +int16_t ACMCELT::InternalInitDecoder(WebRtcACMCodecParams* /* codecParams */) { + return -1; +} + +int32_t ACMCELT::CodecDef(WebRtcNetEQ_CodecDef& /* codecDef */, + const CodecInst& /* codecInst */) { + return -1; +} + +ACMGenericCodec* ACMCELT::CreateInstance(void) { + return NULL; +} + +int16_t ACMCELT::InternalCreateEncoder() { + return -1; +} + +void ACMCELT::DestructEncoderSafe() { + return; +} + +int16_t ACMCELT::InternalCreateDecoder() { + return -1; +} + +void ACMCELT::DestructDecoderSafe() { + return; +} + +void ACMCELT::InternalDestructEncoderInst(void* /* ptrInst */) { + return; +} + +int16_t ACMCELT::UnregisterFromNetEqSafe(ACMNetEQ* /* netEq */, + int16_t /* payloadType */) { + return -1; +} + +bool ACMCELT::IsTrueStereoCodec() { + return true; +} + +int16_t ACMCELT::SetBitRateSafe(const int32_t /*rate*/) { + return -1; +} + +#else //===================== Actual Implementation ======================= + +ACMCELT::ACMCELT(int16_t codecID) + : enc_inst_ptr_(NULL), + dec_inst_ptr_(NULL), + sampling_freq_(32000), // Default sampling frequency. + bitrate_(48000), // Default rate. + channels_(1), // Default send mono. + dec_channels_(1) { // Default receive mono. + // TODO(tlegrand): remove later when ACMGenericCodec has a new constructor. + _codecID = codecID; + + return; +} + +ACMCELT::~ACMCELT() { + if (enc_inst_ptr_ != NULL) { + WebRtcCelt_FreeEnc(enc_inst_ptr_); + enc_inst_ptr_ = NULL; + } + if (dec_inst_ptr_ != NULL) { + WebRtcCelt_FreeDec(dec_inst_ptr_); + dec_inst_ptr_ = NULL; + } + return; +} + +int16_t ACMCELT::InternalEncode(uint8_t* bitStream, int16_t* bitStreamLenByte) { + *bitStreamLenByte = 0; + + // Call Encoder. + *bitStreamLenByte = WebRtcCelt_Encode(enc_inst_ptr_, + &_inAudio[_inAudioIxRead], + bitStream); + + // Increment the read index this tell the caller that how far + // we have gone forward in reading the audio buffer. + _inAudioIxRead += _frameLenSmpl * channels_; + + if (*bitStreamLenByte < 0) { + // Error reported from the encoder. + WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, _uniqueID, + "InternalEncode: Encode error for Celt"); + *bitStreamLenByte = 0; + return -1; + } + + return *bitStreamLenByte; +} + +int16_t ACMCELT::DecodeSafe(uint8_t* /* bitStream */, + int16_t /* bitStreamLenByte */, + int16_t* /* audio */, + int16_t* /* audioSamples */, + char* /* speechType */) { + return 0; +} + +int16_t ACMCELT::InternalInitEncoder(WebRtcACMCodecParams* codecParams) { + // Set bitrate and check that it is withing the valid range. + int16_t status = SetBitRateSafe((codecParams->codecInstant).rate); + if (status < 0) { + return -1; + } + + // If number of channels changed we need to re-create memory. + if (codecParams->codecInstant.channels != channels_) { + WebRtcCelt_FreeEnc(enc_inst_ptr_); + enc_inst_ptr_ = NULL; + // Store new number of channels. + channels_ = codecParams->codecInstant.channels; + if (WebRtcCelt_CreateEnc(&enc_inst_ptr_, channels_) < 0) { + return -1; + } + } + + // Initiate encoder. + if (WebRtcCelt_EncoderInit(enc_inst_ptr_, channels_, bitrate_) >= 0) { + return 0; + } else { + return -1; + } +} + +int16_t ACMCELT::InternalInitDecoder(WebRtcACMCodecParams* codecParams) { + // If number of channels changed we need to re-create memory. + if (codecParams->codecInstant.channels != dec_channels_) { + WebRtcCelt_FreeDec(dec_inst_ptr_); + dec_inst_ptr_ = NULL; + // Store new number of channels. + dec_channels_ = codecParams->codecInstant.channels; + if (WebRtcCelt_CreateDec(&dec_inst_ptr_, dec_channels_) < 0) { + return -1; + } + } + + // Initiate decoder. + if (WebRtcCelt_DecoderInit(dec_inst_ptr_) < 0) { + WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, _uniqueID, + "InternalInitDecoder: init decoder failed for Celt."); + return -1; + } + return 0; +} + +int32_t ACMCELT::CodecDef(WebRtcNetEQ_CodecDef& codecDef, + const CodecInst& codecInst) { + if (!_decoderInitialized) { + WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, _uniqueID, + "CodecDef: Decoder uninitialized for Celt"); + return -1; + } + + // Fill up the structure by calling + // "SET_CODEC_PAR" and "SET_CELT_FUNCTIONS" or "SET_CELTSLAVE_FUNCTIONS". + // Then call NetEQ to add the codec to it's + // database. + SET_CODEC_PAR((codecDef), kDecoderCELT_32, codecInst.pltype, dec_inst_ptr_, + 32000); + // If this is the master of NetEQ, regular decoder will be added, otherwise + // the slave decoder will be used. + if (_isMaster) { + SET_CELT_FUNCTIONS((codecDef)); + } else { + SET_CELTSLAVE_FUNCTIONS((codecDef)); + } + return 0; +} + +ACMGenericCodec* ACMCELT::CreateInstance(void) { + return NULL; +} + +int16_t ACMCELT::InternalCreateEncoder() { + if (WebRtcCelt_CreateEnc(&enc_inst_ptr_, _noChannels) < 0) { + WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, _uniqueID, + "InternalCreateEncoder: create encoder failed for Celt"); + return -1; + } + channels_ = _noChannels; + return 0; +} + +void ACMCELT::DestructEncoderSafe() { + _encoderExist = false; + _encoderInitialized = false; + if (enc_inst_ptr_ != NULL) { + WebRtcCelt_FreeEnc(enc_inst_ptr_); + enc_inst_ptr_ = NULL; + } +} + +int16_t ACMCELT::InternalCreateDecoder() { + if (WebRtcCelt_CreateDec(&dec_inst_ptr_, dec_channels_) < 0) { + WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, _uniqueID, + "InternalCreateDecoder: create decoder failed for Celt"); + return -1; + } + + return 0; +} + +void ACMCELT::DestructDecoderSafe() { + _decoderExist = false; + _decoderInitialized = false; + if (dec_inst_ptr_ != NULL) { + WebRtcCelt_FreeDec(dec_inst_ptr_); + dec_inst_ptr_ = NULL; + } +} + +void ACMCELT::InternalDestructEncoderInst(void* ptrInst) { + if (ptrInst != NULL) { + WebRtcCelt_FreeEnc(static_cast(ptrInst)); + } + return; +} + +int16_t ACMCELT::UnregisterFromNetEqSafe(ACMNetEQ* netEq, int16_t payloadType) { + if (payloadType != _decoderParams.codecInstant.pltype) { + WEBRTC_TRACE( + webrtc::kTraceError, + webrtc::kTraceAudioCoding, + _uniqueID, + "Cannot unregister codec: given payload-type does not match the stored " + "payload type", + _decoderParams.codecInstant.plname, payloadType, + _decoderParams.codecInstant.pltype); + return -1; + } + return netEq->RemoveCodec(kDecoderCELT_32); +} + +bool ACMCELT::IsTrueStereoCodec() { + return true; +} + +int16_t ACMCELT::SetBitRateSafe(const int32_t rate) { + // Check that rate is in the valid range. + if ((rate >= 48000) && (rate <= 96000)) { + bitrate_ = rate; + return 0; + } else { + WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, _uniqueID, + "SetBitRateSafe: Invalid rate Celt"); + return -1; + } +} + +#endif + +} // namespace webrtc diff --git a/src/modules/audio_coding/main/source/acm_celt.h b/src/modules/audio_coding/main/source/acm_celt.h new file mode 100644 index 000000000..2797a9e43 --- /dev/null +++ b/src/modules/audio_coding/main/source/acm_celt.h @@ -0,0 +1,72 @@ +/* + * 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 + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef WEBRTC_MODULES_AUDIO_CODING_MAIN_SOURCE_ACM_CELT_H_ +#define WEBRTC_MODULES_AUDIO_CODING_MAIN_SOURCE_ACM_CELT_H_ + +#include "acm_generic_codec.h" + +// forward declaration +struct CELT_encinst_t_; +struct CELT_decinst_t_; + +namespace webrtc { + +class ACMCELT : public ACMGenericCodec { + public: + ACMCELT(int16_t codecID); + ~ACMCELT(); + + ACMGenericCodec* CreateInstance(void); + + int16_t InternalEncode(uint8_t* bitstream, int16_t* bitStreamLenByte); + + int16_t InternalInitEncoder(WebRtcACMCodecParams *codecParams); + + int16_t InternalInitDecoder(WebRtcACMCodecParams *codecParams); + + protected: + + WebRtc_Word16 DecodeSafe( + WebRtc_UWord8* bitStream, + WebRtc_Word16 bitStreamLenByte, + WebRtc_Word16* audio, + WebRtc_Word16* audioSamples, + WebRtc_Word8* speechType); + + int32_t CodecDef(WebRtcNetEQ_CodecDef& codecDef, const CodecInst& codecInst); + + void DestructEncoderSafe(); + + void DestructDecoderSafe(); + + int16_t InternalCreateEncoder(); + + int16_t InternalCreateDecoder(); + + void InternalDestructEncoderInst(void* ptrInst); + + int16_t UnregisterFromNetEqSafe(ACMNetEQ* netEq, int16_t payloadType); + + bool IsTrueStereoCodec(); + + int16_t SetBitRateSafe(const int32_t rate); + + CELT_encinst_t_* enc_inst_ptr_; + CELT_decinst_t_* dec_inst_ptr_; + uint16_t sampling_freq_; + uint16_t bitrate_; + uint16_t channels_; + uint16_t dec_channels_; +}; + +} // namespace webrtc + +#endif // WEBRTC_MODULES_AUDIO_CODING_MAIN_SOURCE_ACM_CELT_H_ diff --git a/src/modules/audio_coding/main/source/acm_codec_database.cc b/src/modules/audio_coding/main/source/acm_codec_database.cc index 9da92b18c..d75414df9 100644 --- a/src/modules/audio_coding/main/source/acm_codec_database.cc +++ b/src/modules/audio_coding/main/source/acm_codec_database.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 @@ -58,6 +58,10 @@ #include "acm_amrwb.h" #include "amrwb_interface.h" #endif +#ifdef WEBRTC_CODEC_CELT + #include "acm_celt.h" + #include "celt_interface.h" +#endif #ifdef WEBRTC_CODEC_G722 #include "acm_g722.h" #include "g722_interface.h" @@ -111,8 +115,9 @@ const int kDynamicPayloadtypes[ACMCodecDB::kMaxNumCodecs] = { // default channel support, and default rate. #if (defined(WEBRTC_CODEC_PCM16) || \ defined(WEBRTC_CODEC_AMR) || defined(WEBRTC_CODEC_AMRWB) || \ - defined(WEBRTC_CODEC_G729_1) || defined(WEBRTC_CODEC_SPEEX) || \ - defined(WEBRTC_CODEC_G722_1) || defined(WEBRTC_CODEC_G722_1C)) + defined(WEBRTC_CODEC_CELT) || defined(WEBRTC_CODEC_G729_1) || \ + defined(WEBRTC_CODEC_SPEEX) || defined(WEBRTC_CODEC_G722_1) || \ + defined(WEBRTC_CODEC_G722_1C)) static int count_database = 0; #endif @@ -140,6 +145,9 @@ const CodecInst ACMCodecDB::database_[] = { #ifdef WEBRTC_CODEC_AMRWB {kDynamicPayloadtypes[count_database++], "AMR-WB", 16000, 320, 1, 20000}, #endif +#ifdef WEBRTC_CODEC_CELT + {kDynamicPayloadtypes[count_database++], "CELT", 32000, 320, 1, 48000}, +#endif #ifdef WEBRTC_CODEC_G722 {9, "G722", 16000, 320, 1, 64000}, #endif @@ -208,6 +216,9 @@ const ACMCodecDB::CodecSettings ACMCodecDB::codec_settings_[] = { #ifdef WEBRTC_CODEC_AMRWB {3, {320, 640, 960}, 0, 1}, #endif +#ifdef WEBRTC_CODEC_CELT + {1, {320}, 0, 2}, +#endif #ifdef WEBRTC_CODEC_G722 {6, {160, 320, 480, 640, 800, 960}, 0, 2}, #endif @@ -273,6 +284,9 @@ const WebRtcNetEQDecoder ACMCodecDB::neteq_decoders_[] = { #ifdef WEBRTC_CODEC_AMRWB kDecoderAMRWB, #endif +#ifdef WEBRTC_CODEC_CELT + kDecoderCELT_32, +#endif #ifdef WEBRTC_CODEC_G722 kDecoderG722, #endif @@ -698,6 +712,10 @@ ACMGenericCodec* ACMCodecDB::CreateCodecInstance(const CodecInst* codec_inst) { } else if (!STR_CASE_CMP(codec_inst->plname, "AMR-WB")) { #ifdef WEBRTC_CODEC_AMRWB return new ACMAMRwb(kGSMAMRWB); +#endif + } else if (!STR_CASE_CMP(codec_inst->plname, "CELT")) { +#ifdef WEBRTC_CODEC_CELT + return new ACMCELT(kCELT32); #endif } else if (!STR_CASE_CMP(codec_inst->plname, "G722")) { #ifdef WEBRTC_CODEC_G722 diff --git a/src/modules/audio_coding/main/source/acm_codec_database.h b/src/modules/audio_coding/main/source/acm_codec_database.h index 229d4a8a5..1752bbc40 100644 --- a/src/modules/audio_coding/main/source/acm_codec_database.h +++ b/src/modules/audio_coding/main/source/acm_codec_database.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 @@ -51,6 +51,9 @@ class ACMCodecDB { #ifdef WEBRTC_CODEC_AMRWB , kGSMAMRWB #endif +#ifdef WEBRTC_CODEC_CELT + , kCELT32 +#endif #ifdef WEBRTC_CODEC_G722 , kG722 #endif @@ -112,6 +115,9 @@ class ACMCodecDB { #ifndef WEBRTC_CODEC_AMRWB enum {kGSMAMRWB = -1}; #endif +#ifndef WEBRTC_CODEC_CELT + enum {kCELT32 = -1}; +#endif #ifndef WEBRTC_CODEC_G722 enum {kG722 = -1}; #endif diff --git a/src/modules/audio_coding/main/source/acm_generic_codec.cc b/src/modules/audio_coding/main/source/acm_generic_codec.cc index 44aad87ef..0e212fb29 100644 --- a/src/modules/audio_coding/main/source/acm_generic_codec.cc +++ b/src/modules/audio_coding/main/source/acm_generic_codec.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 @@ -664,6 +664,7 @@ ACMGenericCodec::InitEncoderSafe( } } _frameLenSmpl = (codecParams->codecInstant).pacsize; + _noChannels = codecParams->codecInstant.channels; status = InternalInitEncoder(codecParams); if(status < 0) { @@ -700,8 +701,6 @@ ACMGenericCodec::InitEncoderSafe( status = SetVADSafe(codecParams->enableDTX, codecParams->enableVAD, codecParams->vadMode); - _noChannels = codecParams->codecInstant.channels; - return status; } diff --git a/src/modules/audio_coding/main/source/acm_generic_codec.h b/src/modules/audio_coding/main/source/acm_generic_codec.h index 7f50669ea..7f8ef8c47 100644 --- a/src/modules/audio_coding/main/source/acm_generic_codec.h +++ b/src/modules/audio_coding/main/source/acm_generic_codec.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 @@ -811,6 +811,18 @@ public: WebRtc_UWord8* payload, WebRtc_Word16* payloadLenBytes); + /////////////////////////////////////////////////////////////////////////// + // IsTrueStereoCodec() + // Call to see if current encoder is a true stereo codec. This function + // should be overwritten for codecs which are true stereo codecs + // Return value: + // -true if stereo codec + // -false if not stereo codec. + // + virtual bool IsTrueStereoCodec() { + return false; + } + protected: /////////////////////////////////////////////////////////////////////////// // All the functions with FunctionNameSafe(...) contain the actual @@ -1262,7 +1274,6 @@ protected: virtual void SaveDecoderParamSafe( const WebRtcACMCodecParams* codecParams); - // &_inAudio[_inAudioIxWrite] always point to where new audio can be // written to WebRtc_Word16 _inAudioIxWrite; diff --git a/src/modules/audio_coding/main/source/audio_coding_module.gypi b/src/modules/audio_coding/main/source/audio_coding_module.gypi index 39434e519..80114e0ae 100644 --- a/src/modules/audio_coding/main/source/audio_coding_module.gypi +++ b/src/modules/audio_coding/main/source/audio_coding_module.gypi @@ -1,4 +1,4 @@ -# 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 @@ -42,6 +42,8 @@ 'acm_amr.h', 'acm_amrwb.cc', 'acm_amrwb.h', + 'acm_celt.cc', + 'acm_celt.h', 'acm_cng.cc', 'acm_cng.h', 'acm_codec_database.cc', 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 c48c4c408..6691fa3ce 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 @@ -1642,6 +1642,12 @@ AudioCodingModuleImpl::RegisterRecCodecMSSafe( else if(jitterBuffer == ACMNetEQ::slaveJB) { codecArray = &_slaveCodecs[0]; + if (_codecs[codecId]->IsTrueStereoCodec()) { + // True stereo codecs need to use the same codec memory + // for both master and slave. + _slaveCodecs[mirrorId] = _codecs[mirrorId]; + _mirrorCodecIdx[mirrorId] = mirrorId; + } } else { @@ -1827,6 +1833,8 @@ AudioCodingModuleImpl::IncomingPacket( // current payload type. if (_stereoReceive[i]) { _expected_channels = 2; + } else { + _expected_channels = 1; } // Reset previous received channel diff --git a/src/modules/audio_coding/main/test/TestAllCodecs.cc b/src/modules/audio_coding/main/test/TestAllCodecs.cc index 2ad3e1ec0..c64e269e3 100644 --- a/src/modules/audio_coding/main/test/TestAllCodecs.cc +++ b/src/modules/audio_coding/main/test/TestAllCodecs.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 @@ -583,7 +583,7 @@ void TestAllCodecs::Perform() } else { printf("."); } - _testCntr++; + _testCntr++; OpenOutFile(_testCntr); char codecPCMA[] = "PCMA"; RegisterSendCodec('A', codecPCMA, 8000, 64000, 80, 0); @@ -597,13 +597,12 @@ void TestAllCodecs::Perform() RegisterSendCodec('A', codecPCMA, 8000, 64000, 400, 0); Run(_channelA2B); RegisterSendCodec('A', codecPCMA, 8000, 64000, 480, 0); + Run(_channelA2B); if(_testMode != 0) { printf("=======================================================================\n"); } else { printf("."); } - _testCntr++; - Run(_channelA2B); char codecPCMU[] = "PCMU"; RegisterSendCodec('A', codecPCMU, 8000, 64000, 80, 0); Run(_channelA2B); @@ -650,7 +649,19 @@ void TestAllCodecs::Perform() Run(_channelA2B); _outFileB.Close(); #endif - +#ifdef WEBRTC_CODEC_CELT + if(_testMode != 0) { + printf("=======================================================================\n"); + } else { + printf("."); + } + _testCntr++; + OpenOutFile(_testCntr); + char codecCELT_32[] = "CELT"; + RegisterSendCodec('A', codecCELT_32, 32000, 48000, 320, 0); + Run(_channelA2B); + _outFileB.Close(); +#endif if(_testMode != 0) { printf("=======================================================================\n"); } else { diff --git a/src/modules/audio_coding/main/test/TestStereo.cc b/src/modules/audio_coding/main/test/TestStereo.cc index ef633de66..0b267ff39 100644 --- a/src/modules/audio_coding/main/test/TestStereo.cc +++ b/src/modules/audio_coding/main/test/TestStereo.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 @@ -104,6 +104,11 @@ TestPackStereo::SendData( payloadDataMaster[j] = (payloadData[i] & 0xF0) + (payloadData[i+1] >> 4); payloadDataSlave[j] = ((payloadData[i] & 0x0F) << 4) + (payloadData[i+1] & 0x0F); } + } else if (_codecType == 4) { + // True stereo, call both master and slave with whole stream. + memcpy(payloadDataMaster, payloadData, payloadSize); + memcpy(payloadDataSlave, payloadData, payloadSize); + payloadDataSize = payloadSize*2; } } else @@ -115,7 +120,7 @@ TestPackStereo::SendData( payloadDataSize = payloadSize*2; } - if (_codecType != 4) { + if (_codecType != 5) { // Call ACM with two packets, one for each channel rtpInfo.type.Audio.channel = 1; status = _receiverACM->IncomingPacket((WebRtc_Word8*)payloadDataMaster, payloadDataSize/2, rtpInfo); @@ -235,7 +240,8 @@ void TestStereo::Perform() if(!strcmp(myCodecParam.plname, "L16") || !strcmp(myCodecParam.plname, "PCMA")|| !strcmp(myCodecParam.plname, "PCMU")|| - !strcmp(myCodecParam.plname, "G722")) + !strcmp(myCodecParam.plname, "G722")|| + !strcmp(myCodecParam.plname, "CELT")) { myCodecParam.channels=2; _acmB->RegisterReceiveCodec(myCodecParam); @@ -246,7 +252,7 @@ void TestStereo::Perform() _channelA2B = new TestPackStereo; _acmA->RegisterTransportCallback(_channelA2B); _channelA2B->RegisterReceiverACM(_acmB); - + // // Test Stereo-To-Stereo for all codecs. // @@ -410,10 +416,30 @@ void TestStereo::Perform() RegisterSendCodec('A', codecPCMU, 8000, 64000, 80, codec_channels); Run(_channelA2B, audio_channels, codec_channels); _acmA->SetVAD(false, false, VADNormal); - Run(_channelA2B, audio_channels, codec_channels); _outFileB.Close(); #endif - +#ifdef WEBRTC_CODEC_CELT + if(_testMode != 0) { + printf("=======================================================================\n"); + printf("Test number: %d\n",_testCntr + 1); + printf("Test type: Stereo-to-stereo\n"); + } else { + printf("."); + } + _channelA2B->SetCodecType(4); + audio_channels = 2; + codec_channels = 2; + _testCntr++; + OpenOutFile(_testCntr); + char codecCELT[] = "CELT"; + RegisterSendCodec('A', codecCELT, 32000, 48000, 320, codec_channels); + Run(_channelA2B, audio_channels, codec_channels); + _acmA->SetVAD(true, true, VADNormal); + RegisterSendCodec('A', codecCELT, 32000, 48000, 320, codec_channels); + Run(_channelA2B, audio_channels, codec_channels); + _acmA->SetVAD(false, false, VADNormal); + _outFileB.Close(); +#endif // // Test Mono-To-Stereo for all codecs. // @@ -481,13 +507,26 @@ void TestStereo::Perform() Run(_channelA2B, audio_channels, codec_channels); _outFileB.Close(); #endif +#ifdef WEBRTC_CODEC_CELT + if(_testMode != 0) { + printf("===============================================================\n"); + printf("Test number: %d\n",_testCntr + 1); + printf("Test type: Mono-to-stereo\n"); + } + _testCntr++; + _channelA2B->SetCodecType(4); + OpenOutFile(_testCntr); + RegisterSendCodec('A', codecCELT, 32000, 48000, 320, codec_channels); + Run(_channelA2B, audio_channels, codec_channels); + _outFileB.Close(); +#endif // // Test Stereo-To-Mono for all codecs. // audio_channels = 2; codec_channels = 1; - _channelA2B->SetCodecType(4); + _channelA2B->SetCodecType(5); // Register receivers as mono. for(WebRtc_UWord8 n = 0; n < numEncoders; n++) { @@ -495,7 +534,8 @@ void TestStereo::Perform() if(!strcmp(myCodecParam.plname, "L16") || !strcmp(myCodecParam.plname, "PCMA")|| !strcmp(myCodecParam.plname, "PCMU")|| - !strcmp(myCodecParam.plname, "G722")) { + !strcmp(myCodecParam.plname, "G722")|| + !strcmp(myCodecParam.plname, "CELT")) { myCodecParam.channels = 1; _acmB->RegisterReceiveCodec(myCodecParam); } @@ -537,7 +577,7 @@ void TestStereo::Perform() if(_testMode != 0) { printf("===============================================================\n"); printf("Test number: %d\n",_testCntr + 1); - printf("Test type: Mono-to-stereo\n"); + printf("Test type: Stereo-to-mono\n"); } _testCntr++; OpenOutFile(_testCntr); @@ -549,7 +589,7 @@ void TestStereo::Perform() if(_testMode != 0) { printf("===============================================================\n"); printf("Test number: %d\n",_testCntr + 1); - printf("Test type: Mono-to-stereo\n"); + printf("Test type: Stereo-to-mono\n"); } _testCntr++; OpenOutFile(_testCntr); @@ -559,10 +599,22 @@ void TestStereo::Perform() Run(_channelA2B, audio_channels, codec_channels); _outFileB.Close(); #endif +#ifdef WEBRTC_CODEC_CELT + if(_testMode != 0) { + printf("===============================================================\n"); + printf("Test number: %d\n",_testCntr + 1); + printf("Test type: Stereo-to-mono\n"); + } + _testCntr++; + OpenOutFile(_testCntr); + RegisterSendCodec('A', codecCELT, 32000, 48000, 320, codec_channels); + Run(_channelA2B, audio_channels, codec_channels); + _outFileB.Close(); +#endif // Print out which codecs were tested, and which were not, in the run. if(_testMode != 0) { - printf("/nThe following codecs was INCLUDED in the test:\n"); + printf("\nThe following codecs was INCLUDED in the test:\n"); #ifdef WEBRTC_CODEC_G722 printf(" G.722\n"); #endif @@ -716,6 +768,9 @@ void TestStereo::Run(TestPackStereo* channel, int in_channels, int out_channels) if (_counter == 1000) { _counter = 0; } + if (_in_file_mono.EndOfFile()) { + _in_file_mono.Rewind(); + } if (_in_file_stereo.EndOfFile()) { _in_file_stereo.Rewind(); } diff --git a/src/modules/audio_coding/neteq/codec_db.c b/src/modules/audio_coding/neteq/codec_db.c index c15306d3b..cb63aea6c 100644 --- a/src/modules/audio_coding/neteq/codec_db.c +++ b/src/modules/audio_coding/neteq/codec_db.c @@ -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 @@ -161,6 +161,9 @@ int WebRtcNetEQ_DbAdd(CodecDbInst_t *inst, enum WebRtcNetEQDecoder codec, case kDecoderSPEEX_8 : case kDecoderSPEEX_16 : #endif +#ifdef NETEQ_CELT_CODEC + case kDecoderCELT_32 : +#endif #ifdef NETEQ_GSMFR_CODEC case kDecoderGSMFR : #endif @@ -468,6 +471,9 @@ int WebRtcNetEQ_DbGetSplitInfo(SplitInfo_t *inst, enum WebRtcNetEQDecoder codecI case kDecoderSPEEX_8: case kDecoderSPEEX_16: #endif +#ifdef NETEQ_CELT_CODEC + case kDecoderCELT_32 : +#endif #ifdef NETEQ_G729_1_CODEC case kDecoderG729_1: #endif diff --git a/src/modules/audio_coding/neteq/interface/webrtc_neteq.h b/src/modules/audio_coding/neteq/interface/webrtc_neteq.h index 744bd624c..4fef5531c 100644 --- a/src/modules/audio_coding/neteq/interface/webrtc_neteq.h +++ b/src/modules/audio_coding/neteq/interface/webrtc_neteq.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 @@ -58,6 +58,7 @@ enum WebRtcNetEQDecoder kDecoderG722_1C_48, kDecoderSPEEX_8, kDecoderSPEEX_16, + kDecoderCELT_32, kDecoderGSMFR, kDecoderAMR, kDecoderAMRWB, diff --git a/src/modules/audio_coding/neteq/interface/webrtc_neteq_help_macros.h b/src/modules/audio_coding/neteq/interface/webrtc_neteq_help_macros.h index c63b3464d..214bd10d4 100644 --- a/src/modules/audio_coding/neteq/interface/webrtc_neteq_help_macros.h +++ b/src/modules/audio_coding/neteq/interface/webrtc_neteq_help_macros.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 @@ -328,6 +328,28 @@ inst.funcUpdBWEst=NULL; \ inst.funcGetErrorCode=NULL; +#define SET_CELT_FUNCTIONS(inst) \ + inst.funcDecode=(WebRtcNetEQ_FuncDecode)WebRtcCelt_Decode; \ + inst.funcDecodeRCU=NULL; \ + inst.funcDecodePLC=(WebRtcNetEQ_FuncDecodePLC)WebRtcCelt_DecodePlc; \ + inst.funcDecodeInit=(WebRtcNetEQ_FuncDecodeInit)WebRtcCelt_DecoderInit; \ + inst.funcAddLatePkt=NULL; \ + inst.funcGetMDinfo=NULL; \ + inst.funcGetPitch=NULL; \ + inst.funcUpdBWEst=NULL; \ + inst.funcGetErrorCode=NULL; + +#define SET_CELTSLAVE_FUNCTIONS(inst) \ + inst.funcDecode=(WebRtcNetEQ_FuncDecode)WebRtcCelt_DecodeSlave; \ + inst.funcDecodeRCU=NULL; \ + inst.funcDecodePLC=(WebRtcNetEQ_FuncDecodePLC)WebRtcCelt_DecodePlc; \ + inst.funcDecodeInit=(WebRtcNetEQ_FuncDecodeInit)WebRtcCelt_DecoderInit; \ + inst.funcAddLatePkt=NULL; \ + inst.funcGetMDinfo=NULL; \ + inst.funcGetPitch=NULL; \ + inst.funcUpdBWEst=NULL; \ + inst.funcGetErrorCode=NULL; + #define SET_RED_FUNCTIONS(inst) \ inst.funcDecode=NULL; \ inst.funcDecodeRCU=NULL; \ diff --git a/src/modules/audio_coding/neteq/neteq_defines.h b/src/modules/audio_coding/neteq/neteq_defines.h index e428b8b4e..318e6bb7f 100644 --- a/src/modules/audio_coding/neteq/neteq_defines.h +++ b/src/modules/audio_coding/neteq/neteq_defines.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 @@ -79,6 +79,8 @@ * * NETEQ_SPEEX_CODEC Enable Speex (at 8 and 16 kHz sample rate) * + * NETEQ_CELT_CODEC Enable Celt (at 32 kHz sample rate) + * * NETEQ_GSMFR_CODEC Enable GSM-FR * * NETEQ_AMR_CODEC Enable AMR (narrowband) @@ -259,6 +261,7 @@ #define NETEQ_ISAC_SWB_CODEC #define NETEQ_32KHZ_WIDEBAND #define NETEQ_G722_1C_CODEC + #define NETEQ_CELT_CODEC #endif #if (defined(NETEQ_VOICEENGINE_CODECS)) @@ -290,6 +293,7 @@ #define NETEQ_ISAC_SWB_CODEC #define NETEQ_32KHZ_WIDEBAND #define NETEQ_G722_1C_CODEC + #define NETEQ_CELT_CODEC #endif @@ -323,6 +327,7 @@ #define NETEQ_ISAC_SWB_CODEC #define NETEQ_32KHZ_WIDEBAND #define NETEQ_G722_1C_CODEC + #define NETEQ_CELT_CODEC /* Super wideband 48kHz codecs */ #define NETEQ_48KHZ_WIDEBAND diff --git a/src/modules/audio_coding/neteq/packet_buffer.c b/src/modules/audio_coding/neteq/packet_buffer.c index 4b69704ed..8b9073c09 100644 --- a/src/modules/audio_coding/neteq/packet_buffer.c +++ b/src/modules/audio_coding/neteq/packet_buffer.c @@ -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 @@ -678,6 +678,11 @@ int WebRtcNetEQ_GetDefaultCodecSettings(const enum WebRtcNetEQDecoder *codecID, codecBytes = 1250; /* 210ms @ 50kbps */ codecBuffers = 10; } + else if (codecID[i] == kDecoderCELT_32) + { + codecBytes = 1250; /* 210ms @ 50kbps */ + codecBuffers = 10; + } else if (codecID[i] == kDecoderGSMFR) { codecBytes = 340; /* 200ms */ diff --git a/src/modules/audio_coding/neteq/test/NETEQTEST_CodecClass.cc b/src/modules/audio_coding/neteq/test/NETEQTEST_CodecClass.cc index 8956a20f0..64bf508f3 100644 --- a/src/modules/audio_coding/neteq/test/NETEQTEST_CodecClass.cc +++ b/src/modules/audio_coding/neteq/test/NETEQTEST_CodecClass.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 @@ -580,6 +580,31 @@ int decoder_SPEEX::loadToNetEQ(NETEQTEST_NetEQClass & neteq) } #endif +#ifdef CODEC_CELT_32 +#include "celt_interface.h" +decoder_CELT::decoder_CELT(WebRtc_UWord8 pt, WebRtc_UWord16 fs) +: +NETEQTEST_Decoder(kDecoderCELT_32, fs, "CELT", pt) +{ + if (WebRtcCelt_CreateDec((CELT_decinst_t **) &_decoder, 1)) + exit(EXIT_FAILURE); +} + +decoder_CELT::~decoder_CELT() +{ + WebRtcCelt_FreeDec((CELT_decinst_t *) _decoder); +} + +int decoder_CELT::loadToNetEQ(NETEQTEST_NetEQClass & neteq) +{ + WebRtcNetEQ_CodecDef codecInst; + + SET_CELT_FUNCTIONS(codecInst); + + return(NETEQTEST_Decoder::loadToNetEQ(neteq, codecInst)); +} +#endif + #ifdef CODEC_RED int decoder_RED::loadToNetEQ(NETEQTEST_NetEQClass & neteq) { diff --git a/src/modules/audio_coding/neteq/test/NETEQTEST_CodecClass.h b/src/modules/audio_coding/neteq/test/NETEQTEST_CodecClass.h index 61896f4a0..ff4904929 100644 --- a/src/modules/audio_coding/neteq/test/NETEQTEST_CodecClass.h +++ b/src/modules/audio_coding/neteq/test/NETEQTEST_CodecClass.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 @@ -265,6 +265,14 @@ public: int loadToNetEQ(NETEQTEST_NetEQClass & neteq); }; +class decoder_CELT : public NETEQTEST_Decoder +{ +public: + decoder_CELT(WebRtc_UWord8 pt = 0, WebRtc_UWord16 fs = 32000); + virtual ~decoder_CELT(); + int loadToNetEQ(NETEQTEST_NetEQClass & neteq); +}; + class decoder_RED : public NETEQTEST_Decoder { public: diff --git a/src/modules/audio_coding/neteq/test/NetEqRTPplay.cc b/src/modules/audio_coding/neteq/test/NetEqRTPplay.cc index 812beee28..d3f7eb511 100644 --- a/src/modules/audio_coding/neteq/test/NetEqRTPplay.cc +++ b/src/modules/audio_coding/neteq/test/NetEqRTPplay.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 @@ -1027,6 +1027,12 @@ void parsePtypeFile(FILE *ptypeFile, std::map* dec tempDecoder.fs = 16000; } #endif +#ifdef CODEC_CELT_32 + else if(strcmp(codec, "celt32") == 0) { + tempDecoder.codec = kDecoderCELT_32; + tempDecoder.fs = 32000; + } +#endif #ifdef CODEC_SILK_NB else if(strcmp(codec, "silk8") == 0) { tempDecoder.codec = NETEQ_CODEC_SILK_8; @@ -1421,6 +1427,11 @@ void createAndInsertDecoders (NETEQTEST_NetEQClass *neteq, std::mapname[RTP_PAYLOAD_NAME_SIZE - 1] = 0; @@ -258,6 +262,7 @@ ModuleRTPUtility::Payload* RTPReceiverAudio::RegisterReceiveAudioPayload( payload->typeSpecific.Audio.channels = channels; payload->typeSpecific.Audio.bitsPerSample = bitsPerSample; payload->typeSpecific.Audio.rate = rate; + payload->typeSpecific.Audio.trueStereoCodec = isTrueStereo; payload->audio = true; return payload; } @@ -539,6 +544,18 @@ RTPReceiverAudio::ParseAudioCodecSpecific(WebRtcRTPHeader* rtpHeader, rtpHeader); } } + } else if (audioSpecific.trueStereoCodec) + { + // One callback with the whole payload for each channel. + for(int channel = 1; (channel <= audioSpecific.channels) && + (retVal == 0); channel++) + { + // One callback per channel. + rtpHeader->type.Audio.channel = channel; + retVal = CallbackOfReceivedPayloadData(payloadData, + payloadLength, + rtpHeader); + } } else { for(int channel = 1; channel <= audioSpecific.channels && retVal == 0; channel++) diff --git a/src/modules/rtp_rtcp/source/rtp_utility.h b/src/modules/rtp_rtcp/source/rtp_utility.h index 89012235f..70d7a8616 100644 --- a/src/modules/rtp_rtcp/source/rtp_utility.h +++ b/src/modules/rtp_rtcp/source/rtp_utility.h @@ -42,6 +42,7 @@ namespace ModuleRTPUtility WebRtc_UWord8 channels; WebRtc_UWord8 bitsPerSample; WebRtc_UWord32 rate; + bool trueStereoCodec; }; struct VideoPayload {