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