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

Commit ca8186ef authored by Marc Kassis's avatar Marc Kassis
Browse files

Discard decode only output buffer

Workaround: if vendors do not discard the decode only
buffers, MediaCodec should not return them to clients.

Bug: 234708299
Test: atest DecodeOnlyTest
Change-Id: I1c4d7d769390f422ca4f7c8e43dc6da01e6a63e1
parent 96343b43
Loading
Loading
Loading
Loading
+77 −27
Original line number Diff line number Diff line
@@ -1509,6 +1509,21 @@ void MediaCodec::statsBufferReceived(int64_t presentationUs, const sp<MediaCodec
    }
}

bool MediaCodec::discardDecodeOnlyOutputBuffer(size_t index) {
    Mutex::Autolock al(mBufferLock);
    BufferInfo *info = &mPortBuffers[kPortIndexOutput][index];
    sp<MediaCodecBuffer> buffer = info->mData;
    int32_t flags;
    CHECK(buffer->meta()->findInt32("flags", &flags));
    if (flags & BUFFER_FLAG_DECODE_ONLY) {
        info->mOwnedByClient = false;
        info->mData.clear();
        mBufferChannel->discardBuffer(buffer);
        return true;
    }
    return false;
}

// static
status_t MediaCodec::PostAndAwaitResponse(
        const sp<AMessage> &msg, sp<AMessage> *response) {
@@ -3198,7 +3213,8 @@ bool MediaCodec::handleDequeueInputBuffer(const sp<AReplyToken> &replyID, bool n
    return true;
}

bool MediaCodec::handleDequeueOutputBuffer(const sp<AReplyToken> &replyID, bool newRequest) {
MediaCodec::DequeueOutputResult MediaCodec::handleDequeueOutputBuffer(
        const sp<AReplyToken> &replyID, bool newRequest) {
    if (!isExecuting() || (mFlags & kFlagIsAsync)
            || (newRequest && (mFlags & kFlagDequeueOutputPending))) {
        PostReplyWithError(replyID, INVALID_OPERATION);
@@ -3211,7 +3227,7 @@ bool MediaCodec::handleDequeueOutputBuffer(const sp<AReplyToken> &replyID, bool
        sp<AMessage> response = new AMessage;
        BufferInfo *info = peekNextPortBuffer(kPortIndexOutput);
        if (!info) {
            return false;
            return DequeueOutputResult::kNoBuffer;
        }

        // In synchronous mode, output format change should be handled
@@ -3222,10 +3238,13 @@ bool MediaCodec::handleDequeueOutputBuffer(const sp<AReplyToken> &replyID, bool
        if (mFlags & kFlagOutputFormatChanged) {
            PostReplyWithError(replyID, INFO_FORMAT_CHANGED);
            mFlags &= ~kFlagOutputFormatChanged;
            return true;
            return DequeueOutputResult::kRepliedWithError;
        }

        ssize_t index = dequeuePortBuffer(kPortIndexOutput);
        if (discardDecodeOnlyOutputBuffer(index)) {
            return DequeueOutputResult::kDiscardedBuffer;
        }

        response->setSize("index", index);
        response->setSize("offset", buffer->offset());
@@ -3244,9 +3263,10 @@ bool MediaCodec::handleDequeueOutputBuffer(const sp<AReplyToken> &replyID, bool
        statsBufferReceived(timeUs, buffer);

        response->postReply(replyID);
        return DequeueOutputResult::kSuccess;
    }

    return true;
    return DequeueOutputResult::kRepliedWithError;
}

void MediaCodec::onMessageReceived(const sp<AMessage> &msg) {
@@ -3841,11 +3861,26 @@ void MediaCodec::onMessageReceived(const sp<AMessage> &msg) {
                        handleOutputFormatChangeIfNeeded(buffer);
                        onOutputBufferAvailable();
                    } else if (mFlags & kFlagDequeueOutputPending) {
                        CHECK(handleDequeueOutputBuffer(mDequeueOutputReplyID));

                        DequeueOutputResult dequeueResult =
                            handleDequeueOutputBuffer(mDequeueOutputReplyID);
                        switch (dequeueResult) {
                            case DequeueOutputResult::kNoBuffer:
                                TRESPASS();
                                break;
                            case DequeueOutputResult::kDiscardedBuffer:
                                break;
                            case DequeueOutputResult::kRepliedWithError:
                                [[fallthrough]];
                            case DequeueOutputResult::kSuccess:
                            {
                                ++mDequeueOutputTimeoutGeneration;
                                mFlags &= ~kFlagDequeueOutputPending;
                                mDequeueOutputReplyID = 0;
                                break;
                            }
                            default:
                                TRESPASS();
                        }
                    } else {
                        postActivityNotificationIfPossible();
                    }
@@ -4544,10 +4579,13 @@ void MediaCodec::onMessageReceived(const sp<AMessage> &msg) {
                break;
            }

            if (handleDequeueOutputBuffer(replyID, true /* new request */)) {
                break;
            }

            DequeueOutputResult dequeueResult =
                handleDequeueOutputBuffer(replyID, true /* new request */);
            switch (dequeueResult) {
                case DequeueOutputResult::kNoBuffer:
                    [[fallthrough]];
                case DequeueOutputResult::kDiscardedBuffer:
                {
                    int64_t timeoutUs;
                    CHECK(msg->findInt64("timeoutUs", &timeoutUs));

@@ -4568,6 +4606,15 @@ void MediaCodec::onMessageReceived(const sp<AMessage> &msg) {
                    }
                    break;
                }
                case DequeueOutputResult::kRepliedWithError:
                    [[fallthrough]];
                case DequeueOutputResult::kSuccess:
                    break;
                default:
                    TRESPASS();
            }
            break;
        }

        case kWhatDequeueOutputTimedOut:
        {
@@ -5553,6 +5600,9 @@ void MediaCodec::onInputBufferAvailable() {
void MediaCodec::onOutputBufferAvailable() {
    int32_t index;
    while ((index = dequeuePortBuffer(kPortIndexOutput)) >= 0) {
        if (discardDecodeOnlyOutputBuffer(index)) {
            continue;
        }
        const sp<MediaCodecBuffer> &buffer =
            mPortBuffers[kPortIndexOutput][index].mData;
        sp<AMessage> msg = mCallback->dup();
+11 −1
Original line number Diff line number Diff line
@@ -410,6 +410,13 @@ private:
        kBufferRendered,
    };

    enum class DequeueOutputResult {
        kNoBuffer,
        kDiscardedBuffer,
        kRepliedWithError,
        kSuccess,
    };

    struct ResourceManagerServiceProxy;

    State mState;
@@ -556,7 +563,9 @@ private:
            sp<MediaCodecBuffer> *buffer, sp<AMessage> *format);

    bool handleDequeueInputBuffer(const sp<AReplyToken> &replyID, bool newRequest = false);
    bool handleDequeueOutputBuffer(const sp<AReplyToken> &replyID, bool newRequest = false);
    DequeueOutputResult handleDequeueOutputBuffer(
            const sp<AReplyToken> &replyID,
            bool newRequest = false);
    void cancelPendingDequeueOperations();

    void extractCSD(const sp<AMessage> &format);
@@ -640,6 +649,7 @@ private:

    void statsBufferSent(int64_t presentationUs, const sp<MediaCodecBuffer> &buffer);
    void statsBufferReceived(int64_t presentationUs, const sp<MediaCodecBuffer> &buffer);
    bool discardDecodeOnlyOutputBuffer(size_t index);

    enum {
        // the default shape of our latency histogram buckets