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