summaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
authorAvinash Malipatil <avinashmp@google.com>2023-03-13 09:28:34 +0000
committerAvinash Malipatil <avinashmp@google.com>2023-03-13 18:36:06 +0000
commitd45b64d109da41d4b2dde39b11ccae8d435989c7 (patch)
tree66f685d8ebe03c822aa8997120be3c0b46909526 /tests
parent20f5a73f5753b0a1a0b2a8a3944a934de422eb40 (diff)
downloadImsMedia-d45b64d109da41d4b2dde39b11ccae8d435989c7.tar.gz
Add unit test cases for RTCP encoder node.
Bug: 272299057 Test: atest ImsMediaNativeTests Change-Id: I5324935dad859de281ca05b1b13ea46814c9f52a
Diffstat (limited to 'tests')
-rw-r--r--tests/native/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/nodes/RtcpEncoderNodeTests.cpp349
1 files changed, 349 insertions, 0 deletions
diff --git a/tests/native/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/nodes/RtcpEncoderNodeTests.cpp b/tests/native/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/nodes/RtcpEncoderNodeTests.cpp
new file mode 100644
index 00000000..94fd213d
--- /dev/null
+++ b/tests/native/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/nodes/RtcpEncoderNodeTests.cpp
@@ -0,0 +1,349 @@
+/**
+ * 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 <condition_variable>
+#include <mutex>
+#include <RtcpConfig.h>
+#include <AudioConfig.h>
+#include <VideoConfig.h>
+#include <TextConfig.h>
+#include <RtcpEncoderNode.h>
+#include <android/log.h>
+
+using namespace android::telephony::imsmedia;
+using namespace android;
+
+namespace
+{
+// 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 RTCP_INTERVAL = 1;
+const int32_t kIntervalSec = RTCP_INTERVAL;
+int32_t kRtcpXrBlockTypes = 0;
+
+// VideoConfig
+const int32_t kVideoMode = VideoConfig::VIDEO_MODE_PREVIEW;
+const int32_t kMtu = 1500;
+const int32_t kFramerate = DEFAULT_FRAMERATE;
+const int32_t kBitrate = DEFAULT_BITRATE;
+const int32_t kCodecProfile = VideoConfig::AVC_PROFILE_BASELINE;
+const int32_t kCodecLevel = VideoConfig::AVC_LEVEL_12;
+const int32_t kIntraFrameIntervalSec = 1;
+const int32_t kPacketizationMode = VideoConfig::MODE_NON_INTERLEAVED;
+const int32_t kCameraId = 0;
+const int32_t kCameraZoom = 10;
+const int32_t kResolutionWidth = DEFAULT_RESOLUTION_WIDTH;
+const int32_t kResolutionHeight = DEFAULT_RESOLUTION_HEIGHT;
+const android::String8 kPauseImagePath("data/user_de/0/com.android.telephony.imsmedia/test.jpg");
+const int32_t kDeviceOrientationDegree = 0;
+const int32_t kCvoValue = 1;
+const int32_t kRtcpFbTypes = VideoConfig::RTP_FB_NONE;
+
+static std::condition_variable cond;
+static std::mutex timerMutex;
+
+class FakeNode : public BaseNode
+{
+public:
+ bool mOnDataFromFrontNodeCalled = false;
+ virtual ~FakeNode() {}
+ void Stop() {}
+ bool IsRunTime() { return true; }
+ bool IsSourceNode() { return false; }
+ virtual kBaseNodeState GetState() { return kNodeStateRunning; }
+ void SetConfig(void* config) { (void)config; }
+ void OnDataFromFrontNode(ImsMediaSubType, uint8_t*, uint32_t, uint32_t, bool, uint32_t,
+ ImsMediaSubType, uint32_t)
+ {
+ mOnDataFromFrontNodeCalled = true;
+ cond.notify_all();
+ }
+
+ ImsMediaResult Start() { return RESULT_SUCCESS; }
+};
+
+class SessionCallback : public BaseSessionCallback
+{
+public:
+ bool mOnEventCalled = false;
+ virtual ~SessionCallback() {}
+ virtual void onEvent(int32_t, uint64_t, uint64_t)
+ {
+ mOnEventCalled = true;
+ cond.notify_all();
+ }
+};
+
+class RtcpEncoderNodeEx : public RtcpEncoderNode
+{
+public:
+ bool mCallBaseClassMethod = false;
+ bool mProcessTimerMethodCalled = false;
+
+ RtcpEncoderNodeEx(BaseSessionCallback* callback = nullptr) :
+ RtcpEncoderNode(callback)
+ {
+ }
+ virtual ~RtcpEncoderNodeEx() {}
+
+ void ProcessTimer()
+ {
+ mProcessTimerMethodCalled = true;
+ cond.notify_all();
+
+ if (mCallBaseClassMethod)
+ {
+ RtcpEncoderNode::ProcessTimer();
+ }
+ }
+};
+
+class RtcpEncoderNodeTests : public ::testing::Test
+{
+public:
+ virtual ~RtcpEncoderNodeTests() {}
+
+protected:
+ void setupRtcpConfig(RtcpConfig& rtcpConfig)
+ {
+ rtcpConfig.setCanonicalName(kCanonicalName);
+ rtcpConfig.setTransmitPort(kTransmitPort);
+ rtcpConfig.setIntervalSec(kIntervalSec);
+ rtcpConfig.setRtcpXrBlockTypes(kRtcpXrBlockTypes);
+ }
+
+ // using video codec because RTCP has feedback implementation for video media type.
+ void setupVideoConfig(VideoConfig& videoConfig)
+ {
+ videoConfig.setMediaDirection(kMediaDirection);
+ videoConfig.setRemoteAddress(kRemoteAddress);
+ videoConfig.setRemotePort(kRemotePort);
+ RtcpConfig rtcpConfig;
+ setupRtcpConfig(rtcpConfig);
+ videoConfig.setRtcpConfig(rtcpConfig);
+ videoConfig.setMaxMtuBytes(kMtu);
+ videoConfig.setDscp(kDscp);
+ videoConfig.setRxPayloadTypeNumber(kRxPayload);
+ videoConfig.setTxPayloadTypeNumber(kTxPayload);
+ videoConfig.setSamplingRateKHz(kSamplingRate);
+ videoConfig.setVideoMode(kVideoMode);
+ videoConfig.setCodecType(VideoConfig::CODEC_AVC);
+ videoConfig.setFramerate(kFramerate);
+ videoConfig.setBitrate(kBitrate);
+ videoConfig.setCodecProfile(kCodecProfile);
+ videoConfig.setCodecLevel(kCodecLevel);
+ videoConfig.setIntraFrameInterval(kIntraFrameIntervalSec);
+ videoConfig.setPacketizationMode(kPacketizationMode);
+ videoConfig.setCameraId(kCameraId);
+ videoConfig.setCameraZoom(kCameraZoom);
+ videoConfig.setResolutionWidth(kResolutionWidth);
+ videoConfig.setResolutionHeight(kResolutionHeight);
+ videoConfig.setPauseImagePath(kPauseImagePath);
+ videoConfig.setDeviceOrientationDegree(kDeviceOrientationDegree);
+ videoConfig.setCvoValue(kCvoValue);
+ videoConfig.setRtcpFbType(kRtcpFbTypes);
+ }
+
+ FakeNode* connectNodes(RtcpEncoderNode* pRtcpEncNode)
+ {
+ FakeNode* pFakeNode = new FakeNode();
+ pRtcpEncNode->ConnectRearNode(pFakeNode);
+ return pFakeNode;
+ }
+};
+
+TEST_F(RtcpEncoderNodeTests, TestInitState)
+{
+ RtcpEncoderNode* pRtcpEncNode = new RtcpEncoderNode();
+ EXPECT_EQ(pRtcpEncNode->GetNodeId(), kNodeIdRtcpEncoder);
+ EXPECT_EQ(pRtcpEncNode->IsRunTime(), true);
+ EXPECT_EQ(pRtcpEncNode->IsSourceNode(), true);
+ delete pRtcpEncNode;
+}
+
+TEST_F(RtcpEncoderNodeTests, TestConfigChange)
+{
+ RtcpEncoderNode* pRtcpEncNode = new RtcpEncoderNode();
+ VideoConfig videoConfig;
+ setupVideoConfig(videoConfig);
+ pRtcpEncNode->SetConfig(&videoConfig);
+ EXPECT_EQ(pRtcpEncNode->IsSameConfig(&videoConfig), true);
+ delete pRtcpEncNode;
+}
+
+TEST_F(RtcpEncoderNodeTests, TestStartStopSuccess)
+{
+ SessionCallback callback;
+ RtcpEncoderNodeEx* pRtcpEncNode = new RtcpEncoderNodeEx(&callback);
+ kRtcpXrBlockTypes = RtcpConfig::FLAG_RTCPXR_LOSS_RLE_REPORT_BLOCK;
+ VideoConfig videoConfig;
+ setupVideoConfig(videoConfig);
+ pRtcpEncNode->SetConfig(&videoConfig);
+ EXPECT_EQ(pRtcpEncNode->Start(), RESULT_SUCCESS);
+
+ bool timeout = false;
+ constexpr std::chrono::duration<int> waittime = std::chrono::seconds(RTCP_INTERVAL + 1);
+ // Wait for RTCP timer expiry to confirm start success.
+ {
+ pRtcpEncNode->mCallBaseClassMethod = true;
+ std::unique_lock<std::mutex> lock(timerMutex);
+ if (cond.wait_for(lock, waittime) == std::cv_status::timeout)
+ timeout = true;
+
+ EXPECT_EQ(timeout, false);
+ EXPECT_EQ(pRtcpEncNode->mProcessTimerMethodCalled, true);
+ }
+
+ // Check if SendEvent is called.
+ {
+ timeout = false;
+ std::unique_lock<std::mutex> lock(timerMutex);
+ if (cond.wait_for(lock, waittime) == std::cv_status::timeout)
+ timeout = true;
+
+ EXPECT_EQ(timeout, false);
+ EXPECT_EQ(callback.mOnEventCalled, true);
+ }
+
+ // Call stop and make sure RTCP timer doesn't expire.
+ pRtcpEncNode->Stop();
+ {
+ timeout = false;
+ pRtcpEncNode->mProcessTimerMethodCalled = false;
+ std::unique_lock<std::mutex> lock(timerMutex);
+ if (cond.wait_for(lock, waittime) == std::cv_status::timeout)
+ timeout = true;
+
+ EXPECT_EQ(timeout, true);
+ EXPECT_EQ(pRtcpEncNode->mProcessTimerMethodCalled, false);
+ }
+ delete pRtcpEncNode;
+}
+
+TEST_F(RtcpEncoderNodeTests, TestOnRtcpPacket)
+{
+ RtcpEncoderNode* pRtcpEncNode = new RtcpEncoderNode();
+ FakeNode* pRearNode = connectNodes(pRtcpEncNode);
+
+ unsigned char data[10];
+ pRtcpEncNode->OnRtcpPacket(data, 10);
+ EXPECT_EQ(pRearNode->mOnDataFromFrontNodeCalled, true);
+ delete pRtcpEncNode;
+ delete pRearNode;
+}
+
+TEST_F(RtcpEncoderNodeTests, TestSendNack)
+{
+ RtcpEncoderNode* pRtcpEncNode = new RtcpEncoderNode();
+ pRtcpEncNode->SetMediaType(IMS_MEDIA_VIDEO);
+
+ bool bRet = pRtcpEncNode->SendNack(nullptr);
+ EXPECT_EQ(bRet, false);
+
+ NackParams param;
+ param.PID = 0;
+ param.BLP = 0;
+ param.nSecNackCnt = 0;
+ param.bNackReport = true;
+
+ bRet = pRtcpEncNode->SendNack(&param);
+ EXPECT_EQ(bRet, false);
+
+ VideoConfig videoConfig;
+ setupVideoConfig(videoConfig);
+ videoConfig.setRtcpFbType(VideoConfig::RTP_FB_NACK);
+ pRtcpEncNode->SetConfig(&videoConfig);
+ EXPECT_EQ(pRtcpEncNode->Start(), RESULT_SUCCESS);
+ bRet = pRtcpEncNode->SendNack(&param);
+ EXPECT_EQ(bRet, true);
+ pRtcpEncNode->Stop();
+ delete pRtcpEncNode;
+}
+
+TEST_F(RtcpEncoderNodeTests, TestSendPictureLost)
+{
+ RtcpEncoderNode* pRtcpEncNode = new RtcpEncoderNode();
+ pRtcpEncNode->SetMediaType(IMS_MEDIA_VIDEO);
+ VideoConfig videoConfig;
+ setupVideoConfig(videoConfig);
+ videoConfig.setRtcpFbType(VideoConfig::PSFB_PLI);
+ pRtcpEncNode->SetConfig(&videoConfig);
+ EXPECT_EQ(pRtcpEncNode->Start(), RESULT_SUCCESS);
+
+ bool bRet = pRtcpEncNode->SendPictureLost(kPsfbPli);
+ EXPECT_EQ(bRet, true);
+
+ videoConfig.setRtcpFbType(VideoConfig::PSFB_FIR);
+ pRtcpEncNode->SetConfig(&videoConfig);
+ bRet = pRtcpEncNode->SendPictureLost(kPsfbFir);
+ EXPECT_EQ(bRet, true);
+ pRtcpEncNode->Stop();
+ delete pRtcpEncNode;
+}
+
+TEST_F(RtcpEncoderNodeTests, TestSendTmmbrn)
+{
+ RtcpEncoderNode* pRtcpEncNode = new RtcpEncoderNode();
+ pRtcpEncNode->SetMediaType(IMS_MEDIA_VIDEO);
+ VideoConfig videoConfig;
+ setupVideoConfig(videoConfig);
+ videoConfig.setRtcpFbType(VideoConfig::RTP_FB_TMMBR);
+ pRtcpEncNode->SetConfig(&videoConfig);
+ EXPECT_EQ(pRtcpEncNode->Start(), RESULT_SUCCESS);
+
+ TmmbrParams tmmbr;
+ tmmbr.ssrc = 0x1111;
+ tmmbr.exp = 0x2222;
+ tmmbr.mantissa = 0x3333;
+ tmmbr.overhead = 0x4444;
+ bool bRet = pRtcpEncNode->SendTmmbrn(kRtpFbTmmbr, &tmmbr);
+ EXPECT_EQ(bRet, true);
+
+ videoConfig.setRtcpFbType(VideoConfig::RTP_FB_TMMBR);
+ pRtcpEncNode->SetConfig(&videoConfig);
+ bRet = pRtcpEncNode->SendTmmbrn(kRtpFbTmmbr, &tmmbr);
+ EXPECT_EQ(bRet, true);
+ pRtcpEncNode->Stop();
+ delete pRtcpEncNode;
+}
+
+TEST_F(RtcpEncoderNodeTests, SendRtcpXr)
+{
+ RtcpEncoderNode* pRtcpEncNode = new RtcpEncoderNode();
+ pRtcpEncNode->SetMediaType(IMS_MEDIA_VIDEO);
+ EXPECT_EQ(pRtcpEncNode->Start(), RESULT_SUCCESS);
+
+ bool bRet = pRtcpEncNode->SendRtcpXr(nullptr, 0);
+ EXPECT_EQ(bRet, false);
+
+ uint8_t* pDummyRtcpXrPacket = new uint8_t[10];
+ bRet = pRtcpEncNode->SendRtcpXr(pDummyRtcpXrPacket, 10);
+ EXPECT_EQ(bRet, true);
+ pRtcpEncNode->Stop();
+ delete pRtcpEncNode;
+}
+} // namespace \ No newline at end of file