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

Commit deb7a10c authored by Marc Kassis's avatar Marc Kassis Committed by Android (Google) Code Review
Browse files

Merge changes from topic "atv-frame-perfect-seek"

* changes:
  Workaround impl in acodec / ccodec
  Discard decode only output buffer
  Forward decode only flag to ACodec and CCodec
parents 50a70df4 ec910347
Loading
Loading
Loading
Loading
+9 −0
Original line number Original line Diff line number Diff line
@@ -226,6 +226,9 @@ status_t CCodecBufferChannel::queueInputBufferInternal(
    if (buffer->meta()->findInt32("tunnel-first-frame", &tmp) && tmp) {
    if (buffer->meta()->findInt32("tunnel-first-frame", &tmp) && tmp) {
        tunnelFirstFrame = true;
        tunnelFirstFrame = true;
    }
    }
    if (buffer->meta()->findInt32("decode-only", &tmp) && tmp) {
        flags |= C2FrameData::FLAG_DROP_FRAME;
    }
    ALOGV("[%s] queueInputBuffer: buffer->size() = %zu", mName, buffer->size());
    ALOGV("[%s] queueInputBuffer: buffer->size() = %zu", mName, buffer->size());
    std::list<std::unique_ptr<C2Work>> items;
    std::list<std::unique_ptr<C2Work>> items;
    std::unique_ptr<C2Work> work(new C2Work);
    std::unique_ptr<C2Work> work(new C2Work);
@@ -1995,6 +1998,12 @@ bool CCodecBufferChannel::handleWork(
        drop = true;
        drop = true;
    }
    }


    // Workaround: if C2FrameData::FLAG_DROP_FRAME is not implemented in
    // HAL, the flag is then removed in the corresponding output buffer.
    if (work->input.flags & C2FrameData::FLAG_DROP_FRAME) {
        flags |= BUFFER_FLAG_DECODE_ONLY;
    }

    if (notifyClient && !buffer && !flags) {
    if (notifyClient && !buffer && !flags) {
        if (mTunneled && drop && outputFormat) {
        if (mTunneled && drop && outputFormat) {
            ALOGV("[%s] onWorkDone: Keep tunneled, drop frame with format change (%lld)",
            ALOGV("[%s] onWorkDone: Keep tunneled, drop frame with format change (%lld)",
+44 −0
Original line number Original line Diff line number Diff line
@@ -6315,6 +6315,11 @@ void ACodec::BaseState::onInputBufferFilled(const sp<AMessage> &msg) {
                    flags |= OMX_BUFFERFLAG_EOS;
                    flags |= OMX_BUFFERFLAG_EOS;
                }
                }


                int32_t isDecodeOnly = 0;
                if (buffer->meta()->findInt32("decode-only", &isDecodeOnly) && isDecodeOnly != 0) {
                    flags |= OMX_BUFFERFLAG_DECODEONLY;
                    mCodec->mDecodeOnlyTimesUs.emplace(timeUs);
                }
                size_t size = buffer->size();
                size_t size = buffer->size();
                size_t offset = buffer->offset();
                size_t offset = buffer->offset();
                if (buffer->base() != info->mCodecData->base()) {
                if (buffer->base() != info->mCodecData->base()) {
@@ -6344,6 +6349,10 @@ void ACodec::BaseState::onInputBufferFilled(const sp<AMessage> &msg) {
                    ALOGV("[%s] calling emptyBuffer %u w/ EOS",
                    ALOGV("[%s] calling emptyBuffer %u w/ EOS",
                         mCodec->mComponentName.c_str(), bufferID);
                         mCodec->mComponentName.c_str(), bufferID);
                } else {
                } else {
                    if (flags & OMX_BUFFERFLAG_DECODEONLY) {
                        ALOGV("[%s] calling emptyBuffer %u w/ decode only flag",
                            mCodec->mComponentName.c_str(), bufferID);
                    }
#if TRACK_BUFFER_TIMING
#if TRACK_BUFFER_TIMING
                    ALOGI("[%s] calling emptyBuffer %u w/ time %lld us",
                    ALOGI("[%s] calling emptyBuffer %u w/ time %lld us",
                         mCodec->mComponentName.c_str(), bufferID, (long long)timeUs);
                         mCodec->mComponentName.c_str(), bufferID, (long long)timeUs);
@@ -6634,6 +6643,39 @@ bool ACodec::BaseState::onOMXFillBufferDone(


            info->mData.clear();
            info->mData.clear();


            // Workaround: if OMX_BUFFERFLAG_DECODEONLY is not implemented in
            // HAL, the flag is then removed in the corresponding output buffer.

            // for all buffers that were marked as DECODE_ONLY, remove their timestamp
            // if it is smaller than the timestamp of the buffer that was
            // just received
            while (!mCodec->mDecodeOnlyTimesUs.empty() &&
                   *mCodec->mDecodeOnlyTimesUs.begin() < timeUs) {
                    mCodec->mDecodeOnlyTimesUs.erase(mCodec->mDecodeOnlyTimesUs.begin());
            }
            // if OMX_BUFFERFLAG_DECODEONLY is not implemented in HAL, we need to restore the
            // OMX_BUFFERFLAG_DECODEONLY flag to the frames we had saved in the set, the set
            // contains the timestamps of buffers that were marked as DECODE_ONLY by the app
            if (!mCodec->mDecodeOnlyTimesUs.empty() &&
                *mCodec->mDecodeOnlyTimesUs.begin() == timeUs) {
                mCodec->mDecodeOnlyTimesUs.erase(timeUs);
                // If the app queued the last valid buffer as DECODE_ONLY and queued an additional
                // empty buffer as EOS, it's possible that HAL sets the last valid frame as EOS
                // instead and drops the empty buffer. In such a case, we should not add back
                // the OMX_BUFFERFLAG_DECODEONLY flag to it, as doing so will make it so that the
                // app does not receive the EOS buffer, which breaks the contract of EOS buffers
                if (flags & OMX_BUFFERFLAG_EOS) {
                    // Set buffer size to 0, as described by
                    // https://developer.android.com/reference/android/media/MediaCodec.BufferInfo?hl=en#size
                    // a buffer of size 0 should only be used to carry the EOS flag and should
                    // be discarded by the app as it has no data
                    buffer->setRange(0, 0);
                } else {
                    // re-add the OMX_BUFFERFLAG_DECODEONLY flag to the buffer in case it is
                    // not the end of stream buffer
                    flags |= OMX_BUFFERFLAG_DECODEONLY;
                }
            }
            mCodec->mBufferChannel->drainThisBuffer(info->mBufferID, flags);
            mCodec->mBufferChannel->drainThisBuffer(info->mBufferID, flags);


            info->mStatus = BufferInfo::OWNED_BY_DOWNSTREAM;
            info->mStatus = BufferInfo::OWNED_BY_DOWNSTREAM;
@@ -6854,6 +6896,7 @@ void ACodec::UninitializedState::stateEntered() {
    mCodec->mConverter[0].clear();
    mCodec->mConverter[0].clear();
    mCodec->mConverter[1].clear();
    mCodec->mConverter[1].clear();
    mCodec->mComponentName.clear();
    mCodec->mComponentName.clear();
    mCodec->mDecodeOnlyTimesUs.clear();
}
}


bool ACodec::UninitializedState::onMessageReceived(const sp<AMessage> &msg) {
bool ACodec::UninitializedState::onMessageReceived(const sp<AMessage> &msg) {
@@ -8839,6 +8882,7 @@ void ACodec::FlushingState::stateEntered() {
    ALOGV("[%s] Now Flushing", mCodec->mComponentName.c_str());
    ALOGV("[%s] Now Flushing", mCodec->mComponentName.c_str());


    mFlushComplete[kPortIndexInput] = mFlushComplete[kPortIndexOutput] = false;
    mFlushComplete[kPortIndexInput] = mFlushComplete[kPortIndexOutput] = false;
    mCodec->mDecodeOnlyTimesUs.clear();


    // If we haven't transitioned after 3 seconds, we're probably stuck.
    // If we haven't transitioned after 3 seconds, we're probably stuck.
    sp<AMessage> msg = new AMessage(ACodec::kWhatCheckIfStuck, mCodec);
    sp<AMessage> msg = new AMessage(ACodec::kWhatCheckIfStuck, mCodec);
+11 −0
Original line number Original line Diff line number Diff line
@@ -114,6 +114,10 @@ status_t ACodecBufferChannel::queueInputBuffer(const sp<MediaCodecBuffer> &buffe
        if (it->mClientBuffer->meta()->findInt32("csd", &csd)) {
        if (it->mClientBuffer->meta()->findInt32("csd", &csd)) {
            it->mCodecBuffer->meta()->setInt32("csd", csd);
            it->mCodecBuffer->meta()->setInt32("csd", csd);
        }
        }
        int32_t decodeOnly;
        if (it->mClientBuffer->meta()->findInt32("decode-only", &decodeOnly)) {
            it->mCodecBuffer->meta()->setInt32("decode-only", decodeOnly);
        }
    }
    }
    ALOGV("queueInputBuffer #%d", it->mBufferId);
    ALOGV("queueInputBuffer #%d", it->mBufferId);
    sp<AMessage> msg = mInputBufferFilled->dup();
    sp<AMessage> msg = mInputBufferFilled->dup();
@@ -263,6 +267,10 @@ status_t ACodecBufferChannel::queueSecureInputBuffer(
    if (it->mClientBuffer->meta()->findInt32("csd", &csd)) {
    if (it->mClientBuffer->meta()->findInt32("csd", &csd)) {
        it->mCodecBuffer->meta()->setInt32("csd", csd);
        it->mCodecBuffer->meta()->setInt32("csd", csd);
    }
    }
    int32_t decodeOnly;
    if (it->mClientBuffer->meta()->findInt32("decode-only", &decodeOnly)) {
        it->mCodecBuffer->meta()->setInt32("decode-only", decodeOnly);
    }


    ALOGV("queueSecureInputBuffer #%d", it->mBufferId);
    ALOGV("queueSecureInputBuffer #%d", it->mBufferId);
    sp<AMessage> msg = mInputBufferFilled->dup();
    sp<AMessage> msg = mInputBufferFilled->dup();
@@ -634,6 +642,9 @@ void ACodecBufferChannel::drainThisBuffer(
    if (omxFlags & OMX_BUFFERFLAG_EOS) {
    if (omxFlags & OMX_BUFFERFLAG_EOS) {
        flags |= MediaCodec::BUFFER_FLAG_EOS;
        flags |= MediaCodec::BUFFER_FLAG_EOS;
    }
    }
    if (omxFlags & OMX_BUFFERFLAG_DECODEONLY) {
        flags |= MediaCodec::BUFFER_FLAG_DECODE_ONLY;
    }
    it->mClientBuffer->meta()->setInt32("flags", flags);
    it->mClientBuffer->meta()->setInt32("flags", flags);


    mCallback->onOutputBufferAvailable(
    mCallback->onOutputBufferAvailable(
+84 −28
Original line number Original line Diff line number Diff line
@@ -1512,6 +1512,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
// static
status_t MediaCodec::PostAndAwaitResponse(
status_t MediaCodec::PostAndAwaitResponse(
        const sp<AMessage> &msg, sp<AMessage> *response) {
        const sp<AMessage> &msg, sp<AMessage> *response) {
@@ -3201,7 +3216,8 @@ bool MediaCodec::handleDequeueInputBuffer(const sp<AReplyToken> &replyID, bool n
    return true;
    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)
    if (!isExecuting() || (mFlags & kFlagIsAsync)
            || (newRequest && (mFlags & kFlagDequeueOutputPending))) {
            || (newRequest && (mFlags & kFlagDequeueOutputPending))) {
        PostReplyWithError(replyID, INVALID_OPERATION);
        PostReplyWithError(replyID, INVALID_OPERATION);
@@ -3214,7 +3230,7 @@ bool MediaCodec::handleDequeueOutputBuffer(const sp<AReplyToken> &replyID, bool
        sp<AMessage> response = new AMessage;
        sp<AMessage> response = new AMessage;
        BufferInfo *info = peekNextPortBuffer(kPortIndexOutput);
        BufferInfo *info = peekNextPortBuffer(kPortIndexOutput);
        if (!info) {
        if (!info) {
            return false;
            return DequeueOutputResult::kNoBuffer;
        }
        }


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


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


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


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


    return true;
    return DequeueOutputResult::kRepliedWithError;
}
}


void MediaCodec::onMessageReceived(const sp<AMessage> &msg) {
void MediaCodec::onMessageReceived(const sp<AMessage> &msg) {
@@ -3844,11 +3864,26 @@ void MediaCodec::onMessageReceived(const sp<AMessage> &msg) {
                        handleOutputFormatChangeIfNeeded(buffer);
                        handleOutputFormatChangeIfNeeded(buffer);
                        onOutputBufferAvailable();
                        onOutputBufferAvailable();
                    } else if (mFlags & kFlagDequeueOutputPending) {
                    } 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;
                                ++mDequeueOutputTimeoutGeneration;
                                mFlags &= ~kFlagDequeueOutputPending;
                                mFlags &= ~kFlagDequeueOutputPending;
                                mDequeueOutputReplyID = 0;
                                mDequeueOutputReplyID = 0;
                                break;
                            }
                            default:
                                TRESPASS();
                        }
                    } else {
                    } else {
                        postActivityNotificationIfPossible();
                        postActivityNotificationIfPossible();
                    }
                    }
@@ -4547,10 +4582,13 @@ void MediaCodec::onMessageReceived(const sp<AMessage> &msg) {
                break;
                break;
            }
            }


            if (handleDequeueOutputBuffer(replyID, true /* new request */)) {
            DequeueOutputResult dequeueResult =
                break;
                handleDequeueOutputBuffer(replyID, true /* new request */);
            }
            switch (dequeueResult) {

                case DequeueOutputResult::kNoBuffer:
                    [[fallthrough]];
                case DequeueOutputResult::kDiscardedBuffer:
                {
                    int64_t timeoutUs;
                    int64_t timeoutUs;
                    CHECK(msg->findInt64("timeoutUs", &timeoutUs));
                    CHECK(msg->findInt64("timeoutUs", &timeoutUs));


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


        case kWhatDequeueOutputTimedOut:
        case kWhatDequeueOutputTimedOut:
        {
        {
@@ -5229,6 +5276,7 @@ status_t MediaCodec::onQueueInputBuffer(const sp<AMessage> &msg) {


    buffer->setRange(offset, size);
    buffer->setRange(offset, size);
    buffer->meta()->setInt64("timeUs", timeUs);
    buffer->meta()->setInt64("timeUs", timeUs);

    if (flags & BUFFER_FLAG_EOS) {
    if (flags & BUFFER_FLAG_EOS) {
        buffer->meta()->setInt32("eos", true);
        buffer->meta()->setInt32("eos", true);
    }
    }
@@ -5237,7 +5285,12 @@ status_t MediaCodec::onQueueInputBuffer(const sp<AMessage> &msg) {
        buffer->meta()->setInt32("csd", true);
        buffer->meta()->setInt32("csd", true);
    }
    }


    if (mTunneled) {
    bool isBufferDecodeOnly = ((flags & BUFFER_FLAG_DECODE_ONLY) != 0);
    if (isBufferDecodeOnly) {
        buffer->meta()->setInt32("decode-only", true);
    }

    if (mTunneled && !isBufferDecodeOnly) {
        TunnelPeekState previousState = mTunnelPeekState;
        TunnelPeekState previousState = mTunnelPeekState;
        switch(mTunnelPeekState){
        switch(mTunnelPeekState){
            case TunnelPeekState::kEnabledNoBuffer:
            case TunnelPeekState::kEnabledNoBuffer:
@@ -5550,6 +5603,9 @@ void MediaCodec::onInputBufferAvailable() {
void MediaCodec::onOutputBufferAvailable() {
void MediaCodec::onOutputBufferAvailable() {
    int32_t index;
    int32_t index;
    while ((index = dequeuePortBuffer(kPortIndexOutput)) >= 0) {
    while ((index = dequeuePortBuffer(kPortIndexOutput)) >= 0) {
        if (discardDecodeOnlyOutputBuffer(index)) {
            continue;
        }
        const sp<MediaCodecBuffer> &buffer =
        const sp<MediaCodecBuffer> &buffer =
            mPortBuffers[kPortIndexOutput][index].mData;
            mPortBuffers[kPortIndexOutput][index].mData;
        sp<AMessage> msg = mCallback->dup();
        sp<AMessage> msg = mCallback->dup();
+2 −0
Original line number Original line Diff line number Diff line
@@ -17,6 +17,7 @@
#ifndef A_CODEC_H_
#ifndef A_CODEC_H_
#define A_CODEC_H_
#define A_CODEC_H_


#include <set>
#include <stdint.h>
#include <stdint.h>
#include <list>
#include <list>
#include <vector>
#include <vector>
@@ -270,6 +271,7 @@ private:
    std::vector<BufferInfo> mBuffers[2];
    std::vector<BufferInfo> mBuffers[2];
    bool mPortEOS[2];
    bool mPortEOS[2];
    status_t mInputEOSResult;
    status_t mInputEOSResult;
    std::set<int64_t> mDecodeOnlyTimesUs;


    std::list<sp<AMessage>> mDeferredQueue;
    std::list<sp<AMessage>> mDeferredQueue;


Loading