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