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