blob: 83479252faef22220568065a239e257d2a6d00fa [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;
turaj@webrtc.orge46c8d32013-05-22 20:39:43 +0000440 NetEqMainInst->MCUinst.BufferStat_inst.Automode_inst.minimum_delay_ms = 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000441 NetEqMainInst->MCUinst.NoOfExpandCalls = 0;
442 NetEqMainInst->MCUinst.fs = fs;
443
turaj@webrtc.org28d54ab2013-04-22 18:53:35 +0000444 /* Not in AV-sync by default. */
445 NetEqMainInst->MCUinst.av_sync = 0;
446
niklase@google.com470e71d2011-07-07 08:21:25 +0000447#ifdef NETEQ_ATEVENT_DECODE
448 /* init DTMF decoder */
449 ok = WebRtcNetEQ_DtmfDecoderInit(&(NetEqMainInst->MCUinst.DTMF_inst),fs,560);
450 RETURN_ON_ERROR(ok, NetEqMainInst);
451#endif
452
453 /* init RTCP statistics */
454 WebRtcNetEQ_RTCPInit(&(NetEqMainInst->MCUinst.RTCP_inst), 0);
455
456 /* set BufferStat struct to zero */
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000457 WebRtcSpl_MemSetW16((int16_t*) &(NetEqMainInst->MCUinst.BufferStat_inst), 0,
458 sizeof(BufstatsInst_t) / sizeof(int16_t));
niklase@google.com470e71d2011-07-07 08:21:25 +0000459
460 /* reset automode */
461 WebRtcNetEQ_ResetAutomode(&(NetEqMainInst->MCUinst.BufferStat_inst.Automode_inst),
462 NetEqMainInst->MCUinst.PacketBuffer_inst.maxInsertPositions);
463
464 NetEqMainInst->ErrorCode = 0;
465
466#ifdef NETEQ_STEREO
467 /* set master/slave info to undecided */
468 NetEqMainInst->masterSlave = 0;
469#endif
470
471 return (ok);
472}
473
474int WebRtcNetEQ_FlushBuffers(void *inst)
475{
476 int ok = 0;
477
478 /* Typecast inst to internal instance format */
479 MainInst_t *NetEqMainInst = (MainInst_t*) inst;
480
481 if (NetEqMainInst == NULL)
482 {
483 return (-1);
484 }
485
486 /* Flush packet buffer */
487 ok = WebRtcNetEQ_PacketBufferFlush(&NetEqMainInst->MCUinst.PacketBuffer_inst);
488 RETURN_ON_ERROR(ok, NetEqMainInst);
489
490 /* Set MCU to wait for new codec */
491 NetEqMainInst->MCUinst.first_packet = 1;
492
493 /* Flush speech buffer */
494 ok = WebRtcNetEQ_FlushSpeechBuffer(&NetEqMainInst->DSPinst);
495 RETURN_ON_ERROR(ok, NetEqMainInst);
496
497 return 0;
498}
499
500int WebRtcNetEQ_SetAVTPlayout(void *inst, int PlayoutAVTon)
501{
502 MainInst_t *NetEqMainInst = (MainInst_t*) inst;
503 if (NetEqMainInst == NULL) return (-1);
504#ifdef NETEQ_ATEVENT_DECODE
505 NetEqMainInst->MCUinst.AVT_PlayoutOn = PlayoutAVTon;
506 return(0);
507#else
508 if (PlayoutAVTon != 0)
509 {
510 NetEqMainInst->ErrorCode = -DTMF_NOT_SUPPORTED;
511 return (-1);
512 }
513 else
514 {
515 return (0);
516 }
517#endif
518}
519
520int WebRtcNetEQ_SetExtraDelay(void *inst, int DelayInMs)
521{
522 MainInst_t *NetEqMainInst = (MainInst_t*) inst;
523 if (NetEqMainInst == NULL) return (-1);
turaj@webrtc.org6388c3e2013-02-12 21:42:18 +0000524 if ((DelayInMs < 0) || (DelayInMs > 10000))
niklase@google.com470e71d2011-07-07 08:21:25 +0000525 {
526 NetEqMainInst->ErrorCode = -FAULTY_DELAYVALUE;
527 return (-1);
528 }
529 NetEqMainInst->MCUinst.BufferStat_inst.Automode_inst.extraDelayMs = DelayInMs;
530 return (0);
531}
532
turaj@webrtc.orge46c8d32013-05-22 20:39:43 +0000533int WebRtcNetEQ_SetMinimumDelay(void *inst, int minimum_delay_ms) {
534 MainInst_t *NetEqMainInst = (MainInst_t*) inst;
535 if (NetEqMainInst == NULL)
536 return -1;
537 if (minimum_delay_ms < 0 || minimum_delay_ms > 10000) {
538 NetEqMainInst->ErrorCode = -FAULTY_DELAYVALUE;
539 return -1;
540 }
541 NetEqMainInst->MCUinst.BufferStat_inst.Automode_inst.minimum_delay_ms =
542 minimum_delay_ms;
543 return 0;
544}
545
niklase@google.com470e71d2011-07-07 08:21:25 +0000546int WebRtcNetEQ_SetPlayoutMode(void *inst, enum WebRtcNetEQPlayoutMode playoutMode)
547{
548 MainInst_t *NetEqMainInst = (MainInst_t*) inst;
549 if (NetEqMainInst == NULL) return (-1);
550 if ((playoutMode != kPlayoutOn) && (playoutMode != kPlayoutOff) && (playoutMode
551 != kPlayoutFax) && (playoutMode != kPlayoutStreaming))
552 {
553 NetEqMainInst->ErrorCode = -FAULTY_PLAYOUTMODE;
554 return (-1);
555 }
556 else
557 {
558 NetEqMainInst->MCUinst.NetEqPlayoutMode = playoutMode;
559 return (0);
560 }
561}
562
563int WebRtcNetEQ_SetBGNMode(void *inst, enum WebRtcNetEQBGNMode bgnMode)
564{
565
566 MainInst_t *NetEqMainInst = (MainInst_t*) inst;
567
568 /* Instance sanity */
569 if (NetEqMainInst == NULL) return (-1);
570
571 /* Check for corrupt/cleared instance */
572 if (NetEqMainInst->MCUinst.main_inst != NetEqMainInst)
573 {
574 /* Instance is corrupt */
575 NetEqMainInst->ErrorCode = CORRUPT_INSTANCE;
576 return (-1);
577 }
578
579 NetEqMainInst->DSPinst.BGNInst.bgnMode = (enum BGNMode) bgnMode;
580
581 return (0);
582}
583
584int WebRtcNetEQ_GetBGNMode(const void *inst, enum WebRtcNetEQBGNMode *bgnMode)
585{
586
587 const MainInst_t *NetEqMainInst = (const MainInst_t*) inst;
588
589 /* Instance sanity */
590 if (NetEqMainInst == NULL) return (-1);
591
592 *bgnMode = (enum WebRtcNetEQBGNMode) NetEqMainInst->DSPinst.BGNInst.bgnMode;
593
594 return (0);
595}
596
597/************************************************
598 * CodecDB functions
599 */
600
601int WebRtcNetEQ_CodecDbReset(void *inst)
602{
603 int ok = 0;
604 MainInst_t *NetEqMainInst = (MainInst_t*) inst;
605 if (NetEqMainInst == NULL) return (-1);
606 ok = WebRtcNetEQ_DbReset(&NetEqMainInst->MCUinst.codec_DB_inst);
607 if (ok != 0)
608 {
609 NetEqMainInst->ErrorCode = -ok;
610 return (-1);
611 }
612
613 /* set function pointers to NULL to prevent RecOut from using the codec */
614 NetEqMainInst->DSPinst.codec_ptr_inst.funcDecode = NULL;
615 NetEqMainInst->DSPinst.codec_ptr_inst.funcDecodeRCU = NULL;
616 NetEqMainInst->DSPinst.codec_ptr_inst.funcAddLatePkt = NULL;
617 NetEqMainInst->DSPinst.codec_ptr_inst.funcDecode = NULL;
618 NetEqMainInst->DSPinst.codec_ptr_inst.funcDecodeInit = NULL;
619 NetEqMainInst->DSPinst.codec_ptr_inst.funcDecodePLC = NULL;
620 NetEqMainInst->DSPinst.codec_ptr_inst.funcGetMDinfo = NULL;
621 NetEqMainInst->DSPinst.codec_ptr_inst.funcUpdBWEst = NULL;
622 NetEqMainInst->DSPinst.codec_ptr_inst.funcGetErrorCode = NULL;
623
624 return (0);
625}
626
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000627int WebRtcNetEQ_CodecDbGetSizeInfo(void *inst, int16_t *UsedEntries,
628 int16_t *MaxEntries)
niklase@google.com470e71d2011-07-07 08:21:25 +0000629{
630 MainInst_t *NetEqMainInst = (MainInst_t*) inst;
631 if (NetEqMainInst == NULL) return (-1);
632 *MaxEntries = NUM_CODECS;
633 *UsedEntries = NetEqMainInst->MCUinst.codec_DB_inst.nrOfCodecs;
634 return (0);
635}
636
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000637int WebRtcNetEQ_CodecDbGetCodecInfo(void *inst, int16_t Entry,
niklase@google.com470e71d2011-07-07 08:21:25 +0000638 enum WebRtcNetEQDecoder *codec)
639{
640 int i;
641 MainInst_t *NetEqMainInst = (MainInst_t*) inst;
642 if (NetEqMainInst == NULL) return (-1);
643 *codec = (enum WebRtcNetEQDecoder) 0;
644 if ((Entry >= 0) && (Entry < NetEqMainInst->MCUinst.codec_DB_inst.nrOfCodecs))
645 {
646 for (i = 0; i < NUM_TOTAL_CODECS; i++)
647 {
648 if (NetEqMainInst->MCUinst.codec_DB_inst.position[i] == Entry)
649 {
650 *codec = (enum WebRtcNetEQDecoder) i;
651 }
652 }
653 }
654 else
655 {
656 NetEqMainInst->ErrorCode = -(CODEC_DB_NOT_EXIST1);
657 return (-1);
658 }
659 return (0);
660}
661
662int WebRtcNetEQ_CodecDbAdd(void *inst, WebRtcNetEQ_CodecDef *codecInst)
663{
664 int ok = 0;
665 MainInst_t *NetEqMainInst = (MainInst_t*) inst;
666 if (NetEqMainInst == NULL) return (-1);
667 ok = WebRtcNetEQ_DbAdd(&NetEqMainInst->MCUinst.codec_DB_inst, codecInst->codec,
668 codecInst->payloadType, codecInst->funcDecode, codecInst->funcDecodeRCU,
669 codecInst->funcDecodePLC, codecInst->funcDecodeInit, codecInst->funcAddLatePkt,
670 codecInst->funcGetMDinfo, codecInst->funcGetPitch, codecInst->funcUpdBWEst,
tina.legrand@webrtc.org5ac387c2012-11-19 08:02:55 +0000671 codecInst->funcDurationEst, codecInst->funcGetErrorCode,
672 codecInst->codec_state, codecInst->codec_fs);
niklase@google.com470e71d2011-07-07 08:21:25 +0000673 if (ok != 0)
674 {
675 NetEqMainInst->ErrorCode = -ok;
676 return (-1);
677 }
678 return (ok);
679}
680
681int WebRtcNetEQ_CodecDbRemove(void *inst, enum WebRtcNetEQDecoder codec)
682{
683 int ok = 0;
684 MainInst_t *NetEqMainInst = (MainInst_t*) inst;
685 if (NetEqMainInst == NULL) return (-1);
686
687 /* check if currently used codec is being removed */
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000688 if (NetEqMainInst->MCUinst.current_Codec == (int16_t) codec)
niklase@google.com470e71d2011-07-07 08:21:25 +0000689 {
690 /* set function pointers to NULL to prevent RecOut from using the codec */
691 NetEqMainInst->DSPinst.codec_ptr_inst.funcDecode = NULL;
692 NetEqMainInst->DSPinst.codec_ptr_inst.funcDecodeRCU = NULL;
693 NetEqMainInst->DSPinst.codec_ptr_inst.funcAddLatePkt = NULL;
694 NetEqMainInst->DSPinst.codec_ptr_inst.funcDecode = NULL;
695 NetEqMainInst->DSPinst.codec_ptr_inst.funcDecodeInit = NULL;
696 NetEqMainInst->DSPinst.codec_ptr_inst.funcDecodePLC = NULL;
697 NetEqMainInst->DSPinst.codec_ptr_inst.funcGetMDinfo = NULL;
698 NetEqMainInst->DSPinst.codec_ptr_inst.funcUpdBWEst = NULL;
699 NetEqMainInst->DSPinst.codec_ptr_inst.funcGetErrorCode = NULL;
700 }
701
702 ok = WebRtcNetEQ_DbRemove(&NetEqMainInst->MCUinst.codec_DB_inst, codec);
703 if (ok != 0)
704 {
705 NetEqMainInst->ErrorCode = -ok;
706 return (-1);
707 }
708 return (ok);
709}
710
711/*********************************
712 * Real-time functions
713 */
714
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000715int WebRtcNetEQ_RecIn(void *inst, int16_t *p_w16datagramstart, int16_t w16_RTPlen,
716 uint32_t uw32_timeRec)
niklase@google.com470e71d2011-07-07 08:21:25 +0000717{
718 int ok = 0;
719 RTPPacket_t RTPpacket;
720 MainInst_t *NetEqMainInst = (MainInst_t*) inst;
721 if (NetEqMainInst == NULL) return (-1);
722
723 /* Check for corrupt/cleared instance */
724 if (NetEqMainInst->MCUinst.main_inst != NetEqMainInst)
725 {
726 /* Instance is corrupt */
727 NetEqMainInst->ErrorCode = CORRUPT_INSTANCE;
728 return (-1);
729 }
730
731 /* Parse RTP header */
732 ok = WebRtcNetEQ_RTPPayloadInfo(p_w16datagramstart, w16_RTPlen, &RTPpacket);
733 if (ok != 0)
734 {
735 NetEqMainInst->ErrorCode = -ok;
736 return (-1);
737 }
738
739 ok = WebRtcNetEQ_RecInInternal(&NetEqMainInst->MCUinst, &RTPpacket, uw32_timeRec);
740 if (ok != 0)
741 {
742 NetEqMainInst->ErrorCode = -ok;
743 return (-1);
744 }
745 return (ok);
746}
747
748/****************************************************************************
749 * WebRtcNetEQ_RecInRTPStruct(...)
750 *
751 * Alternative RecIn function, used when the RTP data has already been
752 * parsed into an RTP info struct (WebRtcNetEQ_RTPInfo).
753 *
754 * Input:
755 * - inst : NetEQ instance
756 * - rtpInfo : Pointer to RTP info
757 * - payloadPtr : Pointer to the RTP payload (first byte after header)
758 * - payloadLenBytes : Length (in bytes) of the payload in payloadPtr
759 * - timeRec : Receive time (in timestamps of the used codec)
760 *
761 * Return value : 0 - Ok
762 * -1 - Error
763 */
764int WebRtcNetEQ_RecInRTPStruct(void *inst, WebRtcNetEQ_RTPInfo *rtpInfo,
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000765 const uint8_t *payloadPtr, int16_t payloadLenBytes,
766 uint32_t uw32_timeRec)
niklase@google.com470e71d2011-07-07 08:21:25 +0000767{
768 int ok = 0;
769 RTPPacket_t RTPpacket;
770 MainInst_t *NetEqMainInst = (MainInst_t*) inst;
771 if (NetEqMainInst == NULL)
772 {
773 return (-1);
774 }
775
776 /* Check for corrupt/cleared instance */
777 if (NetEqMainInst->MCUinst.main_inst != NetEqMainInst)
778 {
779 /* Instance is corrupt */
780 NetEqMainInst->ErrorCode = CORRUPT_INSTANCE;
781 return (-1);
782 }
783
784 /* Load NetEQ's RTP struct from Module RTP struct */
785 RTPpacket.payloadType = rtpInfo->payloadType;
786 RTPpacket.seqNumber = rtpInfo->sequenceNumber;
787 RTPpacket.timeStamp = rtpInfo->timeStamp;
788 RTPpacket.ssrc = rtpInfo->SSRC;
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000789 RTPpacket.payload = (const int16_t*) payloadPtr;
niklase@google.com470e71d2011-07-07 08:21:25 +0000790 RTPpacket.payloadLen = payloadLenBytes;
791 RTPpacket.starts_byte1 = 0;
792
793 ok = WebRtcNetEQ_RecInInternal(&NetEqMainInst->MCUinst, &RTPpacket, uw32_timeRec);
794 if (ok != 0)
795 {
796 NetEqMainInst->ErrorCode = -ok;
797 return (-1);
798 }
799 return (ok);
800}
801
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000802int WebRtcNetEQ_RecOut(void *inst, int16_t *pw16_outData, int16_t *pw16_len)
niklase@google.com470e71d2011-07-07 08:21:25 +0000803{
804 int ok = 0;
805 MainInst_t *NetEqMainInst = (MainInst_t*) inst;
806#ifdef NETEQ_STEREO
807 MasterSlaveInfo msInfo;
808 msInfo.msMode = NETEQ_MONO;
809#endif
810
811 if (NetEqMainInst == NULL) return (-1);
812
813 /* Check for corrupt/cleared instance */
814 if (NetEqMainInst->DSPinst.main_inst != NetEqMainInst)
815 {
816 /* Instance is corrupt */
817 NetEqMainInst->ErrorCode = CORRUPT_INSTANCE;
818 return (-1);
819 }
820
821#ifdef NETEQ_STEREO
822 NetEqMainInst->DSPinst.msInfo = &msInfo;
823#endif
824
825 ok = WebRtcNetEQ_RecOutInternal(&NetEqMainInst->DSPinst, pw16_outData,
turaj@webrtc.org28d54ab2013-04-22 18:53:35 +0000826 pw16_len, 0 /* not BGN only */, NetEqMainInst->MCUinst.av_sync);
niklase@google.com470e71d2011-07-07 08:21:25 +0000827 if (ok != 0)
828 {
829 NetEqMainInst->ErrorCode = -ok;
830 return (-1);
831 }
832 return (ok);
833}
834
835/****************************************************************************
836 * WebRtcNetEQ_RecOutMasterSlave(...)
837 *
838 * RecOut function for running several NetEQ instances in master/slave mode.
839 * One master can be used to control several slaves.
840 *
841 * Input:
842 * - inst : NetEQ instance
843 * - isMaster : Non-zero indicates that this is the master channel
844 * - msInfo : (slave only) Information from master
845 *
846 * Output:
847 * - inst : Updated NetEQ instance
848 * - pw16_outData : Pointer to vector where output should be written
849 * - pw16_len : Pointer to variable where output length is returned
850 * - msInfo : (master only) Information to slave(s)
851 *
852 * Return value : 0 - Ok
853 * -1 - Error
854 */
855
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000856int WebRtcNetEQ_RecOutMasterSlave(void *inst, int16_t *pw16_outData,
857 int16_t *pw16_len, void *msInfo,
858 int16_t isMaster)
niklase@google.com470e71d2011-07-07 08:21:25 +0000859{
860#ifndef NETEQ_STEREO
861 /* Stereo not supported */
862 return(-1);
863#else
864 int ok = 0;
865 MainInst_t *NetEqMainInst = (MainInst_t*) inst;
866
867 if (NetEqMainInst == NULL) return (-1);
868
869 /* Check for corrupt/cleared instance */
870 if (NetEqMainInst->DSPinst.main_inst != NetEqMainInst)
871 {
872 /* Instance is corrupt */
873 NetEqMainInst->ErrorCode = CORRUPT_INSTANCE;
874 return (-1);
875 }
876
877 if (msInfo == NULL)
878 {
879 /* msInfo not provided */
880 NetEqMainInst->ErrorCode = NETEQ_OTHER_ERROR;
881 return (-1);
882 }
883
884 /* translate from external to internal Master/Slave information */
885 NetEqMainInst->DSPinst.msInfo = (MasterSlaveInfo *) msInfo;
886
887 /* check that we have not done a master/slave switch without first re-initializing */
888 if ((NetEqMainInst->masterSlave == 1 && !isMaster) || /* switch from master to slave */
889 (NetEqMainInst->masterSlave == 2 && isMaster)) /* switch from slave to master */
890 {
891 NetEqMainInst->ErrorCode = ILLEGAL_MASTER_SLAVE_SWITCH;
892 return (-1);
893 }
894
895 if (!isMaster)
896 {
897 /* this is the slave */
898 NetEqMainInst->masterSlave = 2;
899 NetEqMainInst->DSPinst.msInfo->msMode = NETEQ_SLAVE;
900 }
901 else
902 {
903 NetEqMainInst->DSPinst.msInfo->msMode = NETEQ_MASTER;
904 }
905
906 ok = WebRtcNetEQ_RecOutInternal(&NetEqMainInst->DSPinst, pw16_outData,
turaj@webrtc.org28d54ab2013-04-22 18:53:35 +0000907 pw16_len, 0 /* not BGN only */, NetEqMainInst->MCUinst.av_sync);
niklase@google.com470e71d2011-07-07 08:21:25 +0000908 if (ok != 0)
909 {
910 NetEqMainInst->ErrorCode = -ok;
911 return (-1);
912 }
913
914 if (isMaster)
915 {
916 /* this is the master */
917 NetEqMainInst->masterSlave = 1;
918 }
919
920 return (ok);
921#endif
922}
923
924int WebRtcNetEQ_GetMasterSlaveInfoSize()
925{
926#ifdef NETEQ_STEREO
927 return (sizeof(MasterSlaveInfo));
928#else
929 return(-1);
930#endif
931}
932
933/* Special RecOut that does not do any decoding. */
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000934int WebRtcNetEQ_RecOutNoDecode(void *inst, int16_t *pw16_outData,
935 int16_t *pw16_len)
niklase@google.com470e71d2011-07-07 08:21:25 +0000936{
937 int ok = 0;
938 MainInst_t *NetEqMainInst = (MainInst_t*) inst;
939#ifdef NETEQ_STEREO
940 MasterSlaveInfo msInfo;
941#endif
942
943 if (NetEqMainInst == NULL) return (-1);
944
945 /* Check for corrupt/cleared instance */
946 if (NetEqMainInst->DSPinst.main_inst != NetEqMainInst)
947 {
948 /* Instance is corrupt */
949 NetEqMainInst->ErrorCode = CORRUPT_INSTANCE;
950 return (-1);
951 }
952
953#ifdef NETEQ_STEREO
954 /* keep same mode as before */
955 switch (NetEqMainInst->masterSlave)
956 {
957 case 1:
958 {
959 msInfo.msMode = NETEQ_MASTER;
960 break;
961 }
962 case 2:
963 {
964 msInfo.msMode = NETEQ_SLAVE;
965 break;
966 }
967 default:
968 {
969 msInfo.msMode = NETEQ_MONO;
970 break;
971 }
972 }
973
974 NetEqMainInst->DSPinst.msInfo = &msInfo;
975#endif
976
977 ok = WebRtcNetEQ_RecOutInternal(&NetEqMainInst->DSPinst, pw16_outData,
turaj@webrtc.org28d54ab2013-04-22 18:53:35 +0000978 pw16_len, 1 /* BGN only */, NetEqMainInst->MCUinst.av_sync);
niklase@google.com470e71d2011-07-07 08:21:25 +0000979 if (ok != 0)
980 {
981 NetEqMainInst->ErrorCode = -ok;
982 return (-1);
983 }
984 return (ok);
985}
986
987int WebRtcNetEQ_GetRTCPStats(void *inst, WebRtcNetEQ_RTCPStat *RTCP_inst)
988{
989 int ok = 0;
990 MainInst_t *NetEqMainInst = (MainInst_t*) inst;
991 if (NetEqMainInst == NULL) return (-1);
992 ok = WebRtcNetEQ_RTCPGetStats(&NetEqMainInst->MCUinst.RTCP_inst,
993 &RTCP_inst->fraction_lost, &RTCP_inst->cum_lost, &RTCP_inst->ext_max,
994 &RTCP_inst->jitter, 0);
995 if (ok != 0)
996 {
997 NetEqMainInst->ErrorCode = -ok;
998 return (-1);
999 }
1000 return (ok);
1001}
1002
1003int WebRtcNetEQ_GetRTCPStatsNoReset(void *inst, WebRtcNetEQ_RTCPStat *RTCP_inst)
1004{
1005 int ok = 0;
1006 MainInst_t *NetEqMainInst = (MainInst_t*) inst;
1007 if (NetEqMainInst == NULL) return (-1);
1008 ok = WebRtcNetEQ_RTCPGetStats(&NetEqMainInst->MCUinst.RTCP_inst,
1009 &RTCP_inst->fraction_lost, &RTCP_inst->cum_lost, &RTCP_inst->ext_max,
1010 &RTCP_inst->jitter, 1);
1011 if (ok != 0)
1012 {
1013 NetEqMainInst->ErrorCode = -ok;
1014 return (-1);
1015 }
1016 return (ok);
1017}
1018
pbos@webrtc.org0946a562013-04-09 00:28:06 +00001019int WebRtcNetEQ_GetSpeechTimeStamp(void *inst, uint32_t *timestamp)
niklase@google.com470e71d2011-07-07 08:21:25 +00001020{
1021 MainInst_t *NetEqMainInst = (MainInst_t*) inst;
1022 if (NetEqMainInst == NULL) return (-1);
1023
1024 if (NetEqMainInst->MCUinst.TSscalingInitialized)
1025 {
1026 *timestamp = WebRtcNetEQ_ScaleTimestampInternalToExternal(&NetEqMainInst->MCUinst,
1027 NetEqMainInst->DSPinst.videoSyncTimestamp);
1028 }
1029 else
1030 {
1031 *timestamp = NetEqMainInst->DSPinst.videoSyncTimestamp;
1032 }
1033
1034 return (0);
1035}
1036
1037/****************************************************************************
1038 * WebRtcNetEQ_GetSpeechOutputType(...)
1039 *
1040 * Get the output type for the audio provided by the latest call to
1041 * WebRtcNetEQ_RecOut().
1042 *
1043 * kOutputNormal = normal audio (possibly processed)
1044 * kOutputPLC = loss concealment through stretching audio
1045 * kOutputCNG = comfort noise (codec-internal or RFC3389)
1046 * kOutputPLCtoCNG = background noise only due to long expand or error
1047 * kOutputVADPassive = PostDecode VAD signalling passive speaker
1048 *
1049 * Input:
1050 * - inst : NetEQ instance
1051 *
1052 * Output:
1053 * - outputType : Output type from enum list WebRtcNetEQOutputType
1054 *
1055 * Return value : 0 - Ok
1056 * -1 - Error
1057 */
1058
1059int WebRtcNetEQ_GetSpeechOutputType(void *inst, enum WebRtcNetEQOutputType *outputType)
1060{
1061 /* Typecast to internal instance type */
1062 MainInst_t *NetEqMainInst = (MainInst_t*) inst;
1063
1064 if (NetEqMainInst == NULL)
1065 {
1066 return (-1);
1067 }
1068
1069 if ((NetEqMainInst->DSPinst.w16_mode & MODE_BGN_ONLY) != 0)
1070 {
1071 /* If last mode was background noise only */
1072 *outputType = kOutputPLCtoCNG;
1073
1074 }
1075 else if ((NetEqMainInst->DSPinst.w16_mode == MODE_CODEC_INTERNAL_CNG)
1076 || (NetEqMainInst->DSPinst.w16_mode == MODE_RFC3389CNG))
1077 {
1078 /* If CN or internal CNG */
1079 *outputType = kOutputCNG;
1080
1081#ifdef NETEQ_VAD
1082 }
1083 else if ( NetEqMainInst->DSPinst.VADInst.VADDecision == 0 )
1084 {
1085 /* post-decode VAD says passive speaker */
1086 *outputType = kOutputVADPassive;
1087#endif /* NETEQ_VAD */
1088
1089 }
1090 else if ((NetEqMainInst->DSPinst.w16_mode == MODE_EXPAND)
1091 && (NetEqMainInst->DSPinst.ExpandInst.w16_expandMuteFactor == 0))
1092 {
1093 /* Expand mode has faded down to background noise only (very long expand) */
1094 *outputType = kOutputPLCtoCNG;
1095
1096 }
1097 else if (NetEqMainInst->DSPinst.w16_mode == MODE_EXPAND)
1098 {
1099 /* PLC mode */
1100 *outputType = kOutputPLC;
1101
1102 }
1103 else
1104 {
1105 /* Normal speech output type (can still be manipulated, e.g., accelerated) */
1106 *outputType = kOutputNormal;
1107 }
1108
1109 return (0);
1110}
1111
1112/**********************************
1113 * Functions related to VQmon
1114 */
1115
1116#define WEBRTC_NETEQ_CONCEALMENTFLAG_LOST 0x01
1117#define WEBRTC_NETEQ_CONCEALMENTFLAG_DISCARDED 0x02
1118#define WEBRTC_NETEQ_CONCEALMENTFLAG_SUPRESS 0x04
1119#define WEBRTC_NETEQ_CONCEALMENTFLAG_CNGACTIVE 0x80
1120
pbos@webrtc.org0946a562013-04-09 00:28:06 +00001121int WebRtcNetEQ_VQmonRecOutStatistics(void *inst, uint16_t *validVoiceDurationMs,
1122 uint16_t *concealedVoiceDurationMs,
1123 uint8_t *concealedVoiceFlags)
niklase@google.com470e71d2011-07-07 08:21:25 +00001124{
1125 MainInst_t *NetEqMainInst = (MainInst_t*) inst;
pbos@webrtc.org0946a562013-04-09 00:28:06 +00001126 int16_t fs_mult;
1127 int16_t ms_lost;
niklase@google.com470e71d2011-07-07 08:21:25 +00001128 if (NetEqMainInst == NULL) return (-1);
1129 fs_mult = WebRtcSpl_DivW32W16ResW16(NetEqMainInst->MCUinst.fs, 8000);
1130
1131 ms_lost = WebRtcSpl_DivW32W16ResW16(
pbos@webrtc.org0946a562013-04-09 00:28:06 +00001132 (int32_t) NetEqMainInst->DSPinst.w16_concealedTS, (int16_t) (8 * fs_mult));
niklase@google.com470e71d2011-07-07 08:21:25 +00001133 if (ms_lost > NetEqMainInst->DSPinst.millisecondsPerCall) ms_lost
1134 = NetEqMainInst->DSPinst.millisecondsPerCall;
1135
1136 *validVoiceDurationMs = NetEqMainInst->DSPinst.millisecondsPerCall - ms_lost;
1137 *concealedVoiceDurationMs = ms_lost;
1138 if (ms_lost > 0)
1139 {
1140 *concealedVoiceFlags = WEBRTC_NETEQ_CONCEALMENTFLAG_LOST;
1141 }
1142 else
1143 {
1144 *concealedVoiceFlags = 0;
1145 }
1146 NetEqMainInst->DSPinst.w16_concealedTS -= ms_lost * (8 * fs_mult);
1147
1148 return (0);
1149}
1150
pbos@webrtc.org0946a562013-04-09 00:28:06 +00001151int WebRtcNetEQ_VQmonGetConfiguration(void *inst, uint16_t *absMaxDelayMs,
1152 uint8_t *adaptationRate)
niklase@google.com470e71d2011-07-07 08:21:25 +00001153{
1154 /* Dummy check the inst, just to avoid compiler warnings. */
1155 if (inst == NULL)
1156 {
1157 /* Do nothing. */
1158 }
1159
1160 /* Hardcoded variables that are used for VQmon as jitter buffer parameters */
1161 *absMaxDelayMs = 240;
1162 *adaptationRate = 1;
1163 return (0);
1164}
1165
pbos@webrtc.org0946a562013-04-09 00:28:06 +00001166int WebRtcNetEQ_VQmonGetRxStatistics(void *inst, uint16_t *avgDelayMs,
1167 uint16_t *maxDelayMs)
niklase@google.com470e71d2011-07-07 08:21:25 +00001168{
1169 MainInst_t *NetEqMainInst = (MainInst_t*) inst;
1170 if (NetEqMainInst == NULL) return (-1);
pbos@webrtc.org0946a562013-04-09 00:28:06 +00001171 *avgDelayMs = (uint16_t) (NetEqMainInst->MCUinst.BufferStat_inst.avgDelayMsQ8 >> 8);
1172 *maxDelayMs = (uint16_t) NetEqMainInst->MCUinst.BufferStat_inst.maxDelayMs;
niklase@google.com470e71d2011-07-07 08:21:25 +00001173 return (0);
1174}
1175
1176/*************************************
1177 * Statistics functions
1178 */
1179
1180/* Get the "in-call" statistics from NetEQ.
1181 * The statistics are reset after the query. */
1182int WebRtcNetEQ_GetNetworkStatistics(void *inst, WebRtcNetEQ_NetworkStatistics *stats)
1183
1184{
1185
pbos@webrtc.org0946a562013-04-09 00:28:06 +00001186 uint16_t tempU16;
1187 uint32_t tempU32, tempU32_2;
niklase@google.com470e71d2011-07-07 08:21:25 +00001188 int numShift;
1189 MainInst_t *NetEqMainInst = (MainInst_t*) inst;
1190
1191 /* Instance sanity */
1192 if (NetEqMainInst == NULL) return (-1);
1193
roosa@google.comb8ba4d82012-12-14 00:06:18 +00001194 stats->addedSamples = NetEqMainInst->DSPinst.statInst.addedSamples;
1195
niklase@google.com470e71d2011-07-07 08:21:25 +00001196 /*******************/
1197 /* Get buffer size */
1198 /*******************/
1199
henrik.lundin@webrtc.org524eb482011-11-30 16:21:22 +00001200 if (NetEqMainInst->MCUinst.fs != 0)
niklase@google.com470e71d2011-07-07 08:21:25 +00001201 {
pbos@webrtc.org0946a562013-04-09 00:28:06 +00001202 int32_t temp32;
henrik.lundin@webrtc.org524eb482011-11-30 16:21:22 +00001203 /* Query packet buffer for number of samples. */
1204 temp32 = WebRtcNetEQ_PacketBufferGetSize(
tina.legrand@webrtc.org5ac387c2012-11-19 08:02:55 +00001205 &NetEqMainInst->MCUinst.PacketBuffer_inst,
turaj@webrtc.org28d54ab2013-04-22 18:53:35 +00001206 &NetEqMainInst->MCUinst.codec_DB_inst,
1207 NetEqMainInst->MCUinst.av_sync);
henrik.lundin@webrtc.org524eb482011-11-30 16:21:22 +00001208
1209 /* Divide by sample rate.
1210 * Calculate temp32 * 1000 / fs to get result in ms. */
pbos@webrtc.org0946a562013-04-09 00:28:06 +00001211 stats->currentBufferSize = (uint16_t)
henrik.lundin@webrtc.org524eb482011-11-30 16:21:22 +00001212 WebRtcSpl_DivU32U16(temp32 * 1000, NetEqMainInst->MCUinst.fs);
1213
1214 /* Add number of samples yet to play in sync buffer. */
pbos@webrtc.org0946a562013-04-09 00:28:06 +00001215 temp32 = (int32_t) (NetEqMainInst->DSPinst.endPosition -
henrik.lundin@webrtc.org524eb482011-11-30 16:21:22 +00001216 NetEqMainInst->DSPinst.curPosition);
pbos@webrtc.org0946a562013-04-09 00:28:06 +00001217 stats->currentBufferSize += (uint16_t)
henrik.lundin@webrtc.org524eb482011-11-30 16:21:22 +00001218 WebRtcSpl_DivU32U16(temp32 * 1000, NetEqMainInst->MCUinst.fs);
1219 }
1220 else
1221 {
1222 /* Sample rate not initialized. */
1223 stats->currentBufferSize = 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001224 }
1225
1226 /***************************/
1227 /* Get optimal buffer size */
1228 /***************************/
1229
turaj@webrtc.orge46c8d32013-05-22 20:39:43 +00001230 if (NetEqMainInst->MCUinst.fs != 0)
niklase@google.com470e71d2011-07-07 08:21:25 +00001231 {
1232 /* preferredBufferSize = Bopt * packSizeSamples / (fs/1000) */
1233 stats->preferredBufferSize
pbos@webrtc.org0946a562013-04-09 00:28:06 +00001234 = (uint16_t) WEBRTC_SPL_MUL_16_16(
1235 (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 +00001236 WebRtcSpl_DivW32W16ResW16(
pbos@webrtc.org0946a562013-04-09 00:28:06 +00001237 (int32_t) NetEqMainInst->MCUinst.BufferStat_inst.Automode_inst.packetSpeechLenSamp, /* samples per packet */
1238 WebRtcSpl_DivW32W16ResW16( (int32_t) NetEqMainInst->MCUinst.fs, (int16_t) 1000 ) /* samples per ms */
niklase@google.com470e71d2011-07-07 08:21:25 +00001239 ) );
1240
1241 /* add extra delay */
1242 if (NetEqMainInst->MCUinst.BufferStat_inst.Automode_inst.extraDelayMs > 0)
1243 {
1244 stats->preferredBufferSize
1245 += NetEqMainInst->MCUinst.BufferStat_inst.Automode_inst.extraDelayMs;
1246 }
1247 }
1248 else
1249 {
1250 /* sample rate not initialized */
1251 stats->preferredBufferSize = 0;
1252 }
1253
henrik.lundin@webrtc.orgd4398702012-01-04 13:09:55 +00001254 /***********************************/
1255 /* Check if jitter peaks are found */
1256 /***********************************/
1257
1258 stats->jitterPeaksFound =
1259 NetEqMainInst->MCUinst.BufferStat_inst.Automode_inst.peakFound;
1260
niklase@google.com470e71d2011-07-07 08:21:25 +00001261 /***********************/
1262 /* Calculate loss rate */
1263 /***********************/
1264
1265 /* timestamps elapsed since last report */
1266 tempU32 = NetEqMainInst->MCUinst.lastReportTS;
1267
1268 if (NetEqMainInst->MCUinst.lostTS == 0)
1269 {
1270 /* no losses */
1271 stats->currentPacketLossRate = 0;
1272 }
1273 else if (NetEqMainInst->MCUinst.lostTS < tempU32)
1274 {
1275 /* calculate shifts; we want the result in Q14 */
1276 numShift = WebRtcSpl_NormU32(NetEqMainInst->MCUinst.lostTS); /* numerator shift for normalize */
1277
1278 if (numShift < 14)
1279 {
1280 /* cannot shift numerator 14 steps; shift denominator too */
1281 tempU32 = WEBRTC_SPL_RSHIFT_U32(tempU32, 14-numShift); /* right-shift */
1282 }
1283 else
1284 {
1285 /* shift no more than 14 steps */
1286 numShift = 14;
1287 }
1288
1289 if (tempU32 == 0)
1290 {
1291 /* check for zero denominator; result should be zero in this case */
1292 stats->currentPacketLossRate = 0;
1293 }
1294 else
1295 {
1296 /* check that denominator fits in signed 16-bit */
1297 while (tempU32 > WEBRTC_SPL_WORD16_MAX)
1298 {
1299 tempU32 >>= 1; /* right-shift 1 step */
1300 numShift--; /* compensate in numerator */
1301 }
pbos@webrtc.org0946a562013-04-09 00:28:06 +00001302 tempU16 = (uint16_t) tempU32;
niklase@google.com470e71d2011-07-07 08:21:25 +00001303
1304 /* do the shift of numerator */
1305 tempU32
pbos@webrtc.org0946a562013-04-09 00:28:06 +00001306 = WEBRTC_SPL_SHIFT_W32( (uint32_t) NetEqMainInst->MCUinst.lostTS, numShift);
niklase@google.com470e71d2011-07-07 08:21:25 +00001307
pbos@webrtc.org0946a562013-04-09 00:28:06 +00001308 stats->currentPacketLossRate = (uint16_t) WebRtcSpl_DivU32U16(tempU32,
niklase@google.com470e71d2011-07-07 08:21:25 +00001309 tempU16);
1310 }
1311 }
1312 else
1313 {
1314 /* lost count is larger than elapsed time count; probably timestamp wrap-around or something else wrong */
1315 /* set loss rate = 1 */
1316 stats->currentPacketLossRate = 1 << 14; /* 1 in Q14 */
1317 }
1318
1319 /**************************/
1320 /* Calculate discard rate */
1321 /**************************/
1322
1323 /* timestamps elapsed since last report */
1324 tempU32 = NetEqMainInst->MCUinst.lastReportTS;
1325
1326 /* number of discarded samples */
1327 tempU32_2
pbos@webrtc.org0946a562013-04-09 00:28:06 +00001328 = WEBRTC_SPL_MUL_16_U16( (int16_t) NetEqMainInst->MCUinst.PacketBuffer_inst.packSizeSamples,
niklase@google.com470e71d2011-07-07 08:21:25 +00001329 NetEqMainInst->MCUinst.PacketBuffer_inst.discardedPackets);
1330
1331 if (tempU32_2 == 0)
1332 {
1333 /* no discarded samples */
1334 stats->currentDiscardRate = 0;
1335 }
1336 else if (tempU32_2 < tempU32)
1337 {
1338 /* calculate shifts; we want the result in Q14 */
1339 numShift = WebRtcSpl_NormU32(tempU32_2); /* numerator shift for normalize */
1340
1341 if (numShift < 14)
1342 {
1343 /* cannot shift numerator 14 steps; shift denominator too */
1344 tempU32 = WEBRTC_SPL_RSHIFT_U32(tempU32, 14-numShift); /* right-shift */
1345 }
1346 else
1347 {
1348 /* shift no more than 14 steps */
1349 numShift = 14;
1350 }
1351
1352 if (tempU32 == 0)
1353 {
1354 /* check for zero denominator; result should be zero in this case */
1355 stats->currentDiscardRate = 0;
1356 }
1357 else
1358 {
1359 /* check that denominator fits in signed 16-bit */
1360 while (tempU32 > WEBRTC_SPL_WORD16_MAX)
1361 {
1362 tempU32 >>= 1; /* right-shift 1 step */
1363 numShift--; /* compensate in numerator */
1364 }
pbos@webrtc.org0946a562013-04-09 00:28:06 +00001365 tempU16 = (uint16_t) tempU32;
niklase@google.com470e71d2011-07-07 08:21:25 +00001366
1367 /* do the shift of numerator */
1368 tempU32 = WEBRTC_SPL_SHIFT_W32( tempU32_2, numShift);
1369
pbos@webrtc.org0946a562013-04-09 00:28:06 +00001370 stats->currentDiscardRate = (uint16_t) WebRtcSpl_DivU32U16(tempU32, tempU16);
niklase@google.com470e71d2011-07-07 08:21:25 +00001371 }
1372 }
1373 else
1374 {
1375 /* lost count is larger than elapsed time count; probably timestamp wrap-around or something else wrong */
1376 /* set loss rate = 1 */
1377 stats->currentDiscardRate = 1 << 14; /* 1 in Q14 */
1378 }
1379
1380 /*************************************************************/
1381 /* Calculate Accelerate, Expand and Pre-emptive Expand rates */
1382 /*************************************************************/
1383
1384 /* timestamps elapsed since last report */
1385 tempU32 = NetEqMainInst->MCUinst.lastReportTS;
1386
1387 if (NetEqMainInst->DSPinst.statInst.accelerateLength == 0)
1388 {
1389 /* no accelerate */
1390 stats->currentAccelerateRate = 0;
1391 }
1392 else if (NetEqMainInst->DSPinst.statInst.accelerateLength < tempU32)
1393 {
1394 /* calculate shifts; we want the result in Q14 */
1395 numShift = WebRtcSpl_NormU32(NetEqMainInst->DSPinst.statInst.accelerateLength); /* numerator shift for normalize */
1396
1397 if (numShift < 14)
1398 {
1399 /* cannot shift numerator 14 steps; shift denominator too */
1400 tempU32 = WEBRTC_SPL_RSHIFT_U32(tempU32, 14-numShift); /* right-shift */
1401 }
1402 else
1403 {
1404 /* shift no more than 14 steps */
1405 numShift = 14;
1406 }
1407
1408 if (tempU32 == 0)
1409 {
1410 /* check for zero denominator; result should be zero in this case */
1411 stats->currentAccelerateRate = 0;
1412 }
1413 else
1414 {
1415 /* check that denominator fits in signed 16-bit */
1416 while (tempU32 > WEBRTC_SPL_WORD16_MAX)
1417 {
1418 tempU32 >>= 1; /* right-shift 1 step */
1419 numShift--; /* compensate in numerator */
1420 }
pbos@webrtc.org0946a562013-04-09 00:28:06 +00001421 tempU16 = (uint16_t) tempU32;
niklase@google.com470e71d2011-07-07 08:21:25 +00001422
1423 /* do the shift of numerator */
1424 tempU32
1425 = WEBRTC_SPL_SHIFT_W32( NetEqMainInst->DSPinst.statInst.accelerateLength, numShift);
1426
pbos@webrtc.org0946a562013-04-09 00:28:06 +00001427 stats->currentAccelerateRate = (uint16_t) WebRtcSpl_DivU32U16(tempU32,
niklase@google.com470e71d2011-07-07 08:21:25 +00001428 tempU16);
1429 }
1430 }
1431 else
1432 {
1433 /* lost count is larger than elapsed time count; probably timestamp wrap-around or something else wrong */
1434 /* set loss rate = 1 */
1435 stats->currentAccelerateRate = 1 << 14; /* 1 in Q14 */
1436 }
1437
niklase@google.com470e71d2011-07-07 08:21:25 +00001438 /* timestamps elapsed since last report */
1439 tempU32 = NetEqMainInst->MCUinst.lastReportTS;
1440
1441 if (NetEqMainInst->DSPinst.statInst.expandLength == 0)
1442 {
1443 /* no expand */
1444 stats->currentExpandRate = 0;
1445 }
1446 else if (NetEqMainInst->DSPinst.statInst.expandLength < tempU32)
1447 {
1448 /* calculate shifts; we want the result in Q14 */
1449 numShift = WebRtcSpl_NormU32(NetEqMainInst->DSPinst.statInst.expandLength); /* numerator shift for normalize */
1450
1451 if (numShift < 14)
1452 {
1453 /* cannot shift numerator 14 steps; shift denominator too */
1454 tempU32 = WEBRTC_SPL_RSHIFT_U32(tempU32, 14-numShift); /* right-shift */
1455 }
1456 else
1457 {
1458 /* shift no more than 14 steps */
1459 numShift = 14;
1460 }
1461
1462 if (tempU32 == 0)
1463 {
1464 /* check for zero denominator; result should be zero in this case */
1465 stats->currentExpandRate = 0;
1466 }
1467 else
1468 {
1469 /* check that denominator fits in signed 16-bit */
1470 while (tempU32 > WEBRTC_SPL_WORD16_MAX)
1471 {
1472 tempU32 >>= 1; /* right-shift 1 step */
1473 numShift--; /* compensate in numerator */
1474 }
pbos@webrtc.org0946a562013-04-09 00:28:06 +00001475 tempU16 = (uint16_t) tempU32;
niklase@google.com470e71d2011-07-07 08:21:25 +00001476
1477 /* do the shift of numerator */
1478 tempU32
1479 = WEBRTC_SPL_SHIFT_W32( NetEqMainInst->DSPinst.statInst.expandLength, numShift);
1480
pbos@webrtc.org0946a562013-04-09 00:28:06 +00001481 stats->currentExpandRate = (uint16_t) WebRtcSpl_DivU32U16(tempU32, tempU16);
niklase@google.com470e71d2011-07-07 08:21:25 +00001482 }
1483 }
1484 else
1485 {
1486 /* lost count is larger than elapsed time count; probably timestamp wrap-around or something else wrong */
1487 /* set loss rate = 1 */
1488 stats->currentExpandRate = 1 << 14; /* 1 in Q14 */
1489 }
1490
1491 /* timestamps elapsed since last report */
1492 tempU32 = NetEqMainInst->MCUinst.lastReportTS;
1493
1494 if (NetEqMainInst->DSPinst.statInst.preemptiveLength == 0)
1495 {
1496 /* no pre-emptive expand */
1497 stats->currentPreemptiveRate = 0;
1498 }
1499 else if (NetEqMainInst->DSPinst.statInst.preemptiveLength < tempU32)
1500 {
1501 /* calculate shifts; we want the result in Q14 */
1502 numShift = WebRtcSpl_NormU32(NetEqMainInst->DSPinst.statInst.preemptiveLength); /* numerator shift for normalize */
1503
1504 if (numShift < 14)
1505 {
1506 /* cannot shift numerator 14 steps; shift denominator too */
1507 tempU32 = WEBRTC_SPL_RSHIFT_U32(tempU32, 14-numShift); /* right-shift */
1508 }
1509 else
1510 {
1511 /* shift no more than 14 steps */
1512 numShift = 14;
1513 }
1514
1515 if (tempU32 == 0)
1516 {
1517 /* check for zero denominator; result should be zero in this case */
1518 stats->currentPreemptiveRate = 0;
1519 }
1520 else
1521 {
1522 /* check that denominator fits in signed 16-bit */
1523 while (tempU32 > WEBRTC_SPL_WORD16_MAX)
1524 {
1525 tempU32 >>= 1; /* right-shift 1 step */
1526 numShift--; /* compensate in numerator */
1527 }
pbos@webrtc.org0946a562013-04-09 00:28:06 +00001528 tempU16 = (uint16_t) tempU32;
niklase@google.com470e71d2011-07-07 08:21:25 +00001529
1530 /* do the shift of numerator */
1531 tempU32
1532 = WEBRTC_SPL_SHIFT_W32( NetEqMainInst->DSPinst.statInst.preemptiveLength, numShift);
1533
pbos@webrtc.org0946a562013-04-09 00:28:06 +00001534 stats->currentPreemptiveRate = (uint16_t) WebRtcSpl_DivU32U16(tempU32,
niklase@google.com470e71d2011-07-07 08:21:25 +00001535 tempU16);
1536 }
1537 }
1538 else
1539 {
1540 /* lost count is larger than elapsed time count; probably timestamp wrap-around or something else wrong */
1541 /* set loss rate = 1 */
1542 stats->currentPreemptiveRate = 1 << 14; /* 1 in Q14 */
1543 }
1544
henrik.lundin@webrtc.orgd4398702012-01-04 13:09:55 +00001545 stats->clockDriftPPM = WebRtcNetEQ_AverageIAT(
1546 &NetEqMainInst->MCUinst.BufferStat_inst.Automode_inst);
1547
niklase@google.com470e71d2011-07-07 08:21:25 +00001548 /* reset counters */
1549 WebRtcNetEQ_ResetMcuInCallStats(&(NetEqMainInst->MCUinst));
1550 WebRtcNetEQ_ClearInCallStats(&(NetEqMainInst->DSPinst));
1551
1552 return (0);
1553}
1554
henrik.lundin@webrtc.orgdbba1f92011-12-20 15:45:05 +00001555int WebRtcNetEQ_GetRawFrameWaitingTimes(void *inst,
1556 int max_length,
1557 int* waiting_times_ms) {
1558 int i = 0;
1559 MainInst_t *main_inst = (MainInst_t*) inst;
1560 if (main_inst == NULL) return -1;
1561
1562 while ((i < max_length) && (i < main_inst->MCUinst.len_waiting_times)) {
1563 waiting_times_ms[i] = main_inst->MCUinst.waiting_times[i] *
1564 main_inst->DSPinst.millisecondsPerCall;
1565 ++i;
1566 }
1567 assert(i <= kLenWaitingTimes);
1568 WebRtcNetEQ_ResetWaitingTimeStats(&main_inst->MCUinst);
1569 return i;
1570}
1571
niklase@google.com470e71d2011-07-07 08:21:25 +00001572/****************************************************************************
1573 * WebRtcNetEQ_SetVADInstance(...)
1574 *
1575 * Provide a pointer to an allocated VAD instance. If function is never
1576 * called or it is called with NULL pointer as VAD_inst, the post-decode
1577 * VAD functionality is disabled. Also provide pointers to init, setmode
1578 * and VAD functions. These are typically pointers to WebRtcVad_Init,
1579 * WebRtcVad_set_mode and WebRtcVad_Process, respectively, all found in the
1580 * interface file webrtc_vad.h.
1581 *
1582 * Input:
1583 * - NetEQ_inst : NetEQ instance
1584 * - VADinst : VAD instance
1585 * - initFunction : Pointer to VAD init function
1586 * - setmodeFunction : Pointer to VAD setmode function
1587 * - VADfunction : Pointer to VAD function
1588 *
1589 * Output:
1590 * - NetEQ_inst : Updated NetEQ instance
1591 *
1592 * Return value : 0 - Ok
1593 * -1 - Error
1594 */
1595
1596int WebRtcNetEQ_SetVADInstance(void *NetEQ_inst, void *VAD_inst,
1597 WebRtcNetEQ_VADInitFunction initFunction,
1598 WebRtcNetEQ_VADSetmodeFunction setmodeFunction,
1599 WebRtcNetEQ_VADFunction VADFunction)
1600{
1601
1602 /* Typecast to internal instance type */
1603 MainInst_t *NetEqMainInst = (MainInst_t*) NetEQ_inst;
1604 if (NetEqMainInst == NULL)
1605 {
1606 return (-1);
1607 }
1608
1609#ifdef NETEQ_VAD
1610
1611 /* Store pointer in PostDecode VAD struct */
1612 NetEqMainInst->DSPinst.VADInst.VADState = VAD_inst;
1613
1614 /* Store function pointers */
1615 NetEqMainInst->DSPinst.VADInst.initFunction = initFunction;
1616 NetEqMainInst->DSPinst.VADInst.setmodeFunction = setmodeFunction;
1617 NetEqMainInst->DSPinst.VADInst.VADFunction = VADFunction;
1618
1619 /* Call init function and return the result (ok or fail) */
1620 return(WebRtcNetEQ_InitVAD(&NetEqMainInst->DSPinst.VADInst, NetEqMainInst->DSPinst.fs));
1621
1622#else /* NETEQ_VAD not defined */
1623 return (-1);
1624#endif /* NETEQ_VAD */
1625
1626}
1627
1628/****************************************************************************
1629 * WebRtcNetEQ_SetVADMode(...)
1630 *
1631 * Pass an aggressiveness mode parameter to the post-decode VAD instance.
1632 * If this function is never called, mode 0 (quality mode) is used as default.
1633 *
1634 * Input:
1635 * - inst : NetEQ instance
1636 * - mode : mode parameter (same range as WebRtc VAD mode)
1637 *
1638 * Output:
1639 * - inst : Updated NetEQ instance
1640 *
1641 * Return value : 0 - Ok
1642 * -1 - Error
1643 */
1644
bjornv@webrtc.orgf4b77fd2012-01-25 12:40:00 +00001645int WebRtcNetEQ_SetVADMode(void *inst, int mode)
niklase@google.com470e71d2011-07-07 08:21:25 +00001646{
1647
1648 /* Typecast to internal instance type */
1649 MainInst_t *NetEqMainInst = (MainInst_t*) inst;
1650 if (NetEqMainInst == NULL)
1651 {
1652 return (-1);
1653 }
1654
1655#ifdef NETEQ_VAD
1656
1657 /* Set mode and return result */
1658 return(WebRtcNetEQ_SetVADModeInternal(&NetEqMainInst->DSPinst.VADInst, mode));
1659
1660#else /* NETEQ_VAD not defined */
1661 return (-1);
1662#endif /* NETEQ_VAD */
1663
1664}
turaj@webrtc.org92d1f072013-04-15 16:52:04 +00001665
1666void WebRtcNetEQ_GetProcessingActivity(void *inst,
1667 WebRtcNetEQ_ProcessingActivity *stats) {
1668 MainInst_t *NetEqMainInst = (MainInst_t*) inst;
1669
1670 stats->accelerate_bgn_samples =
1671 NetEqMainInst->DSPinst.activity_stats.accelerate_bgn_samples;
1672 stats->accelerate_normal_samples =
1673 NetEqMainInst->DSPinst.activity_stats.accelarate_normal_samples;
1674
1675 stats->expand_bgn_sampels =
1676 NetEqMainInst->DSPinst.activity_stats.expand_bgn_samples;
1677 stats->expand_normal_samples =
1678 NetEqMainInst->DSPinst.activity_stats.expand_normal_samples;
1679
1680 stats->preemptive_expand_bgn_samples =
1681 NetEqMainInst->DSPinst.activity_stats.preemptive_expand_bgn_samples;
1682 stats->preemptive_expand_normal_samples =
1683 NetEqMainInst->DSPinst.activity_stats.preemptive_expand_normal_samples;
1684
1685 stats->merge_expand_bgn_samples =
1686 NetEqMainInst->DSPinst.activity_stats.merge_expand_bgn_samples;
1687 stats->merge_expand_normal_samples =
1688 NetEqMainInst->DSPinst.activity_stats.merge_expand_normal_samples;
1689
1690 WebRtcNetEQ_ClearActivityStats(&NetEqMainInst->DSPinst);
1691}
turaj@webrtc.org28d54ab2013-04-22 18:53:35 +00001692
1693void WebRtcNetEQ_EnableAVSync(void* inst, int enable) {
1694 MainInst_t *NetEqMainInst = (MainInst_t*) inst;
1695 NetEqMainInst->MCUinst.av_sync = (enable != 0) ? 1 : 0;
1696}
1697
1698int WebRtcNetEQ_RecInSyncRTP(void* inst, WebRtcNetEQ_RTPInfo* rtp_info,
1699 uint32_t receive_timestamp) {
1700 MainInst_t *NetEqMainInst = (MainInst_t*) inst;
1701 if (NetEqMainInst->MCUinst.av_sync == 0)
1702 return -1;
1703 if (WebRtcNetEQ_RecInRTPStruct(inst, rtp_info, kSyncPayload,
1704 SYNC_PAYLOAD_LEN_BYTES,
1705 receive_timestamp) < 0) {
1706 return -1;
1707 }
1708 return SYNC_PAYLOAD_LEN_BYTES;
1709}
turaj@webrtc.orge46c8d32013-05-22 20:39:43 +00001710
1711int WebRtcNetEQ_GetRequiredDelayMs(const void* inst) {
1712 const MainInst_t* NetEqMainInst = (MainInst_t*)inst;
1713 const AutomodeInst_t* auto_mode = (NetEqMainInst == NULL) ? NULL :
1714 &NetEqMainInst->MCUinst.BufferStat_inst.Automode_inst;
1715
1716 /* Instance sanity */
1717 if (NetEqMainInst == NULL || auto_mode == NULL)
1718 return 0;
1719
1720 if (NetEqMainInst->MCUinst.fs == 0)
1721 return 0; // Sampling rate not initialized.
1722
1723 /* |required_delay_q8| has the unit of packets in Q8 domain, therefore,
1724 * the corresponding delay is
1725 * required_delay_ms = (1000 * required_delay_q8 * samples_per_packet /
1726 * sample_rate_hz) / 256;
1727 */
1728 return (auto_mode->required_delay_q8 *
1729 ((auto_mode->packetSpeechLenSamp * 1000) / NetEqMainInst->MCUinst.fs) +
1730 128) >> 8;
1731}