Home | History | Annotate | Download | only in omx
      1 /*
      2  * Copyright (C) 2013 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 #include <inttypes.h>
     18 
     19 #define LOG_TAG "GraphicBufferSource"
     20 //#define LOG_NDEBUG 0
     21 #include <utils/Log.h>
     22 
     23 #define STRINGIFY_ENUMS // for asString in HardwareAPI.h/VideoAPI.h
     24 
     25 #include <media/stagefright/omx/GraphicBufferSource.h>
     26 #include <media/stagefright/omx/FrameDropper.h>
     27 #include <media/stagefright/omx/OMXUtils.h>
     28 #include <media/stagefright/foundation/ADebug.h>
     29 #include <media/stagefright/foundation/AMessage.h>
     30 #include <media/stagefright/foundation/ColorUtils.h>
     31 #include <media/stagefright/foundation/FileDescriptor.h>
     32 
     33 #include <media/hardware/MetadataBufferType.h>
     34 #include <ui/GraphicBuffer.h>
     35 #include <gui/BufferItem.h>
     36 #include <media/hardware/HardwareAPI.h>
     37 #include <media/openmax/OMX_Component.h>
     38 #include <media/openmax/OMX_IndexExt.h>
     39 #include <media/OMXBuffer.h>
     40 
     41 #include <inttypes.h>
     42 
     43 #include <functional>
     44 #include <memory>
     45 #include <cmath>
     46 
     47 namespace android {
     48 
     49 /**
     50  * A copiable object managing a buffer in the buffer cache managed by the producer. This object
     51  * holds a reference to the buffer, and maintains which buffer slot it belongs to (if any), and
     52  * whether it is still in a buffer slot. It also maintains whether there are any outstanging acquire
     53  * references to it (by buffers acquired from the slot) mainly so that we can keep a debug
     54  * count of how many buffers we need to still release back to the producer.
     55  */
     56 struct GraphicBufferSource::CachedBuffer {
     57     /**
     58      * Token that is used to track acquire counts (as opposed to all references to this object).
     59      */
     60     struct Acquirable { };
     61 
     62     /**
     63      * Create using a buffer cached in a slot.
     64      */
     65     CachedBuffer(slot_id slot, const sp<GraphicBuffer> &graphicBuffer)
     66         : mIsCached(true),
     67           mSlot(slot),
     68           mGraphicBuffer(graphicBuffer),
     69           mAcquirable(std::make_shared<Acquirable>()) {
     70     }
     71 
     72     /**
     73      * Returns the cache slot that this buffer is cached in, or -1 if it is no longer cached.
     74      *
     75      * This assumes that -1 slot id is invalid; though, it is just a benign collision used for
     76      * debugging. This object explicitly manages whether it is still cached.
     77      */
     78     slot_id getSlot() const {
     79         return mIsCached ? mSlot : -1;
     80     }
     81 
     82     /**
     83      * Returns the cached buffer.
     84      */
     85     sp<GraphicBuffer> getGraphicBuffer() const {
     86         return mGraphicBuffer;
     87     }
     88 
     89     /**
     90      * Checks whether this buffer is still in the buffer cache.
     91      */
     92     bool isCached() const {
     93         return mIsCached;
     94     }
     95 
     96     /**
     97      * Checks whether this buffer has an acquired reference.
     98      */
     99     bool isAcquired() const {
    100         return mAcquirable.use_count() > 1;
    101     }
    102 
    103     /**
    104      * Gets and returns a shared acquired reference.
    105      */
    106     std::shared_ptr<Acquirable> getAcquirable() {
    107         return mAcquirable;
    108     }
    109 
    110 private:
    111     friend void GraphicBufferSource::discardBufferAtSlotIndex_l(ssize_t);
    112 
    113     /**
    114      * This method to be called when the buffer is no longer in the buffer cache.
    115      * Called from discardBufferAtSlotIndex_l.
    116      */
    117     void onDroppedFromCache() {
    118         CHECK_DBG(mIsCached);
    119         mIsCached = false;
    120     }
    121 
    122     bool mIsCached;
    123     slot_id mSlot;
    124     sp<GraphicBuffer> mGraphicBuffer;
    125     std::shared_ptr<Acquirable> mAcquirable;
    126 };
    127 
    128 /**
    129  * A copiable object managing a buffer acquired from the producer. This must always be a cached
    130  * buffer. This objects also manages its acquire fence and any release fences that may be returned
    131  * by the encoder for this buffer (this buffer may be queued to the encoder multiple times).
    132  * If no release fences are added by the encoder, the acquire fence is returned as the release
    133  * fence for this - as it is assumed that noone waited for the acquire fence. Otherwise, it is
    134  * assumed that the encoder has waited for the acquire fence (or returned it as the release
    135  * fence).
    136  */
    137 struct GraphicBufferSource::AcquiredBuffer {
    138     AcquiredBuffer(
    139             const std::shared_ptr<CachedBuffer> &buffer,
    140             std::function<void(AcquiredBuffer *)> onReleased,
    141             const sp<Fence> &acquireFence)
    142         : mBuffer(buffer),
    143           mAcquirable(buffer->getAcquirable()),
    144           mAcquireFence(acquireFence),
    145           mGotReleaseFences(false),
    146           mOnReleased(onReleased) {
    147     }
    148 
    149     /**
    150      * Adds a release fence returned by the encoder to this object. If this is called with an
    151      * valid file descriptor, it is added to the list of release fences. These are returned to the
    152      * producer on release() as a merged fence. Regardless of the validity of the file descriptor,
    153      * we take note that a release fence was attempted to be added and the acquire fence can now be
    154      * assumed as acquired.
    155      */
    156     void addReleaseFenceFd(int fenceFd) {
    157         // save all release fences - these will be propagated to the producer if this buffer is
    158         // ever released to it
    159         if (fenceFd >= 0) {
    160             mReleaseFenceFds.push_back(fenceFd);
    161         }
    162         mGotReleaseFences = true;
    163     }
    164 
    165     /**
    166      * Returns the acquire fence file descriptor associated with this object.
    167      */
    168     int getAcquireFenceFd() {
    169         if (mAcquireFence == nullptr || !mAcquireFence->isValid()) {
    170             return -1;
    171         }
    172         return mAcquireFence->dup();
    173     }
    174 
    175     /**
    176      * Returns whether the buffer is still in the buffer cache.
    177      */
    178     bool isCached() const {
    179         return mBuffer->isCached();
    180     }
    181 
    182     /**
    183      * Returns the acquired buffer.
    184      */
    185     sp<GraphicBuffer> getGraphicBuffer() const {
    186         return mBuffer->getGraphicBuffer();
    187     }
    188 
    189     /**
    190      * Returns the slot that this buffer is cached at, or -1 otherwise.
    191      *
    192      * This assumes that -1 slot id is invalid; though, it is just a benign collision used for
    193      * debugging. This object explicitly manages whether it is still cached.
    194      */
    195     slot_id getSlot() const {
    196         return mBuffer->getSlot();
    197     }
    198 
    199     /**
    200      * Creates and returns a release fence object from the acquire fence and/or any release fences
    201      * added. If no release fences were added (even if invalid), returns the acquire fence.
    202      * Otherwise, it returns a merged fence from all the valid release fences added.
    203      */
    204     sp<Fence> getReleaseFence() {
    205         // If did not receive release fences, we assume this buffer was not consumed (it was
    206         // discarded or dropped). In this case release the acquire fence as the release fence.
    207         // We do this here to avoid a dup, close and recreation of the Fence object.
    208         if (!mGotReleaseFences) {
    209             return mAcquireFence;
    210         }
    211         sp<Fence> ret = getReleaseFence(0, mReleaseFenceFds.size());
    212         // clear fds as fence took ownership of them
    213         mReleaseFenceFds.clear();
    214         return ret;
    215     }
    216 
    217     // this video buffer is no longer referenced by the codec (or kept for later encoding)
    218     // it is now safe to release to the producer
    219     ~AcquiredBuffer() {
    220         //mAcquirable.clear();
    221         mOnReleased(this);
    222         // mOnRelease method should call getReleaseFence() that releases all fds but just in case
    223         ALOGW_IF(!mReleaseFenceFds.empty(), "release fences were not obtained, closing fds");
    224         for (int fildes : mReleaseFenceFds) {
    225             ::close(fildes);
    226             TRESPASS_DBG();
    227         }
    228     }
    229 
    230 private:
    231     std::shared_ptr<GraphicBufferSource::CachedBuffer> mBuffer;
    232     std::shared_ptr<GraphicBufferSource::CachedBuffer::Acquirable> mAcquirable;
    233     sp<Fence> mAcquireFence;
    234     Vector<int> mReleaseFenceFds;
    235     bool mGotReleaseFences;
    236     std::function<void(AcquiredBuffer *)> mOnReleased;
    237 
    238     /**
    239      * Creates and returns a release fence from 0 or more release fence file descriptors in from
    240      * the specified range in the array.
    241      *
    242      * @param start start index
    243      * @param num   number of release fds to merge
    244      */
    245     sp<Fence> getReleaseFence(size_t start, size_t num) const {
    246         if (num == 0) {
    247             return Fence::NO_FENCE;
    248         } else if (num == 1) {
    249             return new Fence(mReleaseFenceFds[start]);
    250         } else {
    251             return Fence::merge("GBS::AB",
    252                                 getReleaseFence(start, num >> 1),
    253                                 getReleaseFence(start + (num >> 1), num - (num >> 1)));
    254         }
    255     }
    256 };
    257 
    258 GraphicBufferSource::GraphicBufferSource() :
    259     mInitCheck(UNKNOWN_ERROR),
    260     mNumAvailableUnacquiredBuffers(0),
    261     mNumOutstandingAcquires(0),
    262     mEndOfStream(false),
    263     mEndOfStreamSent(false),
    264     mLastDataspace(HAL_DATASPACE_UNKNOWN),
    265     mExecuting(false),
    266     mSuspended(false),
    267     mLastFrameTimestampUs(-1),
    268     mStopTimeUs(-1),
    269     mLastActionTimeUs(-1ll),
    270     mSkipFramesBeforeNs(-1ll),
    271     mFrameRepeatIntervalUs(-1ll),
    272     mRepeatLastFrameGeneration(0),
    273     mOutstandingFrameRepeatCount(0),
    274     mFrameRepeatBlockedOnCodecBuffer(false),
    275     mFps(-1.0),
    276     mCaptureFps(-1.0),
    277     mBaseCaptureUs(-1ll),
    278     mBaseFrameUs(-1ll),
    279     mFrameCount(0),
    280     mPrevCaptureUs(-1ll),
    281     mPrevFrameUs(-1ll),
    282     mInputBufferTimeOffsetUs(0ll) {
    283     ALOGV("GraphicBufferSource");
    284 
    285     String8 name("GraphicBufferSource");
    286 
    287     BufferQueue::createBufferQueue(&mProducer, &mConsumer);
    288     mConsumer->setConsumerName(name);
    289 
    290     // Note that we can't create an sp<...>(this) in a ctor that will not keep a
    291     // reference once the ctor ends, as that would cause the refcount of 'this'
    292     // dropping to 0 at the end of the ctor.  Since all we need is a wp<...>
    293     // that's what we create.
    294     wp<BufferQueue::ConsumerListener> listener =
    295             static_cast<BufferQueue::ConsumerListener*>(this);
    296     sp<IConsumerListener> proxy =
    297             new BufferQueue::ProxyConsumerListener(listener);
    298 
    299     mInitCheck = mConsumer->consumerConnect(proxy, false);
    300     if (mInitCheck != NO_ERROR) {
    301         ALOGE("Error connecting to BufferQueue: %s (%d)",
    302                 strerror(-mInitCheck), mInitCheck);
    303         return;
    304     }
    305 
    306     memset(&mDefaultColorAspectsPacked, 0, sizeof(mDefaultColorAspectsPacked));
    307 
    308     CHECK(mInitCheck == NO_ERROR);
    309 }
    310 
    311 GraphicBufferSource::~GraphicBufferSource() {
    312     ALOGV("~GraphicBufferSource");
    313     {
    314         // all acquired buffers must be freed with the mutex locked otherwise our debug assertion
    315         // may trigger
    316         Mutex::Autolock autoLock(mMutex);
    317         mAvailableBuffers.clear();
    318         mSubmittedCodecBuffers.clear();
    319         mLatestBuffer.mBuffer.reset();
    320     }
    321 
    322     if (mNumOutstandingAcquires != 0) {
    323         ALOGW("potential buffer leak: acquired=%d", mNumOutstandingAcquires);
    324         TRESPASS_DBG();
    325     }
    326     if (mConsumer != NULL) {
    327         status_t err = mConsumer->consumerDisconnect();
    328         if (err != NO_ERROR) {
    329             ALOGW("consumerDisconnect failed: %d", err);
    330         }
    331     }
    332 }
    333 
    334 Status GraphicBufferSource::onOmxExecuting() {
    335     Mutex::Autolock autoLock(mMutex);
    336     ALOGV("--> executing; available=%zu, submittable=%zd",
    337             mAvailableBuffers.size(), mFreeCodecBuffers.size());
    338     CHECK(!mExecuting);
    339     mExecuting = true;
    340     mLastDataspace = HAL_DATASPACE_UNKNOWN;
    341     ALOGV("clearing last dataSpace");
    342 
    343     // Start by loading up as many buffers as possible.  We want to do this,
    344     // rather than just submit the first buffer, to avoid a degenerate case:
    345     // if all BQ buffers arrive before we start executing, and we only submit
    346     // one here, the other BQ buffers will just sit until we get notified
    347     // that the codec buffer has been released.  We'd then acquire and
    348     // submit a single additional buffer, repeatedly, never using more than
    349     // one codec buffer simultaneously.  (We could instead try to submit
    350     // all BQ buffers whenever any codec buffer is freed, but if we get the
    351     // initial conditions right that will never be useful.)
    352     while (haveAvailableBuffers_l()) {
    353         if (!fillCodecBuffer_l()) {
    354             ALOGV("stop load with available=%zu+%d",
    355                     mAvailableBuffers.size(), mNumAvailableUnacquiredBuffers);
    356             break;
    357         }
    358     }
    359 
    360     ALOGV("done loading initial frames, available=%zu+%d",
    361             mAvailableBuffers.size(), mNumAvailableUnacquiredBuffers);
    362 
    363     // If EOS has already been signaled, and there are no more frames to
    364     // submit, try to send EOS now as well.
    365     if (mStopTimeUs == -1 && mEndOfStream && !haveAvailableBuffers_l()) {
    366         submitEndOfInputStream_l();
    367     }
    368 
    369     if (mFrameRepeatIntervalUs > 0ll && mLooper == NULL) {
    370         mReflector = new AHandlerReflector<GraphicBufferSource>(this);
    371 
    372         mLooper = new ALooper;
    373         mLooper->registerHandler(mReflector);
    374         mLooper->start();
    375 
    376         if (mLatestBuffer.mBuffer != nullptr) {
    377             queueFrameRepeat_l();
    378         }
    379     }
    380 
    381     return Status::ok();
    382 }
    383 
    384 Status GraphicBufferSource::onOmxIdle() {
    385     ALOGV("omxIdle");
    386 
    387     Mutex::Autolock autoLock(mMutex);
    388 
    389     if (mExecuting) {
    390         // We are only interested in the transition from executing->idle,
    391         // not loaded->idle.
    392         mExecuting = false;
    393     }
    394     return Status::ok();
    395 }
    396 
    397 Status GraphicBufferSource::onOmxLoaded(){
    398     Mutex::Autolock autoLock(mMutex);
    399     if (mLooper != NULL) {
    400         mLooper->unregisterHandler(mReflector->id());
    401         mReflector.clear();
    402 
    403         mLooper->stop();
    404         mLooper.clear();
    405     }
    406 
    407     ALOGV("--> loaded; available=%zu+%d eos=%d eosSent=%d acquired=%d",
    408             mAvailableBuffers.size(), mNumAvailableUnacquiredBuffers,
    409             mEndOfStream, mEndOfStreamSent, mNumOutstandingAcquires);
    410 
    411     // Codec is no longer executing.  Releasing all buffers to bq.
    412     mFreeCodecBuffers.clear();
    413     mSubmittedCodecBuffers.clear();
    414     mLatestBuffer.mBuffer.reset();
    415     mOMXNode.clear();
    416     mExecuting = false;
    417 
    418     return Status::ok();
    419 }
    420 
    421 Status GraphicBufferSource::onInputBufferAdded(codec_buffer_id bufferId) {
    422     Mutex::Autolock autoLock(mMutex);
    423 
    424     if (mExecuting) {
    425         // This should never happen -- buffers can only be allocated when
    426         // transitioning from "loaded" to "idle".
    427         ALOGE("addCodecBuffer: buffer added while executing");
    428         return Status::fromServiceSpecificError(INVALID_OPERATION);
    429     }
    430 
    431     ALOGV("addCodecBuffer: bufferId=%u", bufferId);
    432 
    433     mFreeCodecBuffers.push_back(bufferId);
    434     return Status::ok();
    435 }
    436 
    437 Status GraphicBufferSource::onInputBufferEmptied(codec_buffer_id bufferId, int fenceFd) {
    438     Mutex::Autolock autoLock(mMutex);
    439     FileDescriptor::Autoclose fence(fenceFd);
    440 
    441     ssize_t cbi = mSubmittedCodecBuffers.indexOfKey(bufferId);
    442     if (cbi < 0) {
    443         // This should never happen.
    444         ALOGE("onInputBufferEmptied: buffer not recognized (bufferId=%u)", bufferId);
    445         return Status::fromServiceSpecificError(BAD_VALUE);
    446     }
    447 
    448     std::shared_ptr<AcquiredBuffer> buffer = mSubmittedCodecBuffers.valueAt(cbi);
    449 
    450     // Move buffer to available buffers
    451     mSubmittedCodecBuffers.removeItemsAt(cbi);
    452     mFreeCodecBuffers.push_back(bufferId);
    453 
    454     // header->nFilledLen may not be the original value, so we can't compare
    455     // that to zero to see of this was the EOS buffer.  Instead we just
    456     // see if there is a null AcquiredBuffer, which should only ever happen for EOS.
    457     if (buffer == nullptr) {
    458         if (!(mEndOfStream && mEndOfStreamSent)) {
    459             // This can happen when broken code sends us the same buffer twice in a row.
    460             ALOGE("onInputBufferEmptied: non-EOS null buffer (bufferId=%u)", bufferId);
    461         } else {
    462             ALOGV("onInputBufferEmptied: EOS null buffer (bufferId=%u@%zd)", bufferId, cbi);
    463         }
    464         // No GraphicBuffer to deal with, no additional input or output is expected, so just return.
    465         return Status::fromServiceSpecificError(BAD_VALUE);
    466     }
    467 
    468     if (!mExecuting) {
    469         // this is fine since this could happen when going from Idle to Loaded
    470         ALOGV("onInputBufferEmptied: no longer executing (bufferId=%u@%zd)", bufferId, cbi);
    471         return Status::fromServiceSpecificError(OK);
    472     }
    473 
    474     ALOGV("onInputBufferEmptied: bufferId=%d@%zd [slot=%d, useCount=%ld, handle=%p] acquired=%d",
    475             bufferId, cbi, buffer->getSlot(), buffer.use_count(), buffer->getGraphicBuffer()->handle,
    476             mNumOutstandingAcquires);
    477 
    478     buffer->addReleaseFenceFd(fence.release());
    479     // release codec reference for video buffer just in case remove does not it
    480     buffer.reset();
    481 
    482     if (haveAvailableBuffers_l()) {
    483         // Fill this codec buffer.
    484         CHECK(!mEndOfStreamSent);
    485         ALOGV("onInputBufferEmptied: buffer freed, feeding codec (available=%zu+%d, eos=%d)",
    486                 mAvailableBuffers.size(), mNumAvailableUnacquiredBuffers, mEndOfStream);
    487         fillCodecBuffer_l();
    488     } else if (mEndOfStream && mStopTimeUs == -1) {
    489         // No frames available, but EOS is pending and no stop time, so use this buffer to
    490         // send that.
    491         ALOGV("onInputBufferEmptied: buffer freed, submitting EOS");
    492         submitEndOfInputStream_l();
    493     } else if (mFrameRepeatBlockedOnCodecBuffer) {
    494         bool success = repeatLatestBuffer_l();
    495         ALOGV("onInputBufferEmptied: completing deferred repeatLatestBuffer_l %s",
    496                 success ? "SUCCESS" : "FAILURE");
    497         mFrameRepeatBlockedOnCodecBuffer = false;
    498     }
    499 
    500     // releaseReleasableBuffers_l();
    501     return Status::ok();
    502 }
    503 
    504 void GraphicBufferSource::onDataspaceChanged_l(
    505         android_dataspace dataspace, android_pixel_format pixelFormat) {
    506     ALOGD("got buffer with new dataSpace #%x", dataspace);
    507     mLastDataspace = dataspace;
    508 
    509     if (ColorUtils::convertDataSpaceToV0(dataspace)) {
    510         mOMXNode->dispatchDataSpaceChanged(mLastDataspace, mDefaultColorAspectsPacked, pixelFormat);
    511     }
    512 }
    513 
    514 bool GraphicBufferSource::fillCodecBuffer_l() {
    515     CHECK(mExecuting && haveAvailableBuffers_l());
    516 
    517     if (mFreeCodecBuffers.empty()) {
    518         // No buffers available, bail.
    519         ALOGV("fillCodecBuffer_l: no codec buffers, available=%zu+%d",
    520                 mAvailableBuffers.size(), mNumAvailableUnacquiredBuffers);
    521         return false;
    522     }
    523 
    524     VideoBuffer item;
    525     if (mAvailableBuffers.empty()) {
    526         ALOGV("fillCodecBuffer_l: acquiring available buffer, available=%zu+%d",
    527                 mAvailableBuffers.size(), mNumAvailableUnacquiredBuffers);
    528         if (acquireBuffer_l(&item) != OK) {
    529             ALOGE("fillCodecBuffer_l: failed to acquire available buffer");
    530             return false;
    531         }
    532     } else {
    533         ALOGV("fillCodecBuffer_l: getting available buffer, available=%zu+%d",
    534                 mAvailableBuffers.size(), mNumAvailableUnacquiredBuffers);
    535         item = *mAvailableBuffers.begin();
    536         mAvailableBuffers.erase(mAvailableBuffers.begin());
    537     }
    538 
    539     int64_t itemTimeUs = item.mTimestampNs / 1000;
    540 
    541     // Process ActionItem in the Queue if there is any. If a buffer's timestamp
    542     // is smaller than the first action's timestamp, no action need to be performed.
    543     // If buffer's timestamp is larger or equal than the last action's timestamp,
    544     // only the last action needs to be performed as all the acitions before the
    545     // the action are overridden by the last action. For the other cases, traverse
    546     // the Queue to find the newest action that with timestamp smaller or equal to
    547     // the buffer's timestamp. For example, an action queue like
    548     // [pause 1us], [resume 2us], [pause 3us], [resume 4us], [pause 5us].... Upon
    549     // receiving a buffer with timestamp 3.5us, only the action [pause, 3us] needs
    550     // to be handled and [pause, 1us], [resume 2us] will be discarded.
    551     bool done = false;
    552     bool seeStopAction = false;
    553     if (!mActionQueue.empty()) {
    554         // First scan to check if bufferTimestamp is smaller than first action's timestamp.
    555         ActionItem nextAction = *(mActionQueue.begin());
    556         if (itemTimeUs < nextAction.mActionTimeUs) {
    557             ALOGV("No action. buffer timestamp %lld us < action timestamp: %lld us",
    558                 (long long)itemTimeUs, (long long)nextAction.mActionTimeUs);
    559             // All the actions are ahead. No action need to perform now.
    560             // Release the buffer if is in suspended state, or process the buffer
    561             // if not in suspended state.
    562             done = true;
    563         }
    564 
    565         if (!done) {
    566             // Find the newest action that with timestamp smaller than itemTimeUs. Then
    567             // remove all the actions before and include the newest action.
    568             List<ActionItem>::iterator it = mActionQueue.begin();
    569             while (it != mActionQueue.end() && it->mActionTimeUs <= itemTimeUs
    570                     && nextAction.mAction != ActionItem::STOP) {
    571                 nextAction = *it;
    572                 ++it;
    573             }
    574             mActionQueue.erase(mActionQueue.begin(), it);
    575 
    576             CHECK(itemTimeUs >= nextAction.mActionTimeUs);
    577             switch (nextAction.mAction) {
    578                 case ActionItem::PAUSE:
    579                 {
    580                     mSuspended = true;
    581                     ALOGV("RUNNING/PAUSE -> PAUSE at buffer %lld us  PAUSE Time: %lld us",
    582                             (long long)itemTimeUs, (long long)nextAction.mActionTimeUs);
    583                     break;
    584                 }
    585                 case ActionItem::RESUME:
    586                 {
    587                     mSuspended = false;
    588                     ALOGV("PAUSE/RUNNING -> RUNNING at buffer %lld us  RESUME Time: %lld us",
    589                             (long long)itemTimeUs, (long long)nextAction.mActionTimeUs);
    590                     break;
    591                 }
    592                 case ActionItem::STOP:
    593                 {
    594                     ALOGV("RUNNING/PAUSE -> STOP at buffer %lld us  STOP Time: %lld us",
    595                             (long long)itemTimeUs, (long long)nextAction.mActionTimeUs);
    596                     // Clear the whole ActionQueue as recording is done
    597                     mActionQueue.clear();
    598                     seeStopAction = true;
    599                     break;
    600                 }
    601                 default:
    602                     TRESPASS_DBG("Unknown action type");
    603                     // return true here because we did consume an available buffer, so the
    604                     // loop in onOmxExecuting will eventually terminate even if we hit this.
    605                     return false;
    606             }
    607         }
    608     }
    609 
    610     if (seeStopAction) {
    611         // Clear all the buffers before setting mEndOfStream and signal EndOfInputStream.
    612         releaseAllAvailableBuffers_l();
    613         mEndOfStream = true;
    614         submitEndOfInputStream_l();
    615         return true;
    616     }
    617 
    618     if (mSuspended) {
    619         return true;
    620     }
    621 
    622     int err = UNKNOWN_ERROR;
    623 
    624     // only submit sample if start time is unspecified, or sample
    625     // is queued after the specified start time
    626     if (mSkipFramesBeforeNs < 0ll || item.mTimestampNs >= mSkipFramesBeforeNs) {
    627         // if start time is set, offset time stamp by start time
    628         if (mSkipFramesBeforeNs > 0) {
    629             item.mTimestampNs -= mSkipFramesBeforeNs;
    630         }
    631 
    632         int64_t timeUs = item.mTimestampNs / 1000;
    633         if (mFrameDropper != NULL && mFrameDropper->shouldDrop(timeUs)) {
    634             ALOGV("skipping frame (%lld) to meet max framerate", static_cast<long long>(timeUs));
    635             // set err to OK so that the skipped frame can still be saved as the lastest frame
    636             err = OK;
    637         } else {
    638             err = submitBuffer_l(item); // this takes shared ownership of the acquired buffer on succeess
    639         }
    640     }
    641 
    642     if (err != OK) {
    643         ALOGV("submitBuffer_l failed, will release bq slot %d", item.mBuffer->getSlot());
    644         return true;
    645     } else {
    646         // Don't set the last buffer id if we're not repeating,
    647         // we'll be holding on to the last buffer for nothing.
    648         if (mFrameRepeatIntervalUs > 0ll) {
    649             setLatestBuffer_l(item);
    650         }
    651         ALOGV("buffer submitted [slot=%d, useCount=%ld] acquired=%d",
    652                 item.mBuffer->getSlot(), item.mBuffer.use_count(), mNumOutstandingAcquires);
    653         mLastFrameTimestampUs = itemTimeUs;
    654     }
    655 
    656     return true;
    657 }
    658 
    659 bool GraphicBufferSource::repeatLatestBuffer_l() {
    660     CHECK(mExecuting && !haveAvailableBuffers_l());
    661 
    662     if (mLatestBuffer.mBuffer == nullptr || mSuspended) {
    663         return false;
    664     }
    665 
    666     if (mFreeCodecBuffers.empty()) {
    667         // No buffers available, bail.
    668         ALOGV("repeatLatestBuffer_l: no codec buffers.");
    669         return false;
    670     }
    671 
    672     if (!mLatestBuffer.mBuffer->isCached()) {
    673         ALOGV("repeatLatestBuffer_l: slot was discarded, but repeating our own reference");
    674     }
    675 
    676     // it is ok to update the timestamp of latest buffer as it is only used for submission
    677     status_t err = submitBuffer_l(mLatestBuffer);
    678     if (err != OK) {
    679         return false;
    680     }
    681 
    682     /* repeat last frame up to kRepeatLastFrameCount times.
    683      * in case of static scene, a single repeat might not get rid of encoder
    684      * ghosting completely, refresh a couple more times to get better quality
    685      */
    686     if (--mOutstandingFrameRepeatCount > 0) {
    687         // set up timestamp for repeat frame
    688         mLatestBuffer.mTimestampNs += mFrameRepeatIntervalUs * 1000;
    689         queueFrameRepeat_l();
    690     }
    691 
    692     return true;
    693 }
    694 
    695 void GraphicBufferSource::setLatestBuffer_l(const VideoBuffer &item) {
    696     mLatestBuffer = item;
    697 
    698     ALOGV("setLatestBuffer_l: [slot=%d, useCount=%ld]",
    699             mLatestBuffer.mBuffer->getSlot(), mLatestBuffer.mBuffer.use_count());
    700 
    701     mOutstandingFrameRepeatCount = kRepeatLastFrameCount;
    702     // set up timestamp for repeat frame
    703     mLatestBuffer.mTimestampNs += mFrameRepeatIntervalUs * 1000;
    704     queueFrameRepeat_l();
    705 }
    706 
    707 void GraphicBufferSource::queueFrameRepeat_l() {
    708     mFrameRepeatBlockedOnCodecBuffer = false;
    709 
    710     if (mReflector != NULL) {
    711         sp<AMessage> msg = new AMessage(kWhatRepeatLastFrame, mReflector);
    712         msg->setInt32("generation", ++mRepeatLastFrameGeneration);
    713         msg->post(mFrameRepeatIntervalUs);
    714     }
    715 }
    716 
    717 bool GraphicBufferSource::calculateCodecTimestamp_l(
    718         nsecs_t bufferTimeNs, int64_t *codecTimeUs) {
    719     int64_t timeUs = bufferTimeNs / 1000;
    720     timeUs += mInputBufferTimeOffsetUs;
    721 
    722     if (mCaptureFps > 0.
    723             && (mFps > 2 * mCaptureFps
    724             || mCaptureFps > 2 * mFps)) {
    725         // Time lapse or slow motion mode
    726         if (mPrevCaptureUs < 0ll) {
    727             // first capture
    728             mPrevCaptureUs = mBaseCaptureUs = timeUs;
    729             // adjust the first sample timestamp.
    730             mPrevFrameUs = mBaseFrameUs =
    731                     std::llround((timeUs * mCaptureFps) / mFps);
    732             mFrameCount = 0;
    733         } else {
    734             // snap to nearest capture point
    735             int64_t nFrames = std::llround(
    736                     (timeUs - mPrevCaptureUs) * mCaptureFps / 1000000);
    737             if (nFrames <= 0) {
    738                 // skip this frame as it's too close to previous capture
    739                 ALOGV("skipping frame, timeUs %lld", static_cast<long long>(timeUs));
    740                 return false;
    741             }
    742             mFrameCount += nFrames;
    743             mPrevCaptureUs = mBaseCaptureUs + std::llround(
    744                     mFrameCount * 1000000 / mCaptureFps);
    745             mPrevFrameUs = mBaseFrameUs + std::llround(
    746                     mFrameCount * 1000000 / mFps);
    747         }
    748 
    749         ALOGV("timeUs %lld, captureUs %lld, frameUs %lld",
    750                 static_cast<long long>(timeUs),
    751                 static_cast<long long>(mPrevCaptureUs),
    752                 static_cast<long long>(mPrevFrameUs));
    753     } else {
    754         if (timeUs <= mPrevFrameUs) {
    755             // Drop the frame if it's going backward in time. Bad timestamp
    756             // could disrupt encoder's rate control completely.
    757             ALOGW("Dropping frame that's going backward in time");
    758             return false;
    759         }
    760 
    761         mPrevFrameUs = timeUs;
    762     }
    763 
    764     *codecTimeUs = mPrevFrameUs;
    765     return true;
    766 }
    767 
    768 status_t GraphicBufferSource::submitBuffer_l(const VideoBuffer &item) {
    769     CHECK(!mFreeCodecBuffers.empty());
    770     IOMX::buffer_id codecBufferId = *mFreeCodecBuffers.begin();
    771 
    772     ALOGV("submitBuffer_l [slot=%d, bufferId=%d]", item.mBuffer->getSlot(), codecBufferId);
    773 
    774     int64_t codecTimeUs;
    775     if (!calculateCodecTimestamp_l(item.mTimestampNs, &codecTimeUs)) {
    776         return UNKNOWN_ERROR;
    777     }
    778 
    779     if ((android_dataspace)item.mDataspace != mLastDataspace) {
    780         onDataspaceChanged_l(
    781                 item.mDataspace,
    782                 (android_pixel_format)item.mBuffer->getGraphicBuffer()->format);
    783     }
    784 
    785     std::shared_ptr<AcquiredBuffer> buffer = item.mBuffer;
    786     // use a GraphicBuffer for now as OMXNodeInstance is using GraphicBuffers to hold references
    787     // and it requires this graphic buffer to be able to hold its reference
    788     // and thus we would need to create a new GraphicBuffer from an ANWBuffer separate from the
    789     // acquired GraphicBuffer.
    790     // TODO: this can be reworked globally to use ANWBuffer references
    791     sp<GraphicBuffer> graphicBuffer = buffer->getGraphicBuffer();
    792     status_t err = mOMXNode->emptyBuffer(
    793             codecBufferId, OMX_BUFFERFLAG_ENDOFFRAME, graphicBuffer, codecTimeUs,
    794             buffer->getAcquireFenceFd());
    795 
    796     if (err != OK) {
    797         ALOGW("WARNING: emptyGraphicBuffer failed: 0x%x", err);
    798         return err;
    799     }
    800 
    801     mFreeCodecBuffers.erase(mFreeCodecBuffers.begin());
    802 
    803     ssize_t cbix = mSubmittedCodecBuffers.add(codecBufferId, buffer);
    804     ALOGV("emptyGraphicBuffer succeeded, bufferId=%u@%zd bufhandle=%p",
    805             codecBufferId, cbix, graphicBuffer->handle);
    806     return OK;
    807 }
    808 
    809 void GraphicBufferSource::submitEndOfInputStream_l() {
    810     CHECK(mEndOfStream);
    811     if (mEndOfStreamSent) {
    812         ALOGV("EOS already sent");
    813         return;
    814     }
    815 
    816     if (mFreeCodecBuffers.empty()) {
    817         ALOGV("submitEndOfInputStream_l: no codec buffers available");
    818         return;
    819     }
    820     IOMX::buffer_id codecBufferId = *mFreeCodecBuffers.begin();
    821 
    822     // We reject any additional incoming graphic buffers. There is no acquired buffer used for EOS
    823     status_t err = mOMXNode->emptyBuffer(
    824             codecBufferId, OMX_BUFFERFLAG_ENDOFFRAME | OMX_BUFFERFLAG_EOS);
    825     if (err != OK) {
    826         ALOGW("emptyDirectBuffer EOS failed: 0x%x", err);
    827     } else {
    828         mFreeCodecBuffers.erase(mFreeCodecBuffers.begin());
    829         ssize_t cbix = mSubmittedCodecBuffers.add(codecBufferId, nullptr);
    830         ALOGV("submitEndOfInputStream_l: buffer submitted, bufferId=%u@%zd", codecBufferId, cbix);
    831         mEndOfStreamSent = true;
    832 
    833         // no need to hold onto any buffers for frame repeating
    834         ++mRepeatLastFrameGeneration;
    835         mLatestBuffer.mBuffer.reset();
    836     }
    837 }
    838 
    839 status_t GraphicBufferSource::acquireBuffer_l(VideoBuffer *ab) {
    840     BufferItem bi;
    841     status_t err = mConsumer->acquireBuffer(&bi, 0);
    842     if (err == BufferQueue::NO_BUFFER_AVAILABLE) {
    843         // shouldn't happen
    844         ALOGW("acquireBuffer_l: frame was not available");
    845         return err;
    846     } else if (err != OK) {
    847         ALOGW("acquireBuffer_l: failed with err=%d", err);
    848         return err;
    849     }
    850     --mNumAvailableUnacquiredBuffers;
    851 
    852     // Manage our buffer cache.
    853     std::shared_ptr<CachedBuffer> buffer;
    854     ssize_t bsi = mBufferSlots.indexOfKey(bi.mSlot);
    855     if (bi.mGraphicBuffer != NULL) {
    856         // replace/initialize slot with new buffer
    857         ALOGV("acquireBuffer_l: %s buffer slot %d", bsi < 0 ? "setting" : "UPDATING", bi.mSlot);
    858         if (bsi >= 0) {
    859             discardBufferAtSlotIndex_l(bsi);
    860         } else {
    861             bsi = mBufferSlots.add(bi.mSlot, nullptr);
    862         }
    863         buffer = std::make_shared<CachedBuffer>(bi.mSlot, bi.mGraphicBuffer);
    864         mBufferSlots.replaceValueAt(bsi, buffer);
    865     } else {
    866         buffer = mBufferSlots.valueAt(bsi);
    867     }
    868     int64_t frameNum = bi.mFrameNumber;
    869 
    870     std::shared_ptr<AcquiredBuffer> acquiredBuffer =
    871         std::make_shared<AcquiredBuffer>(
    872                 buffer,
    873                 [frameNum, this](AcquiredBuffer *buffer){
    874                     // AcquiredBuffer's destructor should always be called when mMutex is locked.
    875                     // If we had a reentrant mutex, we could just lock it again to ensure this.
    876                     if (mMutex.tryLock() == 0) {
    877                         TRESPASS_DBG();
    878                         mMutex.unlock();
    879                     }
    880 
    881                     // we can release buffers immediately if not using adapters
    882                     // alternately, we could add them to mSlotsToRelease, but we would
    883                     // somehow need to propagate frame number to that queue
    884                     if (buffer->isCached()) {
    885                         --mNumOutstandingAcquires;
    886                         mConsumer->releaseBuffer(
    887                                 buffer->getSlot(), frameNum, EGL_NO_DISPLAY, EGL_NO_SYNC_KHR,
    888                                 buffer->getReleaseFence());
    889                     }
    890                 },
    891                 bi.mFence);
    892     VideoBuffer videoBuffer{acquiredBuffer, bi.mTimestamp, bi.mDataSpace};
    893     *ab = videoBuffer;
    894     ++mNumOutstandingAcquires;
    895     return OK;
    896 }
    897 
    898 // BufferQueue::ConsumerListener callback
    899 void GraphicBufferSource::onFrameAvailable(const BufferItem& item __unused) {
    900     Mutex::Autolock autoLock(mMutex);
    901 
    902     ALOGV("onFrameAvailable: executing=%d available=%zu+%d",
    903             mExecuting, mAvailableBuffers.size(), mNumAvailableUnacquiredBuffers);
    904     ++mNumAvailableUnacquiredBuffers;
    905 
    906     // For BufferQueue we cannot acquire a buffer if we cannot immediately feed it to the codec
    907     // UNLESS we are discarding this buffer (acquiring and immediately releasing it), which makes
    908     // this an ugly logic.
    909     // NOTE: We could also rely on our debug counter but that is meant only as a debug counter.
    910     if (!areWeDiscardingAvailableBuffers_l() && mFreeCodecBuffers.empty()) {
    911         // we may not be allowed to acquire a possibly encodable buffer, so just note that
    912         // it is available
    913         ALOGV("onFrameAvailable: cannot acquire buffer right now, do it later");
    914 
    915         ++mRepeatLastFrameGeneration; // cancel any pending frame repeat
    916         return;
    917     }
    918 
    919     VideoBuffer buffer;
    920     status_t err = acquireBuffer_l(&buffer);
    921     if (err != OK) {
    922         ALOGE("onFrameAvailable: acquireBuffer returned err=%d", err);
    923     } else {
    924         onBufferAcquired_l(buffer);
    925     }
    926 }
    927 
    928 bool GraphicBufferSource::areWeDiscardingAvailableBuffers_l() {
    929     return mEndOfStreamSent // already sent EOS to codec
    930             || mOMXNode == nullptr // there is no codec connected
    931             || (mSuspended && mActionQueue.empty()) // we are suspended and not waiting for
    932                                                     // any further action
    933             || !mExecuting;
    934 }
    935 
    936 void GraphicBufferSource::onBufferAcquired_l(const VideoBuffer &buffer) {
    937     if (mEndOfStreamSent) {
    938         // This should only be possible if a new buffer was queued after
    939         // EOS was signaled, i.e. the app is misbehaving.
    940         ALOGW("onFrameAvailable: EOS is sent, ignoring frame");
    941     } else if (mOMXNode == NULL || (mSuspended && mActionQueue.empty())) {
    942         // FIXME: if we are suspended but have a resume queued we will stop repeating the last
    943         // frame. Is that the desired behavior?
    944         ALOGV("onFrameAvailable: suspended, ignoring frame");
    945     } else {
    946         ++mRepeatLastFrameGeneration; // cancel any pending frame repeat
    947         mAvailableBuffers.push_back(buffer);
    948         if (mExecuting) {
    949             fillCodecBuffer_l();
    950         }
    951     }
    952 }
    953 
    954 // BufferQueue::ConsumerListener callback
    955 void GraphicBufferSource::onBuffersReleased() {
    956     Mutex::Autolock lock(mMutex);
    957 
    958     uint64_t slotMask;
    959     uint64_t releaseMask;
    960     if (mConsumer->getReleasedBuffers(&releaseMask) != NO_ERROR) {
    961         slotMask = 0xffffffffffffffffULL;
    962         ALOGW("onBuffersReleased: unable to get released buffer set");
    963     } else {
    964         slotMask = releaseMask;
    965         ALOGV("onBuffersReleased: 0x%016" PRIx64, slotMask);
    966     }
    967 
    968     AString unpopulated;
    969     for (int i = 0; i < BufferQueue::NUM_BUFFER_SLOTS; i++) {
    970         if ((slotMask & 0x01) != 0) {
    971             if (!discardBufferInSlot_l(i)) {
    972                 if (!unpopulated.empty()) {
    973                     unpopulated.append(", ");
    974                 }
    975                 unpopulated.append(i);
    976             }
    977         }
    978         slotMask >>= 1;
    979     }
    980     if (!unpopulated.empty()) {
    981         ALOGW("released unpopulated slots: [%s]", unpopulated.c_str());
    982     }
    983 }
    984 
    985 bool GraphicBufferSource::discardBufferInSlot_l(GraphicBufferSource::slot_id i) {
    986     ssize_t bsi = mBufferSlots.indexOfKey(i);
    987     if (bsi < 0) {
    988         return false;
    989     } else {
    990         discardBufferAtSlotIndex_l(bsi);
    991         mBufferSlots.removeItemsAt(bsi);
    992         return true;
    993     }
    994 }
    995 
    996 void GraphicBufferSource::discardBufferAtSlotIndex_l(ssize_t bsi) {
    997     const std::shared_ptr<CachedBuffer>& buffer = mBufferSlots.valueAt(bsi);
    998     // use -2 if there is no latest buffer, and -1 if it is no longer cached
    999     slot_id latestBufferSlot =
   1000         mLatestBuffer.mBuffer == nullptr ? -2 : mLatestBuffer.mBuffer->getSlot();
   1001     ALOGV("releasing acquired buffer: [slot=%d, useCount=%ld], latest: [slot=%d]",
   1002             mBufferSlots.keyAt(bsi), buffer.use_count(), latestBufferSlot);
   1003     mBufferSlots.valueAt(bsi)->onDroppedFromCache();
   1004 
   1005     // If the slot of an acquired buffer is discarded, that buffer will not have to be
   1006     // released to the producer, so account it here. However, it is possible that the
   1007     // acquired buffer has already been discarded so check if it still is.
   1008     if (buffer->isAcquired()) {
   1009         --mNumOutstandingAcquires;
   1010     }
   1011 
   1012     // clear the buffer reference (not technically needed as caller either replaces or deletes
   1013     // it; done here for safety).
   1014     mBufferSlots.editValueAt(bsi).reset();
   1015     CHECK_DBG(buffer == nullptr);
   1016 }
   1017 
   1018 void GraphicBufferSource::releaseAllAvailableBuffers_l() {
   1019     mAvailableBuffers.clear();
   1020     while (mNumAvailableUnacquiredBuffers > 0) {
   1021         VideoBuffer item;
   1022         if (acquireBuffer_l(&item) != OK) {
   1023             ALOGW("releaseAllAvailableBuffers: failed to acquire available unacquired buffer");
   1024             break;
   1025         }
   1026     }
   1027 }
   1028 
   1029 // BufferQueue::ConsumerListener callback
   1030 void GraphicBufferSource::onSidebandStreamChanged() {
   1031     ALOG_ASSERT(false, "GraphicBufferSource can't consume sideband streams");
   1032 }
   1033 
   1034 status_t GraphicBufferSource::configure(
   1035         const sp<IOmxNodeWrapper>& omxNode,
   1036         int32_t dataSpace,
   1037         int32_t bufferCount,
   1038         uint32_t frameWidth,
   1039         uint32_t frameHeight,
   1040         uint32_t consumerUsage) {
   1041     if (omxNode == NULL) {
   1042         return BAD_VALUE;
   1043     }
   1044 
   1045 
   1046     // Call setMaxAcquiredBufferCount without lock.
   1047     // setMaxAcquiredBufferCount could call back to onBuffersReleased
   1048     // if the buffer count change results in releasing of existing buffers,
   1049     // which would lead to deadlock.
   1050     status_t err = mConsumer->setMaxAcquiredBufferCount(bufferCount);
   1051     if (err != NO_ERROR) {
   1052         ALOGE("Unable to set BQ max acquired buffer count to %u: %d",
   1053                 bufferCount, err);
   1054         return err;
   1055     }
   1056 
   1057     {
   1058         Mutex::Autolock autoLock(mMutex);
   1059         mOMXNode = omxNode;
   1060 
   1061         err = mConsumer->setDefaultBufferSize(frameWidth, frameHeight);
   1062         if (err != NO_ERROR) {
   1063             ALOGE("Unable to set BQ default buffer size to %ux%u: %d",
   1064                     frameWidth, frameHeight, err);
   1065             return err;
   1066         }
   1067 
   1068         consumerUsage |= GRALLOC_USAGE_HW_VIDEO_ENCODER;
   1069         mConsumer->setConsumerUsageBits(consumerUsage);
   1070 
   1071         // Sets the default buffer data space
   1072         ALOGD("setting dataspace: %#x, acquired=%d", dataSpace, mNumOutstandingAcquires);
   1073         mConsumer->setDefaultBufferDataSpace((android_dataspace)dataSpace);
   1074         mLastDataspace = (android_dataspace)dataSpace;
   1075 
   1076         mExecuting = false;
   1077         mSuspended = false;
   1078         mEndOfStream = false;
   1079         mEndOfStreamSent = false;
   1080         mSkipFramesBeforeNs = -1ll;
   1081         mFrameRepeatIntervalUs = -1ll;
   1082         mRepeatLastFrameGeneration = 0;
   1083         mOutstandingFrameRepeatCount = 0;
   1084         mLatestBuffer.mBuffer.reset();
   1085         mFrameRepeatBlockedOnCodecBuffer = false;
   1086         mFps = -1.0;
   1087         mCaptureFps = -1.0;
   1088         mBaseCaptureUs = -1ll;
   1089         mBaseFrameUs = -1ll;
   1090         mPrevCaptureUs = -1ll;
   1091         mPrevFrameUs = -1ll;
   1092         mFrameCount = 0;
   1093         mInputBufferTimeOffsetUs = 0;
   1094         mStopTimeUs = -1;
   1095         mActionQueue.clear();
   1096     }
   1097 
   1098     return OK;
   1099 }
   1100 
   1101 status_t GraphicBufferSource::setSuspend(bool suspend, int64_t suspendStartTimeUs) {
   1102     ALOGV("setSuspend=%d at time %lld us", suspend, (long long)suspendStartTimeUs);
   1103 
   1104     Mutex::Autolock autoLock(mMutex);
   1105 
   1106     if (mStopTimeUs != -1) {
   1107         ALOGE("setSuspend failed as STOP action is pending");
   1108         return INVALID_OPERATION;
   1109     }
   1110 
   1111     // Push the action to the queue.
   1112     if (suspendStartTimeUs != -1) {
   1113         // suspendStartTimeUs must be smaller or equal to current systemTime.
   1114         int64_t currentSystemTimeUs = systemTime() / 1000;
   1115         if (suspendStartTimeUs > currentSystemTimeUs) {
   1116             ALOGE("setSuspend failed. %lld is larger than current system time %lld us",
   1117                     (long long)suspendStartTimeUs, (long long)currentSystemTimeUs);
   1118             return INVALID_OPERATION;
   1119         }
   1120         if (mLastActionTimeUs != -1 && suspendStartTimeUs < mLastActionTimeUs) {
   1121             ALOGE("setSuspend failed. %lld is smaller than last action time %lld us",
   1122                     (long long)suspendStartTimeUs, (long long)mLastActionTimeUs);
   1123             return INVALID_OPERATION;
   1124         }
   1125         mLastActionTimeUs = suspendStartTimeUs;
   1126         ActionItem action;
   1127         action.mAction = suspend ? ActionItem::PAUSE : ActionItem::RESUME;
   1128         action.mActionTimeUs = suspendStartTimeUs;
   1129         ALOGV("Push %s action into actionQueue", suspend ? "PAUSE" : "RESUME");
   1130         mActionQueue.push_back(action);
   1131     } else {
   1132         if (suspend) {
   1133             mSuspended = true;
   1134             releaseAllAvailableBuffers_l();
   1135             return OK;
   1136         } else {
   1137             mSuspended = false;
   1138             if (mExecuting && !haveAvailableBuffers_l()
   1139                     && mFrameRepeatBlockedOnCodecBuffer) {
   1140                 if (repeatLatestBuffer_l()) {
   1141                     ALOGV("suspend/deferred repeatLatestBuffer_l SUCCESS");
   1142                     mFrameRepeatBlockedOnCodecBuffer = false;
   1143                 } else {
   1144                     ALOGV("suspend/deferred repeatLatestBuffer_l FAILURE");
   1145                 }
   1146             }
   1147         }
   1148     }
   1149     return OK;
   1150 }
   1151 
   1152 status_t GraphicBufferSource::setRepeatPreviousFrameDelayUs(int64_t repeatAfterUs) {
   1153     ALOGV("setRepeatPreviousFrameDelayUs: delayUs=%lld", (long long)repeatAfterUs);
   1154 
   1155     Mutex::Autolock autoLock(mMutex);
   1156 
   1157     if (mExecuting || repeatAfterUs <= 0ll) {
   1158         return INVALID_OPERATION;
   1159     }
   1160 
   1161     mFrameRepeatIntervalUs = repeatAfterUs;
   1162     return OK;
   1163 }
   1164 
   1165 status_t GraphicBufferSource::setTimeOffsetUs(int64_t timeOffsetUs) {
   1166     Mutex::Autolock autoLock(mMutex);
   1167 
   1168     // timeOffsetUs must be negative for adjustment.
   1169     if (timeOffsetUs >= 0ll) {
   1170         return INVALID_OPERATION;
   1171     }
   1172 
   1173     mInputBufferTimeOffsetUs = timeOffsetUs;
   1174     return OK;
   1175 }
   1176 
   1177 status_t GraphicBufferSource::setMaxFps(float maxFps) {
   1178     ALOGV("setMaxFps: maxFps=%lld", (long long)maxFps);
   1179 
   1180     Mutex::Autolock autoLock(mMutex);
   1181 
   1182     if (mExecuting) {
   1183         return INVALID_OPERATION;
   1184     }
   1185 
   1186     mFrameDropper = new FrameDropper();
   1187     status_t err = mFrameDropper->setMaxFrameRate(maxFps);
   1188     if (err != OK) {
   1189         mFrameDropper.clear();
   1190         return err;
   1191     }
   1192 
   1193     return OK;
   1194 }
   1195 
   1196 status_t GraphicBufferSource::setStartTimeUs(int64_t skipFramesBeforeUs) {
   1197     ALOGV("setStartTimeUs: skipFramesBeforeUs=%lld", (long long)skipFramesBeforeUs);
   1198 
   1199     Mutex::Autolock autoLock(mMutex);
   1200 
   1201     mSkipFramesBeforeNs =
   1202             (skipFramesBeforeUs > 0) ? (skipFramesBeforeUs * 1000) : -1ll;
   1203 
   1204     return OK;
   1205 }
   1206 
   1207 status_t GraphicBufferSource::setStopTimeUs(int64_t stopTimeUs) {
   1208     ALOGV("setStopTimeUs: %lld us", (long long)stopTimeUs);
   1209     Mutex::Autolock autoLock(mMutex);
   1210 
   1211     if (mStopTimeUs != -1) {
   1212         // Ignore if stop time has already been set
   1213         return OK;
   1214     }
   1215 
   1216     // stopTimeUs must be smaller or equal to current systemTime.
   1217     int64_t currentSystemTimeUs = systemTime() / 1000;
   1218     if (stopTimeUs > currentSystemTimeUs) {
   1219         ALOGE("setStopTimeUs failed. %lld is larger than current system time %lld us",
   1220             (long long)stopTimeUs, (long long)currentSystemTimeUs);
   1221         return INVALID_OPERATION;
   1222     }
   1223     if (mLastActionTimeUs != -1 && stopTimeUs < mLastActionTimeUs) {
   1224         ALOGE("setSuspend failed. %lld is smaller than last action time %lld us",
   1225             (long long)stopTimeUs, (long long)mLastActionTimeUs);
   1226         return INVALID_OPERATION;
   1227     }
   1228     mLastActionTimeUs = stopTimeUs;
   1229     ActionItem action;
   1230     action.mAction = ActionItem::STOP;
   1231     action.mActionTimeUs = stopTimeUs;
   1232     mActionQueue.push_back(action);
   1233     mStopTimeUs = stopTimeUs;
   1234     return OK;
   1235 }
   1236 
   1237 status_t GraphicBufferSource::getStopTimeOffsetUs(int64_t *stopTimeOffsetUs) {
   1238     ALOGV("getStopTimeOffsetUs");
   1239     Mutex::Autolock autoLock(mMutex);
   1240     if (mStopTimeUs == -1) {
   1241         ALOGW("Fail to return stopTimeOffsetUs as stop time is not set");
   1242         return INVALID_OPERATION;
   1243     }
   1244     *stopTimeOffsetUs =
   1245         mLastFrameTimestampUs == -1 ? 0 : mStopTimeUs - mLastFrameTimestampUs;
   1246     return OK;
   1247 }
   1248 
   1249 status_t GraphicBufferSource::setTimeLapseConfig(double fps, double captureFps) {
   1250     ALOGV("setTimeLapseConfig: fps=%lg, captureFps=%lg",
   1251             fps, captureFps);
   1252     Mutex::Autolock autoLock(mMutex);
   1253 
   1254     if (mExecuting || !(fps > 0) || !(captureFps > 0)) {
   1255         return INVALID_OPERATION;
   1256     }
   1257 
   1258     mFps = fps;
   1259     mCaptureFps = captureFps;
   1260 
   1261     return OK;
   1262 }
   1263 
   1264 status_t GraphicBufferSource::setColorAspects(int32_t aspectsPacked) {
   1265     Mutex::Autolock autoLock(mMutex);
   1266     mDefaultColorAspectsPacked = aspectsPacked;
   1267     ColorAspects colorAspects = ColorUtils::unpackToColorAspects(aspectsPacked);
   1268     ALOGD("requesting color aspects (R:%d(%s), P:%d(%s), M:%d(%s), T:%d(%s))",
   1269             colorAspects.mRange, asString(colorAspects.mRange),
   1270             colorAspects.mPrimaries, asString(colorAspects.mPrimaries),
   1271             colorAspects.mMatrixCoeffs, asString(colorAspects.mMatrixCoeffs),
   1272             colorAspects.mTransfer, asString(colorAspects.mTransfer));
   1273 
   1274     return OK;
   1275 }
   1276 
   1277 status_t GraphicBufferSource::signalEndOfInputStream() {
   1278     Mutex::Autolock autoLock(mMutex);
   1279     ALOGV("signalEndOfInputStream: executing=%d available=%zu+%d eos=%d",
   1280             mExecuting, mAvailableBuffers.size(), mNumAvailableUnacquiredBuffers, mEndOfStream);
   1281 
   1282     if (mEndOfStream) {
   1283         ALOGE("EOS was already signaled");
   1284         return INVALID_OPERATION;
   1285     }
   1286 
   1287     // Set the end-of-stream flag.  If no frames are pending from the
   1288     // BufferQueue, and a codec buffer is available, and we're executing,
   1289     // and there is no stop timestamp, we initiate the EOS from here.
   1290     // Otherwise, we'll let codecBufferEmptied() (or omxExecuting) do it.
   1291     //
   1292     // Note: if there are no pending frames and all codec buffers are
   1293     // available, we *must* submit the EOS from here or we'll just
   1294     // stall since no future events are expected.
   1295     mEndOfStream = true;
   1296 
   1297     if (mStopTimeUs == -1 && mExecuting && !haveAvailableBuffers_l()) {
   1298         submitEndOfInputStream_l();
   1299     }
   1300 
   1301     return OK;
   1302 }
   1303 
   1304 void GraphicBufferSource::onMessageReceived(const sp<AMessage> &msg) {
   1305     switch (msg->what()) {
   1306         case kWhatRepeatLastFrame:
   1307         {
   1308             Mutex::Autolock autoLock(mMutex);
   1309 
   1310             int32_t generation;
   1311             CHECK(msg->findInt32("generation", &generation));
   1312 
   1313             if (generation != mRepeatLastFrameGeneration) {
   1314                 // stale
   1315                 break;
   1316             }
   1317 
   1318             if (!mExecuting || haveAvailableBuffers_l()) {
   1319                 break;
   1320             }
   1321 
   1322             bool success = repeatLatestBuffer_l();
   1323             if (success) {
   1324                 ALOGV("repeatLatestBuffer_l SUCCESS");
   1325             } else {
   1326                 ALOGV("repeatLatestBuffer_l FAILURE");
   1327                 mFrameRepeatBlockedOnCodecBuffer = true;
   1328             }
   1329             break;
   1330         }
   1331 
   1332         default:
   1333             TRESPASS();
   1334     }
   1335 }
   1336 
   1337 }  // namespace android
   1338