SoftMP3.cpp revision f1a2668f4f09e38722424a6a74f0ea26f49e4110
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 mSawInputEos(false), 53 mSignalledOutputEos(false), 54 mOutputPortSettingsChange(NONE) { 55 initPorts(); 56 initDecoder(); 57} 58 59SoftMP3::~SoftMP3() { 60 if (mDecoderBuf != NULL) { 61 free(mDecoderBuf); 62 mDecoderBuf = NULL; 63 } 64 65 delete mConfig; 66 mConfig = NULL; 67} 68 69void SoftMP3::initPorts() { 70 OMX_PARAM_PORTDEFINITIONTYPE def; 71 InitOMXParams(&def); 72 73 def.nPortIndex = 0; 74 def.eDir = OMX_DirInput; 75 def.nBufferCountMin = kNumBuffers; 76 def.nBufferCountActual = def.nBufferCountMin; 77 def.nBufferSize = 8192; 78 def.bEnabled = OMX_TRUE; 79 def.bPopulated = OMX_FALSE; 80 def.eDomain = OMX_PortDomainAudio; 81 def.bBuffersContiguous = OMX_FALSE; 82 def.nBufferAlignment = 1; 83 84 def.format.audio.cMIMEType = 85 const_cast<char *>(MEDIA_MIMETYPE_AUDIO_MPEG); 86 87 def.format.audio.pNativeRender = NULL; 88 def.format.audio.bFlagErrorConcealment = OMX_FALSE; 89 def.format.audio.eEncoding = OMX_AUDIO_CodingMP3; 90 91 addPort(def); 92 93 def.nPortIndex = 1; 94 def.eDir = OMX_DirOutput; 95 def.nBufferCountMin = kNumBuffers; 96 def.nBufferCountActual = def.nBufferCountMin; 97 def.nBufferSize = kOutputBufferSize; 98 def.bEnabled = OMX_TRUE; 99 def.bPopulated = OMX_FALSE; 100 def.eDomain = OMX_PortDomainAudio; 101 def.bBuffersContiguous = OMX_FALSE; 102 def.nBufferAlignment = 2; 103 104 def.format.audio.cMIMEType = const_cast<char *>("audio/raw"); 105 def.format.audio.pNativeRender = NULL; 106 def.format.audio.bFlagErrorConcealment = OMX_FALSE; 107 def.format.audio.eEncoding = OMX_AUDIO_CodingPCM; 108 109 addPort(def); 110} 111 112void SoftMP3::initDecoder() { 113 mConfig->equalizerType = flat; 114 mConfig->crcEnabled = false; 115 116 uint32_t memRequirements = pvmp3_decoderMemRequirements(); 117 mDecoderBuf = malloc(memRequirements); 118 119 pvmp3_InitDecoder(mConfig, mDecoderBuf); 120 mIsFirst = true; 121} 122 123OMX_ERRORTYPE SoftMP3::internalGetParameter( 124 OMX_INDEXTYPE index, OMX_PTR params) { 125 switch (index) { 126 case OMX_IndexParamAudioPcm: 127 { 128 OMX_AUDIO_PARAM_PCMMODETYPE *pcmParams = 129 (OMX_AUDIO_PARAM_PCMMODETYPE *)params; 130 131 if (!isValidOMXParam(pcmParams)) { 132 return OMX_ErrorBadParameter; 133 } 134 135 if (pcmParams->nPortIndex > 1) { 136 return OMX_ErrorUndefined; 137 } 138 139 pcmParams->eNumData = OMX_NumericalDataSigned; 140 pcmParams->eEndian = OMX_EndianBig; 141 pcmParams->bInterleaved = OMX_TRUE; 142 pcmParams->nBitPerSample = 16; 143 pcmParams->ePCMMode = OMX_AUDIO_PCMModeLinear; 144 pcmParams->eChannelMapping[0] = OMX_AUDIO_ChannelLF; 145 pcmParams->eChannelMapping[1] = OMX_AUDIO_ChannelRF; 146 147 pcmParams->nChannels = mNumChannels; 148 pcmParams->nSamplingRate = mSamplingRate; 149 150 return OMX_ErrorNone; 151 } 152 153 case OMX_IndexParamAudioMp3: 154 { 155 OMX_AUDIO_PARAM_MP3TYPE *mp3Params = 156 (OMX_AUDIO_PARAM_MP3TYPE *)params; 157 158 if (!isValidOMXParam(mp3Params)) { 159 return OMX_ErrorBadParameter; 160 } 161 162 if (mp3Params->nPortIndex > 1) { 163 return OMX_ErrorUndefined; 164 } 165 166 mp3Params->nChannels = mNumChannels; 167 mp3Params->nBitRate = 0 /* unknown */; 168 mp3Params->nSampleRate = mSamplingRate; 169 // other fields are encoder-only 170 171 return OMX_ErrorNone; 172 } 173 174 default: 175 return SimpleSoftOMXComponent::internalGetParameter(index, params); 176 } 177} 178 179OMX_ERRORTYPE SoftMP3::internalSetParameter( 180 OMX_INDEXTYPE index, const OMX_PTR params) { 181 switch (index) { 182 case OMX_IndexParamStandardComponentRole: 183 { 184 const OMX_PARAM_COMPONENTROLETYPE *roleParams = 185 (const OMX_PARAM_COMPONENTROLETYPE *)params; 186 187 if (!isValidOMXParam(roleParams)) { 188 return OMX_ErrorBadParameter; 189 } 190 191 if (strncmp((const char *)roleParams->cRole, 192 "audio_decoder.mp3", 193 OMX_MAX_STRINGNAME_SIZE - 1)) { 194 return OMX_ErrorUndefined; 195 } 196 197 return OMX_ErrorNone; 198 } 199 200 case OMX_IndexParamAudioPcm: 201 { 202 const OMX_AUDIO_PARAM_PCMMODETYPE *pcmParams = 203 (const OMX_AUDIO_PARAM_PCMMODETYPE *)params; 204 205 if (!isValidOMXParam(pcmParams)) { 206 return OMX_ErrorBadParameter; 207 } 208 209 if (pcmParams->nPortIndex != 1) { 210 return OMX_ErrorUndefined; 211 } 212 213 mNumChannels = pcmParams->nChannels; 214 mSamplingRate = pcmParams->nSamplingRate; 215 216 return OMX_ErrorNone; 217 } 218 219 default: 220 return SimpleSoftOMXComponent::internalSetParameter(index, params); 221 } 222} 223 224void SoftMP3::onQueueFilled(OMX_U32 /* portIndex */) { 225 if (mSignalledError || mOutputPortSettingsChange != NONE) { 226 return; 227 } 228 229 List<BufferInfo *> &inQueue = getPortQueue(0); 230 List<BufferInfo *> &outQueue = getPortQueue(1); 231 232 while ((!inQueue.empty() || (mSawInputEos && !mSignalledOutputEos)) && !outQueue.empty()) { 233 BufferInfo *inInfo = NULL; 234 OMX_BUFFERHEADERTYPE *inHeader = NULL; 235 if (!inQueue.empty()) { 236 inInfo = *inQueue.begin(); 237 inHeader = inInfo->mHeader; 238 } 239 240 BufferInfo *outInfo = *outQueue.begin(); 241 OMX_BUFFERHEADERTYPE *outHeader = outInfo->mHeader; 242 outHeader->nFlags = 0; 243 244 if (inHeader) { 245 if (inHeader->nOffset == 0 && inHeader->nFilledLen) { 246 mAnchorTimeUs = inHeader->nTimeStamp; 247 mNumFramesOutput = 0; 248 } 249 250 if (inHeader->nFlags & OMX_BUFFERFLAG_EOS) { 251 mSawInputEos = true; 252 } 253 254 mConfig->pInputBuffer = 255 inHeader->pBuffer + inHeader->nOffset; 256 257 mConfig->inputBufferCurrentLength = inHeader->nFilledLen; 258 } else { 259 mConfig->pInputBuffer = NULL; 260 mConfig->inputBufferCurrentLength = 0; 261 } 262 mConfig->inputBufferMaxLength = 0; 263 mConfig->inputBufferUsedLength = 0; 264 265 mConfig->outputFrameSize = kOutputBufferSize / sizeof(int16_t); 266 267 mConfig->pOutputBuffer = 268 reinterpret_cast<int16_t *>(outHeader->pBuffer); 269 270 ERROR_CODE decoderErr; 271 if ((decoderErr = pvmp3_framedecoder(mConfig, mDecoderBuf)) 272 != NO_DECODING_ERROR) { 273 ALOGV("mp3 decoder returned error %d", decoderErr); 274 275 if (decoderErr != NO_ENOUGH_MAIN_DATA_ERROR 276 && decoderErr != SIDE_INFO_ERROR) { 277 ALOGE("mp3 decoder returned error %d", decoderErr); 278 279 notify(OMX_EventError, OMX_ErrorUndefined, decoderErr, NULL); 280 mSignalledError = true; 281 return; 282 } 283 284 if (mConfig->outputFrameSize == 0) { 285 mConfig->outputFrameSize = kOutputBufferSize / sizeof(int16_t); 286 } 287 288 if (decoderErr == NO_ENOUGH_MAIN_DATA_ERROR && mSawInputEos) { 289 if (!mIsFirst) { 290 // pad the end of the stream with 529 samples, since that many samples 291 // were trimmed off the beginning when decoding started 292 outHeader->nOffset = 0; 293 outHeader->nFilledLen = kPVMP3DecoderDelay * mNumChannels * sizeof(int16_t); 294 295 memset(outHeader->pBuffer, 0, outHeader->nFilledLen); 296 } 297 outHeader->nFlags = OMX_BUFFERFLAG_EOS; 298 mSignalledOutputEos = true; 299 } else { 300 // This is recoverable, just ignore the current frame and 301 // play silence instead. 302 303 // TODO: should we skip silence (and consume input data) 304 // if mIsFirst is true as we may not have a valid 305 // mConfig->samplingRate and mConfig->num_channels? 306 ALOGV_IF(mIsFirst, "insufficient data for first frame, sending silence"); 307 memset(outHeader->pBuffer, 308 0, 309 mConfig->outputFrameSize * sizeof(int16_t)); 310 311 if (inHeader) { 312 mConfig->inputBufferUsedLength = inHeader->nFilledLen; 313 } 314 } 315 } else if (mConfig->samplingRate != mSamplingRate 316 || mConfig->num_channels != mNumChannels) { 317 mSamplingRate = mConfig->samplingRate; 318 mNumChannels = mConfig->num_channels; 319 320 notify(OMX_EventPortSettingsChanged, 1, 0, NULL); 321 mOutputPortSettingsChange = AWAITING_DISABLED; 322 return; 323 } 324 325 if (mIsFirst) { 326 mIsFirst = false; 327 // The decoder delay is 529 samples, so trim that many samples off 328 // the start of the first output buffer. This essentially makes this 329 // decoder have zero delay, which the rest of the pipeline assumes. 330 outHeader->nOffset = 331 kPVMP3DecoderDelay * mNumChannels * sizeof(int16_t); 332 333 outHeader->nFilledLen = 334 mConfig->outputFrameSize * sizeof(int16_t) - outHeader->nOffset; 335 } else if (!mSignalledOutputEos) { 336 outHeader->nOffset = 0; 337 outHeader->nFilledLen = mConfig->outputFrameSize * sizeof(int16_t); 338 } 339 340 outHeader->nTimeStamp = 341 mAnchorTimeUs + (mNumFramesOutput * 1000000ll) / mSamplingRate; 342 343 if (inHeader) { 344 CHECK_GE(inHeader->nFilledLen, mConfig->inputBufferUsedLength); 345 346 inHeader->nOffset += mConfig->inputBufferUsedLength; 347 inHeader->nFilledLen -= mConfig->inputBufferUsedLength; 348 349 350 if (inHeader->nFilledLen == 0) { 351 inInfo->mOwnedByUs = false; 352 inQueue.erase(inQueue.begin()); 353 inInfo = NULL; 354 notifyEmptyBufferDone(inHeader); 355 inHeader = NULL; 356 } 357 } 358 359 mNumFramesOutput += mConfig->outputFrameSize / mNumChannels; 360 361 outInfo->mOwnedByUs = false; 362 outQueue.erase(outQueue.begin()); 363 outInfo = NULL; 364 notifyFillBufferDone(outHeader); 365 outHeader = NULL; 366 } 367} 368 369void SoftMP3::onPortFlushCompleted(OMX_U32 portIndex) { 370 if (portIndex == 0) { 371 // Make sure that the next buffer output does not still 372 // depend on fragments from the last one decoded. 373 pvmp3_InitDecoder(mConfig, mDecoderBuf); 374 mIsFirst = true; 375 mSignalledError = false; 376 mSawInputEos = false; 377 mSignalledOutputEos = false; 378 } 379} 380 381void SoftMP3::onPortEnableCompleted(OMX_U32 portIndex, bool enabled) { 382 if (portIndex != 1) { 383 return; 384 } 385 386 switch (mOutputPortSettingsChange) { 387 case NONE: 388 break; 389 390 case AWAITING_DISABLED: 391 { 392 CHECK(!enabled); 393 mOutputPortSettingsChange = AWAITING_ENABLED; 394 break; 395 } 396 397 default: 398 { 399 CHECK_EQ((int)mOutputPortSettingsChange, (int)AWAITING_ENABLED); 400 CHECK(enabled); 401 mOutputPortSettingsChange = NONE; 402 break; 403 } 404 } 405} 406 407void SoftMP3::onReset() { 408 pvmp3_InitDecoder(mConfig, mDecoderBuf); 409 mIsFirst = true; 410 mSignalledError = false; 411 mSawInputEos = false; 412 mSignalledOutputEos = false; 413 mOutputPortSettingsChange = NONE; 414} 415 416} // namespace android 417 418android::SoftOMXComponent *createSoftOMXComponent( 419 const char *name, const OMX_CALLBACKTYPE *callbacks, 420 OMX_PTR appData, OMX_COMPONENTTYPE **component) { 421 return new android::SoftMP3(name, callbacks, appData, component); 422} 423