summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorbodamnam <bodamnam@google.com>2023-02-07 08:52:42 +0000
committerbodamnam <bodamnam@google.com>2023-02-22 10:21:24 +0000
commit6c19d679661d4c18355b7add0e9a247ffc22454b (patch)
treecb1a96290bdc35a86979f5204e8e4490118a4619
parent0e6c7d339c5feac51992f7c5204ded40d873fd32 (diff)
downloadImsMedia-6c19d679661d4c18355b7add0e9a247ffc22454b.tar.gz
Fix the incorrect CallQuality notification
1) Improve the delete frame logic in AudioJitterBuffer to prevent incorrect lost frame reported 2) Remove unusing logic in AudioJitterBuffer 3) Fix the timing of the MediaQualityAnalyzer starting and add thread initaliation code to prevent the zero value notification 4) Fix call duration 5) Add reporting min/max playout delay 6) Add UT of AudioJitterBuffer for verification Bug: 263846230 Test: loopback testing with ImsMediaTestingApp, atest ImsMediaNativeTests Change-Id: I7c8454051dcdb10f46d7d2d229fe612120e80b51
-rw-r--r--service/src/com/android/telephony/imsmedia/lib/libimsmedia/config/include/CallQuality.h6
-rw-r--r--service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/BaseJitterBuffer.cpp8
-rw-r--r--service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/audio/AudioJitterBuffer.cpp456
-rw-r--r--service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/audio/AudioSession.cpp21
-rw-r--r--service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/audio/MediaQualityAnalyzer.cpp61
-rw-r--r--service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/audio/nodes/IAudioPlayerNode.cpp6
-rw-r--r--service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/include/BaseJitterBuffer.h10
-rw-r--r--service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/include/ImsMediaDefine.h4
-rw-r--r--service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/include/audio/AudioJitterBuffer.h16
-rw-r--r--service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/include/audio/MediaQualityAnalyzer.h3
-rw-r--r--service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/include/nodes/JitterBufferControlNode.h3
-rw-r--r--service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/include/text/TextJitterBuffer.h2
-rw-r--r--service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/include/video/VideoJitterBuffer.h4
-rw-r--r--service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/nodes/JitterBufferControlNode.cpp25
-rw-r--r--service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/text/TextJitterBuffer.cpp3
-rw-r--r--service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/utils/IImsMediaThread.cpp2
-rw-r--r--service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/video/VideoJitterBuffer.cpp6
-rw-r--r--tests/native/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/audio/AudioJitterBufferTest.cpp494
-rw-r--r--tests/native/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/audio/MediaQualityAnalyzerTest.cpp76
19 files changed, 776 insertions, 430 deletions
diff --git a/service/src/com/android/telephony/imsmedia/lib/libimsmedia/config/include/CallQuality.h b/service/src/com/android/telephony/imsmedia/lib/libimsmedia/config/include/CallQuality.h
index 491a6f1f..67fb1f6d 100644
--- a/service/src/com/android/telephony/imsmedia/lib/libimsmedia/config/include/CallQuality.h
+++ b/service/src/com/android/telephony/imsmedia/lib/libimsmedia/config/include/CallQuality.h
@@ -163,7 +163,7 @@ private:
bool mRxSilenceDetected;
/** True if only silence RTP packets are sent for 20 seconds immediately after the call is
* connected. The silence packet can be detected by observing that the RTP timestamp is not
- * contiguous with the end of the int32_terval covered by the previous packet even though the
+ * contiguous with the end of the interval covered by the previous packet even though the
* RTP sequence number has been incremented only by one. Check RFC 3389. */
bool mTxSilenceDetected;
/** The number of voice frames sent by jitter buffer to audio. */
@@ -172,9 +172,9 @@ private:
int32_t mNumNoDataFrames;
/** The number of RTP Voice packets dropped by jitter buffer. */
int32_t mNumDroppedRtpPackets;
- /** The minimum playout delay in the reporting int32_terval in milliseconds. */
+ /** The minimum playout delay in the reporting interval in milliseconds. */
int64_t mMinPlayoutDelayMillis;
- /** The maximum Playout delay in the reporting int32_terval in milliseconds. */
+ /** The maximum Playout delay in the reporting interval in milliseconds. */
int64_t mMaxPlayoutDelayMillis;
/** The total number of RTP SID (Silence Insertion Descriptor) */
int32_t mNumRtpSidPacketsReceived;
diff --git a/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/BaseJitterBuffer.cpp b/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/BaseJitterBuffer.cpp
index 06eda0ff..c039e690 100644
--- a/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/BaseJitterBuffer.cpp
+++ b/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/BaseJitterBuffer.cpp
@@ -32,7 +32,10 @@ BaseJitterBuffer::BaseJitterBuffer()
mMaxSaveFrameNum = 0;
}
-BaseJitterBuffer::~BaseJitterBuffer() {}
+BaseJitterBuffer::~BaseJitterBuffer()
+{
+ mDataQueue.Clear();
+}
void BaseJitterBuffer::SetSessionCallback(BaseSessionCallback* callback)
{
@@ -58,13 +61,12 @@ void BaseJitterBuffer::SetJitterBufferSize(uint32_t nInit, uint32_t nMin, uint32
}
void BaseJitterBuffer::SetJitterOptions(
- uint32_t nReduceTH, uint32_t nStepSize, double zValue, bool bIgnoreSID, bool bImprovement)
+ uint32_t nReduceTH, uint32_t nStepSize, double zValue, bool bIgnoreSID)
{
(void)nReduceTH;
(void)nStepSize;
(void)zValue;
(void)bIgnoreSID;
- (void)bImprovement;
}
uint32_t BaseJitterBuffer::GetCount()
diff --git a/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/audio/AudioJitterBuffer.cpp b/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/audio/AudioJitterBuffer.cpp
index 38b59c39..7332af54 100644
--- a/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/audio/AudioJitterBuffer.cpp
+++ b/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/audio/AudioJitterBuffer.cpp
@@ -23,6 +23,14 @@
#define AUDIO_JITTER_BUFFER_MAX_SIZE (9)
#define AUDIO_JITTER_BUFFER_START_SIZE (4)
#define GET_SEQ_GAP(a, b) ((uint16_t)(a) - (uint16_t)(b))
+#define JITTER_BUFFER_UPDATE_INTERVAL (2000) // ms unit
+#define FRAME_INTERVAL (20) // ms unit
+#define ALLOWABLE_ERROR (10) // ms unit
+#define RESET_THRESHOLD (10000) // ms unit
+#define TS_ROUND_QUARD (3000) // ms unit
+#define USHORT_TS_ROUND_COMPARE(a, b) \
+ (((a) >= (b) && (b) >= TS_ROUND_QUARD) || ((a) <= 0xffff - TS_ROUND_QUARD) || \
+ ((a) <= TS_ROUND_QUARD && (b) >= 0xffff - TS_ROUND_QUARD))
AudioJitterBuffer::AudioJitterBuffer()
{
@@ -31,7 +39,6 @@ AudioJitterBuffer::AudioJitterBuffer()
mMaxJitterBufferSize = AUDIO_JITTER_BUFFER_MAX_SIZE;
AudioJitterBuffer::Reset();
mBufferIgnoreSIDPacket = false;
- mBufferImprovement = false;
}
AudioJitterBuffer::~AudioJitterBuffer() {}
@@ -41,24 +48,21 @@ void AudioJitterBuffer::Reset()
mNextJitterBufferSize = mCurrJitterBufferSize;
mLastPlayedSeqNum = 0;
mLastPlayedTimestamp = 0;
- mIsReceivedFirst = false;
+ mFirstFrameReceived = false;
mDtxOn = false;
mSIDCount = 0;
- mWaiting = false;
+ mWaiting = true;
mDeleteCount = 0;
mBaseTimestamp = 0;
mBaseArrivalTime = 0;
- mUpdateJitterBufferSize = 0;
+ mCannotGetCount = 0;
mCheckUpdateJitterPacketCnt = 0;
- mFourceToUpdateJitterBuffer = false;
+ mEnforceUpdate = false;
mNeedToUpdateBasePacket = false;
- mCanNotGetCount = 0;
- mNullDataCount = 0;
BaseJitterBuffer::Reset();
- mJitterAnalyser.Reset();
- mJitterAnalyser.SetMinMaxJitterBufferSize(mMinJitterBufferSize, mMaxJitterBufferSize);
+ mJitterAnalyzer.Reset();
+ mJitterAnalyzer.SetMinMaxJitterBufferSize(mMinJitterBufferSize, mMaxJitterBufferSize);
mCurrPlayingSeq = 0;
- mBufferUpdateDuration = 0;
}
void AudioJitterBuffer::SetJitterBufferSize(uint32_t nInit, uint32_t nMin, uint32_t nMax)
@@ -92,24 +96,20 @@ void AudioJitterBuffer::SetJitterBufferSize(uint32_t nInit, uint32_t nMin, uint3
mNextJitterBufferSize = mInitJitterBufferSize;
}
- mJitterAnalyser.SetMinMaxJitterBufferSize(mMinJitterBufferSize, mMaxJitterBufferSize);
+ mJitterAnalyzer.SetMinMaxJitterBufferSize(mMinJitterBufferSize, mMaxJitterBufferSize);
}
void AudioJitterBuffer::SetJitterOptions(
- uint32_t nReduceTH, uint32_t nStepSize, double zValue, bool bIgnoreSID, bool bImprovement)
+ uint32_t nReduceTH, uint32_t nStepSize, double zValue, bool bIgnoreSID)
{
- // do it later
mBufferIgnoreSIDPacket = bIgnoreSID;
- mBufferImprovement = bImprovement;
- mJitterAnalyser.SetJitterOptions(nReduceTH, nStepSize, zValue);
+ mJitterAnalyzer.SetJitterOptions(nReduceTH, nStepSize, zValue);
}
void AudioJitterBuffer::Add(ImsMediaSubType subtype, uint8_t* pbBuffer, uint32_t nBufferSize,
- uint32_t nTimestamp, bool bMark, uint32_t nSeqNum, ImsMediaSubType nDataType,
+ uint32_t nTimestamp, bool bMark, uint32_t nSeqNum, ImsMediaSubType /*nDataType*/,
uint32_t arrivalTime)
{
- (void)nDataType;
-
DataEntry currEntry = DataEntry();
currEntry.subtype = subtype;
currEntry.pbBuffer = pbBuffer;
@@ -121,40 +121,38 @@ void AudioJitterBuffer::Add(ImsMediaSubType subtype, uint8_t* pbBuffer, uint32_t
currEntry.bValid = true;
currEntry.arrivalTime = arrivalTime;
- // non-voice issue when min buffer size is 10 (VT case)
- if (mBufferImprovement == false && mCanNotGetCount > 500)
- {
- IMLOGD0("[Add] Refreshed");
- Reset();
- }
- else if (mBufferImprovement)
+ int32_t jitter = 0;
+
+ if (mCannotGetCount > mMaxJitterBufferSize)
{
- if ((mCanNotGetCount > mMaxJitterBufferSize) && (mCanNotGetCount > mMinJitterBufferSize))
+ IMLOGD0("[Add] refreshed");
+ DataEntry* resetData = nullptr;
+
+ while (mDataQueue.Get(&resetData))
{
- IMLOGD0("[Add] Refreshed");
- CollectRxRtpStatus(nSeqNum, kRtpStatusDiscarded);
- Reset();
+ CollectRxRtpStatus(resetData->nSeqNum, kRtpStatusDiscarded);
+ Delete();
}
- }
- int32_t jitter = 0;
+ Reset();
+ }
- if (mBufferIgnoreSIDPacket == false)
+ if (!mBufferIgnoreSIDPacket)
{
- jitter = mJitterAnalyser.CalculateTransitTimeDifference(nTimestamp, arrivalTime);
+ jitter = mJitterAnalyzer.CalculateTransitTimeDifference(nTimestamp, arrivalTime);
mBaseTimestamp = currEntry.nTimestamp;
mBaseArrivalTime = currEntry.arrivalTime;
- mJitterAnalyser.UpdateBaseTimestamp(mBaseTimestamp, mBaseArrivalTime);
+ mJitterAnalyzer.UpdateBaseTimestamp(mBaseTimestamp, mBaseArrivalTime);
}
// TODO: remove mBufferIgnoreSIDPacket logic and the statements
- else if ((mBufferIgnoreSIDPacket == true) && !IsSID(currEntry.pbBuffer, currEntry.nBufferSize))
+ else if (mBufferIgnoreSIDPacket && !IsSID(currEntry.pbBuffer, currEntry.nBufferSize))
{
// first packet delay compensation
- if ((mBaseTimestamp == 0 && mBaseArrivalTime == 0) || (mNeedToUpdateBasePacket == true))
+ if ((mBaseTimestamp == 0 && mBaseArrivalTime == 0) || mNeedToUpdateBasePacket)
{
mBaseTimestamp = currEntry.nTimestamp;
mBaseArrivalTime = currEntry.arrivalTime;
- mJitterAnalyser.UpdateBaseTimestamp(mBaseTimestamp, mBaseArrivalTime);
+ mJitterAnalyzer.UpdateBaseTimestamp(mBaseTimestamp, mBaseArrivalTime);
mNeedToUpdateBasePacket = false;
}
else if (mBaseTimestamp > currEntry.nTimestamp || mBaseArrivalTime > currEntry.arrivalTime)
@@ -162,7 +160,7 @@ void AudioJitterBuffer::Add(ImsMediaSubType subtype, uint8_t* pbBuffer, uint32_t
// rounding case (more consider case)
mBaseTimestamp = currEntry.nTimestamp;
mBaseArrivalTime = currEntry.arrivalTime;
- mJitterAnalyser.UpdateBaseTimestamp(mBaseTimestamp, mBaseArrivalTime);
+ mJitterAnalyzer.UpdateBaseTimestamp(mBaseTimestamp, mBaseArrivalTime);
}
else
{
@@ -171,10 +169,11 @@ void AudioJitterBuffer::Add(ImsMediaSubType subtype, uint8_t* pbBuffer, uint32_t
{
mBaseTimestamp = currEntry.nTimestamp;
mBaseArrivalTime = currEntry.arrivalTime;
- mJitterAnalyser.UpdateBaseTimestamp(mBaseTimestamp, mBaseArrivalTime);
+ mJitterAnalyzer.UpdateBaseTimestamp(mBaseTimestamp, mBaseArrivalTime);
}
else
- { // compensation case
+ {
+ // compensation case
uint32_t temp = currEntry.arrivalTime;
IMLOGD_PACKET2(IM_PACKET_LOG_JITTER, "Before compensation[%u], nSeqNum[%d]", temp,
currEntry.nSeqNum);
@@ -184,7 +183,7 @@ void AudioJitterBuffer::Add(ImsMediaSubType subtype, uint8_t* pbBuffer, uint32_t
}
}
- jitter = mJitterAnalyser.CalculateTransitTimeDifference(nTimestamp, arrivalTime);
+ jitter = mJitterAnalyzer.CalculateTransitTimeDifference(nTimestamp, arrivalTime);
}
RtpPacket* packet = new RtpPacket();
@@ -202,7 +201,7 @@ void AudioJitterBuffer::Add(ImsMediaSubType subtype, uint8_t* pbBuffer, uint32_t
packet->ssrc = mSsrc;
packet->seqNum = nSeqNum;
packet->jitter = jitter;
- packet->arrival = ImsMediaTimer::GetTimeInMilliSeconds();
+ packet->arrival = arrivalTime;
mCallback->SendEvent(kCollectPacketInfo, kStreamRtpRx, reinterpret_cast<uint64_t>(packet));
if (nBufferSize == 0)
@@ -255,115 +254,41 @@ void AudioJitterBuffer::Add(ImsMediaSubType subtype, uint8_t* pbBuffer, uint32_t
}
bool AudioJitterBuffer::Get(ImsMediaSubType* psubtype, uint8_t** ppData, uint32_t* pnDataSize,
- uint32_t* pnTimestamp, bool* pbMark, uint32_t* pnSeqNum, uint32_t* pnChecker)
+ uint32_t* pnTimestamp, bool* pbMark, uint32_t* pnSeqNum, uint32_t currentTime)
{
- if (mNullDataCount < 4)
- {
- mNullDataCount++;
- IMLOGD1("[Get] mNullDataCount is [%d].", mNullDataCount);
-
- if (psubtype)
- *psubtype = MEDIASUBTYPE_UNDEFINED;
- if (ppData)
- *ppData = nullptr;
- if (pnDataSize)
- *pnDataSize = 0;
- if (pnTimestamp)
- *pnTimestamp = 0;
- if (pbMark)
- *pbMark = false;
- if (pnSeqNum)
- *pnSeqNum = 0;
- if (pnChecker)
- *pnChecker = 0;
-
- return false;
- }
-
std::lock_guard<std::mutex> guard(mMutex);
- bool bWait = false;
DataEntry* pEntry = nullptr;
bool bForceToPlay = false;
- mUpdateJitterBufferSize++; // add code for no dtx
mCheckUpdateJitterPacketCnt++;
- int32_t nTimediff = 0;
- // determin bWait
- if (mIsReceivedFirst == false)
+ // update jitter buffer size
+ if (mCheckUpdateJitterPacketCnt * FRAME_INTERVAL > JITTER_BUFFER_UPDATE_INTERVAL)
{
- bWait = true;
- }
- else if (mDtxOn && mDataQueue.GetCount() > 0)
- {
- if (mDataQueue.Get(&pEntry) && IsSID(pEntry->pbBuffer, pEntry->nBufferSize) == false)
- {
- IMLOGD_PACKET0(IM_PACKET_LOG_JITTER, "[Get] bWait = True");
- bWait = true;
- }
+ mCurrJitterBufferSize =
+ mJitterAnalyzer.GetNextJitterBufferSize(mCurrJitterBufferSize, currentTime);
+ mCheckUpdateJitterPacketCnt = 0;
}
- // set current jitter buffer size
- // when dtx occur, calculate nextJitterBufferSize.
- if (mBufferImprovement == false)
+ // enforce update when breach the reset threshold
+ if (mCannotGetCount * FRAME_INTERVAL > RESET_THRESHOLD)
{
- if ((mWaiting == false && bWait == true) || mUpdateJitterBufferSize > 2 * 50)
- {
- uint32_t nPrev_jitterbufferSize = mCurrJitterBufferSize;
- mCurrJitterBufferSize = mJitterAnalyser.GetNextJitterBufferSize(
- mCurrJitterBufferSize, ImsMediaTimer::GetTimeInMilliSeconds());
-
- if (mUpdateJitterBufferSize > 2 * 50)
- { // 2s
- nTimediff = ((int32_t)mCurrJitterBufferSize - (int32_t)nPrev_jitterbufferSize) * 20;
- IMLOGD1("[Get] mFourceToUpdateJitterBuffer set. nTimediff[%d]", nTimediff);
- mFourceToUpdateJitterBuffer = true;
- }
- mUpdateJitterBufferSize = 0;
- }
-
- mWaiting = bWait;
+ IMLOGD_PACKET0(IM_PACKET_LOG_JITTER, "[Get] enforce update");
+ mEnforceUpdate = true;
+ mWaiting = false;
+ mCannotGetCount = 0;
}
- else
- {
- if ((mWaiting == false && bWait == true) || mUpdateJitterBufferSize > 500)
- {
- // update mCurrJitterBufferSize
- if (mCheckUpdateJitterPacketCnt > 50 * mBufferUpdateDuration)
- {
- mCurrJitterBufferSize = mJitterAnalyser.GetNextJitterBufferSize(
- mCurrJitterBufferSize, ImsMediaTimer::GetTimeInMilliSeconds());
- mCheckUpdateJitterPacketCnt = 0;
- }
- if (mUpdateJitterBufferSize > 500)
- {
- IMLOGD_PACKET0(IM_PACKET_LOG_JITTER, "[Get] mFourceToUpdateJitterBuffer set");
- mFourceToUpdateJitterBuffer = true;
- }
-
- mUpdateJitterBufferSize = 0;
- }
-
- mWaiting = bWait;
+ if (mDataQueue.GetCount() == 0)
+ {
+ IMLOGD_PACKET0(IM_PACKET_LOG_JITTER, "[Get] wait - empty");
+ return false;
}
- // Wait case
- if (bWait)
+ else if (mDataQueue.Get(&pEntry) && mWaiting)
{
- if (mDataQueue.Get(&pEntry))
- {
- IMLOGD_PACKET5(IM_PACKET_LOG_JITTER,
- "[Get] time[%u], arrivalTime[%u], nTS[%d], mBaseTimestamp[%u], "
- "mBaseArrivalTime[%u]",
- ImsMediaTimer::GetTimeInMilliSeconds(), pEntry->arrivalTime, pEntry->nTimestamp,
- mBaseTimestamp, mBaseArrivalTime);
- }
+ uint32_t jitterDelay = currentTime - pEntry->arrivalTime;
- if (mDataQueue.GetCount() == 0 ||
- ((mDataQueue.Get(&pEntry) &&
- (ImsMediaTimer::GetTimeInMilliSeconds() - pEntry->arrivalTime) <
- ((mCurrJitterBufferSize - 1) * 20 + 10)) &&
- (mDataQueue.GetCount() <= mCurrJitterBufferSize)))
+ if (jitterDelay < (mCurrJitterBufferSize - 1) * FRAME_INTERVAL + ALLOWABLE_ERROR)
{
if (psubtype)
*psubtype = MEDIASUBTYPE_UNDEFINED;
@@ -377,86 +302,52 @@ bool AudioJitterBuffer::Get(ImsMediaSubType* psubtype, uint8_t** ppData, uint32_
*pbMark = false;
if (pnSeqNum)
*pnSeqNum = 0;
- if (pnChecker)
- *pnChecker = 0;
-
- if (mDataQueue.GetCount() > 0)
- {
- IMLOGD_PACKET5(IM_PACKET_LOG_JITTER,
- "[Get] Wait - Seq[%u], CurrJBSize[%u], curr[%u], th[%u], QueueCount[%u]",
- pEntry->nSeqNum, mCurrJitterBufferSize,
- (uint32_t)(ImsMediaTimer::GetTimeInMilliSeconds() - pEntry->arrivalTime),
- ((mCurrJitterBufferSize - 1) * 20 + 10), mDataQueue.GetCount());
- mCanNotGetCount++;
- }
- else
- {
- IMLOGD_PACKET0(IM_PACKET_LOG_JITTER, "[Get] Wait - empty");
- }
+ IMLOGD_PACKET4(IM_PACKET_LOG_JITTER,
+ "[Get] Wait - seq[%u], CurrJBSize[%u], delay[%u], QueueCount[%u]",
+ pEntry->nSeqNum, mCurrJitterBufferSize, jitterDelay, mDataQueue.GetCount());
+ mCannotGetCount++;
return false;
}
+ else
+ {
+ mWaiting = false; // once waiting is reset, it will not set true until resync
- // the first frame of voice term
- mCurrPlayingTS = pEntry->nTimestamp;
- mCurrPlayingSeq = pEntry->nSeqNum;
+ // the first frame of voice term
+ mCurrPlayingTS = pEntry->nTimestamp;
+ mCurrPlayingSeq = pEntry->nSeqNum;
+ }
}
- if (mDataQueue.Get(&pEntry) == true && pEntry->nTimestamp != mCurrPlayingTS &&
- ((mCurrPlayingTS - 10) < pEntry->nTimestamp) &&
- (pEntry->nTimestamp < (mCurrPlayingTS + 10)))
+ // adjust the playing timestamp
+ if (mDataQueue.Get(&pEntry) && pEntry->nTimestamp != mCurrPlayingTS &&
+ ((mCurrPlayingTS - ALLOWABLE_ERROR) < pEntry->nTimestamp) &&
+ (pEntry->nTimestamp < (mCurrPlayingTS + ALLOWABLE_ERROR)))
{
- IMLOGD_PACKET0(IM_PACKET_LOG_JITTER, "[Get] CurrPlaying nTimestamp Reset!");
mCurrPlayingTS = pEntry->nTimestamp;
mCurrPlayingSeq = pEntry->nSeqNum;
+ IMLOGD_PACKET2(IM_PACKET_LOG_JITTER, "[Get] sync playing TS[%u], seq[%d]", mCurrPlayingTS,
+ mCurrPlayingSeq);
}
- // delete very old data
- while (mDataQueue.GetCount() > 0)
+ while (mDataQueue.Get(&pEntry))
{
- mDataQueue.Get(&pEntry);
-
- if (pEntry == nullptr)
+ if (mDeleteCount > mMinJitterBufferSize &&
+ mDataQueue.GetCount() < mCurrJitterBufferSize + 1)
{
- return false;
- }
+ IMLOGD0("[Get] resync");
+ uint32_t nTempBuferSize = (mCurrJitterBufferSize + AUDIO_JITTER_BUFFER_MIN_SIZE) / 2;
- if (mDeleteCount > 4 && mDataQueue.GetCount() < mCurrJitterBufferSize + 1)
- {
- IMLOGD0("[Get] Resync");
-
- if (mBufferImprovement == false)
+ if (mDataQueue.GetCount() >= nTempBuferSize)
{
- uint32_t nTempBuferSize = (mCurrJitterBufferSize + mMinJitterBufferSize) / 2;
-
- if (mDataQueue.GetCount() > nTempBuferSize)
- {
- mCurrPlayingTS = pEntry->nTimestamp;
- mCurrPlayingSeq = pEntry->nSeqNum;
- }
- else
- {
- mCurrPlayingTS =
- pEntry->nTimestamp - (nTempBuferSize - mDataQueue.GetCount()) * 20;
- mCurrPlayingSeq = 0;
- }
+ mCurrPlayingTS = pEntry->nTimestamp;
+ mCurrPlayingSeq = pEntry->nSeqNum;
}
else
{
- uint32_t nTempBuferSize =
- (mCurrJitterBufferSize + AUDIO_JITTER_BUFFER_MIN_SIZE) / 2;
-
- if (mDataQueue.GetCount() >= nTempBuferSize)
- {
- mCurrPlayingTS = pEntry->nTimestamp;
- mCurrPlayingSeq = pEntry->nSeqNum;
- }
- else
- {
- mCurrPlayingTS =
- pEntry->nTimestamp - (nTempBuferSize - mDataQueue.GetCount()) * 20;
- mCurrPlayingSeq = 0;
- }
+ mCurrPlayingTS = pEntry->nTimestamp -
+ (nTempBuferSize - mDataQueue.GetCount()) * FRAME_INTERVAL;
+ mCurrPlayingSeq = 0;
}
mNeedToUpdateBasePacket = true;
@@ -464,95 +355,77 @@ bool AudioJitterBuffer::Get(ImsMediaSubType* psubtype, uint8_t** ppData, uint32_
break;
}
- if (USHORT_TS_ROUND_COMPARE(pEntry->nTimestamp, mCurrPlayingTS) == false)
+ // a >= b
+ if (USHORT_TS_ROUND_COMPARE(pEntry->nTimestamp, mCurrPlayingTS))
+ {
+ uint32_t timediff = pEntry->nTimestamp - mCurrPlayingTS;
+ mDeleteCount = 0;
+
+ // timestamp compensation logic
+ if ((timediff > 0) && (timediff < FRAME_INTERVAL))
+ {
+ IMLOGD2("[Get] resync - TS[%u], currTS[%u]", pEntry->nTimestamp, mCurrPlayingTS);
+ bForceToPlay = true;
+ }
+
+ break;
+ }
+ else // late arrival
{
if (IsSID(pEntry->pbBuffer, pEntry->nBufferSize))
{
mSIDCount++;
mDtxOn = true;
- IMLOGD_PACKET0(IM_PACKET_LOG_JITTER, "[Get] Dtx On");
}
else
{
mSIDCount = 0;
- // mDtxOn = false;
- IMLOGD_PACKET0(IM_PACKET_LOG_JITTER, "[Get] Dtx Off");
}
+ CollectRxRtpStatus(pEntry->nSeqNum, kRtpStatusLate);
mDeleteCount++;
-
- if (mDtxOn == true)
- {
- CollectRxRtpStatus(pEntry->nSeqNum, kRtpStatusNormal);
- CollectJitterBufferStatus(mCurrJitterBufferSize * 20, mMaxJitterBufferSize * 20);
- }
- else
- {
- CollectRxRtpStatus(pEntry->nSeqNum, kRtpStatusLate);
- }
-
- IMLOGD_PACKET2(IM_PACKET_LOG_JITTER, "[Get] delete TS[%d], PlayingTS[%d]",
- pEntry->nTimestamp, mCurrPlayingTS);
mDataQueue.Delete();
- }
- else
- {
- uint32_t timediff = pEntry->nTimestamp - mCurrPlayingTS;
- mDeleteCount = 0;
-
- // timestamp compensation logic
- if ((timediff > 0) && (timediff < 20))
- {
- IMLOGD2("[Get] resync - TS[%d], PlayingTS[%d]", pEntry->nTimestamp, mCurrPlayingTS);
- bForceToPlay = true;
- }
-
- break;
+ IMLOGD_PACKET0(IM_PACKET_LOG_JITTER, "[Get] delete late arrival");
}
}
// decrease jitter buffer
if (mDtxOn && mSIDCount > 4 && mDataQueue.GetCount() > mCurrJitterBufferSize)
{
- mDataQueue.Get(&pEntry);
- if (pEntry && IsSID(pEntry->pbBuffer, pEntry->nBufferSize))
+ if (mDataQueue.Get(&pEntry) && IsSID(pEntry->pbBuffer, pEntry->nBufferSize))
{
IMLOGD_PACKET5(IM_PACKET_LOG_JITTER,
- "[Get] Delete SID - seq[%d], bMark[%d], nTS[%d], curTS[%d], size[%d]",
+ "[Get] delete SID - seq[%d], mark[%d], TS[%u], currTS[%u], queue[%d]",
pEntry->nSeqNum, pEntry->bMark, pEntry->nTimestamp, mCurrPlayingTS,
mDataQueue.GetCount());
mSIDCount++;
mDtxOn = true;
- IMLOGD_PACKET0(IM_PACKET_LOG_JITTER, "[Get] Dtx On");
-
- CollectRxRtpStatus(pEntry->nSeqNum, kRtpStatusNormal);
- CollectJitterBufferStatus(mCurrJitterBufferSize * 20, mMaxJitterBufferSize * 20);
+ CollectRxRtpStatus(pEntry->nSeqNum, kRtpStatusDiscarded);
+ mDeleteCount++;
mDataQueue.Delete();
bForceToPlay = true;
}
}
// add condition in case of changing Seq# & TS
- if ((mCanNotGetCount > 10) && (mDataQueue.Get(&pEntry) == true) &&
- (pEntry->nTimestamp - mCurrPlayingTS > TS_ROUND_QUARD))
+ if (mDataQueue.Get(&pEntry) && (pEntry->nTimestamp - mCurrPlayingTS) > TS_ROUND_QUARD)
{
- IMLOGD4("[Get] TS changing case [ %d / %u / %u / %d ]", pEntry->nSeqNum, pEntry->nTimestamp,
- mCurrPlayingTS, mDataQueue.GetCount());
+ IMLOGD4("[Get] TS changing case, enforce play [ %d / %u / %u / %d ]", pEntry->nSeqNum,
+ pEntry->nTimestamp, mCurrPlayingTS, mDataQueue.GetCount());
bForceToPlay = true;
}
- if (mFourceToUpdateJitterBuffer == true)
+ if (mEnforceUpdate)
{
// removing delete packet in min JitterBuffer size
if (mDataQueue.GetCount() > mCurrJitterBufferSize + 1)
{
- mDataQueue.Get(&pEntry);
-
- if (pEntry)
+ if (mDataQueue.Get(&pEntry))
{
IMLOGD_PACKET5(IM_PACKET_LOG_JITTER,
- "[Get] Delete Packets - seq[%d], bMark[%d], nTS[%d], curTS[%d], size[%d]",
+ "[Get] Delete Packets - seq[%d], bMark[%d], TS[%u], curTS[%u], "
+ "size[%d]",
pEntry->nSeqNum, pEntry->bMark, pEntry->nTimestamp, mCurrPlayingTS,
mDataQueue.GetCount());
@@ -569,61 +442,27 @@ bool AudioJitterBuffer::Get(ImsMediaSubType* psubtype, uint8_t** ppData, uint32_
IMLOGD_PACKET0(IM_PACKET_LOG_JITTER, "[Get] Dtx Off");
}
- if (mDtxOn == true)
- {
- CollectRxRtpStatus(pEntry->nSeqNum, kRtpStatusNormal);
- CollectJitterBufferStatus(
- mCurrJitterBufferSize * 20, mMaxJitterBufferSize * 20);
- }
- else
- {
- CollectRxRtpStatus(pEntry->nSeqNum, kRtpStatusDiscarded);
- }
-
+ CollectRxRtpStatus(pEntry->nSeqNum, kRtpStatusDiscarded);
mDataQueue.Delete();
bForceToPlay = true;
}
}
- if (mBufferImprovement == false)
- {
- // increase case
- if ((mDataQueue.GetCount() < 2) || (mDataQueue.GetCount() < mCurrJitterBufferSize))
- {
- IMLOGD3("[Get] increase queue size[%d], curr buffer[%d], nTimediff[%d]",
- mDataQueue.GetCount(), mCurrJitterBufferSize, nTimediff);
+ mEnforceUpdate = false;
- if (nTimediff > 0)
- {
- mCurrPlayingTS -= nTimediff;
- mCurrPlayingSeq -= nTimediff / 20;
- IMLOGD1("[Get] increase queue size [%d]", nTimediff / 20);
- }
- }
-
- // reset
- mFourceToUpdateJitterBuffer = false;
- mUpdateJitterBufferSize = 0;
- }
- else
+ if ((mDataQueue.GetCount() < 2) ||
+ (mDataQueue.GetCount() < mCurrJitterBufferSize - mMinJitterBufferSize))
{
- mFourceToUpdateJitterBuffer = false;
- mUpdateJitterBufferSize = 0;
-
- if ((mDataQueue.GetCount() < 2) ||
- (mDataQueue.GetCount() < mCurrJitterBufferSize - mMinJitterBufferSize))
- {
- IMLOGD_PACKET0(IM_PACKET_LOG_JITTER, "[Get] increase packet");
- return false;
- }
+ IMLOGD_PACKET0(IM_PACKET_LOG_JITTER, "[Get] wait stacking");
+ return false;
}
}
- // get data and check the duplication
- if (mDataQueue.Get(&pEntry) && pEntry->nSeqNum == mLastPlayedSeqNum)
+ // discard duplicated packet
+ if (mDataQueue.Get(&pEntry) && mFirstFrameReceived && pEntry->nSeqNum == mLastPlayedSeqNum)
{
IMLOGD_PACKET6(IM_PACKET_LOG_JITTER,
- "[Get] duplicate - curTS[%d], seq[%d], Mark[%d], TS[%d], buffer[%d], size[%d]",
+ "[Get] duplicate - curTS[%u], seq[%d], Mark[%d], TS[%u], size[%d], queue[%d]",
mCurrPlayingTS, pEntry->nSeqNum, pEntry->bMark, pEntry->nTimestamp,
pEntry->nBufferSize, mDataQueue.GetCount());
CollectRxRtpStatus(pEntry->nSeqNum, kRtpStatusDuplicated);
@@ -631,7 +470,7 @@ bool AudioJitterBuffer::Get(ImsMediaSubType* psubtype, uint8_t** ppData, uint32_
mDeleteCount++;
}
- if (mDataQueue.Get(&pEntry) && pEntry != nullptr &&
+ if (mDataQueue.Get(&pEntry) &&
(pEntry->nTimestamp == mCurrPlayingTS || bForceToPlay ||
(pEntry->nTimestamp < TS_ROUND_QUARD && mCurrPlayingTS > 0xFFFF)))
{
@@ -648,31 +487,17 @@ bool AudioJitterBuffer::Get(ImsMediaSubType* psubtype, uint8_t** ppData, uint32_
if (pnSeqNum)
*pnSeqNum = pEntry->nSeqNum;
- mIsReceivedFirst = true;
-
if (IsSID(pEntry->pbBuffer, pEntry->nBufferSize))
{
mSIDCount++;
mDtxOn = true;
- IMLOGD_PACKET0(IM_PACKET_LOG_JITTER, "[Get] Dtx On");
}
else
{
mSIDCount = 0;
- mDtxOn = false;
- IMLOGD_PACKET0(IM_PACKET_LOG_JITTER, "[Get] Dtx Off");
}
- IMLOGD_PACKET7(IM_PACKET_LOG_JITTER,
- "[Get] OK - dtx mode[%d], curTS[%d], seq[%d], Mark[%d], TS[%d], buffer[%d], "
- "size[%d]",
- mDtxOn, mCurrPlayingTS, pEntry->nSeqNum, pEntry->bMark, pEntry->nTimestamp,
- pEntry->nBufferSize, mDataQueue.GetCount());
-
- mCurrPlayingTS = pEntry->nTimestamp + 20;
- mCurrPlayingSeq = pEntry->nSeqNum + 1;
-
- if (mLastPlayedSeqNum > 0)
+ if (mFirstFrameReceived)
{
/** Report the loss gap if the loss gap is over 0 */
uint16_t lostGap = GET_SEQ_GAP(pEntry->nSeqNum, mLastPlayedSeqNum);
@@ -686,19 +511,28 @@ bool AudioJitterBuffer::Get(ImsMediaSubType* psubtype, uint8_t** ppData, uint32_
}
}
+ IMLOGD_PACKET7(IM_PACKET_LOG_JITTER,
+ "[Get] OK - dtx[%d], curTS[%u], seq[%d], mark[%d], TS[%u], size[%d], queue[%d]",
+ mDtxOn, mCurrPlayingTS, pEntry->nSeqNum, pEntry->bMark, pEntry->nTimestamp,
+ pEntry->nBufferSize, mDataQueue.GetCount());
+
+ mCurrPlayingTS = pEntry->nTimestamp + FRAME_INTERVAL;
+ mCurrPlayingSeq = pEntry->nSeqNum + 1;
+ mFirstFrameReceived = true;
mLastPlayedSeqNum = pEntry->nSeqNum;
- mCanNotGetCount = 0;
+ mCannotGetCount = 0;
CollectRxRtpStatus(pEntry->nSeqNum, kRtpStatusNormal);
- CollectJitterBufferStatus(mCurrJitterBufferSize * 20, mMaxJitterBufferSize * 20);
+ CollectJitterBufferStatus(
+ mCurrJitterBufferSize * FRAME_INTERVAL, mMaxJitterBufferSize * FRAME_INTERVAL);
return true;
}
else
{
// TODO: check EVS redundancy in channel aware mode
- if (mDtxOn == false)
+ if (!mDtxOn)
{
- mCanNotGetCount++;
+ mCannotGetCount++;
}
if (psubtype)
@@ -717,18 +551,16 @@ bool AudioJitterBuffer::Get(ImsMediaSubType* psubtype, uint8_t** ppData, uint32_
IMLOGD_PACKET2(IM_PACKET_LOG_JITTER, "[Get] fail - dtx mode[%d], curTS[%d]", mDtxOn,
mCurrPlayingTS);
- mCurrPlayingTS += 20;
- mCurrPlayingSeq += 1;
+ mCurrPlayingTS += FRAME_INTERVAL;
+ mCurrPlayingSeq++;
return false;
}
return false;
}
-bool AudioJitterBuffer::IsSID(uint8_t* pbBuffer, uint32_t nBufferSize)
+bool AudioJitterBuffer::IsSID(uint8_t* /*pbBuffer*/, uint32_t nBufferSize)
{
- // remove warning
- (void)pbBuffer;
switch (mCodecType)
{
case kAudioCodecAmr:
diff --git a/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/audio/AudioSession.cpp b/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/audio/AudioSession.cpp
index 5262cd15..13367521 100644
--- a/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/audio/AudioSession.cpp
+++ b/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/audio/AudioSession.cpp
@@ -123,6 +123,16 @@ ImsMediaResult AudioSession::startGraph(RtpConfig* config)
return RESULT_INVALID_PARAM;
}
+ IMLOGI1("[startGraph] state[%d]", getState());
+
+ if (mMediaQualityAnalyzer != nullptr &&
+ !mMediaQualityAnalyzer->isSameConfig(reinterpret_cast<AudioConfig*>(config)))
+ {
+ mMediaQualityAnalyzer->stop();
+ mMediaQualityAnalyzer->setConfig(reinterpret_cast<AudioConfig*>(config));
+ mMediaQualityAnalyzer->start();
+ }
+
ImsMediaResult ret = RESULT_NOT_READY;
IMLOGD1("[startGraph] mListGraphRtpTx size[%d]", mListGraphRtpTx.size());
@@ -230,17 +240,6 @@ ImsMediaResult AudioSession::startGraph(RtpConfig* config)
}
}
- // TODO : check that the timing is correct
- IMLOGI1("[startGraph] state[%d]", getState());
-
- if (mMediaQualityAnalyzer != nullptr &&
- !mMediaQualityAnalyzer->isSameConfig(reinterpret_cast<AudioConfig*>(config)))
- {
- mMediaQualityAnalyzer->stop();
- mMediaQualityAnalyzer->setConfig(reinterpret_cast<AudioConfig*>(config));
- mMediaQualityAnalyzer->start();
- }
-
return ret;
}
diff --git a/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/audio/MediaQualityAnalyzer.cpp b/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/audio/MediaQualityAnalyzer.cpp
index c8fc8850..55c2568b 100644
--- a/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/audio/MediaQualityAnalyzer.cpp
+++ b/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/audio/MediaQualityAnalyzer.cpp
@@ -36,6 +36,7 @@
MediaQualityAnalyzer::MediaQualityAnalyzer()
{
+ mTimeStarted = 0;
mCodecType = 0;
mCodecAttribute = 0;
mCallback = nullptr;
@@ -118,7 +119,7 @@ void MediaQualityAnalyzer::start()
IMLOGD0("[start]");
mCallQuality.setCodecType(convertAudioCodecType(
mCodecType, ImsMediaAudioUtil::FindMaxEvsBandwidthFromRange(mCodecAttribute)));
-
+ mTimeStarted = ImsMediaTimer::GetTimeInMilliSeconds();
StartThread();
}
@@ -130,13 +131,7 @@ void MediaQualityAnalyzer::stop()
{
StopThread();
mConditionExit.wait_timeout(STOP_TIMEOUT);
-
- if (mCallback != nullptr)
- {
- IMLOGD0("[notifyCallQuality]");
- CallQuality* quality = new CallQuality(mCallQuality);
- mCallback->SendEvent(kAudioCallQualityChangedInd, reinterpret_cast<uint64_t>(quality));
- }
+ notifyCallQuality();
}
reset();
@@ -290,6 +285,20 @@ void MediaQualityAnalyzer::collectRxRtpStatus(
mRtcpXrEncoder->stackRxRtpStatus(packet->status, delay);
IMLOGD_PACKET3(IM_PACKET_LOG_RTP, "[collectRxRtpStatus] seq[%d], status[%d], delay[%u]",
seq, packet->status, delay);
+
+ // set the max playout delay
+ if (delay > mCallQuality.getMaxPlayoutDelayMillis())
+ {
+ mCallQuality.setMaxPlayoutDelayMillis(delay);
+ }
+
+ // set the min playout delay
+ if (delay < mCallQuality.getMinPlayoutDelayMillis() ||
+ mCallQuality.getMinPlayoutDelayMillis() == 0)
+ {
+ mCallQuality.setMinPlayoutDelayMillis(delay);
+ }
+
found = true;
break;
}
@@ -354,18 +363,9 @@ void MediaQualityAnalyzer::processData(const int32_t timeCount)
mCallQuality.getNumRtpPacketsReceived() == 0)
{
mCallQuality.setRtpInactivityDetected(true);
-
- if (mCallback != nullptr)
- {
- IMLOGD0("[notifyCallQuality]");
- CallQuality* callQuality = new CallQuality(mCallQuality);
- mCallback->SendEvent(
- kAudioCallQualityChangedInd, reinterpret_cast<uint64_t>(callQuality));
- }
+ notifyCallQuality();
}
- mCallQuality.setCallDuration(mCallQuality.getCallDuration() + TIMER_INTERVAL);
-
// call quality packet loss
if (timeCount % CALL_QUALITY_MONITORING_TIME == 0)
{
@@ -383,14 +383,7 @@ void MediaQualityAnalyzer::processData(const int32_t timeCount)
if (mCallQuality.getDownlinkCallQualityLevel() != quality)
{
mCallQuality.setDownlinkCallQualityLevel(quality);
-
- if (mCallback != nullptr)
- {
- IMLOGD0("[notifyCallQuality]");
- CallQuality* callQuality = new CallQuality(mCallQuality);
- mCallback->SendEvent(
- kAudioCallQualityChangedInd, reinterpret_cast<uint64_t>(callQuality));
- }
+ notifyCallQuality();
}
mCallQualityNumLostPacket = 0;
@@ -528,6 +521,22 @@ void MediaQualityAnalyzer::processMediaQuality()
}
}
+void MediaQualityAnalyzer::notifyCallQuality()
+{
+ if (mCallback != nullptr)
+ {
+ mCallQuality.setCallDuration(ImsMediaTimer::GetTimeInMilliSeconds() - mTimeStarted);
+
+ IMLOGD1("[notifyCallQuality] duration[%d]", mCallQuality.getCallDuration());
+ CallQuality* callQuality = new CallQuality(mCallQuality);
+ mCallback->SendEvent(kAudioCallQualityChangedInd, reinterpret_cast<uint64_t>(callQuality));
+
+ // reset the items to keep in reporting interval
+ mCallQuality.setMinPlayoutDelayMillis(0);
+ mCallQuality.setMaxPlayoutDelayMillis(0);
+ }
+}
+
void MediaQualityAnalyzer::notifyMediaQualityStatus()
{
IMLOGD0("[notifyMediaQualityStatus]");
diff --git a/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/audio/nodes/IAudioPlayerNode.cpp b/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/audio/nodes/IAudioPlayerNode.cpp
index 240861ff..7488c67e 100644
--- a/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/audio/nodes/IAudioPlayerNode.cpp
+++ b/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/audio/nodes/IAudioPlayerNode.cpp
@@ -137,9 +137,9 @@ void IAudioPlayerNode::SetConfig(void* config)
mSamplingRate = mConfig->getSamplingRateKHz();
SetJitterBufferSize(4, 4, 9);
- SetJitterOptions(80, 1, (double)25 / 10,
- false, /** TODO: when enable DTX, set this true on condition*/
- true);
+ SetJitterOptions(
+ 80, 1, (double)25 / 10, false /** TODO: when enable DTX, set this true on condition*/
+ );
}
bool IAudioPlayerNode::IsSameConfig(void* config)
diff --git a/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/include/BaseJitterBuffer.h b/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/include/BaseJitterBuffer.h
index 1883aecf..76225875 100644
--- a/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/include/BaseJitterBuffer.h
+++ b/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/include/BaseJitterBuffer.h
@@ -41,8 +41,8 @@ public:
*/
virtual void SetCodecType(uint32_t type);
virtual void SetJitterBufferSize(uint32_t nInit, uint32_t nMin, uint32_t nMax);
- virtual void SetJitterOptions(uint32_t nReduceTH, uint32_t nStepSize, double zValue,
- bool bIgnoreSID, bool bImprovement);
+ virtual void SetJitterOptions(
+ uint32_t nReduceTH, uint32_t nStepSize, double zValue, bool bIgnoreSID);
virtual uint32_t GetCount();
virtual void Reset();
virtual void Delete();
@@ -62,6 +62,7 @@ public:
*/
virtual void Add(ImsMediaSubType subtype, uint8_t* data, uint32_t dataSize, uint32_t timestamp,
bool mark, uint32_t seq,
+ /** TODO: remove deprecated argument dataType */
ImsMediaSubType dataType = ImsMediaSubType::MEDIASUBTYPE_UNDEFINED,
uint32_t arrivalTime = 0) = 0;
@@ -75,11 +76,10 @@ public:
* @param timestamp The timestamp of data, it can be milliseconds unit or rtp timestamp unit
* @param mark It is true when the data has marker bit set
* @param seq The sequence number of data. it is 0 when there is no valid sequence number set
- * @param pnChecker
+ * @param currentTime The current timestamp of this method invoked with milliseconds unit
*/
virtual bool Get(ImsMediaSubType* psubtype, uint8_t** ppData, uint32_t* pnDataSize,
- uint32_t* ptimestamp, bool* pmark, uint32_t* pnSeqNum,
- uint32_t* pnChecker = nullptr) = 0;
+ uint32_t* ptimestamp, bool* pmark, uint32_t* pnSeqNum, uint32_t currentTime) = 0;
protected:
BaseSessionCallback* mCallback;
diff --git a/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/include/ImsMediaDefine.h b/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/include/ImsMediaDefine.h
index a445059e..045051c1 100644
--- a/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/include/ImsMediaDefine.h
+++ b/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/include/ImsMediaDefine.h
@@ -26,10 +26,6 @@
#define USHORT_SEQ_ROUND_COMPARE(a, b) \
((((a) >= (b)) && (((b) >= SEQ_ROUND_QUARD) || (((a) <= 0xffff - SEQ_ROUND_QUARD)))) || \
(((a) <= SEQ_ROUND_QUARD) && ((b) >= 0xffff - SEQ_ROUND_QUARD)))
-#define TS_ROUND_QUARD 3000
-#define USHORT_TS_ROUND_COMPARE(a, b) \
- (((a) >= (b) && (b) >= TS_ROUND_QUARD) || ((a) <= 0xffff - TS_ROUND_QUARD) || \
- ((a) <= TS_ROUND_QUARD && (b) >= 0xffff - TS_ROUND_QUARD))
#define IMS_MEDIA_WORD_SIZE 4
using namespace android::telephony::imsmedia;
diff --git a/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/include/audio/AudioJitterBuffer.h b/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/include/audio/AudioJitterBuffer.h
index 2ab210ce..001588fc 100644
--- a/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/include/audio/AudioJitterBuffer.h
+++ b/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/include/audio/AudioJitterBuffer.h
@@ -27,38 +27,32 @@ public:
virtual ~AudioJitterBuffer();
virtual void Reset();
virtual void SetJitterBufferSize(uint32_t nInit, uint32_t nMin, uint32_t nMax);
- void SetJitterOptions(uint32_t nReduceTH, uint32_t nStepSize, double zValue, bool bIgnoreSID,
- bool bImprovement);
+ void SetJitterOptions(uint32_t nReduceTH, uint32_t nStepSize, double zValue, bool bIgnoreSID);
virtual void Add(ImsMediaSubType subtype, uint8_t* pbBuffer, uint32_t nBufferSize,
uint32_t nTimestamp, bool bMark, uint32_t nSeqNum,
ImsMediaSubType nDataType = ImsMediaSubType::MEDIASUBTYPE_UNDEFINED,
uint32_t arrivalTime = 0);
virtual bool Get(ImsMediaSubType* psubtype, uint8_t** ppData, uint32_t* pnDataSize,
- uint32_t* pnTimestamp, bool* pbMark, uint32_t* pnSeqNum, uint32_t* pnChecker = nullptr);
+ uint32_t* pnTimestamp, bool* pbMark, uint32_t* pnSeqNum, uint32_t currentTime);
private:
bool IsSID(uint8_t* pbBuffer, uint32_t nBufferSize);
void CollectRxRtpStatus(int32_t seq, kRtpPacketStatus status);
void CollectJitterBufferStatus(int32_t currSize, int32_t maxSize);
- JitterNetworkAnalyser mJitterAnalyser;
+ JitterNetworkAnalyser mJitterAnalyzer;
bool mDtxOn;
- bool mBufferImprovement;
bool mBufferIgnoreSIDPacket;
bool mNeedToUpdateBasePacket;
- bool mIsReceivedFirst;
bool mWaiting;
- bool mFourceToUpdateJitterBuffer;
- uint32_t mCanNotGetCount;
+ bool mEnforceUpdate;
+ uint32_t mCannotGetCount;
uint32_t mCurrPlayingTS;
uint16_t mCurrPlayingSeq;
uint32_t mBaseTimestamp;
uint32_t mBaseArrivalTime;
- uint32_t mNullDataCount;
- uint32_t mUpdateJitterBufferSize;
uint32_t mCheckUpdateJitterPacketCnt;
uint32_t mCurrJitterBufferSize;
- uint32_t mBufferUpdateDuration;
uint32_t mSIDCount;
uint32_t mDeleteCount;
uint32_t mNextJitterBufferSize;
diff --git a/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/include/audio/MediaQualityAnalyzer.h b/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/include/audio/MediaQualityAnalyzer.h
index 29f0bb48..f83ea088 100644
--- a/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/include/audio/MediaQualityAnalyzer.h
+++ b/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/include/audio/MediaQualityAnalyzer.h
@@ -229,6 +229,7 @@ protected:
*/
void processData(const int32_t timeCount);
void processMediaQuality();
+ void notifyCallQuality();
void notifyMediaQualityStatus();
void AddEvent(uint32_t event, uint64_t paramA, uint64_t paramB);
void processEvent(uint32_t event, uint64_t paramA, uint64_t paramB);
@@ -247,6 +248,8 @@ protected:
std::list<LostPacket*> mListLostPacket;
/** The list of the packets sent */
std::list<RtpPacket*> mListTxPacket;
+ /** The time of call started in milliseconds unit*/
+ int32_t mTimeStarted;
/** The ssrc of the receiving Rtp stream to identify */
int32_t mSSRC;
/** The codec type of the audio session retrieved from the AudioConfig.h */
diff --git a/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/include/nodes/JitterBufferControlNode.h b/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/include/nodes/JitterBufferControlNode.h
index e794ce13..68ee9db1 100644
--- a/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/include/nodes/JitterBufferControlNode.h
+++ b/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/include/nodes/JitterBufferControlNode.h
@@ -27,8 +27,7 @@ public:
BaseSessionCallback* callback = nullptr, ImsMediaType type = IMS_MEDIA_AUDIO);
virtual ~JitterBufferControlNode();
void SetJitterBufferSize(uint32_t nInit, uint32_t nMin, uint32_t nMax);
- void SetJitterOptions(uint32_t nReduceTH, uint32_t nStepSize, double zValue, bool bIgnoreSID,
- bool bImprovement);
+ void SetJitterOptions(uint32_t nReduceTH, uint32_t nStepSize, double zValue, bool bIgnoreSID);
void Reset();
virtual uint32_t GetDataCount();
virtual void OnDataFromFrontNode(ImsMediaSubType subtype, uint8_t* pData, uint32_t nDataSize,
diff --git a/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/include/text/TextJitterBuffer.h b/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/include/text/TextJitterBuffer.h
index 0cab794c..f744d5fc 100644
--- a/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/include/text/TextJitterBuffer.h
+++ b/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/include/text/TextJitterBuffer.h
@@ -30,7 +30,7 @@ public:
ImsMediaSubType dataType = ImsMediaSubType::MEDIASUBTYPE_UNDEFINED,
uint32_t arrivalTime = 0);
virtual bool Get(ImsMediaSubType* subtype, uint8_t** data, uint32_t* dataSize,
- uint32_t* timestamp, bool* mark, uint32_t* seqNum, uint32_t* checker = nullptr);
+ uint32_t* timestamp, bool* mark, uint32_t* seqNum, uint32_t currentTime);
virtual void Delete();
};
diff --git a/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/include/video/VideoJitterBuffer.h b/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/include/video/VideoJitterBuffer.h
index 9319e3fd..104b7cea 100644
--- a/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/include/video/VideoJitterBuffer.h
+++ b/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/include/video/VideoJitterBuffer.h
@@ -44,8 +44,8 @@ public:
virtual void Add(ImsMediaSubType subtype, uint8_t* pbBuffer, uint32_t nBufferSize,
uint32_t nTimeStamp, bool mark, uint32_t nSeqNum, ImsMediaSubType nDataType,
uint32_t arrivalTime);
- virtual bool Get(ImsMediaSubType* pImsMediaSubType, uint8_t** ppData, uint32_t* pnDataSize,
- uint32_t* pnTimeStamp, bool* pmark, uint32_t* pnSeqNum, uint32_t* pnChecker = nullptr);
+ virtual bool Get(ImsMediaSubType* psubtype, uint8_t** ppData, uint32_t* pnDataSize,
+ uint32_t* ptimestamp, bool* pmark, uint32_t* pnSeqNum, uint32_t currentTime);
/**
* @brief Set the video codec type
diff --git a/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/nodes/JitterBufferControlNode.cpp b/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/nodes/JitterBufferControlNode.cpp
index 76b82284..35caa337 100644
--- a/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/nodes/JitterBufferControlNode.cpp
+++ b/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/nodes/JitterBufferControlNode.cpp
@@ -18,7 +18,7 @@
#include <AudioJitterBuffer.h>
#include <VideoJitterBuffer.h>
#include <TextJitterBuffer.h>
-#include <ImsMediaTrace.h>
+#include <ImsMediaTimer.h>
JitterBufferControlNode::JitterBufferControlNode(BaseSessionCallback* callback, ImsMediaType type) :
BaseNode(callback),
@@ -50,8 +50,6 @@ JitterBufferControlNode::~JitterBufferControlNode()
void JitterBufferControlNode::SetJitterBufferSize(uint32_t nInit, uint32_t nMin, uint32_t nMax)
{
- IMLOGD3("[SetJitterBufferSize] init[%d], min[%d], max[%d]", nInit, nMin, nMax);
-
if (mJitterBuffer)
{
mJitterBuffer->SetJitterBufferSize(nInit, nMin, nMax);
@@ -59,21 +57,16 @@ void JitterBufferControlNode::SetJitterBufferSize(uint32_t nInit, uint32_t nMin,
}
void JitterBufferControlNode::SetJitterOptions(
- uint32_t nReduceTH, uint32_t nStepSize, double zValue, bool bIgnoreSID, bool bImprovement)
+ uint32_t nReduceTH, uint32_t nStepSize, double zValue, bool bIgnoreSID)
{
- IMLOGD5("[SetJitterOptions] nReduceTH[%d], nStepSize[%d], zValue[%lf], bSID[%d], bImprove[%d]",
- nReduceTH, nStepSize, zValue, bIgnoreSID, bImprovement);
-
if (mJitterBuffer)
{
- mJitterBuffer->SetJitterOptions(nReduceTH, nStepSize, zValue, bIgnoreSID, bImprovement);
+ mJitterBuffer->SetJitterOptions(nReduceTH, nStepSize, zValue, bIgnoreSID);
}
}
void JitterBufferControlNode::Reset()
{
- IMLOGD0("[Reset]");
-
if (mJitterBuffer)
{
mJitterBuffer->Reset();
@@ -112,12 +105,20 @@ bool JitterBufferControlNode::GetData(ImsMediaSubType* pSubtype, uint8_t** ppDat
uint32_t* pnDataSize, uint32_t* pnTimestamp, bool* pbMark, uint32_t* pnSeqNum,
ImsMediaSubType* pnDataType, uint32_t* arrivalTime)
{
- (void)arrivalTime;
+ if (arrivalTime)
+ {
+ *arrivalTime = 0;
+ }
+
+ if (pnDataType)
+ {
+ *pnDataType = MEDIASUBTYPE_UNDEFINED;
+ }
if (mJitterBuffer)
{
return mJitterBuffer->Get(pSubtype, ppData, pnDataSize, pnTimestamp, pbMark, pnSeqNum,
- reinterpret_cast<uint32_t*>(pnDataType));
+ ImsMediaTimer::GetTimeInMilliSeconds());
}
return false;
diff --git a/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/text/TextJitterBuffer.cpp b/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/text/TextJitterBuffer.cpp
index b9ab83c2..beb1d015 100644
--- a/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/text/TextJitterBuffer.cpp
+++ b/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/text/TextJitterBuffer.cpp
@@ -111,9 +111,8 @@ void TextJitterBuffer::Add(ImsMediaSubType subtype, uint8_t* buffer, uint32_t si
}
bool TextJitterBuffer::Get(ImsMediaSubType* subtype, uint8_t** data, uint32_t* dataSize,
- uint32_t* timestamp, bool* mark, uint32_t* seqNum, uint32_t* checker)
+ uint32_t* timestamp, bool* mark, uint32_t* seqNum, uint32_t /*currentTime*/)
{
- (void)checker;
std::lock_guard<std::mutex> guard(mMutex);
DataEntry* pEntry;
diff --git a/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/utils/IImsMediaThread.cpp b/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/utils/IImsMediaThread.cpp
index 6134121e..816cb014 100644
--- a/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/utils/IImsMediaThread.cpp
+++ b/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/utils/IImsMediaThread.cpp
@@ -20,7 +20,7 @@
IImsMediaThread::IImsMediaThread()
{
- mThreadStopped = false;
+ mThreadStopped = true;
}
IImsMediaThread::~IImsMediaThread() {}
diff --git a/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/video/VideoJitterBuffer.cpp b/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/video/VideoJitterBuffer.cpp
index a80f1b6a..c755360d 100644
--- a/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/video/VideoJitterBuffer.cpp
+++ b/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/video/VideoJitterBuffer.cpp
@@ -306,10 +306,8 @@ void VideoJitterBuffer::Add(ImsMediaSubType subtype, uint8_t* pbBuffer, uint32_t
}
bool VideoJitterBuffer::Get(ImsMediaSubType* subtype, uint8_t** ppData, uint32_t* pnDataSize,
- uint32_t* pnTimestamp, bool* pbMark, uint32_t* pnSeqNum, uint32_t* pnChecker)
+ uint32_t* pnTimestamp, bool* pbMark, uint32_t* pnSeqNum, uint32_t currentTime)
{
- (void)pnChecker;
-
DataEntry* pEntry = nullptr;
bool bValidPacket = false;
std::lock_guard<std::mutex> guard(mMutex);
@@ -511,7 +509,7 @@ bool VideoJitterBuffer::Get(ImsMediaSubType* subtype, uint8_t** ppData, uint32_t
"[Get] bValid[%u], LastPlayedTS[%u], Seq[%u], LastPlayedSeq[%u]", pEntry->bValid,
mLastPlayedTimestamp, pEntry->nSeqNum, mLastPlayedSeqNum);
- uint32_t nCurrTime = ImsMediaTimer::GetTimeInMilliSeconds();
+ uint32_t nCurrTime = currentTime;
if (mLastPlayedTimestamp == 0 || mLastPlayedTime == 0 ||
pEntry->nTimestamp == mLastPlayedTimestamp)
diff --git a/tests/native/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/audio/AudioJitterBufferTest.cpp b/tests/native/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/audio/AudioJitterBufferTest.cpp
new file mode 100644
index 00000000..5d1f19cb
--- /dev/null
+++ b/tests/native/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/audio/AudioJitterBufferTest.cpp
@@ -0,0 +1,494 @@
+/**
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <gtest/gtest.h>
+#include <AudioJitterBuffer.h>
+
+#define TEST_BUFFER_SIZE 10
+#define TEST_FRAME_INTERVAL 20
+
+class AudioJitterBufferCallback : public BaseSessionCallback
+{
+public:
+ AudioJitterBufferCallback()
+ {
+ numNormal = 0;
+ numLost = 0;
+ numDuplicated = 0;
+ numDiscarded = 0;
+ }
+ virtual ~AudioJitterBufferCallback() {}
+
+ virtual void onEvent(int32_t type, uint64_t param1, uint64_t /*param2*/)
+ {
+ if (type == kCollectRxRtpStatus)
+ {
+ SessionCallbackParameter* param = reinterpret_cast<SessionCallbackParameter*>(param1);
+
+ if (param == nullptr)
+ {
+ return;
+ }
+
+ switch (param->param1)
+ {
+ case kRtpStatusDuplicated:
+ numDuplicated++;
+ break;
+ case kRtpStatusDiscarded:
+ numDiscarded++;
+ break;
+ case kRtpStatusNormal:
+ numNormal++;
+ break;
+ default:
+ break;
+ }
+
+ delete param;
+ }
+ else if (type == kCollectOptionalInfo)
+ {
+ SessionCallbackParameter* param = reinterpret_cast<SessionCallbackParameter*>(param1);
+
+ if (param == nullptr)
+ {
+ return;
+ }
+
+ if (param->type == kReportPacketLossGap)
+ {
+ numLost += param->param2;
+ }
+
+ delete param;
+ }
+ }
+
+ int32_t getNumNormal() { return numNormal; }
+ int32_t getNumLost() { return numLost; }
+ int32_t getNumDuplicated() { return numDuplicated; }
+ int32_t getNumDiscarded() { return numDiscarded; }
+
+private:
+ int32_t numNormal;
+ int32_t numLost;
+ int32_t numDuplicated;
+ int32_t numDiscarded;
+};
+
+class AudioJitterBufferTest : public ::testing::Test
+{
+public:
+ AudioJitterBufferTest() {}
+ virtual ~AudioJitterBufferTest() {}
+
+protected:
+ AudioJitterBuffer* mJitterBuffer;
+ AudioJitterBufferCallback mCallback;
+ int32_t mStartJitterBufferSize;
+ int32_t mMinJitterBufferSize;
+ int32_t mMaxJitterBufferSize;
+
+ virtual void SetUp() override
+ {
+ mStartJitterBufferSize = 4;
+ mMinJitterBufferSize = 4;
+ mMaxJitterBufferSize = 9;
+
+ mJitterBuffer = new AudioJitterBuffer();
+ mJitterBuffer->SetCodecType(kAudioCodecAmr);
+ mJitterBuffer->SetSessionCallback(&mCallback);
+ mJitterBuffer->SetJitterBufferSize(
+ mStartJitterBufferSize, mMinJitterBufferSize, mMaxJitterBufferSize);
+ mJitterBuffer->SetJitterOptions(80, 1, 2.5f, false);
+ }
+
+ virtual void TearDown() override { delete mJitterBuffer; }
+};
+
+TEST_F(AudioJitterBufferTest, TestNormalAddGet)
+{
+ const int32_t kNumFrames = 50;
+ char buffer[TEST_BUFFER_SIZE] = {"\x1"};
+ int32_t countGet = 0;
+ int32_t countGetFrame = 0;
+ int32_t countNotGet = 0;
+ int32_t getTime = 0;
+
+ ImsMediaSubType subtype = MEDIASUBTYPE_UNDEFINED;
+ uint8_t* data = nullptr;
+ uint32_t size = 0;
+ uint32_t timestamp = 0;
+ bool mark = false;
+ uint32_t seq = 0;
+
+ for (int32_t i = 0; i < kNumFrames; i++)
+ {
+ int32_t addTime = i * TEST_FRAME_INTERVAL;
+ mJitterBuffer->Add(MEDIASUBTYPE_UNDEFINED, reinterpret_cast<uint8_t*>(buffer), 1,
+ i * TEST_FRAME_INTERVAL, false, i, MEDIASUBTYPE_UNDEFINED, addTime);
+
+ getTime = countGet * TEST_FRAME_INTERVAL;
+
+ if (mJitterBuffer->Get(&subtype, &data, &size, &timestamp, &mark, &seq, getTime))
+ {
+ EXPECT_EQ(size, 1);
+ EXPECT_EQ(timestamp, countGetFrame * TEST_FRAME_INTERVAL);
+ EXPECT_EQ(seq, countGetFrame);
+ mJitterBuffer->Delete();
+ countGetFrame++;
+ }
+ else
+ {
+ countNotGet++;
+ }
+
+ countGet++;
+ }
+
+ while (mJitterBuffer->GetCount() > 0)
+ {
+ getTime = countGet * TEST_FRAME_INTERVAL;
+
+ if (mJitterBuffer->Get(&subtype, &data, &size, &timestamp, &mark, &seq, getTime))
+ {
+ EXPECT_EQ(size, 1);
+ EXPECT_EQ(timestamp, countGetFrame * TEST_FRAME_INTERVAL);
+ EXPECT_EQ(seq, countGetFrame);
+ mJitterBuffer->Delete();
+ countGetFrame++;
+ }
+ else
+ {
+ countNotGet++;
+ }
+
+ countGet++;
+ }
+
+ EXPECT_EQ(countNotGet, mStartJitterBufferSize);
+ EXPECT_EQ(mCallback.getNumNormal(), kNumFrames);
+}
+
+TEST_F(AudioJitterBufferTest, TestNormalAddGetSeqRounding)
+{
+ const int32_t kNumFrames = 20;
+ char buffer[TEST_BUFFER_SIZE] = {"\x1"};
+ int32_t countGet = 0;
+ int32_t countGetFrame = 0;
+ int32_t countNotGet = 0;
+ int32_t getTime = 0;
+
+ ImsMediaSubType subtype = MEDIASUBTYPE_UNDEFINED;
+ uint8_t* data = nullptr;
+ uint32_t size = 0;
+ uint32_t timestamp = 0;
+ bool mark = false;
+ uint32_t seq = 0;
+ uint16_t startSeq = 65530;
+ uint16_t addSeq = 0;
+ uint16_t getSeq = 0;
+
+ for (int32_t i = 0; i < kNumFrames; i++)
+ {
+ addSeq = startSeq + (uint16_t)i;
+ int32_t addTime = i * TEST_FRAME_INTERVAL;
+ mJitterBuffer->Add(MEDIASUBTYPE_UNDEFINED, reinterpret_cast<uint8_t*>(buffer), 1,
+ i * TEST_FRAME_INTERVAL, false, addSeq, MEDIASUBTYPE_UNDEFINED, addTime);
+
+ getTime = countGet * TEST_FRAME_INTERVAL;
+
+ if (mJitterBuffer->Get(&subtype, &data, &size, &timestamp, &mark, &seq, getTime))
+ {
+ getSeq = startSeq + (uint16_t)countGetFrame;
+ EXPECT_EQ(size, 1);
+ EXPECT_EQ(timestamp, countGetFrame * TEST_FRAME_INTERVAL);
+ EXPECT_EQ(seq, getSeq);
+ mJitterBuffer->Delete();
+ countGetFrame++;
+ }
+ else
+ {
+ countNotGet++;
+ }
+ countGet++;
+ }
+
+ while (mJitterBuffer->GetCount() > 0)
+ {
+ getTime = countGet * TEST_FRAME_INTERVAL;
+
+ if (mJitterBuffer->Get(&subtype, &data, &size, &timestamp, &mark, &seq, getTime))
+ {
+ getSeq = startSeq + (uint16_t)countGetFrame;
+ EXPECT_EQ(size, 1);
+ EXPECT_EQ(timestamp, countGetFrame * TEST_FRAME_INTERVAL);
+ EXPECT_EQ(seq, getSeq);
+ mJitterBuffer->Delete();
+ countGetFrame++;
+ }
+ else
+ {
+ countNotGet++;
+ }
+
+ countGet++;
+ }
+
+ EXPECT_EQ(countNotGet, mStartJitterBufferSize);
+ EXPECT_EQ(mCallback.getNumNormal(), kNumFrames);
+}
+
+TEST_F(AudioJitterBufferTest, TestNormalAddGetTimestampRounding)
+{
+ const int32_t kNumFrames = 50;
+ char buffer[TEST_BUFFER_SIZE] = {"\x1"};
+ int32_t countGet = 0;
+ int32_t countGetFrame = 0;
+ int32_t countNotGet = 0;
+ int32_t getTime = 0;
+
+ ImsMediaSubType subtype = MEDIASUBTYPE_UNDEFINED;
+ uint8_t* data = nullptr;
+ uint32_t size = 0;
+ uint32_t timestamp = 0;
+ bool mark = false;
+ uint32_t seq = 0;
+ uint32_t startTimestamp = 4294967295 - 200;
+ uint32_t addTimestamp = 0;
+ uint32_t getTimestamp = 0;
+
+ for (int32_t i = 0; i < kNumFrames; i++)
+ {
+ addTimestamp = startTimestamp + i * TEST_FRAME_INTERVAL;
+ int32_t addTime = i * TEST_FRAME_INTERVAL;
+ mJitterBuffer->Add(MEDIASUBTYPE_UNDEFINED, reinterpret_cast<uint8_t*>(buffer), 1,
+ addTimestamp, false, i, MEDIASUBTYPE_UNDEFINED, addTime);
+
+ getTime = countGet * TEST_FRAME_INTERVAL;
+
+ if (mJitterBuffer->Get(&subtype, &data, &size, &timestamp, &mark, &seq, getTime))
+ {
+ getTimestamp = startTimestamp + countGetFrame * TEST_FRAME_INTERVAL;
+ EXPECT_EQ(size, 1);
+ EXPECT_EQ(timestamp, getTimestamp);
+ EXPECT_EQ(seq, countGetFrame);
+ mJitterBuffer->Delete();
+ countGetFrame++;
+ }
+ else
+ {
+ countNotGet++;
+ }
+
+ countGet++;
+ }
+
+ while (mJitterBuffer->GetCount() > 0)
+ {
+ getTime = countGet * TEST_FRAME_INTERVAL;
+
+ if (mJitterBuffer->Get(&subtype, &data, &size, &timestamp, &mark, &seq, getTime))
+ {
+ getTimestamp = startTimestamp + countGetFrame * TEST_FRAME_INTERVAL;
+ EXPECT_EQ(size, 1);
+ EXPECT_EQ(timestamp, getTimestamp);
+ EXPECT_EQ(seq, countGetFrame);
+ mJitterBuffer->Delete();
+ countGetFrame++;
+ }
+ else
+ {
+ countNotGet++;
+ }
+
+ countGet++;
+ }
+
+ EXPECT_EQ(countNotGet, mStartJitterBufferSize);
+ EXPECT_EQ(mCallback.getNumNormal(), kNumFrames);
+}
+
+TEST_F(AudioJitterBufferTest, TestAddGetDuplicatedSeqDetection)
+{
+ const int32_t kNumFrames = 20;
+ char buffer[TEST_BUFFER_SIZE] = {"\x1"};
+ int32_t countGet = 0;
+ int32_t countGetFrame = 0;
+ int32_t countNotGet = 0;
+ int32_t getTime = 0;
+
+ ImsMediaSubType subtype = MEDIASUBTYPE_UNDEFINED;
+ uint8_t* data = nullptr;
+ uint32_t size = 0;
+ uint32_t timestamp = 0;
+ bool mark = false;
+ uint32_t seq = 0;
+ uint16_t startSeq = 0;
+ uint16_t addSeq = 0;
+ uint16_t getSeq = 0;
+
+ for (int32_t i = 0; i < kNumFrames; i++)
+ {
+ addSeq = startSeq + (uint16_t)i;
+ int32_t addTime = i * TEST_FRAME_INTERVAL;
+ mJitterBuffer->Add(MEDIASUBTYPE_UNDEFINED, reinterpret_cast<uint8_t*>(buffer), 1,
+ i * TEST_FRAME_INTERVAL, false, addSeq, MEDIASUBTYPE_UNDEFINED, addTime);
+
+ if (i == 5)
+ {
+ mJitterBuffer->Add(MEDIASUBTYPE_UNDEFINED, reinterpret_cast<uint8_t*>(buffer), 1,
+ i * TEST_FRAME_INTERVAL, false, addSeq, MEDIASUBTYPE_UNDEFINED, addTime);
+ }
+
+ getTime = countGet * TEST_FRAME_INTERVAL;
+
+ if (mJitterBuffer->Get(&subtype, &data, &size, &timestamp, &mark, &seq, getTime))
+ {
+ getSeq = startSeq + (uint16_t)countGetFrame;
+ EXPECT_EQ(size, 1);
+ EXPECT_EQ(timestamp, countGetFrame * TEST_FRAME_INTERVAL);
+ EXPECT_EQ(seq, getSeq);
+ mJitterBuffer->Delete();
+ countGetFrame++;
+ }
+ else
+ {
+ countNotGet++;
+ }
+
+ countGet++;
+ }
+
+ while (mJitterBuffer->GetCount() > 0)
+ {
+ getTime = countGet * TEST_FRAME_INTERVAL;
+
+ if (mJitterBuffer->Get(&subtype, &data, &size, &timestamp, &mark, &seq, getTime))
+ {
+ getSeq = startSeq + (uint16_t)countGetFrame;
+ EXPECT_EQ(size, 1);
+ EXPECT_EQ(timestamp, countGetFrame * TEST_FRAME_INTERVAL);
+ EXPECT_EQ(seq, getSeq);
+ mJitterBuffer->Delete();
+ countGetFrame++;
+ }
+ else
+ {
+ countNotGet++;
+ }
+
+ countGet++;
+ }
+
+ EXPECT_EQ(mCallback.getNumLost(), 0);
+ EXPECT_EQ(mCallback.getNumDuplicated(), 1);
+ EXPECT_EQ(mCallback.getNumDiscarded(), 0);
+ EXPECT_EQ(countNotGet, mStartJitterBufferSize);
+ EXPECT_EQ(mCallback.getNumNormal(), kNumFrames);
+}
+
+TEST_F(AudioJitterBufferTest, TestAddGetInBurstIncoming)
+{
+ const int32_t kNumFrames = 20;
+ char buffer[TEST_BUFFER_SIZE] = {"\x1"};
+ int32_t countGet = 0;
+ int32_t countGetFrame = 0;
+ int32_t countNotGet = 0;
+ int32_t getTime = 0;
+
+ ImsMediaSubType subtype = MEDIASUBTYPE_UNDEFINED;
+ uint8_t* data = nullptr;
+ uint32_t size = 0;
+ uint32_t timestamp = 0;
+ bool mark = false;
+ uint32_t seq = 0;
+ uint16_t startSeq = 0;
+ uint16_t addSeq = startSeq;
+ uint16_t getSeq = startSeq;
+ uint32_t addTimestamp = 0;
+
+ int32_t addTime = 0;
+ int iter = 0;
+
+ while (addSeq < kNumFrames)
+ {
+ if (iter > 5 && iter < 10) // not added for 4 frame interval
+ {
+ addTime += TEST_FRAME_INTERVAL;
+ }
+ else if (iter >= 10 && iter < 15) // 5 frames burst added
+ {
+ mJitterBuffer->Add(MEDIASUBTYPE_UNDEFINED, reinterpret_cast<uint8_t*>(buffer), 1,
+ addTimestamp, false, addSeq++, MEDIASUBTYPE_UNDEFINED, addTime);
+ addTime += 1; // 1ms burst
+ addTimestamp += TEST_FRAME_INTERVAL;
+ }
+ else // normal
+ {
+ mJitterBuffer->Add(MEDIASUBTYPE_UNDEFINED, reinterpret_cast<uint8_t*>(buffer), 1,
+ addTimestamp, false, addSeq++, MEDIASUBTYPE_UNDEFINED, addTime);
+ addTime += TEST_FRAME_INTERVAL;
+ addTimestamp += TEST_FRAME_INTERVAL;
+ }
+
+ iter++;
+ getTime = countGet * TEST_FRAME_INTERVAL;
+
+ if (mJitterBuffer->Get(&subtype, &data, &size, &timestamp, &mark, &seq, getTime))
+ {
+ EXPECT_EQ(size, 1);
+ EXPECT_EQ(timestamp, countGetFrame * TEST_FRAME_INTERVAL);
+ EXPECT_EQ(seq, getSeq++);
+ mJitterBuffer->Delete();
+ countGetFrame++;
+ }
+ else
+ {
+ countNotGet++;
+ }
+
+ countGet++;
+ }
+
+ while (mJitterBuffer->GetCount() > 0)
+ {
+ getTime = countGet * TEST_FRAME_INTERVAL;
+
+ if (mJitterBuffer->Get(&subtype, &data, &size, &timestamp, &mark, &seq, getTime))
+ {
+ getSeq = startSeq + (uint16_t)countGetFrame;
+ EXPECT_EQ(size, 1);
+ EXPECT_EQ(timestamp, countGetFrame * TEST_FRAME_INTERVAL);
+ EXPECT_EQ(seq, getSeq);
+ mJitterBuffer->Delete();
+ countGetFrame++;
+ }
+ else
+ {
+ countNotGet++;
+ }
+
+ countGet++;
+ }
+
+ EXPECT_EQ(mCallback.getNumLost(), 0);
+ EXPECT_EQ(mCallback.getNumDuplicated(), 0);
+ EXPECT_EQ(mCallback.getNumDiscarded(), 0);
+ EXPECT_EQ(countNotGet, mStartJitterBufferSize);
+ EXPECT_EQ(mCallback.getNumNormal(), kNumFrames);
+} \ No newline at end of file
diff --git a/tests/native/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/audio/MediaQualityAnalyzerTest.cpp b/tests/native/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/audio/MediaQualityAnalyzerTest.cpp
index a979dd4a..a94b6654 100644
--- a/tests/native/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/audio/MediaQualityAnalyzerTest.cpp
+++ b/tests/native/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/audio/MediaQualityAnalyzerTest.cpp
@@ -184,15 +184,50 @@ protected:
}
};
-TEST_F(MediaQualityAnalyzerTest, TestStartStop)
+TEST_F(MediaQualityAnalyzerTest, TestCodecType)
{
- EXPECT_CALL(mCallback, onEvent(kAudioCallQualityChangedInd, _, _)).Times(1);
+ EXPECT_CALL(mCallback, onEvent(kAudioCallQualityChangedInd, _, _)).Times(6);
mAnalyzer->start();
+ mAnalyzer->stop();
+ EXPECT_EQ(CallQuality::AUDIO_QUALITY_AMR_WB, mFakeCallback.getCallQuality().getCodecType());
+
+ mConfig.setCodecType(AudioConfig::CODEC_AMR);
+ mAnalyzer->setConfig(&mConfig);
+ mAnalyzer->start();
+ mAnalyzer->stop();
+ EXPECT_EQ(CallQuality::AUDIO_QUALITY_AMR, mFakeCallback.getCallQuality().getCodecType());
- CallQuality quality = mAnalyzer->getCallQuality();
+ mConfig.setCodecType(AudioConfig::CODEC_EVS);
+ mEvsParam.setEvsBandwidth(EvsParams::EVS_NARROW_BAND);
+ mConfig.setEvsParams(mEvsParam);
+ mAnalyzer->setConfig(&mConfig);
+ mAnalyzer->start();
+ mAnalyzer->stop();
+ EXPECT_EQ(CallQuality::AUDIO_QUALITY_EVS_NB, mFakeCallback.getCallQuality().getCodecType());
+
+ mConfig.setCodecType(AudioConfig::CODEC_EVS);
+ mEvsParam.setEvsBandwidth(EvsParams::EVS_WIDE_BAND);
+ mConfig.setEvsParams(mEvsParam);
+ mAnalyzer->setConfig(&mConfig);
+ mAnalyzer->start();
mAnalyzer->stop();
+ EXPECT_EQ(CallQuality::AUDIO_QUALITY_EVS_WB, mFakeCallback.getCallQuality().getCodecType());
- EXPECT_EQ(mFakeCallback.getCallQuality(), quality);
+ mConfig.setCodecType(AudioConfig::CODEC_EVS);
+ mEvsParam.setEvsBandwidth(EvsParams::EVS_SUPER_WIDE_BAND);
+ mConfig.setEvsParams(mEvsParam);
+ mAnalyzer->setConfig(&mConfig);
+ mAnalyzer->start();
+ mAnalyzer->stop();
+ EXPECT_EQ(CallQuality::AUDIO_QUALITY_EVS_SWB, mFakeCallback.getCallQuality().getCodecType());
+
+ mConfig.setCodecType(AudioConfig::CODEC_EVS);
+ mEvsParam.setEvsBandwidth(EvsParams::EVS_FULL_BAND);
+ mConfig.setEvsParams(mEvsParam);
+ mAnalyzer->setConfig(&mConfig);
+ mAnalyzer->start();
+ mAnalyzer->stop();
+ EXPECT_EQ(CallQuality::AUDIO_QUALITY_EVS_FB, mFakeCallback.getCallQuality().getCodecType());
}
TEST_F(MediaQualityAnalyzerTest, TestCollectTxPackets)
@@ -212,7 +247,6 @@ TEST_F(MediaQualityAnalyzerTest, TestCollectTxPackets)
EXPECT_EQ(mAnalyzer->getTxPacketSize(), numPackets);
EXPECT_EQ(mAnalyzer->getRxPacketSize(), 0);
EXPECT_EQ(mAnalyzer->getLostPacketSize(), 0);
- CallQuality quality = mAnalyzer->getCallQuality();
mAnalyzer->stop();
EXPECT_EQ(mAnalyzer->getTxPacketSize(), 0);
@@ -220,9 +254,7 @@ TEST_F(MediaQualityAnalyzerTest, TestCollectTxPackets)
EXPECT_EQ(mAnalyzer->getLostPacketSize(), 0);
// Check CallQuality value
- CallQuality quality2 = mFakeCallback.getCallQuality();
- EXPECT_EQ(quality2, quality);
- EXPECT_EQ(quality2.getNumRtpPacketsTransmitted(), numPackets);
+ EXPECT_EQ(mFakeCallback.getCallQuality().getNumRtpPacketsTransmitted(), numPackets);
}
TEST_F(MediaQualityAnalyzerTest, TestRtpInactivityNotRunning)
@@ -302,14 +334,10 @@ TEST_F(MediaQualityAnalyzerTest, TestCallQualityInactivity)
EXPECT_CALL(mCallback, onEvent(kAudioCallQualityChangedInd, _, _)).Times(2);
mAnalyzer->start();
mCondition.wait_timeout(4100); // 4.1 sec
-
- CallQuality quality = mAnalyzer->getCallQuality();
mAnalyzer->stop();
// Check CallQuality value
- CallQuality quality2 = mFakeCallback.getCallQuality();
- EXPECT_EQ(quality2, quality);
- EXPECT_TRUE(quality2.getRtpInactivityDetected());
+ EXPECT_TRUE(mFakeCallback.getCallQuality().getRtpInactivityDetected());
}
TEST_F(MediaQualityAnalyzerTest, TestCallQualityLevelChanged)
@@ -346,7 +374,6 @@ TEST_F(MediaQualityAnalyzerTest, TestCallQualityLevelChanged)
EXPECT_EQ(mAnalyzer->getTxPacketSize(), 0);
EXPECT_EQ(mAnalyzer->getRxPacketSize(), numPackets - 1);
EXPECT_EQ(mAnalyzer->getLostPacketSize(), 1);
- CallQuality quality = mAnalyzer->getCallQuality();
mAnalyzer->stop();
EXPECT_EQ(mAnalyzer->getTxPacketSize(), 0);
@@ -354,10 +381,9 @@ TEST_F(MediaQualityAnalyzerTest, TestCallQualityLevelChanged)
EXPECT_EQ(mAnalyzer->getLostPacketSize(), 0);
// Check CallQuality value
- CallQuality quality2 = mFakeCallback.getCallQuality();
- EXPECT_EQ(quality2, quality);
- EXPECT_EQ(quality2.getNumRtpPacketsReceived(), numPackets - 1);
- EXPECT_EQ(quality2.getDownlinkCallQualityLevel(), CallQuality::kCallQualityBad);
+ EXPECT_EQ(mFakeCallback.getCallQuality().getNumRtpPacketsReceived(), numPackets - 1);
+ EXPECT_EQ(mFakeCallback.getCallQuality().getDownlinkCallQualityLevel(),
+ CallQuality::kCallQualityBad);
}
TEST_F(MediaQualityAnalyzerTest, TestJitterInd)
@@ -389,17 +415,14 @@ TEST_F(MediaQualityAnalyzerTest, TestJitterInd)
EXPECT_EQ(mAnalyzer->getRxPacketSize(), numPackets);
EXPECT_EQ(mAnalyzer->getLostPacketSize(), 0);
- CallQuality quality = mAnalyzer->getCallQuality();
mAnalyzer->stop();
EXPECT_EQ(mAnalyzer->getTxPacketSize(), 0);
EXPECT_EQ(mAnalyzer->getRxPacketSize(), 0);
EXPECT_EQ(mAnalyzer->getLostPacketSize(), 0);
- CallQuality quality2 = mFakeCallback.getCallQuality();
- EXPECT_EQ(quality2, quality);
- EXPECT_EQ(quality2.getNumRtpPacketsReceived(), numPackets);
- EXPECT_EQ(quality2.getAverageRelativeJitter(), jitter);
+ EXPECT_EQ(mFakeCallback.getCallQuality().getNumRtpPacketsReceived(), numPackets);
+ EXPECT_EQ(mFakeCallback.getCallQuality().getAverageRelativeJitter(), jitter);
MediaQualityStatus status = mFakeCallback.getMediaQualityStatus();
EXPECT_EQ(status.getRtpJitterMillis(), jitter);
@@ -433,6 +456,7 @@ TEST_F(MediaQualityAnalyzerTest, TestSsrcChange)
EXPECT_EQ(mAnalyzer->getTxPacketSize(), 0);
EXPECT_EQ(mAnalyzer->getRxPacketSize(), numPackets);
EXPECT_EQ(mAnalyzer->getLostPacketSize(), 0);
+
mAnalyzer->stop();
EXPECT_EQ(mAnalyzer->getTxPacketSize(), 0);
@@ -477,16 +501,13 @@ TEST_F(MediaQualityAnalyzerTest, TestPacketLossInd)
EXPECT_EQ(mAnalyzer->getRxPacketSize(), numPackets - 1);
EXPECT_EQ(mAnalyzer->getLostPacketSize(), 1);
- CallQuality quality = mAnalyzer->getCallQuality();
mAnalyzer->stop();
EXPECT_EQ(mAnalyzer->getTxPacketSize(), 0);
EXPECT_EQ(mAnalyzer->getRxPacketSize(), 0);
EXPECT_EQ(mAnalyzer->getLostPacketSize(), 0);
- CallQuality quality2 = mFakeCallback.getCallQuality();
- EXPECT_EQ(quality2, quality);
- EXPECT_EQ(quality2.getNumRtpPacketsNotReceived(), 1);
+ EXPECT_EQ(mFakeCallback.getCallQuality().getNumRtpPacketsNotReceived(), 1);
MediaQualityStatus status = mFakeCallback.getMediaQualityStatus();
EXPECT_EQ(status.getRtpPacketLossRate(), 10);
@@ -502,6 +523,5 @@ TEST_F(MediaQualityAnalyzerTest, TestNotifyMediaQualityStatus)
mAnalyzer->start();
mCondition.wait_timeout(2100); // 2.1 sec
-
mAnalyzer->stop();
} \ No newline at end of file