blob: 7ce6128883b9c29c163106bb5ed35af2193e5429 [file] [log] [blame]
Andreas Huber4b3913a2011-05-11 14:13:42 -07001/*
2 * Copyright (C) 2011 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 "SoftAAC"
19#include <utils/Log.h>
20
21#include "SoftAAC.h"
22
23#include "pvmp4audiodecoder_api.h"
24
25#include <media/stagefright/foundation/ADebug.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
38SoftAAC::SoftAAC(
39 const char *name,
40 const OMX_CALLBACKTYPE *callbacks,
41 OMX_PTR appData,
42 OMX_COMPONENTTYPE **component)
43 : SimpleSoftOMXComponent(name, callbacks, appData, component),
44 mConfig(new tPVMP4AudioDecoderExternal),
45 mDecoderBuf(NULL),
46 mInputBufferCount(0),
47 mUpsamplingFactor(2),
48 mAnchorTimeUs(0),
49 mNumSamplesOutput(0),
50 mSignalledError(false),
51 mOutputPortSettingsChange(NONE) {
52 initPorts();
53 CHECK_EQ(initDecoder(), (status_t)OK);
54}
55
56SoftAAC::~SoftAAC() {
57 free(mDecoderBuf);
58 mDecoderBuf = NULL;
59
60 delete mConfig;
61 mConfig = NULL;
62}
63
64void SoftAAC::initPorts() {
65 OMX_PARAM_PORTDEFINITIONTYPE def;
66 InitOMXParams(&def);
67
68 def.nPortIndex = 0;
69 def.eDir = OMX_DirInput;
70 def.nBufferCountMin = kNumBuffers;
71 def.nBufferCountActual = def.nBufferCountMin;
72 def.nBufferSize = 8192;
73 def.bEnabled = OMX_TRUE;
74 def.bPopulated = OMX_FALSE;
75 def.eDomain = OMX_PortDomainAudio;
76 def.bBuffersContiguous = OMX_FALSE;
77 def.nBufferAlignment = 1;
78
79 def.format.audio.cMIMEType = const_cast<char *>("audio/aac");
80 def.format.audio.pNativeRender = NULL;
81 def.format.audio.bFlagErrorConcealment = OMX_FALSE;
82 def.format.audio.eEncoding = OMX_AUDIO_CodingAAC;
83
84 addPort(def);
85
86 def.nPortIndex = 1;
87 def.eDir = OMX_DirOutput;
88 def.nBufferCountMin = kNumBuffers;
89 def.nBufferCountActual = def.nBufferCountMin;
90 def.nBufferSize = 8192;
91 def.bEnabled = OMX_TRUE;
92 def.bPopulated = OMX_FALSE;
93 def.eDomain = OMX_PortDomainAudio;
94 def.bBuffersContiguous = OMX_FALSE;
95 def.nBufferAlignment = 2;
96
97 def.format.audio.cMIMEType = const_cast<char *>("audio/raw");
98 def.format.audio.pNativeRender = NULL;
99 def.format.audio.bFlagErrorConcealment = OMX_FALSE;
100 def.format.audio.eEncoding = OMX_AUDIO_CodingPCM;
101
102 addPort(def);
103}
104
105status_t SoftAAC::initDecoder() {
106 memset(mConfig, 0, sizeof(tPVMP4AudioDecoderExternal));
107 mConfig->outputFormat = OUTPUTFORMAT_16PCM_INTERLEAVED;
108 mConfig->aacPlusEnabled = 1;
109
110 // The software decoder doesn't properly support mono output on
111 // AACplus files. Always output stereo.
112 mConfig->desiredChannels = 2;
113
114 UInt32 memRequirements = PVMP4AudioDecoderGetMemRequirements();
115 mDecoderBuf = malloc(memRequirements);
116
117 Int err = PVMP4AudioDecoderInitLibrary(mConfig, mDecoderBuf);
118 if (err != MP4AUDEC_SUCCESS) {
119 LOGE("Failed to initialize MP4 audio decoder");
120 return UNKNOWN_ERROR;
121 }
122
123 return OK;
124}
125
126OMX_ERRORTYPE SoftAAC::internalGetParameter(
127 OMX_INDEXTYPE index, OMX_PTR params) {
128 switch (index) {
129 case OMX_IndexParamAudioAac:
130 {
131 OMX_AUDIO_PARAM_AACPROFILETYPE *aacParams =
132 (OMX_AUDIO_PARAM_AACPROFILETYPE *)params;
133
134 if (aacParams->nPortIndex != 0) {
135 return OMX_ErrorUndefined;
136 }
137
138 aacParams->nBitRate = 0;
139 aacParams->nAudioBandWidth = 0;
140 aacParams->nAACtools = 0;
141 aacParams->nAACERtools = 0;
142 aacParams->eAACProfile = OMX_AUDIO_AACObjectMain;
143 aacParams->eAACStreamFormat = OMX_AUDIO_AACStreamFormatMP4FF;
144 aacParams->eChannelMode = OMX_AUDIO_ChannelModeStereo;
145
146 if (!isConfigured()) {
147 aacParams->nChannels = 1;
148 aacParams->nSampleRate = 44100;
149 aacParams->nFrameLength = 0;
150 } else {
151 aacParams->nChannels = mConfig->encodedChannels;
152 aacParams->nSampleRate = mConfig->samplingRate;
153 aacParams->nFrameLength = mConfig->frameLength;
154 }
155
156 return OMX_ErrorNone;
157 }
158
159 case OMX_IndexParamAudioPcm:
160 {
161 OMX_AUDIO_PARAM_PCMMODETYPE *pcmParams =
162 (OMX_AUDIO_PARAM_PCMMODETYPE *)params;
163
164 if (pcmParams->nPortIndex != 1) {
165 return OMX_ErrorUndefined;
166 }
167
168 pcmParams->eNumData = OMX_NumericalDataSigned;
169 pcmParams->eEndian = OMX_EndianBig;
170 pcmParams->bInterleaved = OMX_TRUE;
171 pcmParams->nBitPerSample = 16;
172 pcmParams->ePCMMode = OMX_AUDIO_PCMModeLinear;
173 pcmParams->eChannelMapping[0] = OMX_AUDIO_ChannelLF;
174 pcmParams->eChannelMapping[1] = OMX_AUDIO_ChannelRF;
175
176 if (!isConfigured()) {
177 pcmParams->nChannels = 1;
178 pcmParams->nSamplingRate = 44100;
179 } else {
180 pcmParams->nChannels = mConfig->desiredChannels;
181 pcmParams->nSamplingRate = mConfig->samplingRate;
182 }
183
184 return OMX_ErrorNone;
185 }
186
187 default:
188 return SimpleSoftOMXComponent::internalGetParameter(index, params);
189 }
190}
191
192OMX_ERRORTYPE SoftAAC::internalSetParameter(
193 OMX_INDEXTYPE index, const OMX_PTR params) {
194 switch (index) {
195 case OMX_IndexParamStandardComponentRole:
196 {
197 const OMX_PARAM_COMPONENTROLETYPE *roleParams =
198 (const OMX_PARAM_COMPONENTROLETYPE *)params;
199
200 if (strncmp((const char *)roleParams->cRole,
201 "audio_decoder.aac",
202 OMX_MAX_STRINGNAME_SIZE - 1)) {
203 return OMX_ErrorUndefined;
204 }
205
206 return OMX_ErrorNone;
207 }
208
209 case OMX_IndexParamAudioAac:
210 {
211 const OMX_AUDIO_PARAM_AACPROFILETYPE *aacParams =
212 (const OMX_AUDIO_PARAM_AACPROFILETYPE *)params;
213
214 if (aacParams->nPortIndex != 0) {
215 return OMX_ErrorUndefined;
216 }
217
218 return OMX_ErrorNone;
219 }
220
221 default:
222 return SimpleSoftOMXComponent::internalSetParameter(index, params);
223 }
224}
225
226bool SoftAAC::isConfigured() const {
227 return mInputBufferCount > 0;
228}
229
230void SoftAAC::onQueueFilled(OMX_U32 portIndex) {
231 if (mSignalledError || mOutputPortSettingsChange != NONE) {
232 return;
233 }
234
235 List<BufferInfo *> &inQueue = getPortQueue(0);
236 List<BufferInfo *> &outQueue = getPortQueue(1);
237
238 if (portIndex == 0 && mInputBufferCount == 0) {
239 ++mInputBufferCount;
240
241 BufferInfo *info = *inQueue.begin();
242 OMX_BUFFERHEADERTYPE *header = info->mHeader;
243
244 mConfig->pInputBuffer = header->pBuffer + header->nOffset;
245 mConfig->inputBufferCurrentLength = header->nFilledLen;
246 mConfig->inputBufferMaxLength = 0;
247
248 Int err = PVMP4AudioDecoderConfig(mConfig, mDecoderBuf);
249 if (err != MP4AUDEC_SUCCESS) {
250 mSignalledError = true;
251 notify(OMX_EventError, OMX_ErrorUndefined, err, NULL);
252 return;
253 }
254
255 inQueue.erase(inQueue.begin());
256 info->mOwnedByUs = false;
257 notifyEmptyBufferDone(header);
258
259 notify(OMX_EventPortSettingsChanged, 1, 0, NULL);
260 mOutputPortSettingsChange = AWAITING_DISABLED;
261 return;
262 }
263
264 while (!inQueue.empty() && !outQueue.empty()) {
265 BufferInfo *inInfo = *inQueue.begin();
266 OMX_BUFFERHEADERTYPE *inHeader = inInfo->mHeader;
267
268 BufferInfo *outInfo = *outQueue.begin();
269 OMX_BUFFERHEADERTYPE *outHeader = outInfo->mHeader;
270
271 if (inHeader->nFlags & OMX_BUFFERFLAG_EOS) {
272 inQueue.erase(inQueue.begin());
273 inInfo->mOwnedByUs = false;
274 notifyEmptyBufferDone(inHeader);
275
276 outHeader->nFilledLen = 0;
277 outHeader->nFlags = OMX_BUFFERFLAG_EOS;
278
279 outQueue.erase(outQueue.begin());
280 outInfo->mOwnedByUs = false;
281 notifyFillBufferDone(outHeader);
282 return;
283 }
284
285 if (inHeader->nOffset == 0) {
286 mAnchorTimeUs = inHeader->nTimeStamp;
287 mNumSamplesOutput = 0;
288 }
289
290 mConfig->pInputBuffer = inHeader->pBuffer + inHeader->nOffset;
291 mConfig->inputBufferCurrentLength = inHeader->nFilledLen;
292 mConfig->inputBufferMaxLength = 0;
293 mConfig->inputBufferUsedLength = 0;
294 mConfig->remainderBits = 0;
295
296 mConfig->pOutputBuffer =
297 reinterpret_cast<Int16 *>(outHeader->pBuffer + outHeader->nOffset);
298
299 mConfig->pOutputBuffer_plus = &mConfig->pOutputBuffer[2048];
300 mConfig->repositionFlag = false;
301
302 Int32 prevSamplingRate = mConfig->samplingRate;
303 Int decoderErr = PVMP4AudioDecodeFrame(mConfig, mDecoderBuf);
304
305 /*
306 * AAC+/eAAC+ streams can be signalled in two ways: either explicitly
307 * or implicitly, according to MPEG4 spec. AAC+/eAAC+ is a dual
308 * rate system and the sampling rate in the final output is actually
309 * doubled compared with the core AAC decoder sampling rate.
310 *
311 * Explicit signalling is done by explicitly defining SBR audio object
312 * type in the bitstream. Implicit signalling is done by embedding
313 * SBR content in AAC extension payload specific to SBR, and hence
314 * requires an AAC decoder to perform pre-checks on actual audio frames.
315 *
316 * Thus, we could not say for sure whether a stream is
317 * AAC+/eAAC+ until the first data frame is decoded.
318 */
319 if (mInputBufferCount <= 2) {
320 LOGV("audio/extended audio object type: %d + %d",
321 mConfig->audioObjectType, mConfig->extendedAudioObjectType);
322 LOGV("aac+ upsampling factor: %d desired channels: %d",
323 mConfig->aacPlusUpsamplingFactor, mConfig->desiredChannels);
324
325 if (mInputBufferCount == 1) {
326 mUpsamplingFactor = mConfig->aacPlusUpsamplingFactor;
327 // Check on the sampling rate to see whether it is changed.
328 if (mConfig->samplingRate != prevSamplingRate) {
329 LOGW("Sample rate was %d Hz, but now is %d Hz",
330 prevSamplingRate, mConfig->samplingRate);
331
332 // We'll hold onto the input buffer and will decode
333 // it again once the output port has been reconfigured.
334
335 notify(OMX_EventPortSettingsChanged, 1, 0, NULL);
336 mOutputPortSettingsChange = AWAITING_DISABLED;
337 return;
338 }
339 } else { // mInputBufferCount == 2
340 if (mConfig->extendedAudioObjectType == MP4AUDIO_AAC_LC ||
341 mConfig->extendedAudioObjectType == MP4AUDIO_LTP) {
342 if (mUpsamplingFactor == 2) {
343 // The stream turns out to be not aacPlus mode anyway
344 LOGW("Disable AAC+/eAAC+ since extended audio object "
345 "type is %d",
346 mConfig->extendedAudioObjectType);
347 mConfig->aacPlusEnabled = 0;
348 }
349 } else {
350 if (mUpsamplingFactor == 1) {
351 // aacPlus mode does not buy us anything, but to cause
352 // 1. CPU load to increase, and
353 // 2. a half speed of decoding
354 LOGW("Disable AAC+/eAAC+ since upsampling factor is 1");
355 mConfig->aacPlusEnabled = 0;
356 }
357 }
358 }
359 }
360
361 size_t numOutBytes =
362 mConfig->frameLength * sizeof(int16_t) * mConfig->desiredChannels;
363
364 if (decoderErr == MP4AUDEC_SUCCESS) {
365 CHECK_LE(mConfig->inputBufferUsedLength, inHeader->nFilledLen);
366
367 inHeader->nFilledLen -= mConfig->inputBufferUsedLength;
368 inHeader->nOffset += mConfig->inputBufferUsedLength;
369 } else {
370 memset(outHeader->pBuffer + outHeader->nOffset, 0, numOutBytes);
371 }
372
373 if (mUpsamplingFactor == 2) {
374 if (mConfig->desiredChannels == 1) {
375 memcpy(&mConfig->pOutputBuffer[1024],
376 &mConfig->pOutputBuffer[2048],
377 numOutBytes * 2);
378 }
379 numOutBytes *= 2;
380 }
381
382 outHeader->nFilledLen = numOutBytes;
383 outHeader->nFlags = 0;
384
385 outHeader->nTimeStamp =
386 mAnchorTimeUs
387 + (mNumSamplesOutput * 1000000ll) / mConfig->samplingRate;
388
389 mNumSamplesOutput += mConfig->frameLength * mUpsamplingFactor;
390
391 if (inHeader->nFilledLen == 0) {
392 inInfo->mOwnedByUs = false;
393 inQueue.erase(inQueue.begin());
394 inInfo = NULL;
395 notifyEmptyBufferDone(inHeader);
396 inHeader = NULL;
397 }
398
399 outInfo->mOwnedByUs = false;
400 outQueue.erase(outQueue.begin());
401 outInfo = NULL;
402 notifyFillBufferDone(outHeader);
403 outHeader = NULL;
404
405 ++mInputBufferCount;
406 }
407}
408
409void SoftAAC::onPortFlushCompleted(OMX_U32 portIndex) {
410 if (portIndex == 0) {
411 // Make sure that the next buffer output does not still
412 // depend on fragments from the last one decoded.
413 PVMP4AudioDecoderResetBuffer(mDecoderBuf);
414 }
415}
416
417void SoftAAC::onPortEnableCompleted(OMX_U32 portIndex, bool enabled) {
418 if (portIndex != 1) {
419 return;
420 }
421
422 switch (mOutputPortSettingsChange) {
423 case NONE:
424 break;
425
426 case AWAITING_DISABLED:
427 {
428 CHECK(!enabled);
429 mOutputPortSettingsChange = AWAITING_ENABLED;
430 break;
431 }
432
433 default:
434 {
435 CHECK_EQ((int)mOutputPortSettingsChange, (int)AWAITING_ENABLED);
436 CHECK(enabled);
437 mOutputPortSettingsChange = NONE;
438 break;
439 }
440 }
441}
442
443} // namespace android
444
445android::SoftOMXComponent *createSoftOMXComponent(
446 const char *name, const OMX_CALLBACKTYPE *callbacks,
447 OMX_PTR appData, OMX_COMPONENTTYPE **component) {
448 return new android::SoftAAC(name, callbacks, appData, component);
449}