summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJean-Michel Trivi <jmtrivi@google.com>2010-10-13 11:31:01 -0700
committerJean-Michel Trivi <jmtrivi@google.com>2010-10-13 15:46:34 -0700
commitffbd220f34d275c6231cac8db8f3b50aa16be2b2 (patch)
tree9751b6ce104b5c850bc11febfa543a2f6bdae5df
parent80b645911cfc4ddbd8c011efe55c502cd03c7908 (diff)
downloadandroid_system_media-ffbd220f34d275c6231cac8db8f3b50aa16be2b2.tar.gz
android_system_media-ffbd220f34d275c6231cac8db8f3b50aa16be2b2.tar.bz2
android_system_media-ffbd220f34d275c6231cac8db8f3b50aa16be2b2.zip
Fix bug 3094729 Support AAC+ in OpenSL ES
When playing an AAC+ stream, StageFright will report a change of configuration in the stream between the prepare phase and the start of the playback. The fix consists in retrieving the new configuration in SfPlayer, create a new AudioTrack with the new parameters, and notify AudioPlayer that SfPlayer has a new AudioTrack to use. AudioPlayer will then delete its current AudioTrack, and use the new one from SfPlayer, after configuring it with the current AudioPlayer settings. Change-Id: I23e3ecb2c144b7c4eefae7a970581695545982d4
-rw-r--r--opensles/libopensles/android_AudioPlayer.cpp22
-rw-r--r--opensles/libopensles/android_SfPlayer.cpp89
-rw-r--r--opensles/libopensles/android_SfPlayer.h4
3 files changed, 100 insertions, 15 deletions
diff --git a/opensles/libopensles/android_AudioPlayer.cpp b/opensles/libopensles/android_AudioPlayer.cpp
index 3255062f..9149e5ac 100644
--- a/opensles/libopensles/android_AudioPlayer.cpp
+++ b/opensles/libopensles/android_AudioPlayer.cpp
@@ -463,6 +463,28 @@ static void sfplayer_handlePrefetchEvent(const int event, const int data1, void*
} break;
+ case(android::SfPlayer::kEventNewAudioTrack): {
+ object_lock_exclusive(&ap->mObject);
+ // SfPlayer has a new AudioTrack, delete the old one and configure the new one before
+ // starting to use it
+
+ if (NULL != ap->mAudioTrack) {
+ delete ap->mAudioTrack;
+ ap->mAudioTrack = NULL;
+ }
+ ap->mAudioTrack = ap->mSfPlayer->getAudioTrack();
+ ap->mNumChannels = ap->mSfPlayer->getNumChannels();
+ ap->mSampleRateMilliHz = android_to_sles_sampleRate(ap->mSfPlayer->getSampleRateHz());
+
+ // update the new track with the current settings
+ audioPlayer_auxEffectUpdate(ap);
+ android_audioPlayer_useEventMask(ap);
+ android_audioPlayer_volumeUpdate(ap);
+ android_audioPlayer_setPlayRate(ap, ap->mPlaybackRate.mRate, false /*lockAP*/);
+
+ object_unlock_exclusive(&ap->mObject);
+ } break;
+
case(android::SfPlayer::kEventPrefetchFillLevelUpdate): {
if (!IsInterfaceInitialized(&(ap->mObject), MPH_PREFETCHSTATUS)) {
break;
diff --git a/opensles/libopensles/android_SfPlayer.cpp b/opensles/libopensles/android_SfPlayer.cpp
index ea12dcb6..5d18198c 100644
--- a/opensles/libopensles/android_SfPlayer.cpp
+++ b/opensles/libopensles/android_SfPlayer.cpp
@@ -80,9 +80,6 @@ void SfPlayer::armLooper() {
ANDROID_PRIORITY_AUDIO);
}
-void SfPlayer::useAudioTrack(AudioTrack* pTrack) {
- mAudioTrack = pTrack;
-}
void SfPlayer::setNotifListener(const notif_client_t cbf, void* notifUser) {
mNotifyClient = cbf;
@@ -415,7 +412,9 @@ int64_t SfPlayer::getPositionUsec() {
}
}
-
+/**
+ * called from message loop
+ */
void SfPlayer::reachedEndOfStream() {
SL_LOGV("SfPlayer::reachedEndOfStream");
if (mFlags & kFlagPlaying) {
@@ -431,6 +430,45 @@ void SfPlayer::reachedEndOfStream() {
}
}
+/**
+ * called from message loop
+ */
+void SfPlayer::updatePlaybackParamsFromSource() {
+ if (mAudioSource != 0) {
+ sp<MetaData> meta = mAudioSource->getFormat();
+
+ SL_LOGV("old sample rate = %d", mSampleRateHz);
+ CHECK(meta->findInt32(kKeyChannelCount, &mNumChannels));
+ CHECK(meta->findInt32(kKeySampleRate, &mSampleRateHz));
+ SL_LOGV("new sample rate = %d", mSampleRateHz);
+
+ // the AudioTrack currently used by the AudioPlayer will be deleted by AudioPlayer itself
+ // SfPlayer never deletes the AudioTrack it creates and uses.
+ mAudioTrack = new android::AudioTrack(
+ mPlaybackParams.streamType, // streamType
+ mSampleRateHz, // sampleRate
+ android::AudioSystem::PCM_16_BIT, // format
+ mNumChannels == 1 ? //channel mask
+ android::AudioSystem::CHANNEL_OUT_MONO :
+ android::AudioSystem::CHANNEL_OUT_STEREO,
+ 0, // frameCount (here min)
+ 0, // flags
+ mPlaybackParams.trackcb, // callback
+ mPlaybackParams.trackcbUser, // user
+ 0, // notificationFrame
+ mPlaybackParams.sessionId
+ );
+ if (mFlags & kFlagPlaying) {
+ mAudioTrack->start();
+ }
+
+ // notify the AudioPlayer synchronously there's a new AudioTrack to use and configure
+ sp<AMessage> msg = new AMessage(kWhatNotif, id());
+ msg->setInt32(EVENT_NEW_AUDIOTRACK, 0/*data field unused*/);
+ notify(msg, false /*async*/);
+ }
+}
+
/**
* Message handlers
@@ -529,17 +567,35 @@ void SfPlayer::onDecode() {
}
if (err != OK) {
- if (err != ERROR_END_OF_STREAM) {
- SL_LOGE("MediaSource::read returned error %d", err);
- pause();
- notifyPrepared(err);
- return;
- } else {
- // handle notification and looping at end of stream
- if (0 < mDurationUsec) {
- mLastDecodedPositionUs = mDurationUsec;
+ bool continueDecoding = false;
+ switch(err) {
+ case ERROR_END_OF_STREAM:
+ // handle notification and looping at end of stream
+ if (0 < mDurationUsec) {
+ mLastDecodedPositionUs = mDurationUsec;
+ }
+ reachedEndOfStream();
+ break;
+ case INFO_FORMAT_CHANGED:
+ SL_LOGI("MediaSource::read encountered INFO_FORMAT_CHANGED");
+ // reconfigure output
+ updatePlaybackParamsFromSource();
+ continueDecoding = true;
+ break;
+ case INFO_DISCONTINUITY:
+ SL_LOGI("MediaSource::read encountered INFO_DISCONTINUITY");
+ continueDecoding = true;
+ break;
+ default:
+ SL_LOGE("MediaSource::read returned error %d", err);
+ break;
+ }
+ if (continueDecoding) {
+ if (NULL == mDecodeBuffer) {
+ (new AMessage(kWhatDecode, id()))->post();
+ return;
}
- reachedEndOfStream();
+ } else {
return;
}
}
@@ -645,6 +701,11 @@ void SfPlayer::onNotify(const sp<AMessage> &msg) {
SL_LOGV("\tSfPlayer notifying %s = %d", EVENT_PREPARED, val);
mNotifyClient(kEventPrepared, val, mNotifyUser);
}
+
+ if (msg->findInt32(EVENT_NEW_AUDIOTRACK, &val)) {
+ SL_LOGV("\tSfPlayer notifying %s", EVENT_NEW_AUDIOTRACK);
+ mNotifyClient(kEventNewAudioTrack, val, mNotifyUser);
+ }
}
SfPlayer::CacheStatus SfPlayer::getCacheRemaining(bool *eos) {
diff --git a/opensles/libopensles/android_SfPlayer.h b/opensles/libopensles/android_SfPlayer.h
index 9aeef663..fac00dd2 100644
--- a/opensles/libopensles/android_SfPlayer.h
+++ b/opensles/libopensles/android_SfPlayer.h
@@ -52,6 +52,7 @@
#define EVENT_PREFETCHSTATUSCHANGE "prsc"
#define EVENT_PREFETCHFILLLEVELUPDATE "pflu"
#define EVENT_ENDOFSTREAM "eos"
+#define EVENT_NEW_AUDIOTRACK "nwat"
#define SFPLAYER_SUCCESS 1
#define SFPLAYER_FD_FIND_FILE_SIZE ((int64_t)0xFFFFFFFFFFFFFFFFll)
@@ -89,10 +90,10 @@ struct SfPlayer : public AHandler {
kEventPrefetchStatusChange = 'prsc',
kEventPrefetchFillLevelUpdate = 'pflu',
kEventEndOfStream = 'eos',
+ kEventNewAudioTrack = 'nwat'
};
void armLooper();
- void useAudioTrack(AudioTrack* pTrack);
void setNotifListener(const notif_client_t cbf, void* notifUser);
void setDataSource(const char *uri);
@@ -208,6 +209,7 @@ private:
CacheStatus getCacheRemaining(bool *eos);
int64_t getPositionUsec();
void reachedEndOfStream();
+ void updatePlaybackParamsFromSource();
void notifyStatus();
void notifyCacheFill();
void notifyPrepared(status_t prepareRes);