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