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/webrtc_neteq.c @ 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: 53.2 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/*
12 * Implementation of main NetEQ API.
13 */
14
15#include "webrtc_neteq.h"
16#include "webrtc_neteq_internal.h"
17
18#include <assert.h>
19#include <string.h>
20
21#include "typedefs.h"
22#include "signal_processing_library.h"
23
24#include "neteq_error_codes.h"
25#include "mcu_dsp_common.h"
26#include "rtcp.h"
27
28#define RETURN_ON_ERROR( macroExpr, macroInstPtr )  { \
29    if ((macroExpr) != 0) { \
30    if ((macroExpr) == -1) { \
31    (macroInstPtr)->ErrorCode = - (NETEQ_OTHER_ERROR); \
32    } else { \
33    (macroInstPtr)->ErrorCode = -((int16_t) (macroExpr)); \
34    } \
35    return(-1); \
36    } }
37
38int WebRtcNetEQ_strncpy(char *strDest, int numberOfElements,
39                        const char *strSource, int count)
40{
41    /* check vector lengths */
42    if (count > numberOfElements)
43    {
44        strDest[0] = '\0';
45        return (-1);
46    }
47    else
48    {
49        strncpy(strDest, strSource, count);
50        return (0);
51    }
52}
53
54/**********************************************************
55 * NETEQ Functions
56 */
57
58/*****************************************
59 * Error functions
60 */
61
62int WebRtcNetEQ_GetErrorCode(void *inst)
63{
64    MainInst_t *NetEqMainInst = (MainInst_t*) inst;
65    if (NetEqMainInst == NULL) return (-1);
66    return (NetEqMainInst->ErrorCode);
67}
68
69int WebRtcNetEQ_GetErrorName(int errorCode, char *errorName, int maxStrLen)
70{
71    if ((errorName == NULL) || (maxStrLen <= 0))
72    {
73        return (-1);
74    }
75
76    if (errorCode < 0)
77    {
78        errorCode = -errorCode; // absolute value
79    }
80
81    switch (errorCode)
82    {
83        case 1: // could be -1
84        {
85            WebRtcNetEQ_strncpy(errorName, maxStrLen, "OTHER_ERROR", maxStrLen);
86            break;
87        }
88        case 1001:
89        {
90            WebRtcNetEQ_strncpy(errorName, maxStrLen, "FAULTY_INSTRUCTION", maxStrLen);
91            break;
92        }
93        case 1002:
94        {
95            WebRtcNetEQ_strncpy(errorName, maxStrLen, "FAULTY_NETWORK_TYPE", maxStrLen);
96            break;
97        }
98        case 1003:
99        {
100            WebRtcNetEQ_strncpy(errorName, maxStrLen, "FAULTY_DELAYVALUE", maxStrLen);
101            break;
102        }
103        case 1004:
104        {
105            WebRtcNetEQ_strncpy(errorName, maxStrLen, "FAULTY_PLAYOUTMODE", maxStrLen);
106            break;
107        }
108        case 1005:
109        {
110            WebRtcNetEQ_strncpy(errorName, maxStrLen, "CORRUPT_INSTANCE", maxStrLen);
111            break;
112        }
113        case 1006:
114        {
115            WebRtcNetEQ_strncpy(errorName, maxStrLen, "ILLEGAL_MASTER_SLAVE_SWITCH", maxStrLen);
116            break;
117        }
118        case 1007:
119        {
120            WebRtcNetEQ_strncpy(errorName, maxStrLen, "MASTER_SLAVE_ERROR", maxStrLen);
121            break;
122        }
123        case 2001:
124        {
125            WebRtcNetEQ_strncpy(errorName, maxStrLen, "UNKNOWN_BUFSTAT_DECISION", maxStrLen);
126            break;
127        }
128        case 2002:
129        {
130            WebRtcNetEQ_strncpy(errorName, maxStrLen, "RECOUT_ERROR_DECODING", maxStrLen);
131            break;
132        }
133        case 2003:
134        {
135            WebRtcNetEQ_strncpy(errorName, maxStrLen, "RECOUT_ERROR_SAMPLEUNDERRUN", maxStrLen);
136            break;
137        }
138        case 2004:
139        {
140            WebRtcNetEQ_strncpy(errorName, maxStrLen, "RECOUT_ERROR_DECODED_TOO_MUCH",
141                maxStrLen);
142            break;
143        }
144        case 3001:
145        {
146            WebRtcNetEQ_strncpy(errorName, maxStrLen, "RECIN_CNG_ERROR", maxStrLen);
147            break;
148        }
149        case 3002:
150        {
151            WebRtcNetEQ_strncpy(errorName, maxStrLen, "RECIN_UNKNOWNPAYLOAD", maxStrLen);
152            break;
153        }
154        case 3003:
155        {
156            WebRtcNetEQ_strncpy(errorName, maxStrLen, "RECIN_BUFFERINSERT_ERROR", maxStrLen);
157            break;
158        }
159        case 4001:
160        {
161            WebRtcNetEQ_strncpy(errorName, maxStrLen, "PBUFFER_INIT_ERROR", maxStrLen);
162            break;
163        }
164        case 4002:
165        case 4003:
166        case 4004:
167        case 4005:
168        case 4006:
169        {
170            WebRtcNetEQ_strncpy(errorName, maxStrLen, "PBUFFER_INSERT_ERROR1", maxStrLen);
171            break;
172        }
173        case 4007:
174        {
175            WebRtcNetEQ_strncpy(errorName, maxStrLen, "UNKNOWN_G723_HEADER", maxStrLen);
176            break;
177        }
178        case 4008:
179        {
180            WebRtcNetEQ_strncpy(errorName, maxStrLen, "PBUFFER_NONEXISTING_PACKET", maxStrLen);
181            break;
182        }
183        case 4009:
184        {
185            WebRtcNetEQ_strncpy(errorName, maxStrLen, "PBUFFER_NOT_INITIALIZED", maxStrLen);
186            break;
187        }
188        case 4010:
189        {
190            WebRtcNetEQ_strncpy(errorName, maxStrLen, "AMBIGUOUS_ILBC_FRAME_SIZE", maxStrLen);
191            break;
192        }
193        case 5001:
194        {
195            WebRtcNetEQ_strncpy(errorName, maxStrLen, "CODEC_DB_FULL", maxStrLen);
196            break;
197        }
198        case 5002:
199        case 5003:
200        case 5004:
201        case 5005:
202        {
203            WebRtcNetEQ_strncpy(errorName, maxStrLen, "CODEC_DB_NOT_EXIST", maxStrLen);
204            break;
205        }
206        case 5006:
207        {
208            WebRtcNetEQ_strncpy(errorName, maxStrLen, "CODEC_DB_UNKNOWN_CODEC", maxStrLen);
209            break;
210        }
211        case 5007:
212        {
213            WebRtcNetEQ_strncpy(errorName, maxStrLen, "CODEC_DB_PAYLOAD_TAKEN", maxStrLen);
214            break;
215        }
216        case 5008:
217        {
218            WebRtcNetEQ_strncpy(errorName, maxStrLen, "CODEC_DB_UNSUPPORTED_CODEC", maxStrLen);
219            break;
220        }
221        case 5009:
222        {
223            WebRtcNetEQ_strncpy(errorName, maxStrLen, "CODEC_DB_UNSUPPORTED_FS", maxStrLen);
224            break;
225        }
226        case 6001:
227        {
228            WebRtcNetEQ_strncpy(errorName, maxStrLen, "DTMF_DEC_PARAMETER_ERROR", maxStrLen);
229            break;
230        }
231        case 6002:
232        {
233            WebRtcNetEQ_strncpy(errorName, maxStrLen, "DTMF_INSERT_ERROR", maxStrLen);
234            break;
235        }
236        case 6003:
237        {
238            WebRtcNetEQ_strncpy(errorName, maxStrLen, "DTMF_GEN_UNKNOWN_SAMP_FREQ", maxStrLen);
239            break;
240        }
241        case 6004:
242        {
243            WebRtcNetEQ_strncpy(errorName, maxStrLen, "DTMF_NOT_SUPPORTED", maxStrLen);
244            break;
245        }
246        case 7001:
247        case 7002:
248        {
249            WebRtcNetEQ_strncpy(errorName, maxStrLen, "RED_SPLIT_ERROR", maxStrLen);
250            break;
251        }
252        case 7003:
253        {
254            WebRtcNetEQ_strncpy(errorName, maxStrLen, "RTP_TOO_SHORT_PACKET", maxStrLen);
255            break;
256        }
257        case 7004:
258        {
259            WebRtcNetEQ_strncpy(errorName, maxStrLen, "RTP_CORRUPT_PACKET", maxStrLen);
260            break;
261        }
262        default:
263        {
264            /* check for decoder error ranges */
265            if (errorCode >= 6010 && errorCode <= 6810)
266            {
267                /* iSAC error code */
268                WebRtcNetEQ_strncpy(errorName, maxStrLen, "iSAC ERROR", maxStrLen);
269                break;
270            }
271
272            WebRtcNetEQ_strncpy(errorName, maxStrLen, "UNKNOWN_ERROR", maxStrLen);
273            return (-1);
274        }
275    }
276
277    return (0);
278}
279
280/* Assign functions (create not allowed in order to avoid malloc in lib) */
281int WebRtcNetEQ_AssignSize(int *sizeinbytes)
282{
283    *sizeinbytes = (sizeof(MainInst_t) * 2) / sizeof(int16_t);
284    return (0);
285}
286
287int WebRtcNetEQ_Assign(void **inst, void *NETEQ_inst_Addr)
288{
289    int ok = 0;
290    MainInst_t *NetEqMainInst = (MainInst_t*) NETEQ_inst_Addr;
291    *inst = NETEQ_inst_Addr;
292    if (*inst == NULL) return (-1);
293
294    WebRtcSpl_Init();
295
296    /* Clear memory */
297    WebRtcSpl_MemSetW16((int16_t*) NetEqMainInst, 0,
298        (sizeof(MainInst_t) / sizeof(int16_t)));
299    ok = WebRtcNetEQ_McuReset(&NetEqMainInst->MCUinst);
300    if (ok != 0)
301    {
302        NetEqMainInst->ErrorCode = -ok;
303        return (-1);
304    }
305    return (0);
306}
307
308int WebRtcNetEQ_GetRecommendedBufferSize(void *inst, const enum WebRtcNetEQDecoder *codec,
309                                         int noOfCodecs, enum WebRtcNetEQNetworkType nwType,
310                                         int *MaxNoOfPackets, int *sizeinbytes,
311                                         int* per_packet_overhead_bytes)
312{
313    int ok = 0;
314    int multiplier;
315    MainInst_t *NetEqMainInst = (MainInst_t*) inst;
316    if (NetEqMainInst == NULL) return (-1);
317    *MaxNoOfPackets = 0;
318    *sizeinbytes = 0;
319    ok = WebRtcNetEQ_GetDefaultCodecSettings(codec, noOfCodecs, sizeinbytes,
320                                             MaxNoOfPackets,
321                                             per_packet_overhead_bytes);
322    if (ok != 0)
323    {
324        NetEqMainInst->ErrorCode = -ok;
325        return (-1);
326    }
327    if (nwType == kUDPNormal)
328    {
329        multiplier = 1;
330    }
331    else if (nwType == kUDPVideoSync)
332    {
333        multiplier = 4;
334    }
335    else if (nwType == kTCPNormal)
336    {
337        multiplier = 4;
338    }
339    else if (nwType == kTCPLargeJitter)
340    {
341        multiplier = 8;
342    }
343    else if (nwType == kTCPXLargeJitter)
344    {
345        multiplier = 12;
346    }
347    else
348    {
349        NetEqMainInst->ErrorCode = -FAULTY_NETWORK_TYPE;
350        return (-1);
351    }
352    *MaxNoOfPackets = (*MaxNoOfPackets) * multiplier;
353    *sizeinbytes = (*sizeinbytes) * multiplier;
354    return 0;
355}
356
357int WebRtcNetEQ_AssignBuffer(void *inst, int MaxNoOfPackets, void *NETEQ_Buffer_Addr,
358                             int sizeinbytes)
359{
360    int ok;
361    MainInst_t *NetEqMainInst = (MainInst_t*) inst;
362    if (NetEqMainInst == NULL) return (-1);
363    ok = WebRtcNetEQ_PacketBufferInit(&NetEqMainInst->MCUinst.PacketBuffer_inst,
364        MaxNoOfPackets, (int16_t*) NETEQ_Buffer_Addr, (sizeinbytes >> 1));
365    if (ok != 0)
366    {
367        NetEqMainInst->ErrorCode = -ok;
368        return (-1);
369    }
370    return (ok);
371}
372
373/************************************************
374 * Init functions
375 */
376
377/****************************************************************************
378 * WebRtcNetEQ_Init(...)
379 *
380 * Initialize NetEQ.
381 *
382 * Input:
383 *      - inst          : NetEQ instance
384 *              - fs            : Initial sample rate in Hz (may change with payload)
385 *
386 * Output:
387 *              - inst          : Initialized NetEQ instance
388 *
389 * Return value                 :  0 - Ok
390 *                                                -1 - Error
391 */
392
393int WebRtcNetEQ_Init(void *inst, uint16_t fs)
394{
395    int ok = 0;
396
397    /* Typecast inst to internal instance format */
398    MainInst_t *NetEqMainInst = (MainInst_t*) inst;
399
400    if (NetEqMainInst == NULL)
401    {
402        return (-1);
403    }
404
405#ifdef NETEQ_VAD
406    /* Start out with no PostDecode VAD instance */
407    NetEqMainInst->DSPinst.VADInst.VADState = NULL;
408    /* Also set all VAD function pointers to NULL */
409    NetEqMainInst->DSPinst.VADInst.initFunction = NULL;
410    NetEqMainInst->DSPinst.VADInst.setmodeFunction = NULL;
411    NetEqMainInst->DSPinst.VADInst.VADFunction = NULL;
412#endif /* NETEQ_VAD */
413
414    ok = WebRtcNetEQ_DSPinit(NetEqMainInst); /* Init addresses between MCU and DSP */
415    RETURN_ON_ERROR(ok, NetEqMainInst);
416
417    ok = WebRtcNetEQ_DSPInit(&NetEqMainInst->DSPinst, fs); /* Init dsp side */
418    RETURN_ON_ERROR(ok, NetEqMainInst);
419    /* set BGN mode to default, since it is not cleared by DSP init function */
420    NetEqMainInst->DSPinst.BGNInst.bgnMode = BGN_ON;
421
422    /* init statistics functions and counters */
423    ok = WebRtcNetEQ_ClearInCallStats(&NetEqMainInst->DSPinst);
424    RETURN_ON_ERROR(ok, NetEqMainInst);
425    ok = WebRtcNetEQ_ClearPostCallStats(&NetEqMainInst->DSPinst);
426    RETURN_ON_ERROR(ok, NetEqMainInst);
427    ok = WebRtcNetEQ_ResetMcuJitterStat(&NetEqMainInst->MCUinst);
428    RETURN_ON_ERROR(ok, NetEqMainInst);
429
430    /* flush packet buffer */
431    ok = WebRtcNetEQ_PacketBufferFlush(&NetEqMainInst->MCUinst.PacketBuffer_inst);
432    RETURN_ON_ERROR(ok, NetEqMainInst);
433
434    /* set some variables to initial values */
435    NetEqMainInst->MCUinst.current_Codec = -1;
436    NetEqMainInst->MCUinst.current_Payload = -1;
437    NetEqMainInst->MCUinst.first_packet = 1;
438    NetEqMainInst->MCUinst.one_desc = 0;
439    NetEqMainInst->MCUinst.BufferStat_inst.Automode_inst.extraDelayMs = 0;
440    NetEqMainInst->MCUinst.BufferStat_inst.Automode_inst.minimum_delay_ms = 0;
441    NetEqMainInst->MCUinst.BufferStat_inst.Automode_inst.maximum_delay_ms =
442        10000;
443    NetEqMainInst->MCUinst.NoOfExpandCalls = 0;
444    NetEqMainInst->MCUinst.fs = fs;
445
446    /* Not in AV-sync by default. */
447    NetEqMainInst->MCUinst.av_sync = 0;
448
449#ifdef NETEQ_ATEVENT_DECODE
450    /* init DTMF decoder */
451    ok = WebRtcNetEQ_DtmfDecoderInit(&(NetEqMainInst->MCUinst.DTMF_inst),fs,560);
452    RETURN_ON_ERROR(ok, NetEqMainInst);
453#endif
454
455    /* init RTCP statistics */
456    WebRtcNetEQ_RTCPInit(&(NetEqMainInst->MCUinst.RTCP_inst), 0);
457
458    /* set BufferStat struct to zero */
459    WebRtcSpl_MemSetW16((int16_t*) &(NetEqMainInst->MCUinst.BufferStat_inst), 0,
460        sizeof(BufstatsInst_t) / sizeof(int16_t));
461
462    /* reset automode */
463    WebRtcNetEQ_ResetAutomode(&(NetEqMainInst->MCUinst.BufferStat_inst.Automode_inst),
464        NetEqMainInst->MCUinst.PacketBuffer_inst.maxInsertPositions);
465
466    NetEqMainInst->ErrorCode = 0;
467
468#ifdef NETEQ_STEREO
469    /* set master/slave info to undecided */
470    NetEqMainInst->masterSlave = 0;
471#endif
472
473    /* Set to an invalid value. */
474    NetEqMainInst->MCUinst.decoded_packet_sequence_number = -1;
475    NetEqMainInst->MCUinst.decoded_packet_timestamp = 0;
476
477    return (ok);
478}
479
480int WebRtcNetEQ_FlushBuffers(void *inst)
481{
482    int ok = 0;
483
484    /* Typecast inst to internal instance format */
485    MainInst_t *NetEqMainInst = (MainInst_t*) inst;
486
487    if (NetEqMainInst == NULL)
488    {
489        return (-1);
490    }
491
492    /* Flush packet buffer */
493    ok = WebRtcNetEQ_PacketBufferFlush(&NetEqMainInst->MCUinst.PacketBuffer_inst);
494    RETURN_ON_ERROR(ok, NetEqMainInst);
495
496    /* Set MCU to wait for new codec */
497    NetEqMainInst->MCUinst.first_packet = 1;
498
499    /* Flush speech buffer */
500    ok = WebRtcNetEQ_FlushSpeechBuffer(&NetEqMainInst->DSPinst);
501    RETURN_ON_ERROR(ok, NetEqMainInst);
502
503    return 0;
504}
505
506int WebRtcNetEQ_SetAVTPlayout(void *inst, int PlayoutAVTon)
507{
508    MainInst_t *NetEqMainInst = (MainInst_t*) inst;
509    if (NetEqMainInst == NULL) return (-1);
510#ifdef NETEQ_ATEVENT_DECODE
511    NetEqMainInst->MCUinst.AVT_PlayoutOn = PlayoutAVTon;
512    return(0);
513#else
514    if (PlayoutAVTon != 0)
515    {
516        NetEqMainInst->ErrorCode = -DTMF_NOT_SUPPORTED;
517        return (-1);
518    }
519    else
520    {
521        return (0);
522    }
523#endif
524}
525
526int WebRtcNetEQ_SetExtraDelay(void *inst, int DelayInMs) {
527  MainInst_t *NetEqMainInst = (MainInst_t*) inst;
528  if (NetEqMainInst == NULL) return (-1);
529  if ((DelayInMs < 0) || (DelayInMs > 10000)) {
530    NetEqMainInst->ErrorCode = -FAULTY_DELAYVALUE;
531    return (-1);
532  }
533  NetEqMainInst->MCUinst.BufferStat_inst.Automode_inst.extraDelayMs = DelayInMs;
534  return (0);
535}
536
537int WebRtcNetEQ_SetMinimumDelay(void *inst, int minimum_delay_ms) {
538  MainInst_t *NetEqMainInst = (MainInst_t*) inst;
539  if (NetEqMainInst == NULL)  return -1;
540  if (minimum_delay_ms < 0 || minimum_delay_ms > 10000) {
541    NetEqMainInst->ErrorCode = -FAULTY_DELAYVALUE;
542    return -1;
543  }
544  if ((NetEqMainInst->MCUinst.BufferStat_inst.Automode_inst.maximum_delay_ms >
545      0) && (minimum_delay_ms >
546      NetEqMainInst->MCUinst.BufferStat_inst.Automode_inst.maximum_delay_ms)) {
547    NetEqMainInst->ErrorCode = -FAULTY_DELAYVALUE;
548    return -1;
549  }
550  NetEqMainInst->MCUinst.BufferStat_inst.Automode_inst.minimum_delay_ms =
551      minimum_delay_ms;
552  return 0;
553}
554
555int WebRtcNetEQ_SetMaximumDelay(void *inst, int maximum_delay_ms) {
556  MainInst_t *NetEqMainInst = (MainInst_t*) inst;
557  if (NetEqMainInst == NULL)  return -1;
558  if (maximum_delay_ms < 0 || maximum_delay_ms > 10000) {
559      NetEqMainInst->ErrorCode = -FAULTY_DELAYVALUE;
560      return -1;
561  }
562  if (maximum_delay_ms <
563      NetEqMainInst->MCUinst.BufferStat_inst.Automode_inst.minimum_delay_ms) {
564    NetEqMainInst->ErrorCode = -FAULTY_DELAYVALUE;
565    return -1;
566  }
567  NetEqMainInst->MCUinst.BufferStat_inst.Automode_inst.maximum_delay_ms =
568      maximum_delay_ms;
569  return 0;
570}
571
572int WebRtcNetEQ_SetPlayoutMode(void *inst, enum WebRtcNetEQPlayoutMode playoutMode)
573{
574    MainInst_t *NetEqMainInst = (MainInst_t*) inst;
575    if (NetEqMainInst == NULL) return (-1);
576    if ((playoutMode != kPlayoutOn) && (playoutMode != kPlayoutOff) && (playoutMode
577        != kPlayoutFax) && (playoutMode != kPlayoutStreaming))
578    {
579        NetEqMainInst->ErrorCode = -FAULTY_PLAYOUTMODE;
580        return (-1);
581    }
582    else
583    {
584        NetEqMainInst->MCUinst.NetEqPlayoutMode = playoutMode;
585        return (0);
586    }
587}
588
589int WebRtcNetEQ_SetBGNMode(void *inst, enum WebRtcNetEQBGNMode bgnMode)
590{
591
592    MainInst_t *NetEqMainInst = (MainInst_t*) inst;
593
594    /* Instance sanity */
595    if (NetEqMainInst == NULL) return (-1);
596
597    /* Check for corrupt/cleared instance */
598    if (NetEqMainInst->MCUinst.main_inst != NetEqMainInst)
599    {
600        /* Instance is corrupt */
601        NetEqMainInst->ErrorCode = CORRUPT_INSTANCE;
602        return (-1);
603    }
604
605    NetEqMainInst->DSPinst.BGNInst.bgnMode = (enum BGNMode) bgnMode;
606
607    return (0);
608}
609
610int WebRtcNetEQ_GetBGNMode(const void *inst, enum WebRtcNetEQBGNMode *bgnMode)
611{
612
613    const MainInst_t *NetEqMainInst = (const MainInst_t*) inst;
614
615    /* Instance sanity */
616    if (NetEqMainInst == NULL) return (-1);
617
618    *bgnMode = (enum WebRtcNetEQBGNMode) NetEqMainInst->DSPinst.BGNInst.bgnMode;
619
620    return (0);
621}
622
623/************************************************
624 * CodecDB functions
625 */
626
627int WebRtcNetEQ_CodecDbReset(void *inst)
628{
629    int ok = 0;
630    MainInst_t *NetEqMainInst = (MainInst_t*) inst;
631    if (NetEqMainInst == NULL) return (-1);
632    ok = WebRtcNetEQ_DbReset(&NetEqMainInst->MCUinst.codec_DB_inst);
633    if (ok != 0)
634    {
635        NetEqMainInst->ErrorCode = -ok;
636        return (-1);
637    }
638
639    /* set function pointers to NULL to prevent RecOut from using the codec */
640    NetEqMainInst->DSPinst.codec_ptr_inst.funcDecode = NULL;
641    NetEqMainInst->DSPinst.codec_ptr_inst.funcDecodeRCU = NULL;
642    NetEqMainInst->DSPinst.codec_ptr_inst.funcAddLatePkt = NULL;
643    NetEqMainInst->DSPinst.codec_ptr_inst.funcDecode = NULL;
644    NetEqMainInst->DSPinst.codec_ptr_inst.funcDecodeInit = NULL;
645    NetEqMainInst->DSPinst.codec_ptr_inst.funcDecodePLC = NULL;
646    NetEqMainInst->DSPinst.codec_ptr_inst.funcGetMDinfo = NULL;
647    NetEqMainInst->DSPinst.codec_ptr_inst.funcUpdBWEst = NULL;
648    NetEqMainInst->DSPinst.codec_ptr_inst.funcGetErrorCode = NULL;
649
650    return (0);
651}
652
653int WebRtcNetEQ_CodecDbGetSizeInfo(void *inst, int16_t *UsedEntries,
654                                   int16_t *MaxEntries)
655{
656    MainInst_t *NetEqMainInst = (MainInst_t*) inst;
657    if (NetEqMainInst == NULL) return (-1);
658    *MaxEntries = NUM_CODECS;
659    *UsedEntries = NetEqMainInst->MCUinst.codec_DB_inst.nrOfCodecs;
660    return (0);
661}
662
663int WebRtcNetEQ_CodecDbGetCodecInfo(void *inst, int16_t Entry,
664                                    enum WebRtcNetEQDecoder *codec)
665{
666    int i;
667    MainInst_t *NetEqMainInst = (MainInst_t*) inst;
668    if (NetEqMainInst == NULL) return (-1);
669    *codec = (enum WebRtcNetEQDecoder) 0;
670    if ((Entry >= 0) && (Entry < NetEqMainInst->MCUinst.codec_DB_inst.nrOfCodecs))
671    {
672        for (i = 0; i < NUM_TOTAL_CODECS; i++)
673        {
674            if (NetEqMainInst->MCUinst.codec_DB_inst.position[i] == Entry)
675            {
676                *codec = (enum WebRtcNetEQDecoder) i;
677            }
678        }
679    }
680    else
681    {
682        NetEqMainInst->ErrorCode = -(CODEC_DB_NOT_EXIST1);
683        return (-1);
684    }
685    return (0);
686}
687
688int WebRtcNetEQ_CodecDbAdd(void *inst, WebRtcNetEQ_CodecDef *codecInst)
689{
690    int ok = 0;
691    MainInst_t *NetEqMainInst = (MainInst_t*) inst;
692    if (NetEqMainInst == NULL) return (-1);
693    ok = WebRtcNetEQ_DbAdd(&NetEqMainInst->MCUinst.codec_DB_inst, codecInst->codec,
694        codecInst->payloadType, codecInst->funcDecode, codecInst->funcDecodeRCU,
695        codecInst->funcDecodePLC, codecInst->funcDecodeInit, codecInst->funcAddLatePkt,
696        codecInst->funcGetMDinfo, codecInst->funcGetPitch, codecInst->funcUpdBWEst,
697        codecInst->funcDurationEst, codecInst->funcGetErrorCode,
698        codecInst->codec_state, codecInst->codec_fs);
699    if (ok != 0)
700    {
701        NetEqMainInst->ErrorCode = -ok;
702        return (-1);
703    }
704    return (ok);
705}
706
707int WebRtcNetEQ_CodecDbRemove(void *inst, enum WebRtcNetEQDecoder codec)
708{
709    int ok = 0;
710    MainInst_t *NetEqMainInst = (MainInst_t*) inst;
711    if (NetEqMainInst == NULL) return (-1);
712
713    /* check if currently used codec is being removed */
714    if (NetEqMainInst->MCUinst.current_Codec == (int16_t) codec)
715    {
716        /* set function pointers to NULL to prevent RecOut from using the codec */
717        NetEqMainInst->DSPinst.codec_ptr_inst.funcDecode = NULL;
718        NetEqMainInst->DSPinst.codec_ptr_inst.funcDecodeRCU = NULL;
719        NetEqMainInst->DSPinst.codec_ptr_inst.funcAddLatePkt = NULL;
720        NetEqMainInst->DSPinst.codec_ptr_inst.funcDecode = NULL;
721        NetEqMainInst->DSPinst.codec_ptr_inst.funcDecodeInit = NULL;
722        NetEqMainInst->DSPinst.codec_ptr_inst.funcDecodePLC = NULL;
723        NetEqMainInst->DSPinst.codec_ptr_inst.funcGetMDinfo = NULL;
724        NetEqMainInst->DSPinst.codec_ptr_inst.funcUpdBWEst = NULL;
725        NetEqMainInst->DSPinst.codec_ptr_inst.funcGetErrorCode = NULL;
726    }
727
728    ok = WebRtcNetEQ_DbRemove(&NetEqMainInst->MCUinst.codec_DB_inst, codec);
729    if (ok != 0)
730    {
731        NetEqMainInst->ErrorCode = -ok;
732        return (-1);
733    }
734    return (ok);
735}
736
737/*********************************
738 * Real-time functions
739 */
740
741int WebRtcNetEQ_RecIn(void *inst, int16_t *p_w16datagramstart, int16_t w16_RTPlen,
742                      uint32_t uw32_timeRec)
743{
744    int ok = 0;
745    RTPPacket_t RTPpacket;
746    MainInst_t *NetEqMainInst = (MainInst_t*) inst;
747    if (NetEqMainInst == NULL) return (-1);
748
749    /* Check for corrupt/cleared instance */
750    if (NetEqMainInst->MCUinst.main_inst != NetEqMainInst)
751    {
752        /* Instance is corrupt */
753        NetEqMainInst->ErrorCode = CORRUPT_INSTANCE;
754        return (-1);
755    }
756
757    /* Parse RTP header */
758    ok = WebRtcNetEQ_RTPPayloadInfo(p_w16datagramstart, w16_RTPlen, &RTPpacket);
759    if (ok != 0)
760    {
761        NetEqMainInst->ErrorCode = -ok;
762        return (-1);
763    }
764
765    ok = WebRtcNetEQ_RecInInternal(&NetEqMainInst->MCUinst, &RTPpacket, uw32_timeRec);
766    if (ok != 0)
767    {
768        NetEqMainInst->ErrorCode = -ok;
769        return (-1);
770    }
771    return (ok);
772}
773
774/****************************************************************************
775 * WebRtcNetEQ_RecInRTPStruct(...)
776 *
777 * Alternative RecIn function, used when the RTP data has already been
778 * parsed into an RTP info struct (WebRtcNetEQ_RTPInfo).
779 *
780 * Input:
781 *              - inst              : NetEQ instance
782 *              - rtpInfo                   : Pointer to RTP info
783 *              - payloadPtr        : Pointer to the RTP payload (first byte after header)
784 *      - payloadLenBytes   : Length (in bytes) of the payload in payloadPtr
785 *      - timeRec           : Receive time (in timestamps of the used codec)
786 *
787 * Return value                     :  0 - Ok
788 *                            -1 - Error
789 */
790int WebRtcNetEQ_RecInRTPStruct(void *inst, WebRtcNetEQ_RTPInfo *rtpInfo,
791                               const uint8_t *payloadPtr, int16_t payloadLenBytes,
792                               uint32_t uw32_timeRec)
793{
794    int ok = 0;
795    RTPPacket_t RTPpacket;
796    MainInst_t *NetEqMainInst = (MainInst_t*) inst;
797    if (NetEqMainInst == NULL)
798    {
799        return (-1);
800    }
801
802    /* Check for corrupt/cleared instance */
803    if (NetEqMainInst->MCUinst.main_inst != NetEqMainInst)
804    {
805        /* Instance is corrupt */
806        NetEqMainInst->ErrorCode = CORRUPT_INSTANCE;
807        return (-1);
808    }
809
810    /* Load NetEQ's RTP struct from Module RTP struct */
811    RTPpacket.payloadType = rtpInfo->payloadType;
812    RTPpacket.seqNumber = rtpInfo->sequenceNumber;
813    RTPpacket.timeStamp = rtpInfo->timeStamp;
814    RTPpacket.ssrc = rtpInfo->SSRC;
815    RTPpacket.payload = (const int16_t*) payloadPtr;
816    RTPpacket.payloadLen = payloadLenBytes;
817    RTPpacket.starts_byte1 = 0;
818
819    ok = WebRtcNetEQ_RecInInternal(&NetEqMainInst->MCUinst, &RTPpacket, uw32_timeRec);
820    if (ok != 0)
821    {
822        NetEqMainInst->ErrorCode = -ok;
823        return (-1);
824    }
825    return (ok);
826}
827
828int WebRtcNetEQ_RecOut(void *inst, int16_t *pw16_outData, int16_t *pw16_len)
829{
830    int ok = 0;
831    MainInst_t *NetEqMainInst = (MainInst_t*) inst;
832#ifdef NETEQ_STEREO
833    MasterSlaveInfo msInfo;
834    msInfo.msMode = NETEQ_MONO;
835#endif
836
837    if (NetEqMainInst == NULL) return (-1);
838
839    /* Check for corrupt/cleared instance */
840    if (NetEqMainInst->DSPinst.main_inst != NetEqMainInst)
841    {
842        /* Instance is corrupt */
843        NetEqMainInst->ErrorCode = CORRUPT_INSTANCE;
844        return (-1);
845    }
846
847#ifdef NETEQ_STEREO
848    NetEqMainInst->DSPinst.msInfo = &msInfo;
849#endif
850
851    ok = WebRtcNetEQ_RecOutInternal(&NetEqMainInst->DSPinst, pw16_outData,
852        pw16_len, 0 /* not BGN only */, NetEqMainInst->MCUinst.av_sync);
853    if (ok != 0)
854    {
855        NetEqMainInst->ErrorCode = -ok;
856        return (-1);
857    }
858    return (ok);
859}
860
861/****************************************************************************
862 * WebRtcNetEQ_RecOutMasterSlave(...)
863 *
864 * RecOut function for running several NetEQ instances in master/slave mode.
865 * One master can be used to control several slaves.
866 *
867 * Input:
868 *      - inst          : NetEQ instance
869 *      - isMaster      : Non-zero indicates that this is the master channel
870 *      - msInfo        : (slave only) Information from master
871 *
872 * Output:
873 *              - inst          : Updated NetEQ instance
874 *      - pw16_outData  : Pointer to vector where output should be written
875 *      - pw16_len      : Pointer to variable where output length is returned
876 *      - msInfo        : (master only) Information to slave(s)
877 *
878 * Return value                 :  0 - Ok
879 *                                                -1 - Error
880 */
881
882int WebRtcNetEQ_RecOutMasterSlave(void *inst, int16_t *pw16_outData,
883                                  int16_t *pw16_len, void *msInfo,
884                                  int16_t isMaster)
885{
886#ifndef NETEQ_STEREO
887    /* Stereo not supported */
888    return(-1);
889#else
890    int ok = 0;
891    MainInst_t *NetEqMainInst = (MainInst_t*) inst;
892
893    if (NetEqMainInst == NULL) return (-1);
894
895    /* Check for corrupt/cleared instance */
896    if (NetEqMainInst->DSPinst.main_inst != NetEqMainInst)
897    {
898        /* Instance is corrupt */
899        NetEqMainInst->ErrorCode = CORRUPT_INSTANCE;
900        return (-1);
901    }
902
903    if (msInfo == NULL)
904    {
905        /* msInfo not provided */
906        NetEqMainInst->ErrorCode = NETEQ_OTHER_ERROR;
907        return (-1);
908    }
909
910    /* translate from external to internal Master/Slave information */
911    NetEqMainInst->DSPinst.msInfo = (MasterSlaveInfo *) msInfo;
912
913    /* check that we have not done a master/slave switch without first re-initializing */
914    if ((NetEqMainInst->masterSlave == 1 && !isMaster) || /* switch from master to slave */
915    (NetEqMainInst->masterSlave == 2 && isMaster)) /* switch from slave to master */
916    {
917        NetEqMainInst->ErrorCode = ILLEGAL_MASTER_SLAVE_SWITCH;
918        return (-1);
919    }
920
921    if (!isMaster)
922    {
923        /* this is the slave */
924        NetEqMainInst->masterSlave = 2;
925        NetEqMainInst->DSPinst.msInfo->msMode = NETEQ_SLAVE;
926    }
927    else
928    {
929        NetEqMainInst->DSPinst.msInfo->msMode = NETEQ_MASTER;
930    }
931
932    ok  = WebRtcNetEQ_RecOutInternal(&NetEqMainInst->DSPinst, pw16_outData,
933        pw16_len, 0 /* not BGN only */, NetEqMainInst->MCUinst.av_sync);
934    if (ok != 0)
935    {
936        NetEqMainInst->ErrorCode = -ok;
937        return (-1);
938    }
939
940    if (isMaster)
941    {
942        /* this is the master */
943        NetEqMainInst->masterSlave = 1;
944    }
945
946    return (ok);
947#endif
948}
949
950int WebRtcNetEQ_GetMasterSlaveInfoSize()
951{
952#ifdef NETEQ_STEREO
953    return (sizeof(MasterSlaveInfo));
954#else
955    return(-1);
956#endif
957}
958
959/* Special RecOut that does not do any decoding. */
960int WebRtcNetEQ_RecOutNoDecode(void *inst, int16_t *pw16_outData,
961                               int16_t *pw16_len)
962{
963    int ok = 0;
964    MainInst_t *NetEqMainInst = (MainInst_t*) inst;
965#ifdef NETEQ_STEREO
966    MasterSlaveInfo msInfo;
967#endif
968
969    if (NetEqMainInst == NULL) return (-1);
970
971    /* Check for corrupt/cleared instance */
972    if (NetEqMainInst->DSPinst.main_inst != NetEqMainInst)
973    {
974        /* Instance is corrupt */
975        NetEqMainInst->ErrorCode = CORRUPT_INSTANCE;
976        return (-1);
977    }
978
979#ifdef NETEQ_STEREO
980    /* keep same mode as before */
981    switch (NetEqMainInst->masterSlave)
982    {
983        case 1:
984        {
985            msInfo.msMode = NETEQ_MASTER;
986            break;
987        }
988        case 2:
989        {
990            msInfo.msMode = NETEQ_SLAVE;
991            break;
992        }
993        default:
994        {
995            msInfo.msMode = NETEQ_MONO;
996            break;
997        }
998    }
999
1000    NetEqMainInst->DSPinst.msInfo = &msInfo;
1001#endif
1002
1003    ok = WebRtcNetEQ_RecOutInternal(&NetEqMainInst->DSPinst, pw16_outData,
1004        pw16_len, 1 /* BGN only */, NetEqMainInst->MCUinst.av_sync);
1005    if (ok != 0)
1006    {
1007        NetEqMainInst->ErrorCode = -ok;
1008        return (-1);
1009    }
1010    return (ok);
1011}
1012
1013int WebRtcNetEQ_GetRTCPStats(void *inst, WebRtcNetEQ_RTCPStat *RTCP_inst)
1014{
1015    int ok = 0;
1016    MainInst_t *NetEqMainInst = (MainInst_t*) inst;
1017    if (NetEqMainInst == NULL) return (-1);
1018    ok = WebRtcNetEQ_RTCPGetStats(&NetEqMainInst->MCUinst.RTCP_inst,
1019        &RTCP_inst->fraction_lost, &RTCP_inst->cum_lost, &RTCP_inst->ext_max,
1020        &RTCP_inst->jitter, 0);
1021    if (ok != 0)
1022    {
1023        NetEqMainInst->ErrorCode = -ok;
1024        return (-1);
1025    }
1026    return (ok);
1027}
1028
1029int WebRtcNetEQ_GetRTCPStatsNoReset(void *inst, WebRtcNetEQ_RTCPStat *RTCP_inst)
1030{
1031    int ok = 0;
1032    MainInst_t *NetEqMainInst = (MainInst_t*) inst;
1033    if (NetEqMainInst == NULL) return (-1);
1034    ok = WebRtcNetEQ_RTCPGetStats(&NetEqMainInst->MCUinst.RTCP_inst,
1035        &RTCP_inst->fraction_lost, &RTCP_inst->cum_lost, &RTCP_inst->ext_max,
1036        &RTCP_inst->jitter, 1);
1037    if (ok != 0)
1038    {
1039        NetEqMainInst->ErrorCode = -ok;
1040        return (-1);
1041    }
1042    return (ok);
1043}
1044
1045int WebRtcNetEQ_GetSpeechTimeStamp(void *inst, uint32_t *timestamp)
1046{
1047    MainInst_t *NetEqMainInst = (MainInst_t*) inst;
1048    if (NetEqMainInst == NULL) return (-1);
1049
1050    if (NetEqMainInst->MCUinst.TSscalingInitialized)
1051    {
1052        *timestamp = WebRtcNetEQ_ScaleTimestampInternalToExternal(&NetEqMainInst->MCUinst,
1053            NetEqMainInst->DSPinst.videoSyncTimestamp);
1054    }
1055    else
1056    {
1057        *timestamp = NetEqMainInst->DSPinst.videoSyncTimestamp;
1058    }
1059
1060    return (0);
1061}
1062
1063/****************************************************************************
1064 * WebRtcNetEQ_GetSpeechOutputType(...)
1065 *
1066 * Get the output type for the audio provided by the latest call to
1067 * WebRtcNetEQ_RecOut().
1068 *
1069 * kOutputNormal = normal audio (possibly processed)
1070 * kOutputPLC = loss concealment through stretching audio
1071 * kOutputCNG = comfort noise (codec-internal or RFC3389)
1072 * kOutputPLCtoCNG = background noise only due to long expand or error
1073 * kOutputVADPassive = PostDecode VAD signalling passive speaker
1074 *
1075 * Input:
1076 *      - inst          : NetEQ instance
1077 *
1078 * Output:
1079 *              - outputType    : Output type from enum list WebRtcNetEQOutputType
1080 *
1081 * Return value                 :  0 - Ok
1082 *                                                -1 - Error
1083 */
1084
1085int WebRtcNetEQ_GetSpeechOutputType(void *inst, enum WebRtcNetEQOutputType *outputType)
1086{
1087    /* Typecast to internal instance type */
1088    MainInst_t *NetEqMainInst = (MainInst_t*) inst;
1089
1090    if (NetEqMainInst == NULL)
1091    {
1092        return (-1);
1093    }
1094
1095    if ((NetEqMainInst->DSPinst.w16_mode & MODE_BGN_ONLY) != 0)
1096    {
1097        /* If last mode was background noise only */
1098        *outputType = kOutputPLCtoCNG;
1099
1100    }
1101    else if ((NetEqMainInst->DSPinst.w16_mode == MODE_CODEC_INTERNAL_CNG)
1102        || (NetEqMainInst->DSPinst.w16_mode == MODE_RFC3389CNG))
1103    {
1104        /* If CN or internal CNG */
1105        *outputType = kOutputCNG;
1106
1107#ifdef NETEQ_VAD
1108    }
1109    else if ( NetEqMainInst->DSPinst.VADInst.VADDecision == 0 )
1110    {
1111        /* post-decode VAD says passive speaker */
1112        *outputType = kOutputVADPassive;
1113#endif /* NETEQ_VAD */
1114
1115    }
1116    else if ((NetEqMainInst->DSPinst.w16_mode == MODE_EXPAND)
1117        && (NetEqMainInst->DSPinst.ExpandInst.w16_expandMuteFactor == 0))
1118    {
1119        /* Expand mode has faded down to background noise only (very long expand) */
1120        *outputType = kOutputPLCtoCNG;
1121
1122    }
1123    else if (NetEqMainInst->DSPinst.w16_mode == MODE_EXPAND)
1124    {
1125        /* PLC mode */
1126        *outputType = kOutputPLC;
1127
1128    }
1129    else
1130    {
1131        /* Normal speech output type (can still be manipulated, e.g., accelerated) */
1132        *outputType = kOutputNormal;
1133    }
1134
1135    return (0);
1136}
1137
1138/**********************************
1139 * Functions related to VQmon
1140 */
1141
1142#define WEBRTC_NETEQ_CONCEALMENTFLAG_LOST       0x01
1143#define WEBRTC_NETEQ_CONCEALMENTFLAG_DISCARDED  0x02
1144#define WEBRTC_NETEQ_CONCEALMENTFLAG_SUPRESS    0x04
1145#define WEBRTC_NETEQ_CONCEALMENTFLAG_CNGACTIVE  0x80
1146
1147int WebRtcNetEQ_VQmonRecOutStatistics(void *inst, uint16_t *validVoiceDurationMs,
1148                                      uint16_t *concealedVoiceDurationMs,
1149                                      uint8_t *concealedVoiceFlags)
1150{
1151    MainInst_t *NetEqMainInst = (MainInst_t*) inst;
1152    int16_t fs_mult;
1153    int16_t ms_lost;
1154    if (NetEqMainInst == NULL) return (-1);
1155    fs_mult = WebRtcSpl_DivW32W16ResW16(NetEqMainInst->MCUinst.fs, 8000);
1156
1157    ms_lost = WebRtcSpl_DivW32W16ResW16(
1158        (int32_t) NetEqMainInst->DSPinst.w16_concealedTS, (int16_t) (8 * fs_mult));
1159    if (ms_lost > NetEqMainInst->DSPinst.millisecondsPerCall) ms_lost
1160        = NetEqMainInst->DSPinst.millisecondsPerCall;
1161
1162    *validVoiceDurationMs = NetEqMainInst->DSPinst.millisecondsPerCall - ms_lost;
1163    *concealedVoiceDurationMs = ms_lost;
1164    if (ms_lost > 0)
1165    {
1166        *concealedVoiceFlags = WEBRTC_NETEQ_CONCEALMENTFLAG_LOST;
1167    }
1168    else
1169    {
1170        *concealedVoiceFlags = 0;
1171    }
1172    NetEqMainInst->DSPinst.w16_concealedTS -= ms_lost * (8 * fs_mult);
1173
1174    return (0);
1175}
1176
1177int WebRtcNetEQ_VQmonGetConfiguration(void *inst, uint16_t *absMaxDelayMs,
1178                                      uint8_t *adaptationRate)
1179{
1180    /* Dummy check the inst, just to avoid compiler warnings. */
1181    if (inst == NULL)
1182    {
1183        /* Do nothing. */
1184    }
1185
1186    /* Hardcoded variables that are used for VQmon as jitter buffer parameters */
1187    *absMaxDelayMs = 240;
1188    *adaptationRate = 1;
1189    return (0);
1190}
1191
1192int WebRtcNetEQ_VQmonGetRxStatistics(void *inst, uint16_t *avgDelayMs,
1193                                     uint16_t *maxDelayMs)
1194{
1195    MainInst_t *NetEqMainInst = (MainInst_t*) inst;
1196    if (NetEqMainInst == NULL) return (-1);
1197    *avgDelayMs = (uint16_t) (NetEqMainInst->MCUinst.BufferStat_inst.avgDelayMsQ8 >> 8);
1198    *maxDelayMs = (uint16_t) NetEqMainInst->MCUinst.BufferStat_inst.maxDelayMs;
1199    return (0);
1200}
1201
1202/*************************************
1203 * Statistics functions
1204 */
1205
1206/* Get the "in-call" statistics from NetEQ.
1207 * The statistics are reset after the query. */
1208int WebRtcNetEQ_GetNetworkStatistics(void *inst, WebRtcNetEQ_NetworkStatistics *stats)
1209
1210{
1211
1212    uint16_t tempU16;
1213    uint32_t tempU32, tempU32_2;
1214    int numShift;
1215    MainInst_t *NetEqMainInst = (MainInst_t*) inst;
1216
1217    /* Instance sanity */
1218    if (NetEqMainInst == NULL) return (-1);
1219
1220    stats->addedSamples = NetEqMainInst->DSPinst.statInst.addedSamples;
1221
1222    /*******************/
1223    /* Get buffer size */
1224    /*******************/
1225
1226    if (NetEqMainInst->MCUinst.fs != 0)
1227    {
1228        int32_t temp32;
1229        /* Query packet buffer for number of samples. */
1230        temp32 = WebRtcNetEQ_PacketBufferGetSize(
1231            &NetEqMainInst->MCUinst.PacketBuffer_inst,
1232            &NetEqMainInst->MCUinst.codec_DB_inst,
1233            NetEqMainInst->MCUinst.av_sync);
1234
1235        /* Divide by sample rate.
1236         * Calculate temp32 * 1000 / fs to get result in ms. */
1237        stats->currentBufferSize = (uint16_t)
1238            WebRtcSpl_DivU32U16(temp32 * 1000, NetEqMainInst->MCUinst.fs);
1239
1240        /* Add number of samples yet to play in sync buffer. */
1241        temp32 = (int32_t) (NetEqMainInst->DSPinst.endPosition -
1242            NetEqMainInst->DSPinst.curPosition);
1243        stats->currentBufferSize += (uint16_t)
1244            WebRtcSpl_DivU32U16(temp32 * 1000, NetEqMainInst->MCUinst.fs);
1245    }
1246    else
1247    {
1248        /* Sample rate not initialized. */
1249        stats->currentBufferSize = 0;
1250    }
1251
1252    /***************************/
1253    /* Get optimal buffer size */
1254    /***************************/
1255
1256    if (NetEqMainInst->MCUinst.fs != 0)
1257    {
1258        /* preferredBufferSize = Bopt * packSizeSamples / (fs/1000) */
1259        stats->preferredBufferSize
1260            = (uint16_t) WEBRTC_SPL_MUL_16_16(
1261                (int16_t) ((NetEqMainInst->MCUinst.BufferStat_inst.Automode_inst.optBufLevel) >> 8), /* optimal buffer level in packets shifted to Q0 */
1262                WebRtcSpl_DivW32W16ResW16(
1263                    (int32_t) NetEqMainInst->MCUinst.BufferStat_inst.Automode_inst.packetSpeechLenSamp, /* samples per packet */
1264                    WebRtcSpl_DivW32W16ResW16( (int32_t) NetEqMainInst->MCUinst.fs, (int16_t) 1000 ) /* samples per ms */
1265                ) );
1266
1267        /* add extra delay */
1268        if (NetEqMainInst->MCUinst.BufferStat_inst.Automode_inst.extraDelayMs > 0)
1269        {
1270            stats->preferredBufferSize
1271                += NetEqMainInst->MCUinst.BufferStat_inst.Automode_inst.extraDelayMs;
1272        }
1273    }
1274    else
1275    {
1276        /* sample rate not initialized */
1277        stats->preferredBufferSize = 0;
1278    }
1279
1280    /***********************************/
1281    /* Check if jitter peaks are found */
1282    /***********************************/
1283
1284    stats->jitterPeaksFound =
1285        NetEqMainInst->MCUinst.BufferStat_inst.Automode_inst.peakFound;
1286
1287    /***********************/
1288    /* Calculate loss rate */
1289    /***********************/
1290
1291    /* timestamps elapsed since last report */
1292    tempU32 = NetEqMainInst->MCUinst.lastReportTS;
1293
1294    if (NetEqMainInst->MCUinst.lostTS == 0)
1295    {
1296        /* no losses */
1297        stats->currentPacketLossRate = 0;
1298    }
1299    else if (NetEqMainInst->MCUinst.lostTS < tempU32)
1300    {
1301        /* calculate shifts; we want the result in Q14 */
1302        numShift = WebRtcSpl_NormU32(NetEqMainInst->MCUinst.lostTS); /* numerator shift for normalize */
1303
1304        if (numShift < 14)
1305        {
1306            /* cannot shift numerator 14 steps; shift denominator too */
1307            tempU32 = WEBRTC_SPL_RSHIFT_U32(tempU32, 14-numShift); /* right-shift */
1308        }
1309        else
1310        {
1311            /* shift no more than 14 steps */
1312            numShift = 14;
1313        }
1314
1315        if (tempU32 == 0)
1316        {
1317            /* check for zero denominator; result should be zero in this case */
1318            stats->currentPacketLossRate = 0;
1319        }
1320        else
1321        {
1322            /* check that denominator fits in signed 16-bit */
1323            while (tempU32 > WEBRTC_SPL_WORD16_MAX)
1324            {
1325                tempU32 >>= 1; /* right-shift 1 step */
1326                numShift--; /* compensate in numerator */
1327            }
1328            tempU16 = (uint16_t) tempU32;
1329
1330            /* do the shift of numerator */
1331            tempU32
1332                = WEBRTC_SPL_SHIFT_W32( (uint32_t) NetEqMainInst->MCUinst.lostTS, numShift);
1333
1334            stats->currentPacketLossRate = (uint16_t) WebRtcSpl_DivU32U16(tempU32,
1335                tempU16);
1336        }
1337    }
1338    else
1339    {
1340        /* lost count is larger than elapsed time count; probably timestamp wrap-around or something else wrong */
1341        /* set loss rate = 1 */
1342        stats->currentPacketLossRate = 1 << 14; /* 1 in Q14 */
1343    }
1344
1345    /**************************/
1346    /* Calculate discard rate */
1347    /**************************/
1348
1349    /* timestamps elapsed since last report */
1350    tempU32 = NetEqMainInst->MCUinst.lastReportTS;
1351
1352    /* number of discarded samples */
1353    tempU32_2
1354        = WEBRTC_SPL_MUL_16_U16( (int16_t) NetEqMainInst->MCUinst.PacketBuffer_inst.packSizeSamples,
1355            NetEqMainInst->MCUinst.PacketBuffer_inst.discardedPackets);
1356
1357    if (tempU32_2 == 0)
1358    {
1359        /* no discarded samples */
1360        stats->currentDiscardRate = 0;
1361    }
1362    else if (tempU32_2 < tempU32)
1363    {
1364        /* calculate shifts; we want the result in Q14 */
1365        numShift = WebRtcSpl_NormU32(tempU32_2); /* numerator shift for normalize */
1366
1367        if (numShift < 14)
1368        {
1369            /* cannot shift numerator 14 steps; shift denominator too */
1370            tempU32 = WEBRTC_SPL_RSHIFT_U32(tempU32, 14-numShift); /* right-shift */
1371        }
1372        else
1373        {
1374            /* shift no more than 14 steps */
1375            numShift = 14;
1376        }
1377
1378        if (tempU32 == 0)
1379        {
1380            /* check for zero denominator; result should be zero in this case */
1381            stats->currentDiscardRate = 0;
1382        }
1383        else
1384        {
1385            /* check that denominator fits in signed 16-bit */
1386            while (tempU32 > WEBRTC_SPL_WORD16_MAX)
1387            {
1388                tempU32 >>= 1; /* right-shift 1 step */
1389                numShift--; /* compensate in numerator */
1390            }
1391            tempU16 = (uint16_t) tempU32;
1392
1393            /* do the shift of numerator */
1394            tempU32 = WEBRTC_SPL_SHIFT_W32( tempU32_2, numShift);
1395
1396            stats->currentDiscardRate = (uint16_t) WebRtcSpl_DivU32U16(tempU32, tempU16);
1397        }
1398    }
1399    else
1400    {
1401        /* lost count is larger than elapsed time count; probably timestamp wrap-around or something else wrong */
1402        /* set loss rate = 1 */
1403        stats->currentDiscardRate = 1 << 14; /* 1 in Q14 */
1404    }
1405
1406    /*************************************************************/
1407    /* Calculate Accelerate, Expand and Pre-emptive Expand rates */
1408    /*************************************************************/
1409
1410    /* timestamps elapsed since last report */
1411    tempU32 = NetEqMainInst->MCUinst.lastReportTS;
1412
1413    if (NetEqMainInst->DSPinst.statInst.accelerateLength == 0)
1414    {
1415        /* no accelerate */
1416        stats->currentAccelerateRate = 0;
1417    }
1418    else if (NetEqMainInst->DSPinst.statInst.accelerateLength < tempU32)
1419    {
1420        /* calculate shifts; we want the result in Q14 */
1421        numShift = WebRtcSpl_NormU32(NetEqMainInst->DSPinst.statInst.accelerateLength); /* numerator shift for normalize */
1422
1423        if (numShift < 14)
1424        {
1425            /* cannot shift numerator 14 steps; shift denominator too */
1426            tempU32 = WEBRTC_SPL_RSHIFT_U32(tempU32, 14-numShift); /* right-shift */
1427        }
1428        else
1429        {
1430            /* shift no more than 14 steps */
1431            numShift = 14;
1432        }
1433
1434        if (tempU32 == 0)
1435        {
1436            /* check for zero denominator; result should be zero in this case */
1437            stats->currentAccelerateRate = 0;
1438        }
1439        else
1440        {
1441            /* check that denominator fits in signed 16-bit */
1442            while (tempU32 > WEBRTC_SPL_WORD16_MAX)
1443            {
1444                tempU32 >>= 1; /* right-shift 1 step */
1445                numShift--; /* compensate in numerator */
1446            }
1447            tempU16 = (uint16_t) tempU32;
1448
1449            /* do the shift of numerator */
1450            tempU32
1451                = WEBRTC_SPL_SHIFT_W32( NetEqMainInst->DSPinst.statInst.accelerateLength, numShift);
1452
1453            stats->currentAccelerateRate = (uint16_t) WebRtcSpl_DivU32U16(tempU32,
1454                tempU16);
1455        }
1456    }
1457    else
1458    {
1459        /* lost count is larger than elapsed time count; probably timestamp wrap-around or something else wrong */
1460        /* set loss rate = 1 */
1461        stats->currentAccelerateRate = 1 << 14; /* 1 in Q14 */
1462    }
1463
1464    /* timestamps elapsed since last report */
1465    tempU32 = NetEqMainInst->MCUinst.lastReportTS;
1466
1467    if (NetEqMainInst->DSPinst.statInst.expandLength == 0)
1468    {
1469        /* no expand */
1470        stats->currentExpandRate = 0;
1471    }
1472    else if (NetEqMainInst->DSPinst.statInst.expandLength < tempU32)
1473    {
1474        /* calculate shifts; we want the result in Q14 */
1475        numShift = WebRtcSpl_NormU32(NetEqMainInst->DSPinst.statInst.expandLength); /* numerator shift for normalize */
1476
1477        if (numShift < 14)
1478        {
1479            /* cannot shift numerator 14 steps; shift denominator too */
1480            tempU32 = WEBRTC_SPL_RSHIFT_U32(tempU32, 14-numShift); /* right-shift */
1481        }
1482        else
1483        {
1484            /* shift no more than 14 steps */
1485            numShift = 14;
1486        }
1487
1488        if (tempU32 == 0)
1489        {
1490            /* check for zero denominator; result should be zero in this case */
1491            stats->currentExpandRate = 0;
1492        }
1493        else
1494        {
1495            /* check that denominator fits in signed 16-bit */
1496            while (tempU32 > WEBRTC_SPL_WORD16_MAX)
1497            {
1498                tempU32 >>= 1; /* right-shift 1 step */
1499                numShift--; /* compensate in numerator */
1500            }
1501            tempU16 = (uint16_t) tempU32;
1502
1503            /* do the shift of numerator */
1504            tempU32
1505                = WEBRTC_SPL_SHIFT_W32( NetEqMainInst->DSPinst.statInst.expandLength, numShift);
1506
1507            stats->currentExpandRate = (uint16_t) WebRtcSpl_DivU32U16(tempU32, tempU16);
1508        }
1509    }
1510    else
1511    {
1512        /* lost count is larger than elapsed time count; probably timestamp wrap-around or something else wrong */
1513        /* set loss rate = 1 */
1514        stats->currentExpandRate = 1 << 14; /* 1 in Q14 */
1515    }
1516
1517    /* timestamps elapsed since last report */
1518    tempU32 = NetEqMainInst->MCUinst.lastReportTS;
1519
1520    if (NetEqMainInst->DSPinst.statInst.preemptiveLength == 0)
1521    {
1522        /* no pre-emptive expand */
1523        stats->currentPreemptiveRate = 0;
1524    }
1525    else if (NetEqMainInst->DSPinst.statInst.preemptiveLength < tempU32)
1526    {
1527        /* calculate shifts; we want the result in Q14 */
1528        numShift = WebRtcSpl_NormU32(NetEqMainInst->DSPinst.statInst.preemptiveLength); /* numerator shift for normalize */
1529
1530        if (numShift < 14)
1531        {
1532            /* cannot shift numerator 14 steps; shift denominator too */
1533            tempU32 = WEBRTC_SPL_RSHIFT_U32(tempU32, 14-numShift); /* right-shift */
1534        }
1535        else
1536        {
1537            /* shift no more than 14 steps */
1538            numShift = 14;
1539        }
1540
1541        if (tempU32 == 0)
1542        {
1543            /* check for zero denominator; result should be zero in this case */
1544            stats->currentPreemptiveRate = 0;
1545        }
1546        else
1547        {
1548            /* check that denominator fits in signed 16-bit */
1549            while (tempU32 > WEBRTC_SPL_WORD16_MAX)
1550            {
1551                tempU32 >>= 1; /* right-shift 1 step */
1552                numShift--; /* compensate in numerator */
1553            }
1554            tempU16 = (uint16_t) tempU32;
1555
1556            /* do the shift of numerator */
1557            tempU32
1558                = WEBRTC_SPL_SHIFT_W32( NetEqMainInst->DSPinst.statInst.preemptiveLength, numShift);
1559
1560            stats->currentPreemptiveRate = (uint16_t) WebRtcSpl_DivU32U16(tempU32,
1561                tempU16);
1562        }
1563    }
1564    else
1565    {
1566        /* lost count is larger than elapsed time count; probably timestamp wrap-around or something else wrong */
1567        /* set loss rate = 1 */
1568        stats->currentPreemptiveRate = 1 << 14; /* 1 in Q14 */
1569    }
1570
1571    stats->clockDriftPPM = WebRtcNetEQ_AverageIAT(
1572        &NetEqMainInst->MCUinst.BufferStat_inst.Automode_inst);
1573
1574    /* reset counters */
1575    WebRtcNetEQ_ResetMcuInCallStats(&(NetEqMainInst->MCUinst));
1576    WebRtcNetEQ_ClearInCallStats(&(NetEqMainInst->DSPinst));
1577
1578    return (0);
1579}
1580
1581int WebRtcNetEQ_GetRawFrameWaitingTimes(void *inst,
1582                                        int max_length,
1583                                        int* waiting_times_ms) {
1584  int i = 0;
1585  MainInst_t *main_inst = (MainInst_t*) inst;
1586  if (main_inst == NULL) return -1;
1587
1588  while ((i < max_length) && (i < main_inst->MCUinst.len_waiting_times)) {
1589    waiting_times_ms[i] = main_inst->MCUinst.waiting_times[i] *
1590        main_inst->DSPinst.millisecondsPerCall;
1591    ++i;
1592  }
1593  assert(i <= kLenWaitingTimes);
1594  WebRtcNetEQ_ResetWaitingTimeStats(&main_inst->MCUinst);
1595  return i;
1596}
1597
1598/****************************************************************************
1599 * WebRtcNetEQ_SetVADInstance(...)
1600 *
1601 * Provide a pointer to an allocated VAD instance. If function is never
1602 * called or it is called with NULL pointer as VAD_inst, the post-decode
1603 * VAD functionality is disabled. Also provide pointers to init, setmode
1604 * and VAD functions. These are typically pointers to WebRtcVad_Init,
1605 * WebRtcVad_set_mode and WebRtcVad_Process, respectively, all found in the
1606 * interface file webrtc_vad.h.
1607 *
1608 * Input:
1609 *      - NetEQ_inst        : NetEQ instance
1610 *              - VADinst                   : VAD instance
1611 *              - initFunction      : Pointer to VAD init function
1612 *              - setmodeFunction   : Pointer to VAD setmode function
1613 *              - VADfunction       : Pointer to VAD function
1614 *
1615 * Output:
1616 *              - NetEQ_inst        : Updated NetEQ instance
1617 *
1618 * Return value                     :  0 - Ok
1619 *                                                    -1 - Error
1620 */
1621
1622int WebRtcNetEQ_SetVADInstance(void *NetEQ_inst, void *VAD_inst,
1623                               WebRtcNetEQ_VADInitFunction initFunction,
1624                               WebRtcNetEQ_VADSetmodeFunction setmodeFunction,
1625                               WebRtcNetEQ_VADFunction VADFunction)
1626{
1627
1628    /* Typecast to internal instance type */
1629    MainInst_t *NetEqMainInst = (MainInst_t*) NetEQ_inst;
1630    if (NetEqMainInst == NULL)
1631    {
1632        return (-1);
1633    }
1634
1635#ifdef NETEQ_VAD
1636
1637    /* Store pointer in PostDecode VAD struct */
1638    NetEqMainInst->DSPinst.VADInst.VADState = VAD_inst;
1639
1640    /* Store function pointers */
1641    NetEqMainInst->DSPinst.VADInst.initFunction = initFunction;
1642    NetEqMainInst->DSPinst.VADInst.setmodeFunction = setmodeFunction;
1643    NetEqMainInst->DSPinst.VADInst.VADFunction = VADFunction;
1644
1645    /* Call init function and return the result (ok or fail) */
1646    return(WebRtcNetEQ_InitVAD(&NetEqMainInst->DSPinst.VADInst, NetEqMainInst->DSPinst.fs));
1647
1648#else /* NETEQ_VAD not defined */
1649    return (-1);
1650#endif /* NETEQ_VAD */
1651
1652}
1653
1654/****************************************************************************
1655 * WebRtcNetEQ_SetVADMode(...)
1656 *
1657 * Pass an aggressiveness mode parameter to the post-decode VAD instance.
1658 * If this function is never called, mode 0 (quality mode) is used as default.
1659 *
1660 * Input:
1661 *      - inst          : NetEQ instance
1662 *              - mode                  : mode parameter (same range as WebRtc VAD mode)
1663 *
1664 * Output:
1665 *              - inst          : Updated NetEQ instance
1666 *
1667 * Return value                 :  0 - Ok
1668 *                                                -1 - Error
1669 */
1670
1671int WebRtcNetEQ_SetVADMode(void *inst, int mode)
1672{
1673
1674    /* Typecast to internal instance type */
1675    MainInst_t *NetEqMainInst = (MainInst_t*) inst;
1676    if (NetEqMainInst == NULL)
1677    {
1678        return (-1);
1679    }
1680
1681#ifdef NETEQ_VAD
1682
1683    /* Set mode and return result */
1684    return(WebRtcNetEQ_SetVADModeInternal(&NetEqMainInst->DSPinst.VADInst, mode));
1685
1686#else /* NETEQ_VAD not defined */
1687    return (-1);
1688#endif /* NETEQ_VAD */
1689
1690}
1691
1692void WebRtcNetEQ_GetProcessingActivity(void *inst,
1693                                       WebRtcNetEQ_ProcessingActivity *stats) {
1694  MainInst_t *NetEqMainInst = (MainInst_t*) inst;
1695
1696  stats->accelerate_bgn_samples =
1697      NetEqMainInst->DSPinst.activity_stats.accelerate_bgn_samples;
1698  stats->accelerate_normal_samples =
1699      NetEqMainInst->DSPinst.activity_stats.accelarate_normal_samples;
1700
1701  stats->expand_bgn_sampels =
1702      NetEqMainInst->DSPinst.activity_stats.expand_bgn_samples;
1703  stats->expand_normal_samples =
1704      NetEqMainInst->DSPinst.activity_stats.expand_normal_samples;
1705
1706  stats->preemptive_expand_bgn_samples =
1707      NetEqMainInst->DSPinst.activity_stats.preemptive_expand_bgn_samples;
1708  stats->preemptive_expand_normal_samples =
1709      NetEqMainInst->DSPinst.activity_stats.preemptive_expand_normal_samples;
1710
1711  stats->merge_expand_bgn_samples =
1712      NetEqMainInst->DSPinst.activity_stats.merge_expand_bgn_samples;
1713  stats->merge_expand_normal_samples =
1714      NetEqMainInst->DSPinst.activity_stats.merge_expand_normal_samples;
1715
1716  WebRtcNetEQ_ClearActivityStats(&NetEqMainInst->DSPinst);
1717}
1718
1719void WebRtcNetEQ_EnableAVSync(void* inst, int enable) {
1720  MainInst_t *NetEqMainInst = (MainInst_t*) inst;
1721  NetEqMainInst->MCUinst.av_sync = (enable != 0) ? 1 : 0;
1722}
1723
1724int WebRtcNetEQ_RecInSyncRTP(void* inst, WebRtcNetEQ_RTPInfo* rtp_info,
1725                             uint32_t receive_timestamp) {
1726  MainInst_t *NetEqMainInst = (MainInst_t*) inst;
1727  if (NetEqMainInst->MCUinst.av_sync == 0)
1728    return -1;
1729  if (WebRtcNetEQ_RecInRTPStruct(inst, rtp_info, kSyncPayload,
1730                                 SYNC_PAYLOAD_LEN_BYTES,
1731                                 receive_timestamp) < 0) {
1732    return -1;
1733  }
1734  return SYNC_PAYLOAD_LEN_BYTES;
1735}
1736
1737int WebRtcNetEQ_GetRequiredDelayMs(const void* inst) {
1738  const MainInst_t* NetEqMainInst = (MainInst_t*)inst;
1739  const AutomodeInst_t* auto_mode = (NetEqMainInst == NULL) ? NULL :
1740      &NetEqMainInst->MCUinst.BufferStat_inst.Automode_inst;
1741
1742  /* Instance sanity */
1743  if (NetEqMainInst == NULL || auto_mode == NULL)
1744    return 0;
1745
1746  if (NetEqMainInst->MCUinst.fs == 0)
1747    return 0;  // Sampling rate not initialized.
1748
1749  /* |required_delay_q8| has the unit of packets in Q8 domain, therefore,
1750   * the corresponding delay is
1751   * required_delay_ms = (1000 * required_delay_q8 * samples_per_packet /
1752   *     sample_rate_hz) / 256;
1753   */
1754  return (auto_mode->required_delay_q8 *
1755      ((auto_mode->packetSpeechLenSamp * 1000) / NetEqMainInst->MCUinst.fs) +
1756      128) >> 8;
1757}
1758
1759int WebRtcNetEQ_DecodedRtpInfo(const void* inst,
1760                               int* sequence_number,
1761                               uint32_t* timestamp) {
1762  const MainInst_t *NetEqMainInst = (inst == NULL) ? NULL :
1763      (const MainInst_t*) inst;
1764  if (NetEqMainInst->MCUinst.decoded_packet_sequence_number < 0)
1765    return -1;
1766  *sequence_number = NetEqMainInst->MCUinst.decoded_packet_sequence_number;
1767  *timestamp = NetEqMainInst->MCUinst.decoded_packet_timestamp;
1768  return 0;
1769}
Note: See TracBrowser for help on using the repository browser.