blob: 8f1e34cfffb0a58dccdb1e310b228eb0ad6dd007 [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
turaj@webrtc.orga305e962013-06-06 19:00:09 +0000471 /* Set to an invalid value. */
472 NetEqMainInst->MCUinst.decoded_packet_sequence_number = -1;
473 NetEqMainInst->MCUinst.decoded_packet_timestamp = 0;
474
niklase@google.com470e71d2011-07-07 08:21:25 +0000475 return (ok);
476}
477
478int WebRtcNetEQ_FlushBuffers(void *inst)
479{
480 int ok = 0;
481
482 /* Typecast inst to internal instance format */
483 MainInst_t *NetEqMainInst = (MainInst_t*) inst;
484
485 if (NetEqMainInst == NULL)
486 {
487 return (-1);
488 }
489
490 /* Flush packet buffer */
491 ok = WebRtcNetEQ_PacketBufferFlush(&NetEqMainInst->MCUinst.PacketBuffer_inst);
492 RETURN_ON_ERROR(ok, NetEqMainInst);
493
494 /* Set MCU to wait for new codec */
495 NetEqMainInst->MCUinst.first_packet = 1;
496
497 /* Flush speech buffer */
498 ok = WebRtcNetEQ_FlushSpeechBuffer(&NetEqMainInst->DSPinst);
499 RETURN_ON_ERROR(ok, NetEqMainInst);
500
501 return 0;
502}
503
504int WebRtcNetEQ_SetAVTPlayout(void *inst, int PlayoutAVTon)
505{
506 MainInst_t *NetEqMainInst = (MainInst_t*) inst;
507 if (NetEqMainInst == NULL) return (-1);
508#ifdef NETEQ_ATEVENT_DECODE
509 NetEqMainInst->MCUinst.AVT_PlayoutOn = PlayoutAVTon;
510 return(0);
511#else
512 if (PlayoutAVTon != 0)
513 {
514 NetEqMainInst->ErrorCode = -DTMF_NOT_SUPPORTED;
515 return (-1);
516 }
517 else
518 {
519 return (0);
520 }
521#endif
522}
523
524int WebRtcNetEQ_SetExtraDelay(void *inst, int DelayInMs)
525{
526 MainInst_t *NetEqMainInst = (MainInst_t*) inst;
527 if (NetEqMainInst == NULL) return (-1);
turaj@webrtc.org6388c3e2013-02-12 21:42:18 +0000528 if ((DelayInMs < 0) || (DelayInMs > 10000))
niklase@google.com470e71d2011-07-07 08:21:25 +0000529 {
530 NetEqMainInst->ErrorCode = -FAULTY_DELAYVALUE;
531 return (-1);
532 }
533 NetEqMainInst->MCUinst.BufferStat_inst.Automode_inst.extraDelayMs = DelayInMs;
534 return (0);
535}
536
turaj@webrtc.orge46c8d32013-05-22 20:39:43 +0000537int WebRtcNetEQ_SetMinimumDelay(void *inst, int minimum_delay_ms) {
538 MainInst_t *NetEqMainInst = (MainInst_t*) inst;
539 if (NetEqMainInst == NULL)
540 return -1;
541 if (minimum_delay_ms < 0 || minimum_delay_ms > 10000) {
542 NetEqMainInst->ErrorCode = -FAULTY_DELAYVALUE;
543 return -1;
544 }
545 NetEqMainInst->MCUinst.BufferStat_inst.Automode_inst.minimum_delay_ms =
546 minimum_delay_ms;
547 return 0;
548}
549
niklase@google.com470e71d2011-07-07 08:21:25 +0000550int WebRtcNetEQ_SetPlayoutMode(void *inst, enum WebRtcNetEQPlayoutMode playoutMode)
551{
552 MainInst_t *NetEqMainInst = (MainInst_t*) inst;
553 if (NetEqMainInst == NULL) return (-1);
554 if ((playoutMode != kPlayoutOn) && (playoutMode != kPlayoutOff) && (playoutMode
555 != kPlayoutFax) && (playoutMode != kPlayoutStreaming))
556 {
557 NetEqMainInst->ErrorCode = -FAULTY_PLAYOUTMODE;
558 return (-1);
559 }
560 else
561 {
562 NetEqMainInst->MCUinst.NetEqPlayoutMode = playoutMode;
563 return (0);
564 }
565}
566
567int WebRtcNetEQ_SetBGNMode(void *inst, enum WebRtcNetEQBGNMode bgnMode)
568{
569
570 MainInst_t *NetEqMainInst = (MainInst_t*) inst;
571
572 /* Instance sanity */
573 if (NetEqMainInst == NULL) return (-1);
574
575 /* Check for corrupt/cleared instance */
576 if (NetEqMainInst->MCUinst.main_inst != NetEqMainInst)
577 {
578 /* Instance is corrupt */
579 NetEqMainInst->ErrorCode = CORRUPT_INSTANCE;
580 return (-1);
581 }
582
583 NetEqMainInst->DSPinst.BGNInst.bgnMode = (enum BGNMode) bgnMode;
584
585 return (0);
586}
587
588int WebRtcNetEQ_GetBGNMode(const void *inst, enum WebRtcNetEQBGNMode *bgnMode)
589{
590
591 const MainInst_t *NetEqMainInst = (const MainInst_t*) inst;
592
593 /* Instance sanity */
594 if (NetEqMainInst == NULL) return (-1);
595
596 *bgnMode = (enum WebRtcNetEQBGNMode) NetEqMainInst->DSPinst.BGNInst.bgnMode;
597
598 return (0);
599}
600
601/************************************************
602 * CodecDB functions
603 */
604
605int WebRtcNetEQ_CodecDbReset(void *inst)
606{
607 int ok = 0;
608 MainInst_t *NetEqMainInst = (MainInst_t*) inst;
609 if (NetEqMainInst == NULL) return (-1);
610 ok = WebRtcNetEQ_DbReset(&NetEqMainInst->MCUinst.codec_DB_inst);
611 if (ok != 0)
612 {
613 NetEqMainInst->ErrorCode = -ok;
614 return (-1);
615 }
616
617 /* set function pointers to NULL to prevent RecOut from using the codec */
618 NetEqMainInst->DSPinst.codec_ptr_inst.funcDecode = NULL;
619 NetEqMainInst->DSPinst.codec_ptr_inst.funcDecodeRCU = NULL;
620 NetEqMainInst->DSPinst.codec_ptr_inst.funcAddLatePkt = NULL;
621 NetEqMainInst->DSPinst.codec_ptr_inst.funcDecode = NULL;
622 NetEqMainInst->DSPinst.codec_ptr_inst.funcDecodeInit = NULL;
623 NetEqMainInst->DSPinst.codec_ptr_inst.funcDecodePLC = NULL;
624 NetEqMainInst->DSPinst.codec_ptr_inst.funcGetMDinfo = NULL;
625 NetEqMainInst->DSPinst.codec_ptr_inst.funcUpdBWEst = NULL;
626 NetEqMainInst->DSPinst.codec_ptr_inst.funcGetErrorCode = NULL;
627
628 return (0);
629}
630
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000631int WebRtcNetEQ_CodecDbGetSizeInfo(void *inst, int16_t *UsedEntries,
632 int16_t *MaxEntries)
niklase@google.com470e71d2011-07-07 08:21:25 +0000633{
634 MainInst_t *NetEqMainInst = (MainInst_t*) inst;
635 if (NetEqMainInst == NULL) return (-1);
636 *MaxEntries = NUM_CODECS;
637 *UsedEntries = NetEqMainInst->MCUinst.codec_DB_inst.nrOfCodecs;
638 return (0);
639}
640
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000641int WebRtcNetEQ_CodecDbGetCodecInfo(void *inst, int16_t Entry,
niklase@google.com470e71d2011-07-07 08:21:25 +0000642 enum WebRtcNetEQDecoder *codec)
643{
644 int i;
645 MainInst_t *NetEqMainInst = (MainInst_t*) inst;
646 if (NetEqMainInst == NULL) return (-1);
647 *codec = (enum WebRtcNetEQDecoder) 0;
648 if ((Entry >= 0) && (Entry < NetEqMainInst->MCUinst.codec_DB_inst.nrOfCodecs))
649 {
650 for (i = 0; i < NUM_TOTAL_CODECS; i++)
651 {
652 if (NetEqMainInst->MCUinst.codec_DB_inst.position[i] == Entry)
653 {
654 *codec = (enum WebRtcNetEQDecoder) i;
655 }
656 }
657 }
658 else
659 {
660 NetEqMainInst->ErrorCode = -(CODEC_DB_NOT_EXIST1);
661 return (-1);
662 }
663 return (0);
664}
665
666int WebRtcNetEQ_CodecDbAdd(void *inst, WebRtcNetEQ_CodecDef *codecInst)
667{
668 int ok = 0;
669 MainInst_t *NetEqMainInst = (MainInst_t*) inst;
670 if (NetEqMainInst == NULL) return (-1);
671 ok = WebRtcNetEQ_DbAdd(&NetEqMainInst->MCUinst.codec_DB_inst, codecInst->codec,
672 codecInst->payloadType, codecInst->funcDecode, codecInst->funcDecodeRCU,
673 codecInst->funcDecodePLC, codecInst->funcDecodeInit, codecInst->funcAddLatePkt,
674 codecInst->funcGetMDinfo, codecInst->funcGetPitch, codecInst->funcUpdBWEst,
tina.legrand@webrtc.org5ac387c2012-11-19 08:02:55 +0000675 codecInst->funcDurationEst, codecInst->funcGetErrorCode,
676 codecInst->codec_state, codecInst->codec_fs);
niklase@google.com470e71d2011-07-07 08:21:25 +0000677 if (ok != 0)
678 {
679 NetEqMainInst->ErrorCode = -ok;
680 return (-1);
681 }
682 return (ok);
683}
684
685int WebRtcNetEQ_CodecDbRemove(void *inst, enum WebRtcNetEQDecoder codec)
686{
687 int ok = 0;
688 MainInst_t *NetEqMainInst = (MainInst_t*) inst;
689 if (NetEqMainInst == NULL) return (-1);
690
691 /* check if currently used codec is being removed */
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000692 if (NetEqMainInst->MCUinst.current_Codec == (int16_t) codec)
niklase@google.com470e71d2011-07-07 08:21:25 +0000693 {
694 /* set function pointers to NULL to prevent RecOut from using the codec */
695 NetEqMainInst->DSPinst.codec_ptr_inst.funcDecode = NULL;
696 NetEqMainInst->DSPinst.codec_ptr_inst.funcDecodeRCU = NULL;
697 NetEqMainInst->DSPinst.codec_ptr_inst.funcAddLatePkt = NULL;
698 NetEqMainInst->DSPinst.codec_ptr_inst.funcDecode = NULL;
699 NetEqMainInst->DSPinst.codec_ptr_inst.funcDecodeInit = NULL;
700 NetEqMainInst->DSPinst.codec_ptr_inst.funcDecodePLC = NULL;
701 NetEqMainInst->DSPinst.codec_ptr_inst.funcGetMDinfo = NULL;
702 NetEqMainInst->DSPinst.codec_ptr_inst.funcUpdBWEst = NULL;
703 NetEqMainInst->DSPinst.codec_ptr_inst.funcGetErrorCode = NULL;
704 }
705
706 ok = WebRtcNetEQ_DbRemove(&NetEqMainInst->MCUinst.codec_DB_inst, codec);
707 if (ok != 0)
708 {
709 NetEqMainInst->ErrorCode = -ok;
710 return (-1);
711 }
712 return (ok);
713}
714
715/*********************************
716 * Real-time functions
717 */
718
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000719int WebRtcNetEQ_RecIn(void *inst, int16_t *p_w16datagramstart, int16_t w16_RTPlen,
720 uint32_t uw32_timeRec)
niklase@google.com470e71d2011-07-07 08:21:25 +0000721{
722 int ok = 0;
723 RTPPacket_t RTPpacket;
724 MainInst_t *NetEqMainInst = (MainInst_t*) inst;
725 if (NetEqMainInst == NULL) return (-1);
726
727 /* Check for corrupt/cleared instance */
728 if (NetEqMainInst->MCUinst.main_inst != NetEqMainInst)
729 {
730 /* Instance is corrupt */
731 NetEqMainInst->ErrorCode = CORRUPT_INSTANCE;
732 return (-1);
733 }
734
735 /* Parse RTP header */
736 ok = WebRtcNetEQ_RTPPayloadInfo(p_w16datagramstart, w16_RTPlen, &RTPpacket);
737 if (ok != 0)
738 {
739 NetEqMainInst->ErrorCode = -ok;
740 return (-1);
741 }
742
743 ok = WebRtcNetEQ_RecInInternal(&NetEqMainInst->MCUinst, &RTPpacket, uw32_timeRec);
744 if (ok != 0)
745 {
746 NetEqMainInst->ErrorCode = -ok;
747 return (-1);
748 }
749 return (ok);
750}
751
752/****************************************************************************
753 * WebRtcNetEQ_RecInRTPStruct(...)
754 *
755 * Alternative RecIn function, used when the RTP data has already been
756 * parsed into an RTP info struct (WebRtcNetEQ_RTPInfo).
757 *
758 * Input:
759 * - inst : NetEQ instance
760 * - rtpInfo : Pointer to RTP info
761 * - payloadPtr : Pointer to the RTP payload (first byte after header)
762 * - payloadLenBytes : Length (in bytes) of the payload in payloadPtr
763 * - timeRec : Receive time (in timestamps of the used codec)
764 *
765 * Return value : 0 - Ok
766 * -1 - Error
767 */
768int WebRtcNetEQ_RecInRTPStruct(void *inst, WebRtcNetEQ_RTPInfo *rtpInfo,
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000769 const uint8_t *payloadPtr, int16_t payloadLenBytes,
770 uint32_t uw32_timeRec)
niklase@google.com470e71d2011-07-07 08:21:25 +0000771{
772 int ok = 0;
773 RTPPacket_t RTPpacket;
774 MainInst_t *NetEqMainInst = (MainInst_t*) inst;
775 if (NetEqMainInst == NULL)
776 {
777 return (-1);
778 }
779
780 /* Check for corrupt/cleared instance */
781 if (NetEqMainInst->MCUinst.main_inst != NetEqMainInst)
782 {
783 /* Instance is corrupt */
784 NetEqMainInst->ErrorCode = CORRUPT_INSTANCE;
785 return (-1);
786 }
787
788 /* Load NetEQ's RTP struct from Module RTP struct */
789 RTPpacket.payloadType = rtpInfo->payloadType;
790 RTPpacket.seqNumber = rtpInfo->sequenceNumber;
791 RTPpacket.timeStamp = rtpInfo->timeStamp;
792 RTPpacket.ssrc = rtpInfo->SSRC;
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000793 RTPpacket.payload = (const int16_t*) payloadPtr;
niklase@google.com470e71d2011-07-07 08:21:25 +0000794 RTPpacket.payloadLen = payloadLenBytes;
795 RTPpacket.starts_byte1 = 0;
796
797 ok = WebRtcNetEQ_RecInInternal(&NetEqMainInst->MCUinst, &RTPpacket, uw32_timeRec);
798 if (ok != 0)
799 {
800 NetEqMainInst->ErrorCode = -ok;
801 return (-1);
802 }
803 return (ok);
804}
805
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000806int WebRtcNetEQ_RecOut(void *inst, int16_t *pw16_outData, int16_t *pw16_len)
niklase@google.com470e71d2011-07-07 08:21:25 +0000807{
808 int ok = 0;
809 MainInst_t *NetEqMainInst = (MainInst_t*) inst;
810#ifdef NETEQ_STEREO
811 MasterSlaveInfo msInfo;
812 msInfo.msMode = NETEQ_MONO;
813#endif
814
815 if (NetEqMainInst == NULL) return (-1);
816
817 /* Check for corrupt/cleared instance */
818 if (NetEqMainInst->DSPinst.main_inst != NetEqMainInst)
819 {
820 /* Instance is corrupt */
821 NetEqMainInst->ErrorCode = CORRUPT_INSTANCE;
822 return (-1);
823 }
824
825#ifdef NETEQ_STEREO
826 NetEqMainInst->DSPinst.msInfo = &msInfo;
827#endif
828
829 ok = WebRtcNetEQ_RecOutInternal(&NetEqMainInst->DSPinst, pw16_outData,
turaj@webrtc.org28d54ab2013-04-22 18:53:35 +0000830 pw16_len, 0 /* not BGN only */, NetEqMainInst->MCUinst.av_sync);
niklase@google.com470e71d2011-07-07 08:21:25 +0000831 if (ok != 0)
832 {
833 NetEqMainInst->ErrorCode = -ok;
834 return (-1);
835 }
836 return (ok);
837}
838
839/****************************************************************************
840 * WebRtcNetEQ_RecOutMasterSlave(...)
841 *
842 * RecOut function for running several NetEQ instances in master/slave mode.
843 * One master can be used to control several slaves.
844 *
845 * Input:
846 * - inst : NetEQ instance
847 * - isMaster : Non-zero indicates that this is the master channel
848 * - msInfo : (slave only) Information from master
849 *
850 * Output:
851 * - inst : Updated NetEQ instance
852 * - pw16_outData : Pointer to vector where output should be written
853 * - pw16_len : Pointer to variable where output length is returned
854 * - msInfo : (master only) Information to slave(s)
855 *
856 * Return value : 0 - Ok
857 * -1 - Error
858 */
859
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000860int WebRtcNetEQ_RecOutMasterSlave(void *inst, int16_t *pw16_outData,
861 int16_t *pw16_len, void *msInfo,
862 int16_t isMaster)
niklase@google.com470e71d2011-07-07 08:21:25 +0000863{
864#ifndef NETEQ_STEREO
865 /* Stereo not supported */
866 return(-1);
867#else
868 int ok = 0;
869 MainInst_t *NetEqMainInst = (MainInst_t*) inst;
870
871 if (NetEqMainInst == NULL) return (-1);
872
873 /* Check for corrupt/cleared instance */
874 if (NetEqMainInst->DSPinst.main_inst != NetEqMainInst)
875 {
876 /* Instance is corrupt */
877 NetEqMainInst->ErrorCode = CORRUPT_INSTANCE;
878 return (-1);
879 }
880
881 if (msInfo == NULL)
882 {
883 /* msInfo not provided */
884 NetEqMainInst->ErrorCode = NETEQ_OTHER_ERROR;
885 return (-1);
886 }
887
888 /* translate from external to internal Master/Slave information */
889 NetEqMainInst->DSPinst.msInfo = (MasterSlaveInfo *) msInfo;
890
891 /* check that we have not done a master/slave switch without first re-initializing */
892 if ((NetEqMainInst->masterSlave == 1 && !isMaster) || /* switch from master to slave */
893 (NetEqMainInst->masterSlave == 2 && isMaster)) /* switch from slave to master */
894 {
895 NetEqMainInst->ErrorCode = ILLEGAL_MASTER_SLAVE_SWITCH;
896 return (-1);
897 }
898
899 if (!isMaster)
900 {
901 /* this is the slave */
902 NetEqMainInst->masterSlave = 2;
903 NetEqMainInst->DSPinst.msInfo->msMode = NETEQ_SLAVE;
904 }
905 else
906 {
907 NetEqMainInst->DSPinst.msInfo->msMode = NETEQ_MASTER;
908 }
909
910 ok = WebRtcNetEQ_RecOutInternal(&NetEqMainInst->DSPinst, pw16_outData,
turaj@webrtc.org28d54ab2013-04-22 18:53:35 +0000911 pw16_len, 0 /* not BGN only */, NetEqMainInst->MCUinst.av_sync);
niklase@google.com470e71d2011-07-07 08:21:25 +0000912 if (ok != 0)
913 {
914 NetEqMainInst->ErrorCode = -ok;
915 return (-1);
916 }
917
918 if (isMaster)
919 {
920 /* this is the master */
921 NetEqMainInst->masterSlave = 1;
922 }
923
924 return (ok);
925#endif
926}
927
928int WebRtcNetEQ_GetMasterSlaveInfoSize()
929{
930#ifdef NETEQ_STEREO
931 return (sizeof(MasterSlaveInfo));
932#else
933 return(-1);
934#endif
935}
936
937/* Special RecOut that does not do any decoding. */
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000938int WebRtcNetEQ_RecOutNoDecode(void *inst, int16_t *pw16_outData,
939 int16_t *pw16_len)
niklase@google.com470e71d2011-07-07 08:21:25 +0000940{
941 int ok = 0;
942 MainInst_t *NetEqMainInst = (MainInst_t*) inst;
943#ifdef NETEQ_STEREO
944 MasterSlaveInfo msInfo;
945#endif
946
947 if (NetEqMainInst == NULL) return (-1);
948
949 /* Check for corrupt/cleared instance */
950 if (NetEqMainInst->DSPinst.main_inst != NetEqMainInst)
951 {
952 /* Instance is corrupt */
953 NetEqMainInst->ErrorCode = CORRUPT_INSTANCE;
954 return (-1);
955 }
956
957#ifdef NETEQ_STEREO
958 /* keep same mode as before */
959 switch (NetEqMainInst->masterSlave)
960 {
961 case 1:
962 {
963 msInfo.msMode = NETEQ_MASTER;
964 break;
965 }
966 case 2:
967 {
968 msInfo.msMode = NETEQ_SLAVE;
969 break;
970 }
971 default:
972 {
973 msInfo.msMode = NETEQ_MONO;
974 break;
975 }
976 }
977
978 NetEqMainInst->DSPinst.msInfo = &msInfo;
979#endif
980
981 ok = WebRtcNetEQ_RecOutInternal(&NetEqMainInst->DSPinst, pw16_outData,
turaj@webrtc.org28d54ab2013-04-22 18:53:35 +0000982 pw16_len, 1 /* BGN only */, NetEqMainInst->MCUinst.av_sync);
niklase@google.com470e71d2011-07-07 08:21:25 +0000983 if (ok != 0)
984 {
985 NetEqMainInst->ErrorCode = -ok;
986 return (-1);
987 }
988 return (ok);
989}
990
991int WebRtcNetEQ_GetRTCPStats(void *inst, WebRtcNetEQ_RTCPStat *RTCP_inst)
992{
993 int ok = 0;
994 MainInst_t *NetEqMainInst = (MainInst_t*) inst;
995 if (NetEqMainInst == NULL) return (-1);
996 ok = WebRtcNetEQ_RTCPGetStats(&NetEqMainInst->MCUinst.RTCP_inst,
997 &RTCP_inst->fraction_lost, &RTCP_inst->cum_lost, &RTCP_inst->ext_max,
998 &RTCP_inst->jitter, 0);
999 if (ok != 0)
1000 {
1001 NetEqMainInst->ErrorCode = -ok;
1002 return (-1);
1003 }
1004 return (ok);
1005}
1006
1007int WebRtcNetEQ_GetRTCPStatsNoReset(void *inst, WebRtcNetEQ_RTCPStat *RTCP_inst)
1008{
1009 int ok = 0;
1010 MainInst_t *NetEqMainInst = (MainInst_t*) inst;
1011 if (NetEqMainInst == NULL) return (-1);
1012 ok = WebRtcNetEQ_RTCPGetStats(&NetEqMainInst->MCUinst.RTCP_inst,
1013 &RTCP_inst->fraction_lost, &RTCP_inst->cum_lost, &RTCP_inst->ext_max,
1014 &RTCP_inst->jitter, 1);
1015 if (ok != 0)
1016 {
1017 NetEqMainInst->ErrorCode = -ok;
1018 return (-1);
1019 }
1020 return (ok);
1021}
1022
pbos@webrtc.org0946a562013-04-09 00:28:06 +00001023int WebRtcNetEQ_GetSpeechTimeStamp(void *inst, uint32_t *timestamp)
niklase@google.com470e71d2011-07-07 08:21:25 +00001024{
1025 MainInst_t *NetEqMainInst = (MainInst_t*) inst;
1026 if (NetEqMainInst == NULL) return (-1);
1027
1028 if (NetEqMainInst->MCUinst.TSscalingInitialized)
1029 {
1030 *timestamp = WebRtcNetEQ_ScaleTimestampInternalToExternal(&NetEqMainInst->MCUinst,
1031 NetEqMainInst->DSPinst.videoSyncTimestamp);
1032 }
1033 else
1034 {
1035 *timestamp = NetEqMainInst->DSPinst.videoSyncTimestamp;
1036 }
1037
1038 return (0);
1039}
1040
1041/****************************************************************************
1042 * WebRtcNetEQ_GetSpeechOutputType(...)
1043 *
1044 * Get the output type for the audio provided by the latest call to
1045 * WebRtcNetEQ_RecOut().
1046 *
1047 * kOutputNormal = normal audio (possibly processed)
1048 * kOutputPLC = loss concealment through stretching audio
1049 * kOutputCNG = comfort noise (codec-internal or RFC3389)
1050 * kOutputPLCtoCNG = background noise only due to long expand or error
1051 * kOutputVADPassive = PostDecode VAD signalling passive speaker
1052 *
1053 * Input:
1054 * - inst : NetEQ instance
1055 *
1056 * Output:
1057 * - outputType : Output type from enum list WebRtcNetEQOutputType
1058 *
1059 * Return value : 0 - Ok
1060 * -1 - Error
1061 */
1062
1063int WebRtcNetEQ_GetSpeechOutputType(void *inst, enum WebRtcNetEQOutputType *outputType)
1064{
1065 /* Typecast to internal instance type */
1066 MainInst_t *NetEqMainInst = (MainInst_t*) inst;
1067
1068 if (NetEqMainInst == NULL)
1069 {
1070 return (-1);
1071 }
1072
1073 if ((NetEqMainInst->DSPinst.w16_mode & MODE_BGN_ONLY) != 0)
1074 {
1075 /* If last mode was background noise only */
1076 *outputType = kOutputPLCtoCNG;
1077
1078 }
1079 else if ((NetEqMainInst->DSPinst.w16_mode == MODE_CODEC_INTERNAL_CNG)
1080 || (NetEqMainInst->DSPinst.w16_mode == MODE_RFC3389CNG))
1081 {
1082 /* If CN or internal CNG */
1083 *outputType = kOutputCNG;
1084
1085#ifdef NETEQ_VAD
1086 }
1087 else if ( NetEqMainInst->DSPinst.VADInst.VADDecision == 0 )
1088 {
1089 /* post-decode VAD says passive speaker */
1090 *outputType = kOutputVADPassive;
1091#endif /* NETEQ_VAD */
1092
1093 }
1094 else if ((NetEqMainInst->DSPinst.w16_mode == MODE_EXPAND)
1095 && (NetEqMainInst->DSPinst.ExpandInst.w16_expandMuteFactor == 0))
1096 {
1097 /* Expand mode has faded down to background noise only (very long expand) */
1098 *outputType = kOutputPLCtoCNG;
1099
1100 }
1101 else if (NetEqMainInst->DSPinst.w16_mode == MODE_EXPAND)
1102 {
1103 /* PLC mode */
1104 *outputType = kOutputPLC;
1105
1106 }
1107 else
1108 {
1109 /* Normal speech output type (can still be manipulated, e.g., accelerated) */
1110 *outputType = kOutputNormal;
1111 }
1112
1113 return (0);
1114}
1115
1116/**********************************
1117 * Functions related to VQmon
1118 */
1119
1120#define WEBRTC_NETEQ_CONCEALMENTFLAG_LOST 0x01
1121#define WEBRTC_NETEQ_CONCEALMENTFLAG_DISCARDED 0x02
1122#define WEBRTC_NETEQ_CONCEALMENTFLAG_SUPRESS 0x04
1123#define WEBRTC_NETEQ_CONCEALMENTFLAG_CNGACTIVE 0x80
1124
pbos@webrtc.org0946a562013-04-09 00:28:06 +00001125int WebRtcNetEQ_VQmonRecOutStatistics(void *inst, uint16_t *validVoiceDurationMs,
1126 uint16_t *concealedVoiceDurationMs,
1127 uint8_t *concealedVoiceFlags)
niklase@google.com470e71d2011-07-07 08:21:25 +00001128{
1129 MainInst_t *NetEqMainInst = (MainInst_t*) inst;
pbos@webrtc.org0946a562013-04-09 00:28:06 +00001130 int16_t fs_mult;
1131 int16_t ms_lost;
niklase@google.com470e71d2011-07-07 08:21:25 +00001132 if (NetEqMainInst == NULL) return (-1);
1133 fs_mult = WebRtcSpl_DivW32W16ResW16(NetEqMainInst->MCUinst.fs, 8000);
1134
1135 ms_lost = WebRtcSpl_DivW32W16ResW16(
pbos@webrtc.org0946a562013-04-09 00:28:06 +00001136 (int32_t) NetEqMainInst->DSPinst.w16_concealedTS, (int16_t) (8 * fs_mult));
niklase@google.com470e71d2011-07-07 08:21:25 +00001137 if (ms_lost > NetEqMainInst->DSPinst.millisecondsPerCall) ms_lost
1138 = NetEqMainInst->DSPinst.millisecondsPerCall;
1139
1140 *validVoiceDurationMs = NetEqMainInst->DSPinst.millisecondsPerCall - ms_lost;
1141 *concealedVoiceDurationMs = ms_lost;
1142 if (ms_lost > 0)
1143 {
1144 *concealedVoiceFlags = WEBRTC_NETEQ_CONCEALMENTFLAG_LOST;
1145 }
1146 else
1147 {
1148 *concealedVoiceFlags = 0;
1149 }
1150 NetEqMainInst->DSPinst.w16_concealedTS -= ms_lost * (8 * fs_mult);
1151
1152 return (0);
1153}
1154
pbos@webrtc.org0946a562013-04-09 00:28:06 +00001155int WebRtcNetEQ_VQmonGetConfiguration(void *inst, uint16_t *absMaxDelayMs,
1156 uint8_t *adaptationRate)
niklase@google.com470e71d2011-07-07 08:21:25 +00001157{
1158 /* Dummy check the inst, just to avoid compiler warnings. */
1159 if (inst == NULL)
1160 {
1161 /* Do nothing. */
1162 }
1163
1164 /* Hardcoded variables that are used for VQmon as jitter buffer parameters */
1165 *absMaxDelayMs = 240;
1166 *adaptationRate = 1;
1167 return (0);
1168}
1169
pbos@webrtc.org0946a562013-04-09 00:28:06 +00001170int WebRtcNetEQ_VQmonGetRxStatistics(void *inst, uint16_t *avgDelayMs,
1171 uint16_t *maxDelayMs)
niklase@google.com470e71d2011-07-07 08:21:25 +00001172{
1173 MainInst_t *NetEqMainInst = (MainInst_t*) inst;
1174 if (NetEqMainInst == NULL) return (-1);
pbos@webrtc.org0946a562013-04-09 00:28:06 +00001175 *avgDelayMs = (uint16_t) (NetEqMainInst->MCUinst.BufferStat_inst.avgDelayMsQ8 >> 8);
1176 *maxDelayMs = (uint16_t) NetEqMainInst->MCUinst.BufferStat_inst.maxDelayMs;
niklase@google.com470e71d2011-07-07 08:21:25 +00001177 return (0);
1178}
1179
1180/*************************************
1181 * Statistics functions
1182 */
1183
1184/* Get the "in-call" statistics from NetEQ.
1185 * The statistics are reset after the query. */
1186int WebRtcNetEQ_GetNetworkStatistics(void *inst, WebRtcNetEQ_NetworkStatistics *stats)
1187
1188{
1189
pbos@webrtc.org0946a562013-04-09 00:28:06 +00001190 uint16_t tempU16;
1191 uint32_t tempU32, tempU32_2;
niklase@google.com470e71d2011-07-07 08:21:25 +00001192 int numShift;
1193 MainInst_t *NetEqMainInst = (MainInst_t*) inst;
1194
1195 /* Instance sanity */
1196 if (NetEqMainInst == NULL) return (-1);
1197
roosa@google.comb8ba4d82012-12-14 00:06:18 +00001198 stats->addedSamples = NetEqMainInst->DSPinst.statInst.addedSamples;
1199
niklase@google.com470e71d2011-07-07 08:21:25 +00001200 /*******************/
1201 /* Get buffer size */
1202 /*******************/
1203
henrik.lundin@webrtc.org524eb482011-11-30 16:21:22 +00001204 if (NetEqMainInst->MCUinst.fs != 0)
niklase@google.com470e71d2011-07-07 08:21:25 +00001205 {
pbos@webrtc.org0946a562013-04-09 00:28:06 +00001206 int32_t temp32;
henrik.lundin@webrtc.org524eb482011-11-30 16:21:22 +00001207 /* Query packet buffer for number of samples. */
1208 temp32 = WebRtcNetEQ_PacketBufferGetSize(
tina.legrand@webrtc.org5ac387c2012-11-19 08:02:55 +00001209 &NetEqMainInst->MCUinst.PacketBuffer_inst,
turaj@webrtc.org28d54ab2013-04-22 18:53:35 +00001210 &NetEqMainInst->MCUinst.codec_DB_inst,
1211 NetEqMainInst->MCUinst.av_sync);
henrik.lundin@webrtc.org524eb482011-11-30 16:21:22 +00001212
1213 /* Divide by sample rate.
1214 * Calculate temp32 * 1000 / fs to get result in ms. */
pbos@webrtc.org0946a562013-04-09 00:28:06 +00001215 stats->currentBufferSize = (uint16_t)
henrik.lundin@webrtc.org524eb482011-11-30 16:21:22 +00001216 WebRtcSpl_DivU32U16(temp32 * 1000, NetEqMainInst->MCUinst.fs);
1217
1218 /* Add number of samples yet to play in sync buffer. */
pbos@webrtc.org0946a562013-04-09 00:28:06 +00001219 temp32 = (int32_t) (NetEqMainInst->DSPinst.endPosition -
henrik.lundin@webrtc.org524eb482011-11-30 16:21:22 +00001220 NetEqMainInst->DSPinst.curPosition);
pbos@webrtc.org0946a562013-04-09 00:28:06 +00001221 stats->currentBufferSize += (uint16_t)
henrik.lundin@webrtc.org524eb482011-11-30 16:21:22 +00001222 WebRtcSpl_DivU32U16(temp32 * 1000, NetEqMainInst->MCUinst.fs);
1223 }
1224 else
1225 {
1226 /* Sample rate not initialized. */
1227 stats->currentBufferSize = 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001228 }
1229
1230 /***************************/
1231 /* Get optimal buffer size */
1232 /***************************/
1233
turaj@webrtc.orge46c8d32013-05-22 20:39:43 +00001234 if (NetEqMainInst->MCUinst.fs != 0)
niklase@google.com470e71d2011-07-07 08:21:25 +00001235 {
1236 /* preferredBufferSize = Bopt * packSizeSamples / (fs/1000) */
1237 stats->preferredBufferSize
pbos@webrtc.org0946a562013-04-09 00:28:06 +00001238 = (uint16_t) WEBRTC_SPL_MUL_16_16(
1239 (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 +00001240 WebRtcSpl_DivW32W16ResW16(
pbos@webrtc.org0946a562013-04-09 00:28:06 +00001241 (int32_t) NetEqMainInst->MCUinst.BufferStat_inst.Automode_inst.packetSpeechLenSamp, /* samples per packet */
1242 WebRtcSpl_DivW32W16ResW16( (int32_t) NetEqMainInst->MCUinst.fs, (int16_t) 1000 ) /* samples per ms */
niklase@google.com470e71d2011-07-07 08:21:25 +00001243 ) );
1244
1245 /* add extra delay */
1246 if (NetEqMainInst->MCUinst.BufferStat_inst.Automode_inst.extraDelayMs > 0)
1247 {
1248 stats->preferredBufferSize
1249 += NetEqMainInst->MCUinst.BufferStat_inst.Automode_inst.extraDelayMs;
1250 }
1251 }
1252 else
1253 {
1254 /* sample rate not initialized */
1255 stats->preferredBufferSize = 0;
1256 }
1257
henrik.lundin@webrtc.orgd4398702012-01-04 13:09:55 +00001258 /***********************************/
1259 /* Check if jitter peaks are found */
1260 /***********************************/
1261
1262 stats->jitterPeaksFound =
1263 NetEqMainInst->MCUinst.BufferStat_inst.Automode_inst.peakFound;
1264
niklase@google.com470e71d2011-07-07 08:21:25 +00001265 /***********************/
1266 /* Calculate loss rate */
1267 /***********************/
1268
1269 /* timestamps elapsed since last report */
1270 tempU32 = NetEqMainInst->MCUinst.lastReportTS;
1271
1272 if (NetEqMainInst->MCUinst.lostTS == 0)
1273 {
1274 /* no losses */
1275 stats->currentPacketLossRate = 0;
1276 }
1277 else if (NetEqMainInst->MCUinst.lostTS < tempU32)
1278 {
1279 /* calculate shifts; we want the result in Q14 */
1280 numShift = WebRtcSpl_NormU32(NetEqMainInst->MCUinst.lostTS); /* numerator shift for normalize */
1281
1282 if (numShift < 14)
1283 {
1284 /* cannot shift numerator 14 steps; shift denominator too */
1285 tempU32 = WEBRTC_SPL_RSHIFT_U32(tempU32, 14-numShift); /* right-shift */
1286 }
1287 else
1288 {
1289 /* shift no more than 14 steps */
1290 numShift = 14;
1291 }
1292
1293 if (tempU32 == 0)
1294 {
1295 /* check for zero denominator; result should be zero in this case */
1296 stats->currentPacketLossRate = 0;
1297 }
1298 else
1299 {
1300 /* check that denominator fits in signed 16-bit */
1301 while (tempU32 > WEBRTC_SPL_WORD16_MAX)
1302 {
1303 tempU32 >>= 1; /* right-shift 1 step */
1304 numShift--; /* compensate in numerator */
1305 }
pbos@webrtc.org0946a562013-04-09 00:28:06 +00001306 tempU16 = (uint16_t) tempU32;
niklase@google.com470e71d2011-07-07 08:21:25 +00001307
1308 /* do the shift of numerator */
1309 tempU32
pbos@webrtc.org0946a562013-04-09 00:28:06 +00001310 = WEBRTC_SPL_SHIFT_W32( (uint32_t) NetEqMainInst->MCUinst.lostTS, numShift);
niklase@google.com470e71d2011-07-07 08:21:25 +00001311
pbos@webrtc.org0946a562013-04-09 00:28:06 +00001312 stats->currentPacketLossRate = (uint16_t) WebRtcSpl_DivU32U16(tempU32,
niklase@google.com470e71d2011-07-07 08:21:25 +00001313 tempU16);
1314 }
1315 }
1316 else
1317 {
1318 /* lost count is larger than elapsed time count; probably timestamp wrap-around or something else wrong */
1319 /* set loss rate = 1 */
1320 stats->currentPacketLossRate = 1 << 14; /* 1 in Q14 */
1321 }
1322
1323 /**************************/
1324 /* Calculate discard rate */
1325 /**************************/
1326
1327 /* timestamps elapsed since last report */
1328 tempU32 = NetEqMainInst->MCUinst.lastReportTS;
1329
1330 /* number of discarded samples */
1331 tempU32_2
pbos@webrtc.org0946a562013-04-09 00:28:06 +00001332 = WEBRTC_SPL_MUL_16_U16( (int16_t) NetEqMainInst->MCUinst.PacketBuffer_inst.packSizeSamples,
niklase@google.com470e71d2011-07-07 08:21:25 +00001333 NetEqMainInst->MCUinst.PacketBuffer_inst.discardedPackets);
1334
1335 if (tempU32_2 == 0)
1336 {
1337 /* no discarded samples */
1338 stats->currentDiscardRate = 0;
1339 }
1340 else if (tempU32_2 < tempU32)
1341 {
1342 /* calculate shifts; we want the result in Q14 */
1343 numShift = WebRtcSpl_NormU32(tempU32_2); /* numerator shift for normalize */
1344
1345 if (numShift < 14)
1346 {
1347 /* cannot shift numerator 14 steps; shift denominator too */
1348 tempU32 = WEBRTC_SPL_RSHIFT_U32(tempU32, 14-numShift); /* right-shift */
1349 }
1350 else
1351 {
1352 /* shift no more than 14 steps */
1353 numShift = 14;
1354 }
1355
1356 if (tempU32 == 0)
1357 {
1358 /* check for zero denominator; result should be zero in this case */
1359 stats->currentDiscardRate = 0;
1360 }
1361 else
1362 {
1363 /* check that denominator fits in signed 16-bit */
1364 while (tempU32 > WEBRTC_SPL_WORD16_MAX)
1365 {
1366 tempU32 >>= 1; /* right-shift 1 step */
1367 numShift--; /* compensate in numerator */
1368 }
pbos@webrtc.org0946a562013-04-09 00:28:06 +00001369 tempU16 = (uint16_t) tempU32;
niklase@google.com470e71d2011-07-07 08:21:25 +00001370
1371 /* do the shift of numerator */
1372 tempU32 = WEBRTC_SPL_SHIFT_W32( tempU32_2, numShift);
1373
pbos@webrtc.org0946a562013-04-09 00:28:06 +00001374 stats->currentDiscardRate = (uint16_t) WebRtcSpl_DivU32U16(tempU32, tempU16);
niklase@google.com470e71d2011-07-07 08:21:25 +00001375 }
1376 }
1377 else
1378 {
1379 /* lost count is larger than elapsed time count; probably timestamp wrap-around or something else wrong */
1380 /* set loss rate = 1 */
1381 stats->currentDiscardRate = 1 << 14; /* 1 in Q14 */
1382 }
1383
1384 /*************************************************************/
1385 /* Calculate Accelerate, Expand and Pre-emptive Expand rates */
1386 /*************************************************************/
1387
1388 /* timestamps elapsed since last report */
1389 tempU32 = NetEqMainInst->MCUinst.lastReportTS;
1390
1391 if (NetEqMainInst->DSPinst.statInst.accelerateLength == 0)
1392 {
1393 /* no accelerate */
1394 stats->currentAccelerateRate = 0;
1395 }
1396 else if (NetEqMainInst->DSPinst.statInst.accelerateLength < tempU32)
1397 {
1398 /* calculate shifts; we want the result in Q14 */
1399 numShift = WebRtcSpl_NormU32(NetEqMainInst->DSPinst.statInst.accelerateLength); /* numerator shift for normalize */
1400
1401 if (numShift < 14)
1402 {
1403 /* cannot shift numerator 14 steps; shift denominator too */
1404 tempU32 = WEBRTC_SPL_RSHIFT_U32(tempU32, 14-numShift); /* right-shift */
1405 }
1406 else
1407 {
1408 /* shift no more than 14 steps */
1409 numShift = 14;
1410 }
1411
1412 if (tempU32 == 0)
1413 {
1414 /* check for zero denominator; result should be zero in this case */
1415 stats->currentAccelerateRate = 0;
1416 }
1417 else
1418 {
1419 /* check that denominator fits in signed 16-bit */
1420 while (tempU32 > WEBRTC_SPL_WORD16_MAX)
1421 {
1422 tempU32 >>= 1; /* right-shift 1 step */
1423 numShift--; /* compensate in numerator */
1424 }
pbos@webrtc.org0946a562013-04-09 00:28:06 +00001425 tempU16 = (uint16_t) tempU32;
niklase@google.com470e71d2011-07-07 08:21:25 +00001426
1427 /* do the shift of numerator */
1428 tempU32
1429 = WEBRTC_SPL_SHIFT_W32( NetEqMainInst->DSPinst.statInst.accelerateLength, numShift);
1430
pbos@webrtc.org0946a562013-04-09 00:28:06 +00001431 stats->currentAccelerateRate = (uint16_t) WebRtcSpl_DivU32U16(tempU32,
niklase@google.com470e71d2011-07-07 08:21:25 +00001432 tempU16);
1433 }
1434 }
1435 else
1436 {
1437 /* lost count is larger than elapsed time count; probably timestamp wrap-around or something else wrong */
1438 /* set loss rate = 1 */
1439 stats->currentAccelerateRate = 1 << 14; /* 1 in Q14 */
1440 }
1441
niklase@google.com470e71d2011-07-07 08:21:25 +00001442 /* timestamps elapsed since last report */
1443 tempU32 = NetEqMainInst->MCUinst.lastReportTS;
1444
1445 if (NetEqMainInst->DSPinst.statInst.expandLength == 0)
1446 {
1447 /* no expand */
1448 stats->currentExpandRate = 0;
1449 }
1450 else if (NetEqMainInst->DSPinst.statInst.expandLength < tempU32)
1451 {
1452 /* calculate shifts; we want the result in Q14 */
1453 numShift = WebRtcSpl_NormU32(NetEqMainInst->DSPinst.statInst.expandLength); /* numerator shift for normalize */
1454
1455 if (numShift < 14)
1456 {
1457 /* cannot shift numerator 14 steps; shift denominator too */
1458 tempU32 = WEBRTC_SPL_RSHIFT_U32(tempU32, 14-numShift); /* right-shift */
1459 }
1460 else
1461 {
1462 /* shift no more than 14 steps */
1463 numShift = 14;
1464 }
1465
1466 if (tempU32 == 0)
1467 {
1468 /* check for zero denominator; result should be zero in this case */
1469 stats->currentExpandRate = 0;
1470 }
1471 else
1472 {
1473 /* check that denominator fits in signed 16-bit */
1474 while (tempU32 > WEBRTC_SPL_WORD16_MAX)
1475 {
1476 tempU32 >>= 1; /* right-shift 1 step */
1477 numShift--; /* compensate in numerator */
1478 }
pbos@webrtc.org0946a562013-04-09 00:28:06 +00001479 tempU16 = (uint16_t) tempU32;
niklase@google.com470e71d2011-07-07 08:21:25 +00001480
1481 /* do the shift of numerator */
1482 tempU32
1483 = WEBRTC_SPL_SHIFT_W32( NetEqMainInst->DSPinst.statInst.expandLength, numShift);
1484
pbos@webrtc.org0946a562013-04-09 00:28:06 +00001485 stats->currentExpandRate = (uint16_t) WebRtcSpl_DivU32U16(tempU32, tempU16);
niklase@google.com470e71d2011-07-07 08:21:25 +00001486 }
1487 }
1488 else
1489 {
1490 /* lost count is larger than elapsed time count; probably timestamp wrap-around or something else wrong */
1491 /* set loss rate = 1 */
1492 stats->currentExpandRate = 1 << 14; /* 1 in Q14 */
1493 }
1494
1495 /* timestamps elapsed since last report */
1496 tempU32 = NetEqMainInst->MCUinst.lastReportTS;
1497
1498 if (NetEqMainInst->DSPinst.statInst.preemptiveLength == 0)
1499 {
1500 /* no pre-emptive expand */
1501 stats->currentPreemptiveRate = 0;
1502 }
1503 else if (NetEqMainInst->DSPinst.statInst.preemptiveLength < tempU32)
1504 {
1505 /* calculate shifts; we want the result in Q14 */
1506 numShift = WebRtcSpl_NormU32(NetEqMainInst->DSPinst.statInst.preemptiveLength); /* numerator shift for normalize */
1507
1508 if (numShift < 14)
1509 {
1510 /* cannot shift numerator 14 steps; shift denominator too */
1511 tempU32 = WEBRTC_SPL_RSHIFT_U32(tempU32, 14-numShift); /* right-shift */
1512 }
1513 else
1514 {
1515 /* shift no more than 14 steps */
1516 numShift = 14;
1517 }
1518
1519 if (tempU32 == 0)
1520 {
1521 /* check for zero denominator; result should be zero in this case */
1522 stats->currentPreemptiveRate = 0;
1523 }
1524 else
1525 {
1526 /* check that denominator fits in signed 16-bit */
1527 while (tempU32 > WEBRTC_SPL_WORD16_MAX)
1528 {
1529 tempU32 >>= 1; /* right-shift 1 step */
1530 numShift--; /* compensate in numerator */
1531 }
pbos@webrtc.org0946a562013-04-09 00:28:06 +00001532 tempU16 = (uint16_t) tempU32;
niklase@google.com470e71d2011-07-07 08:21:25 +00001533
1534 /* do the shift of numerator */
1535 tempU32
1536 = WEBRTC_SPL_SHIFT_W32( NetEqMainInst->DSPinst.statInst.preemptiveLength, numShift);
1537
pbos@webrtc.org0946a562013-04-09 00:28:06 +00001538 stats->currentPreemptiveRate = (uint16_t) WebRtcSpl_DivU32U16(tempU32,
niklase@google.com470e71d2011-07-07 08:21:25 +00001539 tempU16);
1540 }
1541 }
1542 else
1543 {
1544 /* lost count is larger than elapsed time count; probably timestamp wrap-around or something else wrong */
1545 /* set loss rate = 1 */
1546 stats->currentPreemptiveRate = 1 << 14; /* 1 in Q14 */
1547 }
1548
henrik.lundin@webrtc.orgd4398702012-01-04 13:09:55 +00001549 stats->clockDriftPPM = WebRtcNetEQ_AverageIAT(
1550 &NetEqMainInst->MCUinst.BufferStat_inst.Automode_inst);
1551
niklase@google.com470e71d2011-07-07 08:21:25 +00001552 /* reset counters */
1553 WebRtcNetEQ_ResetMcuInCallStats(&(NetEqMainInst->MCUinst));
1554 WebRtcNetEQ_ClearInCallStats(&(NetEqMainInst->DSPinst));
1555
1556 return (0);
1557}
1558
henrik.lundin@webrtc.orgdbba1f92011-12-20 15:45:05 +00001559int WebRtcNetEQ_GetRawFrameWaitingTimes(void *inst,
1560 int max_length,
1561 int* waiting_times_ms) {
1562 int i = 0;
1563 MainInst_t *main_inst = (MainInst_t*) inst;
1564 if (main_inst == NULL) return -1;
1565
1566 while ((i < max_length) && (i < main_inst->MCUinst.len_waiting_times)) {
1567 waiting_times_ms[i] = main_inst->MCUinst.waiting_times[i] *
1568 main_inst->DSPinst.millisecondsPerCall;
1569 ++i;
1570 }
1571 assert(i <= kLenWaitingTimes);
1572 WebRtcNetEQ_ResetWaitingTimeStats(&main_inst->MCUinst);
1573 return i;
1574}
1575
niklase@google.com470e71d2011-07-07 08:21:25 +00001576/****************************************************************************
1577 * WebRtcNetEQ_SetVADInstance(...)
1578 *
1579 * Provide a pointer to an allocated VAD instance. If function is never
1580 * called or it is called with NULL pointer as VAD_inst, the post-decode
1581 * VAD functionality is disabled. Also provide pointers to init, setmode
1582 * and VAD functions. These are typically pointers to WebRtcVad_Init,
1583 * WebRtcVad_set_mode and WebRtcVad_Process, respectively, all found in the
1584 * interface file webrtc_vad.h.
1585 *
1586 * Input:
1587 * - NetEQ_inst : NetEQ instance
1588 * - VADinst : VAD instance
1589 * - initFunction : Pointer to VAD init function
1590 * - setmodeFunction : Pointer to VAD setmode function
1591 * - VADfunction : Pointer to VAD function
1592 *
1593 * Output:
1594 * - NetEQ_inst : Updated NetEQ instance
1595 *
1596 * Return value : 0 - Ok
1597 * -1 - Error
1598 */
1599
1600int WebRtcNetEQ_SetVADInstance(void *NetEQ_inst, void *VAD_inst,
1601 WebRtcNetEQ_VADInitFunction initFunction,
1602 WebRtcNetEQ_VADSetmodeFunction setmodeFunction,
1603 WebRtcNetEQ_VADFunction VADFunction)
1604{
1605
1606 /* Typecast to internal instance type */
1607 MainInst_t *NetEqMainInst = (MainInst_t*) NetEQ_inst;
1608 if (NetEqMainInst == NULL)
1609 {
1610 return (-1);
1611 }
1612
1613#ifdef NETEQ_VAD
1614
1615 /* Store pointer in PostDecode VAD struct */
1616 NetEqMainInst->DSPinst.VADInst.VADState = VAD_inst;
1617
1618 /* Store function pointers */
1619 NetEqMainInst->DSPinst.VADInst.initFunction = initFunction;
1620 NetEqMainInst->DSPinst.VADInst.setmodeFunction = setmodeFunction;
1621 NetEqMainInst->DSPinst.VADInst.VADFunction = VADFunction;
1622
1623 /* Call init function and return the result (ok or fail) */
1624 return(WebRtcNetEQ_InitVAD(&NetEqMainInst->DSPinst.VADInst, NetEqMainInst->DSPinst.fs));
1625
1626#else /* NETEQ_VAD not defined */
1627 return (-1);
1628#endif /* NETEQ_VAD */
1629
1630}
1631
1632/****************************************************************************
1633 * WebRtcNetEQ_SetVADMode(...)
1634 *
1635 * Pass an aggressiveness mode parameter to the post-decode VAD instance.
1636 * If this function is never called, mode 0 (quality mode) is used as default.
1637 *
1638 * Input:
1639 * - inst : NetEQ instance
1640 * - mode : mode parameter (same range as WebRtc VAD mode)
1641 *
1642 * Output:
1643 * - inst : Updated NetEQ instance
1644 *
1645 * Return value : 0 - Ok
1646 * -1 - Error
1647 */
1648
bjornv@webrtc.orgf4b77fd2012-01-25 12:40:00 +00001649int WebRtcNetEQ_SetVADMode(void *inst, int mode)
niklase@google.com470e71d2011-07-07 08:21:25 +00001650{
1651
1652 /* Typecast to internal instance type */
1653 MainInst_t *NetEqMainInst = (MainInst_t*) inst;
1654 if (NetEqMainInst == NULL)
1655 {
1656 return (-1);
1657 }
1658
1659#ifdef NETEQ_VAD
1660
1661 /* Set mode and return result */
1662 return(WebRtcNetEQ_SetVADModeInternal(&NetEqMainInst->DSPinst.VADInst, mode));
1663
1664#else /* NETEQ_VAD not defined */
1665 return (-1);
1666#endif /* NETEQ_VAD */
1667
1668}
turaj@webrtc.org92d1f072013-04-15 16:52:04 +00001669
1670void WebRtcNetEQ_GetProcessingActivity(void *inst,
1671 WebRtcNetEQ_ProcessingActivity *stats) {
1672 MainInst_t *NetEqMainInst = (MainInst_t*) inst;
1673
1674 stats->accelerate_bgn_samples =
1675 NetEqMainInst->DSPinst.activity_stats.accelerate_bgn_samples;
1676 stats->accelerate_normal_samples =
1677 NetEqMainInst->DSPinst.activity_stats.accelarate_normal_samples;
1678
1679 stats->expand_bgn_sampels =
1680 NetEqMainInst->DSPinst.activity_stats.expand_bgn_samples;
1681 stats->expand_normal_samples =
1682 NetEqMainInst->DSPinst.activity_stats.expand_normal_samples;
1683
1684 stats->preemptive_expand_bgn_samples =
1685 NetEqMainInst->DSPinst.activity_stats.preemptive_expand_bgn_samples;
1686 stats->preemptive_expand_normal_samples =
1687 NetEqMainInst->DSPinst.activity_stats.preemptive_expand_normal_samples;
1688
1689 stats->merge_expand_bgn_samples =
1690 NetEqMainInst->DSPinst.activity_stats.merge_expand_bgn_samples;
1691 stats->merge_expand_normal_samples =
1692 NetEqMainInst->DSPinst.activity_stats.merge_expand_normal_samples;
1693
1694 WebRtcNetEQ_ClearActivityStats(&NetEqMainInst->DSPinst);
1695}
turaj@webrtc.org28d54ab2013-04-22 18:53:35 +00001696
1697void WebRtcNetEQ_EnableAVSync(void* inst, int enable) {
1698 MainInst_t *NetEqMainInst = (MainInst_t*) inst;
1699 NetEqMainInst->MCUinst.av_sync = (enable != 0) ? 1 : 0;
1700}
1701
1702int WebRtcNetEQ_RecInSyncRTP(void* inst, WebRtcNetEQ_RTPInfo* rtp_info,
1703 uint32_t receive_timestamp) {
1704 MainInst_t *NetEqMainInst = (MainInst_t*) inst;
1705 if (NetEqMainInst->MCUinst.av_sync == 0)
1706 return -1;
1707 if (WebRtcNetEQ_RecInRTPStruct(inst, rtp_info, kSyncPayload,
1708 SYNC_PAYLOAD_LEN_BYTES,
1709 receive_timestamp) < 0) {
1710 return -1;
1711 }
1712 return SYNC_PAYLOAD_LEN_BYTES;
1713}
turaj@webrtc.orge46c8d32013-05-22 20:39:43 +00001714
1715int WebRtcNetEQ_GetRequiredDelayMs(const void* inst) {
1716 const MainInst_t* NetEqMainInst = (MainInst_t*)inst;
1717 const AutomodeInst_t* auto_mode = (NetEqMainInst == NULL) ? NULL :
1718 &NetEqMainInst->MCUinst.BufferStat_inst.Automode_inst;
1719
1720 /* Instance sanity */
1721 if (NetEqMainInst == NULL || auto_mode == NULL)
1722 return 0;
1723
1724 if (NetEqMainInst->MCUinst.fs == 0)
1725 return 0; // Sampling rate not initialized.
1726
1727 /* |required_delay_q8| has the unit of packets in Q8 domain, therefore,
1728 * the corresponding delay is
1729 * required_delay_ms = (1000 * required_delay_q8 * samples_per_packet /
1730 * sample_rate_hz) / 256;
1731 */
1732 return (auto_mode->required_delay_q8 *
1733 ((auto_mode->packetSpeechLenSamp * 1000) / NetEqMainInst->MCUinst.fs) +
1734 128) >> 8;
1735}
turaj@webrtc.orga305e962013-06-06 19:00:09 +00001736
1737int WebRtcNetEQ_DecodedRtpInfo(const void* inst,
1738 int* sequence_number,
1739 uint32_t* timestamp) {
1740 const MainInst_t *NetEqMainInst = (inst == NULL) ? NULL :
1741 (const MainInst_t*) inst;
1742 if (NetEqMainInst->MCUinst.decoded_packet_sequence_number < 0)
1743 return -1;
1744 *sequence_number = NetEqMainInst->MCUinst.decoded_packet_sequence_number;
1745 *timestamp = NetEqMainInst->MCUinst.decoded_packet_timestamp;
1746 return 0;
1747}