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