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_TAG "SoftAAC2" 18 //#define LOG_NDEBUG 0 19 #include <utils/Log.h> 20 21 #include "SoftAAC2.h" 22 23 #include <cutils/properties.h> 24 #include <media/stagefright/foundation/ADebug.h> 25 #include <media/stagefright/foundation/hexdump.h> 26 #include <media/stagefright/MediaErrors.h> 27 28 #define FILEREAD_MAX_LAYERS 2 29 30 #define DRC_DEFAULT_MOBILE_REF_LEVEL 64 /* 64*-0.25dB = -16 dB below full scale for mobile conf */ 31 #define DRC_DEFAULT_MOBILE_DRC_CUT 127 /* maximum compression of dynamic range for mobile conf */ 32 #define DRC_DEFAULT_MOBILE_DRC_BOOST 127 /* maximum compression of dynamic range for mobile conf */ 33 #define MAX_CHANNEL_COUNT 6 /* maximum number of audio channels that can be decoded */ 34 // names of properties that can be used to override the default DRC settings 35 #define PROP_DRC_OVERRIDE_REF_LEVEL "aac_drc_reference_level" 36 #define PROP_DRC_OVERRIDE_CUT "aac_drc_cut" 37 #define PROP_DRC_OVERRIDE_BOOST "aac_drc_boost" 38 39 namespace android { 40 41 template<class T> 42 static void InitOMXParams(T *params) { 43 params->nSize = sizeof(T); 44 params->nVersion.s.nVersionMajor = 1; 45 params->nVersion.s.nVersionMinor = 0; 46 params->nVersion.s.nRevision = 0; 47 params->nVersion.s.nStep = 0; 48 } 49 50 SoftAAC2::SoftAAC2( 51 const char *name, 52 const OMX_CALLBACKTYPE *callbacks, 53 OMX_PTR appData, 54 OMX_COMPONENTTYPE **component) 55 : SimpleSoftOMXComponent(name, callbacks, appData, component), 56 mAACDecoder(NULL), 57 mStreamInfo(NULL), 58 mIsADTS(false), 59 mInputBufferCount(0), 60 mSignalledError(false), 61 mAnchorTimeUs(0), 62 mNumSamplesOutput(0), 63 mOutputPortSettingsChange(NONE) { 64 initPorts(); 65 CHECK_EQ(initDecoder(), (status_t)OK); 66 } 67 68 SoftAAC2::~SoftAAC2() { 69 aacDecoder_Close(mAACDecoder); 70 } 71 72 void SoftAAC2::initPorts() { 73 OMX_PARAM_PORTDEFINITIONTYPE def; 74 InitOMXParams(&def); 75 76 def.nPortIndex = 0; 77 def.eDir = OMX_DirInput; 78 def.nBufferCountMin = kNumInputBuffers; 79 def.nBufferCountActual = def.nBufferCountMin; 80 def.nBufferSize = 8192; 81 def.bEnabled = OMX_TRUE; 82 def.bPopulated = OMX_FALSE; 83 def.eDomain = OMX_PortDomainAudio; 84 def.bBuffersContiguous = OMX_FALSE; 85 def.nBufferAlignment = 1; 86 87 def.format.audio.cMIMEType = const_cast<char *>("audio/aac"); 88 def.format.audio.pNativeRender = NULL; 89 def.format.audio.bFlagErrorConcealment = OMX_FALSE; 90 def.format.audio.eEncoding = OMX_AUDIO_CodingAAC; 91 92 addPort(def); 93 94 def.nPortIndex = 1; 95 def.eDir = OMX_DirOutput; 96 def.nBufferCountMin = kNumOutputBuffers; 97 def.nBufferCountActual = def.nBufferCountMin; 98 def.nBufferSize = 4096 * MAX_CHANNEL_COUNT; 99 def.bEnabled = OMX_TRUE; 100 def.bPopulated = OMX_FALSE; 101 def.eDomain = OMX_PortDomainAudio; 102 def.bBuffersContiguous = OMX_FALSE; 103 def.nBufferAlignment = 2; 104 105 def.format.audio.cMIMEType = const_cast<char *>("audio/raw"); 106 def.format.audio.pNativeRender = NULL; 107 def.format.audio.bFlagErrorConcealment = OMX_FALSE; 108 def.format.audio.eEncoding = OMX_AUDIO_CodingPCM; 109 110 addPort(def); 111 } 112 113 status_t SoftAAC2::initDecoder() { 114 status_t status = UNKNOWN_ERROR; 115 mAACDecoder = aacDecoder_Open(TT_MP4_ADIF, /* num layers */ 1); 116 if (mAACDecoder != NULL) { 117 mStreamInfo = aacDecoder_GetStreamInfo(mAACDecoder); 118 if (mStreamInfo != NULL) { 119 status = OK; 120 } 121 } 122 mDecoderHasData = false; 123 124 // for streams that contain metadata, use the mobile profile DRC settings unless overridden 125 // by platform properties: 126 char value[PROPERTY_VALUE_MAX]; 127 // * AAC_DRC_REFERENCE_LEVEL 128 if (property_get(PROP_DRC_OVERRIDE_REF_LEVEL, value, NULL)) { 129 unsigned refLevel = atoi(value); 130 ALOGV("AAC decoder using AAC_DRC_REFERENCE_LEVEL of %d instead of %d", 131 refLevel, DRC_DEFAULT_MOBILE_REF_LEVEL); 132 aacDecoder_SetParam(mAACDecoder, AAC_DRC_REFERENCE_LEVEL, refLevel); 133 } else { 134 aacDecoder_SetParam(mAACDecoder, AAC_DRC_REFERENCE_LEVEL, DRC_DEFAULT_MOBILE_REF_LEVEL); 135 } 136 // * AAC_DRC_ATTENUATION_FACTOR 137 if (property_get(PROP_DRC_OVERRIDE_CUT, value, NULL)) { 138 unsigned cut = atoi(value); 139 ALOGV("AAC decoder using AAC_DRC_ATTENUATION_FACTOR of %d instead of %d", 140 cut, DRC_DEFAULT_MOBILE_DRC_CUT); 141 aacDecoder_SetParam(mAACDecoder, AAC_DRC_ATTENUATION_FACTOR, cut); 142 } else { 143 aacDecoder_SetParam(mAACDecoder, AAC_DRC_ATTENUATION_FACTOR, DRC_DEFAULT_MOBILE_DRC_CUT); 144 } 145 // * AAC_DRC_BOOST_FACTOR (note: no default, using cut) 146 if (property_get(PROP_DRC_OVERRIDE_BOOST, value, NULL)) { 147 unsigned boost = atoi(value); 148 ALOGV("AAC decoder using AAC_DRC_BOOST_FACTOR of %d", boost); 149 aacDecoder_SetParam(mAACDecoder, AAC_DRC_BOOST_FACTOR, boost); 150 } else { 151 aacDecoder_SetParam(mAACDecoder, AAC_DRC_BOOST_FACTOR, DRC_DEFAULT_MOBILE_DRC_BOOST); 152 } 153 154 return status; 155 } 156 157 OMX_ERRORTYPE SoftAAC2::internalGetParameter( 158 OMX_INDEXTYPE index, OMX_PTR params) { 159 switch (index) { 160 case OMX_IndexParamAudioAac: 161 { 162 OMX_AUDIO_PARAM_AACPROFILETYPE *aacParams = 163 (OMX_AUDIO_PARAM_AACPROFILETYPE *)params; 164 165 if (aacParams->nPortIndex != 0) { 166 return OMX_ErrorUndefined; 167 } 168 169 aacParams->nBitRate = 0; 170 aacParams->nAudioBandWidth = 0; 171 aacParams->nAACtools = 0; 172 aacParams->nAACERtools = 0; 173 aacParams->eAACProfile = OMX_AUDIO_AACObjectMain; 174 175 aacParams->eAACStreamFormat = 176 mIsADTS 177 ? OMX_AUDIO_AACStreamFormatMP4ADTS 178 : OMX_AUDIO_AACStreamFormatMP4FF; 179 180 aacParams->eChannelMode = OMX_AUDIO_ChannelModeStereo; 181 182 if (!isConfigured()) { 183 aacParams->nChannels = 1; 184 aacParams->nSampleRate = 44100; 185 aacParams->nFrameLength = 0; 186 } else { 187 aacParams->nChannels = mStreamInfo->numChannels; 188 aacParams->nSampleRate = mStreamInfo->sampleRate; 189 aacParams->nFrameLength = mStreamInfo->frameSize; 190 } 191 192 return OMX_ErrorNone; 193 } 194 195 case OMX_IndexParamAudioPcm: 196 { 197 OMX_AUDIO_PARAM_PCMMODETYPE *pcmParams = 198 (OMX_AUDIO_PARAM_PCMMODETYPE *)params; 199 200 if (pcmParams->nPortIndex != 1) { 201 return OMX_ErrorUndefined; 202 } 203 204 pcmParams->eNumData = OMX_NumericalDataSigned; 205 pcmParams->eEndian = OMX_EndianBig; 206 pcmParams->bInterleaved = OMX_TRUE; 207 pcmParams->nBitPerSample = 16; 208 pcmParams->ePCMMode = OMX_AUDIO_PCMModeLinear; 209 pcmParams->eChannelMapping[0] = OMX_AUDIO_ChannelLF; 210 pcmParams->eChannelMapping[1] = OMX_AUDIO_ChannelRF; 211 pcmParams->eChannelMapping[2] = OMX_AUDIO_ChannelCF; 212 pcmParams->eChannelMapping[3] = OMX_AUDIO_ChannelLFE; 213 pcmParams->eChannelMapping[4] = OMX_AUDIO_ChannelLS; 214 pcmParams->eChannelMapping[5] = OMX_AUDIO_ChannelRS; 215 216 if (!isConfigured()) { 217 pcmParams->nChannels = 1; 218 pcmParams->nSamplingRate = 44100; 219 } else { 220 pcmParams->nChannels = mStreamInfo->numChannels; 221 pcmParams->nSamplingRate = mStreamInfo->sampleRate; 222 } 223 224 return OMX_ErrorNone; 225 } 226 227 default: 228 return SimpleSoftOMXComponent::internalGetParameter(index, params); 229 } 230 } 231 232 OMX_ERRORTYPE SoftAAC2::internalSetParameter( 233 OMX_INDEXTYPE index, const OMX_PTR params) { 234 switch (index) { 235 case OMX_IndexParamStandardComponentRole: 236 { 237 const OMX_PARAM_COMPONENTROLETYPE *roleParams = 238 (const OMX_PARAM_COMPONENTROLETYPE *)params; 239 240 if (strncmp((const char *)roleParams->cRole, 241 "audio_decoder.aac", 242 OMX_MAX_STRINGNAME_SIZE - 1)) { 243 return OMX_ErrorUndefined; 244 } 245 246 return OMX_ErrorNone; 247 } 248 249 case OMX_IndexParamAudioAac: 250 { 251 const OMX_AUDIO_PARAM_AACPROFILETYPE *aacParams = 252 (const OMX_AUDIO_PARAM_AACPROFILETYPE *)params; 253 254 if (aacParams->nPortIndex != 0) { 255 return OMX_ErrorUndefined; 256 } 257 258 if (aacParams->eAACStreamFormat == OMX_AUDIO_AACStreamFormatMP4FF) { 259 mIsADTS = false; 260 } else if (aacParams->eAACStreamFormat 261 == OMX_AUDIO_AACStreamFormatMP4ADTS) { 262 mIsADTS = true; 263 } else { 264 return OMX_ErrorUndefined; 265 } 266 267 return OMX_ErrorNone; 268 } 269 270 case OMX_IndexParamAudioPcm: 271 { 272 const OMX_AUDIO_PARAM_PCMMODETYPE *pcmParams = 273 (OMX_AUDIO_PARAM_PCMMODETYPE *)params; 274 275 if (pcmParams->nPortIndex != 1) { 276 return OMX_ErrorUndefined; 277 } 278 279 return OMX_ErrorNone; 280 } 281 282 default: 283 return SimpleSoftOMXComponent::internalSetParameter(index, params); 284 } 285 } 286 287 bool SoftAAC2::isConfigured() const { 288 return mInputBufferCount > 0; 289 } 290 291 void SoftAAC2::maybeConfigureDownmix() const { 292 if (mStreamInfo->numChannels > 2) { 293 char value[PROPERTY_VALUE_MAX]; 294 if (!(property_get("media.aac_51_output_enabled", value, NULL) && 295 (!strcmp(value, "1") || !strcasecmp(value, "true")))) { 296 ALOGI("Downmixing multichannel AAC to stereo"); 297 aacDecoder_SetParam(mAACDecoder, AAC_PCM_OUTPUT_CHANNELS, 2); 298 mStreamInfo->numChannels = 2; 299 } 300 } 301 } 302 303 void SoftAAC2::onQueueFilled(OMX_U32 portIndex) { 304 if (mSignalledError || mOutputPortSettingsChange != NONE) { 305 return; 306 } 307 308 UCHAR* inBuffer[FILEREAD_MAX_LAYERS]; 309 UINT inBufferLength[FILEREAD_MAX_LAYERS] = {0}; 310 UINT bytesValid[FILEREAD_MAX_LAYERS] = {0}; 311 312 List<BufferInfo *> &inQueue = getPortQueue(0); 313 List<BufferInfo *> &outQueue = getPortQueue(1); 314 315 if (portIndex == 0 && mInputBufferCount == 0) { 316 ++mInputBufferCount; 317 BufferInfo *info = *inQueue.begin(); 318 OMX_BUFFERHEADERTYPE *header = info->mHeader; 319 320 inBuffer[0] = header->pBuffer + header->nOffset; 321 inBufferLength[0] = header->nFilledLen; 322 323 AAC_DECODER_ERROR decoderErr = 324 aacDecoder_ConfigRaw(mAACDecoder, 325 inBuffer, 326 inBufferLength); 327 328 if (decoderErr != AAC_DEC_OK) { 329 mSignalledError = true; 330 notify(OMX_EventError, OMX_ErrorUndefined, decoderErr, NULL); 331 return; 332 } 333 334 inQueue.erase(inQueue.begin()); 335 info->mOwnedByUs = false; 336 notifyEmptyBufferDone(header); 337 338 // Only send out port settings changed event if both sample rate 339 // and numChannels are valid. 340 if (mStreamInfo->sampleRate && mStreamInfo->numChannels) { 341 maybeConfigureDownmix(); 342 ALOGI("Initially configuring decoder: %d Hz, %d channels", 343 mStreamInfo->sampleRate, 344 mStreamInfo->numChannels); 345 346 notify(OMX_EventPortSettingsChanged, 1, 0, NULL); 347 mOutputPortSettingsChange = AWAITING_DISABLED; 348 } 349 350 return; 351 } 352 353 while (!inQueue.empty() && !outQueue.empty()) { 354 BufferInfo *inInfo = *inQueue.begin(); 355 OMX_BUFFERHEADERTYPE *inHeader = inInfo->mHeader; 356 357 BufferInfo *outInfo = *outQueue.begin(); 358 OMX_BUFFERHEADERTYPE *outHeader = outInfo->mHeader; 359 360 if (inHeader->nFlags & OMX_BUFFERFLAG_EOS) { 361 inQueue.erase(inQueue.begin()); 362 inInfo->mOwnedByUs = false; 363 notifyEmptyBufferDone(inHeader); 364 365 if (mDecoderHasData) { 366 // flush out the decoder's delayed data by calling DecodeFrame 367 // one more time, with the AACDEC_FLUSH flag set 368 INT_PCM *outBuffer = 369 reinterpret_cast<INT_PCM *>( 370 outHeader->pBuffer + outHeader->nOffset); 371 372 AAC_DECODER_ERROR decoderErr = 373 aacDecoder_DecodeFrame(mAACDecoder, 374 outBuffer, 375 outHeader->nAllocLen, 376 AACDEC_FLUSH); 377 mDecoderHasData = false; 378 379 if (decoderErr != AAC_DEC_OK) { 380 mSignalledError = true; 381 382 notify(OMX_EventError, OMX_ErrorUndefined, decoderErr, 383 NULL); 384 385 return; 386 } 387 388 outHeader->nFilledLen = 389 mStreamInfo->frameSize 390 * sizeof(int16_t) 391 * mStreamInfo->numChannels; 392 } else { 393 // we never submitted any data to the decoder, so there's nothing to flush out 394 outHeader->nFilledLen = 0; 395 } 396 397 outHeader->nFlags = OMX_BUFFERFLAG_EOS; 398 399 outQueue.erase(outQueue.begin()); 400 outInfo->mOwnedByUs = false; 401 notifyFillBufferDone(outHeader); 402 return; 403 } 404 405 if (inHeader->nOffset == 0) { 406 mAnchorTimeUs = inHeader->nTimeStamp; 407 mNumSamplesOutput = 0; 408 } 409 410 size_t adtsHeaderSize = 0; 411 if (mIsADTS) { 412 // skip 30 bits, aac_frame_length follows. 413 // ssssssss ssssiiip ppffffPc ccohCCll llllllll lll????? 414 415 const uint8_t *adtsHeader = inHeader->pBuffer + inHeader->nOffset; 416 417 bool signalError = false; 418 if (inHeader->nFilledLen < 7) { 419 ALOGE("Audio data too short to contain even the ADTS header. " 420 "Got %ld bytes.", inHeader->nFilledLen); 421 hexdump(adtsHeader, inHeader->nFilledLen); 422 signalError = true; 423 } else { 424 bool protectionAbsent = (adtsHeader[1] & 1); 425 426 unsigned aac_frame_length = 427 ((adtsHeader[3] & 3) << 11) 428 | (adtsHeader[4] << 3) 429 | (adtsHeader[5] >> 5); 430 431 if (inHeader->nFilledLen < aac_frame_length) { 432 ALOGE("Not enough audio data for the complete frame. " 433 "Got %ld bytes, frame size according to the ADTS " 434 "header is %u bytes.", 435 inHeader->nFilledLen, aac_frame_length); 436 hexdump(adtsHeader, inHeader->nFilledLen); 437 signalError = true; 438 } else { 439 adtsHeaderSize = (protectionAbsent ? 7 : 9); 440 441 inBuffer[0] = (UCHAR *)adtsHeader + adtsHeaderSize; 442 inBufferLength[0] = aac_frame_length - adtsHeaderSize; 443 444 inHeader->nOffset += adtsHeaderSize; 445 inHeader->nFilledLen -= adtsHeaderSize; 446 } 447 } 448 449 if (signalError) { 450 mSignalledError = true; 451 452 notify(OMX_EventError, 453 OMX_ErrorStreamCorrupt, 454 ERROR_MALFORMED, 455 NULL); 456 457 return; 458 } 459 } else { 460 inBuffer[0] = inHeader->pBuffer + inHeader->nOffset; 461 inBufferLength[0] = inHeader->nFilledLen; 462 } 463 464 // Fill and decode 465 INT_PCM *outBuffer = reinterpret_cast<INT_PCM *>( 466 outHeader->pBuffer + outHeader->nOffset); 467 468 bytesValid[0] = inBufferLength[0]; 469 470 int prevSampleRate = mStreamInfo->sampleRate; 471 int prevNumChannels = mStreamInfo->numChannels; 472 473 AAC_DECODER_ERROR decoderErr = AAC_DEC_NOT_ENOUGH_BITS; 474 while (bytesValid[0] > 0 && decoderErr == AAC_DEC_NOT_ENOUGH_BITS) { 475 aacDecoder_Fill(mAACDecoder, 476 inBuffer, 477 inBufferLength, 478 bytesValid); 479 mDecoderHasData = true; 480 481 decoderErr = aacDecoder_DecodeFrame(mAACDecoder, 482 outBuffer, 483 outHeader->nAllocLen, 484 0 /* flags */); 485 486 if (decoderErr == AAC_DEC_NOT_ENOUGH_BITS) { 487 ALOGW("Not enough bits, bytesValid %d", bytesValid[0]); 488 } 489 } 490 491 size_t numOutBytes = 492 mStreamInfo->frameSize * sizeof(int16_t) * mStreamInfo->numChannels; 493 494 if (decoderErr == AAC_DEC_OK) { 495 UINT inBufferUsedLength = inBufferLength[0] - bytesValid[0]; 496 inHeader->nFilledLen -= inBufferUsedLength; 497 inHeader->nOffset += inBufferUsedLength; 498 } else { 499 ALOGW("AAC decoder returned error %d, substituting silence", 500 decoderErr); 501 502 memset(outHeader->pBuffer + outHeader->nOffset, 0, numOutBytes); 503 504 // Discard input buffer. 505 inHeader->nFilledLen = 0; 506 507 aacDecoder_SetParam(mAACDecoder, AAC_TPDEC_CLEAR_BUFFER, 1); 508 509 // fall through 510 } 511 512 if (inHeader->nFilledLen == 0) { 513 inInfo->mOwnedByUs = false; 514 inQueue.erase(inQueue.begin()); 515 inInfo = NULL; 516 notifyEmptyBufferDone(inHeader); 517 inHeader = NULL; 518 } 519 520 /* 521 * AAC+/eAAC+ streams can be signalled in two ways: either explicitly 522 * or implicitly, according to MPEG4 spec. AAC+/eAAC+ is a dual 523 * rate system and the sampling rate in the final output is actually 524 * doubled compared with the core AAC decoder sampling rate. 525 * 526 * Explicit signalling is done by explicitly defining SBR audio object 527 * type in the bitstream. Implicit signalling is done by embedding 528 * SBR content in AAC extension payload specific to SBR, and hence 529 * requires an AAC decoder to perform pre-checks on actual audio frames. 530 * 531 * Thus, we could not say for sure whether a stream is 532 * AAC+/eAAC+ until the first data frame is decoded. 533 */ 534 if (mInputBufferCount <= 2) { 535 if (mStreamInfo->sampleRate != prevSampleRate || 536 mStreamInfo->numChannels != prevNumChannels) { 537 maybeConfigureDownmix(); 538 ALOGI("Reconfiguring decoder: %d->%d Hz, %d->%d channels", 539 prevSampleRate, mStreamInfo->sampleRate, 540 prevNumChannels, mStreamInfo->numChannels); 541 542 notify(OMX_EventPortSettingsChanged, 1, 0, NULL); 543 mOutputPortSettingsChange = AWAITING_DISABLED; 544 return; 545 } 546 } else if (!mStreamInfo->sampleRate || !mStreamInfo->numChannels) { 547 ALOGW("Invalid AAC stream"); 548 mSignalledError = true; 549 notify(OMX_EventError, OMX_ErrorUndefined, decoderErr, NULL); 550 return; 551 } 552 553 if (decoderErr == AAC_DEC_OK || mNumSamplesOutput > 0) { 554 // We'll only output data if we successfully decoded it or 555 // we've previously decoded valid data, in the latter case 556 // (decode failed) we'll output a silent frame. 557 outHeader->nFilledLen = numOutBytes; 558 outHeader->nFlags = 0; 559 560 outHeader->nTimeStamp = 561 mAnchorTimeUs 562 + (mNumSamplesOutput * 1000000ll) / mStreamInfo->sampleRate; 563 564 mNumSamplesOutput += mStreamInfo->frameSize; 565 566 outInfo->mOwnedByUs = false; 567 outQueue.erase(outQueue.begin()); 568 outInfo = NULL; 569 notifyFillBufferDone(outHeader); 570 outHeader = NULL; 571 } 572 573 if (decoderErr == AAC_DEC_OK) { 574 ++mInputBufferCount; 575 } 576 } 577 } 578 579 void SoftAAC2::onPortFlushCompleted(OMX_U32 portIndex) { 580 if (portIndex == 0) { 581 // Make sure that the next buffer output does not still 582 // depend on fragments from the last one decoded. 583 // drain all existing data 584 drainDecoder(); 585 } 586 } 587 588 void SoftAAC2::drainDecoder() { 589 // a buffer big enough for 6 channels of decoded HE-AAC 590 short buf [2048*6]; 591 aacDecoder_DecodeFrame(mAACDecoder, 592 buf, sizeof(buf), AACDEC_FLUSH | AACDEC_CLRHIST | AACDEC_INTR); 593 aacDecoder_DecodeFrame(mAACDecoder, 594 buf, sizeof(buf), AACDEC_FLUSH | AACDEC_CLRHIST | AACDEC_INTR); 595 aacDecoder_SetParam(mAACDecoder, AAC_TPDEC_CLEAR_BUFFER, 1); 596 mDecoderHasData = false; 597 } 598 599 void SoftAAC2::onReset() { 600 drainDecoder(); 601 // reset the "configured" state 602 mInputBufferCount = 0; 603 mNumSamplesOutput = 0; 604 // To make the codec behave the same before and after a reset, we need to invalidate the 605 // streaminfo struct. This does that: 606 mStreamInfo->sampleRate = 0; 607 608 mSignalledError = false; 609 mOutputPortSettingsChange = NONE; 610 } 611 612 void SoftAAC2::onPortEnableCompleted(OMX_U32 portIndex, bool enabled) { 613 if (portIndex != 1) { 614 return; 615 } 616 617 switch (mOutputPortSettingsChange) { 618 case NONE: 619 break; 620 621 case AWAITING_DISABLED: 622 { 623 CHECK(!enabled); 624 mOutputPortSettingsChange = AWAITING_ENABLED; 625 break; 626 } 627 628 default: 629 { 630 CHECK_EQ((int)mOutputPortSettingsChange, (int)AWAITING_ENABLED); 631 CHECK(enabled); 632 mOutputPortSettingsChange = NONE; 633 break; 634 } 635 } 636 } 637 638 } // namespace android 639 640 android::SoftOMXComponent *createSoftOMXComponent( 641 const char *name, const OMX_CALLBACKTYPE *callbacks, 642 OMX_PTR appData, OMX_COMPONENTTYPE **component) { 643 return new android::SoftAAC2(name, callbacks, appData, component); 644 } 645