1 /**
2 * Copyright (C) 2022 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include <RtcpDecoderNode.h>
18 #include <ImsMediaTrace.h>
19 #include <ImsMediaVideoUtil.h>
20
21 #ifdef DEBUG_BITRATE_CHANGE_SIMULATION
22 static int32_t gTestBitrate = 384000;
23 #endif
24
RtcpDecoderNode(BaseSessionCallback * callback)25 RtcpDecoderNode::RtcpDecoderNode(BaseSessionCallback* callback) :
26 BaseNode(callback)
27 {
28 mRtpSession = nullptr;
29 mInactivityTime = 0;
30 mNoRtcpTime = 0;
31 }
32
~RtcpDecoderNode()33 RtcpDecoderNode::~RtcpDecoderNode()
34 {
35 if (mRtpSession != nullptr)
36 {
37 mRtpSession->SetRtcpEncoderListener(nullptr);
38 IRtpSession::ReleaseInstance(mRtpSession);
39 mRtpSession = nullptr;
40 }
41 }
42
GetNodeId()43 kBaseNodeId RtcpDecoderNode::GetNodeId()
44 {
45 return kNodeIdRtcpDecoder;
46 }
47
Start()48 ImsMediaResult RtcpDecoderNode::Start()
49 {
50 IMLOGD0("[Start]");
51
52 if (mRtpSession == nullptr)
53 {
54 mRtpSession = IRtpSession::GetInstance(mMediaType, mLocalAddress, mPeerAddress);
55
56 if (mRtpSession == nullptr)
57 {
58 IMLOGE0("[Start] Can't create rtp session");
59 return RESULT_NOT_READY;
60 }
61 }
62
63 mRtpSession->SetRtcpDecoderListener(this);
64 mNoRtcpTime = 0;
65 mNodeState = kNodeStateRunning;
66 return RESULT_SUCCESS;
67 }
68
Stop()69 void RtcpDecoderNode::Stop()
70 {
71 IMLOGD0("[Stop]");
72
73 if (mRtpSession)
74 {
75 mRtpSession->StopRtcp();
76 }
77
78 mNodeState = kNodeStateStopped;
79 }
80
OnDataFromFrontNode(ImsMediaSubType subtype,uint8_t * pData,uint32_t nDataSize,uint32_t nTimeStamp,bool bMark,uint32_t nSeqNum,ImsMediaSubType nDataType,uint32_t arrivalTime)81 void RtcpDecoderNode::OnDataFromFrontNode(ImsMediaSubType subtype, uint8_t* pData,
82 uint32_t nDataSize, uint32_t nTimeStamp, bool bMark, uint32_t nSeqNum,
83 ImsMediaSubType nDataType, uint32_t arrivalTime)
84 {
85 (void)nDataType;
86 (void)arrivalTime;
87
88 IMLOGD_PACKET6(IM_PACKET_LOG_RTCP,
89 "[OnMediaDataInd] media[%d] subtype[%d], Size[%d], TS[%u], Mark[%d], Seq[%d]",
90 mMediaType, subtype, nDataSize, nTimeStamp, bMark, nSeqNum);
91 if (mRtpSession != nullptr)
92 {
93 mRtpSession->ProcRtcpPacket(pData, nDataSize);
94 }
95 }
96
IsRunTime()97 bool RtcpDecoderNode::IsRunTime()
98 {
99 return true;
100 }
101
IsSourceNode()102 bool RtcpDecoderNode::IsSourceNode()
103 {
104 return false;
105 }
106
SetConfig(void * config)107 void RtcpDecoderNode::SetConfig(void* config)
108 {
109 if (config == nullptr)
110 {
111 return;
112 }
113
114 RtpConfig* pConfig = reinterpret_cast<RtpConfig*>(config);
115 mPeerAddress = RtpAddress(pConfig->getRemoteAddress().c_str(), pConfig->getRemotePort());
116 IMLOGD2("[SetConfig] peer Ip[%s], port[%d]", mPeerAddress.ipAddress, mPeerAddress.port);
117 }
118
IsSameConfig(void * config)119 bool RtcpDecoderNode::IsSameConfig(void* config)
120 {
121 if (config == nullptr)
122 {
123 return true;
124 }
125
126 RtpConfig* pConfig = reinterpret_cast<RtpConfig*>(config);
127 RtpAddress peerAddress =
128 RtpAddress(pConfig->getRemoteAddress().c_str(), pConfig->getRemotePort());
129
130 return (mPeerAddress == peerAddress);
131 }
132
OnRtcpInd(tRtpSvc_IndicationFromStack type,void * data)133 void RtcpDecoderNode::OnRtcpInd(tRtpSvc_IndicationFromStack type, void* data)
134 {
135 if (data == nullptr)
136 {
137 return;
138 }
139
140 switch (type)
141 {
142 case RTPSVC_RECEIVE_RTCP_SR_IND:
143 {
144 tNotifyReceiveRtcpSrInd* payload = reinterpret_cast<tNotifyReceiveRtcpSrInd*>(data);
145 IMLOGD_PACKET2(IM_PACKET_LOG_RTCP, "[OnRtcpInd] RtcpSr - fractionLost[%d], jitter[%d]",
146 payload->stRecvRpt.fractionLost, payload->stRecvRpt.jitter);
147
148 if (mMediaType == IMS_MEDIA_AUDIO)
149 {
150 mCallback->SendEvent(kCollectPacketInfo, kStreamRtcp);
151 }
152 #ifdef DEBUG_BITRATE_CHANGE_SIMULATION
153 else if (mMediaType == IMS_MEDIA_VIDEO)
154 {
155 gTestBitrate *= 0.8;
156 mCallback->SendEvent(kRequestVideoBitrateChange, gTestBitrate);
157 }
158 #endif
159 }
160 break;
161 case RTPSVC_RECEIVE_RTCP_RR_IND:
162 {
163 tNotifyReceiveRtcpRrInd* payload = reinterpret_cast<tNotifyReceiveRtcpRrInd*>(data);
164 IMLOGD_PACKET2(IM_PACKET_LOG_RTCP, "[OnRtcpInd] RtcpRr - fractionLost[%d], jitter[%d]",
165 payload->stRecvRpt.fractionLost, payload->stRecvRpt.jitter);
166
167 if (mMediaType == IMS_MEDIA_AUDIO)
168 {
169 mCallback->SendEvent(kCollectPacketInfo, kStreamRtcp);
170 }
171 #ifdef DEBUG_BITRATE_CHANGE_SIMULATION
172 else if (mMediaType == IMS_MEDIA_VIDEO)
173 {
174 gTestBitrate *= 0.8;
175 mCallback->SendEvent(kRequestVideoBitrateChange, gTestBitrate);
176 }
177 #endif
178 }
179 break;
180 case RTPSVC_RECEIVE_RTCP_FB_IND:
181 case RTPSVC_RECEIVE_RTCP_PAYLOAD_FB_IND:
182 {
183 tRtpSvcIndSt_ReceiveRtcpFeedbackInd* payload =
184 reinterpret_cast<tRtpSvcIndSt_ReceiveRtcpFeedbackInd*>(data);
185 uint32_t feedbackType = 0;
186
187 if (type == RTPSVC_RECEIVE_RTCP_FB_IND)
188 {
189 feedbackType = payload->wFmt;
190 }
191 else if (type == RTPSVC_RECEIVE_RTCP_PAYLOAD_FB_IND)
192 {
193 feedbackType = payload->wFmt + kPsfbBoundary;
194 }
195
196 switch (feedbackType)
197 {
198 case kRtpFbNack:
199 /** do nothing */
200 break;
201 case kRtpFbTmmbr:
202 ReceiveTmmbr(payload);
203 break;
204 case kRtpFbTmmbn:
205 break;
206 case kPsfbPli: // FALL_THROUGH
207 case kPsfbFir:
208 RequestIdrFrame();
209 break;
210 default:
211 IMLOGI2("[OnRtcpInd] unhandled payload[%d], fmt[%d]", payload->wPayloadType,
212 payload->wFmt);
213 break;
214 }
215 }
216 break;
217 default:
218 IMLOGI1("[OnRtcpInd] unhandled type[%d]", type);
219 break;
220 }
221 }
222
OnNumReceivedPacket(uint32_t nNumRtcpSRPacket,uint32_t nNumRtcpRRPacket)223 void RtcpDecoderNode::OnNumReceivedPacket(uint32_t nNumRtcpSRPacket, uint32_t nNumRtcpRRPacket)
224 {
225 IMLOGD_PACKET3(IM_PACKET_LOG_RTCP,
226 "[OnNumReceivedPacket] InactivityTime[%d], numRtcpSR[%d], numRtcpRR[%d]",
227 mInactivityTime, nNumRtcpSRPacket, nNumRtcpRRPacket);
228
229 if (nNumRtcpSRPacket == 0 && nNumRtcpRRPacket == 0)
230 {
231 mNoRtcpTime++;
232 }
233 else
234 {
235 mNoRtcpTime = 0;
236 }
237
238 if (mInactivityTime != 0 && mNoRtcpTime == mInactivityTime)
239 {
240 if (mCallback != nullptr)
241 {
242 mCallback->SendEvent(kImsMediaEventMediaInactivity, kProtocolRtcp, mInactivityTime);
243 }
244 }
245 }
246
OnEvent(uint32_t event,uint32_t param)247 void RtcpDecoderNode::OnEvent(uint32_t event, uint32_t param)
248 {
249 mCallback->SendEvent(event, param);
250 }
251
SetLocalAddress(const RtpAddress & address)252 void RtcpDecoderNode::SetLocalAddress(const RtpAddress& address)
253 {
254 mLocalAddress = address;
255 }
256
SetPeerAddress(const RtpAddress & address)257 void RtcpDecoderNode::SetPeerAddress(const RtpAddress& address)
258 {
259 mPeerAddress = address;
260 }
261
SetInactivityTimerSec(const uint32_t time)262 void RtcpDecoderNode::SetInactivityTimerSec(const uint32_t time)
263 {
264 IMLOGD2("[SetInactivityTimerSec] media[%d], time[%d] reset", mMediaType, time);
265 mInactivityTime = time;
266 mNoRtcpTime = 0;
267 }
268
ReceiveTmmbr(const tRtpSvcIndSt_ReceiveRtcpFeedbackInd * payload)269 void RtcpDecoderNode::ReceiveTmmbr(const tRtpSvcIndSt_ReceiveRtcpFeedbackInd* payload)
270 {
271 if (payload == nullptr || payload->pMsg == nullptr || mCallback == nullptr)
272 {
273 return;
274 }
275
276 // Read bitrate from TMMBR
277 mBitReader.SetBuffer(payload->pMsg, 64);
278 /** read 16 bit and combine it */
279 uint32_t receivedSsrc = mBitReader.Read(16);
280 receivedSsrc = (receivedSsrc << 16) | mBitReader.Read(16);
281 uint32_t receivedExp = mBitReader.Read(6);
282 uint32_t receivedMantissa = mBitReader.Read(17);
283 uint32_t receivedOverhead = mBitReader.Read(9);
284 uint32_t bitrate = receivedMantissa << receivedExp;
285
286 IMLOGD3("[ReceiveTmmbr] received TMMBR, exp[%d], mantissa[%d], bitrate[%d]", receivedExp,
287 receivedMantissa, bitrate);
288
289 // Set the bitrate to encoder
290 mCallback->SendEvent(kRequestVideoBitrateChange, bitrate);
291
292 // Send TMMBN to peer
293 uint32_t exp = 0;
294 uint32_t mantissa = 0;
295 ImsMediaVideoUtil::ConvertBitrateToPower(bitrate, exp, mantissa);
296
297 InternalRequestEventParam* pParam = new InternalRequestEventParam(
298 kRtpFbTmmbn, TmmbrParams(receivedSsrc, exp, mantissa, receivedOverhead));
299 mCallback->SendEvent(kRequestVideoSendTmmbn, reinterpret_cast<uint64_t>(pParam));
300 }
301
RequestIdrFrame()302 void RtcpDecoderNode::RequestIdrFrame()
303 {
304 IMLOGD0("[RequestIdrFrame]");
305
306 if (mCallback != nullptr)
307 {
308 mCallback->SendEvent(kRequestVideoIdrFrame, 0);
309 }
310 }