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