• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2021 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 //#define LOG_NDEBUG 0
6 #define LOG_TAG "H2BGraphicBuferProducer"
7 
8 #include <v4l2_codec2/plugin_store/H2BGraphicBufferProducer.h>
9 
10 #include <log/log.h>
11 #include <types.h>
12 #include <ui/BufferQueueDefs.h>
13 
14 namespace android {
15 
16 using ::android::BufferQueueDefs::BUFFER_NEEDS_REALLOCATION;
17 using ::android::BufferQueueDefs::RELEASE_ALL_BUFFERS;
18 using ::android::hardware::Return;
19 
20 using HBuffer = ::android::hardware::graphics::common::V1_2::HardwareBuffer;
21 using HStatus = ::android::hardware::graphics::bufferqueue::V2_0::Status;
22 using HConnectionType = hardware::graphics::bufferqueue::V2_0::ConnectionType;
23 using HQueueBufferOutput =
24         ::android::hardware::graphics::bufferqueue::V2_0::IGraphicBufferProducer::QueueBufferOutput;
25 
26 using ::android::hardware::graphics::bufferqueue::V2_0::utils::b2h;
27 using ::android::hardware::graphics::bufferqueue::V2_0::utils::h2b;
28 using ::android::hardware::graphics::bufferqueue::V2_0::utils::HFenceWrapper;
29 
H2BGraphicBufferProducer(sp<HGraphicBufferProducer> base)30 H2BGraphicBufferProducer::H2BGraphicBufferProducer(sp<HGraphicBufferProducer> base) : mBase(base) {}
31 
requestBuffer(int slot,sp<GraphicBuffer> * buf)32 status_t H2BGraphicBufferProducer::requestBuffer(int slot, sp<GraphicBuffer>* buf) {
33     bool converted = false;
34     status_t status = UNKNOWN_ERROR;
35     Return<void> transResult = mBase->requestBuffer(
36             slot, [&converted, &status, buf](HStatus hStatus, HBuffer const& hBuffer,
37                                              uint32_t generationNumber) {
38                 converted = h2b(hStatus, &status) && h2b(hBuffer, buf);
39                 if (*buf) {
40                     (*buf)->setGenerationNumber(generationNumber);
41                 }
42             });
43 
44     if (!transResult.isOk()) {
45         ALOGE("%s(): transaction failed: %s", __func__, transResult.description().c_str());
46         return FAILED_TRANSACTION;
47     }
48     if (!converted) {
49         ALOGE("%s(): corrupted transaction.", __func__);
50         return FAILED_TRANSACTION;
51     }
52     if (status != OK) {
53         ALOGD("%s() failed: %d", __func__, status);
54     }
55     return status;
56 }
57 
setMaxDequeuedBufferCount(int maxDequeuedBuffers)58 status_t H2BGraphicBufferProducer::setMaxDequeuedBufferCount(int maxDequeuedBuffers) {
59     status_t status = UNKNOWN_ERROR;
60     Return<HStatus> transResult =
61             mBase->setMaxDequeuedBufferCount(static_cast<int32_t>(maxDequeuedBuffers));
62 
63     if (!transResult.isOk()) {
64         ALOGE("%s(): transaction failed: %s", __func__, transResult.description().c_str());
65         return FAILED_TRANSACTION;
66     }
67     if (!h2b(static_cast<HStatus>(transResult), &status)) {
68         ALOGE("%s(): corrupted transaction.", __func__);
69         return FAILED_TRANSACTION;
70     }
71     if (status != OK) {
72         ALOGD("%s() failed: %d", __func__, status);
73     }
74     return status;
75 }
76 
dequeueBuffer(uint32_t width,uint32_t height,uint32_t pixelFormat,C2AndroidMemoryUsage androidUsage,int * slot,sp<Fence> * fence)77 status_t H2BGraphicBufferProducer::dequeueBuffer(uint32_t width, uint32_t height,
78                                                  uint32_t pixelFormat,
79                                                  C2AndroidMemoryUsage androidUsage, int* slot,
80                                                  sp<Fence>* fence) {
81     using Input = HGraphicBufferProducer::DequeueBufferInput;
82     using Output = HGraphicBufferProducer::DequeueBufferOutput;
83     Input input{width, height, pixelFormat, androidUsage.asGrallocUsage()};
84 
85     bool converted = false;
86     status_t status = UNKNOWN_ERROR;
87     Return<void> transResult = mBase->dequeueBuffer(
88             input, [&converted, &status, &slot, &fence](HStatus hStatus, int32_t hSlot,
89                                                         Output const& hOutput) {
90                 converted = h2b(hStatus, &status);
91                 if (!converted || status != OK) {
92                     return;
93                 }
94 
95                 *slot = hSlot;
96                 if (hOutput.bufferNeedsReallocation) {
97                     status = BUFFER_NEEDS_REALLOCATION;
98                 }
99                 converted = h2b(hOutput.fence, fence);
100             });
101 
102     if (!transResult.isOk()) {
103         ALOGE("%s(): transaction failed: %s", __func__, transResult.description().c_str());
104         return FAILED_TRANSACTION;
105     }
106     if (!converted) {
107         ALOGE("%s(): corrupted transaction.", __func__);
108         return FAILED_TRANSACTION;
109     }
110     // The C2VdaBqBlockPool does not fully own the bufferqueue. After buffers are dequeued here,
111     // they are passed into the codec2 framework, processed, and eventually queued into the
112     // bufferqueue. The C2VdaBqBlockPool cannot determine exactly when a buffer gets queued.
113     // However, if every buffer is being processed by the codec2 framework, then dequeueBuffer()
114     // will return INVALID_OPERATION because of an attempt to dequeue too many buffers.
115     // The C2VdaBqBlockPool cannot prevent this from happening, so just map it to TIMED_OUT
116     // and let the C2VdaBqBlockPool's caller's timeout retry logic handle the failure.
117     if (status == INVALID_OPERATION) {
118         status = TIMED_OUT;
119     }
120     if (status != OK && status != BUFFER_NEEDS_REALLOCATION && status != TIMED_OUT) {
121         ALOGD("%s() failed: %d", __func__, status);
122     }
123     return status;
124 }
125 
detachBuffer(int slot)126 status_t H2BGraphicBufferProducer::detachBuffer(int slot) {
127     status_t status = UNKNOWN_ERROR;
128     Return<HStatus> transResult = mBase->detachBuffer(static_cast<int32_t>(slot));
129 
130     if (!transResult.isOk()) {
131         ALOGE("%s(): transaction failed: %s", __func__, transResult.description().c_str());
132         return FAILED_TRANSACTION;
133     }
134     if (!h2b(static_cast<HStatus>(transResult), &status)) {
135         ALOGE("%s(): corrupted transaction.", __func__);
136         return FAILED_TRANSACTION;
137     }
138     if (status != OK) {
139         ALOGD("%s() failed: %d", __func__, status);
140     }
141     return status;
142 }
143 
attachBuffer(const sp<GraphicBuffer> & buffer,int * outSlot)144 status_t H2BGraphicBufferProducer::attachBuffer(const sp<GraphicBuffer>& buffer, int* outSlot) {
145     HBuffer hBuffer;
146     uint32_t hGenerationNumber;
147     if (!b2h(buffer, &hBuffer, &hGenerationNumber)) {
148         ALOGE("%s: invalid input buffer.", __func__);
149         return BAD_VALUE;
150     }
151 
152     bool converted = false;
153     status_t status = UNKNOWN_ERROR;
154     Return<void> transResult = mBase->attachBuffer(
155             hBuffer, hGenerationNumber,
156             [&converted, &status, outSlot](HStatus hStatus, int32_t hSlot, bool releaseAllBuffers) {
157                 converted = h2b(hStatus, &status);
158                 *outSlot = static_cast<int>(hSlot);
159                 if (converted && releaseAllBuffers && status == OK) {
160                     status = RELEASE_ALL_BUFFERS;
161                 }
162             });
163 
164     if (!transResult.isOk()) {
165         ALOGE("%s(): transaction failed: %s", __func__, transResult.description().c_str());
166         return FAILED_TRANSACTION;
167     }
168     if (!converted) {
169         ALOGE("%s(): corrupted transaction.", __func__);
170         return FAILED_TRANSACTION;
171     }
172     if (status != OK) {
173         ALOGD("%s() failed: %d", __func__, status);
174     }
175     return status;
176 }
177 
cancelBuffer(int slot,const sp<Fence> & fence)178 status_t H2BGraphicBufferProducer::cancelBuffer(int slot, const sp<Fence>& fence) {
179     HFenceWrapper hFenceWrapper;
180     if (!b2h(fence, &hFenceWrapper)) {
181         ALOGE("%s(): corrupted input fence.", __func__);
182         return UNKNOWN_ERROR;
183     }
184 
185     status_t status = UNKNOWN_ERROR;
186     Return<HStatus> transResult =
187             mBase->cancelBuffer(static_cast<int32_t>(slot), hFenceWrapper.getHandle());
188 
189     if (!transResult.isOk()) {
190         ALOGE("%s(): transaction failed: %s", __func__, transResult.description().c_str());
191         return FAILED_TRANSACTION;
192     }
193     if (!h2b(static_cast<HStatus>(transResult), &status)) {
194         ALOGE("%s(): corrupted transaction.", __func__);
195         return FAILED_TRANSACTION;
196     }
197     if (status != OK) {
198         ALOGD("%s() failed: %d", __func__, status);
199     }
200     return status;
201 }
202 
query(int what,int * value)203 int H2BGraphicBufferProducer::query(int what, int* value) {
204     int result = 0;
205     Return<void> transResult =
206             mBase->query(static_cast<int32_t>(what), [&result, value](int32_t r, int32_t v) {
207                 result = static_cast<int>(r);
208                 *value = static_cast<int>(v);
209             });
210 
211     if (!transResult.isOk()) {
212         ALOGE("%s(): transaction failed: %s", __func__, transResult.description().c_str());
213         return FAILED_TRANSACTION;
214     }
215     return result;
216 }
217 
allowAllocation(bool allow)218 status_t H2BGraphicBufferProducer::allowAllocation(bool allow) {
219     status_t status = UNKNOWN_ERROR;
220     Return<HStatus> transResult = mBase->allowAllocation(allow);
221 
222     if (!transResult.isOk()) {
223         ALOGE("%s(): transaction failed: %s", __func__, transResult.description().c_str());
224         return FAILED_TRANSACTION;
225     }
226     if (!h2b(static_cast<HStatus>(transResult), &status)) {
227         ALOGE("%s(): corrupted transaction.", __func__);
228         return FAILED_TRANSACTION;
229     }
230     if (status != OK) {
231         ALOGD("%s() failed: %d", __func__, status);
232     }
233     return status;
234 }
235 
getUniqueId(uint64_t * outId) const236 status_t H2BGraphicBufferProducer::getUniqueId(uint64_t* outId) const {
237     Return<uint64_t> transResult = mBase->getUniqueId();
238 
239     if (!transResult.isOk()) {
240         ALOGE("%s(): transaction failed: %s", __func__, transResult.description().c_str());
241         return FAILED_TRANSACTION;
242     }
243 
244     *outId = static_cast<uint64_t>(transResult);
245     return OK;
246 }
247 
248 // android::IProducerListener cannot be depended by vendor library, so we use HProducerListener
249 // directly.
connect(sp<HProducerListener> const & hListener,int32_t api,bool producerControlledByApp)250 status_t H2BGraphicBufferProducer::connect(sp<HProducerListener> const& hListener, int32_t api,
251                                            bool producerControlledByApp) {
252     bool converted = false;
253     status_t status = UNKNOWN_ERROR;
254     // hack(b/146409777): We pass self-defined api, so we don't use b2h() here.
255     Return<void> transResult = mBase->connect(
256             hListener, static_cast<HConnectionType>(api), producerControlledByApp,
257             [&converted, &status](HStatus hStatus, HQueueBufferOutput const& /* hOutput */) {
258                 converted = h2b(hStatus, &status);
259             });
260 
261     if (!transResult.isOk()) {
262         ALOGE("%s(): transaction failed: %s", __func__, transResult.description().c_str());
263         return FAILED_TRANSACTION;
264     }
265     if (!converted) {
266         ALOGE("%s(): corrupted transaction.", __func__);
267         return FAILED_TRANSACTION;
268     }
269     return status;
270 }
271 
setDequeueTimeout(nsecs_t timeout)272 status_t H2BGraphicBufferProducer::setDequeueTimeout(nsecs_t timeout) {
273     status_t status = UNKNOWN_ERROR;
274     Return<HStatus> transResult = mBase->setDequeueTimeout(static_cast<int64_t>(timeout));
275 
276     if (!transResult.isOk()) {
277         ALOGE("%s(): transaction failed: %s", __func__, transResult.description().c_str());
278         return FAILED_TRANSACTION;
279     }
280     if (!h2b(static_cast<HStatus>(transResult), &status)) {
281         ALOGE("%s(): corrupted transaction.", __func__);
282         return FAILED_TRANSACTION;
283     }
284     return status;
285 }
286 
287 }  // namespace android
288