summaryrefslogtreecommitdiffstats
path: root/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp')
-rw-r--r--media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp73
1 files changed, 50 insertions, 23 deletions
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp b/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp
index 7f8680d..d21884b 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp
@@ -67,6 +67,7 @@ NuPlayer::Renderer::Renderer(
mVideoQueueGeneration(0),
mAudioDrainGeneration(0),
mVideoDrainGeneration(0),
+ mPlaybackRate(1.0),
mAudioFirstAnchorTimeMediaUs(-1),
mAnchorTimeMediaUs(-1),
mAnchorNumFramesWritten(-1),
@@ -121,6 +122,12 @@ void NuPlayer::Renderer::queueEOS(bool audio, status_t finalResult) {
msg->post();
}
+void NuPlayer::Renderer::setPlaybackRate(float rate) {
+ sp<AMessage> msg = new AMessage(kWhatSetRate, id());
+ msg->setFloat("rate", rate);
+ msg->post();
+}
+
void NuPlayer::Renderer::flush(bool audio, bool notifyComplete) {
{
Mutex::Autolock autoLock(mLock);
@@ -172,12 +179,7 @@ void NuPlayer::Renderer::setVideoFrameRate(float fps) {
// Called on any threads.
status_t NuPlayer::Renderer::getCurrentPosition(int64_t *mediaUs) {
- int64_t currentTimeUs = mMediaClock->getTimeMedia(ALooper::GetNowUs());
- if (currentTimeUs == -1) {
- return NO_INIT;
- }
- *mediaUs = currentTimeUs;
- return OK;
+ return mMediaClock->getMediaTime(ALooper::GetNowUs(), mediaUs);
}
void NuPlayer::Renderer::clearAudioFirstAnchorTime_l() {
@@ -361,6 +363,16 @@ void NuPlayer::Renderer::onMessageReceived(const sp<AMessage> &msg) {
break;
}
+ case kWhatSetRate:
+ {
+ CHECK(msg->findFloat("rate", &mPlaybackRate));
+ int32_t ratePermille = (int32_t)(0.5f + 1000 * mPlaybackRate);
+ mPlaybackRate = ratePermille / 1000.0f;
+ mMediaClock->setPlaybackRate(mPlaybackRate);
+ mAudioSink->setPlaybackRatePermille(ratePermille);
+ break;
+ }
+
case kWhatFlush:
{
onFlush(msg);
@@ -541,10 +553,10 @@ size_t NuPlayer::Renderer::fillAudioBuffer(void *buffer, size_t size) {
if (mAudioFirstAnchorTimeMediaUs >= 0) {
int64_t nowUs = ALooper::GetNowUs();
+ int64_t nowMediaUs =
+ mAudioFirstAnchorTimeMediaUs + getPlayedOutAudioDurationUs(nowUs);
// we don't know how much data we are queueing for offloaded tracks.
- mMediaClock->updateAnchor(mAudioFirstAnchorTimeMediaUs,
- nowUs - getPlayedOutAudioDurationUs(nowUs),
- INT64_MAX);
+ mMediaClock->updateAnchor(nowMediaUs, nowUs, INT64_MAX);
}
if (hasEOS) {
@@ -670,21 +682,27 @@ bool NuPlayer::Renderer::onDrainAudioQueue() {
return !mAudioQueue.empty();
}
+int64_t NuPlayer::Renderer::getDurationUsIfPlayedAtSampleRate(uint32_t numFrames) {
+ int32_t sampleRate = offloadingAudio() ?
+ mCurrentOffloadInfo.sample_rate : mCurrentPcmInfo.mSampleRate;
+ // TODO: remove the (int32_t) casting below as it may overflow at 12.4 hours.
+ return (int64_t)((int32_t)numFrames * 1000000LL / sampleRate);
+}
+
+// Calculate duration of pending samples if played at normal rate (i.e., 1.0).
int64_t NuPlayer::Renderer::getPendingAudioPlayoutDurationUs(int64_t nowUs) {
- int64_t writtenAudioDurationUs =
- mNumFramesWritten * 1000LL * mAudioSink->msecsPerFrame();
+ int64_t writtenAudioDurationUs = getDurationUsIfPlayedAtSampleRate(mNumFramesWritten);
return writtenAudioDurationUs - getPlayedOutAudioDurationUs(nowUs);
}
int64_t NuPlayer::Renderer::getRealTimeUs(int64_t mediaTimeUs, int64_t nowUs) {
- int64_t currentPositionUs =
- mMediaClock->getTimeMedia(nowUs, true /* allowPastMaxTime */);
- if (currentPositionUs == -1) {
+ int64_t realUs;
+ if (mMediaClock->getRealTimeFor(mediaTimeUs, &realUs) != OK) {
// If failed to get current position, e.g. due to audio clock is
// not ready, then just play out video immediately without delay.
return nowUs;
}
- return (mediaTimeUs - currentPositionUs) + nowUs;
+ return realUs;
}
void NuPlayer::Renderer::onNewAudioMediaTime(int64_t mediaTimeUs) {
@@ -696,9 +714,8 @@ void NuPlayer::Renderer::onNewAudioMediaTime(int64_t mediaTimeUs) {
}
setAudioFirstAnchorTimeIfNeeded_l(mediaTimeUs);
int64_t nowUs = ALooper::GetNowUs();
- mMediaClock->updateAnchor(mediaTimeUs,
- nowUs + getPendingAudioPlayoutDurationUs(nowUs),
- mediaTimeUs);
+ int64_t nowMediaUs = mediaTimeUs - getPendingAudioPlayoutDurationUs(nowUs);
+ mMediaClock->updateAnchor(nowMediaUs, nowUs, mediaTimeUs);
mAnchorTimeMediaUs = mediaTimeUs;
}
@@ -828,9 +845,11 @@ void NuPlayer::Renderer::onDrainVideoQueue() {
ALOGV("video late by %lld us (%.2f secs)",
mVideoLateByUs, mVideoLateByUs / 1E6);
} else {
+ int64_t mediaUs = 0;
+ mMediaClock->getMediaTime(realTimeUs, &mediaUs);
ALOGV("rendering video at media time %.2f secs",
(mFlags & FLAG_REAL_TIME ? realTimeUs :
- mMediaClock->getTimeMedia(realTimeUs)) / 1E6);
+ mediaUs) / 1E6);
}
} else {
setVideoLateByUs(0);
@@ -1153,7 +1172,7 @@ void NuPlayer::Renderer::onPause() {
++mVideoDrainGeneration;
prepareForMediaRenderingStart_l();
mPaused = true;
- mMediaClock->pause();
+ mMediaClock->setPlaybackRate(0.0);
}
mDrainAudioQueuePending = false;
@@ -1181,7 +1200,7 @@ void NuPlayer::Renderer::onResume() {
{
Mutex::Autolock autoLock(mLock);
mPaused = false;
- mMediaClock->resume();
+ mMediaClock->setPlaybackRate(mPlaybackRate);
if (!mAudioQueue.empty()) {
postDrainAudioQueue_l();
@@ -1222,6 +1241,7 @@ bool NuPlayer::Renderer::getSyncQueues() {
// accessing getTimestamp() or getPosition() every time a data buffer with
// a media time is received.
//
+// Calculate duration of played samples if played at normal rate (i.e., 1.0).
int64_t NuPlayer::Renderer::getPlayedOutAudioDurationUs(int64_t nowUs) {
uint32_t numFramesPlayed;
int64_t numFramesPlayedAt;
@@ -1259,9 +1279,8 @@ int64_t NuPlayer::Renderer::getPlayedOutAudioDurationUs(int64_t nowUs) {
//ALOGD("getPosition: %d %lld", numFramesPlayed, numFramesPlayedAt);
}
- // TODO: remove the (int32_t) casting below as it may overflow at 12.4 hours.
//CHECK_EQ(numFramesPlayed & (1 << 31), 0); // can't be negative until 12.4 hrs, test
- int64_t durationUs = (int64_t)((int32_t)numFramesPlayed * 1000LL * mAudioSink->msecsPerFrame())
+ int64_t durationUs = getDurationUsIfPlayedAtSampleRate(numFramesPlayed)
+ nowUs - numFramesPlayedAt;
if (durationUs < 0) {
// Occurs when numFramesPlayed position is very small and the following:
@@ -1400,6 +1419,10 @@ status_t NuPlayer::Renderer::onOpenAudioSink(
&offloadInfo);
if (err == OK) {
+ if (mPlaybackRate != 1.0) {
+ mAudioSink->setPlaybackRatePermille(
+ (int32_t)(mPlaybackRate * 1000 + 0.5f));
+ }
// If the playback is offloaded to h/w, we pass
// the HAL some metadata information.
// We don't want to do this for PCM because it
@@ -1455,6 +1478,10 @@ status_t NuPlayer::Renderer::onOpenAudioSink(
return err;
}
mCurrentPcmInfo = info;
+ if (mPlaybackRate != 1.0) {
+ mAudioSink->setPlaybackRatePermille(
+ (int32_t)(mPlaybackRate * 1000 + 0.5f));
+ }
mAudioSink->start();
}
if (audioSinkChanged) {