1bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber/*
2bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber * Copyright (C) 2011 The Android Open Source Project
3bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber *
4bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber * Licensed under the Apache License, Version 2.0 (the "License");
5bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber * you may not use this file except in compliance with the License.
6bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber * You may obtain a copy of the License at
7bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber *
8bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber *      http://www.apache.org/licenses/LICENSE-2.0
9bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber *
10bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber * Unless required by applicable law or agreed to in writing, software
11bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber * distributed under the License is distributed on an "AS IS" BASIS,
12bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber * See the License for the specific language governing permissions and
14bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber * limitations under the License.
15bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber */
16bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
17bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber//#define LOG_NDEBUG 0
18bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber#define LOG_TAG "SoftMP3"
19bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber#include <utils/Log.h>
20bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
21bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber#include "SoftMP3.h"
22bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
23bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber#include <media/stagefright/foundation/ADebug.h>
24bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber#include <media/stagefright/MediaDefs.h>
25bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
26bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber#include "include/pvmp3decoder_api.h"
27bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
28bbba88cb1bdc34705d1477208990a06904c022e7Andreas Hubernamespace android {
29bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
30bbba88cb1bdc34705d1477208990a06904c022e7Andreas Hubertemplate<class T>
31bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huberstatic void InitOMXParams(T *params) {
32bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    params->nSize = sizeof(T);
33bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    params->nVersion.s.nVersionMajor = 1;
34bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    params->nVersion.s.nVersionMinor = 0;
35bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    params->nVersion.s.nRevision = 0;
36bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    params->nVersion.s.nStep = 0;
37bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber}
38bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
39bbba88cb1bdc34705d1477208990a06904c022e7Andreas HuberSoftMP3::SoftMP3(
40bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        const char *name,
41bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        const OMX_CALLBACKTYPE *callbacks,
42bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        OMX_PTR appData,
43bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        OMX_COMPONENTTYPE **component)
44bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    : SimpleSoftOMXComponent(name, callbacks, appData, component),
45bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber      mConfig(new tPVMP3DecoderExternal),
46bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber      mDecoderBuf(NULL),
47bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber      mAnchorTimeUs(0),
48bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber      mNumFramesOutput(0),
49bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber      mNumChannels(2),
50bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber      mSamplingRate(44100),
51bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber      mSignalledError(false),
52d089c2540e4f0897c166693f4f13e2023241720eMarco Nelissen      mSawInputEos(false),
53d089c2540e4f0897c166693f4f13e2023241720eMarco Nelissen      mSignalledOutputEos(false),
54bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber      mOutputPortSettingsChange(NONE) {
55bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    initPorts();
56bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    initDecoder();
57bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber}
58bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
59bbba88cb1bdc34705d1477208990a06904c022e7Andreas HuberSoftMP3::~SoftMP3() {
60bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    if (mDecoderBuf != NULL) {
61bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        free(mDecoderBuf);
62bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        mDecoderBuf = NULL;
63bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    }
64bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
65bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    delete mConfig;
66bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    mConfig = NULL;
67bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber}
68bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
69bbba88cb1bdc34705d1477208990a06904c022e7Andreas Hubervoid SoftMP3::initPorts() {
70bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    OMX_PARAM_PORTDEFINITIONTYPE def;
71bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    InitOMXParams(&def);
72bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
73bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    def.nPortIndex = 0;
74bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    def.eDir = OMX_DirInput;
75bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    def.nBufferCountMin = kNumBuffers;
76bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    def.nBufferCountActual = def.nBufferCountMin;
77bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    def.nBufferSize = 8192;
78bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    def.bEnabled = OMX_TRUE;
79bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    def.bPopulated = OMX_FALSE;
80bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    def.eDomain = OMX_PortDomainAudio;
81bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    def.bBuffersContiguous = OMX_FALSE;
82bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    def.nBufferAlignment = 1;
83bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
84bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    def.format.audio.cMIMEType =
85bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        const_cast<char *>(MEDIA_MIMETYPE_AUDIO_MPEG);
86bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
87bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    def.format.audio.pNativeRender = NULL;
88bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    def.format.audio.bFlagErrorConcealment = OMX_FALSE;
89bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    def.format.audio.eEncoding = OMX_AUDIO_CodingMP3;
90bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
91bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    addPort(def);
92bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
93bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    def.nPortIndex = 1;
94bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    def.eDir = OMX_DirOutput;
95bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    def.nBufferCountMin = kNumBuffers;
96bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    def.nBufferCountActual = def.nBufferCountMin;
97bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    def.nBufferSize = kOutputBufferSize;
98bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    def.bEnabled = OMX_TRUE;
99bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    def.bPopulated = OMX_FALSE;
100bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    def.eDomain = OMX_PortDomainAudio;
101bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    def.bBuffersContiguous = OMX_FALSE;
102bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    def.nBufferAlignment = 2;
103bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
104bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    def.format.audio.cMIMEType = const_cast<char *>("audio/raw");
105bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    def.format.audio.pNativeRender = NULL;
106bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    def.format.audio.bFlagErrorConcealment = OMX_FALSE;
107bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    def.format.audio.eEncoding = OMX_AUDIO_CodingPCM;
108bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
109bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    addPort(def);
110bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber}
111bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
112bbba88cb1bdc34705d1477208990a06904c022e7Andreas Hubervoid SoftMP3::initDecoder() {
113bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    mConfig->equalizerType = flat;
114bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    mConfig->crcEnabled = false;
115bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
116bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    uint32_t memRequirements = pvmp3_decoderMemRequirements();
117bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    mDecoderBuf = malloc(memRequirements);
118bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
119bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    pvmp3_InitDecoder(mConfig, mDecoderBuf);
120a98478bfbcc0f7fb4b164d3dce40ca96df75667dMarco Nelissen    mIsFirst = true;
121bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber}
122bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
123bbba88cb1bdc34705d1477208990a06904c022e7Andreas HuberOMX_ERRORTYPE SoftMP3::internalGetParameter(
124bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        OMX_INDEXTYPE index, OMX_PTR params) {
125bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    switch (index) {
126bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        case OMX_IndexParamAudioPcm:
127bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        {
128bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber            OMX_AUDIO_PARAM_PCMMODETYPE *pcmParams =
129bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber                (OMX_AUDIO_PARAM_PCMMODETYPE *)params;
130bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
131bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber            if (pcmParams->nPortIndex > 1) {
132bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber                return OMX_ErrorUndefined;
133bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber            }
134bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
135bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber            pcmParams->eNumData = OMX_NumericalDataSigned;
136bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber            pcmParams->eEndian = OMX_EndianBig;
137bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber            pcmParams->bInterleaved = OMX_TRUE;
138bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber            pcmParams->nBitPerSample = 16;
139bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber            pcmParams->ePCMMode = OMX_AUDIO_PCMModeLinear;
140bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber            pcmParams->eChannelMapping[0] = OMX_AUDIO_ChannelLF;
141bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber            pcmParams->eChannelMapping[1] = OMX_AUDIO_ChannelRF;
142bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
143bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber            pcmParams->nChannels = mNumChannels;
144bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber            pcmParams->nSamplingRate = mSamplingRate;
145bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
146bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber            return OMX_ErrorNone;
147bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        }
148bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
149e0381245dff04aa823a59aa8b85869eddab0f39fLajos Molnar        case OMX_IndexParamAudioMp3:
150e0381245dff04aa823a59aa8b85869eddab0f39fLajos Molnar        {
151e0381245dff04aa823a59aa8b85869eddab0f39fLajos Molnar            OMX_AUDIO_PARAM_MP3TYPE *mp3Params =
152e0381245dff04aa823a59aa8b85869eddab0f39fLajos Molnar                (OMX_AUDIO_PARAM_MP3TYPE *)params;
153e0381245dff04aa823a59aa8b85869eddab0f39fLajos Molnar
154e0381245dff04aa823a59aa8b85869eddab0f39fLajos Molnar            if (mp3Params->nPortIndex > 1) {
155e0381245dff04aa823a59aa8b85869eddab0f39fLajos Molnar                return OMX_ErrorUndefined;
156e0381245dff04aa823a59aa8b85869eddab0f39fLajos Molnar            }
157e0381245dff04aa823a59aa8b85869eddab0f39fLajos Molnar
158e0381245dff04aa823a59aa8b85869eddab0f39fLajos Molnar            mp3Params->nChannels = mNumChannels;
159e0381245dff04aa823a59aa8b85869eddab0f39fLajos Molnar            mp3Params->nBitRate = 0 /* unknown */;
160e0381245dff04aa823a59aa8b85869eddab0f39fLajos Molnar            mp3Params->nSampleRate = mSamplingRate;
161e0381245dff04aa823a59aa8b85869eddab0f39fLajos Molnar            // other fields are encoder-only
162e0381245dff04aa823a59aa8b85869eddab0f39fLajos Molnar
163e0381245dff04aa823a59aa8b85869eddab0f39fLajos Molnar            return OMX_ErrorNone;
164e0381245dff04aa823a59aa8b85869eddab0f39fLajos Molnar        }
165e0381245dff04aa823a59aa8b85869eddab0f39fLajos Molnar
166bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        default:
167bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber            return SimpleSoftOMXComponent::internalGetParameter(index, params);
168bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    }
169bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber}
170bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
171bbba88cb1bdc34705d1477208990a06904c022e7Andreas HuberOMX_ERRORTYPE SoftMP3::internalSetParameter(
172bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        OMX_INDEXTYPE index, const OMX_PTR params) {
173bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    switch (index) {
174bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        case OMX_IndexParamStandardComponentRole:
175bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        {
176bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber            const OMX_PARAM_COMPONENTROLETYPE *roleParams =
177bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber                (const OMX_PARAM_COMPONENTROLETYPE *)params;
178bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
179bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber            if (strncmp((const char *)roleParams->cRole,
180bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber                        "audio_decoder.mp3",
181bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber                        OMX_MAX_STRINGNAME_SIZE - 1)) {
182bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber                return OMX_ErrorUndefined;
183bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber            }
184bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
185bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber            return OMX_ErrorNone;
186bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        }
187bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
18842392e49e167c6a0c573e55e1c1b4c7fa0ceb213Andreas Huber        case OMX_IndexParamAudioPcm:
18942392e49e167c6a0c573e55e1c1b4c7fa0ceb213Andreas Huber        {
19042392e49e167c6a0c573e55e1c1b4c7fa0ceb213Andreas Huber            const OMX_AUDIO_PARAM_PCMMODETYPE *pcmParams =
19142392e49e167c6a0c573e55e1c1b4c7fa0ceb213Andreas Huber                (const OMX_AUDIO_PARAM_PCMMODETYPE *)params;
19242392e49e167c6a0c573e55e1c1b4c7fa0ceb213Andreas Huber
19342392e49e167c6a0c573e55e1c1b4c7fa0ceb213Andreas Huber            if (pcmParams->nPortIndex != 1) {
19442392e49e167c6a0c573e55e1c1b4c7fa0ceb213Andreas Huber                return OMX_ErrorUndefined;
19542392e49e167c6a0c573e55e1c1b4c7fa0ceb213Andreas Huber            }
19642392e49e167c6a0c573e55e1c1b4c7fa0ceb213Andreas Huber
19742392e49e167c6a0c573e55e1c1b4c7fa0ceb213Andreas Huber            mNumChannels = pcmParams->nChannels;
19842392e49e167c6a0c573e55e1c1b4c7fa0ceb213Andreas Huber            mSamplingRate = pcmParams->nSamplingRate;
19942392e49e167c6a0c573e55e1c1b4c7fa0ceb213Andreas Huber
20042392e49e167c6a0c573e55e1c1b4c7fa0ceb213Andreas Huber            return OMX_ErrorNone;
20142392e49e167c6a0c573e55e1c1b4c7fa0ceb213Andreas Huber        }
20242392e49e167c6a0c573e55e1c1b4c7fa0ceb213Andreas Huber
203bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        default:
204bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber            return SimpleSoftOMXComponent::internalSetParameter(index, params);
205bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    }
206bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber}
207bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
20884333e0475bc911adc16417f4ca327c975cf6c36Andreas Hubervoid SoftMP3::onQueueFilled(OMX_U32 /* portIndex */) {
209bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    if (mSignalledError || mOutputPortSettingsChange != NONE) {
210bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        return;
211bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    }
212bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
213bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    List<BufferInfo *> &inQueue = getPortQueue(0);
214bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    List<BufferInfo *> &outQueue = getPortQueue(1);
215bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
216d089c2540e4f0897c166693f4f13e2023241720eMarco Nelissen    while ((!inQueue.empty() || (mSawInputEos && !mSignalledOutputEos)) && !outQueue.empty()) {
217d089c2540e4f0897c166693f4f13e2023241720eMarco Nelissen        BufferInfo *inInfo = NULL;
218d089c2540e4f0897c166693f4f13e2023241720eMarco Nelissen        OMX_BUFFERHEADERTYPE *inHeader = NULL;
219d089c2540e4f0897c166693f4f13e2023241720eMarco Nelissen        if (!inQueue.empty()) {
220d089c2540e4f0897c166693f4f13e2023241720eMarco Nelissen            inInfo = *inQueue.begin();
221d089c2540e4f0897c166693f4f13e2023241720eMarco Nelissen            inHeader = inInfo->mHeader;
222d089c2540e4f0897c166693f4f13e2023241720eMarco Nelissen        }
223bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
224bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        BufferInfo *outInfo = *outQueue.begin();
225bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        OMX_BUFFERHEADERTYPE *outHeader = outInfo->mHeader;
226d089c2540e4f0897c166693f4f13e2023241720eMarco Nelissen        outHeader->nFlags = 0;
227bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
228d089c2540e4f0897c166693f4f13e2023241720eMarco Nelissen        if (inHeader) {
229d089c2540e4f0897c166693f4f13e2023241720eMarco Nelissen            if (inHeader->nOffset == 0 && inHeader->nFilledLen) {
230d089c2540e4f0897c166693f4f13e2023241720eMarco Nelissen                mAnchorTimeUs = inHeader->nTimeStamp;
231d089c2540e4f0897c166693f4f13e2023241720eMarco Nelissen                mNumFramesOutput = 0;
232d089c2540e4f0897c166693f4f13e2023241720eMarco Nelissen            }
233b6209a3d4c29bbb88de5a77546f4d545883cc484Eric Laurent
234d089c2540e4f0897c166693f4f13e2023241720eMarco Nelissen            if (inHeader->nFlags & OMX_BUFFERFLAG_EOS) {
235d089c2540e4f0897c166693f4f13e2023241720eMarco Nelissen                mSawInputEos = true;
23651d7547944967d1157b7fe18e1fb8f7ee6810412Andreas Huber            }
23751d7547944967d1157b7fe18e1fb8f7ee6810412Andreas Huber
238d089c2540e4f0897c166693f4f13e2023241720eMarco Nelissen            mConfig->pInputBuffer =
239d089c2540e4f0897c166693f4f13e2023241720eMarco Nelissen                inHeader->pBuffer + inHeader->nOffset;
240bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
241d089c2540e4f0897c166693f4f13e2023241720eMarco Nelissen            mConfig->inputBufferCurrentLength = inHeader->nFilledLen;
242d089c2540e4f0897c166693f4f13e2023241720eMarco Nelissen        } else {
243d089c2540e4f0897c166693f4f13e2023241720eMarco Nelissen            mConfig->pInputBuffer = NULL;
244d089c2540e4f0897c166693f4f13e2023241720eMarco Nelissen            mConfig->inputBufferCurrentLength = 0;
245bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        }
246bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        mConfig->inputBufferMaxLength = 0;
247bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        mConfig->inputBufferUsedLength = 0;
248bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
249bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        mConfig->outputFrameSize = kOutputBufferSize / sizeof(int16_t);
250bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
251bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        mConfig->pOutputBuffer =
252bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber            reinterpret_cast<int16_t *>(outHeader->pBuffer);
253bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
254bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        ERROR_CODE decoderErr;
255bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        if ((decoderErr = pvmp3_framedecoder(mConfig, mDecoderBuf))
256bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber                != NO_DECODING_ERROR) {
2573856b090cd04ba5dd4a59a12430ed724d5995909Steve Block            ALOGV("mp3 decoder returned error %d", decoderErr);
258bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
259259b39cbfc03cb94c48e66d752836e153e9a2f8bAndreas Huber            if (decoderErr != NO_ENOUGH_MAIN_DATA_ERROR
260259b39cbfc03cb94c48e66d752836e153e9a2f8bAndreas Huber                        && decoderErr != SIDE_INFO_ERROR) {
26129357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block                ALOGE("mp3 decoder returned error %d", decoderErr);
262bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
263bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber                notify(OMX_EventError, OMX_ErrorUndefined, decoderErr, NULL);
264bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber                mSignalledError = true;
265bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber                return;
266bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber            }
267bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
268259b39cbfc03cb94c48e66d752836e153e9a2f8bAndreas Huber            if (mConfig->outputFrameSize == 0) {
269259b39cbfc03cb94c48e66d752836e153e9a2f8bAndreas Huber                mConfig->outputFrameSize = kOutputBufferSize / sizeof(int16_t);
270259b39cbfc03cb94c48e66d752836e153e9a2f8bAndreas Huber            }
271259b39cbfc03cb94c48e66d752836e153e9a2f8bAndreas Huber
272d089c2540e4f0897c166693f4f13e2023241720eMarco Nelissen            if (decoderErr == NO_ENOUGH_MAIN_DATA_ERROR && mSawInputEos) {
273d089c2540e4f0897c166693f4f13e2023241720eMarco Nelissen                if (!mIsFirst) {
274d089c2540e4f0897c166693f4f13e2023241720eMarco Nelissen                    // pad the end of the stream with 529 samples, since that many samples
275d089c2540e4f0897c166693f4f13e2023241720eMarco Nelissen                    // were trimmed off the beginning when decoding started
276d089c2540e4f0897c166693f4f13e2023241720eMarco Nelissen                    outHeader->nOffset = 0;
277d089c2540e4f0897c166693f4f13e2023241720eMarco Nelissen                    outHeader->nFilledLen = kPVMP3DecoderDelay * mNumChannels * sizeof(int16_t);
278d089c2540e4f0897c166693f4f13e2023241720eMarco Nelissen
279d089c2540e4f0897c166693f4f13e2023241720eMarco Nelissen                    memset(outHeader->pBuffer, 0, outHeader->nFilledLen);
280d089c2540e4f0897c166693f4f13e2023241720eMarco Nelissen                }
281d089c2540e4f0897c166693f4f13e2023241720eMarco Nelissen                outHeader->nFlags = OMX_BUFFERFLAG_EOS;
282d089c2540e4f0897c166693f4f13e2023241720eMarco Nelissen                mSignalledOutputEos = true;
283d089c2540e4f0897c166693f4f13e2023241720eMarco Nelissen            } else {
284d089c2540e4f0897c166693f4f13e2023241720eMarco Nelissen                // This is recoverable, just ignore the current frame and
285d089c2540e4f0897c166693f4f13e2023241720eMarco Nelissen                // play silence instead.
286c015b84e5d6f5d1e116d71bfbd3bd8edc3b06511Andy Hung
287c015b84e5d6f5d1e116d71bfbd3bd8edc3b06511Andy Hung                // TODO: should we skip silence (and consume input data)
288c015b84e5d6f5d1e116d71bfbd3bd8edc3b06511Andy Hung                // if mIsFirst is true as we may not have a valid
289c015b84e5d6f5d1e116d71bfbd3bd8edc3b06511Andy Hung                // mConfig->samplingRate and mConfig->num_channels?
290c015b84e5d6f5d1e116d71bfbd3bd8edc3b06511Andy Hung                ALOGV_IF(mIsFirst, "insufficient data for first frame, sending silence");
291d089c2540e4f0897c166693f4f13e2023241720eMarco Nelissen                memset(outHeader->pBuffer,
292d089c2540e4f0897c166693f4f13e2023241720eMarco Nelissen                       0,
293d089c2540e4f0897c166693f4f13e2023241720eMarco Nelissen                       mConfig->outputFrameSize * sizeof(int16_t));
294d089c2540e4f0897c166693f4f13e2023241720eMarco Nelissen
295d089c2540e4f0897c166693f4f13e2023241720eMarco Nelissen                if (inHeader) {
296d089c2540e4f0897c166693f4f13e2023241720eMarco Nelissen                    mConfig->inputBufferUsedLength = inHeader->nFilledLen;
297d089c2540e4f0897c166693f4f13e2023241720eMarco Nelissen                }
298d089c2540e4f0897c166693f4f13e2023241720eMarco Nelissen            }
299bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        } else if (mConfig->samplingRate != mSamplingRate
300bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber                || mConfig->num_channels != mNumChannels) {
301bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber            mSamplingRate = mConfig->samplingRate;
302bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber            mNumChannels = mConfig->num_channels;
303bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
304bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber            notify(OMX_EventPortSettingsChanged, 1, 0, NULL);
305bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber            mOutputPortSettingsChange = AWAITING_DISABLED;
306bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber            return;
307bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        }
308bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
309a98478bfbcc0f7fb4b164d3dce40ca96df75667dMarco Nelissen        if (mIsFirst) {
310a98478bfbcc0f7fb4b164d3dce40ca96df75667dMarco Nelissen            mIsFirst = false;
311a98478bfbcc0f7fb4b164d3dce40ca96df75667dMarco Nelissen            // The decoder delay is 529 samples, so trim that many samples off
312a98478bfbcc0f7fb4b164d3dce40ca96df75667dMarco Nelissen            // the start of the first output buffer. This essentially makes this
313a98478bfbcc0f7fb4b164d3dce40ca96df75667dMarco Nelissen            // decoder have zero delay, which the rest of the pipeline assumes.
31451d7547944967d1157b7fe18e1fb8f7ee6810412Andreas Huber            outHeader->nOffset =
31551d7547944967d1157b7fe18e1fb8f7ee6810412Andreas Huber                kPVMP3DecoderDelay * mNumChannels * sizeof(int16_t);
31651d7547944967d1157b7fe18e1fb8f7ee6810412Andreas Huber
31751d7547944967d1157b7fe18e1fb8f7ee6810412Andreas Huber            outHeader->nFilledLen =
31851d7547944967d1157b7fe18e1fb8f7ee6810412Andreas Huber                mConfig->outputFrameSize * sizeof(int16_t) - outHeader->nOffset;
319d089c2540e4f0897c166693f4f13e2023241720eMarco Nelissen        } else if (!mSignalledOutputEos) {
320a98478bfbcc0f7fb4b164d3dce40ca96df75667dMarco Nelissen            outHeader->nOffset = 0;
321a98478bfbcc0f7fb4b164d3dce40ca96df75667dMarco Nelissen            outHeader->nFilledLen = mConfig->outputFrameSize * sizeof(int16_t);
322a98478bfbcc0f7fb4b164d3dce40ca96df75667dMarco Nelissen        }
323bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
324bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        outHeader->nTimeStamp =
325c015b84e5d6f5d1e116d71bfbd3bd8edc3b06511Andy Hung            mAnchorTimeUs + (mNumFramesOutput * 1000000ll) / mSamplingRate;
326bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
327d089c2540e4f0897c166693f4f13e2023241720eMarco Nelissen        if (inHeader) {
328d089c2540e4f0897c166693f4f13e2023241720eMarco Nelissen            CHECK_GE(inHeader->nFilledLen, mConfig->inputBufferUsedLength);
329bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
330d089c2540e4f0897c166693f4f13e2023241720eMarco Nelissen            inHeader->nOffset += mConfig->inputBufferUsedLength;
331d089c2540e4f0897c166693f4f13e2023241720eMarco Nelissen            inHeader->nFilledLen -= mConfig->inputBufferUsedLength;
332bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
3339da36a6c8df70a5c8179ac78fab33cfbb5078cb2Marco Nelissen
334d089c2540e4f0897c166693f4f13e2023241720eMarco Nelissen            if (inHeader->nFilledLen == 0) {
335d089c2540e4f0897c166693f4f13e2023241720eMarco Nelissen                inInfo->mOwnedByUs = false;
336d089c2540e4f0897c166693f4f13e2023241720eMarco Nelissen                inQueue.erase(inQueue.begin());
337d089c2540e4f0897c166693f4f13e2023241720eMarco Nelissen                inInfo = NULL;
338d089c2540e4f0897c166693f4f13e2023241720eMarco Nelissen                notifyEmptyBufferDone(inHeader);
339d089c2540e4f0897c166693f4f13e2023241720eMarco Nelissen                inHeader = NULL;
340d089c2540e4f0897c166693f4f13e2023241720eMarco Nelissen            }
341b6209a3d4c29bbb88de5a77546f4d545883cc484Eric Laurent        }
342b6209a3d4c29bbb88de5a77546f4d545883cc484Eric Laurent
343d089c2540e4f0897c166693f4f13e2023241720eMarco Nelissen        mNumFramesOutput += mConfig->outputFrameSize / mNumChannels;
344d089c2540e4f0897c166693f4f13e2023241720eMarco Nelissen
345bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        outInfo->mOwnedByUs = false;
346bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        outQueue.erase(outQueue.begin());
347bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        outInfo = NULL;
348bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        notifyFillBufferDone(outHeader);
349bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        outHeader = NULL;
350bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    }
351bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber}
352bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
353bbba88cb1bdc34705d1477208990a06904c022e7Andreas Hubervoid SoftMP3::onPortFlushCompleted(OMX_U32 portIndex) {
354bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    if (portIndex == 0) {
355bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        // Make sure that the next buffer output does not still
356bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        // depend on fragments from the last one decoded.
357bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        pvmp3_InitDecoder(mConfig, mDecoderBuf);
358a98478bfbcc0f7fb4b164d3dce40ca96df75667dMarco Nelissen        mIsFirst = true;
3596e56e8024c98c3e6e62772e1dd345dd2c1c36717Marco Nelissen        mSignalledError = false;
3606e56e8024c98c3e6e62772e1dd345dd2c1c36717Marco Nelissen        mSawInputEos = false;
3616e56e8024c98c3e6e62772e1dd345dd2c1c36717Marco Nelissen        mSignalledOutputEos = false;
362bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    }
363bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber}
364bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
365bbba88cb1bdc34705d1477208990a06904c022e7Andreas Hubervoid SoftMP3::onPortEnableCompleted(OMX_U32 portIndex, bool enabled) {
366bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    if (portIndex != 1) {
367bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        return;
368bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    }
369bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
370bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    switch (mOutputPortSettingsChange) {
371bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        case NONE:
372bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber            break;
373bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
374bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        case AWAITING_DISABLED:
375bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        {
376bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber            CHECK(!enabled);
377bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber            mOutputPortSettingsChange = AWAITING_ENABLED;
378bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber            break;
379bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        }
380bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
381bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        default:
382bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        {
383bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber            CHECK_EQ((int)mOutputPortSettingsChange, (int)AWAITING_ENABLED);
384bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber            CHECK(enabled);
385bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber            mOutputPortSettingsChange = NONE;
386bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber            break;
387bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        }
388bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    }
389bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber}
390bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
3916fc72b01a3b67903b52f1d33b1ad5c960b5365f1Marco Nelissenvoid SoftMP3::onReset() {
3926fc72b01a3b67903b52f1d33b1ad5c960b5365f1Marco Nelissen    pvmp3_InitDecoder(mConfig, mDecoderBuf);
3936fc72b01a3b67903b52f1d33b1ad5c960b5365f1Marco Nelissen    mIsFirst = true;
394d94e716af0e49d775f0c0c4f36dd2c136ba5f2b2Andreas Huber    mSignalledError = false;
395d089c2540e4f0897c166693f4f13e2023241720eMarco Nelissen    mSawInputEos = false;
396d089c2540e4f0897c166693f4f13e2023241720eMarco Nelissen    mSignalledOutputEos = false;
397d94e716af0e49d775f0c0c4f36dd2c136ba5f2b2Andreas Huber    mOutputPortSettingsChange = NONE;
3986fc72b01a3b67903b52f1d33b1ad5c960b5365f1Marco Nelissen}
3996fc72b01a3b67903b52f1d33b1ad5c960b5365f1Marco Nelissen
400bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber}  // namespace android
401bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
402bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huberandroid::SoftOMXComponent *createSoftOMXComponent(
403bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        const char *name, const OMX_CALLBACKTYPE *callbacks,
404bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        OMX_PTR appData, OMX_COMPONENTTYPE **component) {
405bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    return new android::SoftMP3(name, callbacks, appData, component);
406bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber}
407