blob: e8dabed69c305d41750259e8d5246ad1b5307ba8 [file] [log] [blame]
Dave Burkeaeb8fd42012-04-19 00:14:27 -07001/*
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"
Jean-Michel Trivib97cc6a2014-08-01 15:14:14 -070022#include <OMX_AudioExt.h>
Dave Burkeaeb8fd42012-04-19 00:14:27 -070023
24#include <media/stagefright/foundation/ADebug.h>
25#include <media/stagefright/foundation/hexdump.h>
26
27namespace android {
28
29template<class T>
30static void InitOMXParams(T *params) {
31 params->nSize = sizeof(T);
32 params->nVersion.s.nVersionMajor = 1;
33 params->nVersion.s.nVersionMinor = 0;
34 params->nVersion.s.nRevision = 0;
35 params->nVersion.s.nStep = 0;
36}
37
38SoftAACEncoder2::SoftAACEncoder2(
39 const char *name,
40 const OMX_CALLBACKTYPE *callbacks,
41 OMX_PTR appData,
42 OMX_COMPONENTTYPE **component)
43 : SimpleSoftOMXComponent(name, callbacks, appData, component),
44 mAACEncoder(NULL),
45 mNumChannels(1),
46 mSampleRate(44100),
47 mBitRate(0),
Jean-Michel Trivib97cc6a2014-08-01 15:14:14 -070048 mSBRMode(-1),
49 mSBRRatio(0),
Dave Burkeaeb8fd42012-04-19 00:14:27 -070050 mAACProfile(OMX_AUDIO_AACObjectLC),
51 mSentCodecSpecificData(false),
52 mInputSize(0),
53 mInputFrame(NULL),
54 mInputTimeUs(-1ll),
55 mSawInputEOS(false),
56 mSignalledError(false) {
57 initPorts();
58 CHECK_EQ(initEncoder(), (status_t)OK);
59 setAudioParams();
60}
61
62SoftAACEncoder2::~SoftAACEncoder2() {
63 aacEncClose(&mAACEncoder);
64
65 delete[] mInputFrame;
66 mInputFrame = NULL;
67}
68
69void SoftAACEncoder2::initPorts() {
70 OMX_PARAM_PORTDEFINITIONTYPE def;
71 InitOMXParams(&def);
72
73 def.nPortIndex = 0;
74 def.eDir = OMX_DirInput;
75 def.nBufferCountMin = kNumBuffers;
76 def.nBufferCountActual = def.nBufferCountMin;
77 def.nBufferSize = kNumSamplesPerFrame * sizeof(int16_t) * 2;
78 def.bEnabled = OMX_TRUE;
79 def.bPopulated = OMX_FALSE;
80 def.eDomain = OMX_PortDomainAudio;
81 def.bBuffersContiguous = OMX_FALSE;
82 def.nBufferAlignment = 1;
83
84 def.format.audio.cMIMEType = const_cast<char *>("audio/raw");
85 def.format.audio.pNativeRender = NULL;
86 def.format.audio.bFlagErrorConcealment = OMX_FALSE;
87 def.format.audio.eEncoding = OMX_AUDIO_CodingPCM;
88
89 addPort(def);
90
91 def.nPortIndex = 1;
92 def.eDir = OMX_DirOutput;
93 def.nBufferCountMin = kNumBuffers;
94 def.nBufferCountActual = def.nBufferCountMin;
95 def.nBufferSize = 8192;
96 def.bEnabled = OMX_TRUE;
97 def.bPopulated = OMX_FALSE;
98 def.eDomain = OMX_PortDomainAudio;
99 def.bBuffersContiguous = OMX_FALSE;
100 def.nBufferAlignment = 2;
101
102 def.format.audio.cMIMEType = const_cast<char *>("audio/aac");
103 def.format.audio.pNativeRender = NULL;
104 def.format.audio.bFlagErrorConcealment = OMX_FALSE;
105 def.format.audio.eEncoding = OMX_AUDIO_CodingAAC;
106
107 addPort(def);
108}
109
110status_t SoftAACEncoder2::initEncoder() {
111 if (AACENC_OK != aacEncOpen(&mAACEncoder, 0, 0)) {
112 ALOGE("Failed to init AAC encoder");
113 return UNKNOWN_ERROR;
114 }
115 return OK;
116}
117
118OMX_ERRORTYPE SoftAACEncoder2::internalGetParameter(
119 OMX_INDEXTYPE index, OMX_PTR params) {
120 switch (index) {
121 case OMX_IndexParamAudioPortFormat:
122 {
123 OMX_AUDIO_PARAM_PORTFORMATTYPE *formatParams =
124 (OMX_AUDIO_PARAM_PORTFORMATTYPE *)params;
125
Marco Nelissenf70ba042016-02-29 12:47:20 -0800126 if (!isValidOMXParam(formatParams)) {
127 return OMX_ErrorBadParameter;
128 }
129
Dave Burkeaeb8fd42012-04-19 00:14:27 -0700130 if (formatParams->nPortIndex > 1) {
131 return OMX_ErrorUndefined;
132 }
133
134 if (formatParams->nIndex > 0) {
135 return OMX_ErrorNoMore;
136 }
137
138 formatParams->eEncoding =
139 (formatParams->nPortIndex == 0)
140 ? OMX_AUDIO_CodingPCM : OMX_AUDIO_CodingAAC;
141
142 return OMX_ErrorNone;
143 }
144
145 case OMX_IndexParamAudioAac:
146 {
147 OMX_AUDIO_PARAM_AACPROFILETYPE *aacParams =
148 (OMX_AUDIO_PARAM_AACPROFILETYPE *)params;
149
Marco Nelissenf70ba042016-02-29 12:47:20 -0800150 if (!isValidOMXParam(aacParams)) {
151 return OMX_ErrorBadParameter;
152 }
153
Dave Burkeaeb8fd42012-04-19 00:14:27 -0700154 if (aacParams->nPortIndex != 1) {
155 return OMX_ErrorUndefined;
156 }
157
158 aacParams->nBitRate = mBitRate;
159 aacParams->nAudioBandWidth = 0;
160 aacParams->nAACtools = 0;
161 aacParams->nAACERtools = 0;
162 aacParams->eAACProfile = (OMX_AUDIO_AACPROFILETYPE) mAACProfile;
163 aacParams->eAACStreamFormat = OMX_AUDIO_AACStreamFormatMP4FF;
164 aacParams->eChannelMode = OMX_AUDIO_ChannelModeStereo;
165
166 aacParams->nChannels = mNumChannels;
167 aacParams->nSampleRate = mSampleRate;
168 aacParams->nFrameLength = 0;
169
Jean-Michel Trivib97cc6a2014-08-01 15:14:14 -0700170 switch (mSBRMode) {
171 case 1: // sbr on
172 switch (mSBRRatio) {
173 case 0:
174 // set both OMX AAC tool flags
175 aacParams->nAACtools |= OMX_AUDIO_AACToolAndroidSSBR;
176 aacParams->nAACtools |= OMX_AUDIO_AACToolAndroidDSBR;
177 break;
178 case 1:
179 // set single-rate SBR active
180 aacParams->nAACtools |= OMX_AUDIO_AACToolAndroidSSBR;
181 aacParams->nAACtools &= ~OMX_AUDIO_AACToolAndroidDSBR;
182 break;
183 case 2:
184 // set dual-rate SBR active
185 aacParams->nAACtools &= ~OMX_AUDIO_AACToolAndroidSSBR;
186 aacParams->nAACtools |= OMX_AUDIO_AACToolAndroidDSBR;
187 break;
188 default:
189 ALOGE("invalid SBR ratio %d", mSBRRatio);
190 TRESPASS();
191 }
192 break;
193 case 0: // sbr off
194 case -1: // sbr undefined
195 aacParams->nAACtools &= ~OMX_AUDIO_AACToolAndroidSSBR;
196 aacParams->nAACtools &= ~OMX_AUDIO_AACToolAndroidDSBR;
197 break;
198 default:
199 ALOGE("invalid SBR mode %d", mSBRMode);
200 TRESPASS();
201 }
202
203
204
Dave Burkeaeb8fd42012-04-19 00:14:27 -0700205 return OMX_ErrorNone;
206 }
207
208 case OMX_IndexParamAudioPcm:
209 {
210 OMX_AUDIO_PARAM_PCMMODETYPE *pcmParams =
211 (OMX_AUDIO_PARAM_PCMMODETYPE *)params;
212
Marco Nelissenf70ba042016-02-29 12:47:20 -0800213 if (!isValidOMXParam(pcmParams)) {
214 return OMX_ErrorBadParameter;
215 }
216
Dave Burkeaeb8fd42012-04-19 00:14:27 -0700217 if (pcmParams->nPortIndex != 0) {
218 return OMX_ErrorUndefined;
219 }
220
221 pcmParams->eNumData = OMX_NumericalDataSigned;
222 pcmParams->eEndian = OMX_EndianBig;
223 pcmParams->bInterleaved = OMX_TRUE;
224 pcmParams->nBitPerSample = 16;
225 pcmParams->ePCMMode = OMX_AUDIO_PCMModeLinear;
226 pcmParams->eChannelMapping[0] = OMX_AUDIO_ChannelLF;
227 pcmParams->eChannelMapping[1] = OMX_AUDIO_ChannelRF;
228
229 pcmParams->nChannels = mNumChannels;
230 pcmParams->nSamplingRate = mSampleRate;
231
232 return OMX_ErrorNone;
233 }
234
235 default:
236 return SimpleSoftOMXComponent::internalGetParameter(index, params);
237 }
238}
239
240OMX_ERRORTYPE SoftAACEncoder2::internalSetParameter(
241 OMX_INDEXTYPE index, const OMX_PTR params) {
242 switch (index) {
243 case OMX_IndexParamStandardComponentRole:
244 {
245 const OMX_PARAM_COMPONENTROLETYPE *roleParams =
246 (const OMX_PARAM_COMPONENTROLETYPE *)params;
247
Marco Nelissenf70ba042016-02-29 12:47:20 -0800248 if (!isValidOMXParam(roleParams)) {
249 return OMX_ErrorBadParameter;
250 }
251
Dave Burkeaeb8fd42012-04-19 00:14:27 -0700252 if (strncmp((const char *)roleParams->cRole,
253 "audio_encoder.aac",
254 OMX_MAX_STRINGNAME_SIZE - 1)) {
255 return OMX_ErrorUndefined;
256 }
257
258 return OMX_ErrorNone;
259 }
260
261 case OMX_IndexParamAudioPortFormat:
262 {
263 const OMX_AUDIO_PARAM_PORTFORMATTYPE *formatParams =
264 (const OMX_AUDIO_PARAM_PORTFORMATTYPE *)params;
265
Marco Nelissenf70ba042016-02-29 12:47:20 -0800266 if (!isValidOMXParam(formatParams)) {
267 return OMX_ErrorBadParameter;
268 }
269
Dave Burkeaeb8fd42012-04-19 00:14:27 -0700270 if (formatParams->nPortIndex > 1) {
271 return OMX_ErrorUndefined;
272 }
273
274 if (formatParams->nIndex > 0) {
275 return OMX_ErrorNoMore;
276 }
277
278 if ((formatParams->nPortIndex == 0
279 && formatParams->eEncoding != OMX_AUDIO_CodingPCM)
280 || (formatParams->nPortIndex == 1
281 && formatParams->eEncoding != OMX_AUDIO_CodingAAC)) {
282 return OMX_ErrorUndefined;
283 }
284
285 return OMX_ErrorNone;
286 }
287
288 case OMX_IndexParamAudioAac:
289 {
290 OMX_AUDIO_PARAM_AACPROFILETYPE *aacParams =
291 (OMX_AUDIO_PARAM_AACPROFILETYPE *)params;
292
Marco Nelissenf70ba042016-02-29 12:47:20 -0800293 if (!isValidOMXParam(aacParams)) {
294 return OMX_ErrorBadParameter;
295 }
296
Dave Burkeaeb8fd42012-04-19 00:14:27 -0700297 if (aacParams->nPortIndex != 1) {
298 return OMX_ErrorUndefined;
299 }
300
301 mBitRate = aacParams->nBitRate;
302 mNumChannels = aacParams->nChannels;
303 mSampleRate = aacParams->nSampleRate;
Dave Burkeaeb8fd42012-04-19 00:14:27 -0700304 if (aacParams->eAACProfile != OMX_AUDIO_AACObjectNull) {
305 mAACProfile = aacParams->eAACProfile;
306 }
307
Jean-Michel Trivib97cc6a2014-08-01 15:14:14 -0700308 if (!(aacParams->nAACtools & OMX_AUDIO_AACToolAndroidSSBR)
309 && !(aacParams->nAACtools & OMX_AUDIO_AACToolAndroidDSBR)) {
310 mSBRMode = 0;
311 mSBRRatio = 0;
312 } else if ((aacParams->nAACtools & OMX_AUDIO_AACToolAndroidSSBR)
313 && !(aacParams->nAACtools & OMX_AUDIO_AACToolAndroidDSBR)) {
314 mSBRMode = 1;
315 mSBRRatio = 1;
316 } else if (!(aacParams->nAACtools & OMX_AUDIO_AACToolAndroidSSBR)
317 && (aacParams->nAACtools & OMX_AUDIO_AACToolAndroidDSBR)) {
318 mSBRMode = 1;
319 mSBRRatio = 2;
320 } else {
321 mSBRMode = -1; // codec default sbr mode
322 mSBRRatio = 0;
323 }
324
Dave Burkeaeb8fd42012-04-19 00:14:27 -0700325 if (setAudioParams() != OK) {
326 return OMX_ErrorUndefined;
327 }
328
329 return OMX_ErrorNone;
330 }
331
332 case OMX_IndexParamAudioPcm:
333 {
334 OMX_AUDIO_PARAM_PCMMODETYPE *pcmParams =
335 (OMX_AUDIO_PARAM_PCMMODETYPE *)params;
336
Marco Nelissenf70ba042016-02-29 12:47:20 -0800337 if (!isValidOMXParam(pcmParams)) {
338 return OMX_ErrorBadParameter;
339 }
340
Dave Burkeaeb8fd42012-04-19 00:14:27 -0700341 if (pcmParams->nPortIndex != 0) {
342 return OMX_ErrorUndefined;
343 }
344
345 mNumChannels = pcmParams->nChannels;
346 mSampleRate = pcmParams->nSamplingRate;
Dave Burkeaeb8fd42012-04-19 00:14:27 -0700347 if (setAudioParams() != OK) {
348 return OMX_ErrorUndefined;
349 }
350
351 return OMX_ErrorNone;
352 }
353
354 default:
355 return SimpleSoftOMXComponent::internalSetParameter(index, params);
356 }
357}
358
Dave Burkef60c6602012-04-28 21:58:22 -0700359static CHANNEL_MODE getChannelMode(OMX_U32 nChannels) {
Dave Burkeaeb8fd42012-04-19 00:14:27 -0700360 CHANNEL_MODE chMode = MODE_INVALID;
361 switch (nChannels) {
362 case 1: chMode = MODE_1; break;
363 case 2: chMode = MODE_2; break;
364 case 3: chMode = MODE_1_2; break;
365 case 4: chMode = MODE_1_2_1; break;
366 case 5: chMode = MODE_1_2_2; break;
367 case 6: chMode = MODE_1_2_2_1; break;
368 default: chMode = MODE_INVALID;
369 }
370 return chMode;
371}
372
Dave Burkef60c6602012-04-28 21:58:22 -0700373static AUDIO_OBJECT_TYPE getAOTFromProfile(OMX_U32 profile) {
374 if (profile == OMX_AUDIO_AACObjectLC) {
375 return AOT_AAC_LC;
376 } else if (profile == OMX_AUDIO_AACObjectHE) {
377 return AOT_SBR;
Jean-Michel Trivi1b025862013-08-29 15:51:31 -0700378 } else if (profile == OMX_AUDIO_AACObjectHE_PS) {
379 return AOT_PS;
380 } else if (profile == OMX_AUDIO_AACObjectLD) {
381 return AOT_ER_AAC_LD;
Dave Burkef60c6602012-04-28 21:58:22 -0700382 } else if (profile == OMX_AUDIO_AACObjectELD) {
383 return AOT_ER_AAC_ELD;
384 } else {
385 ALOGW("Unsupported AAC profile - defaulting to AAC-LC");
386 return AOT_AAC_LC;
387 }
388}
389
Dave Burkeaeb8fd42012-04-19 00:14:27 -0700390status_t SoftAACEncoder2::setAudioParams() {
Jean-Michel Trivib97cc6a2014-08-01 15:14:14 -0700391 // We call this whenever sample rate, number of channels, bitrate or SBR mode change
Dave Burkeaeb8fd42012-04-19 00:14:27 -0700392 // in reponse to setParameter calls.
393
Jean-Michel Trivib97cc6a2014-08-01 15:14:14 -0700394 ALOGV("setAudioParams: %u Hz, %u channels, %u bps, %i sbr mode, %i sbr ratio",
395 mSampleRate, mNumChannels, mBitRate, mSBRMode, mSBRRatio);
Dave Burkeaeb8fd42012-04-19 00:14:27 -0700396
397 if (AACENC_OK != aacEncoder_SetParam(mAACEncoder, AACENC_AOT,
Dave Burkef60c6602012-04-28 21:58:22 -0700398 getAOTFromProfile(mAACProfile))) {
Dave Burkeaeb8fd42012-04-19 00:14:27 -0700399 ALOGE("Failed to set AAC encoder parameters");
400 return UNKNOWN_ERROR;
401 }
402
403 if (AACENC_OK != aacEncoder_SetParam(mAACEncoder, AACENC_SAMPLERATE, mSampleRate)) {
404 ALOGE("Failed to set AAC encoder parameters");
405 return UNKNOWN_ERROR;
406 }
407 if (AACENC_OK != aacEncoder_SetParam(mAACEncoder, AACENC_BITRATE, mBitRate)) {
408 ALOGE("Failed to set AAC encoder parameters");
409 return UNKNOWN_ERROR;
410 }
411 if (AACENC_OK != aacEncoder_SetParam(mAACEncoder, AACENC_CHANNELMODE,
412 getChannelMode(mNumChannels))) {
413 ALOGE("Failed to set AAC encoder parameters");
414 return UNKNOWN_ERROR;
415 }
416 if (AACENC_OK != aacEncoder_SetParam(mAACEncoder, AACENC_TRANSMUX, TT_MP4_RAW)) {
417 ALOGE("Failed to set AAC encoder parameters");
418 return UNKNOWN_ERROR;
419 }
420
Jean-Michel Trivib97cc6a2014-08-01 15:14:14 -0700421 if (mSBRMode != -1 && mAACProfile == OMX_AUDIO_AACObjectELD) {
422 if (AACENC_OK != aacEncoder_SetParam(mAACEncoder, AACENC_SBR_MODE, mSBRMode)) {
423 ALOGE("Failed to set AAC encoder parameters");
424 return UNKNOWN_ERROR;
425 }
426 }
427
428 /* SBR ratio parameter configurations:
429 0: Default configuration wherein SBR ratio is configured depending on audio object type by
430 the FDK.
431 1: Downsampled SBR (default for ELD)
432 2: Dualrate SBR (default for HE-AAC)
433 */
434 if (AACENC_OK != aacEncoder_SetParam(mAACEncoder, AACENC_SBR_RATIO, mSBRRatio)) {
435 ALOGE("Failed to set AAC encoder parameters");
436 return UNKNOWN_ERROR;
437 }
438
Dave Burkeaeb8fd42012-04-19 00:14:27 -0700439 return OK;
440}
441
Andreas Huber84333e02014-02-07 15:36:10 -0800442void SoftAACEncoder2::onQueueFilled(OMX_U32 /* portIndex */) {
Dave Burkeaeb8fd42012-04-19 00:14:27 -0700443 if (mSignalledError) {
444 return;
445 }
446
447 List<BufferInfo *> &inQueue = getPortQueue(0);
448 List<BufferInfo *> &outQueue = getPortQueue(1);
449
450 if (!mSentCodecSpecificData) {
451 // The very first thing we want to output is the codec specific
452 // data. It does not require any input data but we will need an
453 // output buffer to store it in.
454
455 if (outQueue.empty()) {
456 return;
457 }
458
459 if (AACENC_OK != aacEncEncode(mAACEncoder, NULL, NULL, NULL, NULL)) {
Dave Burkef60c6602012-04-28 21:58:22 -0700460 ALOGE("Unable to initialize encoder for profile / sample-rate / bit-rate / channels");
Dave Burkeaeb8fd42012-04-19 00:14:27 -0700461 notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL);
462 mSignalledError = true;
463 return;
464 }
465
Dave Burkef60c6602012-04-28 21:58:22 -0700466 OMX_U32 actualBitRate = aacEncoder_GetParam(mAACEncoder, AACENC_BITRATE);
467 if (mBitRate != actualBitRate) {
Glenn Kasten66fe2e92014-04-02 10:25:35 -0700468 ALOGW("Requested bitrate %u unsupported, using %u", mBitRate, actualBitRate);
Dave Burkef60c6602012-04-28 21:58:22 -0700469 }
470
Dave Burkeaeb8fd42012-04-19 00:14:27 -0700471 AACENC_InfoStruct encInfo;
472 if (AACENC_OK != aacEncInfo(mAACEncoder, &encInfo)) {
473 ALOGE("Failed to get AAC encoder info");
474 notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL);
475 mSignalledError = true;
476 return;
477 }
478
479 BufferInfo *outInfo = *outQueue.begin();
480 OMX_BUFFERHEADERTYPE *outHeader = outInfo->mHeader;
481 outHeader->nFilledLen = encInfo.confSize;
482 outHeader->nFlags = OMX_BUFFERFLAG_CODECCONFIG;
483
484 uint8_t *out = outHeader->pBuffer + outHeader->nOffset;
485 memcpy(out, encInfo.confBuf, encInfo.confSize);
486
487 outQueue.erase(outQueue.begin());
488 outInfo->mOwnedByUs = false;
489 notifyFillBufferDone(outHeader);
490
491 mSentCodecSpecificData = true;
492 }
493
494 size_t numBytesPerInputFrame =
495 mNumChannels * kNumSamplesPerFrame * sizeof(int16_t);
496
Dave Burkef60c6602012-04-28 21:58:22 -0700497 // Limit input size so we only get one ELD frame
Dave Burkeaeb8fd42012-04-19 00:14:27 -0700498 if (mAACProfile == OMX_AUDIO_AACObjectELD && numBytesPerInputFrame > 512) {
499 numBytesPerInputFrame = 512;
500 }
501
502 for (;;) {
503 // We do the following until we run out of buffers.
504
505 while (mInputSize < numBytesPerInputFrame) {
506 // As long as there's still input data to be read we
507 // will drain "kNumSamplesPerFrame * mNumChannels" samples
508 // into the "mInputFrame" buffer and then encode those
509 // as a unit into an output buffer.
510
511 if (mSawInputEOS || inQueue.empty()) {
512 return;
513 }
514
515 BufferInfo *inInfo = *inQueue.begin();
516 OMX_BUFFERHEADERTYPE *inHeader = inInfo->mHeader;
517
518 const void *inData = inHeader->pBuffer + inHeader->nOffset;
519
520 size_t copy = numBytesPerInputFrame - mInputSize;
521 if (copy > inHeader->nFilledLen) {
522 copy = inHeader->nFilledLen;
523 }
524
525 if (mInputFrame == NULL) {
Dave Burkef60c6602012-04-28 21:58:22 -0700526 mInputFrame = new int16_t[numBytesPerInputFrame / sizeof(int16_t)];
Dave Burkeaeb8fd42012-04-19 00:14:27 -0700527 }
528
529 if (mInputSize == 0) {
530 mInputTimeUs = inHeader->nTimeStamp;
531 }
532
533 memcpy((uint8_t *)mInputFrame + mInputSize, inData, copy);
534 mInputSize += copy;
535
536 inHeader->nOffset += copy;
537 inHeader->nFilledLen -= copy;
538
539 // "Time" on the input buffer has in effect advanced by the
540 // number of audio frames we just advanced nOffset by.
541 inHeader->nTimeStamp +=
542 (copy * 1000000ll / mSampleRate)
543 / (mNumChannels * sizeof(int16_t));
544
545 if (inHeader->nFilledLen == 0) {
546 if (inHeader->nFlags & OMX_BUFFERFLAG_EOS) {
547 mSawInputEOS = true;
548
549 // Pad any remaining data with zeroes.
550 memset((uint8_t *)mInputFrame + mInputSize,
551 0,
552 numBytesPerInputFrame - mInputSize);
553
554 mInputSize = numBytesPerInputFrame;
555 }
556
557 inQueue.erase(inQueue.begin());
558 inInfo->mOwnedByUs = false;
559 notifyEmptyBufferDone(inHeader);
560
561 inData = NULL;
562 inHeader = NULL;
563 inInfo = NULL;
564 }
565 }
566
567 // At this point we have all the input data necessary to encode
568 // a single frame, all we need is an output buffer to store the result
569 // in.
570
571 if (outQueue.empty()) {
572 return;
573 }
574
575 BufferInfo *outInfo = *outQueue.begin();
576 OMX_BUFFERHEADERTYPE *outHeader = outInfo->mHeader;
577
578 uint8_t *outPtr = (uint8_t *)outHeader->pBuffer + outHeader->nOffset;
579 size_t outAvailable = outHeader->nAllocLen - outHeader->nOffset;
580
581 AACENC_InArgs inargs;
582 AACENC_OutArgs outargs;
583 memset(&inargs, 0, sizeof(inargs));
584 memset(&outargs, 0, sizeof(outargs));
585 inargs.numInSamples = numBytesPerInputFrame / sizeof(int16_t);
586
587 void* inBuffer[] = { (unsigned char *)mInputFrame };
588 INT inBufferIds[] = { IN_AUDIO_DATA };
Andreas Hubera5761dc2013-04-04 10:42:23 -0700589 INT inBufferSize[] = { (INT)numBytesPerInputFrame };
Dave Burkeaeb8fd42012-04-19 00:14:27 -0700590 INT inBufferElSize[] = { sizeof(int16_t) };
591
592 AACENC_BufDesc inBufDesc;
593 inBufDesc.numBufs = sizeof(inBuffer) / sizeof(void*);
594 inBufDesc.bufs = (void**)&inBuffer;
595 inBufDesc.bufferIdentifiers = inBufferIds;
596 inBufDesc.bufSizes = inBufferSize;
597 inBufDesc.bufElSizes = inBufferElSize;
598
599 void* outBuffer[] = { outPtr };
600 INT outBufferIds[] = { OUT_BITSTREAM_DATA };
601 INT outBufferSize[] = { 0 };
602 INT outBufferElSize[] = { sizeof(UCHAR) };
603
604 AACENC_BufDesc outBufDesc;
605 outBufDesc.numBufs = sizeof(outBuffer) / sizeof(void*);
606 outBufDesc.bufs = (void**)&outBuffer;
607 outBufDesc.bufferIdentifiers = outBufferIds;
608 outBufDesc.bufSizes = outBufferSize;
609 outBufDesc.bufElSizes = outBufferElSize;
610
611 // Encode the mInputFrame, which is treated as a modulo buffer
612 AACENC_ERROR encoderErr = AACENC_OK;
613 size_t nOutputBytes = 0;
Dave Burkef60c6602012-04-28 21:58:22 -0700614
Dave Burkeaeb8fd42012-04-19 00:14:27 -0700615 do {
616 memset(&outargs, 0, sizeof(outargs));
617
618 outBuffer[0] = outPtr;
619 outBufferSize[0] = outAvailable - nOutputBytes;
620
621 encoderErr = aacEncEncode(mAACEncoder,
622 &inBufDesc,
623 &outBufDesc,
624 &inargs,
625 &outargs);
626
627 if (encoderErr == AACENC_OK) {
628 outPtr += outargs.numOutBytes;
629 nOutputBytes += outargs.numOutBytes;
630
631 if (outargs.numInSamples > 0) {
632 int numRemainingSamples = inargs.numInSamples - outargs.numInSamples;
633 if (numRemainingSamples > 0) {
634 memmove(mInputFrame,
635 &mInputFrame[outargs.numInSamples],
636 sizeof(int16_t) * numRemainingSamples);
637 }
638 inargs.numInSamples -= outargs.numInSamples;
639 }
640 }
641 } while (encoderErr == AACENC_OK && inargs.numInSamples > 0);
642
643 outHeader->nFilledLen = nOutputBytes;
644
645 outHeader->nFlags = OMX_BUFFERFLAG_ENDOFFRAME;
646
647 if (mSawInputEOS) {
648 // We also tag this output buffer with EOS if it corresponds
649 // to the final input buffer.
650 outHeader->nFlags = OMX_BUFFERFLAG_EOS;
651 }
652
653 outHeader->nTimeStamp = mInputTimeUs;
654
655#if 0
656 ALOGI("sending %d bytes of data (time = %lld us, flags = 0x%08lx)",
657 nOutputBytes, mInputTimeUs, outHeader->nFlags);
658
659 hexdump(outHeader->pBuffer + outHeader->nOffset, outHeader->nFilledLen);
660#endif
661
662 outQueue.erase(outQueue.begin());
663 outInfo->mOwnedByUs = false;
664 notifyFillBufferDone(outHeader);
665
666 outHeader = NULL;
667 outInfo = NULL;
668
669 mInputSize = 0;
670 }
671}
672
673} // namespace android
674
675android::SoftOMXComponent *createSoftOMXComponent(
676 const char *name, const OMX_CALLBACKTYPE *callbacks,
677 OMX_PTR appData, OMX_COMPONENTTYPE **component) {
678 return new android::SoftAACEncoder2(name, callbacks, appData, component);
679}