xref: /aosp_15_r20/frameworks/av/media/libstagefright/codecs/aacenc/SoftAACEncoder2.cpp (revision ec779b8e0859a360c3d303172224686826e6e0e1)
1 /*
2  * Copyright (C) 2012 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 "SoftAACEncoder2"
19 #include <log/log.h>
20 #include <utils/Log.h>
21 
22 #include "SoftAACEncoder2.h"
23 #include <OMX_AudioExt.h>
24 #include <OMX_IndexExt.h>
25 
26 #include <media/stagefright/foundation/ADebug.h>
27 #include <media/stagefright/foundation/hexdump.h>
28 #include <utils/misc.h>
29 
30 namespace android {
31 
32 template<class T>
InitOMXParams(T * params)33 static void InitOMXParams(T *params) {
34     params->nSize = sizeof(T);
35     params->nVersion.s.nVersionMajor = 1;
36     params->nVersion.s.nVersionMinor = 0;
37     params->nVersion.s.nRevision = 0;
38     params->nVersion.s.nStep = 0;
39 }
40 
41 static const OMX_U32 kSupportedProfiles[] = {
42     OMX_AUDIO_AACObjectLC,
43     OMX_AUDIO_AACObjectHE,
44     OMX_AUDIO_AACObjectHE_PS,
45     OMX_AUDIO_AACObjectLD,
46     OMX_AUDIO_AACObjectELD,
47 };
48 
SoftAACEncoder2(const char * name,const OMX_CALLBACKTYPE * callbacks,OMX_PTR appData,OMX_COMPONENTTYPE ** component)49 SoftAACEncoder2::SoftAACEncoder2(
50         const char *name,
51         const OMX_CALLBACKTYPE *callbacks,
52         OMX_PTR appData,
53         OMX_COMPONENTTYPE **component)
54     : SimpleSoftOMXComponent(name, callbacks, appData, component),
55       mAACEncoder(NULL),
56       mNumChannels(1),
57       mSampleRate(44100),
58       mBitRate(0),
59       mSBRMode(-1),
60       mSBRRatio(0),
61       mAACProfile(OMX_AUDIO_AACObjectLC),
62       mSentCodecSpecificData(false),
63       mInputSize(0),
64       mInputFrame(NULL),
65       mAllocatedFrameSize(0),
66       mInputTimeUs(-1LL),
67       mSawInputEOS(false),
68       mSignalledError(false) {
69     initPorts();
70     CHECK_EQ(initEncoder(), (status_t)OK);
71     setAudioParams();
72 }
73 
~SoftAACEncoder2()74 SoftAACEncoder2::~SoftAACEncoder2() {
75     aacEncClose(&mAACEncoder);
76 
77     onReset();
78 }
79 
initPorts()80 void SoftAACEncoder2::initPorts() {
81     OMX_PARAM_PORTDEFINITIONTYPE def;
82     InitOMXParams(&def);
83 
84     def.nPortIndex = 0;
85     def.eDir = OMX_DirInput;
86     def.nBufferCountMin = kNumBuffers;
87     def.nBufferCountActual = def.nBufferCountMin;
88     def.nBufferSize = kNumSamplesPerFrame * sizeof(int16_t) * 2;
89     def.bEnabled = OMX_TRUE;
90     def.bPopulated = OMX_FALSE;
91     def.eDomain = OMX_PortDomainAudio;
92     def.bBuffersContiguous = OMX_FALSE;
93     def.nBufferAlignment = 1;
94 
95     def.format.audio.cMIMEType = const_cast<char *>("audio/raw");
96     def.format.audio.pNativeRender = NULL;
97     def.format.audio.bFlagErrorConcealment = OMX_FALSE;
98     def.format.audio.eEncoding = OMX_AUDIO_CodingPCM;
99 
100     addPort(def);
101 
102     def.nPortIndex = 1;
103     def.eDir = OMX_DirOutput;
104     def.nBufferCountMin = kNumBuffers;
105     def.nBufferCountActual = def.nBufferCountMin;
106     def.nBufferSize = 8192;
107     def.bEnabled = OMX_TRUE;
108     def.bPopulated = OMX_FALSE;
109     def.eDomain = OMX_PortDomainAudio;
110     def.bBuffersContiguous = OMX_FALSE;
111     def.nBufferAlignment = 2;
112 
113     def.format.audio.cMIMEType = const_cast<char *>("audio/aac");
114     def.format.audio.pNativeRender = NULL;
115     def.format.audio.bFlagErrorConcealment = OMX_FALSE;
116     def.format.audio.eEncoding = OMX_AUDIO_CodingAAC;
117 
118     addPort(def);
119 }
120 
initEncoder()121 status_t SoftAACEncoder2::initEncoder() {
122     if (AACENC_OK != aacEncOpen(&mAACEncoder, 0, 0)) {
123         ALOGE("Failed to init AAC encoder");
124         return UNKNOWN_ERROR;
125     }
126     return OK;
127 }
128 
internalGetParameter(OMX_INDEXTYPE index,OMX_PTR params)129 OMX_ERRORTYPE SoftAACEncoder2::internalGetParameter(
130         OMX_INDEXTYPE index, OMX_PTR params) {
131     switch ((OMX_U32) index) {
132         case OMX_IndexParamAudioPortFormat:
133         {
134             OMX_AUDIO_PARAM_PORTFORMATTYPE *formatParams =
135                 (OMX_AUDIO_PARAM_PORTFORMATTYPE *)params;
136 
137             if (!isValidOMXParam(formatParams)) {
138                 return OMX_ErrorBadParameter;
139             }
140 
141             if (formatParams->nPortIndex > 1) {
142                 return OMX_ErrorUndefined;
143             }
144 
145             if (formatParams->nIndex > 0) {
146                 return OMX_ErrorNoMore;
147             }
148 
149             formatParams->eEncoding =
150                 (formatParams->nPortIndex == 0)
151                     ? OMX_AUDIO_CodingPCM : OMX_AUDIO_CodingAAC;
152 
153             return OMX_ErrorNone;
154         }
155 
156         case OMX_IndexParamAudioAac:
157         {
158             OMX_AUDIO_PARAM_AACPROFILETYPE *aacParams =
159                 (OMX_AUDIO_PARAM_AACPROFILETYPE *)params;
160 
161             if (!isValidOMXParam(aacParams)) {
162                 return OMX_ErrorBadParameter;
163             }
164 
165             if (aacParams->nPortIndex != 1) {
166                 return OMX_ErrorUndefined;
167             }
168 
169             aacParams->nBitRate = mBitRate;
170             aacParams->nAudioBandWidth = 0;
171             aacParams->nAACtools = 0;
172             aacParams->nAACERtools = 0;
173             aacParams->eAACProfile = (OMX_AUDIO_AACPROFILETYPE) mAACProfile;
174             aacParams->eAACStreamFormat = OMX_AUDIO_AACStreamFormatMP4FF;
175             aacParams->eChannelMode = OMX_AUDIO_ChannelModeStereo;
176 
177             aacParams->nChannels = mNumChannels;
178             aacParams->nSampleRate = mSampleRate;
179             aacParams->nFrameLength = 0;
180 
181             switch (mSBRMode) {
182             case 1: // sbr on
183                 switch (mSBRRatio) {
184                 case 0:
185                     // set both OMX AAC tool flags
186                     aacParams->nAACtools |= OMX_AUDIO_AACToolAndroidSSBR;
187                     aacParams->nAACtools |= OMX_AUDIO_AACToolAndroidDSBR;
188                     break;
189                 case 1:
190                     // set single-rate SBR active
191                     aacParams->nAACtools |= OMX_AUDIO_AACToolAndroidSSBR;
192                     aacParams->nAACtools &= ~OMX_AUDIO_AACToolAndroidDSBR;
193                     break;
194                 case 2:
195                     // set dual-rate SBR active
196                     aacParams->nAACtools &= ~OMX_AUDIO_AACToolAndroidSSBR;
197                     aacParams->nAACtools |= OMX_AUDIO_AACToolAndroidDSBR;
198                     break;
199                 default:
200                     ALOGE("invalid SBR ratio %d", mSBRRatio);
201                     TRESPASS();
202                 }
203                 break;
204             case 0:  // sbr off
205             case -1: // sbr undefined
206                 aacParams->nAACtools &= ~OMX_AUDIO_AACToolAndroidSSBR;
207                 aacParams->nAACtools &= ~OMX_AUDIO_AACToolAndroidDSBR;
208                 break;
209             default:
210                 ALOGE("invalid SBR mode %d", mSBRMode);
211                 TRESPASS();
212             }
213 
214 
215 
216             return OMX_ErrorNone;
217         }
218 
219         case OMX_IndexParamAudioPcm:
220         {
221             OMX_AUDIO_PARAM_PCMMODETYPE *pcmParams =
222                 (OMX_AUDIO_PARAM_PCMMODETYPE *)params;
223 
224             if (!isValidOMXParam(pcmParams)) {
225                 return OMX_ErrorBadParameter;
226             }
227 
228             if (pcmParams->nPortIndex != 0) {
229                 return OMX_ErrorUndefined;
230             }
231 
232             pcmParams->eNumData = OMX_NumericalDataSigned;
233             pcmParams->eEndian = OMX_EndianBig;
234             pcmParams->bInterleaved = OMX_TRUE;
235             pcmParams->nBitPerSample = 16;
236             pcmParams->ePCMMode = OMX_AUDIO_PCMModeLinear;
237             pcmParams->eChannelMapping[0] = OMX_AUDIO_ChannelLF;
238             pcmParams->eChannelMapping[1] = OMX_AUDIO_ChannelRF;
239 
240             pcmParams->nChannels = mNumChannels;
241             pcmParams->nSamplingRate = mSampleRate;
242 
243             return OMX_ErrorNone;
244         }
245 
246         case OMX_IndexParamAudioProfileQuerySupported:
247         {
248             OMX_AUDIO_PARAM_ANDROID_PROFILETYPE *profileParams =
249                 (OMX_AUDIO_PARAM_ANDROID_PROFILETYPE *)params;
250 
251             if (!isValidOMXParam(profileParams)) {
252                 return OMX_ErrorBadParameter;
253             }
254 
255             if (profileParams->nPortIndex != 1) {
256                 return OMX_ErrorUndefined;
257             }
258 
259             if (profileParams->nProfileIndex >= NELEM(kSupportedProfiles)) {
260                 return OMX_ErrorNoMore;
261             }
262 
263             profileParams->eProfile =
264                 kSupportedProfiles[profileParams->nProfileIndex];
265 
266             return OMX_ErrorNone;
267         }
268 
269         default:
270             return SimpleSoftOMXComponent::internalGetParameter(index, params);
271     }
272 }
273 
internalSetParameter(OMX_INDEXTYPE index,const OMX_PTR params)274 OMX_ERRORTYPE SoftAACEncoder2::internalSetParameter(
275         OMX_INDEXTYPE index, const OMX_PTR params) {
276     switch (index) {
277         case OMX_IndexParamStandardComponentRole:
278         {
279             const OMX_PARAM_COMPONENTROLETYPE *roleParams =
280                 (const OMX_PARAM_COMPONENTROLETYPE *)params;
281 
282             if (!isValidOMXParam(roleParams)) {
283                 return OMX_ErrorBadParameter;
284             }
285 
286             if (strncmp((const char *)roleParams->cRole,
287                         "audio_encoder.aac",
288                         OMX_MAX_STRINGNAME_SIZE - 1)) {
289                 return OMX_ErrorUndefined;
290             }
291 
292             return OMX_ErrorNone;
293         }
294 
295         case OMX_IndexParamAudioPortFormat:
296         {
297             const OMX_AUDIO_PARAM_PORTFORMATTYPE *formatParams =
298                 (const OMX_AUDIO_PARAM_PORTFORMATTYPE *)params;
299 
300             if (!isValidOMXParam(formatParams)) {
301                 return OMX_ErrorBadParameter;
302             }
303 
304             if (formatParams->nPortIndex > 1) {
305                 return OMX_ErrorUndefined;
306             }
307 
308             if ((formatParams->nPortIndex == 0
309                         && formatParams->eEncoding != OMX_AUDIO_CodingPCM)
310                 || (formatParams->nPortIndex == 1
311                         && formatParams->eEncoding != OMX_AUDIO_CodingAAC)) {
312                 return OMX_ErrorUndefined;
313             }
314 
315             return OMX_ErrorNone;
316         }
317 
318         case OMX_IndexParamAudioAac:
319         {
320             OMX_AUDIO_PARAM_AACPROFILETYPE *aacParams =
321                 (OMX_AUDIO_PARAM_AACPROFILETYPE *)params;
322 
323             if (!isValidOMXParam(aacParams)) {
324                 return OMX_ErrorBadParameter;
325             }
326 
327             if (aacParams->nPortIndex != 1) {
328                 return OMX_ErrorUndefined;
329             }
330 
331             mBitRate = aacParams->nBitRate;
332             mNumChannels = aacParams->nChannels;
333             mSampleRate = aacParams->nSampleRate;
334             if (aacParams->eAACProfile != OMX_AUDIO_AACObjectNull) {
335                 mAACProfile = aacParams->eAACProfile;
336             }
337 
338             if (!(aacParams->nAACtools & OMX_AUDIO_AACToolAndroidSSBR)
339                     && !(aacParams->nAACtools & OMX_AUDIO_AACToolAndroidDSBR)) {
340                 mSBRMode = 0;
341                 mSBRRatio = 0;
342             } else if ((aacParams->nAACtools & OMX_AUDIO_AACToolAndroidSSBR)
343                     && !(aacParams->nAACtools & OMX_AUDIO_AACToolAndroidDSBR)) {
344                 mSBRMode = 1;
345                 mSBRRatio = 1;
346             } else if (!(aacParams->nAACtools & OMX_AUDIO_AACToolAndroidSSBR)
347                     && (aacParams->nAACtools & OMX_AUDIO_AACToolAndroidDSBR)) {
348                 mSBRMode = 1;
349                 mSBRRatio = 2;
350             } else {
351                 mSBRMode = -1; // codec default sbr mode
352                 mSBRRatio = 0;
353             }
354 
355             if (setAudioParams() != OK) {
356                 return OMX_ErrorUndefined;
357             }
358 
359             return OMX_ErrorNone;
360         }
361 
362         case OMX_IndexParamAudioPcm:
363         {
364             OMX_AUDIO_PARAM_PCMMODETYPE *pcmParams =
365                 (OMX_AUDIO_PARAM_PCMMODETYPE *)params;
366 
367             if (!isValidOMXParam(pcmParams)) {
368                 return OMX_ErrorBadParameter;
369             }
370 
371             if (pcmParams->nPortIndex != 0) {
372                 return OMX_ErrorUndefined;
373             }
374 
375             mNumChannels = pcmParams->nChannels;
376             mSampleRate = pcmParams->nSamplingRate;
377             if (setAudioParams() != OK) {
378                 return OMX_ErrorUndefined;
379             }
380 
381             return OMX_ErrorNone;
382         }
383 
384         default:
385             return SimpleSoftOMXComponent::internalSetParameter(index, params);
386     }
387 }
388 
getChannelMode(OMX_U32 nChannels)389 static CHANNEL_MODE getChannelMode(OMX_U32 nChannels) {
390     CHANNEL_MODE chMode = MODE_INVALID;
391     switch (nChannels) {
392         case 1: chMode = MODE_1; break;
393         case 2: chMode = MODE_2; break;
394         case 3: chMode = MODE_1_2; break;
395         case 4: chMode = MODE_1_2_1; break;
396         case 5: chMode = MODE_1_2_2; break;
397         case 6: chMode = MODE_1_2_2_1; break;
398         default: chMode = MODE_INVALID;
399     }
400     return chMode;
401 }
402 
getAOTFromProfile(OMX_U32 profile)403 static AUDIO_OBJECT_TYPE getAOTFromProfile(OMX_U32 profile) {
404     if (profile == OMX_AUDIO_AACObjectLC) {
405         return AOT_AAC_LC;
406     } else if (profile == OMX_AUDIO_AACObjectHE) {
407         return AOT_SBR;
408     } else if (profile == OMX_AUDIO_AACObjectHE_PS) {
409         return AOT_PS;
410     } else if (profile == OMX_AUDIO_AACObjectLD) {
411         return AOT_ER_AAC_LD;
412     } else if (profile == OMX_AUDIO_AACObjectELD) {
413         return AOT_ER_AAC_ELD;
414     } else {
415         ALOGW("Unsupported AAC profile - defaulting to AAC-LC");
416         return AOT_AAC_LC;
417     }
418 }
419 
setAudioParams()420 status_t SoftAACEncoder2::setAudioParams() {
421     // We call this whenever sample rate, number of channels, bitrate or SBR mode change
422     // in reponse to setParameter calls.
423 
424     ALOGV("setAudioParams: %u Hz, %u channels, %u bps, %i sbr mode, %i sbr ratio",
425          mSampleRate, mNumChannels, mBitRate, mSBRMode, mSBRRatio);
426 
427     if (AACENC_OK != aacEncoder_SetParam(mAACEncoder, AACENC_AOT,
428             getAOTFromProfile(mAACProfile))) {
429         ALOGE("Failed to set AAC encoder parameters");
430         return UNKNOWN_ERROR;
431     }
432 
433     if (AACENC_OK != aacEncoder_SetParam(mAACEncoder, AACENC_SAMPLERATE, mSampleRate)) {
434         ALOGE("Failed to set AAC encoder parameters");
435         return UNKNOWN_ERROR;
436     }
437     if (AACENC_OK != aacEncoder_SetParam(mAACEncoder, AACENC_BITRATE, mBitRate)) {
438         ALOGE("Failed to set AAC encoder parameters");
439         return UNKNOWN_ERROR;
440     }
441     if (AACENC_OK != aacEncoder_SetParam(mAACEncoder, AACENC_CHANNELMODE,
442             getChannelMode(mNumChannels))) {
443         ALOGE("Failed to set AAC encoder parameters");
444         return UNKNOWN_ERROR;
445     }
446     if (AACENC_OK != aacEncoder_SetParam(mAACEncoder, AACENC_TRANSMUX, TT_MP4_RAW)) {
447         ALOGE("Failed to set AAC encoder parameters");
448         return UNKNOWN_ERROR;
449     }
450 
451     if (mSBRMode != -1 && mAACProfile == OMX_AUDIO_AACObjectELD) {
452         if (AACENC_OK != aacEncoder_SetParam(mAACEncoder, AACENC_SBR_MODE, mSBRMode)) {
453             ALOGE("Failed to set AAC encoder parameters");
454             return UNKNOWN_ERROR;
455         }
456     }
457 
458     /* SBR ratio parameter configurations:
459        0: Default configuration wherein SBR ratio is configured depending on audio object type by
460           the FDK.
461        1: Downsampled SBR (default for ELD)
462        2: Dualrate SBR (default for HE-AAC)
463      */
464     if (AACENC_OK != aacEncoder_SetParam(mAACEncoder, AACENC_SBR_RATIO, mSBRRatio)) {
465         ALOGE("Failed to set AAC encoder parameters");
466         return UNKNOWN_ERROR;
467     }
468 
469     return OK;
470 }
471 
onQueueFilled(OMX_U32)472 void SoftAACEncoder2::onQueueFilled(OMX_U32 /* portIndex */) {
473     if (mSignalledError) {
474         return;
475     }
476 
477     List<BufferInfo *> &inQueue = getPortQueue(0);
478     List<BufferInfo *> &outQueue = getPortQueue(1);
479 
480     if (!mSentCodecSpecificData) {
481         // The very first thing we want to output is the codec specific
482         // data. It does not require any input data but we will need an
483         // output buffer to store it in.
484 
485         if (outQueue.empty()) {
486             return;
487         }
488 
489         if (AACENC_OK != aacEncEncode(mAACEncoder, NULL, NULL, NULL, NULL)) {
490             ALOGE("Unable to initialize encoder for profile / sample-rate / bit-rate / channels");
491             notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL);
492             mSignalledError = true;
493             return;
494         }
495 
496         OMX_U32 actualBitRate  = aacEncoder_GetParam(mAACEncoder, AACENC_BITRATE);
497         if (mBitRate != actualBitRate) {
498             ALOGW("Requested bitrate %u unsupported, using %u", mBitRate, actualBitRate);
499         }
500 
501         AACENC_InfoStruct encInfo;
502         if (AACENC_OK != aacEncInfo(mAACEncoder, &encInfo)) {
503             ALOGE("Failed to get AAC encoder info");
504             notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL);
505             mSignalledError = true;
506             return;
507         }
508 
509         BufferInfo *outInfo = *outQueue.begin();
510         OMX_BUFFERHEADERTYPE *outHeader = outInfo->mHeader;
511 
512         if (outHeader->nOffset + encInfo.confSize > outHeader->nAllocLen) {
513             ALOGE("b/34617444");
514             android_errorWriteLog(0x534e4554,"34617444");
515             notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL);
516             mSignalledError = true;
517             return;
518         }
519 
520         outHeader->nFilledLen = encInfo.confSize;
521         outHeader->nFlags = OMX_BUFFERFLAG_CODECCONFIG;
522 
523         uint8_t *out = outHeader->pBuffer + outHeader->nOffset;
524         memcpy(out, encInfo.confBuf, encInfo.confSize);
525 
526         outQueue.erase(outQueue.begin());
527         outInfo->mOwnedByUs = false;
528         notifyFillBufferDone(outHeader);
529 
530         mSentCodecSpecificData = true;
531     }
532 
533     size_t numBytesPerInputFrame =
534         mNumChannels * kNumSamplesPerFrame * sizeof(int16_t);
535 
536     // Limit input size so we only get one ELD frame
537     if (mAACProfile == OMX_AUDIO_AACObjectELD && numBytesPerInputFrame > 512) {
538         numBytesPerInputFrame = 512;
539     }
540 
541     for (;;) {
542         // We do the following until we run out of buffers.
543 
544         while (mInputSize < numBytesPerInputFrame) {
545             // As long as there's still input data to be read we
546             // will drain "kNumSamplesPerFrame * mNumChannels" samples
547             // into the "mInputFrame" buffer and then encode those
548             // as a unit into an output buffer.
549 
550             if (mSawInputEOS || inQueue.empty()) {
551                 return;
552             }
553 
554             BufferInfo *inInfo = *inQueue.begin();
555             OMX_BUFFERHEADERTYPE *inHeader = inInfo->mHeader;
556 
557             const void *inData = inHeader->pBuffer + inHeader->nOffset;
558 
559             size_t copy = numBytesPerInputFrame - mInputSize;
560             if (copy > inHeader->nFilledLen) {
561                 copy = inHeader->nFilledLen;
562             }
563 
564             if (mInputFrame == NULL) {
565                 mInputFrame = new int16_t[numBytesPerInputFrame / sizeof(int16_t)];
566                 mAllocatedFrameSize = numBytesPerInputFrame;
567             } else if (mAllocatedFrameSize != numBytesPerInputFrame) {
568                 ALOGE("b/34621073: changed size from %d to %d",
569                         (int)mAllocatedFrameSize, (int)numBytesPerInputFrame);
570                 android_errorWriteLog(0x534e4554,"34621073");
571                 delete mInputFrame;
572                 mInputFrame = new int16_t[numBytesPerInputFrame / sizeof(int16_t)];
573                 mAllocatedFrameSize = numBytesPerInputFrame;
574 
575             }
576 
577             if (mInputSize == 0) {
578                 mInputTimeUs = inHeader->nTimeStamp;
579             }
580 
581             memcpy((uint8_t *)mInputFrame + mInputSize, inData, copy);
582             mInputSize += copy;
583 
584             inHeader->nOffset += copy;
585             inHeader->nFilledLen -= copy;
586 
587             // "Time" on the input buffer has in effect advanced by the
588             // number of audio frames we just advanced nOffset by.
589             inHeader->nTimeStamp +=
590                 (copy * 1000000LL / mSampleRate)
591                     / (mNumChannels * sizeof(int16_t));
592 
593             if (inHeader->nFilledLen == 0) {
594                 if (inHeader->nFlags & OMX_BUFFERFLAG_EOS) {
595                     mSawInputEOS = true;
596 
597                     // Pad any remaining data with zeroes.
598                     memset((uint8_t *)mInputFrame + mInputSize,
599                            0,
600                            numBytesPerInputFrame - mInputSize);
601 
602                     mInputSize = numBytesPerInputFrame;
603                 }
604 
605                 inQueue.erase(inQueue.begin());
606                 inInfo->mOwnedByUs = false;
607                 notifyEmptyBufferDone(inHeader);
608 
609                 inData = NULL;
610                 inHeader = NULL;
611                 inInfo = NULL;
612             }
613         }
614 
615         // At this  point we have all the input data necessary to encode
616         // a single frame, all we need is an output buffer to store the result
617         // in.
618 
619         if (outQueue.empty()) {
620             return;
621         }
622 
623         BufferInfo *outInfo = *outQueue.begin();
624         OMX_BUFFERHEADERTYPE *outHeader = outInfo->mHeader;
625 
626         uint8_t *outPtr = (uint8_t *)outHeader->pBuffer + outHeader->nOffset;
627         size_t outAvailable = outHeader->nAllocLen - outHeader->nOffset;
628 
629         AACENC_InArgs inargs;
630         AACENC_OutArgs outargs;
631         memset(&inargs, 0, sizeof(inargs));
632         memset(&outargs, 0, sizeof(outargs));
633         inargs.numInSamples = numBytesPerInputFrame / sizeof(int16_t);
634 
635         void* inBuffer[]        = { (unsigned char *)mInputFrame };
636         INT   inBufferIds[]     = { IN_AUDIO_DATA };
637         INT   inBufferSize[]    = { (INT)numBytesPerInputFrame };
638         INT   inBufferElSize[]  = { sizeof(int16_t) };
639 
640         AACENC_BufDesc inBufDesc;
641         inBufDesc.numBufs           = sizeof(inBuffer) / sizeof(void*);
642         inBufDesc.bufs              = (void**)&inBuffer;
643         inBufDesc.bufferIdentifiers = inBufferIds;
644         inBufDesc.bufSizes          = inBufferSize;
645         inBufDesc.bufElSizes        = inBufferElSize;
646 
647         void* outBuffer[]       = { outPtr };
648         INT   outBufferIds[]    = { OUT_BITSTREAM_DATA };
649         INT   outBufferSize[]   = { 0 };
650         INT   outBufferElSize[] = { sizeof(UCHAR) };
651 
652         AACENC_BufDesc outBufDesc;
653         outBufDesc.numBufs           = sizeof(outBuffer) / sizeof(void*);
654         outBufDesc.bufs              = (void**)&outBuffer;
655         outBufDesc.bufferIdentifiers = outBufferIds;
656         outBufDesc.bufSizes          = outBufferSize;
657         outBufDesc.bufElSizes        = outBufferElSize;
658 
659         // Encode the mInputFrame, which is treated as a modulo buffer
660         AACENC_ERROR encoderErr = AACENC_OK;
661         size_t nOutputBytes = 0;
662 
663         do {
664             memset(&outargs, 0, sizeof(outargs));
665 
666             outBuffer[0] = outPtr;
667             outBufferSize[0] = outAvailable - nOutputBytes;
668 
669             encoderErr = aacEncEncode(mAACEncoder,
670                                       &inBufDesc,
671                                       &outBufDesc,
672                                       &inargs,
673                                       &outargs);
674 
675             if (encoderErr == AACENC_OK) {
676                 outPtr += outargs.numOutBytes;
677                 nOutputBytes += outargs.numOutBytes;
678 
679                 if (outargs.numInSamples > 0) {
680                     int numRemainingSamples = inargs.numInSamples - outargs.numInSamples;
681                     if (numRemainingSamples > 0) {
682                         memmove(mInputFrame,
683                                 &mInputFrame[outargs.numInSamples],
684                                 sizeof(int16_t) * numRemainingSamples);
685                     }
686                     inargs.numInSamples -= outargs.numInSamples;
687                 }
688             }
689         } while (encoderErr == AACENC_OK && inargs.numInSamples > 0);
690 
691         outHeader->nFilledLen = nOutputBytes;
692 
693         outHeader->nFlags = OMX_BUFFERFLAG_ENDOFFRAME;
694 
695         if (mSawInputEOS) {
696             // We also tag this output buffer with EOS if it corresponds
697             // to the final input buffer.
698             outHeader->nFlags = OMX_BUFFERFLAG_EOS;
699         }
700 
701         outHeader->nTimeStamp = mInputTimeUs;
702 
703 #if 0
704         ALOGI("sending %d bytes of data (time = %lld us, flags = 0x%08lx)",
705               nOutputBytes, mInputTimeUs, outHeader->nFlags);
706 
707         hexdump(outHeader->pBuffer + outHeader->nOffset, outHeader->nFilledLen);
708 #endif
709 
710         outQueue.erase(outQueue.begin());
711         outInfo->mOwnedByUs = false;
712         notifyFillBufferDone(outHeader);
713 
714         outHeader = NULL;
715         outInfo = NULL;
716 
717         mInputSize = 0;
718     }
719 }
720 
onReset()721 void SoftAACEncoder2::onReset() {
722     delete[] mInputFrame;
723     mInputFrame = NULL;
724     mInputSize = 0;
725     mAllocatedFrameSize = 0;
726 
727     mSentCodecSpecificData = false;
728     mInputTimeUs = -1LL;
729     mSawInputEOS = false;
730     mSignalledError = false;
731 }
732 
733 }  // namespace android
734 
735 __attribute__((cfi_canonical_jump_table))
createSoftOMXComponent(const char * name,const OMX_CALLBACKTYPE * callbacks,OMX_PTR appData,OMX_COMPONENTTYPE ** component)736 android::SoftOMXComponent *createSoftOMXComponent(
737         const char *name, const OMX_CALLBACKTYPE *callbacks,
738         OMX_PTR appData, OMX_COMPONENTTYPE **component) {
739     return new android::SoftAACEncoder2(name, callbacks, appData, component);
740 }
741