1 /**
2 * Copyright (C) 2022 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include <AudioJitterBuffer.h>
18 #include <ImsMediaAudioUtil.h>
19 #include <ImsMediaDataQueue.h>
20 #include <ImsMediaTimer.h>
21 #include <ImsMediaTrace.h>
22 #include <numeric>
23
24 #define AUDIO_JITTER_BUFFER_MIN_SIZE (3)
25 #define AUDIO_JITTER_BUFFER_MAX_SIZE (9)
26 #define AUDIO_JITTER_BUFFER_START_SIZE (4)
27 #define GET_SEQ_GAP(a, b) ((uint16_t)(a) - (uint16_t)(b))
28 #define JITTER_BUFFER_UPDATE_INTERVAL (100) // ms unit
29 #define FRAME_INTERVAL (20) // ms unit
30 #define ALLOWABLE_ERROR (10) // ms unit
31 #define RESET_THRESHOLD_IN_DTX_ENABLED (80) // percentage
32 #define RESET_THRESHOLD_IN_DTX_DISABLED (35) // percentage
33 #define TS_ROUND_QUARD (3000) // ms unit
34 #define SEQ_OUTLIER_THRESHOLD (3000)
35 #define USHORT_TS_ROUND_COMPARE(a, b) \
36 ((((a) >= (b)) && (((b) >= TS_ROUND_QUARD) || ((a) <= 0xffff - TS_ROUND_QUARD))) || \
37 (((a) <= TS_ROUND_QUARD) && ((b) >= 0xffff - TS_ROUND_QUARD)))
38
39 #define MAX_STORED_BUFFER_SIZE (50 * 60 * 60) // 1 hour in frame interval unit
40 #define MAX_QUEUE_SIZE (150) // 3 sec
41 #define DROP_WINDOW (5000) // 5 ec
42
AudioJitterBuffer()43 AudioJitterBuffer::AudioJitterBuffer()
44 {
45 mInitJitterBufferSize = AUDIO_JITTER_BUFFER_START_SIZE;
46 mMinJitterBufferSize = AUDIO_JITTER_BUFFER_MIN_SIZE;
47 mMaxJitterBufferSize = AUDIO_JITTER_BUFFER_MAX_SIZE;
48 mJitterAnalyzer.Reset();
49 mJitterAnalyzer.SetMinMaxJitterBufferSize(mMinJitterBufferSize, mMaxJitterBufferSize);
50 mListJitterBufferSize.clear();
51 mEvsRedundantFrameOffset = -1;
52 AudioJitterBuffer::Reset();
53 }
54
~AudioJitterBuffer()55 AudioJitterBuffer::~AudioJitterBuffer()
56 {
57 AudioJitterBuffer::ClearBuffer();
58 }
59
Reset()60 void AudioJitterBuffer::Reset()
61 {
62 IMLOGD0("[Reset]");
63 mLastPlayedSeqNum = 0;
64 mLastPlayedTimestamp = 0;
65 mFirstFrameReceived = false;
66 mDtxPlayed = false;
67 mDtxReceived = false;
68 mWaiting = true;
69 mUpdatedDelay = 0;
70 mCheckUpdateJitterPacketCnt = 0;
71 mPreservedDtx = nullptr;
72 mPrevGetTime = 0;
73 mListVoiceFrames.clear();
74 mListDropVoiceFrames.clear();
75 mAdditionalDelay = 0;
76 }
77
ClearBuffer()78 void AudioJitterBuffer::ClearBuffer()
79 {
80 IMLOGD0("[ClearBuffer]");
81 std::lock_guard<std::mutex> guard(mMutex);
82 DataEntry* entry = nullptr;
83
84 while (mDataQueue.Get(&entry))
85 {
86 if (entry->eDataType != MEDIASUBTYPE_AUDIO_SID)
87 {
88 CollectRxRtpStatus(entry->nSeqNum, kRtpStatusDiscarded);
89 }
90
91 mDataQueue.Delete();
92 }
93 }
94
SetJitterBufferSize(uint32_t nInit,uint32_t nMin,uint32_t nMax)95 void AudioJitterBuffer::SetJitterBufferSize(uint32_t nInit, uint32_t nMin, uint32_t nMax)
96 {
97 IMLOGD3("[SetJitterBufferSize] %d, %d, %d", nInit, nMin, nMax);
98
99 if (nMin > 0)
100 {
101 mMinJitterBufferSize = nMin;
102 }
103
104 if (nMax > 0)
105 {
106 mMaxJitterBufferSize = nMax;
107 }
108
109 if (nInit > 0)
110 {
111 if (nInit < mMinJitterBufferSize)
112 {
113 nInit = mMinJitterBufferSize;
114 }
115
116 if (nInit > mMaxJitterBufferSize)
117 {
118 nInit = mMaxJitterBufferSize;
119 }
120
121 mInitJitterBufferSize = nInit;
122 mCurrJitterBufferSize = mInitJitterBufferSize;
123 mNextJitterBufferSize = mInitJitterBufferSize;
124 }
125
126 mJitterAnalyzer.SetMinMaxJitterBufferSize(mMinJitterBufferSize, mMaxJitterBufferSize);
127 }
128
SetJitterOptions(uint32_t incThreshold,uint32_t decThreshold,uint32_t stepSize,double zValue)129 void AudioJitterBuffer::SetJitterOptions(
130 uint32_t incThreshold, uint32_t decThreshold, uint32_t stepSize, double zValue)
131 {
132 mJitterAnalyzer.SetJitterOptions(incThreshold, decThreshold, stepSize, zValue);
133 }
134
SetEvsRedundantFrameOffset(const int32_t offset)135 void AudioJitterBuffer::SetEvsRedundantFrameOffset(const int32_t offset)
136 {
137 IMLOGD1("[SetEvsRedundantFrameOffset] offset=%d", offset);
138 mEvsRedundantFrameOffset = offset;
139 }
140
Add(ImsMediaSubType subtype,uint8_t * pbBuffer,uint32_t nBufferSize,uint32_t nTimestamp,bool bMark,uint32_t nSeqNum,ImsMediaSubType nDataType,uint32_t arrivalTime)141 void AudioJitterBuffer::Add(ImsMediaSubType subtype, uint8_t* pbBuffer, uint32_t nBufferSize,
142 uint32_t nTimestamp, bool bMark, uint32_t nSeqNum, ImsMediaSubType nDataType,
143 uint32_t arrivalTime)
144 {
145 DataEntry currEntry = DataEntry();
146 currEntry.subtype = subtype;
147 currEntry.pbBuffer = pbBuffer;
148 currEntry.nBufferSize = nBufferSize;
149 currEntry.nTimestamp = nTimestamp;
150 currEntry.bMark = bMark;
151 currEntry.nSeqNum = nSeqNum;
152 currEntry.bHeader = true;
153 currEntry.bValid = true;
154 currEntry.arrivalTime = arrivalTime;
155 currEntry.eDataType = nDataType;
156
157 if (subtype == MEDIASUBTYPE_REFRESHED)
158 {
159 std::lock_guard<std::mutex> guard(mMutex);
160 mSsrc = nBufferSize;
161 mTimeStarted = arrivalTime;
162 mJitterAnalyzer.Reset();
163 mCurrJitterBufferSize = mInitJitterBufferSize;
164 mNextJitterBufferSize = mCurrJitterBufferSize;
165 mDataQueue.Add(&currEntry);
166
167 IMLOGI2("[Add] ssrc=%u, startTime=%d", mSsrc, mTimeStarted);
168 return;
169 }
170
171 if (currEntry.eDataType == MEDIASUBTYPE_AUDIO_SID)
172 {
173 mDtxReceived = true;
174 }
175
176 int32_t jitter = mJitterAnalyzer.CalculateTransitTimeDifference(nTimestamp, arrivalTime);
177
178 RtpPacket* packet = new RtpPacket();
179
180 switch (currEntry.eDataType)
181 {
182 case MEDIASUBTYPE_AUDIO_SID:
183 packet->rtpDataType = kRtpDataTypeSid;
184 break;
185 default:
186 case MEDIASUBTYPE_AUDIO_NODATA:
187 packet->rtpDataType = kRtpDataTypeNoData;
188 break;
189 case MEDIASUBTYPE_AUDIO_NORMAL:
190 packet->rtpDataType = kRtpDataTypeNormal;
191 break;
192 }
193
194 packet->ssrc = mSsrc;
195 packet->seqNum = nSeqNum;
196 packet->jitter = jitter;
197 packet->arrival = arrivalTime;
198 packet->timestamp = nTimestamp;
199 mCallback->SendEvent(kCollectPacketInfo, kStreamRtpRx, reinterpret_cast<uint64_t>(packet));
200
201 std::lock_guard<std::mutex> guard(mMutex);
202
203 IMLOGD_PACKET8(IM_PACKET_LOG_JITTER,
204 "[Add] seq=%d, mark=%d, TS=%d, size=%d, jitter=%d, queue=%d, playingDiff=%d, "
205 "arrival=%d",
206 nSeqNum, bMark, nTimestamp, nBufferSize, jitter, mDataQueue.GetCount() + 1,
207 mCurrPlayingTS - nTimestamp, arrivalTime);
208
209 if (mDataQueue.GetCount() == 0)
210 { // jitter buffer is empty
211 mDataQueue.Add(&currEntry);
212 }
213 else
214 {
215 DataEntry* pEntry;
216 mDataQueue.GetLast(&pEntry);
217
218 if (pEntry == nullptr)
219 {
220 return;
221 }
222
223 // current data is the latest data
224 if (USHORT_SEQ_ROUND_COMPARE(nSeqNum, pEntry->nSeqNum))
225 {
226 mDataQueue.Add(&currEntry);
227 }
228 else
229 {
230 // find the position of current data and insert current data to the correct position
231 mDataQueue.SetReadPosFirst();
232
233 for (int32_t i = 0; mDataQueue.GetNext(&pEntry); i++)
234 {
235 // late arrival packet
236 if (!USHORT_SEQ_ROUND_COMPARE(nSeqNum, pEntry->nSeqNum))
237 {
238 mDataQueue.InsertAt(i, &currEntry);
239 break;
240 }
241 }
242 }
243 }
244
245 if (currEntry.eDataType != MEDIASUBTYPE_AUDIO_SID)
246 {
247 mListVoiceFrames.push_back(arrivalTime);
248
249 // keep the list 3 times of the drop window
250 if (mListVoiceFrames.size() > DROP_WINDOW * 3 / FRAME_INTERVAL)
251 {
252 mListVoiceFrames.pop_front();
253 }
254 }
255
256 // update jitter buffer size
257 if (!mWaiting && mUpdatedDelay == 0)
258 {
259 uint32_t nextJitterBufferSize =
260 mJitterAnalyzer.GetNextJitterBufferSize(mCurrJitterBufferSize, arrivalTime);
261 mCheckUpdateJitterPacketCnt = 0;
262 mUpdatedDelay = nextJitterBufferSize - mCurrJitterBufferSize;
263 }
264 }
265
Get(ImsMediaSubType * psubtype,uint8_t ** ppData,uint32_t * pnDataSize,uint32_t * pnTimestamp,bool * pbMark,uint32_t * pnSeqNum,uint32_t currentTime,ImsMediaSubType * pDataType)266 bool AudioJitterBuffer::Get(ImsMediaSubType* psubtype, uint8_t** ppData, uint32_t* pnDataSize,
267 uint32_t* pnTimestamp, bool* pbMark, uint32_t* pnSeqNum, uint32_t currentTime,
268 ImsMediaSubType* pDataType)
269 {
270 std::lock_guard<std::mutex> guard(mMutex);
271
272 IMLOGD_PACKET1(IM_PACKET_LOG_JITTER, "[Get] time diff=%d", currentTime - mPrevGetTime);
273 mPrevGetTime = currentTime;
274
275 DataEntry* pEntry = nullptr;
276 bool bForceToPlay = false;
277 mCheckUpdateJitterPacketCnt++;
278
279 if (mDataQueue.Get(&pEntry) && pEntry->subtype == MEDIASUBTYPE_REFRESHED) // ssrc changed
280 {
281 Reset();
282 mDataQueue.Delete(); // delete indication frame of ssrc
283
284 if (!mWaiting && mDataQueue.Get(&pEntry)) // get next frame
285 {
286 mCurrPlayingTS = pEntry->nTimestamp; // play directly
287 mWaiting = false;
288 }
289 }
290
291 // increase delay
292 if (!mWaiting && mDtxPlayed && mUpdatedDelay > 0)
293 {
294 IMLOGD2("[Get] increase delay=%d, curTS=%d", mUpdatedDelay, mCurrPlayingTS);
295 mUpdatedDelay--;
296 mCurrJitterBufferSize++;
297 return false;
298 }
299
300 // decrease delay
301 if (!mWaiting && mDataQueue.Get(&pEntry) && pEntry->eDataType == MEDIASUBTYPE_AUDIO_SID &&
302 mUpdatedDelay < 0)
303 {
304 IMLOGD3("[Get] decrease delay=%d, curTS=%u, queue=%u", mUpdatedDelay, mCurrPlayingTS,
305 mDataQueue.GetCount());
306 mUpdatedDelay++;
307 mCurrJitterBufferSize--;
308 mCurrPlayingTS += FRAME_INTERVAL;
309 }
310
311 int32_t dropRate = GetDropVoiceRateInDuration(DROP_WINDOW, currentTime);
312
313 // resync the jitter buffer
314 if ((dropRate > RESET_THRESHOLD_IN_DTX_ENABLED && mDtxReceived) ||
315 (dropRate > RESET_THRESHOLD_IN_DTX_DISABLED && !mDtxReceived))
316 {
317 if (mCurrJitterBufferSize == mMaxJitterBufferSize)
318 {
319 IMLOGD1("[Get] resync, drop rate=%u", dropRate);
320 mWaiting = true;
321 mTimeStarted = currentTime;
322 }
323 else
324 {
325 IMLOGD1("[Get] increase delay by drop rate=%u", dropRate);
326 mCurrPlayingTS -= FRAME_INTERVAL;
327 mCurrJitterBufferSize++;
328 }
329
330 mListDropVoiceFrames.clear();
331 }
332
333 if (mDataQueue.GetCount() == 0)
334 {
335 IMLOGD_PACKET1(IM_PACKET_LOG_JITTER, "[Get] fail - empty, curTS=%u", mCurrPlayingTS);
336
337 if (!mWaiting)
338 {
339 mCurrPlayingTS += FRAME_INTERVAL;
340 }
341
342 return false;
343 }
344 else if (mDataQueue.Get(&pEntry) && mWaiting)
345 {
346 if (currentTime - mTimeStarted + ALLOWABLE_ERROR < mCurrJitterBufferSize * FRAME_INTERVAL)
347 {
348 if (psubtype)
349 *psubtype = MEDIASUBTYPE_UNDEFINED;
350 if (ppData)
351 *ppData = nullptr;
352 if (pnDataSize)
353 *pnDataSize = 0;
354 if (pnTimestamp)
355 *pnTimestamp = 0;
356 if (pbMark)
357 *pbMark = false;
358 if (pnSeqNum)
359 *pnSeqNum = 0;
360 if (pDataType)
361 *pDataType = MEDIASUBTYPE_UNDEFINED;
362
363 IMLOGD_PACKET5(IM_PACKET_LOG_JITTER,
364 "[Get] Wait - timeStarted=%d, seq=%u, CurrJBSize=%u, delay=%u, "
365 "QueueCount=%u",
366 mTimeStarted, pEntry->nSeqNum, mCurrJitterBufferSize,
367 currentTime - pEntry->arrivalTime, GetCount());
368 return false;
369 }
370 else
371 {
372 // resync when the audio frame stacked over the current jitter buffer size
373 Resync(mCurrJitterBufferSize + 1);
374 mWaiting = false;
375 }
376 }
377
378 mListJitterBufferSize.push_back(mCurrJitterBufferSize);
379
380 if (mListJitterBufferSize.size() > MAX_STORED_BUFFER_SIZE) // 1hour
381 {
382 mListJitterBufferSize.pop_front();
383 }
384
385 // report duplicated packet
386 while (mDataQueue.Get(&pEntry) && mFirstFrameReceived && pEntry->nSeqNum == mLastPlayedSeqNum &&
387 pEntry->nTimestamp == mLastPlayedTimestamp)
388 {
389 IMLOGD6("[Get] duplicate - curTS=%u, seq=%d, mark=%d, TS=%u, size=%d, queue=%d",
390 mCurrPlayingTS, pEntry->nSeqNum, pEntry->bMark, pEntry->nTimestamp,
391 pEntry->nBufferSize, mDataQueue.GetCount());
392 CollectRxRtpStatus(pEntry->nSeqNum, kRtpStatusDuplicated);
393 mDataQueue.Delete();
394 }
395
396 if (currentTime - mTimeStarted < 3000)
397 {
398 // resync when the audio frame stacked over the max jitter buffer size
399 Resync(mMaxJitterBufferSize);
400 }
401 else
402 {
403 Resync(MAX_QUEUE_SIZE);
404 }
405
406 // adjust the playing timestamp
407 if (mDataQueue.Get(&pEntry) && pEntry->nTimestamp != mCurrPlayingTS &&
408 ((mCurrPlayingTS - ALLOWABLE_ERROR) <= pEntry->nTimestamp) &&
409 (pEntry->nTimestamp <= (mCurrPlayingTS + ALLOWABLE_ERROR)))
410 {
411 IMLOGD3("[Get] sync playing curTS=%u, TS=%u, seq=%d", mCurrPlayingTS, pEntry->nTimestamp,
412 pEntry->nSeqNum);
413 mCurrPlayingTS = pEntry->nTimestamp;
414 }
415
416 // delete late arrival
417 while (mDataQueue.Get(&pEntry) && !USHORT_TS_ROUND_COMPARE(pEntry->nTimestamp, mCurrPlayingTS))
418 {
419 mDtxPlayed = (pEntry->eDataType == MEDIASUBTYPE_AUDIO_SID);
420
421 // discard case that latest packet is about to cut by the jitter then update the
422 // sequence number to avoid incorrect lost counting
423 if (pEntry->nSeqNum >= mLastPlayedSeqNum)
424 {
425 CountLostFrames(pEntry->nSeqNum, mLastPlayedSeqNum);
426 mLastPlayedSeqNum = pEntry->nSeqNum;
427 mLastPlayedTimestamp = pEntry->nTimestamp;
428 }
429
430 IMLOGD_PACKET4(IM_PACKET_LOG_JITTER,
431 "[Get] delete late arrival, dtx=%d, seq=%d, curTS=%u, TS=%u", mDtxPlayed,
432 pEntry->nSeqNum, mCurrPlayingTS, pEntry->nTimestamp);
433
434 if (mPreservedDtx != nullptr)
435 {
436 delete mPreservedDtx;
437 }
438
439 mPreservedDtx = nullptr;
440
441 if (mDtxPlayed)
442 {
443 mPreservedDtx = new DataEntry(*pEntry);
444 }
445 else
446 {
447 CollectRxRtpStatus(pEntry->nSeqNum, kRtpStatusLate);
448 mListDropVoiceFrames.push_back(currentTime);
449
450 // keep the list 3 times of the drop window
451 if (mListDropVoiceFrames.size() > DROP_WINDOW * 3 / FRAME_INTERVAL)
452 {
453 mListDropVoiceFrames.pop_front();
454 }
455 }
456
457 mJitterAnalyzer.SetLateArrivals(currentTime);
458 mDataQueue.Delete();
459 }
460
461 // add condition in case of changing Seq# & TS
462 if (mDataQueue.Get(&pEntry) && (pEntry->nTimestamp - mCurrPlayingTS) > TS_ROUND_QUARD)
463 {
464 IMLOGD4("[Get] TS changing case, enforce play [ %d / %u / %u / %d ]", pEntry->nSeqNum,
465 pEntry->nTimestamp, mCurrPlayingTS, mDataQueue.GetCount());
466 bForceToPlay = true;
467 }
468
469 if (mDataQueue.Get(&pEntry) &&
470 (pEntry->nTimestamp == mCurrPlayingTS || bForceToPlay ||
471 (pEntry->nTimestamp < TS_ROUND_QUARD && mCurrPlayingTS > 0xFFFF)))
472 {
473 if (psubtype)
474 *psubtype = pEntry->subtype;
475 if (ppData)
476 *ppData = pEntry->pbBuffer;
477 if (pnDataSize)
478 *pnDataSize = pEntry->nBufferSize;
479 if (pnTimestamp)
480 *pnTimestamp = pEntry->nTimestamp;
481 if (pbMark)
482 *pbMark = pEntry->bMark;
483 if (pnSeqNum)
484 *pnSeqNum = pEntry->nSeqNum;
485 if (pDataType)
486 *pDataType = pEntry->eDataType;
487
488 mDtxPlayed = (pEntry->eDataType == MEDIASUBTYPE_AUDIO_SID);
489
490 if (mFirstFrameReceived)
491 {
492 CountLostFrames(pEntry->nSeqNum, mLastPlayedSeqNum);
493 }
494
495 IMLOGD_PACKET7(IM_PACKET_LOG_JITTER,
496 "[Get] OK, dtx=%d, curTS=%u, seq=%u, TS=%u, size=%u, delay=%u, curSize=%u",
497 mDtxPlayed, mCurrPlayingTS, pEntry->nSeqNum, pEntry->nTimestamp,
498 pEntry->nBufferSize, currentTime - pEntry->arrivalTime, mCurrJitterBufferSize);
499
500 mCurrPlayingTS = pEntry->nTimestamp + FRAME_INTERVAL;
501 mFirstFrameReceived = true;
502 mLastPlayedSeqNum = pEntry->nSeqNum;
503 mLastPlayedTimestamp = pEntry->nTimestamp;
504 CollectRxRtpStatus(pEntry->nSeqNum, kRtpStatusNormal);
505 CollectJitterBufferStatus(
506 mCurrJitterBufferSize * FRAME_INTERVAL, mMaxJitterBufferSize * FRAME_INTERVAL);
507
508 if (mPreservedDtx != nullptr)
509 {
510 delete mPreservedDtx;
511 mPreservedDtx = nullptr;
512 }
513
514 return true;
515 }
516 else
517 {
518 // use the preserved dtx when it is discarded as late arrival
519 if (mPreservedDtx != nullptr)
520 {
521 // push front the preserved dtx to the queue
522 mDataQueue.InsertAt(0, mPreservedDtx);
523 delete mPreservedDtx;
524 mPreservedDtx = nullptr;
525
526 mDataQueue.Get(&pEntry);
527
528 if (psubtype)
529 *psubtype = pEntry->subtype;
530 if (ppData)
531 *ppData = pEntry->pbBuffer;
532 if (pnDataSize)
533 *pnDataSize = pEntry->nBufferSize;
534 if (pnTimestamp)
535 *pnTimestamp = mCurrPlayingTS;
536 if (pbMark)
537 *pbMark = pEntry->bMark;
538 if (pnSeqNum)
539 *pnSeqNum = pEntry->nSeqNum;
540 if (pDataType)
541 *pDataType = pEntry->eDataType;
542
543 IMLOGD_PACKET3(IM_PACKET_LOG_JITTER,
544 "[Get] OK, preserved frame, dtx=%d, curTS=%u, current=%u", mDtxPlayed,
545 mCurrPlayingTS, currentTime);
546
547 mLastPlayedSeqNum = pEntry->nSeqNum;
548 mLastPlayedTimestamp = pEntry->nTimestamp;
549 mCurrPlayingTS += FRAME_INTERVAL;
550 return true;
551 }
552 if (psubtype)
553 *psubtype = MEDIASUBTYPE_UNDEFINED;
554 if (ppData)
555 *ppData = nullptr;
556 if (pnDataSize)
557 *pnDataSize = 0;
558 if (pnTimestamp)
559 *pnTimestamp = 0;
560 if (pbMark)
561 *pbMark = false;
562 if (pnSeqNum)
563 *pnSeqNum = 0;
564 if (pDataType)
565 *pDataType = MEDIASUBTYPE_UNDEFINED;
566
567 IMLOGD_PACKET3(IM_PACKET_LOG_JITTER, "[Get] fail - dtx=%d, curTS=%u, current=%u",
568 mDtxPlayed, mCurrPlayingTS, currentTime);
569
570 mCurrPlayingTS += FRAME_INTERVAL;
571 return false;
572 }
573
574 return false;
575 }
576
GetMeanBufferSize()577 double AudioJitterBuffer::GetMeanBufferSize()
578 {
579 return std::accumulate(mListJitterBufferSize.begin(), mListJitterBufferSize.end(), 0.0f) /
580 mListJitterBufferSize.size();
581 }
582
Resync(uint32_t spareFrames)583 void AudioJitterBuffer::Resync(uint32_t spareFrames)
584 {
585 bool isDeleted = false;
586 DataEntry* entry = nullptr;
587
588 while (mDataQueue.Get(&entry) && GetCount() > spareFrames)
589 {
590 IMLOGD6("[Resync] state=%d, seq=%d, TS=%d, dtx=%d, queue=%d, spareFrames=%d", mWaiting,
591 entry->nSeqNum, entry->nTimestamp, entry->eDataType == MEDIASUBTYPE_AUDIO_SID,
592 GetCount(), spareFrames);
593
594 if (entry->eDataType != MEDIASUBTYPE_AUDIO_SID)
595 {
596 CollectRxRtpStatus(entry->nSeqNum, kRtpStatusDiscarded);
597 }
598
599 if (!mWaiting)
600 {
601 mLastPlayedSeqNum = entry->nSeqNum;
602 mLastPlayedTimestamp = entry->nTimestamp;
603 }
604
605 mDataQueue.Delete();
606 isDeleted = true;
607 }
608
609 if ((mWaiting || isDeleted) && mDataQueue.Get(&entry))
610 {
611 mCurrPlayingTS = entry->nTimestamp;
612 }
613 }
614
CountLostFrames(int32_t currentSeq,int32_t lastSeq)615 void AudioJitterBuffer::CountLostFrames(int32_t currentSeq, int32_t lastSeq)
616 {
617 /** Report the loss gap if the loss gap is over 0 */
618 uint16_t lostGap = GET_SEQ_GAP(currentSeq, lastSeq);
619
620 if (lostGap > 1 && lostGap < SEQ_OUTLIER_THRESHOLD)
621 {
622 uint16_t lostSeq = lastSeq + 1;
623 IMLOGD_PACKET2(IM_PACKET_LOG_JITTER, "[CountLostFrames] lost seq=%u, num=%u", lostSeq,
624 lostGap - 1);
625
626 SessionCallbackParameter* param =
627 new SessionCallbackParameter(kReportPacketLossGap, lostSeq, lostGap - 1);
628 mCallback->SendEvent(kCollectOptionalInfo, reinterpret_cast<uint64_t>(param), 0);
629 }
630 }
631
GetDropVoiceRateInDuration(uint32_t duration,uint32_t currentTime)632 uint32_t AudioJitterBuffer::GetDropVoiceRateInDuration(uint32_t duration, uint32_t currentTime)
633 {
634 uint32_t numVoice = std::count_if(mListVoiceFrames.begin(), mListVoiceFrames.end(),
635 [duration, currentTime, this](uint32_t frameTime)
636 {
637 return ((currentTime - frameTime + mCurrJitterBufferSize * FRAME_INTERVAL) <=
638 duration);
639 });
640
641 uint32_t numDrop = std::count_if(mListDropVoiceFrames.begin(), mListDropVoiceFrames.end(),
642 [duration, currentTime](uint32_t frameTime)
643 {
644 return (currentTime - frameTime <= duration);
645 });
646
647 if (numVoice <= 5)
648 {
649 return 0;
650 }
651
652 return numDrop * 100 / numVoice;
653 }
654
CollectRxRtpStatus(int32_t seq,kRtpPacketStatus status)655 void AudioJitterBuffer::CollectRxRtpStatus(int32_t seq, kRtpPacketStatus status)
656 {
657 if (mCallback != nullptr)
658 {
659 SessionCallbackParameter* param =
660 new SessionCallbackParameter(seq, status, ImsMediaTimer::GetTimeInMilliSeconds());
661 mCallback->SendEvent(kCollectRxRtpStatus, reinterpret_cast<uint64_t>(param));
662 }
663 }
664
CollectJitterBufferStatus(int32_t currSize,int32_t maxSize)665 void AudioJitterBuffer::CollectJitterBufferStatus(int32_t currSize, int32_t maxSize)
666 {
667 if (mCallback != nullptr)
668 {
669 mCallback->SendEvent(kCollectJitterBufferSize, currSize, maxSize);
670 }
671 }
672
GetPartialRedundancyFrame(uint32_t lostSeq,uint32_t currentTimestamp,uint32_t offset,DataEntry ** entry)673 bool AudioJitterBuffer::GetPartialRedundancyFrame(
674 uint32_t lostSeq, uint32_t currentTimestamp, uint32_t offset, DataEntry** entry)
675 {
676 bool foundPartialFrame = false;
677 DataEntry* tempEntry = nullptr;
678 uint32_t partialSeq = lostSeq + offset;
679
680 // find redundancy frame from the queue
681 for (int32_t i = 0; i < mDataQueue.GetCount(); i++)
682 {
683 if (mDataQueue.GetAt(i, &tempEntry) && tempEntry->nSeqNum == partialSeq)
684 {
685 foundPartialFrame = true;
686 break;
687 }
688
689 if (tempEntry->nSeqNum > partialSeq)
690 {
691 break;
692 }
693 }
694
695 if (!foundPartialFrame)
696 {
697 *entry = nullptr;
698 IMLOGD_PACKET1(IM_PACKET_LOG_JITTER,
699 "[GetPartialRedundancyFrame] lostSeq=%d Redundant Frame not found", lostSeq);
700 return false;
701 }
702
703 if (tempEntry->eDataType == MEDIASUBTYPE_AUDIO_SID)
704 {
705 *entry = nullptr;
706 IMLOGD_PACKET1(IM_PACKET_LOG_JITTER,
707 "[GetPartialRedundancyFrame] lostSeq=%d Redundant Frame is SID", lostSeq);
708 return false;
709 }
710
711 // If the timestamp of RF is greater than the (currentframe_timestamp + offset*20msec) then it
712 // cannot be used for concealment.
713 if (tempEntry->nTimestamp > (currentTimestamp + offset * 20))
714 {
715 *entry = nullptr;
716 IMLOGD_PACKET2(IM_PACKET_LOG_JITTER,
717 "[GetPartialRedundancyFrame] RF not in offset timeframe. \
718 RF_timestamp=%u LostFrame_timestamp=%u",
719 tempEntry->nTimestamp, currentTimestamp);
720 return false;
721 }
722
723 if (tempEntry->nBufferSize == 33 || tempEntry->nBufferSize == 34)
724 {
725 *entry = tempEntry;
726 IMLOGD_PACKET4(IM_PACKET_LOG_JITTER,
727 "[GetPartialRedundancyFrame] lostSeq=%d RFSeq=%d, size=%d , curTS=%u", lostSeq,
728 tempEntry->nSeqNum, tempEntry->nBufferSize, mCurrPlayingTS);
729 return true;
730 }
731
732 *entry = nullptr;
733 IMLOGD_PACKET1(IM_PACKET_LOG_JITTER,
734 "[GetPartialRedundancyFrame] lostSeq=%d Redundant Frame not found", lostSeq);
735 return false;
736 }
737
GetNextFrameFirstByte(uint32_t nextSeq,uint8_t * nextFrameFirstByte)738 bool AudioJitterBuffer::GetNextFrameFirstByte(uint32_t nextSeq, uint8_t* nextFrameFirstByte)
739 {
740 DataEntry* pEntry = nullptr;
741 if (mDataQueue.Get(&pEntry) &&
742 (pEntry->eDataType != MEDIASUBTYPE_AUDIO_NODATA && pEntry->nSeqNum == nextSeq))
743 {
744 *nextFrameFirstByte =
745 pEntry->pbBuffer[ImsMediaAudioUtil::CheckEVSPrimaryHeaderFullModeFromSize(
746 pEntry->nBufferSize)
747 ? 1
748 : 0];
749 IMLOGD_PACKET2(IM_PACKET_LOG_JITTER,
750 "[GetNextFrameFirstByte] nextSeq=%d nextFrameFirstByte[%02X]", pEntry->nSeqNum,
751 nextFrameFirstByte[0]);
752 return true;
753 }
754 IMLOGD_PACKET0(IM_PACKET_LOG_JITTER, "[GetNextFrameFirstByte] Next Frame not found");
755 return false;
756 }
757
GetRedundantFrame(uint32_t lostSeq,uint8_t ** ppData,uint32_t * pnDataSize,bool * hasNextFrame,uint8_t * nextFrameFirstByte)758 bool AudioJitterBuffer::GetRedundantFrame(uint32_t lostSeq, uint8_t** ppData, uint32_t* pnDataSize,
759 bool* hasNextFrame, uint8_t* nextFrameFirstByte)
760 {
761 std::lock_guard<std::mutex> guard(mMutex);
762 DataEntry* pEntry = nullptr;
763
764 if (!mDtxPlayed &&
765 GetPartialRedundancyFrame(lostSeq, mCurrPlayingTS, mEvsRedundantFrameOffset, &pEntry))
766 {
767 if (ppData)
768 *ppData = pEntry->pbBuffer;
769 if (pnDataSize)
770 *pnDataSize = pEntry->nBufferSize;
771 *hasNextFrame = GetNextFrameFirstByte((lostSeq + 1), nextFrameFirstByte);
772
773 return true;
774 }
775
776 return false;
777 }
778
SetAdditionalDelay(const int32_t delayMs)779 void AudioJitterBuffer::SetAdditionalDelay(const int32_t delayMs)
780 {
781 std::lock_guard<std::mutex> guard(mMutex);
782
783 if (!mWaiting && mFirstFrameReceived)
784 {
785 int32_t delayDiff = delayMs - mAdditionalDelay;
786 mAdditionalDelay = delayMs;
787
788 int32_t newDelay = delayDiff / FRAME_INTERVAL;
789 mCurrPlayingTS -= newDelay * FRAME_INTERVAL;
790 mCurrJitterBufferSize += newDelay;
791 IMLOGD3("[SetAdditionalDelay] delay=%d, delayDiff=%d, curSize=%d", delayMs, delayDiff,
792 mCurrJitterBufferSize);
793 }
794 }