blob: 7682bfc782dd5288847424c344ea3bce3c83346c [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 <RtcpDecoderNode.h>
#include <ImsMediaTrace.h>
#include <ImsMediaVideoUtil.h>
RtcpDecoderNode::RtcpDecoderNode(BaseSessionCallback* callback) :
BaseNode(callback)
{
mRtpSession = nullptr;
mInactivityTime = 0;
mNoRtcpTime = 0;
}
RtcpDecoderNode::~RtcpDecoderNode()
{
if (mRtpSession != nullptr)
{
mRtpSession->SetRtcpEncoderListener(nullptr);
IRtpSession::ReleaseInstance(mRtpSession);
mRtpSession = nullptr;
}
}
kBaseNodeId RtcpDecoderNode::GetNodeId()
{
return kNodeIdRtcpDecoder;
}
ImsMediaResult RtcpDecoderNode::Start()
{
IMLOGD0("[Start]");
if (mRtpSession == nullptr)
{
mRtpSession = IRtpSession::GetInstance(mMediaType, mLocalAddress, mPeerAddress);
if (mRtpSession == nullptr)
{
IMLOGE0("[Start] Can't create rtp session");
return RESULT_NOT_READY;
}
}
mRtpSession->SetRtcpDecoderListener(this);
mNoRtcpTime = 0;
mNodeState = kNodeStateRunning;
return RESULT_SUCCESS;
}
void RtcpDecoderNode::Stop()
{
IMLOGD0("[Stop]");
if (mRtpSession)
{
mRtpSession->StopRtcp();
}
mNodeState = kNodeStateStopped;
}
void RtcpDecoderNode::OnDataFromFrontNode(ImsMediaSubType subtype, uint8_t* pData,
uint32_t nDataSize, uint32_t nTimeStamp, bool bMark, uint32_t nSeqNum,
ImsMediaSubType nDataType, uint32_t arrivalTime)
{
(void)nDataType;
(void)arrivalTime;
IMLOGD_PACKET6(IM_PACKET_LOG_RTCP,
"[OnMediaDataInd] media[%d] subtype[%d], Size[%d], TS[%u], Mark[%d], Seq[%d]",
mMediaType, subtype, nDataSize, nTimeStamp, bMark, nSeqNum);
mRtpSession->ProcRtcpPacket(pData, nDataSize);
}
bool RtcpDecoderNode::IsRunTime()
{
return true;
}
bool RtcpDecoderNode::IsSourceNode()
{
return false;
}
void RtcpDecoderNode::SetConfig(void* config)
{
if (config == nullptr)
{
return;
}
RtpConfig* pConfig = reinterpret_cast<RtpConfig*>(config);
mPeerAddress = RtpAddress(pConfig->getRemoteAddress().c_str(), pConfig->getRemotePort());
IMLOGD2("[SetConfig] peer Ip[%s], port[%d]", mPeerAddress.ipAddress, mPeerAddress.port);
}
bool RtcpDecoderNode::IsSameConfig(void* config)
{
if (config == nullptr)
{
return true;
}
RtpConfig* pConfig = reinterpret_cast<RtpConfig*>(config);
RtpAddress peerAddress =
RtpAddress(pConfig->getRemoteAddress().c_str(), pConfig->getRemotePort());
return (mPeerAddress == peerAddress);
}
void RtcpDecoderNode::OnRtcpInd(tRtpSvc_IndicationFromStack type, void* data)
{
if (data == nullptr)
{
return;
}
switch (type)
{
case RTPSVC_RECEIVE_RTCP_SR_IND:
{
tNotifyReceiveRtcpSrInd* payload = reinterpret_cast<tNotifyReceiveRtcpSrInd*>(data);
IMLOGD_PACKET2(IM_PACKET_LOG_RTCP, "[OnRtcpInd] RtcpSr - fractionLost[%d], jitter[%d]",
payload->stRecvRpt.fractionLost, payload->stRecvRpt.jitter);
if (mMediaType == IMS_MEDIA_AUDIO)
{
mCallback->SendEvent(kCollectPacketInfo, kStreamRtcp);
}
}
break;
case RTPSVC_RECEIVE_RTCP_RR_IND:
{
tNotifyReceiveRtcpRrInd* payload = reinterpret_cast<tNotifyReceiveRtcpRrInd*>(data);
IMLOGD_PACKET2(IM_PACKET_LOG_RTCP, "[OnRtcpInd] RtcpRr - fractionLost[%d], jitter[%d]",
payload->stRecvRpt.fractionLost, payload->stRecvRpt.jitter);
if (mMediaType == IMS_MEDIA_AUDIO)
{
mCallback->SendEvent(kCollectPacketInfo, kStreamRtcp);
}
}
break;
case RTPSVC_RECEIVE_RTCP_FB_IND:
case RTPSVC_RECEIVE_RTCP_PAYLOAD_FB_IND:
{
tRtpSvcIndSt_ReceiveRtcpFeedbackInd* payload =
reinterpret_cast<tRtpSvcIndSt_ReceiveRtcpFeedbackInd*>(data);
uint32_t feedbackType = 0;
if (type == RTPSVC_RECEIVE_RTCP_FB_IND)
{
feedbackType = payload->wFmt;
}
else if (type == RTPSVC_RECEIVE_RTCP_PAYLOAD_FB_IND)
{
feedbackType = payload->wFmt + kPsfbBoundary;
}
switch (feedbackType)
{
case kRtpFbNack:
/** do nothing */
break;
case kRtpFbTmmbr:
ReceiveTmmbr(payload);
break;
case kRtpFbTmmbn:
break;
case kPsfbPli: // FALL_THROUGH
case kPsfbFir:
RequestIdrFrame();
break;
default:
IMLOGI2("[OnRtcpInd] unhandled payload[%d], fmt[%d]", payload->wPayloadType,
payload->wFmt);
break;
}
}
break;
default:
IMLOGI1("[OnRtcpInd] unhandled type[%d]", type);
break;
}
}
void RtcpDecoderNode::OnNumReceivedPacket(uint32_t nNumRtcpSRPacket, uint32_t nNumRtcpRRPacket)
{
IMLOGD_PACKET3(IM_PACKET_LOG_RTCP,
"[OnNumReceivedPacket] InactivityTime[%d], numRtcpSR[%d], numRtcpRR[%d]",
mInactivityTime, nNumRtcpSRPacket, nNumRtcpRRPacket);
if (nNumRtcpSRPacket == 0 && nNumRtcpRRPacket == 0)
{
mNoRtcpTime++;
}
else
{
mNoRtcpTime = 0;
}
if (mInactivityTime != 0 && mNoRtcpTime == mInactivityTime)
{
if (mCallback != nullptr)
{
mCallback->SendEvent(kImsMediaEventMediaInactivity, kProtocolRtcp, mInactivityTime);
}
}
}
void RtcpDecoderNode::OnEvent(uint32_t event, uint32_t param)
{
mCallback->SendEvent(event, param);
}
void RtcpDecoderNode::SetLocalAddress(const RtpAddress& address)
{
mLocalAddress = address;
}
void RtcpDecoderNode::SetPeerAddress(const RtpAddress& address)
{
mPeerAddress = address;
}
void RtcpDecoderNode::SetInactivityTimerSec(const uint32_t time)
{
IMLOGD2("[SetInactivityTimerSec] media[%d], time[%d] reset", mMediaType, time);
mInactivityTime = time;
mNoRtcpTime = 0;
}
void RtcpDecoderNode::ReceiveTmmbr(const tRtpSvcIndSt_ReceiveRtcpFeedbackInd* payload)
{
if (payload == nullptr || payload->pMsg == nullptr || mCallback == nullptr)
{
return;
}
// Read bitrate from TMMBR
mBitReader.SetBuffer(payload->pMsg, 64);
/** read 16 bit and combine it */
uint32_t receivedSsrc = mBitReader.Read(16);
receivedSsrc = (receivedSsrc << 16) | mBitReader.Read(16);
uint32_t receivedExp = mBitReader.Read(6);
uint32_t receivedMantissa = mBitReader.Read(17);
uint32_t receivedOverhead = mBitReader.Read(9);
uint32_t bitrate = receivedMantissa << receivedExp;
IMLOGD3("[ReceiveTmmbr] received TMMBR, exp[%d], mantissa[%d], bitrate[%d]", receivedExp,
receivedMantissa, bitrate);
// Set the bitrate to encoder
mCallback->SendEvent(kRequestVideoBitrateChange, bitrate);
// Send TMMBN to peer
uint32_t exp = 0;
uint32_t mantissa = 0;
ImsMediaVideoUtil::ConvertBitrateToPower(bitrate, exp, mantissa);
InternalRequestEventParam* pParam = new InternalRequestEventParam(
kRtpFbTmmbr, TmmbrParams(receivedSsrc, exp, mantissa, receivedOverhead));
mCallback->SendEvent(kRequestVideoSendTmmbn, reinterpret_cast<uint64_t>(pParam));
}
void RtcpDecoderNode::RequestIdrFrame()
{
IMLOGD0("[RequestIdrFrame]");
if (mCallback != nullptr)
{
mCallback->SendEvent(kRequestVideoIdrFrame, 0);
}
}