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 <RtpDecoderNode.h>
18 #include <ImsMediaTrace.h>
19 #include <ImsMediaCondition.h>
20 #include <AudioConfig.h>
21 #include <VideoConfig.h>
22 #include <TextConfig.h>
23 #include <ImsMediaTimer.h>
24 
25 #if defined(SIMULATION_DELAY) || defined(SIMULATION_REORDER) || defined(SIMULATION_LOSS)
26 #include <ImsMediaTimer.h>
27 #endif
28 #ifdef SIMULATION_DELAY
29 #define DEBUG_JITTER_MAX_PACKET_INTERVAL 15  // milliseconds
30 #endif
31 #ifdef SIMULATION_REORDER
32 #include <ImsMediaDataQueue.h>
33 #define DEBUG_JITTER_REORDER_MAX 4
34 #define DEBUG_JITTER_REORDER_MIN 4
35 #define DEBUG_JITTER_NORMAL      2
36 #endif
37 #ifdef SIMULATION_LOSS
38 #define DEBUG_JITTER_LOSS_PACKET_INTERVAL 20
39 #endif
40 #ifdef SIMULATION_DUPLICATE
41 #define DEBUG_JITTER_DUPLICATE_PACKET_INTERVAL 30
42 #endif
43 #define MAX_INTER_ARRIVAL_DELAY 350  // Log if inter-arrival delay is greater than 350msec.
44 
RtpDecoderNode(BaseSessionCallback * callback)45 RtpDecoderNode::RtpDecoderNode(BaseSessionCallback* callback) :
46         BaseNode(callback)
47 {
48     mRtpSession = nullptr;
49     mReceivingSSRC = 0;
50     mInactivityTime = 0;
51     mNoRtpTime = 0;
52     mRtpPayloadTx = 0;
53     mRtpPayloadRx = 0;
54     mRtpTxDtmfPayload = 0;
55     mRtpRxDtmfPayload = 0;
56     mDtmfSamplingRate = 0;
57     mCvoValue = CVO_DEFINE_NONE;
58     mRedundantPayload = 0;
59     mArrivalTime = 0;
60     mSubtype = MEDIASUBTYPE_UNDEFINED;
61     mDtmfEndBit = false;
62 #if defined(SIMULATION_LOSS) || defined(SIMULATION_DUPLICATE) || defined(SIMULATION_SSRC_CHANGE)
63     mPacketCounter = 1;
64 #endif
65 #ifdef SIMULATION_DELAY
66     mNextTime = 0;
67 #endif
68 #ifdef SIMULATION_REORDER
69     mReorderDataCount = 0;
70 #endif
71 }
72 
~RtpDecoderNode()73 RtpDecoderNode::~RtpDecoderNode()
74 {
75     // remove IRtpSession here to avoid shared instance in other node from unable to use
76     if (mRtpSession)
77     {
78         mRtpSession->StopRtp();
79         mRtpSession->SetRtpDecoderListener(nullptr);
80         IRtpSession::ReleaseInstance(mRtpSession);
81         mRtpSession = nullptr;
82     }
83 }
84 
GetNodeId()85 kBaseNodeId RtpDecoderNode::GetNodeId()
86 {
87     return kNodeIdRtpDecoder;
88 }
89 
Start()90 ImsMediaResult RtpDecoderNode::Start()
91 {
92     IMLOGD1("[Start] type[%d]", mMediaType);
93 
94     if (mRtpPayloadTx == 0 || mRtpPayloadRx == 0)
95     {
96         IMLOGE0("[Start] invalid payload number");
97         return RESULT_INVALID_PARAM;
98     }
99 
100     if (mRtpSession == nullptr)
101     {
102         mRtpSession = IRtpSession::GetInstance(mMediaType, mLocalAddress, mPeerAddress);
103 
104         if (mRtpSession == nullptr)
105         {
106             IMLOGE0("[Start] - Can't create rtp session");
107             return RESULT_NOT_READY;
108         }
109     }
110 
111     if (mMediaType == IMS_MEDIA_AUDIO)
112     {
113         mRtpSession->SetRtpPayloadParam(mRtpPayloadTx, mRtpPayloadRx, mSamplingRate * 1000,
114                 mRtpTxDtmfPayload, mRtpRxDtmfPayload, mDtmfSamplingRate * 1000);
115     }
116     else if (mMediaType == IMS_MEDIA_VIDEO)
117     {
118         mRtpSession->SetRtpPayloadParam(mRtpPayloadTx, mRtpPayloadRx, mSamplingRate * 1000);
119     }
120     else if (mMediaType == IMS_MEDIA_TEXT)
121     {
122         if (mRedundantPayload > 0)
123         {
124             mRtpSession->SetRtpPayloadParam(mRtpPayloadTx, mRtpPayloadRx, mSamplingRate * 1000,
125                     mRedundantPayload, mSamplingRate * 1000);
126         }
127         else
128         {
129             mRtpSession->SetRtpPayloadParam(mRtpPayloadTx, mRtpPayloadRx, mSamplingRate * 1000);
130         }
131     }
132 
133     mRtpSession->SetRtpDecoderListener(this);
134     mRtpSession->StartRtp();
135     mReceivingSSRC = 0;
136     mNoRtpTime = 0;
137     mSubtype = MEDIASUBTYPE_UNDEFINED;
138     mNodeState = kNodeStateRunning;
139     mPacketTimestamp = ImsMediaTimer::GetTimeInMilliSeconds();
140 #if defined(SIMULATION_LOSS) || defined(SIMULATION_DUPLICATE) || defined(SIMULATION_SSRC_CHANGE)
141     mPacketCounter = 1;
142 #endif
143     return RESULT_SUCCESS;
144 }
145 
Stop()146 void RtpDecoderNode::Stop()
147 {
148     IMLOGD1("[Stop] type[%d]", mMediaType);
149 
150     mReceivingSSRC = 0;
151 
152     if (mRtpSession)
153     {
154         mRtpSession->StopRtp();
155     }
156 
157     mNodeState = kNodeStateStopped;
158 }
159 
OnDataFromFrontNode(ImsMediaSubType subtype,uint8_t * data,uint32_t datasize,uint32_t timestamp,bool mark,uint32_t seq,ImsMediaSubType nDataType,uint32_t arrivalTime)160 void RtpDecoderNode::OnDataFromFrontNode(ImsMediaSubType subtype, uint8_t* data, uint32_t datasize,
161         uint32_t timestamp, bool mark, uint32_t seq, ImsMediaSubType nDataType,
162         uint32_t arrivalTime)
163 {
164     IMLOGD_PACKET8(IM_PACKET_LOG_RTP,
165             "[OnDataFromFrontNode] media[%d], subtype[%d] Size[%d], TS[%d], Mark[%d], Seq[%d], "
166             "datatype[%d], arrivalTime[%u]",
167             mMediaType, subtype, datasize, timestamp, mark, seq, nDataType, arrivalTime);
168 
169     mArrivalTime = arrivalTime;
170     // Check if the inter-arrival delay is large. It will be followed by burst.
171     uint64_t interArrivalDelay = arrivalTime - mPacketTimestamp;
172     mPacketTimestamp = arrivalTime;
173     if (interArrivalDelay > MAX_INTER_ARRIVAL_DELAY)
174     {
175         IMLOGD1("[RtpDecoderNode] Inter-arrival delay=%u msec", interArrivalDelay);
176     }
177 
178 #ifdef SIMULATION_DELAY
179     {
180         ImsMediaCondition condition;
181         uint32_t delay = ImsMediaTimer::GenerateRandom(DEBUG_JITTER_MAX_PACKET_INTERVAL);
182         mArrivalTime += delay;
183         condition.wait_timeout(delay);
184     }
185 #endif
186 
187 #if defined(SIMULATION_LOSS) || defined(SIMULATION_DUPLICATE) || defined(SIMULATION_SSRC_CHANGE)
188 #if defined(SIMULATION_LOSS) || defined(SIMULATION_DUPLICATE)
189     bool flag = false;
190 #endif
191 #ifdef SIMULATION_LOSS
192 
193     uint32_t seed = ImsMediaTimer::GenerateRandom(5);
194     if (mPacketCounter % DEBUG_JITTER_LOSS_PACKET_INTERVAL == 0 || seed % 5 == 0)
195     {
196         flag = true;
197     }
198 #endif
199 #ifdef SIMULATION_DUPLICATE
200     if ((mPacketCounter % DEBUG_JITTER_DUPLICATE_PACKET_INTERVAL) == 0)
201     {
202         flag = true;
203     }
204 #endif
205 #ifdef SIMULATION_SSRC_CHANGE
206     if (mPacketCounter == 1)
207     {
208         mTestSsrc = *reinterpret_cast<uint32_t*>(data + 8);
209         mTestSeq = 0;
210     }
211     else if (mPacketCounter % 15 == 0)
212     {
213         mTestSsrc += mPacketCounter;
214         mTestSeq += mPacketCounter;
215     }
216 
217     *reinterpret_cast<uint32_t*>(data + 8) = mTestSsrc;
218 #endif
219     mPacketCounter++;
220 #endif
221 #ifdef SIMULATION_REORDER
222     {
223         // add data to jitter gen buffer
224         DataEntry entry;
225         entry.subtype = MEDIASUBTYPE_RTPPACKET;
226         entry.pbBuffer = data;
227         entry.nBufferSize = datasize;
228         entry.nTimestamp = 0;
229         entry.bMark = 0;
230         entry.nSeqNum = 0;
231         entry.arrivalTime = arrivalTime;
232 
233         if (mReorderDataCount < DEBUG_JITTER_NORMAL)
234         {
235             jitterData.Add(&entry);
236         }
237         else if (mReorderDataCount < DEBUG_JITTER_NORMAL + DEBUG_JITTER_REORDER_MAX)
238         {
239             int32_t nCurrReorderSize;
240             int32_t nInsertPos;
241             uint32_t nCurrJitterBufferSize;
242             nCurrJitterBufferSize = jitterData.GetCount();
243 
244             if (DEBUG_JITTER_REORDER_MAX > DEBUG_JITTER_REORDER_MIN)
245             {
246                 nCurrReorderSize = mReorderDataCount - DEBUG_JITTER_NORMAL + 1 -
247                         ImsMediaTimer::GenerateRandom(
248                                 DEBUG_JITTER_REORDER_MAX - DEBUG_JITTER_REORDER_MIN + 1);
249             }
250             else
251             {
252                 nCurrReorderSize = mReorderDataCount - DEBUG_JITTER_NORMAL + 1;
253             }
254 
255             if (nCurrReorderSize > 0)
256             {
257                 nCurrReorderSize = ImsMediaTimer::GenerateRandom(nCurrReorderSize + 1);
258             }
259 
260             nInsertPos = nCurrJitterBufferSize - nCurrReorderSize;
261 
262             if (nInsertPos < 0)
263             {
264                 nInsertPos = 0;
265             }
266 
267             jitterData.InsertAt(nInsertPos, &entry);
268         }
269 
270         mReorderDataCount++;
271 
272         if (mReorderDataCount >= DEBUG_JITTER_NORMAL + DEBUG_JITTER_REORDER_MAX)
273         {
274             mReorderDataCount = 0;
275         }
276 
277         // send
278         while (jitterData.GetCount() >= DEBUG_JITTER_REORDER_MAX)
279         {
280             DataEntry* pEntry;
281 
282             if (jitterData.Get(&pEntry))
283             {
284 #ifdef SIMULATION_LOSS
285                 if (flag == false)
286                 {
287                     mRtpSession->ProcRtpPacket(pEntry->pbBuffer, pEntry->nBufferSize);
288                 }
289 #else
290 #ifdef SIMULATION_DUPLICATE
291                 if (flag == true)
292                 {
293                     mRtpSession->ProcRtpPacket(pEntry->pbBuffer, pEntry->nBufferSize);
294                 }
295 #endif
296                 mRtpSession->ProcRtpPacket(pEntry->pbBuffer, pEntry->nBufferSize);
297 #endif
298                 jitterData.Delete();
299             }
300         }
301     }
302 #else
303 #ifdef SIMULATION_LOSS
304     if (flag == false)
305     {
306         mRtpSession->ProcRtpPacket(data, datasize);
307     }
308 #else
309 #ifdef SIMULATION_DUPLICATE
310     if (flag == true)
311     {
312         mRtpSession->ProcRtpPacket(data, datasize);
313     }
314 #endif
315     mRtpSession->ProcRtpPacket(data, datasize);
316 #endif
317 #endif
318 }
319 
IsRunTime()320 bool RtpDecoderNode::IsRunTime()
321 {
322     return true;
323 }
324 
IsSourceNode()325 bool RtpDecoderNode::IsSourceNode()
326 {
327     return false;
328 }
329 
SetConfig(void * config)330 void RtpDecoderNode::SetConfig(void* config)
331 {
332     IMLOGD1("[SetConfig] type[%d]", mMediaType);
333 
334     if (config == nullptr)
335     {
336         return;
337     }
338 
339     if (mMediaType == IMS_MEDIA_AUDIO)
340     {
341         AudioConfig* pConfig = reinterpret_cast<AudioConfig*>(config);
342         mPeerAddress = RtpAddress(pConfig->getRemoteAddress().c_str(), pConfig->getRemotePort());
343         mSamplingRate = pConfig->getSamplingRateKHz();
344         mRtpPayloadTx = pConfig->getTxPayloadTypeNumber();
345         mRtpPayloadRx = pConfig->getRxPayloadTypeNumber();
346         mRtpTxDtmfPayload = pConfig->getTxDtmfPayloadTypeNumber();
347         mRtpRxDtmfPayload = pConfig->getRxDtmfPayloadTypeNumber();
348         mDtmfSamplingRate = pConfig->getDtmfsamplingRateKHz();
349     }
350     else if (mMediaType == IMS_MEDIA_VIDEO)
351     {
352         VideoConfig* pConfig = reinterpret_cast<VideoConfig*>(config);
353         mPeerAddress = RtpAddress(pConfig->getRemoteAddress().c_str(), pConfig->getRemotePort());
354         mSamplingRate = pConfig->getSamplingRateKHz();
355         mRtpPayloadTx = pConfig->getTxPayloadTypeNumber();
356         mRtpPayloadRx = pConfig->getRxPayloadTypeNumber();
357         mCvoValue = pConfig->getCvoValue();
358     }
359     else if (mMediaType == IMS_MEDIA_TEXT)
360     {
361         TextConfig* pConfig = reinterpret_cast<TextConfig*>(config);
362         mPeerAddress = RtpAddress(pConfig->getRemoteAddress().c_str(), pConfig->getRemotePort());
363         mSamplingRate = pConfig->getSamplingRateKHz();
364         mRtpPayloadTx = pConfig->getTxPayloadTypeNumber();
365         mRtpPayloadRx = pConfig->getRxPayloadTypeNumber();
366         mRedundantPayload = pConfig->getRedundantPayload();
367     }
368 
369     IMLOGD2("[SetConfig] peer Ip[%s], port[%d]", mPeerAddress.ipAddress, mPeerAddress.port);
370 }
371 
IsSameConfig(void * config)372 bool RtpDecoderNode::IsSameConfig(void* config)
373 {
374     if (config == nullptr)
375     {
376         return true;
377     }
378 
379     if (mMediaType == IMS_MEDIA_AUDIO)
380     {
381         AudioConfig* pConfig = reinterpret_cast<AudioConfig*>(config);
382         return (mPeerAddress ==
383                         RtpAddress(pConfig->getRemoteAddress().c_str(), pConfig->getRemotePort()) &&
384                 mSamplingRate == pConfig->getSamplingRateKHz() &&
385                 mRtpPayloadTx == pConfig->getTxPayloadTypeNumber() &&
386                 mRtpPayloadRx == pConfig->getRxPayloadTypeNumber() &&
387                 mRtpTxDtmfPayload == pConfig->getTxDtmfPayloadTypeNumber() &&
388                 mRtpRxDtmfPayload == pConfig->getRxDtmfPayloadTypeNumber() &&
389                 mDtmfSamplingRate == pConfig->getDtmfsamplingRateKHz());
390     }
391     else if (mMediaType == IMS_MEDIA_VIDEO)
392     {
393         VideoConfig* pConfig = reinterpret_cast<VideoConfig*>(config);
394         return (mPeerAddress ==
395                         RtpAddress(pConfig->getRemoteAddress().c_str(), pConfig->getRemotePort()) &&
396                 mSamplingRate == pConfig->getSamplingRateKHz() &&
397                 mRtpPayloadTx == pConfig->getTxPayloadTypeNumber() &&
398                 mRtpPayloadRx == pConfig->getRxPayloadTypeNumber() &&
399                 mCvoValue == pConfig->getCvoValue());
400     }
401     else if (mMediaType == IMS_MEDIA_TEXT)
402     {
403         TextConfig* pConfig = reinterpret_cast<TextConfig*>(config);
404         return (mPeerAddress ==
405                         RtpAddress(pConfig->getRemoteAddress().c_str(), pConfig->getRemotePort()) &&
406                 mSamplingRate == pConfig->getSamplingRateKHz() &&
407                 mRtpPayloadTx == pConfig->getTxPayloadTypeNumber() &&
408                 mRtpPayloadRx == pConfig->getRxPayloadTypeNumber() &&
409                 mRedundantPayload == pConfig->getRedundantPayload());
410     }
411 
412     return false;
413 }
414 
OnMediaDataInd(unsigned char * data,uint32_t datasize,uint32_t timestamp,bool mark,uint16_t seq,uint32_t payloadType,uint32_t ssrc,const RtpHeaderExtensionInfo & extensionInfo)415 void RtpDecoderNode::OnMediaDataInd(unsigned char* data, uint32_t datasize, uint32_t timestamp,
416         bool mark, uint16_t seq, uint32_t payloadType, uint32_t ssrc,
417         const RtpHeaderExtensionInfo& extensionInfo)
418 {
419     IMLOGD_PACKET8(IM_PACKET_LOG_RTP,
420             "[OnMediaDataInd] media[%d] size[%d], TS[%d], mark[%d], seq[%d], payloadType[%d] "
421             "sampling[%d], extensionSize[%d]",
422             mMediaType, datasize, timestamp, mark, seq, payloadType, mSamplingRate,
423             extensionInfo.length);
424 
425     if (mMediaType == IMS_MEDIA_AUDIO && mRtpPayloadRx != payloadType &&
426             mRtpPayloadTx != payloadType && payloadType != mRtpRxDtmfPayload &&
427             payloadType != mRtpTxDtmfPayload)
428     {
429         IMLOGE1("[OnMediaDataInd] media[%d] invalid frame", mMediaType);
430         return;
431     }
432 
433     // no need to change to timestamp to milliseconds unit in audio or text packet
434     if (mMediaType != IMS_MEDIA_VIDEO && mSamplingRate != 0)
435     {
436         timestamp = timestamp / (mSamplingRate);
437     }
438 
439     if (mReceivingSSRC != ssrc)
440     {
441         IMLOGI3("[OnMediaDataInd] media[%d] SSRC changed, [%x] -> [%x]", mMediaType, mReceivingSSRC,
442                 ssrc);
443         mReceivingSSRC = ssrc;
444         SendDataToRearNode(MEDIASUBTYPE_REFRESHED, nullptr, mReceivingSSRC, 0, 0, 0,
445                 MEDIASUBTYPE_UNDEFINED, mArrivalTime);
446     }
447 
448     if (mMediaType == IMS_MEDIA_AUDIO &&
449             (payloadType == mRtpRxDtmfPayload || payloadType == mRtpTxDtmfPayload) && datasize >= 4)
450     {
451         processDtmf(data);
452         return;
453     }
454 
455     if (extensionInfo.length > 0 && mMediaType == IMS_MEDIA_AUDIO)
456     {
457         std::list<RtpHeaderExtension>* extensions = DecodeRtpHeaderExtension(extensionInfo);
458 
459         if (mCallback != nullptr && extensions != nullptr)
460         {
461             mCallback->SendEvent(
462                     kImsMediaEventHeaderExtensionReceived, reinterpret_cast<uint64_t>(extensions));
463         }
464     }
465 
466     if (extensionInfo.extensionData != nullptr && extensionInfo.extensionDataSize >= 2 &&
467             mMediaType == IMS_MEDIA_VIDEO && mCvoValue != CVO_DEFINE_NONE)
468     {
469         uint16_t extensionId = extensionInfo.extensionData[0] >> 4;
470 
471         if (extensionId == mCvoValue)
472         {
473             // 0: Front-facing camera, 1: Back-facing camera
474             uint16_t cameraId = extensionInfo.extensionData[1] >> 3;
475             uint16_t rotation = extensionInfo.extensionData[1] & 0x07;
476 
477             switch (rotation)
478             {
479                 case 0:  // No rotation (Rotated 0CW/CCW = To rotate 0CW/CCW)
480                 case 4:  // + Horizontal Flip, but it's treated as same as above
481                     mSubtype = MEDIASUBTYPE_ROT0;
482                     break;
483                 case 1:  // Rotated 270CW(90CCW) = To rotate 90CW(270CCW)
484                 case 5:  // + Horizontal Flip, but it's treated as same as above
485                     mSubtype = MEDIASUBTYPE_ROT90;
486                     break;
487                 case 2:  // Rotated 180CW = To rotate 180CW
488                 case 6:  // + Horizontal Flip, but it's treated as same as above
489                     mSubtype = MEDIASUBTYPE_ROT180;
490                     break;
491                 case 3:  // Rotated 90CW(270CCW) = To rotate 270CW(90CCW)
492                 case 7:  // + Horizontal Flip, but it's treated as same as above
493                     mSubtype = MEDIASUBTYPE_ROT270;
494                     break;
495                 default:
496                     break;
497             }
498 
499             IMLOGD4("[OnMediaDataInd] extensionId[%d], cameraId[%d], rotation[%d], subtype[%d]",
500                     extensionId, cameraId, rotation, mSubtype);
501         }
502     }
503 
504     if (mMediaType == IMS_MEDIA_TEXT)
505     {
506         if (payloadType == mRtpPayloadTx)
507         {
508             if (mRedundantPayload == 0)
509             {
510                 mSubtype = MEDIASUBTYPE_BITSTREAM_T140;
511             }
512             else
513             {
514                 mSubtype = MEDIASUBTYPE_BITSTREAM_T140_RED;
515             }
516         }
517         else if (payloadType == mRedundantPayload)
518         {
519             mSubtype = MEDIASUBTYPE_BITSTREAM_T140;
520         }
521         else
522         {
523             IMLOGI2("[OnMediaDataInd] media[%d] INVALID payload[%d] is received", mMediaType,
524                     payloadType);
525         }
526     }
527 
528 #ifdef SIMULATION_SSRC_CHANGE
529     seq += mTestSeq;
530 #endif
531     SendDataToRearNode(
532             mSubtype, data, datasize, timestamp, mark, seq, MEDIASUBTYPE_UNDEFINED, mArrivalTime);
533 }
534 
OnNumReceivedPacket(uint32_t nNumRtpPacket)535 void RtpDecoderNode::OnNumReceivedPacket(uint32_t nNumRtpPacket)
536 {
537     IMLOGD_PACKET2(IM_PACKET_LOG_RTP, "[OnNumReceivedPacket] InactivityTime[%d], numRtp[%d]",
538             mInactivityTime, nNumRtpPacket);
539 
540     if (nNumRtpPacket == 0)
541     {
542         mNoRtpTime++;
543     }
544     else
545     {
546         mNoRtpTime = 0;
547     }
548 
549     if (mInactivityTime != 0 && mNoRtpTime == mInactivityTime)
550     {
551         if (mCallback != nullptr)
552         {
553             mCallback->SendEvent(kImsMediaEventMediaInactivity, kProtocolRtp, mInactivityTime);
554         }
555     }
556 }
557 
SetLocalAddress(const RtpAddress & address)558 void RtpDecoderNode::SetLocalAddress(const RtpAddress& address)
559 {
560     mLocalAddress = address;
561 }
562 
SetPeerAddress(const RtpAddress & address)563 void RtpDecoderNode::SetPeerAddress(const RtpAddress& address)
564 {
565     mPeerAddress = address;
566 }
567 
SetInactivityTimerSec(const uint32_t time)568 void RtpDecoderNode::SetInactivityTimerSec(const uint32_t time)
569 {
570     IMLOGD2("[SetInactivityTimerSec] media[%d], time[%d] reset", mMediaType, time);
571     mInactivityTime = time;
572     mNoRtpTime = 0;
573 }
574 
processDtmf(uint8_t * data)575 void RtpDecoderNode::processDtmf(uint8_t* data)
576 {
577     /** dtmf event payload format
578      *  0                   1                   2                   3
579      *  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
580      * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
581      * |     event     |E|R| volume    |          duration             |
582      * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
583      */
584 
585     // check end bit and send event once per event
586     if (data[1] & 0x80)
587     {
588         if (mDtmfEndBit)
589         {
590             uint8_t digit = data[0];
591             int32_t duration = data[2];
592             mSamplingRate != 0 ? duration = ((duration << 8) | data[3]) / mSamplingRate
593                                : 0;  // convert milliseconds
594 
595             IMLOGD2("[processDtmf] dtmf received, digit[%d], duration[%d]", digit, duration);
596 
597             mCallback->SendEvent(kAudioDtmfReceivedInd, digit, duration);
598             mDtmfEndBit = false;
599         }
600     }
601     else
602     {
603         // mark true when the new event started
604         mDtmfEndBit = true;
605     }
606 }
607 
DecodeRtpHeaderExtension(const RtpHeaderExtensionInfo & extensionInfo)608 std::list<RtpHeaderExtension>* RtpDecoderNode::DecodeRtpHeaderExtension(
609         const RtpHeaderExtensionInfo& extensionInfo)
610 {
611     if (extensionInfo.length == 0 || extensionInfo.extensionData == nullptr ||
612             extensionInfo.extensionDataSize == 0)
613     {
614         return nullptr;
615     }
616 
617     std::list<RtpHeaderExtension>* extensions = new std::list<RtpHeaderExtension>();
618 
619     // header
620     bool useTwoByteHeader =
621             (extensionInfo.definedByProfile == RtpHeaderExtensionInfo::kBitPatternForTwoByteHeader);
622     uint32_t length = extensionInfo.length;  // word size
623     IMLOGD2("[DecodeRtpHeaderExtension] twoByteHeader[%d], len[%d]", useTwoByteHeader, length);
624 
625     uint32_t offset = 0;
626     int32_t remainingSize = extensionInfo.extensionDataSize;
627 
628     while (remainingSize > 0)
629     {
630         RtpHeaderExtension extension;
631 
632         if (useTwoByteHeader)
633         {
634             // header
635             extension.setLocalIdentifier(extensionInfo.extensionData[offset++]);
636             int8_t dataSize = extensionInfo.extensionData[offset++];  // add header
637 
638             // payload
639             if (dataSize > 0)
640             {
641                 extension.setExtensionData(
642                         reinterpret_cast<const uint8_t*>(extensionInfo.extensionData + offset),
643                         dataSize);
644             }
645 
646             offset += dataSize;
647             remainingSize -= (dataSize + 2);  // remove two byte header too
648         }
649         else  // one byte header
650         {
651             // header
652             extension.setLocalIdentifier(extensionInfo.extensionData[offset] >> 4);
653             int8_t dataSize = (extensionInfo.extensionData[offset] & 0x0F) + 1;  // data + header
654             offset++;
655 
656             // payload
657             if (dataSize > 0)
658             {
659                 extension.setExtensionData(
660                         reinterpret_cast<const uint8_t*>(extensionInfo.extensionData + offset),
661                         dataSize);
662             }
663 
664             offset += dataSize;
665             remainingSize -= (dataSize + 1);  // remove one byte header too
666         }
667 
668         extensions->push_back(extension);
669 
670         while (remainingSize > 0 && extensionInfo.extensionData[offset] == 0x00)  // ignore padding
671         {
672             offset++;
673             remainingSize--;
674         }
675     }
676 
677     return extensions;
678 }