summaryrefslogtreecommitdiffstats
path: root/media
diff options
context:
space:
mode:
Diffstat (limited to 'media')
-rw-r--r--media/libstagefright/MediaSync.cpp78
1 files changed, 65 insertions, 13 deletions
diff --git a/media/libstagefright/MediaSync.cpp b/media/libstagefright/MediaSync.cpp
index ec956c4..8030a36 100644
--- a/media/libstagefright/MediaSync.cpp
+++ b/media/libstagefright/MediaSync.cpp
@@ -179,6 +179,42 @@ sp<const MediaClock> MediaSync::getMediaClock() {
return mMediaClock;
}
+status_t MediaSync::getPlayTimeForPendingAudioFrames(int64_t *outTimeUs) {
+ Mutex::Autolock lock(mMutex);
+ // User should check the playback rate if it doesn't want to receive a
+ // huge number for play time.
+ if (mPlaybackRate == 0.0f) {
+ *outTimeUs = INT64_MAX;
+ return OK;
+ }
+
+ uint32_t numFramesPlayed = 0;
+ if (mAudioTrack != NULL) {
+ status_t res = mAudioTrack->getPosition(&numFramesPlayed);
+ if (res != OK) {
+ return res;
+ }
+ }
+
+ int64_t numPendingFrames = mNumFramesWritten - numFramesPlayed;
+ if (numPendingFrames < 0) {
+ numPendingFrames = 0;
+ ALOGW("getPlayTimeForPendingAudioFrames: pending frame count is negative.");
+ }
+ double timeUs = numPendingFrames * 1000000.0
+ / (mNativeSampleRateInHz * (double)mPlaybackRate);
+ if (timeUs > (double)INT64_MAX) {
+ // Overflow.
+ *outTimeUs = INT64_MAX;
+ ALOGW("getPlayTimeForPendingAudioFrames: play time for pending audio frames "
+ "is too high, possibly due to super low playback rate(%f)", mPlaybackRate);
+ } else {
+ *outTimeUs = (int64_t)timeUs;
+ }
+
+ return OK;
+}
+
status_t MediaSync::updateQueuedAudioData(
size_t sizeInBytes, int64_t presentationTimeUs) {
if (sizeInBytes == 0) {
@@ -195,13 +231,14 @@ status_t MediaSync::updateQueuedAudioData(
int64_t numFrames = sizeInBytes / mAudioTrack->frameSize();
int64_t maxMediaTimeUs = presentationTimeUs
+ getDurationIfPlayedAtNativeSampleRate_l(numFrames);
- mNumFramesWritten += numFrames;
int64_t nowUs = ALooper::GetNowUs();
- int64_t nowMediaUs = maxMediaTimeUs
+ int64_t nowMediaUs = presentationTimeUs
- getDurationIfPlayedAtNativeSampleRate_l(mNumFramesWritten)
+ getPlayedOutAudioDurationMedia_l(nowUs);
+ mNumFramesWritten += numFrames;
+
int64_t oldRealTime = -1;
if (mNextBufferItemMediaUs != -1) {
oldRealTime = getRealTime(mNextBufferItemMediaUs, nowUs);
@@ -212,12 +249,13 @@ status_t MediaSync::updateQueuedAudioData(
if (oldRealTime != -1) {
int64_t newRealTime = getRealTime(mNextBufferItemMediaUs, nowUs);
- if (newRealTime < oldRealTime) {
- mNextBufferItemMediaUs = -1;
- onDrainVideo_l();
+ if (newRealTime >= oldRealTime) {
+ return OK;
}
}
+ mNextBufferItemMediaUs = -1;
+ onDrainVideo_l();
return OK;
}
@@ -316,12 +354,12 @@ void MediaSync::onDrainVideo_l() {
return;
}
- int64_t nowUs = ALooper::GetNowUs();
-
while (!mBufferItems.empty()) {
+ int64_t nowUs = ALooper::GetNowUs();
BufferItem *bufferItem = &*mBufferItems.begin();
int64_t itemMediaUs = bufferItem->mTimestamp / 1000;
int64_t itemRealUs = getRealTime(itemMediaUs, nowUs);
+
if (itemRealUs <= nowUs) {
if (mHasAudio) {
if (nowUs - itemRealUs <= kMaxAllowedVideoLateTimeUs) {
@@ -341,15 +379,13 @@ void MediaSync::onDrainVideo_l() {
}
mBufferItems.erase(mBufferItems.begin());
-
- if (mBufferItems.empty()) {
- mNextBufferItemMediaUs = -1;
- }
+ mNextBufferItemMediaUs = -1;
} else {
if (mNextBufferItemMediaUs == -1
- || mNextBufferItemMediaUs != itemMediaUs) {
+ || mNextBufferItemMediaUs > itemMediaUs) {
sp<AMessage> msg = new AMessage(kWhatDrainVideo, this);
msg->post(itemRealUs - nowUs);
+ mNextBufferItemMediaUs = itemMediaUs;
}
break;
}
@@ -395,7 +431,9 @@ void MediaSync::onFrameAvailableFromInput() {
}
mBufferItems.push_back(bufferItem);
- onDrainVideo_l();
+ if (mBufferItems.size() == 1) {
+ onDrainVideo_l();
+ }
}
void MediaSync::renderOneBufferItem_l( const BufferItem &bufferItem) {
@@ -499,6 +537,20 @@ void MediaSync::onMessageReceived(const sp<AMessage> &msg) {
case kWhatDrainVideo:
{
Mutex::Autolock lock(mMutex);
+ if (mNextBufferItemMediaUs != -1) {
+ int64_t nowUs = ALooper::GetNowUs();
+ int64_t itemRealUs = getRealTime(mNextBufferItemMediaUs, nowUs);
+
+ // The message could arrive earlier than expected due to
+ // various reasons, e.g., media clock has been changed because
+ // of new anchor time or playback rate. In such cases, the
+ // message needs to be re-posted.
+ if (itemRealUs > nowUs) {
+ msg->post(itemRealUs - nowUs);
+ break;
+ }
+ }
+
onDrainVideo_l();
break;
}