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 123void *SoftMP3::memsetSafe(OMX_BUFFERHEADERTYPE *outHeader, int c, size_t len) { 124 if (len > outHeader->nAllocLen) { 125 ALOGE("memset buffer too small: got %u, expected %zu", outHeader->nAllocLen, len); 126 android_errorWriteLog(0x534e4554, "29422022"); 127 notify(OMX_EventError, OMX_ErrorUndefined, OUTPUT_BUFFER_TOO_SMALL, NULL); 128 mSignalledError = true; 129 return NULL; 130 } 131 return memset(outHeader->pBuffer, c, len); 132} 133 134OMX_ERRORTYPE SoftMP3::internalGetParameter( 135 OMX_INDEXTYPE index, OMX_PTR params) { 136 switch (index) { 137 case OMX_IndexParamAudioPcm: 138 { 139 OMX_AUDIO_PARAM_PCMMODETYPE *pcmParams = 140 (OMX_AUDIO_PARAM_PCMMODETYPE *)params; 141 142 if (!isValidOMXParam(pcmParams)) { 143 return OMX_ErrorBadParameter; 144 } 145 146 if (pcmParams->nPortIndex > 1) { 147 return OMX_ErrorUndefined; 148 } 149 150 pcmParams->eNumData = OMX_NumericalDataSigned; 151 pcmParams->eEndian = OMX_EndianBig; 152 pcmParams->bInterleaved = OMX_TRUE; 153 pcmParams->nBitPerSample = 16; 154 pcmParams->ePCMMode = OMX_AUDIO_PCMModeLinear; 155 pcmParams->eChannelMapping[0] = OMX_AUDIO_ChannelLF; 156 pcmParams->eChannelMapping[1] = OMX_AUDIO_ChannelRF; 157 158 pcmParams->nChannels = mNumChannels; 159 pcmParams->nSamplingRate = mSamplingRate; 160 161 return OMX_ErrorNone; 162 } 163 164 case OMX_IndexParamAudioMp3: 165 { 166 OMX_AUDIO_PARAM_MP3TYPE *mp3Params = 167 (OMX_AUDIO_PARAM_MP3TYPE *)params; 168 169 if (!isValidOMXParam(mp3Params)) { 170 return OMX_ErrorBadParameter; 171 } 172 173 if (mp3Params->nPortIndex > 1) { 174 return OMX_ErrorUndefined; 175 } 176 177 mp3Params->nChannels = mNumChannels; 178 mp3Params->nBitRate = 0 /* unknown */; 179 mp3Params->nSampleRate = mSamplingRate; 180 // other fields are encoder-only 181 182 return OMX_ErrorNone; 183 } 184 185 default: 186 return SimpleSoftOMXComponent::internalGetParameter(index, params); 187 } 188} 189 190OMX_ERRORTYPE SoftMP3::internalSetParameter( 191 OMX_INDEXTYPE index, const OMX_PTR params) { 192 switch (index) { 193 case OMX_IndexParamStandardComponentRole: 194 { 195 const OMX_PARAM_COMPONENTROLETYPE *roleParams = 196 (const OMX_PARAM_COMPONENTROLETYPE *)params; 197 198 if (!isValidOMXParam(roleParams)) { 199 return OMX_ErrorBadParameter; 200 } 201 202 if (strncmp((const char *)roleParams->cRole, 203 "audio_decoder.mp3", 204 OMX_MAX_STRINGNAME_SIZE - 1)) { 205 return OMX_ErrorUndefined; 206 } 207 208 return OMX_ErrorNone; 209 } 210 211 case OMX_IndexParamAudioPcm: 212 { 213 const OMX_AUDIO_PARAM_PCMMODETYPE *pcmParams = 214 (const OMX_AUDIO_PARAM_PCMMODETYPE *)params; 215 216 if (!isValidOMXParam(pcmParams)) { 217 return OMX_ErrorBadParameter; 218 } 219 220 if (pcmParams->nPortIndex != 1) { 221 return OMX_ErrorUndefined; 222 } 223 224 mNumChannels = pcmParams->nChannels; 225 mSamplingRate = pcmParams->nSamplingRate; 226 227 return OMX_ErrorNone; 228 } 229 230 default: 231 return SimpleSoftOMXComponent::internalSetParameter(index, params); 232 } 233} 234 235void SoftMP3::onQueueFilled(OMX_U32 /* portIndex */) { 236 if (mSignalledError || mOutputPortSettingsChange != NONE) { 237 return; 238 } 239 240 List<BufferInfo *> &inQueue = getPortQueue(0); 241 List<BufferInfo *> &outQueue = getPortQueue(1); 242 243 while ((!inQueue.empty() || (mSawInputEos && !mSignalledOutputEos)) && !outQueue.empty()) { 244 BufferInfo *inInfo = NULL; 245 OMX_BUFFERHEADERTYPE *inHeader = NULL; 246 if (!inQueue.empty()) { 247 inInfo = *inQueue.begin(); 248 inHeader = inInfo->mHeader; 249 } 250 251 BufferInfo *outInfo = *outQueue.begin(); 252 OMX_BUFFERHEADERTYPE *outHeader = outInfo->mHeader; 253 outHeader->nFlags = 0; 254 255 if (inHeader) { 256 if (inHeader->nOffset == 0 && inHeader->nFilledLen) { 257 mAnchorTimeUs = inHeader->nTimeStamp; 258 mNumFramesOutput = 0; 259 } 260 261 if (inHeader->nFlags & OMX_BUFFERFLAG_EOS) { 262 mSawInputEos = true; 263 } 264 265 mConfig->pInputBuffer = 266 inHeader->pBuffer + inHeader->nOffset; 267 268 mConfig->inputBufferCurrentLength = inHeader->nFilledLen; 269 } else { 270 mConfig->pInputBuffer = NULL; 271 mConfig->inputBufferCurrentLength = 0; 272 } 273 mConfig->inputBufferMaxLength = 0; 274 mConfig->inputBufferUsedLength = 0; 275 276 mConfig->outputFrameSize = kOutputBufferSize / sizeof(int16_t); 277 if ((int32)outHeader->nAllocLen < mConfig->outputFrameSize) { 278 ALOGE("input buffer too small: got %u, expected %u", 279 outHeader->nAllocLen, mConfig->outputFrameSize); 280 android_errorWriteLog(0x534e4554, "27793371"); 281 notify(OMX_EventError, OMX_ErrorUndefined, OUTPUT_BUFFER_TOO_SMALL, NULL); 282 mSignalledError = true; 283 return; 284 } 285 286 mConfig->pOutputBuffer = 287 reinterpret_cast<int16_t *>(outHeader->pBuffer); 288 289 ERROR_CODE decoderErr; 290 if ((decoderErr = pvmp3_framedecoder(mConfig, mDecoderBuf)) 291 != NO_DECODING_ERROR) { 292 ALOGV("mp3 decoder returned error %d", decoderErr); 293 294 if (decoderErr != NO_ENOUGH_MAIN_DATA_ERROR 295 && decoderErr != SIDE_INFO_ERROR) { 296 ALOGE("mp3 decoder returned error %d", decoderErr); 297 298 notify(OMX_EventError, OMX_ErrorUndefined, decoderErr, NULL); 299 mSignalledError = true; 300 return; 301 } 302 303 if (mConfig->outputFrameSize == 0) { 304 mConfig->outputFrameSize = kOutputBufferSize / sizeof(int16_t); 305 } 306 307 if (decoderErr == NO_ENOUGH_MAIN_DATA_ERROR && mSawInputEos) { 308 if (!mIsFirst) { 309 // pad the end of the stream with 529 samples, since that many samples 310 // were trimmed off the beginning when decoding started 311 outHeader->nOffset = 0; 312 outHeader->nFilledLen = kPVMP3DecoderDelay * mNumChannels * sizeof(int16_t); 313 314 if (!memsetSafe(outHeader, 0, outHeader->nFilledLen)) { 315 return; 316 } 317 318 } 319 outHeader->nFlags = OMX_BUFFERFLAG_EOS; 320 mSignalledOutputEos = true; 321 } else { 322 // This is recoverable, just ignore the current frame and 323 // play silence instead. 324 325 // TODO: should we skip silence (and consume input data) 326 // if mIsFirst is true as we may not have a valid 327 // mConfig->samplingRate and mConfig->num_channels? 328 ALOGV_IF(mIsFirst, "insufficient data for first frame, sending silence"); 329 if (!memsetSafe(outHeader, 0, mConfig->outputFrameSize * sizeof(int16_t))) { 330 return; 331 } 332 333 if (inHeader) { 334 mConfig->inputBufferUsedLength = inHeader->nFilledLen; 335 } 336 } 337 } else if (mConfig->samplingRate != mSamplingRate 338 || mConfig->num_channels != mNumChannels) { 339 mSamplingRate = mConfig->samplingRate; 340 mNumChannels = mConfig->num_channels; 341 342 notify(OMX_EventPortSettingsChanged, 1, 0, NULL); 343 mOutputPortSettingsChange = AWAITING_DISABLED; 344 return; 345 } 346 347 if (mIsFirst) { 348 mIsFirst = false; 349 // The decoder delay is 529 samples, so trim that many samples off 350 // the start of the first output buffer. This essentially makes this 351 // decoder have zero delay, which the rest of the pipeline assumes. 352 outHeader->nOffset = 353 kPVMP3DecoderDelay * mNumChannels * sizeof(int16_t); 354 355 outHeader->nFilledLen = 356 mConfig->outputFrameSize * sizeof(int16_t) - outHeader->nOffset; 357 } else if (!mSignalledOutputEos) { 358 outHeader->nOffset = 0; 359 outHeader->nFilledLen = mConfig->outputFrameSize * sizeof(int16_t); 360 } 361 362 outHeader->nTimeStamp = 363 mAnchorTimeUs + (mNumFramesOutput * 1000000ll) / mSamplingRate; 364 365 if (inHeader) { 366 CHECK_GE(inHeader->nFilledLen, mConfig->inputBufferUsedLength); 367 368 inHeader->nOffset += mConfig->inputBufferUsedLength; 369 inHeader->nFilledLen -= mConfig->inputBufferUsedLength; 370 371 372 if (inHeader->nFilledLen == 0) { 373 inInfo->mOwnedByUs = false; 374 inQueue.erase(inQueue.begin()); 375 inInfo = NULL; 376 notifyEmptyBufferDone(inHeader); 377 inHeader = NULL; 378 } 379 } 380 381 mNumFramesOutput += mConfig->outputFrameSize / mNumChannels; 382 383 outInfo->mOwnedByUs = false; 384 outQueue.erase(outQueue.begin()); 385 outInfo = NULL; 386 notifyFillBufferDone(outHeader); 387 outHeader = NULL; 388 } 389} 390 391void SoftMP3::onPortFlushCompleted(OMX_U32 portIndex) { 392 if (portIndex == 0) { 393 // Make sure that the next buffer output does not still 394 // depend on fragments from the last one decoded. 395 pvmp3_InitDecoder(mConfig, mDecoderBuf); 396 mIsFirst = true; 397 mSignalledError = false; 398 mSawInputEos = false; 399 mSignalledOutputEos = false; 400 } 401} 402 403void SoftMP3::onPortEnableCompleted(OMX_U32 portIndex, bool enabled) { 404 if (portIndex != 1) { 405 return; 406 } 407 408 switch (mOutputPortSettingsChange) { 409 case NONE: 410 break; 411 412 case AWAITING_DISABLED: 413 { 414 CHECK(!enabled); 415 mOutputPortSettingsChange = AWAITING_ENABLED; 416 break; 417 } 418 419 default: 420 { 421 CHECK_EQ((int)mOutputPortSettingsChange, (int)AWAITING_ENABLED); 422 CHECK(enabled); 423 mOutputPortSettingsChange = NONE; 424 break; 425 } 426 } 427} 428 429void SoftMP3::onReset() { 430 pvmp3_InitDecoder(mConfig, mDecoderBuf); 431 mIsFirst = true; 432 mSignalledError = false; 433 mSawInputEos = false; 434 mSignalledOutputEos = false; 435 mOutputPortSettingsChange = NONE; 436} 437 438} // namespace android 439 440android::SoftOMXComponent *createSoftOMXComponent( 441 const char *name, const OMX_CALLBACKTYPE *callbacks, 442 OMX_PTR appData, OMX_COMPONENTTYPE **component) { 443 return new android::SoftMP3(name, callbacks, appData, component); 444} 445