blob: b1ec0f579b47a6be8d5e6a3d471b1b28c33a50ee [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 <RtcpPacket.h>
#include <RtpTrace.h>
#include <RtpError.h>
#include <RtpSession.h>
RtcpPacket::RtcpPacket() :
m_objSrPktList(std::list<RtcpSrPacket*>()),
m_objRrPktList(std::list<RtcpRrPacket*>()),
m_objFbPktList(std::list<RtcpFbPacket*>()),
m_pobjSdesPkt(RTP_NULL),
m_pobjByePkt(RTP_NULL),
m_pobjAppPkt(RTP_NULL),
m_pobjRtcpXrPkt(RTP_NULL)
{
} // Constructor
RtcpPacket::~RtcpPacket()
{
// delete all RtcpSrPacket objects.
for (const auto& pobjSrPkt : m_objSrPktList)
{
delete pobjSrPkt;
}
m_objSrPktList.clear();
// delete all RtcpRrPacket objects
for (const auto& pobjRrPkt : m_objRrPktList)
{
delete pobjRrPkt;
}
m_objRrPktList.clear();
// delete all RtcpFbPacket objects
for (const auto& pobjFbPkt : m_objFbPktList)
{
delete pobjFbPkt;
}
m_objFbPktList.clear();
if (m_pobjSdesPkt != RTP_NULL)
{
delete m_pobjSdesPkt;
m_pobjSdesPkt = RTP_NULL;
}
if (m_pobjByePkt != RTP_NULL)
{
delete m_pobjByePkt;
m_pobjByePkt = RTP_NULL;
}
if (m_pobjAppPkt != RTP_NULL)
{
delete m_pobjAppPkt;
m_pobjAppPkt = RTP_NULL;
}
if (m_pobjRtcpXrPkt != RTP_NULL)
{
delete m_pobjRtcpXrPkt;
m_pobjRtcpXrPkt = RTP_NULL;
}
} // Destructor
RtcpHeader RtcpPacket::getHeader()
{
return m_objHeader;
}
std::list<RtcpSrPacket*>& RtcpPacket::getSrPacketList()
{
return m_objSrPktList;
}
std::list<RtcpRrPacket*>& RtcpPacket::getRrPacketList()
{
return m_objRrPktList;
}
std::list<RtcpFbPacket*>& RtcpPacket::getFbPacketList()
{
return m_objFbPktList;
}
RtcpSdesPacket* RtcpPacket::getSdesPacket()
{
return m_pobjSdesPkt;
}
RtpDt_Void RtcpPacket::setSdesPacketData(IN RtcpSdesPacket* pobjSdesData)
{
m_pobjSdesPkt = pobjSdesData;
}
RtcpByePacket* RtcpPacket::getByePacket()
{
return m_pobjByePkt;
}
RtpDt_Void RtcpPacket::setByePacketData(IN RtcpByePacket* pobjByePktData)
{
m_pobjByePkt = pobjByePktData;
}
RtcpAppPacket* RtcpPacket::getAppPacket()
{
return m_pobjAppPkt;
}
RtpDt_Void RtcpPacket::setAppPktData(IN RtcpAppPacket* pobjAppData)
{
m_pobjAppPkt = pobjAppData;
}
eRTP_STATUS_CODE RtcpPacket::addSrPacketData(IN RtcpSrPacket* pobjSrPkt)
{
if (pobjSrPkt == RTP_NULL)
{
return RTP_FAILURE;
}
m_objSrPktList.push_back(pobjSrPkt);
return RTP_SUCCESS;
}
eRTP_STATUS_CODE RtcpPacket::addRrPacketData(IN RtcpRrPacket* pobjRrPkt)
{
if (pobjRrPkt == RTP_NULL)
{
return RTP_FAILURE;
}
m_objRrPktList.push_back(pobjRrPkt);
return RTP_SUCCESS;
}
eRTP_STATUS_CODE RtcpPacket::addFbPacketData(IN RtcpFbPacket* pobjFbPkt)
{
if (pobjFbPkt == RTP_NULL)
{
return RTP_FAILURE;
}
m_objFbPktList.push_back(pobjFbPkt);
return RTP_SUCCESS;
}
RtcpXrPacket* RtcpPacket::getXrPacket()
{
return m_pobjRtcpXrPkt;
}
RtpDt_Void RtcpPacket::setXrPacket(IN RtcpXrPacket* pobjRtcpXrData)
{
m_pobjRtcpXrPkt = pobjRtcpXrData;
}
eRTP_STATUS_CODE RtcpPacket::decodeRtcpPacket(IN RtpBuffer* pobjRtcpPktBuf,
IN RtpDt_UInt16 usExtHdrLen, IN RtcpConfigInfo* pobjRtcpCfgInfo)
{
RtpDt_UInt32 uiCurPos = RTP_ZERO;
eRtp_Bool bSrPkt = eRTP_FALSE;
eRtp_Bool bRrPkt = eRTP_FALSE;
eRtp_Bool bFbPkt = eRTP_FALSE;
eRtp_Bool bOtherPkt = eRTP_FALSE;
if (pobjRtcpPktBuf == NULL || pobjRtcpPktBuf->getBuffer() == NULL ||
pobjRtcpPktBuf->getLength() < RTP_WORD_SIZE)
return RTP_INVALID_PARAMS;
// Check RTCP with only common header case.
if (pobjRtcpPktBuf->getLength() == RTP_WORD_SIZE)
{
m_objHeader.decodeRtcpHeader(pobjRtcpPktBuf->getBuffer(), pobjRtcpPktBuf->getLength());
return RTP_SUCCESS;
}
// Get RTCP Compound packet
RtpDt_UInt32 uiCompPktLen = pobjRtcpPktBuf->getLength();
RtpDt_Int32 iTrackCompLen = uiCompPktLen;
while (iTrackCompLen >= RTCP_FIXED_HDR_LEN)
{
RtpDt_UChar* pucBuffer = pobjRtcpPktBuf->getBuffer();
pucBuffer += uiCurPos;
m_objHeader.decodeRtcpHeader(pucBuffer, iTrackCompLen);
uiCurPos += RTCP_FIXED_HDR_LEN;
pucBuffer += RTCP_FIXED_HDR_LEN;
iTrackCompLen -= RTCP_FIXED_HDR_LEN;
RtpDt_UChar uiVersion = m_objHeader.getVersion();
if (uiVersion != RTP_VERSION_NUM)
{
RTP_TRACE_ERROR("[DecodeRtcpPacket] RTCP version[%d] is Invalid.", uiVersion, RTP_ZERO);
return RTP_INVALID_MSG;
}
// get length
RtpDt_UInt16 usPktLen = m_objHeader.getLength();
usPktLen -= RTP_WORD_SIZE;
if (usPktLen > iTrackCompLen)
{
RTP_TRACE_ERROR(
"[DecodeRtcpPacket] RTCP packet length is Invalid.", usPktLen, iTrackCompLen);
return RTP_INVALID_MSG;
}
RTP_TRACE_MESSAGE("[DecodeRtcpPacket] packet length: %d, compound packet length: %d",
usPktLen, iTrackCompLen);
// get packet type
RtpDt_UInt32 uiPktType = m_objHeader.getPacketType();
RTP_TRACE_MESSAGE("[DecodeRtcpPacket] packet type: %d report count: %d", uiPktType,
m_objHeader.getReceptionReportCount());
eRTP_STATUS_CODE eDecodeRes = RTP_FAILURE;
switch (uiPktType)
{
case RTCP_SR:
{
RTP_TRACE_MESSAGE("[DecodeRtcpPacket] Decoding RTCP_SR", 0, 0);
RtcpSrPacket* pobjSrPkt = new RtcpSrPacket();
if (pobjSrPkt == RTP_NULL)
{
RTP_TRACE_ERROR("[Memory Error] new returned NULL.", RTP_ZERO, RTP_ZERO);
return RTP_MEMORY_FAIL;
}
pobjSrPkt->setRtcpHdrInfo(m_objHeader);
eDecodeRes = pobjSrPkt->decodeSrPacket(pucBuffer, usPktLen, usExtHdrLen);
addSrPacketData(pobjSrPkt);
bSrPkt = eRTP_TRUE;
break;
} // RTCP_SR
case RTCP_RR:
{
RTP_TRACE_MESSAGE("[DecodeRtcpPacket] Decoding RTCP_RR", 0, 0);
RtpDt_UInt16 uiRrPktLen = usPktLen;
RtcpRrPacket* pobjRrPkt = new RtcpRrPacket();
if (pobjRrPkt == RTP_NULL)
{
RTP_TRACE_ERROR("[Memory Error] new returned NULL.", RTP_ZERO, RTP_ZERO);
return RTP_MEMORY_FAIL;
}
pobjRrPkt->setRtcpHdrInfo(m_objHeader);
eDecodeRes = pobjRrPkt->decodeRrPacket(pucBuffer, uiRrPktLen, usExtHdrLen);
addRrPacketData(pobjRrPkt);
bRrPkt = eRTP_TRUE;
break;
} // RTCP_RR
case RTCP_SDES:
{
RTP_TRACE_MESSAGE("[DecodeRtcpPacket] Decoding RTCP_SDES", 0, 0);
m_pobjSdesPkt = new RtcpSdesPacket();
if (m_pobjSdesPkt == RTP_NULL)
{
RTP_TRACE_ERROR("[Memory Error] new returned NULL.", RTP_ZERO, RTP_ZERO);
return RTP_MEMORY_FAIL;
}
m_pobjSdesPkt->setRtcpHdrInfo(m_objHeader);
eDecodeRes = m_pobjSdesPkt->decodeSdesPacket(pucBuffer, usPktLen, pobjRtcpCfgInfo);
bOtherPkt = eRTP_TRUE;
break;
} // RTCP_SDES
case RTCP_BYE:
{
RTP_TRACE_MESSAGE("[DecodeRtcpPacket] Decoding RTCP_BYE", 0, 0);
m_pobjByePkt = new RtcpByePacket();
if (m_pobjByePkt == RTP_NULL)
{
RTP_TRACE_ERROR("[Memory Error] new returned NULL.", RTP_ZERO, RTP_ZERO);
return RTP_MEMORY_FAIL;
}
m_pobjByePkt->setRtcpHdrInfo(m_objHeader);
eDecodeRes = m_pobjByePkt->decodeByePacket(pucBuffer, usPktLen);
bOtherPkt = eRTP_TRUE;
break;
} // RTCP_BYE
case RTCP_APP:
{
RTP_TRACE_MESSAGE("[DecodeRtcpPacket] Decoding RTCP_APP", 0, 0);
m_pobjAppPkt = new RtcpAppPacket();
if (m_pobjAppPkt == RTP_NULL)
{
RTP_TRACE_ERROR("[Memory Error] new returned NULL.", RTP_ZERO, RTP_ZERO);
return RTP_MEMORY_FAIL;
}
m_pobjAppPkt->setRtcpHdrInfo(m_objHeader);
eDecodeRes = m_pobjAppPkt->decodeAppPacket(pucBuffer, usPktLen);
bOtherPkt = eRTP_TRUE;
break;
} // RTCP_APP
case RTCP_RTPFB:
case RTCP_PSFB:
{
RTP_TRACE_MESSAGE("[DecodeRtcpPacket] Decoding RTCP_RTPFB", 0, 0);
RtcpFbPacket* pobjFbPkt = new RtcpFbPacket();
if (pobjFbPkt == RTP_NULL)
{
RTP_TRACE_ERROR("[Memory Error] new returned NULL.", RTP_ZERO, RTP_ZERO);
return RTP_MEMORY_FAIL;
}
pobjFbPkt->setRtcpHdrInfo(m_objHeader);
eDecodeRes = pobjFbPkt->decodeRtcpFbPacket(pucBuffer, usPktLen);
addFbPacketData(pobjFbPkt);
bFbPkt = eRTP_TRUE;
break;
} // RTCP_RTPFB || RTCP_PSFB
default:
{
RTP_TRACE_WARNING(
"[DecodeRtcpPacket], Invalid RTCP MSG type received", RTP_ZERO, RTP_ZERO);
return RTP_INVALID_MSG;
} // default
}; // switch
if (eDecodeRes != RTP_SUCCESS)
{
RTP_TRACE_ERROR("[DecodeRtcpPacket], Decoding Error[%d]", eDecodeRes, RTP_ZERO);
return eDecodeRes;
}
iTrackCompLen -= usPktLen;
uiCurPos += usPktLen;
} // while
if ((bSrPkt == eRTP_FALSE) && (bRrPkt == eRTP_FALSE) && (bFbPkt == eRTP_FALSE) &&
(bOtherPkt == eRTP_FALSE))
{
RTP_TRACE_ERROR("[DecodeRtcpPacket], no rtcp sr,rr,fb packets", 0, 0);
return RTP_DECODE_ERROR;
}
return RTP_SUCCESS;
} // decodeRtcpPacket
eRTP_STATUS_CODE RtcpPacket::formRtcpPacket(OUT RtpBuffer* pobjRtcpPktBuf)
{
RTP_TRACE_MESSAGE("formRtcpPacket", 0, 0);
RtpDt_UInt16 usSrSize = m_objSrPktList.size();
RtpDt_UInt16 usRrSize = m_objRrPktList.size();
RtpDt_UInt16 usFbSize = m_objFbPktList.size();
pobjRtcpPktBuf->setLength(RTP_ZERO);
if ((usSrSize == RTP_ZERO) && (usRrSize == RTP_ZERO) && (m_pobjByePkt == RTP_NULL))
{
RTP_TRACE_WARNING("[formRtcpPacket] m_pobjSrPkt is NULL", RTP_ZERO, RTP_ZERO);
return RTP_FAILURE;
}
if ((m_pobjByePkt == RTP_NULL) && (m_pobjSdesPkt == RTP_NULL) && (m_pobjAppPkt == RTP_NULL) &&
(usFbSize == RTP_ZERO))
{
RTP_TRACE_WARNING("[formRtcpPacket] Not present 2nd pkt in Comp pkt", RTP_ZERO, RTP_ZERO);
return RTP_FAILURE;
}
eRTP_STATUS_CODE eEncodeRes = RTP_FAILURE;
for (auto& pobjSrPkt : m_objSrPktList)
{
// get key material element from list.
eEncodeRes = pobjSrPkt->formSrPacket(pobjRtcpPktBuf);
if (eEncodeRes != RTP_SUCCESS)
{
RTP_TRACE_WARNING("[formRtcpPacket] Error in SR pkt encoding", RTP_ZERO, RTP_ZERO);
return eEncodeRes;
}
}
for (auto& pobjRrPkt : m_objRrPktList)
{
// get key material element from list.
eEncodeRes = pobjRrPkt->formRrPacket(pobjRtcpPktBuf, eRTP_TRUE);
if (eEncodeRes != RTP_SUCCESS)
{
RTP_TRACE_WARNING("[formRtcpPacket] Error in RR pkt encoding", RTP_ZERO, RTP_ZERO);
return eEncodeRes;
}
}
if (m_pobjSdesPkt != RTP_NULL)
{
eEncodeRes = m_pobjSdesPkt->formSdesPacket(pobjRtcpPktBuf);
if (eEncodeRes != RTP_SUCCESS)
{
RTP_TRACE_WARNING("[formRtcpPacket] Error in SDES pkt encoding", RTP_ZERO, RTP_ZERO);
return eEncodeRes;
}
}
if (m_pobjAppPkt != RTP_NULL)
{
eEncodeRes = m_pobjAppPkt->formAppPacket(pobjRtcpPktBuf);
if (eEncodeRes != RTP_SUCCESS)
{
RTP_TRACE_WARNING("[formRtcpPacket] Error in APP pkt encoding", RTP_ZERO, RTP_ZERO);
return eEncodeRes;
}
}
if (m_pobjByePkt != RTP_NULL)
{
eEncodeRes = m_pobjByePkt->formByePacket(pobjRtcpPktBuf);
if (eEncodeRes != RTP_SUCCESS)
{
RTP_TRACE_WARNING("[formRtcpPacket] Error in BYE pkt encoding", RTP_ZERO, RTP_ZERO);
return eEncodeRes;
}
}
if (m_objFbPktList.size() != RTP_ZERO)
{
RtcpFbPacket* pobjRtcpFbPkt = m_objFbPktList.front();
eEncodeRes = pobjRtcpFbPkt->formRtcpFbPacket(pobjRtcpPktBuf);
if (eEncodeRes != RTP_SUCCESS)
{
RTP_TRACE_WARNING("[formRtcpPacket] Error in Fb pkt encoding.", RTP_ZERO, RTP_ZERO);
return eEncodeRes;
}
}
if (m_pobjRtcpXrPkt != RTP_NULL)
{
eEncodeRes = m_pobjRtcpXrPkt->formRtcpXrPacket(pobjRtcpPktBuf);
if (eEncodeRes != RTP_SUCCESS)
{
RTP_TRACE_WARNING("[formRtcpPacket] Error in XR pkt encoding", RTP_ZERO, RTP_ZERO);
return eEncodeRes;
}
}
return RTP_SUCCESS;
} // formRtcpPacket