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
131f1a2668f4f09e38722424a6a74f0ea26f49e4110Marco Nelissen            if (!isValidOMXParam(pcmParams)) {
132f1a2668f4f09e38722424a6a74f0ea26f49e4110Marco Nelissen                return OMX_ErrorBadParameter;
133f1a2668f4f09e38722424a6a74f0ea26f49e4110Marco Nelissen            }
134f1a2668f4f09e38722424a6a74f0ea26f49e4110Marco Nelissen
135bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber            if (pcmParams->nPortIndex > 1) {
136bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber                return OMX_ErrorUndefined;
137bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber            }
138bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
139bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber            pcmParams->eNumData = OMX_NumericalDataSigned;
140bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber            pcmParams->eEndian = OMX_EndianBig;
141bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber            pcmParams->bInterleaved = OMX_TRUE;
142bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber            pcmParams->nBitPerSample = 16;
143bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber            pcmParams->ePCMMode = OMX_AUDIO_PCMModeLinear;
144bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber            pcmParams->eChannelMapping[0] = OMX_AUDIO_ChannelLF;
145bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber            pcmParams->eChannelMapping[1] = OMX_AUDIO_ChannelRF;
146bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
147bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber            pcmParams->nChannels = mNumChannels;
148bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber            pcmParams->nSamplingRate = mSamplingRate;
149bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
150bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber            return OMX_ErrorNone;
151bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        }
152bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
153e0381245dff04aa823a59aa8b85869eddab0f39fLajos Molnar        case OMX_IndexParamAudioMp3:
154e0381245dff04aa823a59aa8b85869eddab0f39fLajos Molnar        {
155e0381245dff04aa823a59aa8b85869eddab0f39fLajos Molnar            OMX_AUDIO_PARAM_MP3TYPE *mp3Params =
156e0381245dff04aa823a59aa8b85869eddab0f39fLajos Molnar                (OMX_AUDIO_PARAM_MP3TYPE *)params;
157e0381245dff04aa823a59aa8b85869eddab0f39fLajos Molnar
158f1a2668f4f09e38722424a6a74f0ea26f49e4110Marco Nelissen            if (!isValidOMXParam(mp3Params)) {
159f1a2668f4f09e38722424a6a74f0ea26f49e4110Marco Nelissen                return OMX_ErrorBadParameter;
160f1a2668f4f09e38722424a6a74f0ea26f49e4110Marco Nelissen            }
161f1a2668f4f09e38722424a6a74f0ea26f49e4110Marco Nelissen
162e0381245dff04aa823a59aa8b85869eddab0f39fLajos Molnar            if (mp3Params->nPortIndex > 1) {
163e0381245dff04aa823a59aa8b85869eddab0f39fLajos Molnar                return OMX_ErrorUndefined;
164e0381245dff04aa823a59aa8b85869eddab0f39fLajos Molnar            }
165e0381245dff04aa823a59aa8b85869eddab0f39fLajos Molnar
166e0381245dff04aa823a59aa8b85869eddab0f39fLajos Molnar            mp3Params->nChannels = mNumChannels;
167e0381245dff04aa823a59aa8b85869eddab0f39fLajos Molnar            mp3Params->nBitRate = 0 /* unknown */;
168e0381245dff04aa823a59aa8b85869eddab0f39fLajos Molnar            mp3Params->nSampleRate = mSamplingRate;
169e0381245dff04aa823a59aa8b85869eddab0f39fLajos Molnar            // other fields are encoder-only
170e0381245dff04aa823a59aa8b85869eddab0f39fLajos Molnar
171e0381245dff04aa823a59aa8b85869eddab0f39fLajos Molnar            return OMX_ErrorNone;
172e0381245dff04aa823a59aa8b85869eddab0f39fLajos Molnar        }
173e0381245dff04aa823a59aa8b85869eddab0f39fLajos Molnar
174bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        default:
175bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber            return SimpleSoftOMXComponent::internalGetParameter(index, params);
176bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    }
177bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber}
178bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
179bbba88cb1bdc34705d1477208990a06904c022e7Andreas HuberOMX_ERRORTYPE SoftMP3::internalSetParameter(
180bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        OMX_INDEXTYPE index, const OMX_PTR params) {
181bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    switch (index) {
182bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        case OMX_IndexParamStandardComponentRole:
183bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        {
184bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber            const OMX_PARAM_COMPONENTROLETYPE *roleParams =
185bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber                (const OMX_PARAM_COMPONENTROLETYPE *)params;
186bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
187f1a2668f4f09e38722424a6a74f0ea26f49e4110Marco Nelissen            if (!isValidOMXParam(roleParams)) {
188f1a2668f4f09e38722424a6a74f0ea26f49e4110Marco Nelissen                return OMX_ErrorBadParameter;
189f1a2668f4f09e38722424a6a74f0ea26f49e4110Marco Nelissen            }
190f1a2668f4f09e38722424a6a74f0ea26f49e4110Marco Nelissen
191bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber            if (strncmp((const char *)roleParams->cRole,
192bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber                        "audio_decoder.mp3",
193bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber                        OMX_MAX_STRINGNAME_SIZE - 1)) {
194bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber                return OMX_ErrorUndefined;
195bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber            }
196bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
197bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber            return OMX_ErrorNone;
198bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        }
199bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
20042392e49e167c6a0c573e55e1c1b4c7fa0ceb213Andreas Huber        case OMX_IndexParamAudioPcm:
20142392e49e167c6a0c573e55e1c1b4c7fa0ceb213Andreas Huber        {
20242392e49e167c6a0c573e55e1c1b4c7fa0ceb213Andreas Huber            const OMX_AUDIO_PARAM_PCMMODETYPE *pcmParams =
20342392e49e167c6a0c573e55e1c1b4c7fa0ceb213Andreas Huber                (const OMX_AUDIO_PARAM_PCMMODETYPE *)params;
20442392e49e167c6a0c573e55e1c1b4c7fa0ceb213Andreas Huber
205f1a2668f4f09e38722424a6a74f0ea26f49e4110Marco Nelissen            if (!isValidOMXParam(pcmParams)) {
206f1a2668f4f09e38722424a6a74f0ea26f49e4110Marco Nelissen                return OMX_ErrorBadParameter;
207f1a2668f4f09e38722424a6a74f0ea26f49e4110Marco Nelissen            }
208f1a2668f4f09e38722424a6a74f0ea26f49e4110Marco Nelissen
20942392e49e167c6a0c573e55e1c1b4c7fa0ceb213Andreas Huber            if (pcmParams->nPortIndex != 1) {
21042392e49e167c6a0c573e55e1c1b4c7fa0ceb213Andreas Huber                return OMX_ErrorUndefined;
21142392e49e167c6a0c573e55e1c1b4c7fa0ceb213Andreas Huber            }
21242392e49e167c6a0c573e55e1c1b4c7fa0ceb213Andreas Huber
21342392e49e167c6a0c573e55e1c1b4c7fa0ceb213Andreas Huber            mNumChannels = pcmParams->nChannels;
21442392e49e167c6a0c573e55e1c1b4c7fa0ceb213Andreas Huber            mSamplingRate = pcmParams->nSamplingRate;
21542392e49e167c6a0c573e55e1c1b4c7fa0ceb213Andreas Huber
21642392e49e167c6a0c573e55e1c1b4c7fa0ceb213Andreas Huber            return OMX_ErrorNone;
21742392e49e167c6a0c573e55e1c1b4c7fa0ceb213Andreas Huber        }
21842392e49e167c6a0c573e55e1c1b4c7fa0ceb213Andreas Huber
219bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        default:
220bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber            return SimpleSoftOMXComponent::internalSetParameter(index, params);
221bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    }
222bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber}
223bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
22484333e0475bc911adc16417f4ca327c975cf6c36Andreas Hubervoid SoftMP3::onQueueFilled(OMX_U32 /* portIndex */) {
225bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    if (mSignalledError || mOutputPortSettingsChange != NONE) {
226bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        return;
227bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    }
228bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
229bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    List<BufferInfo *> &inQueue = getPortQueue(0);
230bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    List<BufferInfo *> &outQueue = getPortQueue(1);
231bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
232d089c2540e4f0897c166693f4f13e2023241720eMarco Nelissen    while ((!inQueue.empty() || (mSawInputEos && !mSignalledOutputEos)) && !outQueue.empty()) {
233d089c2540e4f0897c166693f4f13e2023241720eMarco Nelissen        BufferInfo *inInfo = NULL;
234d089c2540e4f0897c166693f4f13e2023241720eMarco Nelissen        OMX_BUFFERHEADERTYPE *inHeader = NULL;
235d089c2540e4f0897c166693f4f13e2023241720eMarco Nelissen        if (!inQueue.empty()) {
236d089c2540e4f0897c166693f4f13e2023241720eMarco Nelissen            inInfo = *inQueue.begin();
237d089c2540e4f0897c166693f4f13e2023241720eMarco Nelissen            inHeader = inInfo->mHeader;
238d089c2540e4f0897c166693f4f13e2023241720eMarco Nelissen        }
239bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
240bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        BufferInfo *outInfo = *outQueue.begin();
241bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        OMX_BUFFERHEADERTYPE *outHeader = outInfo->mHeader;
242d089c2540e4f0897c166693f4f13e2023241720eMarco Nelissen        outHeader->nFlags = 0;
243bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
244d089c2540e4f0897c166693f4f13e2023241720eMarco Nelissen        if (inHeader) {
245d089c2540e4f0897c166693f4f13e2023241720eMarco Nelissen            if (inHeader->nOffset == 0 && inHeader->nFilledLen) {
246d089c2540e4f0897c166693f4f13e2023241720eMarco Nelissen                mAnchorTimeUs = inHeader->nTimeStamp;
247d089c2540e4f0897c166693f4f13e2023241720eMarco Nelissen                mNumFramesOutput = 0;
248d089c2540e4f0897c166693f4f13e2023241720eMarco Nelissen            }
249b6209a3d4c29bbb88de5a77546f4d545883cc484Eric Laurent
250d089c2540e4f0897c166693f4f13e2023241720eMarco Nelissen            if (inHeader->nFlags & OMX_BUFFERFLAG_EOS) {
251d089c2540e4f0897c166693f4f13e2023241720eMarco Nelissen                mSawInputEos = true;
25251d7547944967d1157b7fe18e1fb8f7ee6810412Andreas Huber            }
25351d7547944967d1157b7fe18e1fb8f7ee6810412Andreas Huber
254d089c2540e4f0897c166693f4f13e2023241720eMarco Nelissen            mConfig->pInputBuffer =
255d089c2540e4f0897c166693f4f13e2023241720eMarco Nelissen                inHeader->pBuffer + inHeader->nOffset;
256bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
257d089c2540e4f0897c166693f4f13e2023241720eMarco Nelissen            mConfig->inputBufferCurrentLength = inHeader->nFilledLen;
258d089c2540e4f0897c166693f4f13e2023241720eMarco Nelissen        } else {
259d089c2540e4f0897c166693f4f13e2023241720eMarco Nelissen            mConfig->pInputBuffer = NULL;
260d089c2540e4f0897c166693f4f13e2023241720eMarco Nelissen            mConfig->inputBufferCurrentLength = 0;
261bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        }
262bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        mConfig->inputBufferMaxLength = 0;
263bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        mConfig->inputBufferUsedLength = 0;
264bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
265bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        mConfig->outputFrameSize = kOutputBufferSize / sizeof(int16_t);
26630940b31b21f47eaa15786764e013d0a283d7d49Marco Nelissen        if ((int32)outHeader->nAllocLen < mConfig->outputFrameSize) {
2679fde506b8d37bd472969524bcef1d03b24c39c6cMarco Nelissen            ALOGE("input buffer too small: got %u, expected %u",
26830940b31b21f47eaa15786764e013d0a283d7d49Marco Nelissen                outHeader->nAllocLen, mConfig->outputFrameSize);
26930940b31b21f47eaa15786764e013d0a283d7d49Marco Nelissen            android_errorWriteLog(0x534e4554, "27793371");
27030940b31b21f47eaa15786764e013d0a283d7d49Marco Nelissen            notify(OMX_EventError, OMX_ErrorUndefined, OUTPUT_BUFFER_TOO_SMALL, NULL);
27130940b31b21f47eaa15786764e013d0a283d7d49Marco Nelissen            mSignalledError = true;
27230940b31b21f47eaa15786764e013d0a283d7d49Marco Nelissen            return;
27330940b31b21f47eaa15786764e013d0a283d7d49Marco Nelissen        }
274bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
275bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        mConfig->pOutputBuffer =
276bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber            reinterpret_cast<int16_t *>(outHeader->pBuffer);
277bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
278bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        ERROR_CODE decoderErr;
279bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        if ((decoderErr = pvmp3_framedecoder(mConfig, mDecoderBuf))
280bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber                != NO_DECODING_ERROR) {
2813856b090cd04ba5dd4a59a12430ed724d5995909Steve Block            ALOGV("mp3 decoder returned error %d", decoderErr);
282bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
283259b39cbfc03cb94c48e66d752836e153e9a2f8bAndreas Huber            if (decoderErr != NO_ENOUGH_MAIN_DATA_ERROR
284259b39cbfc03cb94c48e66d752836e153e9a2f8bAndreas Huber                        && decoderErr != SIDE_INFO_ERROR) {
28529357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block                ALOGE("mp3 decoder returned error %d", decoderErr);
286bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
287bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber                notify(OMX_EventError, OMX_ErrorUndefined, decoderErr, NULL);
288bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber                mSignalledError = true;
289bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber                return;
290bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber            }
291bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
292259b39cbfc03cb94c48e66d752836e153e9a2f8bAndreas Huber            if (mConfig->outputFrameSize == 0) {
293259b39cbfc03cb94c48e66d752836e153e9a2f8bAndreas Huber                mConfig->outputFrameSize = kOutputBufferSize / sizeof(int16_t);
294259b39cbfc03cb94c48e66d752836e153e9a2f8bAndreas Huber            }
295259b39cbfc03cb94c48e66d752836e153e9a2f8bAndreas Huber
296d089c2540e4f0897c166693f4f13e2023241720eMarco Nelissen            if (decoderErr == NO_ENOUGH_MAIN_DATA_ERROR && mSawInputEos) {
297d089c2540e4f0897c166693f4f13e2023241720eMarco Nelissen                if (!mIsFirst) {
298d089c2540e4f0897c166693f4f13e2023241720eMarco Nelissen                    // pad the end of the stream with 529 samples, since that many samples
299d089c2540e4f0897c166693f4f13e2023241720eMarco Nelissen                    // were trimmed off the beginning when decoding started
300d089c2540e4f0897c166693f4f13e2023241720eMarco Nelissen                    outHeader->nOffset = 0;
301d089c2540e4f0897c166693f4f13e2023241720eMarco Nelissen                    outHeader->nFilledLen = kPVMP3DecoderDelay * mNumChannels * sizeof(int16_t);
302d089c2540e4f0897c166693f4f13e2023241720eMarco Nelissen
303d089c2540e4f0897c166693f4f13e2023241720eMarco Nelissen                    memset(outHeader->pBuffer, 0, outHeader->nFilledLen);
304d089c2540e4f0897c166693f4f13e2023241720eMarco Nelissen                }
305d089c2540e4f0897c166693f4f13e2023241720eMarco Nelissen                outHeader->nFlags = OMX_BUFFERFLAG_EOS;
306d089c2540e4f0897c166693f4f13e2023241720eMarco Nelissen                mSignalledOutputEos = true;
307d089c2540e4f0897c166693f4f13e2023241720eMarco Nelissen            } else {
308d089c2540e4f0897c166693f4f13e2023241720eMarco Nelissen                // This is recoverable, just ignore the current frame and
309d089c2540e4f0897c166693f4f13e2023241720eMarco Nelissen                // play silence instead.
310c015b84e5d6f5d1e116d71bfbd3bd8edc3b06511Andy Hung
311c015b84e5d6f5d1e116d71bfbd3bd8edc3b06511Andy Hung                // TODO: should we skip silence (and consume input data)
312c015b84e5d6f5d1e116d71bfbd3bd8edc3b06511Andy Hung                // if mIsFirst is true as we may not have a valid
313c015b84e5d6f5d1e116d71bfbd3bd8edc3b06511Andy Hung                // mConfig->samplingRate and mConfig->num_channels?
314c015b84e5d6f5d1e116d71bfbd3bd8edc3b06511Andy Hung                ALOGV_IF(mIsFirst, "insufficient data for first frame, sending silence");
315d089c2540e4f0897c166693f4f13e2023241720eMarco Nelissen                memset(outHeader->pBuffer,
316d089c2540e4f0897c166693f4f13e2023241720eMarco Nelissen                       0,
317d089c2540e4f0897c166693f4f13e2023241720eMarco Nelissen                       mConfig->outputFrameSize * sizeof(int16_t));
318d089c2540e4f0897c166693f4f13e2023241720eMarco Nelissen
319d089c2540e4f0897c166693f4f13e2023241720eMarco Nelissen                if (inHeader) {
320d089c2540e4f0897c166693f4f13e2023241720eMarco Nelissen                    mConfig->inputBufferUsedLength = inHeader->nFilledLen;
321d089c2540e4f0897c166693f4f13e2023241720eMarco Nelissen                }
322d089c2540e4f0897c166693f4f13e2023241720eMarco Nelissen            }
323bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        } else if (mConfig->samplingRate != mSamplingRate
324bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber                || mConfig->num_channels != mNumChannels) {
325bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber            mSamplingRate = mConfig->samplingRate;
326bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber            mNumChannels = mConfig->num_channels;
327bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
328bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber            notify(OMX_EventPortSettingsChanged, 1, 0, NULL);
329bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber            mOutputPortSettingsChange = AWAITING_DISABLED;
330bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber            return;
331bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        }
332bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
333a98478bfbcc0f7fb4b164d3dce40ca96df75667dMarco Nelissen        if (mIsFirst) {
334a98478bfbcc0f7fb4b164d3dce40ca96df75667dMarco Nelissen            mIsFirst = false;
335a98478bfbcc0f7fb4b164d3dce40ca96df75667dMarco Nelissen            // The decoder delay is 529 samples, so trim that many samples off
336a98478bfbcc0f7fb4b164d3dce40ca96df75667dMarco Nelissen            // the start of the first output buffer. This essentially makes this
337a98478bfbcc0f7fb4b164d3dce40ca96df75667dMarco Nelissen            // decoder have zero delay, which the rest of the pipeline assumes.
33851d7547944967d1157b7fe18e1fb8f7ee6810412Andreas Huber            outHeader->nOffset =
33951d7547944967d1157b7fe18e1fb8f7ee6810412Andreas Huber                kPVMP3DecoderDelay * mNumChannels * sizeof(int16_t);
34051d7547944967d1157b7fe18e1fb8f7ee6810412Andreas Huber
34151d7547944967d1157b7fe18e1fb8f7ee6810412Andreas Huber            outHeader->nFilledLen =
34251d7547944967d1157b7fe18e1fb8f7ee6810412Andreas Huber                mConfig->outputFrameSize * sizeof(int16_t) - outHeader->nOffset;
343d089c2540e4f0897c166693f4f13e2023241720eMarco Nelissen        } else if (!mSignalledOutputEos) {
344a98478bfbcc0f7fb4b164d3dce40ca96df75667dMarco Nelissen            outHeader->nOffset = 0;
345a98478bfbcc0f7fb4b164d3dce40ca96df75667dMarco Nelissen            outHeader->nFilledLen = mConfig->outputFrameSize * sizeof(int16_t);
346a98478bfbcc0f7fb4b164d3dce40ca96df75667dMarco Nelissen        }
347bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
348bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        outHeader->nTimeStamp =
349c015b84e5d6f5d1e116d71bfbd3bd8edc3b06511Andy Hung            mAnchorTimeUs + (mNumFramesOutput * 1000000ll) / mSamplingRate;
350bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
351d089c2540e4f0897c166693f4f13e2023241720eMarco Nelissen        if (inHeader) {
352d089c2540e4f0897c166693f4f13e2023241720eMarco Nelissen            CHECK_GE(inHeader->nFilledLen, mConfig->inputBufferUsedLength);
353bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
354d089c2540e4f0897c166693f4f13e2023241720eMarco Nelissen            inHeader->nOffset += mConfig->inputBufferUsedLength;
355d089c2540e4f0897c166693f4f13e2023241720eMarco Nelissen            inHeader->nFilledLen -= mConfig->inputBufferUsedLength;
356bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
3579da36a6c8df70a5c8179ac78fab33cfbb5078cb2Marco Nelissen
358d089c2540e4f0897c166693f4f13e2023241720eMarco Nelissen            if (inHeader->nFilledLen == 0) {
359d089c2540e4f0897c166693f4f13e2023241720eMarco Nelissen                inInfo->mOwnedByUs = false;
360d089c2540e4f0897c166693f4f13e2023241720eMarco Nelissen                inQueue.erase(inQueue.begin());
361d089c2540e4f0897c166693f4f13e2023241720eMarco Nelissen                inInfo = NULL;
362d089c2540e4f0897c166693f4f13e2023241720eMarco Nelissen                notifyEmptyBufferDone(inHeader);
363d089c2540e4f0897c166693f4f13e2023241720eMarco Nelissen                inHeader = NULL;
364d089c2540e4f0897c166693f4f13e2023241720eMarco Nelissen            }
365b6209a3d4c29bbb88de5a77546f4d545883cc484Eric Laurent        }
366b6209a3d4c29bbb88de5a77546f4d545883cc484Eric Laurent
367d089c2540e4f0897c166693f4f13e2023241720eMarco Nelissen        mNumFramesOutput += mConfig->outputFrameSize / mNumChannels;
368d089c2540e4f0897c166693f4f13e2023241720eMarco Nelissen
369bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        outInfo->mOwnedByUs = false;
370bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        outQueue.erase(outQueue.begin());
371bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        outInfo = NULL;
372bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        notifyFillBufferDone(outHeader);
373bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        outHeader = NULL;
374bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    }
375bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber}
376bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
377bbba88cb1bdc34705d1477208990a06904c022e7Andreas Hubervoid SoftMP3::onPortFlushCompleted(OMX_U32 portIndex) {
378bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    if (portIndex == 0) {
379bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        // Make sure that the next buffer output does not still
380bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        // depend on fragments from the last one decoded.
381bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        pvmp3_InitDecoder(mConfig, mDecoderBuf);
382a98478bfbcc0f7fb4b164d3dce40ca96df75667dMarco Nelissen        mIsFirst = true;
3836e56e8024c98c3e6e62772e1dd345dd2c1c36717Marco Nelissen        mSignalledError = false;
3846e56e8024c98c3e6e62772e1dd345dd2c1c36717Marco Nelissen        mSawInputEos = false;
3856e56e8024c98c3e6e62772e1dd345dd2c1c36717Marco Nelissen        mSignalledOutputEos = false;
386bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    }
387bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber}
388bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
389bbba88cb1bdc34705d1477208990a06904c022e7Andreas Hubervoid SoftMP3::onPortEnableCompleted(OMX_U32 portIndex, bool enabled) {
390bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    if (portIndex != 1) {
391bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        return;
392bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    }
393bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
394bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    switch (mOutputPortSettingsChange) {
395bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        case NONE:
396bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber            break;
397bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
398bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        case AWAITING_DISABLED:
399bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        {
400bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber            CHECK(!enabled);
401bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber            mOutputPortSettingsChange = AWAITING_ENABLED;
402bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber            break;
403bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        }
404bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
405bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        default:
406bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        {
407bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber            CHECK_EQ((int)mOutputPortSettingsChange, (int)AWAITING_ENABLED);
408bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber            CHECK(enabled);
409bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber            mOutputPortSettingsChange = NONE;
410bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber            break;
411bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        }
412bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    }
413bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber}
414bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
4156fc72b01a3b67903b52f1d33b1ad5c960b5365f1Marco Nelissenvoid SoftMP3::onReset() {
4166fc72b01a3b67903b52f1d33b1ad5c960b5365f1Marco Nelissen    pvmp3_InitDecoder(mConfig, mDecoderBuf);
4176fc72b01a3b67903b52f1d33b1ad5c960b5365f1Marco Nelissen    mIsFirst = true;
418d94e716af0e49d775f0c0c4f36dd2c136ba5f2b2Andreas Huber    mSignalledError = false;
419d089c2540e4f0897c166693f4f13e2023241720eMarco Nelissen    mSawInputEos = false;
420d089c2540e4f0897c166693f4f13e2023241720eMarco Nelissen    mSignalledOutputEos = false;
421d94e716af0e49d775f0c0c4f36dd2c136ba5f2b2Andreas Huber    mOutputPortSettingsChange = NONE;
4226fc72b01a3b67903b52f1d33b1ad5c960b5365f1Marco Nelissen}
4236fc72b01a3b67903b52f1d33b1ad5c960b5365f1Marco Nelissen
424bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber}  // namespace android
425bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber
426bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huberandroid::SoftOMXComponent *createSoftOMXComponent(
427bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        const char *name, const OMX_CALLBACKTYPE *callbacks,
428bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber        OMX_PTR appData, OMX_COMPONENTTYPE **component) {
429bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber    return new android::SoftMP3(name, callbacks, appData, component);
430bbba88cb1bdc34705d1477208990a06904c022e7Andreas Huber}
431