summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBodam Nam <bodamnam@google.com>2023-04-06 05:42:57 +0000
committerAndroid (Google) Code Review <android-gerrit@google.com>2023-04-06 05:42:57 +0000
commit2a830cf2777b9275726f37b4155877759fe0044e (patch)
tree49abc06a083668716ea25b16dcd2ea3517c7b397
parent7a5fc2963d77634dbc5ee736a386839f6268f057 (diff)
parent36ce548bf901827a93dbac250dfa566b8f44f00c (diff)
downloadImsMedia-2a830cf2777b9275726f37b4155877759fe0044e.tar.gz
Merge "Add UT for AudioRtpPayloadEncoder/Decoder" into udc-dev
-rw-r--r--service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/audio/nodes/AudioRtpPayloadDecoderNode.cpp42
-rw-r--r--service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/audio/nodes/AudioRtpPayloadEncoderNode.cpp61
-rw-r--r--service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/include/audio/nodes/AudioRtpPayloadDecoderNode.h4
-rw-r--r--service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/include/audio/nodes/AudioRtpPayloadEncoderNode.h2
-rw-r--r--tests/native/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/audio/node/AudioRtpPayloadNodeTest.cpp296
5 files changed, 346 insertions, 59 deletions
diff --git a/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/audio/nodes/AudioRtpPayloadDecoderNode.cpp b/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/audio/nodes/AudioRtpPayloadDecoderNode.cpp
index 2525acfd..279557fc 100644
--- a/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/audio/nodes/AudioRtpPayloadDecoderNode.cpp
+++ b/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/audio/nodes/AudioRtpPayloadDecoderNode.cpp
@@ -49,7 +49,7 @@ ImsMediaResult AudioRtpPayloadDecoderNode::Start()
mEvsMode = (kEvsBitrate)ImsMediaAudioUtil::GetMaximumEvsMode(mCoreEvsMode);
mEvsCodecMode = (kEvsCodecMode)ImsMediaAudioUtil::ConvertEvsCodecMode(mEvsMode);
- mPrevCMR = 15;
+ mPrevCMR = mCodecType == kAudioCodecEvs ? 127 : 15;
mListFrameType.clear();
mNodeState = kNodeStateRunning;
return RESULT_SUCCESS;
@@ -133,7 +133,7 @@ void AudioRtpPayloadDecoderNode::OnDataFromFrontNode(ImsMediaSubType subtype, ui
{
case kAudioCodecAmr:
case kAudioCodecAmrWb:
- DecodePayloadAmr(pData, nDataSize, nTimestamp, bMark, nSeqNum, arrivalTime);
+ DecodePayloadAmr(pData, nDataSize, nTimestamp, nSeqNum, arrivalTime);
break;
case kAudioCodecPcmu:
case kAudioCodecPcma:
@@ -152,14 +152,13 @@ void AudioRtpPayloadDecoderNode::OnDataFromFrontNode(ImsMediaSubType subtype, ui
}
void AudioRtpPayloadDecoderNode::DecodePayloadAmr(uint8_t* pData, uint32_t nDataSize,
- uint32_t nTimestamp, bool bMark, uint32_t nSeqNum, uint32_t arrivalTime)
+ uint32_t nTimestamp, uint32_t nSeqNum, uint32_t arrivalTime)
{
if (pData == nullptr || nDataSize == 0)
{
return;
}
- (void)bMark;
uint32_t timestamp = nTimestamp;
uint32_t eRate;
uint32_t f;
@@ -167,9 +166,9 @@ void AudioRtpPayloadDecoderNode::DecodePayloadAmr(uint8_t* pData, uint32_t nData
uint32_t QbitPos; // Q_Speech_Sid_Bad
IMLOGD_PACKET5(IM_PACKET_LOG_PH,
- "[DecodePayloadAmr] GetCodectype[%d], octetAligned[%d], nSeqNum[%d], TS[%u], "
+ "[DecodePayloadAmr] codec type[%d], octetAligned[%d], size[%d], TS[%u], "
"arrivalTime[%u]",
- mCodecType, mOctetAligned, nSeqNum, timestamp, arrivalTime);
+ mCodecType, mOctetAligned, nDataSize, timestamp, arrivalTime);
mBitReader.SetBuffer(pData, nDataSize);
// read cmr
@@ -236,19 +235,20 @@ void AudioRtpPayloadDecoderNode::DecodePayloadAmr(uint8_t* pData, uint32_t nData
mListFrameType.pop_front();
mBitWriter.SetBuffer(mPayload, MAX_AUDIO_PAYLOAD_SIZE);
- // set payload header
+ uint32_t bufferSize = (nDataBitSize + 7) >> 3;
+ // set TOC
mBitWriter.Write(f, 1);
mBitWriter.Write(eRate, 4);
mBitWriter.Write(QbitPos, 1);
mBitWriter.Write(0, 2);
mBitReader.ReadByteBuffer(mPayload + 1, nDataBitSize);
- // add payload header to payload size
- uint32_t nBufferSize = ((nDataBitSize + 7) >> 3) + 1;
+ bufferSize++;
+
IMLOGD_PACKET6(IM_PACKET_LOG_PH,
"[DecodePayloadAmr] result = %02X %02X %02X %02X, len[%d], eRate[%d]", mPayload[0],
- mPayload[1], mPayload[2], mPayload[3], nBufferSize, eRate);
+ mPayload[1], mPayload[2], mPayload[3], bufferSize, eRate);
// send remaining packet number in bundle as bMark value
- SendDataToRearNode(MEDIASUBTYPE_RTPPAYLOAD, mPayload, nBufferSize, timestamp,
+ SendDataToRearNode(MEDIASUBTYPE_RTPPAYLOAD, mPayload, bufferSize, timestamp,
mListFrameType.size(), nSeqNum, MEDIASUBTYPE_UNDEFINED, arrivalTime);
timestamp += 20;
@@ -263,10 +263,9 @@ void AudioRtpPayloadDecoderNode::DecodePayloadEvs(uint8_t* pData, uint32_t nData
return;
}
- IMLOGD_PACKET5(IM_PACKET_LOG_PH,
- "[DecodePayloadEvs] GetCodectype[%d], octetAligned[%d], nSeqNum[%d], TS[%u], "
- "arrivalTime[%u]",
- mCodecType, mOctetAligned, nSeqNum, nTimeStamp, arrivalTime);
+ IMLOGD_PACKET4(IM_PACKET_LOG_PH,
+ "[DecodePayloadEvs] codec type[%d], size[%d], TS[%u], arrivalTime[%u]", mCodecType,
+ nDataSize, nTimeStamp, arrivalTime);
kRtpPyaloadHeaderMode eEVSReceivedPHFormat = kRtpPyaloadHeaderModeEvsCompact;
kEvsCodecMode kEvsCodecMode = kEvsCodecModePrimary;
@@ -321,7 +320,7 @@ void AudioRtpPayloadDecoderNode::DecodePayloadEvs(uint8_t* pData, uint32_t nData
mBitReader.ReadByteBuffer(mPayload, nDataBitSize);
- IMLOGD6("[DecodePayloadEvs] Result =%02X %02X %02X %02X, len=%d,nFrameType=%d",
+ IMLOGD6("[DecodePayloadEvs] Result=%02X %02X %02X %02X, len=%d,nFrameType=%d",
mPayload[0], mPayload[1], mPayload[2], mPayload[3], nDataSize, nFrameType);
SendDataToRearNode(MEDIASUBTYPE_RTPPAYLOAD, mPayload, nDataSize, timestamp, bMark,
@@ -608,7 +607,6 @@ void AudioRtpPayloadDecoderNode::DecodePayloadEvs(uint8_t* pData, uint32_t nData
}
else // ToC byte
{
- IMLOGD0("[DecodePayloadEvs] Decoding TOC header");
toc_f = mBitReader.Read(1);
toc_ft_m = mBitReader.Read(1);
toc_ft_q = mBitReader.Read(1);
@@ -636,14 +634,16 @@ void AudioRtpPayloadDecoderNode::DecodePayloadEvs(uint8_t* pData, uint32_t nData
}
mBitWriter.SetBuffer(mPayload, MAX_AUDIO_PAYLOAD_SIZE);
+ uint32_t bufferSize = (nDataBitSize + 7) >> 3;
+ // set TOC
mBitWriter.Write(h, 1);
mBitWriter.Write(toc_f, 1);
mBitWriter.Write(toc_ft_m, 1);
mBitWriter.Write(toc_ft_q, 1);
mBitWriter.Write(toc_ft_b, 4);
-
mBitReader.ReadByteBuffer(mPayload + 1, nDataBitSize);
+ bufferSize++;
// remove padding bit
{
@@ -653,10 +653,10 @@ void AudioRtpPayloadDecoderNode::DecodePayloadEvs(uint8_t* pData, uint32_t nData
}
IMLOGD6("[DecodePayloadEvs] result = %02X %02X %02X %02X, len=%d, eRate=%d",
- mPayload[0], mPayload[1], mPayload[2], mPayload[3], nDataSize, toc_ft_b);
+ mPayload[0], mPayload[1], mPayload[2], mPayload[3], bufferSize, toc_ft_b);
- SendDataToRearNode(MEDIASUBTYPE_RTPPAYLOAD, mPayload, (((nDataBitSize + 7) >> 3)),
- timestamp, mListFrameType.size(), nSeqNum, MEDIASUBTYPE_UNDEFINED, arrivalTime);
+ SendDataToRearNode(MEDIASUBTYPE_RTPPAYLOAD, mPayload, bufferSize, timestamp,
+ mListFrameType.size(), nSeqNum, MEDIASUBTYPE_UNDEFINED, arrivalTime);
timestamp += 20;
}
diff --git a/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/audio/nodes/AudioRtpPayloadEncoderNode.cpp b/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/audio/nodes/AudioRtpPayloadEncoderNode.cpp
index 028eba2d..cffcb2c8 100644
--- a/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/audio/nodes/AudioRtpPayloadEncoderNode.cpp
+++ b/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/audio/nodes/AudioRtpPayloadEncoderNode.cpp
@@ -51,11 +51,13 @@ kBaseNodeId AudioRtpPayloadEncoderNode::GetNodeId()
ImsMediaResult AudioRtpPayloadEncoderNode::Start()
{
- IMLOGD2("[Start] codecType[%d], mode[%d]", mCodecType, mOctetAligned);
mMaxNumOfFrame = mPtime / 20;
mEvsMode = (kEvsBitrate)ImsMediaAudioUtil::GetMaximumEvsMode(mCoreEvsMode);
mEvsCodecMode = (kEvsCodecMode)ImsMediaAudioUtil::ConvertEvsCodecMode(mEvsMode);
+ IMLOGD5("[Start] codecType[%d], mode[%d], num of frames[%d], evs bitrate[%d], evs mode[%d]",
+ mCodecType, mOctetAligned, mMaxNumOfFrame, mEvsMode, mEvsCodecMode);
+
if (mMaxNumOfFrame == 0 || mMaxNumOfFrame > MAX_FRAME_IN_PACKET)
{
IMLOGE1("[Start] Invalid ptime [%d]", mPtime);
@@ -86,16 +88,15 @@ bool AudioRtpPayloadEncoderNode::IsSourceNode()
return false;
}
-void AudioRtpPayloadEncoderNode::OnDataFromFrontNode(ImsMediaSubType subtype, uint8_t* pData,
+void AudioRtpPayloadEncoderNode::OnDataFromFrontNode(ImsMediaSubType /*subtype*/, uint8_t* pData,
uint32_t nDataSize, uint32_t nTimestamp, bool bMark, uint32_t nSeqNum,
ImsMediaSubType nDataType, uint32_t arrivalTime)
{
- (void)subtype;
switch (mCodecType)
{
case kAudioCodecAmr:
case kAudioCodecAmrWb:
- EncodePayloadAmr(pData, nDataSize, nTimestamp, bMark);
+ EncodePayloadAmr(pData, nDataSize, nTimestamp);
break;
case kAudioCodecPcmu:
case kAudioCodecPcma:
@@ -166,16 +167,15 @@ bool AudioRtpPayloadEncoderNode::IsSameConfig(void* config)
}
void AudioRtpPayloadEncoderNode::EncodePayloadAmr(
- uint8_t* pData, uint32_t nDataSize, uint32_t nTimestamp, bool bMark)
+ uint8_t* pData, uint32_t nDataSize, uint32_t nTimestamp)
{
- (void)bMark;
uint32_t nCmr = 15;
uint32_t f, ft, q, nDataBitSize;
-#ifndef LEGACY_AUDIO_ENABLED // for ap audio test
+ // remove TOC from the encoder
pData++;
nDataSize -= 1;
-#endif
+
if (nDataSize > 4)
{
IMLOGD_PACKET5(IM_PACKET_LOG_PH, "[EncodePayloadAmr] src = %02X %02X %02X %02X, len[%d]",
@@ -277,28 +277,18 @@ void AudioRtpPayloadEncoderNode::EncodePayloadAmr(
void AudioRtpPayloadEncoderNode::EncodePayloadEvs(
uint8_t* pData, uint32_t nDataSize, uint32_t nTimeStamp)
{
- kRtpPyaloadHeaderMode eEVSPayloadFormat = kRtpPyaloadHeaderModeEvsHeaderFull;
- kEvsCodecMode kEvsCodecMode;
-
- // 0111 1111 is no request.
- uint32_t nEVSBW = 0x07;
- uint32_t nEVSBR = 0x0f;
- uint32_t nFrameType = 0;
-
if (nDataSize == 0)
{
return;
}
- eEVSPayloadFormat = mEvsPayloadHeaderMode;
+ uint32_t nFrameType = 0;
// compact or header-full format, default is compact formats
- kEvsCodecMode = mEvsCodecMode;
-
// primary or amr-wb io mode, default is primary mode
// primary or amr-wb io mode base on frameSize.
mCurrNumOfFrame++;
- if (eEVSPayloadFormat == kRtpPyaloadHeaderModeEvsCompact)
+ if (mEvsPayloadHeaderMode == kRtpPyaloadHeaderModeEvsCompact)
{
memset(mPayload, 0, MAX_AUDIO_PAYLOAD_SIZE);
mBWHeader.SetBuffer(mPayload, MAX_AUDIO_PAYLOAD_SIZE);
@@ -306,7 +296,7 @@ void AudioRtpPayloadEncoderNode::EncodePayloadEvs(
mTimestamp = nTimeStamp;
// exactly one coded frame without any additional EVS RTP payload header
- if (kEvsCodecMode == kEvsCodecModePrimary)
+ if (mEvsCodecMode == kEvsCodecModePrimary)
{
// calculate nDataBitSize from nDataSize
nFrameType = (uint32_t)ImsMediaAudioUtil::ConvertLenToEVSAudioMode(nDataSize);
@@ -354,9 +344,8 @@ void AudioRtpPayloadEncoderNode::EncodePayloadEvs(
mFirstFrame = false;
}
// one 3-bit CMR field, one coded frame, and zero-padding bits if necessary
- else if (kEvsCodecMode == kEvsCodecModeAmrIo)
+ else if (mEvsCodecMode == kEvsCodecModeAmrIo)
{
- IMLOGE0("[EncodePayloadEvs] COMPACT and AMR_WB_IO");
// calculate nDataBitSize from nDataSize
nFrameType = (uint32_t)ImsMediaAudioUtil::ConvertLenToAmrWbMode(nDataSize);
uint32_t nDataBitSize = ImsMediaAudioUtil::ConvertAmrWbModeToBitLen(nFrameType);
@@ -447,17 +436,23 @@ void AudioRtpPayloadEncoderNode::EncodePayloadEvs(
return;
}
}
- else if (eEVSPayloadFormat == kRtpPyaloadHeaderModeEvsHeaderFull)
+ else if (mEvsPayloadHeaderMode == kRtpPyaloadHeaderModeEvsHeaderFull)
{
+ // 0111 1111 is no request.
+ uint32_t nEVSBW = 0x07;
+ uint32_t nEVSBR = 0x0f;
+
+ // remove 1 byte toc field from the codec
+ pData++;
+ nDataSize--;
+
uint32_t cmr_h, cmr_t, cmr_d = 0; // CMR byte
memset(mPayload, 0, MAX_AUDIO_PAYLOAD_SIZE);
mBWHeader.SetBuffer(mPayload, MAX_AUDIO_PAYLOAD_SIZE);
mBWPayload.SetBuffer(mPayload, MAX_AUDIO_PAYLOAD_SIZE);
- if (kEvsCodecMode == kEvsCodecModePrimary)
+ if (mEvsCodecMode == kEvsCodecModePrimary)
{
- IMLOGE0("[EncodePayloadEvs] HF and PRI");
-
if (nFrameType == kImsAudioEvsPrimaryModeSID || mSendCMR) // CMR value
{
// Header Type identification bit(1bit) - always set to 1
@@ -537,9 +532,8 @@ void AudioRtpPayloadEncoderNode::EncodePayloadEvs(
mFirstFrame = false;
}
}
- else if (kEvsCodecMode == kEvsCodecModeAmrIo)
+ else if (mEvsCodecMode == kEvsCodecModeAmrIo)
{
- IMLOGE0("[EncodePayloadEvs] HF and AMR_WB_IO");
// set CMR byte
// at EVS AMR WB IO Mode, CMR field shall include.
// Header Type identification bit(1bit) - always set to 1
@@ -624,8 +618,7 @@ void AudioRtpPayloadEncoderNode::EncodePayloadEvs(
IMLOGE0("[EncodePayloadEvs] invalid codec mode");
return;
}
-
- } // end of if(eEVSPayloadFormat == kRtpPyaloadHeaderModeEvsHeaderFull)
+ }
else
{
IMLOGE0("[EncodePayloadEvs] invalid payload format");
@@ -637,19 +630,17 @@ void AudioRtpPayloadEncoderNode::EncodePayloadEvs(
uint32_t AudioRtpPayloadEncoderNode::CheckPaddingNecessity(uint32_t nTotalSize)
{
- kEvsCodecMode kEvsCodecMode;
+ kEvsCodecMode evsCodecMode;
uint32_t nEVSCompactId;
uint32_t nSize = nTotalSize;
// check EVS compact size
while (nSize != 0 &&
- ImsMediaAudioUtil::ConvertEVSPayloadMode(nSize, &kEvsCodecMode, &nEVSCompactId) ==
+ ImsMediaAudioUtil::ConvertEVSPayloadMode(nSize, &evsCodecMode, &nEVSCompactId) ==
kRtpPyaloadHeaderModeEvsCompact)
{
mPayload[nSize] = 0;
nSize++;
-
- IMLOGD1("[CheckPaddingNecessity] Add Padding - size[%d]", nSize);
}
return nSize;
diff --git a/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/include/audio/nodes/AudioRtpPayloadDecoderNode.h b/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/include/audio/nodes/AudioRtpPayloadDecoderNode.h
index 469ea586..c074f0be 100644
--- a/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/include/audio/nodes/AudioRtpPayloadDecoderNode.h
+++ b/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/include/audio/nodes/AudioRtpPayloadDecoderNode.h
@@ -45,8 +45,8 @@ public:
uint32_t arrivalTime = 0);
private:
- void DecodePayloadAmr(uint8_t* pData, uint32_t nDataSize, uint32_t nTimestamp, bool bMark,
- uint32_t nSeqNum, uint32_t arrivalTime);
+ void DecodePayloadAmr(uint8_t* pData, uint32_t nDataSize, uint32_t nTimestamp, uint32_t nSeqNum,
+ uint32_t arrivalTime);
void DecodePayloadEvs(uint8_t* pData, uint32_t nDataSize, uint32_t nTimeStamp, bool bMark,
uint32_t nSeqNum, uint32_t arrivalTime);
bool ProcessCMRForEVS(kRtpPyaloadHeaderMode eEVSPayloadHeaderMode, kEvsCmrCodeType cmr_t,
diff --git a/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/include/audio/nodes/AudioRtpPayloadEncoderNode.h b/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/include/audio/nodes/AudioRtpPayloadEncoderNode.h
index 28adc783..cc3be7f3 100644
--- a/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/include/audio/nodes/AudioRtpPayloadEncoderNode.h
+++ b/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/include/audio/nodes/AudioRtpPayloadEncoderNode.h
@@ -38,7 +38,7 @@ public:
virtual bool IsSameConfig(void* config);
private:
- void EncodePayloadAmr(uint8_t* pData, uint32_t nDataSize, uint32_t nTimestamp, bool bMark);
+ void EncodePayloadAmr(uint8_t* pData, uint32_t nDataSize, uint32_t nTimestamp);
void EncodePayloadEvs(uint8_t* pData, uint32_t nDataSize, uint32_t nTimeStamp);
uint32_t CheckPaddingNecessity(uint32_t nTotalSize);
diff --git a/tests/native/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/audio/node/AudioRtpPayloadNodeTest.cpp b/tests/native/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/audio/node/AudioRtpPayloadNodeTest.cpp
new file mode 100644
index 00000000..0221f6fa
--- /dev/null
+++ b/tests/native/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/audio/node/AudioRtpPayloadNodeTest.cpp
@@ -0,0 +1,296 @@
+/**
+ * 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 <AudioConfig.h>
+#include <AudioRtpPayloadEncoderNode.h>
+#include <AudioRtpPayloadDecoderNode.h>
+#include <string.h>
+
+using namespace android::telephony::imsmedia;
+using namespace android;
+
+// RtpConfig
+const int32_t kMediaDirection = RtpConfig::MEDIA_DIRECTION_SEND_RECEIVE;
+const String8 kRemoteAddress("127.0.0.1");
+const int32_t kRemotePort = 10000;
+const int8_t kDscp = 0;
+const int8_t kRxPayload = 96;
+const int8_t kTxPayload = 96;
+const int8_t kSamplingRate = 16;
+
+// RtcpConfig
+const String8 kCanonicalName("name");
+const int32_t kTransmitPort = 10001;
+const int32_t kIntervalSec = 5;
+const int32_t kRtcpXrBlockTypes = 0;
+
+// AudioConfig
+const int8_t kPTimeMillis = 20;
+const int32_t kMaxPtimeMillis = 100;
+const bool kDtxEnabled = true;
+const int8_t kDtmfPayloadTypeNumber = 103;
+const int8_t kDtmfsamplingRateKHz = 16;
+
+// AmrParam
+const int32_t kAmrMode = AmrParams::AMR_MODE_8;
+const bool kOctetAligned = false;
+const int32_t kMaxRedundancyMillis = 240;
+
+// EvsParam
+const int32_t kEvsBandwidth = EvsParams::EVS_SUPER_WIDE_BAND;
+const int32_t kEvsMode = EvsParams::EVS_MODE_13;
+const int8_t kChannelAwareMode = 2;
+
+namespace
+{
+class FakeNode : public BaseNode
+{
+public:
+ explicit FakeNode(BaseSessionCallback* callback = nullptr) :
+ BaseNode(callback)
+ {
+ frameSize = 0;
+ memset(dataFrame, 0, sizeof(dataFrame));
+ }
+ virtual ~FakeNode() {}
+ virtual ImsMediaResult Start() { return RESULT_SUCCESS; }
+ virtual void Stop() {}
+ virtual bool IsRunTime() { return true; }
+ virtual bool IsSourceNode() { return false; }
+ virtual void SetConfig(void* config) { (void)config; }
+ virtual void OnDataFromFrontNode(ImsMediaSubType /*IMS_MEDIA_AUDIO*/, uint8_t* data,
+ uint32_t size, uint32_t /*timestamp*/, bool /*mark*/, uint32_t /*seq*/,
+ ImsMediaSubType /*dataType*/, uint32_t /*arrivalTime*/)
+ {
+ if (data != nullptr && size > 0)
+ {
+ memset(dataFrame, 0, sizeof(dataFrame));
+ memcpy(dataFrame, data, size);
+ frameSize = size;
+ }
+ }
+
+ virtual kBaseNodeState GetState() { return kNodeStateRunning; }
+
+ uint32_t GetFrameSize() { return frameSize; }
+ uint8_t* GetDataFrame() { return dataFrame; }
+
+private:
+ uint32_t frameSize;
+ uint8_t dataFrame[DEFAULT_MTU];
+};
+
+class AudioRtpPayloadNodeTest : public ::testing::Test
+{
+public:
+ AudioRtpPayloadNodeTest()
+ {
+ encoder = nullptr;
+ decoder = nullptr;
+ fakeNode = nullptr;
+ }
+ virtual ~AudioRtpPayloadNodeTest() {}
+
+protected:
+ AmrParams amr;
+ EvsParams evs;
+ RtcpConfig rtcp;
+ AudioConfig audioConfig;
+ AudioRtpPayloadEncoderNode* encoder;
+ AudioRtpPayloadDecoderNode* decoder;
+ FakeNode* fakeNode;
+ std::list<BaseNode*> nodes;
+
+ virtual void SetUp() override
+ {
+ rtcp.setCanonicalName(kCanonicalName);
+ rtcp.setTransmitPort(kTransmitPort);
+ rtcp.setIntervalSec(kIntervalSec);
+ rtcp.setRtcpXrBlockTypes(kRtcpXrBlockTypes);
+
+ setupAudioConfig();
+ setupNodes(&audioConfig);
+ }
+
+ virtual void TearDown() override
+ {
+ while (nodes.size() > 0)
+ {
+ BaseNode* node = nodes.front();
+ node->Stop();
+ delete node;
+ nodes.pop_front();
+ }
+ }
+
+public:
+ void setupNodes(AudioConfig* config)
+ {
+ encoder = new AudioRtpPayloadEncoderNode();
+ encoder->SetMediaType(IMS_MEDIA_AUDIO);
+ encoder->SetConfig(config);
+ nodes.push_back(encoder);
+
+ decoder = new AudioRtpPayloadDecoderNode();
+ decoder->SetMediaType(IMS_MEDIA_AUDIO);
+ decoder->SetConfig(config);
+ nodes.push_back(decoder);
+ encoder->ConnectRearNode(decoder);
+
+ fakeNode = new FakeNode();
+ fakeNode->SetMediaType(IMS_MEDIA_AUDIO);
+ fakeNode->SetConfig(config);
+ nodes.push_back(fakeNode);
+ decoder->ConnectRearNode(fakeNode);
+ }
+
+ void setupAudioConfig()
+ {
+ amr.setAmrMode(kAmrMode);
+ amr.setOctetAligned(kOctetAligned);
+ amr.setMaxRedundancyMillis(kMaxRedundancyMillis);
+
+ audioConfig.setMediaDirection(kMediaDirection);
+ audioConfig.setRemoteAddress(kRemoteAddress);
+ audioConfig.setRemotePort(kRemotePort);
+ audioConfig.setRtcpConfig(rtcp);
+ audioConfig.setDscp(kDscp);
+ audioConfig.setRxPayloadTypeNumber(kRxPayload);
+ audioConfig.setTxPayloadTypeNumber(kTxPayload);
+ audioConfig.setSamplingRateKHz(kSamplingRate);
+ audioConfig.setPtimeMillis(kPTimeMillis);
+ audioConfig.setMaxPtimeMillis(kMaxPtimeMillis);
+ audioConfig.setDtxEnabled(kDtxEnabled);
+ audioConfig.setCodecType(AudioConfig::CODEC_AMR_WB);
+ audioConfig.setTxDtmfPayloadTypeNumber(kDtmfPayloadTypeNumber);
+ audioConfig.setRxDtmfPayloadTypeNumber(kDtmfPayloadTypeNumber);
+ audioConfig.setDtmfsamplingRateKHz(kDtmfsamplingRateKHz);
+ audioConfig.setAmrParams(amr);
+ audioConfig.setEvsParams(evs);
+ }
+};
+
+TEST_F(AudioRtpPayloadNodeTest, startFail)
+{
+ audioConfig.setPtimeMillis(0);
+ encoder->SetConfig(&audioConfig);
+ EXPECT_EQ(encoder->Start(), RESULT_INVALID_PARAM);
+}
+
+TEST_F(AudioRtpPayloadNodeTest, startAndUpdate)
+{
+ EXPECT_EQ(encoder->Start(), RESULT_SUCCESS);
+ EXPECT_EQ(decoder->Start(), RESULT_SUCCESS);
+
+ // no update
+ EXPECT_EQ(encoder->UpdateConfig(&audioConfig), RESULT_SUCCESS);
+ EXPECT_EQ(decoder->UpdateConfig(&audioConfig), RESULT_SUCCESS);
+
+ // update
+ audioConfig.setCodecType(AudioConfig::CODEC_AMR);
+ EXPECT_EQ(encoder->UpdateConfig(&audioConfig), RESULT_SUCCESS);
+ EXPECT_EQ(decoder->UpdateConfig(&audioConfig), RESULT_SUCCESS);
+}
+
+TEST_F(AudioRtpPayloadNodeTest, testAmrBandwidthEfficientDataProcess)
+{
+ EXPECT_EQ(encoder->Start(), RESULT_SUCCESS);
+ EXPECT_EQ(decoder->Start(), RESULT_SUCCESS);
+
+ // AMR-WB mode 8 audio frame with toc field
+ uint8_t testFrame[] = {0x44, 0xe6, 0x6e, 0x84, 0x8a, 0xa4, 0xda, 0xc8, 0xf2, 0x6c, 0xeb, 0x87,
+ 0xe4, 0x56, 0x0f, 0x49, 0x47, 0xfa, 0xdc, 0xa7, 0x9d, 0xbb, 0xcf, 0xda, 0xda, 0x67,
+ 0x80, 0xc2, 0x7f, 0x8d, 0x5b, 0xab, 0xd9, 0xbb, 0xd7, 0x1e, 0x60, 0x96, 0x5d, 0xdd,
+ 0x28, 0x65, 0x5f, 0x43, 0xf4, 0xb9, 0x0d, 0x7d, 0x05, 0x4e, 0x30, 0x50, 0xe1, 0x98,
+ 0x03, 0xed, 0xee, 0x8a, 0xa8, 0x34, 0x40};
+
+ encoder->OnDataFromFrontNode(MEDIASUBTYPE_UNDEFINED, testFrame, sizeof(testFrame), 0, false, 0);
+ EXPECT_EQ(fakeNode->GetFrameSize(), sizeof(testFrame));
+ EXPECT_EQ(memcmp(fakeNode->GetDataFrame(), testFrame, fakeNode->GetFrameSize()), 0);
+}
+
+TEST_F(AudioRtpPayloadNodeTest, testAmrOctetAlignedDataProcess)
+{
+ amr.setOctetAligned(true);
+ audioConfig.setAmrParams(amr);
+ encoder->SetConfig(&audioConfig);
+ decoder->SetConfig(&audioConfig);
+ EXPECT_EQ(encoder->Start(), RESULT_SUCCESS);
+ EXPECT_EQ(decoder->Start(), RESULT_SUCCESS);
+
+ // AMR-WB mode 8 audio frame with toc field
+ uint8_t testFrame[] = {0x44, 0xe6, 0x6e, 0x84, 0x8a, 0xa4, 0xda, 0xc8, 0xf2, 0x6c, 0xeb, 0x87,
+ 0xe4, 0x56, 0x0f, 0x49, 0x47, 0xfa, 0xdc, 0xa7, 0x9d, 0xbb, 0xcf, 0xda, 0xda, 0x67,
+ 0x80, 0xc2, 0x7f, 0x8d, 0x5b, 0xab, 0xd9, 0xbb, 0xd7, 0x1e, 0x60, 0x96, 0x5d, 0xdd,
+ 0x28, 0x65, 0x5f, 0x43, 0xf4, 0xb9, 0x0d, 0x7d, 0x05, 0x4e, 0x30, 0x50, 0xe1, 0x98,
+ 0x03, 0xed, 0xee, 0x8a, 0xa8, 0x34, 0x40};
+
+ encoder->OnDataFromFrontNode(MEDIASUBTYPE_UNDEFINED, testFrame, sizeof(testFrame), 0, false, 0);
+ EXPECT_EQ(fakeNode->GetFrameSize(), sizeof(testFrame));
+ EXPECT_EQ(memcmp(fakeNode->GetDataFrame(), testFrame, fakeNode->GetFrameSize()), 0);
+}
+
+TEST_F(AudioRtpPayloadNodeTest, testEvsCompactModeDataProcess)
+{
+ evs.setEvsBandwidth(kEvsBandwidth);
+ evs.setEvsMode(kEvsMode);
+ evs.setChannelAwareMode(kChannelAwareMode);
+ evs.setUseHeaderFullOnly(false);
+ evs.setCodecModeRequest(-1);
+
+ audioConfig.setEvsParams(evs);
+ audioConfig.setCodecType(AudioConfig::CODEC_EVS);
+ encoder->SetConfig(&audioConfig);
+ decoder->SetConfig(&audioConfig);
+ EXPECT_EQ(encoder->Start(), RESULT_SUCCESS);
+ EXPECT_EQ(decoder->Start(), RESULT_SUCCESS);
+
+ // EVS mode 13.2 kbps frame without toc field
+ uint8_t testFrame[] = {0xce, 0x40, 0xf2, 0xb2, 0xa4, 0xce, 0x4f, 0xd9, 0xfa, 0xe9, 0x77, 0xdc,
+ 0x9b, 0xc0, 0xa8, 0x10, 0xc8, 0xc3, 0x0f, 0xc9, 0x52, 0xc1, 0xda, 0x45, 0x7e, 0x6c,
+ 0x55, 0x47, 0xff, 0xff, 0xff, 0xff, 0xe0};
+
+ encoder->OnDataFromFrontNode(MEDIASUBTYPE_UNDEFINED, testFrame, sizeof(testFrame), 0, false, 0);
+ EXPECT_EQ(fakeNode->GetFrameSize(), sizeof(testFrame));
+ EXPECT_EQ(memcmp(fakeNode->GetDataFrame(), testFrame, fakeNode->GetFrameSize()), 0);
+}
+
+TEST_F(AudioRtpPayloadNodeTest, testEvsHeaderFullModeDataProcess)
+{
+ evs.setEvsBandwidth(kEvsBandwidth);
+ evs.setEvsMode(kEvsMode);
+ evs.setChannelAwareMode(kChannelAwareMode);
+ evs.setUseHeaderFullOnly(true);
+ evs.setCodecModeRequest(-1);
+
+ audioConfig.setEvsParams(evs);
+ audioConfig.setCodecType(AudioConfig::CODEC_EVS);
+ encoder->SetConfig(&audioConfig);
+ decoder->SetConfig(&audioConfig);
+ EXPECT_EQ(encoder->Start(), RESULT_SUCCESS);
+ EXPECT_EQ(decoder->Start(), RESULT_SUCCESS);
+
+ // EVS mode 13.2 kbps frame with toc field
+ uint8_t testFrame[] = {0x04, 0xce, 0x40, 0xf2, 0xb2, 0xa4, 0xce, 0x4f, 0xd9, 0xfa, 0xe9, 0x77,
+ 0xdc, 0x9b, 0xc0, 0xa8, 0x10, 0xc8, 0xc3, 0x0f, 0xc9, 0x52, 0xc1, 0xda, 0x45, 0x7e,
+ 0x6c, 0x55, 0x47, 0xff, 0xff, 0xff, 0xff, 0xe0};
+
+ encoder->OnDataFromFrontNode(MEDIASUBTYPE_UNDEFINED, testFrame, sizeof(testFrame), 0, false, 0);
+ EXPECT_EQ(fakeNode->GetFrameSize(), sizeof(testFrame));
+ EXPECT_EQ(memcmp(fakeNode->GetDataFrame(), testFrame, fakeNode->GetFrameSize()), 0);
+}
+} // namespace