summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndreas Huber <andih@google.com>2010-07-20 09:44:34 -0700
committerandroid-build SharedAccount <android-build@sekiwake.mtv.corp.google.com>2010-08-17 23:53:34 -0700
commit4b34662bacbf542a68708a9ddc25b7f22649ab99 (patch)
treefd7ff312ce590903faa6925c1e80d2d016784beb
parenteb2e09546986652259364daedba24b7f914c32c6 (diff)
downloadbase-4b34662bacbf542a68708a9ddc25b7f22649ab99.tar.gz
Squashed commit of the following:
commit 4abf16bb04dc9695fedf4007a84f903074312ccd Author: Andreas Huber <andih@google.com> Date: Tue Jul 20 09:21:17 2010 -0700 Support a single format change at the beginning of audio playback. This way the AAC+ decoder may change its output format from what is originally encoded in the audio stream and we'll still play it back correctly. Change-Id: Icc790122744745e9a88099788d4818ca1e265a82 related-to-bug: 2826841 commit 09c74da63e6ad5cb5dafb70f62696d75d2978967 Author: James Dong <jdong@google.com> Date: Sun Jul 18 17:57:01 2010 -0700 Fix MPEG4Extractor to extract sampling frequency correctly when SBR is enabled. Change-Id: I883c81dad3ea465e71cb5590e89d763671a90ff8 commit f672bf2a782dc7d5fb6325d611a7fe17045dfe9a Author: James Dong <jdong@google.com> Date: Thu Jul 8 20:56:13 2010 -0700 Enable the support for decoding audio with AAC+ and eAAC+ features bug - 282684 Change-Id: I73c8377af3cc4edd3ee7cea86dc3b1c369fbd78b Change-Id: I012f1179e933b6d1345d2368f357576c722485f7
-rw-r--r--include/media/stagefright/AudioPlayer.h4
-rw-r--r--media/libstagefright/AudioPlayer.cpp66
-rw-r--r--media/libstagefright/codecs/aacdec/AACDecoder.cpp110
-rw-r--r--media/libstagefright/include/AACDecoder.h4
4 files changed, 136 insertions, 48 deletions
diff --git a/include/media/stagefright/AudioPlayer.h b/include/media/stagefright/AudioPlayer.h
index 9af587121b94..9a09586be68e 100644
--- a/include/media/stagefright/AudioPlayer.h
+++ b/include/media/stagefright/AudioPlayer.h
@@ -86,6 +86,10 @@ private:
bool mStarted;
+ bool mIsFirstBuffer;
+ status_t mFirstBufferResult;
+ MediaBuffer *mFirstBuffer;
+
sp<MediaPlayerBase::AudioSink> mAudioSink;
static void AudioCallback(int event, void *user, void *info);
diff --git a/media/libstagefright/AudioPlayer.cpp b/media/libstagefright/AudioPlayer.cpp
index bcf246397266..c27cfc81739d 100644
--- a/media/libstagefright/AudioPlayer.cpp
+++ b/media/libstagefright/AudioPlayer.cpp
@@ -23,6 +23,7 @@
#include <media/stagefright/AudioPlayer.h>
#include <media/stagefright/MediaDebug.h>
#include <media/stagefright/MediaDefs.h>
+#include <media/stagefright/MediaErrors.h>
#include <media/stagefright/MediaSource.h>
#include <media/stagefright/MetaData.h>
@@ -41,6 +42,9 @@ AudioPlayer::AudioPlayer(const sp<MediaPlayerBase::AudioSink> &audioSink)
mReachedEOS(false),
mFinalStatus(OK),
mStarted(false),
+ mIsFirstBuffer(false),
+ mFirstBufferResult(OK),
+ mFirstBuffer(NULL),
mAudioSink(audioSink) {
}
@@ -68,6 +72,24 @@ status_t AudioPlayer::start(bool sourceAlreadyStarted) {
}
}
+ // We allow an optional INFO_FORMAT_CHANGED at the very beginning
+ // of playback, if there is one, getFormat below will retrieve the
+ // updated format, if there isn't, we'll stash away the valid buffer
+ // of data to be used on the first audio callback.
+
+ CHECK(mFirstBuffer == NULL);
+
+ mFirstBufferResult = mSource->read(&mFirstBuffer);
+ if (mFirstBufferResult == INFO_FORMAT_CHANGED) {
+ LOGV("INFO_FORMAT_CHANGED!!!");
+
+ CHECK(mFirstBuffer == NULL);
+ mFirstBufferResult = OK;
+ mIsFirstBuffer = false;
+ } else {
+ mIsFirstBuffer = true;
+ }
+
sp<MetaData> format = mSource->getFormat();
const char *mime;
bool success = format->findCString(kKeyMIMEType, &mime);
@@ -87,7 +109,14 @@ status_t AudioPlayer::start(bool sourceAlreadyStarted) {
DEFAULT_AUDIOSINK_BUFFERCOUNT,
&AudioPlayer::AudioSinkCallback, this);
if (err != OK) {
- mSource->stop();
+ if (mFirstBuffer != NULL) {
+ mFirstBuffer->release();
+ mFirstBuffer = NULL;
+ }
+
+ if (!sourceAlreadyStarted) {
+ mSource->stop();
+ }
return err;
}
@@ -108,7 +137,14 @@ status_t AudioPlayer::start(bool sourceAlreadyStarted) {
delete mAudioTrack;
mAudioTrack = NULL;
- mSource->stop();
+ if (mFirstBuffer != NULL) {
+ mFirstBuffer->release();
+ mFirstBuffer = NULL;
+ }
+
+ if (!sourceAlreadyStarted) {
+ mSource->stop();
+ }
return err;
}
@@ -159,6 +195,12 @@ void AudioPlayer::stop() {
// Make sure to release any buffer we hold onto so that the
// source is able to stop().
+
+ if (mFirstBuffer != NULL) {
+ mFirstBuffer->release();
+ mFirstBuffer = NULL;
+ }
+
if (mInputBuffer != NULL) {
LOGV("AudioPlayer releasing input buffer.");
@@ -243,6 +285,14 @@ size_t AudioPlayer::fillBuffer(void *data, size_t size) {
Mutex::Autolock autoLock(mLock);
if (mSeeking) {
+ if (mIsFirstBuffer) {
+ if (mFirstBuffer != NULL) {
+ mFirstBuffer->release();
+ mFirstBuffer = NULL;
+ }
+ mIsFirstBuffer = false;
+ }
+
options.setSeekTo(mSeekTimeUs);
if (mInputBuffer != NULL) {
@@ -255,7 +305,17 @@ size_t AudioPlayer::fillBuffer(void *data, size_t size) {
}
if (mInputBuffer == NULL) {
- status_t err = mSource->read(&mInputBuffer, &options);
+ status_t err;
+
+ if (mIsFirstBuffer) {
+ mInputBuffer = mFirstBuffer;
+ mFirstBuffer = NULL;
+ err = mFirstBufferResult;
+
+ mIsFirstBuffer = false;
+ } else {
+ err = mSource->read(&mInputBuffer, &options);
+ }
CHECK((err == OK && mInputBuffer != NULL)
|| (err != OK && mInputBuffer == NULL));
diff --git a/media/libstagefright/codecs/aacdec/AACDecoder.cpp b/media/libstagefright/codecs/aacdec/AACDecoder.cpp
index 2bc44483fd3f..8ae1135b704a 100644
--- a/media/libstagefright/codecs/aacdec/AACDecoder.cpp
+++ b/media/libstagefright/codecs/aacdec/AACDecoder.cpp
@@ -15,6 +15,7 @@
*/
#include "AACDecoder.h"
+#define LOG_TAG "AACDecoder"
#include "../../include/ESDS.h"
@@ -36,26 +37,33 @@ AACDecoder::AACDecoder(const sp<MediaSource> &source)
mAnchorTimeUs(0),
mNumSamplesOutput(0),
mInputBuffer(NULL) {
-}
-AACDecoder::~AACDecoder() {
- if (mStarted) {
- stop();
- }
+ sp<MetaData> srcFormat = mSource->getFormat();
- delete mConfig;
- mConfig = NULL;
-}
+ int32_t sampleRate;
+ CHECK(srcFormat->findInt32(kKeySampleRate, &sampleRate));
-status_t AACDecoder::start(MetaData *params) {
- CHECK(!mStarted);
+ mMeta = new MetaData;
+ mMeta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_RAW);
- mBufferGroup = new MediaBufferGroup;
- mBufferGroup->add_buffer(new MediaBuffer(2048 * 2));
+ // We'll always output stereo, regardless of how many channels are
+ // present in the input due to decoder limitations.
+ mMeta->setInt32(kKeyChannelCount, 2);
+ mMeta->setInt32(kKeySampleRate, sampleRate);
+ int64_t durationUs;
+ if (srcFormat->findInt64(kKeyDuration, &durationUs)) {
+ mMeta->setInt64(kKeyDuration, durationUs);
+ }
+ mMeta->setCString(kKeyDecoderComponent, "AACDecoder");
+
+ mInitCheck = initCheck();
+}
+
+status_t AACDecoder::initCheck() {
+ memset(mConfig, 0, sizeof(tPVMP4AudioDecoderExternal));
mConfig->outputFormat = OUTPUTFORMAT_16PCM_INTERLEAVED;
- mConfig->aacPlusUpsamplingFactor = 0;
- mConfig->aacPlusEnabled = false;
+ mConfig->aacPlusEnabled = 1;
// The software decoder doesn't properly support mono output on
// AACplus files. Always output stereo.
@@ -64,8 +72,11 @@ status_t AACDecoder::start(MetaData *params) {
UInt32 memRequirements = PVMP4AudioDecoderGetMemRequirements();
mDecoderBuf = malloc(memRequirements);
- CHECK_EQ(PVMP4AudioDecoderInitLibrary(mConfig, mDecoderBuf),
- MP4AUDEC_SUCCESS);
+ status_t err = PVMP4AudioDecoderInitLibrary(mConfig, mDecoderBuf);
+ if (err != MP4AUDEC_SUCCESS) {
+ LOGE("Failed to initialize MP4 audio decoder");
+ return UNKNOWN_ERROR;
+ }
uint32_t type;
const void *data;
@@ -83,18 +94,29 @@ status_t AACDecoder::start(MetaData *params) {
mConfig->pInputBuffer = (UChar *)codec_specific_data;
mConfig->inputBufferCurrentLength = codec_specific_data_size;
mConfig->inputBufferMaxLength = 0;
- mConfig->inputBufferUsedLength = 0;
- mConfig->remainderBits = 0;
-
- mConfig->pOutputBuffer = NULL;
- mConfig->pOutputBuffer_plus = NULL;
- mConfig->repositionFlag = false;
if (PVMP4AudioDecoderConfig(mConfig, mDecoderBuf)
!= MP4AUDEC_SUCCESS) {
return ERROR_UNSUPPORTED;
}
}
+ return OK;
+}
+
+AACDecoder::~AACDecoder() {
+ if (mStarted) {
+ stop();
+ }
+
+ delete mConfig;
+ mConfig = NULL;
+}
+
+status_t AACDecoder::start(MetaData *params) {
+ CHECK(!mStarted);
+
+ mBufferGroup = new MediaBufferGroup;
+ mBufferGroup->add_buffer(new MediaBuffer(4096 * 2));
mSource->start();
@@ -127,28 +149,7 @@ status_t AACDecoder::stop() {
}
sp<MetaData> AACDecoder::getFormat() {
- sp<MetaData> srcFormat = mSource->getFormat();
-
- int32_t sampleRate;
- CHECK(srcFormat->findInt32(kKeySampleRate, &sampleRate));
-
- sp<MetaData> meta = new MetaData;
- meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_RAW);
-
- // We'll always output stereo, regardless of how many channels are
- // present in the input due to decoder limitations.
- meta->setInt32(kKeyChannelCount, 2);
-
- meta->setInt32(kKeySampleRate, sampleRate);
-
- int64_t durationUs;
- if (srcFormat->findInt64(kKeyDuration, &durationUs)) {
- meta->setInt64(kKeyDuration, durationUs);
- }
-
- meta->setCString(kKeyDecoderComponent, "AACDecoder");
-
- return meta;
+ return mMeta;
}
status_t AACDecoder::read(
@@ -200,13 +201,32 @@ status_t AACDecoder::read(
mConfig->remainderBits = 0;
mConfig->pOutputBuffer = static_cast<Int16 *>(buffer->data());
- mConfig->pOutputBuffer_plus = NULL;
+ mConfig->pOutputBuffer_plus = &mConfig->pOutputBuffer[2048];
mConfig->repositionFlag = false;
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;
+ }
+
size_t numOutBytes =
mConfig->frameLength * sizeof(int16_t) * mConfig->desiredChannels;
+ if (mConfig->aacPlusUpsamplingFactor == 2) {
+ if (mConfig->desiredChannels == 1) {
+ memcpy(&mConfig->pOutputBuffer[1024], &mConfig->pOutputBuffer[2048], numOutBytes * 2);
+ }
+ numOutBytes *= 2;
+ }
if (decoderErr != MP4AUDEC_SUCCESS) {
LOGW("AAC decoder returned error %d, substituting silence", decoderErr);
diff --git a/media/libstagefright/include/AACDecoder.h b/media/libstagefright/include/AACDecoder.h
index f09addd2d611..200f93c646b8 100644
--- a/media/libstagefright/include/AACDecoder.h
+++ b/media/libstagefright/include/AACDecoder.h
@@ -25,6 +25,7 @@ struct tPVMP4AudioDecoderExternal;
namespace android {
struct MediaBufferGroup;
+struct MetaData;
struct AACDecoder : public MediaSource {
AACDecoder(const sp<MediaSource> &source);
@@ -41,6 +42,7 @@ protected:
virtual ~AACDecoder();
private:
+ sp<MetaData> mMeta;
sp<MediaSource> mSource;
bool mStarted;
@@ -50,9 +52,11 @@ private:
void *mDecoderBuf;
int64_t mAnchorTimeUs;
int64_t mNumSamplesOutput;
+ status_t mInitCheck;
MediaBuffer *mInputBuffer;
+ status_t initCheck();
AACDecoder(const AACDecoder &);
AACDecoder &operator=(const AACDecoder &);
};