am 0f7c543c: am eb6e3edc: Merge "Coalesce multiple encoded AAC frames into a single input buffer on this particular OMX codec to increase throughput significantly." into froyo

Merge commit '0f7c543cc48d287591b5638a15bf8ca977e162a2' into kraken

* commit '0f7c543cc48d287591b5638a15bf8ca977e162a2':
  Coalesce multiple encoded AAC frames into a single input buffer on this particular OMX codec to increase throughput significantly.
diff --git a/cmds/stagefright/stagefright.cpp b/cmds/stagefright/stagefright.cpp
index 55bb581..fec9e1a 100644
--- a/cmds/stagefright/stagefright.cpp
+++ b/cmds/stagefright/stagefright.cpp
@@ -158,6 +158,7 @@
     MediaSource::ReadOptions options;
 
     int64_t sumDecodeUs = 0;
+    int64_t totalBytes = 0;
 
     while (numIterationsLeft-- > 0) {
         long numFrames = 0;
@@ -188,6 +189,7 @@
             }
 
             sumDecodeUs += delayDecodeUs;
+            totalBytes += buffer->range_length();
 
             buffer->release();
             buffer = NULL;
@@ -216,11 +218,20 @@
     printf("\n");
 
     int64_t delay = getNowUs() - startTime;
-    printf("avg. %.2f fps\n", n * 1E6 / delay);
-    printf("avg. time to decode one buffer %.2f usecs\n",
-           (double)sumDecodeUs / n);
+    if (!strncasecmp("video/", mime, 6)) {
+        printf("avg. %.2f fps\n", n * 1E6 / delay);
 
-    printf("decoded a total of %d frame(s).\n", n);
+        printf("avg. time to decode one buffer %.2f usecs\n",
+               (double)sumDecodeUs / n);
+
+        printf("decoded a total of %d frame(s).\n", n);
+    } else if (!strncasecmp("audio/", mime, 6)) {
+        // Frame count makes less sense for audio, as the output buffer
+        // sizes may be different across decoders.
+        printf("avg. %.2f KB/sec\n", totalBytes / 1024 * 1E6 / delay);
+
+        printf("decoded a total of %lld bytes\n", totalBytes);
+    }
 }
 
 static void usage(const char *me) {
diff --git a/include/media/stagefright/OMXCodec.h b/include/media/stagefright/OMXCodec.h
index d58c711..1d76a1a 100644
--- a/include/media/stagefright/OMXCodec.h
+++ b/include/media/stagefright/OMXCodec.h
@@ -87,16 +87,17 @@
     };
 
     enum Quirks {
-        kNeedsFlushBeforeDisable             = 1,
-        kWantsNALFragments                   = 2,
-        kRequiresLoadedToIdleAfterAllocation = 4,
-        kRequiresAllocateBufferOnInputPorts  = 8,
-        kRequiresFlushCompleteEmulation      = 16,
-        kRequiresAllocateBufferOnOutputPorts = 32,
-        kRequiresFlushBeforeShutdown         = 64,
-        kDefersOutputBufferAllocation        = 128,
-        kDecoderLiesAboutNumberOfChannels    = 256,
-        kInputBufferSizesAreBogus            = 512,
+        kNeedsFlushBeforeDisable              = 1,
+        kWantsNALFragments                    = 2,
+        kRequiresLoadedToIdleAfterAllocation  = 4,
+        kRequiresAllocateBufferOnInputPorts   = 8,
+        kRequiresFlushCompleteEmulation       = 16,
+        kRequiresAllocateBufferOnOutputPorts  = 32,
+        kRequiresFlushBeforeShutdown          = 64,
+        kDefersOutputBufferAllocation         = 128,
+        kDecoderLiesAboutNumberOfChannels     = 256,
+        kInputBufferSizesAreBogus             = 512,
+        kSupportsMultipleFramesPerInputBuffer = 1024,
     };
 
     struct BufferInfo {
@@ -137,6 +138,8 @@
     bool mOutputPortSettingsHaveChanged;
     int64_t mSeekTimeUs;
 
+    MediaBuffer *mLeftOverBuffer;
+
     Mutex mLock;
     Condition mAsyncCompletion;
 
diff --git a/media/libstagefright/OMXCodec.cpp b/media/libstagefright/OMXCodec.cpp
index 20d9540..2346639 100644
--- a/media/libstagefright/OMXCodec.cpp
+++ b/media/libstagefright/OMXCodec.cpp
@@ -103,6 +103,7 @@
     { MEDIA_MIMETYPE_AUDIO_MPEG, "OMX.TI.MP3.decode" },
     { MEDIA_MIMETYPE_AUDIO_MPEG, "MP3Decoder" },
 //    { MEDIA_MIMETYPE_AUDIO_MPEG, "OMX.PV.mp3dec" },
+//    { MEDIA_MIMETYPE_AUDIO_AMR_NB, "OMX.TI.AMR.decode" },
     { MEDIA_MIMETYPE_AUDIO_AMR_NB, "AMRNBDecoder" },
 //    { MEDIA_MIMETYPE_AUDIO_AMR_NB, "OMX.PV.amrdec" },
     { MEDIA_MIMETYPE_AUDIO_AMR_WB, "OMX.TI.WBAMR.decode" },
@@ -284,6 +285,7 @@
     if (!strcmp(componentName, "OMX.TI.AAC.decode")) {
         quirks |= kNeedsFlushBeforeDisable;
         quirks |= kRequiresFlushCompleteEmulation;
+        quirks |= kSupportsMultipleFramesPerInputBuffer;
     }
     if (!strncmp(componentName, "OMX.qcom.video.encoder.", 23)) {
         quirks |= kRequiresLoadedToIdleAfterAllocation;
@@ -533,7 +535,28 @@
                 return err;
             }
         }
+    } else if (!strncasecmp(mMIME, "audio/", 6)) {
+        if ((mQuirks & kSupportsMultipleFramesPerInputBuffer)
+            && !strcmp(mComponentName, "OMX.TI.AAC.decode")) {
+            OMX_PARAM_PORTDEFINITIONTYPE def;
+            InitOMXParams(&def);
+            def.nPortIndex = kPortIndexInput;
+
+            status_t err = mOMX->getParameter(
+                    mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
+            CHECK_EQ(err, OK);
+
+            const size_t kMinBufferSize = 100 * 1024;
+            if (def.nBufferSize < kMinBufferSize) {
+                def.nBufferSize = kMinBufferSize;
+            }
+
+            err = mOMX->setParameter(
+                    mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
+            CHECK_EQ(err, OK);
+        }
     }
+
     if (!strcasecmp(mMIME, MEDIA_MIMETYPE_IMAGE_JPEG)
         && !strcmp(mComponentName, "OMX.TI.JPEG.decode")) {
         OMX_COLOR_FORMATTYPE format =
@@ -1049,7 +1072,8 @@
       mSignalledEOS(false),
       mNoMoreOutputData(false),
       mOutputPortSettingsHaveChanged(false),
-      mSeekTimeUs(-1) {
+      mSeekTimeUs(-1),
+      mLeftOverBuffer(NULL) {
     mPortStatus[kPortIndexInput] = ENABLED;
     mPortStatus[kPortIndexOutput] = ENABLED;
 
@@ -1938,66 +1962,104 @@
         return;
     }
 
-    MediaBuffer *srcBuffer;
     status_t err;
-    if (mSeekTimeUs >= 0) {
-        MediaSource::ReadOptions options;
-        options.setSeekTo(mSeekTimeUs);
 
-        mSeekTimeUs = -1;
-        mBufferFilled.signal();
+    bool signalEOS = false;
+    int64_t timestampUs = 0;
 
-        err = mSource->read(&srcBuffer, &options);
-    } else {
-        err = mSource->read(&srcBuffer);
+    size_t offset = 0;
+    int32_t n = 0;
+    for (;;) {
+        MediaBuffer *srcBuffer;
+        if (mSeekTimeUs >= 0) {
+            if (mLeftOverBuffer) {
+                mLeftOverBuffer->release();
+                mLeftOverBuffer = NULL;
+            }
+
+            MediaSource::ReadOptions options;
+            options.setSeekTo(mSeekTimeUs);
+
+            mSeekTimeUs = -1;
+            mBufferFilled.signal();
+
+            err = mSource->read(&srcBuffer, &options);
+        } else if (mLeftOverBuffer) {
+            srcBuffer = mLeftOverBuffer;
+            mLeftOverBuffer = NULL;
+
+            err = OK;
+        } else {
+            err = mSource->read(&srcBuffer);
+        }
+
+        if (err != OK) {
+            signalEOS = true;
+            mFinalStatus = err;
+            mSignalledEOS = true;
+            break;
+        }
+
+        size_t remainingBytes = info->mSize - offset;
+
+        if (srcBuffer->range_length() > remainingBytes) {
+            if (offset == 0) {
+                CODEC_LOGE(
+                     "Codec's input buffers are too small to accomodate "
+                     "buffer read from source (info->mSize = %d, srcLength = %d)",
+                     info->mSize, srcBuffer->range_length());
+
+                srcBuffer->release();
+                srcBuffer = NULL;
+
+                setState(ERROR);
+                return;
+            }
+
+            mLeftOverBuffer = srcBuffer;
+            break;
+        }
+
+        memcpy((uint8_t *)info->mData + offset,
+               (const uint8_t *)srcBuffer->data() + srcBuffer->range_offset(),
+               srcBuffer->range_length());
+
+        if (offset == 0) {
+            CHECK(srcBuffer->meta_data()->findInt64(kKeyTime, &timestampUs));
+            CHECK(timestampUs >= 0);
+        }
+
+        offset += srcBuffer->range_length();
+
+        srcBuffer->release();
+        srcBuffer = NULL;
+
+        ++n;
+
+        if (!(mQuirks & kSupportsMultipleFramesPerInputBuffer)) {
+            break;
+        }
+    }
+
+    if (n > 1) {
+        LOGV("coalesced %d frames into one input buffer", n);
     }
 
     OMX_U32 flags = OMX_BUFFERFLAG_ENDOFFRAME;
-    OMX_TICKS timestampUs = 0;
-    size_t srcLength = 0;
 
-    if (err != OK) {
-        CODEC_LOGV("signalling end of input stream.");
+    if (signalEOS) {
         flags |= OMX_BUFFERFLAG_EOS;
-
-        mFinalStatus = err;
-        mSignalledEOS = true;
     } else {
         mNoMoreOutputData = false;
-
-        srcLength = srcBuffer->range_length();
-
-        if (info->mSize < srcLength) {
-            CODEC_LOGE(
-                 "Codec's input buffers are too small to accomodate "
-                 "buffer read from source (info->mSize = %d, srcLength = %d)",
-                 info->mSize, srcLength);
-
-            srcBuffer->release();
-            srcBuffer = NULL;
-
-            setState(ERROR);
-            return;
-        }
-        memcpy(info->mData,
-               (const uint8_t *)srcBuffer->data() + srcBuffer->range_offset(),
-               srcLength);
-
-        if (srcBuffer->meta_data()->findInt64(kKeyTime, &timestampUs)) {
-            CODEC_LOGV("Calling emptyBuffer on buffer %p (length %d), "
-                       "timestamp %lld us (%.2f secs)",
-                       info->mBuffer, srcLength,
-                       timestampUs, timestampUs / 1E6);
-        }
     }
 
-    if (srcBuffer != NULL) {
-        srcBuffer->release();
-        srcBuffer = NULL;
-    }
+    CODEC_LOGV("Calling emptyBuffer on buffer %p (length %d), "
+               "timestamp %lld us (%.2f secs)",
+               info->mBuffer, offset,
+               timestampUs, timestampUs / 1E6);
 
     err = mOMX->emptyBuffer(
-            mNode, info->mBuffer, 0, srcLength,
+            mNode, info->mBuffer, 0, offset,
             flags, timestampUs);
 
     if (err != OK) {
@@ -2352,6 +2414,11 @@
         }
     }
 
+    if (mLeftOverBuffer) {
+        mLeftOverBuffer->release();
+        mLeftOverBuffer = NULL;
+    }
+
     mSource->stop();
 
     CODEC_LOGV("stopped");