blob: d13902d2665331649055807fb420431faca76fd2 [file] [log] [blame]
niklase@google.com470e71d2011-07-07 08:21:25 +00001/*
bjornv@webrtc.orgf4b77fd2012-01-25 12:40:00 +00002 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
niklase@google.com470e71d2011-07-07 08:21:25 +00003 *
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
henrik.lundin@webrtc.orgdbba1f92011-12-20 15:45:05 +000018#include <assert.h>
niklase@google.com470e71d2011-07-07 08:21:25 +000019#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 = -((WebRtc_Word16) (macroExpr)); \
34 } \
35 return(-1); \
36 } }
37
leozwang@webrtc.org91b359e2012-02-28 17:26:14 +000038int WebRtcNetEQ_strncpy(char *strDest, int numberOfElements,
39 const char *strSource, int count)
niklase@google.com470e71d2011-07-07 08:21:25 +000040{
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/*****************************************
henrik.lundin@webrtc.org1e100a92012-09-11 09:23:32 +000059 * Error functions
niklase@google.com470e71d2011-07-07 08:21:25 +000060 */
61
niklase@google.com470e71d2011-07-07 08:21:25 +000062int WebRtcNetEQ_GetErrorCode(void *inst)
63{
64 MainInst_t *NetEqMainInst = (MainInst_t*) inst;
65 if (NetEqMainInst == NULL) return (-1);
66 return (NetEqMainInst->ErrorCode);
67}
68
leozwang@webrtc.org91b359e2012-02-28 17:26:14 +000069int WebRtcNetEQ_GetErrorName(int errorCode, char *errorName, int maxStrLen)
niklase@google.com470e71d2011-07-07 08:21:25 +000070{
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(WebRtc_Word16);
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);
kma@webrtc.orgac4d70d2012-10-05 00:19:01 +0000293
294 WebRtcSpl_Init();
295
niklase@google.com470e71d2011-07-07 08:21:25 +0000296 /* Clear memory */
297 WebRtcSpl_MemSetW16((WebRtc_Word16*) NetEqMainInst, 0,
298 (sizeof(MainInst_t) / sizeof(WebRtc_Word16)));
299 ok = WebRtcNetEQ_McuReset(&NetEqMainInst->MCUinst);
300 if (ok != 0)
301 {
302 NetEqMainInst->ErrorCode = -ok;
303 return (-1);
304 }
305 return (0);
306}
307
perkj@webrtc.org6b1bfd62011-12-02 12:48:19 +0000308int WebRtcNetEQ_GetRecommendedBufferSize(void *inst, const enum WebRtcNetEQDecoder *codec,
niklase@google.com470e71d2011-07-07 08:21:25 +0000309 int noOfCodecs, enum WebRtcNetEQNetworkType nwType,
310 int *MaxNoOfPackets, int *sizeinbytes)
311{
312 int ok = 0;
313 int multiplier;
314 MainInst_t *NetEqMainInst = (MainInst_t*) inst;
315 if (NetEqMainInst == NULL) return (-1);
316 *MaxNoOfPackets = 0;
317 *sizeinbytes = 0;
318 ok = WebRtcNetEQ_GetDefaultCodecSettings(codec, noOfCodecs, sizeinbytes, MaxNoOfPackets);
319 if (ok != 0)
320 {
321 NetEqMainInst->ErrorCode = -ok;
322 return (-1);
323 }
324 if (nwType == kUDPNormal)
325 {
326 multiplier = 1;
327 }
328 else if (nwType == kUDPVideoSync)
329 {
330 multiplier = 4;
331 }
332 else if (nwType == kTCPNormal)
333 {
334 multiplier = 4;
335 }
336 else if (nwType == kTCPLargeJitter)
337 {
338 multiplier = 8;
339 }
340 else if (nwType == kTCPXLargeJitter)
341 {
niklas.enbom@webrtc.orgcd2f1352013-01-24 22:05:30 +0000342 multiplier = 20;
niklase@google.com470e71d2011-07-07 08:21:25 +0000343 }
344 else
345 {
346 NetEqMainInst->ErrorCode = -FAULTY_NETWORK_TYPE;
347 return (-1);
348 }
349 *MaxNoOfPackets = (*MaxNoOfPackets) * multiplier;
350 *sizeinbytes = (*sizeinbytes) * multiplier;
henrik.lundin@webrtc.orgf0effa12012-09-11 12:44:06 +0000351 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000352}
353
354int WebRtcNetEQ_AssignBuffer(void *inst, int MaxNoOfPackets, void *NETEQ_Buffer_Addr,
355 int sizeinbytes)
356{
357 int ok;
358 MainInst_t *NetEqMainInst = (MainInst_t*) inst;
359 if (NetEqMainInst == NULL) return (-1);
360 ok = WebRtcNetEQ_PacketBufferInit(&NetEqMainInst->MCUinst.PacketBuffer_inst,
361 MaxNoOfPackets, (WebRtc_Word16*) NETEQ_Buffer_Addr, (sizeinbytes >> 1));
362 if (ok != 0)
363 {
364 NetEqMainInst->ErrorCode = -ok;
365 return (-1);
366 }
367 return (ok);
368}
369
370/************************************************
371 * Init functions
372 */
373
374/****************************************************************************
375 * WebRtcNetEQ_Init(...)
376 *
377 * Initialize NetEQ.
378 *
379 * Input:
380 * - inst : NetEQ instance
381 * - fs : Initial sample rate in Hz (may change with payload)
382 *
383 * Output:
384 * - inst : Initialized NetEQ instance
385 *
386 * Return value : 0 - Ok
387 * -1 - Error
388 */
389
390int WebRtcNetEQ_Init(void *inst, WebRtc_UWord16 fs)
391{
392 int ok = 0;
393
394 /* Typecast inst to internal instance format */
395 MainInst_t *NetEqMainInst = (MainInst_t*) inst;
396
397 if (NetEqMainInst == NULL)
398 {
399 return (-1);
400 }
401
402#ifdef NETEQ_VAD
403 /* Start out with no PostDecode VAD instance */
404 NetEqMainInst->DSPinst.VADInst.VADState = NULL;
405 /* Also set all VAD function pointers to NULL */
406 NetEqMainInst->DSPinst.VADInst.initFunction = NULL;
407 NetEqMainInst->DSPinst.VADInst.setmodeFunction = NULL;
408 NetEqMainInst->DSPinst.VADInst.VADFunction = NULL;
409#endif /* NETEQ_VAD */
410
411 ok = WebRtcNetEQ_DSPinit(NetEqMainInst); /* Init addresses between MCU and DSP */
412 RETURN_ON_ERROR(ok, NetEqMainInst);
413
414 ok = WebRtcNetEQ_DSPInit(&NetEqMainInst->DSPinst, fs); /* Init dsp side */
415 RETURN_ON_ERROR(ok, NetEqMainInst);
416 /* set BGN mode to default, since it is not cleared by DSP init function */
417 NetEqMainInst->DSPinst.BGNInst.bgnMode = BGN_ON;
418
419 /* init statistics functions and counters */
420 ok = WebRtcNetEQ_ClearInCallStats(&NetEqMainInst->DSPinst);
421 RETURN_ON_ERROR(ok, NetEqMainInst);
422 ok = WebRtcNetEQ_ClearPostCallStats(&NetEqMainInst->DSPinst);
423 RETURN_ON_ERROR(ok, NetEqMainInst);
424 ok = WebRtcNetEQ_ResetMcuJitterStat(&NetEqMainInst->MCUinst);
425 RETURN_ON_ERROR(ok, NetEqMainInst);
426
427 /* flush packet buffer */
428 ok = WebRtcNetEQ_PacketBufferFlush(&NetEqMainInst->MCUinst.PacketBuffer_inst);
429 RETURN_ON_ERROR(ok, NetEqMainInst);
430
431 /* set some variables to initial values */
432 NetEqMainInst->MCUinst.current_Codec = -1;
433 NetEqMainInst->MCUinst.current_Payload = -1;
434 NetEqMainInst->MCUinst.first_packet = 1;
435 NetEqMainInst->MCUinst.one_desc = 0;
436 NetEqMainInst->MCUinst.BufferStat_inst.Automode_inst.extraDelayMs = 0;
437 NetEqMainInst->MCUinst.NoOfExpandCalls = 0;
438 NetEqMainInst->MCUinst.fs = fs;
439
440#ifdef NETEQ_ATEVENT_DECODE
441 /* init DTMF decoder */
442 ok = WebRtcNetEQ_DtmfDecoderInit(&(NetEqMainInst->MCUinst.DTMF_inst),fs,560);
443 RETURN_ON_ERROR(ok, NetEqMainInst);
444#endif
445
446 /* init RTCP statistics */
447 WebRtcNetEQ_RTCPInit(&(NetEqMainInst->MCUinst.RTCP_inst), 0);
448
449 /* set BufferStat struct to zero */
450 WebRtcSpl_MemSetW16((WebRtc_Word16*) &(NetEqMainInst->MCUinst.BufferStat_inst), 0,
451 sizeof(BufstatsInst_t) / sizeof(WebRtc_Word16));
452
453 /* reset automode */
454 WebRtcNetEQ_ResetAutomode(&(NetEqMainInst->MCUinst.BufferStat_inst.Automode_inst),
455 NetEqMainInst->MCUinst.PacketBuffer_inst.maxInsertPositions);
456
457 NetEqMainInst->ErrorCode = 0;
458
459#ifdef NETEQ_STEREO
460 /* set master/slave info to undecided */
461 NetEqMainInst->masterSlave = 0;
462#endif
463
464 return (ok);
465}
466
467int WebRtcNetEQ_FlushBuffers(void *inst)
468{
469 int ok = 0;
470
471 /* Typecast inst to internal instance format */
472 MainInst_t *NetEqMainInst = (MainInst_t*) inst;
473
474 if (NetEqMainInst == NULL)
475 {
476 return (-1);
477 }
478
479 /* Flush packet buffer */
480 ok = WebRtcNetEQ_PacketBufferFlush(&NetEqMainInst->MCUinst.PacketBuffer_inst);
481 RETURN_ON_ERROR(ok, NetEqMainInst);
482
483 /* Set MCU to wait for new codec */
484 NetEqMainInst->MCUinst.first_packet = 1;
485
486 /* Flush speech buffer */
487 ok = WebRtcNetEQ_FlushSpeechBuffer(&NetEqMainInst->DSPinst);
488 RETURN_ON_ERROR(ok, NetEqMainInst);
489
490 return 0;
491}
492
493int WebRtcNetEQ_SetAVTPlayout(void *inst, int PlayoutAVTon)
494{
495 MainInst_t *NetEqMainInst = (MainInst_t*) inst;
496 if (NetEqMainInst == NULL) return (-1);
497#ifdef NETEQ_ATEVENT_DECODE
498 NetEqMainInst->MCUinst.AVT_PlayoutOn = PlayoutAVTon;
499 return(0);
500#else
501 if (PlayoutAVTon != 0)
502 {
503 NetEqMainInst->ErrorCode = -DTMF_NOT_SUPPORTED;
504 return (-1);
505 }
506 else
507 {
508 return (0);
509 }
510#endif
511}
512
513int WebRtcNetEQ_SetExtraDelay(void *inst, int DelayInMs)
514{
515 MainInst_t *NetEqMainInst = (MainInst_t*) inst;
516 if (NetEqMainInst == NULL) return (-1);
niklas.enbom@webrtc.orgcd2f1352013-01-24 22:05:30 +0000517 if ((DelayInMs < 0) || (DelayInMs > 1000))
niklase@google.com470e71d2011-07-07 08:21:25 +0000518 {
519 NetEqMainInst->ErrorCode = -FAULTY_DELAYVALUE;
520 return (-1);
521 }
522 NetEqMainInst->MCUinst.BufferStat_inst.Automode_inst.extraDelayMs = DelayInMs;
523 return (0);
524}
525
526int WebRtcNetEQ_SetPlayoutMode(void *inst, enum WebRtcNetEQPlayoutMode playoutMode)
527{
528 MainInst_t *NetEqMainInst = (MainInst_t*) inst;
529 if (NetEqMainInst == NULL) return (-1);
530 if ((playoutMode != kPlayoutOn) && (playoutMode != kPlayoutOff) && (playoutMode
531 != kPlayoutFax) && (playoutMode != kPlayoutStreaming))
532 {
533 NetEqMainInst->ErrorCode = -FAULTY_PLAYOUTMODE;
534 return (-1);
535 }
536 else
537 {
538 NetEqMainInst->MCUinst.NetEqPlayoutMode = playoutMode;
539 return (0);
540 }
541}
542
543int WebRtcNetEQ_SetBGNMode(void *inst, enum WebRtcNetEQBGNMode bgnMode)
544{
545
546 MainInst_t *NetEqMainInst = (MainInst_t*) inst;
547
548 /* Instance sanity */
549 if (NetEqMainInst == NULL) return (-1);
550
551 /* Check for corrupt/cleared instance */
552 if (NetEqMainInst->MCUinst.main_inst != NetEqMainInst)
553 {
554 /* Instance is corrupt */
555 NetEqMainInst->ErrorCode = CORRUPT_INSTANCE;
556 return (-1);
557 }
558
559 NetEqMainInst->DSPinst.BGNInst.bgnMode = (enum BGNMode) bgnMode;
560
561 return (0);
562}
563
564int WebRtcNetEQ_GetBGNMode(const void *inst, enum WebRtcNetEQBGNMode *bgnMode)
565{
566
567 const MainInst_t *NetEqMainInst = (const MainInst_t*) inst;
568
569 /* Instance sanity */
570 if (NetEqMainInst == NULL) return (-1);
571
572 *bgnMode = (enum WebRtcNetEQBGNMode) NetEqMainInst->DSPinst.BGNInst.bgnMode;
573
574 return (0);
575}
576
577/************************************************
578 * CodecDB functions
579 */
580
581int WebRtcNetEQ_CodecDbReset(void *inst)
582{
583 int ok = 0;
584 MainInst_t *NetEqMainInst = (MainInst_t*) inst;
585 if (NetEqMainInst == NULL) return (-1);
586 ok = WebRtcNetEQ_DbReset(&NetEqMainInst->MCUinst.codec_DB_inst);
587 if (ok != 0)
588 {
589 NetEqMainInst->ErrorCode = -ok;
590 return (-1);
591 }
592
593 /* set function pointers to NULL to prevent RecOut from using the codec */
594 NetEqMainInst->DSPinst.codec_ptr_inst.funcDecode = NULL;
595 NetEqMainInst->DSPinst.codec_ptr_inst.funcDecodeRCU = NULL;
596 NetEqMainInst->DSPinst.codec_ptr_inst.funcAddLatePkt = NULL;
597 NetEqMainInst->DSPinst.codec_ptr_inst.funcDecode = NULL;
598 NetEqMainInst->DSPinst.codec_ptr_inst.funcDecodeInit = NULL;
599 NetEqMainInst->DSPinst.codec_ptr_inst.funcDecodePLC = NULL;
600 NetEqMainInst->DSPinst.codec_ptr_inst.funcGetMDinfo = NULL;
601 NetEqMainInst->DSPinst.codec_ptr_inst.funcUpdBWEst = NULL;
602 NetEqMainInst->DSPinst.codec_ptr_inst.funcGetErrorCode = NULL;
603
604 return (0);
605}
606
607int WebRtcNetEQ_CodecDbGetSizeInfo(void *inst, WebRtc_Word16 *UsedEntries,
608 WebRtc_Word16 *MaxEntries)
609{
610 MainInst_t *NetEqMainInst = (MainInst_t*) inst;
611 if (NetEqMainInst == NULL) return (-1);
612 *MaxEntries = NUM_CODECS;
613 *UsedEntries = NetEqMainInst->MCUinst.codec_DB_inst.nrOfCodecs;
614 return (0);
615}
616
617int WebRtcNetEQ_CodecDbGetCodecInfo(void *inst, WebRtc_Word16 Entry,
618 enum WebRtcNetEQDecoder *codec)
619{
620 int i;
621 MainInst_t *NetEqMainInst = (MainInst_t*) inst;
622 if (NetEqMainInst == NULL) return (-1);
623 *codec = (enum WebRtcNetEQDecoder) 0;
624 if ((Entry >= 0) && (Entry < NetEqMainInst->MCUinst.codec_DB_inst.nrOfCodecs))
625 {
626 for (i = 0; i < NUM_TOTAL_CODECS; i++)
627 {
628 if (NetEqMainInst->MCUinst.codec_DB_inst.position[i] == Entry)
629 {
630 *codec = (enum WebRtcNetEQDecoder) i;
631 }
632 }
633 }
634 else
635 {
636 NetEqMainInst->ErrorCode = -(CODEC_DB_NOT_EXIST1);
637 return (-1);
638 }
639 return (0);
640}
641
642int WebRtcNetEQ_CodecDbAdd(void *inst, WebRtcNetEQ_CodecDef *codecInst)
643{
644 int ok = 0;
645 MainInst_t *NetEqMainInst = (MainInst_t*) inst;
646 if (NetEqMainInst == NULL) return (-1);
647 ok = WebRtcNetEQ_DbAdd(&NetEqMainInst->MCUinst.codec_DB_inst, codecInst->codec,
648 codecInst->payloadType, codecInst->funcDecode, codecInst->funcDecodeRCU,
649 codecInst->funcDecodePLC, codecInst->funcDecodeInit, codecInst->funcAddLatePkt,
650 codecInst->funcGetMDinfo, codecInst->funcGetPitch, codecInst->funcUpdBWEst,
tina.legrand@webrtc.org5ac387c2012-11-19 08:02:55 +0000651 codecInst->funcDurationEst, codecInst->funcGetErrorCode,
652 codecInst->codec_state, codecInst->codec_fs);
niklase@google.com470e71d2011-07-07 08:21:25 +0000653 if (ok != 0)
654 {
655 NetEqMainInst->ErrorCode = -ok;
656 return (-1);
657 }
658 return (ok);
659}
660
661int WebRtcNetEQ_CodecDbRemove(void *inst, enum WebRtcNetEQDecoder codec)
662{
663 int ok = 0;
664 MainInst_t *NetEqMainInst = (MainInst_t*) inst;
665 if (NetEqMainInst == NULL) return (-1);
666
667 /* check if currently used codec is being removed */
668 if (NetEqMainInst->MCUinst.current_Codec == (WebRtc_Word16) codec)
669 {
670 /* set function pointers to NULL to prevent RecOut from using the codec */
671 NetEqMainInst->DSPinst.codec_ptr_inst.funcDecode = NULL;
672 NetEqMainInst->DSPinst.codec_ptr_inst.funcDecodeRCU = NULL;
673 NetEqMainInst->DSPinst.codec_ptr_inst.funcAddLatePkt = NULL;
674 NetEqMainInst->DSPinst.codec_ptr_inst.funcDecode = NULL;
675 NetEqMainInst->DSPinst.codec_ptr_inst.funcDecodeInit = NULL;
676 NetEqMainInst->DSPinst.codec_ptr_inst.funcDecodePLC = NULL;
677 NetEqMainInst->DSPinst.codec_ptr_inst.funcGetMDinfo = NULL;
678 NetEqMainInst->DSPinst.codec_ptr_inst.funcUpdBWEst = NULL;
679 NetEqMainInst->DSPinst.codec_ptr_inst.funcGetErrorCode = NULL;
680 }
681
682 ok = WebRtcNetEQ_DbRemove(&NetEqMainInst->MCUinst.codec_DB_inst, codec);
683 if (ok != 0)
684 {
685 NetEqMainInst->ErrorCode = -ok;
686 return (-1);
687 }
688 return (ok);
689}
690
691/*********************************
692 * Real-time functions
693 */
694
695int WebRtcNetEQ_RecIn(void *inst, WebRtc_Word16 *p_w16datagramstart, WebRtc_Word16 w16_RTPlen,
696 WebRtc_UWord32 uw32_timeRec)
697{
698 int ok = 0;
699 RTPPacket_t RTPpacket;
700 MainInst_t *NetEqMainInst = (MainInst_t*) inst;
701 if (NetEqMainInst == NULL) return (-1);
702
703 /* Check for corrupt/cleared instance */
704 if (NetEqMainInst->MCUinst.main_inst != NetEqMainInst)
705 {
706 /* Instance is corrupt */
707 NetEqMainInst->ErrorCode = CORRUPT_INSTANCE;
708 return (-1);
709 }
710
711 /* Parse RTP header */
712 ok = WebRtcNetEQ_RTPPayloadInfo(p_w16datagramstart, w16_RTPlen, &RTPpacket);
713 if (ok != 0)
714 {
715 NetEqMainInst->ErrorCode = -ok;
716 return (-1);
717 }
718
719 ok = WebRtcNetEQ_RecInInternal(&NetEqMainInst->MCUinst, &RTPpacket, uw32_timeRec);
720 if (ok != 0)
721 {
722 NetEqMainInst->ErrorCode = -ok;
723 return (-1);
724 }
725 return (ok);
726}
727
728/****************************************************************************
729 * WebRtcNetEQ_RecInRTPStruct(...)
730 *
731 * Alternative RecIn function, used when the RTP data has already been
732 * parsed into an RTP info struct (WebRtcNetEQ_RTPInfo).
733 *
734 * Input:
735 * - inst : NetEQ instance
736 * - rtpInfo : Pointer to RTP info
737 * - payloadPtr : Pointer to the RTP payload (first byte after header)
738 * - payloadLenBytes : Length (in bytes) of the payload in payloadPtr
739 * - timeRec : Receive time (in timestamps of the used codec)
740 *
741 * Return value : 0 - Ok
742 * -1 - Error
743 */
744int WebRtcNetEQ_RecInRTPStruct(void *inst, WebRtcNetEQ_RTPInfo *rtpInfo,
745 const WebRtc_UWord8 *payloadPtr, WebRtc_Word16 payloadLenBytes,
746 WebRtc_UWord32 uw32_timeRec)
747{
748 int ok = 0;
749 RTPPacket_t RTPpacket;
750 MainInst_t *NetEqMainInst = (MainInst_t*) inst;
751 if (NetEqMainInst == NULL)
752 {
753 return (-1);
754 }
755
756 /* Check for corrupt/cleared instance */
757 if (NetEqMainInst->MCUinst.main_inst != NetEqMainInst)
758 {
759 /* Instance is corrupt */
760 NetEqMainInst->ErrorCode = CORRUPT_INSTANCE;
761 return (-1);
762 }
763
764 /* Load NetEQ's RTP struct from Module RTP struct */
765 RTPpacket.payloadType = rtpInfo->payloadType;
766 RTPpacket.seqNumber = rtpInfo->sequenceNumber;
767 RTPpacket.timeStamp = rtpInfo->timeStamp;
768 RTPpacket.ssrc = rtpInfo->SSRC;
769 RTPpacket.payload = (const WebRtc_Word16*) payloadPtr;
770 RTPpacket.payloadLen = payloadLenBytes;
771 RTPpacket.starts_byte1 = 0;
772
773 ok = WebRtcNetEQ_RecInInternal(&NetEqMainInst->MCUinst, &RTPpacket, uw32_timeRec);
774 if (ok != 0)
775 {
776 NetEqMainInst->ErrorCode = -ok;
777 return (-1);
778 }
779 return (ok);
780}
781
782int WebRtcNetEQ_RecOut(void *inst, WebRtc_Word16 *pw16_outData, WebRtc_Word16 *pw16_len)
783{
784 int ok = 0;
785 MainInst_t *NetEqMainInst = (MainInst_t*) inst;
786#ifdef NETEQ_STEREO
787 MasterSlaveInfo msInfo;
788 msInfo.msMode = NETEQ_MONO;
789#endif
790
791 if (NetEqMainInst == NULL) return (-1);
792
793 /* Check for corrupt/cleared instance */
794 if (NetEqMainInst->DSPinst.main_inst != NetEqMainInst)
795 {
796 /* Instance is corrupt */
797 NetEqMainInst->ErrorCode = CORRUPT_INSTANCE;
798 return (-1);
799 }
800
801#ifdef NETEQ_STEREO
802 NetEqMainInst->DSPinst.msInfo = &msInfo;
803#endif
804
805 ok = WebRtcNetEQ_RecOutInternal(&NetEqMainInst->DSPinst, pw16_outData,
806 pw16_len, 0 /* not BGN only */);
807 if (ok != 0)
808 {
809 NetEqMainInst->ErrorCode = -ok;
810 return (-1);
811 }
812 return (ok);
813}
814
815/****************************************************************************
816 * WebRtcNetEQ_RecOutMasterSlave(...)
817 *
818 * RecOut function for running several NetEQ instances in master/slave mode.
819 * One master can be used to control several slaves.
820 *
821 * Input:
822 * - inst : NetEQ instance
823 * - isMaster : Non-zero indicates that this is the master channel
824 * - msInfo : (slave only) Information from master
825 *
826 * Output:
827 * - inst : Updated NetEQ instance
828 * - pw16_outData : Pointer to vector where output should be written
829 * - pw16_len : Pointer to variable where output length is returned
830 * - msInfo : (master only) Information to slave(s)
831 *
832 * Return value : 0 - Ok
833 * -1 - Error
834 */
835
836int WebRtcNetEQ_RecOutMasterSlave(void *inst, WebRtc_Word16 *pw16_outData,
837 WebRtc_Word16 *pw16_len, void *msInfo,
838 WebRtc_Word16 isMaster)
839{
840#ifndef NETEQ_STEREO
841 /* Stereo not supported */
842 return(-1);
843#else
844 int ok = 0;
845 MainInst_t *NetEqMainInst = (MainInst_t*) inst;
846
847 if (NetEqMainInst == NULL) return (-1);
848
849 /* Check for corrupt/cleared instance */
850 if (NetEqMainInst->DSPinst.main_inst != NetEqMainInst)
851 {
852 /* Instance is corrupt */
853 NetEqMainInst->ErrorCode = CORRUPT_INSTANCE;
854 return (-1);
855 }
856
857 if (msInfo == NULL)
858 {
859 /* msInfo not provided */
860 NetEqMainInst->ErrorCode = NETEQ_OTHER_ERROR;
861 return (-1);
862 }
863
864 /* translate from external to internal Master/Slave information */
865 NetEqMainInst->DSPinst.msInfo = (MasterSlaveInfo *) msInfo;
866
867 /* check that we have not done a master/slave switch without first re-initializing */
868 if ((NetEqMainInst->masterSlave == 1 && !isMaster) || /* switch from master to slave */
869 (NetEqMainInst->masterSlave == 2 && isMaster)) /* switch from slave to master */
870 {
871 NetEqMainInst->ErrorCode = ILLEGAL_MASTER_SLAVE_SWITCH;
872 return (-1);
873 }
874
875 if (!isMaster)
876 {
877 /* this is the slave */
878 NetEqMainInst->masterSlave = 2;
879 NetEqMainInst->DSPinst.msInfo->msMode = NETEQ_SLAVE;
880 }
881 else
882 {
883 NetEqMainInst->DSPinst.msInfo->msMode = NETEQ_MASTER;
884 }
885
886 ok = WebRtcNetEQ_RecOutInternal(&NetEqMainInst->DSPinst, pw16_outData,
887 pw16_len, 0 /* not BGN only */);
888 if (ok != 0)
889 {
890 NetEqMainInst->ErrorCode = -ok;
891 return (-1);
892 }
893
894 if (isMaster)
895 {
896 /* this is the master */
897 NetEqMainInst->masterSlave = 1;
898 }
899
900 return (ok);
901#endif
902}
903
904int WebRtcNetEQ_GetMasterSlaveInfoSize()
905{
906#ifdef NETEQ_STEREO
907 return (sizeof(MasterSlaveInfo));
908#else
909 return(-1);
910#endif
911}
912
913/* Special RecOut that does not do any decoding. */
914int WebRtcNetEQ_RecOutNoDecode(void *inst, WebRtc_Word16 *pw16_outData,
915 WebRtc_Word16 *pw16_len)
916{
917 int ok = 0;
918 MainInst_t *NetEqMainInst = (MainInst_t*) inst;
919#ifdef NETEQ_STEREO
920 MasterSlaveInfo msInfo;
921#endif
922
923 if (NetEqMainInst == NULL) return (-1);
924
925 /* Check for corrupt/cleared instance */
926 if (NetEqMainInst->DSPinst.main_inst != NetEqMainInst)
927 {
928 /* Instance is corrupt */
929 NetEqMainInst->ErrorCode = CORRUPT_INSTANCE;
930 return (-1);
931 }
932
933#ifdef NETEQ_STEREO
934 /* keep same mode as before */
935 switch (NetEqMainInst->masterSlave)
936 {
937 case 1:
938 {
939 msInfo.msMode = NETEQ_MASTER;
940 break;
941 }
942 case 2:
943 {
944 msInfo.msMode = NETEQ_SLAVE;
945 break;
946 }
947 default:
948 {
949 msInfo.msMode = NETEQ_MONO;
950 break;
951 }
952 }
953
954 NetEqMainInst->DSPinst.msInfo = &msInfo;
955#endif
956
957 ok = WebRtcNetEQ_RecOutInternal(&NetEqMainInst->DSPinst, pw16_outData,
958 pw16_len, 1 /* BGN only */);
959 if (ok != 0)
960 {
961 NetEqMainInst->ErrorCode = -ok;
962 return (-1);
963 }
964 return (ok);
965}
966
967int WebRtcNetEQ_GetRTCPStats(void *inst, WebRtcNetEQ_RTCPStat *RTCP_inst)
968{
969 int ok = 0;
970 MainInst_t *NetEqMainInst = (MainInst_t*) inst;
971 if (NetEqMainInst == NULL) return (-1);
972 ok = WebRtcNetEQ_RTCPGetStats(&NetEqMainInst->MCUinst.RTCP_inst,
973 &RTCP_inst->fraction_lost, &RTCP_inst->cum_lost, &RTCP_inst->ext_max,
974 &RTCP_inst->jitter, 0);
975 if (ok != 0)
976 {
977 NetEqMainInst->ErrorCode = -ok;
978 return (-1);
979 }
980 return (ok);
981}
982
983int WebRtcNetEQ_GetRTCPStatsNoReset(void *inst, WebRtcNetEQ_RTCPStat *RTCP_inst)
984{
985 int ok = 0;
986 MainInst_t *NetEqMainInst = (MainInst_t*) inst;
987 if (NetEqMainInst == NULL) return (-1);
988 ok = WebRtcNetEQ_RTCPGetStats(&NetEqMainInst->MCUinst.RTCP_inst,
989 &RTCP_inst->fraction_lost, &RTCP_inst->cum_lost, &RTCP_inst->ext_max,
990 &RTCP_inst->jitter, 1);
991 if (ok != 0)
992 {
993 NetEqMainInst->ErrorCode = -ok;
994 return (-1);
995 }
996 return (ok);
997}
998
999int WebRtcNetEQ_GetSpeechTimeStamp(void *inst, WebRtc_UWord32 *timestamp)
1000{
1001 MainInst_t *NetEqMainInst = (MainInst_t*) inst;
1002 if (NetEqMainInst == NULL) return (-1);
1003
1004 if (NetEqMainInst->MCUinst.TSscalingInitialized)
1005 {
1006 *timestamp = WebRtcNetEQ_ScaleTimestampInternalToExternal(&NetEqMainInst->MCUinst,
1007 NetEqMainInst->DSPinst.videoSyncTimestamp);
1008 }
1009 else
1010 {
1011 *timestamp = NetEqMainInst->DSPinst.videoSyncTimestamp;
1012 }
1013
1014 return (0);
1015}
1016
1017/****************************************************************************
1018 * WebRtcNetEQ_GetSpeechOutputType(...)
1019 *
1020 * Get the output type for the audio provided by the latest call to
1021 * WebRtcNetEQ_RecOut().
1022 *
1023 * kOutputNormal = normal audio (possibly processed)
1024 * kOutputPLC = loss concealment through stretching audio
1025 * kOutputCNG = comfort noise (codec-internal or RFC3389)
1026 * kOutputPLCtoCNG = background noise only due to long expand or error
1027 * kOutputVADPassive = PostDecode VAD signalling passive speaker
1028 *
1029 * Input:
1030 * - inst : NetEQ instance
1031 *
1032 * Output:
1033 * - outputType : Output type from enum list WebRtcNetEQOutputType
1034 *
1035 * Return value : 0 - Ok
1036 * -1 - Error
1037 */
1038
1039int WebRtcNetEQ_GetSpeechOutputType(void *inst, enum WebRtcNetEQOutputType *outputType)
1040{
1041 /* Typecast to internal instance type */
1042 MainInst_t *NetEqMainInst = (MainInst_t*) inst;
1043
1044 if (NetEqMainInst == NULL)
1045 {
1046 return (-1);
1047 }
1048
1049 if ((NetEqMainInst->DSPinst.w16_mode & MODE_BGN_ONLY) != 0)
1050 {
1051 /* If last mode was background noise only */
1052 *outputType = kOutputPLCtoCNG;
1053
1054 }
1055 else if ((NetEqMainInst->DSPinst.w16_mode == MODE_CODEC_INTERNAL_CNG)
1056 || (NetEqMainInst->DSPinst.w16_mode == MODE_RFC3389CNG))
1057 {
1058 /* If CN or internal CNG */
1059 *outputType = kOutputCNG;
1060
1061#ifdef NETEQ_VAD
1062 }
1063 else if ( NetEqMainInst->DSPinst.VADInst.VADDecision == 0 )
1064 {
1065 /* post-decode VAD says passive speaker */
1066 *outputType = kOutputVADPassive;
1067#endif /* NETEQ_VAD */
1068
1069 }
1070 else if ((NetEqMainInst->DSPinst.w16_mode == MODE_EXPAND)
1071 && (NetEqMainInst->DSPinst.ExpandInst.w16_expandMuteFactor == 0))
1072 {
1073 /* Expand mode has faded down to background noise only (very long expand) */
1074 *outputType = kOutputPLCtoCNG;
1075
1076 }
1077 else if (NetEqMainInst->DSPinst.w16_mode == MODE_EXPAND)
1078 {
1079 /* PLC mode */
1080 *outputType = kOutputPLC;
1081
1082 }
1083 else
1084 {
1085 /* Normal speech output type (can still be manipulated, e.g., accelerated) */
1086 *outputType = kOutputNormal;
1087 }
1088
1089 return (0);
1090}
1091
1092/**********************************
1093 * Functions related to VQmon
1094 */
1095
1096#define WEBRTC_NETEQ_CONCEALMENTFLAG_LOST 0x01
1097#define WEBRTC_NETEQ_CONCEALMENTFLAG_DISCARDED 0x02
1098#define WEBRTC_NETEQ_CONCEALMENTFLAG_SUPRESS 0x04
1099#define WEBRTC_NETEQ_CONCEALMENTFLAG_CNGACTIVE 0x80
1100
1101int WebRtcNetEQ_VQmonRecOutStatistics(void *inst, WebRtc_UWord16 *validVoiceDurationMs,
1102 WebRtc_UWord16 *concealedVoiceDurationMs,
1103 WebRtc_UWord8 *concealedVoiceFlags)
1104{
1105 MainInst_t *NetEqMainInst = (MainInst_t*) inst;
1106 WebRtc_Word16 fs_mult;
1107 WebRtc_Word16 ms_lost;
1108 if (NetEqMainInst == NULL) return (-1);
1109 fs_mult = WebRtcSpl_DivW32W16ResW16(NetEqMainInst->MCUinst.fs, 8000);
1110
1111 ms_lost = WebRtcSpl_DivW32W16ResW16(
1112 (WebRtc_Word32) NetEqMainInst->DSPinst.w16_concealedTS, (WebRtc_Word16) (8 * fs_mult));
1113 if (ms_lost > NetEqMainInst->DSPinst.millisecondsPerCall) ms_lost
1114 = NetEqMainInst->DSPinst.millisecondsPerCall;
1115
1116 *validVoiceDurationMs = NetEqMainInst->DSPinst.millisecondsPerCall - ms_lost;
1117 *concealedVoiceDurationMs = ms_lost;
1118 if (ms_lost > 0)
1119 {
1120 *concealedVoiceFlags = WEBRTC_NETEQ_CONCEALMENTFLAG_LOST;
1121 }
1122 else
1123 {
1124 *concealedVoiceFlags = 0;
1125 }
1126 NetEqMainInst->DSPinst.w16_concealedTS -= ms_lost * (8 * fs_mult);
1127
1128 return (0);
1129}
1130
1131int WebRtcNetEQ_VQmonGetConfiguration(void *inst, WebRtc_UWord16 *absMaxDelayMs,
1132 WebRtc_UWord8 *adaptationRate)
1133{
1134 /* Dummy check the inst, just to avoid compiler warnings. */
1135 if (inst == NULL)
1136 {
1137 /* Do nothing. */
1138 }
1139
1140 /* Hardcoded variables that are used for VQmon as jitter buffer parameters */
1141 *absMaxDelayMs = 240;
1142 *adaptationRate = 1;
1143 return (0);
1144}
1145
1146int WebRtcNetEQ_VQmonGetRxStatistics(void *inst, WebRtc_UWord16 *avgDelayMs,
1147 WebRtc_UWord16 *maxDelayMs)
1148{
1149 MainInst_t *NetEqMainInst = (MainInst_t*) inst;
1150 if (NetEqMainInst == NULL) return (-1);
1151 *avgDelayMs = (WebRtc_UWord16) (NetEqMainInst->MCUinst.BufferStat_inst.avgDelayMsQ8 >> 8);
1152 *maxDelayMs = (WebRtc_UWord16) NetEqMainInst->MCUinst.BufferStat_inst.maxDelayMs;
1153 return (0);
1154}
1155
1156/*************************************
1157 * Statistics functions
1158 */
1159
1160/* Get the "in-call" statistics from NetEQ.
1161 * The statistics are reset after the query. */
1162int WebRtcNetEQ_GetNetworkStatistics(void *inst, WebRtcNetEQ_NetworkStatistics *stats)
1163
1164{
1165
1166 WebRtc_UWord16 tempU16;
1167 WebRtc_UWord32 tempU32, tempU32_2;
1168 int numShift;
1169 MainInst_t *NetEqMainInst = (MainInst_t*) inst;
1170
1171 /* Instance sanity */
1172 if (NetEqMainInst == NULL) return (-1);
1173
roosa@google.comb8ba4d82012-12-14 00:06:18 +00001174 stats->addedSamples = NetEqMainInst->DSPinst.statInst.addedSamples;
1175
niklase@google.com470e71d2011-07-07 08:21:25 +00001176 /*******************/
1177 /* Get buffer size */
1178 /*******************/
1179
henrik.lundin@webrtc.org524eb482011-11-30 16:21:22 +00001180 if (NetEqMainInst->MCUinst.fs != 0)
niklase@google.com470e71d2011-07-07 08:21:25 +00001181 {
henrik.lundin@webrtc.org524eb482011-11-30 16:21:22 +00001182 WebRtc_Word32 temp32;
1183 /* Query packet buffer for number of samples. */
1184 temp32 = WebRtcNetEQ_PacketBufferGetSize(
tina.legrand@webrtc.org5ac387c2012-11-19 08:02:55 +00001185 &NetEqMainInst->MCUinst.PacketBuffer_inst,
1186 &NetEqMainInst->MCUinst.codec_DB_inst);
henrik.lundin@webrtc.org524eb482011-11-30 16:21:22 +00001187
1188 /* Divide by sample rate.
1189 * Calculate temp32 * 1000 / fs to get result in ms. */
1190 stats->currentBufferSize = (WebRtc_UWord16)
1191 WebRtcSpl_DivU32U16(temp32 * 1000, NetEqMainInst->MCUinst.fs);
1192
1193 /* Add number of samples yet to play in sync buffer. */
1194 temp32 = (WebRtc_Word32) (NetEqMainInst->DSPinst.endPosition -
1195 NetEqMainInst->DSPinst.curPosition);
1196 stats->currentBufferSize += (WebRtc_UWord16)
1197 WebRtcSpl_DivU32U16(temp32 * 1000, NetEqMainInst->MCUinst.fs);
1198 }
1199 else
1200 {
1201 /* Sample rate not initialized. */
1202 stats->currentBufferSize = 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001203 }
1204
1205 /***************************/
1206 /* Get optimal buffer size */
1207 /***************************/
1208
1209 if (NetEqMainInst->MCUinst.fs != 0 && NetEqMainInst->MCUinst.fs <= WEBRTC_SPL_WORD16_MAX)
1210 {
1211 /* preferredBufferSize = Bopt * packSizeSamples / (fs/1000) */
1212 stats->preferredBufferSize
1213 = (WebRtc_UWord16) WEBRTC_SPL_MUL_16_16(
1214 (WebRtc_Word16) ((NetEqMainInst->MCUinst.BufferStat_inst.Automode_inst.optBufLevel) >> 8), /* optimal buffer level in packets shifted to Q0 */
1215 WebRtcSpl_DivW32W16ResW16(
1216 (WebRtc_Word32) NetEqMainInst->MCUinst.BufferStat_inst.Automode_inst.packetSpeechLenSamp, /* samples per packet */
1217 WebRtcSpl_DivW32W16ResW16( (WebRtc_Word32) NetEqMainInst->MCUinst.fs, (WebRtc_Word16) 1000 ) /* samples per ms */
1218 ) );
1219
1220 /* add extra delay */
1221 if (NetEqMainInst->MCUinst.BufferStat_inst.Automode_inst.extraDelayMs > 0)
1222 {
1223 stats->preferredBufferSize
1224 += NetEqMainInst->MCUinst.BufferStat_inst.Automode_inst.extraDelayMs;
1225 }
1226 }
1227 else
1228 {
1229 /* sample rate not initialized */
1230 stats->preferredBufferSize = 0;
1231 }
1232
henrik.lundin@webrtc.orgd4398702012-01-04 13:09:55 +00001233 /***********************************/
1234 /* Check if jitter peaks are found */
1235 /***********************************/
1236
1237 stats->jitterPeaksFound =
1238 NetEqMainInst->MCUinst.BufferStat_inst.Automode_inst.peakFound;
1239
niklase@google.com470e71d2011-07-07 08:21:25 +00001240 /***********************/
1241 /* Calculate loss rate */
1242 /***********************/
1243
1244 /* timestamps elapsed since last report */
1245 tempU32 = NetEqMainInst->MCUinst.lastReportTS;
1246
1247 if (NetEqMainInst->MCUinst.lostTS == 0)
1248 {
1249 /* no losses */
1250 stats->currentPacketLossRate = 0;
1251 }
1252 else if (NetEqMainInst->MCUinst.lostTS < tempU32)
1253 {
1254 /* calculate shifts; we want the result in Q14 */
1255 numShift = WebRtcSpl_NormU32(NetEqMainInst->MCUinst.lostTS); /* numerator shift for normalize */
1256
1257 if (numShift < 14)
1258 {
1259 /* cannot shift numerator 14 steps; shift denominator too */
1260 tempU32 = WEBRTC_SPL_RSHIFT_U32(tempU32, 14-numShift); /* right-shift */
1261 }
1262 else
1263 {
1264 /* shift no more than 14 steps */
1265 numShift = 14;
1266 }
1267
1268 if (tempU32 == 0)
1269 {
1270 /* check for zero denominator; result should be zero in this case */
1271 stats->currentPacketLossRate = 0;
1272 }
1273 else
1274 {
1275 /* check that denominator fits in signed 16-bit */
1276 while (tempU32 > WEBRTC_SPL_WORD16_MAX)
1277 {
1278 tempU32 >>= 1; /* right-shift 1 step */
1279 numShift--; /* compensate in numerator */
1280 }
1281 tempU16 = (WebRtc_UWord16) tempU32;
1282
1283 /* do the shift of numerator */
1284 tempU32
1285 = WEBRTC_SPL_SHIFT_W32( (WebRtc_UWord32) NetEqMainInst->MCUinst.lostTS, numShift);
1286
1287 stats->currentPacketLossRate = (WebRtc_UWord16) WebRtcSpl_DivU32U16(tempU32,
1288 tempU16);
1289 }
1290 }
1291 else
1292 {
1293 /* lost count is larger than elapsed time count; probably timestamp wrap-around or something else wrong */
1294 /* set loss rate = 1 */
1295 stats->currentPacketLossRate = 1 << 14; /* 1 in Q14 */
1296 }
1297
1298 /**************************/
1299 /* Calculate discard rate */
1300 /**************************/
1301
1302 /* timestamps elapsed since last report */
1303 tempU32 = NetEqMainInst->MCUinst.lastReportTS;
1304
1305 /* number of discarded samples */
1306 tempU32_2
1307 = WEBRTC_SPL_MUL_16_U16( (WebRtc_Word16) NetEqMainInst->MCUinst.PacketBuffer_inst.packSizeSamples,
1308 NetEqMainInst->MCUinst.PacketBuffer_inst.discardedPackets);
1309
1310 if (tempU32_2 == 0)
1311 {
1312 /* no discarded samples */
1313 stats->currentDiscardRate = 0;
1314 }
1315 else if (tempU32_2 < tempU32)
1316 {
1317 /* calculate shifts; we want the result in Q14 */
1318 numShift = WebRtcSpl_NormU32(tempU32_2); /* numerator shift for normalize */
1319
1320 if (numShift < 14)
1321 {
1322 /* cannot shift numerator 14 steps; shift denominator too */
1323 tempU32 = WEBRTC_SPL_RSHIFT_U32(tempU32, 14-numShift); /* right-shift */
1324 }
1325 else
1326 {
1327 /* shift no more than 14 steps */
1328 numShift = 14;
1329 }
1330
1331 if (tempU32 == 0)
1332 {
1333 /* check for zero denominator; result should be zero in this case */
1334 stats->currentDiscardRate = 0;
1335 }
1336 else
1337 {
1338 /* check that denominator fits in signed 16-bit */
1339 while (tempU32 > WEBRTC_SPL_WORD16_MAX)
1340 {
1341 tempU32 >>= 1; /* right-shift 1 step */
1342 numShift--; /* compensate in numerator */
1343 }
1344 tempU16 = (WebRtc_UWord16) tempU32;
1345
1346 /* do the shift of numerator */
1347 tempU32 = WEBRTC_SPL_SHIFT_W32( tempU32_2, numShift);
1348
1349 stats->currentDiscardRate = (WebRtc_UWord16) WebRtcSpl_DivU32U16(tempU32, tempU16);
1350 }
1351 }
1352 else
1353 {
1354 /* lost count is larger than elapsed time count; probably timestamp wrap-around or something else wrong */
1355 /* set loss rate = 1 */
1356 stats->currentDiscardRate = 1 << 14; /* 1 in Q14 */
1357 }
1358
1359 /*************************************************************/
1360 /* Calculate Accelerate, Expand and Pre-emptive Expand rates */
1361 /*************************************************************/
1362
1363 /* timestamps elapsed since last report */
1364 tempU32 = NetEqMainInst->MCUinst.lastReportTS;
1365
1366 if (NetEqMainInst->DSPinst.statInst.accelerateLength == 0)
1367 {
1368 /* no accelerate */
1369 stats->currentAccelerateRate = 0;
1370 }
1371 else if (NetEqMainInst->DSPinst.statInst.accelerateLength < tempU32)
1372 {
1373 /* calculate shifts; we want the result in Q14 */
1374 numShift = WebRtcSpl_NormU32(NetEqMainInst->DSPinst.statInst.accelerateLength); /* numerator shift for normalize */
1375
1376 if (numShift < 14)
1377 {
1378 /* cannot shift numerator 14 steps; shift denominator too */
1379 tempU32 = WEBRTC_SPL_RSHIFT_U32(tempU32, 14-numShift); /* right-shift */
1380 }
1381 else
1382 {
1383 /* shift no more than 14 steps */
1384 numShift = 14;
1385 }
1386
1387 if (tempU32 == 0)
1388 {
1389 /* check for zero denominator; result should be zero in this case */
1390 stats->currentAccelerateRate = 0;
1391 }
1392 else
1393 {
1394 /* check that denominator fits in signed 16-bit */
1395 while (tempU32 > WEBRTC_SPL_WORD16_MAX)
1396 {
1397 tempU32 >>= 1; /* right-shift 1 step */
1398 numShift--; /* compensate in numerator */
1399 }
1400 tempU16 = (WebRtc_UWord16) tempU32;
1401
1402 /* do the shift of numerator */
1403 tempU32
1404 = WEBRTC_SPL_SHIFT_W32( NetEqMainInst->DSPinst.statInst.accelerateLength, numShift);
1405
1406 stats->currentAccelerateRate = (WebRtc_UWord16) WebRtcSpl_DivU32U16(tempU32,
1407 tempU16);
1408 }
1409 }
1410 else
1411 {
1412 /* lost count is larger than elapsed time count; probably timestamp wrap-around or something else wrong */
1413 /* set loss rate = 1 */
1414 stats->currentAccelerateRate = 1 << 14; /* 1 in Q14 */
1415 }
1416
niklase@google.com470e71d2011-07-07 08:21:25 +00001417 /* timestamps elapsed since last report */
1418 tempU32 = NetEqMainInst->MCUinst.lastReportTS;
1419
1420 if (NetEqMainInst->DSPinst.statInst.expandLength == 0)
1421 {
1422 /* no expand */
1423 stats->currentExpandRate = 0;
1424 }
1425 else if (NetEqMainInst->DSPinst.statInst.expandLength < tempU32)
1426 {
1427 /* calculate shifts; we want the result in Q14 */
1428 numShift = WebRtcSpl_NormU32(NetEqMainInst->DSPinst.statInst.expandLength); /* numerator shift for normalize */
1429
1430 if (numShift < 14)
1431 {
1432 /* cannot shift numerator 14 steps; shift denominator too */
1433 tempU32 = WEBRTC_SPL_RSHIFT_U32(tempU32, 14-numShift); /* right-shift */
1434 }
1435 else
1436 {
1437 /* shift no more than 14 steps */
1438 numShift = 14;
1439 }
1440
1441 if (tempU32 == 0)
1442 {
1443 /* check for zero denominator; result should be zero in this case */
1444 stats->currentExpandRate = 0;
1445 }
1446 else
1447 {
1448 /* check that denominator fits in signed 16-bit */
1449 while (tempU32 > WEBRTC_SPL_WORD16_MAX)
1450 {
1451 tempU32 >>= 1; /* right-shift 1 step */
1452 numShift--; /* compensate in numerator */
1453 }
1454 tempU16 = (WebRtc_UWord16) tempU32;
1455
1456 /* do the shift of numerator */
1457 tempU32
1458 = WEBRTC_SPL_SHIFT_W32( NetEqMainInst->DSPinst.statInst.expandLength, numShift);
1459
1460 stats->currentExpandRate = (WebRtc_UWord16) WebRtcSpl_DivU32U16(tempU32, tempU16);
1461 }
1462 }
1463 else
1464 {
1465 /* lost count is larger than elapsed time count; probably timestamp wrap-around or something else wrong */
1466 /* set loss rate = 1 */
1467 stats->currentExpandRate = 1 << 14; /* 1 in Q14 */
1468 }
1469
1470 /* timestamps elapsed since last report */
1471 tempU32 = NetEqMainInst->MCUinst.lastReportTS;
1472
1473 if (NetEqMainInst->DSPinst.statInst.preemptiveLength == 0)
1474 {
1475 /* no pre-emptive expand */
1476 stats->currentPreemptiveRate = 0;
1477 }
1478 else if (NetEqMainInst->DSPinst.statInst.preemptiveLength < tempU32)
1479 {
1480 /* calculate shifts; we want the result in Q14 */
1481 numShift = WebRtcSpl_NormU32(NetEqMainInst->DSPinst.statInst.preemptiveLength); /* numerator shift for normalize */
1482
1483 if (numShift < 14)
1484 {
1485 /* cannot shift numerator 14 steps; shift denominator too */
1486 tempU32 = WEBRTC_SPL_RSHIFT_U32(tempU32, 14-numShift); /* right-shift */
1487 }
1488 else
1489 {
1490 /* shift no more than 14 steps */
1491 numShift = 14;
1492 }
1493
1494 if (tempU32 == 0)
1495 {
1496 /* check for zero denominator; result should be zero in this case */
1497 stats->currentPreemptiveRate = 0;
1498 }
1499 else
1500 {
1501 /* check that denominator fits in signed 16-bit */
1502 while (tempU32 > WEBRTC_SPL_WORD16_MAX)
1503 {
1504 tempU32 >>= 1; /* right-shift 1 step */
1505 numShift--; /* compensate in numerator */
1506 }
1507 tempU16 = (WebRtc_UWord16) tempU32;
1508
1509 /* do the shift of numerator */
1510 tempU32
1511 = WEBRTC_SPL_SHIFT_W32( NetEqMainInst->DSPinst.statInst.preemptiveLength, numShift);
1512
1513 stats->currentPreemptiveRate = (WebRtc_UWord16) WebRtcSpl_DivU32U16(tempU32,
1514 tempU16);
1515 }
1516 }
1517 else
1518 {
1519 /* lost count is larger than elapsed time count; probably timestamp wrap-around or something else wrong */
1520 /* set loss rate = 1 */
1521 stats->currentPreemptiveRate = 1 << 14; /* 1 in Q14 */
1522 }
1523
henrik.lundin@webrtc.orgd4398702012-01-04 13:09:55 +00001524 stats->clockDriftPPM = WebRtcNetEQ_AverageIAT(
1525 &NetEqMainInst->MCUinst.BufferStat_inst.Automode_inst);
1526
niklase@google.com470e71d2011-07-07 08:21:25 +00001527 /* reset counters */
1528 WebRtcNetEQ_ResetMcuInCallStats(&(NetEqMainInst->MCUinst));
1529 WebRtcNetEQ_ClearInCallStats(&(NetEqMainInst->DSPinst));
1530
1531 return (0);
1532}
1533
henrik.lundin@webrtc.orgdbba1f92011-12-20 15:45:05 +00001534int WebRtcNetEQ_GetRawFrameWaitingTimes(void *inst,
1535 int max_length,
1536 int* waiting_times_ms) {
1537 int i = 0;
1538 MainInst_t *main_inst = (MainInst_t*) inst;
1539 if (main_inst == NULL) return -1;
1540
1541 while ((i < max_length) && (i < main_inst->MCUinst.len_waiting_times)) {
1542 waiting_times_ms[i] = main_inst->MCUinst.waiting_times[i] *
1543 main_inst->DSPinst.millisecondsPerCall;
1544 ++i;
1545 }
1546 assert(i <= kLenWaitingTimes);
1547 WebRtcNetEQ_ResetWaitingTimeStats(&main_inst->MCUinst);
1548 return i;
1549}
1550
niklase@google.com470e71d2011-07-07 08:21:25 +00001551/****************************************************************************
1552 * WebRtcNetEQ_SetVADInstance(...)
1553 *
1554 * Provide a pointer to an allocated VAD instance. If function is never
1555 * called or it is called with NULL pointer as VAD_inst, the post-decode
1556 * VAD functionality is disabled. Also provide pointers to init, setmode
1557 * and VAD functions. These are typically pointers to WebRtcVad_Init,
1558 * WebRtcVad_set_mode and WebRtcVad_Process, respectively, all found in the
1559 * interface file webrtc_vad.h.
1560 *
1561 * Input:
1562 * - NetEQ_inst : NetEQ instance
1563 * - VADinst : VAD instance
1564 * - initFunction : Pointer to VAD init function
1565 * - setmodeFunction : Pointer to VAD setmode function
1566 * - VADfunction : Pointer to VAD function
1567 *
1568 * Output:
1569 * - NetEQ_inst : Updated NetEQ instance
1570 *
1571 * Return value : 0 - Ok
1572 * -1 - Error
1573 */
1574
1575int WebRtcNetEQ_SetVADInstance(void *NetEQ_inst, void *VAD_inst,
1576 WebRtcNetEQ_VADInitFunction initFunction,
1577 WebRtcNetEQ_VADSetmodeFunction setmodeFunction,
1578 WebRtcNetEQ_VADFunction VADFunction)
1579{
1580
1581 /* Typecast to internal instance type */
1582 MainInst_t *NetEqMainInst = (MainInst_t*) NetEQ_inst;
1583 if (NetEqMainInst == NULL)
1584 {
1585 return (-1);
1586 }
1587
1588#ifdef NETEQ_VAD
1589
1590 /* Store pointer in PostDecode VAD struct */
1591 NetEqMainInst->DSPinst.VADInst.VADState = VAD_inst;
1592
1593 /* Store function pointers */
1594 NetEqMainInst->DSPinst.VADInst.initFunction = initFunction;
1595 NetEqMainInst->DSPinst.VADInst.setmodeFunction = setmodeFunction;
1596 NetEqMainInst->DSPinst.VADInst.VADFunction = VADFunction;
1597
1598 /* Call init function and return the result (ok or fail) */
1599 return(WebRtcNetEQ_InitVAD(&NetEqMainInst->DSPinst.VADInst, NetEqMainInst->DSPinst.fs));
1600
1601#else /* NETEQ_VAD not defined */
1602 return (-1);
1603#endif /* NETEQ_VAD */
1604
1605}
1606
1607/****************************************************************************
1608 * WebRtcNetEQ_SetVADMode(...)
1609 *
1610 * Pass an aggressiveness mode parameter to the post-decode VAD instance.
1611 * If this function is never called, mode 0 (quality mode) is used as default.
1612 *
1613 * Input:
1614 * - inst : NetEQ instance
1615 * - mode : mode parameter (same range as WebRtc VAD mode)
1616 *
1617 * Output:
1618 * - inst : Updated NetEQ instance
1619 *
1620 * Return value : 0 - Ok
1621 * -1 - Error
1622 */
1623
bjornv@webrtc.orgf4b77fd2012-01-25 12:40:00 +00001624int WebRtcNetEQ_SetVADMode(void *inst, int mode)
niklase@google.com470e71d2011-07-07 08:21:25 +00001625{
1626
1627 /* Typecast to internal instance type */
1628 MainInst_t *NetEqMainInst = (MainInst_t*) inst;
1629 if (NetEqMainInst == NULL)
1630 {
1631 return (-1);
1632 }
1633
1634#ifdef NETEQ_VAD
1635
1636 /* Set mode and return result */
1637 return(WebRtcNetEQ_SetVADModeInternal(&NetEqMainInst->DSPinst.VADInst, mode));
1638
1639#else /* NETEQ_VAD not defined */
1640 return (-1);
1641#endif /* NETEQ_VAD */
1642
1643}