blob: 15d618e76ec2b51b5f03949a4d1842ffbe76fd47 [file] [log] [blame]
niklase@google.com470e71d2011-07-07 08:21:25 +00001/*
tina.legrand@webrtc.org45175852012-06-01 09:27:35 +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 the RecIn function, which is the main function for inserting RTP
13 * packets into NetEQ.
14 */
15
16#include "mcu.h"
17
18#include <string.h>
19
20#include "signal_processing_library.h"
21
22#include "automode.h"
23#include "dtmf_buffer.h"
24#include "neteq_defines.h"
25#include "neteq_error_codes.h"
26
27
28int WebRtcNetEQ_RecInInternal(MCUInst_t *MCU_inst, RTPPacket_t *RTPpacketInput,
pbos@webrtc.org0946a562013-04-09 00:28:06 +000029 uint32_t uw32_timeRec)
niklase@google.com470e71d2011-07-07 08:21:25 +000030{
31 RTPPacket_t RTPpacket[2];
32 int i_k;
33 int i_ok = 0, i_No_Of_Payloads = 1;
pbos@webrtc.org0946a562013-04-09 00:28:06 +000034 int16_t flushed = 0;
35 int16_t codecPos;
niklase@google.com470e71d2011-07-07 08:21:25 +000036 int curr_Codec;
pbos@webrtc.org0946a562013-04-09 00:28:06 +000037 int16_t isREDPayload = 0;
38 int32_t temp_bufsize;
niklase@google.com470e71d2011-07-07 08:21:25 +000039#ifdef NETEQ_RED_CODEC
40 RTPPacket_t* RTPpacketPtr[2]; /* Support for redundancy up to 2 payloads */
41 RTPpacketPtr[0] = &RTPpacket[0];
42 RTPpacketPtr[1] = &RTPpacket[1];
43#endif
44
tina.legrand@webrtc.org5ac387c2012-11-19 08:02:55 +000045 temp_bufsize = WebRtcNetEQ_PacketBufferGetSize(&MCU_inst->PacketBuffer_inst,
turaj@webrtc.org28d54ab2013-04-22 18:53:35 +000046 &MCU_inst->codec_DB_inst,
47 MCU_inst->av_sync);
niklase@google.com470e71d2011-07-07 08:21:25 +000048 /*
49 * Copy from input RTP packet to local copy
50 * (mainly to enable multiple payloads using RED)
51 */
52
53 WEBRTC_SPL_MEMCPY_W8(&RTPpacket[0], RTPpacketInput, sizeof(RTPPacket_t));
54
55 /* Reinitialize NetEq if it's needed (changed SSRC or first call) */
56
57 if ((RTPpacket[0].ssrc != MCU_inst->ssrc) || (MCU_inst->first_packet == 1))
58 {
59 WebRtcNetEQ_RTCPInit(&MCU_inst->RTCP_inst, RTPpacket[0].seqNumber);
60 MCU_inst->first_packet = 0;
61
62 /* Flush the buffer */
63 WebRtcNetEQ_PacketBufferFlush(&MCU_inst->PacketBuffer_inst);
64
65 /* Store new SSRC */
66 MCU_inst->ssrc = RTPpacket[0].ssrc;
67
68 /* Update codecs */
69 MCU_inst->timeStamp = RTPpacket[0].timeStamp;
70 MCU_inst->current_Payload = RTPpacket[0].payloadType;
71
72 /*Set MCU to update codec on next SignalMCU call */
73 MCU_inst->new_codec = 1;
74
75 /* Reset timestamp scaling */
76 MCU_inst->TSscalingInitialized = 0;
77
78 }
79
80 /* Call RTCP statistics */
81 i_ok |= WebRtcNetEQ_RTCPUpdate(&(MCU_inst->RTCP_inst), RTPpacket[0].seqNumber,
82 RTPpacket[0].timeStamp, uw32_timeRec);
83
84 /* If Redundancy is supported and this is the redundancy payload, separate the payloads */
85#ifdef NETEQ_RED_CODEC
86 if (RTPpacket[0].payloadType == WebRtcNetEQ_DbGetPayload(&MCU_inst->codec_DB_inst,
87 kDecoderRED))
88 {
89
90 /* Split the payload into a main and a redundancy payloads */
91 i_ok = WebRtcNetEQ_RedundancySplit(RTPpacketPtr, 2, &i_No_Of_Payloads);
92 if (i_ok < 0)
93 {
94 /* error returned */
95 return i_ok;
96 }
97
98 /*
99 * Only accept a few redundancies of the same type as the main data,
100 * AVT events and CNG.
101 */
102 if ((i_No_Of_Payloads > 1) && (RTPpacket[0].payloadType != RTPpacket[1].payloadType)
103 && (RTPpacket[0].payloadType != WebRtcNetEQ_DbGetPayload(&MCU_inst->codec_DB_inst,
104 kDecoderAVT)) && (RTPpacket[1].payloadType != WebRtcNetEQ_DbGetPayload(
105 &MCU_inst->codec_DB_inst, kDecoderAVT)) && (!WebRtcNetEQ_DbIsCNGPayload(
106 &MCU_inst->codec_DB_inst, RTPpacket[0].payloadType))
107 && (!WebRtcNetEQ_DbIsCNGPayload(&MCU_inst->codec_DB_inst, RTPpacket[1].payloadType)))
108 {
109 i_No_Of_Payloads = 1;
110 }
111 isREDPayload = 1;
112 }
113#endif
114
115 /* loop over the number of payloads */
116 for (i_k = 0; i_k < i_No_Of_Payloads; i_k++)
117 {
118
119 if (isREDPayload == 1)
120 {
121 RTPpacket[i_k].rcuPlCntr = i_k;
122 }
123 else
124 {
125 RTPpacket[i_k].rcuPlCntr = 0;
126 }
127
128 /* Force update of SplitInfo if it's iLBC because of potential change between 20/30ms */
129 if (RTPpacket[i_k].payloadType == WebRtcNetEQ_DbGetPayload(&MCU_inst->codec_DB_inst,
130 kDecoderILBC))
131 {
132 i_ok = WebRtcNetEQ_DbGetSplitInfo(
133 &MCU_inst->PayloadSplit_inst,
134 (enum WebRtcNetEQDecoder) WebRtcNetEQ_DbGetCodec(&MCU_inst->codec_DB_inst,
135 RTPpacket[i_k].payloadType), RTPpacket[i_k].payloadLen);
136 if (i_ok < 0)
137 {
138 /* error returned */
139 return i_ok;
140 }
141 }
142
143 /* Get information about timestamp scaling for this payload type */
144 i_ok = WebRtcNetEQ_GetTimestampScaling(MCU_inst, RTPpacket[i_k].payloadType);
145 if (i_ok < 0)
146 {
147 /* error returned */
148 return i_ok;
149 }
150
151 if (MCU_inst->TSscalingInitialized == 0 && MCU_inst->scalingFactor != kTSnoScaling)
152 {
153 /* Must initialize scaling with current timestamps */
154 MCU_inst->externalTS = RTPpacket[i_k].timeStamp;
155 MCU_inst->internalTS = RTPpacket[i_k].timeStamp;
156 MCU_inst->TSscalingInitialized = 1;
157 }
158
159 /* Adjust timestamp if timestamp scaling is needed (e.g. SILK or G.722) */
160 if (MCU_inst->TSscalingInitialized == 1)
161 {
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000162 uint32_t newTS = WebRtcNetEQ_ScaleTimestampExternalToInternal(MCU_inst,
niklase@google.com470e71d2011-07-07 08:21:25 +0000163 RTPpacket[i_k].timeStamp);
164
165 /* save the incoming timestamp for next time */
166 MCU_inst->externalTS = RTPpacket[i_k].timeStamp;
167
168 /* add the scaled difference to last scaled timestamp and save ... */
169 MCU_inst->internalTS = newTS;
170
171 RTPpacket[i_k].timeStamp = newTS;
172 }
173
174 /* Is this a DTMF packet?*/
175 if (RTPpacket[i_k].payloadType == WebRtcNetEQ_DbGetPayload(&MCU_inst->codec_DB_inst,
176 kDecoderAVT))
177 {
178#ifdef NETEQ_ATEVENT_DECODE
179 if (MCU_inst->AVT_PlayoutOn)
180 {
181 i_ok = WebRtcNetEQ_DtmfInsertEvent(&MCU_inst->DTMF_inst,
182 RTPpacket[i_k].payload, RTPpacket[i_k].payloadLen,
183 RTPpacket[i_k].timeStamp);
184 if (i_ok != 0)
185 {
186 return i_ok;
187 }
188 }
189#endif
190#ifdef NETEQ_STEREO
191 if (MCU_inst->usingStereo == 0)
192 {
193 /* do not set this for DTMF packets when using stereo mode */
194 MCU_inst->BufferStat_inst.Automode_inst.lastPackCNGorDTMF = 1;
195 }
196#else
197 MCU_inst->BufferStat_inst.Automode_inst.lastPackCNGorDTMF = 1;
198#endif
199 }
200 else if (WebRtcNetEQ_DbIsCNGPayload(&MCU_inst->codec_DB_inst,
201 RTPpacket[i_k].payloadType))
202 {
203 /* Is this a CNG packet? how should we handle this?*/
204#ifdef NETEQ_CNG_CODEC
205 /* Get CNG sample rate */
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000206 uint16_t fsCng = WebRtcNetEQ_DbGetSampleRate(&MCU_inst->codec_DB_inst,
niklase@google.com470e71d2011-07-07 08:21:25 +0000207 RTPpacket[i_k].payloadType);
tina.legrand@webrtc.orga7d83872012-10-18 10:00:52 +0000208
209 /* Force sampling frequency to 32000 Hz CNG 48000 Hz. */
210 /* TODO(tlegrand): remove limitation once ACM has full 48 kHz
211 * support. */
212 if (fsCng > 32000) {
213 fsCng = 32000;
214 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000215 if ((fsCng != MCU_inst->fs) && (fsCng > 8000))
216 {
217 /*
218 * We have received CNG with a different sample rate from what we are using
219 * now (must be > 8000, since we may use only one CNG type (default) for all
220 * frequencies). Flush buffer and signal new codec.
221 */
222 WebRtcNetEQ_PacketBufferFlush(&MCU_inst->PacketBuffer_inst);
223 MCU_inst->new_codec = 1;
224 MCU_inst->current_Codec = -1;
225 }
226 i_ok = WebRtcNetEQ_PacketBufferInsert(&MCU_inst->PacketBuffer_inst,
turaj@webrtc.org28d54ab2013-04-22 18:53:35 +0000227 &RTPpacket[i_k], &flushed, MCU_inst->av_sync);
niklase@google.com470e71d2011-07-07 08:21:25 +0000228 if (i_ok < 0)
229 {
230 return RECIN_CNG_ERROR;
231 }
232 MCU_inst->BufferStat_inst.Automode_inst.lastPackCNGorDTMF = 1;
233#else /* NETEQ_CNG_CODEC not defined */
234 return RECIN_UNKNOWNPAYLOAD;
235#endif /* NETEQ_CNG_CODEC */
236 }
237 else
238 {
239 /* Reinitialize the splitting if the payload and/or the payload length has changed */
240 curr_Codec = WebRtcNetEQ_DbGetCodec(&MCU_inst->codec_DB_inst,
241 RTPpacket[i_k].payloadType);
242 if (curr_Codec != MCU_inst->current_Codec)
243 {
244 if (curr_Codec < 0)
245 {
246 return RECIN_UNKNOWNPAYLOAD;
247 }
248 MCU_inst->current_Codec = curr_Codec;
249 MCU_inst->current_Payload = RTPpacket[i_k].payloadType;
250 i_ok = WebRtcNetEQ_DbGetSplitInfo(&MCU_inst->PayloadSplit_inst,
251 (enum WebRtcNetEQDecoder) MCU_inst->current_Codec,
252 RTPpacket[i_k].payloadLen);
253 if (i_ok < 0)
254 { /* error returned */
255 return i_ok;
256 }
257 WebRtcNetEQ_PacketBufferFlush(&MCU_inst->PacketBuffer_inst);
258 MCU_inst->new_codec = 1;
259 }
260
niklase@google.com470e71d2011-07-07 08:21:25 +0000261 /* Parse the payload and insert it into the buffer */
262 i_ok = WebRtcNetEQ_SplitAndInsertPayload(&RTPpacket[i_k],
turaj@webrtc.org28d54ab2013-04-22 18:53:35 +0000263 &MCU_inst->PacketBuffer_inst, &MCU_inst->PayloadSplit_inst,
264 &flushed, MCU_inst->av_sync);
niklase@google.com470e71d2011-07-07 08:21:25 +0000265 if (i_ok < 0)
266 {
267 return i_ok;
268 }
269 if (MCU_inst->BufferStat_inst.Automode_inst.lastPackCNGorDTMF != 0)
270 {
271 /* first normal packet after CNG or DTMF */
272 MCU_inst->BufferStat_inst.Automode_inst.lastPackCNGorDTMF = -1;
273 }
274 }
275 /* Reset DSP timestamp etc. if packet buffer flushed */
276 if (flushed)
277 {
278 MCU_inst->new_codec = 1;
279 }
280 }
281
282 /*
283 * Update Bandwidth Estimate
284 * Only send the main payload to BWE
285 */
286 if ((curr_Codec = WebRtcNetEQ_DbGetCodec(&MCU_inst->codec_DB_inst,
287 RTPpacket[0].payloadType)) >= 0)
288 {
289 codecPos = MCU_inst->codec_DB_inst.position[curr_Codec];
290 if (MCU_inst->codec_DB_inst.funcUpdBWEst[codecPos] != NULL) /* codec has BWE function */
291 {
292 if (RTPpacket[0].starts_byte1) /* check for shifted byte alignment */
293 {
294 /* re-align to 16-bit alignment */
295 for (i_k = 0; i_k < RTPpacket[0].payloadLen; i_k++)
296 {
297 WEBRTC_SPL_SET_BYTE(RTPpacket[0].payload,
298 WEBRTC_SPL_GET_BYTE(RTPpacket[0].payload, i_k+1),
299 i_k);
300 }
301 RTPpacket[0].starts_byte1 = 0;
302 }
303
304 MCU_inst->codec_DB_inst.funcUpdBWEst[codecPos](
305 MCU_inst->codec_DB_inst.codec_state[codecPos],
pbos@webrtc.orge4b60642013-04-10 18:06:57 +0000306 (const uint16_t *) RTPpacket[0].payload,
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000307 (int32_t) RTPpacket[0].payloadLen, RTPpacket[0].seqNumber,
308 (uint32_t) RTPpacket[0].timeStamp, (uint32_t) uw32_timeRec);
niklase@google.com470e71d2011-07-07 08:21:25 +0000309 }
310 }
311
312 if (MCU_inst->BufferStat_inst.Automode_inst.lastPackCNGorDTMF == 0)
313 {
314 /* Calculate the total speech length carried in each packet */
tina.legrand@webrtc.org5ac387c2012-11-19 08:02:55 +0000315 temp_bufsize = WebRtcNetEQ_PacketBufferGetSize(
turaj@webrtc.org28d54ab2013-04-22 18:53:35 +0000316 &MCU_inst->PacketBuffer_inst, &MCU_inst->codec_DB_inst,
317 MCU_inst->av_sync) - temp_bufsize;
niklase@google.com470e71d2011-07-07 08:21:25 +0000318
319 if ((temp_bufsize > 0) && (MCU_inst->BufferStat_inst.Automode_inst.lastPackCNGorDTMF
320 == 0) && (temp_bufsize
321 != MCU_inst->BufferStat_inst.Automode_inst.packetSpeechLenSamp))
322 {
323 /* Change the auto-mode parameters if packet length has changed */
324 WebRtcNetEQ_SetPacketSpeechLen(&(MCU_inst->BufferStat_inst.Automode_inst),
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000325 (int16_t) temp_bufsize, MCU_inst->fs);
niklase@google.com470e71d2011-07-07 08:21:25 +0000326 }
327
328 /* update statistics */
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000329 if ((int32_t) (RTPpacket[0].timeStamp - MCU_inst->timeStamp) >= 0
niklase@google.com470e71d2011-07-07 08:21:25 +0000330 && !MCU_inst->new_codec)
331 {
332 /*
333 * Only update statistics if incoming packet is not older than last played out
334 * packet, and if new codec flag is not set.
335 */
336 WebRtcNetEQ_UpdateIatStatistics(&MCU_inst->BufferStat_inst.Automode_inst,
337 MCU_inst->PacketBuffer_inst.maxInsertPositions, RTPpacket[0].seqNumber,
338 RTPpacket[0].timeStamp, MCU_inst->fs,
339 WebRtcNetEQ_DbIsMDCodec((enum WebRtcNetEQDecoder) MCU_inst->current_Codec),
340 (MCU_inst->NetEqPlayoutMode == kPlayoutStreaming));
341 }
342 }
343 else if (MCU_inst->BufferStat_inst.Automode_inst.lastPackCNGorDTMF == -1)
344 {
345 /*
346 * This is first "normal" packet after CNG or DTMF.
347 * Reset packet time counter and measure time until next packet,
348 * but don't update statistics.
349 */
350 MCU_inst->BufferStat_inst.Automode_inst.lastPackCNGorDTMF = 0;
351 MCU_inst->BufferStat_inst.Automode_inst.packetIatCountSamp = 0;
352 }
353 return 0;
354
355}
356
357int WebRtcNetEQ_GetTimestampScaling(MCUInst_t *MCU_inst, int rtpPayloadType)
358{
359 enum WebRtcNetEQDecoder codec;
360 int codecNumber;
361
362 codecNumber = WebRtcNetEQ_DbGetCodec(&MCU_inst->codec_DB_inst, rtpPayloadType);
363 if (codecNumber < 0)
364 {
365 /* error */
366 return codecNumber;
367 }
368
369 /* cast to enumerator */
370 codec = (enum WebRtcNetEQDecoder) codecNumber;
371
372 /*
373 * The factor obtained below is the number with which the RTP timestamp must be
374 * multiplied to get the true sample count.
375 */
376 switch (codec)
377 {
378 case kDecoderG722:
tina.legrand@webrtc.org45175852012-06-01 09:27:35 +0000379 case kDecoderG722_2ch:
niklase@google.com470e71d2011-07-07 08:21:25 +0000380 {
381 /* Use timestamp scaling with factor 2 (two output samples per RTP timestamp) */
382 MCU_inst->scalingFactor = kTSscalingTwo;
383 break;
384 }
turaj@webrtc.orgb0dff122012-12-03 17:43:52 +0000385 case kDecoderISACfb:
tina.legrand@webrtc.orga7d83872012-10-18 10:00:52 +0000386 case kDecoderOpus:
387 {
turaj@webrtc.orgb0dff122012-12-03 17:43:52 +0000388 /* We resample Opus internally to 32 kHz, and isac-fb decodes at
389 * 32 kHz, but timestamps are counted at 48 kHz. So there are two
390 * output samples per three RTP timestamp ticks. */
tina.legrand@webrtc.orga7d83872012-10-18 10:00:52 +0000391 MCU_inst->scalingFactor = kTSscalingTwoThirds;
392 break;
393 }
394
niklase@google.com470e71d2011-07-07 08:21:25 +0000395 case kDecoderAVT:
396 case kDecoderCNG:
397 {
tina.legrand@webrtc.orga7d83872012-10-18 10:00:52 +0000398 /* TODO(tlegrand): remove scaling once ACM has full 48 kHz
399 * support. */
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000400 uint16_t sample_freq =
tina.legrand@webrtc.orga7d83872012-10-18 10:00:52 +0000401 WebRtcNetEQ_DbGetSampleRate(&MCU_inst->codec_DB_inst,
402 rtpPayloadType);
403 if (sample_freq == 48000) {
404 MCU_inst->scalingFactor = kTSscalingTwoThirds;
405 }
406
407 /* For sample_freq <= 32 kHz, do not change the timestamp scaling
408 * settings. */
niklase@google.com470e71d2011-07-07 08:21:25 +0000409 break;
410 }
411 default:
412 {
413 /* do not use timestamp scaling */
414 MCU_inst->scalingFactor = kTSnoScaling;
415 break;
416 }
417 }
418 return 0;
419}
420
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000421uint32_t WebRtcNetEQ_ScaleTimestampExternalToInternal(const MCUInst_t *MCU_inst,
422 uint32_t externalTS)
niklase@google.com470e71d2011-07-07 08:21:25 +0000423{
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000424 int32_t timestampDiff;
425 uint32_t internalTS;
niklase@google.com470e71d2011-07-07 08:21:25 +0000426
427 /* difference between this and last incoming timestamp */
428 timestampDiff = externalTS - MCU_inst->externalTS;
429
430 switch (MCU_inst->scalingFactor)
431 {
432 case kTSscalingTwo:
433 {
434 /* multiply with 2 */
435 timestampDiff = WEBRTC_SPL_LSHIFT_W32(timestampDiff, 1);
436 break;
437 }
438 case kTSscalingTwoThirds:
439 {
440 /* multiply with 2/3 */
441 timestampDiff = WEBRTC_SPL_LSHIFT_W32(timestampDiff, 1);
442 timestampDiff = WebRtcSpl_DivW32W16(timestampDiff, 3);
443 break;
444 }
445 case kTSscalingFourThirds:
446 {
447 /* multiply with 4/3 */
448 timestampDiff = WEBRTC_SPL_LSHIFT_W32(timestampDiff, 2);
449 timestampDiff = WebRtcSpl_DivW32W16(timestampDiff, 3);
450 break;
451 }
452 default:
453 {
454 /* no scaling */
455 }
456 }
457
458 /* add the scaled difference to last scaled timestamp and save ... */
459 internalTS = MCU_inst->internalTS + timestampDiff;
460
461 return internalTS;
462}
463
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000464uint32_t WebRtcNetEQ_ScaleTimestampInternalToExternal(const MCUInst_t *MCU_inst,
465 uint32_t internalTS)
niklase@google.com470e71d2011-07-07 08:21:25 +0000466{
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000467 int32_t timestampDiff;
468 uint32_t externalTS;
niklase@google.com470e71d2011-07-07 08:21:25 +0000469
470 /* difference between this and last incoming timestamp */
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000471 timestampDiff = (int32_t) internalTS - MCU_inst->internalTS;
niklase@google.com470e71d2011-07-07 08:21:25 +0000472
473 switch (MCU_inst->scalingFactor)
474 {
475 case kTSscalingTwo:
476 {
477 /* divide by 2 */
478 timestampDiff = WEBRTC_SPL_RSHIFT_W32(timestampDiff, 1);
479 break;
480 }
481 case kTSscalingTwoThirds:
482 {
483 /* multiply with 3/2 */
484 timestampDiff = WEBRTC_SPL_MUL_32_16(timestampDiff, 3);
485 timestampDiff = WEBRTC_SPL_RSHIFT_W32(timestampDiff, 1);
486 break;
487 }
488 case kTSscalingFourThirds:
489 {
490 /* multiply with 3/4 */
491 timestampDiff = WEBRTC_SPL_MUL_32_16(timestampDiff, 3);
492 timestampDiff = WEBRTC_SPL_RSHIFT_W32(timestampDiff, 2);
493 break;
494 }
495 default:
496 {
497 /* no scaling */
498 }
499 }
500
501 /* add the scaled difference to last scaled timestamp and save ... */
502 externalTS = MCU_inst->externalTS + timestampDiff;
503
504 return externalTS;
505}