henrik.lundin@webrtc.org 75f8c78d08 Fixing path to ptypes.txt in NetEqRTPplay
The default path to the file ptypes.txt needed by NetEqRTPplay
had gone old. Updating to new repo layout.

Also purging old payload types from the file itself.

Review URL: https://webrtc-codereview.appspot.com/966035

git-svn-id: http://webrtc.googlecode.com/svn/trunk@3243 4adac7df-926f-26a2-2b94-8c16560cd09d
2012-12-06 15:22:00 +00:00

1811 lines
57 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.
*/
//TODO(hlundin): Reformat file to meet style guide.
#include <assert.h>
#include <stdio.h>
/* header includes */
#include "typedefs.h"
#include "webrtc_neteq.h"
#include "webrtc_neteq_internal.h"
#include "webrtc_neteq_help_macros.h"
#include "neteq_error_codes.h" // for the API test
#include "NETEQTEST_RTPpacket.h"
#include "NETEQTEST_DummyRTPpacket.h"
#include "NETEQTEST_NetEQClass.h"
#include "NETEQTEST_CodecClass.h"
#ifdef WEBRTC_ANDROID
#include <ctype.h> // isalpha
#endif
#include <string.h>
#include <stdlib.h>
#include <time.h>
#include <map>
#include <vector>
#ifdef WIN32
#include <cassert>
#include <windows.h>
#endif
#ifdef WEBRTC_LINUX
#include <netinet/in.h>
#include <libgen.h>
#include <cassert>
#endif
//#include "vld.h"
//#define NETEQ_DELAY_LOGGING
//#define DUMMY_SLAVE_CHANNEL
#ifdef NETEQ_DELAY_LOGGING
#include "delay_logging.h"
#define DUMMY_SLAVE_CHANNEL // do not use a slave channel, only generate zeros instead
#endif
/************************/
/* Define payload types */
/************************/
// Payload types are defined in the textfile ptypes.txt, and can be changed after compilation.
/*********************/
/* Misc. definitions */
/*********************/
#define TIME_STEP 1
#define FIRSTLINELEN 40
#define MAX_NETEQ_BUFFERSIZE 170000 //100000
#define CHECK_ZERO(a) {int errCode = a; char tempErrName[WEBRTC_NETEQ_MAX_ERROR_NAME]; if((errCode)!=0){errCode = WebRtcNetEQ_GetErrorCode(inst); WebRtcNetEQ_GetErrorName(errCode, tempErrName, WEBRTC_NETEQ_MAX_ERROR_NAME); printf("\n %s \n line: %d \n error at %s\n Error Code = %d\n",__FILE__,__LINE__,#a, errCode); exit(0);}}
#define CHECK_NOT_NULL(a) if((a)==NULL){printf("\n %s \n line: %d \nerror at %s\n",__FILE__,__LINE__,#a );return(-1);}
//#define PLAY_CLEAN // ignore arrival times and let the packets arrive according to RTP timestamps
#define HDR_SIZE 8 // rtpplay packet header size in bytes
//#define JUNK_DATA // scramble the payloads to test error resilience
//#define ZERO_TS_START
#ifdef JUNK_DATA
#define SEED_FILE "randseed.txt"
#endif
#ifdef WIN32
#define MY_MAX_DRIVE _MAX_DRIVE
#define MY_MAX_PATH _MAX_PATH
#define MY_MAX_FNAME _MAX_FNAME
#define MY_MAX_EXT _MAX_EXT
#elif defined(WEBRTC_LINUX)
#include <linux/limits.h>
#define MY_MAX_PATH PATH_MAX
#elif defined(WEBRTC_MAC)
#include <sys/syslimits.h>
#define MY_MAX_PATH PATH_MAX
#endif // WEBRTC_MAC
/************/
/* Typedefs */
/************/
typedef struct {
enum WebRtcNetEQDecoder codec;
enum stereoModes stereo;
NETEQTEST_Decoder * decoder[2];
int fs;
} decoderStruct;
/*************************/
/* Function declarations */
/*************************/
void stereoInterleave(WebRtc_Word16 *data, WebRtc_Word16 totalLen);
int getNextRecoutTime(FILE *fp, WebRtc_UWord32 *nextTime);
void getNextExtraDelay(FILE *fp, WebRtc_UWord32 *t, int *d);
bool splitStereo(NETEQTEST_RTPpacket* rtp, NETEQTEST_RTPpacket* rtpSlave,
const WebRtc_Word16 *stereoPtype, const enum stereoModes *stereoMode, int noOfStereoCodecs,
const WebRtc_Word16 *cngPtype, int noOfCngCodecs,
bool *isStereo);
void parsePtypeFile(FILE *ptypeFile, std::map<WebRtc_UWord8, decoderStruct>* decoders);
int populateUsedCodec(std::map<WebRtc_UWord8, decoderStruct>* decoders, enum WebRtcNetEQDecoder *usedCodec);
void createAndInsertDecoders (NETEQTEST_NetEQClass *neteq, std::map<WebRtc_UWord8, decoderStruct>* decoders, int channelNumber);
void free_coders(std::map<WebRtc_UWord8, decoderStruct> & decoders);
int doAPItest();
bool changeStereoMode(NETEQTEST_RTPpacket & rtp, std::map<WebRtc_UWord8, decoderStruct> & decoders, enum stereoModes *stereoMode);
/********************/
/* Global variables */
/********************/
WebRtc_Word16 NetEqPacketBuffer[MAX_NETEQ_BUFFERSIZE>>1];
WebRtc_Word16 NetEqPacketBufferSlave[MAX_NETEQ_BUFFERSIZE>>1];
#ifdef NETEQ_DELAY_LOGGING
extern "C" {
FILE *delay_fid2; /* file pointer */
WebRtc_UWord32 tot_received_packets=0;
}
#endif
#ifdef DEF_BUILD_DATE
extern char BUILD_DATE;
#endif
WebRtc_UWord32 writtenSamples = 0;
WebRtc_UWord32 simClock=0;
int main(int argc, char* argv[])
{
std::vector<NETEQTEST_NetEQClass *> NetEQvector;
enum WebRtcNetEQDecoder usedCodec[kDecoderReservedEnd-1];
int noOfCodecs;
int ok;
WebRtc_Word16 out_data[640*2];
WebRtc_Word16 outLen, writeLen;
int fs = 8000;
WebRtcNetEQ_RTCPStat RTCPstat;
#ifdef WIN32
char outdrive[MY_MAX_DRIVE];
char outpath[MY_MAX_PATH];
char outfile[MY_MAX_FNAME];
char outext[MY_MAX_EXT];
#endif
char outfilename[MY_MAX_PATH];
#ifdef NETEQ_DELAY_LOGGING
float clock_float;
int temp_var;
#endif
#ifdef JUNK_DATA
FILE *seedfile;
#endif
FILE *recoutTimes = NULL;
FILE *extraDelays = NULL;
WebRtcNetEQPlayoutMode streamingMode = kPlayoutOn;
bool preParseRTP = false;
bool rtpOnly = false;
int packetLen = 0;
int packetCount = 0;
std::map<WebRtc_UWord8, decoderStruct> decoders;
bool dummyRtp = false;
bool noDecode = false;
bool filterSSRC = false;
uint32_t ssrc;
#ifdef DEF_BUILD_DATE
printf("Build time: %s\n", __BUILD_DATE);
#endif
/* check number of parameters */
if ((argc < 3)
#ifdef WIN32 // implicit output file name possible for windows
&& (argc < 2)
#endif
) {
/* print help text and exit */
printf("Test program for NetEQ.\n");
printf("The program reads an RTP stream from file and inserts it into NetEQ.\n");
printf("The format of the RTP stream file should be the same as for rtpplay,\n");
printf("and can be obtained e.g., from Ethereal by using\n");
printf("Statistics -> RTP -> Show All Streams -> [select a stream] -> Save As\n\n");
printf("Usage:\n\n");
#ifdef WIN32
printf("%s RTPfile [outfile] [-options]\n", argv[0]);
#else
printf("%s RTPfile outfile [-options]\n", argv[0]);
#endif
printf("where:\n");
printf("RTPfile : RTP stream input file\n\n");
printf("outfile : PCM speech output file\n");
printf(" Output file name is derived from RTP file name if omitted\n\n");
printf("-options are optional switches:\n");
printf("\t-recout datfile : supply recout times\n");
printf("\t-extradelay datfile : supply extra delay settings and timing\n");
printf("\t-streaming : engage streaming mode\n");
printf("\t-fax : engage fax mode\n");
printf("\t-preparsertp : use RecIn with pre-parsed RTP\n");
printf("\t-rtponly packLenBytes : input file consists of constant size RTP packets without RTPplay headers\n");
printf("\t-dummyrtp : input file contains only RTP headers\n");
printf("\t-nodecode : no decoding will be done\n");
printf("\t-ssrc 0xNNNNNNNN : discard all other SSRCs\n");
//printf("\t-switchms : switch from mono to stereo (copy channel) after 10 seconds\n");
//printf("\t-duplicate : use two instances with identical input (2-channel mono)\n");
return(0);
}
if (strcmp(argv[1], "-apitest")==0) {
// do API test and then return
ok=doAPItest();
if (ok==0)
printf("API test successful!\n");
else
printf("API test failed!\n");
return(ok);
}
FILE* in_file=fopen(argv[1],"rb");
CHECK_NOT_NULL(in_file);
printf("Input file: %s\n",argv[1]);
int argIx = 2; // index of next argument from command line
if ( argc >= 3 && argv[2][0] != '-' ) { // output name given on command line
strcpy(outfilename, argv[2]);
argIx++;
} else { // derive output name from input name
#ifdef WIN32
_splitpath(argv[1],outdrive,outpath,outfile,outext);
_makepath(outfilename,outdrive,outpath,outfile,"pcm");
#else
fprintf(stderr,"Output file name must be specified.\n");
return(-1);
#endif
}
FILE* out_file=fopen(outfilename,"wb");
if (out_file==NULL) {
fprintf(stderr,"Could not open file %s for writing\n", outfilename);
return(-1);
}
printf("Output file: %s\n",outfilename);
// Parse for more arguments, all beginning with '-'
while( argIx < argc ) {
if (argv[argIx][0] != '-') {
fprintf(stderr,"Unknown input argument %s\n", argv[argIx]);
return(-1);
}
if( strcmp(argv[argIx], "-recout") == 0 ) {
argIx++;
recoutTimes = fopen(argv[argIx], "rb");
CHECK_NOT_NULL(recoutTimes);
argIx++;
}
else if( strcmp(argv[argIx], "-extradelay") == 0 ) {
argIx++;
extraDelays = fopen(argv[argIx], "rb");
CHECK_NOT_NULL(extraDelays);
argIx++;
}
else if( strcmp(argv[argIx], "-streaming") == 0 ) {
argIx++;
streamingMode = kPlayoutStreaming;
}
else if( strcmp(argv[argIx], "-fax") == 0 ) {
argIx++;
streamingMode = kPlayoutFax;
}
else if( strcmp(argv[argIx], "-preparsertp") == 0 ) {
argIx++;
preParseRTP = true;
}
else if( strcmp(argv[argIx], "-rtponly") == 0 ) {
argIx++;
rtpOnly = true;
packetLen = atoi(argv[argIx]);
argIx++;
if (packetLen <= 0)
{
printf("Wrong packet size used with argument -rtponly.\n");
exit(1);
}
}
else if (strcmp(argv[argIx], "-dummyrtp") == 0
|| strcmp(argv[argIx], "-dummy") == 0)
{
argIx++;
dummyRtp = true;
noDecode = true; // force noDecode since there are no payloads
}
else if (strcmp(argv[argIx], "-nodecode") == 0)
{
argIx++;
noDecode = true;
}
else if (strcmp(argv[argIx], "-ssrc") == 0)
{
argIx++;
filterSSRC = true;
if (sscanf(argv[argIx], "%X", &ssrc) != 1)
{
printf("Could not read SSRC argument.\n");
exit(1);
}
argIx++;
}
//else if( strcmp(argv[argIx], "-switchms") == 0 ) {
// argIx++;
// switchMS = true;
//}
//else if( strcmp(argv[argIx], "-duplicate") == 0 ) {
// argIx++;
// duplicatePayload = true;
//}
else {
fprintf(stderr,"Unknown input argument %s\n", argv[argIx]);
return(-1);
}
}
#ifdef NETEQ_DELAY_LOGGING
char delayfile[MY_MAX_PATH];
#ifdef WIN32
_splitpath(outfilename,outdrive,outpath,outfile,outext);
_makepath(delayfile,outdrive,outpath,outfile,"d");
#else
sprintf(delayfile, "%s.d", outfilename);
#endif
delay_fid2 = fopen(delayfile,"wb");
fprintf(delay_fid2, "#!NetEQ_Delay_Logging%s\n", NETEQ_DELAY_LOGGING_VERSION_STRING);
#endif
char ptypesfile[MY_MAX_PATH];
#ifdef WIN32
_splitpath(argv[0],outdrive,outpath,outfile,outext);
_makepath(ptypesfile,outdrive,outpath,"ptypes","txt");
#elif defined(WEBRTC_ANDROID)
strcpy(ptypesfile, "/sdcard/ptypes.txt");
#else
// TODO(hlundin): Include path to ptypes, as for WIN32 above.
strcpy(ptypesfile, "ptypes.txt");
#endif
FILE *ptypeFile = fopen(ptypesfile,"rt");
if (!ptypeFile) {
// Check if we can find the file at the usual place in the trunk.
if (strstr(argv[0], "out/Debug/")) {
int path_len = strstr(argv[0], "out/Debug/") - argv[0];
strncpy(ptypesfile, argv[0], path_len);
ptypesfile[path_len] = '\0';
strcat(ptypesfile,
"webrtc/modules/audio_coding/neteq/test/ptypes.txt");
ptypeFile = fopen(ptypesfile,"rt");
}
}
CHECK_NOT_NULL(ptypeFile);
printf("Ptypes file: %s\n\n", ptypesfile);
parsePtypeFile(ptypeFile, &decoders);
fclose(ptypeFile);
noOfCodecs = populateUsedCodec(&decoders, usedCodec);
/* read RTP file header */
if (!rtpOnly)
{
if (NETEQTEST_RTPpacket::skipFileHeader(in_file) != 0)
{
fprintf(stderr, "Wrong format in RTP file.\n");
return -1;
}
}
/* check payload type for first speech packet */
long tempFilePos = ftell(in_file);
enum stereoModes stereoMode = stereoModeMono;
NETEQTEST_RTPpacket *rtp;
NETEQTEST_RTPpacket *slaveRtp;
if (!dummyRtp)
{
rtp = new NETEQTEST_RTPpacket();
slaveRtp = new NETEQTEST_RTPpacket();
}
else
{
rtp = new NETEQTEST_DummyRTPpacket();
slaveRtp = new NETEQTEST_DummyRTPpacket();
}
/* Uncomment and edit the line(s) below to block some payload types. */
//rtp->blockPT(72);
//rtp->blockPT(23);
/* Select a specific SSRC. */
if (filterSSRC) {
rtp->selectSSRC(ssrc);
}
if (!rtpOnly)
{
while (rtp->readFromFile(in_file) >= 0)
{
if (decoders.count(rtp->payloadType()) > 0
&& decoders[rtp->payloadType()].codec != kDecoderRED
&& decoders[rtp->payloadType()].codec != kDecoderAVT
&& decoders[rtp->payloadType()].codec != kDecoderCNG )
{
stereoMode = decoders[rtp->payloadType()].stereo;
fs = decoders[rtp->payloadType()].fs;
break;
}
}
}
else
{
while (rtp->readFixedFromFile(in_file, packetLen) >= 0)
{
if (decoders.count(rtp->payloadType()) > 0
&& decoders[rtp->payloadType()].codec != kDecoderRED
&& decoders[rtp->payloadType()].codec != kDecoderAVT
&& decoders[rtp->payloadType()].codec != kDecoderCNG )
{
stereoMode = decoders[rtp->payloadType()].stereo;
fs = decoders[rtp->payloadType()].fs;
break;
}
}
}
fseek(in_file, tempFilePos, SEEK_SET /* from beginning */);
/* read first packet */
if (!rtpOnly)
{
rtp->readFromFile(in_file);
}
else
{
rtp->readFixedFromFile(in_file, packetLen);
rtp->setTime((1000 * rtp->timeStamp()) / fs);
}
if (!rtp)
{
printf("\nWarning: RTP file is empty\n\n");
}
/* Initialize NetEQ instances */
int numInst = 1;
if (stereoMode > stereoModeMono)
{
numInst = 2;
}
for (int i = 0; i < numInst; i++)
{
// create memory, allocate, initialize, and allocate packet buffer memory
NetEQvector.push_back (new NETEQTEST_NetEQClass(usedCodec, noOfCodecs, static_cast<WebRtc_UWord16>(fs), kTCPLargeJitter));
createAndInsertDecoders (NetEQvector[i], &decoders, i /* channel */);
WebRtcNetEQ_SetAVTPlayout(NetEQvector[i]->instance(),1); // enable DTMF playout
WebRtcNetEQ_SetPlayoutMode(NetEQvector[i]->instance(), streamingMode);
NetEQvector[i]->usePreparseRTP(preParseRTP);
NetEQvector[i]->setNoDecode(noDecode);
if (numInst > 1)
{
// we are using master/slave mode
if (i == 0)
{
// first instance is master
NetEQvector[i]->setMaster();
}
else
{
// all other are slaves
NetEQvector[i]->setSlave();
}
}
}
#ifdef ZERO_TS_START
WebRtc_UWord32 firstTS = rtp->timeStamp();
rtp->setTimeStamp(0);
#else
WebRtc_UWord32 firstTS = 0;
#endif
// check stereo mode
if (stereoMode > stereoModeMono)
{
if(rtp->splitStereo(slaveRtp, stereoMode))
{
printf("Error in splitStereo\n");
}
}
#ifdef PLAY_CLEAN
WebRtc_UWord32 prevTS = rtp->timeStamp();
WebRtc_UWord32 currTS, prev_time;
#endif
#ifdef JUNK_DATA
unsigned int random_seed = (unsigned int) /*1196764538; */time(NULL);
srand(random_seed);
if ( (seedfile = fopen(SEED_FILE, "a+t") ) == NULL ) {
fprintf(stderr, "Error: Could not open file %s\n", SEED_FILE);
}
else {
fprintf(seedfile, "%u\n", random_seed);
fclose(seedfile);
}
#endif
WebRtc_UWord32 nextRecoutTime;
int lastRecout = getNextRecoutTime(recoutTimes, &nextRecoutTime); // does nothing if recoutTimes == NULL
if (recoutTimes)
simClock = (rtp->time() < nextRecoutTime ? rtp->time(): nextRecoutTime);
else
simClock = rtp->time(); // start immediately with first packet
WebRtc_UWord32 start_clock = simClock;
WebRtc_UWord32 nextExtraDelayTime;
int extraDelay = -1;
getNextExtraDelay(extraDelays, &nextExtraDelayTime, &extraDelay);
void *msInfo;
msInfo = malloc(WebRtcNetEQ_GetMasterSlaveInfoSize());
if(msInfo == NULL)
return(-1);
while(rtp->dataLen() >= 0 || (recoutTimes && !lastRecout)) {
// printf("simClock = %Lu\n", simClock);
#ifdef NETEQ_DELAY_LOGGING
temp_var = NETEQ_DELAY_LOGGING_SIGNAL_CLOCK;
clock_float = (float) simClock;
if (fwrite(&temp_var, sizeof(int), 1, delay_fid2) != 1) {
return -1;
}
if (fwrite(&clock_float, sizeof(float), 1, delay_fid2) != 1) {
return -1;
}
#endif
/* time to set extra delay */
if (extraDelay > -1 && simClock >= nextExtraDelayTime) {
// set extra delay for all instances
for (int i = 0; i < numInst; i++)
{
WebRtcNetEQ_SetExtraDelay(NetEQvector[i]->instance(), extraDelay);
}
getNextExtraDelay(extraDelays, &nextExtraDelayTime, &extraDelay);
}
/* check if time to receive */
while (simClock >= rtp->time() && rtp->dataLen() >= 0)
{
if (rtp->dataLen() > 0)
{
// insert main packet
NetEQvector[0]->recIn(*rtp);
if (stereoMode > stereoModeMono
&& slaveRtp->dataLen() > 0)
{
// insert slave packet
NetEQvector[1]->recIn(*slaveRtp);
}
}
/* get next packet */
#ifdef PLAY_CLEAN
prev_time = rtp->time();
#endif
if (!rtpOnly)
{
rtp->readFromFile(in_file);
}
else
{
rtp->readFixedFromFile(in_file, packetLen);
rtp->setTime((1000 * rtp->timeStamp()) / fs);
}
if (rtp->dataLen() >= 0)
{
rtp->setTimeStamp(rtp->timeStamp() - firstTS);
}
packetCount++;
if (changeStereoMode(*rtp, decoders, &stereoMode))
{
printf("Warning: stereo mode changed\n");
}
if (stereoMode > stereoModeMono)
{
if(rtp->splitStereo(slaveRtp, stereoMode))
{
printf("Error in splitStereo\n");
}
}
#ifdef PLAY_CLEAN
currTS = rtp->timeStamp();
rtp->setTime(prev_time + (currTS-prevTS)/(fs/1000));
prevTS = currTS;
#endif
}
/* check if time to RecOut */
if ( (!recoutTimes && (simClock%10)==0) // recout times not given from file
|| ( recoutTimes && (simClock >= nextRecoutTime) ) ) // recout times given from file
{
if (stereoMode > stereoModeMono)
{
// stereo
WebRtc_Word16 tempLen;
tempLen = NetEQvector[0]->recOut( out_data, msInfo ); // master
outLen = NetEQvector[1]->recOut( &out_data[tempLen], msInfo ); // slave
assert(tempLen == outLen);
writeLen = outLen * 2;
stereoInterleave(out_data, writeLen);
}
else
{
// mono
outLen = NetEQvector[0]->recOut( out_data );
writeLen = outLen;
}
// write to file
if (fwrite(out_data, writeLen, 2, out_file) != 2) {
return -1;
}
writtenSamples += writeLen;
lastRecout = getNextRecoutTime(recoutTimes, &nextRecoutTime); // does nothing if recoutTimes == NULL
/* ask for statistics */
WebRtcNetEQ_NetworkStatistics inCallStats;
WebRtcNetEQ_GetNetworkStatistics(NetEQvector[0]->instance(), &inCallStats);
}
/* increase time */
simClock+=TIME_STEP;
}
fclose(in_file);
fclose(out_file);
#ifdef NETEQ_DELAY_LOGGING
temp_var = NETEQ_DELAY_LOGGING_SIGNAL_EOF;
if (fwrite(&temp_var, sizeof(int), 1, delay_fid2) != 1) {
return -1;
}
if (fwrite(&tot_received_packets, sizeof(WebRtc_UWord32),
1, delay_fid2) != 1) {
return -1;
}
fprintf(delay_fid2,"End of file\n");
fclose(delay_fid2);
#endif
WebRtcNetEQ_GetRTCPStats(NetEQvector[0]->instance(), &RTCPstat);
printf("RTCP statistics:\n");
printf(" cum_lost : %d\n", (int) RTCPstat.cum_lost);
printf(" ext_max : %d\n", (int) RTCPstat.ext_max);
printf(" fraction_lost : %d (%f%%)\n", RTCPstat.fraction_lost, (float)(100.0*RTCPstat.fraction_lost/256.0));
printf(" jitter : %d\n", (int) RTCPstat.jitter);
printf("\n Call duration ms : %u\n", simClock-start_clock);
printf("\nComplexity estimates (including sub-components):\n");
printf(" RecIn complexity : %.2f MCPS\n", NetEQvector[0]->getRecInTime() / ((float) 1000*(simClock-start_clock)));
printf(" RecOut complexity : %.2f MCPS\n", NetEQvector[0]->getRecOutTime() / ((float) 1000*(simClock-start_clock)));
free_coders(decoders);
//free_coders(0 /* first channel */);
// if (stereoMode > stereoModeMono) {
// free_coders(1 /* second channel */);
// }
free(msInfo);
for (std::vector<NETEQTEST_NetEQClass *>::iterator it = NetEQvector.begin();
it < NetEQvector.end(); delete *it++) {
}
printf("\nSimulation done!\n");
#ifdef JUNK_DATA
if ( (seedfile = fopen(SEED_FILE, "a+t") ) == NULL ) {
fprintf(stderr, "Error: Could not open file %s\n", SEED_FILE);
}
else {
fprintf(seedfile, "ok\n\n");
fclose(seedfile);
}
#endif
// Log complexity to file
/* FILE *statfile;
statfile = fopen("complexity.txt","at");
fprintf(statfile,"%.4f, %.4f\n", (float) totTime_RecIn.QuadPart / ((float) 1000*(simClock-start_clock)), (float) totTime_RecOut.QuadPart / ((float) 1000*(simClock-start_clock)));
fclose(statfile);*/
return(0);
}
/****************/
/* Subfunctions */
/****************/
bool splitStereo(NETEQTEST_RTPpacket* rtp, NETEQTEST_RTPpacket* rtpSlave,
const WebRtc_Word16 *stereoPtype, const enum stereoModes *stereoMode, int noOfStereoCodecs,
const WebRtc_Word16 *cngPtype, int noOfCngCodecs,
bool *isStereo)
{
// init
//bool isStereo = false;
enum stereoModes tempStereoMode = stereoModeMono;
bool isCng = false;
// check payload length
if (rtp->dataLen() <= 0) {
//*isStereo = false; // don't change
return(*isStereo);
}
// check payload type
WebRtc_Word16 ptype = rtp->payloadType();
// is this a cng payload?
for (int k = 0; k < noOfCngCodecs; k++) {
if (ptype == cngPtype[k]) {
// do not change stereo state
isCng = true;
tempStereoMode = stereoModeFrame;
}
}
if (!isCng)
{
*isStereo = false;
// is this payload type a stereo codec? which type?
for (int k = 0; k < noOfStereoCodecs; k++) {
if (ptype == stereoPtype[k]) {
tempStereoMode = stereoMode[k];
*isStereo = true;
break; // exit for loop
}
}
}
if (*isStereo)
{
// split the payload if stereo
if(rtp->splitStereo(rtpSlave, tempStereoMode))
{
printf("Error in splitStereo\n");
}
}
return(*isStereo);
}
void stereoInterleave(WebRtc_Word16 *data, WebRtc_Word16 totalLen)
{
int k;
for(k = totalLen/2; k < totalLen; k++) {
WebRtc_Word16 temp = data[k];
memmove(&data[2*k - totalLen + 2], &data[2*k - totalLen + 1], (totalLen - k -1) * sizeof(WebRtc_Word16));
data[2*k - totalLen + 1] = temp;
}
}
int getNextRecoutTime(FILE *fp, WebRtc_UWord32 *nextTime) {
float tempTime;
if (!fp) {
return -1;
}
if (fread(&tempTime, sizeof(float), 1, fp) != 0) {
// not end of file
*nextTime = (WebRtc_UWord32) tempTime;
return 0;
}
*nextTime = 0;
fclose(fp);
return 1;
}
void getNextExtraDelay(FILE *fp, WebRtc_UWord32 *t, int *d) {
float temp[2];
if(!fp) {
*d = -1;
return;
}
if (fread(&temp, sizeof(float), 2, fp) != 0) {
// not end of file
*t = (WebRtc_UWord32) temp[0];
*d = (int) temp[1];
return;
}
*d = -1;
fclose(fp);
return;
}
void parsePtypeFile(FILE *ptypeFile, std::map<WebRtc_UWord8, decoderStruct>* decoders)
{
int n, pt;
char codec[100];
decoderStruct tempDecoder;
// read first line
n = fscanf(ptypeFile, "%s %i\n", codec, &pt);
while (n==2)
{
memset(&tempDecoder, 0, sizeof(decoderStruct));
tempDecoder.stereo = stereoModeMono;
if( pt >= 0 // < 0 disables this codec
&& isalpha(codec[0]) ) // and is a letter
{
/* check for stereo */
int L = strlen(codec);
bool isStereo = false;
if (codec[L-1] == '*') {
// stereo codec
isStereo = true;
// remove '*'
codec[L-1] = '\0';
}
#ifdef CODEC_G711
if(strcmp(codec, "pcmu") == 0) {
tempDecoder.codec = kDecoderPCMu;
tempDecoder.fs = 8000;
}
else if(strcmp(codec, "pcma") == 0) {
tempDecoder.codec = kDecoderPCMa;
tempDecoder.fs = 8000;
}
#endif
#ifdef CODEC_IPCMU
else if(strcmp(codec, "eg711u") == 0) {
tempDecoder.codec = kDecoderEG711u;
tempDecoder.fs = 8000;
}
#endif
#ifdef CODEC_IPCMA
else if(strcmp(codec, "eg711a") == 0) {
tempDecoder.codec = kDecoderEG711a;
tempDecoder.fs = 8000;
}
#endif
#ifdef CODEC_ILBC
else if(strcmp(codec, "ilbc") == 0) {
tempDecoder.codec = kDecoderILBC;
tempDecoder.fs = 8000;
}
#endif
#ifdef CODEC_ISAC
else if(strcmp(codec, "isac") == 0) {
tempDecoder.codec = kDecoderISAC;
tempDecoder.fs = 16000;
}
#endif
#ifdef CODEC_ISACLC
else if(strcmp(codec, "isaclc") == 0) {
tempDecoder.codec = NETEQ_CODEC_ISACLC;
tempDecoder.fs = 16000;
}
#endif
#ifdef CODEC_ISAC_SWB
else if(strcmp(codec, "isacswb") == 0) {
tempDecoder.codec = kDecoderISACswb;
tempDecoder.fs = 32000;
}
#endif
#ifdef CODEC_ISAC_FB
else if(strcmp(codec, "isacfb") == 0) {
tempDecoder.codec = kDecoderISACfb;
tempDecoder.fs = 32000;
}
#endif
#ifdef CODEC_IPCMWB
else if(strcmp(codec, "ipcmwb") == 0) {
tempDecoder.codec = kDecoderIPCMwb;
tempDecoder.fs = 16000;
}
#endif
#ifdef CODEC_G722
else if(strcmp(codec, "g722") == 0) {
tempDecoder.codec = kDecoderG722;
tempDecoder.fs = 16000;
}
#endif
#ifdef CODEC_G722_1_16
else if(strcmp(codec, "g722_1_16") == 0) {
tempDecoder.codec = kDecoderG722_1_16;
tempDecoder.fs = 16000;
}
#endif
#ifdef CODEC_G722_1_24
else if(strcmp(codec, "g722_1_24") == 0) {
tempDecoder.codec = kDecoderG722_1_24;
tempDecoder.fs = 16000;
}
#endif
#ifdef CODEC_G722_1_32
else if(strcmp(codec, "g722_1_32") == 0) {
tempDecoder.codec = kDecoderG722_1_32;
tempDecoder.fs = 16000;
}
#endif
#ifdef CODEC_G722_1C_24
else if(strcmp(codec, "g722_1c_24") == 0) {
tempDecoder.codec = kDecoderG722_1C_24;
tempDecoder.fs = 32000;
}
#endif
#ifdef CODEC_G722_1C_32
else if(strcmp(codec, "g722_1c_32") == 0) {
tempDecoder.codec = kDecoderG722_1C_32;
tempDecoder.fs = 32000;
}
#endif
#ifdef CODEC_G722_1C_48
else if(strcmp(codec, "g722_1c_48") == 0) {
tempDecoder.codec = kDecoderG722_1C_48;
tempDecoder.fs = 32000;
}
#endif
#ifdef CODEC_G723
else if(strcmp(codec, "g723") == 0) {
tempDecoder.codec = NETEQ_CODEC_G723;
tempDecoder.fs = 8000;
}
#endif
#ifdef CODEC_G726
else if(strcmp(codec, "g726_16") == 0) {
tempDecoder.codec = kDecoderG726_16;
tempDecoder.fs = 8000;
}
else if(strcmp(codec, "g726_24") == 0) {
tempDecoder.codec = kDecoderG726_24;
tempDecoder.fs = 8000;
}
else if(strcmp(codec, "g726_32") == 0) {
tempDecoder.codec = kDecoderG726_32;
tempDecoder.fs = 8000;
}
else if(strcmp(codec, "g726_40") == 0) {
tempDecoder.codec = kDecoderG726_40;
tempDecoder.fs = 8000;
}
#endif
#ifdef CODEC_G729
else if(strcmp(codec, "g729") == 0) {
tempDecoder.codec = kDecoderG729;
tempDecoder.fs = 8000;
}
#endif
#ifdef CODEC_G729D
else if(strcmp(codec, "g729d") == 0) {
tempDecoder.codec = NETEQ_CODEC_G729D;
tempDecoder.fs = 8000;
}
#endif
#ifdef CODEC_G729_1
else if(strcmp(codec, "g729_1") == 0) {
tempDecoder.codec = kDecoderG729_1;
tempDecoder.fs = 16000;
}
#endif
#ifdef CODEC_GSMFR
else if(strcmp(codec, "gsmfr") == 0) {
tempDecoder.codec = kDecoderGSMFR;
tempDecoder.fs = 8000;
}
#endif
#ifdef CODEC_GSMEFR
else if(strcmp(codec, "gsmefr") == 0) {
tempDecoder.codec = NETEQ_CODEC_GSMEFR;
tempDecoder.fs = 8000;
}
#endif
#ifdef CODEC_AMR
else if(strcmp(codec, "amr") == 0) {
tempDecoder.codec = kDecoderAMR;
tempDecoder.fs = 8000;
}
#endif
#ifdef CODEC_AMRWB
else if(strcmp(codec, "amrwb") == 0) {
tempDecoder.codec = kDecoderAMRWB;
tempDecoder.fs = 16000;
}
#endif
#ifdef CODEC_DVI4
else if(strcmp(codec, "dvi4") == 0) {
tempDecoder.codec = NETEQ_CODEC_DVI4;
tempDecoder.fs = 8000;
}
#endif
#ifdef CODEC_SPEEX_8
else if(strcmp(codec, "speex8") == 0) {
tempDecoder.codec = kDecoderSPEEX_8;
tempDecoder.fs = 8000;
}
#endif
#ifdef CODEC_SPEEX_16
else if(strcmp(codec, "speex16") == 0) {
tempDecoder.codec = kDecoderSPEEX_16;
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;
tempDecoder.fs = 8000;
}
#endif
#ifdef CODEC_SILK_WB
else if(strcmp(codec, "silk12") == 0) {
tempDecoder.codec = NETEQ_CODEC_SILK_12;
tempDecoder.fs = 16000;
}
else if(strcmp(codec, "silk16") == 0) {
tempDecoder.codec = NETEQ_CODEC_SILK_16;
tempDecoder.fs = 16000;
}
#endif
#ifdef CODEC_SILK_SWB
else if(strcmp(codec, "silk24") == 0) {
tempDecoder.codec = NETEQ_CODEC_SILK_24;
tempDecoder.fs = 32000;
}
#endif
#ifdef CODEC_MELPE
else if(strcmp(codec, "melpe") == 0) {
tempDecoder.codec = NETEQ_CODEC_MELPE;
tempDecoder.fs = 8000;
}
#endif
#ifdef CODEC_PCM16B
else if(strcmp(codec, "pcm16b") == 0) {
tempDecoder.codec = kDecoderPCM16B;
tempDecoder.fs = 8000;
}
#endif
#ifdef CODEC_PCM16B_WB
else if(strcmp(codec, "pcm16b_wb") == 0) {
tempDecoder.codec = kDecoderPCM16Bwb;
tempDecoder.fs = 16000;
}
#endif
#ifdef CODEC_PCM16B_32KHZ
else if(strcmp(codec, "pcm16b_swb32khz") == 0) {
tempDecoder.codec = kDecoderPCM16Bswb32kHz;
tempDecoder.fs = 32000;
}
#endif
#ifdef CODEC_PCM16B_48KHZ
else if(strcmp(codec, "pcm16b_swb48khz") == 0) {
tempDecoder.codec = kDecoderPCM16Bswb48kHz;
tempDecoder.fs = 48000;
}
#endif
#ifdef CODEC_CNGCODEC8
else if(strcmp(codec, "cn") == 0) {
tempDecoder.codec = kDecoderCNG;
tempDecoder.fs = 8000;
}
#endif
#ifdef CODEC_CNGCODEC16
else if(strcmp(codec, "cn_wb") == 0) {
tempDecoder.codec = kDecoderCNG;
tempDecoder.fs = 16000;
}
#endif
#ifdef CODEC_CNGCODEC32
else if(strcmp(codec, "cn_swb32") == 0) {
tempDecoder.codec = kDecoderCNG;
tempDecoder.fs = 32000;
}
#endif
#ifdef CODEC_CNGCODEC48
else if(strcmp(codec, "cn_swb48") == 0) {
tempDecoder.codec = kDecoderCNG;
tempDecoder.fs = 48000;
}
#endif
#ifdef CODEC_ATEVENT_DECODE
else if(strcmp(codec, "avt") == 0) {
tempDecoder.codec = kDecoderAVT;
tempDecoder.fs = 8000;
}
#endif
#ifdef CODEC_RED
else if(strcmp(codec, "red") == 0) {
tempDecoder.codec = kDecoderRED;
tempDecoder.fs = 8000;
}
#endif
else if(isalpha(codec[0])) {
printf("Unsupported codec %s\n", codec);
// read next line and continue while loop
n = fscanf(ptypeFile, "%s %i\n", codec, &pt);
continue;
}
else {
// name is not recognized, and does not start with a letter
// hence, it is commented out
// read next line and continue while loop
n = fscanf(ptypeFile, "%s %i\n", codec, &pt);
continue;
}
// handle stereo
if (tempDecoder.codec == kDecoderCNG)
{
// always set stereo mode for CNG, even if it is not marked at stereo
tempDecoder.stereo = stereoModeFrame;
}
else if(isStereo)
{
switch(tempDecoder.codec) {
// sample based codecs
case kDecoderPCMu:
case kDecoderPCMa:
case kDecoderG722:
{
// 1 octet per sample
tempDecoder.stereo = stereoModeSample1;
break;
}
case kDecoderPCM16B:
case kDecoderPCM16Bwb:
case kDecoderPCM16Bswb32kHz:
case kDecoderPCM16Bswb48kHz:
{
// 2 octets per sample
tempDecoder.stereo = stereoModeSample2;
break;
}
case kDecoderCELT_32:
{
tempDecoder.stereo = stereoModeDuplicate;
break;
}
// fixed-rate frame codecs
// case kDecoderG729:
// case NETEQ_CODEC_G729D:
// case NETEQ_CODEC_G729E:
// case kDecoderG722_1_16:
// case kDecoderG722_1_24:
// case kDecoderG722_1_32:
// case kDecoderG722_1C_24:
// case kDecoderG722_1C_32:
// case kDecoderG722_1C_48:
// case NETEQ_CODEC_MELPE:
// {
// tempDecoder.stereo = stereoModeFrame;
// break;
// }
default:
{
printf("Cannot use codec %s as stereo codec\n", codec);
exit(0);
}
}
}
if (pt > 127)
{
printf("Payload type must be less than 128\n");
exit(0);
}
// insert into codecs map
(*decoders)[static_cast<WebRtc_UWord8>(pt)] = tempDecoder;
}
n = fscanf(ptypeFile, "%s %i\n", codec, &pt);
} // end while
}
bool changeStereoMode(NETEQTEST_RTPpacket & rtp, std::map<WebRtc_UWord8, decoderStruct> & decoders, enum stereoModes *stereoMode)
{
if (decoders.count(rtp.payloadType()) > 0
&& decoders[rtp.payloadType()].codec != kDecoderRED
&& decoders[rtp.payloadType()].codec != kDecoderAVT
&& decoders[rtp.payloadType()].codec != kDecoderCNG )
{
if (decoders[rtp.payloadType()].stereo != *stereoMode)
{
*stereoMode = decoders[rtp.payloadType()].stereo;
return true; // stereo mode did change
}
}
return false; // stereo mode did not change
}
int populateUsedCodec(std::map<WebRtc_UWord8, decoderStruct>* decoders, enum WebRtcNetEQDecoder *usedCodec)
{
int numCodecs = 0;
std::map<WebRtc_UWord8, decoderStruct>::iterator it;
it = decoders->begin();
for (int i = 0; i < static_cast<int>(decoders->size()); i++, it++)
{
usedCodec[numCodecs] = (*it).second.codec;
numCodecs++;
}
return numCodecs;
}
void createAndInsertDecoders (NETEQTEST_NetEQClass *neteq, std::map<WebRtc_UWord8, decoderStruct>* decoders, int channelNumber)
{
std::map<WebRtc_UWord8, decoderStruct>::iterator it;
for (it = decoders->begin(); it != decoders->end(); it++)
{
if (channelNumber == 0 ||
((*it).second.stereo > stereoModeMono ))
{
// create decoder instance
WebRtc_UWord8 pt = static_cast<WebRtc_UWord8>( (*it).first );
NETEQTEST_Decoder **dec = &((*it).second.decoder[channelNumber]);
enum WebRtcNetEQDecoder type = (*it).second.codec;
switch (type)
{
#ifdef CODEC_G711
case kDecoderPCMu:
*dec = new decoder_PCMU( pt );
break;
case kDecoderPCMa:
*dec = new decoder_PCMA( pt );
break;
#endif
#ifdef CODEC_IPCMU
case kDecoderEG711u:
*dec = new decoder_IPCMU( pt );
break;
#endif
#ifdef CODEC_IPCMA
case kDecoderEG711a:
*dec = new decoder_IPCMA( pt );
break;
#endif
#ifdef CODEC_IPCMWB
case kDecoderIPCMwb:
*dec = new decoder_IPCMWB( pt );
break;
#endif
#ifdef CODEC_ILBC
case kDecoderILBC:
*dec = new decoder_ILBC( pt );
break;
#endif
#ifdef CODEC_ISAC
case kDecoderISAC:
*dec = new decoder_iSAC( pt );
break;
#endif
#ifdef CODEC_ISAC_SWB
case kDecoderISACswb:
*dec = new decoder_iSACSWB( pt );
break;
#endif
#ifdef CODEC_ISAC_FB
case kDecoderISACfb:
*dec = new decoder_iSACFB(pt);
break;
#endif
#ifdef CODEC_G729
case kDecoderG729:
*dec = new decoder_G729( pt );
break;
case NETEQ_CODEC_G729D:
printf("Error: G729D not supported\n");
break;
#endif
#ifdef CODEC_G729E
case NETEQ_CODEC_G729E:
*dec = new decoder_G729E( pt );
break;
#endif
#ifdef CODEC_G729_1
case kDecoderG729_1:
*dec = new decoder_G729_1( pt );
break;
#endif
#ifdef CODEC_G723
case NETEQ_CODEC_G723:
*dec = new decoder_G723( pt );
break;
#endif
#ifdef CODEC_PCM16B
case kDecoderPCM16B:
*dec = new decoder_PCM16B_NB( pt );
break;
#endif
#ifdef CODEC_PCM16B_WB
case kDecoderPCM16Bwb:
*dec = new decoder_PCM16B_WB( pt );
break;
#endif
#ifdef CODEC_PCM16B_32KHZ
case kDecoderPCM16Bswb32kHz:
*dec = new decoder_PCM16B_SWB32( pt );
break;
#endif
#ifdef CODEC_PCM16B_48KHZ
case kDecoderPCM16Bswb48kHz:
*dec = new decoder_PCM16B_SWB48( pt );
break;
#endif
#ifdef CODEC_DVI4
case NETEQ_CODEC_DVI4:
*dec = new decoder_DVI4( pt );
break;
#endif
#ifdef CODEC_G722
case kDecoderG722:
*dec = new decoder_G722( pt );
break;
#endif
#ifdef CODEC_G722_1_16
case kDecoderG722_1_16:
*dec = new decoder_G722_1_16( pt );
break;
#endif
#ifdef CODEC_G722_1_24
case kDecoderG722_1_24:
*dec = new decoder_G722_1_24( pt );
break;
#endif
#ifdef CODEC_G722_1_32
case kDecoderG722_1_32:
*dec = new decoder_G722_1_32( pt );
break;
#endif
#ifdef CODEC_G722_1C_24
case kDecoderG722_1C_24:
*dec = new decoder_G722_1C_24( pt );
break;
#endif
#ifdef CODEC_G722_1C_32
case kDecoderG722_1C_32:
*dec = new decoder_G722_1C_32( pt );
break;
#endif
#ifdef CODEC_G722_1C_48
case kDecoderG722_1C_48:
*dec = new decoder_G722_1C_48( pt );
break;
#endif
#ifdef CODEC_AMR
case kDecoderAMR:
*dec = new decoder_AMR( pt );
break;
#endif
#ifdef CODEC_AMRWB
case kDecoderAMRWB:
*dec = new decoder_AMRWB( pt );
break;
#endif
#ifdef CODEC_GSMFR
case kDecoderGSMFR:
*dec = new decoder_GSMFR( pt );
break;
#endif
#ifdef CODEC_GSMEFR
case NETEQ_CODEC_GSMEFR:
*dec = new decoder_GSMEFR( pt );
break;
#endif
#ifdef CODEC_G726
case kDecoderG726_16:
*dec = new decoder_G726_16( pt );
break;
case kDecoderG726_24:
*dec = new decoder_G726_24( pt );
break;
case kDecoderG726_32:
*dec = new decoder_G726_32( pt );
break;
case kDecoderG726_40:
*dec = new decoder_G726_40( pt );
break;
#endif
#ifdef CODEC_MELPE
case NETEQ_CODEC_MELPE:
#if (_MSC_VER >= 1400) && !defined(_WIN64) // only for Visual 2005 or later, and not for x64
*dec = new decoder_MELPE( pt );
#endif
break;
#endif
#ifdef CODEC_SPEEX_8
case kDecoderSPEEX_8:
*dec = new decoder_SPEEX( pt, 8000 );
break;
#endif
#ifdef CODEC_SPEEX_16
case kDecoderSPEEX_16:
*dec = new decoder_SPEEX( pt, 16000 );
break;
#endif
#ifdef CODEC_CELT_32
case kDecoderCELT_32:
if (channelNumber == 0)
*dec = new decoder_CELT( pt, 32000 );
else
*dec = new decoder_CELTslave( pt, 32000 );
break;
#endif
#ifdef CODEC_RED
case kDecoderRED:
*dec = new decoder_RED( pt );
break;
#endif
#ifdef CODEC_ATEVENT_DECODE
case kDecoderAVT:
*dec = new decoder_AVT( pt );
break;
#endif
#if (defined(CODEC_CNGCODEC8) || defined(CODEC_CNGCODEC16) || \
defined(CODEC_CNGCODEC32) || defined(CODEC_CNGCODEC48))
case kDecoderCNG:
*dec = new decoder_CNG( pt, static_cast<WebRtc_UWord16>((*it).second.fs) );
break;
#endif
#ifdef CODEC_ISACLC
case NETEQ_CODEC_ISACLC:
*dec = new decoder_iSACLC( pt );
break;
#endif
#ifdef CODEC_SILK_NB
case NETEQ_CODEC_SILK_8:
#if (_MSC_VER >= 1400) && !defined(_WIN64) // only for Visual 2005 or later, and not for x64
*dec = new decoder_SILK8( pt );
#endif
break;
#endif
#ifdef CODEC_SILK_WB
case NETEQ_CODEC_SILK_12:
#if (_MSC_VER >= 1400) && !defined(_WIN64) // only for Visual 2005 or later, and not for x64
*dec = new decoder_SILK12( pt );
#endif
break;
#endif
#ifdef CODEC_SILK_WB
case NETEQ_CODEC_SILK_16:
#if (_MSC_VER >= 1400) && !defined(_WIN64) // only for Visual 2005 or later, and not for x64
*dec = new decoder_SILK16( pt );
#endif
break;
#endif
#ifdef CODEC_SILK_SWB
case NETEQ_CODEC_SILK_24:
#if (_MSC_VER >= 1400) && !defined(_WIN64) // only for Visual 2005 or later, and not for x64
*dec = new decoder_SILK24( pt );
#endif
break;
#endif
default:
printf("Unknown codec type encountered in createAndInsertDecoders\n");
exit(0);
}
// insert into codec DB
if (*dec)
{
(*dec)->loadToNetEQ(*neteq);
}
}
}
}
void free_coders(std::map<WebRtc_UWord8, decoderStruct> & decoders)
{
std::map<WebRtc_UWord8, decoderStruct>::iterator it;
for (it = decoders.begin(); it != decoders.end(); it++)
{
if ((*it).second.decoder[0])
{
delete (*it).second.decoder[0];
}
if ((*it).second.decoder[1])
{
delete (*it).second.decoder[1];
}
}
}
#include "pcm16b.h"
#include "g711_interface.h"
#include "isac.h"
int doAPItest() {
void *inst;
enum WebRtcNetEQDecoder usedCodec;
int NetEqBufferMaxPackets, BufferSizeInBytes;
WebRtcNetEQ_CodecDef codecInst;
WebRtcNetEQ_RTCPStat RTCPstat;
WebRtc_UWord32 timestamp;
int memorySize;
int ok;
printf("API-test:\n\n");
/* test that API functions return -1 if instance is NULL */
#define CHECK_MINUS_ONE(x) {int errCode = x; if((errCode)!=-1){printf("\n API test failed at line %d: %s. Function did not return -1 as expected\n",__LINE__,#x); return(-1);}}
//#define RESET_ERROR(x) ((MainInst_t*) x)->ErrorCode = 0;
inst = NULL;
CHECK_MINUS_ONE(WebRtcNetEQ_GetErrorCode(inst))
CHECK_MINUS_ONE(WebRtcNetEQ_Assign(&inst, NULL))
// printf("WARNING: Test of WebRtcNetEQ_Assign() is disabled due to a bug.\n");
usedCodec=kDecoderPCMu;
CHECK_MINUS_ONE(WebRtcNetEQ_GetRecommendedBufferSize(inst, &usedCodec, 1, kTCPLargeJitter, &NetEqBufferMaxPackets, &BufferSizeInBytes))
CHECK_MINUS_ONE(WebRtcNetEQ_AssignBuffer(inst, NetEqBufferMaxPackets, NetEqPacketBuffer, BufferSizeInBytes))
CHECK_MINUS_ONE(WebRtcNetEQ_Init(inst, 8000))
CHECK_MINUS_ONE(WebRtcNetEQ_SetAVTPlayout(inst, 0))
CHECK_MINUS_ONE(WebRtcNetEQ_SetExtraDelay(inst, 17))
CHECK_MINUS_ONE(WebRtcNetEQ_SetPlayoutMode(inst, kPlayoutOn))
CHECK_MINUS_ONE(WebRtcNetEQ_CodecDbReset(inst))
CHECK_MINUS_ONE(WebRtcNetEQ_CodecDbAdd(inst, &codecInst))
CHECK_MINUS_ONE(WebRtcNetEQ_CodecDbRemove(inst, usedCodec))
WebRtc_Word16 temp1, temp2;
CHECK_MINUS_ONE(WebRtcNetEQ_CodecDbGetSizeInfo(inst, &temp1, &temp2))
CHECK_MINUS_ONE(WebRtcNetEQ_CodecDbGetCodecInfo(inst, 0, &usedCodec))
CHECK_MINUS_ONE(WebRtcNetEQ_RecIn(inst, &temp1, 17, 4711))
CHECK_MINUS_ONE(WebRtcNetEQ_RecOut(inst, &temp1, &temp2))
CHECK_MINUS_ONE(WebRtcNetEQ_GetRTCPStats(inst, &RTCPstat)); // error here!!!
CHECK_MINUS_ONE(WebRtcNetEQ_GetSpeechTimeStamp(inst, &timestamp))
WebRtcNetEQOutputType temptype;
CHECK_MINUS_ONE(WebRtcNetEQ_GetSpeechOutputType(inst, &temptype))
WebRtc_UWord8 tempFlags;
WebRtc_UWord16 utemp1, utemp2;
CHECK_MINUS_ONE(WebRtcNetEQ_VQmonRecOutStatistics(inst, &utemp1, &utemp2, &tempFlags))
CHECK_MINUS_ONE(WebRtcNetEQ_VQmonGetRxStatistics(inst, &utemp1, &utemp2))
WebRtcNetEQ_AssignSize(&memorySize);
CHECK_ZERO(WebRtcNetEQ_Assign(&inst, malloc(memorySize)))
/* init with wrong sample frequency */
CHECK_MINUS_ONE(WebRtcNetEQ_Init(inst, 17))
/* init with correct fs */
CHECK_ZERO(WebRtcNetEQ_Init(inst, 8000))
/* GetRecommendedBufferSize with wrong codec */
usedCodec=kDecoderReservedStart;
ok = WebRtcNetEQ_GetRecommendedBufferSize(inst, &usedCodec, 1, kTCPLargeJitter , &NetEqBufferMaxPackets, &BufferSizeInBytes);
if((ok!=-1) || ((ok==-1)&&(WebRtcNetEQ_GetErrorCode(inst)!=-CODEC_DB_UNKNOWN_CODEC))){
printf("WebRtcNetEQ_GetRecommendedBufferSize() did not return proper error code for wrong codec.\n");
printf("return value = %d; error code = %d\n", ok, WebRtcNetEQ_GetErrorCode(inst));
}
//RESET_ERROR(inst)
/* GetRecommendedBufferSize with wrong network type */
usedCodec = kDecoderPCMu;
ok=WebRtcNetEQ_GetRecommendedBufferSize(inst, &usedCodec, 1, (enum WebRtcNetEQNetworkType) 4711 , &NetEqBufferMaxPackets, &BufferSizeInBytes);
if ((ok!=-1) || ((ok==-1)&&(WebRtcNetEQ_GetErrorCode(inst)!=-FAULTY_NETWORK_TYPE))) {
printf("WebRtcNetEQ_GetRecommendedBufferSize() did not return proper error code for wrong network type.\n");
printf("return value = %d; error code = %d\n", ok, WebRtcNetEQ_GetErrorCode(inst));
//RESET_ERROR(inst)
}
CHECK_ZERO(WebRtcNetEQ_GetRecommendedBufferSize(inst, &usedCodec, 1, kTCPLargeJitter , &NetEqBufferMaxPackets, &BufferSizeInBytes))
/* try to do RecIn before assigning the packet buffer */
/* makeRTPheader(rtp_data, NETEQ_CODEC_AVT_PT, 17,4711, 1235412312);
makeDTMFpayload(&rtp_data[12], 1, 1, 10, 100);
ok = WebRtcNetEQ_RecIn(inst, (short *) rtp_data, 12+4, 4711);
printf("return value = %d; error code = %d\n", ok, WebRtcNetEQ_GetErrorCode(inst));*/
/* check all limits of WebRtcNetEQ_AssignBuffer */
ok=WebRtcNetEQ_AssignBuffer(inst, NetEqBufferMaxPackets, NetEqPacketBuffer, 149<<1);
if((ok!=-1)||((ok==-1)&&(WebRtcNetEQ_GetErrorCode(inst)!=-PBUFFER_INIT_ERROR))) {
printf("WebRtcNetEQ_AssignBuffer() did not return proper error code for wrong sizeinbytes\n");
}
ok=WebRtcNetEQ_AssignBuffer(inst, NetEqBufferMaxPackets, NULL, BufferSizeInBytes);
if((ok!=-1)||((ok==-1)&&(WebRtcNetEQ_GetErrorCode(inst)!=-PBUFFER_INIT_ERROR))) {
printf("WebRtcNetEQ_AssignBuffer() did not return proper error code for NULL memory pointer\n");
}
ok=WebRtcNetEQ_AssignBuffer(inst, 1, NetEqPacketBuffer, BufferSizeInBytes);
if((ok!=-1)||((ok==-1)&&(WebRtcNetEQ_GetErrorCode(inst)!=-PBUFFER_INIT_ERROR))) {
printf("WebRtcNetEQ_AssignBuffer() did not return proper error code for wrong MaxNoOfPackets\n");
}
ok=WebRtcNetEQ_AssignBuffer(inst, 601, NetEqPacketBuffer, BufferSizeInBytes);
if((ok!=-1)||((ok==-1)&&(WebRtcNetEQ_GetErrorCode(inst)!=-PBUFFER_INIT_ERROR))) {
printf("WebRtcNetEQ_AssignBuffer() did not return proper error code for wrong MaxNoOfPackets\n");
}
/* do correct assignbuffer */
CHECK_ZERO(WebRtcNetEQ_AssignBuffer(inst, NetEqBufferMaxPackets, NetEqPacketBuffer, BufferSizeInBytes))
ok=WebRtcNetEQ_SetExtraDelay(inst, -1);
if((ok!=-1)||((ok==-1)&&(WebRtcNetEQ_GetErrorCode(inst)!=-FAULTY_DELAYVALUE))) {
printf("WebRtcNetEQ_SetExtraDelay() did not return proper error code for too small delay\n");
}
ok=WebRtcNetEQ_SetExtraDelay(inst, 1001);
if((ok!=-1)||((ok==-1)&&(WebRtcNetEQ_GetErrorCode(inst)!=-FAULTY_DELAYVALUE))) {
printf("WebRtcNetEQ_SetExtraDelay() did not return proper error code for too large delay\n");
}
ok=WebRtcNetEQ_SetPlayoutMode(inst,(enum WebRtcNetEQPlayoutMode) 4711);
if((ok!=-1)||((ok==-1)&&(WebRtcNetEQ_GetErrorCode(inst)!=-FAULTY_PLAYOUTMODE))) {
printf("WebRtcNetEQ_SetPlayoutMode() did not return proper error code for wrong mode\n");
}
/* number of codecs should return zero before adding any codecs */
WebRtcNetEQ_CodecDbGetSizeInfo(inst, &temp1, &temp2);
if(temp1!=0)
printf("WebRtcNetEQ_CodecDbGetSizeInfo() return non-zero number of codecs in DB before adding any codecs\n");
/* get info from empty database */
ok=WebRtcNetEQ_CodecDbGetCodecInfo(inst, 17, &usedCodec);
if((ok!=-1)||((ok==-1)&&(WebRtcNetEQ_GetErrorCode(inst)!=-CODEC_DB_NOT_EXIST1))) {
printf("WebRtcNetEQ_CodecDbGetCodecInfo() did not return proper error code for out-of-range entry number\n");
}
/* remove codec from empty database */
ok=WebRtcNetEQ_CodecDbRemove(inst,kDecoderPCMa);
if((ok!=-1)||((ok==-1)&&(WebRtcNetEQ_GetErrorCode(inst)!=-CODEC_DB_NOT_EXIST4))) {
printf("WebRtcNetEQ_CodecDbRemove() did not return proper error code when removing codec that has not been added\n");
}
/* add codec with unsupported fs */
#ifdef CODEC_PCM16B
#ifndef NETEQ_48KHZ_WIDEBAND
SET_CODEC_PAR(codecInst,kDecoderPCM16Bswb48kHz,77,NULL,48000);
SET_PCM16B_SWB48_FUNCTIONS(codecInst);
ok=WebRtcNetEQ_CodecDbAdd(inst, &codecInst);
if((ok!=-1)||((ok==-1)&&(WebRtcNetEQ_GetErrorCode(inst)!=-CODEC_DB_UNSUPPORTED_FS))) {
printf("WebRtcNetEQ_CodecDbAdd() did not return proper error code when adding codec with unsupported sample freq\n");
}
#else
printf("Could not test adding codec with unsupported sample frequency since NetEQ is compiled with 48kHz support.\n");
#endif
#else
printf("Could not test adding codec with unsupported sample frequency since NetEQ is compiled without PCM16B support.\n");
#endif
/* add two codecs with identical payload types */
SET_CODEC_PAR(codecInst,kDecoderPCMa,17,NULL,8000);
SET_PCMA_FUNCTIONS(codecInst);
CHECK_ZERO(WebRtcNetEQ_CodecDbAdd(inst, &codecInst))
SET_CODEC_PAR(codecInst,kDecoderPCMu,17,NULL,8000);
SET_PCMU_FUNCTIONS(codecInst);
ok=WebRtcNetEQ_CodecDbAdd(inst, &codecInst);
if((ok!=-1)||((ok==-1)&&(WebRtcNetEQ_GetErrorCode(inst)!=-CODEC_DB_PAYLOAD_TAKEN))) {
printf("WebRtcNetEQ_CodecDbAdd() did not return proper error code when adding two codecs with identical payload types\n");
}
/* try adding several payload types for CNG codecs */
SET_CODEC_PAR(codecInst,kDecoderCNG,105,NULL,16000);
SET_CNG_FUNCTIONS(codecInst);
CHECK_ZERO(WebRtcNetEQ_CodecDbAdd(inst, &codecInst))
SET_CODEC_PAR(codecInst,kDecoderCNG,13,NULL,8000);
SET_CNG_FUNCTIONS(codecInst);
CHECK_ZERO(WebRtcNetEQ_CodecDbAdd(inst, &codecInst))
/* try adding a speech codec over a CNG codec */
SET_CODEC_PAR(codecInst,kDecoderISAC,105,NULL,16000); /* same as WB CNG above */
SET_ISAC_FUNCTIONS(codecInst);
ok=WebRtcNetEQ_CodecDbAdd(inst, &codecInst);
if((ok!=-1)||((ok==-1)&&(WebRtcNetEQ_GetErrorCode(inst)!=-CODEC_DB_PAYLOAD_TAKEN))) {
printf("WebRtcNetEQ_CodecDbAdd() did not return proper error code when adding a speech codec over a CNG codec\n");
}
/* try adding a CNG codec over a speech codec */
SET_CODEC_PAR(codecInst,kDecoderCNG,17,NULL,32000); /* same as PCMU above */
SET_CNG_FUNCTIONS(codecInst);
ok=WebRtcNetEQ_CodecDbAdd(inst, &codecInst);
if((ok!=-1)||((ok==-1)&&(WebRtcNetEQ_GetErrorCode(inst)!=-CODEC_DB_PAYLOAD_TAKEN))) {
printf("WebRtcNetEQ_CodecDbAdd() did not return proper error code when adding a speech codec over a CNG codec\n");
}
/* remove codec out of range */
ok=WebRtcNetEQ_CodecDbRemove(inst,kDecoderReservedStart);
if((ok!=-1)||((ok==-1)&&(WebRtcNetEQ_GetErrorCode(inst)!=-CODEC_DB_UNSUPPORTED_CODEC))) {
printf("WebRtcNetEQ_CodecDbRemove() did not return proper error code when removing codec that is out of range\n");
}
ok=WebRtcNetEQ_CodecDbRemove(inst,kDecoderReservedEnd);
if((ok!=-1)||((ok==-1)&&(WebRtcNetEQ_GetErrorCode(inst)!=-CODEC_DB_UNSUPPORTED_CODEC))) {
printf("WebRtcNetEQ_CodecDbRemove() did not return proper error code when removing codec that is out of range\n");
}
/*SET_CODEC_PAR(codecInst,kDecoderEG711a,NETEQ_CODEC_EG711A_PT,NetEqiPCMAState,8000);
SET_IPCMA_FUNCTIONS(codecInst);
CHECK_ZERO(WebRtcNetEQ_CodecDbAdd(inst, &codecInst))
*/
free(inst);
return(0);
}