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