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