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>
InitOMXParams(T * params)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
SoftAACEncoder2(const char * name,const OMX_CALLBACKTYPE * callbacks,OMX_PTR appData,OMX_COMPONENTTYPE ** component)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
~SoftAACEncoder2()74 SoftAACEncoder2::~SoftAACEncoder2() {
75 aacEncClose(&mAACEncoder);
76
77 onReset();
78 }
79
initPorts()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
initEncoder()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
internalGetParameter(OMX_INDEXTYPE index,OMX_PTR params)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
internalSetParameter(OMX_INDEXTYPE index,const OMX_PTR params)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
getChannelMode(OMX_U32 nChannels)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
getAOTFromProfile(OMX_U32 profile)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
setAudioParams()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
onQueueFilled(OMX_U32)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
onReset()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 __attribute__((cfi_canonical_jump_table))
createSoftOMXComponent(const char * name,const OMX_CALLBACKTYPE * callbacks,OMX_PTR appData,OMX_COMPONENTTYPE ** component)736 android::SoftOMXComponent *createSoftOMXComponent(
737 const char *name, const OMX_CALLBACKTYPE *callbacks,
738 OMX_PTR appData, OMX_COMPONENTTYPE **component) {
739 return new android::SoftAACEncoder2(name, callbacks, appData, component);
740 }
741