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_AACObjectELD) { 296 return AOT_ER_AAC_ELD; 297 } else { 298 ALOGW("Unsupported AAC profile - defaulting to AAC-LC"); 299 return AOT_AAC_LC; 300 } 301 } 302 303 status_t SoftAACEncoder2::setAudioParams() { 304 // We call this whenever sample rate, number of channels or bitrate change 305 // in reponse to setParameter calls. 306 307 ALOGV("setAudioParams: %lu Hz, %lu channels, %lu bps", 308 mSampleRate, mNumChannels, mBitRate); 309 310 if (AACENC_OK != aacEncoder_SetParam(mAACEncoder, AACENC_AOT, 311 getAOTFromProfile(mAACProfile))) { 312 ALOGE("Failed to set AAC encoder parameters"); 313 return UNKNOWN_ERROR; 314 } 315 316 if (AACENC_OK != aacEncoder_SetParam(mAACEncoder, AACENC_SAMPLERATE, mSampleRate)) { 317 ALOGE("Failed to set AAC encoder parameters"); 318 return UNKNOWN_ERROR; 319 } 320 if (AACENC_OK != aacEncoder_SetParam(mAACEncoder, AACENC_BITRATE, mBitRate)) { 321 ALOGE("Failed to set AAC encoder parameters"); 322 return UNKNOWN_ERROR; 323 } 324 if (AACENC_OK != aacEncoder_SetParam(mAACEncoder, AACENC_CHANNELMODE, 325 getChannelMode(mNumChannels))) { 326 ALOGE("Failed to set AAC encoder parameters"); 327 return UNKNOWN_ERROR; 328 } 329 if (AACENC_OK != aacEncoder_SetParam(mAACEncoder, AACENC_TRANSMUX, TT_MP4_RAW)) { 330 ALOGE("Failed to set AAC encoder parameters"); 331 return UNKNOWN_ERROR; 332 } 333 334 return OK; 335 } 336 337 void SoftAACEncoder2::onQueueFilled(OMX_U32 portIndex) { 338 if (mSignalledError) { 339 return; 340 } 341 342 List<BufferInfo *> &inQueue = getPortQueue(0); 343 List<BufferInfo *> &outQueue = getPortQueue(1); 344 345 if (!mSentCodecSpecificData) { 346 // The very first thing we want to output is the codec specific 347 // data. It does not require any input data but we will need an 348 // output buffer to store it in. 349 350 if (outQueue.empty()) { 351 return; 352 } 353 354 if (AACENC_OK != aacEncEncode(mAACEncoder, NULL, NULL, NULL, NULL)) { 355 ALOGE("Unable to initialize encoder for profile / sample-rate / bit-rate / channels"); 356 notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL); 357 mSignalledError = true; 358 return; 359 } 360 361 OMX_U32 actualBitRate = aacEncoder_GetParam(mAACEncoder, AACENC_BITRATE); 362 if (mBitRate != actualBitRate) { 363 ALOGW("Requested bitrate %lu unsupported, using %lu", mBitRate, actualBitRate); 364 } 365 366 AACENC_InfoStruct encInfo; 367 if (AACENC_OK != aacEncInfo(mAACEncoder, &encInfo)) { 368 ALOGE("Failed to get AAC encoder info"); 369 notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL); 370 mSignalledError = true; 371 return; 372 } 373 374 BufferInfo *outInfo = *outQueue.begin(); 375 OMX_BUFFERHEADERTYPE *outHeader = outInfo->mHeader; 376 outHeader->nFilledLen = encInfo.confSize; 377 outHeader->nFlags = OMX_BUFFERFLAG_CODECCONFIG; 378 379 uint8_t *out = outHeader->pBuffer + outHeader->nOffset; 380 memcpy(out, encInfo.confBuf, encInfo.confSize); 381 382 outQueue.erase(outQueue.begin()); 383 outInfo->mOwnedByUs = false; 384 notifyFillBufferDone(outHeader); 385 386 mSentCodecSpecificData = true; 387 } 388 389 size_t numBytesPerInputFrame = 390 mNumChannels * kNumSamplesPerFrame * sizeof(int16_t); 391 392 // Limit input size so we only get one ELD frame 393 if (mAACProfile == OMX_AUDIO_AACObjectELD && numBytesPerInputFrame > 512) { 394 numBytesPerInputFrame = 512; 395 } 396 397 for (;;) { 398 // We do the following until we run out of buffers. 399 400 while (mInputSize < numBytesPerInputFrame) { 401 // As long as there's still input data to be read we 402 // will drain "kNumSamplesPerFrame * mNumChannels" samples 403 // into the "mInputFrame" buffer and then encode those 404 // as a unit into an output buffer. 405 406 if (mSawInputEOS || inQueue.empty()) { 407 return; 408 } 409 410 BufferInfo *inInfo = *inQueue.begin(); 411 OMX_BUFFERHEADERTYPE *inHeader = inInfo->mHeader; 412 413 const void *inData = inHeader->pBuffer + inHeader->nOffset; 414 415 size_t copy = numBytesPerInputFrame - mInputSize; 416 if (copy > inHeader->nFilledLen) { 417 copy = inHeader->nFilledLen; 418 } 419 420 if (mInputFrame == NULL) { 421 mInputFrame = new int16_t[numBytesPerInputFrame / sizeof(int16_t)]; 422 } 423 424 if (mInputSize == 0) { 425 mInputTimeUs = inHeader->nTimeStamp; 426 } 427 428 memcpy((uint8_t *)mInputFrame + mInputSize, inData, copy); 429 mInputSize += copy; 430 431 inHeader->nOffset += copy; 432 inHeader->nFilledLen -= copy; 433 434 // "Time" on the input buffer has in effect advanced by the 435 // number of audio frames we just advanced nOffset by. 436 inHeader->nTimeStamp += 437 (copy * 1000000ll / mSampleRate) 438 / (mNumChannels * sizeof(int16_t)); 439 440 if (inHeader->nFilledLen == 0) { 441 if (inHeader->nFlags & OMX_BUFFERFLAG_EOS) { 442 mSawInputEOS = true; 443 444 // Pad any remaining data with zeroes. 445 memset((uint8_t *)mInputFrame + mInputSize, 446 0, 447 numBytesPerInputFrame - mInputSize); 448 449 mInputSize = numBytesPerInputFrame; 450 } 451 452 inQueue.erase(inQueue.begin()); 453 inInfo->mOwnedByUs = false; 454 notifyEmptyBufferDone(inHeader); 455 456 inData = NULL; 457 inHeader = NULL; 458 inInfo = NULL; 459 } 460 } 461 462 // At this point we have all the input data necessary to encode 463 // a single frame, all we need is an output buffer to store the result 464 // in. 465 466 if (outQueue.empty()) { 467 return; 468 } 469 470 BufferInfo *outInfo = *outQueue.begin(); 471 OMX_BUFFERHEADERTYPE *outHeader = outInfo->mHeader; 472 473 uint8_t *outPtr = (uint8_t *)outHeader->pBuffer + outHeader->nOffset; 474 size_t outAvailable = outHeader->nAllocLen - outHeader->nOffset; 475 476 AACENC_InArgs inargs; 477 AACENC_OutArgs outargs; 478 memset(&inargs, 0, sizeof(inargs)); 479 memset(&outargs, 0, sizeof(outargs)); 480 inargs.numInSamples = numBytesPerInputFrame / sizeof(int16_t); 481 482 void* inBuffer[] = { (unsigned char *)mInputFrame }; 483 INT inBufferIds[] = { IN_AUDIO_DATA }; 484 INT inBufferSize[] = { (INT)numBytesPerInputFrame }; 485 INT inBufferElSize[] = { sizeof(int16_t) }; 486 487 AACENC_BufDesc inBufDesc; 488 inBufDesc.numBufs = sizeof(inBuffer) / sizeof(void*); 489 inBufDesc.bufs = (void**)&inBuffer; 490 inBufDesc.bufferIdentifiers = inBufferIds; 491 inBufDesc.bufSizes = inBufferSize; 492 inBufDesc.bufElSizes = inBufferElSize; 493 494 void* outBuffer[] = { outPtr }; 495 INT outBufferIds[] = { OUT_BITSTREAM_DATA }; 496 INT outBufferSize[] = { 0 }; 497 INT outBufferElSize[] = { sizeof(UCHAR) }; 498 499 AACENC_BufDesc outBufDesc; 500 outBufDesc.numBufs = sizeof(outBuffer) / sizeof(void*); 501 outBufDesc.bufs = (void**)&outBuffer; 502 outBufDesc.bufferIdentifiers = outBufferIds; 503 outBufDesc.bufSizes = outBufferSize; 504 outBufDesc.bufElSizes = outBufferElSize; 505 506 // Encode the mInputFrame, which is treated as a modulo buffer 507 AACENC_ERROR encoderErr = AACENC_OK; 508 size_t nOutputBytes = 0; 509 510 do { 511 memset(&outargs, 0, sizeof(outargs)); 512 513 outBuffer[0] = outPtr; 514 outBufferSize[0] = outAvailable - nOutputBytes; 515 516 encoderErr = aacEncEncode(mAACEncoder, 517 &inBufDesc, 518 &outBufDesc, 519 &inargs, 520 &outargs); 521 522 if (encoderErr == AACENC_OK) { 523 outPtr += outargs.numOutBytes; 524 nOutputBytes += outargs.numOutBytes; 525 526 if (outargs.numInSamples > 0) { 527 int numRemainingSamples = inargs.numInSamples - outargs.numInSamples; 528 if (numRemainingSamples > 0) { 529 memmove(mInputFrame, 530 &mInputFrame[outargs.numInSamples], 531 sizeof(int16_t) * numRemainingSamples); 532 } 533 inargs.numInSamples -= outargs.numInSamples; 534 } 535 } 536 } while (encoderErr == AACENC_OK && inargs.numInSamples > 0); 537 538 outHeader->nFilledLen = nOutputBytes; 539 540 outHeader->nFlags = OMX_BUFFERFLAG_ENDOFFRAME; 541 542 if (mSawInputEOS) { 543 // We also tag this output buffer with EOS if it corresponds 544 // to the final input buffer. 545 outHeader->nFlags = OMX_BUFFERFLAG_EOS; 546 } 547 548 outHeader->nTimeStamp = mInputTimeUs; 549 550 #if 0 551 ALOGI("sending %d bytes of data (time = %lld us, flags = 0x%08lx)", 552 nOutputBytes, mInputTimeUs, outHeader->nFlags); 553 554 hexdump(outHeader->pBuffer + outHeader->nOffset, outHeader->nFilledLen); 555 #endif 556 557 outQueue.erase(outQueue.begin()); 558 outInfo->mOwnedByUs = false; 559 notifyFillBufferDone(outHeader); 560 561 outHeader = NULL; 562 outInfo = NULL; 563 564 mInputSize = 0; 565 } 566 } 567 568 } // namespace android 569 570 android::SoftOMXComponent *createSoftOMXComponent( 571 const char *name, const OMX_CALLBACKTYPE *callbacks, 572 OMX_PTR appData, OMX_COMPONENTTYPE **component) { 573 return new android::SoftAACEncoder2(name, callbacks, appData, component); 574 } 575