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
1582720c8b094cfa58de314daa8e5e4fb4fa81fe3b2Marco Nelissen            if (!isValidOMXParam(formatParams)) {
1592720c8b094cfa58de314daa8e5e4fb4fa81fe3b2Marco Nelissen                return OMX_ErrorBadParameter;
1602720c8b094cfa58de314daa8e5e4fb4fa81fe3b2Marco Nelissen            }
1612720c8b094cfa58de314daa8e5e4fb4fa81fe3b2Marco Nelissen
16283f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber            if (formatParams->nPortIndex > 1) {
16383f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber                return OMX_ErrorUndefined;
16483f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber            }
16583f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber
16683f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber            if (formatParams->nIndex > 0) {
16783f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber                return OMX_ErrorNoMore;
16883f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber            }
16983f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber
17083f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber            formatParams->eEncoding =
17183f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber                (formatParams->nPortIndex == 0)
17283f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber                    ? OMX_AUDIO_CodingPCM : OMX_AUDIO_CodingAMR;
17383f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber
17483f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber            return OMX_ErrorNone;
17583f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber        }
17683f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber
17783f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber        case OMX_IndexParamAudioAmr:
17883f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber        {
17983f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber            OMX_AUDIO_PARAM_AMRTYPE *amrParams =
18083f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber                (OMX_AUDIO_PARAM_AMRTYPE *)params;
18183f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber
1822720c8b094cfa58de314daa8e5e4fb4fa81fe3b2Marco Nelissen            if (!isValidOMXParam(amrParams)) {
1832720c8b094cfa58de314daa8e5e4fb4fa81fe3b2Marco Nelissen                return OMX_ErrorBadParameter;
1842720c8b094cfa58de314daa8e5e4fb4fa81fe3b2Marco Nelissen            }
1852720c8b094cfa58de314daa8e5e4fb4fa81fe3b2Marco Nelissen
18683f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber            if (amrParams->nPortIndex != 1) {
18783f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber                return OMX_ErrorUndefined;
18883f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber            }
18983f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber
19083f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber            amrParams->nChannels = 1;
19183f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber            amrParams->nBitRate = mBitRate;
19283f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber
19383f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber            amrParams->eAMRBandMode =
19483f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber                (OMX_AUDIO_AMRBANDMODETYPE)(mMode + OMX_AUDIO_AMRBandModeWB0);
19583f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber
19683f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber            amrParams->eAMRDTXMode = OMX_AUDIO_AMRDTXModeOff;
19783f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber            amrParams->eAMRFrameFormat = OMX_AUDIO_AMRFrameFormatFSF;
19883f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber
19983f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber            return OMX_ErrorNone;
20083f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber        }
20183f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber
20283f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber        case OMX_IndexParamAudioPcm:
20383f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber        {
20483f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber            OMX_AUDIO_PARAM_PCMMODETYPE *pcmParams =
20583f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber                (OMX_AUDIO_PARAM_PCMMODETYPE *)params;
20683f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber
2072720c8b094cfa58de314daa8e5e4fb4fa81fe3b2Marco Nelissen            if (!isValidOMXParam(pcmParams)) {
2082720c8b094cfa58de314daa8e5e4fb4fa81fe3b2Marco Nelissen                return OMX_ErrorBadParameter;
2092720c8b094cfa58de314daa8e5e4fb4fa81fe3b2Marco Nelissen            }
2102720c8b094cfa58de314daa8e5e4fb4fa81fe3b2Marco Nelissen
21183f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber            if (pcmParams->nPortIndex != 0) {
21283f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber                return OMX_ErrorUndefined;
21383f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber            }
21483f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber
21583f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber            pcmParams->eNumData = OMX_NumericalDataSigned;
21683f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber            pcmParams->eEndian = OMX_EndianBig;
21783f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber            pcmParams->bInterleaved = OMX_TRUE;
21883f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber            pcmParams->nBitPerSample = 16;
21983f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber            pcmParams->ePCMMode = OMX_AUDIO_PCMModeLinear;
22083f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber            pcmParams->eChannelMapping[0] = OMX_AUDIO_ChannelCF;
22183f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber
22283f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber            pcmParams->nChannels = 1;
22383f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber            pcmParams->nSamplingRate = kSampleRate;
22483f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber
22583f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber            return OMX_ErrorNone;
22683f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber        }
22783f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber
22883f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber        default:
22983f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber            return SimpleSoftOMXComponent::internalGetParameter(index, params);
23083f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber    }
23183f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber}
23283f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber
23383f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas HuberOMX_ERRORTYPE SoftAMRWBEncoder::internalSetParameter(
23483f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber        OMX_INDEXTYPE index, const OMX_PTR params) {
23583f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber    switch (index) {
23683f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber        case OMX_IndexParamStandardComponentRole:
23783f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber        {
23883f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber            const OMX_PARAM_COMPONENTROLETYPE *roleParams =
23983f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber                (const OMX_PARAM_COMPONENTROLETYPE *)params;
24083f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber
2412720c8b094cfa58de314daa8e5e4fb4fa81fe3b2Marco Nelissen            if (!isValidOMXParam(roleParams)) {
2422720c8b094cfa58de314daa8e5e4fb4fa81fe3b2Marco Nelissen                return OMX_ErrorBadParameter;
2432720c8b094cfa58de314daa8e5e4fb4fa81fe3b2Marco Nelissen            }
2442720c8b094cfa58de314daa8e5e4fb4fa81fe3b2Marco Nelissen
24583f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber            if (strncmp((const char *)roleParams->cRole,
24683f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber                        "audio_encoder.amrwb",
24783f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber                        OMX_MAX_STRINGNAME_SIZE - 1)) {
24883f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber                return OMX_ErrorUndefined;
24983f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber            }
25083f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber
25183f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber            return OMX_ErrorNone;
25283f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber        }
25383f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber
25483f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber        case OMX_IndexParamAudioPortFormat:
25583f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber        {
25683f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber            const OMX_AUDIO_PARAM_PORTFORMATTYPE *formatParams =
25783f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber                (const OMX_AUDIO_PARAM_PORTFORMATTYPE *)params;
25883f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber
2592720c8b094cfa58de314daa8e5e4fb4fa81fe3b2Marco Nelissen            if (!isValidOMXParam(formatParams)) {
2602720c8b094cfa58de314daa8e5e4fb4fa81fe3b2Marco Nelissen                return OMX_ErrorBadParameter;
2612720c8b094cfa58de314daa8e5e4fb4fa81fe3b2Marco Nelissen            }
2622720c8b094cfa58de314daa8e5e4fb4fa81fe3b2Marco Nelissen
26383f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber            if (formatParams->nPortIndex > 1) {
26483f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber                return OMX_ErrorUndefined;
26583f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber            }
26683f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber
26783f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber            if ((formatParams->nPortIndex == 0
26883f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber                        && formatParams->eEncoding != OMX_AUDIO_CodingPCM)
26983f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber                || (formatParams->nPortIndex == 1
27083f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber                        && formatParams->eEncoding != OMX_AUDIO_CodingAMR)) {
27183f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber                return OMX_ErrorUndefined;
27283f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber            }
27383f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber
27483f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber            return OMX_ErrorNone;
27583f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber        }
27683f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber
27783f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber        case OMX_IndexParamAudioAmr:
27883f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber        {
27983f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber            OMX_AUDIO_PARAM_AMRTYPE *amrParams =
28083f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber                (OMX_AUDIO_PARAM_AMRTYPE *)params;
28183f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber
2822720c8b094cfa58de314daa8e5e4fb4fa81fe3b2Marco Nelissen            if (!isValidOMXParam(amrParams)) {
2832720c8b094cfa58de314daa8e5e4fb4fa81fe3b2Marco Nelissen                return OMX_ErrorBadParameter;
2842720c8b094cfa58de314daa8e5e4fb4fa81fe3b2Marco Nelissen            }
2852720c8b094cfa58de314daa8e5e4fb4fa81fe3b2Marco Nelissen
28683f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber            if (amrParams->nPortIndex != 1) {
28783f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber                return OMX_ErrorUndefined;
28883f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber            }
28983f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber
29083f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber            if (amrParams->nChannels != 1
29183f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber                    || amrParams->eAMRDTXMode != OMX_AUDIO_AMRDTXModeOff
29283f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber                    || amrParams->eAMRFrameFormat
29383f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber                            != OMX_AUDIO_AMRFrameFormatFSF
29483f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber                    || amrParams->eAMRBandMode < OMX_AUDIO_AMRBandModeWB0
29583f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber                    || amrParams->eAMRBandMode > OMX_AUDIO_AMRBandModeWB8) {
29683f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber                return OMX_ErrorUndefined;
29783f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber            }
29883f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber
29983f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber            mBitRate = amrParams->nBitRate;
30083f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber
30183f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber            mMode = (VOAMRWBMODE)(
30283f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber                    amrParams->eAMRBandMode - OMX_AUDIO_AMRBandModeWB0);
30383f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber
30483f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber            amrParams->eAMRDTXMode = OMX_AUDIO_AMRDTXModeOff;
30583f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber            amrParams->eAMRFrameFormat = OMX_AUDIO_AMRFrameFormatFSF;
30683f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber
30783f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber            if (VO_ERR_NONE !=
30883f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber                    mApiHandle->SetParam(
30983f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber                        mEncoderHandle, VO_PID_AMRWB_MODE,  &mMode)) {
31083f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber                ALOGE("Failed to set AMRWB encoder mode to %d", mMode);
31183f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber                return OMX_ErrorUndefined;
31283f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber            }
31383f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber
31483f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber            return OMX_ErrorNone;
31583f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber        }
31683f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber
31783f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber        case OMX_IndexParamAudioPcm:
31883f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber        {
31983f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber            OMX_AUDIO_PARAM_PCMMODETYPE *pcmParams =
32083f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber                (OMX_AUDIO_PARAM_PCMMODETYPE *)params;
32183f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber
3222720c8b094cfa58de314daa8e5e4fb4fa81fe3b2Marco Nelissen            if (!isValidOMXParam(pcmParams)) {
3232720c8b094cfa58de314daa8e5e4fb4fa81fe3b2Marco Nelissen                return OMX_ErrorBadParameter;
3242720c8b094cfa58de314daa8e5e4fb4fa81fe3b2Marco Nelissen            }
3252720c8b094cfa58de314daa8e5e4fb4fa81fe3b2Marco Nelissen
32683f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber            if (pcmParams->nPortIndex != 0) {
32783f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber                return OMX_ErrorUndefined;
32883f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber            }
32983f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber
33083f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber            if (pcmParams->nChannels != 1
33183f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber                    || pcmParams->nSamplingRate != (OMX_U32)kSampleRate) {
33283f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber                return OMX_ErrorUndefined;
33383f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber            }
33483f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber
33583f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber            return OMX_ErrorNone;
33683f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber        }
33783f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber
33883f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber
33983f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber        default:
34083f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber            return SimpleSoftOMXComponent::internalSetParameter(index, params);
34183f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber    }
34283f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber}
34383f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber
34484333e0475bc911adc16417f4ca327c975cf6c36Andreas Hubervoid SoftAMRWBEncoder::onQueueFilled(OMX_U32 /* portIndex */) {
34583f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber    if (mSignalledError) {
34683f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber        return;
34783f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber    }
34883f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber
34983f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber    List<BufferInfo *> &inQueue = getPortQueue(0);
35083f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber    List<BufferInfo *> &outQueue = getPortQueue(1);
35183f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber
35283f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber    size_t numBytesPerInputFrame = kNumSamplesPerFrame * sizeof(int16_t);
35383f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber
35483f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber    for (;;) {
35583f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber        // We do the following until we run out of buffers.
35683f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber
35783f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber        while (mInputSize < numBytesPerInputFrame) {
35883f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber            // As long as there's still input data to be read we
35983f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber            // will drain "kNumSamplesPerFrame" samples
36083f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber            // into the "mInputFrame" buffer and then encode those
36183f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber            // as a unit into an output buffer.
36283f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber
36383f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber            if (mSawInputEOS || inQueue.empty()) {
36483f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber                return;
36583f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber            }
36683f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber
36783f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber            BufferInfo *inInfo = *inQueue.begin();
36883f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber            OMX_BUFFERHEADERTYPE *inHeader = inInfo->mHeader;
36983f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber
37083f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber            const void *inData = inHeader->pBuffer + inHeader->nOffset;
37183f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber
37283f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber            size_t copy = numBytesPerInputFrame - mInputSize;
37383f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber            if (copy > inHeader->nFilledLen) {
37483f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber                copy = inHeader->nFilledLen;
37583f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber            }
37683f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber
37783f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber            if (mInputSize == 0) {
37883f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber                mInputTimeUs = inHeader->nTimeStamp;
37983f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber            }
38083f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber
38183f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber            memcpy((uint8_t *)mInputFrame + mInputSize, inData, copy);
38283f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber            mInputSize += copy;
38383f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber
38483f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber            inHeader->nOffset += copy;
38583f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber            inHeader->nFilledLen -= copy;
38683f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber
38783f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber            // "Time" on the input buffer has in effect advanced by the
38883f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber            // number of audio frames we just advanced nOffset by.
38983f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber            inHeader->nTimeStamp +=
39083f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber                (copy * 1000000ll / kSampleRate) / sizeof(int16_t);
39183f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber
39283f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber            if (inHeader->nFilledLen == 0) {
39383f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber                if (inHeader->nFlags & OMX_BUFFERFLAG_EOS) {
39483f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber                    ALOGV("saw input EOS");
39583f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber                    mSawInputEOS = true;
39683f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber
39783f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber                    // Pad any remaining data with zeroes.
39883f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber                    memset((uint8_t *)mInputFrame + mInputSize,
39983f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber                           0,
40083f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber                           numBytesPerInputFrame - mInputSize);
40183f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber
40283f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber                    mInputSize = numBytesPerInputFrame;
40383f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber                }
40483f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber
40583f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber                inQueue.erase(inQueue.begin());
40683f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber                inInfo->mOwnedByUs = false;
40783f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber                notifyEmptyBufferDone(inHeader);
40883f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber
40983f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber                inData = NULL;
41083f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber                inHeader = NULL;
41183f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber                inInfo = NULL;
41283f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber            }
41383f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber        }
41483f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber
41583f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber        // At this  point we have all the input data necessary to encode
41683f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber        // a single frame, all we need is an output buffer to store the result
41783f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber        // in.
41883f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber
41983f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber        if (outQueue.empty()) {
42083f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber            return;
42183f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber        }
42283f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber
42383f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber        BufferInfo *outInfo = *outQueue.begin();
42483f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber        OMX_BUFFERHEADERTYPE *outHeader = outInfo->mHeader;
42583f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber
42683f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber        uint8_t *outPtr = outHeader->pBuffer + outHeader->nOffset;
42783f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber        size_t outAvailable = outHeader->nAllocLen - outHeader->nOffset;
42883f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber
42983f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber        VO_CODECBUFFER inputData;
43083f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber        memset(&inputData, 0, sizeof(inputData));
43183f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber        inputData.Buffer = (unsigned char *) mInputFrame;
43283f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber        inputData.Length = mInputSize;
43383f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber
43483f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber        CHECK_EQ(VO_ERR_NONE,
43583f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber                 mApiHandle->SetInputData(mEncoderHandle, &inputData));
43683f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber
43783f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber        VO_CODECBUFFER outputData;
43883f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber        memset(&outputData, 0, sizeof(outputData));
43983f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber        VO_AUDIO_OUTPUTINFO outputInfo;
44083f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber        memset(&outputInfo, 0, sizeof(outputInfo));
44183f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber
44283f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber        outputData.Buffer = outPtr;
44383f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber        outputData.Length = outAvailable;
44483f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber        VO_U32 ret = mApiHandle->GetOutputData(
44583f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber                mEncoderHandle, &outputData, &outputInfo);
44683f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber        CHECK(ret == VO_ERR_NONE || ret == VO_ERR_INPUT_BUFFER_SMALL);
44783f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber
44883f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber        outHeader->nFilledLen = outputData.Length;
44983f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber        outHeader->nFlags = OMX_BUFFERFLAG_ENDOFFRAME;
45083f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber
45183f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber        if (mSawInputEOS) {
45283f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber            // We also tag this output buffer with EOS if it corresponds
45383f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber            // to the final input buffer.
45483f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber            outHeader->nFlags = OMX_BUFFERFLAG_EOS;
45583f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber        }
45683f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber
45783f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber        outHeader->nTimeStamp = mInputTimeUs;
45883f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber
45983f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber#if 0
46083f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber        ALOGI("sending %ld bytes of data (time = %lld us, flags = 0x%08lx)",
46183f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber              outHeader->nFilledLen, mInputTimeUs, outHeader->nFlags);
46283f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber
46383f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber        hexdump(outHeader->pBuffer + outHeader->nOffset, outHeader->nFilledLen);
46483f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber#endif
46583f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber
46683f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber        outQueue.erase(outQueue.begin());
46783f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber        outInfo->mOwnedByUs = false;
46883f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber        notifyFillBufferDone(outHeader);
46983f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber
47083f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber        outHeader = NULL;
47183f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber        outInfo = NULL;
47283f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber
47383f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber        mInputSize = 0;
47483f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber    }
47583f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber}
47683f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber
47783f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber}  // namespace android
47883f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber
47983f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huberandroid::SoftOMXComponent *createSoftOMXComponent(
48083f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber        const char *name, const OMX_CALLBACKTYPE *callbacks,
48183f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber        OMX_PTR appData, OMX_COMPONENTTYPE **component) {
48283f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber    return new android::SoftAMRWBEncoder(name, callbacks, appData, component);
48383f70f4472e9b0cacc5d372eddfcef4b02662d10Andreas Huber}
484