/* * Copyright (c) 2011 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_codec_database.h" #include "acm_common_defs.h" #include "acm_g7221c.h" #include "acm_neteq.h" #include "webrtc_neteq.h" #include "webrtc_neteq_help_macros.h" #include "trace.h" #ifdef WEBRTC_CODEC_G722_1C // NOTE! G.722.1C is not included in the open-source package. Modify this file or your // codec API to match the function call and name of used G.722.1C API file. // #include "g7221C_interface.h" #endif namespace webrtc { #ifndef WEBRTC_CODEC_G722_1C ACMG722_1C::ACMG722_1C( WebRtc_Word16 /* codecID */) { return; } ACMG722_1C::~ACMG722_1C() { return; } WebRtc_Word16 ACMG722_1C::InternalEncode( WebRtc_UWord8* /* bitStream */, WebRtc_Word16* /* bitStreamLenByte */) { return -1; } WebRtc_Word16 ACMG722_1C::DecodeSafe( WebRtc_UWord8* /* bitStream */, WebRtc_Word16 /* bitStreamLenByte */, WebRtc_Word16* /* audio */, WebRtc_Word16* /* audioSamples */, WebRtc_Word8* /* speechType */) { return -1; } WebRtc_Word16 ACMG722_1C::InternalInitEncoder( WebRtcACMCodecParams* /* codecParams */) { return -1; } WebRtc_Word16 ACMG722_1C::InternalInitDecoder( WebRtcACMCodecParams* /* codecParams */) { return -1; } WebRtc_Word32 ACMG722_1C::CodecDef( WebRtcNetEQ_CodecDef& /* codecDef */, const CodecInst& /* codecInst */) { return -1; } ACMGenericCodec* ACMG722_1C::CreateInstance(void) { return NULL; } WebRtc_Word16 ACMG722_1C::InternalCreateEncoder() { return -1; } void ACMG722_1C::DestructEncoderSafe() { return; } WebRtc_Word16 ACMG722_1C::InternalCreateDecoder() { return -1; } void ACMG722_1C::DestructDecoderSafe() { return; } void ACMG722_1C::InternalDestructEncoderInst( void* /* ptrInst */) { return; } WebRtc_Word16 ACMG722_1C::UnregisterFromNetEqSafe( ACMNetEQ* /* netEq */, WebRtc_Word16 /* payloadType */) { return -1; } #else //===================== Actual Implementation ======================= // Remove when integrating a real G,722.1 wrapper struct G722_1_Inst_t_; extern WebRtc_Word16 WebRtcG7221C_CreateEnc24(G722_1C_24_encinst_t_** encInst); extern WebRtc_Word16 WebRtcG7221C_CreateEnc32(G722_1C_32_encinst_t_** encInst); extern WebRtc_Word16 WebRtcG7221C_CreateEnc48(G722_1C_48_encinst_t_** encInst); extern WebRtc_Word16 WebRtcG7221C_CreateDec24(G722_1C_24_decinst_t_** decInst); extern WebRtc_Word16 WebRtcG7221C_CreateDec32(G722_1C_32_decinst_t_** decInst); extern WebRtc_Word16 WebRtcG7221C_CreateDec48(G722_1C_48_decinst_t_** decInst); extern WebRtc_Word16 WebRtcG7221C_FreeEnc24(G722_1C_24_encinst_t_** encInst); extern WebRtc_Word16 WebRtcG7221C_FreeEnc32(G722_1C_32_encinst_t_** encInst); extern WebRtc_Word16 WebRtcG7221C_FreeEnc48(G722_1C_48_encinst_t_** encInst); extern WebRtc_Word16 WebRtcG7221C_FreeDec24(G722_1C_24_decinst_t_** decInst); extern WebRtc_Word16 WebRtcG7221C_FreeDec32(G722_1C_32_decinst_t_** decInst); extern WebRtc_Word16 WebRtcG7221C_FreeDec48(G722_1C_48_decinst_t_** decInst); extern WebRtc_Word16 WebRtcG7221C_EncoderInit24(G722_1C_24_encinst_t_* encInst); extern WebRtc_Word16 WebRtcG7221C_EncoderInit32(G722_1C_32_encinst_t_* encInst); extern WebRtc_Word16 WebRtcG7221C_EncoderInit48(G722_1C_48_encinst_t_* encInst); extern WebRtc_Word16 WebRtcG7221C_DecoderInit24(G722_1C_24_decinst_t_* decInst); extern WebRtc_Word16 WebRtcG7221C_DecoderInit32(G722_1C_32_decinst_t_* decInst); extern WebRtc_Word16 WebRtcG7221C_DecoderInit48(G722_1C_48_decinst_t_* decInst); extern WebRtc_Word16 WebRtcG7221C_Encode24(G722_1C_24_encinst_t_* encInst, WebRtc_Word16* input, WebRtc_Word16 len, WebRtc_Word16* output); extern WebRtc_Word16 WebRtcG7221C_Encode32(G722_1C_32_encinst_t_* encInst, WebRtc_Word16* input, WebRtc_Word16 len, WebRtc_Word16* output); extern WebRtc_Word16 WebRtcG7221C_Encode48(G722_1C_48_encinst_t_* encInst, WebRtc_Word16* input, WebRtc_Word16 len, WebRtc_Word16* output); extern WebRtc_Word16 WebRtcG7221C_Decode24(G722_1C_24_decinst_t_* decInst, WebRtc_Word16* bitstream, WebRtc_Word16 len, WebRtc_Word16* output); extern WebRtc_Word16 WebRtcG7221C_Decode32(G722_1C_32_decinst_t_* decInst, WebRtc_Word16* bitstream, WebRtc_Word16 len, WebRtc_Word16* output); extern WebRtc_Word16 WebRtcG7221C_Decode48(G722_1C_48_decinst_t_* decInst, WebRtc_Word16* bitstream, WebRtc_Word16 len, WebRtc_Word16* output); extern WebRtc_Word16 WebRtcG7221C_DecodePlc24(G722_1C_24_decinst_t_* decInst, WebRtc_Word16* output, WebRtc_Word16 nrLostFrames); extern WebRtc_Word16 WebRtcG7221C_DecodePlc32(G722_1C_32_decinst_t_* decInst, WebRtc_Word16* output, WebRtc_Word16 nrLostFrames); extern WebRtc_Word16 WebRtcG7221C_DecodePlc48(G722_1C_48_decinst_t_* decInst, WebRtc_Word16* output, WebRtc_Word16 nrLostFrames); ACMG722_1C::ACMG722_1C( WebRtc_Word16 codecID): _encoderInstPtr(NULL), _encoderInstPtrRight(NULL), _decoderInstPtr(NULL), _encoderInst24Ptr(NULL), _encoderInst24PtrR(NULL), _encoderInst32Ptr(NULL), _encoderInst32PtrR(NULL), _encoderInst48Ptr(NULL), _encoderInst48PtrR(NULL), _decoderInst24Ptr(NULL), _decoderInst32Ptr(NULL), _decoderInst48Ptr(NULL) { _codecID = codecID; if(_codecID == ACMCodecDB::g722_1C_24) { _operationalRate = 24000; } else if(_codecID == ACMCodecDB::g722_1C_32) { _operationalRate = 32000; } else if(_codecID == ACMCodecDB::g722_1C_48) { _operationalRate = 48000; } else { WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, _uniqueID, "Wrong codec id for G722_1c."); _operationalRate = -1; } return; } ACMG722_1C::~ACMG722_1C() { if(_encoderInstPtr != NULL) { delete _encoderInstPtr; _encoderInstPtr = NULL; } if(_encoderInstPtrRight != NULL) { delete _encoderInstPtrRight; _encoderInstPtrRight = NULL; } if(_decoderInstPtr != NULL) { delete _decoderInstPtr; _decoderInstPtr = NULL; } switch(_operationalRate) { case 24000: { _encoderInst24Ptr = NULL; _encoderInst24PtrR = NULL; _decoderInst24Ptr = NULL; break; } case 32000: { _encoderInst32Ptr = NULL; _encoderInst32PtrR = NULL; _decoderInst32Ptr = NULL; break; } case 48000: { _encoderInst48Ptr = NULL; _encoderInst48PtrR = NULL; _decoderInst48Ptr = NULL; break; } default: { WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, _uniqueID, "Wrong rate for G722_1c."); break; } } return; } WebRtc_Word16 ACMG722_1C::InternalEncode( WebRtc_UWord8* bitStream, WebRtc_Word16* bitStreamLenByte) { WebRtc_Word16 leftChannel[640]; WebRtc_Word16 rightChannel[640]; WebRtc_Word16 lenInBytes; WebRtc_Word16 outB[240]; // If stereo, split input signal in left and right channel before encoding if(_noChannels == 2) { for (int i=0, j=0; i<_frameLenSmpl*2; i+=2, j++) { leftChannel[j] = _inAudio[_inAudioIxRead+i]; rightChannel[j] = _inAudio[_inAudioIxRead+i+1]; } } else { memcpy(leftChannel, &_inAudio[_inAudioIxRead], 640); } switch(_operationalRate) { case 24000: { lenInBytes = WebRtcG7221C_Encode24(_encoderInst24Ptr, leftChannel, 640, &outB[0]); if (_noChannels == 2) { lenInBytes += WebRtcG7221C_Encode24(_encoderInst24PtrR, rightChannel, 640, &outB[lenInBytes/2]); } break; } case 32000: { lenInBytes = WebRtcG7221C_Encode32(_encoderInst32Ptr, leftChannel, 640, &outB[0]); if (_noChannels == 2) { lenInBytes += WebRtcG7221C_Encode32(_encoderInst32PtrR, rightChannel, 640, &outB[lenInBytes/2]); } break; } case 48000: { lenInBytes = WebRtcG7221C_Encode48(_encoderInst48Ptr, leftChannel, 640, &outB[0]); if (_noChannels == 2) { lenInBytes += WebRtcG7221C_Encode48(_encoderInst48PtrR, rightChannel, 640, &outB[lenInBytes/2]); } break; } default: { WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, _uniqueID, "InternalEncode: Wrong rate for G722_1c."); return -1; break; } } memcpy(bitStream, outB, lenInBytes); *bitStreamLenByte = lenInBytes; // increment the read index this tell the caller that how far // we have gone forward in reading the audio buffer _inAudioIxRead += 640*_noChannels; return *bitStreamLenByte; } WebRtc_Word16 ACMG722_1C::DecodeSafe( WebRtc_UWord8* /* bitStream */, WebRtc_Word16 /* bitStreamLenByte */, WebRtc_Word16* /* audio */, WebRtc_Word16* /* audioSamples */, WebRtc_Word8* /* speechType */) { return 0; } WebRtc_Word16 ACMG722_1C::InternalInitEncoder( WebRtcACMCodecParams* codecParams) { WebRtc_Word16 ret; switch(_operationalRate) { case 24000: { ret = WebRtcG7221C_EncoderInit24(_encoderInst24PtrR); if (ret < 0) { return ret; } return WebRtcG7221C_EncoderInit24(_encoderInst24Ptr); break; } case 32000: { ret = WebRtcG7221C_EncoderInit32(_encoderInst32PtrR); if (ret < 0) { return ret; } return WebRtcG7221C_EncoderInit32(_encoderInst32Ptr); break; } case 48000: { ret = WebRtcG7221C_EncoderInit48(_encoderInst48PtrR); if (ret < 0) { return ret; } return WebRtcG7221C_EncoderInit48(_encoderInst48Ptr); break; } default: { WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, _uniqueID, "InternalInitEncode: Wrong rate for G722_1c."); return -1; break; } } } WebRtc_Word16 ACMG722_1C::InternalInitDecoder( WebRtcACMCodecParams* /* codecParams */) { switch(_operationalRate) { case 24000: { return WebRtcG7221C_DecoderInit24(_decoderInst24Ptr); break; } case 32000: { return WebRtcG7221C_DecoderInit32(_decoderInst32Ptr); break; } case 48000: { return WebRtcG7221C_DecoderInit48(_decoderInst48Ptr); break; } default: { WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, _uniqueID, "InternalInitDecoder: Wrong rate for G722_1c."); return -1; break; } } } WebRtc_Word32 ACMG722_1C::CodecDef( WebRtcNetEQ_CodecDef& codecDef, const CodecInst& codecInst) { if (!_decoderInitialized) { WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, _uniqueID, "CodeDef: decoder not initialized for G722_1c"); return -1; } // NetEq has an array of pointers to WebRtcNetEQ_CodecDef. // get an entry of that array (neteq wrapper will allocate memory) // by calling "netEq->CodecDef", where "NETEQ_CODEC_G722_1_XX" would // be the index of the entry. // Fill up the given structure by calling // "SET_CODEC_PAR" & "SET_G722_1_XX_FUNCTION." // Then return the structure back to NetEQ to add the codec to it's // database. switch(_operationalRate) { case 24000: { SET_CODEC_PAR((codecDef), kDecoderG722_1C_24, codecInst.pltype, _decoderInst24Ptr, 32000); SET_G722_1C_24_FUNCTIONS((codecDef)); break; } case 32000: { SET_CODEC_PAR((codecDef), kDecoderG722_1C_32, codecInst.pltype, _decoderInst32Ptr, 32000); SET_G722_1C_32_FUNCTIONS((codecDef)); break; } case 48000: { SET_CODEC_PAR((codecDef), kDecoderG722_1C_32, codecInst.pltype, _decoderInst48Ptr, 32000); SET_G722_1C_48_FUNCTIONS((codecDef)); break; } default: { WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, _uniqueID, "CodeDef: Wrong rate for G722_1c."); return -1; break; } } return 0; } ACMGenericCodec* ACMG722_1C::CreateInstance(void) { return NULL; } WebRtc_Word16 ACMG722_1C::InternalCreateEncoder() { if((_encoderInstPtr == NULL) || (_encoderInstPtrRight == NULL)) { return -1; } switch(_operationalRate) { case 24000: { WebRtcG7221C_CreateEnc24(&_encoderInst24Ptr); WebRtcG7221C_CreateEnc24(&_encoderInst24PtrR); break; } case 32000: { WebRtcG7221C_CreateEnc32(&_encoderInst32Ptr); WebRtcG7221C_CreateEnc32(&_encoderInst32PtrR); break; } case 48000: { WebRtcG7221C_CreateEnc48(&_encoderInst48Ptr); WebRtcG7221C_CreateEnc48(&_encoderInst48PtrR); break; } default: { WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, _uniqueID, "InternalCreateEncoder: Wrong rate for G722_1c."); return -1; break; } } return 0; } void ACMG722_1C::DestructEncoderSafe() { _encoderExist = false; _encoderInitialized = false; if(_encoderInstPtr != NULL) { delete _encoderInstPtr; _encoderInstPtr = NULL; } if(_encoderInstPtrRight != NULL) { delete _encoderInstPtrRight; _encoderInstPtrRight = NULL; } _encoderInst24Ptr = NULL; _encoderInst32Ptr = NULL; _encoderInst48Ptr = NULL; } WebRtc_Word16 ACMG722_1C::InternalCreateDecoder() { if(_decoderInstPtr == NULL) { WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, _uniqueID, "InternalCreateEncoder: cannot create decoder"); return -1; } switch(_operationalRate) { case 24000: { WebRtcG7221C_CreateDec24(&_decoderInst24Ptr); break; } case 32000: { WebRtcG7221C_CreateDec32(&_decoderInst32Ptr); break; } case 48000: { WebRtcG7221C_CreateDec48(&_decoderInst48Ptr); break; } default: { WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, _uniqueID, "InternalCreateEncoder: Wrong rate for G722_1c."); return -1; break; } } return 0; } void ACMG722_1C::DestructDecoderSafe() { _decoderExist = false; _decoderInitialized = false; if(_decoderInstPtr != NULL) { delete _decoderInstPtr; _decoderInstPtr = NULL; } _decoderInst24Ptr = NULL; _decoderInst32Ptr = NULL; _decoderInst48Ptr = NULL; } void ACMG722_1C::InternalDestructEncoderInst( void* ptrInst) { if(ptrInst != NULL) { delete ptrInst; } return; } WebRtc_Word16 ACMG722_1C::UnregisterFromNetEqSafe( ACMNetEQ* netEq, WebRtc_Word16 payloadType) { if(payloadType != _decoderParams.codecInstant.pltype) { WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, _uniqueID, "Cannot unregister codec %s given payload-type %d does not match \ the stored payload type", _decoderParams.codecInstant.plname, payloadType, _decoderParams.codecInstant.pltype); return -1; } switch(_operationalRate) { case 24000: { return netEq->RemoveCodec(kDecoderG722_1C_24); } case 32000: { return netEq->RemoveCodec(kDecoderG722_1C_32); } case 48000: { return netEq->RemoveCodec(kDecoderG722_1C_48); } default: { WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceAudioCoding, _uniqueID, "Could not remove codec from NetEQ for G722_1c. \ Sampling frequency doesn't match"); return -1; } } } #endif } // namespace webrtc