blob: fad690d08102c99a9eba3705d52cbe004d3cadcd [file] [log] [blame]
andrew@webrtc.orgb015cbe2012-10-22 18:19:231/*
2 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
3 *
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
18#include <assert.h>
19#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.orgfbda0fc2013-04-09 00:28:0633 (macroInstPtr)->ErrorCode = -((int16_t) (macroExpr)); \
andrew@webrtc.orgb015cbe2012-10-22 18:19:2334 } \
35 return(-1); \
36 } }
37
38int WebRtcNetEQ_strncpy(char *strDest, int numberOfElements,
39 const char *strSource, int count)
40{
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/*****************************************
59 * Error functions
60 */
61
62int WebRtcNetEQ_GetErrorCode(void *inst)
63{
64 MainInst_t *NetEqMainInst = (MainInst_t*) inst;
65 if (NetEqMainInst == NULL) return (-1);
66 return (NetEqMainInst->ErrorCode);
67}
68
69int WebRtcNetEQ_GetErrorName(int errorCode, char *errorName, int maxStrLen)
70{
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.orgfbda0fc2013-04-09 00:28:06283 *sizeinbytes = (sizeof(MainInst_t) * 2) / sizeof(int16_t);
andrew@webrtc.orgb015cbe2012-10-22 18:19:23284 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
294 WebRtcSpl_Init();
295
296 /* Clear memory */
pbos@webrtc.orgfbda0fc2013-04-09 00:28:06297 WebRtcSpl_MemSetW16((int16_t*) NetEqMainInst, 0,
298 (sizeof(MainInst_t) / sizeof(int16_t)));
andrew@webrtc.orgb015cbe2012-10-22 18:19:23299 ok = WebRtcNetEQ_McuReset(&NetEqMainInst->MCUinst);
300 if (ok != 0)
301 {
302 NetEqMainInst->ErrorCode = -ok;
303 return (-1);
304 }
305 return (0);
306}
307
308int WebRtcNetEQ_GetRecommendedBufferSize(void *inst, const enum WebRtcNetEQDecoder *codec,
309 int noOfCodecs, enum WebRtcNetEQNetworkType nwType,
turaj@webrtc.orgead8a5b2013-02-12 21:42:18310 int *MaxNoOfPackets, int *sizeinbytes,
311 int* per_packet_overhead_bytes)
andrew@webrtc.orgb015cbe2012-10-22 18:19:23312{
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.orgead8a5b2013-02-12 21:42:18319 ok = WebRtcNetEQ_GetDefaultCodecSettings(codec, noOfCodecs, sizeinbytes,
320 MaxNoOfPackets,
321 per_packet_overhead_bytes);
andrew@webrtc.orgb015cbe2012-10-22 18:19:23322 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.orgead8a5b2013-02-12 21:42:18345 multiplier = 12;
andrew@webrtc.orgb015cbe2012-10-22 18:19:23346 }
347 else
348 {
349 NetEqMainInst->ErrorCode = -FAULTY_NETWORK_TYPE;
350 return (-1);
351 }
352 *MaxNoOfPackets = (*MaxNoOfPackets) * multiplier;
353 *sizeinbytes = (*sizeinbytes) * multiplier;
354 return 0;
355}
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.orgfbda0fc2013-04-09 00:28:06364 MaxNoOfPackets, (int16_t*) NETEQ_Buffer_Addr, (sizeinbytes >> 1));
andrew@webrtc.orgb015cbe2012-10-22 18:19:23365 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.orgfbda0fc2013-04-09 00:28:06393int WebRtcNetEQ_Init(void *inst, uint16_t fs)
andrew@webrtc.orgb015cbe2012-10-22 18:19:23394{
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.orgd5577342013-05-22 20:39:43440 NetEqMainInst->MCUinst.BufferStat_inst.Automode_inst.minimum_delay_ms = 0;
pwestin@webrtc.org280c0b92013-08-06 21:01:36441 NetEqMainInst->MCUinst.BufferStat_inst.Automode_inst.maximum_delay_ms =
442 10000;
andrew@webrtc.orgb015cbe2012-10-22 18:19:23443 NetEqMainInst->MCUinst.NoOfExpandCalls = 0;
444 NetEqMainInst->MCUinst.fs = fs;
445
turaj@webrtc.org92aa25b2013-04-22 18:53:35446 /* Not in AV-sync by default. */
447 NetEqMainInst->MCUinst.av_sync = 0;
448
andrew@webrtc.orgb015cbe2012-10-22 18:19:23449#ifdef NETEQ_ATEVENT_DECODE
450 /* init DTMF decoder */
451 ok = WebRtcNetEQ_DtmfDecoderInit(&(NetEqMainInst->MCUinst.DTMF_inst),fs,560);
452 RETURN_ON_ERROR(ok, NetEqMainInst);
453#endif
454
455 /* init RTCP statistics */
456 WebRtcNetEQ_RTCPInit(&(NetEqMainInst->MCUinst.RTCP_inst), 0);
457
458 /* set BufferStat struct to zero */
pbos@webrtc.orgfbda0fc2013-04-09 00:28:06459 WebRtcSpl_MemSetW16((int16_t*) &(NetEqMainInst->MCUinst.BufferStat_inst), 0,
460 sizeof(BufstatsInst_t) / sizeof(int16_t));
andrew@webrtc.orgb015cbe2012-10-22 18:19:23461
462 /* reset automode */
463 WebRtcNetEQ_ResetAutomode(&(NetEqMainInst->MCUinst.BufferStat_inst.Automode_inst),
464 NetEqMainInst->MCUinst.PacketBuffer_inst.maxInsertPositions);
465
466 NetEqMainInst->ErrorCode = 0;
467
468#ifdef NETEQ_STEREO
469 /* set master/slave info to undecided */
470 NetEqMainInst->masterSlave = 0;
471#endif
472
turaj@webrtc.orgd0631e32013-06-06 19:00:09473 /* Set to an invalid value. */
474 NetEqMainInst->MCUinst.decoded_packet_sequence_number = -1;
475 NetEqMainInst->MCUinst.decoded_packet_timestamp = 0;
476
andrew@webrtc.orgb015cbe2012-10-22 18:19:23477 return (ok);
478}
479
480int WebRtcNetEQ_FlushBuffers(void *inst)
481{
482 int ok = 0;
483
484 /* Typecast inst to internal instance format */
485 MainInst_t *NetEqMainInst = (MainInst_t*) inst;
486
487 if (NetEqMainInst == NULL)
488 {
489 return (-1);
490 }
491
492 /* Flush packet buffer */
493 ok = WebRtcNetEQ_PacketBufferFlush(&NetEqMainInst->MCUinst.PacketBuffer_inst);
494 RETURN_ON_ERROR(ok, NetEqMainInst);
495
496 /* Set MCU to wait for new codec */
497 NetEqMainInst->MCUinst.first_packet = 1;
498
499 /* Flush speech buffer */
500 ok = WebRtcNetEQ_FlushSpeechBuffer(&NetEqMainInst->DSPinst);
501 RETURN_ON_ERROR(ok, NetEqMainInst);
502
503 return 0;
504}
505
506int WebRtcNetEQ_SetAVTPlayout(void *inst, int PlayoutAVTon)
507{
508 MainInst_t *NetEqMainInst = (MainInst_t*) inst;
509 if (NetEqMainInst == NULL) return (-1);
510#ifdef NETEQ_ATEVENT_DECODE
511 NetEqMainInst->MCUinst.AVT_PlayoutOn = PlayoutAVTon;
512 return(0);
513#else
514 if (PlayoutAVTon != 0)
515 {
516 NetEqMainInst->ErrorCode = -DTMF_NOT_SUPPORTED;
517 return (-1);
518 }
519 else
520 {
521 return (0);
522 }
523#endif
524}
525
pwestin@webrtc.org280c0b92013-08-06 21:01:36526int WebRtcNetEQ_SetExtraDelay(void *inst, int DelayInMs) {
527 MainInst_t *NetEqMainInst = (MainInst_t*) inst;
528 if (NetEqMainInst == NULL) return (-1);
529 if ((DelayInMs < 0) || (DelayInMs > 10000)) {
530 NetEqMainInst->ErrorCode = -FAULTY_DELAYVALUE;
531 return (-1);
532 }
533 NetEqMainInst->MCUinst.BufferStat_inst.Automode_inst.extraDelayMs = DelayInMs;
534 return (0);
andrew@webrtc.orgb015cbe2012-10-22 18:19:23535}
536
turaj@webrtc.orgd5577342013-05-22 20:39:43537int WebRtcNetEQ_SetMinimumDelay(void *inst, int minimum_delay_ms) {
538 MainInst_t *NetEqMainInst = (MainInst_t*) inst;
pwestin@webrtc.org280c0b92013-08-06 21:01:36539 if (NetEqMainInst == NULL) return -1;
turaj@webrtc.orgd5577342013-05-22 20:39:43540 if (minimum_delay_ms < 0 || minimum_delay_ms > 10000) {
pwestin@webrtc.org280c0b92013-08-06 21:01:36541 NetEqMainInst->ErrorCode = -FAULTY_DELAYVALUE;
542 return -1;
543 }
544 if ((NetEqMainInst->MCUinst.BufferStat_inst.Automode_inst.maximum_delay_ms >
545 0) && (minimum_delay_ms >
546 NetEqMainInst->MCUinst.BufferStat_inst.Automode_inst.maximum_delay_ms)) {
547 NetEqMainInst->ErrorCode = -FAULTY_DELAYVALUE;
548 return -1;
turaj@webrtc.orgd5577342013-05-22 20:39:43549 }
550 NetEqMainInst->MCUinst.BufferStat_inst.Automode_inst.minimum_delay_ms =
551 minimum_delay_ms;
552 return 0;
553}
554
pwestin@webrtc.org280c0b92013-08-06 21:01:36555int WebRtcNetEQ_SetMaximumDelay(void *inst, int maximum_delay_ms) {
556 MainInst_t *NetEqMainInst = (MainInst_t*) inst;
557 if (NetEqMainInst == NULL) return -1;
558 if (maximum_delay_ms < 0 || maximum_delay_ms > 10000) {
559 NetEqMainInst->ErrorCode = -FAULTY_DELAYVALUE;
560 return -1;
561 }
562 if (maximum_delay_ms <
563 NetEqMainInst->MCUinst.BufferStat_inst.Automode_inst.minimum_delay_ms) {
564 NetEqMainInst->ErrorCode = -FAULTY_DELAYVALUE;
565 return -1;
566 }
567 NetEqMainInst->MCUinst.BufferStat_inst.Automode_inst.maximum_delay_ms =
568 maximum_delay_ms;
569 return 0;
570}
571
andrew@webrtc.orgb015cbe2012-10-22 18:19:23572int WebRtcNetEQ_SetPlayoutMode(void *inst, enum WebRtcNetEQPlayoutMode playoutMode)
573{
574 MainInst_t *NetEqMainInst = (MainInst_t*) inst;
575 if (NetEqMainInst == NULL) return (-1);
576 if ((playoutMode != kPlayoutOn) && (playoutMode != kPlayoutOff) && (playoutMode
577 != kPlayoutFax) && (playoutMode != kPlayoutStreaming))
578 {
579 NetEqMainInst->ErrorCode = -FAULTY_PLAYOUTMODE;
580 return (-1);
581 }
582 else
583 {
584 NetEqMainInst->MCUinst.NetEqPlayoutMode = playoutMode;
585 return (0);
586 }
587}
588
589int WebRtcNetEQ_SetBGNMode(void *inst, enum WebRtcNetEQBGNMode bgnMode)
590{
591
592 MainInst_t *NetEqMainInst = (MainInst_t*) inst;
593
594 /* Instance sanity */
595 if (NetEqMainInst == NULL) return (-1);
596
597 /* Check for corrupt/cleared instance */
598 if (NetEqMainInst->MCUinst.main_inst != NetEqMainInst)
599 {
600 /* Instance is corrupt */
601 NetEqMainInst->ErrorCode = CORRUPT_INSTANCE;
602 return (-1);
603 }
604
605 NetEqMainInst->DSPinst.BGNInst.bgnMode = (enum BGNMode) bgnMode;
606
607 return (0);
608}
609
610int WebRtcNetEQ_GetBGNMode(const void *inst, enum WebRtcNetEQBGNMode *bgnMode)
611{
612
613 const MainInst_t *NetEqMainInst = (const MainInst_t*) inst;
614
615 /* Instance sanity */
616 if (NetEqMainInst == NULL) return (-1);
617
618 *bgnMode = (enum WebRtcNetEQBGNMode) NetEqMainInst->DSPinst.BGNInst.bgnMode;
619
620 return (0);
621}
622
623/************************************************
624 * CodecDB functions
625 */
626
627int WebRtcNetEQ_CodecDbReset(void *inst)
628{
629 int ok = 0;
630 MainInst_t *NetEqMainInst = (MainInst_t*) inst;
631 if (NetEqMainInst == NULL) return (-1);
632 ok = WebRtcNetEQ_DbReset(&NetEqMainInst->MCUinst.codec_DB_inst);
633 if (ok != 0)
634 {
635 NetEqMainInst->ErrorCode = -ok;
636 return (-1);
637 }
638
639 /* set function pointers to NULL to prevent RecOut from using the codec */
640 NetEqMainInst->DSPinst.codec_ptr_inst.funcDecode = NULL;
641 NetEqMainInst->DSPinst.codec_ptr_inst.funcDecodeRCU = NULL;
642 NetEqMainInst->DSPinst.codec_ptr_inst.funcAddLatePkt = NULL;
643 NetEqMainInst->DSPinst.codec_ptr_inst.funcDecode = NULL;
644 NetEqMainInst->DSPinst.codec_ptr_inst.funcDecodeInit = NULL;
645 NetEqMainInst->DSPinst.codec_ptr_inst.funcDecodePLC = NULL;
646 NetEqMainInst->DSPinst.codec_ptr_inst.funcGetMDinfo = NULL;
647 NetEqMainInst->DSPinst.codec_ptr_inst.funcUpdBWEst = NULL;
648 NetEqMainInst->DSPinst.codec_ptr_inst.funcGetErrorCode = NULL;
649
650 return (0);
651}
652
pbos@webrtc.orgfbda0fc2013-04-09 00:28:06653int WebRtcNetEQ_CodecDbGetSizeInfo(void *inst, int16_t *UsedEntries,
654 int16_t *MaxEntries)
andrew@webrtc.orgb015cbe2012-10-22 18:19:23655{
656 MainInst_t *NetEqMainInst = (MainInst_t*) inst;
657 if (NetEqMainInst == NULL) return (-1);
658 *MaxEntries = NUM_CODECS;
659 *UsedEntries = NetEqMainInst->MCUinst.codec_DB_inst.nrOfCodecs;
660 return (0);
661}
662
pbos@webrtc.orgfbda0fc2013-04-09 00:28:06663int WebRtcNetEQ_CodecDbGetCodecInfo(void *inst, int16_t Entry,
andrew@webrtc.orgb015cbe2012-10-22 18:19:23664 enum WebRtcNetEQDecoder *codec)
665{
666 int i;
667 MainInst_t *NetEqMainInst = (MainInst_t*) inst;
668 if (NetEqMainInst == NULL) return (-1);
669 *codec = (enum WebRtcNetEQDecoder) 0;
670 if ((Entry >= 0) && (Entry < NetEqMainInst->MCUinst.codec_DB_inst.nrOfCodecs))
671 {
672 for (i = 0; i < NUM_TOTAL_CODECS; i++)
673 {
674 if (NetEqMainInst->MCUinst.codec_DB_inst.position[i] == Entry)
675 {
676 *codec = (enum WebRtcNetEQDecoder) i;
677 }
678 }
679 }
680 else
681 {
682 NetEqMainInst->ErrorCode = -(CODEC_DB_NOT_EXIST1);
683 return (-1);
684 }
685 return (0);
686}
687
688int WebRtcNetEQ_CodecDbAdd(void *inst, WebRtcNetEQ_CodecDef *codecInst)
689{
690 int ok = 0;
691 MainInst_t *NetEqMainInst = (MainInst_t*) inst;
692 if (NetEqMainInst == NULL) return (-1);
693 ok = WebRtcNetEQ_DbAdd(&NetEqMainInst->MCUinst.codec_DB_inst, codecInst->codec,
694 codecInst->payloadType, codecInst->funcDecode, codecInst->funcDecodeRCU,
695 codecInst->funcDecodePLC, codecInst->funcDecodeInit, codecInst->funcAddLatePkt,
696 codecInst->funcGetMDinfo, codecInst->funcGetPitch, codecInst->funcUpdBWEst,
tina.legrand@webrtc.orgc05b5612012-11-19 08:02:55697 codecInst->funcDurationEst, codecInst->funcGetErrorCode,
698 codecInst->codec_state, codecInst->codec_fs);
andrew@webrtc.orgb015cbe2012-10-22 18:19:23699 if (ok != 0)
700 {
701 NetEqMainInst->ErrorCode = -ok;
702 return (-1);
703 }
704 return (ok);
705}
706
707int WebRtcNetEQ_CodecDbRemove(void *inst, enum WebRtcNetEQDecoder codec)
708{
709 int ok = 0;
710 MainInst_t *NetEqMainInst = (MainInst_t*) inst;
711 if (NetEqMainInst == NULL) return (-1);
712
713 /* check if currently used codec is being removed */
pbos@webrtc.orgfbda0fc2013-04-09 00:28:06714 if (NetEqMainInst->MCUinst.current_Codec == (int16_t) codec)
andrew@webrtc.orgb015cbe2012-10-22 18:19:23715 {
716 /* set function pointers to NULL to prevent RecOut from using the codec */
717 NetEqMainInst->DSPinst.codec_ptr_inst.funcDecode = NULL;
718 NetEqMainInst->DSPinst.codec_ptr_inst.funcDecodeRCU = NULL;
719 NetEqMainInst->DSPinst.codec_ptr_inst.funcAddLatePkt = NULL;
720 NetEqMainInst->DSPinst.codec_ptr_inst.funcDecode = NULL;
721 NetEqMainInst->DSPinst.codec_ptr_inst.funcDecodeInit = NULL;
722 NetEqMainInst->DSPinst.codec_ptr_inst.funcDecodePLC = NULL;
723 NetEqMainInst->DSPinst.codec_ptr_inst.funcGetMDinfo = NULL;
724 NetEqMainInst->DSPinst.codec_ptr_inst.funcUpdBWEst = NULL;
725 NetEqMainInst->DSPinst.codec_ptr_inst.funcGetErrorCode = NULL;
726 }
727
728 ok = WebRtcNetEQ_DbRemove(&NetEqMainInst->MCUinst.codec_DB_inst, codec);
729 if (ok != 0)
730 {
731 NetEqMainInst->ErrorCode = -ok;
732 return (-1);
733 }
734 return (ok);
735}
736
737/*********************************
738 * Real-time functions
739 */
740
pbos@webrtc.orgfbda0fc2013-04-09 00:28:06741int WebRtcNetEQ_RecIn(void *inst, int16_t *p_w16datagramstart, int16_t w16_RTPlen,
742 uint32_t uw32_timeRec)
andrew@webrtc.orgb015cbe2012-10-22 18:19:23743{
744 int ok = 0;
745 RTPPacket_t RTPpacket;
746 MainInst_t *NetEqMainInst = (MainInst_t*) inst;
747 if (NetEqMainInst == NULL) return (-1);
748
749 /* Check for corrupt/cleared instance */
750 if (NetEqMainInst->MCUinst.main_inst != NetEqMainInst)
751 {
752 /* Instance is corrupt */
753 NetEqMainInst->ErrorCode = CORRUPT_INSTANCE;
754 return (-1);
755 }
756
757 /* Parse RTP header */
758 ok = WebRtcNetEQ_RTPPayloadInfo(p_w16datagramstart, w16_RTPlen, &RTPpacket);
759 if (ok != 0)
760 {
761 NetEqMainInst->ErrorCode = -ok;
762 return (-1);
763 }
764
765 ok = WebRtcNetEQ_RecInInternal(&NetEqMainInst->MCUinst, &RTPpacket, uw32_timeRec);
766 if (ok != 0)
767 {
768 NetEqMainInst->ErrorCode = -ok;
769 return (-1);
770 }
771 return (ok);
772}
773
774/****************************************************************************
775 * WebRtcNetEQ_RecInRTPStruct(...)
776 *
777 * Alternative RecIn function, used when the RTP data has already been
778 * parsed into an RTP info struct (WebRtcNetEQ_RTPInfo).
779 *
780 * Input:
781 * - inst : NetEQ instance
782 * - rtpInfo : Pointer to RTP info
783 * - payloadPtr : Pointer to the RTP payload (first byte after header)
784 * - payloadLenBytes : Length (in bytes) of the payload in payloadPtr
785 * - timeRec : Receive time (in timestamps of the used codec)
786 *
787 * Return value : 0 - Ok
788 * -1 - Error
789 */
790int WebRtcNetEQ_RecInRTPStruct(void *inst, WebRtcNetEQ_RTPInfo *rtpInfo,
pbos@webrtc.orgfbda0fc2013-04-09 00:28:06791 const uint8_t *payloadPtr, int16_t payloadLenBytes,
792 uint32_t uw32_timeRec)
andrew@webrtc.orgb015cbe2012-10-22 18:19:23793{
794 int ok = 0;
795 RTPPacket_t RTPpacket;
796 MainInst_t *NetEqMainInst = (MainInst_t*) inst;
797 if (NetEqMainInst == NULL)
798 {
799 return (-1);
800 }
801
802 /* Check for corrupt/cleared instance */
803 if (NetEqMainInst->MCUinst.main_inst != NetEqMainInst)
804 {
805 /* Instance is corrupt */
806 NetEqMainInst->ErrorCode = CORRUPT_INSTANCE;
807 return (-1);
808 }
809
810 /* Load NetEQ's RTP struct from Module RTP struct */
811 RTPpacket.payloadType = rtpInfo->payloadType;
812 RTPpacket.seqNumber = rtpInfo->sequenceNumber;
813 RTPpacket.timeStamp = rtpInfo->timeStamp;
814 RTPpacket.ssrc = rtpInfo->SSRC;
pbos@webrtc.orgfbda0fc2013-04-09 00:28:06815 RTPpacket.payload = (const int16_t*) payloadPtr;
andrew@webrtc.orgb015cbe2012-10-22 18:19:23816 RTPpacket.payloadLen = payloadLenBytes;
817 RTPpacket.starts_byte1 = 0;
818
819 ok = WebRtcNetEQ_RecInInternal(&NetEqMainInst->MCUinst, &RTPpacket, uw32_timeRec);
820 if (ok != 0)
821 {
822 NetEqMainInst->ErrorCode = -ok;
823 return (-1);
824 }
825 return (ok);
826}
827
pbos@webrtc.orgfbda0fc2013-04-09 00:28:06828int WebRtcNetEQ_RecOut(void *inst, int16_t *pw16_outData, int16_t *pw16_len)
andrew@webrtc.orgb015cbe2012-10-22 18:19:23829{
830 int ok = 0;
831 MainInst_t *NetEqMainInst = (MainInst_t*) inst;
832#ifdef NETEQ_STEREO
833 MasterSlaveInfo msInfo;
834 msInfo.msMode = NETEQ_MONO;
835#endif
836
837 if (NetEqMainInst == NULL) return (-1);
838
839 /* Check for corrupt/cleared instance */
840 if (NetEqMainInst->DSPinst.main_inst != NetEqMainInst)
841 {
842 /* Instance is corrupt */
843 NetEqMainInst->ErrorCode = CORRUPT_INSTANCE;
844 return (-1);
845 }
846
847#ifdef NETEQ_STEREO
848 NetEqMainInst->DSPinst.msInfo = &msInfo;
849#endif
850
851 ok = WebRtcNetEQ_RecOutInternal(&NetEqMainInst->DSPinst, pw16_outData,
turaj@webrtc.org92aa25b2013-04-22 18:53:35852 pw16_len, 0 /* not BGN only */, NetEqMainInst->MCUinst.av_sync);
andrew@webrtc.orgb015cbe2012-10-22 18:19:23853 if (ok != 0)
854 {
855 NetEqMainInst->ErrorCode = -ok;
856 return (-1);
857 }
858 return (ok);
859}
860
861/****************************************************************************
862 * WebRtcNetEQ_RecOutMasterSlave(...)
863 *
864 * RecOut function for running several NetEQ instances in master/slave mode.
865 * One master can be used to control several slaves.
866 *
867 * Input:
868 * - inst : NetEQ instance
869 * - isMaster : Non-zero indicates that this is the master channel
870 * - msInfo : (slave only) Information from master
871 *
872 * Output:
873 * - inst : Updated NetEQ instance
874 * - pw16_outData : Pointer to vector where output should be written
875 * - pw16_len : Pointer to variable where output length is returned
876 * - msInfo : (master only) Information to slave(s)
877 *
878 * Return value : 0 - Ok
879 * -1 - Error
880 */
881
pbos@webrtc.orgfbda0fc2013-04-09 00:28:06882int WebRtcNetEQ_RecOutMasterSlave(void *inst, int16_t *pw16_outData,
883 int16_t *pw16_len, void *msInfo,
884 int16_t isMaster)
andrew@webrtc.orgb015cbe2012-10-22 18:19:23885{
886#ifndef NETEQ_STEREO
887 /* Stereo not supported */
888 return(-1);
889#else
890 int ok = 0;
891 MainInst_t *NetEqMainInst = (MainInst_t*) inst;
892
893 if (NetEqMainInst == NULL) return (-1);
894
895 /* Check for corrupt/cleared instance */
896 if (NetEqMainInst->DSPinst.main_inst != NetEqMainInst)
897 {
898 /* Instance is corrupt */
899 NetEqMainInst->ErrorCode = CORRUPT_INSTANCE;
900 return (-1);
901 }
902
903 if (msInfo == NULL)
904 {
905 /* msInfo not provided */
906 NetEqMainInst->ErrorCode = NETEQ_OTHER_ERROR;
907 return (-1);
908 }
909
910 /* translate from external to internal Master/Slave information */
911 NetEqMainInst->DSPinst.msInfo = (MasterSlaveInfo *) msInfo;
912
913 /* check that we have not done a master/slave switch without first re-initializing */
914 if ((NetEqMainInst->masterSlave == 1 && !isMaster) || /* switch from master to slave */
915 (NetEqMainInst->masterSlave == 2 && isMaster)) /* switch from slave to master */
916 {
917 NetEqMainInst->ErrorCode = ILLEGAL_MASTER_SLAVE_SWITCH;
918 return (-1);
919 }
920
921 if (!isMaster)
922 {
923 /* this is the slave */
924 NetEqMainInst->masterSlave = 2;
925 NetEqMainInst->DSPinst.msInfo->msMode = NETEQ_SLAVE;
926 }
927 else
928 {
929 NetEqMainInst->DSPinst.msInfo->msMode = NETEQ_MASTER;
930 }
931
932 ok = WebRtcNetEQ_RecOutInternal(&NetEqMainInst->DSPinst, pw16_outData,
turaj@webrtc.org92aa25b2013-04-22 18:53:35933 pw16_len, 0 /* not BGN only */, NetEqMainInst->MCUinst.av_sync);
andrew@webrtc.orgb015cbe2012-10-22 18:19:23934 if (ok != 0)
935 {
936 NetEqMainInst->ErrorCode = -ok;
937 return (-1);
938 }
939
940 if (isMaster)
941 {
942 /* this is the master */
943 NetEqMainInst->masterSlave = 1;
944 }
945
946 return (ok);
947#endif
948}
949
950int WebRtcNetEQ_GetMasterSlaveInfoSize()
951{
952#ifdef NETEQ_STEREO
953 return (sizeof(MasterSlaveInfo));
954#else
955 return(-1);
956#endif
957}
958
959/* Special RecOut that does not do any decoding. */
pbos@webrtc.orgfbda0fc2013-04-09 00:28:06960int WebRtcNetEQ_RecOutNoDecode(void *inst, int16_t *pw16_outData,
961 int16_t *pw16_len)
andrew@webrtc.orgb015cbe2012-10-22 18:19:23962{
963 int ok = 0;
964 MainInst_t *NetEqMainInst = (MainInst_t*) inst;
965#ifdef NETEQ_STEREO
966 MasterSlaveInfo msInfo;
967#endif
968
969 if (NetEqMainInst == NULL) return (-1);
970
971 /* Check for corrupt/cleared instance */
972 if (NetEqMainInst->DSPinst.main_inst != NetEqMainInst)
973 {
974 /* Instance is corrupt */
975 NetEqMainInst->ErrorCode = CORRUPT_INSTANCE;
976 return (-1);
977 }
978
979#ifdef NETEQ_STEREO
980 /* keep same mode as before */
981 switch (NetEqMainInst->masterSlave)
982 {
983 case 1:
984 {
985 msInfo.msMode = NETEQ_MASTER;
986 break;
987 }
988 case 2:
989 {
990 msInfo.msMode = NETEQ_SLAVE;
991 break;
992 }
993 default:
994 {
995 msInfo.msMode = NETEQ_MONO;
996 break;
997 }
998 }
999
1000 NetEqMainInst->DSPinst.msInfo = &msInfo;
1001#endif
1002
1003 ok = WebRtcNetEQ_RecOutInternal(&NetEqMainInst->DSPinst, pw16_outData,
turaj@webrtc.org92aa25b2013-04-22 18:53:351004 pw16_len, 1 /* BGN only */, NetEqMainInst->MCUinst.av_sync);
andrew@webrtc.orgb015cbe2012-10-22 18:19:231005 if (ok != 0)
1006 {
1007 NetEqMainInst->ErrorCode = -ok;
1008 return (-1);
1009 }
1010 return (ok);
1011}
1012
1013int WebRtcNetEQ_GetRTCPStats(void *inst, WebRtcNetEQ_RTCPStat *RTCP_inst)
1014{
1015 int ok = 0;
1016 MainInst_t *NetEqMainInst = (MainInst_t*) inst;
1017 if (NetEqMainInst == NULL) return (-1);
1018 ok = WebRtcNetEQ_RTCPGetStats(&NetEqMainInst->MCUinst.RTCP_inst,
1019 &RTCP_inst->fraction_lost, &RTCP_inst->cum_lost, &RTCP_inst->ext_max,
1020 &RTCP_inst->jitter, 0);
1021 if (ok != 0)
1022 {
1023 NetEqMainInst->ErrorCode = -ok;
1024 return (-1);
1025 }
1026 return (ok);
1027}
1028
1029int WebRtcNetEQ_GetRTCPStatsNoReset(void *inst, WebRtcNetEQ_RTCPStat *RTCP_inst)
1030{
1031 int ok = 0;
1032 MainInst_t *NetEqMainInst = (MainInst_t*) inst;
1033 if (NetEqMainInst == NULL) return (-1);
1034 ok = WebRtcNetEQ_RTCPGetStats(&NetEqMainInst->MCUinst.RTCP_inst,
1035 &RTCP_inst->fraction_lost, &RTCP_inst->cum_lost, &RTCP_inst->ext_max,
1036 &RTCP_inst->jitter, 1);
1037 if (ok != 0)
1038 {
1039 NetEqMainInst->ErrorCode = -ok;
1040 return (-1);
1041 }
1042 return (ok);
1043}
1044
pbos@webrtc.orgfbda0fc2013-04-09 00:28:061045int WebRtcNetEQ_GetSpeechTimeStamp(void *inst, uint32_t *timestamp)
andrew@webrtc.orgb015cbe2012-10-22 18:19:231046{
1047 MainInst_t *NetEqMainInst = (MainInst_t*) inst;
1048 if (NetEqMainInst == NULL) return (-1);
1049
1050 if (NetEqMainInst->MCUinst.TSscalingInitialized)
1051 {
1052 *timestamp = WebRtcNetEQ_ScaleTimestampInternalToExternal(&NetEqMainInst->MCUinst,
1053 NetEqMainInst->DSPinst.videoSyncTimestamp);
1054 }
1055 else
1056 {
1057 *timestamp = NetEqMainInst->DSPinst.videoSyncTimestamp;
1058 }
1059
1060 return (0);
1061}
1062
1063/****************************************************************************
1064 * WebRtcNetEQ_GetSpeechOutputType(...)
1065 *
1066 * Get the output type for the audio provided by the latest call to
1067 * WebRtcNetEQ_RecOut().
1068 *
1069 * kOutputNormal = normal audio (possibly processed)
1070 * kOutputPLC = loss concealment through stretching audio
1071 * kOutputCNG = comfort noise (codec-internal or RFC3389)
1072 * kOutputPLCtoCNG = background noise only due to long expand or error
1073 * kOutputVADPassive = PostDecode VAD signalling passive speaker
1074 *
1075 * Input:
1076 * - inst : NetEQ instance
1077 *
1078 * Output:
1079 * - outputType : Output type from enum list WebRtcNetEQOutputType
1080 *
1081 * Return value : 0 - Ok
1082 * -1 - Error
1083 */
1084
1085int WebRtcNetEQ_GetSpeechOutputType(void *inst, enum WebRtcNetEQOutputType *outputType)
1086{
1087 /* Typecast to internal instance type */
1088 MainInst_t *NetEqMainInst = (MainInst_t*) inst;
1089
1090 if (NetEqMainInst == NULL)
1091 {
1092 return (-1);
1093 }
1094
1095 if ((NetEqMainInst->DSPinst.w16_mode & MODE_BGN_ONLY) != 0)
1096 {
1097 /* If last mode was background noise only */
1098 *outputType = kOutputPLCtoCNG;
1099
1100 }
1101 else if ((NetEqMainInst->DSPinst.w16_mode == MODE_CODEC_INTERNAL_CNG)
1102 || (NetEqMainInst->DSPinst.w16_mode == MODE_RFC3389CNG))
1103 {
1104 /* If CN or internal CNG */
1105 *outputType = kOutputCNG;
1106
andrew@webrtc.orgb015cbe2012-10-22 18:19:231107 }
1108 else if ((NetEqMainInst->DSPinst.w16_mode == MODE_EXPAND)
1109 && (NetEqMainInst->DSPinst.ExpandInst.w16_expandMuteFactor == 0))
1110 {
1111 /* Expand mode has faded down to background noise only (very long expand) */
1112 *outputType = kOutputPLCtoCNG;
1113
1114 }
1115 else if (NetEqMainInst->DSPinst.w16_mode == MODE_EXPAND)
1116 {
1117 /* PLC mode */
1118 *outputType = kOutputPLC;
1119
wu@webrtc.org79d6daf2013-12-13 19:17:431120#ifdef NETEQ_VAD
1121 }
1122 else if ( NetEqMainInst->DSPinst.VADInst.VADDecision == 0 )
1123 {
1124 /* post-decode VAD says passive speaker */
1125 *outputType = kOutputVADPassive;
1126#endif /* NETEQ_VAD */
1127
andrew@webrtc.orgb015cbe2012-10-22 18:19:231128 }
1129 else
1130 {
1131 /* Normal speech output type (can still be manipulated, e.g., accelerated) */
1132 *outputType = kOutputNormal;
1133 }
1134
1135 return (0);
1136}
1137
1138/**********************************
1139 * Functions related to VQmon
1140 */
1141
1142#define WEBRTC_NETEQ_CONCEALMENTFLAG_LOST 0x01
1143#define WEBRTC_NETEQ_CONCEALMENTFLAG_DISCARDED 0x02
1144#define WEBRTC_NETEQ_CONCEALMENTFLAG_SUPRESS 0x04
1145#define WEBRTC_NETEQ_CONCEALMENTFLAG_CNGACTIVE 0x80
1146
pbos@webrtc.orgfbda0fc2013-04-09 00:28:061147int WebRtcNetEQ_VQmonRecOutStatistics(void *inst, uint16_t *validVoiceDurationMs,
1148 uint16_t *concealedVoiceDurationMs,
1149 uint8_t *concealedVoiceFlags)
andrew@webrtc.orgb015cbe2012-10-22 18:19:231150{
1151 MainInst_t *NetEqMainInst = (MainInst_t*) inst;
pbos@webrtc.orgfbda0fc2013-04-09 00:28:061152 int16_t fs_mult;
1153 int16_t ms_lost;
andrew@webrtc.orgb015cbe2012-10-22 18:19:231154 if (NetEqMainInst == NULL) return (-1);
1155 fs_mult = WebRtcSpl_DivW32W16ResW16(NetEqMainInst->MCUinst.fs, 8000);
1156
1157 ms_lost = WebRtcSpl_DivW32W16ResW16(
pbos@webrtc.orgfbda0fc2013-04-09 00:28:061158 (int32_t) NetEqMainInst->DSPinst.w16_concealedTS, (int16_t) (8 * fs_mult));
andrew@webrtc.orgb015cbe2012-10-22 18:19:231159 if (ms_lost > NetEqMainInst->DSPinst.millisecondsPerCall) ms_lost
1160 = NetEqMainInst->DSPinst.millisecondsPerCall;
1161
1162 *validVoiceDurationMs = NetEqMainInst->DSPinst.millisecondsPerCall - ms_lost;
1163 *concealedVoiceDurationMs = ms_lost;
1164 if (ms_lost > 0)
1165 {
1166 *concealedVoiceFlags = WEBRTC_NETEQ_CONCEALMENTFLAG_LOST;
1167 }
1168 else
1169 {
1170 *concealedVoiceFlags = 0;
1171 }
1172 NetEqMainInst->DSPinst.w16_concealedTS -= ms_lost * (8 * fs_mult);
1173
1174 return (0);
1175}
1176
pbos@webrtc.orgfbda0fc2013-04-09 00:28:061177int WebRtcNetEQ_VQmonGetConfiguration(void *inst, uint16_t *absMaxDelayMs,
1178 uint8_t *adaptationRate)
andrew@webrtc.orgb015cbe2012-10-22 18:19:231179{
1180 /* Dummy check the inst, just to avoid compiler warnings. */
1181 if (inst == NULL)
1182 {
1183 /* Do nothing. */
1184 }
1185
1186 /* Hardcoded variables that are used for VQmon as jitter buffer parameters */
1187 *absMaxDelayMs = 240;
1188 *adaptationRate = 1;
1189 return (0);
1190}
1191
pbos@webrtc.orgfbda0fc2013-04-09 00:28:061192int WebRtcNetEQ_VQmonGetRxStatistics(void *inst, uint16_t *avgDelayMs,
1193 uint16_t *maxDelayMs)
andrew@webrtc.orgb015cbe2012-10-22 18:19:231194{
1195 MainInst_t *NetEqMainInst = (MainInst_t*) inst;
1196 if (NetEqMainInst == NULL) return (-1);
pbos@webrtc.orgfbda0fc2013-04-09 00:28:061197 *avgDelayMs = (uint16_t) (NetEqMainInst->MCUinst.BufferStat_inst.avgDelayMsQ8 >> 8);
1198 *maxDelayMs = (uint16_t) NetEqMainInst->MCUinst.BufferStat_inst.maxDelayMs;
andrew@webrtc.orgb015cbe2012-10-22 18:19:231199 return (0);
1200}
1201
1202/*************************************
1203 * Statistics functions
1204 */
1205
1206/* Get the "in-call" statistics from NetEQ.
1207 * The statistics are reset after the query. */
1208int WebRtcNetEQ_GetNetworkStatistics(void *inst, WebRtcNetEQ_NetworkStatistics *stats)
1209
1210{
1211
pbos@webrtc.orgfbda0fc2013-04-09 00:28:061212 uint16_t tempU16;
1213 uint32_t tempU32, tempU32_2;
andrew@webrtc.orgb015cbe2012-10-22 18:19:231214 int numShift;
1215 MainInst_t *NetEqMainInst = (MainInst_t*) inst;
1216
1217 /* Instance sanity */
1218 if (NetEqMainInst == NULL) return (-1);
1219
roosa@google.com0049a762012-12-14 00:06:181220 stats->addedSamples = NetEqMainInst->DSPinst.statInst.addedSamples;
1221
andrew@webrtc.orgb015cbe2012-10-22 18:19:231222 /*******************/
1223 /* Get buffer size */
1224 /*******************/
1225
1226 if (NetEqMainInst->MCUinst.fs != 0)
1227 {
pbos@webrtc.orgfbda0fc2013-04-09 00:28:061228 int32_t temp32;
andrew@webrtc.orgb015cbe2012-10-22 18:19:231229 /* Query packet buffer for number of samples. */
1230 temp32 = WebRtcNetEQ_PacketBufferGetSize(
tina.legrand@webrtc.orgc05b5612012-11-19 08:02:551231 &NetEqMainInst->MCUinst.PacketBuffer_inst,
turaj@webrtc.org92aa25b2013-04-22 18:53:351232 &NetEqMainInst->MCUinst.codec_DB_inst,
1233 NetEqMainInst->MCUinst.av_sync);
andrew@webrtc.orgb015cbe2012-10-22 18:19:231234
1235 /* Divide by sample rate.
1236 * Calculate temp32 * 1000 / fs to get result in ms. */
pbos@webrtc.orgfbda0fc2013-04-09 00:28:061237 stats->currentBufferSize = (uint16_t)
andrew@webrtc.orgb015cbe2012-10-22 18:19:231238 WebRtcSpl_DivU32U16(temp32 * 1000, NetEqMainInst->MCUinst.fs);
1239
1240 /* Add number of samples yet to play in sync buffer. */
pbos@webrtc.orgfbda0fc2013-04-09 00:28:061241 temp32 = (int32_t) (NetEqMainInst->DSPinst.endPosition -
andrew@webrtc.orgb015cbe2012-10-22 18:19:231242 NetEqMainInst->DSPinst.curPosition);
pbos@webrtc.orgfbda0fc2013-04-09 00:28:061243 stats->currentBufferSize += (uint16_t)
andrew@webrtc.orgb015cbe2012-10-22 18:19:231244 WebRtcSpl_DivU32U16(temp32 * 1000, NetEqMainInst->MCUinst.fs);
1245 }
1246 else
1247 {
1248 /* Sample rate not initialized. */
1249 stats->currentBufferSize = 0;
1250 }
1251
1252 /***************************/
1253 /* Get optimal buffer size */
1254 /***************************/
1255
turaj@webrtc.orgd5577342013-05-22 20:39:431256 if (NetEqMainInst->MCUinst.fs != 0)
andrew@webrtc.orgb015cbe2012-10-22 18:19:231257 {
1258 /* preferredBufferSize = Bopt * packSizeSamples / (fs/1000) */
1259 stats->preferredBufferSize
pbos@webrtc.orgfbda0fc2013-04-09 00:28:061260 = (uint16_t) WEBRTC_SPL_MUL_16_16(
1261 (int16_t) ((NetEqMainInst->MCUinst.BufferStat_inst.Automode_inst.optBufLevel) >> 8), /* optimal buffer level in packets shifted to Q0 */
andrew@webrtc.orgb015cbe2012-10-22 18:19:231262 WebRtcSpl_DivW32W16ResW16(
pbos@webrtc.orgfbda0fc2013-04-09 00:28:061263 (int32_t) NetEqMainInst->MCUinst.BufferStat_inst.Automode_inst.packetSpeechLenSamp, /* samples per packet */
1264 WebRtcSpl_DivW32W16ResW16( (int32_t) NetEqMainInst->MCUinst.fs, (int16_t) 1000 ) /* samples per ms */
andrew@webrtc.orgb015cbe2012-10-22 18:19:231265 ) );
1266
1267 /* add extra delay */
1268 if (NetEqMainInst->MCUinst.BufferStat_inst.Automode_inst.extraDelayMs > 0)
1269 {
1270 stats->preferredBufferSize
1271 += NetEqMainInst->MCUinst.BufferStat_inst.Automode_inst.extraDelayMs;
1272 }
1273 }
1274 else
1275 {
1276 /* sample rate not initialized */
1277 stats->preferredBufferSize = 0;
1278 }
1279
1280 /***********************************/
1281 /* Check if jitter peaks are found */
1282 /***********************************/
1283
1284 stats->jitterPeaksFound =
1285 NetEqMainInst->MCUinst.BufferStat_inst.Automode_inst.peakFound;
1286
1287 /***********************/
1288 /* Calculate loss rate */
1289 /***********************/
1290
1291 /* timestamps elapsed since last report */
1292 tempU32 = NetEqMainInst->MCUinst.lastReportTS;
1293
1294 if (NetEqMainInst->MCUinst.lostTS == 0)
1295 {
1296 /* no losses */
1297 stats->currentPacketLossRate = 0;
1298 }
1299 else if (NetEqMainInst->MCUinst.lostTS < tempU32)
1300 {
1301 /* calculate shifts; we want the result in Q14 */
1302 numShift = WebRtcSpl_NormU32(NetEqMainInst->MCUinst.lostTS); /* numerator shift for normalize */
1303
1304 if (numShift < 14)
1305 {
1306 /* cannot shift numerator 14 steps; shift denominator too */
1307 tempU32 = WEBRTC_SPL_RSHIFT_U32(tempU32, 14-numShift); /* right-shift */
1308 }
1309 else
1310 {
1311 /* shift no more than 14 steps */
1312 numShift = 14;
1313 }
1314
1315 if (tempU32 == 0)
1316 {
1317 /* check for zero denominator; result should be zero in this case */
1318 stats->currentPacketLossRate = 0;
1319 }
1320 else
1321 {
1322 /* check that denominator fits in signed 16-bit */
1323 while (tempU32 > WEBRTC_SPL_WORD16_MAX)
1324 {
1325 tempU32 >>= 1; /* right-shift 1 step */
1326 numShift--; /* compensate in numerator */
1327 }
pbos@webrtc.orgfbda0fc2013-04-09 00:28:061328 tempU16 = (uint16_t) tempU32;
andrew@webrtc.orgb015cbe2012-10-22 18:19:231329
1330 /* do the shift of numerator */
1331 tempU32
pbos@webrtc.orgfbda0fc2013-04-09 00:28:061332 = WEBRTC_SPL_SHIFT_W32( (uint32_t) NetEqMainInst->MCUinst.lostTS, numShift);
andrew@webrtc.orgb015cbe2012-10-22 18:19:231333
pbos@webrtc.orgfbda0fc2013-04-09 00:28:061334 stats->currentPacketLossRate = (uint16_t) WebRtcSpl_DivU32U16(tempU32,
andrew@webrtc.orgb015cbe2012-10-22 18:19:231335 tempU16);
1336 }
1337 }
1338 else
1339 {
1340 /* lost count is larger than elapsed time count; probably timestamp wrap-around or something else wrong */
1341 /* set loss rate = 1 */
1342 stats->currentPacketLossRate = 1 << 14; /* 1 in Q14 */
1343 }
1344
1345 /**************************/
1346 /* Calculate discard rate */
1347 /**************************/
1348
1349 /* timestamps elapsed since last report */
1350 tempU32 = NetEqMainInst->MCUinst.lastReportTS;
1351
1352 /* number of discarded samples */
1353 tempU32_2
pbos@webrtc.orgfbda0fc2013-04-09 00:28:061354 = WEBRTC_SPL_MUL_16_U16( (int16_t) NetEqMainInst->MCUinst.PacketBuffer_inst.packSizeSamples,
andrew@webrtc.orgb015cbe2012-10-22 18:19:231355 NetEqMainInst->MCUinst.PacketBuffer_inst.discardedPackets);
1356
1357 if (tempU32_2 == 0)
1358 {
1359 /* no discarded samples */
1360 stats->currentDiscardRate = 0;
1361 }
1362 else if (tempU32_2 < tempU32)
1363 {
1364 /* calculate shifts; we want the result in Q14 */
1365 numShift = WebRtcSpl_NormU32(tempU32_2); /* numerator shift for normalize */
1366
1367 if (numShift < 14)
1368 {
1369 /* cannot shift numerator 14 steps; shift denominator too */
1370 tempU32 = WEBRTC_SPL_RSHIFT_U32(tempU32, 14-numShift); /* right-shift */
1371 }
1372 else
1373 {
1374 /* shift no more than 14 steps */
1375 numShift = 14;
1376 }
1377
1378 if (tempU32 == 0)
1379 {
1380 /* check for zero denominator; result should be zero in this case */
1381 stats->currentDiscardRate = 0;
1382 }
1383 else
1384 {
1385 /* check that denominator fits in signed 16-bit */
1386 while (tempU32 > WEBRTC_SPL_WORD16_MAX)
1387 {
1388 tempU32 >>= 1; /* right-shift 1 step */
1389 numShift--; /* compensate in numerator */
1390 }
pbos@webrtc.orgfbda0fc2013-04-09 00:28:061391 tempU16 = (uint16_t) tempU32;
andrew@webrtc.orgb015cbe2012-10-22 18:19:231392
1393 /* do the shift of numerator */
1394 tempU32 = WEBRTC_SPL_SHIFT_W32( tempU32_2, numShift);
1395
pbos@webrtc.orgfbda0fc2013-04-09 00:28:061396 stats->currentDiscardRate = (uint16_t) WebRtcSpl_DivU32U16(tempU32, tempU16);
andrew@webrtc.orgb015cbe2012-10-22 18:19:231397 }
1398 }
1399 else
1400 {
1401 /* lost count is larger than elapsed time count; probably timestamp wrap-around or something else wrong */
1402 /* set loss rate = 1 */
1403 stats->currentDiscardRate = 1 << 14; /* 1 in Q14 */
1404 }
1405
1406 /*************************************************************/
1407 /* Calculate Accelerate, Expand and Pre-emptive Expand rates */
1408 /*************************************************************/
1409
1410 /* timestamps elapsed since last report */
1411 tempU32 = NetEqMainInst->MCUinst.lastReportTS;
1412
1413 if (NetEqMainInst->DSPinst.statInst.accelerateLength == 0)
1414 {
1415 /* no accelerate */
1416 stats->currentAccelerateRate = 0;
1417 }
1418 else if (NetEqMainInst->DSPinst.statInst.accelerateLength < tempU32)
1419 {
1420 /* calculate shifts; we want the result in Q14 */
1421 numShift = WebRtcSpl_NormU32(NetEqMainInst->DSPinst.statInst.accelerateLength); /* numerator shift for normalize */
1422
1423 if (numShift < 14)
1424 {
1425 /* cannot shift numerator 14 steps; shift denominator too */
1426 tempU32 = WEBRTC_SPL_RSHIFT_U32(tempU32, 14-numShift); /* right-shift */
1427 }
1428 else
1429 {
1430 /* shift no more than 14 steps */
1431 numShift = 14;
1432 }
1433
1434 if (tempU32 == 0)
1435 {
1436 /* check for zero denominator; result should be zero in this case */
1437 stats->currentAccelerateRate = 0;
1438 }
1439 else
1440 {
1441 /* check that denominator fits in signed 16-bit */
1442 while (tempU32 > WEBRTC_SPL_WORD16_MAX)
1443 {
1444 tempU32 >>= 1; /* right-shift 1 step */
1445 numShift--; /* compensate in numerator */
1446 }
pbos@webrtc.orgfbda0fc2013-04-09 00:28:061447 tempU16 = (uint16_t) tempU32;
andrew@webrtc.orgb015cbe2012-10-22 18:19:231448
1449 /* do the shift of numerator */
1450 tempU32
1451 = WEBRTC_SPL_SHIFT_W32( NetEqMainInst->DSPinst.statInst.accelerateLength, numShift);
1452
pbos@webrtc.orgfbda0fc2013-04-09 00:28:061453 stats->currentAccelerateRate = (uint16_t) WebRtcSpl_DivU32U16(tempU32,
andrew@webrtc.orgb015cbe2012-10-22 18:19:231454 tempU16);
1455 }
1456 }
1457 else
1458 {
1459 /* lost count is larger than elapsed time count; probably timestamp wrap-around or something else wrong */
1460 /* set loss rate = 1 */
1461 stats->currentAccelerateRate = 1 << 14; /* 1 in Q14 */
1462 }
1463
1464 /* timestamps elapsed since last report */
1465 tempU32 = NetEqMainInst->MCUinst.lastReportTS;
1466
1467 if (NetEqMainInst->DSPinst.statInst.expandLength == 0)
1468 {
1469 /* no expand */
1470 stats->currentExpandRate = 0;
1471 }
1472 else if (NetEqMainInst->DSPinst.statInst.expandLength < tempU32)
1473 {
1474 /* calculate shifts; we want the result in Q14 */
1475 numShift = WebRtcSpl_NormU32(NetEqMainInst->DSPinst.statInst.expandLength); /* numerator shift for normalize */
1476
1477 if (numShift < 14)
1478 {
1479 /* cannot shift numerator 14 steps; shift denominator too */
1480 tempU32 = WEBRTC_SPL_RSHIFT_U32(tempU32, 14-numShift); /* right-shift */
1481 }
1482 else
1483 {
1484 /* shift no more than 14 steps */
1485 numShift = 14;
1486 }
1487
1488 if (tempU32 == 0)
1489 {
1490 /* check for zero denominator; result should be zero in this case */
1491 stats->currentExpandRate = 0;
1492 }
1493 else
1494 {
1495 /* check that denominator fits in signed 16-bit */
1496 while (tempU32 > WEBRTC_SPL_WORD16_MAX)
1497 {
1498 tempU32 >>= 1; /* right-shift 1 step */
1499 numShift--; /* compensate in numerator */
1500 }
pbos@webrtc.orgfbda0fc2013-04-09 00:28:061501 tempU16 = (uint16_t) tempU32;
andrew@webrtc.orgb015cbe2012-10-22 18:19:231502
1503 /* do the shift of numerator */
1504 tempU32
1505 = WEBRTC_SPL_SHIFT_W32( NetEqMainInst->DSPinst.statInst.expandLength, numShift);
1506
pbos@webrtc.orgfbda0fc2013-04-09 00:28:061507 stats->currentExpandRate = (uint16_t) WebRtcSpl_DivU32U16(tempU32, tempU16);
andrew@webrtc.orgb015cbe2012-10-22 18:19:231508 }
1509 }
1510 else
1511 {
1512 /* lost count is larger than elapsed time count; probably timestamp wrap-around or something else wrong */
1513 /* set loss rate = 1 */
1514 stats->currentExpandRate = 1 << 14; /* 1 in Q14 */
1515 }
1516
1517 /* timestamps elapsed since last report */
1518 tempU32 = NetEqMainInst->MCUinst.lastReportTS;
1519
1520 if (NetEqMainInst->DSPinst.statInst.preemptiveLength == 0)
1521 {
1522 /* no pre-emptive expand */
1523 stats->currentPreemptiveRate = 0;
1524 }
1525 else if (NetEqMainInst->DSPinst.statInst.preemptiveLength < tempU32)
1526 {
1527 /* calculate shifts; we want the result in Q14 */
1528 numShift = WebRtcSpl_NormU32(NetEqMainInst->DSPinst.statInst.preemptiveLength); /* numerator shift for normalize */
1529
1530 if (numShift < 14)
1531 {
1532 /* cannot shift numerator 14 steps; shift denominator too */
1533 tempU32 = WEBRTC_SPL_RSHIFT_U32(tempU32, 14-numShift); /* right-shift */
1534 }
1535 else
1536 {
1537 /* shift no more than 14 steps */
1538 numShift = 14;
1539 }
1540
1541 if (tempU32 == 0)
1542 {
1543 /* check for zero denominator; result should be zero in this case */
1544 stats->currentPreemptiveRate = 0;
1545 }
1546 else
1547 {
1548 /* check that denominator fits in signed 16-bit */
1549 while (tempU32 > WEBRTC_SPL_WORD16_MAX)
1550 {
1551 tempU32 >>= 1; /* right-shift 1 step */
1552 numShift--; /* compensate in numerator */
1553 }
pbos@webrtc.orgfbda0fc2013-04-09 00:28:061554 tempU16 = (uint16_t) tempU32;
andrew@webrtc.orgb015cbe2012-10-22 18:19:231555
1556 /* do the shift of numerator */
1557 tempU32
1558 = WEBRTC_SPL_SHIFT_W32( NetEqMainInst->DSPinst.statInst.preemptiveLength, numShift);
1559
pbos@webrtc.orgfbda0fc2013-04-09 00:28:061560 stats->currentPreemptiveRate = (uint16_t) WebRtcSpl_DivU32U16(tempU32,
andrew@webrtc.orgb015cbe2012-10-22 18:19:231561 tempU16);
1562 }
1563 }
1564 else
1565 {
1566 /* lost count is larger than elapsed time count; probably timestamp wrap-around or something else wrong */
1567 /* set loss rate = 1 */
1568 stats->currentPreemptiveRate = 1 << 14; /* 1 in Q14 */
1569 }
1570
1571 stats->clockDriftPPM = WebRtcNetEQ_AverageIAT(
1572 &NetEqMainInst->MCUinst.BufferStat_inst.Automode_inst);
1573
1574 /* reset counters */
1575 WebRtcNetEQ_ResetMcuInCallStats(&(NetEqMainInst->MCUinst));
1576 WebRtcNetEQ_ClearInCallStats(&(NetEqMainInst->DSPinst));
1577
1578 return (0);
1579}
1580
1581int WebRtcNetEQ_GetRawFrameWaitingTimes(void *inst,
1582 int max_length,
1583 int* waiting_times_ms) {
1584 int i = 0;
1585 MainInst_t *main_inst = (MainInst_t*) inst;
1586 if (main_inst == NULL) return -1;
1587
1588 while ((i < max_length) && (i < main_inst->MCUinst.len_waiting_times)) {
1589 waiting_times_ms[i] = main_inst->MCUinst.waiting_times[i] *
1590 main_inst->DSPinst.millisecondsPerCall;
1591 ++i;
1592 }
1593 assert(i <= kLenWaitingTimes);
1594 WebRtcNetEQ_ResetWaitingTimeStats(&main_inst->MCUinst);
1595 return i;
1596}
1597
1598/****************************************************************************
1599 * WebRtcNetEQ_SetVADInstance(...)
1600 *
1601 * Provide a pointer to an allocated VAD instance. If function is never
1602 * called or it is called with NULL pointer as VAD_inst, the post-decode
1603 * VAD functionality is disabled. Also provide pointers to init, setmode
1604 * and VAD functions. These are typically pointers to WebRtcVad_Init,
1605 * WebRtcVad_set_mode and WebRtcVad_Process, respectively, all found in the
1606 * interface file webrtc_vad.h.
1607 *
1608 * Input:
1609 * - NetEQ_inst : NetEQ instance
1610 * - VADinst : VAD instance
1611 * - initFunction : Pointer to VAD init function
1612 * - setmodeFunction : Pointer to VAD setmode function
1613 * - VADfunction : Pointer to VAD function
1614 *
1615 * Output:
1616 * - NetEQ_inst : Updated NetEQ instance
1617 *
1618 * Return value : 0 - Ok
1619 * -1 - Error
1620 */
1621
1622int WebRtcNetEQ_SetVADInstance(void *NetEQ_inst, void *VAD_inst,
1623 WebRtcNetEQ_VADInitFunction initFunction,
1624 WebRtcNetEQ_VADSetmodeFunction setmodeFunction,
1625 WebRtcNetEQ_VADFunction VADFunction)
1626{
1627
1628 /* Typecast to internal instance type */
1629 MainInst_t *NetEqMainInst = (MainInst_t*) NetEQ_inst;
1630 if (NetEqMainInst == NULL)
1631 {
1632 return (-1);
1633 }
1634
1635#ifdef NETEQ_VAD
1636
1637 /* Store pointer in PostDecode VAD struct */
1638 NetEqMainInst->DSPinst.VADInst.VADState = VAD_inst;
1639
1640 /* Store function pointers */
1641 NetEqMainInst->DSPinst.VADInst.initFunction = initFunction;
1642 NetEqMainInst->DSPinst.VADInst.setmodeFunction = setmodeFunction;
1643 NetEqMainInst->DSPinst.VADInst.VADFunction = VADFunction;
1644
1645 /* Call init function and return the result (ok or fail) */
1646 return(WebRtcNetEQ_InitVAD(&NetEqMainInst->DSPinst.VADInst, NetEqMainInst->DSPinst.fs));
1647
1648#else /* NETEQ_VAD not defined */
1649 return (-1);
1650#endif /* NETEQ_VAD */
1651
1652}
1653
1654/****************************************************************************
1655 * WebRtcNetEQ_SetVADMode(...)
1656 *
1657 * Pass an aggressiveness mode parameter to the post-decode VAD instance.
1658 * If this function is never called, mode 0 (quality mode) is used as default.
1659 *
1660 * Input:
1661 * - inst : NetEQ instance
1662 * - mode : mode parameter (same range as WebRtc VAD mode)
1663 *
1664 * Output:
1665 * - inst : Updated NetEQ instance
1666 *
1667 * Return value : 0 - Ok
1668 * -1 - Error
1669 */
1670
1671int WebRtcNetEQ_SetVADMode(void *inst, int mode)
1672{
1673
1674 /* Typecast to internal instance type */
1675 MainInst_t *NetEqMainInst = (MainInst_t*) inst;
1676 if (NetEqMainInst == NULL)
1677 {
1678 return (-1);
1679 }
1680
1681#ifdef NETEQ_VAD
1682
1683 /* Set mode and return result */
1684 return(WebRtcNetEQ_SetVADModeInternal(&NetEqMainInst->DSPinst.VADInst, mode));
1685
1686#else /* NETEQ_VAD not defined */
1687 return (-1);
1688#endif /* NETEQ_VAD */
1689
1690}
turaj@webrtc.org56e04842013-04-15 16:52:041691
1692void WebRtcNetEQ_GetProcessingActivity(void *inst,
1693 WebRtcNetEQ_ProcessingActivity *stats) {
1694 MainInst_t *NetEqMainInst = (MainInst_t*) inst;
1695
1696 stats->accelerate_bgn_samples =
1697 NetEqMainInst->DSPinst.activity_stats.accelerate_bgn_samples;
1698 stats->accelerate_normal_samples =
1699 NetEqMainInst->DSPinst.activity_stats.accelarate_normal_samples;
1700
1701 stats->expand_bgn_sampels =
1702 NetEqMainInst->DSPinst.activity_stats.expand_bgn_samples;
1703 stats->expand_normal_samples =
1704 NetEqMainInst->DSPinst.activity_stats.expand_normal_samples;
1705
1706 stats->preemptive_expand_bgn_samples =
1707 NetEqMainInst->DSPinst.activity_stats.preemptive_expand_bgn_samples;
1708 stats->preemptive_expand_normal_samples =
1709 NetEqMainInst->DSPinst.activity_stats.preemptive_expand_normal_samples;
1710
1711 stats->merge_expand_bgn_samples =
1712 NetEqMainInst->DSPinst.activity_stats.merge_expand_bgn_samples;
1713 stats->merge_expand_normal_samples =
1714 NetEqMainInst->DSPinst.activity_stats.merge_expand_normal_samples;
1715
1716 WebRtcNetEQ_ClearActivityStats(&NetEqMainInst->DSPinst);
1717}
turaj@webrtc.org92aa25b2013-04-22 18:53:351718
1719void WebRtcNetEQ_EnableAVSync(void* inst, int enable) {
1720 MainInst_t *NetEqMainInst = (MainInst_t*) inst;
1721 NetEqMainInst->MCUinst.av_sync = (enable != 0) ? 1 : 0;
1722}
1723
1724int WebRtcNetEQ_RecInSyncRTP(void* inst, WebRtcNetEQ_RTPInfo* rtp_info,
1725 uint32_t receive_timestamp) {
1726 MainInst_t *NetEqMainInst = (MainInst_t*) inst;
1727 if (NetEqMainInst->MCUinst.av_sync == 0)
1728 return -1;
1729 if (WebRtcNetEQ_RecInRTPStruct(inst, rtp_info, kSyncPayload,
1730 SYNC_PAYLOAD_LEN_BYTES,
1731 receive_timestamp) < 0) {
1732 return -1;
1733 }
1734 return SYNC_PAYLOAD_LEN_BYTES;
1735}
turaj@webrtc.orgd5577342013-05-22 20:39:431736
1737int WebRtcNetEQ_GetRequiredDelayMs(const void* inst) {
1738 const MainInst_t* NetEqMainInst = (MainInst_t*)inst;
1739 const AutomodeInst_t* auto_mode = (NetEqMainInst == NULL) ? NULL :
1740 &NetEqMainInst->MCUinst.BufferStat_inst.Automode_inst;
1741
1742 /* Instance sanity */
1743 if (NetEqMainInst == NULL || auto_mode == NULL)
1744 return 0;
1745
1746 if (NetEqMainInst->MCUinst.fs == 0)
1747 return 0; // Sampling rate not initialized.
1748
1749 /* |required_delay_q8| has the unit of packets in Q8 domain, therefore,
1750 * the corresponding delay is
1751 * required_delay_ms = (1000 * required_delay_q8 * samples_per_packet /
1752 * sample_rate_hz) / 256;
1753 */
1754 return (auto_mode->required_delay_q8 *
1755 ((auto_mode->packetSpeechLenSamp * 1000) / NetEqMainInst->MCUinst.fs) +
1756 128) >> 8;
1757}
turaj@webrtc.orgd0631e32013-06-06 19:00:091758
1759int WebRtcNetEQ_DecodedRtpInfo(const void* inst,
1760 int* sequence_number,
1761 uint32_t* timestamp) {
1762 const MainInst_t *NetEqMainInst = (inst == NULL) ? NULL :
1763 (const MainInst_t*) inst;
1764 if (NetEqMainInst->MCUinst.decoded_packet_sequence_number < 0)
1765 return -1;
1766 *sequence_number = NetEqMainInst->MCUinst.decoded_packet_sequence_number;
1767 *timestamp = NetEqMainInst->MCUinst.decoded_packet_timestamp;
1768 return 0;
1769}