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