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 }