xref: /aosp_15_r20/frameworks/av/media/codec2/vndk/include/C2BqBufferPriv.h (revision ec779b8e0859a360c3d303172224686826e6e0e1)
1 /*
2  * Copyright (C) 2018 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #ifndef STAGEFRIGHT_CODEC2_BQ_BUFFER_PRIV_H_
18 #define STAGEFRIGHT_CODEC2_BQ_BUFFER_PRIV_H_
19 
20 #include <android/hardware/graphics/bufferqueue/2.0/IGraphicBufferProducer.h>
21 
22 #include <C2Buffer.h>
23 #include <C2BlockInternal.h>
24 
25 #include <functional>
26 
27 namespace android {
28 class GraphicBuffer;
29 }  // namespace android
30 
31 /**
32  * BufferQueue based BlockPool.
33  *
34  * This creates graphic blocks from BufferQueue. BufferQueue here is HIDL-ized IGBP.
35  * HIDL-ized IGBP enables vendor HAL to call IGBP interfaces via HIDL over process boundary.
36  * HIDL-ized IGBP is called as HGBP. HGBP had been used from multiple places in android,
37  * but now this is the only place HGBP is still used.
38  *
39  * Initially there is no HGBP configured, in the case graphic blocks are allocated
40  * from gralloc directly upon \fetchGraphicBlock() requests.
41  *
42  * HGBP can be configured as null as well, in the case graphic blocks are allocated
43  * from gralloc directly upon \fetchGraphicBlock() requests.
44  *
45  * If a specific HGBP is configured, the HGBP acts as an allocator for creating graphic blocks.
46  *
47  *
48  * HGBP/IGBP and the BlockPool
49  *
50  * GraphicBuffer(s) from BufferQueue(IGBP/IGBC) are based on slot id.
51  * A created GraphicBuffer occupies a slot(so the GraphicBuffer has a slot-id).
52  * A GraphicBuffer is produced and consumed and recyled based on the slot-id
53  * w.r.t. BufferQueue.
54  *
55  * HGBP::dequeueBuffer() returns a slot id where the slot has an available GraphicBuffer.
56  * If it is necessary, HGBP allocates a new GraphicBuffer to the slot and indicates
57  * that a new buffer is allocated as return flag.
58  * To retrieve the GraphicBuffer, HGBP::requestBuffer() along with the slot id
59  * is required. In order to save HGBP remote calls, the blockpool caches the
60  * allocated GraphicBuffer(s) along with the slot information.
61  *
62  * The blockpool provides C2GraphicBlock upon \fetchGraphicBlock().
63  * The C2GraphicBlock has a native handle, which is extracted from a GraphicBuffer
64  * and then cloned for independent life-cycle with the GraphicBuffer. The GraphicBuffer
65  * is allocated by HGBP::dequeueBuffer() and retrieved by HGBP::requestBuffer()
66  * if there is a HGBP configured.
67  *
68  *
69  * Life-cycle of C2GraphicBlock
70  *
71  * The decoder HAL writes a decoded frame into C2GraphicBlock. Upon
72  * completion, the component sends the block to the client in the remote process
73  * (i.e. to MediaCodec). The remote process renders the frame into the output surface
74  * via IGBP::queueBuffer() (Note: this is not hidlized.).
75  *
76  * If the decoder HAL destroys the C2GraphicBlock without transferring to the
77  * client, the destroy request goes to the BlockPool. Then
78  * the BlockPool free the associated GraphicBuffer from a slot to
79  * HGBP in order to recycle via HGBP::cancelBuffer().
80  *
81  *
82  * Clearing the Cache(GraphicBuffer)
83  *
84  * When the output surface is switched to a new surface, The GraphicBuffers from
85  * the old surface is either migrated or cleared.
86  *
87  * The GraphicBuffer(s) still in use are migrated to a new surface during
88  * configuration via HGBP::attachBuffer(). The GraphicBuffer(s) not in use are
89  * cleared from the cache inside the BlockPool.
90  *
91  * When the surface is switched to a null surface, all the
92  * GraphicBuffers in the cache are cleared.
93  *
94  *
95  * Workaround w.r.t. b/322731059 (Deferring cleaning the cache)
96  *
97  * Some vendor devices have issues with graphic buffer lifecycle management,
98  * where the graphic buffers get released even when the cloned native handles
99  * in the remote process are not closed yet. This issue led to rare crashes
100  * for those devices when the cache is cleared early.
101  *
102  * We workarounded the crash by deferring the cleaning of the cache.
103  * The workaround is not enabled by default, and can be enabled via a
104  * system property as shown below:
105  *
106  *        'debug.codec2.bqpool_dealloc_after_stop' = 1
107  *
108  * Configuring the debug flag will call \::setDeferDeallocationAfterStop()
109  * after the blockpool creation. This will enable the deferring.
110  *
111  * After enabling the deferring, clearing the GraphicBuffer is delayed until
112  *  1) \::clearDeferredBlocks() is called.
113  *        Typically after HAL processes stop() request.
114  *  2) Or a new ::fetchGraphicBlock() is called.
115  *
116  *  Since the deferring will delay the deallocation, the deferring will result
117  *  in more memory consumption during the brief period.
118  */
119 class C2BufferQueueBlockPool : public C2BlockPool {
120 public:
121     C2BufferQueueBlockPool(const std::shared_ptr<C2Allocator> &allocator, const local_id_t localId);
122 
123     virtual ~C2BufferQueueBlockPool() override;
124 
getAllocatorId()125     virtual C2Allocator::id_t getAllocatorId() const override {
126         return mAllocator->getId();
127     };
128 
getLocalId()129     virtual local_id_t getLocalId() const override {
130         return mLocalId;
131     };
132 
133     virtual c2_status_t fetchGraphicBlock(
134             uint32_t width,
135             uint32_t height,
136             uint32_t format,
137             C2MemoryUsage usage,
138             std::shared_ptr<C2GraphicBlock> *block /* nonnull */) override;
139 
140     virtual c2_status_t fetchGraphicBlock(
141             uint32_t width,
142             uint32_t height,
143             uint32_t format,
144             C2MemoryUsage usage,
145             std::shared_ptr<C2GraphicBlock> *block /* nonnull */,
146             C2Fence *fence /* nonnull */) override;
147 
148     typedef std::function<void(uint64_t producer, int32_t slot, int64_t nsecs)> OnRenderCallback;
149 
150     /**
151      * Sets render callback.
152      *
153      * \param renderCallbak callback to call for all dequeue buffer.
154      */
155     virtual void setRenderCallback(const OnRenderCallback &renderCallback = OnRenderCallback());
156 
157     typedef ::android::hardware::graphics::bufferqueue::V2_0::
158             IGraphicBufferProducer HGraphicBufferProducer;
159     /**
160      * Configures an IGBP in order to create blocks. A newly created block is
161      * dequeued from the configured IGBP. Unique Id of IGBP and the slot number of
162      * blocks are passed via native_handle. Managing IGBP is responsibility of caller.
163      * When IGBP is not configured, block will be created via allocator.
164      * Since zero is not used for Unique Id of IGBP, if IGBP is not configured or producer
165      * is configured as nullptr, unique id which is bundled in native_handle is zero.
166      *
167      * \param producer      the IGBP, which will be used to fetch blocks
168      *                      This could be null, in the case this blockpool will
169      *                      allocate backed GraphicBuffer via allocator(gralloc).
170      */
171     virtual void configureProducer(const android::sp<HGraphicBufferProducer> &producer);
172 
173     /**
174      * Configures an IGBP in order to create blocks. A newly created block is
175      * dequeued from the configured IGBP. Unique Id of IGBP and the slot number of
176      * blocks are passed via native_handle. Managing IGBP is responsibility of caller.
177      * When IGBP is not configured, block will be created via allocator.
178      * Since zero is not used for Unique Id of IGBP, if IGBP is not configured or producer
179      * is configured as nullptr, unique id which is bundled in native_handle is zero.
180      *
181      * \param producer      the IGBP, which will be used to fetch blocks
182      *                      This could be null, in the case this blockpool will
183      *                      allocate backed GraphicBuffer via allocator(gralloc).
184      * \param syncMemory    Shared memory for synchronization of allocation & deallocation.
185      * \param bqId          Id of IGBP
186      * \param generationId  Generation Id for rendering output
187      * \param consumerUsage consumerUsage flagof the IGBP
188      */
189     virtual void configureProducer(
190             const android::sp<HGraphicBufferProducer> &producer,
191             native_handle_t *syncMemory,
192             uint64_t bqId,
193             uint32_t generationId,
194             uint64_t consumerUsage);
195 
196     virtual void getConsumerUsage(uint64_t *consumerUsage);
197 
198     /**
199      * Invalidate the class.
200      *
201      * After the call, fetchGraphicBlock() will return C2_BAD_STATE.
202      */
203     virtual void invalidate();
204 
205     /**
206      * Defer deallocation of cached blocks.
207      *
208      * Deallocation of cached blocks will be deferred until
209      * \clearDeferredBlocks() is called. Or a new block allocation is
210      * requested by \fetchGraphicBlock().
211      */
212     void setDeferDeallocationAfterStop();
213 
214 
215     /**
216      * Clear deferred blocks.
217      *
218      * Deallocation of cached blocks can be deferred by
219      * \setDeferDeallocationAfterStop().
220      * clear(deallocate) those deferred cached blocks explicitly.
221      * Use this interface, if the blockpool could be inactive indefinitely.
222      */
223     void clearDeferredBlocks();
224 
225 private:
226     const std::shared_ptr<C2Allocator> mAllocator;
227     const local_id_t mLocalId;
228 
229     class Impl;
230     std::shared_ptr<Impl> mImpl;
231 
232     friend struct C2BufferQueueBlockPoolData;
233 };
234 
235 class C2SurfaceSyncMemory;
236 
237 struct C2BufferQueueBlockPoolData : public _C2BlockPoolData {
238 public:
239     typedef ::android::hardware::graphics::bufferqueue::V2_0::
240             IGraphicBufferProducer HGraphicBufferProducer;
241 
242     // Create a remote BlockPoolData.
243     C2BufferQueueBlockPoolData(
244             uint32_t generation, uint64_t bqId, int32_t bqSlot,
245             const std::shared_ptr<int> &owner,
246             const android::sp<HGraphicBufferProducer>& producer);
247 
248     // Create a local BlockPoolData.
249     C2BufferQueueBlockPoolData(
250             uint32_t generation, uint64_t bqId, int32_t bqSlot,
251             const std::shared_ptr<int> &owner,
252             const android::sp<HGraphicBufferProducer>& producer,
253             std::shared_ptr<C2SurfaceSyncMemory>);
254 
255     virtual ~C2BufferQueueBlockPoolData() override;
256 
257     virtual type_t getType() const override;
258 
259     int migrate(const android::sp<HGraphicBufferProducer>& producer,
260                 uint32_t toGeneration, uint64_t toUsage, uint64_t toBqId,
261                 android::sp<android::GraphicBuffer>& graphicBuffer, uint32_t oldGeneration,
262                 std::shared_ptr<C2SurfaceSyncMemory> syncMem);
263 private:
264     friend struct _C2BlockFactory;
265 
266     // Methods delegated from _C2BlockFactory.
267     void getBufferQueueData(uint32_t* generation, uint64_t* bqId, int32_t* bqSlot) const;
268     bool holdBlockFromBufferQueue(const std::shared_ptr<int>& owner,
269                                   const android::sp<HGraphicBufferProducer>& igbp,
270                                   std::shared_ptr<C2SurfaceSyncMemory> syncMem);
271     bool beginTransferBlockToClient();
272     bool endTransferBlockToClient(bool transfer);
273     bool beginAttachBlockToBufferQueue();
274     bool endAttachBlockToBufferQueue(const std::shared_ptr<int>& owner,
275                                      const android::sp<HGraphicBufferProducer>& igbp,
276                                      std::shared_ptr<C2SurfaceSyncMemory> syncMem,
277                                      uint32_t generation, uint64_t bqId, int32_t bqSlot);
278     bool displayBlockToBufferQueue();
279 
280     const bool mLocal;
281     bool mHeld;
282 
283     // Data of the corresponding buffer.
284     uint32_t mGeneration;
285     uint64_t mBqId;
286     int32_t mBqSlot;
287 
288     // Data of the current IGBP, updated at migrate(). If the values are
289     // mismatched, then the corresponding buffer will not be cancelled back to
290     // IGBP at the destructor.
291     uint32_t mCurrentGeneration;
292     uint64_t mCurrentBqId;
293 
294     bool mTransfer; // local transfer to remote
295     bool mAttach; // attach on remote
296     bool mDisplay; // display on remote;
297     std::weak_ptr<int> mOwner;
298     android::sp<HGraphicBufferProducer> mIgbp;
299     std::shared_ptr<C2SurfaceSyncMemory> mSyncMem;
300     mutable std::mutex mLock;
301 };
302 
303 #endif // STAGEFRIGHT_CODEC2_BUFFER_PRIV_H_
304