Deliver non-realtime OMX messages in a timely manner

Allow non-realtime messages to always be delivered even if the
end-of-stream is never reached. Start using a timeout to process
all messages on a periodic basis after the first non-realtime
message is encountered. This guarantees that non-realtime
messages are delivered in a reasonable amount of time.

This only affects tunnel mode decoders, since they are the only
decoders that produce frame-rendered messages, and frame-rendered
messages are the only non-realtime messages.

Note that this introduces periodic wakeups even when the decoder
is not actively rendering. This should not be problematic from a
performance perspective since a non-active decoder means the
device is likely underutilized.

Bug: 240622361
Fixes: 240622361
Test: atest android.media.decoder.cts.DecoderTest#testTunneledAudioUnderrunHevc
Change-Id: I0b9d4bcd56cc64fc37f52d295111e4e3eb6a157f
diff --git a/media/libstagefright/omx/OMXNodeInstance.cpp b/media/libstagefright/omx/OMXNodeInstance.cpp
index bebd516..c82a303 100644
--- a/media/libstagefright/omx/OMXNodeInstance.cpp
+++ b/media/libstagefright/omx/OMXNodeInstance.cpp
@@ -316,7 +316,7 @@
     // that a new message is available on the queue. Otherwise, the message stays on the queue, but
     // the listener is not notified of it. It will process this message when a subsequent message
     // is posted with |realTime| set to true.
-    void post(const omx_message &msg, bool realTime = true);
+    void post(const omx_message &msg, bool realTime);
 
     bool loop();
 
@@ -325,18 +325,15 @@
 
 private:
     enum {
-        // This is used for frame_rendered message batching, which will eventually end up in a
-        // single AMessage in MediaCodec when it is signaled to the app. AMessage can contain
-        // up-to 64 key-value pairs, and each frame_rendered message uses 2 keys, so the max
-        // value for this would be 32. Nonetheless, limit this to 12 to which gives at least 10
-        // mseconds of batching at 120Hz.
-        kMaxQueueSize = 12,
+        // Don't delay non-realtime messages longer than 200ms
+        kMaxBatchedDelayNs = 200 * 1000 * 1000,
     };
 
     Mutex mLock;
 
     sp<OMXNodeInstance> const mOwner;
     bool mDone;
+    bool mHasBatchedMessages;
     Condition mQueueChanged;
     std::list<omx_message> mQueue;
 
@@ -350,7 +347,8 @@
 
 OMXNodeInstance::CallbackDispatcher::CallbackDispatcher(const sp<OMXNodeInstance> &owner)
     : mOwner(owner),
-      mDone(false) {
+      mDone(false),
+      mHasBatchedMessages(false) {
     mThread = new CallbackDispatcherThread(this);
     mThread->run("OMXCallbackDisp", ANDROID_PRIORITY_FOREGROUND);
 }
@@ -358,7 +356,6 @@
 OMXNodeInstance::CallbackDispatcher::~CallbackDispatcher() {
     {
         Mutex::Autolock autoLock(mLock);
-
         mDone = true;
         mQueueChanged.signal();
     }
@@ -377,8 +374,11 @@
     Mutex::Autolock autoLock(mLock);
 
     mQueue.push_back(msg);
-    if (realTime || mQueue.size() >= kMaxQueueSize) {
+    if (realTime) {
         mQueueChanged.signal();
+    } else if (!mHasBatchedMessages) {
+        mHasBatchedMessages = true;
+        mQueueChanged.signal(); // The first non-realtime message is not batched.
     }
 }
 
@@ -393,11 +393,16 @@
 bool OMXNodeInstance::CallbackDispatcher::loop() {
     for (;;) {
         std::list<omx_message> messages;
+        std::list<long long> messageTimestamps;
 
         {
             Mutex::Autolock autoLock(mLock);
             while (!mDone && mQueue.empty()) {
-                mQueueChanged.wait(mLock);
+                if (mHasBatchedMessages) {
+                    mQueueChanged.waitRelative(mLock, kMaxBatchedDelayNs);
+                } else {
+                    mQueueChanged.wait(mLock);
+                }
             }
 
             if (mDone) {
@@ -2447,7 +2452,7 @@
     msg.type = omx_message::EMPTY_BUFFER_DONE;
     msg.fenceFd = fenceFd;
     msg.u.buffer_data.buffer = instance->findBufferID(pBuffer);
-    instance->mDispatcher->post(msg);
+    instance->mDispatcher->post(msg, true /* realTime */);
 
     return OMX_ErrorNone;
 }
@@ -2475,7 +2480,7 @@
     msg.u.extended_buffer_data.range_length = pBuffer->nFilledLen;
     msg.u.extended_buffer_data.flags = pBuffer->nFlags;
     msg.u.extended_buffer_data.timestamp = pBuffer->nTimeStamp;
-    instance->mDispatcher->post(msg);
+    instance->mDispatcher->post(msg, true /* realTime */);
 
     return OMX_ErrorNone;
 }