Merge "MediaSync: fix the optimization code path to reduce messages posted to drain video."
diff --git a/media/libstagefright/MediaSync.cpp b/media/libstagefright/MediaSync.cpp
index ec956c4..9c37a3d 100644
--- a/media/libstagefright/MediaSync.cpp
+++ b/media/libstagefright/MediaSync.cpp
@@ -195,13 +195,14 @@
     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 +213,13 @@
 
     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 +318,12 @@
         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 +343,13 @@
             }
 
             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 +395,9 @@
     }
 
     mBufferItems.push_back(bufferItem);
-    onDrainVideo_l();
+    if (mBufferItems.size() == 1) {
+        onDrainVideo_l();
+    }
 }
 
 void MediaSync::renderOneBufferItem_l( const BufferItem &bufferItem) {
@@ -499,6 +501,20 @@
         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;
         }