blob: b28f39c3d0325b5672f560be4ef52c1a06b3458b [file] [log] [blame]
niklase@google.com470e71d2011-07-07 08:21:25 +00001/*
tina.legrand@webrtc.orgfaa0ab82012-04-18 17:59:53 +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 * Signal the MCU that data is available and ask for a RecOut decision.
13 */
14
15#include "mcu.h"
16
17#include <string.h>
18
19#include "signal_processing_library.h"
20
21#include "automode.h"
22#include "dtmf_buffer.h"
23#include "mcu_dsp_common.h"
24#include "neteq_error_codes.h"
25
26#ifdef NETEQ_DELAY_LOGGING
27#include "delay_logging.h"
28#include <stdio.h>
29
30extern FILE *delay_fid2; /* file pointer to delay log file */
31#endif
32
33
34/*
35 * Signals the MCU that DSP status data is available.
36 */
37int WebRtcNetEQ_SignalMcu(MCUInst_t *inst)
38{
39
40 int i_bufferpos, i_res;
41 WebRtc_UWord16 uw16_instr;
42 DSP2MCU_info_t dspInfo;
43 WebRtc_Word16 *blockPtr, blockLen;
44 WebRtc_UWord32 uw32_availableTS;
45 RTPPacket_t temp_pkt;
46 WebRtc_Word32 w32_bufsize, w32_tmp;
47 WebRtc_Word16 payloadType = -1;
48 WebRtc_Word16 wantedNoOfTimeStamps;
49 WebRtc_Word32 totalTS;
50 WebRtc_Word16 oldPT, latePacketExist = 0;
51 WebRtc_UWord32 oldTS, prevTS, uw32_tmp;
52 WebRtc_UWord16 prevSeqNo;
53 WebRtc_Word16 nextSeqNoAvail;
54 WebRtc_Word16 fs_mult, w16_tmp;
55 WebRtc_Word16 lastModeBGNonly = 0;
56#ifdef NETEQ_DELAY_LOGGING
57 int temp_var;
58#endif
59 int playDtmf = 0;
60
61 fs_mult = WebRtcSpl_DivW32W16ResW16(inst->fs, 8000);
62
63 /* Increment counter since last statistics report */
64 inst->lastReportTS += inst->timestampsPerCall;
65
henrik.lundin@webrtc.orgdbba1f92011-12-20 15:45:05 +000066 /* Increment waiting time for all packets. */
67 WebRtcNetEQ_IncrementWaitingTimes(&inst->PacketBuffer_inst);
68
niklase@google.com470e71d2011-07-07 08:21:25 +000069 /* Read info from DSP so we now current status */
70
71 WEBRTC_SPL_MEMCPY_W8(&dspInfo,inst->pw16_readAddress,sizeof(DSP2MCU_info_t));
72
73 /* Set blockPtr to first payload block */
74 blockPtr = &inst->pw16_writeAddress[3];
75
76 /* Clear instruction word and number of lost samples (2*WebRtc_Word16) */
77 inst->pw16_writeAddress[0] = 0;
78 inst->pw16_writeAddress[1] = 0;
79 inst->pw16_writeAddress[2] = 0;
80
81 if ((dspInfo.lastMode & MODE_AWAITING_CODEC_PTR) != 0)
82 {
83 /*
84 * Make sure state is adjusted so that a codec update is
85 * performed when first packet arrives.
86 */
87 if (inst->new_codec != 1)
88 {
89 inst->current_Codec = -1;
90 }
91 dspInfo.lastMode = (dspInfo.lastMode ^ MODE_AWAITING_CODEC_PTR);
92 }
93
94#ifdef NETEQ_STEREO
95 if ((dspInfo.lastMode & MODE_MASTER_DTMF_SIGNAL) != 0)
96 {
97 playDtmf = 1; /* force DTMF decision */
98 dspInfo.lastMode = (dspInfo.lastMode ^ MODE_MASTER_DTMF_SIGNAL);
99 }
100
101 if ((dspInfo.lastMode & MODE_USING_STEREO) != 0)
102 {
103 if (inst->usingStereo == 0)
104 {
105 /* stereo mode changed; reset automode instance to re-synchronize statistics */
106 WebRtcNetEQ_ResetAutomode(&(inst->BufferStat_inst.Automode_inst),
107 inst->PacketBuffer_inst.maxInsertPositions);
108 }
109 inst->usingStereo = 1;
110 dspInfo.lastMode = (dspInfo.lastMode ^ MODE_USING_STEREO);
111 }
112 else
113 {
114 inst->usingStereo = 0;
115 }
116#endif
117
118 /* detect if BGN_ONLY flag is set in lastMode */
119 if ((dspInfo.lastMode & MODE_BGN_ONLY) != 0)
120 {
121 lastModeBGNonly = 1; /* remember flag */
122 dspInfo.lastMode ^= MODE_BGN_ONLY; /* clear the flag */
123 }
124
125 if ((dspInfo.lastMode == MODE_RFC3389CNG) || (dspInfo.lastMode == MODE_CODEC_INTERNAL_CNG)
126 || (dspInfo.lastMode == MODE_EXPAND))
127 {
128 /*
129 * If last mode was CNG (or Expand, since this could be covering up for a lost CNG
130 * packet), increase the CNGplayedTS counter.
131 */
132 inst->BufferStat_inst.uw32_CNGplayedTS += inst->timestampsPerCall;
133
134 if (dspInfo.lastMode == MODE_RFC3389CNG)
135 {
136 /* remember that RFC3389CNG is on (needed if CNG is interrupted by DTMF) */
137 inst->BufferStat_inst.w16_cngOn = CNG_RFC3389_ON;
138 }
139 else if (dspInfo.lastMode == MODE_CODEC_INTERNAL_CNG)
140 {
141 /* remember that internal CNG is on (needed if CNG is interrupted by DTMF) */
142 inst->BufferStat_inst.w16_cngOn = CNG_INTERNAL_ON;
143 }
144
145 }
146
147 /* Update packet size from previously decoded packet */
148 if (dspInfo.frameLen > 0)
149 {
150 inst->PacketBuffer_inst.packSizeSamples = dspInfo.frameLen;
151 }
152
153 /* Look for late packet (unless codec has changed) */
154 if (inst->new_codec != 1)
155 {
156 if (WebRtcNetEQ_DbIsMDCodec((enum WebRtcNetEQDecoder) inst->current_Codec))
157 {
158 WebRtcNetEQ_PacketBufferFindLowestTimestamp(&inst->PacketBuffer_inst,
159 inst->timeStamp, &uw32_availableTS, &i_bufferpos, 1, &payloadType);
160 if ((inst->new_codec != 1) && (inst->timeStamp == uw32_availableTS)
161 && (inst->timeStamp < dspInfo.playedOutTS) && (i_bufferpos != -1)
162 && (WebRtcNetEQ_DbGetPayload(&(inst->codec_DB_inst),
163 (enum WebRtcNetEQDecoder) inst->current_Codec) == payloadType))
164 {
henrik.lundin@webrtc.orgdbba1f92011-12-20 15:45:05 +0000165 int waitingTime;
niklase@google.com470e71d2011-07-07 08:21:25 +0000166 temp_pkt.payload = blockPtr + 1;
167 i_res = WebRtcNetEQ_PacketBufferExtract(&inst->PacketBuffer_inst, &temp_pkt,
henrik.lundin@webrtc.orgdbba1f92011-12-20 15:45:05 +0000168 i_bufferpos, &waitingTime);
niklase@google.com470e71d2011-07-07 08:21:25 +0000169 if (i_res < 0)
170 { /* error returned */
171 return i_res;
172 }
henrik.lundin@webrtc.orgdbba1f92011-12-20 15:45:05 +0000173 WebRtcNetEQ_StoreWaitingTime(inst, waitingTime);
niklase@google.com470e71d2011-07-07 08:21:25 +0000174 *blockPtr = temp_pkt.payloadLen;
175 /* set the flag if this is a redundant payload */
176 if (temp_pkt.rcuPlCntr > 0)
177 {
178 *blockPtr = (*blockPtr) | (DSP_CODEC_RED_FLAG);
179 }
180 blockPtr += ((temp_pkt.payloadLen + 1) >> 1) + 1;
181
182 /*
183 * Close the data with a zero size block, in case we will not write any
184 * more data.
185 */
186 *blockPtr = 0;
187 inst->pw16_writeAddress[0] = (inst->pw16_writeAddress[0] & 0xf0ff)
188 | DSP_CODEC_ADD_LATE_PKT;
189 latePacketExist = 1;
190 }
191 }
192 }
193
194 i_res = WebRtcNetEQ_PacketBufferFindLowestTimestamp(&inst->PacketBuffer_inst,
195 dspInfo.playedOutTS, &uw32_availableTS, &i_bufferpos, (inst->new_codec == 0),
196 &payloadType);
197 if (i_res < 0)
198 { /* error returned */
199 return i_res;
200 }
201
202 if (inst->BufferStat_inst.w16_cngOn == CNG_RFC3389_ON)
203 {
204 /*
205 * Because of timestamp peculiarities, we have to "manually" disallow using a CNG
206 * packet with the same timestamp as the one that was last played. This can happen
207 * when using redundancy and will cause the timing to shift.
208 */
209 while (i_bufferpos != -1 && WebRtcNetEQ_DbIsCNGPayload(&inst->codec_DB_inst,
210 payloadType) && dspInfo.playedOutTS >= uw32_availableTS)
211 {
212
213 /* Don't use this packet, discard it */
214 inst->PacketBuffer_inst.payloadType[i_bufferpos] = -1;
215 inst->PacketBuffer_inst.payloadLengthBytes[i_bufferpos] = 0;
216 inst->PacketBuffer_inst.numPacketsInBuffer--;
217
218 /* Check buffer again */
219 WebRtcNetEQ_PacketBufferFindLowestTimestamp(&inst->PacketBuffer_inst,
220 dspInfo.playedOutTS, &uw32_availableTS, &i_bufferpos, (inst->new_codec == 0),
221 &payloadType);
222 }
223 }
224
225 /* Check packet buffer */
226 w32_bufsize = WebRtcNetEQ_PacketBufferGetSize(&inst->PacketBuffer_inst);
227
228 if (dspInfo.lastMode == MODE_SUCCESS_ACCELERATE || dspInfo.lastMode
229 == MODE_LOWEN_ACCELERATE || dspInfo.lastMode == MODE_SUCCESS_PREEMPTIVE
230 || dspInfo.lastMode == MODE_LOWEN_PREEMPTIVE)
231 {
232 /* Subtract (dspInfo.samplesLeft + inst->timestampsPerCall) from sampleMemory */
233 inst->BufferStat_inst.Automode_inst.sampleMemory -= dspInfo.samplesLeft
234 + inst->timestampsPerCall;
niklase@google.com470e71d2011-07-07 08:21:25 +0000235 }
236
237 /* calculate total current buffer size (in ms*8), including sync buffer */
238 w32_bufsize = WebRtcSpl_DivW32W16((w32_bufsize + dspInfo.samplesLeft), fs_mult);
239
niklase@google.com470e71d2011-07-07 08:21:25 +0000240#ifdef NETEQ_ATEVENT_DECODE
241 /* DTMF data will affect the decision */
242 if (WebRtcNetEQ_DtmfDecode(&inst->DTMF_inst, blockPtr + 1, blockPtr + 2,
243 dspInfo.playedOutTS + inst->BufferStat_inst.uw32_CNGplayedTS) > 0)
244 {
245 playDtmf = 1;
246
247 /* Flag DTMF payload */
248 inst->pw16_writeAddress[0] = inst->pw16_writeAddress[0] | DSP_DTMF_PAYLOAD;
249
250 /* Block Length in bytes */
251 blockPtr[0] = 4;
252 /* Advance to next payload position */
253 blockPtr += 3;
254 }
255#endif
256
257 /* Update statistics and make decision */
258 uw16_instr = WebRtcNetEQ_BufstatsDecision(&inst->BufferStat_inst,
259 inst->PacketBuffer_inst.packSizeSamples, w32_bufsize, dspInfo.playedOutTS,
260 uw32_availableTS, i_bufferpos == -1,
261 WebRtcNetEQ_DbIsCNGPayload(&inst->codec_DB_inst, payloadType), dspInfo.lastMode,
262 inst->NetEqPlayoutMode, inst->timestampsPerCall, inst->NoOfExpandCalls, fs_mult,
263 lastModeBGNonly, playDtmf);
264
265 /* Check if time to reset loss counter */
266 if (inst->lastReportTS > WEBRTC_SPL_UMUL(inst->fs, MAX_LOSS_REPORT_PERIOD))
267 {
268 /* reset loss counter */
269 WebRtcNetEQ_ResetMcuInCallStats(inst);
270 }
271
272 /* Check sync buffer size */
273 if ((dspInfo.samplesLeft >= inst->timestampsPerCall) && (uw16_instr
274 != BUFSTATS_DO_ACCELERATE) && (uw16_instr != BUFSTATS_DO_MERGE) && (uw16_instr
275 != BUFSTATS_DO_PREEMPTIVE_EXPAND))
276 {
277 *blockPtr = 0;
278 inst->pw16_writeAddress[0] = (inst->pw16_writeAddress[0] & 0x0fff) | DSP_INSTR_NORMAL;
279 return 0;
280 }
281
282 if (uw16_instr == BUFSTATS_DO_EXPAND)
283 {
284 inst->NoOfExpandCalls++;
285 }
286 else
287 {
niklase@google.com470e71d2011-07-07 08:21:25 +0000288 /* reset counter */
289 inst->NoOfExpandCalls = 0;
290 }
291
292 /* New codec or big change in packet number? */
tina.legrand@webrtc.orgfaa0ab82012-04-18 17:59:53 +0000293 if ((inst->new_codec) || (uw16_instr == BUFSTAT_REINIT))
niklase@google.com470e71d2011-07-07 08:21:25 +0000294 {
295 CodecFuncInst_t cinst;
296
297 /* Clear other instructions */
298 blockPtr = &inst->pw16_writeAddress[3];
299 /* Clear instruction word */
300 inst->pw16_writeAddress[0] = 0;
301
302 inst->timeStamp = uw32_availableTS;
303 dspInfo.playedOutTS = uw32_availableTS;
304 if (inst->current_Codec != -1)
305 {
306 i_res = WebRtcNetEQ_DbGetPtrs(&inst->codec_DB_inst,
307 (enum WebRtcNetEQDecoder) inst->current_Codec, &cinst);
308 if (i_res < 0)
309 { /* error returned */
310 return i_res;
311 }
312 }
313 else
314 {
315 /* The main codec has not been initialized yet (first packets are DTMF or CNG). */
316 if (WebRtcNetEQ_DbIsCNGPayload(&inst->codec_DB_inst, payloadType))
317 {
318 /* The currently extracted packet is CNG; get CNG fs */
319 WebRtc_UWord16 tempFs;
320
321 tempFs = WebRtcNetEQ_DbGetSampleRate(&inst->codec_DB_inst, payloadType);
322 if (tempFs > 0)
323 {
324 inst->fs = tempFs;
325 }
326 }
327 WebRtcSpl_MemSetW16((WebRtc_Word16*) &cinst, 0,
328 sizeof(CodecFuncInst_t) / sizeof(WebRtc_Word16));
329 cinst.codec_fs = inst->fs;
330 }
331 cinst.timeStamp = inst->timeStamp;
332 blockLen = (sizeof(CodecFuncInst_t)) >> (sizeof(WebRtc_Word16) - 1); /* in Word16 */
333 *blockPtr = blockLen * 2;
334 blockPtr++;
335 WEBRTC_SPL_MEMCPY_W8(blockPtr,&cinst,sizeof(CodecFuncInst_t));
336 blockPtr += blockLen;
337 inst->new_codec = 0;
338
339 /* Reinitialize the MCU fs */
340 i_res = WebRtcNetEQ_McuSetFs(inst, cinst.codec_fs);
341 if (i_res < 0)
342 { /* error returned */
343 return i_res;
344 }
345
346 /* Set the packet size by guessing */
347 inst->PacketBuffer_inst.packSizeSamples = inst->timestampsPerCall * 3;
348
349 WebRtcNetEQ_ResetAutomode(&(inst->BufferStat_inst.Automode_inst),
350 inst->PacketBuffer_inst.maxInsertPositions);
351
352#ifdef NETEQ_CNG_CODEC
353 /* Also insert CNG state as this might be needed by DSP */
354 i_res = WebRtcNetEQ_DbGetPtrs(&inst->codec_DB_inst, kDecoderCNG, &cinst);
355 if ((i_res < 0) && (i_res != CODEC_DB_NOT_EXIST1))
356 {
357 /* other error returned */
358 /* (CODEC_DB_NOT_EXIST1 simply indicates that CNG is not used */
359 return i_res;
360 }
361 else
362 {
363 /* CNG exists */
364 blockLen = (sizeof(cinst.codec_state)) >> (sizeof(WebRtc_Word16) - 1);
365 *blockPtr = blockLen * 2;
366 blockPtr++;
367 WEBRTC_SPL_MEMCPY_W8(blockPtr,&cinst.codec_state,sizeof(cinst.codec_state));
368 blockPtr += blockLen;
369 }
370#endif
371
372 inst->pw16_writeAddress[0] = (inst->pw16_writeAddress[0] & 0xf0ff)
373 | DSP_CODEC_NEW_CODEC;
374
375 if (uw16_instr == BUFSTATS_DO_RFC3389CNG_NOPACKET)
376 {
377 /*
378 * Change decision to CNG packet, since we do have a CNG packet, but it was
379 * considered too early to use. Now, use it anyway.
380 */
381 uw16_instr = BUFSTATS_DO_RFC3389CNG_PACKET;
382 }
383 else if (uw16_instr != BUFSTATS_DO_RFC3389CNG_PACKET)
384 {
385 uw16_instr = BUFSTATS_DO_NORMAL;
386 }
387
388 /* reset loss counter */
389 WebRtcNetEQ_ResetMcuInCallStats(inst);
390 }
391
392 /* Should we just reset the decoder? */
393 if (uw16_instr == BUFSTAT_REINIT_DECODER)
394 {
395 /* Change decision to normal and flag decoder reset */
396 uw16_instr = BUFSTATS_DO_NORMAL;
397 inst->pw16_writeAddress[0] = (inst->pw16_writeAddress[0] & 0xf0ff) | DSP_CODEC_RESET;
398 }
399
400 /* Expand requires no new packet */
401 if (uw16_instr == BUFSTATS_DO_EXPAND)
402 {
403
404 inst->timeStamp = dspInfo.playedOutTS;
405
406 /* Have we got one descriptor left? */
407 if (WebRtcNetEQ_DbIsMDCodec((enum WebRtcNetEQDecoder) inst->current_Codec)
408 && (dspInfo.MD || latePacketExist))
409 {
410
411 if (dspInfo.lastMode != MODE_ONE_DESCRIPTOR)
412 {
413 /* this is the first "consecutive" one-descriptor decoding; reset counter */
414 inst->one_desc = 0;
415 }
416 if (inst->one_desc < MAX_ONE_DESC)
417 {
418 /* use that one descriptor */
419 inst->one_desc++; /* increase counter */
420 inst->pw16_writeAddress[0] = (inst->pw16_writeAddress[0] & 0x0fff)
421 | DSP_INSTR_NORMAL_ONE_DESC;
422
423 /* decrease counter since we did no Expand */
424 inst->NoOfExpandCalls = WEBRTC_SPL_MAX(inst->NoOfExpandCalls - 1, 0);
425 return 0;
426 }
427 else
428 {
429 /* too many consecutive one-descriptor decodings; do expand instead */
430 inst->one_desc = 0; /* reset counter */
431 }
432
433 }
434
435 inst->pw16_writeAddress[0] = (inst->pw16_writeAddress[0] & 0x0fff) | DSP_INSTR_EXPAND;
436 return 0;
437 }
438
439 /* Merge is not needed if we still have a descriptor */
440 if ((uw16_instr == BUFSTATS_DO_MERGE) && (dspInfo.MD != 0))
441 {
442 inst->pw16_writeAddress[0] = (inst->pw16_writeAddress[0] & 0x0fff)
443 | DSP_INSTR_NORMAL_ONE_DESC;
444 *blockPtr = 0;
445 return 0;
446 }
447
448 /* Do CNG without trying to extract any packets from buffer */
449 if (uw16_instr == BUFSTATS_DO_RFC3389CNG_NOPACKET)
450 {
451 inst->pw16_writeAddress[0] = (inst->pw16_writeAddress[0] & 0x0fff)
452 | DSP_INSTR_DO_RFC3389CNG;
453 *blockPtr = 0;
454 return 0;
455 }
456
457 /* Do built-in CNG without extracting any new packets from buffer */
458 if (uw16_instr == BUFSTATS_DO_INTERNAL_CNG_NOPACKET)
459 {
460 inst->pw16_writeAddress[0] = (inst->pw16_writeAddress[0] & 0x0fff)
461 | DSP_INSTR_DO_CODEC_INTERNAL_CNG;
462 *blockPtr = 0;
463 return 0;
464 }
465
466 /* Do DTMF without extracting any new packets from buffer */
467 if (uw16_instr == BUFSTATS_DO_DTMF_ONLY)
468 {
469 WebRtc_UWord32 timeStampJump = 0;
470
471 /* Update timestamp */
472 if ((inst->BufferStat_inst.uw32_CNGplayedTS > 0) && (dspInfo.lastMode != MODE_DTMF))
473 {
474 /* Jump in timestamps if needed */
475 timeStampJump = inst->BufferStat_inst.uw32_CNGplayedTS;
476 inst->pw16_writeAddress[1] = (WebRtc_UWord16) (timeStampJump >> 16);
477 inst->pw16_writeAddress[2] = (WebRtc_UWord16) (timeStampJump & 0xFFFF);
478 }
479
480 inst->timeStamp = dspInfo.playedOutTS + timeStampJump;
481
niklase@google.com470e71d2011-07-07 08:21:25 +0000482 inst->BufferStat_inst.uw32_CNGplayedTS = 0;
483 inst->NoOfExpandCalls = 0;
484
485 inst->pw16_writeAddress[0] = (inst->pw16_writeAddress[0] & 0x0fff)
486 | DSP_INSTR_DTMF_GENERATE;
487 *blockPtr = 0;
488 return 0;
489 }
490
491 if (uw16_instr == BUFSTATS_DO_ACCELERATE)
492 {
493 /* In order to do a Accelerate we need at least 30 ms of data */
494 if (dspInfo.samplesLeft >= (3 * 80 * fs_mult))
495 {
496 /* Already have enough data, so we do not need to extract any more */
497 inst->pw16_writeAddress[0] = (inst->pw16_writeAddress[0] & 0x0fff)
498 | DSP_INSTR_ACCELERATE;
499 *blockPtr = 0;
500 inst->BufferStat_inst.Automode_inst.sampleMemory
501 = (WebRtc_Word32) dspInfo.samplesLeft;
502 inst->BufferStat_inst.Automode_inst.prevTimeScale = 1;
503 return 0;
504 }
505 else if ((dspInfo.samplesLeft >= (1 * 80 * fs_mult))
506 && (inst->PacketBuffer_inst.packSizeSamples >= (240 * fs_mult)))
507 {
508 /* Avoid decoding more data as it might overflow playout buffer */
509 inst->pw16_writeAddress[0] = (inst->pw16_writeAddress[0] & 0x0fff)
510 | DSP_INSTR_NORMAL;
511 *blockPtr = 0;
512 return 0;
513 }
514 else if ((dspInfo.samplesLeft < (1 * 80 * fs_mult))
515 && (inst->PacketBuffer_inst.packSizeSamples >= (240 * fs_mult)))
516 {
517 /* For >= 30ms allow Accelerate with a decoding to avoid overflow in playout buffer */
518 wantedNoOfTimeStamps = inst->timestampsPerCall;
519 }
520 else if (dspInfo.samplesLeft >= (2 * 80 * fs_mult))
521 {
522 /* We need to decode another 10 ms in order to do an Accelerate */
523 wantedNoOfTimeStamps = inst->timestampsPerCall;
524 }
525 else
526 {
527 /*
528 * Build up decoded data by decoding at least 20 ms of data.
529 * Do not perform Accelerate yet, but wait until we only need to do one decoding.
530 */
531 wantedNoOfTimeStamps = 2 * inst->timestampsPerCall;
532 uw16_instr = BUFSTATS_DO_NORMAL;
533 }
534 }
535 else if (uw16_instr == BUFSTATS_DO_PREEMPTIVE_EXPAND)
536 {
537 /* In order to do a Preemptive Expand we need at least 30 ms of data */
538 if (dspInfo.samplesLeft >= (3 * 80 * fs_mult))
539 {
540 /* Already have enough data, so we do not need to extract any more */
541 inst->pw16_writeAddress[0] = (inst->pw16_writeAddress[0] & 0x0fff)
542 | DSP_INSTR_PREEMPTIVE_EXPAND;
543 *blockPtr = 0;
544 inst->BufferStat_inst.Automode_inst.sampleMemory
545 = (WebRtc_Word32) dspInfo.samplesLeft;
546 inst->BufferStat_inst.Automode_inst.prevTimeScale = 1;
547 return 0;
548 }
549 else if ((dspInfo.samplesLeft >= (1 * 80 * fs_mult))
550 && (inst->PacketBuffer_inst.packSizeSamples >= (240 * fs_mult)))
551 {
552 /*
553 * Avoid decoding more data as it might overflow playout buffer;
554 * still try Preemptive Expand though.
555 */
556 inst->pw16_writeAddress[0] = (inst->pw16_writeAddress[0] & 0x0fff)
557 | DSP_INSTR_PREEMPTIVE_EXPAND;
558 *blockPtr = 0;
559 inst->BufferStat_inst.Automode_inst.sampleMemory
560 = (WebRtc_Word32) dspInfo.samplesLeft;
561 inst->BufferStat_inst.Automode_inst.prevTimeScale = 1;
562 return 0;
563 }
564 else if ((dspInfo.samplesLeft < (1 * 80 * fs_mult))
565 && (inst->PacketBuffer_inst.packSizeSamples >= (240 * fs_mult)))
566 {
567 /*
568 * For >= 30ms allow Preemptive Expand with a decoding to avoid overflow in
569 * playout buffer
570 */
571 wantedNoOfTimeStamps = inst->timestampsPerCall;
572 }
573 else if (dspInfo.samplesLeft >= (2 * 80 * fs_mult))
574 {
575 /* We need to decode another 10 ms in order to do an Preemptive Expand */
576 wantedNoOfTimeStamps = inst->timestampsPerCall;
577 }
578 else
579 {
580 /*
581 * Build up decoded data by decoding at least 20 ms of data,
582 * Still try to perform Preemptive Expand.
583 */
584 wantedNoOfTimeStamps = 2 * inst->timestampsPerCall;
585 }
586 }
587 else
588 {
589 wantedNoOfTimeStamps = inst->timestampsPerCall;
590 }
591
592 /* Otherwise get data from buffer, try to get at least 10ms */
593 totalTS = 0;
594 oldTS = uw32_availableTS;
595 if ((i_bufferpos > -1) && (uw16_instr != BUFSTATS_DO_ALTERNATIVE_PLC) && (uw16_instr
596 != BUFSTATS_DO_ALTERNATIVE_PLC_INC_TS) && (uw16_instr != BUFSTATS_DO_AUDIO_REPETITION)
597 && (uw16_instr != BUFSTATS_DO_AUDIO_REPETITION_INC_TS))
598 {
599 uw32_tmp = (uw32_availableTS - dspInfo.playedOutTS);
600 inst->pw16_writeAddress[1] = (WebRtc_UWord16) (uw32_tmp >> 16);
601 inst->pw16_writeAddress[2] = (WebRtc_UWord16) (uw32_tmp & 0xFFFF);
602 if (inst->BufferStat_inst.w16_cngOn == CNG_OFF)
603 {
604 /*
605 * Adjustment of TS only corresponds to an actual packet loss
606 * if comfort noise is not played. If comfort noise was just played,
607 * this adjustment of TS is only done to get back in sync with the
608 * stream TS; no loss to report.
609 */
610 inst->lostTS += uw32_tmp;
611 }
612
613 if (uw16_instr != BUFSTATS_DO_RFC3389CNG_PACKET)
614 {
615 /* We are about to decode and use a non-CNG packet => CNG period is ended */
616 inst->BufferStat_inst.w16_cngOn = CNG_OFF;
617 }
618
niklase@google.com470e71d2011-07-07 08:21:25 +0000619 /*
620 * Reset CNG timestamp as a new packet will be delivered.
621 * (Also if CNG packet, since playedOutTS is updated.)
622 */
623 inst->BufferStat_inst.uw32_CNGplayedTS = 0;
624
625 prevSeqNo = inst->PacketBuffer_inst.seqNumber[i_bufferpos];
626 prevTS = inst->PacketBuffer_inst.timeStamp[i_bufferpos];
627 oldPT = inst->PacketBuffer_inst.payloadType[i_bufferpos];
628
629 /* clear flag bits */
630 inst->pw16_writeAddress[0] = inst->pw16_writeAddress[0] & 0xFF3F;
631 do
632 {
henrik.lundin@webrtc.orgdbba1f92011-12-20 15:45:05 +0000633 int waitingTime;
niklase@google.com470e71d2011-07-07 08:21:25 +0000634 inst->timeStamp = uw32_availableTS;
635 /* Write directly to shared memory */
636 temp_pkt.payload = blockPtr + 1;
637 i_res = WebRtcNetEQ_PacketBufferExtract(&inst->PacketBuffer_inst, &temp_pkt,
henrik.lundin@webrtc.orgdbba1f92011-12-20 15:45:05 +0000638 i_bufferpos, &waitingTime);
niklase@google.com470e71d2011-07-07 08:21:25 +0000639
640 if (i_res < 0)
641 {
642 /* error returned */
643 return i_res;
644 }
henrik.lundin@webrtc.orgdbba1f92011-12-20 15:45:05 +0000645 WebRtcNetEQ_StoreWaitingTime(inst, waitingTime);
niklase@google.com470e71d2011-07-07 08:21:25 +0000646
647#ifdef NETEQ_DELAY_LOGGING
648 temp_var = NETEQ_DELAY_LOGGING_SIGNAL_DECODE;
leozwang@webrtc.org354b0ed2012-06-01 17:46:21 +0000649 if ((fwrite(&temp_var, sizeof(int),
650 1, delay_fid2) != 1) ||
651 (fwrite(&temp_pkt.timeStamp, sizeof(WebRtc_UWord32),
652 1, delay_fid2) != 1) ||
653 (fwrite(&dspInfo.samplesLeft, sizeof(WebRtc_UWord16),
654 1, delay_fid2) != 1)) {
655 return -1;
656 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000657#endif
658
659 *blockPtr = temp_pkt.payloadLen;
660 /* set the flag if this is a redundant payload */
661 if (temp_pkt.rcuPlCntr > 0)
662 {
663 *blockPtr = (*blockPtr) | (DSP_CODEC_RED_FLAG);
664 }
665 blockPtr += ((temp_pkt.payloadLen + 1) >> 1) + 1;
666
667 if (i_bufferpos > -1)
668 {
669 /*
670 * Store number of TS extracted (last extracted is assumed to be of
671 * packSizeSamples).
672 */
673 totalTS = uw32_availableTS - oldTS + inst->PacketBuffer_inst.packSizeSamples;
674 }
675 /* Check what next packet is available */
676 WebRtcNetEQ_PacketBufferFindLowestTimestamp(&inst->PacketBuffer_inst,
677 inst->timeStamp, &uw32_availableTS, &i_bufferpos, 0, &payloadType);
678
679 nextSeqNoAvail = 0;
680 if ((i_bufferpos > -1) && (oldPT
681 == inst->PacketBuffer_inst.payloadType[i_bufferpos]))
682 {
683 w16_tmp = inst->PacketBuffer_inst.seqNumber[i_bufferpos] - prevSeqNo;
684 w32_tmp = inst->PacketBuffer_inst.timeStamp[i_bufferpos] - prevTS;
685 if ((w16_tmp == 1) || /* Next packet */
686 ((w16_tmp == 0) && (w32_tmp == inst->PacketBuffer_inst.packSizeSamples)))
687 { /* or packet split into frames */
688 nextSeqNoAvail = 1;
689 }
690 prevSeqNo = inst->PacketBuffer_inst.seqNumber[i_bufferpos];
691 }
692
693 }
694 while ((totalTS < wantedNoOfTimeStamps) && (nextSeqNoAvail == 1));
695 }
696
697 if ((uw16_instr == BUFSTATS_DO_ACCELERATE)
698 || (uw16_instr == BUFSTATS_DO_PREEMPTIVE_EXPAND))
699 {
700 /* Check that we have enough data (30ms) to do the Accelearate */
701 if ((totalTS + dspInfo.samplesLeft) < WEBRTC_SPL_MUL(3,inst->timestampsPerCall)
702 && (uw16_instr == BUFSTATS_DO_ACCELERATE))
703 {
704 /* Not enough, do normal operation instead */
705 uw16_instr = BUFSTATS_DO_NORMAL;
706 }
707 else
708 {
709 inst->BufferStat_inst.Automode_inst.sampleMemory
710 = (WebRtc_Word32) dspInfo.samplesLeft + totalTS;
711 inst->BufferStat_inst.Automode_inst.prevTimeScale = 1;
712 }
713 }
714
715 /* Close the data with a zero size block */
716 *blockPtr = 0;
717
718 /* Write data to DSP */
719 switch (uw16_instr)
720 {
721 case BUFSTATS_DO_NORMAL:
722 /* Normal with decoding included */
723 inst->pw16_writeAddress[0] = (inst->pw16_writeAddress[0] & 0x0fff)
724 | DSP_INSTR_NORMAL;
725 break;
726 case BUFSTATS_DO_ACCELERATE:
727 inst->pw16_writeAddress[0] = (inst->pw16_writeAddress[0] & 0x0fff)
728 | DSP_INSTR_ACCELERATE;
729 break;
730 case BUFSTATS_DO_MERGE:
731 inst->pw16_writeAddress[0] = (inst->pw16_writeAddress[0] & 0x0fff)
732 | DSP_INSTR_MERGE;
733 break;
734 case BUFSTATS_DO_RFC3389CNG_PACKET:
735 inst->pw16_writeAddress[0] = (inst->pw16_writeAddress[0] & 0x0fff)
736 | DSP_INSTR_DO_RFC3389CNG;
737 break;
738 case BUFSTATS_DO_ALTERNATIVE_PLC:
739 inst->pw16_writeAddress[1] = 0;
740 inst->pw16_writeAddress[0] = (inst->pw16_writeAddress[0] & 0x0fff)
741 | DSP_INSTR_DO_ALTERNATIVE_PLC;
742 break;
743 case BUFSTATS_DO_ALTERNATIVE_PLC_INC_TS:
744 inst->pw16_writeAddress[1] = 0;
745 inst->pw16_writeAddress[0] = (inst->pw16_writeAddress[0] & 0x0fff)
746 | DSP_INSTR_DO_ALTERNATIVE_PLC_INC_TS;
747 break;
748 case BUFSTATS_DO_AUDIO_REPETITION:
749 inst->pw16_writeAddress[1] = 0;
750 inst->pw16_writeAddress[0] = (inst->pw16_writeAddress[0] & 0x0fff)
751 | DSP_INSTR_DO_AUDIO_REPETITION;
752 break;
753 case BUFSTATS_DO_AUDIO_REPETITION_INC_TS:
754 inst->pw16_writeAddress[1] = 0;
755 inst->pw16_writeAddress[0] = (inst->pw16_writeAddress[0] & 0x0fff)
756 | DSP_INSTR_DO_AUDIO_REPETITION_INC_TS;
757 break;
758 case BUFSTATS_DO_PREEMPTIVE_EXPAND:
759 inst->pw16_writeAddress[0] = (inst->pw16_writeAddress[0] & 0x0fff)
760 | DSP_INSTR_PREEMPTIVE_EXPAND;
761 break;
762 default:
763 return UNKNOWN_BUFSTAT_DECISION;
764 }
765
766 inst->timeStamp = dspInfo.playedOutTS;
767 return 0;
768
769}