mediaplayer: optimize buffer queue management

Various changes for power consumption including:
    Restrict the number of messages in flight.
    Buffer more frames in the GenericSource so reads occur in a burst.

Bug: 15094301
Change-Id: I783481fd91f3fdd445b95e88ab82178f649f1a38
Signed-off-by: Phil Burk <philburk@google.com>
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
index df3e992..9020a8d 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
@@ -50,6 +50,10 @@
 
 namespace android {
 
+// TODO optimize buffer size for power consumption
+// The offload read buffer size is 32 KB but 24 KB uses less power.
+const size_t NuPlayer::kAggregateBufferSizeBytes = 24 * 1024;
+
 struct NuPlayer::Action : public RefBase {
     Action() {}
 
@@ -730,7 +734,7 @@
 
                 if (err == -EWOULDBLOCK) {
                     if (mSource->feedMoreTSData() == OK) {
-                        msg->post(10000ll);
+                        msg->post(10 * 1000ll);
                     }
                 }
             } else if (what == Decoder::kWhatEOS) {
@@ -995,6 +999,7 @@
     ALOGV("both audio and video are flushed now.");
 
     mPendingAudioAccessUnit.clear();
+    mAggregateBuffer.clear();
 
     if (mTimeDiscontinuityPending) {
         mRenderer->signalTimeDiscontinuity();
@@ -1256,14 +1261,8 @@
     // Aggregate smaller buffers into a larger buffer.
     // The goal is to reduce power consumption.
     // Unfortunately this does not work with the software AAC decoder.
-    // TODO optimize buffer size for power consumption
-    // The offload read buffer size is 32 KB but 24 KB uses less power.
-    const int kAudioBigBufferSizeBytes = 24 * 1024;
-    bool doBufferAggregation = (audio && mOffloadAudio);
-    sp<ABuffer> biggerBuffer;
+    bool doBufferAggregation = (audio && mOffloadAudio);;
     bool needMoreData = false;
-    int numSmallBuffers = 0;
-    bool gotTime = false;
 
     bool dropAccessUnit;
     do {
@@ -1279,14 +1278,10 @@
         }
 
         if (err == -EWOULDBLOCK) {
-            if (biggerBuffer == NULL) {
-                return err;
-            } else {
-                break; // Reply with data that we already have.
-            }
+            return err;
         } else if (err != OK) {
             if (err == INFO_DISCONTINUITY) {
-                if (biggerBuffer != NULL) {
+                if (mAggregateBuffer != NULL) {
                     // We already have some data so save this for later.
                     mPendingAudioErr = err;
                     mPendingAudioAccessUnit = accessUnit;
@@ -1401,46 +1396,45 @@
 
         size_t smallSize = accessUnit->size();
         needMoreData = false;
-        if (doBufferAggregation && (biggerBuffer == NULL)
+        if (doBufferAggregation && (mAggregateBuffer == NULL)
                 // Don't bother if only room for a few small buffers.
-                && (smallSize < (kAudioBigBufferSizeBytes / 3))) {
+                && (smallSize < (kAggregateBufferSizeBytes / 3))) {
             // Create a larger buffer for combining smaller buffers from the extractor.
-            biggerBuffer = new ABuffer(kAudioBigBufferSizeBytes);
-            biggerBuffer->setRange(0, 0); // start empty
+            mAggregateBuffer = new ABuffer(kAggregateBufferSizeBytes);
+            mAggregateBuffer->setRange(0, 0); // start empty
         }
 
-        if (biggerBuffer != NULL) {
+        if (mAggregateBuffer != NULL) {
             int64_t timeUs;
+            int64_t dummy;
             bool smallTimestampValid = accessUnit->meta()->findInt64("timeUs", &timeUs);
+            bool bigTimestampValid = mAggregateBuffer->meta()->findInt64("timeUs", &dummy);
             // Will the smaller buffer fit?
-            size_t bigSize = biggerBuffer->size();
-            size_t roomLeft = biggerBuffer->capacity() - bigSize;
+            size_t bigSize = mAggregateBuffer->size();
+            size_t roomLeft = mAggregateBuffer->capacity() - bigSize;
             // Should we save this small buffer for the next big buffer?
             // If the first small buffer did not have a timestamp then save
             // any buffer that does have a timestamp until the next big buffer.
             if ((smallSize > roomLeft)
-                || (!gotTime && (numSmallBuffers > 0) && smallTimestampValid)) {
+                || (!bigTimestampValid && (bigSize > 0) && smallTimestampValid)) {
                 mPendingAudioErr = err;
                 mPendingAudioAccessUnit = accessUnit;
                 accessUnit.clear();
             } else {
+                // Grab time from first small buffer if available.
+                if ((bigSize == 0) && smallTimestampValid) {
+                    mAggregateBuffer->meta()->setInt64("timeUs", timeUs);
+                }
                 // Append small buffer to the bigger buffer.
-                memcpy(biggerBuffer->base() + bigSize, accessUnit->data(), smallSize);
+                memcpy(mAggregateBuffer->base() + bigSize, accessUnit->data(), smallSize);
                 bigSize += smallSize;
-                biggerBuffer->setRange(0, bigSize);
+                mAggregateBuffer->setRange(0, bigSize);
 
-                // Keep looping until we run out of room in the biggerBuffer.
+                // Keep looping until we run out of room in the mAggregateBuffer.
                 needMoreData = true;
 
-                // Grab time from first small buffer if available.
-                if ((numSmallBuffers == 0) && smallTimestampValid) {
-                    biggerBuffer->meta()->setInt64("timeUs", timeUs);
-                    gotTime = true;
-                }
-
-                ALOGV("feedDecoderInputData() #%d, smallSize = %zu, bigSize = %zu, capacity = %zu",
-                        numSmallBuffers, smallSize, bigSize, biggerBuffer->capacity());
-                numSmallBuffers++;
+                ALOGV("feedDecoderInputData() smallSize = %zu, bigSize = %zu, capacity = %zu",
+                        smallSize, bigSize, mAggregateBuffer->capacity());
             }
         }
     } while (dropAccessUnit || needMoreData);
@@ -1459,9 +1453,11 @@
         mCCDecoder->decode(accessUnit);
     }
 
-    if (biggerBuffer != NULL) {
-        ALOGV("feedDecoderInputData() reply with aggregated buffer, %d", numSmallBuffers);
-        reply->setBuffer("buffer", biggerBuffer);
+    if (mAggregateBuffer != NULL) {
+        ALOGV("feedDecoderInputData() reply with aggregated buffer, %zu",
+                mAggregateBuffer->size());
+        reply->setBuffer("buffer", mAggregateBuffer);
+        mAggregateBuffer.clear();
     } else {
         reply->setBuffer("buffer", accessUnit);
     }