From 36ce548bf901827a93dbac250dfa566b8f44f00c Mon Sep 17 00:00:00 2001 From: bodamnam Date: Mon, 20 Mar 2023 05:26:43 +0000 Subject: Add UT for AudioRtpPayloadEncoder/Decoder 1) Add UT for AudioRtpPayloadEncoder/Decoder 2) Define default CMR for EVS codec 3) Refactoring debug logs Bug: 272299058 Test: atest ImsMediaNativeTests, Verified voice call of AMR/AMR-WB/EVS codec using ImsMediaTestingApp Change-Id: Id34764633a45cc35bb77cbac9676966824b83fdf --- .../audio/nodes/AudioRtpPayloadDecoderNode.cpp | 42 +-- .../audio/nodes/AudioRtpPayloadEncoderNode.cpp | 61 ++--- .../audio/nodes/AudioRtpPayloadDecoderNode.h | 4 +- .../audio/nodes/AudioRtpPayloadEncoderNode.h | 2 +- .../core/audio/node/AudioRtpPayloadNodeTest.cpp | 296 +++++++++++++++++++++ 5 files changed, 346 insertions(+), 59 deletions(-) create mode 100644 tests/native/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/audio/node/AudioRtpPayloadNodeTest.cpp 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 +#include +#include +#include +#include + +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 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 -- cgit v1.2.3