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