summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/android/AudioPlayer_to_android.cpp19
-rw-r--r--src/android/android_GenericMediaPlayer.cpp19
-rw-r--r--src/android/android_GenericMediaPlayer.h2
-rw-r--r--src/android/android_GenericPlayer.cpp22
-rw-r--r--src/android/android_GenericPlayer.h6
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: