blob: 38b3ce4d3a47ed21add2720fe1f81403c71ff3c4 [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 { \
pbos@webrtc.org0946a562013-04-09 00:28:06 +000033 (macroInstPtr)->ErrorCode = -((int16_t) (macroExpr)); \
niklase@google.com470e71d2011-07-07 08:21:25 +000034 } \
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{
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000283 *sizeinbytes = (sizeof(MainInst_t) * 2) / sizeof(int16_t);
niklase@google.com470e71d2011-07-07 08:21:25 +0000284 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 */
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000297 WebRtcSpl_MemSetW16((int16_t*) NetEqMainInst, 0,
298 (sizeof(MainInst_t) / sizeof(int16_t)));
niklase@google.com470e71d2011-07-07 08:21:25 +0000299 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,
turaj@webrtc.org6388c3e2013-02-12 21:42:18 +0000310 int *MaxNoOfPackets, int *sizeinbytes,
311 int* per_packet_overhead_bytes)
niklase@google.com470e71d2011-07-07 08:21:25 +0000312{
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;
turaj@webrtc.org6388c3e2013-02-12 21:42:18 +0000319 ok = WebRtcNetEQ_GetDefaultCodecSettings(codec, noOfCodecs, sizeinbytes,
320 MaxNoOfPackets,
321 per_packet_overhead_bytes);
niklase@google.com470e71d2011-07-07 08:21:25 +0000322 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 {
turaj@webrtc.org6388c3e2013-02-12 21:42:18 +0000345 multiplier = 12;
niklase@google.com470e71d2011-07-07 08:21:25 +0000346 }
347 else
348 {
349 NetEqMainInst->ErrorCode = -FAULTY_NETWORK_TYPE;
350 return (-1);
351 }
352 *MaxNoOfPackets = (*MaxNoOfPackets) * multiplier;
353 *sizeinbytes = (*sizeinbytes) * multiplier;
henrik.lundin@webrtc.orgf0effa12012-09-11 12:44:06 +0000354 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000355}
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,
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000364 MaxNoOfPackets, (int16_t*) NETEQ_Buffer_Addr, (sizeinbytes >> 1));
niklase@google.com470e71d2011-07-07 08:21:25 +0000365 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
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000393int WebRtcNetEQ_Init(void *inst, uint16_t fs)
niklase@google.com470e71d2011-07-07 08:21:25 +0000394{
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.NoOfExpandCalls = 0;
441 NetEqMainInst->MCUinst.fs = fs;
442
443#ifdef NETEQ_ATEVENT_DECODE
444 /* init DTMF decoder */
445 ok = WebRtcNetEQ_DtmfDecoderInit(&(NetEqMainInst->MCUinst.DTMF_inst),fs,560);
446 RETURN_ON_ERROR(ok, NetEqMainInst);
447#endif
448
449 /* init RTCP statistics */
450 WebRtcNetEQ_RTCPInit(&(NetEqMainInst->MCUinst.RTCP_inst), 0);
451
452 /* set BufferStat struct to zero */
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000453 WebRtcSpl_MemSetW16((int16_t*) &(NetEqMainInst->MCUinst.BufferStat_inst), 0,
454 sizeof(BufstatsInst_t) / sizeof(int16_t));
niklase@google.com470e71d2011-07-07 08:21:25 +0000455
456 /* reset automode */
457 WebRtcNetEQ_ResetAutomode(&(NetEqMainInst->MCUinst.BufferStat_inst.Automode_inst),
458 NetEqMainInst->MCUinst.PacketBuffer_inst.maxInsertPositions);
459
460 NetEqMainInst->ErrorCode = 0;
461
462#ifdef NETEQ_STEREO
463 /* set master/slave info to undecided */
464 NetEqMainInst->masterSlave = 0;
465#endif
466
467 return (ok);
468}
469
470int WebRtcNetEQ_FlushBuffers(void *inst)
471{
472 int ok = 0;
473
474 /* Typecast inst to internal instance format */
475 MainInst_t *NetEqMainInst = (MainInst_t*) inst;
476
477 if (NetEqMainInst == NULL)
478 {
479 return (-1);
480 }
481
482 /* Flush packet buffer */
483 ok = WebRtcNetEQ_PacketBufferFlush(&NetEqMainInst->MCUinst.PacketBuffer_inst);
484 RETURN_ON_ERROR(ok, NetEqMainInst);
485
486 /* Set MCU to wait for new codec */
487 NetEqMainInst->MCUinst.first_packet = 1;
488
489 /* Flush speech buffer */
490 ok = WebRtcNetEQ_FlushSpeechBuffer(&NetEqMainInst->DSPinst);
491 RETURN_ON_ERROR(ok, NetEqMainInst);
492
493 return 0;
494}
495
496int WebRtcNetEQ_SetAVTPlayout(void *inst, int PlayoutAVTon)
497{
498 MainInst_t *NetEqMainInst = (MainInst_t*) inst;
499 if (NetEqMainInst == NULL) return (-1);
500#ifdef NETEQ_ATEVENT_DECODE
501 NetEqMainInst->MCUinst.AVT_PlayoutOn = PlayoutAVTon;
502 return(0);
503#else
504 if (PlayoutAVTon != 0)
505 {
506 NetEqMainInst->ErrorCode = -DTMF_NOT_SUPPORTED;
507 return (-1);
508 }
509 else
510 {
511 return (0);
512 }
513#endif
514}
515
516int WebRtcNetEQ_SetExtraDelay(void *inst, int DelayInMs)
517{
518 MainInst_t *NetEqMainInst = (MainInst_t*) inst;
519 if (NetEqMainInst == NULL) return (-1);
turaj@webrtc.org6388c3e2013-02-12 21:42:18 +0000520 if ((DelayInMs < 0) || (DelayInMs > 10000))
niklase@google.com470e71d2011-07-07 08:21:25 +0000521 {
522 NetEqMainInst->ErrorCode = -FAULTY_DELAYVALUE;
523 return (-1);
524 }
525 NetEqMainInst->MCUinst.BufferStat_inst.Automode_inst.extraDelayMs = DelayInMs;
526 return (0);
527}
528
529int WebRtcNetEQ_SetPlayoutMode(void *inst, enum WebRtcNetEQPlayoutMode playoutMode)
530{
531 MainInst_t *NetEqMainInst = (MainInst_t*) inst;
532 if (NetEqMainInst == NULL) return (-1);
533 if ((playoutMode != kPlayoutOn) && (playoutMode != kPlayoutOff) && (playoutMode
534 != kPlayoutFax) && (playoutMode != kPlayoutStreaming))
535 {
536 NetEqMainInst->ErrorCode = -FAULTY_PLAYOUTMODE;
537 return (-1);
538 }
539 else
540 {
541 NetEqMainInst->MCUinst.NetEqPlayoutMode = playoutMode;
542 return (0);
543 }
544}
545
546int WebRtcNetEQ_SetBGNMode(void *inst, enum WebRtcNetEQBGNMode bgnMode)
547{
548
549 MainInst_t *NetEqMainInst = (MainInst_t*) inst;
550
551 /* Instance sanity */
552 if (NetEqMainInst == NULL) return (-1);
553
554 /* Check for corrupt/cleared instance */
555 if (NetEqMainInst->MCUinst.main_inst != NetEqMainInst)
556 {
557 /* Instance is corrupt */
558 NetEqMainInst->ErrorCode = CORRUPT_INSTANCE;
559 return (-1);
560 }
561
562 NetEqMainInst->DSPinst.BGNInst.bgnMode = (enum BGNMode) bgnMode;
563
564 return (0);
565}
566
567int WebRtcNetEQ_GetBGNMode(const void *inst, enum WebRtcNetEQBGNMode *bgnMode)
568{
569
570 const MainInst_t *NetEqMainInst = (const MainInst_t*) inst;
571
572 /* Instance sanity */
573 if (NetEqMainInst == NULL) return (-1);
574
575 *bgnMode = (enum WebRtcNetEQBGNMode) NetEqMainInst->DSPinst.BGNInst.bgnMode;
576
577 return (0);
578}
579
580/************************************************
581 * CodecDB functions
582 */
583
584int WebRtcNetEQ_CodecDbReset(void *inst)
585{
586 int ok = 0;
587 MainInst_t *NetEqMainInst = (MainInst_t*) inst;
588 if (NetEqMainInst == NULL) return (-1);
589 ok = WebRtcNetEQ_DbReset(&NetEqMainInst->MCUinst.codec_DB_inst);
590 if (ok != 0)
591 {
592 NetEqMainInst->ErrorCode = -ok;
593 return (-1);
594 }
595
596 /* set function pointers to NULL to prevent RecOut from using the codec */
597 NetEqMainInst->DSPinst.codec_ptr_inst.funcDecode = NULL;
598 NetEqMainInst->DSPinst.codec_ptr_inst.funcDecodeRCU = NULL;
599 NetEqMainInst->DSPinst.codec_ptr_inst.funcAddLatePkt = NULL;
600 NetEqMainInst->DSPinst.codec_ptr_inst.funcDecode = NULL;
601 NetEqMainInst->DSPinst.codec_ptr_inst.funcDecodeInit = NULL;
602 NetEqMainInst->DSPinst.codec_ptr_inst.funcDecodePLC = NULL;
603 NetEqMainInst->DSPinst.codec_ptr_inst.funcGetMDinfo = NULL;
604 NetEqMainInst->DSPinst.codec_ptr_inst.funcUpdBWEst = NULL;
605 NetEqMainInst->DSPinst.codec_ptr_inst.funcGetErrorCode = NULL;
606
607 return (0);
608}
609
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000610int WebRtcNetEQ_CodecDbGetSizeInfo(void *inst, int16_t *UsedEntries,
611 int16_t *MaxEntries)
niklase@google.com470e71d2011-07-07 08:21:25 +0000612{
613 MainInst_t *NetEqMainInst = (MainInst_t*) inst;
614 if (NetEqMainInst == NULL) return (-1);
615 *MaxEntries = NUM_CODECS;
616 *UsedEntries = NetEqMainInst->MCUinst.codec_DB_inst.nrOfCodecs;
617 return (0);
618}
619
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000620int WebRtcNetEQ_CodecDbGetCodecInfo(void *inst, int16_t Entry,
niklase@google.com470e71d2011-07-07 08:21:25 +0000621 enum WebRtcNetEQDecoder *codec)
622{
623 int i;
624 MainInst_t *NetEqMainInst = (MainInst_t*) inst;
625 if (NetEqMainInst == NULL) return (-1);
626 *codec = (enum WebRtcNetEQDecoder) 0;
627 if ((Entry >= 0) && (Entry < NetEqMainInst->MCUinst.codec_DB_inst.nrOfCodecs))
628 {
629 for (i = 0; i < NUM_TOTAL_CODECS; i++)
630 {
631 if (NetEqMainInst->MCUinst.codec_DB_inst.position[i] == Entry)
632 {
633 *codec = (enum WebRtcNetEQDecoder) i;
634 }
635 }
636 }
637 else
638 {
639 NetEqMainInst->ErrorCode = -(CODEC_DB_NOT_EXIST1);
640 return (-1);
641 }
642 return (0);
643}
644
645int WebRtcNetEQ_CodecDbAdd(void *inst, WebRtcNetEQ_CodecDef *codecInst)
646{
647 int ok = 0;
648 MainInst_t *NetEqMainInst = (MainInst_t*) inst;
649 if (NetEqMainInst == NULL) return (-1);
650 ok = WebRtcNetEQ_DbAdd(&NetEqMainInst->MCUinst.codec_DB_inst, codecInst->codec,
651 codecInst->payloadType, codecInst->funcDecode, codecInst->funcDecodeRCU,
652 codecInst->funcDecodePLC, codecInst->funcDecodeInit, codecInst->funcAddLatePkt,
653 codecInst->funcGetMDinfo, codecInst->funcGetPitch, codecInst->funcUpdBWEst,
tina.legrand@webrtc.org5ac387c2012-11-19 08:02:55 +0000654 codecInst->funcDurationEst, codecInst->funcGetErrorCode,
655 codecInst->codec_state, codecInst->codec_fs);
niklase@google.com470e71d2011-07-07 08:21:25 +0000656 if (ok != 0)
657 {
658 NetEqMainInst->ErrorCode = -ok;
659 return (-1);
660 }
661 return (ok);
662}
663
664int WebRtcNetEQ_CodecDbRemove(void *inst, enum WebRtcNetEQDecoder codec)
665{
666 int ok = 0;
667 MainInst_t *NetEqMainInst = (MainInst_t*) inst;
668 if (NetEqMainInst == NULL) return (-1);
669
670 /* check if currently used codec is being removed */
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000671 if (NetEqMainInst->MCUinst.current_Codec == (int16_t) codec)
niklase@google.com470e71d2011-07-07 08:21:25 +0000672 {
673 /* set function pointers to NULL to prevent RecOut from using the codec */
674 NetEqMainInst->DSPinst.codec_ptr_inst.funcDecode = NULL;
675 NetEqMainInst->DSPinst.codec_ptr_inst.funcDecodeRCU = NULL;
676 NetEqMainInst->DSPinst.codec_ptr_inst.funcAddLatePkt = NULL;
677 NetEqMainInst->DSPinst.codec_ptr_inst.funcDecode = NULL;
678 NetEqMainInst->DSPinst.codec_ptr_inst.funcDecodeInit = NULL;
679 NetEqMainInst->DSPinst.codec_ptr_inst.funcDecodePLC = NULL;
680 NetEqMainInst->DSPinst.codec_ptr_inst.funcGetMDinfo = NULL;
681 NetEqMainInst->DSPinst.codec_ptr_inst.funcUpdBWEst = NULL;
682 NetEqMainInst->DSPinst.codec_ptr_inst.funcGetErrorCode = NULL;
683 }
684
685 ok = WebRtcNetEQ_DbRemove(&NetEqMainInst->MCUinst.codec_DB_inst, codec);
686 if (ok != 0)
687 {
688 NetEqMainInst->ErrorCode = -ok;
689 return (-1);
690 }
691 return (ok);
692}
693
694/*********************************
695 * Real-time functions
696 */
697
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000698int WebRtcNetEQ_RecIn(void *inst, int16_t *p_w16datagramstart, int16_t w16_RTPlen,
699 uint32_t uw32_timeRec)
niklase@google.com470e71d2011-07-07 08:21:25 +0000700{
701 int ok = 0;
702 RTPPacket_t RTPpacket;
703 MainInst_t *NetEqMainInst = (MainInst_t*) inst;
704 if (NetEqMainInst == NULL) return (-1);
705
706 /* Check for corrupt/cleared instance */
707 if (NetEqMainInst->MCUinst.main_inst != NetEqMainInst)
708 {
709 /* Instance is corrupt */
710 NetEqMainInst->ErrorCode = CORRUPT_INSTANCE;
711 return (-1);
712 }
713
714 /* Parse RTP header */
715 ok = WebRtcNetEQ_RTPPayloadInfo(p_w16datagramstart, w16_RTPlen, &RTPpacket);
716 if (ok != 0)
717 {
718 NetEqMainInst->ErrorCode = -ok;
719 return (-1);
720 }
721
722 ok = WebRtcNetEQ_RecInInternal(&NetEqMainInst->MCUinst, &RTPpacket, uw32_timeRec);
723 if (ok != 0)
724 {
725 NetEqMainInst->ErrorCode = -ok;
726 return (-1);
727 }
728 return (ok);
729}
730
731/****************************************************************************
732 * WebRtcNetEQ_RecInRTPStruct(...)
733 *
734 * Alternative RecIn function, used when the RTP data has already been
735 * parsed into an RTP info struct (WebRtcNetEQ_RTPInfo).
736 *
737 * Input:
738 * - inst : NetEQ instance
739 * - rtpInfo : Pointer to RTP info
740 * - payloadPtr : Pointer to the RTP payload (first byte after header)
741 * - payloadLenBytes : Length (in bytes) of the payload in payloadPtr
742 * - timeRec : Receive time (in timestamps of the used codec)
743 *
744 * Return value : 0 - Ok
745 * -1 - Error
746 */
747int WebRtcNetEQ_RecInRTPStruct(void *inst, WebRtcNetEQ_RTPInfo *rtpInfo,
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000748 const uint8_t *payloadPtr, int16_t payloadLenBytes,
749 uint32_t uw32_timeRec)
niklase@google.com470e71d2011-07-07 08:21:25 +0000750{
751 int ok = 0;
752 RTPPacket_t RTPpacket;
753 MainInst_t *NetEqMainInst = (MainInst_t*) inst;
754 if (NetEqMainInst == NULL)
755 {
756 return (-1);
757 }
758
759 /* Check for corrupt/cleared instance */
760 if (NetEqMainInst->MCUinst.main_inst != NetEqMainInst)
761 {
762 /* Instance is corrupt */
763 NetEqMainInst->ErrorCode = CORRUPT_INSTANCE;
764 return (-1);
765 }
766
767 /* Load NetEQ's RTP struct from Module RTP struct */
768 RTPpacket.payloadType = rtpInfo->payloadType;
769 RTPpacket.seqNumber = rtpInfo->sequenceNumber;
770 RTPpacket.timeStamp = rtpInfo->timeStamp;
771 RTPpacket.ssrc = rtpInfo->SSRC;
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000772 RTPpacket.payload = (const int16_t*) payloadPtr;
niklase@google.com470e71d2011-07-07 08:21:25 +0000773 RTPpacket.payloadLen = payloadLenBytes;
774 RTPpacket.starts_byte1 = 0;
775
776 ok = WebRtcNetEQ_RecInInternal(&NetEqMainInst->MCUinst, &RTPpacket, uw32_timeRec);
777 if (ok != 0)
778 {
779 NetEqMainInst->ErrorCode = -ok;
780 return (-1);
781 }
782 return (ok);
783}
784
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000785int WebRtcNetEQ_RecOut(void *inst, int16_t *pw16_outData, int16_t *pw16_len)
niklase@google.com470e71d2011-07-07 08:21:25 +0000786{
787 int ok = 0;
788 MainInst_t *NetEqMainInst = (MainInst_t*) inst;
789#ifdef NETEQ_STEREO
790 MasterSlaveInfo msInfo;
791 msInfo.msMode = NETEQ_MONO;
792#endif
793
794 if (NetEqMainInst == NULL) return (-1);
795
796 /* Check for corrupt/cleared instance */
797 if (NetEqMainInst->DSPinst.main_inst != NetEqMainInst)
798 {
799 /* Instance is corrupt */
800 NetEqMainInst->ErrorCode = CORRUPT_INSTANCE;
801 return (-1);
802 }
803
804#ifdef NETEQ_STEREO
805 NetEqMainInst->DSPinst.msInfo = &msInfo;
806#endif
807
808 ok = WebRtcNetEQ_RecOutInternal(&NetEqMainInst->DSPinst, pw16_outData,
809 pw16_len, 0 /* not BGN only */);
810 if (ok != 0)
811 {
812 NetEqMainInst->ErrorCode = -ok;
813 return (-1);
814 }
815 return (ok);
816}
817
818/****************************************************************************
819 * WebRtcNetEQ_RecOutMasterSlave(...)
820 *
821 * RecOut function for running several NetEQ instances in master/slave mode.
822 * One master can be used to control several slaves.
823 *
824 * Input:
825 * - inst : NetEQ instance
826 * - isMaster : Non-zero indicates that this is the master channel
827 * - msInfo : (slave only) Information from master
828 *
829 * Output:
830 * - inst : Updated NetEQ instance
831 * - pw16_outData : Pointer to vector where output should be written
832 * - pw16_len : Pointer to variable where output length is returned
833 * - msInfo : (master only) Information to slave(s)
834 *
835 * Return value : 0 - Ok
836 * -1 - Error
837 */
838
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000839int WebRtcNetEQ_RecOutMasterSlave(void *inst, int16_t *pw16_outData,
840 int16_t *pw16_len, void *msInfo,
841 int16_t isMaster)
niklase@google.com470e71d2011-07-07 08:21:25 +0000842{
843#ifndef NETEQ_STEREO
844 /* Stereo not supported */
845 return(-1);
846#else
847 int ok = 0;
848 MainInst_t *NetEqMainInst = (MainInst_t*) inst;
849
850 if (NetEqMainInst == NULL) return (-1);
851
852 /* Check for corrupt/cleared instance */
853 if (NetEqMainInst->DSPinst.main_inst != NetEqMainInst)
854 {
855 /* Instance is corrupt */
856 NetEqMainInst->ErrorCode = CORRUPT_INSTANCE;
857 return (-1);
858 }
859
860 if (msInfo == NULL)
861 {
862 /* msInfo not provided */
863 NetEqMainInst->ErrorCode = NETEQ_OTHER_ERROR;
864 return (-1);
865 }
866
867 /* translate from external to internal Master/Slave information */
868 NetEqMainInst->DSPinst.msInfo = (MasterSlaveInfo *) msInfo;
869
870 /* check that we have not done a master/slave switch without first re-initializing */
871 if ((NetEqMainInst->masterSlave == 1 && !isMaster) || /* switch from master to slave */
872 (NetEqMainInst->masterSlave == 2 && isMaster)) /* switch from slave to master */
873 {
874 NetEqMainInst->ErrorCode = ILLEGAL_MASTER_SLAVE_SWITCH;
875 return (-1);
876 }
877
878 if (!isMaster)
879 {
880 /* this is the slave */
881 NetEqMainInst->masterSlave = 2;
882 NetEqMainInst->DSPinst.msInfo->msMode = NETEQ_SLAVE;
883 }
884 else
885 {
886 NetEqMainInst->DSPinst.msInfo->msMode = NETEQ_MASTER;
887 }
888
889 ok = WebRtcNetEQ_RecOutInternal(&NetEqMainInst->DSPinst, pw16_outData,
890 pw16_len, 0 /* not BGN only */);
891 if (ok != 0)
892 {
893 NetEqMainInst->ErrorCode = -ok;
894 return (-1);
895 }
896
897 if (isMaster)
898 {
899 /* this is the master */
900 NetEqMainInst->masterSlave = 1;
901 }
902
903 return (ok);
904#endif
905}
906
907int WebRtcNetEQ_GetMasterSlaveInfoSize()
908{
909#ifdef NETEQ_STEREO
910 return (sizeof(MasterSlaveInfo));
911#else
912 return(-1);
913#endif
914}
915
916/* Special RecOut that does not do any decoding. */
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000917int WebRtcNetEQ_RecOutNoDecode(void *inst, int16_t *pw16_outData,
918 int16_t *pw16_len)
niklase@google.com470e71d2011-07-07 08:21:25 +0000919{
920 int ok = 0;
921 MainInst_t *NetEqMainInst = (MainInst_t*) inst;
922#ifdef NETEQ_STEREO
923 MasterSlaveInfo msInfo;
924#endif
925
926 if (NetEqMainInst == NULL) return (-1);
927
928 /* Check for corrupt/cleared instance */
929 if (NetEqMainInst->DSPinst.main_inst != NetEqMainInst)
930 {
931 /* Instance is corrupt */
932 NetEqMainInst->ErrorCode = CORRUPT_INSTANCE;
933 return (-1);
934 }
935
936#ifdef NETEQ_STEREO
937 /* keep same mode as before */
938 switch (NetEqMainInst->masterSlave)
939 {
940 case 1:
941 {
942 msInfo.msMode = NETEQ_MASTER;
943 break;
944 }
945 case 2:
946 {
947 msInfo.msMode = NETEQ_SLAVE;
948 break;
949 }
950 default:
951 {
952 msInfo.msMode = NETEQ_MONO;
953 break;
954 }
955 }
956
957 NetEqMainInst->DSPinst.msInfo = &msInfo;
958#endif
959
960 ok = WebRtcNetEQ_RecOutInternal(&NetEqMainInst->DSPinst, pw16_outData,
961 pw16_len, 1 /* BGN only */);
962 if (ok != 0)
963 {
964 NetEqMainInst->ErrorCode = -ok;
965 return (-1);
966 }
967 return (ok);
968}
969
970int WebRtcNetEQ_GetRTCPStats(void *inst, WebRtcNetEQ_RTCPStat *RTCP_inst)
971{
972 int ok = 0;
973 MainInst_t *NetEqMainInst = (MainInst_t*) inst;
974 if (NetEqMainInst == NULL) return (-1);
975 ok = WebRtcNetEQ_RTCPGetStats(&NetEqMainInst->MCUinst.RTCP_inst,
976 &RTCP_inst->fraction_lost, &RTCP_inst->cum_lost, &RTCP_inst->ext_max,
977 &RTCP_inst->jitter, 0);
978 if (ok != 0)
979 {
980 NetEqMainInst->ErrorCode = -ok;
981 return (-1);
982 }
983 return (ok);
984}
985
986int WebRtcNetEQ_GetRTCPStatsNoReset(void *inst, WebRtcNetEQ_RTCPStat *RTCP_inst)
987{
988 int ok = 0;
989 MainInst_t *NetEqMainInst = (MainInst_t*) inst;
990 if (NetEqMainInst == NULL) return (-1);
991 ok = WebRtcNetEQ_RTCPGetStats(&NetEqMainInst->MCUinst.RTCP_inst,
992 &RTCP_inst->fraction_lost, &RTCP_inst->cum_lost, &RTCP_inst->ext_max,
993 &RTCP_inst->jitter, 1);
994 if (ok != 0)
995 {
996 NetEqMainInst->ErrorCode = -ok;
997 return (-1);
998 }
999 return (ok);
1000}
1001
pbos@webrtc.org0946a562013-04-09 00:28:06 +00001002int WebRtcNetEQ_GetSpeechTimeStamp(void *inst, uint32_t *timestamp)
niklase@google.com470e71d2011-07-07 08:21:25 +00001003{
1004 MainInst_t *NetEqMainInst = (MainInst_t*) inst;
1005 if (NetEqMainInst == NULL) return (-1);
1006
1007 if (NetEqMainInst->MCUinst.TSscalingInitialized)
1008 {
1009 *timestamp = WebRtcNetEQ_ScaleTimestampInternalToExternal(&NetEqMainInst->MCUinst,
1010 NetEqMainInst->DSPinst.videoSyncTimestamp);
1011 }
1012 else
1013 {
1014 *timestamp = NetEqMainInst->DSPinst.videoSyncTimestamp;
1015 }
1016
1017 return (0);
1018}
1019
1020/****************************************************************************
1021 * WebRtcNetEQ_GetSpeechOutputType(...)
1022 *
1023 * Get the output type for the audio provided by the latest call to
1024 * WebRtcNetEQ_RecOut().
1025 *
1026 * kOutputNormal = normal audio (possibly processed)
1027 * kOutputPLC = loss concealment through stretching audio
1028 * kOutputCNG = comfort noise (codec-internal or RFC3389)
1029 * kOutputPLCtoCNG = background noise only due to long expand or error
1030 * kOutputVADPassive = PostDecode VAD signalling passive speaker
1031 *
1032 * Input:
1033 * - inst : NetEQ instance
1034 *
1035 * Output:
1036 * - outputType : Output type from enum list WebRtcNetEQOutputType
1037 *
1038 * Return value : 0 - Ok
1039 * -1 - Error
1040 */
1041
1042int WebRtcNetEQ_GetSpeechOutputType(void *inst, enum WebRtcNetEQOutputType *outputType)
1043{
1044 /* Typecast to internal instance type */
1045 MainInst_t *NetEqMainInst = (MainInst_t*) inst;
1046
1047 if (NetEqMainInst == NULL)
1048 {
1049 return (-1);
1050 }
1051
1052 if ((NetEqMainInst->DSPinst.w16_mode & MODE_BGN_ONLY) != 0)
1053 {
1054 /* If last mode was background noise only */
1055 *outputType = kOutputPLCtoCNG;
1056
1057 }
1058 else if ((NetEqMainInst->DSPinst.w16_mode == MODE_CODEC_INTERNAL_CNG)
1059 || (NetEqMainInst->DSPinst.w16_mode == MODE_RFC3389CNG))
1060 {
1061 /* If CN or internal CNG */
1062 *outputType = kOutputCNG;
1063
1064#ifdef NETEQ_VAD
1065 }
1066 else if ( NetEqMainInst->DSPinst.VADInst.VADDecision == 0 )
1067 {
1068 /* post-decode VAD says passive speaker */
1069 *outputType = kOutputVADPassive;
1070#endif /* NETEQ_VAD */
1071
1072 }
1073 else if ((NetEqMainInst->DSPinst.w16_mode == MODE_EXPAND)
1074 && (NetEqMainInst->DSPinst.ExpandInst.w16_expandMuteFactor == 0))
1075 {
1076 /* Expand mode has faded down to background noise only (very long expand) */
1077 *outputType = kOutputPLCtoCNG;
1078
1079 }
1080 else if (NetEqMainInst->DSPinst.w16_mode == MODE_EXPAND)
1081 {
1082 /* PLC mode */
1083 *outputType = kOutputPLC;
1084
1085 }
1086 else
1087 {
1088 /* Normal speech output type (can still be manipulated, e.g., accelerated) */
1089 *outputType = kOutputNormal;
1090 }
1091
1092 return (0);
1093}
1094
1095/**********************************
1096 * Functions related to VQmon
1097 */
1098
1099#define WEBRTC_NETEQ_CONCEALMENTFLAG_LOST 0x01
1100#define WEBRTC_NETEQ_CONCEALMENTFLAG_DISCARDED 0x02
1101#define WEBRTC_NETEQ_CONCEALMENTFLAG_SUPRESS 0x04
1102#define WEBRTC_NETEQ_CONCEALMENTFLAG_CNGACTIVE 0x80
1103
pbos@webrtc.org0946a562013-04-09 00:28:06 +00001104int WebRtcNetEQ_VQmonRecOutStatistics(void *inst, uint16_t *validVoiceDurationMs,
1105 uint16_t *concealedVoiceDurationMs,
1106 uint8_t *concealedVoiceFlags)
niklase@google.com470e71d2011-07-07 08:21:25 +00001107{
1108 MainInst_t *NetEqMainInst = (MainInst_t*) inst;
pbos@webrtc.org0946a562013-04-09 00:28:06 +00001109 int16_t fs_mult;
1110 int16_t ms_lost;
niklase@google.com470e71d2011-07-07 08:21:25 +00001111 if (NetEqMainInst == NULL) return (-1);
1112 fs_mult = WebRtcSpl_DivW32W16ResW16(NetEqMainInst->MCUinst.fs, 8000);
1113
1114 ms_lost = WebRtcSpl_DivW32W16ResW16(
pbos@webrtc.org0946a562013-04-09 00:28:06 +00001115 (int32_t) NetEqMainInst->DSPinst.w16_concealedTS, (int16_t) (8 * fs_mult));
niklase@google.com470e71d2011-07-07 08:21:25 +00001116 if (ms_lost > NetEqMainInst->DSPinst.millisecondsPerCall) ms_lost
1117 = NetEqMainInst->DSPinst.millisecondsPerCall;
1118
1119 *validVoiceDurationMs = NetEqMainInst->DSPinst.millisecondsPerCall - ms_lost;
1120 *concealedVoiceDurationMs = ms_lost;
1121 if (ms_lost > 0)
1122 {
1123 *concealedVoiceFlags = WEBRTC_NETEQ_CONCEALMENTFLAG_LOST;
1124 }
1125 else
1126 {
1127 *concealedVoiceFlags = 0;
1128 }
1129 NetEqMainInst->DSPinst.w16_concealedTS -= ms_lost * (8 * fs_mult);
1130
1131 return (0);
1132}
1133
pbos@webrtc.org0946a562013-04-09 00:28:06 +00001134int WebRtcNetEQ_VQmonGetConfiguration(void *inst, uint16_t *absMaxDelayMs,
1135 uint8_t *adaptationRate)
niklase@google.com470e71d2011-07-07 08:21:25 +00001136{
1137 /* Dummy check the inst, just to avoid compiler warnings. */
1138 if (inst == NULL)
1139 {
1140 /* Do nothing. */
1141 }
1142
1143 /* Hardcoded variables that are used for VQmon as jitter buffer parameters */
1144 *absMaxDelayMs = 240;
1145 *adaptationRate = 1;
1146 return (0);
1147}
1148
pbos@webrtc.org0946a562013-04-09 00:28:06 +00001149int WebRtcNetEQ_VQmonGetRxStatistics(void *inst, uint16_t *avgDelayMs,
1150 uint16_t *maxDelayMs)
niklase@google.com470e71d2011-07-07 08:21:25 +00001151{
1152 MainInst_t *NetEqMainInst = (MainInst_t*) inst;
1153 if (NetEqMainInst == NULL) return (-1);
pbos@webrtc.org0946a562013-04-09 00:28:06 +00001154 *avgDelayMs = (uint16_t) (NetEqMainInst->MCUinst.BufferStat_inst.avgDelayMsQ8 >> 8);
1155 *maxDelayMs = (uint16_t) NetEqMainInst->MCUinst.BufferStat_inst.maxDelayMs;
niklase@google.com470e71d2011-07-07 08:21:25 +00001156 return (0);
1157}
1158
1159/*************************************
1160 * Statistics functions
1161 */
1162
1163/* Get the "in-call" statistics from NetEQ.
1164 * The statistics are reset after the query. */
1165int WebRtcNetEQ_GetNetworkStatistics(void *inst, WebRtcNetEQ_NetworkStatistics *stats)
1166
1167{
1168
pbos@webrtc.org0946a562013-04-09 00:28:06 +00001169 uint16_t tempU16;
1170 uint32_t tempU32, tempU32_2;
niklase@google.com470e71d2011-07-07 08:21:25 +00001171 int numShift;
1172 MainInst_t *NetEqMainInst = (MainInst_t*) inst;
1173
1174 /* Instance sanity */
1175 if (NetEqMainInst == NULL) return (-1);
1176
roosa@google.comb8ba4d82012-12-14 00:06:18 +00001177 stats->addedSamples = NetEqMainInst->DSPinst.statInst.addedSamples;
1178
niklase@google.com470e71d2011-07-07 08:21:25 +00001179 /*******************/
1180 /* Get buffer size */
1181 /*******************/
1182
henrik.lundin@webrtc.org524eb482011-11-30 16:21:22 +00001183 if (NetEqMainInst->MCUinst.fs != 0)
niklase@google.com470e71d2011-07-07 08:21:25 +00001184 {
pbos@webrtc.org0946a562013-04-09 00:28:06 +00001185 int32_t temp32;
henrik.lundin@webrtc.org524eb482011-11-30 16:21:22 +00001186 /* Query packet buffer for number of samples. */
1187 temp32 = WebRtcNetEQ_PacketBufferGetSize(
tina.legrand@webrtc.org5ac387c2012-11-19 08:02:55 +00001188 &NetEqMainInst->MCUinst.PacketBuffer_inst,
1189 &NetEqMainInst->MCUinst.codec_DB_inst);
henrik.lundin@webrtc.org524eb482011-11-30 16:21:22 +00001190
1191 /* Divide by sample rate.
1192 * Calculate temp32 * 1000 / fs to get result in ms. */
pbos@webrtc.org0946a562013-04-09 00:28:06 +00001193 stats->currentBufferSize = (uint16_t)
henrik.lundin@webrtc.org524eb482011-11-30 16:21:22 +00001194 WebRtcSpl_DivU32U16(temp32 * 1000, NetEqMainInst->MCUinst.fs);
1195
1196 /* Add number of samples yet to play in sync buffer. */
pbos@webrtc.org0946a562013-04-09 00:28:06 +00001197 temp32 = (int32_t) (NetEqMainInst->DSPinst.endPosition -
henrik.lundin@webrtc.org524eb482011-11-30 16:21:22 +00001198 NetEqMainInst->DSPinst.curPosition);
pbos@webrtc.org0946a562013-04-09 00:28:06 +00001199 stats->currentBufferSize += (uint16_t)
henrik.lundin@webrtc.org524eb482011-11-30 16:21:22 +00001200 WebRtcSpl_DivU32U16(temp32 * 1000, NetEqMainInst->MCUinst.fs);
1201 }
1202 else
1203 {
1204 /* Sample rate not initialized. */
1205 stats->currentBufferSize = 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001206 }
1207
1208 /***************************/
1209 /* Get optimal buffer size */
1210 /***************************/
1211
1212 if (NetEqMainInst->MCUinst.fs != 0 && NetEqMainInst->MCUinst.fs <= WEBRTC_SPL_WORD16_MAX)
1213 {
1214 /* preferredBufferSize = Bopt * packSizeSamples / (fs/1000) */
1215 stats->preferredBufferSize
pbos@webrtc.org0946a562013-04-09 00:28:06 +00001216 = (uint16_t) WEBRTC_SPL_MUL_16_16(
1217 (int16_t) ((NetEqMainInst->MCUinst.BufferStat_inst.Automode_inst.optBufLevel) >> 8), /* optimal buffer level in packets shifted to Q0 */
niklase@google.com470e71d2011-07-07 08:21:25 +00001218 WebRtcSpl_DivW32W16ResW16(
pbos@webrtc.org0946a562013-04-09 00:28:06 +00001219 (int32_t) NetEqMainInst->MCUinst.BufferStat_inst.Automode_inst.packetSpeechLenSamp, /* samples per packet */
1220 WebRtcSpl_DivW32W16ResW16( (int32_t) NetEqMainInst->MCUinst.fs, (int16_t) 1000 ) /* samples per ms */
niklase@google.com470e71d2011-07-07 08:21:25 +00001221 ) );
1222
1223 /* add extra delay */
1224 if (NetEqMainInst->MCUinst.BufferStat_inst.Automode_inst.extraDelayMs > 0)
1225 {
1226 stats->preferredBufferSize
1227 += NetEqMainInst->MCUinst.BufferStat_inst.Automode_inst.extraDelayMs;
1228 }
1229 }
1230 else
1231 {
1232 /* sample rate not initialized */
1233 stats->preferredBufferSize = 0;
1234 }
1235
henrik.lundin@webrtc.orgd4398702012-01-04 13:09:55 +00001236 /***********************************/
1237 /* Check if jitter peaks are found */
1238 /***********************************/
1239
1240 stats->jitterPeaksFound =
1241 NetEqMainInst->MCUinst.BufferStat_inst.Automode_inst.peakFound;
1242
niklase@google.com470e71d2011-07-07 08:21:25 +00001243 /***********************/
1244 /* Calculate loss rate */
1245 /***********************/
1246
1247 /* timestamps elapsed since last report */
1248 tempU32 = NetEqMainInst->MCUinst.lastReportTS;
1249
1250 if (NetEqMainInst->MCUinst.lostTS == 0)
1251 {
1252 /* no losses */
1253 stats->currentPacketLossRate = 0;
1254 }
1255 else if (NetEqMainInst->MCUinst.lostTS < tempU32)
1256 {
1257 /* calculate shifts; we want the result in Q14 */
1258 numShift = WebRtcSpl_NormU32(NetEqMainInst->MCUinst.lostTS); /* numerator shift for normalize */
1259
1260 if (numShift < 14)
1261 {
1262 /* cannot shift numerator 14 steps; shift denominator too */
1263 tempU32 = WEBRTC_SPL_RSHIFT_U32(tempU32, 14-numShift); /* right-shift */
1264 }
1265 else
1266 {
1267 /* shift no more than 14 steps */
1268 numShift = 14;
1269 }
1270
1271 if (tempU32 == 0)
1272 {
1273 /* check for zero denominator; result should be zero in this case */
1274 stats->currentPacketLossRate = 0;
1275 }
1276 else
1277 {
1278 /* check that denominator fits in signed 16-bit */
1279 while (tempU32 > WEBRTC_SPL_WORD16_MAX)
1280 {
1281 tempU32 >>= 1; /* right-shift 1 step */
1282 numShift--; /* compensate in numerator */
1283 }
pbos@webrtc.org0946a562013-04-09 00:28:06 +00001284 tempU16 = (uint16_t) tempU32;
niklase@google.com470e71d2011-07-07 08:21:25 +00001285
1286 /* do the shift of numerator */
1287 tempU32
pbos@webrtc.org0946a562013-04-09 00:28:06 +00001288 = WEBRTC_SPL_SHIFT_W32( (uint32_t) NetEqMainInst->MCUinst.lostTS, numShift);
niklase@google.com470e71d2011-07-07 08:21:25 +00001289
pbos@webrtc.org0946a562013-04-09 00:28:06 +00001290 stats->currentPacketLossRate = (uint16_t) WebRtcSpl_DivU32U16(tempU32,
niklase@google.com470e71d2011-07-07 08:21:25 +00001291 tempU16);
1292 }
1293 }
1294 else
1295 {
1296 /* lost count is larger than elapsed time count; probably timestamp wrap-around or something else wrong */
1297 /* set loss rate = 1 */
1298 stats->currentPacketLossRate = 1 << 14; /* 1 in Q14 */
1299 }
1300
1301 /**************************/
1302 /* Calculate discard rate */
1303 /**************************/
1304
1305 /* timestamps elapsed since last report */
1306 tempU32 = NetEqMainInst->MCUinst.lastReportTS;
1307
1308 /* number of discarded samples */
1309 tempU32_2
pbos@webrtc.org0946a562013-04-09 00:28:06 +00001310 = WEBRTC_SPL_MUL_16_U16( (int16_t) NetEqMainInst->MCUinst.PacketBuffer_inst.packSizeSamples,
niklase@google.com470e71d2011-07-07 08:21:25 +00001311 NetEqMainInst->MCUinst.PacketBuffer_inst.discardedPackets);
1312
1313 if (tempU32_2 == 0)
1314 {
1315 /* no discarded samples */
1316 stats->currentDiscardRate = 0;
1317 }
1318 else if (tempU32_2 < tempU32)
1319 {
1320 /* calculate shifts; we want the result in Q14 */
1321 numShift = WebRtcSpl_NormU32(tempU32_2); /* numerator shift for normalize */
1322
1323 if (numShift < 14)
1324 {
1325 /* cannot shift numerator 14 steps; shift denominator too */
1326 tempU32 = WEBRTC_SPL_RSHIFT_U32(tempU32, 14-numShift); /* right-shift */
1327 }
1328 else
1329 {
1330 /* shift no more than 14 steps */
1331 numShift = 14;
1332 }
1333
1334 if (tempU32 == 0)
1335 {
1336 /* check for zero denominator; result should be zero in this case */
1337 stats->currentDiscardRate = 0;
1338 }
1339 else
1340 {
1341 /* check that denominator fits in signed 16-bit */
1342 while (tempU32 > WEBRTC_SPL_WORD16_MAX)
1343 {
1344 tempU32 >>= 1; /* right-shift 1 step */
1345 numShift--; /* compensate in numerator */
1346 }
pbos@webrtc.org0946a562013-04-09 00:28:06 +00001347 tempU16 = (uint16_t) tempU32;
niklase@google.com470e71d2011-07-07 08:21:25 +00001348
1349 /* do the shift of numerator */
1350 tempU32 = WEBRTC_SPL_SHIFT_W32( tempU32_2, numShift);
1351
pbos@webrtc.org0946a562013-04-09 00:28:06 +00001352 stats->currentDiscardRate = (uint16_t) WebRtcSpl_DivU32U16(tempU32, tempU16);
niklase@google.com470e71d2011-07-07 08:21:25 +00001353 }
1354 }
1355 else
1356 {
1357 /* lost count is larger than elapsed time count; probably timestamp wrap-around or something else wrong */
1358 /* set loss rate = 1 */
1359 stats->currentDiscardRate = 1 << 14; /* 1 in Q14 */
1360 }
1361
1362 /*************************************************************/
1363 /* Calculate Accelerate, Expand and Pre-emptive Expand rates */
1364 /*************************************************************/
1365
1366 /* timestamps elapsed since last report */
1367 tempU32 = NetEqMainInst->MCUinst.lastReportTS;
1368
1369 if (NetEqMainInst->DSPinst.statInst.accelerateLength == 0)
1370 {
1371 /* no accelerate */
1372 stats->currentAccelerateRate = 0;
1373 }
1374 else if (NetEqMainInst->DSPinst.statInst.accelerateLength < tempU32)
1375 {
1376 /* calculate shifts; we want the result in Q14 */
1377 numShift = WebRtcSpl_NormU32(NetEqMainInst->DSPinst.statInst.accelerateLength); /* numerator shift for normalize */
1378
1379 if (numShift < 14)
1380 {
1381 /* cannot shift numerator 14 steps; shift denominator too */
1382 tempU32 = WEBRTC_SPL_RSHIFT_U32(tempU32, 14-numShift); /* right-shift */
1383 }
1384 else
1385 {
1386 /* shift no more than 14 steps */
1387 numShift = 14;
1388 }
1389
1390 if (tempU32 == 0)
1391 {
1392 /* check for zero denominator; result should be zero in this case */
1393 stats->currentAccelerateRate = 0;
1394 }
1395 else
1396 {
1397 /* check that denominator fits in signed 16-bit */
1398 while (tempU32 > WEBRTC_SPL_WORD16_MAX)
1399 {
1400 tempU32 >>= 1; /* right-shift 1 step */
1401 numShift--; /* compensate in numerator */
1402 }
pbos@webrtc.org0946a562013-04-09 00:28:06 +00001403 tempU16 = (uint16_t) tempU32;
niklase@google.com470e71d2011-07-07 08:21:25 +00001404
1405 /* do the shift of numerator */
1406 tempU32
1407 = WEBRTC_SPL_SHIFT_W32( NetEqMainInst->DSPinst.statInst.accelerateLength, numShift);
1408
pbos@webrtc.org0946a562013-04-09 00:28:06 +00001409 stats->currentAccelerateRate = (uint16_t) WebRtcSpl_DivU32U16(tempU32,
niklase@google.com470e71d2011-07-07 08:21:25 +00001410 tempU16);
1411 }
1412 }
1413 else
1414 {
1415 /* lost count is larger than elapsed time count; probably timestamp wrap-around or something else wrong */
1416 /* set loss rate = 1 */
1417 stats->currentAccelerateRate = 1 << 14; /* 1 in Q14 */
1418 }
1419
niklase@google.com470e71d2011-07-07 08:21:25 +00001420 /* timestamps elapsed since last report */
1421 tempU32 = NetEqMainInst->MCUinst.lastReportTS;
1422
1423 if (NetEqMainInst->DSPinst.statInst.expandLength == 0)
1424 {
1425 /* no expand */
1426 stats->currentExpandRate = 0;
1427 }
1428 else if (NetEqMainInst->DSPinst.statInst.expandLength < tempU32)
1429 {
1430 /* calculate shifts; we want the result in Q14 */
1431 numShift = WebRtcSpl_NormU32(NetEqMainInst->DSPinst.statInst.expandLength); /* numerator shift for normalize */
1432
1433 if (numShift < 14)
1434 {
1435 /* cannot shift numerator 14 steps; shift denominator too */
1436 tempU32 = WEBRTC_SPL_RSHIFT_U32(tempU32, 14-numShift); /* right-shift */
1437 }
1438 else
1439 {
1440 /* shift no more than 14 steps */
1441 numShift = 14;
1442 }
1443
1444 if (tempU32 == 0)
1445 {
1446 /* check for zero denominator; result should be zero in this case */
1447 stats->currentExpandRate = 0;
1448 }
1449 else
1450 {
1451 /* check that denominator fits in signed 16-bit */
1452 while (tempU32 > WEBRTC_SPL_WORD16_MAX)
1453 {
1454 tempU32 >>= 1; /* right-shift 1 step */
1455 numShift--; /* compensate in numerator */
1456 }
pbos@webrtc.org0946a562013-04-09 00:28:06 +00001457 tempU16 = (uint16_t) tempU32;
niklase@google.com470e71d2011-07-07 08:21:25 +00001458
1459 /* do the shift of numerator */
1460 tempU32
1461 = WEBRTC_SPL_SHIFT_W32( NetEqMainInst->DSPinst.statInst.expandLength, numShift);
1462
pbos@webrtc.org0946a562013-04-09 00:28:06 +00001463 stats->currentExpandRate = (uint16_t) WebRtcSpl_DivU32U16(tempU32, tempU16);
niklase@google.com470e71d2011-07-07 08:21:25 +00001464 }
1465 }
1466 else
1467 {
1468 /* lost count is larger than elapsed time count; probably timestamp wrap-around or something else wrong */
1469 /* set loss rate = 1 */
1470 stats->currentExpandRate = 1 << 14; /* 1 in Q14 */
1471 }
1472
1473 /* timestamps elapsed since last report */
1474 tempU32 = NetEqMainInst->MCUinst.lastReportTS;
1475
1476 if (NetEqMainInst->DSPinst.statInst.preemptiveLength == 0)
1477 {
1478 /* no pre-emptive expand */
1479 stats->currentPreemptiveRate = 0;
1480 }
1481 else if (NetEqMainInst->DSPinst.statInst.preemptiveLength < tempU32)
1482 {
1483 /* calculate shifts; we want the result in Q14 */
1484 numShift = WebRtcSpl_NormU32(NetEqMainInst->DSPinst.statInst.preemptiveLength); /* numerator shift for normalize */
1485
1486 if (numShift < 14)
1487 {
1488 /* cannot shift numerator 14 steps; shift denominator too */
1489 tempU32 = WEBRTC_SPL_RSHIFT_U32(tempU32, 14-numShift); /* right-shift */
1490 }
1491 else
1492 {
1493 /* shift no more than 14 steps */
1494 numShift = 14;
1495 }
1496
1497 if (tempU32 == 0)
1498 {
1499 /* check for zero denominator; result should be zero in this case */
1500 stats->currentPreemptiveRate = 0;
1501 }
1502 else
1503 {
1504 /* check that denominator fits in signed 16-bit */
1505 while (tempU32 > WEBRTC_SPL_WORD16_MAX)
1506 {
1507 tempU32 >>= 1; /* right-shift 1 step */
1508 numShift--; /* compensate in numerator */
1509 }
pbos@webrtc.org0946a562013-04-09 00:28:06 +00001510 tempU16 = (uint16_t) tempU32;
niklase@google.com470e71d2011-07-07 08:21:25 +00001511
1512 /* do the shift of numerator */
1513 tempU32
1514 = WEBRTC_SPL_SHIFT_W32( NetEqMainInst->DSPinst.statInst.preemptiveLength, numShift);
1515
pbos@webrtc.org0946a562013-04-09 00:28:06 +00001516 stats->currentPreemptiveRate = (uint16_t) WebRtcSpl_DivU32U16(tempU32,
niklase@google.com470e71d2011-07-07 08:21:25 +00001517 tempU16);
1518 }
1519 }
1520 else
1521 {
1522 /* lost count is larger than elapsed time count; probably timestamp wrap-around or something else wrong */
1523 /* set loss rate = 1 */
1524 stats->currentPreemptiveRate = 1 << 14; /* 1 in Q14 */
1525 }
1526
henrik.lundin@webrtc.orgd4398702012-01-04 13:09:55 +00001527 stats->clockDriftPPM = WebRtcNetEQ_AverageIAT(
1528 &NetEqMainInst->MCUinst.BufferStat_inst.Automode_inst);
1529
niklase@google.com470e71d2011-07-07 08:21:25 +00001530 /* reset counters */
1531 WebRtcNetEQ_ResetMcuInCallStats(&(NetEqMainInst->MCUinst));
1532 WebRtcNetEQ_ClearInCallStats(&(NetEqMainInst->DSPinst));
1533
1534 return (0);
1535}
1536
henrik.lundin@webrtc.orgdbba1f92011-12-20 15:45:05 +00001537int WebRtcNetEQ_GetRawFrameWaitingTimes(void *inst,
1538 int max_length,
1539 int* waiting_times_ms) {
1540 int i = 0;
1541 MainInst_t *main_inst = (MainInst_t*) inst;
1542 if (main_inst == NULL) return -1;
1543
1544 while ((i < max_length) && (i < main_inst->MCUinst.len_waiting_times)) {
1545 waiting_times_ms[i] = main_inst->MCUinst.waiting_times[i] *
1546 main_inst->DSPinst.millisecondsPerCall;
1547 ++i;
1548 }
1549 assert(i <= kLenWaitingTimes);
1550 WebRtcNetEQ_ResetWaitingTimeStats(&main_inst->MCUinst);
1551 return i;
1552}
1553
niklase@google.com470e71d2011-07-07 08:21:25 +00001554/****************************************************************************
1555 * WebRtcNetEQ_SetVADInstance(...)
1556 *
1557 * Provide a pointer to an allocated VAD instance. If function is never
1558 * called or it is called with NULL pointer as VAD_inst, the post-decode
1559 * VAD functionality is disabled. Also provide pointers to init, setmode
1560 * and VAD functions. These are typically pointers to WebRtcVad_Init,
1561 * WebRtcVad_set_mode and WebRtcVad_Process, respectively, all found in the
1562 * interface file webrtc_vad.h.
1563 *
1564 * Input:
1565 * - NetEQ_inst : NetEQ instance
1566 * - VADinst : VAD instance
1567 * - initFunction : Pointer to VAD init function
1568 * - setmodeFunction : Pointer to VAD setmode function
1569 * - VADfunction : Pointer to VAD function
1570 *
1571 * Output:
1572 * - NetEQ_inst : Updated NetEQ instance
1573 *
1574 * Return value : 0 - Ok
1575 * -1 - Error
1576 */
1577
1578int WebRtcNetEQ_SetVADInstance(void *NetEQ_inst, void *VAD_inst,
1579 WebRtcNetEQ_VADInitFunction initFunction,
1580 WebRtcNetEQ_VADSetmodeFunction setmodeFunction,
1581 WebRtcNetEQ_VADFunction VADFunction)
1582{
1583
1584 /* Typecast to internal instance type */
1585 MainInst_t *NetEqMainInst = (MainInst_t*) NetEQ_inst;
1586 if (NetEqMainInst == NULL)
1587 {
1588 return (-1);
1589 }
1590
1591#ifdef NETEQ_VAD
1592
1593 /* Store pointer in PostDecode VAD struct */
1594 NetEqMainInst->DSPinst.VADInst.VADState = VAD_inst;
1595
1596 /* Store function pointers */
1597 NetEqMainInst->DSPinst.VADInst.initFunction = initFunction;
1598 NetEqMainInst->DSPinst.VADInst.setmodeFunction = setmodeFunction;
1599 NetEqMainInst->DSPinst.VADInst.VADFunction = VADFunction;
1600
1601 /* Call init function and return the result (ok or fail) */
1602 return(WebRtcNetEQ_InitVAD(&NetEqMainInst->DSPinst.VADInst, NetEqMainInst->DSPinst.fs));
1603
1604#else /* NETEQ_VAD not defined */
1605 return (-1);
1606#endif /* NETEQ_VAD */
1607
1608}
1609
1610/****************************************************************************
1611 * WebRtcNetEQ_SetVADMode(...)
1612 *
1613 * Pass an aggressiveness mode parameter to the post-decode VAD instance.
1614 * If this function is never called, mode 0 (quality mode) is used as default.
1615 *
1616 * Input:
1617 * - inst : NetEQ instance
1618 * - mode : mode parameter (same range as WebRtc VAD mode)
1619 *
1620 * Output:
1621 * - inst : Updated NetEQ instance
1622 *
1623 * Return value : 0 - Ok
1624 * -1 - Error
1625 */
1626
bjornv@webrtc.orgf4b77fd2012-01-25 12:40:00 +00001627int WebRtcNetEQ_SetVADMode(void *inst, int mode)
niklase@google.com470e71d2011-07-07 08:21:25 +00001628{
1629
1630 /* Typecast to internal instance type */
1631 MainInst_t *NetEqMainInst = (MainInst_t*) inst;
1632 if (NetEqMainInst == NULL)
1633 {
1634 return (-1);
1635 }
1636
1637#ifdef NETEQ_VAD
1638
1639 /* Set mode and return result */
1640 return(WebRtcNetEQ_SetVADModeInternal(&NetEqMainInst->DSPinst.VADInst, mode));
1641
1642#else /* NETEQ_VAD not defined */
1643 return (-1);
1644#endif /* NETEQ_VAD */
1645
1646}