Another attempt for fixing AAC+/eAAC+ related issue

The decoder has to decode the very first two frames (decoder specific data + first data
frame) in order to be really sure whether a stream is AAC or AAC+/eAAC+.

bug - 2966336

Change-Id: Ib12a07285933df0d6c346370a12f70e99e811881
This commit is contained in:
James Dong
2010-09-17 20:50:07 -07:00
parent 4258bfb7a9
commit 40da64f07b
2 changed files with 59 additions and 12 deletions

View File

@@ -123,6 +123,8 @@ status_t AACDecoder::start(MetaData *params) {
mAnchorTimeUs = 0;
mNumSamplesOutput = 0;
mStarted = true;
mNumDecodedBuffers = 0;
mUpsamplingFactor = 2;
return OK;
}
@@ -207,22 +209,65 @@ status_t AACDecoder::read(
Int decoderErr = PVMP4AudioDecodeFrame(mConfig, mDecoderBuf);
// Check on the sampling rate to see whether it is changed.
int32_t sampleRate;
CHECK(mMeta->findInt32(kKeySampleRate, &sampleRate));
if (mConfig->samplingRate != sampleRate) {
mMeta->setInt32(kKeySampleRate, mConfig->samplingRate);
LOGW("Sample rate was %d, but now is %d",
sampleRate, mConfig->samplingRate);
buffer->release();
mInputBuffer->release();
mInputBuffer = NULL;
return INFO_FORMAT_CHANGED;
/*
* AAC+/eAAC+ streams can be signalled in two ways: either explicitly
* or implicitly, according to MPEG4 spec. AAC+/eAAC+ is a dual
* rate system and the sampling rate in the final output is actually
* doubled compared with the core AAC decoder sampling rate.
*
* Explicit signalling is done by explicitly defining SBR audio object
* type in the bitstream. Implicit signalling is done by embedding
* SBR content in AAC extension payload specific to SBR, and hence
* requires an AAC decoder to perform pre-checks on actual audio frames.
*
* Thus, we could not say for sure whether a stream is
* AAC+/eAAC+ until the first data frame is decoded.
*/
if (++mNumDecodedBuffers <= 2) {
LOGV("audio/extended audio object type: %d + %d",
mConfig->audioObjectType, mConfig->extendedAudioObjectType);
LOGV("aac+ upsampling factor: %d desired channels: %d",
mConfig->aacPlusUpsamplingFactor, mConfig->desiredChannels);
CHECK(mNumDecodedBuffers > 0);
if (mNumDecodedBuffers == 1) {
mUpsamplingFactor = mConfig->aacPlusUpsamplingFactor;
// Check on the sampling rate to see whether it is changed.
int32_t sampleRate;
CHECK(mMeta->findInt32(kKeySampleRate, &sampleRate));
if (mConfig->samplingRate != sampleRate) {
mMeta->setInt32(kKeySampleRate, mConfig->samplingRate);
LOGW("Sample rate was %d Hz, but now is %d Hz",
sampleRate, mConfig->samplingRate);
buffer->release();
mInputBuffer->release();
mInputBuffer = NULL;
return INFO_FORMAT_CHANGED;
}
} else { // mNumDecodedBuffers == 2
if (mConfig->extendedAudioObjectType == MP4AUDIO_AAC_LC ||
mConfig->extendedAudioObjectType == MP4AUDIO_LTP) {
if (mUpsamplingFactor == 2) {
// The stream turns out to be not aacPlus mode anyway
LOGW("Disable AAC+/eAAC+ since extended audio object type is %d",
mConfig->extendedAudioObjectType);
mConfig->aacPlusEnabled = 0;
}
} else {
if (mUpsamplingFactor == 1) {
// aacPlus mode does not buy us anything, but to cause
// 1. CPU load to increase, and
// 2. a half speed of decoding
LOGW("Disable AAC+/eAAC+ since upsampling factor is 1");
mConfig->aacPlusEnabled = 0;
}
}
}
}
size_t numOutBytes =
mConfig->frameLength * sizeof(int16_t) * mConfig->desiredChannels;
if (mConfig->aacPlusUpsamplingFactor == 2) {
if (mUpsamplingFactor == 2) {
if (mConfig->desiredChannels == 1) {
memcpy(&mConfig->pOutputBuffer[1024], &mConfig->pOutputBuffer[2048], numOutBytes * 2);
}

View File

@@ -53,6 +53,8 @@ private:
int64_t mAnchorTimeUs;
int64_t mNumSamplesOutput;
status_t mInitCheck;
int64_t mNumDecodedBuffers;
int32_t mUpsamplingFactor;
MediaBuffer *mInputBuffer;