Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit fbf70086 authored by Brian Lindahl's avatar Brian Lindahl
Browse files

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
parent dd37fb45
Loading
Loading
Loading
Loading
+18 −13
Original line number Diff line number Diff line
@@ -316,7 +316,7 @@ struct OMXNodeInstance::CallbackDispatcher : public RefBase {
    // 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 @@ protected:

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 @@ private:

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(const sp<OMXNodeInstance
OMXNodeInstance::CallbackDispatcher::~CallbackDispatcher() {
    {
        Mutex::Autolock autoLock(mLock);

        mDone = true;
        mQueueChanged.signal();
    }
@@ -377,8 +374,11 @@ void OMXNodeInstance::CallbackDispatcher::post(const omx_message &msg, bool real
    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,12 +393,17 @@ void OMXNodeInstance::CallbackDispatcher::dispatch(std::list<omx_message> &messa
bool OMXNodeInstance::CallbackDispatcher::loop() {
    for (;;) {
        std::list<omx_message> messages;
        std::list<long long> messageTimestamps;

        {
            Mutex::Autolock autoLock(mLock);
            while (!mDone && mQueue.empty()) {
                if (mHasBatchedMessages) {
                    mQueueChanged.waitRelative(mLock, kMaxBatchedDelayNs);
                } else {
                    mQueueChanged.wait(mLock);
                }
            }

            if (mDone) {
                break;
@@ -2447,7 +2452,7 @@ OMX_ERRORTYPE OMXNodeInstance::OnEmptyBufferDone(
    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 @@ OMX_ERRORTYPE OMXNodeInstance::OnFillBufferDone(
    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;
}