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 <AudioRtpPayloadEncoderNode.h>
18 #include <ImsMediaAudioUtil.h>
19 #include <ImsMediaTrace.h>
20 #include <AudioConfig.h>
21 #include <EvsParams.h>
22
AudioRtpPayloadEncoderNode(BaseSessionCallback * callback)23 AudioRtpPayloadEncoderNode::AudioRtpPayloadEncoderNode(BaseSessionCallback* callback) :
24 BaseNode(callback)
25 {
26 mCodecType = 0;
27 mOctetAligned = false;
28 mPtime = 0;
29 memset(mPayload, 0, sizeof(mPayload));
30 mFirstFrame = false;
31 mTimestamp = 0;
32 mMaxNumOfFrame = 0;
33 mCurrNumOfFrame = 0;
34 mCurrFramePos = 0;
35 mTotalPayloadSize = 0;
36 mEvsBandwidth = kEvsBandwidthNone;
37 mEvsCodecMode = kEvsCodecModePrimary;
38 mEvsOffset = 0;
39 mSendCMR = 0;
40 mEvsMode = kEvsAmrIoModeBitrate00660;
41 mCoreEvsMode = 0;
42 mEvsPayloadHeaderMode = kRtpPyaloadHeaderModeEvsCompact;
43 }
44
~AudioRtpPayloadEncoderNode()45 AudioRtpPayloadEncoderNode::~AudioRtpPayloadEncoderNode() {}
46
GetNodeId()47 kBaseNodeId AudioRtpPayloadEncoderNode::GetNodeId()
48 {
49 return kNodeIdAudioPayloadEncoder;
50 }
51
Start()52 ImsMediaResult AudioRtpPayloadEncoderNode::Start()
53 {
54 mMaxNumOfFrame = mPtime / 20;
55 mEvsMode = (kEvsBitrate)ImsMediaAudioUtil::GetMaximumEvsMode(mCoreEvsMode);
56 mEvsCodecMode = (kEvsCodecMode)ImsMediaAudioUtil::ConvertEvsCodecMode(mEvsMode);
57
58 IMLOGD5("[Start] codecType[%d], mode[%d], num of frames[%d], evs bitrate[%d], evs mode[%d]",
59 mCodecType, mOctetAligned, mMaxNumOfFrame, mEvsMode, mEvsCodecMode);
60
61 if (mMaxNumOfFrame == 0 || mMaxNumOfFrame > MAX_FRAME_IN_PACKET)
62 {
63 IMLOGE1("[Start] Invalid ptime [%d]", mPtime);
64 return RESULT_INVALID_PARAM;
65 }
66
67 mCurrNumOfFrame = 0;
68 mCurrFramePos = 0;
69 mFirstFrame = true;
70 mTotalPayloadSize = 0;
71 mNodeState = kNodeStateRunning;
72 return RESULT_SUCCESS;
73 }
74
Stop()75 void AudioRtpPayloadEncoderNode::Stop()
76 {
77 IMLOGD0("[Stop]");
78 mNodeState = kNodeStateStopped;
79 }
80
IsRunTime()81 bool AudioRtpPayloadEncoderNode::IsRunTime()
82 {
83 return true;
84 }
85
IsSourceNode()86 bool AudioRtpPayloadEncoderNode::IsSourceNode()
87 {
88 return false;
89 }
90
OnDataFromFrontNode(ImsMediaSubType,uint8_t * pData,uint32_t nDataSize,uint32_t nTimestamp,bool bMark,uint32_t nSeqNum,ImsMediaSubType nDataType,uint32_t arrivalTime)91 void AudioRtpPayloadEncoderNode::OnDataFromFrontNode(ImsMediaSubType /*subtype*/, uint8_t* pData,
92 uint32_t nDataSize, uint32_t nTimestamp, bool bMark, uint32_t nSeqNum,
93 ImsMediaSubType nDataType, uint32_t arrivalTime)
94 {
95 switch (mCodecType)
96 {
97 case kAudioCodecAmr:
98 case kAudioCodecAmrWb:
99 EncodePayloadAmr(pData, nDataSize, nTimestamp);
100 break;
101 case kAudioCodecPcmu:
102 case kAudioCodecPcma:
103 SendDataToRearNode(MEDIASUBTYPE_RTPPAYLOAD, pData, nDataSize, nTimestamp, bMark,
104 nSeqNum, nDataType, arrivalTime);
105 break;
106 case kAudioCodecEvs:
107 EncodePayloadEvs(pData, nDataSize, nTimestamp);
108 break;
109 default:
110 IMLOGE1("[OnDataFromFrontNode] invalid codec type[%d]", mCodecType);
111 SendDataToRearNode(MEDIASUBTYPE_RTPPAYLOAD, pData, nDataSize, nTimestamp, bMark,
112 nSeqNum, nDataType, arrivalTime);
113 break;
114 }
115 }
116
SetConfig(void * config)117 void AudioRtpPayloadEncoderNode::SetConfig(void* config)
118 {
119 AudioConfig* pConfig = reinterpret_cast<AudioConfig*>(config);
120
121 if (pConfig != nullptr)
122 {
123 mCodecType = ImsMediaAudioUtil::ConvertCodecType(pConfig->getCodecType());
124 if (mCodecType == kAudioCodecAmr || mCodecType == kAudioCodecAmrWb)
125 {
126 mOctetAligned = pConfig->getAmrParams().getOctetAligned();
127 }
128 else if (mCodecType == kAudioCodecEvs)
129 {
130 mEvsBandwidth = (kEvsBandwidth)pConfig->getEvsParams().getEvsBandwidth();
131 mEvsPayloadHeaderMode =
132 (kRtpPyaloadHeaderMode)pConfig->getEvsParams().getUseHeaderFullOnly();
133 mCoreEvsMode = pConfig->getEvsParams().getEvsMode();
134 mEvsOffset = pConfig->getEvsParams().getChannelAwareMode();
135 mSendCMR = pConfig->getEvsParams().getCodecModeRequest();
136 }
137
138 mPtime = pConfig->getPtimeMillis();
139 }
140 }
141
IsSameConfig(void * config)142 bool AudioRtpPayloadEncoderNode::IsSameConfig(void* config)
143 {
144 if (config == nullptr)
145 return true;
146 AudioConfig* pConfig = reinterpret_cast<AudioConfig*>(config);
147
148 if (mCodecType == ImsMediaAudioUtil::ConvertCodecType(pConfig->getCodecType()))
149 {
150 if (mCodecType == kAudioCodecAmr || mCodecType == kAudioCodecAmrWb)
151 {
152 return (mOctetAligned == pConfig->getAmrParams().getOctetAligned());
153 }
154 else if (mCodecType == kAudioCodecEvs)
155 {
156 return (mEvsBandwidth == (kEvsBandwidth)pConfig->getEvsParams().getEvsBandwidth() &&
157 mEvsPayloadHeaderMode ==
158 (kRtpPyaloadHeaderMode)pConfig->getEvsParams().getUseHeaderFullOnly() &&
159 mCoreEvsMode ==
160 ImsMediaAudioUtil::GetMaximumEvsMode(
161 pConfig->getEvsParams().getEvsMode()) &&
162 mEvsOffset == pConfig->getEvsParams().getChannelAwareMode());
163 }
164 }
165
166 return false;
167 }
168
EncodePayloadAmr(uint8_t * pData,uint32_t nDataSize,uint32_t nTimestamp)169 void AudioRtpPayloadEncoderNode::EncodePayloadAmr(
170 uint8_t* pData, uint32_t nDataSize, uint32_t nTimestamp)
171 {
172 uint32_t nCmr = 15;
173 uint32_t f, ft, q, nDataBitSize;
174
175 // remove TOC from the encoder
176 pData++;
177 nDataSize -= 1;
178
179 if (nDataSize > 4)
180 {
181 IMLOGD_PACKET5(IM_PACKET_LOG_PH, "[EncodePayloadAmr] src = %02X %02X %02X %02X, len[%d]",
182 pData[0], pData[1], pData[2], pData[3], nDataSize);
183 }
184
185 IMLOGD_PACKET2(IM_PACKET_LOG_PH, "[EncodePayloadAmr] codectype[%d], octetAligned[%d]",
186 mCodecType, mOctetAligned);
187
188 mCurrNumOfFrame++;
189 f = (mCurrNumOfFrame == mMaxNumOfFrame) ? 0 : 1;
190
191 if (mCodecType == kAudioCodecAmr)
192 {
193 nCmr = 0x0F;
194 ft = ImsMediaAudioUtil::ConvertLenToAmrMode(nDataSize);
195 nDataBitSize = ImsMediaAudioUtil::ConvertAmrModeToBitLen(ft);
196 }
197 else
198 {
199 nCmr = 0x0F;
200 ft = ImsMediaAudioUtil::ConvertLenToAmrWbMode(nDataSize);
201 nDataBitSize = ImsMediaAudioUtil::ConvertAmrWbModeToBitLen(ft);
202 }
203
204 q = 1;
205
206 // the first paylaod
207 if (mCurrNumOfFrame == 1)
208 {
209 memset(mPayload, 0, MAX_AUDIO_PAYLOAD_SIZE);
210 mBWHeader.SetBuffer(mPayload, MAX_AUDIO_PAYLOAD_SIZE);
211 mBWPayload.SetBuffer(mPayload, MAX_AUDIO_PAYLOAD_SIZE);
212 mBWHeader.Write(nCmr, 4);
213
214 if (mOctetAligned == true)
215 {
216 mBWHeader.Write(0, 4);
217 mBWPayload.Seek(8 + mMaxNumOfFrame * 8);
218 }
219 else
220 {
221 mBWPayload.Seek(4 + mMaxNumOfFrame * 6);
222 }
223
224 mTimestamp = nTimestamp;
225 }
226
227 // Payload ToC
228 mBWHeader.Write(f, 1);
229 mBWHeader.Write(ft, 4);
230 mBWHeader.Write(q, 1);
231
232 if (mOctetAligned == true)
233 {
234 mBWHeader.AddPadding();
235 }
236
237 IMLOGD_PACKET2(IM_PACKET_LOG_PH, "[EncodePayloadAmr] nDataBitSize[%d], nDataSize[%d]",
238 nDataBitSize, nDataSize);
239
240 // Speech Frame
241 mBWPayload.WriteByteBuffer(pData, nDataBitSize);
242
243 if (mOctetAligned == true)
244 {
245 mBWPayload.AddPadding();
246 }
247
248 mTotalPayloadSize += nDataSize;
249
250 if (mCurrNumOfFrame == mMaxNumOfFrame)
251 {
252 mBWHeader.Flush();
253 mBWPayload.AddPadding();
254 mBWPayload.Flush();
255 uint32_t nTotalSize = mBWPayload.GetBufferSize();
256
257 IMLOGD_PACKET7(IM_PACKET_LOG_PH,
258 "[EncodePayloadAmr] result = %02X %02X %02X %02X %02X %02X, len[%d]", mPayload[0],
259 mPayload[1], mPayload[2], mPayload[3], mPayload[4], mPayload[5], nTotalSize);
260
261 if (mTotalPayloadSize > 0)
262 {
263 SendDataToRearNode(
264 MEDIASUBTYPE_RTPPAYLOAD, mPayload, nTotalSize, mTimestamp, mFirstFrame, 0);
265 }
266
267 mCurrNumOfFrame = 0;
268 mTotalPayloadSize = 0;
269
270 if (mFirstFrame)
271 {
272 mFirstFrame = false;
273 }
274 }
275 }
276
EncodePayloadEvs(uint8_t * pData,uint32_t nDataSize,uint32_t nTimeStamp)277 void AudioRtpPayloadEncoderNode::EncodePayloadEvs(
278 uint8_t* pData, uint32_t nDataSize, uint32_t nTimeStamp)
279 {
280 if (nDataSize == 0)
281 {
282 return;
283 }
284
285 uint32_t nFrameType = 0;
286 // compact or header-full format, default is compact formats
287 // primary or amr-wb io mode, default is primary mode
288 // primary or amr-wb io mode base on frameSize.
289 mCurrNumOfFrame++;
290
291 if (mEvsPayloadHeaderMode == kRtpPyaloadHeaderModeEvsCompact)
292 {
293 memset(mPayload, 0, MAX_AUDIO_PAYLOAD_SIZE);
294 mBWHeader.SetBuffer(mPayload, MAX_AUDIO_PAYLOAD_SIZE);
295 mBWPayload.SetBuffer(mPayload, MAX_AUDIO_PAYLOAD_SIZE);
296
297 mTimestamp = nTimeStamp;
298 // exactly one coded frame without any additional EVS RTP payload header
299 if (mEvsCodecMode == kEvsCodecModePrimary)
300 {
301 // calculate nDataBitSize from nDataSize
302 nFrameType = (uint32_t)ImsMediaAudioUtil::ConvertLenToEVSAudioMode(nDataSize);
303 uint32_t nDataBitSize =
304 ImsMediaAudioUtil::ConvertEVSAudioModeToBitLen((kImsAudioEvsMode)nFrameType);
305
306 if (nDataBitSize == 0)
307 {
308 return;
309 }
310
311 // special case, EVS Primary 2.8 kbps frame in Compact format
312 if (nFrameType == 0)
313 {
314 // First data bit d(0) of the EVS Primary 2.8 kbps is always set to '0'
315 pData[0] = pData[0] & 0x7f;
316 }
317
318 // write speech Frame
319 mBWPayload.WriteByteBuffer(pData, nDataBitSize);
320 mTotalPayloadSize += nDataSize;
321
322 mBWHeader.AddPadding();
323 mBWHeader.Flush();
324
325 mBWPayload.AddPadding();
326 mBWPayload.Flush();
327
328 uint32_t nTotalSize = mBWPayload.GetBufferSize();
329
330 IMLOGD_PACKET7(IM_PACKET_LOG_PH, "[EncodePayloadEvs] result =\
331 %02X %02X %02X %02X %02X %02X, len[%d]",
332 mPayload[0], mPayload[1], mPayload[2], mPayload[3], mPayload[4], mPayload[5],
333 nTotalSize);
334
335 if (mTotalPayloadSize > 0)
336 {
337 SendDataToRearNode(
338 MEDIASUBTYPE_RTPPAYLOAD, mPayload, nTotalSize, mTimestamp, mFirstFrame, 0);
339 }
340
341 mCurrNumOfFrame = 0;
342 mTotalPayloadSize = 0;
343 if (mFirstFrame)
344 mFirstFrame = false;
345 }
346 // one 3-bit CMR field, one coded frame, and zero-padding bits if necessary
347 else if (mEvsCodecMode == kEvsCodecModeAmrIo)
348 {
349 // calculate nDataBitSize from nDataSize
350 nFrameType = (uint32_t)ImsMediaAudioUtil::ConvertLenToAmrWbMode(nDataSize);
351 uint32_t nDataBitSize = ImsMediaAudioUtil::ConvertAmrWbModeToBitLen(nFrameType);
352
353 // 0: 6.6, 1: 8.85, 2: 12.65, 3: 15.85, 4: 18.25, 5: 23.05, 6: 23.85, 7: none
354 // 0111(7) is no request.
355 uint32_t nCmr = 0x07;
356
357 // write CMR except SID
358 // at EVS AMR WB IO Mode, SID packet does not include cmr field...and no processing
359 if (nFrameType != kImsAudioAmrWbModeSID)
360 {
361 mBWHeader.Write(nCmr, 3);
362 mBWPayload.Seek(3);
363
364 // append a speech data bit(0) after the last speech data bit
365 uint8_t nDataBit0 = 0;
366 uint32_t i = 0;
367 uint32_t remain = 0;
368
369 nDataBit0 = pData[0] >> 7;
370 for (i = 0; i < (nDataSize - 1); i++)
371 {
372 pData[i] = pData[i] << 1;
373 pData[i] = pData[i] + (pData[i + 1] >> 7);
374 }
375
376 // set the last speech data byte
377 remain = nDataBitSize % 8;
378 if (remain == 0)
379 remain = 8;
380 pData[nDataSize - 1] = pData[nDataSize - 1] << 1;
381 nDataBit0 = nDataBit0 << (8 - remain);
382 pData[nDataSize - 1] = pData[nDataSize - 1] + nDataBit0;
383 }
384 else // kImsAudioAmrWbModeSID case
385 {
386 // EVS amr io mode's SID is used HF format.
387 // set cmr
388 nCmr = 0xff; // no request - 0xff
389 mBWHeader.Write(nCmr, 8);
390 mBWPayload.Seek(8);
391
392 // set ToC
393 // Header Type identification bit(1bit) - always set to 0
394 uint32_t toc_h = 0;
395 // (1bit - always set to 0 in compact AMR WB IO mode)
396 uint32_t toc_f = 0;
397 // 1 1 1001 - EVS AMR IO Mode, Q bit set 1, 1001 indicate SID packet
398 uint32_t ft = 0x39;
399
400 mBWHeader.Write(toc_h, 1);
401 mBWHeader.Write(toc_f, 1);
402 mBWHeader.Write(ft, 6);
403 mBWPayload.Seek(8);
404 }
405
406 // write speech Frame
407 mBWPayload.WriteByteBuffer(pData, nDataBitSize);
408 mTotalPayloadSize += nDataSize;
409
410 mBWHeader.Flush();
411
412 mBWPayload.AddPadding();
413 mBWPayload.Flush();
414
415 uint32_t nTotalSize = mBWPayload.GetBufferSize();
416
417 IMLOGD_PACKET7(IM_PACKET_LOG_PH,
418 "[EncodePayloadEvs] Result = %02X %02X %02X %02X %02X %02X, len[%d]",
419 mPayload[0], mPayload[1], mPayload[2], mPayload[3], mPayload[4], mPayload[5],
420 nTotalSize);
421
422 if (mTotalPayloadSize > 0)
423 {
424 SendDataToRearNode(
425 MEDIASUBTYPE_RTPPAYLOAD, mPayload, nTotalSize, mTimestamp, mFirstFrame, 0);
426 }
427
428 mCurrNumOfFrame = 0;
429 mTotalPayloadSize = 0;
430 if (mFirstFrame)
431 mFirstFrame = false;
432 }
433 else
434 {
435 IMLOGE0("[EncodePayloadEvs] Invalid codec mode");
436 return;
437 }
438 }
439 else if (mEvsPayloadHeaderMode == kRtpPyaloadHeaderModeEvsHeaderFull)
440 {
441 // 0111 1111 is no request.
442 uint32_t nEVSBW = 0x07;
443 uint32_t nEVSBR = 0x0f;
444
445 uint32_t cmr_h, cmr_t, cmr_d = 0; // CMR byte
446 memset(mPayload, 0, MAX_AUDIO_PAYLOAD_SIZE);
447 mBWHeader.SetBuffer(mPayload, MAX_AUDIO_PAYLOAD_SIZE);
448 mBWPayload.SetBuffer(mPayload, MAX_AUDIO_PAYLOAD_SIZE);
449
450 if (mEvsCodecMode == kEvsCodecModePrimary)
451 {
452 if (nFrameType == kImsAudioEvsPrimaryModeSID || mSendCMR) // CMR value
453 {
454 // Header Type identification bit(1bit) - always set to 1
455 cmr_h = 1;
456 // Type of Request(3bits) - NB(000), IO(001), FB(100), WB(101), SWB(110)
457 cmr_t = nEVSBW;
458 // codec mode request(4bits)
459 cmr_d = nEVSBR;
460 }
461
462 // set ToC byte
463 uint32_t toc_h = 0; // Header Type identification bit(1bit) - always set to 0
464 uint32_t toc_f = (mCurrNumOfFrame == mMaxNumOfFrame) ? 0 : 1; // (1bit)
465 uint32_t toc_ft_m = 0; // EVS mode(1bit), Primary mode is 0
466 uint32_t toc_ft_q = 0; // Q bit(1bit) - zero for kEvsCodecModePrimary
467 uint32_t toc_ft_b =
468 ImsMediaAudioUtil::ConvertLenToEVSAudioMode(nDataSize); // EVS bit rate(4bits)
469 uint32_t nDataBitSize =
470 ImsMediaAudioUtil::ConvertEVSAudioModeToBitLen((kImsAudioEvsMode)toc_ft_b);
471
472 // write CMR and seek the position of the first paylaod
473 if (mCurrNumOfFrame == 1)
474 {
475 // set CMR byte - it's optional field...
476 if (nFrameType == kImsAudioEvsPrimaryModeSID || mSendCMR)
477 {
478 // check writing CMR or not
479 // write CMR byte
480 mBWHeader.Write(cmr_h, 1);
481 mBWHeader.Write(cmr_t, 3);
482 mBWHeader.Write(cmr_d, 4);
483
484 mBWPayload.Seek(8);
485 }
486
487 // ToC field.
488 mBWPayload.Seek(mMaxNumOfFrame * 8); // jump ToC bytes
489 mTimestamp = nTimeStamp; // set timestamp as the first frame
490 }
491
492 // write ToC
493 mBWHeader.Write(toc_h, 1);
494 mBWHeader.Write(toc_f, 1);
495 mBWHeader.Write(toc_ft_m, 1);
496 mBWHeader.Write(toc_ft_q, 1);
497 mBWHeader.Write(toc_ft_b, 4);
498
499 // write Speech Frame
500 mBWPayload.WriteByteBuffer(pData, nDataBitSize);
501 mBWPayload.AddPadding();
502
503 mTotalPayloadSize += nDataSize;
504
505 if (mCurrNumOfFrame == mMaxNumOfFrame)
506 {
507 // mBWHeader.AddPadding();
508 mBWHeader.Flush();
509
510 mBWPayload.AddPadding();
511 mBWPayload.Flush();
512
513 uint32_t nTotalSize = mBWPayload.GetBufferSize();
514 IMLOGD_PACKET7(IM_PACKET_LOG_PH,
515 "[EncodePayloadEvs] Result = %02X %02X %02X %02X %02X %02X, len[%d]",
516 mPayload[0], mPayload[1], mPayload[2], mPayload[3], mPayload[4],
517 mPayload[5], nTotalSize);
518
519 if (mTotalPayloadSize > 0)
520 {
521 SendDataToRearNode(MEDIASUBTYPE_RTPPAYLOAD, mPayload,
522 CheckPaddingNecessity(nTotalSize), mTimestamp, mFirstFrame, 0);
523 }
524
525 mCurrNumOfFrame = 0;
526 mTotalPayloadSize = 0;
527 if (mFirstFrame)
528 mFirstFrame = false;
529 }
530 }
531 else if (mEvsCodecMode == kEvsCodecModeAmrIo)
532 {
533 // set CMR byte
534 // at EVS AMR WB IO Mode, CMR field shall include.
535 // Header Type identification bit(1bit) - always set to 1
536 cmr_h = 1;
537 /* Type of Request(3bits) - NB(000), IO(001), WB(010), SWB(011), FB(100), WB 13.2
538 * channel-aware(101), SWB 13.2 channel-aware(110), reserved(111) */
539 cmr_t = nEVSBW;
540 // codec mode request(4bits) 1111 is no request.
541 cmr_d = nEVSBR;
542
543 // set ToC byte
544 // Header Type identification bit(1bit) - always set to 0
545 uint32_t toc_h = 0;
546 // (1bit)
547 uint32_t toc_f = (mCurrNumOfFrame == mMaxNumOfFrame) ? 0 : 1;
548 // EVS mode(1bit), AMR-WB IO mode is 1
549 uint32_t toc_ft_m = 1;
550 // Q bit(1bit) - 1 for AMR_WB_IO
551 // for ORG EVS to avoid the issue -#EURAVOLTE-567
552 uint32_t toc_ft_q = 1;
553 // EVS AMR WB IO bit rate(4bits)
554 uint32_t toc_ft_b = (uint32_t)ImsMediaAudioUtil::ConvertLenToAmrWbMode(nDataSize);
555 uint32_t nDataBitSize = ImsMediaAudioUtil::ConvertAmrWbModeToBitLen(toc_ft_b);
556
557 // write CMR and seek the position of the first paylaod
558 if (mCurrNumOfFrame == 1)
559 {
560 // write CMR byte
561 mBWHeader.Write(cmr_h, 1);
562 mBWHeader.Write(cmr_t, 3);
563 mBWHeader.Write(cmr_d, 4);
564
565 // seek the position of the first paylaod
566 // add speech data after CMR and ToC
567 mBWPayload.Seek(8 + mMaxNumOfFrame * 8);
568
569 mTimestamp = nTimeStamp; // set timestamp as the first frame
570 }
571
572 // write ToC
573 mBWHeader.Write(toc_h, 1);
574 mBWHeader.Write(toc_f, 1);
575 mBWHeader.Write(toc_ft_m, 1);
576 mBWHeader.Write(toc_ft_q, 1);
577 mBWHeader.Write(toc_ft_b, 4);
578
579 // write Speech Frame
580 mBWPayload.WriteByteBuffer(pData, nDataBitSize);
581 mBWPayload.AddPadding();
582
583 mTotalPayloadSize += nDataSize;
584
585 if (mCurrNumOfFrame == mMaxNumOfFrame)
586 {
587 // mBWHeader.AddPadding();
588 mBWHeader.Flush();
589
590 mBWPayload.AddPadding();
591 mBWPayload.Flush();
592
593 uint32_t nTotalSize = mBWPayload.GetBufferSize();
594
595 IMLOGD_PACKET7(IM_PACKET_LOG_PH,
596 "[EncodePayloadEvs] result = %02X %02X %02X %02X %02X %02X, len[%d]",
597 mPayload[0], mPayload[1], mPayload[2], mPayload[3], mPayload[4],
598 mPayload[5], nTotalSize);
599
600 if (mTotalPayloadSize > 0)
601 {
602 SendDataToRearNode(MEDIASUBTYPE_RTPPAYLOAD, mPayload,
603 CheckPaddingNecessity(nTotalSize), mTimestamp, mFirstFrame, 0);
604 }
605
606 mCurrNumOfFrame = 0;
607 mTotalPayloadSize = 0;
608 if (mFirstFrame)
609 mFirstFrame = false;
610 }
611 }
612 else
613 {
614 IMLOGE0("[EncodePayloadEvs] invalid codec mode");
615 return;
616 }
617 }
618 else
619 {
620 IMLOGE0("[EncodePayloadEvs] invalid payload format");
621 return;
622 }
623
624 return;
625 }
626
CheckPaddingNecessity(uint32_t nTotalSize)627 uint32_t AudioRtpPayloadEncoderNode::CheckPaddingNecessity(uint32_t nTotalSize)
628 {
629 kEvsCodecMode evsCodecMode;
630 uint32_t nEVSCompactId;
631 uint32_t nSize = nTotalSize;
632
633 // check EVS compact size
634 while (nSize != 0 &&
635 ImsMediaAudioUtil::ConvertEVSPayloadMode(nSize, &evsCodecMode, &nEVSCompactId) ==
636 kRtpPyaloadHeaderModeEvsCompact)
637 {
638 mPayload[nSize] = 0;
639 nSize++;
640 }
641
642 return nSize;
643 }
644