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 <RtcpEncoderNode.h>
18 #include <ImsMediaTrace.h>
19 #include <VideoConfig.h>
20
21 #define RTCPFBMNGR_PLI_FIR_REQUEST_MIN_INTERVAL 1000
22
RtcpEncoderNode(BaseSessionCallback * callback)23 RtcpEncoderNode::RtcpEncoderNode(BaseSessionCallback* callback) :
24 BaseNode(callback)
25 {
26 mRtpSession = nullptr;
27 mRtcpInterval = 0;
28 mRtcpXrPayload = nullptr;
29 mEnableRtcpBye = false;
30 mRtcpXrBlockTypes = RtcpConfig::FLAG_RTCPXR_NONE;
31 mRtcpXrCounter = 0;
32 mTimer = nullptr;
33 mLastTimeSentPli = 0;
34 mLastTimeSentFir = 0;
35 }
36
~RtcpEncoderNode()37 RtcpEncoderNode::~RtcpEncoderNode()
38 {
39 if (mRtpSession != nullptr)
40 {
41 mRtpSession->StopRtcp();
42 mRtpSession->SetRtcpEncoderListener(nullptr);
43 IRtpSession::ReleaseInstance(mRtpSession);
44 mRtpSession = nullptr;
45 }
46
47 mRtcpXrBlockTypes = RtcpConfig::FLAG_RTCPXR_NONE;
48 mRtcpXrCounter = 0;
49 }
50
GetNodeId()51 kBaseNodeId RtcpEncoderNode::GetNodeId()
52 {
53 return kNodeIdRtcpEncoder;
54 }
55
Start()56 ImsMediaResult RtcpEncoderNode::Start()
57 {
58 std::lock_guard<std::mutex> guard(mMutexTimer);
59
60 if (mRtpSession == nullptr)
61 {
62 mRtpSession = IRtpSession::GetInstance(mMediaType, mLocalAddress, mPeerAddress);
63
64 if (mRtpSession == nullptr)
65 {
66 IMLOGE0("[Start] Can't create rtp session");
67 return RESULT_NOT_READY;
68 }
69 }
70
71 IMLOGD4("[Start] interval[%d], rtcpBye[%d], rtcpXrBlock[%d], rtcpFbTypes[%d]", mRtcpInterval,
72 mEnableRtcpBye, mRtcpXrBlockTypes, mRtcpFbTypes);
73 mRtpSession->SetRtcpEncoderListener(this);
74 mRtpSession->SetRtcpInterval(mRtcpInterval);
75
76 if (mRtcpInterval > 0)
77 {
78 mRtpSession->StartRtcp(mEnableRtcpBye);
79 }
80
81 if (mTimer == nullptr)
82 {
83 mTimer = ImsMediaTimer::TimerStart(1000, true, OnTimer, this);
84 IMLOGD0("[Start] Rtcp Timer started");
85 }
86
87 mRtcpXrCounter = 1;
88 mNodeState = kNodeStateRunning;
89 return RESULT_SUCCESS;
90 }
91
Stop()92 void RtcpEncoderNode::Stop()
93 {
94 IMLOGD0("[Stop]");
95 std::lock_guard<std::mutex> guard(mMutexTimer);
96
97 if (mRtpSession != nullptr)
98 {
99 mRtpSession->StopRtcp();
100 }
101
102 if (mTimer != nullptr)
103 {
104 ImsMediaTimer::TimerStop(mTimer, nullptr);
105 mTimer = nullptr;
106 IMLOGD0("[Stop] Rtcp Timer stopped");
107 }
108
109 mNodeState = kNodeStateStopped;
110 }
111
IsRunTime()112 bool RtcpEncoderNode::IsRunTime()
113 {
114 return true;
115 }
116
IsSourceNode()117 bool RtcpEncoderNode::IsSourceNode()
118 {
119 return true;
120 }
121
SetConfig(void * config)122 void RtcpEncoderNode::SetConfig(void* config)
123 {
124 RtpConfig* pConfig = reinterpret_cast<RtpConfig*>(config);
125 mPeerAddress = RtpAddress(pConfig->getRemoteAddress().c_str(), pConfig->getRemotePort());
126 mRtcpInterval = pConfig->getRtcpConfig().getIntervalSec();
127 mRtcpXrBlockTypes = pConfig->getRtcpConfig().getRtcpXrBlockTypes();
128 mEnableRtcpBye = false;
129
130 IMLOGD4("[SetConfig] peer Ip[%s], port[%d], interval[%d], rtcpxr[%d]", mPeerAddress.ipAddress,
131 mPeerAddress.port, mRtcpInterval, mRtcpXrBlockTypes);
132
133 if (mMediaType == IMS_MEDIA_VIDEO)
134 {
135 VideoConfig* videoConfig = reinterpret_cast<VideoConfig*>(config);
136 mRtcpFbTypes = videoConfig->getRtcpFbType();
137 IMLOGD1("[SetConfig] rtcpFbTypes[%d]", mRtcpFbTypes);
138 }
139 }
140
IsSameConfig(void * config)141 bool RtcpEncoderNode::IsSameConfig(void* config)
142 {
143 if (config == nullptr)
144 {
145 return true;
146 }
147
148 RtpConfig* pConfig = reinterpret_cast<RtpConfig*>(config);
149 RtpAddress peerAddress =
150 RtpAddress(pConfig->getRemoteAddress().c_str(), pConfig->getRemotePort());
151
152 if (mMediaType == IMS_MEDIA_VIDEO)
153 {
154 VideoConfig* videoConfig = reinterpret_cast<VideoConfig*>(config);
155 return (mPeerAddress == peerAddress &&
156 mRtcpInterval == videoConfig->getRtcpConfig().getIntervalSec() &&
157 mRtcpXrBlockTypes == videoConfig->getRtcpConfig().getRtcpXrBlockTypes() &&
158 mRtcpFbTypes == videoConfig->getRtcpFbType());
159 }
160 else
161 {
162 return (mPeerAddress == peerAddress &&
163 mRtcpInterval == pConfig->getRtcpConfig().getIntervalSec() &&
164 mRtcpXrBlockTypes == pConfig->getRtcpConfig().getRtcpXrBlockTypes());
165 }
166 }
167
OnRtcpPacket(unsigned char * pData,uint32_t wLen)168 void RtcpEncoderNode::OnRtcpPacket(unsigned char* pData, uint32_t wLen)
169 {
170 ImsMediaSubType subtype = MEDIASUBTYPE_RTCPPACKET;
171
172 if (mEnableRtcpBye == true)
173 {
174 uint8_t* pCurr;
175 int32_t nRemainSize;
176 pCurr = reinterpret_cast<uint8_t*>(pData);
177 nRemainSize = wLen;
178
179 while (nRemainSize >= 4)
180 {
181 uint8_t PT = pCurr[1];
182 uint32_t length;
183 IMLOGD_PACKET1(IM_PACKET_LOG_RTCP, "[OnRtcpPacket] PT[%d]", PT);
184
185 if (PT == 203)
186 {
187 subtype = MEDIASUBTYPE_RTCPPACKET_BYE;
188 break;
189 }
190
191 length = pCurr[2];
192 length <<= 8;
193 length += pCurr[3];
194 length = (length + 1) * 4;
195
196 pCurr += length;
197 nRemainSize -= length;
198 }
199 }
200
201 SendDataToRearNode(subtype, pData, wLen, 0, 0, 0);
202 }
203
OnTimer(hTimerHandler hTimer,void * pUserData)204 void RtcpEncoderNode::OnTimer(hTimerHandler hTimer, void* pUserData)
205 {
206 (void)hTimer;
207 RtcpEncoderNode* pNode = reinterpret_cast<RtcpEncoderNode*>(pUserData);
208
209 if (pNode != nullptr)
210 {
211 pNode->ProcessTimer();
212 }
213 }
214
ProcessTimer()215 void RtcpEncoderNode::ProcessTimer()
216 {
217 std::lock_guard<std::mutex> guard(mMutexTimer);
218
219 if (mTimer == nullptr || mRtpSession == nullptr)
220 {
221 return;
222 }
223
224 mRtpSession->OnTimer();
225
226 mRtcpXrCounter++;
227
228 if (mRtcpXrBlockTypes != 0 && mRtcpInterval != 0 && mRtcpXrCounter % mRtcpInterval == 0)
229 {
230 mCallback->SendEvent(kGetRtcpXrReportBlock, mRtcpXrBlockTypes);
231 }
232 }
233
SetLocalAddress(const RtpAddress & address)234 void RtcpEncoderNode::SetLocalAddress(const RtpAddress& address)
235 {
236 mLocalAddress = address;
237 }
238
SetPeerAddress(const RtpAddress & address)239 void RtcpEncoderNode::SetPeerAddress(const RtpAddress& address)
240 {
241 mPeerAddress = address;
242 }
243
SendNack(NackParams * param)244 bool RtcpEncoderNode::SendNack(NackParams* param)
245 {
246 if (param == nullptr)
247 {
248 return false;
249 }
250
251 if (mRtcpFbTypes & VideoConfig::RTP_FB_NACK)
252 {
253 IMLOGD3("[SendNack] PID[%d], BLP[%d], nSecNackCnt[%d]", param->PID, param->BLP,
254 param->nSecNackCnt);
255
256 /* Generic NACK format
257 0 1 2 3
258 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
259 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
260 | PID | BLP |
261 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+*/
262
263 // create a Nack payload
264 uint8_t pNackBuff[4];
265 mBitWriter.SetBuffer(pNackBuff, 32);
266 mBitWriter.Write(param->PID, 16); // PID
267 mBitWriter.Write(param->BLP, 16); // BLP
268
269 if (param->bNackReport)
270 {
271 if (mRtpSession != nullptr)
272 {
273 return mRtpSession->SendRtcpFeedback(kRtpFbNack, pNackBuff, 4);
274 }
275 }
276 }
277
278 return false;
279 }
280
SendPictureLost(const uint32_t type)281 bool RtcpEncoderNode::SendPictureLost(const uint32_t type)
282 {
283 if (mRtpSession == nullptr)
284 {
285 return false;
286 }
287
288 IMLOGD1("[SendPictureLost] type[%d]", type);
289
290 uint32_t nCurrentTime = ImsMediaTimer::GetTimeInMilliSeconds();
291
292 if (type == kPsfbPli && mRtcpFbTypes & VideoConfig::PSFB_PLI)
293 {
294 if (mLastTimeSentPli == 0 ||
295 (mLastTimeSentPli + RTCPFBMNGR_PLI_FIR_REQUEST_MIN_INTERVAL < nCurrentTime))
296 {
297 if (mRtpSession->SendRtcpFeedback(kPsfbPli, nullptr, 0))
298 {
299 mLastTimeSentPli = nCurrentTime;
300 return true;
301 }
302 }
303 }
304 else if (type == kPsfbFir && mRtcpFbTypes & VideoConfig::PSFB_FIR)
305 {
306 if (mLastTimeSentFir == 0 ||
307 (mLastTimeSentFir + RTCPFBMNGR_PLI_FIR_REQUEST_MIN_INTERVAL < nCurrentTime))
308 {
309 if (mRtpSession->SendRtcpFeedback(kPsfbFir, nullptr, 0))
310 {
311 mLastTimeSentFir = nCurrentTime;
312 return true;
313 }
314 }
315 }
316
317 return false;
318 }
319
SendTmmbrn(const uint32_t type,TmmbrParams * param)320 bool RtcpEncoderNode::SendTmmbrn(const uint32_t type, TmmbrParams* param)
321 {
322 if (mRtpSession == nullptr || param == nullptr)
323 {
324 return false;
325 }
326
327 IMLOGD5("[SendTmmbrn] type[%d], ssrc[%x], exp[%d], mantissa[%d], overhead[%d]", type,
328 param->ssrc, param->exp, param->mantissa, param->overhead);
329
330 /** TMMBR/TMMBN message format
331 0 1 2 3
332 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
333 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
334 | SSRC |
335 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
336 | MxTBR Exp | MxTBR Mantissa |Measured Overhead|
337 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
338 */
339
340 uint8_t buffer[8];
341 mBitWriter.SetBuffer(buffer, 64);
342 mBitWriter.Write((param->ssrc & 0xFFFF0000) >> 16, 16);
343 mBitWriter.Write(param->ssrc & 0x0000FFFF, 16);
344 // MxTBR = mantissa * 2^exp
345 mBitWriter.Write(param->exp, 6); // MxTBR Exp
346 mBitWriter.Write(param->mantissa, 17); // MxTBR Mantissa
347 // avg_OH (new) = 15/16*avg_OH (old) + 1/16*pckt_OH,
348 mBitWriter.Write(param->overhead, 9); // Measured Overhead
349
350 if (type == kRtpFbTmmbr && mRtcpFbTypes & VideoConfig::RTP_FB_TMMBR)
351 {
352 return mRtpSession->SendRtcpFeedback(kRtpFbTmmbr, buffer, 8);
353 }
354 else if (type == kRtpFbTmmbn && mRtcpFbTypes & VideoConfig::RTP_FB_TMMBN)
355 {
356 return mRtpSession->SendRtcpFeedback(kRtpFbTmmbn, buffer, 8);
357 }
358
359 return false;
360 }
361
SendRtcpXr(uint8_t * data,uint32_t size)362 bool RtcpEncoderNode::SendRtcpXr(uint8_t* data, uint32_t size)
363 {
364 if (data == nullptr || mRtpSession == nullptr)
365 {
366 return false;
367 }
368
369 IMLOGD1("[SendRtcpXr] size[%d]", size);
370
371 // send buffer to packets
372 mRtpSession->SendRtcpXr(data, size);
373
374 delete data;
375 return true;
376 }