Note: We no longer publish the latest version of our code here. We primarily use a kumc-bmi github organization. The heron ETL repository, in particular, is not public. Peers in the informatics community should see MultiSiteDev for details on requesting access.

source: webrtc/webrtc/modules/audio_coding/neteq/test/NetEqRTPplay.cc @ 0:4bda6873e34c

pub_scrub_3792 tip
Last change on this file since 0:4bda6873e34c was 0:4bda6873e34c, checked in by Michael Prittie <mprittie@…>, 6 years ago

Scrubbed password for publication.

File size: 56.8 KB
Line 
1/*
2 *  Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
3 *
4 *  Use of this source code is governed by a BSD-style license
5 *  that can be found in the LICENSE file in the root of the source
6 *  tree. An additional intellectual property rights grant can be found
7 *  in the file PATENTS.  All contributing project authors may
8 *  be found in the AUTHORS file in the root of the source tree.
9 */
10
11//TODO(hlundin): Reformat file to meet style guide.
12
13#include <assert.h>
14#include <stdio.h>
15
16/* header includes */
17#include "typedefs.h"
18#include "webrtc_neteq.h"
19#include "webrtc_neteq_internal.h"
20#include "webrtc_neteq_help_macros.h"
21#include "neteq_error_codes.h" // for the API test
22
23#include "NETEQTEST_RTPpacket.h"
24#include "NETEQTEST_DummyRTPpacket.h"
25#include "NETEQTEST_NetEQClass.h"
26#include "NETEQTEST_CodecClass.h"
27
28#ifdef WEBRTC_ANDROID
29#include <ctype.h> // isalpha
30#endif
31#include <string.h>
32#include <stdlib.h>
33#include <time.h>
34#include <map>
35#include <vector>
36
37#ifdef WIN32
38#include <assert.h>
39#include <windows.h>
40#endif
41
42#ifdef WEBRTC_LINUX
43#include <assert.h>
44#include <libgen.h>
45#include <netinet/in.h>
46#endif
47
48//#include "vld.h"
49
50//#define NETEQ_DELAY_LOGGING
51//#define DUMMY_SLAVE_CHANNEL
52
53#ifdef NETEQ_DELAY_LOGGING
54#include "delay_logging.h"
55#define DUMMY_SLAVE_CHANNEL // do not use a slave channel, only generate zeros instead
56#endif
57
58
59/************************/
60/* Define payload types */
61/************************/
62
63// Payload types are defined in the textfile ptypes.txt, and can be changed after compilation.
64
65
66
67/*********************/
68/* Misc. definitions */
69/*********************/
70
71#define TIME_STEP 1
72#define FIRSTLINELEN 40
73#define MAX_NETEQ_BUFFERSIZE    170000 //100000
74#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);}}
75#define CHECK_NOT_NULL(a) if((a)==NULL){printf("\n %s \n line: %d \nerror at %s\n",__FILE__,__LINE__,#a );return(-1);}
76//#define PLAY_CLEAN // ignore arrival times and let the packets arrive according to RTP timestamps
77#define HDR_SIZE 8 // rtpplay packet header size in bytes
78//#define JUNK_DATA   // scramble the payloads to test error resilience
79//#define ZERO_TS_START
80
81#ifdef JUNK_DATA
82    #define SEED_FILE "randseed.txt"
83#endif
84
85#ifdef WIN32
86#define MY_MAX_DRIVE _MAX_DRIVE
87#define MY_MAX_PATH _MAX_PATH
88#define MY_MAX_FNAME _MAX_FNAME
89#define MY_MAX_EXT _MAX_EXT
90
91#elif defined(WEBRTC_LINUX)
92#include <linux/limits.h>
93#define MY_MAX_PATH PATH_MAX
94
95#elif defined(WEBRTC_MAC)
96#include <sys/syslimits.h>
97#define MY_MAX_PATH PATH_MAX
98#endif // WEBRTC_MAC
99
100/************/
101/* Typedefs */
102/************/
103
104typedef struct {
105    enum WebRtcNetEQDecoder  codec;
106    enum stereoModes    stereo;
107    NETEQTEST_Decoder * decoder[2];
108    int            fs;
109} decoderStruct;
110
111
112/*************************/
113/* Function declarations */
114/*************************/
115
116void stereoInterleave(int16_t *data, int16_t totalLen);
117int getNextRecoutTime(FILE *fp, uint32_t *nextTime);
118void getNextExtraDelay(FILE *fp, uint32_t *t, int *d);
119bool splitStereo(NETEQTEST_RTPpacket* rtp, NETEQTEST_RTPpacket* rtpSlave,
120                 const int16_t *stereoPtype, const enum stereoModes *stereoMode, int noOfStereoCodecs,
121                 const int16_t *cngPtype, int noOfCngCodecs,
122                 bool *isStereo);
123void parsePtypeFile(FILE *ptypeFile, std::map<uint8_t, decoderStruct>* decoders);
124int populateUsedCodec(std::map<uint8_t, decoderStruct>* decoders, enum WebRtcNetEQDecoder *usedCodec);
125void createAndInsertDecoders (NETEQTEST_NetEQClass *neteq, std::map<uint8_t, decoderStruct>* decoders, int channelNumber);
126void free_coders(std::map<uint8_t, decoderStruct> & decoders);
127int doAPItest();
128bool changeStereoMode(NETEQTEST_RTPpacket & rtp, std::map<uint8_t, decoderStruct> & decoders, enum stereoModes *stereoMode);
129
130
131
132/********************/
133/* Global variables */
134/********************/
135
136int16_t NetEqPacketBuffer[MAX_NETEQ_BUFFERSIZE>>1];
137int16_t NetEqPacketBufferSlave[MAX_NETEQ_BUFFERSIZE>>1];
138
139#ifdef NETEQ_DELAY_LOGGING
140extern "C" {
141    FILE *delay_fid2;   /* file pointer */
142    uint32_t tot_received_packets=0;
143}
144#endif
145
146#ifdef DEF_BUILD_DATE
147extern char BUILD_DATE;
148#endif
149
150uint32_t writtenSamples = 0;
151uint32_t simClock=0;
152
153int main(int argc, char* argv[])
154{
155    std::vector<NETEQTEST_NetEQClass *> NetEQvector;
156
157    enum WebRtcNetEQDecoder usedCodec[kDecoderReservedEnd-1];
158    int noOfCodecs;
159    int ok;
160    int16_t out_data[640*2];
161    int16_t outLen, writeLen;
162    int fs = 8000;
163    WebRtcNetEQ_RTCPStat RTCPstat;
164#ifdef WIN32
165    char outdrive[MY_MAX_DRIVE];
166    char outpath[MY_MAX_PATH];
167    char outfile[MY_MAX_FNAME];
168    char outext[MY_MAX_EXT];
169#endif
170    char outfilename[MY_MAX_PATH];
171#ifdef NETEQ_DELAY_LOGGING
172    float clock_float;
173    int temp_var;
174#endif
175#ifdef JUNK_DATA
176    FILE *seedfile;
177#endif
178    FILE *recoutTimes = NULL;
179    FILE *extraDelays = NULL;
180    WebRtcNetEQPlayoutMode streamingMode = kPlayoutOn;
181    bool preParseRTP = false;
182    bool rtpOnly = false;
183    int packetLen = 0;
184    int packetCount = 0;
185    std::map<uint8_t, decoderStruct> decoders;
186    bool dummyRtp = false;
187    bool noDecode = false;
188    bool filterSSRC = false;
189    uint32_t ssrc;
190
191#ifdef DEF_BUILD_DATE
192    printf("Build time: %s\n", __BUILD_DATE);
193#endif
194
195    /* check number of parameters */
196    if ((argc < 3)
197#ifdef WIN32 // implicit output file name possible for windows
198        && (argc < 2)
199#endif
200        ) {
201        /* print help text and exit */
202        printf("Test program for NetEQ.\n");
203        printf("The program reads an RTP stream from file and inserts it into NetEQ.\n");
204        printf("The format of the RTP stream file should be the same as for rtpplay,\n");
205        printf("and can be obtained e.g., from Ethereal by using\n");
206        printf("Statistics -> RTP -> Show All Streams -> [select a stream] -> Save As\n\n");
207        printf("Usage:\n\n");
208#ifdef WIN32
209        printf("%s RTPfile [outfile] [-options]\n", argv[0]);
210#else
211        printf("%s RTPfile outfile [-options]\n", argv[0]);
212#endif
213        printf("where:\n");
214
215        printf("RTPfile      : RTP stream input file\n\n");
216
217        printf("outfile      : PCM speech output file\n");
218        printf("               Output file name is derived from RTP file name if omitted\n\n");
219
220        printf("-options are optional switches:\n");
221        printf("\t-recout datfile        : supply recout times\n");
222        printf("\t-extradelay datfile    : supply extra delay settings and timing\n");
223        printf("\t-streaming             : engage streaming mode\n");
224        printf("\t-fax                   : engage fax mode\n");
225        printf("\t-preparsertp           : use RecIn with pre-parsed RTP\n");
226        printf("\t-rtponly packLenBytes  : input file consists of constant size RTP packets without RTPplay headers\n");
227        printf("\t-dummyrtp              : input file contains only RTP headers\n");
228        printf("\t-nodecode              : no decoding will be done\n");
229        printf("\t-ssrc 0xNNNNNNNN       : discard all other SSRCs\n");
230        //printf("\t-switchms              : switch from mono to stereo (copy channel) after 10 seconds\n");
231        //printf("\t-duplicate             : use two instances with identical input (2-channel mono)\n");
232
233        return(0);
234    }
235
236    if (strcmp(argv[1], "-apitest")==0) {
237        // do API test and then return
238        ok=doAPItest();
239
240        if (ok==0)
241            printf("API test successful!\n");
242        else
243            printf("API test failed!\n");
244
245        return(ok);
246    }
247
248    FILE* in_file=fopen(argv[1],"rb");
249    CHECK_NOT_NULL(in_file);
250    printf("Input file: %s\n",argv[1]);
251
252    int argIx = 2; // index of next argument from command line
253
254    if ( argc >= 3 && argv[2][0] != '-' ) { // output name given on command line
255        strcpy(outfilename, argv[2]);
256        argIx++;
257    } else { // derive output name from input name
258#ifdef WIN32
259        _splitpath(argv[1],outdrive,outpath,outfile,outext);
260        _makepath(outfilename,outdrive,outpath,outfile,"pcm");
261#else
262        fprintf(stderr,"Output file name must be specified.\n");
263        return(-1);
264#endif
265    }
266    FILE* out_file=fopen(outfilename,"wb");
267    if (out_file==NULL) {
268        fprintf(stderr,"Could not open file %s for writing\n", outfilename);
269        return(-1);
270    }
271    printf("Output file: %s\n",outfilename);
272
273    // Parse for more arguments, all beginning with '-'
274    while( argIx < argc ) {
275        if (argv[argIx][0] != '-') {
276            fprintf(stderr,"Unknown input argument %s\n", argv[argIx]);
277            return(-1);
278        }
279
280        if( strcmp(argv[argIx], "-recout") == 0 ) {
281            argIx++;
282            recoutTimes = fopen(argv[argIx], "rb");
283            CHECK_NOT_NULL(recoutTimes);
284            argIx++;
285        }
286        else if( strcmp(argv[argIx], "-extradelay") == 0 ) {
287            argIx++;
288            extraDelays = fopen(argv[argIx], "rb");
289            CHECK_NOT_NULL(extraDelays);
290            argIx++;
291        }
292        else if( strcmp(argv[argIx], "-streaming") == 0 ) {
293            argIx++;
294            streamingMode = kPlayoutStreaming;
295        }
296        else if( strcmp(argv[argIx], "-fax") == 0 ) {
297            argIx++;
298            streamingMode = kPlayoutFax;
299        }
300        else if( strcmp(argv[argIx], "-preparsertp") == 0 ) {
301            argIx++;
302            preParseRTP = true;
303        }
304        else if( strcmp(argv[argIx], "-rtponly") == 0 ) {
305            argIx++;
306            rtpOnly = true;
307            packetLen = atoi(argv[argIx]);
308            argIx++;
309            if (packetLen <= 0)
310            {
311                printf("Wrong packet size used with argument -rtponly.\n");
312                exit(1);
313            }
314        }
315        else if (strcmp(argv[argIx], "-dummyrtp") == 0
316            || strcmp(argv[argIx], "-dummy") == 0)
317        {
318            argIx++;
319            dummyRtp = true;
320            noDecode = true; // force noDecode since there are no payloads
321        }
322        else if (strcmp(argv[argIx], "-nodecode") == 0)
323        {
324            argIx++;
325            noDecode = true;
326        }
327        else if (strcmp(argv[argIx], "-ssrc") == 0)
328        {
329            argIx++;
330            filterSSRC = true;
331            if (sscanf(argv[argIx], "%X", &ssrc) != 1)
332            {
333                printf("Could not read SSRC argument.\n");
334                exit(1);
335            }
336            argIx++;
337        }
338        //else if( strcmp(argv[argIx], "-switchms") == 0 ) {
339        //    argIx++;
340        //    switchMS = true;
341        //}
342        //else if( strcmp(argv[argIx], "-duplicate") == 0 ) {
343        //    argIx++;
344        //    duplicatePayload = true;
345        //}
346        else {
347            fprintf(stderr,"Unknown input argument %s\n", argv[argIx]);
348            return(-1);
349        }
350    }
351
352
353
354#ifdef NETEQ_DELAY_LOGGING
355    char delayfile[MY_MAX_PATH];
356#ifdef WIN32
357    _splitpath(outfilename,outdrive,outpath,outfile,outext);
358    _makepath(delayfile,outdrive,outpath,outfile,"d");
359#else
360    sprintf(delayfile, "%s.d", outfilename);
361#endif
362    delay_fid2 = fopen(delayfile,"wb");
363    fprintf(delay_fid2, "#!NetEQ_Delay_Logging%s\n", NETEQ_DELAY_LOGGING_VERSION_STRING);
364#endif
365
366    char ptypesfile[MY_MAX_PATH];
367#ifdef WIN32
368    _splitpath(argv[0],outdrive,outpath,outfile,outext);
369    _makepath(ptypesfile,outdrive,outpath,"ptypes","txt");
370#elif defined(WEBRTC_ANDROID)
371  strcpy(ptypesfile, "/sdcard/ptypes.txt");
372#else
373    // TODO(hlundin): Include path to ptypes, as for WIN32 above.
374  strcpy(ptypesfile, "ptypes.txt");
375#endif
376    FILE *ptypeFile = fopen(ptypesfile,"rt");
377    if (!ptypeFile) {
378        // Check if we can find the file at the usual place in the trunk.
379        if (strstr(argv[0], "out/Debug/")) {
380            int path_len = strstr(argv[0], "out/Debug/") - argv[0];
381            strncpy(ptypesfile, argv[0], path_len);
382            ptypesfile[path_len] = '\0';
383            strcat(ptypesfile,
384                   "webrtc/modules/audio_coding/neteq/test/ptypes.txt");
385            ptypeFile = fopen(ptypesfile,"rt");
386        }
387    }
388    CHECK_NOT_NULL(ptypeFile);
389    printf("Ptypes file: %s\n\n", ptypesfile);
390
391    parsePtypeFile(ptypeFile, &decoders);
392    fclose(ptypeFile);
393
394    noOfCodecs = populateUsedCodec(&decoders, usedCodec);
395
396
397    /* read RTP file header */
398    if (!rtpOnly)
399    {
400        if (NETEQTEST_RTPpacket::skipFileHeader(in_file) != 0)
401        {
402            fprintf(stderr, "Wrong format in RTP file.\n");
403            return -1;
404        }
405    }
406
407    /* check payload type for first speech packet */
408    long tempFilePos = ftell(in_file);
409    enum stereoModes stereoMode = stereoModeMono;
410
411    NETEQTEST_RTPpacket *rtp;
412    NETEQTEST_RTPpacket *slaveRtp;
413    if (!dummyRtp)
414    {
415        rtp = new NETEQTEST_RTPpacket();
416        slaveRtp = new NETEQTEST_RTPpacket();
417    }
418    else
419    {
420        rtp = new NETEQTEST_DummyRTPpacket();
421        slaveRtp = new NETEQTEST_DummyRTPpacket();
422    }
423
424    /* Uncomment and edit the line(s) below to block some payload types. */
425    //rtp->blockPT(72);
426    //rtp->blockPT(23);
427
428    /* Select a specific SSRC. */
429    if (filterSSRC) {
430        rtp->selectSSRC(ssrc);
431    }
432
433    if (!rtpOnly)
434    {
435        while (rtp->readFromFile(in_file) >= 0)
436        {
437            if (decoders.count(rtp->payloadType()) > 0
438                && decoders[rtp->payloadType()].codec != kDecoderRED
439                && decoders[rtp->payloadType()].codec != kDecoderAVT
440                && decoders[rtp->payloadType()].codec != kDecoderCNG )
441            {
442                stereoMode = decoders[rtp->payloadType()].stereo;
443                fs = decoders[rtp->payloadType()].fs;
444                break;
445            }
446        }
447    }
448    else
449    {
450        while (rtp->readFixedFromFile(in_file, packetLen) >= 0)
451        {
452            if (decoders.count(rtp->payloadType()) > 0
453                && decoders[rtp->payloadType()].codec != kDecoderRED
454                && decoders[rtp->payloadType()].codec != kDecoderAVT
455                && decoders[rtp->payloadType()].codec != kDecoderCNG )
456            {
457                stereoMode = decoders[rtp->payloadType()].stereo;
458                fs = decoders[rtp->payloadType()].fs;
459                break;
460            }
461        }
462    }
463
464    fseek(in_file, tempFilePos, SEEK_SET /* from beginning */);
465
466    /* read first packet */
467    if (!rtpOnly)
468    {
469        rtp->readFromFile(in_file);
470    }
471    else
472    {
473        rtp->readFixedFromFile(in_file, packetLen);
474        rtp->setTime((1000 * rtp->timeStamp()) / fs);
475    }
476    if (!rtp)
477    {
478        printf("\nWarning: RTP file is empty\n\n");
479    }
480
481
482    /* Initialize NetEQ instances */
483    int numInst = 1;
484    if (stereoMode > stereoModeMono)
485    {
486        numInst = 2;
487    }
488
489    for (int i = 0; i < numInst; i++)
490    {
491        // create memory, allocate, initialize, and allocate packet buffer memory
492        NetEQvector.push_back (new NETEQTEST_NetEQClass(usedCodec, noOfCodecs, static_cast<uint16_t>(fs), kTCPLargeJitter));
493
494        createAndInsertDecoders (NetEQvector[i], &decoders, i /* channel */);
495
496        WebRtcNetEQ_SetAVTPlayout(NetEQvector[i]->instance(),1); // enable DTMF playout
497
498        WebRtcNetEQ_SetPlayoutMode(NetEQvector[i]->instance(), streamingMode);
499
500        NetEQvector[i]->usePreparseRTP(preParseRTP);
501
502        NetEQvector[i]->setNoDecode(noDecode);
503
504        if (numInst > 1)
505        {
506            // we are using master/slave mode
507            if (i == 0)
508            {
509                // first instance is master
510                NetEQvector[i]->setMaster();
511            }
512            else
513            {
514                // all other are slaves
515                NetEQvector[i]->setSlave();
516            }
517        }
518    }
519
520
521#ifdef ZERO_TS_START
522    uint32_t firstTS = rtp->timeStamp();
523    rtp->setTimeStamp(0);
524#else
525    uint32_t firstTS = 0;
526#endif
527
528    // check stereo mode
529    if (stereoMode > stereoModeMono)
530    {
531        if(rtp->splitStereo(slaveRtp, stereoMode))
532        {
533            printf("Error in splitStereo\n");
534        }
535    }
536
537#ifdef PLAY_CLEAN
538    uint32_t prevTS = rtp->timeStamp();
539    uint32_t currTS, prev_time;
540#endif
541
542#ifdef JUNK_DATA
543    unsigned int random_seed = (unsigned int) /*1196764538; */time(NULL);
544    srand(random_seed);
545
546    if ( (seedfile = fopen(SEED_FILE, "a+t") ) == NULL ) {
547        fprintf(stderr, "Error: Could not open file %s\n", SEED_FILE);
548    }
549    else {
550        fprintf(seedfile, "%u\n", random_seed);
551        fclose(seedfile);
552    }
553#endif
554
555    uint32_t nextRecoutTime;
556    int lastRecout = getNextRecoutTime(recoutTimes, &nextRecoutTime); // does nothing if recoutTimes == NULL
557
558    if (recoutTimes)
559        simClock = (rtp->time() < nextRecoutTime ? rtp->time(): nextRecoutTime);
560    else
561        simClock = rtp->time(); // start immediately with first packet
562
563    uint32_t start_clock = simClock;
564
565    uint32_t nextExtraDelayTime;
566    int extraDelay = -1;
567    getNextExtraDelay(extraDelays, &nextExtraDelayTime, &extraDelay);
568
569    void *msInfo;
570    msInfo = malloc(WebRtcNetEQ_GetMasterSlaveInfoSize());
571    if(msInfo == NULL)
572        return(-1);
573
574    while(rtp->dataLen() >= 0 || (recoutTimes && !lastRecout)) {
575//        printf("simClock = %Lu\n", simClock);
576
577#ifdef NETEQ_DELAY_LOGGING
578        temp_var = NETEQ_DELAY_LOGGING_SIGNAL_CLOCK;
579        clock_float = (float) simClock;
580        if (fwrite(&temp_var, sizeof(int), 1, delay_fid2) != 1) {
581          return -1;
582        }
583        if (fwrite(&clock_float, sizeof(float), 1, delay_fid2) != 1) {
584          return -1;
585        }
586#endif
587        /* time to set extra delay */
588        if (extraDelay > -1 && simClock >= nextExtraDelayTime) {
589            // set extra delay for all instances
590            for (int i = 0; i < numInst; i++)
591            {
592                WebRtcNetEQ_SetExtraDelay(NetEQvector[i]->instance(), extraDelay);
593            }
594            getNextExtraDelay(extraDelays, &nextExtraDelayTime, &extraDelay);
595        }
596
597        /* check if time to receive */
598        while (simClock >= rtp->time() && rtp->dataLen() >= 0)
599        {
600            if (rtp->dataLen() > 0)
601            {
602
603                // insert main packet
604                NetEQvector[0]->recIn(*rtp);
605
606                if (stereoMode > stereoModeMono
607                    && slaveRtp->dataLen() > 0)
608                {
609                    // insert slave packet
610                    NetEQvector[1]->recIn(*slaveRtp);
611                }
612
613            }
614
615            /* get next packet */
616#ifdef PLAY_CLEAN
617            prev_time = rtp->time();
618#endif
619            if (!rtpOnly)
620            {
621                rtp->readFromFile(in_file);
622            }
623            else
624            {
625                rtp->readFixedFromFile(in_file, packetLen);
626                rtp->setTime((1000 * rtp->timeStamp()) / fs);
627            }
628
629            if (rtp->dataLen() >= 0)
630            {
631                rtp->setTimeStamp(rtp->timeStamp() - firstTS);
632            }
633
634            packetCount++;
635
636            if (changeStereoMode(*rtp, decoders, &stereoMode))
637            {
638                printf("Warning: stereo mode changed\n");
639            }
640
641            if (stereoMode > stereoModeMono)
642            {
643                if(rtp->splitStereo(slaveRtp, stereoMode))
644                {
645                    printf("Error in splitStereo\n");
646                }
647            }
648
649#ifdef PLAY_CLEAN
650            currTS = rtp->timeStamp();
651            rtp->setTime(prev_time + (currTS-prevTS)/(fs/1000));
652            prevTS = currTS;
653#endif
654        }
655
656        /* check if time to RecOut */
657        if ( (!recoutTimes && (simClock%10)==0) // recout times not given from file
658        || ( recoutTimes && (simClock >= nextRecoutTime) ) ) // recout times given from file
659        {
660            if (stereoMode > stereoModeMono)
661            {
662                // stereo
663                int16_t tempLen;
664                tempLen = NetEQvector[0]->recOut( out_data, msInfo ); // master
665                outLen = NetEQvector[1]->recOut( &out_data[tempLen], msInfo ); // slave
666
667                assert(tempLen == outLen);
668
669                writeLen = outLen * 2;
670                stereoInterleave(out_data, writeLen);
671            }
672            else
673            {
674                // mono
675                outLen = NetEQvector[0]->recOut( out_data );
676                writeLen = outLen;
677            }
678
679            // write to file
680            if (fwrite(out_data, writeLen, 2, out_file) != 2) {
681              return -1;
682            }
683            writtenSamples += writeLen;
684
685
686            lastRecout = getNextRecoutTime(recoutTimes, &nextRecoutTime); // does nothing if recoutTimes == NULL
687
688            /* ask for statistics */
689            WebRtcNetEQ_NetworkStatistics inCallStats;
690            WebRtcNetEQ_GetNetworkStatistics(NetEQvector[0]->instance(), &inCallStats);
691
692        }
693
694        /* increase time */
695        simClock+=TIME_STEP;
696    }
697
698    fclose(in_file);
699    fclose(out_file);
700
701#ifdef NETEQ_DELAY_LOGGING
702    temp_var = NETEQ_DELAY_LOGGING_SIGNAL_EOF;
703    if (fwrite(&temp_var, sizeof(int), 1, delay_fid2) != 1) {
704      return -1;
705    }
706    if (fwrite(&tot_received_packets, sizeof(uint32_t),
707               1, delay_fid2) != 1) {
708      return -1;
709    }
710    fprintf(delay_fid2,"End of file\n");
711    fclose(delay_fid2);
712#endif
713
714    WebRtcNetEQ_GetRTCPStats(NetEQvector[0]->instance(), &RTCPstat);
715    printf("RTCP statistics:\n");
716    printf("    cum_lost        : %d\n", (int) RTCPstat.cum_lost);
717    printf("    ext_max         : %d\n", (int) RTCPstat.ext_max);
718    printf("    fraction_lost   : %d (%f%%)\n", RTCPstat.fraction_lost, (float)(100.0*RTCPstat.fraction_lost/256.0));
719    printf("    jitter          : %d\n", (int) RTCPstat.jitter);
720
721    printf("\n    Call duration ms    : %u\n", simClock-start_clock);
722
723    printf("\nComplexity estimates (including sub-components):\n");
724    printf("    RecIn complexity    : %.2f MCPS\n", NetEQvector[0]->getRecInTime() / ((float) 1000*(simClock-start_clock)));
725    printf("    RecOut complexity   : %.2f MCPS\n", NetEQvector[0]->getRecOutTime() / ((float) 1000*(simClock-start_clock)));
726
727    free_coders(decoders);
728    //free_coders(0 /* first channel */);
729 //   if (stereoMode > stereoModeMono) {
730 //       free_coders(1 /* second channel */);
731 //   }
732    free(msInfo);
733
734    for (std::vector<NETEQTEST_NetEQClass *>::iterator it = NetEQvector.begin();
735        it < NetEQvector.end(); delete *it++) {
736    }
737
738    printf("\nSimulation done!\n");
739
740#ifdef JUNK_DATA
741    if ( (seedfile = fopen(SEED_FILE, "a+t") ) == NULL ) {
742        fprintf(stderr, "Error: Could not open file %s\n", SEED_FILE);
743    }
744    else {
745        fprintf(seedfile, "ok\n\n");
746        fclose(seedfile);
747    }
748#endif
749
750
751    // Log complexity to file
752/*    FILE *statfile;
753    statfile = fopen("complexity.txt","at");
754    fprintf(statfile,"%.4f, %.4f\n", (float) totTime_RecIn.QuadPart / ((float) 1000*(simClock-start_clock)), (float) totTime_RecOut.QuadPart / ((float) 1000*(simClock-start_clock)));
755    fclose(statfile);*/
756
757    return(0);
758
759}
760
761
762
763
764
765/****************/
766/* Subfunctions */
767/****************/
768
769bool splitStereo(NETEQTEST_RTPpacket* rtp, NETEQTEST_RTPpacket* rtpSlave,
770                 const int16_t *stereoPtype, const enum stereoModes *stereoMode, int noOfStereoCodecs,
771                 const int16_t *cngPtype, int noOfCngCodecs,
772                 bool *isStereo)
773{
774
775    // init
776    //bool isStereo = false;
777    enum stereoModes tempStereoMode = stereoModeMono;
778    bool isCng = false;
779
780    // check payload length
781    if (rtp->dataLen() <= 0) {
782        //*isStereo = false; // don't change
783        return(*isStereo);
784    }
785
786    // check payload type
787    int16_t ptype = rtp->payloadType();
788
789    // is this a cng payload?
790    for (int k = 0; k < noOfCngCodecs; k++) {
791        if (ptype == cngPtype[k]) {
792            // do not change stereo state
793            isCng = true;
794            tempStereoMode = stereoModeFrame;
795        }
796    }
797
798    if (!isCng)
799    {
800        *isStereo = false;
801
802        // is this payload type a stereo codec? which type?
803        for (int k = 0; k < noOfStereoCodecs; k++) {
804            if (ptype == stereoPtype[k]) {
805                tempStereoMode = stereoMode[k];
806                *isStereo = true;
807                break; // exit for loop
808            }
809        }
810    }
811
812    if (*isStereo)
813    {
814        // split the payload if stereo
815
816        if(rtp->splitStereo(rtpSlave, tempStereoMode))
817        {
818            printf("Error in splitStereo\n");
819        }
820
821    }
822
823    return(*isStereo);
824
825}
826
827void stereoInterleave(int16_t *data, int16_t totalLen)
828{
829    int k;
830
831    for(k = totalLen/2; k < totalLen; k++) {
832        int16_t temp = data[k];
833        memmove(&data[2*k - totalLen + 2], &data[2*k - totalLen + 1], (totalLen - k -1) *  sizeof(int16_t));
834        data[2*k - totalLen + 1] = temp;
835    }
836}
837
838
839int getNextRecoutTime(FILE *fp, uint32_t *nextTime) {
840
841    float tempTime;
842
843    if (!fp) {
844        return -1;
845    }
846
847    if (fread(&tempTime, sizeof(float), 1, fp) != 0) {
848        // not end of file
849        *nextTime = (uint32_t) tempTime;
850        return 0;
851    }
852
853    *nextTime = 0;
854    fclose(fp);
855
856    return 1;
857}
858
859void getNextExtraDelay(FILE *fp, uint32_t *t, int *d) {
860
861    float temp[2];
862
863    if(!fp) {
864        *d = -1;
865        return;
866    }
867
868    if (fread(&temp, sizeof(float), 2, fp) != 0) {
869        // not end of file
870        *t = (uint32_t) temp[0];
871        *d = (int) temp[1];
872        return;
873    }
874
875    *d = -1;
876    fclose(fp);
877
878    return;
879}
880
881
882void parsePtypeFile(FILE *ptypeFile, std::map<uint8_t, decoderStruct>* decoders)
883{
884    int n, pt;
885    char codec[100];
886    decoderStruct tempDecoder;
887
888    // read first line
889    n = fscanf(ptypeFile, "%s %i\n", codec, &pt);
890
891    while (n==2)
892    {
893        memset(&tempDecoder, 0, sizeof(decoderStruct));
894        tempDecoder.stereo = stereoModeMono;
895
896        if( pt >= 0  // < 0 disables this codec
897            && isalpha(codec[0]) ) // and is a letter
898        {
899
900            /* check for stereo */
901            int L = strlen(codec);
902            bool isStereo = false;
903
904            if (codec[L-1] == '*') {
905                // stereo codec
906                isStereo = true;
907
908                // remove '*'
909                codec[L-1] = '\0';
910            }
911
912#ifdef CODEC_G711
913            if(strcmp(codec, "pcmu") == 0) {
914                tempDecoder.codec = kDecoderPCMu;
915                tempDecoder.fs = 8000;
916            }
917            else if(strcmp(codec, "pcma") == 0) {
918                tempDecoder.codec = kDecoderPCMa;
919                tempDecoder.fs = 8000;
920            }
921#endif
922#ifdef CODEC_IPCMU
923            else if(strcmp(codec, "eg711u") == 0) {
924                tempDecoder.codec = kDecoderEG711u;
925                tempDecoder.fs = 8000;
926            }
927#endif
928#ifdef CODEC_IPCMA
929            else if(strcmp(codec, "eg711a") == 0) {
930                tempDecoder.codec = kDecoderEG711a;
931                tempDecoder.fs = 8000;
932            }
933#endif
934#ifdef CODEC_ILBC
935            else if(strcmp(codec, "ilbc") == 0) {
936                tempDecoder.codec = kDecoderILBC;
937                tempDecoder.fs = 8000;
938            }
939#endif
940#ifdef CODEC_ISAC
941            else if(strcmp(codec, "isac") == 0) {
942                tempDecoder.codec = kDecoderISAC;
943                tempDecoder.fs = 16000;
944            }
945#endif
946#ifdef CODEC_ISACLC
947            else if(strcmp(codec, "isaclc") == 0) {
948                tempDecoder.codec = NETEQ_CODEC_ISACLC;
949                tempDecoder.fs = 16000;
950            }
951#endif
952#ifdef CODEC_ISAC_SWB
953            else if(strcmp(codec, "isacswb") == 0) {
954                tempDecoder.codec = kDecoderISACswb;
955                tempDecoder.fs = 32000;
956            }
957#endif
958#ifdef CODEC_ISAC_FB
959            else if(strcmp(codec, "isacfb") == 0) {
960                tempDecoder.codec = kDecoderISACfb;
961                tempDecoder.fs = 32000;
962            }
963#endif
964#ifdef CODEC_IPCMWB
965            else if(strcmp(codec, "ipcmwb") == 0) {
966                tempDecoder.codec = kDecoderIPCMwb;
967                tempDecoder.fs = 16000;
968            }
969#endif
970#ifdef CODEC_G722
971            else if(strcmp(codec, "g722") == 0) {
972                tempDecoder.codec = kDecoderG722;
973                tempDecoder.fs = 16000;
974            }
975#endif
976#ifdef CODEC_G722_1_16
977            else if(strcmp(codec, "g722_1_16") == 0) {
978                tempDecoder.codec = kDecoderG722_1_16;
979                tempDecoder.fs = 16000;
980            }
981#endif
982#ifdef CODEC_G722_1_24
983            else if(strcmp(codec, "g722_1_24") == 0) {
984                tempDecoder.codec = kDecoderG722_1_24;
985                tempDecoder.fs = 16000;
986            }
987#endif
988#ifdef CODEC_G722_1_32
989            else if(strcmp(codec, "g722_1_32") == 0) {
990                tempDecoder.codec = kDecoderG722_1_32;
991                tempDecoder.fs = 16000;
992            }
993#endif
994#ifdef CODEC_G722_1C_24
995            else if(strcmp(codec, "g722_1c_24") == 0) {
996                tempDecoder.codec = kDecoderG722_1C_24;
997                tempDecoder.fs = 32000;
998            }
999#endif
1000#ifdef CODEC_G722_1C_32
1001            else if(strcmp(codec, "g722_1c_32") == 0) {
1002                tempDecoder.codec = kDecoderG722_1C_32;
1003                tempDecoder.fs = 32000;
1004            }
1005#endif
1006#ifdef CODEC_G722_1C_48
1007            else if(strcmp(codec, "g722_1c_48") == 0) {
1008                tempDecoder.codec = kDecoderG722_1C_48;
1009                tempDecoder.fs = 32000;
1010            }
1011#endif
1012#ifdef CODEC_G723
1013            else if(strcmp(codec, "g723") == 0) {
1014                tempDecoder.codec = NETEQ_CODEC_G723;
1015                tempDecoder.fs = 8000;
1016            }
1017#endif
1018#ifdef CODEC_G726
1019            else if(strcmp(codec, "g726_16") == 0) {
1020                tempDecoder.codec = kDecoderG726_16;
1021                tempDecoder.fs = 8000;
1022            }
1023            else if(strcmp(codec, "g726_24") == 0) {
1024                tempDecoder.codec = kDecoderG726_24;
1025                tempDecoder.fs = 8000;
1026            }
1027            else if(strcmp(codec, "g726_32") == 0) {
1028                tempDecoder.codec = kDecoderG726_32;
1029                tempDecoder.fs = 8000;
1030            }
1031            else if(strcmp(codec, "g726_40") == 0) {
1032                tempDecoder.codec = kDecoderG726_40;
1033                tempDecoder.fs = 8000;
1034            }
1035#endif
1036#ifdef CODEC_G729
1037            else if(strcmp(codec, "g729") == 0) {
1038                tempDecoder.codec = kDecoderG729;
1039                tempDecoder.fs = 8000;
1040            }
1041#endif
1042#ifdef CODEC_G729D
1043            else if(strcmp(codec, "g729d") == 0) {
1044                tempDecoder.codec = NETEQ_CODEC_G729D;
1045                tempDecoder.fs = 8000;
1046            }
1047#endif
1048#ifdef CODEC_G729_1
1049            else if(strcmp(codec, "g729_1") == 0) {
1050                tempDecoder.codec = kDecoderG729_1;
1051                tempDecoder.fs = 16000;
1052            }
1053#endif
1054#ifdef CODEC_GSMFR
1055            else if(strcmp(codec, "gsmfr") == 0) {
1056                tempDecoder.codec = kDecoderGSMFR;
1057                tempDecoder.fs = 8000;
1058            }
1059#endif
1060#ifdef CODEC_GSMEFR
1061            else if(strcmp(codec, "gsmefr") == 0) {
1062                tempDecoder.codec = NETEQ_CODEC_GSMEFR;
1063                tempDecoder.fs = 8000;
1064            }
1065#endif
1066#ifdef CODEC_AMR
1067            else if(strcmp(codec, "amr") == 0) {
1068                tempDecoder.codec = kDecoderAMR;
1069                tempDecoder.fs = 8000;
1070            }
1071#endif
1072#ifdef CODEC_AMRWB
1073            else if(strcmp(codec, "amrwb") == 0) {
1074                tempDecoder.codec = kDecoderAMRWB;
1075                tempDecoder.fs = 16000;
1076            }
1077#endif
1078#ifdef CODEC_DVI4
1079            else if(strcmp(codec, "dvi4") == 0) {
1080                tempDecoder.codec = NETEQ_CODEC_DVI4;
1081                tempDecoder.fs = 8000;
1082            }
1083#endif
1084#ifdef CODEC_SPEEX_8
1085            else if(strcmp(codec, "speex8") == 0) {
1086                tempDecoder.codec = kDecoderSPEEX_8;
1087                tempDecoder.fs = 8000;
1088            }
1089#endif
1090#ifdef CODEC_SPEEX_16
1091            else if(strcmp(codec, "speex16") == 0) {
1092                tempDecoder.codec = kDecoderSPEEX_16;
1093                tempDecoder.fs = 16000;
1094            }
1095#endif
1096#ifdef CODEC_CELT_32
1097            else if(strcmp(codec, "celt32") == 0) {
1098                tempDecoder.codec = kDecoderCELT_32;
1099                tempDecoder.fs = 32000;
1100            }
1101#endif
1102#ifdef CODEC_SILK_NB
1103            else if(strcmp(codec, "silk8") == 0) {
1104                tempDecoder.codec = NETEQ_CODEC_SILK_8;
1105                tempDecoder.fs = 8000;
1106            }
1107#endif
1108#ifdef CODEC_SILK_WB
1109            else if(strcmp(codec, "silk12") == 0) {
1110                tempDecoder.codec = NETEQ_CODEC_SILK_12;
1111                tempDecoder.fs = 16000;
1112            }
1113            else if(strcmp(codec, "silk16") == 0) {
1114                tempDecoder.codec = NETEQ_CODEC_SILK_16;
1115                tempDecoder.fs = 16000;
1116            }
1117#endif
1118#ifdef CODEC_SILK_SWB
1119            else if(strcmp(codec, "silk24") == 0) {
1120                tempDecoder.codec = NETEQ_CODEC_SILK_24;
1121                tempDecoder.fs = 32000;
1122            }
1123#endif
1124#ifdef CODEC_MELPE
1125            else if(strcmp(codec, "melpe") == 0) {
1126                tempDecoder.codec = NETEQ_CODEC_MELPE;
1127                tempDecoder.fs = 8000;
1128            }
1129#endif
1130#ifdef CODEC_PCM16B
1131            else if(strcmp(codec, "pcm16b") == 0) {
1132                tempDecoder.codec = kDecoderPCM16B;
1133                tempDecoder.fs = 8000;
1134            }
1135#endif
1136#ifdef CODEC_PCM16B_WB
1137            else if(strcmp(codec, "pcm16b_wb") == 0) {
1138                tempDecoder.codec = kDecoderPCM16Bwb;
1139                tempDecoder.fs = 16000;
1140            }
1141#endif
1142#ifdef CODEC_PCM16B_32KHZ
1143            else if(strcmp(codec, "pcm16b_swb32khz") == 0) {
1144                tempDecoder.codec = kDecoderPCM16Bswb32kHz;
1145                tempDecoder.fs = 32000;
1146            }
1147#endif
1148#ifdef CODEC_PCM16B_48KHZ
1149            else if(strcmp(codec, "pcm16b_swb48khz") == 0) {
1150                tempDecoder.codec = kDecoderPCM16Bswb48kHz;
1151                tempDecoder.fs = 48000;
1152            }
1153#endif
1154#ifdef CODEC_CNGCODEC8
1155            else if(strcmp(codec, "cn") == 0) {
1156                tempDecoder.codec = kDecoderCNG;
1157                tempDecoder.fs = 8000;
1158            }
1159#endif
1160#ifdef CODEC_CNGCODEC16
1161            else if(strcmp(codec, "cn_wb") == 0) {
1162                tempDecoder.codec = kDecoderCNG;
1163                tempDecoder.fs = 16000;
1164            }
1165#endif
1166#ifdef CODEC_CNGCODEC32
1167            else if(strcmp(codec, "cn_swb32") == 0) {
1168                tempDecoder.codec = kDecoderCNG;
1169                tempDecoder.fs = 32000;
1170            }
1171#endif
1172#ifdef CODEC_CNGCODEC48
1173            else if(strcmp(codec, "cn_swb48") == 0) {
1174                tempDecoder.codec = kDecoderCNG;
1175                tempDecoder.fs = 48000;
1176            }
1177#endif
1178#ifdef CODEC_ATEVENT_DECODE
1179            else if(strcmp(codec, "avt") == 0) {
1180                tempDecoder.codec = kDecoderAVT;
1181                tempDecoder.fs = 8000;
1182            }
1183#endif
1184#ifdef CODEC_RED
1185            else if(strcmp(codec, "red") == 0) {
1186                tempDecoder.codec = kDecoderRED;
1187                tempDecoder.fs = 8000;
1188            }
1189#endif
1190            else if(isalpha(codec[0])) {
1191                printf("Unsupported codec %s\n", codec);
1192                // read next line and continue while loop
1193                n = fscanf(ptypeFile, "%s %i\n", codec, &pt);
1194                continue;
1195            }
1196            else {
1197                // name is not recognized, and does not start with a letter
1198                // hence, it is commented out
1199                // read next line and continue while loop
1200                n = fscanf(ptypeFile, "%s %i\n", codec, &pt);
1201                continue;
1202            }
1203
1204            // handle stereo
1205            if (tempDecoder.codec == kDecoderCNG)
1206            {
1207                // always set stereo mode for CNG, even if it is not marked at stereo
1208                tempDecoder.stereo = stereoModeFrame;
1209            }
1210            else if(isStereo)
1211            {
1212                switch(tempDecoder.codec) {
1213                    // sample based codecs
1214                    case kDecoderPCMu:
1215                    case kDecoderPCMa:
1216                    case kDecoderG722:
1217                        {
1218                            // 1 octet per sample
1219                            tempDecoder.stereo = stereoModeSample1;
1220                            break;
1221                        }
1222                    case kDecoderPCM16B:
1223                    case kDecoderPCM16Bwb:
1224                    case kDecoderPCM16Bswb32kHz:
1225                    case kDecoderPCM16Bswb48kHz:
1226                        {
1227                            // 2 octets per sample
1228                            tempDecoder.stereo = stereoModeSample2;
1229                            break;
1230                        }
1231
1232                    case kDecoderCELT_32:
1233                    {
1234                      tempDecoder.stereo = stereoModeDuplicate;
1235                      break;
1236                    }
1237                        // fixed-rate frame codecs
1238//                    case kDecoderG729:
1239//                    case NETEQ_CODEC_G729D:
1240//                    case NETEQ_CODEC_G729E:
1241//                    case kDecoderG722_1_16:
1242//                    case kDecoderG722_1_24:
1243//                    case kDecoderG722_1_32:
1244//                    case kDecoderG722_1C_24:
1245//                    case kDecoderG722_1C_32:
1246//                    case kDecoderG722_1C_48:
1247//                    case NETEQ_CODEC_MELPE:
1248//                        {
1249//                            tempDecoder.stereo = stereoModeFrame;
1250//                            break;
1251//                        }
1252                    default:
1253                        {
1254                            printf("Cannot use codec %s as stereo codec\n", codec);
1255                            exit(0);
1256                        }
1257                }
1258            }
1259
1260            if (pt > 127)
1261            {
1262                printf("Payload type must be less than 128\n");
1263                exit(0);
1264            }
1265
1266            // insert into codecs map
1267            (*decoders)[static_cast<uint8_t>(pt)] = tempDecoder;
1268
1269        }
1270
1271        n = fscanf(ptypeFile, "%s %i\n", codec, &pt);
1272    }  // end while
1273
1274}
1275
1276
1277bool changeStereoMode(NETEQTEST_RTPpacket & rtp, std::map<uint8_t, decoderStruct> & decoders, enum stereoModes *stereoMode)
1278{
1279        if (decoders.count(rtp.payloadType()) > 0
1280            && decoders[rtp.payloadType()].codec != kDecoderRED
1281            && decoders[rtp.payloadType()].codec != kDecoderAVT
1282            && decoders[rtp.payloadType()].codec != kDecoderCNG )
1283        {
1284            if (decoders[rtp.payloadType()].stereo != *stereoMode)
1285            {
1286                *stereoMode = decoders[rtp.payloadType()].stereo;
1287                return true; // stereo mode did change
1288            }
1289        }
1290
1291        return false; // stereo mode did not change
1292}
1293
1294
1295int populateUsedCodec(std::map<uint8_t, decoderStruct>* decoders, enum WebRtcNetEQDecoder *usedCodec)
1296{
1297    int numCodecs = 0;
1298
1299    std::map<uint8_t, decoderStruct>::iterator it;
1300
1301    it = decoders->begin();
1302
1303    for (int i = 0; i < static_cast<int>(decoders->size()); i++, it++)
1304    {
1305        usedCodec[numCodecs] = (*it).second.codec;
1306        numCodecs++;
1307    }
1308
1309    return numCodecs;
1310}
1311
1312
1313void createAndInsertDecoders (NETEQTEST_NetEQClass *neteq, std::map<uint8_t, decoderStruct>* decoders, int channelNumber)
1314{
1315    std::map<uint8_t, decoderStruct>::iterator it;
1316
1317    for (it = decoders->begin(); it != decoders->end();  it++)
1318    {
1319        if (channelNumber == 0 ||
1320            ((*it).second.stereo > stereoModeMono ))
1321        {
1322            // create decoder instance
1323            uint8_t pt = static_cast<uint8_t>( (*it).first );
1324            NETEQTEST_Decoder **dec = &((*it).second.decoder[channelNumber]);
1325            enum WebRtcNetEQDecoder type = (*it).second.codec;
1326
1327            switch (type)
1328            {
1329#ifdef CODEC_G711
1330            case kDecoderPCMu:
1331                *dec = new decoder_PCMU( pt );
1332                break;
1333            case kDecoderPCMa:
1334                *dec = new decoder_PCMA( pt );
1335                break;
1336#endif
1337#ifdef CODEC_IPCMU
1338            case kDecoderEG711u:
1339                *dec = new decoder_IPCMU( pt );
1340                break;
1341#endif
1342#ifdef CODEC_IPCMA
1343            case kDecoderEG711a:
1344                *dec = new decoder_IPCMA( pt );
1345                break;
1346#endif
1347#ifdef CODEC_IPCMWB
1348            case kDecoderIPCMwb:
1349                *dec = new decoder_IPCMWB( pt );
1350                break;
1351#endif
1352#ifdef CODEC_ILBC
1353            case kDecoderILBC:
1354                *dec = new decoder_ILBC( pt );
1355                break;
1356#endif
1357#ifdef CODEC_ISAC
1358            case kDecoderISAC:
1359                *dec = new decoder_iSAC( pt );
1360                break;
1361#endif
1362#ifdef CODEC_ISAC_SWB
1363            case kDecoderISACswb:
1364                *dec = new decoder_iSACSWB( pt );
1365                break;
1366#endif
1367#ifdef CODEC_ISAC_FB
1368            case kDecoderISACfb:
1369                *dec = new decoder_iSACFB(pt);
1370                break;
1371#endif
1372#ifdef CODEC_G729
1373            case kDecoderG729:
1374                *dec = new decoder_G729( pt );
1375                break;
1376            case NETEQ_CODEC_G729D:
1377                printf("Error: G729D not supported\n");
1378                break;
1379#endif
1380#ifdef CODEC_G729E
1381            case NETEQ_CODEC_G729E:
1382                *dec = new decoder_G729E( pt );
1383                break;
1384#endif
1385#ifdef CODEC_G729_1
1386            case kDecoderG729_1:
1387                *dec = new decoder_G729_1( pt );
1388                break;
1389#endif
1390#ifdef CODEC_G723
1391            case NETEQ_CODEC_G723:
1392                *dec = new decoder_G723( pt );
1393                break;
1394#endif
1395#ifdef CODEC_PCM16B
1396            case kDecoderPCM16B:
1397                *dec = new decoder_PCM16B_NB( pt );
1398                break;
1399#endif
1400#ifdef CODEC_PCM16B_WB
1401            case kDecoderPCM16Bwb:
1402                *dec = new decoder_PCM16B_WB( pt );
1403                break;
1404#endif
1405#ifdef CODEC_PCM16B_32KHZ
1406            case kDecoderPCM16Bswb32kHz:
1407                *dec = new decoder_PCM16B_SWB32( pt );
1408                break;
1409#endif
1410#ifdef CODEC_PCM16B_48KHZ
1411            case kDecoderPCM16Bswb48kHz:
1412                *dec = new decoder_PCM16B_SWB48( pt );
1413                break;
1414#endif
1415#ifdef CODEC_DVI4
1416            case NETEQ_CODEC_DVI4:
1417                *dec = new decoder_DVI4( pt );
1418                break;
1419#endif
1420#ifdef CODEC_G722
1421            case kDecoderG722:
1422                *dec = new decoder_G722( pt );
1423                break;
1424#endif
1425#ifdef CODEC_G722_1_16
1426            case kDecoderG722_1_16:
1427                *dec = new decoder_G722_1_16( pt );
1428                break;
1429#endif
1430#ifdef CODEC_G722_1_24
1431            case kDecoderG722_1_24:
1432                *dec = new decoder_G722_1_24( pt );
1433                break;
1434#endif
1435#ifdef CODEC_G722_1_32
1436            case kDecoderG722_1_32:
1437                *dec = new decoder_G722_1_32( pt );
1438                break;
1439#endif
1440#ifdef CODEC_G722_1C_24
1441            case kDecoderG722_1C_24:
1442                *dec = new decoder_G722_1C_24( pt );
1443                break;
1444#endif
1445#ifdef CODEC_G722_1C_32
1446            case kDecoderG722_1C_32:
1447                *dec = new decoder_G722_1C_32( pt );
1448                break;
1449#endif
1450#ifdef CODEC_G722_1C_48
1451            case kDecoderG722_1C_48:
1452                *dec = new decoder_G722_1C_48( pt );
1453                break;
1454#endif
1455#ifdef CODEC_AMR
1456            case kDecoderAMR:
1457                *dec = new decoder_AMR( pt );
1458                break;
1459#endif
1460#ifdef CODEC_AMRWB
1461            case kDecoderAMRWB:
1462                *dec = new decoder_AMRWB( pt );
1463                break;
1464#endif
1465#ifdef CODEC_GSMFR
1466            case kDecoderGSMFR:
1467                *dec = new decoder_GSMFR( pt );
1468                break;
1469#endif
1470#ifdef CODEC_GSMEFR
1471            case NETEQ_CODEC_GSMEFR:
1472                *dec = new decoder_GSMEFR( pt );
1473                break;
1474#endif
1475#ifdef CODEC_G726
1476            case kDecoderG726_16:
1477                *dec = new decoder_G726_16( pt );
1478                break;
1479            case kDecoderG726_24:
1480                *dec = new decoder_G726_24( pt );
1481                break;
1482            case kDecoderG726_32:
1483                *dec = new decoder_G726_32( pt );
1484                break;
1485            case kDecoderG726_40:
1486                *dec = new decoder_G726_40( pt );
1487                break;
1488#endif
1489#ifdef CODEC_MELPE
1490            case NETEQ_CODEC_MELPE:
1491#if (_MSC_VER >= 1400) && !defined(_WIN64) // only for Visual 2005 or later, and not for x64
1492                *dec = new decoder_MELPE( pt );
1493#endif
1494                break;
1495#endif
1496#ifdef CODEC_SPEEX_8
1497            case kDecoderSPEEX_8:
1498                *dec = new decoder_SPEEX( pt, 8000 );
1499                break;
1500#endif
1501#ifdef CODEC_SPEEX_16
1502            case kDecoderSPEEX_16:
1503                *dec = new decoder_SPEEX( pt, 16000 );
1504                break;
1505#endif
1506#ifdef CODEC_CELT_32
1507            case kDecoderCELT_32:
1508              if (channelNumber == 0)
1509                *dec = new decoder_CELT( pt, 32000 );
1510              else
1511                *dec = new decoder_CELTslave( pt, 32000 );
1512                break;
1513#endif
1514#ifdef CODEC_RED
1515            case kDecoderRED:
1516                *dec = new decoder_RED( pt );
1517                break;
1518#endif
1519#ifdef CODEC_ATEVENT_DECODE
1520            case kDecoderAVT:
1521                *dec = new decoder_AVT( pt );
1522                break;
1523#endif
1524#if (defined(CODEC_CNGCODEC8) || defined(CODEC_CNGCODEC16) || \
1525    defined(CODEC_CNGCODEC32) || defined(CODEC_CNGCODEC48))
1526            case kDecoderCNG:
1527                *dec = new decoder_CNG( pt, static_cast<uint16_t>((*it).second.fs) );
1528                break;
1529#endif
1530#ifdef CODEC_ISACLC
1531            case NETEQ_CODEC_ISACLC:
1532                *dec = new decoder_iSACLC( pt );
1533                break;
1534#endif
1535#ifdef CODEC_SILK_NB
1536            case NETEQ_CODEC_SILK_8:
1537#if (_MSC_VER >= 1400) && !defined(_WIN64) // only for Visual 2005 or later, and not for x64
1538                *dec = new decoder_SILK8( pt );
1539#endif
1540                break;
1541#endif
1542#ifdef CODEC_SILK_WB
1543            case NETEQ_CODEC_SILK_12:
1544#if (_MSC_VER >= 1400) && !defined(_WIN64) // only for Visual 2005 or later, and not for x64
1545                *dec = new decoder_SILK12( pt );
1546#endif
1547                break;
1548#endif
1549#ifdef CODEC_SILK_WB
1550            case NETEQ_CODEC_SILK_16:
1551#if (_MSC_VER >= 1400) && !defined(_WIN64) // only for Visual 2005 or later, and not for x64
1552                *dec = new decoder_SILK16( pt );
1553#endif
1554                break;
1555#endif
1556#ifdef CODEC_SILK_SWB
1557            case NETEQ_CODEC_SILK_24:
1558#if (_MSC_VER >= 1400) && !defined(_WIN64) // only for Visual 2005 or later, and not for x64
1559                *dec = new decoder_SILK24( pt );
1560#endif
1561                break;
1562#endif
1563
1564            default:
1565                printf("Unknown codec type encountered in createAndInsertDecoders\n");
1566                exit(0);
1567            }
1568
1569            // insert into codec DB
1570            if (*dec)
1571            {
1572                (*dec)->loadToNetEQ(*neteq);
1573            }
1574        }
1575    }
1576
1577}
1578
1579
1580void free_coders(std::map<uint8_t, decoderStruct> & decoders)
1581{
1582    std::map<uint8_t, decoderStruct>::iterator it;
1583
1584    for (it = decoders.begin(); it != decoders.end();  it++)
1585    {
1586        if ((*it).second.decoder[0])
1587        {
1588            delete (*it).second.decoder[0];
1589        }
1590
1591        if ((*it).second.decoder[1])
1592        {
1593            delete (*it).second.decoder[1];
1594        }
1595    }
1596}
1597
1598
1599
1600#include "pcm16b.h"
1601#include "g711_interface.h"
1602#include "isac.h"
1603
1604int doAPItest() {
1605
1606    void *inst;
1607    enum WebRtcNetEQDecoder usedCodec;
1608    int NetEqBufferMaxPackets, BufferSizeInBytes;
1609    WebRtcNetEQ_CodecDef codecInst;
1610    WebRtcNetEQ_RTCPStat RTCPstat;
1611    uint32_t timestamp;
1612    int memorySize;
1613    int ok;
1614    int overhead_bytes;
1615
1616    printf("API-test:\n\n");
1617
1618    /* test that API functions return -1 if instance is NULL */
1619#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);}}
1620//#define RESET_ERROR(x) ((MainInst_t*) x)->ErrorCode = 0;
1621    inst = NULL;
1622
1623    CHECK_MINUS_ONE(WebRtcNetEQ_GetErrorCode(inst))
1624    CHECK_MINUS_ONE(WebRtcNetEQ_Assign(&inst, NULL))
1625//  printf("WARNING: Test of WebRtcNetEQ_Assign() is disabled due to a bug.\n");
1626    usedCodec=kDecoderPCMu;
1627    CHECK_MINUS_ONE(WebRtcNetEQ_GetRecommendedBufferSize(inst, &usedCodec, 1, kTCPLargeJitter,  &NetEqBufferMaxPackets, &BufferSizeInBytes, &overhead_bytes))
1628    CHECK_MINUS_ONE(WebRtcNetEQ_AssignBuffer(inst, NetEqBufferMaxPackets, NetEqPacketBuffer, BufferSizeInBytes))
1629
1630    CHECK_MINUS_ONE(WebRtcNetEQ_Init(inst, 8000))
1631    CHECK_MINUS_ONE(WebRtcNetEQ_SetAVTPlayout(inst, 0))
1632    CHECK_MINUS_ONE(WebRtcNetEQ_SetExtraDelay(inst, 17))
1633    CHECK_MINUS_ONE(WebRtcNetEQ_SetPlayoutMode(inst, kPlayoutOn))
1634
1635    CHECK_MINUS_ONE(WebRtcNetEQ_CodecDbReset(inst))
1636    CHECK_MINUS_ONE(WebRtcNetEQ_CodecDbAdd(inst, &codecInst))
1637    CHECK_MINUS_ONE(WebRtcNetEQ_CodecDbRemove(inst, usedCodec))
1638    int16_t temp1, temp2;
1639    CHECK_MINUS_ONE(WebRtcNetEQ_CodecDbGetSizeInfo(inst, &temp1, &temp2))
1640    CHECK_MINUS_ONE(WebRtcNetEQ_CodecDbGetCodecInfo(inst, 0, &usedCodec))
1641
1642    CHECK_MINUS_ONE(WebRtcNetEQ_RecIn(inst, &temp1, 17, 4711))
1643    CHECK_MINUS_ONE(WebRtcNetEQ_RecOut(inst, &temp1, &temp2))
1644    CHECK_MINUS_ONE(WebRtcNetEQ_GetRTCPStats(inst, &RTCPstat)); // error here!!!
1645    CHECK_MINUS_ONE(WebRtcNetEQ_GetSpeechTimeStamp(inst, &timestamp))
1646    WebRtcNetEQOutputType temptype;
1647    CHECK_MINUS_ONE(WebRtcNetEQ_GetSpeechOutputType(inst, &temptype))
1648
1649    uint8_t tempFlags;
1650    uint16_t utemp1, utemp2;
1651    CHECK_MINUS_ONE(WebRtcNetEQ_VQmonRecOutStatistics(inst, &utemp1, &utemp2, &tempFlags))
1652    CHECK_MINUS_ONE(WebRtcNetEQ_VQmonGetRxStatistics(inst, &utemp1, &utemp2))
1653
1654    WebRtcNetEQ_AssignSize(&memorySize);
1655    CHECK_ZERO(WebRtcNetEQ_Assign(&inst, malloc(memorySize)))
1656
1657    /* init with wrong sample frequency */
1658    CHECK_MINUS_ONE(WebRtcNetEQ_Init(inst, 17))
1659
1660    /* init with correct fs */
1661    CHECK_ZERO(WebRtcNetEQ_Init(inst, 8000))
1662
1663    /* GetRecommendedBufferSize with wrong codec */
1664    usedCodec=kDecoderReservedStart;
1665    ok = WebRtcNetEQ_GetRecommendedBufferSize(inst, &usedCodec, 1, kTCPLargeJitter , &NetEqBufferMaxPackets, &BufferSizeInBytes, &overhead_bytes);
1666    if((ok!=-1) || ((ok==-1)&&(WebRtcNetEQ_GetErrorCode(inst)!=-CODEC_DB_UNKNOWN_CODEC))){
1667        printf("WebRtcNetEQ_GetRecommendedBufferSize() did not return proper error code for wrong codec.\n");
1668        printf("return value = %d; error code = %d\n", ok, WebRtcNetEQ_GetErrorCode(inst));
1669    }
1670    //RESET_ERROR(inst)
1671
1672    /* GetRecommendedBufferSize with wrong network type */
1673    usedCodec = kDecoderPCMu;
1674    ok=WebRtcNetEQ_GetRecommendedBufferSize(inst, &usedCodec, 1, (enum WebRtcNetEQNetworkType) 4711 , &NetEqBufferMaxPackets, &BufferSizeInBytes, &overhead_bytes);
1675    if ((ok!=-1) || ((ok==-1)&&(WebRtcNetEQ_GetErrorCode(inst)!=-FAULTY_NETWORK_TYPE))) {
1676        printf("WebRtcNetEQ_GetRecommendedBufferSize() did not return proper error code for wrong network type.\n");
1677        printf("return value = %d; error code = %d\n", ok, WebRtcNetEQ_GetErrorCode(inst));
1678        //RESET_ERROR(inst)
1679    }
1680    CHECK_ZERO(WebRtcNetEQ_GetRecommendedBufferSize(inst, &usedCodec, 1, kTCPLargeJitter , &NetEqBufferMaxPackets, &BufferSizeInBytes, &overhead_bytes))
1681
1682    /* try to do RecIn before assigning the packet buffer */
1683/*  makeRTPheader(rtp_data, NETEQ_CODEC_AVT_PT, 17,4711, 1235412312);
1684    makeDTMFpayload(&rtp_data[12], 1, 1, 10, 100);
1685    ok = WebRtcNetEQ_RecIn(inst, (short *) rtp_data, 12+4, 4711);
1686    printf("return value = %d; error code = %d\n", ok, WebRtcNetEQ_GetErrorCode(inst));*/
1687
1688    /* check all limits of WebRtcNetEQ_AssignBuffer */
1689    ok=WebRtcNetEQ_AssignBuffer(inst, NetEqBufferMaxPackets, NetEqPacketBuffer, 149<<1);
1690    if((ok!=-1)||((ok==-1)&&(WebRtcNetEQ_GetErrorCode(inst)!=-PBUFFER_INIT_ERROR))) {
1691        printf("WebRtcNetEQ_AssignBuffer() did not return proper error code for wrong sizeinbytes\n");
1692    }
1693    ok=WebRtcNetEQ_AssignBuffer(inst, NetEqBufferMaxPackets, NULL, BufferSizeInBytes);
1694    if((ok!=-1)||((ok==-1)&&(WebRtcNetEQ_GetErrorCode(inst)!=-PBUFFER_INIT_ERROR))) {
1695        printf("WebRtcNetEQ_AssignBuffer() did not return proper error code for NULL memory pointer\n");
1696    }
1697    ok=WebRtcNetEQ_AssignBuffer(inst, 1, NetEqPacketBuffer, BufferSizeInBytes);
1698    if((ok!=-1)||((ok==-1)&&(WebRtcNetEQ_GetErrorCode(inst)!=-PBUFFER_INIT_ERROR))) {
1699        printf("WebRtcNetEQ_AssignBuffer() did not return proper error code for wrong MaxNoOfPackets\n");
1700    }
1701    ok=WebRtcNetEQ_AssignBuffer(inst, 601, NetEqPacketBuffer, BufferSizeInBytes);
1702    if((ok!=-1)||((ok==-1)&&(WebRtcNetEQ_GetErrorCode(inst)!=-PBUFFER_INIT_ERROR))) {
1703        printf("WebRtcNetEQ_AssignBuffer() did not return proper error code for wrong MaxNoOfPackets\n");
1704    }
1705
1706    /* do correct assignbuffer */
1707    CHECK_ZERO(WebRtcNetEQ_AssignBuffer(inst, NetEqBufferMaxPackets, NetEqPacketBuffer, BufferSizeInBytes))
1708
1709    ok=WebRtcNetEQ_SetExtraDelay(inst, -1);
1710    if((ok!=-1)||((ok==-1)&&(WebRtcNetEQ_GetErrorCode(inst)!=-FAULTY_DELAYVALUE))) {
1711        printf("WebRtcNetEQ_SetExtraDelay() did not return proper error code for too small delay\n");
1712    }
1713    ok=WebRtcNetEQ_SetExtraDelay(inst, 1001);
1714    if((ok!=-1)||((ok==-1)&&(WebRtcNetEQ_GetErrorCode(inst)!=-FAULTY_DELAYVALUE))) {
1715        printf("WebRtcNetEQ_SetExtraDelay() did not return proper error code for too large delay\n");
1716    }
1717
1718    ok=WebRtcNetEQ_SetPlayoutMode(inst,(enum WebRtcNetEQPlayoutMode) 4711);
1719    if((ok!=-1)||((ok==-1)&&(WebRtcNetEQ_GetErrorCode(inst)!=-FAULTY_PLAYOUTMODE))) {
1720        printf("WebRtcNetEQ_SetPlayoutMode() did not return proper error code for wrong mode\n");
1721    }
1722
1723    /* number of codecs should return zero before adding any codecs */
1724    WebRtcNetEQ_CodecDbGetSizeInfo(inst, &temp1, &temp2);
1725    if(temp1!=0)
1726        printf("WebRtcNetEQ_CodecDbGetSizeInfo() return non-zero number of codecs in DB before adding any codecs\n");
1727
1728    /* get info from empty database */
1729    ok=WebRtcNetEQ_CodecDbGetCodecInfo(inst, 17, &usedCodec);
1730    if((ok!=-1)||((ok==-1)&&(WebRtcNetEQ_GetErrorCode(inst)!=-CODEC_DB_NOT_EXIST1))) {
1731        printf("WebRtcNetEQ_CodecDbGetCodecInfo() did not return proper error code for out-of-range entry number\n");
1732    }
1733
1734    /* remove codec from empty database */
1735    ok=WebRtcNetEQ_CodecDbRemove(inst,kDecoderPCMa);
1736    if((ok!=-1)||((ok==-1)&&(WebRtcNetEQ_GetErrorCode(inst)!=-CODEC_DB_NOT_EXIST4))) {
1737        printf("WebRtcNetEQ_CodecDbRemove() did not return proper error code when removing codec that has not been added\n");
1738    }
1739
1740    /* add codec with unsupported fs */
1741#ifdef CODEC_PCM16B
1742#ifndef NETEQ_48KHZ_WIDEBAND
1743    SET_CODEC_PAR(codecInst,kDecoderPCM16Bswb48kHz,77,NULL,48000);
1744    SET_PCM16B_SWB48_FUNCTIONS(codecInst);
1745    ok=WebRtcNetEQ_CodecDbAdd(inst, &codecInst);
1746    if((ok!=-1)||((ok==-1)&&(WebRtcNetEQ_GetErrorCode(inst)!=-CODEC_DB_UNSUPPORTED_FS))) {
1747        printf("WebRtcNetEQ_CodecDbAdd() did not return proper error code when adding codec with unsupported sample freq\n");
1748    }
1749#else
1750    printf("Could not test adding codec with unsupported sample frequency since NetEQ is compiled with 48kHz support.\n");
1751#endif
1752#else
1753    printf("Could not test adding codec with unsupported sample frequency since NetEQ is compiled without PCM16B support.\n");
1754#endif
1755
1756    /* add two codecs with identical payload types */
1757    SET_CODEC_PAR(codecInst,kDecoderPCMa,17,NULL,8000);
1758    SET_PCMA_FUNCTIONS(codecInst);
1759    CHECK_ZERO(WebRtcNetEQ_CodecDbAdd(inst, &codecInst))
1760
1761    SET_CODEC_PAR(codecInst,kDecoderPCMu,17,NULL,8000);
1762    SET_PCMU_FUNCTIONS(codecInst);
1763    ok=WebRtcNetEQ_CodecDbAdd(inst, &codecInst);
1764    if((ok!=-1)||((ok==-1)&&(WebRtcNetEQ_GetErrorCode(inst)!=-CODEC_DB_PAYLOAD_TAKEN))) {
1765        printf("WebRtcNetEQ_CodecDbAdd() did not return proper error code when adding two codecs with identical payload types\n");
1766    }
1767
1768    /* try adding several payload types for CNG codecs */
1769    SET_CODEC_PAR(codecInst,kDecoderCNG,105,NULL,16000);
1770    SET_CNG_FUNCTIONS(codecInst);
1771    CHECK_ZERO(WebRtcNetEQ_CodecDbAdd(inst, &codecInst))
1772    SET_CODEC_PAR(codecInst,kDecoderCNG,13,NULL,8000);
1773    SET_CNG_FUNCTIONS(codecInst);
1774    CHECK_ZERO(WebRtcNetEQ_CodecDbAdd(inst, &codecInst))
1775
1776    /* try adding a speech codec over a CNG codec */
1777    SET_CODEC_PAR(codecInst,kDecoderISAC,105,NULL,16000); /* same as WB CNG above */
1778    SET_ISAC_FUNCTIONS(codecInst);
1779    ok=WebRtcNetEQ_CodecDbAdd(inst, &codecInst);
1780    if((ok!=-1)||((ok==-1)&&(WebRtcNetEQ_GetErrorCode(inst)!=-CODEC_DB_PAYLOAD_TAKEN))) {
1781        printf("WebRtcNetEQ_CodecDbAdd() did not return proper error code when adding a speech codec over a CNG codec\n");
1782    }
1783
1784    /* try adding a CNG codec over a speech codec */
1785    SET_CODEC_PAR(codecInst,kDecoderCNG,17,NULL,32000); /* same as PCMU above */
1786    SET_CNG_FUNCTIONS(codecInst);
1787    ok=WebRtcNetEQ_CodecDbAdd(inst, &codecInst);
1788    if((ok!=-1)||((ok==-1)&&(WebRtcNetEQ_GetErrorCode(inst)!=-CODEC_DB_PAYLOAD_TAKEN))) {
1789        printf("WebRtcNetEQ_CodecDbAdd() did not return proper error code when adding a speech codec over a CNG codec\n");
1790    }
1791
1792
1793    /* remove codec out of range */
1794    ok=WebRtcNetEQ_CodecDbRemove(inst,kDecoderReservedStart);
1795    if((ok!=-1)||((ok==-1)&&(WebRtcNetEQ_GetErrorCode(inst)!=-CODEC_DB_UNSUPPORTED_CODEC))) {
1796        printf("WebRtcNetEQ_CodecDbRemove() did not return proper error code when removing codec that is out of range\n");
1797    }
1798    ok=WebRtcNetEQ_CodecDbRemove(inst,kDecoderReservedEnd);
1799    if((ok!=-1)||((ok==-1)&&(WebRtcNetEQ_GetErrorCode(inst)!=-CODEC_DB_UNSUPPORTED_CODEC))) {
1800        printf("WebRtcNetEQ_CodecDbRemove() did not return proper error code when removing codec that is out of range\n");
1801    }
1802
1803    /*SET_CODEC_PAR(codecInst,kDecoderEG711a,NETEQ_CODEC_EG711A_PT,NetEqiPCMAState,8000);
1804    SET_IPCMA_FUNCTIONS(codecInst);
1805    CHECK_ZERO(WebRtcNetEQ_CodecDbAdd(inst, &codecInst))
1806*/
1807    free(inst);
1808
1809    return(0);
1810
1811}
Note: See TracBrowser for help on using the repository browser.