diff options
author | Jean-Michel Trivi <jmtrivi@google.com> | 2010-10-13 11:31:01 -0700 |
---|---|---|
committer | Jean-Michel Trivi <jmtrivi@google.com> | 2010-10-13 15:46:34 -0700 |
commit | ffbd220f34d275c6231cac8db8f3b50aa16be2b2 (patch) | |
tree | 9751b6ce104b5c850bc11febfa543a2f6bdae5df | |
parent | 80b645911cfc4ddbd8c011efe55c502cd03c7908 (diff) | |
download | android_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.cpp | 22 | ||||
-rw-r--r-- | opensles/libopensles/android_SfPlayer.cpp | 89 | ||||
-rw-r--r-- | opensles/libopensles/android_SfPlayer.h | 4 |
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); |