xref: /aosp_15_r20/frameworks/av/media/libstagefright/codecs/amrnb/dec/SoftAMR.cpp (revision ec779b8e0859a360c3d303172224686826e6e0e1)
1 /*
2  * Copyright (C) 2011 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 //#define LOG_NDEBUG 0
18 #define LOG_TAG "SoftAMR"
19 #include <utils/Log.h>
20 
21 #include "SoftAMR.h"
22 
23 #include <media/stagefright/foundation/ADebug.h>
24 
25 namespace android {
26 
27 template<class T>
InitOMXParams(T * params)28 static void InitOMXParams(T *params) {
29     params->nSize = sizeof(T);
30     params->nVersion.s.nVersionMajor = 1;
31     params->nVersion.s.nVersionMinor = 0;
32     params->nVersion.s.nRevision = 0;
33     params->nVersion.s.nStep = 0;
34 }
35 
SoftAMR(const char * name,const OMX_CALLBACKTYPE * callbacks,OMX_PTR appData,OMX_COMPONENTTYPE ** component)36 SoftAMR::SoftAMR(
37         const char *name,
38         const OMX_CALLBACKTYPE *callbacks,
39         OMX_PTR appData,
40         OMX_COMPONENTTYPE **component)
41     : SimpleSoftOMXComponent(name, callbacks, appData, component),
42       mMode(MODE_NARROW),
43       mState(NULL),
44       mDecoderBuf(NULL),
45       mDecoderCookie(NULL),
46       mInputBufferCount(0),
47       mAnchorTimeUs(0),
48       mNumSamplesOutput(0),
49       mSignalledError(false),
50       mOutputPortSettingsChange(NONE) {
51     if (!strcmp(name, "OMX.google.amrwb.decoder")) {
52         mMode = MODE_WIDE;
53     } else {
54         CHECK(!strcmp(name, "OMX.google.amrnb.decoder"));
55     }
56 
57     initPorts();
58     CHECK_EQ(initDecoder(), (status_t)OK);
59 }
60 
~SoftAMR()61 SoftAMR::~SoftAMR() {
62     if (mMode == MODE_NARROW) {
63         GSMDecodeFrameExit(&mState);
64         mState = NULL;
65     } else {
66         free(mDecoderBuf);
67         mDecoderBuf = NULL;
68 
69         mState = NULL;
70         mDecoderCookie = NULL;
71     }
72 }
73 
initPorts()74 void SoftAMR::initPorts() {
75     OMX_PARAM_PORTDEFINITIONTYPE def;
76     InitOMXParams(&def);
77 
78     def.nPortIndex = 0;
79     def.eDir = OMX_DirInput;
80     def.nBufferCountMin = kNumBuffers;
81     def.nBufferCountActual = def.nBufferCountMin;
82     def.nBufferSize = 8192;
83     def.bEnabled = OMX_TRUE;
84     def.bPopulated = OMX_FALSE;
85     def.eDomain = OMX_PortDomainAudio;
86     def.bBuffersContiguous = OMX_FALSE;
87     def.nBufferAlignment = 1;
88 
89     def.format.audio.cMIMEType =
90         mMode == MODE_NARROW
91             ? const_cast<char *>("audio/amr")
92             : const_cast<char *>("audio/amrwb");
93 
94     def.format.audio.pNativeRender = NULL;
95     def.format.audio.bFlagErrorConcealment = OMX_FALSE;
96     def.format.audio.eEncoding = OMX_AUDIO_CodingAMR;
97 
98     addPort(def);
99 
100     def.nPortIndex = 1;
101     def.eDir = OMX_DirOutput;
102     def.nBufferCountMin = kNumBuffers;
103     def.nBufferCountActual = def.nBufferCountMin;
104 
105     def.nBufferSize =
106         (mMode == MODE_NARROW ? kNumSamplesPerFrameNB : kNumSamplesPerFrameWB)
107             * sizeof(int16_t);
108 
109     def.bEnabled = OMX_TRUE;
110     def.bPopulated = OMX_FALSE;
111     def.eDomain = OMX_PortDomainAudio;
112     def.bBuffersContiguous = OMX_FALSE;
113     def.nBufferAlignment = 2;
114 
115     def.format.audio.cMIMEType = const_cast<char *>("audio/raw");
116     def.format.audio.pNativeRender = NULL;
117     def.format.audio.bFlagErrorConcealment = OMX_FALSE;
118     def.format.audio.eEncoding = OMX_AUDIO_CodingPCM;
119 
120     addPort(def);
121 }
122 
initDecoder()123 status_t SoftAMR::initDecoder() {
124     if (mMode == MODE_NARROW) {
125         Word16 err = GSMInitDecode(&mState, (Word8 *)"AMRNBDecoder");
126 
127         if (err != 0) {
128             return UNKNOWN_ERROR;
129         }
130     } else {
131         int32_t memReq = pvDecoder_AmrWbMemRequirements();
132         mDecoderBuf = malloc(memReq);
133 
134         pvDecoder_AmrWb_Init(&mState, mDecoderBuf, &mDecoderCookie);
135     }
136 
137     return OK;
138 }
139 
internalGetParameter(OMX_INDEXTYPE index,OMX_PTR params)140 OMX_ERRORTYPE SoftAMR::internalGetParameter(
141         OMX_INDEXTYPE index, OMX_PTR params) {
142     switch (index) {
143         case OMX_IndexParamAudioPortFormat:
144         {
145             OMX_AUDIO_PARAM_PORTFORMATTYPE *formatParams =
146                 (OMX_AUDIO_PARAM_PORTFORMATTYPE *)params;
147 
148             if (!isValidOMXParam(formatParams)) {
149                 return OMX_ErrorBadParameter;
150             }
151 
152             if (formatParams->nPortIndex > 1) {
153                 return OMX_ErrorUndefined;
154             }
155 
156             if (formatParams->nIndex > 0) {
157                 return OMX_ErrorNoMore;
158             }
159 
160             formatParams->eEncoding =
161                 (formatParams->nPortIndex == 0)
162                     ? OMX_AUDIO_CodingAMR : OMX_AUDIO_CodingPCM;
163 
164             return OMX_ErrorNone;
165         }
166 
167         case OMX_IndexParamAudioAmr:
168         {
169             OMX_AUDIO_PARAM_AMRTYPE *amrParams =
170                 (OMX_AUDIO_PARAM_AMRTYPE *)params;
171 
172             if (!isValidOMXParam(amrParams)) {
173                 return OMX_ErrorBadParameter;
174             }
175 
176             if (amrParams->nPortIndex != 0) {
177                 return OMX_ErrorUndefined;
178             }
179 
180             amrParams->nChannels = 1;
181             amrParams->eAMRDTXMode = OMX_AUDIO_AMRDTXModeOff;
182             amrParams->eAMRFrameFormat = OMX_AUDIO_AMRFrameFormatFSF;
183 
184             if (!isConfigured()) {
185                 amrParams->nBitRate = 0;
186                 amrParams->eAMRBandMode = OMX_AUDIO_AMRBandModeUnused;
187             } else {
188                 amrParams->nBitRate = 0;
189                 amrParams->eAMRBandMode =
190                     mMode == MODE_NARROW
191                         ? OMX_AUDIO_AMRBandModeNB0 : OMX_AUDIO_AMRBandModeWB0;
192             }
193 
194             return OMX_ErrorNone;
195         }
196 
197         case OMX_IndexParamAudioPcm:
198         {
199             OMX_AUDIO_PARAM_PCMMODETYPE *pcmParams =
200                 (OMX_AUDIO_PARAM_PCMMODETYPE *)params;
201 
202             if (!isValidOMXParam(pcmParams)) {
203                 return OMX_ErrorBadParameter;
204             }
205 
206             if (pcmParams->nPortIndex != 1) {
207                 return OMX_ErrorUndefined;
208             }
209 
210             pcmParams->nChannels = 1;
211             pcmParams->eNumData = OMX_NumericalDataSigned;
212             pcmParams->eEndian = OMX_EndianBig;
213             pcmParams->bInterleaved = OMX_TRUE;
214             pcmParams->nBitPerSample = 16;
215 
216             pcmParams->nSamplingRate =
217                 (mMode == MODE_NARROW) ? kSampleRateNB : kSampleRateWB;
218 
219             pcmParams->ePCMMode = OMX_AUDIO_PCMModeLinear;
220             pcmParams->eChannelMapping[0] = OMX_AUDIO_ChannelLF;
221             pcmParams->eChannelMapping[1] = OMX_AUDIO_ChannelRF;
222 
223             return OMX_ErrorNone;
224         }
225 
226         default:
227             return SimpleSoftOMXComponent::internalGetParameter(index, params);
228     }
229 }
230 
internalSetParameter(OMX_INDEXTYPE index,const OMX_PTR params)231 OMX_ERRORTYPE SoftAMR::internalSetParameter(
232         OMX_INDEXTYPE index, const OMX_PTR params) {
233     switch (index) {
234         case OMX_IndexParamStandardComponentRole:
235         {
236             const OMX_PARAM_COMPONENTROLETYPE *roleParams =
237                 (const OMX_PARAM_COMPONENTROLETYPE *)params;
238 
239             if (!isValidOMXParam(roleParams)) {
240                 return OMX_ErrorBadParameter;
241             }
242 
243             if (mMode == MODE_NARROW) {
244                 if (strncmp((const char *)roleParams->cRole,
245                             "audio_decoder.amrnb",
246                             OMX_MAX_STRINGNAME_SIZE - 1)) {
247                     return OMX_ErrorUndefined;
248                 }
249             } else {
250                 if (strncmp((const char *)roleParams->cRole,
251                             "audio_decoder.amrwb",
252                             OMX_MAX_STRINGNAME_SIZE - 1)) {
253                     return OMX_ErrorUndefined;
254                 }
255             }
256 
257             return OMX_ErrorNone;
258         }
259 
260         case OMX_IndexParamAudioPortFormat:
261         {
262             const OMX_AUDIO_PARAM_PORTFORMATTYPE *formatParams =
263                 (const OMX_AUDIO_PARAM_PORTFORMATTYPE *)params;
264 
265             if (!isValidOMXParam(formatParams)) {
266                 return OMX_ErrorBadParameter;
267             }
268 
269             if (formatParams->nPortIndex > 1) {
270                 return OMX_ErrorUndefined;
271             }
272 
273             if ((formatParams->nPortIndex == 0
274                         && formatParams->eEncoding != OMX_AUDIO_CodingAMR)
275                 || (formatParams->nPortIndex == 1
276                         && formatParams->eEncoding != OMX_AUDIO_CodingPCM)) {
277                 return OMX_ErrorUndefined;
278             }
279 
280             return OMX_ErrorNone;
281         }
282 
283         case OMX_IndexParamAudioAmr:
284         {
285             const OMX_AUDIO_PARAM_AMRTYPE *aacParams =
286                 (const OMX_AUDIO_PARAM_AMRTYPE *)params;
287 
288             if (!isValidOMXParam(aacParams)) {
289                 return OMX_ErrorBadParameter;
290             }
291 
292             if (aacParams->nPortIndex != 0) {
293                 return OMX_ErrorUndefined;
294             }
295 
296             return OMX_ErrorNone;
297         }
298 
299         case OMX_IndexParamAudioPcm:
300         {
301             const OMX_AUDIO_PARAM_PCMMODETYPE *pcmParams =
302                 (OMX_AUDIO_PARAM_PCMMODETYPE *)params;
303 
304             if (!isValidOMXParam(pcmParams)) {
305                 return OMX_ErrorBadParameter;
306             }
307 
308             if (pcmParams->nPortIndex != 1) {
309                 return OMX_ErrorUndefined;
310             }
311 
312             return OMX_ErrorNone;
313         }
314 
315         default:
316             return SimpleSoftOMXComponent::internalSetParameter(index, params);
317     }
318 }
319 
isConfigured() const320 bool SoftAMR::isConfigured() const {
321     return mInputBufferCount > 0;
322 }
323 
getFrameSize(unsigned FT)324 static size_t getFrameSize(unsigned FT) {
325     static const size_t kFrameSizeWB[10] = {
326         132, 177, 253, 285, 317, 365, 397, 461, 477, 40
327     };
328 
329     if (FT >= 10) {
330         return 1;
331     }
332 
333     size_t frameSize = kFrameSizeWB[FT];
334 
335     // Round up bits to bytes and add 1 for the header byte.
336     frameSize = (frameSize + 7) / 8 + 1;
337 
338     return frameSize;
339 }
340 
onQueueFilled(OMX_U32)341 void SoftAMR::onQueueFilled(OMX_U32 /* portIndex */) {
342     List<BufferInfo *> &inQueue = getPortQueue(0);
343     List<BufferInfo *> &outQueue = getPortQueue(1);
344 
345     if (mSignalledError || mOutputPortSettingsChange != NONE) {
346         return;
347     }
348 
349     while (!inQueue.empty() && !outQueue.empty()) {
350         BufferInfo *inInfo = *inQueue.begin();
351         OMX_BUFFERHEADERTYPE *inHeader = inInfo->mHeader;
352 
353         BufferInfo *outInfo = *outQueue.begin();
354         OMX_BUFFERHEADERTYPE *outHeader = outInfo->mHeader;
355 
356         if ((inHeader->nFlags & OMX_BUFFERFLAG_EOS) && inHeader->nFilledLen == 0) {
357             inQueue.erase(inQueue.begin());
358             inInfo->mOwnedByUs = false;
359             notifyEmptyBufferDone(inHeader);
360 
361             outHeader->nFilledLen = 0;
362             outHeader->nFlags = OMX_BUFFERFLAG_EOS;
363 
364             outQueue.erase(outQueue.begin());
365             outInfo->mOwnedByUs = false;
366             notifyFillBufferDone(outHeader);
367             return;
368         }
369 
370         if (inHeader->nFilledLen == 0) {
371             inInfo->mOwnedByUs = false;
372             inQueue.erase(inQueue.begin());
373             notifyEmptyBufferDone(inHeader);
374             continue;
375         }
376 
377         if (inHeader->nOffset == 0) {
378             mAnchorTimeUs = inHeader->nTimeStamp;
379             mNumSamplesOutput = 0;
380         }
381 
382         const uint8_t *inputPtr = inHeader->pBuffer + inHeader->nOffset;
383         int32_t numBytesRead;
384 
385         if (mMode == MODE_NARROW) {
386             if (outHeader->nAllocLen < kNumSamplesPerFrameNB * sizeof(int16_t)) {
387                 ALOGE("b/27662364: NB expected output buffer %zu bytes vs %u",
388                        kNumSamplesPerFrameNB * sizeof(int16_t), outHeader->nAllocLen);
389                 android_errorWriteLog(0x534e4554, "27662364");
390                 notify(OMX_EventError, OMX_ErrorOverflow, 0, NULL);
391                 mSignalledError = true;
392                 return;
393             }
394 
395             int16 mode = ((inputPtr[0] >> 3) & 0x0f);
396             // for WMF since MIME_IETF is used when calling AMRDecode.
397             size_t frameSize = WmfDecBytesPerFrame[mode] + 1;
398 
399             if (inHeader->nFilledLen < frameSize) {
400                 ALOGE("b/27662364: expected %zu bytes vs %u", frameSize, inHeader->nFilledLen);
401                 notify(OMX_EventError, OMX_ErrorStreamCorrupt, 0, NULL);
402                 mSignalledError = true;
403                 return;
404             }
405 
406             numBytesRead =
407                 AMRDecode(mState,
408                   (Frame_Type_3GPP)((inputPtr[0] >> 3) & 0x0f),
409                   (UWord8 *)&inputPtr[1],
410                   reinterpret_cast<int16_t *>(outHeader->pBuffer),
411                   MIME_IETF);
412 
413             if (numBytesRead == -1) {
414                 ALOGE("PV AMR decoder AMRDecode() call failed");
415 
416                 notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL);
417                 mSignalledError = true;
418 
419                 return;
420             }
421 
422             ++numBytesRead;  // Include the frame type header byte.
423 
424             if (static_cast<size_t>(numBytesRead) > inHeader->nFilledLen) {
425                 // This is bad, should never have happened, but did. Abort now.
426 
427                 notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL);
428                 mSignalledError = true;
429 
430                 return;
431             }
432         } else {
433             if (outHeader->nAllocLen < kNumSamplesPerFrameWB * sizeof(int16_t)) {
434                 ALOGE("b/27662364: WB expected output buffer %zu bytes vs %u",
435                        kNumSamplesPerFrameWB * sizeof(int16_t), outHeader->nAllocLen);
436                 android_errorWriteLog(0x534e4554, "27662364");
437                 notify(OMX_EventError, OMX_ErrorOverflow, 0, NULL);
438                 mSignalledError = true;
439                 return;
440             }
441 
442             int16 mode = ((inputPtr[0] >> 3) & 0x0f);
443 
444             if (mode >= 10 && mode <= 13) {
445                 ALOGE("encountered illegal frame type %d in AMR WB content.",
446                       mode);
447 
448                 notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL);
449                 mSignalledError = true;
450 
451                 return;
452             }
453 
454             size_t frameSize = getFrameSize(mode);
455             if (inHeader->nFilledLen < frameSize) {
456                 ALOGE("b/27662364: expected %zu bytes vs %u", frameSize, inHeader->nFilledLen);
457                 notify(OMX_EventError, OMX_ErrorStreamCorrupt, 0, NULL);
458                 mSignalledError = true;
459                 return;
460             }
461 
462             int16_t *outPtr = (int16_t *)outHeader->pBuffer;
463 
464             if (mode >= 9) {
465                 // Produce silence instead of comfort noise and for
466                 // speech lost/no data.
467                 memset(outPtr, 0, kNumSamplesPerFrameWB * sizeof(int16_t));
468             } else if (mode < 9) {
469                 int16 frameType;
470                 mime_unsorting(
471                         const_cast<uint8_t *>(&inputPtr[1]),
472                         mInputSampleBuffer,
473                         &frameType, &mode, 1, &mRxState);
474 
475                 int16_t numSamplesOutput;
476                 pvDecoder_AmrWb(
477                         mode, mInputSampleBuffer,
478                         outPtr,
479                         &numSamplesOutput,
480                         mDecoderBuf, frameType, mDecoderCookie);
481 
482                 CHECK_EQ((int)numSamplesOutput, (int)kNumSamplesPerFrameWB);
483 
484                 for (int i = 0; i < kNumSamplesPerFrameWB; ++i) {
485                     /* Delete the 2 LSBs (14-bit output) */
486                     outPtr[i] &= 0xfffC;
487                 }
488             }
489 
490             numBytesRead = frameSize;
491         }
492 
493         inHeader->nOffset += numBytesRead;
494         inHeader->nFilledLen -= numBytesRead;
495 
496         outHeader->nFlags = 0;
497         outHeader->nOffset = 0;
498 
499         if (mMode == MODE_NARROW) {
500             outHeader->nFilledLen = kNumSamplesPerFrameNB * sizeof(int16_t);
501 
502             outHeader->nTimeStamp =
503                 mAnchorTimeUs
504                     + (mNumSamplesOutput * 1000000LL) / kSampleRateNB;
505 
506             mNumSamplesOutput += kNumSamplesPerFrameNB;
507         } else {
508             outHeader->nFilledLen = kNumSamplesPerFrameWB * sizeof(int16_t);
509 
510             outHeader->nTimeStamp =
511                 mAnchorTimeUs
512                     + (mNumSamplesOutput * 1000000LL) / kSampleRateWB;
513 
514             mNumSamplesOutput += kNumSamplesPerFrameWB;
515         }
516 
517         if (inHeader->nFilledLen == 0 && (inHeader->nFlags & OMX_BUFFERFLAG_EOS) == 0) {
518             inInfo->mOwnedByUs = false;
519             inQueue.erase(inQueue.begin());
520             inInfo = NULL;
521             notifyEmptyBufferDone(inHeader);
522             inHeader = NULL;
523         }
524 
525         outInfo->mOwnedByUs = false;
526         outQueue.erase(outQueue.begin());
527         outInfo = NULL;
528         notifyFillBufferDone(outHeader);
529         outHeader = NULL;
530 
531         ++mInputBufferCount;
532     }
533 }
534 
onPortFlushCompleted(OMX_U32 portIndex)535 void SoftAMR::onPortFlushCompleted(OMX_U32 portIndex) {
536     ALOGV("onPortFlushCompleted portindex %d, resetting frame ", portIndex);
537     if (portIndex == 0) {
538         if (mMode == MODE_NARROW) {
539            Speech_Decode_Frame_reset(mState);
540         } else {
541            pvDecoder_AmrWb_Reset(mState, 0 /* reset_all */);
542         }
543     }
544 }
545 
onPortEnableCompleted(OMX_U32 portIndex,bool enabled)546 void SoftAMR::onPortEnableCompleted(OMX_U32 portIndex, bool enabled) {
547     if (portIndex != 1) {
548         return;
549     }
550 
551     switch (mOutputPortSettingsChange) {
552         case NONE:
553             break;
554 
555         case AWAITING_DISABLED:
556         {
557             CHECK(!enabled);
558             mOutputPortSettingsChange = AWAITING_ENABLED;
559             break;
560         }
561 
562         default:
563         {
564             CHECK_EQ((int)mOutputPortSettingsChange, (int)AWAITING_ENABLED);
565             CHECK(enabled);
566             mOutputPortSettingsChange = NONE;
567             break;
568         }
569     }
570 }
571 
onReset()572 void SoftAMR::onReset() {
573     mSignalledError = false;
574     mOutputPortSettingsChange = NONE;
575 }
576 
577 }  // namespace android
578 
579 __attribute__((cfi_canonical_jump_table))
createSoftOMXComponent(const char * name,const OMX_CALLBACKTYPE * callbacks,OMX_PTR appData,OMX_COMPONENTTYPE ** component)580 android::SoftOMXComponent *createSoftOMXComponent(
581         const char *name, const OMX_CALLBACKTYPE *callbacks,
582         OMX_PTR appData, OMX_COMPONENTTYPE **component) {
583     return new android::SoftAMR(name, callbacks, appData, component);
584 }
585 
586