
This is a copy of http://review.webrtc.org/864014/ This adds a FuncDurationEst to each codec instance which estimates the duration of a packet given the packet contents and the duration of the previous packet. By default, this simply returns the duration of the previous packet (which is what is currently assumed to be the duration of all future packets). This patch also provides an initial implementation of this function for G.711 which returns the actual number of samples in the packet. BUG=issue1015 Review URL: https://webrtc-codereview.appspot.com/935016 git-svn-id: http://webrtc.googlecode.com/svn/trunk@3129 4adac7df-926f-26a2-2b94-8c16560cd09d
774 lines
20 KiB
C
774 lines
20 KiB
C
/*
|
|
* 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.
|
|
*/
|
|
|
|
/*
|
|
* Implementation of the codec database.
|
|
*/
|
|
|
|
#include "codec_db.h"
|
|
|
|
#include <string.h> /* to define NULL */
|
|
|
|
#include "signal_processing_library.h"
|
|
|
|
#include "neteq_error_codes.h"
|
|
|
|
/*
|
|
* Resets the codec database.
|
|
*/
|
|
|
|
int WebRtcNetEQ_DbReset(CodecDbInst_t *inst)
|
|
{
|
|
int i;
|
|
|
|
WebRtcSpl_MemSetW16((WebRtc_Word16*) inst, 0,
|
|
sizeof(CodecDbInst_t) / sizeof(WebRtc_Word16));
|
|
|
|
for (i = 0; i < NUM_TOTAL_CODECS; i++)
|
|
{
|
|
inst->position[i] = -1;
|
|
}
|
|
|
|
for (i = 0; i < NUM_CODECS; i++)
|
|
{
|
|
inst->payloadType[i] = -1;
|
|
}
|
|
|
|
for (i = 0; i < NUM_CNG_CODECS; i++)
|
|
{
|
|
inst->CNGpayloadType[i] = -1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
* Adds a new codec to the database.
|
|
*/
|
|
|
|
int WebRtcNetEQ_DbAdd(CodecDbInst_t *inst, enum WebRtcNetEQDecoder codec,
|
|
WebRtc_Word16 payloadType, FuncDecode funcDecode,
|
|
FuncDecode funcDecodeRCU, FuncDecodePLC funcDecodePLC,
|
|
FuncDecodeInit funcDecodeInit, FuncAddLatePkt funcAddLatePkt,
|
|
FuncGetMDinfo funcGetMDinfo, FuncGetPitchInfo funcGetPitch,
|
|
FuncUpdBWEst funcUpdBWEst, FuncDurationEst funcDurationEst,
|
|
FuncGetErrorCode funcGetErrorCode, void* codec_state,
|
|
WebRtc_UWord16 codec_fs)
|
|
{
|
|
|
|
int temp;
|
|
int insertCNGcodec = 0, overwriteCNGcodec = 0, CNGpos = -1;
|
|
|
|
#ifndef NETEQ_RED_CODEC
|
|
if (codec == kDecoderRED)
|
|
{
|
|
return CODEC_DB_UNSUPPORTED_CODEC;
|
|
}
|
|
#endif
|
|
if (((int) codec <= (int) kDecoderReservedStart) || ((int) codec
|
|
>= (int) kDecoderReservedEnd))
|
|
{
|
|
return CODEC_DB_UNSUPPORTED_CODEC;
|
|
}
|
|
|
|
if ((codec_fs != 8000)
|
|
#ifdef NETEQ_WIDEBAND
|
|
&&(codec_fs!=16000)
|
|
#endif
|
|
#ifdef NETEQ_32KHZ_WIDEBAND
|
|
&&(codec_fs!=32000)
|
|
#endif
|
|
#if defined(NETEQ_48KHZ_WIDEBAND) || defined(NETEQ_OPUS_CODEC)
|
|
&&(codec_fs!=48000)
|
|
#endif
|
|
)
|
|
{
|
|
return CODEC_DB_UNSUPPORTED_FS;
|
|
}
|
|
|
|
/* Ensure that the codec type is supported */
|
|
switch (codec)
|
|
{
|
|
#ifdef NETEQ_PCM16B_CODEC
|
|
case kDecoderPCM16B :
|
|
case kDecoderPCM16B_2ch :
|
|
#endif
|
|
#ifdef NETEQ_G711_CODEC
|
|
case kDecoderPCMu :
|
|
case kDecoderPCMa :
|
|
case kDecoderPCMu_2ch :
|
|
case kDecoderPCMa_2ch :
|
|
#endif
|
|
#ifdef NETEQ_ILBC_CODEC
|
|
case kDecoderILBC :
|
|
#endif
|
|
#ifdef NETEQ_ISAC_CODEC
|
|
case kDecoderISAC :
|
|
#endif
|
|
#ifdef NETEQ_ISAC_SWB_CODEC
|
|
case kDecoderISACswb :
|
|
#endif
|
|
#ifdef NETEQ_OPUS_CODEC
|
|
case kDecoderOpus :
|
|
case kDecoderOpus_2ch :
|
|
#endif
|
|
#ifdef NETEQ_G722_CODEC
|
|
case kDecoderG722 :
|
|
case kDecoderG722_2ch :
|
|
#endif
|
|
#ifdef NETEQ_WIDEBAND
|
|
case kDecoderPCM16Bwb :
|
|
case kDecoderPCM16Bwb_2ch :
|
|
#endif
|
|
#ifdef NETEQ_32KHZ_WIDEBAND
|
|
case kDecoderPCM16Bswb32kHz :
|
|
case kDecoderPCM16Bswb32kHz_2ch :
|
|
#endif
|
|
#ifdef NETEQ_CNG_CODEC
|
|
case kDecoderCNG :
|
|
#endif
|
|
#ifdef NETEQ_ATEVENT_DECODE
|
|
case kDecoderAVT :
|
|
#endif
|
|
#ifdef NETEQ_RED_CODEC
|
|
case kDecoderRED :
|
|
#endif
|
|
#ifdef NETEQ_48KHZ_WIDEBAND
|
|
case kDecoderPCM16Bswb48kHz :
|
|
#endif
|
|
#ifdef NETEQ_ARBITRARY_CODEC
|
|
case kDecoderArbitrary:
|
|
#endif
|
|
#ifdef NETEQ_G729_CODEC
|
|
case kDecoderG729:
|
|
#endif
|
|
#ifdef NETEQ_G729_1_CODEC
|
|
case kDecoderG729_1 :
|
|
#endif
|
|
#ifdef NETEQ_G726_CODEC
|
|
case kDecoderG726_16 :
|
|
case kDecoderG726_24 :
|
|
case kDecoderG726_32 :
|
|
case kDecoderG726_40 :
|
|
#endif
|
|
#ifdef NETEQ_G722_1_CODEC
|
|
case kDecoderG722_1_16 :
|
|
case kDecoderG722_1_24 :
|
|
case kDecoderG722_1_32 :
|
|
#endif
|
|
#ifdef NETEQ_G722_1C_CODEC
|
|
case kDecoderG722_1C_24 :
|
|
case kDecoderG722_1C_32 :
|
|
case kDecoderG722_1C_48 :
|
|
#endif
|
|
#ifdef NETEQ_SPEEX_CODEC
|
|
case kDecoderSPEEX_8 :
|
|
case kDecoderSPEEX_16 :
|
|
#endif
|
|
#ifdef NETEQ_CELT_CODEC
|
|
case kDecoderCELT_32 :
|
|
case kDecoderCELT_32_2ch :
|
|
#endif
|
|
#ifdef NETEQ_GSMFR_CODEC
|
|
case kDecoderGSMFR :
|
|
#endif
|
|
#ifdef NETEQ_AMR_CODEC
|
|
case kDecoderAMR :
|
|
#endif
|
|
#ifdef NETEQ_AMRWB_CODEC
|
|
case kDecoderAMRWB :
|
|
#endif
|
|
{
|
|
/* If we end up here, the inserted codec is supported => Do nothing */
|
|
break;
|
|
}
|
|
default:
|
|
{
|
|
/* If we get to this point, the inserted codec is not supported */
|
|
return CODEC_DB_UNSUPPORTED_CODEC;
|
|
}
|
|
}
|
|
|
|
/* Check to see if payload type is taken */
|
|
if (WebRtcNetEQ_DbGetCodec(inst, payloadType) > 0)
|
|
{
|
|
return CODEC_DB_PAYLOAD_TAKEN;
|
|
}
|
|
|
|
/* Special case for CNG codecs */
|
|
if (codec == kDecoderCNG)
|
|
{
|
|
/* check if this is first CNG codec to be registered */
|
|
if (WebRtcNetEQ_DbGetPayload(inst, codec) == CODEC_DB_NOT_EXIST2)
|
|
{
|
|
/* no other CNG codec found */
|
|
insertCNGcodec = 1;
|
|
}
|
|
|
|
/* find the appropriate insert position in CNG payload vector */
|
|
switch (codec_fs)
|
|
{
|
|
#ifdef NETEQ_WIDEBAND
|
|
case 16000:
|
|
CNGpos = 1;
|
|
break;
|
|
#endif
|
|
#ifdef NETEQ_32KHZ_WIDEBAND
|
|
case 32000:
|
|
CNGpos = 2;
|
|
break;
|
|
#endif
|
|
#ifdef NETEQ_48KHZ_WIDEBAND
|
|
case 48000:
|
|
CNGpos = 3;
|
|
break;
|
|
#endif
|
|
default: /* 8000 Hz case */
|
|
CNGpos = 0;
|
|
/*
|
|
* The 8 kHz CNG payload type is the one associated with the regular codec DB
|
|
* should override any other setting.
|
|
* Overwrite if this isn't the first CNG
|
|
*/
|
|
overwriteCNGcodec = !insertCNGcodec;
|
|
break;
|
|
}
|
|
|
|
/* insert CNG payload type */
|
|
inst->CNGpayloadType[CNGpos] = payloadType;
|
|
|
|
}
|
|
|
|
if ((codec != kDecoderCNG) || (insertCNGcodec == 1) || (overwriteCNGcodec == 1))
|
|
{
|
|
/* Check if we have reached the maximum numbers of simultaneous codecs */
|
|
if (inst->nrOfCodecs == NUM_CODECS) return CODEC_DB_FULL;
|
|
|
|
/* Check that codec has not already been initialized to DB =>
|
|
remove it and reinitialize according to new spec */
|
|
if ((inst->position[codec] != -1) && (overwriteCNGcodec != 1))
|
|
{ /* if registering multiple CNG codecs, don't remove, just overwrite */
|
|
WebRtcNetEQ_DbRemove(inst, codec);
|
|
}
|
|
|
|
if (overwriteCNGcodec == 1)
|
|
{
|
|
temp = inst->position[codec];
|
|
}
|
|
else
|
|
{
|
|
temp = inst->nrOfCodecs; /* Store this codecs position */
|
|
inst->position[codec] = temp;
|
|
inst->nrOfCodecs++;
|
|
}
|
|
|
|
inst->payloadType[temp] = payloadType;
|
|
|
|
/* Copy to database */
|
|
inst->codec_state[temp] = codec_state;
|
|
inst->funcDecode[temp] = funcDecode;
|
|
inst->funcDecodeRCU[temp] = funcDecodeRCU;
|
|
inst->funcAddLatePkt[temp] = funcAddLatePkt;
|
|
inst->funcDecodeInit[temp] = funcDecodeInit;
|
|
inst->funcDecodePLC[temp] = funcDecodePLC;
|
|
inst->funcGetMDinfo[temp] = funcGetMDinfo;
|
|
inst->funcGetPitch[temp] = funcGetPitch;
|
|
inst->funcUpdBWEst[temp] = funcUpdBWEst;
|
|
inst->funcDurationEst[temp] = funcDurationEst;
|
|
inst->funcGetErrorCode[temp] = funcGetErrorCode;
|
|
inst->codec_fs[temp] = codec_fs;
|
|
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
* Removes a codec from the database.
|
|
*/
|
|
|
|
int WebRtcNetEQ_DbRemove(CodecDbInst_t *inst, enum WebRtcNetEQDecoder codec)
|
|
{
|
|
int i;
|
|
int pos = -1;
|
|
|
|
#ifndef NETEQ_RED_CODEC
|
|
if (codec == kDecoderRED)
|
|
{
|
|
return CODEC_DB_UNSUPPORTED_CODEC;
|
|
}
|
|
#endif
|
|
if (((int) codec <= (int) kDecoderReservedStart) || ((int) codec
|
|
>= (int) kDecoderReservedEnd))
|
|
{
|
|
return CODEC_DB_UNSUPPORTED_CODEC;
|
|
}
|
|
|
|
pos = inst->position[codec];
|
|
if (pos == -1)
|
|
{
|
|
return CODEC_DB_NOT_EXIST4;
|
|
}
|
|
else
|
|
{
|
|
/* Remove this codec */
|
|
inst->position[codec] = -1;
|
|
for (i = pos; i < (inst->nrOfCodecs - 1); i++)
|
|
{
|
|
inst->payloadType[i] = inst->payloadType[i + 1];
|
|
inst->codec_state[i] = inst->codec_state[i + 1];
|
|
inst->funcDecode[i] = inst->funcDecode[i + 1];
|
|
inst->funcDecodeRCU[i] = inst->funcDecodeRCU[i + 1];
|
|
inst->funcAddLatePkt[i] = inst->funcAddLatePkt[i + 1];
|
|
inst->funcDecodeInit[i] = inst->funcDecodeInit[i + 1];
|
|
inst->funcDecodePLC[i] = inst->funcDecodePLC[i + 1];
|
|
inst->funcGetMDinfo[i] = inst->funcGetMDinfo[i + 1];
|
|
inst->funcGetPitch[i] = inst->funcGetPitch[i + 1];
|
|
inst->funcUpdBWEst[i] = inst->funcUpdBWEst[i + 1];
|
|
inst->funcGetErrorCode[i] = inst->funcGetErrorCode[i + 1];
|
|
inst->codec_fs[i] = inst->codec_fs[i + 1];
|
|
}
|
|
inst->payloadType[i] = -1;
|
|
inst->codec_state[i] = NULL;
|
|
inst->funcDecode[i] = NULL;
|
|
inst->funcDecodeRCU[i] = NULL;
|
|
inst->funcAddLatePkt[i] = NULL;
|
|
inst->funcDecodeInit[i] = NULL;
|
|
inst->funcDecodePLC[i] = NULL;
|
|
inst->funcGetMDinfo[i] = NULL;
|
|
inst->funcGetPitch[i] = NULL;
|
|
inst->funcUpdBWEst[i] = NULL;
|
|
inst->funcGetErrorCode[i] = NULL;
|
|
inst->codec_fs[i] = 0;
|
|
/* Move down all the codecs above this one */
|
|
for (i = 0; i < NUM_TOTAL_CODECS; i++)
|
|
{
|
|
if (inst->position[i] >= pos)
|
|
{
|
|
inst->position[i] = inst->position[i] - 1;
|
|
}
|
|
}
|
|
inst->nrOfCodecs--;
|
|
|
|
if (codec == kDecoderCNG)
|
|
{
|
|
/* also remove all registered CNG payload types */
|
|
for (i = 0; i < NUM_CNG_CODECS; i++)
|
|
{
|
|
inst->CNGpayloadType[i] = -1;
|
|
}
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
* Get the decoder function pointers for a codec.
|
|
*/
|
|
|
|
int WebRtcNetEQ_DbGetPtrs(CodecDbInst_t *inst, enum WebRtcNetEQDecoder codec,
|
|
CodecFuncInst_t *ptr_inst)
|
|
{
|
|
|
|
int pos = inst->position[codec];
|
|
if ((codec <= kDecoderReservedStart) || (codec >= kDecoderReservedEnd) || (codec
|
|
> NUM_TOTAL_CODECS))
|
|
{
|
|
/* ERROR */
|
|
pos = -1;
|
|
}
|
|
if (pos >= 0)
|
|
{
|
|
ptr_inst->codec_state = inst->codec_state[pos];
|
|
ptr_inst->funcAddLatePkt = inst->funcAddLatePkt[pos];
|
|
ptr_inst->funcDecode = inst->funcDecode[pos];
|
|
ptr_inst->funcDecodeRCU = inst->funcDecodeRCU[pos];
|
|
ptr_inst->funcDecodeInit = inst->funcDecodeInit[pos];
|
|
ptr_inst->funcDecodePLC = inst->funcDecodePLC[pos];
|
|
ptr_inst->funcGetMDinfo = inst->funcGetMDinfo[pos];
|
|
ptr_inst->funcUpdBWEst = inst->funcUpdBWEst[pos];
|
|
ptr_inst->funcGetErrorCode = inst->funcGetErrorCode[pos];
|
|
ptr_inst->codec_fs = inst->codec_fs[pos];
|
|
return 0;
|
|
}
|
|
else
|
|
{
|
|
WebRtcSpl_MemSetW16((WebRtc_Word16*) ptr_inst, 0,
|
|
sizeof(CodecFuncInst_t) / sizeof(WebRtc_Word16));
|
|
return CODEC_DB_NOT_EXIST1;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Returns payload number given a codec identifier.
|
|
*/
|
|
|
|
int WebRtcNetEQ_DbGetPayload(CodecDbInst_t *inst, enum WebRtcNetEQDecoder codecID)
|
|
{
|
|
if (inst->position[codecID] == -1)
|
|
return CODEC_DB_NOT_EXIST2;
|
|
else
|
|
return (inst->payloadType[inst->position[codecID]]);
|
|
|
|
}
|
|
|
|
/*
|
|
* Returns codec identifier given a payload number.
|
|
* Returns -1 if the payload type does not exist.
|
|
*/
|
|
|
|
int WebRtcNetEQ_DbGetCodec(const CodecDbInst_t *inst, int payloadType)
|
|
{
|
|
int i, pos;
|
|
|
|
for (i = 0; i < NUM_TOTAL_CODECS; i++)
|
|
{
|
|
pos = inst->position[i];
|
|
if (pos != -1)
|
|
{
|
|
if (inst->payloadType[pos] == payloadType) return i;
|
|
}
|
|
}
|
|
|
|
/* did not find payload type */
|
|
/* check if it's a CNG codec */
|
|
if (WebRtcNetEQ_DbIsCNGPayload(inst, payloadType))
|
|
{
|
|
return kDecoderCNG;
|
|
}
|
|
|
|
/* found no match */
|
|
return CODEC_DB_NOT_EXIST3;
|
|
}
|
|
|
|
/*
|
|
* Extracts the Payload Split information of the codec with the specified payloadType.
|
|
*/
|
|
|
|
int WebRtcNetEQ_DbGetSplitInfo(SplitInfo_t *inst, enum WebRtcNetEQDecoder codecID,
|
|
int codedsize)
|
|
{
|
|
|
|
switch (codecID)
|
|
{
|
|
#ifdef NETEQ_ISAC_CODEC
|
|
case kDecoderISAC:
|
|
#endif
|
|
#ifdef NETEQ_ISAC_SWB_CODEC
|
|
case kDecoderISACswb:
|
|
#endif
|
|
#ifdef NETEQ_OPUS_CODEC
|
|
case kDecoderOpus:
|
|
case kDecoderOpus_2ch :
|
|
#endif
|
|
#ifdef NETEQ_ARBITRARY_CODEC
|
|
case kDecoderArbitrary:
|
|
#endif
|
|
#ifdef NETEQ_AMR_CODEC
|
|
case kDecoderAMR:
|
|
#endif
|
|
#ifdef NETEQ_AMRWB_CODEC
|
|
case kDecoderAMRWB:
|
|
#endif
|
|
#ifdef NETEQ_G726_CODEC
|
|
/* Treat G726 as non-splittable to simplify the implementation */
|
|
case kDecoderG726_16:
|
|
case kDecoderG726_24:
|
|
case kDecoderG726_32:
|
|
case kDecoderG726_40:
|
|
#endif
|
|
#ifdef NETEQ_SPEEX_CODEC
|
|
case kDecoderSPEEX_8:
|
|
case kDecoderSPEEX_16:
|
|
#endif
|
|
#ifdef NETEQ_CELT_CODEC
|
|
case kDecoderCELT_32 :
|
|
case kDecoderCELT_32_2ch :
|
|
#endif
|
|
#ifdef NETEQ_G729_1_CODEC
|
|
case kDecoderG729_1:
|
|
#endif
|
|
{
|
|
/* These codecs' payloads are not splittable */
|
|
inst->deltaBytes = NO_SPLIT;
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
* Sample based coders are a special case.
|
|
* In this case, deltaTime signals the number of bytes per timestamp unit times 2
|
|
* in log2 domain.
|
|
*/
|
|
#if (defined NETEQ_G711_CODEC)
|
|
case kDecoderPCMu:
|
|
case kDecoderPCMa:
|
|
case kDecoderPCMu_2ch:
|
|
case kDecoderPCMa_2ch:
|
|
{
|
|
inst->deltaBytes = -12;
|
|
inst->deltaTime = 1;
|
|
return 0;
|
|
}
|
|
#endif
|
|
#if (defined NETEQ_G722_CODEC)
|
|
case kDecoderG722:
|
|
case kDecoderG722_2ch:
|
|
{
|
|
inst->deltaBytes = -14;
|
|
inst->deltaTime = 0;
|
|
return 0;
|
|
}
|
|
#endif
|
|
#if (defined NETEQ_PCM16B_CODEC)
|
|
case kDecoderPCM16B:
|
|
case kDecoderPCM16B_2ch:
|
|
{
|
|
inst->deltaBytes = -12;
|
|
inst->deltaTime = 2;
|
|
return 0;
|
|
}
|
|
#endif
|
|
#if ((defined NETEQ_PCM16B_CODEC)&&(defined NETEQ_WIDEBAND))
|
|
case kDecoderPCM16Bwb:
|
|
case kDecoderPCM16Bwb_2ch:
|
|
{
|
|
inst->deltaBytes = -14;
|
|
inst->deltaTime = 2;
|
|
return 0;
|
|
}
|
|
#endif
|
|
#if ((defined NETEQ_PCM16B_CODEC)&&(defined NETEQ_32KHZ_WIDEBAND))
|
|
case kDecoderPCM16Bswb32kHz:
|
|
case kDecoderPCM16Bswb32kHz_2ch:
|
|
{
|
|
inst->deltaBytes = -18;
|
|
inst->deltaTime = 2;
|
|
return 0;
|
|
}
|
|
#endif
|
|
#if ((defined NETEQ_PCM16B_CODEC)&&(defined NETEQ_48KHZ_WIDEBAND))
|
|
case kDecoderPCM16Bswb48kHz:
|
|
{
|
|
inst->deltaBytes = -22;
|
|
inst->deltaTime = 2;
|
|
return 0;
|
|
}
|
|
#endif
|
|
|
|
/* Splittable payloads */
|
|
#ifdef NETEQ_G722_1_CODEC
|
|
case kDecoderG722_1_16:
|
|
{
|
|
inst->deltaBytes = 40;
|
|
inst->deltaTime = 320;
|
|
return 0;
|
|
}
|
|
case kDecoderG722_1_24:
|
|
{
|
|
inst->deltaBytes = 60;
|
|
inst->deltaTime = 320;
|
|
return 0;
|
|
}
|
|
case kDecoderG722_1_32:
|
|
{
|
|
inst->deltaBytes = 80;
|
|
inst->deltaTime = 320;
|
|
return 0;
|
|
}
|
|
#endif
|
|
#ifdef NETEQ_G722_1C_CODEC
|
|
case kDecoderG722_1C_24:
|
|
{
|
|
inst->deltaBytes = 60;
|
|
inst->deltaTime = 640;
|
|
return 0;
|
|
}
|
|
case kDecoderG722_1C_32:
|
|
{
|
|
inst->deltaBytes = 80;
|
|
inst->deltaTime = 640;
|
|
return 0;
|
|
}
|
|
case kDecoderG722_1C_48:
|
|
{
|
|
inst->deltaBytes = 120;
|
|
inst->deltaTime = 640;
|
|
return 0;
|
|
}
|
|
#endif
|
|
#ifdef NETEQ_G729_CODEC
|
|
case kDecoderG729:
|
|
{
|
|
inst->deltaBytes = 10;
|
|
inst->deltaTime = 80;
|
|
return 0;
|
|
}
|
|
#endif
|
|
#ifdef NETEQ_ILBC_CODEC
|
|
case kDecoderILBC:
|
|
{
|
|
/* Check for splitting of iLBC packets.
|
|
* If payload size is a multiple of 50 bytes it should be split into 30ms frames.
|
|
* If payload size is a multiple of 38 bytes it should be split into 20ms frames.
|
|
* Least common multiplier between 38 and 50 is 950, so the payload size must be less than
|
|
* 950 bytes in order to resolve the frames unambiguously.
|
|
* Currently max 12 frames in one bundle.
|
|
*/
|
|
switch (codedsize)
|
|
{
|
|
case 50:
|
|
case 100:
|
|
case 150:
|
|
case 200:
|
|
case 250:
|
|
case 300:
|
|
case 350:
|
|
case 400:
|
|
case 450:
|
|
case 500:
|
|
case 550:
|
|
case 600:
|
|
{
|
|
inst->deltaBytes = 50;
|
|
inst->deltaTime = 240;
|
|
break;
|
|
}
|
|
case 38:
|
|
case 76:
|
|
case 114:
|
|
case 152:
|
|
case 190:
|
|
case 228:
|
|
case 266:
|
|
case 304:
|
|
case 342:
|
|
case 380:
|
|
case 418:
|
|
case 456:
|
|
{
|
|
inst->deltaBytes = 38;
|
|
inst->deltaTime = 160;
|
|
break;
|
|
}
|
|
default:
|
|
{
|
|
return AMBIGUOUS_ILBC_FRAME_SIZE; /* Something not supported... */
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
#endif
|
|
#ifdef NETEQ_GSMFR_CODEC
|
|
case kDecoderGSMFR:
|
|
{
|
|
inst->deltaBytes = 33;
|
|
inst->deltaTime = 160;
|
|
return 0;
|
|
}
|
|
#endif
|
|
default:
|
|
{ /*Unknown codec */
|
|
inst->deltaBytes = NO_SPLIT;
|
|
return CODEC_DB_UNKNOWN_CODEC;
|
|
}
|
|
} /* end of switch */
|
|
}
|
|
|
|
/*
|
|
* Returns 1 if codec is multiple description, 0 otherwise.
|
|
* NOTE: This function is a stub, since there currently are no MD codecs.
|
|
*/
|
|
int WebRtcNetEQ_DbIsMDCodec(enum WebRtcNetEQDecoder codecID)
|
|
{
|
|
if (0) /* Add test for MD codecs here */
|
|
return 1;
|
|
else
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
* Returns 1 if payload type is registered as a CNG codec, 0 otherwise
|
|
*/
|
|
int WebRtcNetEQ_DbIsCNGPayload(const CodecDbInst_t *inst, int payloadType)
|
|
{
|
|
#ifdef NETEQ_CNG_CODEC
|
|
int i;
|
|
|
|
for(i=0; i<NUM_CNG_CODECS; i++)
|
|
{
|
|
if( (inst->CNGpayloadType[i] != -1) && (inst->CNGpayloadType[i] == payloadType) )
|
|
{
|
|
return 1;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
/*
|
|
* Return the sample rate for the codec with the given payload type, 0 if error
|
|
*/
|
|
WebRtc_UWord16 WebRtcNetEQ_DbGetSampleRate(CodecDbInst_t *inst, int payloadType)
|
|
{
|
|
int i;
|
|
CodecFuncInst_t codecInst;
|
|
|
|
/* Sanity */
|
|
if (inst == NULL)
|
|
{
|
|
/* return 0 Hz */
|
|
return 0;
|
|
}
|
|
|
|
/* Check among CNG payloads */
|
|
for (i = 0; i < NUM_CNG_CODECS; i++)
|
|
{
|
|
if ((inst->CNGpayloadType[i] != -1) && (inst->CNGpayloadType[i] == payloadType))
|
|
{
|
|
switch (i)
|
|
{
|
|
#ifdef NETEQ_WIDEBAND
|
|
case 1:
|
|
return 16000;
|
|
#endif
|
|
#ifdef NETEQ_32KHZ_WIDEBAND
|
|
case 2:
|
|
return 32000;
|
|
#endif
|
|
#ifdef NETEQ_48KHZ_WIDEBAND
|
|
case 3:
|
|
return 48000;
|
|
#endif
|
|
default:
|
|
return 8000;
|
|
}
|
|
}
|
|
}
|
|
|
|
/* Not a CNG payload, check the other payloads */
|
|
i = WebRtcNetEQ_DbGetCodec(inst, payloadType);
|
|
if (i >= 0)
|
|
{
|
|
if (WebRtcNetEQ_DbGetPtrs(inst, (enum WebRtcNetEQDecoder) i, &codecInst) != 0)
|
|
{
|
|
/* Unexpected error, return 0 Hz */
|
|
return 0;
|
|
}
|
|
return codecInst.codec_fs;
|
|
}
|
|
|
|
/* If we end up here, we got an error, return 0 Hz */
|
|
return 0;
|
|
|
|
}
|
|
|