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