diff options
| -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: |
