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
146 if (mMediaType == IMS_MEDIA_AUDIO)
147 {
148 RtcpSr* rtcpSr = new RtcpSr(payload->ntpTimestampMsw, payload->ntpTimestampLsw,
149 payload->rtpTimestamp, payload->sendPktCount, payload->sendOctCount,
150 RtcpRecvReport(payload->stRecvRpt.ssrc, payload->stRecvRpt.fractionLost,
151 payload->stRecvRpt.cumPktsLost, payload->stRecvRpt.extHighSeqNum,
152 payload->stRecvRpt.jitter, payload->stRecvRpt.lsr,
153 payload->stRecvRpt.delayLsr));
154 mCallback->SendEvent(
155 kCollectPacketInfo, kStreamRtcp, reinterpret_cast<uint64_t>(rtcpSr));
156 }
157 #ifdef DEBUG_BITRATE_CHANGE_SIMULATION
158 else if (mMediaType == IMS_MEDIA_VIDEO)
159 {
160 gTestBitrate *= 0.8;
161 mCallback->SendEvent(kRequestVideoBitrateChange, gTestBitrate);
162 }
163 #endif
164 }
165 break;
166 case RTPSVC_RECEIVE_RTCP_RR_IND:
167 {
168 tNotifyReceiveRtcpRrInd* payload = reinterpret_cast<tNotifyReceiveRtcpRrInd*>(data);
169 IMLOGD_PACKET2(IM_PACKET_LOG_RTCP, "[OnRtcpInd] RtcpRr - fractionLost[%d], jitter[%d]",
170 payload->stRecvRpt.fractionLost, payload->stRecvRpt.jitter);
171
172 if (mMediaType == IMS_MEDIA_AUDIO)
173 {
174 mCallback->SendEvent(kCollectPacketInfo, kStreamRtcp);
175 }
176 #ifdef DEBUG_BITRATE_CHANGE_SIMULATION
177 else if (mMediaType == IMS_MEDIA_VIDEO)
178 {
179 gTestBitrate *= 0.8;
180 mCallback->SendEvent(kRequestVideoBitrateChange, gTestBitrate);
181 }
182 #endif
183 }
184 break;
185 case RTPSVC_RECEIVE_RTCP_FB_IND:
186 case RTPSVC_RECEIVE_RTCP_PAYLOAD_FB_IND:
187 {
188 tRtpSvcIndSt_ReceiveRtcpFeedbackInd* payload =
189 reinterpret_cast<tRtpSvcIndSt_ReceiveRtcpFeedbackInd*>(data);
190 uint32_t feedbackType = 0;
191
192 if (type == RTPSVC_RECEIVE_RTCP_FB_IND)
193 {
194 feedbackType = payload->wFmt;
195 }
196 else if (type == RTPSVC_RECEIVE_RTCP_PAYLOAD_FB_IND)
197 {
198 feedbackType = payload->wFmt + kPsfbBoundary;
199 }
200
201 switch (feedbackType)
202 {
203 case kRtpFbNack:
204 /** do nothing */
205 break;
206 case kRtpFbTmmbr:
207 ReceiveTmmbr(payload);
208 break;
209 case kRtpFbTmmbn:
210 break;
211 case kPsfbPli: // FALL_THROUGH
212 case kPsfbFir:
213 RequestIdrFrame();
214 break;
215 default:
216 IMLOGI2("[OnRtcpInd] unhandled payload[%d], fmt[%d]", payload->wPayloadType,
217 payload->wFmt);
218 break;
219 }
220 }
221 break;
222 default:
223 IMLOGI1("[OnRtcpInd] unhandled type[%d]", type);
224 break;
225 }
226 }
227
OnNumReceivedPacket(uint32_t nNumRtcpSRPacket,uint32_t nNumRtcpRRPacket)228 void RtcpDecoderNode::OnNumReceivedPacket(uint32_t nNumRtcpSRPacket, uint32_t nNumRtcpRRPacket)
229 {
230 IMLOGD_PACKET3(IM_PACKET_LOG_RTCP,
231 "[OnNumReceivedPacket] InactivityTime[%d], numRtcpSR[%d], numRtcpRR[%d]",
232 mInactivityTime, nNumRtcpSRPacket, nNumRtcpRRPacket);
233
234 if (nNumRtcpSRPacket == 0 && nNumRtcpRRPacket == 0)
235 {
236 mNoRtcpTime++;
237 }
238 else
239 {
240 mNoRtcpTime = 0;
241 }
242
243 if (mInactivityTime != 0 && mNoRtcpTime == mInactivityTime)
244 {
245 if (mCallback != nullptr)
246 {
247 mCallback->SendEvent(kImsMediaEventMediaInactivity, kProtocolRtcp, mInactivityTime);
248 }
249 }
250 }
251
OnEvent(uint32_t event,uint32_t param)252 void RtcpDecoderNode::OnEvent(uint32_t event, uint32_t param)
253 {
254 mCallback->SendEvent(event, param);
255 }
256
SetLocalAddress(const RtpAddress & address)257 void RtcpDecoderNode::SetLocalAddress(const RtpAddress& address)
258 {
259 mLocalAddress = address;
260 }
261
SetPeerAddress(const RtpAddress & address)262 void RtcpDecoderNode::SetPeerAddress(const RtpAddress& address)
263 {
264 mPeerAddress = address;
265 }
266
SetInactivityTimerSec(const uint32_t time)267 void RtcpDecoderNode::SetInactivityTimerSec(const uint32_t time)
268 {
269 IMLOGD2("[SetInactivityTimerSec] media[%d], time[%d] reset", mMediaType, time);
270 mInactivityTime = time;
271 mNoRtcpTime = 0;
272 }
273
ReceiveTmmbr(const tRtpSvcIndSt_ReceiveRtcpFeedbackInd * payload)274 void RtcpDecoderNode::ReceiveTmmbr(const tRtpSvcIndSt_ReceiveRtcpFeedbackInd* payload)
275 {
276 if (payload == nullptr || payload->pMsg == nullptr || mCallback == nullptr)
277 {
278 return;
279 }
280
281 // Read bitrate from TMMBR
282 mBitReader.SetBuffer(payload->pMsg, 64);
283 /** read 16 bit and combine it */
284 uint32_t receivedSsrc = mBitReader.Read(16);
285 receivedSsrc = (receivedSsrc << 16) | mBitReader.Read(16);
286 uint32_t receivedExp = mBitReader.Read(6);
287 uint32_t receivedMantissa = mBitReader.Read(17);
288 uint32_t receivedOverhead = mBitReader.Read(9);
289 uint32_t bitrate = receivedMantissa << receivedExp;
290
291 IMLOGD3("[ReceiveTmmbr] received TMMBR, exp[%d], mantissa[%d], bitrate[%d]", receivedExp,
292 receivedMantissa, bitrate);
293
294 // Set the bitrate to encoder
295 mCallback->SendEvent(kRequestVideoBitrateChange, bitrate);
296
297 // Send TMMBN to peer
298 uint32_t exp = 0;
299 uint32_t mantissa = 0;
300 ImsMediaVideoUtil::ConvertBitrateToPower(bitrate, exp, mantissa);
301
302 InternalRequestEventParam* pParam = new InternalRequestEventParam(
303 kRtpFbTmmbn, TmmbrParams(receivedSsrc, exp, mantissa, receivedOverhead));
304 mCallback->SendEvent(kRequestVideoSendTmmbn, reinterpret_cast<uint64_t>(pParam));
305 }
306
RequestIdrFrame()307 void RtcpDecoderNode::RequestIdrFrame()
308 {
309 IMLOGD0("[RequestIdrFrame]");
310
311 if (mCallback != nullptr)
312 {
313 mCallback->SendEvent(kRequestVideoIdrFrame, 0);
314 }
315 }