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