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