1 /* 2 * Copyright (C) 2012 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 "SoftAAC2" 19 #include <utils/Log.h> 20 21 #include "SoftAAC2.h" 22 #include <OMX_AudioExt.h> 23 #include <OMX_IndexExt.h> 24 25 #include <cutils/properties.h> 26 #include <media/stagefright/foundation/ADebug.h> 27 #include <media/stagefright/foundation/hexdump.h> 28 #include <media/stagefright/MediaErrors.h> 29 #include <utils/misc.h> 30 31 #include <math.h> 32 33 #define FILEREAD_MAX_LAYERS 2 34 35 #define DRC_DEFAULT_MOBILE_REF_LEVEL 64 /* 64*-0.25dB = -16 dB below full scale for mobile conf */ 36 #define DRC_DEFAULT_MOBILE_DRC_CUT 127 /* maximum compression of dynamic range for mobile conf */ 37 #define DRC_DEFAULT_MOBILE_DRC_BOOST 127 /* maximum compression of dynamic range for mobile conf */ 38 #define DRC_DEFAULT_MOBILE_DRC_HEAVY 1 /* switch for heavy compression for mobile conf */ 39 #define DRC_DEFAULT_MOBILE_ENC_LEVEL -1 /* encoder target level; -1 => the value is unknown, otherwise dB step value (e.g. 64 for -16 dB) */ 40 #define MAX_CHANNEL_COUNT 8 /* maximum number of audio channels that can be decoded */ 41 // names of properties that can be used to override the default DRC settings 42 #define PROP_DRC_OVERRIDE_REF_LEVEL "aac_drc_reference_level" 43 #define PROP_DRC_OVERRIDE_CUT "aac_drc_cut" 44 #define PROP_DRC_OVERRIDE_BOOST "aac_drc_boost" 45 #define PROP_DRC_OVERRIDE_HEAVY "aac_drc_heavy" 46 #define PROP_DRC_OVERRIDE_ENC_LEVEL "aac_drc_enc_target_level" 47 48 namespace android { 49 50 template<class T> 51 static void InitOMXParams(T *params) { 52 params->nSize = sizeof(T); 53 params->nVersion.s.nVersionMajor = 1; 54 params->nVersion.s.nVersionMinor = 0; 55 params->nVersion.s.nRevision = 0; 56 params->nVersion.s.nStep = 0; 57 } 58 59 static const OMX_U32 kSupportedProfiles[] = { 60 OMX_AUDIO_AACObjectLC, 61 OMX_AUDIO_AACObjectHE, 62 OMX_AUDIO_AACObjectHE_PS, 63 OMX_AUDIO_AACObjectLD, 64 OMX_AUDIO_AACObjectELD, 65 }; 66 67 SoftAAC2::SoftAAC2( 68 const char *name, 69 const OMX_CALLBACKTYPE *callbacks, 70 OMX_PTR appData, 71 OMX_COMPONENTTYPE **component) 72 : SimpleSoftOMXComponent(name, callbacks, appData, component), 73 mAACDecoder(NULL), 74 mStreamInfo(NULL), 75 mIsADTS(false), 76 mInputBufferCount(0), 77 mOutputBufferCount(0), 78 mSignalledError(false), 79 mLastInHeader(NULL), 80 mOutputPortSettingsChange(NONE) { 81 initPorts(); 82 CHECK_EQ(initDecoder(), (status_t)OK); 83 } 84 85 SoftAAC2::~SoftAAC2() { 86 aacDecoder_Close(mAACDecoder); 87 delete[] mOutputDelayRingBuffer; 88 } 89 90 void SoftAAC2::initPorts() { 91 OMX_PARAM_PORTDEFINITIONTYPE def; 92 InitOMXParams(&def); 93 94 def.nPortIndex = 0; 95 def.eDir = OMX_DirInput; 96 def.nBufferCountMin = kNumInputBuffers; 97 def.nBufferCountActual = def.nBufferCountMin; 98 def.nBufferSize = 8192; 99 def.bEnabled = OMX_TRUE; 100 def.bPopulated = OMX_FALSE; 101 def.eDomain = OMX_PortDomainAudio; 102 def.bBuffersContiguous = OMX_FALSE; 103 def.nBufferAlignment = 1; 104 105 def.format.audio.cMIMEType = const_cast<char *>("audio/aac"); 106 def.format.audio.pNativeRender = NULL; 107 def.format.audio.bFlagErrorConcealment = OMX_FALSE; 108 def.format.audio.eEncoding = OMX_AUDIO_CodingAAC; 109 110 addPort(def); 111 112 def.nPortIndex = 1; 113 def.eDir = OMX_DirOutput; 114 def.nBufferCountMin = kNumOutputBuffers; 115 def.nBufferCountActual = def.nBufferCountMin; 116 def.nBufferSize = 4096 * MAX_CHANNEL_COUNT; 117 def.bEnabled = OMX_TRUE; 118 def.bPopulated = OMX_FALSE; 119 def.eDomain = OMX_PortDomainAudio; 120 def.bBuffersContiguous = OMX_FALSE; 121 def.nBufferAlignment = 2; 122 123 def.format.audio.cMIMEType = const_cast<char *>("audio/raw"); 124 def.format.audio.pNativeRender = NULL; 125 def.format.audio.bFlagErrorConcealment = OMX_FALSE; 126 def.format.audio.eEncoding = OMX_AUDIO_CodingPCM; 127 128 addPort(def); 129 } 130 131 status_t SoftAAC2::initDecoder() { 132 ALOGV("initDecoder()"); 133 status_t status = UNKNOWN_ERROR; 134 mAACDecoder = aacDecoder_Open(TT_MP4_ADIF, /* num layers */ 1); 135 if (mAACDecoder != NULL) { 136 mStreamInfo = aacDecoder_GetStreamInfo(mAACDecoder); 137 if (mStreamInfo != NULL) { 138 status = OK; 139 } 140 } 141 142 mEndOfInput = false; 143 mEndOfOutput = false; 144 mOutputDelayCompensated = 0; 145 mOutputDelayRingBufferSize = 2048 * MAX_CHANNEL_COUNT * kNumDelayBlocksMax; 146 mOutputDelayRingBuffer = new short[mOutputDelayRingBufferSize]; 147 mOutputDelayRingBufferWritePos = 0; 148 mOutputDelayRingBufferReadPos = 0; 149 mOutputDelayRingBufferFilled = 0; 150 151 if (mAACDecoder == NULL) { 152 ALOGE("AAC decoder is null. TODO: Can not call aacDecoder_SetParam in the following code"); 153 } 154 155 //aacDecoder_SetParam(mAACDecoder, AAC_PCM_LIMITER_ENABLE, 0); 156 157 //init DRC wrapper 158 mDrcWrap.setDecoderHandle(mAACDecoder); 159 mDrcWrap.submitStreamData(mStreamInfo); 160 161 // for streams that contain metadata, use the mobile profile DRC settings unless overridden by platform properties 162 // TODO: change the DRC settings depending on audio output device type (HDMI, loadspeaker, headphone) 163 char value[PROPERTY_VALUE_MAX]; 164 // DRC_PRES_MODE_WRAP_DESIRED_TARGET 165 if (property_get(PROP_DRC_OVERRIDE_REF_LEVEL, value, NULL)) { 166 unsigned refLevel = atoi(value); 167 ALOGV("AAC decoder using desired DRC target reference level of %d instead of %d", refLevel, 168 DRC_DEFAULT_MOBILE_REF_LEVEL); 169 mDrcWrap.setParam(DRC_PRES_MODE_WRAP_DESIRED_TARGET, refLevel); 170 } else { 171 mDrcWrap.setParam(DRC_PRES_MODE_WRAP_DESIRED_TARGET, DRC_DEFAULT_MOBILE_REF_LEVEL); 172 } 173 // DRC_PRES_MODE_WRAP_DESIRED_ATT_FACTOR 174 if (property_get(PROP_DRC_OVERRIDE_CUT, value, NULL)) { 175 unsigned cut = atoi(value); 176 ALOGV("AAC decoder using desired DRC attenuation factor of %d instead of %d", cut, 177 DRC_DEFAULT_MOBILE_DRC_CUT); 178 mDrcWrap.setParam(DRC_PRES_MODE_WRAP_DESIRED_ATT_FACTOR, cut); 179 } else { 180 mDrcWrap.setParam(DRC_PRES_MODE_WRAP_DESIRED_ATT_FACTOR, DRC_DEFAULT_MOBILE_DRC_CUT); 181 } 182 // DRC_PRES_MODE_WRAP_DESIRED_BOOST_FACTOR 183 if (property_get(PROP_DRC_OVERRIDE_BOOST, value, NULL)) { 184 unsigned boost = atoi(value); 185 ALOGV("AAC decoder using desired DRC boost factor of %d instead of %d", boost, 186 DRC_DEFAULT_MOBILE_DRC_BOOST); 187 mDrcWrap.setParam(DRC_PRES_MODE_WRAP_DESIRED_BOOST_FACTOR, boost); 188 } else { 189 mDrcWrap.setParam(DRC_PRES_MODE_WRAP_DESIRED_BOOST_FACTOR, DRC_DEFAULT_MOBILE_DRC_BOOST); 190 } 191 // DRC_PRES_MODE_WRAP_DESIRED_HEAVY 192 if (property_get(PROP_DRC_OVERRIDE_HEAVY, value, NULL)) { 193 unsigned heavy = atoi(value); 194 ALOGV("AAC decoder using desried DRC heavy compression switch of %d instead of %d", heavy, 195 DRC_DEFAULT_MOBILE_DRC_HEAVY); 196 mDrcWrap.setParam(DRC_PRES_MODE_WRAP_DESIRED_HEAVY, heavy); 197 } else { 198 mDrcWrap.setParam(DRC_PRES_MODE_WRAP_DESIRED_HEAVY, DRC_DEFAULT_MOBILE_DRC_HEAVY); 199 } 200 // DRC_PRES_MODE_WRAP_ENCODER_TARGET 201 if (property_get(PROP_DRC_OVERRIDE_ENC_LEVEL, value, NULL)) { 202 unsigned encoderRefLevel = atoi(value); 203 ALOGV("AAC decoder using encoder-side DRC reference level of %d instead of %d", 204 encoderRefLevel, DRC_DEFAULT_MOBILE_ENC_LEVEL); 205 mDrcWrap.setParam(DRC_PRES_MODE_WRAP_ENCODER_TARGET, encoderRefLevel); 206 } else { 207 mDrcWrap.setParam(DRC_PRES_MODE_WRAP_ENCODER_TARGET, DRC_DEFAULT_MOBILE_ENC_LEVEL); 208 } 209 210 // By default, the decoder creates a 5.1 channel downmix signal. 211 // For seven and eight channel input streams, enable 6.1 and 7.1 channel output 212 aacDecoder_SetParam(mAACDecoder, AAC_PCM_MAX_OUTPUT_CHANNELS, -1); 213 214 return status; 215 } 216 217 OMX_ERRORTYPE SoftAAC2::internalGetParameter( 218 OMX_INDEXTYPE index, OMX_PTR params) { 219 switch ((OMX_U32) index) { 220 case OMX_IndexParamAudioAac: 221 { 222 OMX_AUDIO_PARAM_AACPROFILETYPE *aacParams = 223 (OMX_AUDIO_PARAM_AACPROFILETYPE *)params; 224 225 if (!isValidOMXParam(aacParams)) { 226 return OMX_ErrorBadParameter; 227 } 228 229 if (aacParams->nPortIndex != 0) { 230 return OMX_ErrorUndefined; 231 } 232 233 aacParams->nBitRate = 0; 234 aacParams->nAudioBandWidth = 0; 235 aacParams->nAACtools = 0; 236 aacParams->nAACERtools = 0; 237 aacParams->eAACProfile = OMX_AUDIO_AACObjectMain; 238 239 aacParams->eAACStreamFormat = 240 mIsADTS 241 ? OMX_AUDIO_AACStreamFormatMP4ADTS 242 : OMX_AUDIO_AACStreamFormatMP4FF; 243 244 aacParams->eChannelMode = OMX_AUDIO_ChannelModeStereo; 245 246 if (!isConfigured()) { 247 aacParams->nChannels = 1; 248 aacParams->nSampleRate = 44100; 249 aacParams->nFrameLength = 0; 250 } else { 251 aacParams->nChannels = mStreamInfo->numChannels; 252 aacParams->nSampleRate = mStreamInfo->sampleRate; 253 aacParams->nFrameLength = mStreamInfo->frameSize; 254 } 255 256 return OMX_ErrorNone; 257 } 258 259 case OMX_IndexParamAudioPcm: 260 { 261 OMX_AUDIO_PARAM_PCMMODETYPE *pcmParams = 262 (OMX_AUDIO_PARAM_PCMMODETYPE *)params; 263 264 if (!isValidOMXParam(pcmParams)) { 265 return OMX_ErrorBadParameter; 266 } 267 268 if (pcmParams->nPortIndex != 1) { 269 return OMX_ErrorUndefined; 270 } 271 272 pcmParams->eNumData = OMX_NumericalDataSigned; 273 pcmParams->eEndian = OMX_EndianBig; 274 pcmParams->bInterleaved = OMX_TRUE; 275 pcmParams->nBitPerSample = 16; 276 pcmParams->ePCMMode = OMX_AUDIO_PCMModeLinear; 277 pcmParams->eChannelMapping[0] = OMX_AUDIO_ChannelLF; 278 pcmParams->eChannelMapping[1] = OMX_AUDIO_ChannelRF; 279 pcmParams->eChannelMapping[2] = OMX_AUDIO_ChannelCF; 280 pcmParams->eChannelMapping[3] = OMX_AUDIO_ChannelLFE; 281 pcmParams->eChannelMapping[4] = OMX_AUDIO_ChannelLS; 282 pcmParams->eChannelMapping[5] = OMX_AUDIO_ChannelRS; 283 284 if (!isConfigured()) { 285 pcmParams->nChannels = 1; 286 pcmParams->nSamplingRate = 44100; 287 } else { 288 pcmParams->nChannels = mStreamInfo->numChannels; 289 pcmParams->nSamplingRate = mStreamInfo->sampleRate; 290 } 291 292 return OMX_ErrorNone; 293 } 294 295 case OMX_IndexParamAudioProfileQuerySupported: 296 { 297 OMX_AUDIO_PARAM_ANDROID_PROFILETYPE *profileParams = 298 (OMX_AUDIO_PARAM_ANDROID_PROFILETYPE *)params; 299 300 if (!isValidOMXParam(profileParams)) { 301 return OMX_ErrorBadParameter; 302 } 303 304 if (profileParams->nPortIndex != 0) { 305 return OMX_ErrorUndefined; 306 } 307 308 if (profileParams->nProfileIndex >= NELEM(kSupportedProfiles)) { 309 return OMX_ErrorNoMore; 310 } 311 312 profileParams->eProfile = 313 kSupportedProfiles[profileParams->nProfileIndex]; 314 315 return OMX_ErrorNone; 316 } 317 318 default: 319 return SimpleSoftOMXComponent::internalGetParameter(index, params); 320 } 321 } 322 323 OMX_ERRORTYPE SoftAAC2::internalSetParameter( 324 OMX_INDEXTYPE index, const OMX_PTR params) { 325 switch ((int)index) { 326 case OMX_IndexParamStandardComponentRole: 327 { 328 const OMX_PARAM_COMPONENTROLETYPE *roleParams = 329 (const OMX_PARAM_COMPONENTROLETYPE *)params; 330 331 if (!isValidOMXParam(roleParams)) { 332 return OMX_ErrorBadParameter; 333 } 334 335 if (strncmp((const char *)roleParams->cRole, 336 "audio_decoder.aac", 337 OMX_MAX_STRINGNAME_SIZE - 1)) { 338 return OMX_ErrorUndefined; 339 } 340 341 return OMX_ErrorNone; 342 } 343 344 case OMX_IndexParamAudioAac: 345 { 346 const OMX_AUDIO_PARAM_AACPROFILETYPE *aacParams = 347 (const OMX_AUDIO_PARAM_AACPROFILETYPE *)params; 348 349 if (!isValidOMXParam(aacParams)) { 350 return OMX_ErrorBadParameter; 351 } 352 353 if (aacParams->nPortIndex != 0) { 354 return OMX_ErrorUndefined; 355 } 356 357 if (aacParams->eAACStreamFormat == OMX_AUDIO_AACStreamFormatMP4FF) { 358 mIsADTS = false; 359 } else if (aacParams->eAACStreamFormat 360 == OMX_AUDIO_AACStreamFormatMP4ADTS) { 361 mIsADTS = true; 362 } else { 363 return OMX_ErrorUndefined; 364 } 365 366 return OMX_ErrorNone; 367 } 368 369 case OMX_IndexParamAudioAndroidAacPresentation: 370 { 371 const OMX_AUDIO_PARAM_ANDROID_AACPRESENTATIONTYPE *aacPresParams = 372 (const OMX_AUDIO_PARAM_ANDROID_AACPRESENTATIONTYPE *)params; 373 374 if (!isValidOMXParam(aacPresParams)) { 375 return OMX_ErrorBadParameter; 376 } 377 378 // for the following parameters of the OMX_AUDIO_PARAM_AACPROFILETYPE structure, 379 // a value of -1 implies the parameter is not set by the application: 380 // nMaxOutputChannels -1 by default 381 // nDrcCut uses default platform properties, see initDecoder() 382 // nDrcBoost idem 383 // nHeavyCompression idem 384 // nTargetReferenceLevel idem 385 // nEncodedTargetLevel idem 386 if (aacPresParams->nMaxOutputChannels >= 0) { 387 int max; 388 if (aacPresParams->nMaxOutputChannels >= 8) { max = 8; } 389 else if (aacPresParams->nMaxOutputChannels >= 6) { max = 6; } 390 else if (aacPresParams->nMaxOutputChannels >= 2) { max = 2; } 391 else { 392 // -1 or 0: disable downmix, 1: mono 393 max = aacPresParams->nMaxOutputChannels; 394 } 395 ALOGV("set nMaxOutputChannels=%d", max); 396 aacDecoder_SetParam(mAACDecoder, AAC_PCM_MAX_OUTPUT_CHANNELS, max); 397 } 398 bool updateDrcWrapper = false; 399 if (aacPresParams->nDrcBoost >= 0) { 400 ALOGV("set nDrcBoost=%d", aacPresParams->nDrcBoost); 401 mDrcWrap.setParam(DRC_PRES_MODE_WRAP_DESIRED_BOOST_FACTOR, 402 aacPresParams->nDrcBoost); 403 updateDrcWrapper = true; 404 } 405 if (aacPresParams->nDrcCut >= 0) { 406 ALOGV("set nDrcCut=%d", aacPresParams->nDrcCut); 407 mDrcWrap.setParam(DRC_PRES_MODE_WRAP_DESIRED_ATT_FACTOR, aacPresParams->nDrcCut); 408 updateDrcWrapper = true; 409 } 410 if (aacPresParams->nHeavyCompression >= 0) { 411 ALOGV("set nHeavyCompression=%d", aacPresParams->nHeavyCompression); 412 mDrcWrap.setParam(DRC_PRES_MODE_WRAP_DESIRED_HEAVY, 413 aacPresParams->nHeavyCompression); 414 updateDrcWrapper = true; 415 } 416 if (aacPresParams->nTargetReferenceLevel >= 0) { 417 ALOGV("set nTargetReferenceLevel=%d", aacPresParams->nTargetReferenceLevel); 418 mDrcWrap.setParam(DRC_PRES_MODE_WRAP_DESIRED_TARGET, 419 aacPresParams->nTargetReferenceLevel); 420 updateDrcWrapper = true; 421 } 422 if (aacPresParams->nEncodedTargetLevel >= 0) { 423 ALOGV("set nEncodedTargetLevel=%d", aacPresParams->nEncodedTargetLevel); 424 mDrcWrap.setParam(DRC_PRES_MODE_WRAP_ENCODER_TARGET, 425 aacPresParams->nEncodedTargetLevel); 426 updateDrcWrapper = true; 427 } 428 if (aacPresParams->nPCMLimiterEnable >= 0) { 429 aacDecoder_SetParam(mAACDecoder, AAC_PCM_LIMITER_ENABLE, 430 (aacPresParams->nPCMLimiterEnable != 0)); 431 } 432 if (updateDrcWrapper) { 433 mDrcWrap.update(); 434 } 435 436 return OMX_ErrorNone; 437 } 438 439 case OMX_IndexParamAudioPcm: 440 { 441 const OMX_AUDIO_PARAM_PCMMODETYPE *pcmParams = 442 (OMX_AUDIO_PARAM_PCMMODETYPE *)params; 443 444 if (!isValidOMXParam(pcmParams)) { 445 return OMX_ErrorBadParameter; 446 } 447 448 if (pcmParams->nPortIndex != 1) { 449 return OMX_ErrorUndefined; 450 } 451 452 return OMX_ErrorNone; 453 } 454 455 default: 456 return SimpleSoftOMXComponent::internalSetParameter(index, params); 457 } 458 } 459 460 bool SoftAAC2::isConfigured() const { 461 return mInputBufferCount > 0; 462 } 463 464 bool SoftAAC2::outputDelayRingBufferPutSamples(INT_PCM *samples, int32_t numSamples) { 465 if (numSamples == 0) { 466 return true; 467 } 468 if (outputDelayRingBufferSpaceLeft() < numSamples) { 469 ALOGE("RING BUFFER WOULD OVERFLOW"); 470 return false; 471 } 472 if (mOutputDelayRingBufferWritePos + numSamples <= mOutputDelayRingBufferSize 473 && (mOutputDelayRingBufferReadPos <= mOutputDelayRingBufferWritePos 474 || mOutputDelayRingBufferReadPos > mOutputDelayRingBufferWritePos + numSamples)) { 475 // faster memcopy loop without checks, if the preconditions allow this 476 for (int32_t i = 0; i < numSamples; i++) { 477 mOutputDelayRingBuffer[mOutputDelayRingBufferWritePos++] = samples[i]; 478 } 479 480 if (mOutputDelayRingBufferWritePos >= mOutputDelayRingBufferSize) { 481 mOutputDelayRingBufferWritePos -= mOutputDelayRingBufferSize; 482 } 483 } else { 484 ALOGV("slow SoftAAC2::outputDelayRingBufferPutSamples()"); 485 486 for (int32_t i = 0; i < numSamples; i++) { 487 mOutputDelayRingBuffer[mOutputDelayRingBufferWritePos] = samples[i]; 488 mOutputDelayRingBufferWritePos++; 489 if (mOutputDelayRingBufferWritePos >= mOutputDelayRingBufferSize) { 490 mOutputDelayRingBufferWritePos -= mOutputDelayRingBufferSize; 491 } 492 } 493 } 494 mOutputDelayRingBufferFilled += numSamples; 495 return true; 496 } 497 498 int32_t SoftAAC2::outputDelayRingBufferGetSamples(INT_PCM *samples, int32_t numSamples) { 499 500 if (numSamples > mOutputDelayRingBufferFilled) { 501 ALOGE("RING BUFFER WOULD UNDERRUN"); 502 return -1; 503 } 504 505 if (mOutputDelayRingBufferReadPos + numSamples <= mOutputDelayRingBufferSize 506 && (mOutputDelayRingBufferWritePos < mOutputDelayRingBufferReadPos 507 || mOutputDelayRingBufferWritePos >= mOutputDelayRingBufferReadPos + numSamples)) { 508 // faster memcopy loop without checks, if the preconditions allow this 509 if (samples != 0) { 510 for (int32_t i = 0; i < numSamples; i++) { 511 samples[i] = mOutputDelayRingBuffer[mOutputDelayRingBufferReadPos++]; 512 } 513 } else { 514 mOutputDelayRingBufferReadPos += numSamples; 515 } 516 if (mOutputDelayRingBufferReadPos >= mOutputDelayRingBufferSize) { 517 mOutputDelayRingBufferReadPos -= mOutputDelayRingBufferSize; 518 } 519 } else { 520 ALOGV("slow SoftAAC2::outputDelayRingBufferGetSamples()"); 521 522 for (int32_t i = 0; i < numSamples; i++) { 523 if (samples != 0) { 524 samples[i] = mOutputDelayRingBuffer[mOutputDelayRingBufferReadPos]; 525 } 526 mOutputDelayRingBufferReadPos++; 527 if (mOutputDelayRingBufferReadPos >= mOutputDelayRingBufferSize) { 528 mOutputDelayRingBufferReadPos -= mOutputDelayRingBufferSize; 529 } 530 } 531 } 532 mOutputDelayRingBufferFilled -= numSamples; 533 return numSamples; 534 } 535 536 int32_t SoftAAC2::outputDelayRingBufferSamplesAvailable() { 537 return mOutputDelayRingBufferFilled; 538 } 539 540 int32_t SoftAAC2::outputDelayRingBufferSpaceLeft() { 541 return mOutputDelayRingBufferSize - outputDelayRingBufferSamplesAvailable(); 542 } 543 544 545 void SoftAAC2::onQueueFilled(OMX_U32 /* portIndex */) { 546 if (mSignalledError || mOutputPortSettingsChange != NONE) { 547 return; 548 } 549 550 UCHAR* inBuffer[FILEREAD_MAX_LAYERS]; 551 UINT inBufferLength[FILEREAD_MAX_LAYERS] = {0}; 552 UINT bytesValid[FILEREAD_MAX_LAYERS] = {0}; 553 554 List<BufferInfo *> &inQueue = getPortQueue(0); 555 List<BufferInfo *> &outQueue = getPortQueue(1); 556 557 while ((!inQueue.empty() || mEndOfInput) && !outQueue.empty()) { 558 if (!inQueue.empty()) { 559 INT_PCM tmpOutBuffer[2048 * MAX_CHANNEL_COUNT]; 560 BufferInfo *inInfo = *inQueue.begin(); 561 OMX_BUFFERHEADERTYPE *inHeader = inInfo->mHeader; 562 563 mEndOfInput = (inHeader->nFlags & OMX_BUFFERFLAG_EOS) != 0; 564 565 if (mInputBufferCount == 0 && !(inHeader->nFlags & OMX_BUFFERFLAG_CODECCONFIG)) { 566 ALOGE("first buffer should have OMX_BUFFERFLAG_CODECCONFIG set"); 567 inHeader->nFlags |= OMX_BUFFERFLAG_CODECCONFIG; 568 } 569 if ((inHeader->nFlags & OMX_BUFFERFLAG_CODECCONFIG) != 0) { 570 BufferInfo *inInfo = *inQueue.begin(); 571 OMX_BUFFERHEADERTYPE *inHeader = inInfo->mHeader; 572 573 inBuffer[0] = inHeader->pBuffer + inHeader->nOffset; 574 inBufferLength[0] = inHeader->nFilledLen; 575 576 AAC_DECODER_ERROR decoderErr = 577 aacDecoder_ConfigRaw(mAACDecoder, 578 inBuffer, 579 inBufferLength); 580 581 if (decoderErr != AAC_DEC_OK) { 582 ALOGW("aacDecoder_ConfigRaw decoderErr = 0x%4.4x", decoderErr); 583 mSignalledError = true; 584 notify(OMX_EventError, OMX_ErrorUndefined, decoderErr, NULL); 585 return; 586 } 587 588 mInputBufferCount++; 589 mOutputBufferCount++; // fake increase of outputBufferCount to keep the counters aligned 590 591 inInfo->mOwnedByUs = false; 592 inQueue.erase(inQueue.begin()); 593 mLastInHeader = NULL; 594 inInfo = NULL; 595 notifyEmptyBufferDone(inHeader); 596 inHeader = NULL; 597 598 // Only send out port settings changed event if both sample rate 599 // and numChannels are valid. 600 if (mStreamInfo->sampleRate && mStreamInfo->numChannels) { 601 ALOGI("Initially configuring decoder: %d Hz, %d channels", 602 mStreamInfo->sampleRate, 603 mStreamInfo->numChannels); 604 605 notify(OMX_EventPortSettingsChanged, 1, 0, NULL); 606 mOutputPortSettingsChange = AWAITING_DISABLED; 607 } 608 return; 609 } 610 611 if (inHeader->nFilledLen == 0) { 612 inInfo->mOwnedByUs = false; 613 inQueue.erase(inQueue.begin()); 614 mLastInHeader = NULL; 615 inInfo = NULL; 616 notifyEmptyBufferDone(inHeader); 617 inHeader = NULL; 618 continue; 619 } 620 621 if (mIsADTS) { 622 size_t adtsHeaderSize = 0; 623 // skip 30 bits, aac_frame_length follows. 624 // ssssssss ssssiiip ppffffPc ccohCCll llllllll lll????? 625 626 const uint8_t *adtsHeader = inHeader->pBuffer + inHeader->nOffset; 627 628 bool signalError = false; 629 if (inHeader->nFilledLen < 7) { 630 ALOGE("Audio data too short to contain even the ADTS header. " 631 "Got %d bytes.", inHeader->nFilledLen); 632 hexdump(adtsHeader, inHeader->nFilledLen); 633 signalError = true; 634 } else { 635 bool protectionAbsent = (adtsHeader[1] & 1); 636 637 unsigned aac_frame_length = 638 ((adtsHeader[3] & 3) << 11) 639 | (adtsHeader[4] << 3) 640 | (adtsHeader[5] >> 5); 641 642 if (inHeader->nFilledLen < aac_frame_length) { 643 ALOGE("Not enough audio data for the complete frame. " 644 "Got %d bytes, frame size according to the ADTS " 645 "header is %u bytes.", 646 inHeader->nFilledLen, aac_frame_length); 647 hexdump(adtsHeader, inHeader->nFilledLen); 648 signalError = true; 649 } else { 650 adtsHeaderSize = (protectionAbsent ? 7 : 9); 651 if (aac_frame_length < adtsHeaderSize) { 652 signalError = true; 653 } else { 654 inBuffer[0] = (UCHAR *)adtsHeader + adtsHeaderSize; 655 inBufferLength[0] = aac_frame_length - adtsHeaderSize; 656 657 inHeader->nOffset += adtsHeaderSize; 658 inHeader->nFilledLen -= adtsHeaderSize; 659 } 660 } 661 } 662 663 if (signalError) { 664 mSignalledError = true; 665 notify(OMX_EventError, OMX_ErrorStreamCorrupt, ERROR_MALFORMED, NULL); 666 return; 667 } 668 669 // insert buffer size and time stamp 670 mBufferSizes.add(inBufferLength[0]); 671 if (mLastInHeader != inHeader) { 672 mBufferTimestamps.add(inHeader->nTimeStamp); 673 mLastInHeader = inHeader; 674 } else { 675 int64_t currentTime = mBufferTimestamps.top(); 676 currentTime += mStreamInfo->aacSamplesPerFrame * 677 1000000ll / mStreamInfo->aacSampleRate; 678 mBufferTimestamps.add(currentTime); 679 } 680 } else { 681 inBuffer[0] = inHeader->pBuffer + inHeader->nOffset; 682 inBufferLength[0] = inHeader->nFilledLen; 683 mLastInHeader = inHeader; 684 mBufferTimestamps.add(inHeader->nTimeStamp); 685 mBufferSizes.add(inHeader->nFilledLen); 686 } 687 688 // Fill and decode 689 bytesValid[0] = inBufferLength[0]; 690 691 INT prevSampleRate = mStreamInfo->sampleRate; 692 INT prevNumChannels = mStreamInfo->numChannels; 693 694 aacDecoder_Fill(mAACDecoder, 695 inBuffer, 696 inBufferLength, 697 bytesValid); 698 699 // run DRC check 700 mDrcWrap.submitStreamData(mStreamInfo); 701 mDrcWrap.update(); 702 703 UINT inBufferUsedLength = inBufferLength[0] - bytesValid[0]; 704 inHeader->nFilledLen -= inBufferUsedLength; 705 inHeader->nOffset += inBufferUsedLength; 706 707 AAC_DECODER_ERROR decoderErr; 708 int numLoops = 0; 709 do { 710 if (outputDelayRingBufferSpaceLeft() < 711 (mStreamInfo->frameSize * mStreamInfo->numChannels)) { 712 ALOGV("skipping decode: not enough space left in ringbuffer"); 713 break; 714 } 715 716 int numConsumed = mStreamInfo->numTotalBytes; 717 decoderErr = aacDecoder_DecodeFrame(mAACDecoder, 718 tmpOutBuffer, 719 2048 * MAX_CHANNEL_COUNT, 720 0 /* flags */); 721 722 numConsumed = mStreamInfo->numTotalBytes - numConsumed; 723 numLoops++; 724 725 if (decoderErr == AAC_DEC_NOT_ENOUGH_BITS) { 726 break; 727 } 728 mDecodedSizes.add(numConsumed); 729 730 if (decoderErr != AAC_DEC_OK) { 731 ALOGW("aacDecoder_DecodeFrame decoderErr = 0x%4.4x", decoderErr); 732 } 733 734 if (bytesValid[0] != 0) { 735 ALOGE("bytesValid[0] != 0 should never happen"); 736 mSignalledError = true; 737 notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL); 738 return; 739 } 740 741 size_t numOutBytes = 742 mStreamInfo->frameSize * sizeof(int16_t) * mStreamInfo->numChannels; 743 744 if (decoderErr == AAC_DEC_OK) { 745 if (!outputDelayRingBufferPutSamples(tmpOutBuffer, 746 mStreamInfo->frameSize * mStreamInfo->numChannels)) { 747 mSignalledError = true; 748 notify(OMX_EventError, OMX_ErrorUndefined, decoderErr, NULL); 749 return; 750 } 751 } else { 752 ALOGW("AAC decoder returned error 0x%4.4x, substituting silence", decoderErr); 753 754 memset(tmpOutBuffer, 0, numOutBytes); // TODO: check for overflow 755 756 if (!outputDelayRingBufferPutSamples(tmpOutBuffer, 757 mStreamInfo->frameSize * mStreamInfo->numChannels)) { 758 mSignalledError = true; 759 notify(OMX_EventError, OMX_ErrorUndefined, decoderErr, NULL); 760 return; 761 } 762 763 // Discard input buffer. 764 if (inHeader) { 765 inHeader->nFilledLen = 0; 766 } 767 768 aacDecoder_SetParam(mAACDecoder, AAC_TPDEC_CLEAR_BUFFER, 1); 769 770 // After an error, replace the last entry in mBufferSizes with the sum of the 771 // last <numLoops> entries from mDecodedSizes to resynchronize the in/out lists. 772 mBufferSizes.pop(); 773 int n = 0; 774 for (int i = 0; i < numLoops; i++) { 775 n += mDecodedSizes.itemAt(mDecodedSizes.size() - numLoops + i); 776 } 777 mBufferSizes.add(n); 778 779 // fall through 780 } 781 782 /* 783 * AAC+/eAAC+ streams can be signalled in two ways: either explicitly 784 * or implicitly, according to MPEG4 spec. AAC+/eAAC+ is a dual 785 * rate system and the sampling rate in the final output is actually 786 * doubled compared with the core AAC decoder sampling rate. 787 * 788 * Explicit signalling is done by explicitly defining SBR audio object 789 * type in the bitstream. Implicit signalling is done by embedding 790 * SBR content in AAC extension payload specific to SBR, and hence 791 * requires an AAC decoder to perform pre-checks on actual audio frames. 792 * 793 * Thus, we could not say for sure whether a stream is 794 * AAC+/eAAC+ until the first data frame is decoded. 795 */ 796 if (!mStreamInfo->sampleRate || !mStreamInfo->numChannels) { 797 if ((mInputBufferCount > 2) && (mOutputBufferCount <= 1)) { 798 ALOGW("Invalid AAC stream"); 799 mSignalledError = true; 800 notify(OMX_EventError, OMX_ErrorUndefined, decoderErr, NULL); 801 return; 802 } 803 } else if ((mStreamInfo->sampleRate != prevSampleRate) || 804 (mStreamInfo->numChannels != prevNumChannels)) { 805 ALOGI("Reconfiguring decoder: %d->%d Hz, %d->%d channels", 806 prevSampleRate, mStreamInfo->sampleRate, 807 prevNumChannels, mStreamInfo->numChannels); 808 809 notify(OMX_EventPortSettingsChanged, 1, 0, NULL); 810 mOutputPortSettingsChange = AWAITING_DISABLED; 811 812 if (inHeader && inHeader->nFilledLen == 0) { 813 inInfo->mOwnedByUs = false; 814 mInputBufferCount++; 815 inQueue.erase(inQueue.begin()); 816 mLastInHeader = NULL; 817 inInfo = NULL; 818 notifyEmptyBufferDone(inHeader); 819 inHeader = NULL; 820 } 821 return; 822 } 823 if (inHeader && inHeader->nFilledLen == 0) { 824 inInfo->mOwnedByUs = false; 825 mInputBufferCount++; 826 inQueue.erase(inQueue.begin()); 827 mLastInHeader = NULL; 828 inInfo = NULL; 829 notifyEmptyBufferDone(inHeader); 830 inHeader = NULL; 831 } else { 832 ALOGV("inHeader->nFilledLen = %d", inHeader ? inHeader->nFilledLen : 0); 833 } 834 } while (decoderErr == AAC_DEC_OK); 835 } 836 837 int32_t outputDelay = mStreamInfo->outputDelay * mStreamInfo->numChannels; 838 839 if (!mEndOfInput && mOutputDelayCompensated < outputDelay) { 840 // discard outputDelay at the beginning 841 int32_t toCompensate = outputDelay - mOutputDelayCompensated; 842 int32_t discard = outputDelayRingBufferSamplesAvailable(); 843 if (discard > toCompensate) { 844 discard = toCompensate; 845 } 846 int32_t discarded = outputDelayRingBufferGetSamples(0, discard); 847 mOutputDelayCompensated += discarded; 848 continue; 849 } 850 851 if (mEndOfInput) { 852 while (mOutputDelayCompensated > 0) { 853 // a buffer big enough for MAX_CHANNEL_COUNT channels of decoded HE-AAC 854 INT_PCM tmpOutBuffer[2048 * MAX_CHANNEL_COUNT]; 855 856 // run DRC check 857 mDrcWrap.submitStreamData(mStreamInfo); 858 mDrcWrap.update(); 859 860 AAC_DECODER_ERROR decoderErr = 861 aacDecoder_DecodeFrame(mAACDecoder, 862 tmpOutBuffer, 863 2048 * MAX_CHANNEL_COUNT, 864 AACDEC_FLUSH); 865 if (decoderErr != AAC_DEC_OK) { 866 ALOGW("aacDecoder_DecodeFrame decoderErr = 0x%4.4x", decoderErr); 867 } 868 869 int32_t tmpOutBufferSamples = mStreamInfo->frameSize * mStreamInfo->numChannels; 870 if (tmpOutBufferSamples > mOutputDelayCompensated) { 871 tmpOutBufferSamples = mOutputDelayCompensated; 872 } 873 outputDelayRingBufferPutSamples(tmpOutBuffer, tmpOutBufferSamples); 874 mOutputDelayCompensated -= tmpOutBufferSamples; 875 } 876 } 877 878 while (!outQueue.empty() 879 && outputDelayRingBufferSamplesAvailable() 880 >= mStreamInfo->frameSize * mStreamInfo->numChannels) { 881 BufferInfo *outInfo = *outQueue.begin(); 882 OMX_BUFFERHEADERTYPE *outHeader = outInfo->mHeader; 883 884 if (outHeader->nOffset != 0) { 885 ALOGE("outHeader->nOffset != 0 is not handled"); 886 mSignalledError = true; 887 notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL); 888 return; 889 } 890 891 INT_PCM *outBuffer = 892 reinterpret_cast<INT_PCM *>(outHeader->pBuffer + outHeader->nOffset); 893 int samplesize = mStreamInfo->numChannels * sizeof(int16_t); 894 if (outHeader->nOffset 895 + mStreamInfo->frameSize * samplesize 896 > outHeader->nAllocLen) { 897 ALOGE("buffer overflow"); 898 mSignalledError = true; 899 notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL); 900 return; 901 902 } 903 904 int available = outputDelayRingBufferSamplesAvailable(); 905 int numSamples = outHeader->nAllocLen / sizeof(int16_t); 906 if (numSamples > available) { 907 numSamples = available; 908 } 909 int64_t currentTime = 0; 910 if (available) { 911 912 int numFrames = numSamples / (mStreamInfo->frameSize * mStreamInfo->numChannels); 913 numSamples = numFrames * (mStreamInfo->frameSize * mStreamInfo->numChannels); 914 915 ALOGV("%d samples available (%d), or %d frames", 916 numSamples, available, numFrames); 917 int64_t *nextTimeStamp = &mBufferTimestamps.editItemAt(0); 918 currentTime = *nextTimeStamp; 919 int32_t *currentBufLeft = &mBufferSizes.editItemAt(0); 920 for (int i = 0; i < numFrames; i++) { 921 int32_t decodedSize = mDecodedSizes.itemAt(0); 922 mDecodedSizes.removeAt(0); 923 ALOGV("decoded %d of %d", decodedSize, *currentBufLeft); 924 if (*currentBufLeft > decodedSize) { 925 // adjust/interpolate next time stamp 926 *currentBufLeft -= decodedSize; 927 *nextTimeStamp += mStreamInfo->aacSamplesPerFrame * 928 1000000ll / mStreamInfo->aacSampleRate; 929 ALOGV("adjusted nextTimeStamp/size to %lld/%d", 930 (long long) *nextTimeStamp, *currentBufLeft); 931 } else { 932 // move to next timestamp in list 933 if (mBufferTimestamps.size() > 0) { 934 mBufferTimestamps.removeAt(0); 935 nextTimeStamp = &mBufferTimestamps.editItemAt(0); 936 mBufferSizes.removeAt(0); 937 currentBufLeft = &mBufferSizes.editItemAt(0); 938 ALOGV("moved to next time/size: %lld/%d", 939 (long long) *nextTimeStamp, *currentBufLeft); 940 } 941 // try to limit output buffer size to match input buffers 942 // (e.g when an input buffer contained 4 "sub" frames, output 943 // at most 4 decoded units in the corresponding output buffer) 944 // This is optional. Remove the next three lines to fill the output 945 // buffer with as many units as available. 946 numFrames = i + 1; 947 numSamples = numFrames * mStreamInfo->frameSize * mStreamInfo->numChannels; 948 break; 949 } 950 } 951 952 ALOGV("getting %d from ringbuffer", numSamples); 953 int32_t ns = outputDelayRingBufferGetSamples(outBuffer, numSamples); 954 if (ns != numSamples) { 955 ALOGE("not a complete frame of samples available"); 956 mSignalledError = true; 957 notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL); 958 return; 959 } 960 } 961 962 outHeader->nFilledLen = numSamples * sizeof(int16_t); 963 964 if (mEndOfInput && !outQueue.empty() && outputDelayRingBufferSamplesAvailable() == 0) { 965 outHeader->nFlags = OMX_BUFFERFLAG_EOS; 966 mEndOfOutput = true; 967 } else { 968 outHeader->nFlags = 0; 969 } 970 971 outHeader->nTimeStamp = currentTime; 972 973 mOutputBufferCount++; 974 outInfo->mOwnedByUs = false; 975 outQueue.erase(outQueue.begin()); 976 outInfo = NULL; 977 ALOGV("out timestamp %lld / %d", outHeader->nTimeStamp, outHeader->nFilledLen); 978 notifyFillBufferDone(outHeader); 979 outHeader = NULL; 980 } 981 982 if (mEndOfInput) { 983 int ringBufAvail = outputDelayRingBufferSamplesAvailable(); 984 if (!outQueue.empty() 985 && ringBufAvail < mStreamInfo->frameSize * mStreamInfo->numChannels) { 986 if (!mEndOfOutput) { 987 // send partial or empty block signaling EOS 988 mEndOfOutput = true; 989 BufferInfo *outInfo = *outQueue.begin(); 990 OMX_BUFFERHEADERTYPE *outHeader = outInfo->mHeader; 991 992 INT_PCM *outBuffer = reinterpret_cast<INT_PCM *>(outHeader->pBuffer 993 + outHeader->nOffset); 994 int32_t ns = outputDelayRingBufferGetSamples(outBuffer, ringBufAvail); 995 if (ns < 0) { 996 ns = 0; 997 } 998 outHeader->nFilledLen = ns; 999 outHeader->nFlags = OMX_BUFFERFLAG_EOS; 1000 1001 outHeader->nTimeStamp = mBufferTimestamps.itemAt(0); 1002 mBufferTimestamps.clear(); 1003 mBufferSizes.clear(); 1004 mDecodedSizes.clear(); 1005 1006 mOutputBufferCount++; 1007 outInfo->mOwnedByUs = false; 1008 outQueue.erase(outQueue.begin()); 1009 outInfo = NULL; 1010 notifyFillBufferDone(outHeader); 1011 outHeader = NULL; 1012 } 1013 break; // if outQueue not empty but no more output 1014 } 1015 } 1016 } 1017 } 1018 1019 void SoftAAC2::onPortFlushCompleted(OMX_U32 portIndex) { 1020 if (portIndex == 0) { 1021 // Make sure that the next buffer output does not still 1022 // depend on fragments from the last one decoded. 1023 // drain all existing data 1024 drainDecoder(); 1025 mBufferTimestamps.clear(); 1026 mBufferSizes.clear(); 1027 mDecodedSizes.clear(); 1028 mLastInHeader = NULL; 1029 mEndOfInput = false; 1030 } else { 1031 int avail; 1032 while ((avail = outputDelayRingBufferSamplesAvailable()) > 0) { 1033 if (avail > mStreamInfo->frameSize * mStreamInfo->numChannels) { 1034 avail = mStreamInfo->frameSize * mStreamInfo->numChannels; 1035 } 1036 int32_t ns = outputDelayRingBufferGetSamples(0, avail); 1037 if (ns != avail) { 1038 ALOGW("not a complete frame of samples available"); 1039 break; 1040 } 1041 mOutputBufferCount++; 1042 } 1043 mOutputDelayRingBufferReadPos = mOutputDelayRingBufferWritePos; 1044 mEndOfOutput = false; 1045 } 1046 } 1047 1048 void SoftAAC2::drainDecoder() { 1049 // flush decoder until outputDelay is compensated 1050 while (mOutputDelayCompensated > 0) { 1051 // a buffer big enough for MAX_CHANNEL_COUNT channels of decoded HE-AAC 1052 INT_PCM tmpOutBuffer[2048 * MAX_CHANNEL_COUNT]; 1053 1054 // run DRC check 1055 mDrcWrap.submitStreamData(mStreamInfo); 1056 mDrcWrap.update(); 1057 1058 AAC_DECODER_ERROR decoderErr = 1059 aacDecoder_DecodeFrame(mAACDecoder, 1060 tmpOutBuffer, 1061 2048 * MAX_CHANNEL_COUNT, 1062 AACDEC_FLUSH); 1063 if (decoderErr != AAC_DEC_OK) { 1064 ALOGW("aacDecoder_DecodeFrame decoderErr = 0x%4.4x", decoderErr); 1065 } 1066 1067 int32_t tmpOutBufferSamples = mStreamInfo->frameSize * mStreamInfo->numChannels; 1068 if (tmpOutBufferSamples > mOutputDelayCompensated) { 1069 tmpOutBufferSamples = mOutputDelayCompensated; 1070 } 1071 outputDelayRingBufferPutSamples(tmpOutBuffer, tmpOutBufferSamples); 1072 1073 mOutputDelayCompensated -= tmpOutBufferSamples; 1074 } 1075 } 1076 1077 void SoftAAC2::onReset() { 1078 drainDecoder(); 1079 // reset the "configured" state 1080 mInputBufferCount = 0; 1081 mOutputBufferCount = 0; 1082 mOutputDelayCompensated = 0; 1083 mOutputDelayRingBufferWritePos = 0; 1084 mOutputDelayRingBufferReadPos = 0; 1085 mOutputDelayRingBufferFilled = 0; 1086 mEndOfInput = false; 1087 mEndOfOutput = false; 1088 mBufferTimestamps.clear(); 1089 mBufferSizes.clear(); 1090 mDecodedSizes.clear(); 1091 mLastInHeader = NULL; 1092 1093 // To make the codec behave the same before and after a reset, we need to invalidate the 1094 // streaminfo struct. This does that: 1095 mStreamInfo->sampleRate = 0; // TODO: mStreamInfo is read only 1096 1097 mSignalledError = false; 1098 mOutputPortSettingsChange = NONE; 1099 } 1100 1101 void SoftAAC2::onPortEnableCompleted(OMX_U32 portIndex, bool enabled) { 1102 if (portIndex != 1) { 1103 return; 1104 } 1105 1106 switch (mOutputPortSettingsChange) { 1107 case NONE: 1108 break; 1109 1110 case AWAITING_DISABLED: 1111 { 1112 CHECK(!enabled); 1113 mOutputPortSettingsChange = AWAITING_ENABLED; 1114 break; 1115 } 1116 1117 default: 1118 { 1119 CHECK_EQ((int)mOutputPortSettingsChange, (int)AWAITING_ENABLED); 1120 CHECK(enabled); 1121 mOutputPortSettingsChange = NONE; 1122 break; 1123 } 1124 } 1125 } 1126 1127 } // namespace android 1128 1129 android::SoftOMXComponent *createSoftOMXComponent( 1130 const char *name, const OMX_CALLBACKTYPE *callbacks, 1131 OMX_PTR appData, OMX_COMPONENTTYPE **component) { 1132 return new android::SoftAAC2(name, callbacks, appData, component); 1133 } 1134