blob: 8a1f99af67b24f872724228dff794a51fa19c95e [file] [log] [blame]
/**
* Copyright (C) 2022 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 <algorithm>
#include <RtpSession.h>
#include <RtpTrace.h>
#include <RtpError.h>
#include <RtpStackUtil.h>
#include <RtpReceiverInfo.h>
#include <RtcpPacket.h>
#include <RtcpChunk.h>
#include <RtpSessionManager.h>
#include <RtcpFbPacket.h>
extern RtpDt_Void Rtp_RtcpTimerCb(IN RtpDt_Void* pvTimerId, IN RtpDt_Void* pvData);
RtpSession::RtpSession() :
m_pobjTransAddr(RTP_NULL),
m_usRtpPort(RTP_ZERO),
m_usRtcpPort(RTP_ZERO),
m_pobjRtpStack(RTP_NULL),
m_usExtHdrLen(RTP_ZERO),
m_pobjRtcpCfgInfo(RTP_NULL),
m_bEnableRTP(eRTP_FALSE),
m_bEnableRTCP(eRTP_FALSE),
m_bEnableRTCPBye(eRTP_FALSE),
m_usRTCPTimerVal(RTP_ZERO),
m_usSeqNum(RTP_ZERO),
m_usSeqNumCycles(RTP_ZERO),
m_pobjPayloadInfo(RTP_NULL),
m_pobjAppInterface(RTP_NULL),
m_uiSsrc(RTP_ZERO),
m_uiSessionMtu(RTP_DEF_MTU_SIZE),
m_uiRtpSendPktCount(RTP_ZERO),
m_uiRtpSendOctCount(RTP_ZERO),
m_uiRtcpSendPktCount(RTP_ZERO),
m_uiRtcpSendOctCount(RTP_ZERO),
m_bSelfCollisionByeSent(eRTP_FAILURE),
m_pTimerId(RTP_NULL),
m_bRtcpSendPkt(eRTP_FALSE),
m_bSndRtcpByePkt(eRTP_FALSE),
m_lastRTTDelay(RTP_ZERO),
m_bisXr(eRTP_FALSE),
m_bFirstRtpRecvd(eRTP_FALSE)
{
m_pobjRtcpCfgInfo = new RtcpConfigInfo();
m_pobjRtpRcvrInfoList = new std::list<RtpReceiverInfo*>();
m_pobjPayloadInfo = new RtpPayloadInfo();
m_pobjUtlRcvrList = RTP_NULL;
m_stRtcpXr.m_pBlockBuffer = RTP_NULL;
}
RtpSession::RtpSession(IN RtpStack* pobjStack) :
m_pobjTransAddr(RTP_NULL),
m_usRtpPort(RTP_ZERO),
m_usRtcpPort(RTP_ZERO),
m_pobjRtpStack(pobjStack),
m_usExtHdrLen(RTP_ZERO),
m_pobjRtcpCfgInfo(RTP_NULL),
m_bEnableRTP(eRTP_FALSE),
m_bEnableRTCP(eRTP_FALSE),
m_bEnableRTCPBye(eRTP_FALSE),
m_usRTCPTimerVal(RTP_ZERO),
m_usSeqNum(RTP_ZERO),
m_usSeqNumCycles(RTP_ZERO),
m_pobjPayloadInfo(RTP_NULL),
m_pobjAppInterface(RTP_NULL),
m_uiSsrc(RTP_ZERO),
m_uiSessionMtu(RTP_DEF_MTU_SIZE),
m_uiRtpSendPktCount(RTP_ZERO),
m_uiRtpSendOctCount(RTP_ZERO),
m_uiRtcpSendPktCount(RTP_ZERO),
m_uiRtcpSendOctCount(RTP_ZERO),
m_bSelfCollisionByeSent(eRTP_FAILURE),
m_pTimerId(RTP_NULL),
m_bRtcpSendPkt(eRTP_FALSE),
m_bSndRtcpByePkt(eRTP_FALSE),
m_lastRTTDelay(RTP_ZERO),
m_bisXr(eRTP_FALSE),
m_bFirstRtpRecvd(eRTP_FALSE)
{
m_pobjRtcpCfgInfo = new RtcpConfigInfo();
m_pobjPayloadInfo = new RtpPayloadInfo();
m_pobjRtpRcvrInfoList = new std::list<RtpReceiverInfo*>();
m_pobjUtlRcvrList = RTP_NULL;
m_stRtcpXr.m_pBlockBuffer = RTP_NULL;
}
RtpSession::~RtpSession()
{
std::lock_guard<std::mutex> guard(m_objRtpSessionLock);
if (m_pobjTransAddr != RTP_NULL)
{
delete m_pobjTransAddr;
m_pobjTransAddr = RTP_NULL;
}
m_pobjRtpStack = RTP_NULL;
if (m_pobjRtcpCfgInfo != RTP_NULL)
{
delete m_pobjRtcpCfgInfo;
m_pobjRtcpCfgInfo = RTP_NULL;
}
if (m_pobjPayloadInfo != RTP_NULL)
{
delete m_pobjPayloadInfo;
m_pobjPayloadInfo = RTP_NULL;
}
if (m_pTimerId != RTP_NULL)
{
}
// delete all RTP session objects.
RtpDt_UInt16 usSize = RTP_ZERO;
usSize = m_pobjRtpRcvrInfoList->size();
for (RtpDt_UInt32 uiCount = RTP_ZERO; uiCount < usSize; uiCount++)
{
RtpReceiverInfo* pobjRcvrElm = RTP_NULL;
// get the member information
pobjRcvrElm = m_pobjRtpRcvrInfoList->front();
m_pobjRtpRcvrInfoList->pop_front();
delete pobjRcvrElm;
} // for
delete m_pobjRtpRcvrInfoList;
delete m_pobjAppInterface;
m_pobjRtpRcvrInfoList = RTP_NULL;
m_pobjAppInterface = RTP_NULL;
}
RtpDt_UInt16 RtpSession::getExtHdrLen()
{
return m_usExtHdrLen;
}
RtpDt_Void RtpSession::setSsrc(IN RtpDt_UInt32 uiSsrc)
{
m_uiSsrc = uiSsrc;
}
RtpDt_UInt32 RtpSession::getSsrc()
{
return m_uiSsrc;
}
RtpDt_Void RtpSession::setRtpPort(IN RtpDt_UInt16 usPort)
{
m_usRtpPort = usPort;
}
RtpDt_UInt16 RtpSession::getRtpPort()
{
return m_usRtpPort;
}
RtpDt_Void RtpSession::setRtpTransAddr(IN RtpBuffer* pobjDestTransAddr)
{
if (m_pobjTransAddr != RTP_NULL)
delete m_pobjTransAddr;
m_pobjTransAddr = pobjDestTransAddr;
}
RtpBuffer* RtpSession::getRtpTransAddr()
{
return m_pobjTransAddr;
}
eRtp_Bool RtpSession::compareRtpSessions(IN RtpSession* pobjSession)
{
if (pobjSession == RTP_NULL)
{
RTP_TRACE_WARNING("compareRtpSessions, Input param is Null.", RTP_ZERO, RTP_ZERO);
return eRTP_FAILURE;
}
if (m_uiSsrc == pobjSession->getSsrc())
{
if (m_usRtpPort == pobjSession->getRtpPort())
{
RtpBuffer* objRtpBuff = pobjSession->getRtpTransAddr();
if (m_pobjTransAddr == RTP_NULL && objRtpBuff == RTP_NULL)
{
return eRTP_SUCCESS;
}
RtpDt_UChar* pcTranAddr1 = m_pobjTransAddr->getBuffer();
RtpDt_UInt32 uiTBufLen = m_pobjTransAddr->getLength();
RtpDt_UChar* pcTranAddr2 = objRtpBuff->getBuffer();
if (pcTranAddr1 == RTP_NULL || pcTranAddr2 == RTP_NULL)
{
return eRTP_FAILURE;
}
if (memcmp(pcTranAddr1, pcTranAddr2, uiTBufLen) == RTP_ZERO)
{
return eRTP_SUCCESS;
}
}
}
return eRTP_FAILURE;
} // compareRtpSessions
RtpDt_Void Rtp_RtcpTimerCb(IN RtpDt_Void* pvTimerId, IN RtpDt_Void* pvData)
{
RtpSessionManager* pobjActSesDb = RtpSessionManager::getInstance();
RtpSession* pobjRtpSession = static_cast<RtpSession*>(pvData);
if (pobjRtpSession == RTP_NULL)
{
RTP_TRACE_WARNING("Rtp_RtcpTimerCb, pvTimerId is NULL.", RTP_ZERO, RTP_ZERO);
return;
}
eRtp_Bool bResult = pobjActSesDb->isValidRtpSession(pvData);
if (bResult != eRTP_TRUE)
{
return;
}
pobjRtpSession->rtcpTimerExpiry(pvTimerId);
}
RtpDt_UInt32 RtpSession::estimateRtcpPktSize()
{
RtpDt_UInt32 uiEstRtcpSize = RTP_ZERO;
RtpDt_UInt32 uiSdesItems = RTP_ZERO;
uiSdesItems = m_pobjRtcpCfgInfo->getSdesItemCount();
if ((m_bSelfCollisionByeSent == eRTP_TRUE) || (m_bSndRtcpByePkt == eRTP_TRUE))
{
uiEstRtcpSize = RTP_DEF_BYE_PKT_SIZE;
uiEstRtcpSize += m_pobjRtcpCfgInfo->getByeReasonSize();
RTP_TRACE_MESSAGE("estimateRtcpPktSize, [Bye packet size : %d]", uiEstRtcpSize, RTP_NULL);
}
else if (uiSdesItems > RTP_ZERO)
{
RtpDt_UInt32 uiSdesPktSize = RTP_WORD_SIZE;
uiSdesPktSize = uiSdesPktSize + m_pobjRtcpCfgInfo->estimateSdesPktSize();
RTP_TRACE_MESSAGE("estimateRtcpPktSize, [uiSdesPktSize : %d]", uiSdesPktSize, RTP_NULL);
uiEstRtcpSize += uiSdesPktSize;
}
if (m_pobjRtcpCfgInfo->isRtcpAppPktSendEnable() == eRTP_TRUE)
{
uiEstRtcpSize += RTP_DEF_APP_PKT_SIZE;
uiEstRtcpSize += m_pobjRtcpCfgInfo->getAppDepDataSize();
RTP_TRACE_MESSAGE("estimateRtcpPktSize, [after app pkt size: %d]", uiEstRtcpSize, RTP_NULL);
}
return uiEstRtcpSize;
}
eRTP_STATUS_CODE RtpSession::formSrList(IN RtpDt_UInt32 uiSndrCount, OUT RtcpPacket* pobjRtcpPkt)
{
eRTP_STATUS_CODE eStatus = RTP_SUCCESS;
RtpDt_UInt32 uiTmpFlg = RTP_ZERO;
while (uiSndrCount > RTP_MAX_RECEP_REP_CNT)
{
RtcpSrPacket* pobjSrPkt = new RtcpSrPacket();
if (pobjSrPkt == RTP_NULL)
{
RTP_TRACE_ERROR("[Memory Error] new returned NULL.", RTP_ZERO, RTP_ZERO);
return RTP_MEMORY_FAIL;
}
// construct SR packet
eStatus = pobjRtcpPkt->addSrPacketData(pobjSrPkt);
if (eStatus != RTP_SUCCESS)
{
return eStatus;
}
eStatus = populateSrpacket(pobjSrPkt, RTP_MAX_RECEP_REP_CNT);
if (eStatus != RTP_SUCCESS)
{
return eStatus;
}
uiSndrCount = uiSndrCount - RTP_MAX_RECEP_REP_CNT;
uiTmpFlg = RTP_ONE;
} // while
if ((uiSndrCount > RTP_ZERO) || (uiTmpFlg == RTP_ZERO))
{
RtcpSrPacket* pobjSrPkt = new RtcpSrPacket();
if (pobjSrPkt == RTP_NULL)
{
RTP_TRACE_ERROR("[Memory Error] new returned NULL.", RTP_ZERO, RTP_ZERO);
return RTP_MEMORY_FAIL;
}
// construct SR packet
eStatus = pobjRtcpPkt->addSrPacketData(pobjSrPkt);
if (eStatus != RTP_SUCCESS)
{
return eStatus;
}
eStatus = populateSrpacket(pobjSrPkt, uiSndrCount);
if (eStatus != RTP_SUCCESS)
{
return eStatus;
}
}
return RTP_SUCCESS;
} // formSrList
eRTP_STATUS_CODE RtpSession::formRrList(IN RtpDt_UInt32 uiSndrCount, OUT RtcpPacket* pobjRtcpPkt)
{
eRTP_STATUS_CODE eStatus = RTP_SUCCESS;
RtpDt_UInt32 uiTmpFlg = RTP_ZERO;
while (uiSndrCount > RTP_MAX_RECEP_REP_CNT)
{
RtcpRrPacket* pobjRrPkt = new RtcpRrPacket();
if (pobjRrPkt == RTP_NULL)
{
RTP_TRACE_ERROR("[Memory Error] new returned NULL.", RTP_ZERO, RTP_ZERO);
return RTP_MEMORY_FAIL;
}
// construct RR packet
eStatus = pobjRtcpPkt->addRrPacketData(pobjRrPkt);
if (eStatus != RTP_SUCCESS)
{
RTP_TRACE_WARNING("formRrList, error in addRrPacketData.", RTP_ZERO, RTP_ZERO);
return eStatus;
}
eStatus = populateReportPacket(pobjRrPkt, eRTP_TRUE, RTP_MAX_RECEP_REP_CNT);
if (eStatus != RTP_SUCCESS)
{
RTP_TRACE_WARNING("formRrList, error in populateReportPacket.", RTP_ZERO, RTP_ZERO);
return eStatus;
}
uiSndrCount = uiSndrCount - RTP_MAX_RECEP_REP_CNT;
uiTmpFlg = RTP_ONE;
} // while
if ((uiSndrCount > RTP_ZERO) || (uiTmpFlg == RTP_ZERO))
{
RtcpRrPacket* pobjRrPkt = new RtcpRrPacket();
if (pobjRrPkt == RTP_NULL)
{
RTP_TRACE_ERROR("[Memory Error] new returned NULL.", RTP_ZERO, RTP_ZERO);
return RTP_MEMORY_FAIL;
}
// construct RR packet
eStatus = pobjRtcpPkt->addRrPacketData(pobjRrPkt);
if (eStatus != RTP_SUCCESS)
{
RTP_TRACE_WARNING("formRrList, error in addRrPacketData.", RTP_ZERO, RTP_ZERO);
return eStatus;
}
eStatus = populateReportPacket(pobjRrPkt, eRTP_TRUE, uiSndrCount);
if (eStatus != RTP_SUCCESS)
{
RTP_TRACE_WARNING("formRrList, error in populateReportPacket.", RTP_ZERO, RTP_ZERO);
return eStatus;
}
}
return RTP_SUCCESS;
} // formSrList
RtpDt_UInt32 RtpSession::numberOfReportBlocks(
IN RtpDt_UInt32 uiMtuSize, IN RtpDt_UInt32 uiEstRtcpSize)
{
RtpDt_UInt32 uiReportDefSize = RTCP_FIXED_HDR_LEN + RTP_DEF_SR_SPEC_SIZE;
// determine the sender count
RtpDt_UInt32 uiRemTotalSize = uiMtuSize - uiEstRtcpSize;
// one SR packet size with 31 report blocks
RtpDt_UInt32 uiReportMaxSize = uiReportDefSize + (RTP_MAX_RECEP_REP_CNT * RTP_DEF_REP_BLK_SIZE);
RtpDt_UInt32 uiTotalNumofReport = uiRemTotalSize / uiReportMaxSize;
uiRemTotalSize = uiRemTotalSize - (uiReportMaxSize * uiTotalNumofReport);
uiRemTotalSize = uiRemTotalSize - uiReportDefSize;
RtpDt_UInt32 uiRemRepBlkNum = uiRemTotalSize / RTP_DEF_REP_BLK_SIZE;
uiRemRepBlkNum += uiTotalNumofReport * RTP_MAX_RECEP_REP_CNT;
return uiRemRepBlkNum;
}
RtpDt_UInt32 RtpSession::calculateTotalRtcpSize(
IN RtpDt_UInt32 uiSndrCount, IN RtpDt_UInt32 uiEstRtcpSize, IN eRtp_Bool isSR)
{
RtpDt_UInt32 uiReortDefSize = RTP_ZERO;
if (isSR == eRTP_TRUE)
{
uiReortDefSize = RTCP_FIXED_HDR_LEN + RTP_DEF_SR_SPEC_SIZE;
}
else
{
uiReortDefSize = RTCP_FIXED_HDR_LEN;
}
RtpDt_UInt32 uiTmpSndrCount = uiSndrCount;
RtpDt_UInt32 uiReortFlg = RTP_ZERO;
RtpDt_UInt32 uiReportTotalSize = RTP_ZERO;
while (uiTmpSndrCount > RTP_MAX_RECEP_REP_CNT)
{
uiReportTotalSize += uiReortDefSize + (RTP_MAX_RECEP_REP_CNT * RTP_DEF_REP_BLK_SIZE);
uiTmpSndrCount = uiTmpSndrCount - RTP_MAX_RECEP_REP_CNT;
uiReportTotalSize += m_usExtHdrLen;
uiReortFlg = RTP_ONE;
}
if ((uiTmpSndrCount > RTP_ZERO) || (uiReortFlg == RTP_ZERO))
{
uiReportTotalSize += uiReortDefSize + (uiTmpSndrCount * RTP_DEF_REP_BLK_SIZE);
}
RtpDt_UInt32 uiTotalRtcpSize = uiEstRtcpSize + uiReportTotalSize;
return uiTotalRtcpSize;
}
RtpDt_Void RtpSession::rtpSetTimestamp()
{
RtpOsUtil::GetNtpTime(m_stCurNtpRtcpTs);
if (m_bRtcpSendPkt == eRTP_FALSE)
{
m_bRtcpSendPkt = eRTP_TRUE;
}
RtpDt_UInt32 uiSamplingRate = m_pobjPayloadInfo->getSamplingRate();
// The RTP timestamp corresponds to the same instant as the NTP timestamp,
// but it is expressed inthe units of the RTP media clock.
// The value is generally not the same as the RTP timestamp of the previous data packet,
// because some time will have elapsed since the data in that packet was samples
// RTP Timestamp = Last RTP Pkt timestamp
// + timegap between last RTP packet and current RTCP packet
m_curRtcpTimestamp = RtpStackUtil::calcRtpTimestamp(
m_curRtpTimestamp, &m_stCurNtpRtcpTs, &m_stCurNtpTimestamp, uiSamplingRate);
}
eRTP_STATUS_CODE RtpSession::rtpMakeCompoundRtcpPacket(IN_OUT RtcpPacket* objRtcpPkt)
{
// estimate the size of the RTCP packet
RtpDt_UInt32 uiEstRtcpSize = estimateRtcpPktSize();
RtpDt_UInt32 uiSndrCount = getSenderCount();
// get mtu size
RtpStackProfile* pobjProfile = m_pobjRtpStack->getStackProfile();
RtpDt_UInt32 uiMtuSize = pobjProfile->getMtuSize();
RtpDt_UInt32 uiSdesItems = m_pobjRtcpCfgInfo->getSdesItemCount();
eRTP_STATUS_CODE eEncRes = RTP_FAILURE;
// check number of packets are sent
if ((m_bRtpSendPkt == eRTP_TRUE) || (m_bSelfCollisionByeSent == eRTP_TRUE) ||
(m_bSndRtcpByePkt == eRTP_TRUE))
{
RtpDt_UInt32 uiTotalRtcpSize = RTP_ZERO;
uiTotalRtcpSize = calculateTotalRtcpSize(uiSndrCount, uiEstRtcpSize, eRTP_TRUE);
if (uiTotalRtcpSize < uiMtuSize)
{
RTP_TRACE_MESSAGE(
"rtpMakeCompoundRtcpPacket,[uiTotalRtcpSize : %d] [Estimated Size : %d]",
uiTotalRtcpSize, uiEstRtcpSize);
eEncRes = formSrList(uiSndrCount, objRtcpPkt);
if (eEncRes != RTP_SUCCESS)
{
RTP_TRACE_ERROR("formSrList error: %d", eEncRes, 0);
m_pobjAppInterface->rtcpTimerHdlErrorInd(eEncRes);
return eEncRes;
}
}
else
{
RtpDt_UInt32 uiRemRepBlkNum = RTP_ZERO;
uiRemRepBlkNum = numberOfReportBlocks(uiMtuSize, uiEstRtcpSize);
eEncRes = formSrList(uiRemRepBlkNum, objRtcpPkt);
if (eEncRes != RTP_SUCCESS)
{
RTP_TRACE_ERROR("formSrList error: %d", eEncRes, 0);
m_pobjAppInterface->rtcpTimerHdlErrorInd(eEncRes);
return eEncRes;
}
}
} // SR
else
{
RtpDt_UInt32 uiTotalRtcpSize = RTP_ZERO;
uiTotalRtcpSize = calculateTotalRtcpSize(uiSndrCount, uiEstRtcpSize, eRTP_FALSE);
if (uiTotalRtcpSize < uiMtuSize)
{
eEncRes = formRrList(uiSndrCount, objRtcpPkt);
if (eEncRes != RTP_SUCCESS)
{
RTP_TRACE_ERROR("formRrList error: %d", eEncRes, 0);
m_pobjAppInterface->rtcpTimerHdlErrorInd(eEncRes);
return eEncRes;
}
}
else
{
RtpDt_UInt32 uiRemRepBlkNum = RTP_ZERO;
uiRemRepBlkNum = numberOfReportBlocks(uiMtuSize, uiEstRtcpSize);
eEncRes = formRrList(uiRemRepBlkNum, objRtcpPkt);
if (eEncRes != RTP_SUCCESS)
{
RTP_TRACE_ERROR("formRrList error: %d", eEncRes, 0);
m_pobjAppInterface->rtcpTimerHdlErrorInd(eEncRes);
return eEncRes;
}
}
} // RR
if ((m_bSelfCollisionByeSent == eRTP_TRUE) || (m_bSndRtcpByePkt == eRTP_TRUE))
{
eRTP_STATUS_CODE eStatus = RTP_SUCCESS;
// construct BYE packet
eStatus = populateByePacket(objRtcpPkt);
if (eStatus != RTP_SUCCESS)
{
RTP_TRACE_ERROR("populateByePacket error: %d", eEncRes, 0);
m_pobjAppInterface->rtcpTimerHdlErrorInd(eStatus);
return eStatus;
}
}
else if (uiSdesItems > RTP_ZERO)
{
eRTP_STATUS_CODE eStatus = RTP_SUCCESS;
eStatus = constructSdesPkt(objRtcpPkt);
if (eStatus != RTP_SUCCESS)
{
RTP_TRACE_ERROR("constructSdesPkt error: %d", eEncRes, 0);
m_pobjAppInterface->rtcpTimerHdlErrorInd(eStatus);
return eStatus;
}
}
if (m_bisXr == eRTP_TRUE)
{
eRTP_STATUS_CODE eStatus = RTP_SUCCESS;
eStatus = populateRtcpXrPacket(objRtcpPkt);
if (eStatus != RTP_SUCCESS)
{
RTP_TRACE_ERROR("populateRtcpXrPacket error: %d", eEncRes, 0);
m_pobjAppInterface->rtcpTimerHdlErrorInd(eStatus);
return eStatus;
}
m_bisXr = eRTP_FALSE;
}
return RTP_SUCCESS;
}
eRTP_STATUS_CODE RtpSession::rtpSendRtcpPacket(IN_OUT RtcpPacket* objRtcpPkt)
{
RtpBuffer* pRtcpBuf = new RtpBuffer();
if (pRtcpBuf == RTP_NULL)
{
RTP_TRACE_ERROR("[Memory Error] new returned NULL.", RTP_ZERO, RTP_ZERO);
m_pobjAppInterface->rtcpTimerHdlErrorInd(RTP_MEMORY_FAIL);
return RTP_FAILURE;
}
RtpDt_UChar* pcBuff = new RtpDt_UChar[RTP_DEF_MTU_SIZE];
if (pcBuff == RTP_NULL)
{
RTP_TRACE_ERROR("[Memory Error] new returned NULL.", RTP_ZERO, RTP_ZERO);
delete pRtcpBuf;
m_pobjAppInterface->rtcpTimerHdlErrorInd(RTP_MEMORY_FAIL);
return RTP_FAILURE;
}
pRtcpBuf->setBufferInfo(RTP_DEF_MTU_SIZE, pcBuff);
// construct the packet
eRTP_STATUS_CODE eEncRes = RTP_FAILURE;
eEncRes = objRtcpPkt->formRtcpPacket(pRtcpBuf);
if (eEncRes == RTP_SUCCESS)
{
// pass the RTCP buffer to application.
eRtp_Bool bStatus = eRTP_FALSE;
bStatus = m_pobjAppInterface->rtcpPacketSendInd(pRtcpBuf, this);
if (bStatus == eRTP_FALSE)
{
RTP_TRACE_WARNING("rtpSendRtcpPacket, RTCP send error.", RTP_ZERO, RTP_ZERO);
}
}
else
{
RTP_TRACE_ERROR("rtpSendRtcpPacket, error in formRtcpPacket.", RTP_ZERO, RTP_ZERO);
m_pobjAppInterface->rtcpTimerHdlErrorInd(eEncRes);
}
// update average rtcp size
m_objTimerInfo.updateAvgRtcpSize(pRtcpBuf->getLength());
delete pRtcpBuf;
if (m_stRtcpXr.m_pBlockBuffer != RTP_NULL)
{
delete m_stRtcpXr.m_pBlockBuffer;
m_stRtcpXr.m_pBlockBuffer = RTP_NULL;
}
return RTP_SUCCESS;
}
RtpDt_Void RtpSession::rtcpTimerExpiry(IN RtpDt_Void* pvTimerId)
{
// RtpDt_UInt32 uiSamplingRate = RTP_ZERO;
std::lock_guard<std::mutex> guard(m_objRtpSessionLock);
eRtp_Bool bSessAlive = eRTP_FALSE;
RtpSessionManager* pobjActSesDb = RtpSessionManager::getInstance();
bSessAlive = pobjActSesDb->isValidRtpSession(this);
if (!bSessAlive)
{
return;
}
if (m_pTimerId == pvTimerId)
{
m_pTimerId = RTP_NULL;
}
RtpDt_UInt16 usMembers = m_pobjRtpRcvrInfoList->size();
RtpDt_UInt32 uiTempTc = m_objTimerInfo.getTc();
RtpDt_Double dTempT = rtcp_interval(usMembers);
// convert uiTempT to milliseconds
dTempT = dTempT * RTP_SEC_TO_MILLISEC;
RtpDt_UInt32 uiRoundDiff = (RtpDt_UInt32)dTempT;
uiRoundDiff = ((uiRoundDiff / 100) * 100);
// uiTempTn = m_objTimerInfo.getTp() + (RtpDt_UInt32)dTempT;
RtpDt_UInt32 uiTempTn = m_objTimerInfo.getTp() + uiRoundDiff;
RTP_TRACE_MESSAGE(
"rtcpTimerExpiry [Tp : %u] [difference = %u]", m_objTimerInfo.getTp(), uiRoundDiff);
RTP_TRACE_MESSAGE(
"rtcpTimerExpiry [Tp : %u] [difference = %f]", m_objTimerInfo.getTp(), dTempT);
RTP_TRACE_MESSAGE("rtcpTimerExpiry before processing[Tn : %u] [Tc : %u]", uiTempTn, uiTempTc);
m_objTimerInfo.setTn(uiTempTn);
RtpDt_UInt32 uiTimerVal = RTP_ZERO;
RtpDt_Void* pvData = RTP_NULL;
if ((m_bSelfCollisionByeSent != eRTP_TRUE) || (m_bSndRtcpByePkt != eRTP_TRUE))
{
if (uiTempTn > uiTempTc)
{
uiTimerVal = uiTempTn - uiTempTc;
if (uiTimerVal > uiRoundDiff)
{
uiTimerVal = uiRoundDiff;
}
/*uiTempTn = uiTempTc + uiRoundDiff;
m_objTimerInfo.setTn(uiTempTn);
m_objTimerInfo.setTp(uiTempTc);*/
RTP_TRACE_MESSAGE("rtcpTimerExpiry [Tn : %u] [Tc : %u]", uiTempTn, uiTempTc);
eRtp_Bool bTSres = eRTP_FALSE;
bTSres = m_pobjAppInterface->RtpStopTimer(m_pTimerId, &pvData);
m_pTimerId = RTP_NULL;
if (bTSres == eRTP_FALSE)
{
return;
}
if (m_bEnableRTCP == eRTP_TRUE)
{
RtpDt_Void* pvSTRes = m_pobjAppInterface->RtpStartTimer(
uiTimerVal, eRTP_FALSE, m_pfnTimerCb, reinterpret_cast<RtpDt_Void*>(this));
if (pvSTRes == RTP_NULL)
{
return;
}
m_pTimerId = pvSTRes;
}
return;
}
}
// set timestamp
rtpSetTimestamp();
RtcpPacket objRtcpPkt;
eRTP_STATUS_CODE eEncRes = RTP_FAILURE;
eEncRes = rtpMakeCompoundRtcpPacket(&objRtcpPkt);
if (eEncRes != RTP_SUCCESS)
{
RTP_TRACE_ERROR("MakeCompoundRtcpPacket Error: %d", eEncRes, RTP_ZERO);
return;
}
// check number of packets are sent
eEncRes = rtpSendRtcpPacket(&objRtcpPkt);
if (eEncRes != RTP_SUCCESS)
{
RTP_TRACE_ERROR("rtpSendRtcpPacket Error: %d", eEncRes, RTP_ZERO);
return;
}
// set Tp with Tc
m_objTimerInfo.setTp(uiTempTc);
// recalculate timer in
dTempT = rtcp_interval(usMembers);
dTempT = dTempT * RTP_SEC_TO_MILLISEC;
uiRoundDiff = (RtpDt_UInt32)dTempT;
uiTempTn = uiTempTc + uiRoundDiff;
// uiTempTn = uiTempTc + dTempT;
m_objTimerInfo.setTn(uiTempTn);
// restart the timer
// uiTimerVal = m_objTimerInfo.getTn() - uiTempTc;
if (m_usRTCPTimerVal > RTP_ZERO)
{
uiTimerVal = m_usRTCPTimerVal * RTP_SEC_TO_MILLISEC;
}
else
{
uiTimerVal = uiRoundDiff;
}
// uiTimerVal = (RtpDt_UInt32)dTempT;
// Reschedule the next report for time tn
if (m_pTimerId != RTP_NULL)
{
eRtp_Bool bTSres = eRTP_FALSE;
bTSres = m_pobjAppInterface->RtpStopTimer(m_pTimerId, &pvData);
m_pTimerId = RTP_NULL;
if (bTSres == eRTP_FALSE)
{
return;
}
}
if (m_bEnableRTCP == eRTP_TRUE)
{
RtpDt_Void* pvSTRes = RTP_NULL;
pvSTRes = m_pobjAppInterface->RtpStartTimer(
uiTimerVal, eRTP_FALSE, m_pfnTimerCb, reinterpret_cast<RtpDt_Void*>(this));
if (pvSTRes == RTP_NULL)
{
return;
}
m_pTimerId = pvSTRes;
}
// set m_bInitial = false
m_objTimerInfo.setInitial(eRTP_FALSE);
// update we_sent
if (m_objTimerInfo.getWeSent() == RTP_TWO)
{
m_objTimerInfo.setWeSent(RTP_ONE);
}
else
{
m_objTimerInfo.setWeSent(RTP_ZERO);
}
// set pmembers with members
m_objTimerInfo.setPmembers(usMembers);
// set m_bRtpSendPkt to false
m_bRtpSendPkt = eRTP_FALSE;
return;
} // rtcpTimerExpiry
eRTP_STATUS_CODE RtpSession::populateSrpacket(
OUT RtcpSrPacket* pobjSrPkt, IN RtpDt_UInt32 uiRecepCount)
{
tRTP_NTP_TIME* pstNtpTime = pobjSrPkt->getNtpTime();
// NTP timestamp, most significant word
pstNtpTime->m_uiNtpHigh32Bits = m_stCurNtpRtcpTs.m_uiNtpHigh32Bits;
// NTP timestamp, least significant word
pstNtpTime->m_uiNtpLow32Bits = m_stCurNtpRtcpTs.m_uiNtpLow32Bits;
// RTCP timestamp
pobjSrPkt->setRtpTimestamp(m_curRtcpTimestamp);
// sender's packet count
pobjSrPkt->setSendPktCount(m_uiRtpSendPktCount);
// sender's octet count
pobjSrPkt->setSendOctetCount(m_uiRtpSendOctCount);
eRTP_STATUS_CODE eRepPktSta = RTP_FAILURE;
eRepPktSta = populateReportPacket(pobjSrPkt->getRrPktInfo(), eRTP_FALSE, uiRecepCount);
if (eRepPktSta != RTP_SUCCESS)
{
return eRepPktSta;
}
return RTP_SUCCESS;
} // populateSrpacket
RtpDt_Void RtpSession::cleanUtlReceiverList()
{
// populate report blocks
for (const auto& pobjRcvrElm : *m_pobjUtlRcvrList)
{
delete pobjRcvrElm;
}
m_pobjUtlRcvrList->clear();
} // cleanUtlReceiverList
eRTP_STATUS_CODE RtpSession::populateReportPacket(
OUT RtcpRrPacket* pobjRrPkt, IN eRtp_Bool bRrPkt, IN RtpDt_UInt32 uiRecepCount)
{
RtcpHeader* pRtcpHdr = pobjRrPkt->getRtcpHdrInfo();
std::list<RtcpReportBlock*>& pobjRepBlkLst = pobjRrPkt->getReportBlockList();
// get receiver list size
if (bRrPkt == eRTP_TRUE)
{
pRtcpHdr->populateRtcpHeader((RtpDt_UChar)uiRecepCount, (RtpDt_UChar)RTCP_RR, m_uiSsrc);
}
else
{
pRtcpHdr->populateRtcpHeader((RtpDt_UChar)uiRecepCount, (RtpDt_UChar)RTCP_SR, m_uiSsrc);
}
if (uiRecepCount == RTP_ZERO)
{
return RTP_SUCCESS;
}
std::list<RtpReceiverInfo*>* pobjTmpRcvrList = m_pobjRtpRcvrInfoList;
m_pobjUtlRcvrList = new std::list<RtpReceiverInfo*>();
if (m_pobjUtlRcvrList == RTP_NULL)
{
RTP_TRACE_ERROR("[Memory Error] new returned NULL.", RTP_ZERO, RTP_ZERO);
return RTP_MEMORY_FAIL;
}
eRtp_Bool bFirstPos = eRTP_TRUE;
RtpDt_UInt32 uiTmpRecpCount = RTP_ZERO;
std::list<RtpReceiverInfo*>::iterator iter;
// populate report blocks
for (auto& pobjRcvrElm : *m_pobjRtpRcvrInfoList)
{
// get the member information
if ((pobjRcvrElm->isSender() == eRTP_TRUE) && (uiTmpRecpCount <= uiRecepCount))
{
RtcpReportBlock* pobjRepBlk = new RtcpReportBlock();
if (pobjRepBlk == RTP_NULL)
{
RTP_TRACE_ERROR("[Memory Error] new returned NULL.", RTP_ZERO, RTP_ZERO);
cleanUtlReceiverList();
delete m_pobjUtlRcvrList;
m_pobjUtlRcvrList = RTP_NULL;
return RTP_MEMORY_FAIL;
}
pobjRcvrElm->populateReportBlock(pobjRepBlk);
pobjRepBlkLst.push_back(pobjRepBlk);
pobjRcvrElm->setSenderFlag(eRTP_FALSE);
m_pobjUtlRcvrList->push_back(pobjRcvrElm);
uiTmpRecpCount = uiTmpRecpCount + RTP_ONE;
}
else
{
if (pobjRcvrElm->getCsrcFlag() == eRTP_TRUE)
{
m_pobjUtlRcvrList->push_back(pobjRcvrElm);
}
else
{
if (bFirstPos == eRTP_TRUE)
{
m_pobjUtlRcvrList->push_front(pobjRcvrElm);
iter = m_pobjUtlRcvrList->begin();
bFirstPos = eRTP_FALSE;
}
else
{
m_pobjUtlRcvrList->insert(iter, pobjRcvrElm);
}
}
}
}
m_pobjRtpRcvrInfoList->clear();
m_pobjRtpRcvrInfoList = m_pobjUtlRcvrList;
delete pobjTmpRcvrList;
#ifdef ENABLE_RTCPEXT
// Extension header
if (m_usExtHdrLen > RTP_ZERO)
{
RtpBuffer* pobjExtHdrInfo = new RtpBuffer();
if (pobjExtHdrInfo == RTP_NULL)
{
RTP_TRACE_ERROR("[Memory Error] new returned NULL.", RTP_ZERO, RTP_ZERO);
return RTP_MEMORY_FAIL;
}
else
{
m_pobjAppInterface->getRtpHdrExtInfo(pobjExtHdrInfo);
pobjRrPkt->setExtHdrInfo(pobjExtHdrInfo);
}
}
#endif
return RTP_SUCCESS;
} // populateReportPacket
eRTP_STATUS_CODE RtpSession::populateByePacket(IN_OUT RtcpPacket* pobjRtcpPkt)
{
RtcpByePacket* pobjByePkt = new RtcpByePacket();
if (pobjByePkt == RTP_NULL)
{
RTP_TRACE_ERROR("[Memory Error] new returned NULL.", RTP_ZERO, RTP_ZERO);
return RTP_MEMORY_FAIL;
}
RtcpHeader* pRtcpHdr = pobjByePkt->getRtcpHdrInfo();
pobjRtcpPkt->setByePacketData(pobjByePkt);
// populate App packet header.
pRtcpHdr->populateRtcpHeader((RtpDt_UChar)RTP_ONE, RTCP_BYE, m_uiSsrc);
return RTP_SUCCESS;
} // populateByePacket
eRTP_STATUS_CODE RtpSession::populateAppPacket(IN_OUT RtcpPacket* pobjRtcpPkt)
{
RtcpAppPacket* pobjAppPkt = new RtcpAppPacket();
if (pobjAppPkt == RTP_NULL)
{
RTP_TRACE_ERROR("[Memory Error] new returned NULL.", RTP_ZERO, RTP_ZERO);
return RTP_MEMORY_FAIL;
}
RtpBuffer* pobjPayload = new RtpBuffer();
if (pobjPayload == RTP_NULL)
{
RTP_TRACE_ERROR("[Memory Error] new returned NULL.", RTP_ZERO, RTP_ZERO);
delete pobjAppPkt;
return RTP_MEMORY_FAIL;
}
// fill application dependent data
pobjAppPkt->setAppData(pobjPayload);
RtcpHeader* pRtcpHdr = pobjAppPkt->getRtcpHdrInfo();
RtpDt_UInt16 usSubType = RTP_ZERO;
RtpDt_UInt32 uiName = RTP_ZERO;
eRtp_Bool bStatus = eRTP_FALSE;
pobjRtcpPkt->setAppPktData(pobjAppPkt);
bStatus = m_pobjAppInterface->rtcpAppPayloadReqInd(usSubType, uiName, pobjPayload);
if (bStatus != eRTP_TRUE)
{
return RTP_FAILURE;
}
// populate App packet header.
pRtcpHdr->populateRtcpHeader((RtpDt_UChar)usSubType, RTCP_APP, m_uiSsrc);
// fill name
pobjAppPkt->setName(uiName);
return RTP_SUCCESS;
} // populateAppPacket
eRTP_STATUS_CODE RtpSession::populateRtcpFbPacket(IN_OUT RtcpPacket* pobjRtcpPkt,
IN RtpDt_UInt32 uiFbType, IN RtpDt_Char* pcBuff, IN RtpDt_UInt32 uiLen,
IN RtpDt_UInt32 uiMediaSSRC, IN RtpDt_UInt32 uiPayloadType)
{
// create RtcpFbPacket
RtcpFbPacket* pobjRtcpRtpFbPacket = new RtcpFbPacket();
// create payload FCI buffer
RtpBuffer* pobjPayload = new RtpBuffer(uiLen, reinterpret_cast<RtpDt_UChar*>(pcBuff));
// set Media SSRC
pobjRtcpRtpFbPacket->setMediaSsrc(uiMediaSSRC);
// set FCI data
pobjRtcpRtpFbPacket->setFCI(pobjPayload);
// set feedback type
pobjRtcpRtpFbPacket->setPayloadType((eRTCP_TYPE)uiPayloadType);
// set the RTCP packet
pobjRtcpPkt->addFbPacketData(pobjRtcpRtpFbPacket);
// get and populate the RTCP header
RtcpHeader* pRtcpHdr = pobjRtcpRtpFbPacket->getRtcpHdrInfo();
pRtcpHdr->populateRtcpHeader((RtpDt_UChar)uiFbType, uiPayloadType, m_uiSsrc);
return RTP_SUCCESS;
}
eRTP_STATUS_CODE RtpSession::constructSdesPkt(IN_OUT RtcpPacket* pobjRtcpPkt)
{
if (m_pobjRtcpCfgInfo == RTP_NULL || pobjRtcpPkt == RTP_NULL)
return RTP_FAILURE;
RtpDt_UInt32 uiSdesItems = m_pobjRtcpCfgInfo->getSdesItemCount();
RtcpSdesPacket* pobjSdesPkt = new RtcpSdesPacket();
if (pobjSdesPkt == RTP_NULL)
{
RTP_TRACE_ERROR("[Memory Error] new returned NULL.", RTP_ZERO, RTP_ZERO);
return RTP_MEMORY_FAIL;
}
RtcpChunk* pobjChunk = new RtcpChunk();
if (pobjChunk == RTP_NULL)
{
RTP_TRACE_ERROR("[Memory Error] new returned NULL.", RTP_ZERO, RTP_ZERO);
delete pobjSdesPkt;
return RTP_MEMORY_FAIL;
}
RtcpHeader* pRtcpHdr = pobjSdesPkt->getRtcpHdrInfo();
if (pRtcpHdr == RTP_NULL)
{
RTP_TRACE_ERROR("Failed to retrieve Rtcp Header Info", RTP_ZERO, RTP_ZERO);
delete pobjSdesPkt;
delete pobjChunk;
return RTP_FAILURE;
}
std::list<RtcpChunk*>& pobjSdesList = pobjSdesPkt->getSdesChunkList();
pobjRtcpPkt->setSdesPacketData(pobjSdesPkt);
// populate SDES packet header.
pRtcpHdr->populateRtcpHeader(RTP_ONE, RTCP_SDES, m_uiSsrc);
pobjSdesList.push_back(pobjChunk);
pobjChunk->setSsrc(m_uiSsrc);
std::list<tRTCP_SDES_ITEM*>& pobjChunkList = pobjChunk->getSdesItemList();
for (RtpDt_UInt32 uiCount = RTP_ZERO; uiCount < uiSdesItems; uiCount++)
{
tRTCP_SDES_ITEM* pstSdesItem = m_pobjRtcpCfgInfo->getRtcpSdesItem(uiCount);
if (pstSdesItem && pstSdesItem->pValue != RTP_NULL)
{
tRTCP_SDES_ITEM* pstTmpSdesItem = new tRTCP_SDES_ITEM();
if (pstTmpSdesItem == RTP_NULL)
{
return RTP_MEMORY_FAIL;
}
RtpDt_UChar* pucSdesBuf = new RtpDt_UChar[pstSdesItem->ucLength];
if (pucSdesBuf == RTP_NULL)
{
delete pstTmpSdesItem;
return RTP_MEMORY_FAIL;
}
pstTmpSdesItem->ucType = pstSdesItem->ucType;
pstTmpSdesItem->ucLength = pstSdesItem->ucLength;
memcpy(pucSdesBuf, pstSdesItem->pValue, pstSdesItem->ucLength);
pstTmpSdesItem->pValue = pucSdesBuf;
pobjChunkList.push_back(pstTmpSdesItem);
}
}
return RTP_SUCCESS;
} // constructSdesPkt
eRTP_STATUS_CODE RtpSession::disableRtp()
{
m_bEnableRTP = eRTP_FALSE;
return RTP_SUCCESS;
}
eRTP_STATUS_CODE RtpSession::enableRtp()
{
m_bEnableRTP = eRTP_TRUE;
return RTP_SUCCESS;
}
eRtp_Bool RtpSession::isRtpEnabled()
{
return m_bEnableRTP;
}
eRTP_STATUS_CODE RtpSession::enableRtcp(eRtp_Bool enableRTCPBye)
{
RtpStackProfile* pobjRtpProfile = m_pobjRtpStack->getStackProfile();
if (pobjRtpProfile == RTP_NULL)
return RTP_FAILURE;
// timer value shall be in milli seconds
RtpDt_UInt32 uiTimerVal = RTP_INIT_TRUE_T_MIN * RTP_SEC_TO_MILLISEC;
if (m_usRTCPTimerVal > RTP_ZERO)
{
uiTimerVal = m_usRTCPTimerVal * RTP_SEC_TO_MILLISEC;
}
if (m_bEnableRTCP == eRTP_TRUE)
{
RTP_TRACE_WARNING("enableRtcp, m_bEnableRTCP is already enabled.", RTP_ZERO, RTP_ZERO);
return RTP_RTCP_ALREADY_RUNNING;
}
m_bEnableRTCP = eRTP_TRUE;
m_bEnableRTCPBye = enableRTCPBye;
RtpSessionManager* pobjActSesDb = RtpSessionManager::getInstance();
pobjActSesDb->addRtpSession(reinterpret_cast<RtpDt_Void*>(this));
RtpDt_Void* pvData = RTP_NULL;
if (m_pTimerId != RTP_NULL && m_pobjAppInterface != RTP_NULL)
{
eRtp_Bool bTSres = eRTP_FALSE;
bTSres = m_pobjAppInterface->RtpStopTimer(m_pTimerId, &pvData);
m_pTimerId = RTP_NULL;
if (bTSres == eRTP_FALSE)
{
RTP_TRACE_WARNING("enableRtcp, Stop timer is returned NULL value.", RTP_ZERO, RTP_ZERO);
return RTP_TIMER_PROC_ERR;
}
}
RtpDt_Void* pvSTRes = RTP_NULL;
if (m_pobjAppInterface != RTP_NULL)
{
m_pfnTimerCb = Rtp_RtcpTimerCb;
// start RTCP timer with default value
pvSTRes = m_pobjAppInterface->RtpStartTimer(
uiTimerVal, eRTP_FALSE, m_pfnTimerCb, reinterpret_cast<RtpDt_Void*>(this));
if (pvSTRes == RTP_NULL)
{
RTP_TRACE_WARNING(
"enableRtcp, start timer is returned NULL value.", RTP_ZERO, RTP_ZERO);
return RTP_TIMER_PROC_ERR;
}
}
m_pTimerId = pvSTRes;
RtpDt_UInt32 uiTempTc = m_objTimerInfo.getTc();
m_objTimerInfo.setTp(uiTempTc);
m_objTimerInfo.setTn(uiTempTc + uiTimerVal);
// RTCP BW
m_objTimerInfo.setRtcpBw(pobjRtpProfile->getRtcpBandwidth());
// AVG RTCP SIZE
m_objTimerInfo.setAvgRtcpSize(pobjRtpProfile->getRtcpBandwidth());
return RTP_SUCCESS;
}
eRTP_STATUS_CODE RtpSession::disableRtcp()
{
RtpDt_Void* pvData = RTP_NULL;
RtpSessionManager* pobjActSesDb = RtpSessionManager::getInstance();
pobjActSesDb->removeRtpSession(this);
m_bEnableRTCP = eRTP_FALSE;
m_bEnableRTCPBye = eRTP_FALSE;
if (m_pTimerId != RTP_NULL && m_pobjAppInterface != RTP_NULL)
{
m_pobjAppInterface->RtpStopTimer(m_pTimerId, &pvData);
m_pTimerId = RTP_NULL;
}
m_objTimerInfo.cleanUp();
return RTP_SUCCESS;
}
eRTP_STATUS_CODE RtpSession::initSession(
IN IRtpAppInterface* pobjAppInterface, IN RtcpConfigInfo* pobjRtcpConfigInfo)
{
// set m_pobjAppInterface
if (pobjAppInterface != RTP_NULL)
{
if (m_pobjAppInterface != RTP_NULL)
delete m_pobjAppInterface;
m_pobjAppInterface = pobjAppInterface;
}
else
{
RTP_TRACE_WARNING("initSession, pobjAppInterface is NULL.", RTP_ZERO, RTP_ZERO);
return RTP_INVALID_PARAMS;
}
// set pobjRtcpConfigInfo
if (pobjRtcpConfigInfo != RTP_NULL)
{
if (m_pobjRtcpCfgInfo != RTP_NULL)
delete m_pobjRtcpCfgInfo;
m_pobjRtcpCfgInfo = pobjRtcpConfigInfo;
}
// m_usExtHdrLen = usExtHdrLen;
// generate sequence number
m_usSeqNum = (RtpDt_UInt16)RtpOsUtil::Rand();
m_curRtpTimestamp = (RtpDt_UInt16)RtpOsUtil::Rand();
RtpOsUtil::GetNtpTime(m_stCurNtpTimestamp);
return RTP_SUCCESS;
} // initSession
eRTP_STATUS_CODE RtpSession::setPayload(
IN RtpPayloadInfo* pstPayloadInfo, IN RtpDt_UInt16 usExtHdrLen)
{
// set RTP payload information
if (pstPayloadInfo != RTP_NULL)
{
if (m_pobjPayloadInfo == RTP_NULL)
{
RTP_TRACE_ERROR("setPayload, m_pobjPayloadInfo is NULL.", RTP_ZERO, RTP_ZERO);
return RTP_INVALID_PARAMS;
}
m_pobjPayloadInfo->setRtpPayloadInfo(pstPayloadInfo);
}
else
{
RTP_TRACE_ERROR("setPayload, pstPayloadInfo is NULL.", RTP_ZERO, RTP_ZERO);
return RTP_INVALID_PARAMS;
}
m_usExtHdrLen = usExtHdrLen;
return RTP_SUCCESS;
} // setpayload
eRTP_STATUS_CODE RtpSession::updatePayload(IN RtpPayloadInfo* pstPayloadInfo)
{
m_pobjPayloadInfo->setRtpPayloadInfo(pstPayloadInfo);
return RTP_SUCCESS;
} // updatePayload
eRTP_STATUS_CODE RtpSession::setRTCPTimerValue(IN RtpDt_UInt16 usRTCPTimerVal)
{
m_usRTCPTimerVal = usRTCPTimerVal;
return RTP_SUCCESS;
}
eRTP_STATUS_CODE RtpSession::deleteRtpSession()
{
RtpDt_Void* pvData = RTP_NULL;
std::lock_guard<std::mutex> guard(m_objRtpSessionLock);
RtpSessionManager* pobjActSesDb = RtpSessionManager::getInstance();
pobjActSesDb->removeRtpSession(this);
if (m_pTimerId != RTP_NULL)
{
m_pobjAppInterface->RtpStopTimer(m_pTimerId, &pvData);
m_pTimerId = RTP_NULL;
}
for (auto& pobjRcvrElm : *m_pobjRtpRcvrInfoList)
{
m_pobjAppInterface->deleteRcvrInfo(
pobjRcvrElm->getSsrc(), pobjRcvrElm->getIpAddr(), pobjRcvrElm->getPort());
}
return RTP_SUCCESS;
} // deleteRtpSession
eRTP_STATUS_CODE RtpSession::collisionSendRtcpByePkt(IN RtpDt_UInt32 uiReceivedSsrc)
{
(RtpDt_Void) uiReceivedSsrc;
m_bSelfCollisionByeSent = eRTP_TRUE;
return RTP_SUCCESS;
} // collisionSendRtcpByePkt
eRTP_STATUS_CODE RtpSession::chkRcvdSsrcStatus(
IN RtpBuffer* pobjRtpAddr, IN RtpDt_UInt16 usPort, IN RtpDt_UInt32 uiRcvdSsrc)
{
eRTP_STATUS_CODE eResult = RTP_SUCCESS;
checkSsrcCollisionOnRcv(pobjRtpAddr, usPort, uiRcvdSsrc, eResult);
return eResult;
} // chkRcvdSsrcStatus
RtpReceiverInfo* RtpSession::checkSsrcCollisionOnRcv(IN RtpBuffer* pobjRtpAddr,
IN RtpDt_UInt16 usPort, IN RtpDt_UInt32 uiRcvdSsrc, OUT eRTP_STATUS_CODE& eResult)
{
if (m_pobjRtpRcvrInfoList == RTP_NULL)
{
eResult = RTP_INVALID_PARAMS;
return RTP_NULL;
}
for (auto& pobjRcvInfo : *m_pobjRtpRcvrInfoList)
{
RtpDt_UInt32 uiTmpSsrc = RTP_ZERO;
if (pobjRcvInfo == RTP_NULL)
break;
uiTmpSsrc = pobjRcvInfo->getSsrc();
if (uiTmpSsrc == uiRcvdSsrc)
{
RtpBuffer* pobjTmpDestAddr = pobjRcvInfo->getIpAddr();
RtpDt_UChar* pcDestAddr = pobjTmpDestAddr->getBuffer();
RtpDt_UChar* pcRcvDestAddr = pobjRtpAddr->getBuffer();
RtpDt_UInt16 usTmpPort = pobjRcvInfo->getPort();
RtpDt_UInt32 uiRcvDestAddrLen = pobjRtpAddr->getLength();
if (pobjRcvInfo->getCsrcFlag() == eRTP_TRUE)
{
eResult = RTP_RCVD_CSRC_ENTRY;
return pobjRcvInfo;
}
if (usTmpPort != usPort)
{
RTP_TRACE_WARNING("checkSsrcCollisionOnRcv - Port prevPort[%d], receivedPort[%d]",
usTmpPort, usPort);
eResult = RTP_REMOTE_SSRC_COLLISION;
return pobjRcvInfo;
}
if (pcDestAddr == RTP_NULL || pcRcvDestAddr == RTP_NULL)
{
eResult = RTP_INVALID_PARAMS;
return RTP_NULL;
}
if (memcmp(pcDestAddr, pcRcvDestAddr, uiRcvDestAddrLen) != RTP_ZERO)
{
eResult = RTP_REMOTE_SSRC_COLLISION;
return pobjRcvInfo;
}
eResult = RTP_OLD_SSRC_RCVD;
return pobjRcvInfo;
}
}
eResult = RTP_NEW_SSRC_RCVD;
return RTP_NULL;
} // checkSsrcCollisionOnRcv
eRtp_Bool RtpSession::findEntryInCsrcList(
IN std::list<RtpDt_UInt32>& pobjCsrcList, IN RtpDt_UInt32 uiSsrc)
{
if (pobjCsrcList.empty())
{
return eRTP_FALSE;
}
auto result = std::find(pobjCsrcList.begin(), pobjCsrcList.end(), uiSsrc);
return (result != pobjCsrcList.end()) ? eRTP_TRUE : eRTP_FALSE;
} // findEntryInCsrcList
eRtp_Bool RtpSession::findEntryInRcvrList(IN RtpDt_UInt32 uiSsrc)
{
for (auto& pobjRcvInfo : *m_pobjRtpRcvrInfoList)
{
if (pobjRcvInfo != RTP_NULL && pobjRcvInfo->getSsrc() == uiSsrc)
{
return eRTP_TRUE;
}
}
return eRTP_FALSE;
} // findEntryInRcvrList
eRTP_STATUS_CODE RtpSession::processCsrcList(
IN RtpHeader* pobjRtpHeader, IN RtpDt_UChar ucCsrcCount)
{
eRtp_Bool bRcvrStatus = eRTP_FALSE;
RtpDt_UInt16 usPos = RTP_ZERO;
std::list<RtpDt_UInt32>& pobjCsrcList = pobjRtpHeader->getCsrcList();
for (std::list<RtpDt_UInt32>::iterator listIterator = pobjCsrcList.begin();
(usPos < ucCsrcCount && listIterator != pobjCsrcList.end()); usPos = usPos + RTP_ONE)
{
RtpDt_UInt32 csrc = (*listIterator);
bRcvrStatus = findEntryInRcvrList(csrc);
if (bRcvrStatus == eRTP_FALSE)
{
RtpReceiverInfo* pobjRcvInfo = RTP_NULL;
pobjRcvInfo = new RtpReceiverInfo();
if (pobjRcvInfo == RTP_NULL)
{
RTP_TRACE_ERROR("[Memory Error] new returned NULL.", RTP_ZERO, RTP_ZERO);
return RTP_MEMORY_FAIL;
}
// fill pobjRcvInfo
// ssrc
pobjRcvInfo->setSsrc(csrc);
// m_bSender
pobjRcvInfo->setSenderFlag(eRTP_FALSE);
pobjRcvInfo->setCsrcFlag(eRTP_TRUE);
// add entry into receiver list.
m_pobjRtpRcvrInfoList->push_back(pobjRcvInfo);
RTP_TRACE_MESSAGE("processCsrcList - added ssrc[%x] from port[%d] to receiver list",
pobjRcvInfo->getSsrc(), pobjRcvInfo->getPort());
}
++listIterator;
}
return RTP_SUCCESS;
} // processCsrcList
eRTP_STATUS_CODE RtpSession::processRcvdRtpPkt(IN RtpBuffer* pobjRtpAddr, IN RtpDt_UInt16 usPort,
IN RtpBuffer* pobjRTPPacket, OUT RtpPacket* pobjRtpPkt)
{
std::lock_guard<std::mutex> guard(m_objRtpSessionLock);
// validation
if ((pobjRTPPacket == RTP_NULL) || (pobjRtpPkt == RTP_NULL) || (pobjRtpAddr == RTP_NULL))
{
RTP_TRACE_WARNING(
"processRcvdRtpPkt, pobjRTPPacket || pobjRtpPkt is NULL.", RTP_ZERO, RTP_ZERO);
return RTP_INVALID_PARAMS;
}
RtpDt_UInt32 uiRcvdOcts = pobjRTPPacket->getLength();
// decode the packet
eRtp_Bool eRtpDecodeRes = eRTP_FAILURE;
eRtpDecodeRes = pobjRtpPkt->decodePacket(pobjRTPPacket);
if (eRtpDecodeRes == eRTP_FAILURE)
{
RTP_TRACE_WARNING("processRcvdRtpPkt -RTP_DECODE_ERROR", RTP_ZERO, RTP_ZERO);
return RTP_DECODE_ERROR;
}
RtpHeader* pobjRtpHeader = pobjRtpPkt->getRtpHeader();
// check received payload type is matching with expected RTP payload types.
if (!checkRtpPayloadType(pobjRtpHeader, m_pobjPayloadInfo))
{
RTP_TRACE_WARNING(
"processRcvdRtpPkt -eRcvdResult == RTP_INVALID_PARAMS.invalid payload type)",
RTP_ZERO, RTP_ZERO);
return RTP_INVALID_PARAMS;
}
// check received ssrc is matching with the current RTP session.
RtpDt_UInt32 uiReceivedSsrc = pobjRtpHeader->getRtpSsrc();
RtpDt_UChar ucCsrcCount = pobjRtpHeader->getCsrcCount();
eRtp_Bool bCsrcStatus = eRTP_FALSE;
if (ucCsrcCount > RTP_ZERO)
{
std::list<RtpDt_UInt32>& pobjCsrcList = pobjRtpHeader->getCsrcList();
bCsrcStatus = findEntryInCsrcList(pobjCsrcList, m_uiSsrc);
}
if ((uiReceivedSsrc == m_uiSsrc) || (bCsrcStatus == eRTP_TRUE))
{
RtpStackProfile* pobjRtpProfile = m_pobjRtpStack->getStackProfile();
RtpDt_UInt32 uiTermNum = pobjRtpProfile->getTermNumber();
eRTP_STATUS_CODE eByeRes = RTP_SUCCESS;
// collision happened.
if ((m_bEnableRTCP == eRTP_TRUE) && (m_bEnableRTCPBye == eRTP_TRUE) &&
(m_bRtpSendPkt == eRTP_TRUE))
{
eByeRes = collisionSendRtcpByePkt(uiReceivedSsrc);
if (eByeRes != RTP_SUCCESS)
{
RTP_TRACE_WARNING("processRcvdRtpPkt -eByeRes", RTP_ZERO, RTP_ZERO);
return eByeRes;
}
}
else
{
// generate SSRC
RtpDt_UInt32 uiNewSsrc = RTP_ZERO;
uiNewSsrc = RtpStackUtil::generateNewSsrc(uiTermNum);
m_uiSsrc = uiNewSsrc;
}
RTP_TRACE_WARNING("processRcvdRtpPkt RTP_OWN_SSRC_COLLISION)", RTP_ZERO, RTP_ZERO);
return RTP_OWN_SSRC_COLLISION;
}
// check SSRC collision on m_objRtpRcvrInfoList
eRTP_STATUS_CODE eRcvdResult = RTP_FAILURE;
RtpReceiverInfo* pobjRcvInfo =
checkSsrcCollisionOnRcv(pobjRtpAddr, usPort, uiReceivedSsrc, eRcvdResult);
if (eRcvdResult == RTP_REMOTE_SSRC_COLLISION)
{
RTP_TRACE_WARNING(
"processRcvdRtpPkt -eRcvdResult == RTP_REMOTE_SSRC_COLLISION)", RTP_ZERO, RTP_ZERO);
return eRcvdResult;
}
if (eRcvdResult != RTP_NEW_SSRC_RCVD && pobjRcvInfo == RTP_NULL)
{
RTP_TRACE_WARNING(
"processRcvdRtpPkt -eRcvdResult == RTP_INVALID_PARAMS. pobjRcvInfo is NULL)",
RTP_ZERO, RTP_ZERO);
return RTP_INVALID_PARAMS;
}
if (eRcvdResult == RTP_NEW_SSRC_RCVD)
{
// add entry into the list.
pobjRcvInfo = new RtpReceiverInfo();
if (pobjRcvInfo == RTP_NULL)
{
RTP_TRACE_ERROR("[Memory Error] new returned NULL.", RTP_ZERO, RTP_ZERO);
return RTP_MEMORY_FAIL;
}
// initialize the rcvr info
pobjRcvInfo->initSeq(pobjRtpHeader->getSequenceNumber());
// populate pobjRcvInfo object
// ip address
pobjRcvInfo->setIpAddr(pobjRtpAddr);
// port
pobjRcvInfo->setPort(usPort);
// ssrc
pobjRcvInfo->setSsrc(uiReceivedSsrc);
// m_bSender
pobjRcvInfo->setSenderFlag(eRTP_TRUE);
pobjRcvInfo->setprevRtpTimestamp(m_curRtpTimestamp);
pobjRcvInfo->setprevNtpTimestamp(&m_stCurNtpTimestamp);
m_pobjRtpRcvrInfoList->push_back(pobjRcvInfo);
RTP_TRACE_MESSAGE("processRcvdRtpPkt - added ssrc[%x] from port[%d] to receiver list",
pobjRcvInfo->getSsrc(), pobjRcvInfo->getPort());
// first RTP packet received
m_bFirstRtpRecvd = eRTP_TRUE;
} // RTP_NEW_SSRC_RCVD
else if (m_bFirstRtpRecvd == eRTP_FALSE)
{
// initialize the receiver info
pobjRcvInfo->initSeq(pobjRtpHeader->getSequenceNumber());
// m_bSender
pobjRcvInfo->setSenderFlag(eRTP_TRUE);
// first RTP packet received
m_bFirstRtpRecvd = eRTP_TRUE;
}
if (eRcvdResult == RTP_RCVD_CSRC_ENTRY)
{
pobjRcvInfo->initSeq(pobjRtpHeader->getSequenceNumber());
// ip address
pobjRcvInfo->setIpAddr(pobjRtpAddr);
// port
pobjRcvInfo->setPort(usPort);
// m_bSender
pobjRcvInfo->setSenderFlag(eRTP_TRUE);
} // RTP_RCVD_CSRC_ENTRY
// process CSRC list
processCsrcList(pobjRtpHeader, ucCsrcCount);
if (pobjRcvInfo == RTP_NULL)
return RTP_SUCCESS;
// calculate interarrival jitter
pobjRcvInfo->calcJitter(pobjRtpHeader->getRtpTimestamp(), m_pobjPayloadInfo->getSamplingRate());
// update ROC
RtpDt_UInt16 usTempSeqNum = pobjRtpHeader->getSequenceNumber();
RtpDt_UInt32 uiUpdateSeqRes = pobjRcvInfo->updateSeq(usTempSeqNum);
// update statistics
// m_uiTotalRcvdRtpPkts
pobjRcvInfo->incrTotalRcvdRtpPkts();
// m_uiTotalRcvdRtpOcts
pobjRcvInfo->incrTotalRcvdRtpOcts(uiRcvdOcts);
// m_bSender
pobjRcvInfo->setSenderFlag(eRTP_TRUE);
if (uiUpdateSeqRes == RTP_ZERO)
{
RTP_TRACE_WARNING(
"processRcvdRtpPkt -uiUpdateSeqRes == RTP_ZERO - RTP_BAD_SEQ)", RTP_ZERO, RTP_ZERO);
return RTP_BAD_SEQ;
}
return RTP_SUCCESS;
} // processRcvdRtpPkt
eRTP_STATUS_CODE RtpSession::populateRtpHeader(
IN_OUT RtpHeader* pobjRtpHdr, IN eRtp_Bool eSetMarker, IN RtpDt_UChar ucPayloadType)
{
// version
pobjRtpHdr->setVersion((RtpDt_UChar)RTP_VERSION_NUM);
// marker
if (eSetMarker == eRTP_TRUE)
{
pobjRtpHdr->setMarker();
}
// payload type
pobjRtpHdr->setPayloadType((RtpDt_UChar)ucPayloadType);
// sequence number
if (m_uiRtpSendPktCount == RTP_ZERO)
{
pobjRtpHdr->setSequenceNumber(m_usSeqNum);
}
else
{
m_usSeqNum++;
pobjRtpHdr->setSequenceNumber(m_usSeqNum);
}
// Synchronization source
pobjRtpHdr->setRtpSsrc(m_uiSsrc);
return RTP_SUCCESS;
} // populateRtpHeader
eRTP_STATUS_CODE RtpSession::createRtpPacket(IN RtpBuffer* pobjPayload, IN eRtp_Bool eSetMarker,
IN RtpDt_UChar ucPayloadType, IN eRtp_Bool bUseLastTimestamp,
IN RtpDt_UInt32 uiRtpTimestampDiff, IN RtpBuffer* pobjXHdr, OUT RtpBuffer* pRtpPkt)
{
RtpPacket objRtpPacket;
RtpHeader* pobjRtpHdr = objRtpPacket.getRtpHeader();
// populate Rtp header information.
populateRtpHeader(pobjRtpHdr, eSetMarker, ucPayloadType);
if (pobjXHdr && pobjXHdr->getLength() > RTP_ZERO)
pobjRtpHdr->setExtension(RTP_ONE);
else
pobjRtpHdr->setExtension(RTP_ZERO);
// set timestamp
m_stPrevNtpTimestamp = m_stCurNtpTimestamp;
m_prevRtpTimestamp = m_curRtpTimestamp;
RtpDt_UInt32 uiSamplingRate = RTP_ZERO;
if (!bUseLastTimestamp)
{
m_stPrevNtpTimestamp = m_stCurNtpTimestamp;
m_prevRtpTimestamp = m_curRtpTimestamp;
RtpOsUtil::GetNtpTime(m_stCurNtpTimestamp);
if (m_uiRtpSendPktCount == RTP_ZERO)
{
m_stPrevNtpTimestamp = m_stCurNtpTimestamp;
}
if (uiRtpTimestampDiff)
{
m_curRtpTimestamp += uiRtpTimestampDiff;
}
else
{
uiSamplingRate = m_pobjPayloadInfo->getSamplingRate();
m_curRtpTimestamp = RtpStackUtil::calcRtpTimestamp(m_prevRtpTimestamp,
&m_stCurNtpTimestamp, &m_stPrevNtpTimestamp, uiSamplingRate);
}
}
pobjRtpHdr->setRtpTimestamp(m_curRtpTimestamp);
// set pobjPayload to RtpPacket
objRtpPacket.setRtpPayload(pobjPayload);
// construct RTP packet
RtpDt_UInt32 uiRtpLength = pobjPayload->getLength();
#ifdef ENABLE_PADDING
RtpDt_UInt32 uiPadLength = uiRtpLength % RTP_FOUR;
if (uiPadLength > RTP_ZERO)
{
uiPadLength = RTP_FOUR - uiPadLength;
uiRtpLength += uiPadLength;
// set padding bit to header
pobjRtpHdr->setPadding();
}
#endif
uiRtpLength += RTP_FIXED_HDR_LEN;
uiRtpLength += (RTP_FOUR * pobjRtpHdr->getCsrcCount());
if (pobjXHdr)
uiRtpLength += pobjXHdr->getLength();
RtpDt_UChar* pucRtpBuffer = new RtpDt_UChar[uiRtpLength];
if (pucRtpBuffer == RTP_NULL)
{
RTP_TRACE_WARNING("createRtpPacket, error in allocating memory ", RTP_ZERO, RTP_ZERO);
// set rtp payload as NULL in RtpPacket
objRtpPacket.setRtpPayload(RTP_NULL);
return RTP_MEMORY_FAIL;
}
memset(pucRtpBuffer, RTP_ZERO, uiRtpLength);
pRtpPkt->setBufferInfo(uiRtpLength, pucRtpBuffer);
if ((pobjXHdr && pobjXHdr->getLength() > RTP_ZERO))
{
objRtpPacket.setExtHeader(pobjXHdr);
}
else
{
delete pobjXHdr;
}
// encode the Rtp packet.
eRtp_Bool bPackRes = eRTP_TRUE;
bPackRes = objRtpPacket.formPacket(pRtpPkt);
// set pobjPayload to NULL in both success and failure case
objRtpPacket.setRtpPayload(RTP_NULL);
if (bPackRes != eRTP_TRUE)
{
RTP_TRACE_WARNING(
"createRtpPacket - formPacket failed!! bPackRes != eRTP_TRUE", RTP_ZERO, RTP_ZERO);
return RTP_ENCODE_ERROR;
}
// update statistics
m_uiRtpSendPktCount++;
m_uiRtpSendOctCount += pobjPayload->getLength();
// set we_sent flag as true
m_objTimerInfo.setWeSent(RTP_TWO);
// set m_bRtpSendPkt to true
m_bRtpSendPkt = eRTP_TRUE;
return RTP_SUCCESS;
} // createRtpPacket
RtpReceiverInfo* RtpSession::processRtcpPkt(
IN RtpDt_UInt32 uiRcvdSsrc, IN RtpBuffer* pobjRtcpAddr, IN RtpDt_UInt16 usPort)
{
eRTP_STATUS_CODE eRcvdResult = RTP_SUCCESS;
// check SSRC collision on m_objRtpRcvrInfoList
RtpReceiverInfo* pobjRcvInfo =
checkSsrcCollisionOnRcv(pobjRtcpAddr, usPort, uiRcvdSsrc, eRcvdResult);
if (eRcvdResult == RTP_NEW_SSRC_RCVD)
{
// add entry into the list.
pobjRcvInfo = new RtpReceiverInfo();
if (pobjRcvInfo == RTP_NULL)
{
return RTP_NULL;
}
// populate pobjRcvInfo object
// ip address
pobjRcvInfo->setIpAddr(pobjRtcpAddr);
// port
pobjRcvInfo->setPort(usPort);
// ssrc
pobjRcvInfo->setSsrc(uiRcvdSsrc);
m_pobjRtpRcvrInfoList->push_back(pobjRcvInfo);
RTP_TRACE_MESSAGE("processRtcpPkt - added ssrc[%x] from port[%d] to receiver list",
pobjRcvInfo->getSsrc(), pobjRcvInfo->getPort());
}
else if (eRcvdResult != RTP_INVALID_PARAMS)
{
// m_bSender should be FALSE for RTCP
/* if(pobjRcvInfo != NULL)
{
pobjRcvInfo->setSenderFlag(eRTP_FALSE);
}
*/
}
return pobjRcvInfo;
} // processRtcpPkt
RtpDt_Void RtpSession::delEntryFromRcvrList(IN RtpDt_UInt32* puiSsrc)
{
for (auto it = m_pobjRtpRcvrInfoList->begin(); it != m_pobjRtpRcvrInfoList->end();)
{
if ((*it)->getSsrc() == *puiSsrc)
{
it = m_pobjRtpRcvrInfoList->erase(it);
break;
}
else
{
++it;
}
}
} // delEntryFromRcvrList
eRTP_STATUS_CODE RtpSession::processByePacket(
IN RtcpByePacket* pobjByePkt, IN RtpBuffer* pobjRtcpAddr, IN RtpDt_UInt16 usPort)
{
(RtpDt_Void) pobjRtcpAddr, (RtpDt_Void)usPort;
RtcpHeader* pobjHdrInfo = pobjByePkt->getRtcpHdrInfo();
RtpDt_UInt16 usNumSsrc = pobjHdrInfo->getReceptionReportCount();
std::list<RtpDt_UInt32*>& pobjSsrcList = pobjByePkt->getSsrcList();
RtpDt_UInt16 usPos = RTP_ZERO;
// delete entry from receiver list
for (std::list<RtpDt_UInt32*>::iterator listIterator = pobjSsrcList.begin();
(usPos < usNumSsrc && listIterator != pobjSsrcList.end()); usPos = usPos + RTP_ONE)
{
if (usPos == RTP_ZERO)
{
RtpDt_UInt32 uiSsrc = pobjHdrInfo->getSsrc();
delEntryFromRcvrList(&uiSsrc);
}
else
{
RtpDt_UInt32* puiSsrc = RTP_NULL;
// get element from list
puiSsrc = (*listIterator);
if (puiSsrc != RTP_NULL)
{
delEntryFromRcvrList(puiSsrc);
}
++listIterator;
}
} // for
// get size of the pobjSsrcList
eRtp_Bool bByeResult = eRTP_FALSE;
RtpDt_UInt16 usRcvrNum = m_pobjRtpRcvrInfoList->size();
bByeResult = m_objTimerInfo.updateByePktInfo(usRcvrNum);
if ((bByeResult == eRTP_TRUE) && (m_bEnableRTCP == eRTP_TRUE) &&
(m_pobjAppInterface != RTP_NULL))
{
// Reschedule the next report for time tn
RtpDt_UInt32 uiTempTn = m_objTimerInfo.getTn();
RtpDt_UInt32 uiTempTc = m_objTimerInfo.getTc();
RTP_TRACE_MESSAGE(
"processByePacket before processing[Tn : %u] [Tc : %u]", uiTempTn, uiTempTc);
RtpDt_UInt16 usMembers = m_pobjRtpRcvrInfoList->size();
uiTempTc = m_objTimerInfo.getTc();
RtpDt_Double dTempT = rtcp_interval(usMembers);
// convert uiTempT to milliseconds
RtpDt_UInt32 uiTimerVal = RTP_ZERO;
dTempT = dTempT * RTP_SEC_TO_MILLISEC;
RtpDt_UInt32 uiRoundDiff = (RtpDt_UInt32)dTempT;
uiRoundDiff = ((uiRoundDiff / 100) * 100);
if (uiTempTn > uiTempTc)
{
uiTimerVal = uiTempTn - uiTempTc;
if (uiTimerVal > uiRoundDiff)
{
uiTimerVal = uiRoundDiff;
}
}
else
{
uiTimerVal = uiRoundDiff;
}
RTP_TRACE_MESSAGE("processByePacket [uiTimerVal : %u]", uiTimerVal, RTP_ZERO);
RtpDt_Void* pvData = RTP_NULL;
eRtp_Bool bTSres = eRTP_FALSE;
if (m_pTimerId != RTP_NULL)
{
bTSres = m_pobjAppInterface->RtpStopTimer(m_pTimerId, &pvData);
m_pTimerId = RTP_NULL;
if (bTSres == eRTP_FALSE)
{
return RTP_TIMER_PROC_ERR;
}
}
RtpDt_Void* pvSTRes =
m_pobjAppInterface->RtpStartTimer(uiTimerVal, eRTP_FALSE, m_pfnTimerCb, this);
if (pvSTRes == RTP_NULL)
{
return RTP_TIMER_PROC_ERR;
}
m_pTimerId = pvSTRes;
}
return RTP_SUCCESS;
} // processByePacket
eRTP_STATUS_CODE RtpSession::processSdesPacket(IN RtcpSdesPacket* pobjSdesPkt)
{
(RtpDt_Void) pobjSdesPkt;
return RTP_SUCCESS;
}
eRTP_STATUS_CODE RtpSession::processRcvdRtcpPkt(IN RtpBuffer* pobjRtcpAddr, IN RtpDt_UInt16 usPort,
IN RtpBuffer* pobjRTCPBuf, OUT RtcpPacket* pobjRtcpPkt)
{
if (m_bEnableRTCP != eRTP_TRUE)
{
RTP_TRACE_WARNING("[ProcessRcvdRtcpPkt], RTCP is not enabled", RTP_ZERO, RTP_ZERO);
return RTP_NO_RTCP_SUPPORT;
}
// validity checking
if (pobjRtcpAddr == RTP_NULL || pobjRTCPBuf == RTP_NULL || pobjRtcpPkt == RTP_NULL)
{
RTP_TRACE_ERROR("[ProcessRcvdRtcpPkt] Invalid params. pobjRtcpAddr[%x] pobjRTCPBuf[%x]",
pobjRtcpAddr, pobjRTCPBuf);
return RTP_INVALID_PARAMS;
}
RtpDt_UInt16 usExtHdrLen = RTP_ZERO;
eRTP_STATUS_CODE eDecodeStatus = RTP_FAILURE;
tRTP_NTP_TIME stNtpTs = {RTP_ZERO, RTP_ZERO};
RtpOsUtil::GetNtpTime(stNtpTs);
RtpDt_UInt32 currentTime = RtpStackUtil::getMidFourOctets(&stNtpTs);
// decode compound packet
eDecodeStatus = pobjRtcpPkt->decodeRtcpPacket(pobjRTCPBuf, usExtHdrLen, m_pobjRtcpCfgInfo);
if (eDecodeStatus != RTP_SUCCESS)
{
RTP_TRACE_ERROR(
"[ProcessRcvdRtcpPkt], Error Decoding compound RTCP packet!", RTP_ZERO, RTP_ZERO);
return eDecodeStatus;
}
// update average rtcp size
RtpDt_UInt32 uiRcvdPktSize = pobjRTCPBuf->getLength();
m_objTimerInfo.updateAvgRtcpSize(uiRcvdPktSize);
std::list<RtcpSrPacket*>& pobjSrList = pobjRtcpPkt->getSrPacketList();
if (pobjSrList.size() > RTP_ZERO)
{
// get key material element from list.
RtcpSrPacket* pobjSrPkt = pobjSrList.front();
RtcpRrPacket* pobjRRPkt = pobjSrPkt->getRrPktInfo();
RtcpHeader* pobjRtcpHdr = pobjRRPkt->getRtcpHdrInfo();
RtpDt_UInt32 uiRcvdSsrc = pobjRtcpHdr->getSsrc();
// calculate RTTD
std::list<RtcpReportBlock*>& pobjReportBlkList = pobjRRPkt->getReportBlockList();
if (pobjReportBlkList.size() > RTP_ZERO)
{
RtcpReportBlock* pobjReportBlk = pobjReportBlkList.front();
if (pobjReportBlk != RTP_NULL)
{
calculateAndSetRTTD(
currentTime, pobjReportBlk->getLastSR(), pobjReportBlk->getDelayLastSR());
}
}
// decrement rtcp port by one
usPort = usPort - RTP_ONE;
RtpReceiverInfo* pobjRcvInfo = processRtcpPkt(uiRcvdSsrc, pobjRtcpAddr, usPort);
if (pobjRcvInfo != RTP_NULL)
{
stNtpTs = {RTP_ZERO, RTP_ZERO};
pobjRcvInfo->setpreSrTimestamp(pobjSrPkt->getNtpTime());
RtpOsUtil::GetNtpTime(stNtpTs);
pobjRcvInfo->setLastSrNtpTimestamp(&stNtpTs);
}
} // RTCP SR
// RTCP RR packet
std::list<RtcpRrPacket*>& pobjRrList = pobjRtcpPkt->getRrPacketList();
if (pobjRrList.size() > RTP_ZERO)
{
// get key material element from list.
RtcpRrPacket* pobjRrPkt = pobjRrList.front();
// calculate RTTD
std::list<RtcpReportBlock*>& pobjReportBlkList = pobjRrPkt->getReportBlockList();
if (pobjReportBlkList.size() > RTP_ZERO)
{
RtcpReportBlock* pobjReportBlk = pobjReportBlkList.front();
if (pobjReportBlk != RTP_NULL)
{
calculateAndSetRTTD(
currentTime, pobjReportBlk->getLastSR(), pobjReportBlk->getDelayLastSR());
}
}
RtcpHeader* pobjRtcpHdr = pobjRrPkt->getRtcpHdrInfo();
RtpDt_UInt32 uiRcvdSsrc = pobjRtcpHdr->getSsrc();
// decrement rtcp port by one
usPort = usPort - RTP_ONE;
processRtcpPkt(uiRcvdSsrc, pobjRtcpAddr, usPort);
} // RTCP RR
// RTCP SDES packet
RtcpSdesPacket* pobjSdesPkt = pobjRtcpPkt->getSdesPacket();
if (pobjSdesPkt != RTP_NULL)
{
// sdes
processSdesPacket(pobjSdesPkt);
}
// RTCP BYE packet
RtcpByePacket* pobjByePkt = pobjRtcpPkt->getByePacket();
if (pobjByePkt != RTP_NULL)
{
// bye
processByePacket(pobjByePkt, pobjRtcpAddr, usPort);
}
return RTP_SUCCESS;
} // processRcvdRtcpPkt
eRtp_Bool RtpSession::sendRtcpByePacket()
{
RtcpPacket objRtcpPkt;
std::lock_guard<std::mutex> guard(m_objRtpSessionLock);
if (m_bEnableRTCP == eRTP_TRUE && m_bEnableRTCPBye == eRTP_TRUE)
{
m_bSndRtcpByePkt = eRTP_TRUE;
// set timestamp
rtpSetTimestamp();
if (rtpMakeCompoundRtcpPacket(&objRtcpPkt) != RTP_SUCCESS)
{
return eRTP_FALSE;
}
if (rtpSendRtcpPacket(&objRtcpPkt) == RTP_SUCCESS)
{
if (m_bSelfCollisionByeSent == eRTP_TRUE)
{
// generate SSRC
RtpStackProfile* pobjRtpProfile = m_pobjRtpStack->getStackProfile();
RtpDt_UInt32 uiTermNum = pobjRtpProfile->getTermNumber();
RtpDt_UInt32 uiNewSsrc = RTP_ZERO;
uiNewSsrc = RtpStackUtil::generateNewSsrc(uiTermNum);
m_uiSsrc = uiNewSsrc;
RTP_TRACE_WARNING(
"sendRtcpByePacket::SSRC after collision: %x", m_uiSsrc, RTP_ZERO);
}
return eRTP_TRUE;
}
}
return eRTP_FALSE;
}
eRtp_Bool RtpSession::sendRtcpRtpFbPacket(IN RtpDt_UInt32 uiFbType, IN RtpDt_Char* pcbuff,
IN RtpDt_UInt32 uiLen, IN RtpDt_UInt32 uiMediaSsrc)
{
RtcpPacket objRtcpPkt;
std::lock_guard<std::mutex> guard(m_objRtpSessionLock);
// set timestamp
rtpSetTimestamp();
if (rtpMakeCompoundRtcpPacket(&objRtcpPkt) != RTP_SUCCESS)
{
return eRTP_FALSE;
}
populateRtcpFbPacket(&objRtcpPkt, uiFbType, pcbuff, uiLen, uiMediaSsrc, RTCP_RTPFB);
if (rtpSendRtcpPacket(&objRtcpPkt) == RTP_SUCCESS)
{
return eRTP_TRUE;
}
return eRTP_FALSE;
}
eRtp_Bool RtpSession::sendRtcpPayloadFbPacket(IN RtpDt_UInt32 uiFbType, IN RtpDt_Char* pcbuff,
IN RtpDt_UInt32 uiLen, IN RtpDt_UInt32 uiMediaSsrc)
{
RtcpPacket objRtcpPkt;
std::lock_guard<std::mutex> guard(m_objRtpSessionLock);
// set timestamp
rtpSetTimestamp();
if (rtpMakeCompoundRtcpPacket(&objRtcpPkt) != RTP_SUCCESS)
{
return eRTP_FALSE;
}
populateRtcpFbPacket(&objRtcpPkt, uiFbType, pcbuff, uiLen, uiMediaSsrc, RTCP_PSFB);
if (rtpSendRtcpPacket(&objRtcpPkt) == RTP_SUCCESS)
{
return eRTP_TRUE;
}
return eRTP_FALSE;
}
RtpDt_Double RtpSession::rtcp_interval(IN RtpDt_UInt16 usMembers)
{
RtpDt_Double const RTCP_MIN_TIME = 5.;
/**
* The target RTCP bandwidth, i.e., the total bandwidth
* that will be used for RTCP packets by all members of this session,
* in octets per second. This will be a specified fraction of the
* "session bandwidth" parameter supplied to the application at
* startup.
*/
RtpDt_Double ulRtcp_bw = m_objTimerInfo.getRtcpBw();
RtpDt_Double const RTCP_SENDER_BW_FRACTION = 0.25L;
RtpDt_Double const RTCP_RCVR_BW_FRACTION = (1 - RTCP_SENDER_BW_FRACTION);
RtpDt_Double const COMPENSATION = 2.71828 - 1.5;
RtpDt_Double ulRtcp_min_time = RTCP_MIN_TIME;
RtpDt_Double ulTimerVal = RTP_ZERO;
RtpDt_Double dDefTimerVal = 2.5;
if (usMembers == RTP_ZERO)
{
RTP_TRACE_MESSAGE("rtcp_interval usmebers is equal to 0", RTP_NULL, RTP_NULL);
ulTimerVal = dDefTimerVal;
return ulTimerVal;
}
/*
* Very first call at application start-up uses half the min
* delay for quicker notification while still allowing some time
* before reporting for randomization and to learn about other
* sources so the report interval will converage to the correct
* interval more quickly.
*/
if (m_objTimerInfo.isInitial())
{
ulRtcp_min_time /= RTP_TWO;
}
/*
* Dedicate a fraction of the RTCP bandwidth to senders unless
* the number of senders is large enough that their share is
* more than that fraction.
*/
RtpDt_Int32 uiNumMemComp = RTP_ZERO;
uiNumMemComp = usMembers;
RtpDt_UInt32 uiSenders = getSenderCount();
if (uiSenders <= usMembers * RTCP_SENDER_BW_FRACTION)
{
if (m_objTimerInfo.getWeSent() != RTP_ZERO)
{
ulRtcp_bw *= RTCP_SENDER_BW_FRACTION;
uiNumMemComp = uiSenders;
}
else
{
ulRtcp_bw *= RTCP_RCVR_BW_FRACTION;
uiNumMemComp -= uiSenders;
}
}
// m_objTimerInfo.setRtcpBw(ulRtcp_bw);
/*
* The effective number of sites times the average packet size is
* the total number of octets sent when each site sends a report.
* Dividing this by the effective bandwidth gives the time
* interval over which those packets must be sent in order to
* meet the bandwidth target, with a minimum enforced. In that
* time interval we send one report so this time is also our
* average time between reports.
*/
ulTimerVal = m_objTimerInfo.getAvgRtcpSize() * uiNumMemComp / ulRtcp_bw;
if (ulTimerVal < ulRtcp_min_time)
{
ulTimerVal = ulRtcp_min_time;
}
/*
* To avoid traffic bursts from unintended synchronization with
* other sites, we then pick our actual next report interval as a
* random number uniformly distributed between 0.5*t and 1.5*t.
*/
RtpDt_Double ulRRand = RTP_ZERO;
ulRRand = RtpOsUtil::RRand();
ulTimerVal = ulTimerVal * ((ulRRand) + 0.5);
ulTimerVal = ulTimerVal / COMPENSATION;
/*if(dDefTimerVal > ulTimerVal)
{
RTP_TRACE_MESSAGE("rtcp_interval dDefTimerVal > ulTimerVal [gen =%f], [def = %f]",
ulTimerVal, dDefTimerVal);
ulTimerVal = dDefTimerVal;
}*/
if (ulTimerVal < 0)
{
ulTimerVal = RTP_INIT_TRUE_T_MIN;
RTP_TRACE_MESSAGE("Generated a negative timer value. using Default", RTP_NULL, RTP_NULL);
}
return ulTimerVal;
} // rtcp_interval
RtpDt_UInt32 RtpSession::getSenderCount()
{
RtpDt_UInt32 uiSenderCnt = RTP_ZERO;
for (auto& pobjRcvrElm : *m_pobjRtpRcvrInfoList)
{
// get key material element from list.
if (pobjRcvrElm != RTP_NULL && pobjRcvrElm->isSender() == eRTP_TRUE &&
pobjRcvrElm->getTotalRcvdRtpPkts() != 0)
{
uiSenderCnt = uiSenderCnt + RTP_ONE;
}
}
return uiSenderCnt;
} // getSenderCount
RtpDt_Void RtpSession::calculateAndSetRTTD(
RtpDt_UInt32 currentTime, RtpDt_UInt32 lsr, RtpDt_UInt32 dlsr)
{
if (lsr == 0 || dlsr == 0)
{
m_lastRTTDelay = 0;
}
else
{
m_lastRTTDelay = (currentTime - lsr - dlsr);
}
RTP_TRACE_MESSAGE("calculateAndSetRTTD = %d", m_lastRTTDelay, RTP_NULL);
}
eRTP_STATUS_CODE RtpSession::populateRtcpXrPacket(IN_OUT RtcpPacket* pobjRtcpPkt)
{
// create RtcpXrPacket
RtcpXrPacket* pobjRtcpXrPacket = new RtcpXrPacket();
if (pobjRtcpXrPacket == RTP_NULL)
{
RTP_TRACE_ERROR("[Memory Error] new returned NULL.", RTP_ZERO, RTP_ZERO);
return RTP_FAILURE;
}
// set extended report block data
RtpBuffer* pobjPayload = new RtpBuffer(m_stRtcpXr.nlength, m_stRtcpXr.m_pBlockBuffer);
if (pobjPayload == RTP_NULL)
{
RTP_TRACE_ERROR("[Memory Error] new returned NULL.", RTP_ZERO, RTP_ZERO);
delete pobjRtcpXrPacket;
return RTP_FAILURE;
}
pobjRtcpXrPacket->setReportBlk(pobjPayload);
// set RTTD
pobjRtcpXrPacket->setRTTD(m_lastRTTDelay);
// set RTTD offset
pobjRtcpXrPacket->setRttdOffset(m_stRtcpXr.nRttdOffset);
// set the RTCP packet
pobjRtcpPkt->setXrPacket(pobjRtcpXrPacket);
// get and populate the RTCP header
RtcpHeader* pRtcpHdr = pobjRtcpXrPacket->getRtcpHdrInfo();
RtpDt_UInt16 usSubType = RTP_ZERO;
pRtcpHdr->populateRtcpHeader((RtpDt_UChar)usSubType, RTCP_XR, m_uiSsrc);
return RTP_SUCCESS;
}
eRTP_STATUS_CODE RtpSession::sendRtcpXrPacket(
IN RtpDt_UChar* m_pBlockBuffer, IN RtpDt_UInt16 nblockLength, IN RtpDt_UInt16 nRttdOffset)
{
// set timestamp
m_stRtcpXr.m_pBlockBuffer = new RtpDt_UChar[nblockLength];
if (m_stRtcpXr.m_pBlockBuffer == RTP_NULL)
{
RTP_TRACE_ERROR("[Memory Error] new returned NULL.", RTP_ZERO, RTP_ZERO);
return RTP_FAILURE;
}
memcpy(m_stRtcpXr.m_pBlockBuffer, m_pBlockBuffer, nblockLength);
m_stRtcpXr.nlength = nblockLength;
m_stRtcpXr.nRttdOffset = nRttdOffset;
m_bisXr = eRTP_TRUE;
return RTP_SUCCESS;
}
eRtp_Bool RtpSession::checkRtpPayloadType(
IN RtpHeader* pobjRtpHeader, IN RtpPayloadInfo* m_pobjPayloadInfo)
{
RtpDt_Int32 i = 0;
for (; i < RTP_MAX_PAYLOAD_TYPE; i++)
{
if (pobjRtpHeader->getPayloadType() == m_pobjPayloadInfo->getPayloadType(i))
break;
RTP_TRACE_MESSAGE("checkRtpPayloadType rcvd payload = %d--- set payload =%d",
pobjRtpHeader->getPayloadType(), m_pobjPayloadInfo->getPayloadType(i));
}
if (i == RTP_MAX_PAYLOAD_TYPE)
return eRTP_FALSE;
else
return eRTP_TRUE;
}
RtpDt_UInt32 RtpSession::getRTTD()
{
return m_lastRTTDelay;
}