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 "SoftAACEncoder" 19#include <utils/Log.h> 20 21#include "SoftAACEncoder.h" 22 23#include "voAAC.h" 24#include "cmnMemory.h" 25 26#include <media/stagefright/foundation/ADebug.h> 27#include <media/stagefright/foundation/hexdump.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 40SoftAACEncoder::SoftAACEncoder( 41 const char *name, 42 const OMX_CALLBACKTYPE *callbacks, 43 OMX_PTR appData, 44 OMX_COMPONENTTYPE **component) 45 : SimpleSoftOMXComponent(name, callbacks, appData, component), 46 mEncoderHandle(NULL), 47 mApiHandle(NULL), 48 mMemOperator(NULL), 49 mNumChannels(1), 50 mSampleRate(44100), 51 mBitRate(0), 52 mSentCodecSpecificData(false), 53 mInputSize(0), 54 mInputFrame(NULL), 55 mInputTimeUs(-1ll), 56 mSawInputEOS(false), 57 mSignalledError(false) { 58 initPorts(); 59 CHECK_EQ(initEncoder(), (status_t)OK); 60 61 setAudioParams(); 62} 63 64SoftAACEncoder::~SoftAACEncoder() { 65 onReset(); 66 67 if (mEncoderHandle) { 68 CHECK_EQ(VO_ERR_NONE, mApiHandle->Uninit(mEncoderHandle)); 69 mEncoderHandle = NULL; 70 } 71 72 delete mApiHandle; 73 mApiHandle = NULL; 74 75 delete mMemOperator; 76 mMemOperator = NULL; 77} 78 79void SoftAACEncoder::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 SoftAACEncoder::initEncoder() { 121 mApiHandle = new VO_AUDIO_CODECAPI; 122 123 if (VO_ERR_NONE != voGetAACEncAPI(mApiHandle)) { 124 ALOGE("Failed to get api handle"); 125 return UNKNOWN_ERROR; 126 } 127 128 mMemOperator = new VO_MEM_OPERATOR; 129 mMemOperator->Alloc = cmnMemAlloc; 130 mMemOperator->Copy = cmnMemCopy; 131 mMemOperator->Free = cmnMemFree; 132 mMemOperator->Set = cmnMemSet; 133 mMemOperator->Check = cmnMemCheck; 134 135 VO_CODEC_INIT_USERDATA userData; 136 memset(&userData, 0, sizeof(userData)); 137 userData.memflag = VO_IMF_USERMEMOPERATOR; 138 userData.memData = (VO_PTR) mMemOperator; 139 if (VO_ERR_NONE != 140 mApiHandle->Init(&mEncoderHandle, VO_AUDIO_CodingAAC, &userData)) { 141 ALOGE("Failed to init AAC encoder"); 142 return UNKNOWN_ERROR; 143 } 144 145 return OK; 146} 147 148OMX_ERRORTYPE SoftAACEncoder::internalGetParameter( 149 OMX_INDEXTYPE index, OMX_PTR params) { 150 switch (index) { 151 case OMX_IndexParamAudioPortFormat: 152 { 153 OMX_AUDIO_PARAM_PORTFORMATTYPE *formatParams = 154 (OMX_AUDIO_PARAM_PORTFORMATTYPE *)params; 155 156 if (!isValidOMXParam(formatParams)) { 157 return OMX_ErrorBadParameter; 158 } 159 160 if (formatParams->nPortIndex > 1) { 161 return OMX_ErrorUndefined; 162 } 163 164 if (formatParams->nIndex > 0) { 165 return OMX_ErrorNoMore; 166 } 167 168 formatParams->eEncoding = 169 (formatParams->nPortIndex == 0) 170 ? OMX_AUDIO_CodingPCM : OMX_AUDIO_CodingAAC; 171 172 return OMX_ErrorNone; 173 } 174 175 case OMX_IndexParamAudioAac: 176 { 177 OMX_AUDIO_PARAM_AACPROFILETYPE *aacParams = 178 (OMX_AUDIO_PARAM_AACPROFILETYPE *)params; 179 180 if (!isValidOMXParam(aacParams)) { 181 return OMX_ErrorBadParameter; 182 } 183 184 if (aacParams->nPortIndex != 1) { 185 return OMX_ErrorUndefined; 186 } 187 188 aacParams->nBitRate = mBitRate; 189 aacParams->nAudioBandWidth = 0; 190 aacParams->nAACtools = 0; 191 aacParams->nAACERtools = 0; 192 aacParams->eAACProfile = OMX_AUDIO_AACObjectMain; 193 aacParams->eAACStreamFormat = OMX_AUDIO_AACStreamFormatMP4FF; 194 aacParams->eChannelMode = OMX_AUDIO_ChannelModeStereo; 195 196 aacParams->nChannels = mNumChannels; 197 aacParams->nSampleRate = mSampleRate; 198 aacParams->nFrameLength = 0; 199 200 return OMX_ErrorNone; 201 } 202 203 case OMX_IndexParamAudioPcm: 204 { 205 OMX_AUDIO_PARAM_PCMMODETYPE *pcmParams = 206 (OMX_AUDIO_PARAM_PCMMODETYPE *)params; 207 208 if (!isValidOMXParam(pcmParams)) { 209 return OMX_ErrorBadParameter; 210 } 211 212 if (pcmParams->nPortIndex != 0) { 213 return OMX_ErrorUndefined; 214 } 215 216 pcmParams->eNumData = OMX_NumericalDataSigned; 217 pcmParams->eEndian = OMX_EndianBig; 218 pcmParams->bInterleaved = OMX_TRUE; 219 pcmParams->nBitPerSample = 16; 220 pcmParams->ePCMMode = OMX_AUDIO_PCMModeLinear; 221 pcmParams->eChannelMapping[0] = OMX_AUDIO_ChannelLF; 222 pcmParams->eChannelMapping[1] = OMX_AUDIO_ChannelRF; 223 224 pcmParams->nChannels = mNumChannels; 225 pcmParams->nSamplingRate = mSampleRate; 226 227 return OMX_ErrorNone; 228 } 229 230 default: 231 return SimpleSoftOMXComponent::internalGetParameter(index, params); 232 } 233} 234 235OMX_ERRORTYPE SoftAACEncoder::internalSetParameter( 236 OMX_INDEXTYPE index, const OMX_PTR params) { 237 switch (index) { 238 case OMX_IndexParamStandardComponentRole: 239 { 240 const OMX_PARAM_COMPONENTROLETYPE *roleParams = 241 (const OMX_PARAM_COMPONENTROLETYPE *)params; 242 243 if (!isValidOMXParam(roleParams)) { 244 return OMX_ErrorBadParameter; 245 } 246 247 if (strncmp((const char *)roleParams->cRole, 248 "audio_encoder.aac", 249 OMX_MAX_STRINGNAME_SIZE - 1)) { 250 return OMX_ErrorUndefined; 251 } 252 253 return OMX_ErrorNone; 254 } 255 256 case OMX_IndexParamAudioPortFormat: 257 { 258 const OMX_AUDIO_PARAM_PORTFORMATTYPE *formatParams = 259 (const OMX_AUDIO_PARAM_PORTFORMATTYPE *)params; 260 261 if (!isValidOMXParam(formatParams)) { 262 return OMX_ErrorBadParameter; 263 } 264 265 if (formatParams->nPortIndex > 1) { 266 return OMX_ErrorUndefined; 267 } 268 269 if ((formatParams->nPortIndex == 0 270 && formatParams->eEncoding != OMX_AUDIO_CodingPCM) 271 || (formatParams->nPortIndex == 1 272 && formatParams->eEncoding != OMX_AUDIO_CodingAAC)) { 273 return OMX_ErrorUndefined; 274 } 275 276 return OMX_ErrorNone; 277 } 278 279 case OMX_IndexParamAudioAac: 280 { 281 OMX_AUDIO_PARAM_AACPROFILETYPE *aacParams = 282 (OMX_AUDIO_PARAM_AACPROFILETYPE *)params; 283 284 if (!isValidOMXParam(aacParams)) { 285 return OMX_ErrorBadParameter; 286 } 287 288 if (aacParams->nPortIndex != 1) { 289 return OMX_ErrorUndefined; 290 } 291 292 mBitRate = aacParams->nBitRate; 293 mNumChannels = aacParams->nChannels; 294 mSampleRate = aacParams->nSampleRate; 295 296 if (setAudioParams() != OK) { 297 return OMX_ErrorUndefined; 298 } 299 300 return OMX_ErrorNone; 301 } 302 303 case OMX_IndexParamAudioPcm: 304 { 305 OMX_AUDIO_PARAM_PCMMODETYPE *pcmParams = 306 (OMX_AUDIO_PARAM_PCMMODETYPE *)params; 307 308 if (!isValidOMXParam(pcmParams)) { 309 return OMX_ErrorBadParameter; 310 } 311 312 if (pcmParams->nPortIndex != 0) { 313 return OMX_ErrorUndefined; 314 } 315 316 mNumChannels = pcmParams->nChannels; 317 mSampleRate = pcmParams->nSamplingRate; 318 319 if (setAudioParams() != OK) { 320 return OMX_ErrorUndefined; 321 } 322 323 return OMX_ErrorNone; 324 } 325 326 327 default: 328 return SimpleSoftOMXComponent::internalSetParameter(index, params); 329 } 330} 331 332status_t SoftAACEncoder::setAudioParams() { 333 // We call this whenever sample rate, number of channels or bitrate change 334 // in reponse to setParameter calls. 335 336 ALOGV("setAudioParams: %lu Hz, %lu channels, %lu bps", 337 mSampleRate, mNumChannels, mBitRate); 338 339 status_t err = setAudioSpecificConfigData(); 340 341 if (err != OK) { 342 return err; 343 } 344 345 AACENC_PARAM params; 346 memset(¶ms, 0, sizeof(params)); 347 params.sampleRate = mSampleRate; 348 params.bitRate = mBitRate; 349 params.nChannels = mNumChannels; 350 params.adtsUsed = 0; // We add adts header in the file writer if needed. 351 if (VO_ERR_NONE != mApiHandle->SetParam( 352 mEncoderHandle, VO_PID_AAC_ENCPARAM, ¶ms)) { 353 ALOGE("Failed to set AAC encoder parameters"); 354 return UNKNOWN_ERROR; 355 } 356 357 return OK; 358} 359 360static status_t getSampleRateTableIndex(int32_t sampleRate, int32_t &index) { 361 static const int32_t kSampleRateTable[] = { 362 96000, 88200, 64000, 48000, 44100, 32000, 363 24000, 22050, 16000, 12000, 11025, 8000 364 }; 365 const int32_t tableSize = 366 sizeof(kSampleRateTable) / sizeof(kSampleRateTable[0]); 367 368 for (int32_t i = 0; i < tableSize; ++i) { 369 if (sampleRate == kSampleRateTable[i]) { 370 index = i; 371 return OK; 372 } 373 } 374 375 return UNKNOWN_ERROR; 376} 377 378status_t SoftAACEncoder::setAudioSpecificConfigData() { 379 // The AAC encoder's audio specific config really only encodes 380 // number of channels and the sample rate (mapped to an index into 381 // a fixed sample rate table). 382 383 int32_t index; 384 status_t err = getSampleRateTableIndex(mSampleRate, index); 385 if (err != OK) { 386 ALOGE("Unsupported sample rate (%lu Hz)", mSampleRate); 387 return err; 388 } 389 390 if (mNumChannels > 2 || mNumChannels <= 0) { 391 ALOGE("Unsupported number of channels(%lu)", mNumChannels); 392 return UNKNOWN_ERROR; 393 } 394 395 // OMX_AUDIO_AACObjectLC 396 mAudioSpecificConfigData[0] = ((0x02 << 3) | (index >> 1)); 397 mAudioSpecificConfigData[1] = ((index & 0x01) << 7) | (mNumChannels << 3); 398 399 return OK; 400} 401 402void SoftAACEncoder::onQueueFilled(OMX_U32 portIndex) { 403 if (mSignalledError) { 404 return; 405 } 406 407 List<BufferInfo *> &inQueue = getPortQueue(0); 408 List<BufferInfo *> &outQueue = getPortQueue(1); 409 410 if (!mSentCodecSpecificData) { 411 // The very first thing we want to output is the codec specific 412 // data. It does not require any input data but we will need an 413 // output buffer to store it in. 414 415 if (outQueue.empty()) { 416 return; 417 } 418 419 BufferInfo *outInfo = *outQueue.begin(); 420 OMX_BUFFERHEADERTYPE *outHeader = outInfo->mHeader; 421 outHeader->nFilledLen = sizeof(mAudioSpecificConfigData); 422 outHeader->nFlags = OMX_BUFFERFLAG_CODECCONFIG; 423 424 uint8_t *out = outHeader->pBuffer + outHeader->nOffset; 425 memcpy(out, mAudioSpecificConfigData, sizeof(mAudioSpecificConfigData)); 426 427#if 0 428 ALOGI("sending codec specific data."); 429 hexdump(out, sizeof(mAudioSpecificConfigData)); 430#endif 431 432 outQueue.erase(outQueue.begin()); 433 outInfo->mOwnedByUs = false; 434 notifyFillBufferDone(outHeader); 435 436 mSentCodecSpecificData = true; 437 } 438 439 size_t numBytesPerInputFrame = 440 mNumChannels * kNumSamplesPerFrame * sizeof(int16_t); 441 442 for (;;) { 443 // We do the following until we run out of buffers. 444 445 while (mInputSize < numBytesPerInputFrame) { 446 // As long as there's still input data to be read we 447 // will drain "kNumSamplesPerFrame * mNumChannels" samples 448 // into the "mInputFrame" buffer and then encode those 449 // as a unit into an output buffer. 450 451 if (mSawInputEOS || inQueue.empty()) { 452 return; 453 } 454 455 BufferInfo *inInfo = *inQueue.begin(); 456 OMX_BUFFERHEADERTYPE *inHeader = inInfo->mHeader; 457 458 const void *inData = inHeader->pBuffer + inHeader->nOffset; 459 460 size_t copy = numBytesPerInputFrame - mInputSize; 461 if (copy > inHeader->nFilledLen) { 462 copy = inHeader->nFilledLen; 463 } 464 465 if (mInputFrame == NULL) { 466 mInputFrame = new int16_t[kNumSamplesPerFrame * mNumChannels]; 467 } 468 469 if (mInputSize == 0) { 470 mInputTimeUs = inHeader->nTimeStamp; 471 } 472 473 memcpy((uint8_t *)mInputFrame + mInputSize, inData, copy); 474 mInputSize += copy; 475 476 inHeader->nOffset += copy; 477 inHeader->nFilledLen -= copy; 478 479 // "Time" on the input buffer has in effect advanced by the 480 // number of audio frames we just advanced nOffset by. 481 inHeader->nTimeStamp += 482 (copy * 1000000ll / mSampleRate) 483 / (mNumChannels * sizeof(int16_t)); 484 485 if (inHeader->nFilledLen == 0) { 486 if (inHeader->nFlags & OMX_BUFFERFLAG_EOS) { 487 ALOGV("saw input EOS"); 488 mSawInputEOS = true; 489 490 // Pad any remaining data with zeroes. 491 memset((uint8_t *)mInputFrame + mInputSize, 492 0, 493 numBytesPerInputFrame - mInputSize); 494 495 mInputSize = numBytesPerInputFrame; 496 } 497 498 inQueue.erase(inQueue.begin()); 499 inInfo->mOwnedByUs = false; 500 notifyEmptyBufferDone(inHeader); 501 502 inData = NULL; 503 inHeader = NULL; 504 inInfo = NULL; 505 } 506 } 507 508 // At this point we have all the input data necessary to encode 509 // a single frame, all we need is an output buffer to store the result 510 // in. 511 512 if (outQueue.empty()) { 513 return; 514 } 515 516 BufferInfo *outInfo = *outQueue.begin(); 517 OMX_BUFFERHEADERTYPE *outHeader = outInfo->mHeader; 518 519 VO_CODECBUFFER inputData; 520 memset(&inputData, 0, sizeof(inputData)); 521 inputData.Buffer = (unsigned char *)mInputFrame; 522 inputData.Length = numBytesPerInputFrame; 523 CHECK(VO_ERR_NONE == 524 mApiHandle->SetInputData(mEncoderHandle, &inputData)); 525 526 VO_CODECBUFFER outputData; 527 memset(&outputData, 0, sizeof(outputData)); 528 VO_AUDIO_OUTPUTINFO outputInfo; 529 memset(&outputInfo, 0, sizeof(outputInfo)); 530 531 uint8_t *outPtr = (uint8_t *)outHeader->pBuffer + outHeader->nOffset; 532 size_t outAvailable = outHeader->nAllocLen - outHeader->nOffset; 533 534 VO_U32 ret = VO_ERR_NONE; 535 size_t nOutputBytes = 0; 536 do { 537 outputData.Buffer = outPtr; 538 outputData.Length = outAvailable - nOutputBytes; 539 ret = mApiHandle->GetOutputData( 540 mEncoderHandle, &outputData, &outputInfo); 541 if (ret == VO_ERR_NONE) { 542 outPtr += outputData.Length; 543 nOutputBytes += outputData.Length; 544 } 545 } while (ret != VO_ERR_INPUT_BUFFER_SMALL); 546 547 outHeader->nFilledLen = nOutputBytes; 548 549 outHeader->nFlags = OMX_BUFFERFLAG_ENDOFFRAME; 550 551 if (mSawInputEOS) { 552 // We also tag this output buffer with EOS if it corresponds 553 // to the final input buffer. 554 outHeader->nFlags = OMX_BUFFERFLAG_EOS; 555 } 556 557 outHeader->nTimeStamp = mInputTimeUs; 558 559#if 0 560 ALOGI("sending %d bytes of data (time = %lld us, flags = 0x%08lx)", 561 nOutputBytes, mInputTimeUs, outHeader->nFlags); 562 563 hexdump(outHeader->pBuffer + outHeader->nOffset, outHeader->nFilledLen); 564#endif 565 566 outQueue.erase(outQueue.begin()); 567 outInfo->mOwnedByUs = false; 568 notifyFillBufferDone(outHeader); 569 570 outHeader = NULL; 571 outInfo = NULL; 572 573 mInputSize = 0; 574 } 575} 576 577void SoftAACEncoder::onReset() { 578 delete[] mInputFrame; 579 mInputFrame = NULL; 580 mInputSize = 0; 581 582 mSentCodecSpecificData = false; 583 mInputTimeUs = -1ll; 584 mSawInputEOS = false; 585 mSignalledError = false; 586} 587 588} // namespace android 589 590android::SoftOMXComponent *createSoftOMXComponent( 591 const char *name, const OMX_CALLBACKTYPE *callbacks, 592 OMX_PTR appData, OMX_COMPONENTTYPE **component) { 593 return new android::SoftAACEncoder(name, callbacks, appData, component); 594} 595