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