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 }