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