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