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