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