diff options
| author | Jean-Michel Trivi <jmtrivi@google.com> | 2012-05-04 13:49:20 -0700 |
|---|---|---|
| committer | Jean-Michel Trivi <jmtrivi@google.com> | 2012-05-08 09:17:56 -0700 |
| commit | 91145ef159d3e165a461cbd76341ff8ed3d72bae (patch) | |
| tree | f4f1027c23e4f028ea9113187c90923714097c13 | |
| parent | 8daa09a2af477dbe495839ccf806919a02aa53cd (diff) | |
| download | android_frameworks_wilhelm-jellybean.tar.gz android_frameworks_wilhelm-jellybean.tar.bz2 android_frameworks_wilhelm-jellybean.zip | |
Playback rate on OpenSL ES AudioPlayer playing from URI/FDjellybean-stablejellybean
Allow AudioPlayer to use the platform's 500-2000 range (in
permille) of playback rate for audio when the data source
is a URI or FD.
Since play events for those players are simulated through
monitoring the playback position, scale the time
between updates so play events are delivered in content
time, not presentation time (as defined in OpenSL ES
specification, "positions do not scale with changes in
playback rate").
Bug 5898620
Change-Id: Ib512caebd7f3983c9e845be62e48dfee8499e59c
| -rw-r--r-- | src/android/AudioPlayer_to_android.cpp | 19 | ||||
| -rw-r--r-- | src/android/android_GenericMediaPlayer.cpp | 19 | ||||
| -rw-r--r-- | src/android/android_GenericMediaPlayer.h | 2 | ||||
| -rw-r--r-- | src/android/android_GenericPlayer.cpp | 22 | ||||
| -rw-r--r-- | src/android/android_GenericPlayer.h | 6 |
5 files changed, 64 insertions, 4 deletions
diff --git a/src/android/AudioPlayer_to_android.cpp b/src/android/AudioPlayer_to_android.cpp index 7002829..73ee427 100644 --- a/src/android/AudioPlayer_to_android.cpp +++ b/src/android/AudioPlayer_to_android.cpp @@ -33,6 +33,9 @@ template class android::KeyedVector<SLuint32, android::AudioEffect* > ; #define AUDIOTRACK_MIN_PLAYBACKRATE_PERMILLE 500 #define AUDIOTRACK_MAX_PLAYBACKRATE_PERMILLE 2000 +#define MEDIAPLAYER_MIN_PLAYBACKRATE_PERMILLE AUDIOTRACK_MIN_PLAYBACKRATE_PERMILLE +#define MEDIAPLAYER_MAX_PLAYBACKRATE_PERMILLE AUDIOTRACK_MAX_PLAYBACKRATE_PERMILLE + //----------------------------------------------------------------------------- // FIXME this method will be absorbed into android_audioPlayer_setPlayState() once // bufferqueue and uri/fd playback are moved under the GenericPlayer C++ object @@ -1276,12 +1279,15 @@ void android_audioPlayer_create(CAudioPlayer *pAudioPlayer) { // can be set or used regardless of whether the interface is // exposed on the AudioPlayer or not - // Only AudioTrack supports a non-trivial playback rate switch (pAudioPlayer->mAndroidObjType) { case AUDIOPLAYER_FROM_PCM_BUFFERQUEUE: pAudioPlayer->mPlaybackRate.mMinRate = AUDIOTRACK_MIN_PLAYBACKRATE_PERMILLE; pAudioPlayer->mPlaybackRate.mMaxRate = AUDIOTRACK_MAX_PLAYBACKRATE_PERMILLE; break; + case AUDIOPLAYER_FROM_URIFD: + pAudioPlayer->mPlaybackRate.mMinRate = MEDIAPLAYER_MIN_PLAYBACKRATE_PERMILLE; + pAudioPlayer->mPlaybackRate.mMaxRate = MEDIAPLAYER_MAX_PLAYBACKRATE_PERMILLE; + break; default: // use the default range break; @@ -1740,10 +1746,15 @@ SLresult android_audioPlayer_setPlaybackRateAndConstraints(CAudioPlayer *ap, SLp } } break; - case AUDIOPLAYER_FROM_URIFD: - assert(rate == 1000); + case AUDIOPLAYER_FROM_URIFD: { + assert((MEDIAPLAYER_MIN_PLAYBACKRATE_PERMILLE <= rate) && + (rate <= MEDIAPLAYER_MAX_PLAYBACKRATE_PERMILLE)); assert(constraints & SL_RATEPROP_NOPITCHCORAUDIO); - // that was easy + // apply the SL ES playback rate on the GenericPlayer + if (ap->mAPlayer != 0) { + ap->mAPlayer->setPlaybackRate((int16_t)rate); + } + } break; default: diff --git a/src/android/android_GenericMediaPlayer.cpp b/src/android/android_GenericMediaPlayer.cpp index 04f4f8e..629c54e 100644 --- a/src/android/android_GenericMediaPlayer.cpp +++ b/src/android/android_GenericMediaPlayer.cpp @@ -308,6 +308,20 @@ void GenericMediaPlayer::setVideoSurfaceTexture(const sp<ISurfaceTexture> &surfa mVideoSurfaceTexture = surfaceTexture; } +//-------------------------------------------------- +void GenericMediaPlayer::setPlaybackRate(int32_t ratePermille) { + SL_LOGV("GenericMediaPlayer::setPlaybackRate(%d)", ratePermille); + GenericPlayer::setPlaybackRate(ratePermille); + sp<IMediaPlayer> player; + getPreparedPlayer(player); + if (player != 0) { + Parcel rateParcel; + if (rateParcel.writeInt32(ratePermille) == OK) { + player->setParameter(KEY_PARAMETER_PLAYBACK_RATE_PERMILLE, rateParcel); + } + } +} + //-------------------------------------------------- // Event handlers @@ -575,6 +589,11 @@ void GenericMediaPlayer::afterMediaPlayerPreparedSuccessfully() { } else { SL_LOGD("media player prepared on non-local source"); } + // when the MediaPlayer mPlayer is prepared, apply the playback rate + Parcel rateParcel; + if (rateParcel.writeInt32((int32_t)mPlaybackRatePermille) == OK) { + mPlayer->setParameter(KEY_PARAMETER_PLAYBACK_RATE_PERMILLE, rateParcel); + } } diff --git a/src/android/android_GenericMediaPlayer.h b/src/android/android_GenericMediaPlayer.h index c0497ba..e4e556b 100644 --- a/src/android/android_GenericMediaPlayer.h +++ b/src/android/android_GenericMediaPlayer.h @@ -91,6 +91,8 @@ public: virtual void setVideoSurfaceTexture(const sp<ISurfaceTexture> &surfaceTexture); + virtual void setPlaybackRate(int32_t ratePermille); + protected: friend class MediaPlayerNotificationClient; diff --git a/src/android/android_GenericPlayer.cpp b/src/android/android_GenericPlayer.cpp index 0fd975c..e87f9a8 100644 --- a/src/android/android_GenericPlayer.cpp +++ b/src/android/android_GenericPlayer.cpp @@ -31,6 +31,7 @@ GenericPlayer::GenericPlayer(const AudioPlayback_Parameters* params) : mStateFlags(0), mPlaybackParams(*params), mDurationMsec(ANDROID_UNKNOWN_TIME), + mPlaybackRatePermille(1000), mCacheStatus(kStatusEmpty), mCacheFill(0), mLastNotifiedCacheFill(0), @@ -231,6 +232,15 @@ void GenericPlayer::setAuxEffectSendLevel(float level) //-------------------------------------------------- +void GenericPlayer::setPlaybackRate(int32_t ratePermille) { + SL_LOGV("GenericPlayer::setPlaybackRate(ratePermille=%d)", ratePermille); + { + Mutex::Autolock _l(mSettingsLock); + mPlaybackRatePermille = (int16_t)ratePermille; + } +} + +//-------------------------------------------------- // Call after changing any of the IPlay settings related to SL_PLAYEVENT_* void GenericPlayer::setPlayEvents(int32_t eventFlags, int32_t markerPositionMs, int32_t positionUpdatePeriodMs) @@ -671,8 +681,20 @@ void GenericPlayer::updateOneShot(int positionMs) // we have a new observed position mObservedPositionMs = positionMs; + if (mPlaybackRatePermille == 0) { + // playback is frozen, no update expected (and no division by zero below) + return; + } + // post the new one-shot message if needed if (advancesPositionInRealTime() && delayUs >= 0) { + // scale delay according to playback rate (reported positions won't change, but reported + // time will advance slower or faster depending on rate) + { + Mutex::Autolock _l(mSettingsLock); + delayUs = delayUs * 1000 / mPlaybackRatePermille; + } + // 20 ms min delay to avoid near busy waiting if (delayUs < 20000LL) { delayUs = 20000LL; diff --git a/src/android/android_GenericPlayer.h b/src/android/android_GenericPlayer.h index bc52846..f73eb3e 100644 --- a/src/android/android_GenericPlayer.h +++ b/src/android/android_GenericPlayer.h @@ -84,6 +84,8 @@ public: void attachAuxEffect(int32_t effectId); void setAuxEffectSendLevel(float level); + virtual void setPlaybackRate(int32_t ratePermille); + // Call after changing any of the IPlay settings related to SL_PLAYEVENT_* void setPlayEvents(int32_t eventFlags, int32_t markerPosition, int32_t positionUpdatePeriod); @@ -181,6 +183,7 @@ protected: // protected by mSettingsLock int32_t mDurationMsec; + int16_t mPlaybackRatePermille; CacheStatus_t mCacheStatus; int16_t mCacheFill; // cache fill level + played back level in permille @@ -191,6 +194,9 @@ protected: // supply the latest known position or ANDROID_UNKNOWN_TIME if position is unknown to caller. void updateOneShot(int positionMs = ANDROID_UNKNOWN_TIME); + // players that "render" data to present it to the user (a music player, a video player), + // should return true, while players that only decode (hopefully faster than "real time") + // should return false. virtual bool advancesPositionInRealTime() const { return true; } private: |
