summaryrefslogtreecommitdiffstats
path: root/media
diff options
context:
space:
mode:
authorRonghua Wu <ronghuawu@google.com>2014-10-08 15:13:29 -0700
committerRonghua Wu <ronghuawu@google.com>2014-10-13 16:24:49 -0700
commita73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57 (patch)
tree0e385a27935b7912d276f972b7ed288e329fa2d8 /media
parenta4c3d8f0f9aab53b106d95e6139e0465908909f4 (diff)
downloadframeworks_av-a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57.zip
frameworks_av-a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57.tar.gz
frameworks_av-a73d9e0b3d171d2bfcd9eb07df9d6d36ae74df57.tar.bz2
NuPlayer: query current position from NuPlayerRenderer.
Bug: 17653702 Change-Id: Ie0b1f92420b071a0cfcd389f5e7917a54d332541
Diffstat (limited to 'media')
-rw-r--r--media/libmediaplayerservice/nuplayer/NuPlayer.cpp48
-rw-r--r--media/libmediaplayerservice/nuplayer/NuPlayer.h4
-rw-r--r--media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp94
-rw-r--r--media/libmediaplayerservice/nuplayer/NuPlayerDriver.h8
-rw-r--r--media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp232
-rw-r--r--media/libmediaplayerservice/nuplayer/NuPlayerRenderer.h33
6 files changed, 194 insertions, 225 deletions
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
index 1c73995..eb5821b 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
@@ -151,7 +151,6 @@ private:
NuPlayer::NuPlayer()
: mUIDValid(false),
mSourceFlags(0),
- mCurrentPositionUs(0),
mVideoIsAVC(false),
mOffloadAudio(false),
mCurrentOffloadInfo(AUDIO_INFO_INITIALIZER),
@@ -169,7 +168,6 @@ NuPlayer::NuPlayer()
mFlushingVideo(NONE),
mSkipRenderingAudioUntilMediaTimeUs(-1ll),
mSkipRenderingVideoUntilMediaTimeUs(-1ll),
- mVideoLateByUs(0ll),
mNumFramesTotal(0ll),
mNumFramesDropped(0ll),
mVideoScalingMode(NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW),
@@ -546,8 +544,11 @@ void NuPlayer::onMessageReceived(const sp<AMessage> &msg) {
// the extractor may not yet be started and will assert.
// If the video decoder is not set (perhaps audio only in this case)
// do not perform a seek as it is not needed.
- mDeferredActions.push_back(
- new SeekAction(mCurrentPositionUs, false /* needNotify */));
+ int64_t currentPositionUs = 0;
+ if (getCurrentPosition(&currentPositionUs) == OK) {
+ mDeferredActions.push_back(
+ new SeekAction(currentPositionUs, false /* needNotify */));
+ }
}
// If there is a new surface texture, instantiate decoders
@@ -581,7 +582,6 @@ void NuPlayer::onMessageReceived(const sp<AMessage> &msg) {
mVideoEOS = false;
mSkipRenderingAudioUntilMediaTimeUs = -1;
mSkipRenderingVideoUntilMediaTimeUs = -1;
- mVideoLateByUs = 0;
mNumFramesTotal = 0;
mNumFramesDropped = 0;
mStarted = true;
@@ -889,22 +889,6 @@ void NuPlayer::onMessageReceived(const sp<AMessage> &msg) {
&& (mVideoEOS || mVideoDecoder == NULL)) {
notifyListener(MEDIA_PLAYBACK_COMPLETE, 0, 0);
}
- } else if (what == Renderer::kWhatPosition) {
- int64_t positionUs;
- CHECK(msg->findInt64("positionUs", &positionUs));
- mCurrentPositionUs = positionUs;
-
- CHECK(msg->findInt64("videoLateByUs", &mVideoLateByUs));
-
- if (mDriver != NULL) {
- sp<NuPlayerDriver> driver = mDriver.promote();
- if (driver != NULL) {
- driver->notifyPosition(positionUs);
-
- driver->notifyFrameStats(
- mNumFramesTotal, mNumFramesDropped);
- }
- }
} else if (what == Renderer::kWhatFlushComplete) {
int32_t audio;
CHECK(msg->findInt32("audio", &audio));
@@ -1053,10 +1037,6 @@ void NuPlayer::handleFlushComplete(bool audio, bool isDecoder) {
case FLUSHING_DECODER:
{
*state = FLUSHED;
-
- if (!audio) {
- mVideoLateByUs = 0;
- }
break;
}
@@ -1066,7 +1046,6 @@ void NuPlayer::handleFlushComplete(bool audio, bool isDecoder) {
ALOGV("initiating %s decoder shutdown", audio ? "audio" : "video");
if (!audio) {
- mVideoLateByUs = 0;
// Widevine source reads must stop before releasing the video decoder.
if (mSource != NULL && mSourceFlags & Source::FLAG_SECURE) {
mSource->stop();
@@ -1487,7 +1466,7 @@ status_t NuPlayer::feedDecoderInputData(bool audio, const sp<AMessage> &msg) {
dropAccessUnit = false;
if (!audio
&& !(mSourceFlags & Source::FLAG_SECURE)
- && mVideoLateByUs > 100000ll
+ && mRenderer->getVideoLateByUs() > 100000ll
&& mVideoIsAVC
&& !IsAVCReferenceFrame(accessUnit)) {
dropAccessUnit = true;
@@ -1822,6 +1801,20 @@ status_t NuPlayer::selectTrack(size_t trackIndex, bool select) {
return err;
}
+status_t NuPlayer::getCurrentPosition(int64_t *mediaUs) {
+ sp<Renderer> renderer = mRenderer;
+ if (renderer == NULL) {
+ return NO_INIT;
+ }
+
+ return renderer->getCurrentPosition(mediaUs);
+}
+
+void NuPlayer::getStats(int64_t *numFramesTotal, int64_t *numFramesDropped) {
+ *numFramesTotal = mNumFramesTotal;
+ *numFramesDropped = mNumFramesDropped;
+}
+
sp<MetaData> NuPlayer::getFileMeta() {
return mSource->getFileFormatMeta();
}
@@ -1879,7 +1872,6 @@ void NuPlayer::performSeek(int64_t seekTimeUs, bool needNotify) {
if (mDriver != NULL) {
sp<NuPlayerDriver> driver = mDriver.promote();
if (driver != NULL) {
- driver->notifyPosition(seekTimeUs);
if (needNotify) {
driver->notifySeekComplete();
}
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayer.h b/media/libmediaplayerservice/nuplayer/NuPlayer.h
index 1b9a756..c61510c 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayer.h
+++ b/media/libmediaplayerservice/nuplayer/NuPlayer.h
@@ -67,6 +67,8 @@ struct NuPlayer : public AHandler {
status_t getTrackInfo(Parcel* reply) const;
status_t getSelectedTrack(int32_t type, Parcel* reply) const;
status_t selectTrack(size_t trackIndex, bool select);
+ status_t getCurrentPosition(int64_t *mediaUs);
+ void getStats(int64_t *mNumFramesTotal, int64_t *mNumFramesDropped);
sp<MetaData> getFileMeta();
@@ -126,7 +128,6 @@ private:
sp<Source> mSource;
uint32_t mSourceFlags;
sp<NativeWindowWrapper> mNativeWindow;
- int64_t mCurrentPositionUs;
sp<MediaPlayerBase::AudioSink> mAudioSink;
sp<Decoder> mVideoDecoder;
bool mVideoIsAVC;
@@ -179,7 +180,6 @@ private:
int64_t mSkipRenderingAudioUntilMediaTimeUs;
int64_t mSkipRenderingVideoUntilMediaTimeUs;
- int64_t mVideoLateByUs;
int64_t mNumFramesTotal, mNumFramesDropped;
int32_t mVideoScalingMode;
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp b/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp
index c57955d..6a80313 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp
@@ -26,6 +26,7 @@
#include <media/stagefright/foundation/ADebug.h>
#include <media/stagefright/foundation/ALooper.h>
+#include <media/stagefright/foundation/AUtils.h>
#include <media/stagefright/MetaData.h>
#include <media/stagefright/Utils.h>
@@ -38,10 +39,7 @@ NuPlayerDriver::NuPlayerDriver()
mSetSurfaceInProgress(false),
mDurationUs(-1),
mPositionUs(-1),
- mNotifyTimeRealUs(-1),
- mPauseStartedTimeUs(-1),
- mNumFramesTotal(0),
- mNumFramesDropped(0),
+ mSeekInProgress(false),
mLooper(new ALooper),
mPlayerFlags(0),
mAtEOS(false),
@@ -276,14 +274,6 @@ status_t NuPlayerDriver::start() {
mPositionUs = -1;
} else {
mPlayer->resume();
- if (mNotifyTimeRealUs != -1) {
- // Pause time must be set if here by setPauseStartedTimeIfNeeded().
- //CHECK(mPauseStartedTimeUs != -1);
-
- // if no seek occurs, adjust our notify time so that getCurrentPosition()
- // is continuous if read immediately after calling start().
- mNotifyTimeRealUs += ALooper::GetNowUs() - mPauseStartedTimeUs;
- }
}
break;
}
@@ -293,7 +283,6 @@ status_t NuPlayerDriver::start() {
}
mState = STATE_RUNNING;
- mPauseStartedTimeUs = -1;
return OK;
}
@@ -322,7 +311,6 @@ status_t NuPlayerDriver::stop() {
default:
return INVALID_OPERATION;
}
- setPauseStartedTimeIfNeeded();
return OK;
}
@@ -336,7 +324,6 @@ status_t NuPlayerDriver::pause() {
return OK;
case STATE_RUNNING:
- setPauseStartedTimeIfNeeded();
mState = STATE_PAUSED;
notifyListener_l(MEDIA_PAUSED);
mPlayer->pause();
@@ -374,6 +361,7 @@ status_t NuPlayerDriver::seekTo(int msec) {
case STATE_PAUSED:
{
mAtEOS = false;
+ mSeekInProgress = true;
// seeks can take a while, so we essentially paused
notifyListener_l(MEDIA_PAUSED);
mPlayer->seekToAsync(seekTimeUs, true /* needNotify */);
@@ -385,44 +373,23 @@ status_t NuPlayerDriver::seekTo(int msec) {
}
mPositionUs = seekTimeUs;
- mNotifyTimeRealUs = -1;
return OK;
}
status_t NuPlayerDriver::getCurrentPosition(int *msec) {
- Mutex::Autolock autoLock(mLock);
+ int64_t tempUs = 0;
+ status_t ret = mPlayer->getCurrentPosition(&tempUs);
- if (mPositionUs < 0) {
- // mPositionUs is the media time.
- // It is negative under these cases
- // (1) == -1 after reset, or very first playback, no stream notification yet.
- // (2) == -1 start after end of stream, no stream notification yet.
- // (3) == large negative # after ~292,471 years of continuous playback.
-
- //CHECK_EQ(mPositionUs, -1);
- *msec = 0;
- } else if (mNotifyTimeRealUs == -1) {
- // A seek has occurred just occurred, no stream notification yet.
- // mPositionUs (>= 0) is the new media position.
- *msec = mPositionUs / 1000;
+ Mutex::Autolock autoLock(mLock);
+ // We need to check mSeekInProgress here because mPlayer->seekToAsync is an async call, which
+ // means getCurrentPosition can be called before seek is completed. Iow, renderer may return a
+ // position value that's different the seek to position.
+ if (ret != OK || mSeekInProgress) {
+ tempUs = (mPositionUs <= 0) ? 0 : mPositionUs;
} else {
- // mPosition must be valid (i.e. >= 0) by the first check above.
- // We're either playing or have pause time set: mPauseStartedTimeUs is >= 0
- //LOG_ALWAYS_FATAL_IF(
- // !isPlaying() && mPauseStartedTimeUs < 0,
- // "Player in non-playing mState(%d) and mPauseStartedTimeUs(%lld) < 0",
- // mState, (long long)mPauseStartedTimeUs);
- ALOG_ASSERT(mNotifyTimeRealUs >= 0);
- int64_t nowUs =
- (isPlaying() ? ALooper::GetNowUs() : mPauseStartedTimeUs);
- *msec = (mPositionUs + nowUs - mNotifyTimeRealUs + 500ll) / 1000;
- // It is possible for *msec to be negative if the media position is > 596 hours.
- // but we turn on this checking in NDEBUG == 0 mode.
- ALOG_ASSERT(*msec >= 0);
- ALOGV("getCurrentPosition nowUs(%lld)", (long long)nowUs);
+ mPositionUs = tempUs;
}
- ALOGV("getCurrentPosition returning(%d) mPositionUs(%lld) mNotifyRealTimeUs(%lld)",
- *msec, (long long)mPositionUs, (long long)mNotifyTimeRealUs);
+ *msec = (int)divRound(tempUs, (int64_t)(1000));
return OK;
}
@@ -605,17 +572,10 @@ void NuPlayerDriver::notifyDuration(int64_t durationUs) {
mDurationUs = durationUs;
}
-void NuPlayerDriver::notifyPosition(int64_t positionUs) {
- Mutex::Autolock autoLock(mLock);
- if (isPlaying()) {
- mPositionUs = positionUs;
- mNotifyTimeRealUs = ALooper::GetNowUs();
- }
-}
-
void NuPlayerDriver::notifySeekComplete() {
ALOGV("notifySeekComplete(%p)", this);
Mutex::Autolock autoLock(mLock);
+ mSeekInProgress = false;
notifySeekComplete_l();
}
@@ -636,26 +596,21 @@ void NuPlayerDriver::notifySeekComplete_l() {
notifyListener_l(wasSeeking ? MEDIA_SEEK_COMPLETE : MEDIA_PREPARED);
}
-void NuPlayerDriver::notifyFrameStats(
- int64_t numFramesTotal, int64_t numFramesDropped) {
- Mutex::Autolock autoLock(mLock);
- mNumFramesTotal = numFramesTotal;
- mNumFramesDropped = numFramesDropped;
-}
-
status_t NuPlayerDriver::dump(
int fd, const Vector<String16> & /* args */) const {
- Mutex::Autolock autoLock(mLock);
+ int64_t numFramesTotal;
+ int64_t numFramesDropped;
+ mPlayer->getStats(&numFramesTotal, &numFramesDropped);
FILE *out = fdopen(dup(fd), "w");
fprintf(out, " NuPlayer\n");
fprintf(out, " numFramesTotal(%" PRId64 "), numFramesDropped(%" PRId64 "), "
"percentageDropped(%.2f)\n",
- mNumFramesTotal,
- mNumFramesDropped,
- mNumFramesTotal == 0
- ? 0.0 : (double)mNumFramesDropped / mNumFramesTotal);
+ numFramesTotal,
+ numFramesDropped,
+ numFramesTotal == 0
+ ? 0.0 : (double)numFramesDropped / numFramesTotal);
fclose(out);
out = NULL;
@@ -690,7 +645,6 @@ void NuPlayerDriver::notifyListener_l(
case MEDIA_ERROR:
{
mAtEOS = true;
- setPauseStartedTimeIfNeeded();
break;
}
@@ -758,10 +712,4 @@ void NuPlayerDriver::notifyFlagsChanged(uint32_t flags) {
mPlayerFlags = flags;
}
-void NuPlayerDriver::setPauseStartedTimeIfNeeded() {
- if (mPauseStartedTimeUs == -1) {
- mPauseStartedTimeUs = ALooper::GetNowUs();
- }
-}
-
} // namespace android
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerDriver.h b/media/libmediaplayerservice/nuplayer/NuPlayerDriver.h
index f2bd431..5cba7d9 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerDriver.h
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerDriver.h
@@ -68,10 +68,8 @@ struct NuPlayerDriver : public MediaPlayerInterface {
void notifyResetComplete();
void notifySetSurfaceComplete();
void notifyDuration(int64_t durationUs);
- void notifyPosition(int64_t positionUs);
void notifySeekComplete();
void notifySeekComplete_l();
- void notifyFrameStats(int64_t numFramesTotal, int64_t numFramesDropped);
void notifyListener(int msg, int ext1 = 0, int ext2 = 0, const Parcel *in = NULL);
void notifyFlagsChanged(uint32_t flags);
@@ -106,10 +104,7 @@ private:
bool mSetSurfaceInProgress;
int64_t mDurationUs;
int64_t mPositionUs;
- int64_t mNotifyTimeRealUs;
- int64_t mPauseStartedTimeUs;
- int64_t mNumFramesTotal;
- int64_t mNumFramesDropped;
+ bool mSeekInProgress;
// <<<
sp<ALooper> mLooper;
@@ -125,7 +120,6 @@ private:
status_t prepare_l();
void notifyListener_l(int msg, int ext1 = 0, int ext2 = 0, const Parcel *in = NULL);
- void setPauseStartedTimeIfNeeded();
DISALLOW_EVIL_CONSTRUCTORS(NuPlayerDriver);
};
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp b/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp
index e5c64f6..7b9dbb7 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp
@@ -25,6 +25,7 @@
#include <media/stagefright/foundation/ABuffer.h>
#include <media/stagefright/foundation/ADebug.h>
#include <media/stagefright/foundation/AMessage.h>
+#include <media/stagefright/foundation/AUtils.h>
#include <media/stagefright/MediaErrors.h>
#include <media/stagefright/MetaData.h>
@@ -63,22 +64,21 @@ NuPlayer::Renderer::Renderer(
mDrainVideoQueuePending(false),
mAudioQueueGeneration(0),
mVideoQueueGeneration(0),
- mFirstAnchorTimeMediaUs(-1),
- mAnchorTimeMediaUs(-1),
- mAnchorTimeRealUs(-1),
- mFlushingAudio(false),
- mFlushingVideo(false),
+ mAudioFirstAnchorTimeMediaUs(-1),
+ mVideoAnchorTimeMediaUs(-1),
+ mVideoAnchorTimeRealUs(-1),
+ mVideoLateByUs(0ll),
mHasAudio(false),
mHasVideo(false),
+ mPauseStartedTimeRealUs(-1),
+ mFlushingAudio(false),
+ mFlushingVideo(false),
mSyncQueues(false),
mPaused(false),
- mPauseStartedTimeRealUs(-1),
mVideoSampleReceived(false),
mVideoRenderingStarted(false),
mVideoRenderingStartGeneration(0),
mAudioRenderingStartGeneration(0),
- mLastPositionUpdateUs(-1ll),
- mVideoLateByUs(0ll),
mAudioOffloadPauseTimeoutGeneration(0),
mAudioOffloadTornDown(false) {
readProperties();
@@ -137,9 +137,9 @@ void NuPlayer::Renderer::signalTimeDiscontinuity() {
Mutex::Autolock autoLock(mLock);
// CHECK(mAudioQueue.empty());
// CHECK(mVideoQueue.empty());
- mFirstAnchorTimeMediaUs = -1;
- mAnchorTimeMediaUs = -1;
- mAnchorTimeRealUs = -1;
+ setAudioFirstAnchorTime(-1);
+ setVideoAnchorTime(-1, -1);
+ setVideoLateByUs(0);
mSyncQueues = false;
}
@@ -165,6 +165,78 @@ void NuPlayer::Renderer::setVideoFrameRate(float fps) {
msg->post();
}
+status_t NuPlayer::Renderer::getCurrentPosition(int64_t *mediaUs) {
+ return getCurrentPosition(mediaUs, ALooper::GetNowUs());
+}
+
+status_t NuPlayer::Renderer::getCurrentPosition(int64_t *mediaUs, int64_t nowUs) {
+ Mutex::Autolock autoLock(mTimeLock);
+ if (!mHasAudio && !mHasVideo) {
+ return NO_INIT;
+ }
+
+ int64_t positionUs = 0;
+ if (!mHasAudio) {
+ if (mVideoAnchorTimeMediaUs < 0) {
+ return NO_INIT;
+ }
+ positionUs = (nowUs - mVideoAnchorTimeRealUs) + mVideoAnchorTimeMediaUs;
+
+ if (mPauseStartedTimeRealUs != -1) {
+ positionUs -= (nowUs - mPauseStartedTimeRealUs);
+ }
+ } else {
+ if (mAudioFirstAnchorTimeMediaUs < 0) {
+ return NO_INIT;
+ }
+ positionUs = mAudioFirstAnchorTimeMediaUs + getPlayedOutAudioDurationUs(nowUs);
+ }
+ *mediaUs = (positionUs <= 0) ? 0 : positionUs;
+ return OK;
+}
+
+void NuPlayer::Renderer::setHasMedia(bool audio) {
+ Mutex::Autolock autoLock(mTimeLock);
+ if (audio) {
+ mHasAudio = true;
+ } else {
+ mHasVideo = true;
+ }
+}
+
+void NuPlayer::Renderer::setAudioFirstAnchorTime(int64_t mediaUs) {
+ Mutex::Autolock autoLock(mTimeLock);
+ mAudioFirstAnchorTimeMediaUs = mediaUs;
+}
+
+void NuPlayer::Renderer::setAudioFirstAnchorTimeIfNeeded(int64_t mediaUs) {
+ Mutex::Autolock autoLock(mTimeLock);
+ if (mAudioFirstAnchorTimeMediaUs == -1) {
+ mAudioFirstAnchorTimeMediaUs = mediaUs;
+ }
+}
+
+void NuPlayer::Renderer::setVideoAnchorTime(int64_t mediaUs, int64_t realUs) {
+ Mutex::Autolock autoLock(mTimeLock);
+ mVideoAnchorTimeMediaUs = mediaUs;
+ mVideoAnchorTimeRealUs = realUs;
+}
+
+void NuPlayer::Renderer::setVideoLateByUs(int64_t lateUs) {
+ Mutex::Autolock autoLock(mTimeLock);
+ mVideoLateByUs = lateUs;
+}
+
+int64_t NuPlayer::Renderer::getVideoLateByUs() {
+ Mutex::Autolock autoLock(mTimeLock);
+ return mVideoLateByUs;
+}
+
+void NuPlayer::Renderer::setPauseStartedTimeRealUs(int64_t realUs) {
+ Mutex::Autolock autoLock(mTimeLock);
+ mPauseStartedTimeRealUs = realUs;
+}
+
void NuPlayer::Renderer::onMessageReceived(const sp<AMessage> &msg) {
switch (msg->what()) {
case kWhatStopAudioSink:
@@ -388,16 +460,7 @@ size_t NuPlayer::Renderer::fillAudioBuffer(void *buffer, size_t size) {
int64_t mediaTimeUs;
CHECK(entry->mBuffer->meta()->findInt64("timeUs", &mediaTimeUs));
ALOGV("rendering audio at media time %.2f secs", mediaTimeUs / 1E6);
- if (mFirstAnchorTimeMediaUs == -1) {
- mFirstAnchorTimeMediaUs = mediaTimeUs;
- }
-
- int64_t nowUs = ALooper::GetNowUs();
- mAnchorTimeMediaUs =
- mFirstAnchorTimeMediaUs + getPlayedOutAudioDurationUs(nowUs);
- mAnchorTimeRealUs = nowUs;
-
- notifyPosition();
+ setAudioFirstAnchorTimeIfNeeded(mediaTimeUs);
}
size_t copy = entry->mBuffer->size() - entry->mOffset;
@@ -468,15 +531,8 @@ bool NuPlayer::Renderer::onDrainAudioQueue() {
int64_t mediaTimeUs;
CHECK(entry->mBuffer->meta()->findInt64("timeUs", &mediaTimeUs));
ALOGV("rendering audio at media time %.2f secs", mediaTimeUs / 1E6);
- if (mFirstAnchorTimeMediaUs == -1) {
- mFirstAnchorTimeMediaUs = mediaTimeUs;
- }
- mAnchorTimeMediaUs = mediaTimeUs;
-
- int64_t nowUs = ALooper::GetNowUs();
- mAnchorTimeRealUs = nowUs + getPendingAudioPlayoutDurationUs(nowUs);
- notifyPosition();
+ setAudioFirstAnchorTimeIfNeeded(mediaTimeUs);
}
size_t copy = entry->mBuffer->size() - entry->mOffset;
@@ -534,6 +590,14 @@ int64_t NuPlayer::Renderer::getPendingAudioPlayoutDurationUs(int64_t nowUs) {
return writtenAudioDurationUs - getPlayedOutAudioDurationUs(nowUs);
}
+int64_t NuPlayer::Renderer::getRealTimeUs(int64_t mediaTimeUs, int64_t nowUs) {
+ int64_t currentPositionUs;
+ if (getCurrentPosition(&currentPositionUs, nowUs) != OK) {
+ currentPositionUs = 0;
+ }
+ return (mediaTimeUs - currentPositionUs) + nowUs;
+}
+
void NuPlayer::Renderer::postDrainVideoQueue() {
if (mDrainVideoQueuePending
|| mSyncQueues
@@ -568,21 +632,11 @@ void NuPlayer::Renderer::postDrainVideoQueue() {
int64_t mediaTimeUs;
CHECK(entry.mBuffer->meta()->findInt64("timeUs", &mediaTimeUs));
- if (mFirstAnchorTimeMediaUs == -1 && !mHasAudio) {
- mFirstAnchorTimeMediaUs = mediaTimeUs;
- }
- if (mAnchorTimeMediaUs < 0) {
- if (!mHasAudio) {
- mAnchorTimeMediaUs = mediaTimeUs;
- mAnchorTimeRealUs = nowUs;
- if (!mPaused || mVideoSampleReceived) {
- notifyPosition();
- }
- }
+ if (mVideoAnchorTimeMediaUs < 0) {
+ setVideoAnchorTime(mediaTimeUs, nowUs);
realTimeUs = nowUs;
} else {
- realTimeUs =
- (mediaTimeUs - mAnchorTimeMediaUs) + mAnchorTimeRealUs;
+ realTimeUs = getRealTimeUs(mediaTimeUs, nowUs);
}
}
@@ -618,10 +672,11 @@ void NuPlayer::Renderer::onDrainVideoQueue() {
mVideoQueue.erase(mVideoQueue.begin());
entry = NULL;
- mVideoLateByUs = 0ll;
+ setVideoLateByUs(0);
return;
}
+ int64_t nowUs = -1;
int64_t realTimeUs;
if (mFlags & FLAG_REAL_TIME) {
CHECK(entry->mBuffer->meta()->findInt64("timeUs", &realTimeUs));
@@ -629,13 +684,17 @@ void NuPlayer::Renderer::onDrainVideoQueue() {
int64_t mediaTimeUs;
CHECK(entry->mBuffer->meta()->findInt64("timeUs", &mediaTimeUs));
- realTimeUs = mediaTimeUs - mAnchorTimeMediaUs + mAnchorTimeRealUs;
+ nowUs = ALooper::GetNowUs();
+ realTimeUs = getRealTimeUs(mediaTimeUs, nowUs);
}
bool tooLate = false;
if (!mPaused) {
- mVideoLateByUs = ALooper::GetNowUs() - realTimeUs;
+ if (nowUs == -1) {
+ nowUs = ALooper::GetNowUs();
+ }
+ setVideoLateByUs(nowUs - realTimeUs);
tooLate = (mVideoLateByUs > 40000);
if (tooLate) {
@@ -644,13 +703,14 @@ void NuPlayer::Renderer::onDrainVideoQueue() {
} else {
ALOGV("rendering video at media time %.2f secs",
(mFlags & FLAG_REAL_TIME ? realTimeUs :
- (realTimeUs + mAnchorTimeMediaUs - mAnchorTimeRealUs)) / 1E6);
+ (realTimeUs + mVideoAnchorTimeMediaUs - mVideoAnchorTimeRealUs)) / 1E6);
}
} else {
- mVideoLateByUs = 0ll;
- if (!mHasAudio && !mVideoSampleReceived) {
- mAnchorTimeMediaUs = -1;
- mAnchorTimeRealUs = -1;
+ setVideoLateByUs(0);
+ if (!mVideoSampleReceived) {
+ // This will ensure that the first frame after a flush won't be used as anchor
+ // when renderer is in paused state, because resume can happen any time after seek.
+ setVideoAnchorTime(-1, -1);
}
}
@@ -693,10 +753,9 @@ void NuPlayer::Renderer::onQueueBuffer(const sp<AMessage> &msg) {
int32_t audio;
CHECK(msg->findInt32("audio", &audio));
- if (audio) {
- mHasAudio = true;
- } else {
- mHasVideo = true;
+ setHasMedia(audio);
+
+ if (mHasVideo) {
if (mVideoScheduler == NULL) {
mVideoScheduler = new VideoFrameScheduler();
mVideoScheduler->init();
@@ -837,9 +896,7 @@ void NuPlayer::Renderer::onFlush(const sp<AMessage> &msg) {
{
Mutex::Autolock autoLock(mLock);
syncQueuesDone_l();
- if (!mHasAudio) {
- mPauseStartedTimeRealUs = -1;
- }
+ setPauseStartedTimeRealUs(-1);
}
ALOGV("flushing %s", audio ? "audio" : "video");
@@ -852,7 +909,7 @@ void NuPlayer::Renderer::onFlush(const sp<AMessage> &msg) {
prepareForMediaRenderingStart();
if (offloadingAudio()) {
- mFirstAnchorTimeMediaUs = -1;
+ setAudioFirstAnchorTime(-1);
}
}
@@ -943,42 +1000,6 @@ void NuPlayer::Renderer::onDisableOffloadAudio() {
++mAudioQueueGeneration;
}
-void NuPlayer::Renderer::notifyPosition() {
- // notifyPosition() must be called only after setting mAnchorTimeRealUs
- // and mAnchorTimeMediaUs, and must not be paused as it extrapolates position.
- //CHECK_GE(mAnchorTimeRealUs, 0);
- //CHECK_GE(mAnchorTimeMediaUs, 0);
- //CHECK(!mPaused || !mHasAudio); // video-only does display in paused mode.
-
- int64_t nowUs = ALooper::GetNowUs();
-
- if (mLastPositionUpdateUs >= 0
- && nowUs < mLastPositionUpdateUs + kMinPositionUpdateDelayUs) {
- return;
- }
- mLastPositionUpdateUs = nowUs;
-
- int64_t positionUs = (nowUs - mAnchorTimeRealUs) + mAnchorTimeMediaUs;
-
- //ALOGD("notifyPosition: positionUs(%lld) nowUs(%lld) mAnchorTimeRealUs(%lld)"
- // " mAnchorTimeMediaUs(%lld) mFirstAnchorTimeMediaUs(%lld)",
- // (long long)positionUs, (long long)nowUs, (long long)mAnchorTimeRealUs,
- // (long long)mAnchorTimeMediaUs, (long long)mFirstAnchorTimeMediaUs);
-
- // Due to adding the latency to mAnchorTimeRealUs in onDrainAudioQueue(),
- // positionUs may be less than the first media time. This is avoided
- // here to prevent potential retrograde motion of the position bar
- // when starting up after a seek.
- if (positionUs < mFirstAnchorTimeMediaUs) {
- positionUs = mFirstAnchorTimeMediaUs;
- }
- sp<AMessage> notify = mNotify->dup();
- notify->setInt32("what", kWhatPosition);
- notify->setInt64("positionUs", positionUs);
- notify->setInt64("videoLateByUs", mVideoLateByUs);
- notify->post();
-}
-
void NuPlayer::Renderer::onPause() {
if (mPaused) {
ALOGW("Renderer::onPause() called while already paused!");
@@ -990,9 +1011,7 @@ void NuPlayer::Renderer::onPause() {
++mVideoQueueGeneration;
prepareForMediaRenderingStart();
mPaused = true;
- if (!mHasAudio) {
- mPauseStartedTimeRealUs = ALooper::GetNowUs();
- }
+ setPauseStartedTimeRealUs(ALooper::GetNowUs());
}
mDrainAudioQueuePending = false;
@@ -1021,9 +1040,11 @@ void NuPlayer::Renderer::onResume() {
Mutex::Autolock autoLock(mLock);
mPaused = false;
- if (!mHasAudio && mPauseStartedTimeRealUs != -1) {
- mAnchorTimeRealUs += ALooper::GetNowUs() - mPauseStartedTimeRealUs;
- mPauseStartedTimeRealUs = -1;
+ if (mPauseStartedTimeRealUs != -1) {
+ int64_t newAnchorRealUs =
+ mVideoAnchorTimeRealUs + ALooper::GetNowUs() - mPauseStartedTimeRealUs;
+ setVideoAnchorTime(mVideoAnchorTimeMediaUs, newAnchorRealUs);
+ setPauseStartedTimeRealUs(-1);
}
if (!mAudioQueue.empty()) {
@@ -1045,7 +1066,6 @@ void NuPlayer::Renderer::onSetVideoFrameRate(float fps) {
// TODO: Remove unnecessary calls to getPlayedOutAudioDurationUs()
// as it acquires locks and may query the audio driver.
//
-// Some calls are not needed since notifyPosition() doesn't always deliver a message.
// Some calls could conceivably retrieve extrapolated data instead of
// accessing getTimestamp() or getPosition() every time a data buffer with
// a media time is received.
@@ -1113,15 +1133,11 @@ void NuPlayer::Renderer::onAudioOffloadTearDown(AudioOffloadTearDownReason reaso
}
mAudioOffloadTornDown = true;
- int64_t firstAudioTimeUs;
- {
- Mutex::Autolock autoLock(mLock);
- firstAudioTimeUs = mFirstAnchorTimeMediaUs;
+ int64_t currentPositionUs;
+ if (getCurrentPosition(&currentPositionUs) != OK) {
+ currentPositionUs = 0;
}
- int64_t currentPositionUs =
- firstAudioTimeUs + getPlayedOutAudioDurationUs(ALooper::GetNowUs());
-
mAudioSink->stop();
mAudioSink->flush();
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.h b/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.h
index d27c238..db1dab6 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.h
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.h
@@ -59,6 +59,17 @@ struct NuPlayer::Renderer : public AHandler {
void setVideoFrameRate(float fps);
+ // Following setters and getters are protected by mTimeLock.
+ status_t getCurrentPosition(int64_t *mediaUs);
+ status_t getCurrentPosition(int64_t *mediaUs, int64_t nowUs);
+ void setHasMedia(bool audio);
+ void setAudioFirstAnchorTime(int64_t mediaUs);
+ void setAudioFirstAnchorTimeIfNeeded(int64_t mediaUs);
+ void setVideoAnchorTime(int64_t mediaUs, int64_t realUs);
+ void setVideoLateByUs(int64_t lateUs);
+ int64_t getVideoLateByUs();
+ void setPauseStartedTimeRealUs(int64_t realUs);
+
enum {
kWhatEOS = 'eos ',
kWhatFlushComplete = 'fluC',
@@ -117,27 +128,33 @@ private:
int32_t mAudioQueueGeneration;
int32_t mVideoQueueGeneration;
- int64_t mFirstAnchorTimeMediaUs;
- int64_t mAnchorTimeMediaUs;
- int64_t mAnchorTimeRealUs;
+ Mutex mTimeLock;
+ // |mTimeLock| protects the following 7 member vars that are related to time.
+ // Note: those members are only written on Renderer thread, so reading on Renderer thread
+ // doesn't need to be protected. Otherwise accessing those members must be protected by
+ // |mTimeLock|.
+ // TODO: move those members to a seperated media clock class.
+ int64_t mAudioFirstAnchorTimeMediaUs;
+ int64_t mVideoAnchorTimeMediaUs;
+ int64_t mVideoAnchorTimeRealUs;
+ int64_t mVideoLateByUs;
+ bool mHasAudio;
+ bool mHasVideo;
+ int64_t mPauseStartedTimeRealUs;
Mutex mFlushLock; // protects the following 2 member vars.
bool mFlushingAudio;
bool mFlushingVideo;
- bool mHasAudio;
- bool mHasVideo;
bool mSyncQueues;
bool mPaused;
- int64_t mPauseStartedTimeRealUs;
bool mVideoSampleReceived;
bool mVideoRenderingStarted;
int32_t mVideoRenderingStartGeneration;
int32_t mAudioRenderingStartGeneration;
int64_t mLastPositionUpdateUs;
- int64_t mVideoLateByUs;
int32_t mAudioOffloadPauseTimeoutGeneration;
bool mAudioOffloadTornDown;
@@ -149,6 +166,8 @@ private:
int64_t getPlayedOutAudioDurationUs(int64_t nowUs);
void postDrainAudioQueue_l(int64_t delayUs = 0);
+ int64_t getRealTimeUs(int64_t mediaTimeUs, int64_t nowUs);
+
void onDrainVideoQueue();
void postDrainVideoQueue();