summaryrefslogtreecommitdiffstats
path: root/media
diff options
context:
space:
mode:
authorDave Burke <daveburke@google.com>2012-04-28 21:58:22 -0700
committerDave Burke <daveburke@google.com>2012-04-30 09:18:24 -0700
commitf60c660f048d5f5e2458cff243c20400d73757a7 (patch)
treeb2bf22e36da46fd25979df618f8661b4b0510dad /media
parent83faee053cfd4251dbb591b62039f563ffdac399 (diff)
downloadframeworks_av-f60c660f048d5f5e2458cff243c20400d73757a7.zip
frameworks_av-f60c660f048d5f5e2458cff243c20400d73757a7.tar.gz
frameworks_av-f60c660f048d5f5e2458cff243c20400d73757a7.tar.bz2
Added support for HE-AAC recording
Fixed bug in decoder related to sample rates / channel counts Made decoder follow Fraunhofer pattern Log if bitrate not available Bug: 6275957 Change-Id: I47a8e29358fa4a88ebc73fe02d46a2bfb96c64fe
Diffstat (limited to 'media')
-rw-r--r--media/libmedia/MediaProfiles.cpp3
-rw-r--r--media/libmediaplayerservice/StagefrightRecorder.cpp12
-rw-r--r--media/libstagefright/codecs/aacdec/SoftAAC2.cpp50
-rw-r--r--media/libstagefright/codecs/aacenc/SoftAACEncoder2.cpp31
4 files changed, 66 insertions, 30 deletions
diff --git a/media/libmedia/MediaProfiles.cpp b/media/libmedia/MediaProfiles.cpp
index c08f033..6929efa 100644
--- a/media/libmedia/MediaProfiles.cpp
+++ b/media/libmedia/MediaProfiles.cpp
@@ -44,7 +44,8 @@ const MediaProfiles::NameToTagMap MediaProfiles::sAudioEncoderNameMap[] = {
{"amrnb", AUDIO_ENCODER_AMR_NB},
{"amrwb", AUDIO_ENCODER_AMR_WB},
{"aac", AUDIO_ENCODER_AAC},
- {"aaceld", AUDIO_ENCODER_AAC_ELD},
+ {"heaac", AUDIO_ENCODER_HE_AAC},
+ {"aaceld", AUDIO_ENCODER_AAC_ELD}
};
const MediaProfiles::NameToTagMap MediaProfiles::sFileFormatMap[] = {
diff --git a/media/libmediaplayerservice/StagefrightRecorder.cpp b/media/libmediaplayerservice/StagefrightRecorder.cpp
index b676cc7..727fd0d 100644
--- a/media/libmediaplayerservice/StagefrightRecorder.cpp
+++ b/media/libmediaplayerservice/StagefrightRecorder.cpp
@@ -820,10 +820,15 @@ sp<MediaSource> StagefrightRecorder::createAudioSource() {
mime = MEDIA_MIMETYPE_AUDIO_AAC;
encMeta->setInt32(kKeyAACProfile, OMX_AUDIO_AACObjectLC);
break;
+ case AUDIO_ENCODER_HE_AAC:
+ mime = MEDIA_MIMETYPE_AUDIO_AAC;
+ encMeta->setInt32(kKeyAACProfile, OMX_AUDIO_AACObjectHE);
+ break;
case AUDIO_ENCODER_AAC_ELD:
mime = MEDIA_MIMETYPE_AUDIO_AAC;
encMeta->setInt32(kKeyAACProfile, OMX_AUDIO_AACObjectELD);
break;
+
default:
ALOGE("Unknown audio encoder: %d", mAudioEncoder);
return NULL;
@@ -844,7 +849,6 @@ sp<MediaSource> StagefrightRecorder::createAudioSource() {
OMXClient client;
CHECK_EQ(client.connect(), (status_t)OK);
-
sp<MediaSource> audioEncoder =
OMXCodec::Create(client.interface(), encMeta,
true /* createEncoder */, audioSource);
@@ -859,6 +863,7 @@ status_t StagefrightRecorder::startAACRecording() {
CHECK_EQ(mOutputFormat, OUTPUT_FORMAT_AAC_ADTS);
CHECK(mAudioEncoder == AUDIO_ENCODER_AAC ||
+ mAudioEncoder == AUDIO_ENCODER_HE_AAC ||
mAudioEncoder == AUDIO_ENCODER_AAC_ELD);
CHECK(mAudioSource != AUDIO_SOURCE_CNT);
@@ -977,7 +982,9 @@ status_t StagefrightRecorder::startMPEG2TSRecording() {
sp<MediaWriter> writer = new MPEG2TSWriter(mOutputFd);
if (mAudioSource != AUDIO_SOURCE_CNT) {
- if (mAudioEncoder != AUDIO_ENCODER_AAC) {
+ if (mAudioEncoder != AUDIO_ENCODER_AAC &&
+ mAudioEncoder != AUDIO_ENCODER_HE_AAC &&
+ mAudioEncoder != AUDIO_ENCODER_AAC_ELD) {
return ERROR_UNSUPPORTED;
}
@@ -1442,6 +1449,7 @@ status_t StagefrightRecorder::setupAudioEncoder(const sp<MediaWriter>& writer) {
case AUDIO_ENCODER_AMR_NB:
case AUDIO_ENCODER_AMR_WB:
case AUDIO_ENCODER_AAC:
+ case AUDIO_ENCODER_HE_AAC:
case AUDIO_ENCODER_AAC_ELD:
break;
diff --git a/media/libstagefright/codecs/aacdec/SoftAAC2.cpp b/media/libstagefright/codecs/aacdec/SoftAAC2.cpp
index 547a554..bf7befd 100644
--- a/media/libstagefright/codecs/aacdec/SoftAAC2.cpp
+++ b/media/libstagefright/codecs/aacdec/SoftAAC2.cpp
@@ -142,9 +142,9 @@ OMX_ERRORTYPE SoftAAC2::internalGetParameter(
aacParams->nSampleRate = 44100;
aacParams->nFrameLength = 0;
} else {
- aacParams->nChannels = mStreamInfo->channelConfig;
- aacParams->nSampleRate = mStreamInfo->aacSampleRate;
- aacParams->nFrameLength = mStreamInfo->aacSamplesPerFrame;
+ aacParams->nChannels = mStreamInfo->numChannels;
+ aacParams->nSampleRate = mStreamInfo->sampleRate;
+ aacParams->nFrameLength = mStreamInfo->frameSize;
}
return OMX_ErrorNone;
@@ -175,7 +175,7 @@ OMX_ERRORTYPE SoftAAC2::internalGetParameter(
pcmParams->nChannels = 1;
pcmParams->nSamplingRate = 44100;
} else {
- pcmParams->nChannels = mStreamInfo->channelConfig;
+ pcmParams->nChannels = mStreamInfo->numChannels;
pcmParams->nSamplingRate = mStreamInfo->sampleRate;
}
@@ -185,6 +185,7 @@ OMX_ERRORTYPE SoftAAC2::internalGetParameter(
default:
return SimpleSoftOMXComponent::internalGetParameter(index, params);
}
+
}
OMX_ERRORTYPE SoftAAC2::internalSetParameter(
@@ -254,7 +255,6 @@ void SoftAAC2::onQueueFilled(OMX_U32 portIndex) {
UCHAR* inBuffer[FILEREAD_MAX_LAYERS];
UINT inBufferLength[FILEREAD_MAX_LAYERS] = {0};
UINT bytesValid[FILEREAD_MAX_LAYERS] = {0};
- AAC_DECODER_ERROR decoderErr;
List<BufferInfo *> &inQueue = getPortQueue(0);
List<BufferInfo *> &outQueue = getPortQueue(1);
@@ -277,7 +277,6 @@ void SoftAAC2::onQueueFilled(OMX_U32 portIndex) {
notify(OMX_EventError, OMX_ErrorUndefined, decoderErr, NULL);
return;
}
-
inQueue.erase(inQueue.begin());
info->mOwnedByUs = false;
notifyEmptyBufferDone(header);
@@ -303,10 +302,16 @@ void SoftAAC2::onQueueFilled(OMX_U32 portIndex) {
// the AACDEC_FLUSH flag set
INT_PCM *outBuffer =
reinterpret_cast<INT_PCM *>(outHeader->pBuffer + outHeader->nOffset);
- decoderErr = aacDecoder_DecodeFrame(mAACDecoder,
- outBuffer,
- outHeader->nAllocLen,
- AACDEC_FLUSH);
+ AAC_DECODER_ERROR decoderErr = aacDecoder_DecodeFrame(mAACDecoder,
+ outBuffer,
+ outHeader->nAllocLen,
+ AACDEC_FLUSH);
+ if (decoderErr != AAC_DEC_OK) {
+ mSignalledError = true;
+ notify(OMX_EventError, OMX_ErrorUndefined, decoderErr, NULL);
+ return;
+ }
+
outHeader->nFilledLen =
mStreamInfo->frameSize * sizeof(int16_t) * mStreamInfo->numChannels;
outHeader->nFlags = OMX_BUFFERFLAG_EOS;
@@ -352,23 +357,27 @@ void SoftAAC2::onQueueFilled(OMX_U32 portIndex) {
inBufferLength[0] = inHeader->nFilledLen;
}
-
// Fill and decode
INT_PCM *outBuffer = reinterpret_cast<INT_PCM *>(outHeader->pBuffer + outHeader->nOffset);
bytesValid[0] = inBufferLength[0];
int flags = mInputDiscontinuity ? AACDEC_INTR : 0;
int prevSampleRate = mStreamInfo->sampleRate;
- decoderErr = aacDecoder_Fill(mAACDecoder,
- inBuffer,
- inBufferLength,
- bytesValid);
+ int prevNumChannels = mStreamInfo->numChannels;
- decoderErr = aacDecoder_DecodeFrame(mAACDecoder,
- outBuffer,
- outHeader->nAllocLen,
- flags);
+ AAC_DECODER_ERROR decoderErr = AAC_DEC_NOT_ENOUGH_BITS;
+ while (bytesValid[0] > 0 && decoderErr == AAC_DEC_NOT_ENOUGH_BITS) {
+ aacDecoder_Fill(mAACDecoder,
+ inBuffer,
+ inBufferLength,
+ bytesValid);
+ decoderErr = aacDecoder_DecodeFrame(mAACDecoder,
+ outBuffer,
+ outHeader->nAllocLen,
+ flags);
+
+ }
mInputDiscontinuity = false;
/*
@@ -386,7 +395,8 @@ void SoftAAC2::onQueueFilled(OMX_U32 portIndex) {
* AAC+/eAAC+ until the first data frame is decoded.
*/
if (mInputBufferCount <= 2) {
- if (mStreamInfo->sampleRate != prevSampleRate) {
+ if (mStreamInfo->sampleRate != prevSampleRate ||
+ mStreamInfo->numChannels != prevNumChannels) {
// We're going to want to revisit this input buffer, but
// may have already advanced the offset. Undo that if
// necessary.
diff --git a/media/libstagefright/codecs/aacenc/SoftAACEncoder2.cpp b/media/libstagefright/codecs/aacenc/SoftAACEncoder2.cpp
index 4947fb2..7719435 100644
--- a/media/libstagefright/codecs/aacenc/SoftAACEncoder2.cpp
+++ b/media/libstagefright/codecs/aacenc/SoftAACEncoder2.cpp
@@ -239,7 +239,6 @@ OMX_ERRORTYPE SoftAACEncoder2::internalSetParameter(
mBitRate = aacParams->nBitRate;
mNumChannels = aacParams->nChannels;
mSampleRate = aacParams->nSampleRate;
-
if (aacParams->eAACProfile != OMX_AUDIO_AACObjectNull) {
mAACProfile = aacParams->eAACProfile;
}
@@ -262,7 +261,6 @@ OMX_ERRORTYPE SoftAACEncoder2::internalSetParameter(
mNumChannels = pcmParams->nChannels;
mSampleRate = pcmParams->nSamplingRate;
-
if (setAudioParams() != OK) {
return OMX_ErrorUndefined;
}
@@ -275,7 +273,7 @@ OMX_ERRORTYPE SoftAACEncoder2::internalSetParameter(
}
}
-CHANNEL_MODE getChannelMode(OMX_U32 nChannels) {
+static CHANNEL_MODE getChannelMode(OMX_U32 nChannels) {
CHANNEL_MODE chMode = MODE_INVALID;
switch (nChannels) {
case 1: chMode = MODE_1; break;
@@ -289,6 +287,19 @@ CHANNEL_MODE getChannelMode(OMX_U32 nChannels) {
return chMode;
}
+static AUDIO_OBJECT_TYPE getAOTFromProfile(OMX_U32 profile) {
+ if (profile == OMX_AUDIO_AACObjectLC) {
+ return AOT_AAC_LC;
+ } else if (profile == OMX_AUDIO_AACObjectHE) {
+ return AOT_SBR;
+ } else if (profile == OMX_AUDIO_AACObjectELD) {
+ return AOT_ER_AAC_ELD;
+ } else {
+ ALOGW("Unsupported AAC profile - defaulting to AAC-LC");
+ return AOT_AAC_LC;
+ }
+}
+
status_t SoftAACEncoder2::setAudioParams() {
// We call this whenever sample rate, number of channels or bitrate change
// in reponse to setParameter calls.
@@ -297,7 +308,7 @@ status_t SoftAACEncoder2::setAudioParams() {
mSampleRate, mNumChannels, mBitRate);
if (AACENC_OK != aacEncoder_SetParam(mAACEncoder, AACENC_AOT,
- mAACProfile == OMX_AUDIO_AACObjectELD ? AOT_ER_AAC_ELD : AOT_AAC_LC)) {
+ getAOTFromProfile(mAACProfile))) {
ALOGE("Failed to set AAC encoder parameters");
return UNKNOWN_ERROR;
}
@@ -341,12 +352,17 @@ void SoftAACEncoder2::onQueueFilled(OMX_U32 portIndex) {
}
if (AACENC_OK != aacEncEncode(mAACEncoder, NULL, NULL, NULL, NULL)) {
- ALOGE("Failed to initialize AAC encoder");
+ ALOGE("Unable to initialize encoder for profile / sample-rate / bit-rate / channels");
notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL);
mSignalledError = true;
return;
}
+ OMX_U32 actualBitRate = aacEncoder_GetParam(mAACEncoder, AACENC_BITRATE);
+ if (mBitRate != actualBitRate) {
+ ALOGW("Requested bitrate %lu unsupported, using %lu", mBitRate, actualBitRate);
+ }
+
AACENC_InfoStruct encInfo;
if (AACENC_OK != aacEncInfo(mAACEncoder, &encInfo)) {
ALOGE("Failed to get AAC encoder info");
@@ -373,7 +389,7 @@ void SoftAACEncoder2::onQueueFilled(OMX_U32 portIndex) {
size_t numBytesPerInputFrame =
mNumChannels * kNumSamplesPerFrame * sizeof(int16_t);
- // BUGBUG: Fraunhofer's decoder chokes on large chunks of AAC-ELD
+ // Limit input size so we only get one ELD frame
if (mAACProfile == OMX_AUDIO_AACObjectELD && numBytesPerInputFrame > 512) {
numBytesPerInputFrame = 512;
}
@@ -402,7 +418,7 @@ void SoftAACEncoder2::onQueueFilled(OMX_U32 portIndex) {
}
if (mInputFrame == NULL) {
- mInputFrame = new int16_t[kNumSamplesPerFrame * mNumChannels];
+ mInputFrame = new int16_t[numBytesPerInputFrame / sizeof(int16_t)];
}
if (mInputSize == 0) {
@@ -490,6 +506,7 @@ void SoftAACEncoder2::onQueueFilled(OMX_U32 portIndex) {
// Encode the mInputFrame, which is treated as a modulo buffer
AACENC_ERROR encoderErr = AACENC_OK;
size_t nOutputBytes = 0;
+
do {
memset(&outargs, 0, sizeof(outargs));