183f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber/*
283f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber * Copyright (C) 2012 The Android Open Source Project
383f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber *
483f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber * Licensed under the Apache License, Version 2.0 (the "License");
583f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber * you may not use this file except in compliance with the License.
683f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber * You may obtain a copy of the License at
783f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber *
883f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber *      http://www.apache.org/licenses/LICENSE-2.0
983f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber *
1083f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber * Unless required by applicable law or agreed to in writing, software
1183f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber * distributed under the License is distributed on an "AS IS" BASIS,
1283f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1383f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber * See the License for the specific language governing permissions and
1483f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber * limitations under the License.
1583f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber */
1683f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber
1783f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber//#define LOG_NDEBUG 0
1883f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber#define LOG_TAG "SoftAMRWBEncoder"
1983f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber#include <utils/Log.h>
2083f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber
2183f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber#include "SoftAMRWBEncoder.h"
2283f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber
2383f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber#include "cmnMemory.h"
2483f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber
2583f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber#include <media/stagefright/foundation/ADebug.h>
2683f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber#include <media/stagefright/foundation/hexdump.h>
2783f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber
2883f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Hubernamespace android {
2983f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber
3083f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huberstatic const int32_t kSampleRate = 16000;
3183f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber
3283f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Hubertemplate<class T>
3383f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huberstatic void InitOMXParams(T *params) {
3483f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber    params->nSize = sizeof(T);
3583f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber    params->nVersion.s.nVersionMajor = 1;
3683f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber    params->nVersion.s.nVersionMinor = 0;
3783f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber    params->nVersion.s.nRevision = 0;
3883f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber    params->nVersion.s.nStep = 0;
3983f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber}
4083f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber
4183f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas HuberSoftAMRWBEncoder::SoftAMRWBEncoder(
4283f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber        const char *name,
4383f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber        const OMX_CALLBACKTYPE *callbacks,
4483f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber        OMX_PTR appData,
4583f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber        OMX_COMPONENTTYPE **component)
4683f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber    : SimpleSoftOMXComponent(name, callbacks, appData, component),
4783f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber      mEncoderHandle(NULL),
4883f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber      mApiHandle(NULL),
4983f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber      mMemOperator(NULL),
5083f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber      mBitRate(0),
5183f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber      mMode(VOAMRWB_MD66),
5283f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber      mInputSize(0),
5383f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber      mInputTimeUs(-1ll),
5483f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber      mSawInputEOS(false),
5583f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber      mSignalledError(false) {
5683f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber    initPorts();
5783f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber    CHECK_EQ(initEncoder(), (status_t)OK);
5883f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber}
5983f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber
6083f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas HuberSoftAMRWBEncoder::~SoftAMRWBEncoder() {
6183f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber    if (mEncoderHandle != NULL) {
6283f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber        CHECK_EQ(VO_ERR_NONE, mApiHandle->Uninit(mEncoderHandle));
6383f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber        mEncoderHandle = NULL;
6483f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber    }
6583f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber
6683f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber    delete mApiHandle;
6783f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber    mApiHandle = NULL;
6883f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber
6983f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber    delete mMemOperator;
7083f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber    mMemOperator = NULL;
7183f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber}
7283f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber
7383f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Hubervoid SoftAMRWBEncoder::initPorts() {
7483f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber    OMX_PARAM_PORTDEFINITIONTYPE def;
7583f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber    InitOMXParams(&def);
7683f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber
7783f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber    def.nPortIndex = 0;
7883f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber    def.eDir = OMX_DirInput;
7983f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber    def.nBufferCountMin = kNumBuffers;
8083f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber    def.nBufferCountActual = def.nBufferCountMin;
8183f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber    def.nBufferSize = kNumSamplesPerFrame * sizeof(int16_t);
8283f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber    def.bEnabled = OMX_TRUE;
8383f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber    def.bPopulated = OMX_FALSE;
8483f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber    def.eDomain = OMX_PortDomainAudio;
8583f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber    def.bBuffersContiguous = OMX_FALSE;
8683f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber    def.nBufferAlignment = 1;
8783f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber
8883f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber    def.format.audio.cMIMEType = const_cast<char *>("audio/raw");
8983f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber    def.format.audio.pNativeRender = NULL;
9083f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber    def.format.audio.bFlagErrorConcealment = OMX_FALSE;
9183f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber    def.format.audio.eEncoding = OMX_AUDIO_CodingPCM;
9283f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber
9383f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber    addPort(def);
9483f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber
9583f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber    def.nPortIndex = 1;
9683f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber    def.eDir = OMX_DirOutput;
9783f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber    def.nBufferCountMin = kNumBuffers;
9883f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber    def.nBufferCountActual = def.nBufferCountMin;
9983f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber    def.nBufferSize = 8192;
10083f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber    def.bEnabled = OMX_TRUE;
10183f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber    def.bPopulated = OMX_FALSE;
10283f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber    def.eDomain = OMX_PortDomainAudio;
10383f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber    def.bBuffersContiguous = OMX_FALSE;
10483f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber    def.nBufferAlignment = 2;
10583f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber
10683f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber    def.format.audio.cMIMEType = const_cast<char *>("audio/amr-wb");
10783f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber    def.format.audio.pNativeRender = NULL;
10883f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber    def.format.audio.bFlagErrorConcealment = OMX_FALSE;
10983f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber    def.format.audio.eEncoding = OMX_AUDIO_CodingAMR;
11083f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber
11183f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber    addPort(def);
11283f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber}
11383f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber
11483f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huberstatus_t SoftAMRWBEncoder::initEncoder() {
11583f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber    mApiHandle = new VO_AUDIO_CODECAPI;
11683f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber
11783f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber    if (VO_ERR_NONE != voGetAMRWBEncAPI(mApiHandle)) {
11883f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber        ALOGE("Failed to get api handle");
11983f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber        return UNKNOWN_ERROR;
12083f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber    }
12183f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber
12283f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber    mMemOperator = new VO_MEM_OPERATOR;
12383f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber    mMemOperator->Alloc = cmnMemAlloc;
12483f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber    mMemOperator->Copy = cmnMemCopy;
12583f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber    mMemOperator->Free = cmnMemFree;
12683f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber    mMemOperator->Set = cmnMemSet;
12783f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber    mMemOperator->Check = cmnMemCheck;
12883f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber
12983f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber    VO_CODEC_INIT_USERDATA userData;
13083f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber    memset(&userData, 0, sizeof(userData));
13183f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber    userData.memflag = VO_IMF_USERMEMOPERATOR;
13283f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber    userData.memData = (VO_PTR) mMemOperator;
13383f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber
13483f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber    if (VO_ERR_NONE != mApiHandle->Init(
13583f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber                &mEncoderHandle, VO_AUDIO_CodingAMRWB, &userData)) {
13683f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber        ALOGE("Failed to init AMRWB encoder");
13783f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber        return UNKNOWN_ERROR;
13883f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber    }
13983f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber
14083f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber    VOAMRWBFRAMETYPE type = VOAMRWB_RFC3267;
14183f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber    if (VO_ERR_NONE != mApiHandle->SetParam(
14283f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber                mEncoderHandle, VO_PID_AMRWB_FRAMETYPE, &type)) {
14383f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber        ALOGE("Failed to set AMRWB encoder frame type to %d", type);
14483f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber        return UNKNOWN_ERROR;
14583f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber    }
14683f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber
14783f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber    return OK;
14883f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber}
14983f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber
15083f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas HuberOMX_ERRORTYPE SoftAMRWBEncoder::internalGetParameter(
15183f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber        OMX_INDEXTYPE index, OMX_PTR params) {
15283f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber    switch (index) {
15383f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber        case OMX_IndexParamAudioPortFormat:
15483f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber        {
15583f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber            OMX_AUDIO_PARAM_PORTFORMATTYPE *formatParams =
15683f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber                (OMX_AUDIO_PARAM_PORTFORMATTYPE *)params;
15783f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber
15883f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber            if (formatParams->nPortIndex > 1) {
15983f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber                return OMX_ErrorUndefined;
16083f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber            }
16183f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber
16283f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber            if (formatParams->nIndex > 0) {
16383f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber                return OMX_ErrorNoMore;
16483f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber            }
16583f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber
16683f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber            formatParams->eEncoding =
16783f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber                (formatParams->nPortIndex == 0)
16883f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber                    ? OMX_AUDIO_CodingPCM : OMX_AUDIO_CodingAMR;
16983f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber
17083f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber            return OMX_ErrorNone;
17183f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber        }
17283f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber
17383f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber        case OMX_IndexParamAudioAmr:
17483f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber        {
17583f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber            OMX_AUDIO_PARAM_AMRTYPE *amrParams =
17683f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber                (OMX_AUDIO_PARAM_AMRTYPE *)params;
17783f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber
17883f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber            if (amrParams->nPortIndex != 1) {
17983f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber                return OMX_ErrorUndefined;
18083f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber            }
18183f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber
18283f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber            amrParams->nChannels = 1;
18383f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber            amrParams->nBitRate = mBitRate;
18483f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber
18583f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber            amrParams->eAMRBandMode =
18683f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber                (OMX_AUDIO_AMRBANDMODETYPE)(mMode + OMX_AUDIO_AMRBandModeWB0);
18783f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber
18883f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber            amrParams->eAMRDTXMode = OMX_AUDIO_AMRDTXModeOff;
18983f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber            amrParams->eAMRFrameFormat = OMX_AUDIO_AMRFrameFormatFSF;
19083f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber
19183f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber            return OMX_ErrorNone;
19283f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber        }
19383f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber
19483f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber        case OMX_IndexParamAudioPcm:
19583f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber        {
19683f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber            OMX_AUDIO_PARAM_PCMMODETYPE *pcmParams =
19783f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber                (OMX_AUDIO_PARAM_PCMMODETYPE *)params;
19883f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber
19983f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber            if (pcmParams->nPortIndex != 0) {
20083f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber                return OMX_ErrorUndefined;
20183f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber            }
20283f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber
20383f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber            pcmParams->eNumData = OMX_NumericalDataSigned;
20483f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber            pcmParams->eEndian = OMX_EndianBig;
20583f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber            pcmParams->bInterleaved = OMX_TRUE;
20683f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber            pcmParams->nBitPerSample = 16;
20783f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber            pcmParams->ePCMMode = OMX_AUDIO_PCMModeLinear;
20883f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber            pcmParams->eChannelMapping[0] = OMX_AUDIO_ChannelCF;
20983f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber
21083f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber            pcmParams->nChannels = 1;
21183f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber            pcmParams->nSamplingRate = kSampleRate;
21283f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber
21383f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber            return OMX_ErrorNone;
21483f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber        }
21583f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber
21683f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber        default:
21783f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber            return SimpleSoftOMXComponent::internalGetParameter(index, params);
21883f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber    }
21983f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber}
22083f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber
22183f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas HuberOMX_ERRORTYPE SoftAMRWBEncoder::internalSetParameter(
22283f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber        OMX_INDEXTYPE index, const OMX_PTR params) {
22383f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber    switch (index) {
22483f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber        case OMX_IndexParamStandardComponentRole:
22583f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber        {
22683f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber            const OMX_PARAM_COMPONENTROLETYPE *roleParams =
22783f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber                (const OMX_PARAM_COMPONENTROLETYPE *)params;
22883f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber
22983f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber            if (strncmp((const char *)roleParams->cRole,
23083f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber                        "audio_encoder.amrwb",
23183f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber                        OMX_MAX_STRINGNAME_SIZE - 1)) {
23283f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber                return OMX_ErrorUndefined;
23383f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber            }
23483f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber
23583f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber            return OMX_ErrorNone;
23683f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber        }
23783f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber
23883f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber        case OMX_IndexParamAudioPortFormat:
23983f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber        {
24083f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber            const OMX_AUDIO_PARAM_PORTFORMATTYPE *formatParams =
24183f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber                (const OMX_AUDIO_PARAM_PORTFORMATTYPE *)params;
24283f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber
24383f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber            if (formatParams->nPortIndex > 1) {
24483f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber                return OMX_ErrorUndefined;
24583f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber            }
24683f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber
24783f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber            if (formatParams->nIndex > 0) {
24883f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber                return OMX_ErrorNoMore;
24983f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber            }
25083f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber
25183f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber            if ((formatParams->nPortIndex == 0
25283f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber                        && formatParams->eEncoding != OMX_AUDIO_CodingPCM)
25383f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber                || (formatParams->nPortIndex == 1
25483f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber                        && formatParams->eEncoding != OMX_AUDIO_CodingAMR)) {
25583f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber                return OMX_ErrorUndefined;
25683f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber            }
25783f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber
25883f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber            return OMX_ErrorNone;
25983f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber        }
26083f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber
26183f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber        case OMX_IndexParamAudioAmr:
26283f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber        {
26383f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber            OMX_AUDIO_PARAM_AMRTYPE *amrParams =
26483f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber                (OMX_AUDIO_PARAM_AMRTYPE *)params;
26583f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber
26683f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber            if (amrParams->nPortIndex != 1) {
26783f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber                return OMX_ErrorUndefined;
26883f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber            }
26983f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber
27083f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber            if (amrParams->nChannels != 1
27183f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber                    || amrParams->eAMRDTXMode != OMX_AUDIO_AMRDTXModeOff
27283f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber                    || amrParams->eAMRFrameFormat
27383f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber                            != OMX_AUDIO_AMRFrameFormatFSF
27483f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber                    || amrParams->eAMRBandMode < OMX_AUDIO_AMRBandModeWB0
27583f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber                    || amrParams->eAMRBandMode > OMX_AUDIO_AMRBandModeWB8) {
27683f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber                return OMX_ErrorUndefined;
27783f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber            }
27883f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber
27983f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber            mBitRate = amrParams->nBitRate;
28083f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber
28183f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber            mMode = (VOAMRWBMODE)(
28283f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber                    amrParams->eAMRBandMode - OMX_AUDIO_AMRBandModeWB0);
28383f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber
28483f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber            amrParams->eAMRDTXMode = OMX_AUDIO_AMRDTXModeOff;
28583f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber            amrParams->eAMRFrameFormat = OMX_AUDIO_AMRFrameFormatFSF;
28683f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber
28783f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber            if (VO_ERR_NONE !=
28883f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber                    mApiHandle->SetParam(
28983f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber                        mEncoderHandle, VO_PID_AMRWB_MODE,  &mMode)) {
29083f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber                ALOGE("Failed to set AMRWB encoder mode to %d", mMode);
29183f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber                return OMX_ErrorUndefined;
29283f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber            }
29383f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber
29483f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber            return OMX_ErrorNone;
29583f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber        }
29683f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber
29783f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber        case OMX_IndexParamAudioPcm:
29883f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber        {
29983f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber            OMX_AUDIO_PARAM_PCMMODETYPE *pcmParams =
30083f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber                (OMX_AUDIO_PARAM_PCMMODETYPE *)params;
30183f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber
30283f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber            if (pcmParams->nPortIndex != 0) {
30383f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber                return OMX_ErrorUndefined;
30483f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber            }
30583f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber
30683f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber            if (pcmParams->nChannels != 1
30783f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber                    || pcmParams->nSamplingRate != (OMX_U32)kSampleRate) {
30883f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber                return OMX_ErrorUndefined;
30983f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber            }
31083f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber
31183f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber            return OMX_ErrorNone;
31283f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber        }
31383f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber
31483f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber
31583f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber        default:
31683f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber            return SimpleSoftOMXComponent::internalSetParameter(index, params);
31783f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber    }
31883f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber}
31983f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber
32084333e0475bc911adc16417f4ca327c975cf6c36Andreas Hubervoid SoftAMRWBEncoder::onQueueFilled(OMX_U32 /* portIndex */) {
32183f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber    if (mSignalledError) {
32283f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber        return;
32383f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber    }
32483f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber
32583f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber    List<BufferInfo *> &inQueue = getPortQueue(0);
32683f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber    List<BufferInfo *> &outQueue = getPortQueue(1);
32783f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber
32883f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber    size_t numBytesPerInputFrame = kNumSamplesPerFrame * sizeof(int16_t);
32983f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber
33083f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber    for (;;) {
33183f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber        // We do the following until we run out of buffers.
33283f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber
33383f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber        while (mInputSize < numBytesPerInputFrame) {
33483f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber            // As long as there's still input data to be read we
33583f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber            // will drain "kNumSamplesPerFrame" samples
33683f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber            // into the "mInputFrame" buffer and then encode those
33783f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber            // as a unit into an output buffer.
33883f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber
33983f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber            if (mSawInputEOS || inQueue.empty()) {
34083f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber                return;
34183f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber            }
34283f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber
34383f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber            BufferInfo *inInfo = *inQueue.begin();
34483f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber            OMX_BUFFERHEADERTYPE *inHeader = inInfo->mHeader;
34583f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber
34683f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber            const void *inData = inHeader->pBuffer + inHeader->nOffset;
34783f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber
34883f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber            size_t copy = numBytesPerInputFrame - mInputSize;
34983f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber            if (copy > inHeader->nFilledLen) {
35083f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber                copy = inHeader->nFilledLen;
35183f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber            }
35283f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber
35383f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber            if (mInputSize == 0) {
35483f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber                mInputTimeUs = inHeader->nTimeStamp;
35583f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber            }
35683f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber
35783f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber            memcpy((uint8_t *)mInputFrame + mInputSize, inData, copy);
35883f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber            mInputSize += copy;
35983f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber
36083f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber            inHeader->nOffset += copy;
36183f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber            inHeader->nFilledLen -= copy;
36283f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber
36383f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber            // "Time" on the input buffer has in effect advanced by the
36483f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber            // number of audio frames we just advanced nOffset by.
36583f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber            inHeader->nTimeStamp +=
36683f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber                (copy * 1000000ll / kSampleRate) / sizeof(int16_t);
36783f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber
36883f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber            if (inHeader->nFilledLen == 0) {
36983f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber                if (inHeader->nFlags & OMX_BUFFERFLAG_EOS) {
37083f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber                    ALOGV("saw input EOS");
37183f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber                    mSawInputEOS = true;
37283f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber
37383f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber                    // Pad any remaining data with zeroes.
37483f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber                    memset((uint8_t *)mInputFrame + mInputSize,
37583f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber                           0,
37683f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber                           numBytesPerInputFrame - mInputSize);
37783f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber
37883f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber                    mInputSize = numBytesPerInputFrame;
37983f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber                }
38083f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber
38183f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber                inQueue.erase(inQueue.begin());
38283f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber                inInfo->mOwnedByUs = false;
38383f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber                notifyEmptyBufferDone(inHeader);
38483f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber
38583f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber                inData = NULL;
38683f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber                inHeader = NULL;
38783f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber                inInfo = NULL;
38883f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber            }
38983f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber        }
39083f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber
39183f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber        // At this  point we have all the input data necessary to encode
39283f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber        // a single frame, all we need is an output buffer to store the result
39383f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber        // in.
39483f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber
39583f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber        if (outQueue.empty()) {
39683f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber            return;
39783f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber        }
39883f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber
39983f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber        BufferInfo *outInfo = *outQueue.begin();
40083f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber        OMX_BUFFERHEADERTYPE *outHeader = outInfo->mHeader;
40183f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber
40283f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber        uint8_t *outPtr = outHeader->pBuffer + outHeader->nOffset;
40383f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber        size_t outAvailable = outHeader->nAllocLen - outHeader->nOffset;
40483f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber
40583f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber        VO_CODECBUFFER inputData;
40683f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber        memset(&inputData, 0, sizeof(inputData));
40783f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber        inputData.Buffer = (unsigned char *) mInputFrame;
40883f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber        inputData.Length = mInputSize;
40983f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber
41083f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber        CHECK_EQ(VO_ERR_NONE,
41183f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber                 mApiHandle->SetInputData(mEncoderHandle, &inputData));
41283f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber
41383f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber        VO_CODECBUFFER outputData;
41483f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber        memset(&outputData, 0, sizeof(outputData));
41583f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber        VO_AUDIO_OUTPUTINFO outputInfo;
41683f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber        memset(&outputInfo, 0, sizeof(outputInfo));
41783f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber
41883f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber        outputData.Buffer = outPtr;
41983f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber        outputData.Length = outAvailable;
42083f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber        VO_U32 ret = mApiHandle->GetOutputData(
42183f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber                mEncoderHandle, &outputData, &outputInfo);
42283f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber        CHECK(ret == VO_ERR_NONE || ret == VO_ERR_INPUT_BUFFER_SMALL);
42383f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber
42483f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber        outHeader->nFilledLen = outputData.Length;
42583f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber        outHeader->nFlags = OMX_BUFFERFLAG_ENDOFFRAME;
42683f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber
42783f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber        if (mSawInputEOS) {
42883f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber            // We also tag this output buffer with EOS if it corresponds
42983f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber            // to the final input buffer.
43083f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber            outHeader->nFlags = OMX_BUFFERFLAG_EOS;
43183f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber        }
43283f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber
43383f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber        outHeader->nTimeStamp = mInputTimeUs;
43483f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber
43583f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber#if 0
43683f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber        ALOGI("sending %ld bytes of data (time = %lld us, flags = 0x%08lx)",
43783f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber              outHeader->nFilledLen, mInputTimeUs, outHeader->nFlags);
43883f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber
43983f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber        hexdump(outHeader->pBuffer + outHeader->nOffset, outHeader->nFilledLen);
44083f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber#endif
44183f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber
44283f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber        outQueue.erase(outQueue.begin());
44383f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber        outInfo->mOwnedByUs = false;
44483f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber        notifyFillBufferDone(outHeader);
44583f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber
44683f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber        outHeader = NULL;
44783f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber        outInfo = NULL;
44883f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber
44983f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber        mInputSize = 0;
45083f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber    }
45183f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber}
45283f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber
45383f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber}  // namespace android
45483f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber
45583f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huberandroid::SoftOMXComponent *createSoftOMXComponent(
45683f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber        const char *name, const OMX_CALLBACKTYPE *callbacks,
45783f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber        OMX_PTR appData, OMX_COMPONENTTYPE **component) {
45883f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber    return new android::SoftAMRWBEncoder(name, callbacks, appData, component);
45983f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber}
460