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