/*
 * Copyright (C) 2013 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <inttypes.h>

#define LOG_TAG "GraphicBufferSource"
//#define LOG_NDEBUG 0
#include <utils/Log.h>

#define STRINGIFY_ENUMS // for asString in HardwareAPI.h/VideoAPI.h

#include <media/stagefright/bqhelper/GraphicBufferSource.h>
#include <media/stagefright/bqhelper/FrameDropper.h>
#include <media/stagefright/foundation/ADebug.h>
#include <media/stagefright/foundation/AMessage.h>
#include <media/stagefright/foundation/ColorUtils.h>
#include <media/stagefright/foundation/FileDescriptor.h>

#include <android-base/properties.h>
#include <media/hardware/MetadataBufferType.h>
#include <ui/GraphicBuffer.h>
#include <gui/BufferItem.h>
#include <gui/BufferQueue.h>
#include <gui/bufferqueue/1.0/WGraphicBufferProducer.h>
#include <gui/bufferqueue/2.0/B2HGraphicBufferProducer.h>
#include <gui/IGraphicBufferProducer.h>
#include <gui/IGraphicBufferConsumer.h>
#include <media/hardware/HardwareAPI.h>

#include <inttypes.h>

#include <functional>
#include <memory>
#include <cmath>

namespace android {

namespace {
// kTimestampFluctuation is an upper bound of timestamp fluctuation from the
// source that GraphicBufferSource allows. The unit of kTimestampFluctuation is
// frames. More specifically, GraphicBufferSource will drop a frame if
//
// expectedNewFrametimestamp - actualNewFrameTimestamp <
//     (0.5 - kTimestampFluctuation) * expectedtimePeriodBetweenFrames
//
// where
// - expectedNewFrameTimestamp is the calculated ideal timestamp of the new
//   incoming frame
// - actualNewFrameTimestamp is the timestamp received from the source
// - expectedTimePeriodBetweenFrames is the ideal difference of the timestamps
//   of two adjacent frames
//
// See GraphicBufferSource::calculateCodecTimestamp_l() for more detail about
// how kTimestampFluctuation is used.
//
// kTimestampFluctuation should be non-negative. A higher value causes a smaller
// chance of dropping frames, but at the same time a higher bound on the
// difference between the source timestamp and the interpreted (snapped)
// timestamp.
//
// The value of 0.05 means that GraphicBufferSource expects the input timestamps
// to fluctuate no more than 5% from the regular time period.
//
// TODO: Justify the choice of this value, or make it configurable.
constexpr double kTimestampFluctuation = 0.05;
}

/**
 * A copiable object managing a buffer in the buffer cache managed by the producer. This object
 * holds a reference to the buffer, and maintains which buffer slot it belongs to (if any), and
 * whether it is still in a buffer slot. It also maintains whether there are any outstanging acquire
 * references to it (by buffers acquired from the slot) mainly so that we can keep a debug
 * count of how many buffers we need to still release back to the producer.
 */
struct GraphicBufferSource::CachedBuffer {
    /**
     * Token that is used to track acquire counts (as opposed to all references to this object).
     */
    struct Acquirable { };

    /**
     * Create using a buffer cached in a slot.
     */
    CachedBuffer(slot_id slot, const sp<GraphicBuffer> &graphicBuffer)
        : mIsCached(true),
          mSlot(slot),
          mGraphicBuffer(graphicBuffer),
          mAcquirable(std::make_shared<Acquirable>()) {
    }

    /**
     * Returns the cache slot that this buffer is cached in, or -1 if it is no longer cached.
     *
     * This assumes that -1 slot id is invalid; though, it is just a benign collision used for
     * debugging. This object explicitly manages whether it is still cached.
     */
    slot_id getSlot() const {
        return mIsCached ? mSlot : -1;
    }

    /**
     * Returns the cached buffer.
     */
    sp<GraphicBuffer> getGraphicBuffer() const {
        return mGraphicBuffer;
    }

    /**
     * Checks whether this buffer is still in the buffer cache.
     */
    bool isCached() const {
        return mIsCached;
    }

    /**
     * Checks whether this buffer has an acquired reference.
     */
    bool isAcquired() const {
        return mAcquirable.use_count() > 1;
    }

    /**
     * Gets and returns a shared acquired reference.
     */
    std::shared_ptr<Acquirable> getAcquirable() {
        return mAcquirable;
    }

private:
    friend void GraphicBufferSource::discardBufferAtSlotIndex_l(ssize_t);

    /**
     * This method to be called when the buffer is no longer in the buffer cache.
     * Called from discardBufferAtSlotIndex_l.
     */
    void onDroppedFromCache() {
        CHECK_DBG(mIsCached);
        mIsCached = false;
    }

    bool mIsCached;
    slot_id mSlot;
    sp<GraphicBuffer> mGraphicBuffer;
    std::shared_ptr<Acquirable> mAcquirable;
};

/**
 * A copiable object managing a buffer acquired from the producer. This must always be a cached
 * buffer. This objects also manages its acquire fence and any release fences that may be returned
 * by the encoder for this buffer (this buffer may be queued to the encoder multiple times).
 * If no release fences are added by the encoder, the acquire fence is returned as the release
 * fence for this - as it is assumed that noone waited for the acquire fence. Otherwise, it is
 * assumed that the encoder has waited for the acquire fence (or returned it as the release
 * fence).
 */
struct GraphicBufferSource::AcquiredBuffer {
    AcquiredBuffer(
            const std::shared_ptr<CachedBuffer> &buffer,
            std::function<void(AcquiredBuffer *)> onReleased,
            const sp<Fence> &acquireFence)
        : mBuffer(buffer),
          mAcquirable(buffer->getAcquirable()),
          mAcquireFence(acquireFence),
          mGotReleaseFences(false),
          mOnReleased(onReleased) {
    }

    /**
     * Adds a release fence returned by the encoder to this object. If this is called with an
     * valid file descriptor, it is added to the list of release fences. These are returned to the
     * producer on release() as a merged fence. Regardless of the validity of the file descriptor,
     * we take note that a release fence was attempted to be added and the acquire fence can now be
     * assumed as acquired.
     */
    void addReleaseFenceFd(int fenceFd) {
        // save all release fences - these will be propagated to the producer if this buffer is
        // ever released to it
        if (fenceFd >= 0) {
            mReleaseFenceFds.push_back(fenceFd);
        }
        mGotReleaseFences = true;
    }

    /**
     * Returns the acquire fence file descriptor associated with this object.
     */
    int getAcquireFenceFd() {
        if (mAcquireFence == nullptr || !mAcquireFence->isValid()) {
            return -1;
        }
        return mAcquireFence->dup();
    }

    /**
     * Returns whether the buffer is still in the buffer cache.
     */
    bool isCached() const {
        return mBuffer->isCached();
    }

    /**
     * Returns the acquired buffer.
     */
    sp<GraphicBuffer> getGraphicBuffer() const {
        return mBuffer->getGraphicBuffer();
    }

    /**
     * Returns the slot that this buffer is cached at, or -1 otherwise.
     *
     * This assumes that -1 slot id is invalid; though, it is just a benign collision used for
     * debugging. This object explicitly manages whether it is still cached.
     */
    slot_id getSlot() const {
        return mBuffer->getSlot();
    }

    /**
     * Creates and returns a release fence object from the acquire fence and/or any release fences
     * added. If no release fences were added (even if invalid), returns the acquire fence.
     * Otherwise, it returns a merged fence from all the valid release fences added.
     */
    sp<Fence> getReleaseFence() {
        // If did not receive release fences, we assume this buffer was not consumed (it was
        // discarded or dropped). In this case release the acquire fence as the release fence.
        // We do this here to avoid a dup, close and recreation of the Fence object.
        if (!mGotReleaseFences) {
            return mAcquireFence;
        }
        sp<Fence> ret = getReleaseFence(0, mReleaseFenceFds.size());
        // clear fds as fence took ownership of them
        mReleaseFenceFds.clear();
        return ret;
    }

    // this video buffer is no longer referenced by the codec (or kept for later encoding)
    // it is now safe to release to the producer
    ~AcquiredBuffer() {
        //mAcquirable.clear();
        mOnReleased(this);
        // mOnRelease method should call getReleaseFence() that releases all fds but just in case
        ALOGW_IF(!mReleaseFenceFds.empty(), "release fences were not obtained, closing fds");
        for (int fildes : mReleaseFenceFds) {
            ::close(fildes);
            TRESPASS_DBG();
        }
    }

private:
    std::shared_ptr<GraphicBufferSource::CachedBuffer> mBuffer;
    std::shared_ptr<GraphicBufferSource::CachedBuffer::Acquirable> mAcquirable;
    sp<Fence> mAcquireFence;
    Vector<int> mReleaseFenceFds;
    bool mGotReleaseFences;
    std::function<void(AcquiredBuffer *)> mOnReleased;

    /**
     * Creates and returns a release fence from 0 or more release fence file descriptors in from
     * the specified range in the array.
     *
     * @param start start index
     * @param num   number of release fds to merge
     */
    sp<Fence> getReleaseFence(size_t start, size_t num) const {
        if (num == 0) {
            return Fence::NO_FENCE;
        } else if (num == 1) {
            return new Fence(mReleaseFenceFds[start]);
        } else {
            return Fence::merge("GBS::AB",
                                getReleaseFence(start, num >> 1),
                                getReleaseFence(start + (num >> 1), num - (num >> 1)));
        }
    }
};

struct GraphicBufferSource::ConsumerProxy : public BufferQueue::ConsumerListener {
    ConsumerProxy(const wp<GraphicBufferSource> &gbs) : mGbs(gbs) {}

    ~ConsumerProxy() = default;

    void onFrameAvailable(const BufferItem& item) override {
        sp<GraphicBufferSource> gbs = mGbs.promote();
        if (gbs != nullptr) {
            gbs->onFrameAvailable(item);
        }
    }

    void onBuffersReleased() override {
        sp<GraphicBufferSource> gbs = mGbs.promote();
        if (gbs != nullptr) {
            gbs->onBuffersReleased();
        }
    }

    void onSidebandStreamChanged() override {
        sp<GraphicBufferSource> gbs = mGbs.promote();
        if (gbs != nullptr) {
            gbs->onSidebandStreamChanged();
        }
    }

private:
    // Note that GraphicBufferSource is holding an sp to us, we can't hold
    // an sp back to GraphicBufferSource as the circular dependency will
    // make both immortal.
    wp<GraphicBufferSource> mGbs;
};

GraphicBufferSource::GraphicBufferSource() :
    mInitCheck(UNKNOWN_ERROR),
    mNumAvailableUnacquiredBuffers(0),
    mNumOutstandingAcquires(0),
    mEndOfStream(false),
    mEndOfStreamSent(false),
    mLastDataspace(HAL_DATASPACE_UNKNOWN),
    mExecuting(false),
    mSuspended(false),
    mLastFrameTimestampUs(-1),
    mStopTimeUs(-1),
    mLastActionTimeUs(-1LL),
    mSkipFramesBeforeNs(-1LL),
    mFrameRepeatIntervalUs(-1LL),
    mRepeatLastFrameGeneration(0),
    mOutstandingFrameRepeatCount(0),
    mFrameRepeatBlockedOnCodecBuffer(false),
    mFps(-1.0),
    mCaptureFps(-1.0),
    mBaseCaptureUs(-1LL),
    mBaseFrameUs(-1LL),
    mFrameCount(0),
    mPrevCaptureUs(-1LL),
    mPrevFrameUs(-1LL),
    mInputBufferTimeOffsetUs(0LL) {
    ALOGV("GraphicBufferSource");

    String8 name("GraphicBufferSource");

    BufferQueue::createBufferQueue(&mProducer, &mConsumer);
    mConsumer->setConsumerName(name);

    // create the consumer listener interface, and hold sp so that this
    // interface lives as long as the GraphicBufferSource.
    mConsumerProxy = new ConsumerProxy(this);

    sp<IConsumerListener> proxy =
            new BufferQueue::ProxyConsumerListener(mConsumerProxy);

    mInitCheck = mConsumer->consumerConnect(proxy, false);
    if (mInitCheck != NO_ERROR) {
        ALOGE("Error connecting to BufferQueue: %s (%d)",
                strerror(-mInitCheck), mInitCheck);
        return;
    }

    memset(&mDefaultColorAspectsPacked, 0, sizeof(mDefaultColorAspectsPacked));

    CHECK(mInitCheck == NO_ERROR);
}

GraphicBufferSource::~GraphicBufferSource() {
    ALOGV("~GraphicBufferSource");
    {
        // all acquired buffers must be freed with the mutex locked otherwise our debug assertion
        // may trigger
        Mutex::Autolock autoLock(mMutex);
        mAvailableBuffers.clear();
        mSubmittedCodecBuffers.clear();
        mLatestBuffer.mBuffer.reset();
    }

    if (mNumOutstandingAcquires != 0) {
        ALOGW("potential buffer leak: acquired=%d", mNumOutstandingAcquires);
        TRESPASS_DBG();
    }
    if (mConsumer != NULL) {
        status_t err = mConsumer->consumerDisconnect();
        if (err != NO_ERROR) {
            ALOGW("consumerDisconnect failed: %d", err);
        }
    }
}

sp<IGraphicBufferProducer> GraphicBufferSource::getIGraphicBufferProducer() const {
    return mProducer;
}

sp<::android::hardware::graphics::bufferqueue::V1_0::IGraphicBufferProducer>
GraphicBufferSource::getHGraphicBufferProducer_V1_0() const {
    using TWGraphicBufferProducer = ::android::TWGraphicBufferProducer<
        ::android::hardware::graphics::bufferqueue::V1_0::IGraphicBufferProducer>;

    return new TWGraphicBufferProducer(getIGraphicBufferProducer());
}

sp<::android::hardware::graphics::bufferqueue::V2_0::IGraphicBufferProducer>
GraphicBufferSource::getHGraphicBufferProducer() const {
    return new ::android::hardware::graphics::bufferqueue::V2_0::utils::
                    B2HGraphicBufferProducer(getIGraphicBufferProducer());
}

status_t GraphicBufferSource::start() {
    Mutex::Autolock autoLock(mMutex);
    ALOGV("--> start; available=%zu, submittable=%zd",
            mAvailableBuffers.size(), mFreeCodecBuffers.size());
    CHECK(!mExecuting);
    mExecuting = true;
    mLastDataspace = HAL_DATASPACE_UNKNOWN;
    ALOGV("clearing last dataSpace");

    // Start by loading up as many buffers as possible.  We want to do this,
    // rather than just submit the first buffer, to avoid a degenerate case:
    // if all BQ buffers arrive before we start executing, and we only submit
    // one here, the other BQ buffers will just sit until we get notified
    // that the codec buffer has been released.  We'd then acquire and
    // submit a single additional buffer, repeatedly, never using more than
    // one codec buffer simultaneously.  (We could instead try to submit
    // all BQ buffers whenever any codec buffer is freed, but if we get the
    // initial conditions right that will never be useful.)
    while (haveAvailableBuffers_l()) {
        if (!fillCodecBuffer_l()) {
            ALOGV("stop load with available=%zu+%d",
                    mAvailableBuffers.size(), mNumAvailableUnacquiredBuffers);
            break;
        }
    }

    ALOGV("done loading initial frames, available=%zu+%d",
            mAvailableBuffers.size(), mNumAvailableUnacquiredBuffers);

    // If EOS has already been signaled, and there are no more frames to
    // submit, try to send EOS now as well.
    if (mStopTimeUs == -1 && mEndOfStream && !haveAvailableBuffers_l()) {
        submitEndOfInputStream_l();
    }

    if (mFrameRepeatIntervalUs > 0LL && mLooper == NULL) {
        mReflector = new AHandlerReflector<GraphicBufferSource>(this);

        mLooper = new ALooper;
        mLooper->registerHandler(mReflector);
        mLooper->start();

        if (mLatestBuffer.mBuffer != nullptr) {
            queueFrameRepeat_l();
        }
    }

    return OK;
}

status_t GraphicBufferSource::stop() {
    ALOGV("stop");

    Mutex::Autolock autoLock(mMutex);

    if (mExecuting) {
        // We are only interested in the transition from executing->idle,
        // not loaded->idle.
        mExecuting = false;
    }
    return OK;
}

status_t GraphicBufferSource::release(){
    sp<ALooper> looper;
    {
        Mutex::Autolock autoLock(mMutex);
        looper = mLooper;
        if (mLooper != NULL) {
            mLooper->unregisterHandler(mReflector->id());
            mReflector.clear();

            mLooper.clear();
        }

        ALOGV("--> release; available=%zu+%d eos=%d eosSent=%d acquired=%d",
                mAvailableBuffers.size(), mNumAvailableUnacquiredBuffers,
                mEndOfStream, mEndOfStreamSent, mNumOutstandingAcquires);

        // Codec is no longer executing.  Releasing all buffers to bq.
        mFreeCodecBuffers.clear();
        mSubmittedCodecBuffers.clear();
        mLatestBuffer.mBuffer.reset();
        mComponent.clear();
        mExecuting = false;
    }
    if (looper != NULL) {
        looper->stop();
    }
    return OK;
}

status_t GraphicBufferSource::onInputBufferAdded(codec_buffer_id bufferId) {
    Mutex::Autolock autoLock(mMutex);

    if (mExecuting) {
        // This should never happen -- buffers can only be allocated when
        // transitioning from "loaded" to "idle".
        ALOGE("addCodecBuffer: buffer added while executing");
        return INVALID_OPERATION;
    }

    ALOGV("addCodecBuffer: bufferId=%u", bufferId);

    mFreeCodecBuffers.push_back(bufferId);
    return OK;
}

status_t GraphicBufferSource::onInputBufferEmptied(codec_buffer_id bufferId, int fenceFd) {
    Mutex::Autolock autoLock(mMutex);
    FileDescriptor::Autoclose fence(fenceFd);

    ssize_t cbi = mSubmittedCodecBuffers.indexOfKey(bufferId);
    if (cbi < 0) {
        // This should never happen.
        ALOGE("onInputBufferEmptied: buffer not recognized (bufferId=%u)", bufferId);
        return BAD_VALUE;
    }

    std::shared_ptr<AcquiredBuffer> buffer = mSubmittedCodecBuffers.valueAt(cbi);

    // Move buffer to available buffers
    mSubmittedCodecBuffers.removeItemsAt(cbi);
    mFreeCodecBuffers.push_back(bufferId);

    // header->nFilledLen may not be the original value, so we can't compare
    // that to zero to see of this was the EOS buffer.  Instead we just
    // see if there is a null AcquiredBuffer, which should only ever happen for EOS.
    if (buffer == nullptr) {
        if (!(mEndOfStream && mEndOfStreamSent)) {
            // This can happen when broken code sends us the same buffer twice in a row.
            ALOGE("onInputBufferEmptied: non-EOS null buffer (bufferId=%u)", bufferId);
        } else {
            ALOGV("onInputBufferEmptied: EOS null buffer (bufferId=%u@%zd)", bufferId, cbi);
        }
        // No GraphicBuffer to deal with, no additional input or output is expected, so just return.
        return BAD_VALUE;
    }

    if (!mExecuting) {
        // this is fine since this could happen when going from Idle to Loaded
        ALOGV("onInputBufferEmptied: no longer executing (bufferId=%u@%zd)", bufferId, cbi);
        return OK;
    }

    ALOGV("onInputBufferEmptied: bufferId=%d@%zd [slot=%d, useCount=%ld, handle=%p] acquired=%d",
            bufferId, cbi, buffer->getSlot(), buffer.use_count(), buffer->getGraphicBuffer()->handle,
            mNumOutstandingAcquires);

    buffer->addReleaseFenceFd(fence.release());
    // release codec reference for video buffer just in case remove does not it
    buffer.reset();

    if (haveAvailableBuffers_l()) {
        // Fill this codec buffer.
        CHECK(!mEndOfStreamSent);
        ALOGV("onInputBufferEmptied: buffer freed, feeding codec (available=%zu+%d, eos=%d)",
                mAvailableBuffers.size(), mNumAvailableUnacquiredBuffers, mEndOfStream);
        fillCodecBuffer_l();
    } else if (mEndOfStream && mStopTimeUs == -1) {
        // No frames available, but EOS is pending and no stop time, so use this buffer to
        // send that.
        ALOGV("onInputBufferEmptied: buffer freed, submitting EOS");
        submitEndOfInputStream_l();
    } else if (mFrameRepeatBlockedOnCodecBuffer) {
        bool success = repeatLatestBuffer_l();
        ALOGV("onInputBufferEmptied: completing deferred repeatLatestBuffer_l %s",
                success ? "SUCCESS" : "FAILURE");
        mFrameRepeatBlockedOnCodecBuffer = false;
    }

    // releaseReleasableBuffers_l();
    return OK;
}

void GraphicBufferSource::onDataspaceChanged_l(
        android_dataspace dataspace, android_pixel_format pixelFormat) {
    ALOGD("got buffer with new dataSpace #%x", dataspace);
    mLastDataspace = dataspace;

    if (ColorUtils::convertDataSpaceToV0(dataspace)) {
        mComponent->dispatchDataSpaceChanged(
                mLastDataspace, mDefaultColorAspectsPacked, pixelFormat);
    }
}

bool GraphicBufferSource::fillCodecBuffer_l() {
    CHECK(mExecuting && haveAvailableBuffers_l());

    if (mFreeCodecBuffers.empty()) {
        // No buffers available, bail.
        ALOGV("fillCodecBuffer_l: no codec buffers, available=%zu+%d",
                mAvailableBuffers.size(), mNumAvailableUnacquiredBuffers);
        return false;
    }

    VideoBuffer item;
    if (mAvailableBuffers.empty()) {
        ALOGV("fillCodecBuffer_l: acquiring available buffer, available=%zu+%d",
                mAvailableBuffers.size(), mNumAvailableUnacquiredBuffers);
        if (acquireBuffer_l(&item) != OK) {
            ALOGE("fillCodecBuffer_l: failed to acquire available buffer");
            return false;
        }
    } else {
        ALOGV("fillCodecBuffer_l: getting available buffer, available=%zu+%d",
                mAvailableBuffers.size(), mNumAvailableUnacquiredBuffers);
        item = *mAvailableBuffers.begin();
        mAvailableBuffers.erase(mAvailableBuffers.begin());
    }

    int64_t itemTimeUs = item.mTimestampNs / 1000;

    // Process ActionItem in the Queue if there is any. If a buffer's timestamp
    // is smaller than the first action's timestamp, no action need to be performed.
    // If buffer's timestamp is larger or equal than the last action's timestamp,
    // only the last action needs to be performed as all the acitions before the
    // the action are overridden by the last action. For the other cases, traverse
    // the Queue to find the newest action that with timestamp smaller or equal to
    // the buffer's timestamp. For example, an action queue like
    // [pause 1us], [resume 2us], [pause 3us], [resume 4us], [pause 5us].... Upon
    // receiving a buffer with timestamp 3.5us, only the action [pause, 3us] needs
    // to be handled and [pause, 1us], [resume 2us] will be discarded.
    bool done = false;
    bool seeStopAction = false;
    if (!mActionQueue.empty()) {
        // First scan to check if bufferTimestamp is smaller than first action's timestamp.
        ActionItem nextAction = *(mActionQueue.begin());
        if (itemTimeUs < nextAction.mActionTimeUs) {
            ALOGV("No action. buffer timestamp %lld us < action timestamp: %lld us",
                (long long)itemTimeUs, (long long)nextAction.mActionTimeUs);
            // All the actions are ahead. No action need to perform now.
            // Release the buffer if is in suspended state, or process the buffer
            // if not in suspended state.
            done = true;
        }

        if (!done) {
            // Find the newest action that with timestamp smaller than itemTimeUs. Then
            // remove all the actions before and include the newest action.
            List<ActionItem>::iterator it = mActionQueue.begin();
            while (it != mActionQueue.end() && it->mActionTimeUs <= itemTimeUs
                    && nextAction.mAction != ActionItem::STOP) {
                nextAction = *it;
                ++it;
            }
            mActionQueue.erase(mActionQueue.begin(), it);

            CHECK(itemTimeUs >= nextAction.mActionTimeUs);
            switch (nextAction.mAction) {
                case ActionItem::PAUSE:
                {
                    mSuspended = true;
                    ALOGV("RUNNING/PAUSE -> PAUSE at buffer %lld us  PAUSE Time: %lld us",
                            (long long)itemTimeUs, (long long)nextAction.mActionTimeUs);
                    break;
                }
                case ActionItem::RESUME:
                {
                    mSuspended = false;
                    ALOGV("PAUSE/RUNNING -> RUNNING at buffer %lld us  RESUME Time: %lld us",
                            (long long)itemTimeUs, (long long)nextAction.mActionTimeUs);
                    break;
                }
                case ActionItem::STOP:
                {
                    ALOGV("RUNNING/PAUSE -> STOP at buffer %lld us  STOP Time: %lld us",
                            (long long)itemTimeUs, (long long)nextAction.mActionTimeUs);
                    // Clear the whole ActionQueue as recording is done
                    mActionQueue.clear();
                    seeStopAction = true;
                    break;
                }
                default:
                    TRESPASS_DBG("Unknown action type");
                    // return true here because we did consume an available buffer, so the
                    // loop in start will eventually terminate even if we hit this.
                    return false;
            }
        }
    }

    if (seeStopAction) {
        // Clear all the buffers before setting mEndOfStream and signal EndOfInputStream.
        releaseAllAvailableBuffers_l();
        mEndOfStream = true;
        submitEndOfInputStream_l();
        return true;
    }

    if (mSuspended) {
        return true;
    }

    int err = UNKNOWN_ERROR;

    // only submit sample if start time is unspecified, or sample
    // is queued after the specified start time
    if (mSkipFramesBeforeNs < 0LL || item.mTimestampNs >= mSkipFramesBeforeNs) {
        // if start time is set, offset time stamp by start time
        if (mSkipFramesBeforeNs > 0) {
            item.mTimestampNs -= mSkipFramesBeforeNs;
        }

        int64_t timeUs = item.mTimestampNs / 1000;
        if (mFrameDropper != NULL && mFrameDropper->shouldDrop(timeUs)) {
            ALOGV("skipping frame (%lld) to meet max framerate", static_cast<long long>(timeUs));
            // set err to OK so that the skipped frame can still be saved as the lastest frame
            err = OK;
        } else {
            err = submitBuffer_l(item); // this takes shared ownership of the acquired buffer on succeess
        }
    }

    if (err != OK) {
        ALOGV("submitBuffer_l failed, will release bq slot %d", item.mBuffer->getSlot());
        return true;
    } else {
        // Don't set the last buffer id if we're not repeating,
        // we'll be holding on to the last buffer for nothing.
        if (mFrameRepeatIntervalUs > 0LL) {
            setLatestBuffer_l(item);
        }
        ALOGV("buffer submitted [slot=%d, useCount=%ld] acquired=%d",
                item.mBuffer->getSlot(), item.mBuffer.use_count(), mNumOutstandingAcquires);
        mLastFrameTimestampUs = itemTimeUs;
    }

    return true;
}

bool GraphicBufferSource::repeatLatestBuffer_l() {
    CHECK(mExecuting && !haveAvailableBuffers_l());

    if (mLatestBuffer.mBuffer == nullptr || mSuspended) {
        return false;
    }

    if (mFreeCodecBuffers.empty()) {
        // No buffers available, bail.
        ALOGV("repeatLatestBuffer_l: no codec buffers.");
        return false;
    }

    if (!mLatestBuffer.mBuffer->isCached()) {
        ALOGV("repeatLatestBuffer_l: slot was discarded, but repeating our own reference");
    }

    // it is ok to update the timestamp of latest buffer as it is only used for submission
    status_t err = submitBuffer_l(mLatestBuffer);
    if (err != OK) {
        return false;
    }

    /* repeat last frame up to kRepeatLastFrameCount times.
     * in case of static scene, a single repeat might not get rid of encoder
     * ghosting completely, refresh a couple more times to get better quality
     */
    if (--mOutstandingFrameRepeatCount > 0) {
        // set up timestamp for repeat frame
        mLatestBuffer.mTimestampNs += mFrameRepeatIntervalUs * 1000;
        queueFrameRepeat_l();
    }

    return true;
}

void GraphicBufferSource::setLatestBuffer_l(const VideoBuffer &item) {
    mLatestBuffer = item;

    ALOGV("setLatestBuffer_l: [slot=%d, useCount=%ld]",
            mLatestBuffer.mBuffer->getSlot(), mLatestBuffer.mBuffer.use_count());

    mOutstandingFrameRepeatCount = kRepeatLastFrameCount;
    // set up timestamp for repeat frame
    mLatestBuffer.mTimestampNs += mFrameRepeatIntervalUs * 1000;
    queueFrameRepeat_l();
}

void GraphicBufferSource::queueFrameRepeat_l() {
    mFrameRepeatBlockedOnCodecBuffer = false;

    if (mReflector != NULL) {
        sp<AMessage> msg = new AMessage(kWhatRepeatLastFrame, mReflector);
        msg->setInt32("generation", ++mRepeatLastFrameGeneration);
        msg->post(mFrameRepeatIntervalUs);
    }
}

#ifdef __clang__
__attribute__((no_sanitize("integer")))
#endif
bool GraphicBufferSource::calculateCodecTimestamp_l(
        nsecs_t bufferTimeNs, int64_t *codecTimeUs) {
    int64_t timeUs = bufferTimeNs / 1000;
    timeUs += mInputBufferTimeOffsetUs;

    if (mCaptureFps > 0.
            && (mFps > 2 * mCaptureFps
            || mCaptureFps > 2 * mFps)) {
        // Time lapse or slow motion mode
        if (mPrevCaptureUs < 0LL) {
            // first capture
            mPrevCaptureUs = mBaseCaptureUs = timeUs;
            // adjust the first sample timestamp.
            mPrevFrameUs = mBaseFrameUs =
                    std::llround((timeUs * mCaptureFps) / mFps);
            mFrameCount = 0;
        } else if (mSnapTimestamps) {
            double nFrames = (timeUs - mPrevCaptureUs) * mCaptureFps / 1000000;
            if (nFrames < 0.5 - kTimestampFluctuation) {
                // skip this frame as it's too close to previous capture
                ALOGD("skipping frame, timeUs %lld",
                      static_cast<long long>(timeUs));
                return false;
            }
            // snap to nearest capture point
            if (nFrames <= 1.0) {
                nFrames = 1.0;
            }
            mFrameCount += std::llround(nFrames);
            mPrevCaptureUs = mBaseCaptureUs + std::llround(
                    mFrameCount * 1000000 / mCaptureFps);
            mPrevFrameUs = mBaseFrameUs + std::llround(
                    mFrameCount * 1000000 / mFps);
        } else {
            if (timeUs <= mPrevCaptureUs) {
                if (mFrameDropper != NULL && mFrameDropper->disabled()) {
                    // Warn only, client has disabled frame drop logic possibly for image
                    // encoding cases where camera's ZSL mode could send out of order frames.
                    ALOGW("Received frame that's going backward in time");
                } else {
                    // Drop the frame if it's going backward in time. Bad timestamp
                    // could disrupt encoder's rate control completely.
                    ALOGW("Dropping frame that's going backward in time");
                    return false;
                }
            }
            mPrevCaptureUs = timeUs;
            mPrevFrameUs = mBaseFrameUs + std::llround(
                    (timeUs - mBaseCaptureUs) * (mCaptureFps / mFps));
        }

        ALOGV("timeUs %lld, captureUs %lld, frameUs %lld",
                static_cast<long long>(timeUs),
                static_cast<long long>(mPrevCaptureUs),
                static_cast<long long>(mPrevFrameUs));
    } else {
        if (timeUs <= mPrevFrameUs) {
            if (mFrameDropper != NULL && mFrameDropper->disabled()) {
                // Warn only, client has disabled frame drop logic possibly for image
                // encoding cases where camera's ZSL mode could send out of order frames.
                ALOGW("Received frame that's going backward in time");
            } else {
                // Drop the frame if it's going backward in time. Bad timestamp
                // could disrupt encoder's rate control completely.
                ALOGW("Dropping frame that's going backward in time");
                return false;
            }
        }

        mPrevFrameUs = timeUs;
    }

    *codecTimeUs = mPrevFrameUs;
    return true;
}

status_t GraphicBufferSource::submitBuffer_l(const VideoBuffer &item) {
    CHECK(!mFreeCodecBuffers.empty());
    uint32_t codecBufferId = *mFreeCodecBuffers.begin();

    ALOGV("submitBuffer_l [slot=%d, bufferId=%d]", item.mBuffer->getSlot(), codecBufferId);

    int64_t codecTimeUs;
    if (!calculateCodecTimestamp_l(item.mTimestampNs, &codecTimeUs)) {
        return UNKNOWN_ERROR;
    }

    if ((android_dataspace)item.mDataspace != mLastDataspace) {
        onDataspaceChanged_l(
                item.mDataspace,
                (android_pixel_format)item.mBuffer->getGraphicBuffer()->format);
    }

    std::shared_ptr<AcquiredBuffer> buffer = item.mBuffer;
    // use a GraphicBuffer for now as component is using GraphicBuffers to hold references
    // and it requires this graphic buffer to be able to hold its reference
    // and thus we would need to create a new GraphicBuffer from an ANWBuffer separate from the
    // acquired GraphicBuffer.
    // TODO: this can be reworked globally to use ANWBuffer references
    sp<GraphicBuffer> graphicBuffer = buffer->getGraphicBuffer();
    status_t err = mComponent->submitBuffer(
            codecBufferId, graphicBuffer, codecTimeUs, buffer->getAcquireFenceFd());

    if (err != OK) {
        ALOGW("WARNING: emptyGraphicBuffer failed: 0x%x", err);
        return err;
    }

    mFreeCodecBuffers.erase(mFreeCodecBuffers.begin());

    ssize_t cbix = mSubmittedCodecBuffers.add(codecBufferId, buffer);
    ALOGV("emptyGraphicBuffer succeeded, bufferId=%u@%zd bufhandle=%p",
            codecBufferId, cbix, graphicBuffer->handle);
    return OK;
}

void GraphicBufferSource::submitEndOfInputStream_l() {
    CHECK(mEndOfStream);
    if (mEndOfStreamSent) {
        ALOGV("EOS already sent");
        return;
    }

    if (mFreeCodecBuffers.empty()) {
        ALOGV("submitEndOfInputStream_l: no codec buffers available");
        return;
    }
    uint32_t codecBufferId = *mFreeCodecBuffers.begin();

    // We reject any additional incoming graphic buffers. There is no acquired buffer used for EOS
    status_t err = mComponent->submitEos(codecBufferId);
    if (err != OK) {
        ALOGW("emptyDirectBuffer EOS failed: 0x%x", err);
    } else {
        mFreeCodecBuffers.erase(mFreeCodecBuffers.begin());
        ssize_t cbix = mSubmittedCodecBuffers.add(codecBufferId, nullptr);
        ALOGV("submitEndOfInputStream_l: buffer submitted, bufferId=%u@%zd", codecBufferId, cbix);
        mEndOfStreamSent = true;

        // no need to hold onto any buffers for frame repeating
        ++mRepeatLastFrameGeneration;
        mLatestBuffer.mBuffer.reset();
    }
}

status_t GraphicBufferSource::acquireBuffer_l(VideoBuffer *ab) {
    BufferItem bi;
    status_t err = mConsumer->acquireBuffer(&bi, 0);
    if (err == BufferQueue::NO_BUFFER_AVAILABLE) {
        // shouldn't happen
        ALOGW("acquireBuffer_l: frame was not available");
        return err;
    } else if (err != OK) {
        ALOGW("acquireBuffer_l: failed with err=%d", err);
        return err;
    }
    --mNumAvailableUnacquiredBuffers;

    // Manage our buffer cache.
    std::shared_ptr<CachedBuffer> buffer;
    ssize_t bsi = mBufferSlots.indexOfKey(bi.mSlot);
    if (bi.mGraphicBuffer != NULL) {
        // replace/initialize slot with new buffer
        ALOGV("acquireBuffer_l: %s buffer slot %d", bsi < 0 ? "setting" : "UPDATING", bi.mSlot);
        if (bsi >= 0) {
            discardBufferAtSlotIndex_l(bsi);
        } else {
            bsi = mBufferSlots.add(bi.mSlot, nullptr);
        }
        buffer = std::make_shared<CachedBuffer>(bi.mSlot, bi.mGraphicBuffer);
        mBufferSlots.replaceValueAt(bsi, buffer);
    } else {
        buffer = mBufferSlots.valueAt(bsi);
    }
    int64_t frameNum = bi.mFrameNumber;

    std::shared_ptr<AcquiredBuffer> acquiredBuffer =
        std::make_shared<AcquiredBuffer>(
                buffer,
                [frameNum, this](AcquiredBuffer *buffer){
                    // AcquiredBuffer's destructor should always be called when mMutex is locked.
                    // If we had a reentrant mutex, we could just lock it again to ensure this.
                    if (mMutex.tryLock() == 0) {
                        TRESPASS_DBG();
                        mMutex.unlock();
                    }

                    // we can release buffers immediately if not using adapters
                    // alternately, we could add them to mSlotsToRelease, but we would
                    // somehow need to propagate frame number to that queue
                    if (buffer->isCached()) {
                        --mNumOutstandingAcquires;
                        mConsumer->releaseBuffer(
                                buffer->getSlot(), frameNum, EGL_NO_DISPLAY, EGL_NO_SYNC_KHR,
                                buffer->getReleaseFence());
                    }
                },
                bi.mFence);
    VideoBuffer videoBuffer{acquiredBuffer, bi.mTimestamp, bi.mDataSpace};
    *ab = videoBuffer;
    ++mNumOutstandingAcquires;
    return OK;
}

// BufferQueue::ConsumerListener callback
void GraphicBufferSource::onFrameAvailable(const BufferItem& item __unused) {
    Mutex::Autolock autoLock(mMutex);

    ALOGV("onFrameAvailable: executing=%d available=%zu+%d",
            mExecuting, mAvailableBuffers.size(), mNumAvailableUnacquiredBuffers);
    ++mNumAvailableUnacquiredBuffers;

    // For BufferQueue we cannot acquire a buffer if we cannot immediately feed it to the codec
    // UNLESS we are discarding this buffer (acquiring and immediately releasing it), which makes
    // this an ugly logic.
    // NOTE: We could also rely on our debug counter but that is meant only as a debug counter.
    if (!areWeDiscardingAvailableBuffers_l() && mFreeCodecBuffers.empty()) {
        // we may not be allowed to acquire a possibly encodable buffer, so just note that
        // it is available
        ALOGV("onFrameAvailable: cannot acquire buffer right now, do it later");

        ++mRepeatLastFrameGeneration; // cancel any pending frame repeat
        return;
    }

    VideoBuffer buffer;
    status_t err = acquireBuffer_l(&buffer);
    if (err != OK) {
        ALOGE("onFrameAvailable: acquireBuffer returned err=%d", err);
    } else {
        onBufferAcquired_l(buffer);
    }
}

bool GraphicBufferSource::areWeDiscardingAvailableBuffers_l() {
    return mEndOfStreamSent // already sent EOS to codec
            || mComponent == nullptr // there is no codec connected
            || (mSuspended && mActionQueue.empty()) // we are suspended and not waiting for
                                                    // any further action
            || !mExecuting;
}

void GraphicBufferSource::onBufferAcquired_l(const VideoBuffer &buffer) {
    if (mEndOfStreamSent) {
        // This should only be possible if a new buffer was queued after
        // EOS was signaled, i.e. the app is misbehaving.
        ALOGW("onFrameAvailable: EOS is sent, ignoring frame");
    } else if (mComponent == NULL || (mSuspended && mActionQueue.empty())) {
        // FIXME: if we are suspended but have a resume queued we will stop repeating the last
        // frame. Is that the desired behavior?
        ALOGV("onFrameAvailable: suspended, ignoring frame");
    } else {
        ++mRepeatLastFrameGeneration; // cancel any pending frame repeat
        mAvailableBuffers.push_back(buffer);
        if (mExecuting) {
            fillCodecBuffer_l();
        }
    }
}

// BufferQueue::ConsumerListener callback
void GraphicBufferSource::onBuffersReleased() {
    Mutex::Autolock lock(mMutex);

    uint64_t slotMask;
    uint64_t releaseMask;
    if (mConsumer->getReleasedBuffers(&releaseMask) != NO_ERROR) {
        slotMask = 0xffffffffffffffffULL;
        ALOGW("onBuffersReleased: unable to get released buffer set");
    } else {
        slotMask = releaseMask;
        ALOGV("onBuffersReleased: 0x%016" PRIx64, slotMask);
    }

    AString unpopulated;
    for (int i = 0; i < BufferQueue::NUM_BUFFER_SLOTS; i++) {
        if ((slotMask & 0x01) != 0) {
            if (!discardBufferInSlot_l(i)) {
                if (!unpopulated.empty()) {
                    unpopulated.append(", ");
                }
                unpopulated.append(i);
            }
        }
        slotMask >>= 1;
    }
    if (!unpopulated.empty()) {
        ALOGW("released unpopulated slots: [%s]", unpopulated.c_str());
    }
}

bool GraphicBufferSource::discardBufferInSlot_l(GraphicBufferSource::slot_id i) {
    ssize_t bsi = mBufferSlots.indexOfKey(i);
    if (bsi < 0) {
        return false;
    } else {
        discardBufferAtSlotIndex_l(bsi);
        mBufferSlots.removeItemsAt(bsi);
        return true;
    }
}

void GraphicBufferSource::discardBufferAtSlotIndex_l(ssize_t bsi) {
    const std::shared_ptr<CachedBuffer>& buffer = mBufferSlots.valueAt(bsi);
    // use -2 if there is no latest buffer, and -1 if it is no longer cached
    slot_id latestBufferSlot =
        mLatestBuffer.mBuffer == nullptr ? -2 : mLatestBuffer.mBuffer->getSlot();
    ALOGV("releasing acquired buffer: [slot=%d, useCount=%ld], latest: [slot=%d]",
            mBufferSlots.keyAt(bsi), buffer.use_count(), latestBufferSlot);
    mBufferSlots.valueAt(bsi)->onDroppedFromCache();

    // If the slot of an acquired buffer is discarded, that buffer will not have to be
    // released to the producer, so account it here. However, it is possible that the
    // acquired buffer has already been discarded so check if it still is.
    if (buffer->isAcquired()) {
        --mNumOutstandingAcquires;
    }

    // clear the buffer reference (not technically needed as caller either replaces or deletes
    // it; done here for safety).
    mBufferSlots.editValueAt(bsi).reset();
    CHECK_DBG(buffer == nullptr);
}

void GraphicBufferSource::releaseAllAvailableBuffers_l() {
    mAvailableBuffers.clear();
    while (mNumAvailableUnacquiredBuffers > 0) {
        VideoBuffer item;
        if (acquireBuffer_l(&item) != OK) {
            ALOGW("releaseAllAvailableBuffers: failed to acquire available unacquired buffer");
            break;
        }
    }
}

// BufferQueue::ConsumerListener callback
void GraphicBufferSource::onSidebandStreamChanged() {
    ALOG_ASSERT(false, "GraphicBufferSource can't consume sideband streams");
}

status_t GraphicBufferSource::configure(
        const sp<ComponentWrapper>& component,
        int32_t dataSpace,
        int32_t bufferCount,
        uint32_t frameWidth,
        uint32_t frameHeight,
        uint32_t consumerUsage) {
    if (component == NULL) {
        return BAD_VALUE;
    }


    // Call setMaxAcquiredBufferCount without lock.
    // setMaxAcquiredBufferCount could call back to onBuffersReleased
    // if the buffer count change results in releasing of existing buffers,
    // which would lead to deadlock.
    status_t err = mConsumer->setMaxAcquiredBufferCount(bufferCount);
    if (err != NO_ERROR) {
        ALOGE("Unable to set BQ max acquired buffer count to %u: %d",
                bufferCount, err);
        return err;
    }

    {
        Mutex::Autolock autoLock(mMutex);
        mComponent = component;

        err = mConsumer->setDefaultBufferSize(frameWidth, frameHeight);
        if (err != NO_ERROR) {
            ALOGE("Unable to set BQ default buffer size to %ux%u: %d",
                    frameWidth, frameHeight, err);
            return err;
        }

        consumerUsage |= GRALLOC_USAGE_HW_VIDEO_ENCODER;
        mConsumer->setConsumerUsageBits(consumerUsage);

        // Set impl. defined format as default. Depending on the usage flags
        // the device-specific implementation will derive the exact format.
        err = mConsumer->setDefaultBufferFormat(HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED);
        if (err != NO_ERROR) {
            ALOGE("Failed to configure surface default format ret: %d", err);
            return err;
        }

        // Sets the default buffer data space
        ALOGD("setting dataspace: %#x, acquired=%d", dataSpace, mNumOutstandingAcquires);
        mConsumer->setDefaultBufferDataSpace((android_dataspace)dataSpace);
        mLastDataspace = (android_dataspace)dataSpace;

        mExecuting = false;
        mSuspended = false;
        mEndOfStream = false;
        mEndOfStreamSent = false;
        mSkipFramesBeforeNs = -1LL;
        mFrameDropper.clear();
        mFrameRepeatIntervalUs = -1LL;
        mRepeatLastFrameGeneration = 0;
        mOutstandingFrameRepeatCount = 0;
        mLatestBuffer.mBuffer.reset();
        mFrameRepeatBlockedOnCodecBuffer = false;
        mFps = -1.0;
        mCaptureFps = -1.0;
        mBaseCaptureUs = -1LL;
        mBaseFrameUs = -1LL;
        mPrevCaptureUs = -1LL;
        mPrevFrameUs = -1LL;
        mFrameCount = 0;
        mInputBufferTimeOffsetUs = 0;
        mStopTimeUs = -1;
        mActionQueue.clear();
    }

    return OK;
}

status_t GraphicBufferSource::setSuspend(bool suspend, int64_t suspendStartTimeUs) {
    ALOGV("setSuspend=%d at time %lld us", suspend, (long long)suspendStartTimeUs);

    Mutex::Autolock autoLock(mMutex);

    if (mStopTimeUs != -1) {
        ALOGE("setSuspend failed as STOP action is pending");
        return INVALID_OPERATION;
    }

    // Push the action to the queue.
    if (suspendStartTimeUs != -1) {
        // suspendStartTimeUs must be smaller or equal to current systemTime.
        int64_t currentSystemTimeUs = systemTime() / 1000;
        if (suspendStartTimeUs > currentSystemTimeUs) {
            ALOGE("setSuspend failed. %lld is larger than current system time %lld us",
                    (long long)suspendStartTimeUs, (long long)currentSystemTimeUs);
            return INVALID_OPERATION;
        }
        if (mLastActionTimeUs != -1 && suspendStartTimeUs < mLastActionTimeUs) {
            ALOGE("setSuspend failed. %lld is smaller than last action time %lld us",
                    (long long)suspendStartTimeUs, (long long)mLastActionTimeUs);
            return INVALID_OPERATION;
        }
        mLastActionTimeUs = suspendStartTimeUs;
        ActionItem action;
        action.mAction = suspend ? ActionItem::PAUSE : ActionItem::RESUME;
        action.mActionTimeUs = suspendStartTimeUs;
        ALOGV("Push %s action into actionQueue", suspend ? "PAUSE" : "RESUME");
        mActionQueue.push_back(action);
    } else {
        if (suspend) {
            mSuspended = true;
            releaseAllAvailableBuffers_l();
            return OK;
        } else {
            mSuspended = false;
            if (mExecuting && !haveAvailableBuffers_l()
                    && mFrameRepeatBlockedOnCodecBuffer) {
                if (repeatLatestBuffer_l()) {
                    ALOGV("suspend/deferred repeatLatestBuffer_l SUCCESS");
                    mFrameRepeatBlockedOnCodecBuffer = false;
                } else {
                    ALOGV("suspend/deferred repeatLatestBuffer_l FAILURE");
                }
            }
        }
    }
    return OK;
}

status_t GraphicBufferSource::setRepeatPreviousFrameDelayUs(int64_t repeatAfterUs) {
    ALOGV("setRepeatPreviousFrameDelayUs: delayUs=%lld", (long long)repeatAfterUs);

    Mutex::Autolock autoLock(mMutex);

    if (mExecuting || repeatAfterUs <= 0LL) {
        return INVALID_OPERATION;
    }

    mFrameRepeatIntervalUs = repeatAfterUs;
    return OK;
}

status_t GraphicBufferSource::setTimeOffsetUs(int64_t timeOffsetUs) {
    Mutex::Autolock autoLock(mMutex);

    // timeOffsetUs must be negative for adjustment.
    if (timeOffsetUs >= 0LL) {
        return INVALID_OPERATION;
    }

    mInputBufferTimeOffsetUs = timeOffsetUs;
    return OK;
}

status_t GraphicBufferSource::setMaxFps(float maxFps) {
    ALOGV("setMaxFps: maxFps=%lld", (long long)maxFps);

    Mutex::Autolock autoLock(mMutex);

    if (mExecuting) {
        return INVALID_OPERATION;
    }

    mFrameDropper = new FrameDropper();
    status_t err = mFrameDropper->setMaxFrameRate(maxFps);
    if (err != OK) {
        mFrameDropper.clear();
        return err;
    }

    return OK;
}

status_t GraphicBufferSource::setStartTimeUs(int64_t skipFramesBeforeUs) {
    ALOGV("setStartTimeUs: skipFramesBeforeUs=%lld", (long long)skipFramesBeforeUs);

    Mutex::Autolock autoLock(mMutex);

    mSkipFramesBeforeNs =
            (skipFramesBeforeUs > 0 && skipFramesBeforeUs <= INT64_MAX / 1000) ?
            (skipFramesBeforeUs * 1000) : -1LL;

    return OK;
}

status_t GraphicBufferSource::setStopTimeUs(int64_t stopTimeUs) {
    ALOGV("setStopTimeUs: %lld us", (long long)stopTimeUs);
    Mutex::Autolock autoLock(mMutex);

    if (mStopTimeUs != -1) {
        // Ignore if stop time has already been set
        return OK;
    }

    // stopTimeUs must be smaller or equal to current systemTime.
    int64_t currentSystemTimeUs = systemTime() / 1000;
    if (stopTimeUs > currentSystemTimeUs) {
        ALOGE("setStopTimeUs failed. %lld is larger than current system time %lld us",
            (long long)stopTimeUs, (long long)currentSystemTimeUs);
        return INVALID_OPERATION;
    }
    if (mLastActionTimeUs != -1 && stopTimeUs < mLastActionTimeUs) {
        ALOGE("setSuspend failed. %lld is smaller than last action time %lld us",
            (long long)stopTimeUs, (long long)mLastActionTimeUs);
        return INVALID_OPERATION;
    }
    mLastActionTimeUs = stopTimeUs;
    ActionItem action;
    action.mAction = ActionItem::STOP;
    action.mActionTimeUs = stopTimeUs;
    mActionQueue.push_back(action);
    mStopTimeUs = stopTimeUs;
    return OK;
}

status_t GraphicBufferSource::getStopTimeOffsetUs(int64_t *stopTimeOffsetUs) {
    ALOGV("getStopTimeOffsetUs");
    Mutex::Autolock autoLock(mMutex);
    if (mStopTimeUs == -1) {
        ALOGW("Fail to return stopTimeOffsetUs as stop time is not set");
        return INVALID_OPERATION;
    }
    *stopTimeOffsetUs =
        mLastFrameTimestampUs == -1 ? 0 : mStopTimeUs - mLastFrameTimestampUs;
    return OK;
}

status_t GraphicBufferSource::setTimeLapseConfig(double fps, double captureFps) {
    ALOGV("setTimeLapseConfig: fps=%lg, captureFps=%lg",
            fps, captureFps);
    Mutex::Autolock autoLock(mMutex);

    if (mExecuting || !(fps > 0) || !(captureFps > 0)) {
        return INVALID_OPERATION;
    }

    mFps = fps;
    mCaptureFps = captureFps;
    if (captureFps > fps) {
        mSnapTimestamps = 1 == base::GetIntProperty(
                "debug.stagefright.snap_timestamps", int64_t(0));
    } else {
        mSnapTimestamps = false;
    }

    return OK;
}

status_t GraphicBufferSource::setColorAspects(int32_t aspectsPacked) {
    Mutex::Autolock autoLock(mMutex);
    mDefaultColorAspectsPacked = aspectsPacked;
    ColorAspects colorAspects = ColorUtils::unpackToColorAspects(aspectsPacked);
    ALOGD("requesting color aspects (R:%d(%s), P:%d(%s), M:%d(%s), T:%d(%s))",
            colorAspects.mRange, asString(colorAspects.mRange),
            colorAspects.mPrimaries, asString(colorAspects.mPrimaries),
            colorAspects.mMatrixCoeffs, asString(colorAspects.mMatrixCoeffs),
            colorAspects.mTransfer, asString(colorAspects.mTransfer));

    return OK;
}

status_t GraphicBufferSource::signalEndOfInputStream() {
    Mutex::Autolock autoLock(mMutex);
    ALOGV("signalEndOfInputStream: executing=%d available=%zu+%d eos=%d",
            mExecuting, mAvailableBuffers.size(), mNumAvailableUnacquiredBuffers, mEndOfStream);

    if (mEndOfStream) {
        ALOGE("EOS was already signaled");
        return INVALID_OPERATION;
    }

    // Set the end-of-stream flag.  If no frames are pending from the
    // BufferQueue, and a codec buffer is available, and we're executing,
    // and there is no stop timestamp, we initiate the EOS from here.
    // Otherwise, we'll let codecBufferEmptied() (or start) do it.
    //
    // Note: if there are no pending frames and all codec buffers are
    // available, we *must* submit the EOS from here or we'll just
    // stall since no future events are expected.
    mEndOfStream = true;

    if (mStopTimeUs == -1 && mExecuting && !haveAvailableBuffers_l()) {
        submitEndOfInputStream_l();
    }

    return OK;
}

void GraphicBufferSource::onMessageReceived(const sp<AMessage> &msg) {
    switch (msg->what()) {
        case kWhatRepeatLastFrame:
        {
            Mutex::Autolock autoLock(mMutex);

            int32_t generation;
            CHECK(msg->findInt32("generation", &generation));

            if (generation != mRepeatLastFrameGeneration) {
                // stale
                break;
            }

            if (!mExecuting || haveAvailableBuffers_l()) {
                break;
            }

            bool success = repeatLatestBuffer_l();
            if (success) {
                ALOGV("repeatLatestBuffer_l SUCCESS");
            } else {
                ALOGV("repeatLatestBuffer_l FAILURE");
                mFrameRepeatBlockedOnCodecBuffer = true;
            }
            break;
        }

        default:
            TRESPASS();
    }
}

}  // namespace android
