tina.legrand@webrtc.org 84519ec0a2 Fixing some inconsistencies in WebRTC audio coding module. I've added setup information for all codecs which are not part of WebRTC, but possible to hook in.
Please help me review.
Henrik: review neteq_defines.h
Turaj: review all files, but the one Henrik reviews.
Zakk: FYI only.
Review URL: http://webrtc-codereview.appspot.com/138004

git-svn-id: http://webrtc.googlecode.com/svn/trunk@505 4adac7df-926f-26a2-2b94-8c16560cd09d
2011-09-01 07:47:31 +00:00

450 lines
9.5 KiB
C++

/*
* 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_g722.h"
#include "acm_codec_database.h"
#include "acm_common_defs.h"
#include "acm_neteq.h"
#include "trace.h"
#include "webrtc_neteq.h"
#include "webrtc_neteq_help_macros.h"
#include "g722_interface.h"
namespace webrtc {
#ifndef WEBRTC_CODEC_G722
ACMG722::ACMG722(
WebRtc_Word16 /* codecID */)
{
return;
}
ACMG722::~ACMG722()
{
return;
}
WebRtc_Word32
ACMG722::Add10MsDataSafe(
const WebRtc_UWord32 /* timestamp */,
const WebRtc_Word16* /* data */,
const WebRtc_UWord16 /* lengthSmpl */,
const WebRtc_UWord8 /* audioChannel */)
{
return -1;
}
WebRtc_Word16
ACMG722::InternalEncode(
WebRtc_UWord8* /* bitStream */,
WebRtc_Word16* /* bitStreamLenByte */)
{
return -1;
}
WebRtc_Word16
ACMG722::DecodeSafe(
WebRtc_UWord8* /* bitStream */,
WebRtc_Word16 /* bitStreamLenByte */,
WebRtc_Word16* /* audio */,
WebRtc_Word16* /* audioSamples */,
WebRtc_Word8* /* speechType */)
{
return -1;
}
WebRtc_Word16
ACMG722::InternalInitEncoder(
WebRtcACMCodecParams* /* codecParams */)
{
return -1;
}
WebRtc_Word16
ACMG722::InternalInitDecoder(
WebRtcACMCodecParams* /* codecParams */)
{
return -1;
}
WebRtc_Word32
ACMG722::CodecDef(
WebRtcNetEQ_CodecDef& /* codecDef */,
const CodecInst& /* codecInst */)
{
return -1;
}
ACMGenericCodec*
ACMG722::CreateInstance(void)
{
return NULL;
}
WebRtc_Word16
ACMG722::InternalCreateEncoder()
{
return -1;
}
void
ACMG722::DestructEncoderSafe()
{
return;
}
WebRtc_Word16
ACMG722::InternalCreateDecoder()
{
return -1;
}
void
ACMG722::DestructDecoderSafe()
{
return;
}
void
ACMG722::InternalDestructEncoderInst(
void* /* ptrInst */)
{
return;
}
WebRtc_Word16
ACMG722::UnregisterFromNetEqSafe(
ACMNetEQ* /* netEq */,
WebRtc_Word16 /* payloadType */)
{
return -1;
}
#else //===================== Actual Implementation =======================
// Encoder and decoder memory
struct ACMG722EncStr {
G722EncInst* inst; // instance for left channel in case of stereo
G722EncInst* instRight; // instance for right channel in case of stereo
};
struct ACMG722DecStr {
G722DecInst* inst; // instance for left channel in case of stereo
G722DecInst* instRight; // instance for right channel in case of stereo
};
ACMG722::ACMG722(
WebRtc_Word16 codecID)
{
// Encoder
_ptrEncStr = new ACMG722EncStr;
if(_ptrEncStr != NULL)
{
_ptrEncStr->inst = NULL;
_ptrEncStr->instRight = NULL;
}
// Decoder
_ptrDecStr = new ACMG722DecStr;
if(_ptrDecStr != NULL)
{
_ptrDecStr->inst = NULL;
_ptrDecStr->instRight = NULL; // Not used
}
_codecID = codecID;
return;
}
ACMG722::~ACMG722()
{
if(_ptrEncStr != NULL)
{
if(_ptrEncStr->inst != NULL)
{
WebRtcG722_FreeEncoder(_ptrEncStr->inst);
_ptrEncStr->inst = NULL;
}
if(_ptrEncStr->instRight != NULL)
{
WebRtcG722_FreeEncoder(_ptrEncStr->instRight);
_ptrEncStr->instRight = NULL;
}
delete _ptrEncStr;
_ptrEncStr = NULL;
}
if(_ptrDecStr != NULL)
{
if(_ptrDecStr->inst != NULL)
{
WebRtcG722_FreeDecoder(_ptrDecStr->inst);
_ptrDecStr->inst = NULL;
}
if(_ptrDecStr->instRight != NULL)
{
WebRtcG722_FreeDecoder(_ptrDecStr->instRight);
_ptrDecStr->instRight = NULL;
}
delete _ptrDecStr;
_ptrDecStr = NULL;
}
return;
}
WebRtc_Word32
ACMG722::Add10MsDataSafe(
const WebRtc_UWord32 timestamp,
const WebRtc_Word16* data,
const WebRtc_UWord16 lengthSmpl,
const WebRtc_UWord8 audioChannel)
{
return ACMGenericCodec::Add10MsDataSafe((timestamp>>1), data, lengthSmpl,
audioChannel);
}
WebRtc_Word16
ACMG722::InternalEncode(
WebRtc_UWord8* bitStream,
WebRtc_Word16* bitStreamLenByte)
{
// If stereo, split input signal in left and right channel before encoding
if(_noChannels == 2) {
WebRtc_Word16 leftChannel[960];
WebRtc_Word16 rightChannel[960];
WebRtc_UWord8 outLeft[480];
WebRtc_UWord8 outRight[480];
WebRtc_Word16 lenInBytes;
for (int i=0, j=0; i<_frameLenSmpl*2; i+=2, j++) {
leftChannel[j] = _inAudio[_inAudioIxRead+i];
rightChannel[j] = _inAudio[_inAudioIxRead+i+1];
}
lenInBytes = WebRtcG722_Encode(_encoderInstPtr,
leftChannel, _frameLenSmpl, (WebRtc_Word16*)outLeft);
lenInBytes += WebRtcG722_Encode(_encoderInstPtrRight,
rightChannel, _frameLenSmpl, (WebRtc_Word16*)outRight);
*bitStreamLenByte = lenInBytes;
// Interleave the 4 bits per sample from left and right channel
for (int i=0, j=0; i<lenInBytes; i+=2, j++)
{
bitStream[i] = (outRight[j] & 0xF0) + (outLeft[j] >> 4);
bitStream[i+1] = ((outRight[j] & 0x0F) << 4) + (outLeft[j] & 0x0F);
}
} else {
*bitStreamLenByte = WebRtcG722_Encode(_encoderInstPtr,
&_inAudio[_inAudioIxRead], _frameLenSmpl, (WebRtc_Word16*)bitStream);
}
// increment the read index this tell the caller how far
// we have gone forward in reading the audio buffer
_inAudioIxRead += _frameLenSmpl*_noChannels;
return *bitStreamLenByte;
}
WebRtc_Word16
ACMG722::DecodeSafe(
WebRtc_UWord8* /* bitStream */,
WebRtc_Word16 /* bitStreamLenByte */,
WebRtc_Word16* /* audio */,
WebRtc_Word16* /* audioSamples */,
WebRtc_Word8* /* speechType */)
{
return 0;
}
WebRtc_Word16
ACMG722::InternalInitEncoder(
WebRtcACMCodecParams* codecParams)
{
if(codecParams->codecInstant.channels == 2)
{
// Create codec struct for right channel
if (_ptrEncStr->instRight == NULL)
{
WebRtcG722_CreateEncoder(&_ptrEncStr->instRight);
if(_ptrEncStr->instRight == NULL)
{
return -1;
}
}
_encoderInstPtrRight = (G722EncInst*)_ptrEncStr->instRight;
if (WebRtcG722_EncoderInit(_encoderInstPtrRight) < 0)
{
return -1;
}
}
return WebRtcG722_EncoderInit(_encoderInstPtr);
}
WebRtc_Word16
ACMG722::InternalInitDecoder(
WebRtcACMCodecParams* /* codecParams */)
{
return WebRtcG722_DecoderInit(_decoderInstPtr);
}
WebRtc_Word32
ACMG722::CodecDef(
WebRtcNetEQ_CodecDef& codecDef,
const CodecInst& codecInst)
{
if (!_decoderInitialized)
{
// TODO: log error
return -1;
}
// Fill up the structure by calling
// "SET_CODEC_PAR" & "SET_G722_FUNCTION."
// Then call NetEQ to add the codec to it's
// database.
SET_CODEC_PAR((codecDef), kDecoderG722, codecInst.pltype,
_decoderInstPtr, 16000);
SET_G722_FUNCTIONS((codecDef));
return 0;
}
ACMGenericCodec*
ACMG722::CreateInstance(void)
{
return NULL;
}
WebRtc_Word16
ACMG722::InternalCreateEncoder()
{
if(_ptrEncStr == NULL)
{
// this structure must be created at the costructor
// if it is still NULL then there is a probelm and
// we dont continue
return -1;
}
WebRtcG722_CreateEncoder(&_ptrEncStr->inst);
if(_ptrEncStr->inst == NULL)
{
return -1;
}
_encoderInstPtr = (G722EncInst*)_ptrEncStr->inst;
return 0;
}
void
ACMG722::DestructEncoderSafe()
{
if(_ptrEncStr != NULL)
{
if(_ptrEncStr->inst != NULL)
{
WebRtcG722_FreeEncoder(_ptrEncStr->inst);
_ptrEncStr->inst = NULL;
}
}
_encoderExist = false;
_encoderInitialized = false;
}
WebRtc_Word16
ACMG722::InternalCreateDecoder()
{
if(_ptrDecStr == NULL)
{
// this structure must be created at the costructor
// if it is still NULL then there is a probelm and
// we dont continue
return -1;
}
WebRtcG722_CreateDecoder(&_ptrDecStr->inst);
if(_ptrDecStr->inst == NULL)
{
return -1;
}
_decoderInstPtr = (G722DecInst*)_ptrDecStr->inst;
return 0;
}
void
ACMG722::DestructDecoderSafe()
{
_decoderExist = false;
_decoderInitialized = false;
if(_ptrDecStr != NULL)
{
if(_ptrDecStr->inst != NULL)
{
WebRtcG722_FreeDecoder(_ptrDecStr->inst);
_ptrDecStr->inst = NULL;
}
}
}
void
ACMG722::InternalDestructEncoderInst(
void* ptrInst)
{
if(ptrInst != NULL)
{
WebRtcG722_FreeEncoder((G722EncInst*)ptrInst);
}
return;
}
WebRtc_Word16
ACMG722::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;
}
return netEq->RemoveCodec(kDecoderG722);
}
#endif
} // namespace webrtc