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 "SoftAACEncoder2" 19 #include <utils/Log.h> 20 21 #include "SoftAACEncoder2.h" 22 #include <OMX_AudioExt.h> 23 24 #include <media/stagefright/foundation/ADebug.h> 25 #include <media/stagefright/foundation/hexdump.h> 26 27 namespace android { 28 29 template<class T> 30 static void InitOMXParams(T *params) { 31 params->nSize = sizeof(T); 32 params->nVersion.s.nVersionMajor = 1; 33 params->nVersion.s.nVersionMinor = 0; 34 params->nVersion.s.nRevision = 0; 35 params->nVersion.s.nStep = 0; 36 } 37 38 SoftAACEncoder2::SoftAACEncoder2( 39 const char *name, 40 const OMX_CALLBACKTYPE *callbacks, 41 OMX_PTR appData, 42 OMX_COMPONENTTYPE **component) 43 : SimpleSoftOMXComponent(name, callbacks, appData, component), 44 mAACEncoder(NULL), 45 mNumChannels(1), 46 mSampleRate(44100), 47 mBitRate(0), 48 mSBRMode(-1), 49 mSBRRatio(0), 50 mAACProfile(OMX_AUDIO_AACObjectLC), 51 mSentCodecSpecificData(false), 52 mInputSize(0), 53 mInputFrame(NULL), 54 mInputTimeUs(-1ll), 55 mSawInputEOS(false), 56 mSignalledError(false) { 57 initPorts(); 58 CHECK_EQ(initEncoder(), (status_t)OK); 59 setAudioParams(); 60 } 61 62 SoftAACEncoder2::~SoftAACEncoder2() { 63 aacEncClose(&mAACEncoder); 64 65 delete[] mInputFrame; 66 mInputFrame = NULL; 67 } 68 69 void SoftAACEncoder2::initPorts() { 70 OMX_PARAM_PORTDEFINITIONTYPE def; 71 InitOMXParams(&def); 72 73 def.nPortIndex = 0; 74 def.eDir = OMX_DirInput; 75 def.nBufferCountMin = kNumBuffers; 76 def.nBufferCountActual = def.nBufferCountMin; 77 def.nBufferSize = kNumSamplesPerFrame * sizeof(int16_t) * 2; 78 def.bEnabled = OMX_TRUE; 79 def.bPopulated = OMX_FALSE; 80 def.eDomain = OMX_PortDomainAudio; 81 def.bBuffersContiguous = OMX_FALSE; 82 def.nBufferAlignment = 1; 83 84 def.format.audio.cMIMEType = const_cast<char *>("audio/raw"); 85 def.format.audio.pNativeRender = NULL; 86 def.format.audio.bFlagErrorConcealment = OMX_FALSE; 87 def.format.audio.eEncoding = OMX_AUDIO_CodingPCM; 88 89 addPort(def); 90 91 def.nPortIndex = 1; 92 def.eDir = OMX_DirOutput; 93 def.nBufferCountMin = kNumBuffers; 94 def.nBufferCountActual = def.nBufferCountMin; 95 def.nBufferSize = 8192; 96 def.bEnabled = OMX_TRUE; 97 def.bPopulated = OMX_FALSE; 98 def.eDomain = OMX_PortDomainAudio; 99 def.bBuffersContiguous = OMX_FALSE; 100 def.nBufferAlignment = 2; 101 102 def.format.audio.cMIMEType = const_cast<char *>("audio/aac"); 103 def.format.audio.pNativeRender = NULL; 104 def.format.audio.bFlagErrorConcealment = OMX_FALSE; 105 def.format.audio.eEncoding = OMX_AUDIO_CodingAAC; 106 107 addPort(def); 108 } 109 110 status_t SoftAACEncoder2::initEncoder() { 111 if (AACENC_OK != aacEncOpen(&mAACEncoder, 0, 0)) { 112 ALOGE("Failed to init AAC encoder"); 113 return UNKNOWN_ERROR; 114 } 115 return OK; 116 } 117 118 OMX_ERRORTYPE SoftAACEncoder2::internalGetParameter( 119 OMX_INDEXTYPE index, OMX_PTR params) { 120 switch (index) { 121 case OMX_IndexParamAudioPortFormat: 122 { 123 OMX_AUDIO_PARAM_PORTFORMATTYPE *formatParams = 124 (OMX_AUDIO_PARAM_PORTFORMATTYPE *)params; 125 126 if (formatParams->nPortIndex > 1) { 127 return OMX_ErrorUndefined; 128 } 129 130 if (formatParams->nIndex > 0) { 131 return OMX_ErrorNoMore; 132 } 133 134 formatParams->eEncoding = 135 (formatParams->nPortIndex == 0) 136 ? OMX_AUDIO_CodingPCM : OMX_AUDIO_CodingAAC; 137 138 return OMX_ErrorNone; 139 } 140 141 case OMX_IndexParamAudioAac: 142 { 143 OMX_AUDIO_PARAM_AACPROFILETYPE *aacParams = 144 (OMX_AUDIO_PARAM_AACPROFILETYPE *)params; 145 146 if (aacParams->nPortIndex != 1) { 147 return OMX_ErrorUndefined; 148 } 149 150 aacParams->nBitRate = mBitRate; 151 aacParams->nAudioBandWidth = 0; 152 aacParams->nAACtools = 0; 153 aacParams->nAACERtools = 0; 154 aacParams->eAACProfile = (OMX_AUDIO_AACPROFILETYPE) mAACProfile; 155 aacParams->eAACStreamFormat = OMX_AUDIO_AACStreamFormatMP4FF; 156 aacParams->eChannelMode = OMX_AUDIO_ChannelModeStereo; 157 158 aacParams->nChannels = mNumChannels; 159 aacParams->nSampleRate = mSampleRate; 160 aacParams->nFrameLength = 0; 161 162 switch (mSBRMode) { 163 case 1: // sbr on 164 switch (mSBRRatio) { 165 case 0: 166 // set both OMX AAC tool flags 167 aacParams->nAACtools |= OMX_AUDIO_AACToolAndroidSSBR; 168 aacParams->nAACtools |= OMX_AUDIO_AACToolAndroidDSBR; 169 break; 170 case 1: 171 // set single-rate SBR active 172 aacParams->nAACtools |= OMX_AUDIO_AACToolAndroidSSBR; 173 aacParams->nAACtools &= ~OMX_AUDIO_AACToolAndroidDSBR; 174 break; 175 case 2: 176 // set dual-rate SBR active 177 aacParams->nAACtools &= ~OMX_AUDIO_AACToolAndroidSSBR; 178 aacParams->nAACtools |= OMX_AUDIO_AACToolAndroidDSBR; 179 break; 180 default: 181 ALOGE("invalid SBR ratio %d", mSBRRatio); 182 TRESPASS(); 183 } 184 break; 185 case 0: // sbr off 186 case -1: // sbr undefined 187 aacParams->nAACtools &= ~OMX_AUDIO_AACToolAndroidSSBR; 188 aacParams->nAACtools &= ~OMX_AUDIO_AACToolAndroidDSBR; 189 break; 190 default: 191 ALOGE("invalid SBR mode %d", mSBRMode); 192 TRESPASS(); 193 } 194 195 196 197 return OMX_ErrorNone; 198 } 199 200 case OMX_IndexParamAudioPcm: 201 { 202 OMX_AUDIO_PARAM_PCMMODETYPE *pcmParams = 203 (OMX_AUDIO_PARAM_PCMMODETYPE *)params; 204 205 if (pcmParams->nPortIndex != 0) { 206 return OMX_ErrorUndefined; 207 } 208 209 pcmParams->eNumData = OMX_NumericalDataSigned; 210 pcmParams->eEndian = OMX_EndianBig; 211 pcmParams->bInterleaved = OMX_TRUE; 212 pcmParams->nBitPerSample = 16; 213 pcmParams->ePCMMode = OMX_AUDIO_PCMModeLinear; 214 pcmParams->eChannelMapping[0] = OMX_AUDIO_ChannelLF; 215 pcmParams->eChannelMapping[1] = OMX_AUDIO_ChannelRF; 216 217 pcmParams->nChannels = mNumChannels; 218 pcmParams->nSamplingRate = mSampleRate; 219 220 return OMX_ErrorNone; 221 } 222 223 default: 224 return SimpleSoftOMXComponent::internalGetParameter(index, params); 225 } 226 } 227 228 OMX_ERRORTYPE SoftAACEncoder2::internalSetParameter( 229 OMX_INDEXTYPE index, const OMX_PTR params) { 230 switch (index) { 231 case OMX_IndexParamStandardComponentRole: 232 { 233 const OMX_PARAM_COMPONENTROLETYPE *roleParams = 234 (const OMX_PARAM_COMPONENTROLETYPE *)params; 235 236 if (strncmp((const char *)roleParams->cRole, 237 "audio_encoder.aac", 238 OMX_MAX_STRINGNAME_SIZE - 1)) { 239 return OMX_ErrorUndefined; 240 } 241 242 return OMX_ErrorNone; 243 } 244 245 case OMX_IndexParamAudioPortFormat: 246 { 247 const OMX_AUDIO_PARAM_PORTFORMATTYPE *formatParams = 248 (const OMX_AUDIO_PARAM_PORTFORMATTYPE *)params; 249 250 if (formatParams->nPortIndex > 1) { 251 return OMX_ErrorUndefined; 252 } 253 254 if (formatParams->nIndex > 0) { 255 return OMX_ErrorNoMore; 256 } 257 258 if ((formatParams->nPortIndex == 0 259 && formatParams->eEncoding != OMX_AUDIO_CodingPCM) 260 || (formatParams->nPortIndex == 1 261 && formatParams->eEncoding != OMX_AUDIO_CodingAAC)) { 262 return OMX_ErrorUndefined; 263 } 264 265 return OMX_ErrorNone; 266 } 267 268 case OMX_IndexParamAudioAac: 269 { 270 OMX_AUDIO_PARAM_AACPROFILETYPE *aacParams = 271 (OMX_AUDIO_PARAM_AACPROFILETYPE *)params; 272 273 if (aacParams->nPortIndex != 1) { 274 return OMX_ErrorUndefined; 275 } 276 277 mBitRate = aacParams->nBitRate; 278 mNumChannels = aacParams->nChannels; 279 mSampleRate = aacParams->nSampleRate; 280 if (aacParams->eAACProfile != OMX_AUDIO_AACObjectNull) { 281 mAACProfile = aacParams->eAACProfile; 282 } 283 284 if (!(aacParams->nAACtools & OMX_AUDIO_AACToolAndroidSSBR) 285 && !(aacParams->nAACtools & OMX_AUDIO_AACToolAndroidDSBR)) { 286 mSBRMode = 0; 287 mSBRRatio = 0; 288 } else if ((aacParams->nAACtools & OMX_AUDIO_AACToolAndroidSSBR) 289 && !(aacParams->nAACtools & OMX_AUDIO_AACToolAndroidDSBR)) { 290 mSBRMode = 1; 291 mSBRRatio = 1; 292 } else if (!(aacParams->nAACtools & OMX_AUDIO_AACToolAndroidSSBR) 293 && (aacParams->nAACtools & OMX_AUDIO_AACToolAndroidDSBR)) { 294 mSBRMode = 1; 295 mSBRRatio = 2; 296 } else { 297 mSBRMode = -1; // codec default sbr mode 298 mSBRRatio = 0; 299 } 300 301 if (setAudioParams() != OK) { 302 return OMX_ErrorUndefined; 303 } 304 305 return OMX_ErrorNone; 306 } 307 308 case OMX_IndexParamAudioPcm: 309 { 310 OMX_AUDIO_PARAM_PCMMODETYPE *pcmParams = 311 (OMX_AUDIO_PARAM_PCMMODETYPE *)params; 312 313 if (pcmParams->nPortIndex != 0) { 314 return OMX_ErrorUndefined; 315 } 316 317 mNumChannels = pcmParams->nChannels; 318 mSampleRate = pcmParams->nSamplingRate; 319 if (setAudioParams() != OK) { 320 return OMX_ErrorUndefined; 321 } 322 323 return OMX_ErrorNone; 324 } 325 326 default: 327 return SimpleSoftOMXComponent::internalSetParameter(index, params); 328 } 329 } 330 331 static CHANNEL_MODE getChannelMode(OMX_U32 nChannels) { 332 CHANNEL_MODE chMode = MODE_INVALID; 333 switch (nChannels) { 334 case 1: chMode = MODE_1; break; 335 case 2: chMode = MODE_2; break; 336 case 3: chMode = MODE_1_2; break; 337 case 4: chMode = MODE_1_2_1; break; 338 case 5: chMode = MODE_1_2_2; break; 339 case 6: chMode = MODE_1_2_2_1; break; 340 default: chMode = MODE_INVALID; 341 } 342 return chMode; 343 } 344 345 static AUDIO_OBJECT_TYPE getAOTFromProfile(OMX_U32 profile) { 346 if (profile == OMX_AUDIO_AACObjectLC) { 347 return AOT_AAC_LC; 348 } else if (profile == OMX_AUDIO_AACObjectHE) { 349 return AOT_SBR; 350 } else if (profile == OMX_AUDIO_AACObjectHE_PS) { 351 return AOT_PS; 352 } else if (profile == OMX_AUDIO_AACObjectLD) { 353 return AOT_ER_AAC_LD; 354 } else if (profile == OMX_AUDIO_AACObjectELD) { 355 return AOT_ER_AAC_ELD; 356 } else { 357 ALOGW("Unsupported AAC profile - defaulting to AAC-LC"); 358 return AOT_AAC_LC; 359 } 360 } 361 362 status_t SoftAACEncoder2::setAudioParams() { 363 // We call this whenever sample rate, number of channels, bitrate or SBR mode change 364 // in reponse to setParameter calls. 365 366 ALOGV("setAudioParams: %u Hz, %u channels, %u bps, %i sbr mode, %i sbr ratio", 367 mSampleRate, mNumChannels, mBitRate, mSBRMode, mSBRRatio); 368 369 if (AACENC_OK != aacEncoder_SetParam(mAACEncoder, AACENC_AOT, 370 getAOTFromProfile(mAACProfile))) { 371 ALOGE("Failed to set AAC encoder parameters"); 372 return UNKNOWN_ERROR; 373 } 374 375 if (AACENC_OK != aacEncoder_SetParam(mAACEncoder, AACENC_SAMPLERATE, mSampleRate)) { 376 ALOGE("Failed to set AAC encoder parameters"); 377 return UNKNOWN_ERROR; 378 } 379 if (AACENC_OK != aacEncoder_SetParam(mAACEncoder, AACENC_BITRATE, mBitRate)) { 380 ALOGE("Failed to set AAC encoder parameters"); 381 return UNKNOWN_ERROR; 382 } 383 if (AACENC_OK != aacEncoder_SetParam(mAACEncoder, AACENC_CHANNELMODE, 384 getChannelMode(mNumChannels))) { 385 ALOGE("Failed to set AAC encoder parameters"); 386 return UNKNOWN_ERROR; 387 } 388 if (AACENC_OK != aacEncoder_SetParam(mAACEncoder, AACENC_TRANSMUX, TT_MP4_RAW)) { 389 ALOGE("Failed to set AAC encoder parameters"); 390 return UNKNOWN_ERROR; 391 } 392 393 if (mSBRMode != -1 && mAACProfile == OMX_AUDIO_AACObjectELD) { 394 if (AACENC_OK != aacEncoder_SetParam(mAACEncoder, AACENC_SBR_MODE, mSBRMode)) { 395 ALOGE("Failed to set AAC encoder parameters"); 396 return UNKNOWN_ERROR; 397 } 398 } 399 400 /* SBR ratio parameter configurations: 401 0: Default configuration wherein SBR ratio is configured depending on audio object type by 402 the FDK. 403 1: Downsampled SBR (default for ELD) 404 2: Dualrate SBR (default for HE-AAC) 405 */ 406 if (AACENC_OK != aacEncoder_SetParam(mAACEncoder, AACENC_SBR_RATIO, mSBRRatio)) { 407 ALOGE("Failed to set AAC encoder parameters"); 408 return UNKNOWN_ERROR; 409 } 410 411 return OK; 412 } 413 414 void SoftAACEncoder2::onQueueFilled(OMX_U32 /* portIndex */) { 415 if (mSignalledError) { 416 return; 417 } 418 419 List<BufferInfo *> &inQueue = getPortQueue(0); 420 List<BufferInfo *> &outQueue = getPortQueue(1); 421 422 if (!mSentCodecSpecificData) { 423 // The very first thing we want to output is the codec specific 424 // data. It does not require any input data but we will need an 425 // output buffer to store it in. 426 427 if (outQueue.empty()) { 428 return; 429 } 430 431 if (AACENC_OK != aacEncEncode(mAACEncoder, NULL, NULL, NULL, NULL)) { 432 ALOGE("Unable to initialize encoder for profile / sample-rate / bit-rate / channels"); 433 notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL); 434 mSignalledError = true; 435 return; 436 } 437 438 OMX_U32 actualBitRate = aacEncoder_GetParam(mAACEncoder, AACENC_BITRATE); 439 if (mBitRate != actualBitRate) { 440 ALOGW("Requested bitrate %u unsupported, using %u", mBitRate, actualBitRate); 441 } 442 443 AACENC_InfoStruct encInfo; 444 if (AACENC_OK != aacEncInfo(mAACEncoder, &encInfo)) { 445 ALOGE("Failed to get AAC encoder info"); 446 notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL); 447 mSignalledError = true; 448 return; 449 } 450 451 BufferInfo *outInfo = *outQueue.begin(); 452 OMX_BUFFERHEADERTYPE *outHeader = outInfo->mHeader; 453 outHeader->nFilledLen = encInfo.confSize; 454 outHeader->nFlags = OMX_BUFFERFLAG_CODECCONFIG; 455 456 uint8_t *out = outHeader->pBuffer + outHeader->nOffset; 457 memcpy(out, encInfo.confBuf, encInfo.confSize); 458 459 outQueue.erase(outQueue.begin()); 460 outInfo->mOwnedByUs = false; 461 notifyFillBufferDone(outHeader); 462 463 mSentCodecSpecificData = true; 464 } 465 466 size_t numBytesPerInputFrame = 467 mNumChannels * kNumSamplesPerFrame * sizeof(int16_t); 468 469 // Limit input size so we only get one ELD frame 470 if (mAACProfile == OMX_AUDIO_AACObjectELD && numBytesPerInputFrame > 512) { 471 numBytesPerInputFrame = 512; 472 } 473 474 for (;;) { 475 // We do the following until we run out of buffers. 476 477 while (mInputSize < numBytesPerInputFrame) { 478 // As long as there's still input data to be read we 479 // will drain "kNumSamplesPerFrame * mNumChannels" samples 480 // into the "mInputFrame" buffer and then encode those 481 // as a unit into an output buffer. 482 483 if (mSawInputEOS || inQueue.empty()) { 484 return; 485 } 486 487 BufferInfo *inInfo = *inQueue.begin(); 488 OMX_BUFFERHEADERTYPE *inHeader = inInfo->mHeader; 489 490 const void *inData = inHeader->pBuffer + inHeader->nOffset; 491 492 size_t copy = numBytesPerInputFrame - mInputSize; 493 if (copy > inHeader->nFilledLen) { 494 copy = inHeader->nFilledLen; 495 } 496 497 if (mInputFrame == NULL) { 498 mInputFrame = new int16_t[numBytesPerInputFrame / sizeof(int16_t)]; 499 } 500 501 if (mInputSize == 0) { 502 mInputTimeUs = inHeader->nTimeStamp; 503 } 504 505 memcpy((uint8_t *)mInputFrame + mInputSize, inData, copy); 506 mInputSize += copy; 507 508 inHeader->nOffset += copy; 509 inHeader->nFilledLen -= copy; 510 511 // "Time" on the input buffer has in effect advanced by the 512 // number of audio frames we just advanced nOffset by. 513 inHeader->nTimeStamp += 514 (copy * 1000000ll / mSampleRate) 515 / (mNumChannels * sizeof(int16_t)); 516 517 if (inHeader->nFilledLen == 0) { 518 if (inHeader->nFlags & OMX_BUFFERFLAG_EOS) { 519 mSawInputEOS = true; 520 521 // Pad any remaining data with zeroes. 522 memset((uint8_t *)mInputFrame + mInputSize, 523 0, 524 numBytesPerInputFrame - mInputSize); 525 526 mInputSize = numBytesPerInputFrame; 527 } 528 529 inQueue.erase(inQueue.begin()); 530 inInfo->mOwnedByUs = false; 531 notifyEmptyBufferDone(inHeader); 532 533 inData = NULL; 534 inHeader = NULL; 535 inInfo = NULL; 536 } 537 } 538 539 // At this point we have all the input data necessary to encode 540 // a single frame, all we need is an output buffer to store the result 541 // in. 542 543 if (outQueue.empty()) { 544 return; 545 } 546 547 BufferInfo *outInfo = *outQueue.begin(); 548 OMX_BUFFERHEADERTYPE *outHeader = outInfo->mHeader; 549 550 uint8_t *outPtr = (uint8_t *)outHeader->pBuffer + outHeader->nOffset; 551 size_t outAvailable = outHeader->nAllocLen - outHeader->nOffset; 552 553 AACENC_InArgs inargs; 554 AACENC_OutArgs outargs; 555 memset(&inargs, 0, sizeof(inargs)); 556 memset(&outargs, 0, sizeof(outargs)); 557 inargs.numInSamples = numBytesPerInputFrame / sizeof(int16_t); 558 559 void* inBuffer[] = { (unsigned char *)mInputFrame }; 560 INT inBufferIds[] = { IN_AUDIO_DATA }; 561 INT inBufferSize[] = { (INT)numBytesPerInputFrame }; 562 INT inBufferElSize[] = { sizeof(int16_t) }; 563 564 AACENC_BufDesc inBufDesc; 565 inBufDesc.numBufs = sizeof(inBuffer) / sizeof(void*); 566 inBufDesc.bufs = (void**)&inBuffer; 567 inBufDesc.bufferIdentifiers = inBufferIds; 568 inBufDesc.bufSizes = inBufferSize; 569 inBufDesc.bufElSizes = inBufferElSize; 570 571 void* outBuffer[] = { outPtr }; 572 INT outBufferIds[] = { OUT_BITSTREAM_DATA }; 573 INT outBufferSize[] = { 0 }; 574 INT outBufferElSize[] = { sizeof(UCHAR) }; 575 576 AACENC_BufDesc outBufDesc; 577 outBufDesc.numBufs = sizeof(outBuffer) / sizeof(void*); 578 outBufDesc.bufs = (void**)&outBuffer; 579 outBufDesc.bufferIdentifiers = outBufferIds; 580 outBufDesc.bufSizes = outBufferSize; 581 outBufDesc.bufElSizes = outBufferElSize; 582 583 // Encode the mInputFrame, which is treated as a modulo buffer 584 AACENC_ERROR encoderErr = AACENC_OK; 585 size_t nOutputBytes = 0; 586 587 do { 588 memset(&outargs, 0, sizeof(outargs)); 589 590 outBuffer[0] = outPtr; 591 outBufferSize[0] = outAvailable - nOutputBytes; 592 593 encoderErr = aacEncEncode(mAACEncoder, 594 &inBufDesc, 595 &outBufDesc, 596 &inargs, 597 &outargs); 598 599 if (encoderErr == AACENC_OK) { 600 outPtr += outargs.numOutBytes; 601 nOutputBytes += outargs.numOutBytes; 602 603 if (outargs.numInSamples > 0) { 604 int numRemainingSamples = inargs.numInSamples - outargs.numInSamples; 605 if (numRemainingSamples > 0) { 606 memmove(mInputFrame, 607 &mInputFrame[outargs.numInSamples], 608 sizeof(int16_t) * numRemainingSamples); 609 } 610 inargs.numInSamples -= outargs.numInSamples; 611 } 612 } 613 } while (encoderErr == AACENC_OK && inargs.numInSamples > 0); 614 615 outHeader->nFilledLen = nOutputBytes; 616 617 outHeader->nFlags = OMX_BUFFERFLAG_ENDOFFRAME; 618 619 if (mSawInputEOS) { 620 // We also tag this output buffer with EOS if it corresponds 621 // to the final input buffer. 622 outHeader->nFlags = OMX_BUFFERFLAG_EOS; 623 } 624 625 outHeader->nTimeStamp = mInputTimeUs; 626 627 #if 0 628 ALOGI("sending %d bytes of data (time = %lld us, flags = 0x%08lx)", 629 nOutputBytes, mInputTimeUs, outHeader->nFlags); 630 631 hexdump(outHeader->pBuffer + outHeader->nOffset, outHeader->nFilledLen); 632 #endif 633 634 outQueue.erase(outQueue.begin()); 635 outInfo->mOwnedByUs = false; 636 notifyFillBufferDone(outHeader); 637 638 outHeader = NULL; 639 outInfo = NULL; 640 641 mInputSize = 0; 642 } 643 } 644 645 } // namespace android 646 647 android::SoftOMXComponent *createSoftOMXComponent( 648 const char *name, const OMX_CALLBACKTYPE *callbacks, 649 OMX_PTR appData, OMX_COMPONENTTYPE **component) { 650 return new android::SoftAACEncoder2(name, callbacks, appData, component); 651 } 652