• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 }