1 #include "include/dvr/dvr_api.h"
2 #include "include/dvr/dvr_buffer_queue.h"
3
4 #include <android/native_window.h>
5 #include <private/dvr/buffer_hub_queue_producer.h>
6
7 #include "dvr_internal.h"
8 #include "dvr_buffer_queue_internal.h"
9
10 using namespace android;
11 using android::dvr::BufferConsumer;
12 using android::dvr::BufferHubBuffer;
13 using android::dvr::BufferHubQueueProducer;
14 using android::dvr::BufferProducer;
15 using android::dvr::ConsumerQueue;
16 using android::dvr::ProducerQueue;
17 using android::dvr::ProducerQueueConfigBuilder;
18 using android::dvr::UsagePolicy;
19
20 extern "C" {
21
DvrWriteBufferQueue(const std::shared_ptr<ProducerQueue> & producer_queue)22 DvrWriteBufferQueue::DvrWriteBufferQueue(
23 const std::shared_ptr<ProducerQueue>& producer_queue)
24 : producer_queue_(producer_queue),
25 width_(producer_queue->default_width()),
26 height_(producer_queue->default_height()),
27 format_(producer_queue->default_format()) {}
28
GetNativeWindow(ANativeWindow ** out_window)29 int DvrWriteBufferQueue::GetNativeWindow(ANativeWindow** out_window) {
30 if (native_window_ == nullptr) {
31 // Lazy creation of |native_window|, as not everyone is using
32 // DvrWriteBufferQueue as an external surface.
33 sp<IGraphicBufferProducer> gbp =
34 BufferHubQueueProducer::Create(producer_queue_);
35 native_window_ = new Surface(gbp, true);
36 }
37
38 *out_window = static_cast<ANativeWindow*>(native_window_.get());
39 return 0;
40 }
41
CreateReadQueue(DvrReadBufferQueue ** out_read_queue)42 int DvrWriteBufferQueue::CreateReadQueue(DvrReadBufferQueue** out_read_queue) {
43 std::unique_ptr<ConsumerQueue> consumer_queue =
44 producer_queue_->CreateConsumerQueue();
45 if (consumer_queue == nullptr) {
46 ALOGE(
47 "DvrWriteBufferQueue::CreateReadQueue: Failed to create consumer queue "
48 "from producer queue: queue_id=%d.", producer_queue_->id());
49 return -ENOMEM;
50 }
51
52 *out_read_queue = new DvrReadBufferQueue(std::move(consumer_queue));
53 return 0;
54 }
55
Dequeue(int timeout,DvrWriteBuffer * write_buffer,int * out_fence_fd)56 int DvrWriteBufferQueue::Dequeue(int timeout, DvrWriteBuffer* write_buffer,
57 int* out_fence_fd) {
58 DvrNativeBufferMetadata meta;
59 DvrWriteBuffer* buffer = nullptr;
60 int fence_fd = -1;
61 if (const int ret = GainBuffer(timeout, &buffer, &meta, &fence_fd))
62 return ret;
63 if (!buffer)
64 return -ENOMEM;
65
66 write_buffers_[buffer->slot].reset(buffer);
67 write_buffer->write_buffer = std::move(buffer->write_buffer);
68 *out_fence_fd = fence_fd;
69 return 0;
70 }
71
GainBuffer(int timeout,DvrWriteBuffer ** out_write_buffer,DvrNativeBufferMetadata * out_meta,int * out_fence_fd)72 int DvrWriteBufferQueue::GainBuffer(int timeout,
73 DvrWriteBuffer** out_write_buffer,
74 DvrNativeBufferMetadata* out_meta,
75 int* out_fence_fd) {
76 size_t slot;
77 pdx::LocalHandle release_fence;
78
79 // Need to retry N+1 times, where N is total number of buffers in the queue.
80 // As in the worst case, we will dequeue all N buffers and reallocate them, on
81 // the {N+1}th dequeue, we are guaranteed to get a buffer with new dimension.
82 size_t max_retries = 1 + producer_queue_->capacity();
83 size_t retry = 0;
84
85 for (; retry < max_retries; retry++) {
86 auto buffer_status =
87 producer_queue_->Dequeue(timeout, &slot, out_meta, &release_fence);
88 if (!buffer_status) {
89 ALOGE_IF(buffer_status.error() != ETIMEDOUT,
90 "DvrWriteBufferQueue::GainBuffer: Failed to dequeue buffer: %s",
91 buffer_status.GetErrorMessage().c_str());
92 return -buffer_status.error();
93 }
94
95 if (write_buffers_[slot] == nullptr) {
96 // Lazy initialization of a write_buffers_ slot. Note that a slot will
97 // only be dynamically allocated once during the entire cycle life of a
98 // queue.
99 write_buffers_[slot] = std::make_unique<DvrWriteBuffer>();
100 write_buffers_[slot]->slot = slot;
101 }
102
103 LOG_ALWAYS_FATAL_IF(
104 write_buffers_[slot]->write_buffer,
105 "DvrWriteBufferQueue::GainBuffer: Buffer slot is not empty: %zu", slot);
106 write_buffers_[slot]->write_buffer = std::move(buffer_status.take());
107
108 const auto& buffer_producer = write_buffers_[slot]->write_buffer;
109 if (!buffer_producer)
110 return -ENOMEM;
111
112 if (width_ == buffer_producer->width() &&
113 height_ == buffer_producer->height() &&
114 format_ == buffer_producer->format()) {
115 // Producer queue returns a buffer matches the current request.
116 break;
117 }
118
119 // Needs reallocation. Note that if there are already multiple available
120 // buffers in the queue, the next one returned from |queue_->Dequeue| may
121 // still have the old buffer dimension or format. Retry up to N+1 times or
122 // until we dequeued a buffer with new configuration.
123 ALOGD_IF(TRACE,
124 "DvrWriteBufferQueue::Dequeue: requested buffer at slot: %zu "
125 "(w=%u, h=%u, fmt=%u) is different from the buffer returned "
126 "(w=%u, h=%u, fmt=%u). Need re-allocation.",
127 slot, width_, height_, format_, buffer_producer->width(),
128 buffer_producer->height(), buffer_producer->format());
129
130 // Currently, we are not storing |layer_count| and |usage| in queue
131 // configuration. Copy those setup from the last buffer dequeued before we
132 // remove it.
133 uint32_t old_layer_count = buffer_producer->layer_count();
134 uint64_t old_usage = buffer_producer->usage();
135
136 // Allocate a new producer buffer with new buffer configs. Note that if
137 // there are already multiple available buffers in the queue, the next one
138 // returned from |queue_->Dequeue| may still have the old buffer dimension
139 // or format. Retry up to BufferHubQueue::kMaxQueueCapacity times or until
140 // we dequeued a buffer with new configuration.
141 auto remove_status = producer_queue_->RemoveBuffer(slot);
142 if (!remove_status) {
143 ALOGE("DvrWriteBufferQueue::Dequeue: Failed to remove buffer: %s",
144 remove_status.GetErrorMessage().c_str());
145 return -remove_status.error();
146 }
147 // Make sure that the previously allocated buffer is dereferenced from
148 // write_buffers_ array.
149 write_buffers_[slot]->write_buffer = nullptr;
150
151 auto allocate_status = producer_queue_->AllocateBuffer(
152 width_, height_, old_layer_count, format_, old_usage);
153 if (!allocate_status) {
154 ALOGE("DvrWriteBufferQueue::Dequeue: Failed to allocate buffer: %s",
155 allocate_status.GetErrorMessage().c_str());
156 return -allocate_status.error();
157 }
158 }
159
160 if (retry >= max_retries) {
161 ALOGE(
162 "DvrWriteBufferQueue::Dequeue: Failed to re-allocate buffer after "
163 "resizing.");
164 return -ENOMEM;
165 }
166
167 *out_write_buffer = write_buffers_[slot].release();
168 *out_fence_fd = release_fence.Release();
169
170 return 0;
171 }
172
PostBuffer(DvrWriteBuffer * write_buffer,const DvrNativeBufferMetadata * meta,int ready_fence_fd)173 int DvrWriteBufferQueue::PostBuffer(DvrWriteBuffer* write_buffer,
174 const DvrNativeBufferMetadata* meta,
175 int ready_fence_fd) {
176 LOG_FATAL_IF(
177 (write_buffers->slot < 0 || write_buffers->slot >= write_buffers_.size()),
178 "DvrWriteBufferQueue::ReleaseBuffer: Invalid slot: %zu", slot);
179
180 // Some basic sanity checks before we put the buffer back into a slot.
181 size_t slot = static_cast<size_t>(write_buffer->slot);
182 if (write_buffers_[slot] != nullptr) {
183 ALOGE("DvrWriteBufferQueue::PostBuffer: Slot is not empty: %zu", slot);
184 return -EINVAL;
185 }
186 if (write_buffer->write_buffer == nullptr) {
187 ALOGE("DvrWriteBufferQueue::PostBuffer: Invalid write buffer.");
188 return -EINVAL;
189 }
190 if (write_buffer->write_buffer->id() != producer_queue_->GetBufferId(slot)) {
191 ALOGE(
192 "DvrWriteBufferQueue::PostBuffer: Buffer to be posted does not "
193 "belong to this buffer queue. Posting buffer: id=%d, buffer in "
194 "queue: id=%d",
195 write_buffer->write_buffer->id(), producer_queue_->GetBufferId(slot));
196 return -EINVAL;
197 }
198
199 write_buffer->write_buffer->SetQueueIndex(next_post_index_++);
200 pdx::LocalHandle fence(ready_fence_fd);
201 const int ret = write_buffer->write_buffer->PostAsync(meta, fence);
202 if (ret < 0) {
203 ALOGE("DvrWriteBufferQueue::PostBuffer: Failed to post buffer, ret=%d",
204 ret);
205 return ret;
206 }
207
208 // Put the DvrWriteBuffer pointer back into its slot for reuse.
209 write_buffers_[slot].reset(write_buffer);
210 // It's import to reset the write buffer client now. It should stay invalid
211 // until next GainBuffer on the same slot.
212 write_buffers_[slot]->write_buffer = nullptr;
213 return 0;
214 }
215
ResizeBuffer(uint32_t width,uint32_t height)216 int DvrWriteBufferQueue::ResizeBuffer(uint32_t width, uint32_t height) {
217 if (width == 0 || height == 0) {
218 ALOGE(
219 "DvrWriteBufferQueue::ResizeBuffer: invalid buffer dimension: w=%u, "
220 "h=%u.",
221 width, height);
222 return -EINVAL;
223 }
224
225 width_ = width;
226 height_ = height;
227 return 0;
228 }
229
dvrWriteBufferQueueCreate(uint32_t width,uint32_t height,uint32_t format,uint32_t layer_count,uint64_t usage,size_t capacity,size_t metadata_size,DvrWriteBufferQueue ** out_write_queue)230 int dvrWriteBufferQueueCreate(uint32_t width, uint32_t height, uint32_t format,
231 uint32_t layer_count, uint64_t usage,
232 size_t capacity, size_t metadata_size,
233 DvrWriteBufferQueue** out_write_queue) {
234 if (!out_write_queue)
235 return -EINVAL;
236
237 auto config_builder = ProducerQueueConfigBuilder()
238 .SetDefaultWidth(width)
239 .SetDefaultHeight(height)
240 .SetDefaultFormat(format)
241 .SetMetadataSize(metadata_size);
242 std::unique_ptr<ProducerQueue> producer_queue =
243 ProducerQueue::Create(config_builder.Build(), UsagePolicy{});
244 if (!producer_queue) {
245 ALOGE("dvrWriteBufferQueueCreate: Failed to create producer queue.");
246 return -ENOMEM;
247 }
248
249 auto status = producer_queue->AllocateBuffers(width, height, layer_count,
250 format, usage, capacity);
251 if (!status.ok()) {
252 ALOGE("dvrWriteBufferQueueCreate: Failed to allocate buffers.");
253 return -ENOMEM;
254 }
255
256 *out_write_queue = new DvrWriteBufferQueue(std::move(producer_queue));
257 return 0;
258 }
259
dvrWriteBufferQueueDestroy(DvrWriteBufferQueue * write_queue)260 void dvrWriteBufferQueueDestroy(DvrWriteBufferQueue* write_queue) {
261 delete write_queue;
262 }
263
dvrWriteBufferQueueGetCapacity(DvrWriteBufferQueue * write_queue)264 ssize_t dvrWriteBufferQueueGetCapacity(DvrWriteBufferQueue* write_queue) {
265 if (!write_queue)
266 return -EINVAL;
267
268 return write_queue->capacity();
269 }
270
dvrWriteBufferQueueGetId(DvrWriteBufferQueue * write_queue)271 int dvrWriteBufferQueueGetId(DvrWriteBufferQueue* write_queue) {
272 if (!write_queue)
273 return -EINVAL;
274
275 return write_queue->id();
276 }
277
dvrWriteBufferQueueGetExternalSurface(DvrWriteBufferQueue * write_queue,ANativeWindow ** out_window)278 int dvrWriteBufferQueueGetExternalSurface(DvrWriteBufferQueue* write_queue,
279 ANativeWindow** out_window) {
280 ALOGW(
281 "dvrWriteBufferQueueGetExternalSurface: This API has been deprecated and "
282 "renamed to dvrWriteBufferQueueGetANativeWindow.");
283 return dvrWriteBufferQueueGetANativeWindow(write_queue, out_window);
284 }
285
dvrWriteBufferQueueGetANativeWindow(DvrWriteBufferQueue * write_queue,ANativeWindow ** out_window)286 int dvrWriteBufferQueueGetANativeWindow(DvrWriteBufferQueue* write_queue,
287 ANativeWindow** out_window) {
288 if (!write_queue || !out_window)
289 return -EINVAL;
290
291 return write_queue->GetNativeWindow(out_window);
292 }
293
dvrWriteBufferQueueCreateReadQueue(DvrWriteBufferQueue * write_queue,DvrReadBufferQueue ** out_read_queue)294 int dvrWriteBufferQueueCreateReadQueue(DvrWriteBufferQueue* write_queue,
295 DvrReadBufferQueue** out_read_queue) {
296 if (!write_queue || !out_read_queue)
297 return -EINVAL;
298
299 return write_queue->CreateReadQueue(out_read_queue);
300 }
301
dvrWriteBufferQueueDequeue(DvrWriteBufferQueue * write_queue,int timeout,DvrWriteBuffer * write_buffer,int * out_fence_fd)302 int dvrWriteBufferQueueDequeue(DvrWriteBufferQueue* write_queue, int timeout,
303 DvrWriteBuffer* write_buffer,
304 int* out_fence_fd) {
305 if (!write_queue || !write_buffer || !out_fence_fd)
306 return -EINVAL;
307
308 return write_queue->Dequeue(timeout, write_buffer, out_fence_fd);
309 }
310
dvrWriteBufferQueueGainBuffer(DvrWriteBufferQueue * write_queue,int timeout,DvrWriteBuffer ** out_write_buffer,DvrNativeBufferMetadata * out_meta,int * out_fence_fd)311 int dvrWriteBufferQueueGainBuffer(DvrWriteBufferQueue* write_queue, int timeout,
312 DvrWriteBuffer** out_write_buffer,
313 DvrNativeBufferMetadata* out_meta,
314 int* out_fence_fd) {
315 if (!write_queue || !out_write_buffer || !out_meta || !out_fence_fd)
316 return -EINVAL;
317
318 return write_queue->GainBuffer(timeout, out_write_buffer, out_meta,
319 out_fence_fd);
320 }
321
dvrWriteBufferQueuePostBuffer(DvrWriteBufferQueue * write_queue,DvrWriteBuffer * write_buffer,const DvrNativeBufferMetadata * meta,int ready_fence_fd)322 int dvrWriteBufferQueuePostBuffer(DvrWriteBufferQueue* write_queue,
323 DvrWriteBuffer* write_buffer,
324 const DvrNativeBufferMetadata* meta,
325 int ready_fence_fd) {
326 if (!write_queue || !write_buffer || !write_buffer->write_buffer || !meta)
327 return -EINVAL;
328
329 return write_queue->PostBuffer(write_buffer, meta, ready_fence_fd);
330 }
331
dvrWriteBufferQueueResizeBuffer(DvrWriteBufferQueue * write_queue,uint32_t width,uint32_t height)332 int dvrWriteBufferQueueResizeBuffer(DvrWriteBufferQueue* write_queue,
333 uint32_t width, uint32_t height) {
334 if (!write_queue)
335 return -EINVAL;
336
337 return write_queue->ResizeBuffer(width, height);
338 }
339
340 // ReadBufferQueue
341
DvrReadBufferQueue(const std::shared_ptr<ConsumerQueue> & consumer_queue)342 DvrReadBufferQueue::DvrReadBufferQueue(
343 const std::shared_ptr<ConsumerQueue>& consumer_queue)
344 : consumer_queue_(consumer_queue) {}
345
CreateReadQueue(DvrReadBufferQueue ** out_read_queue)346 int DvrReadBufferQueue::CreateReadQueue(DvrReadBufferQueue** out_read_queue) {
347 std::unique_ptr<ConsumerQueue> consumer_queue =
348 consumer_queue_->CreateConsumerQueue();
349 if (consumer_queue == nullptr) {
350 ALOGE(
351 "DvrReadBufferQueue::CreateReadQueue: Failed to create consumer queue "
352 "from producer queue: queue_id=%d.", consumer_queue_->id());
353 return -ENOMEM;
354 }
355
356 *out_read_queue = new DvrReadBufferQueue(std::move(consumer_queue));
357 return 0;
358 }
359
Dequeue(int timeout,DvrReadBuffer * read_buffer,int * out_fence_fd,void * out_meta,size_t meta_size_bytes)360 int DvrReadBufferQueue::Dequeue(int timeout, DvrReadBuffer* read_buffer,
361 int* out_fence_fd, void* out_meta,
362 size_t meta_size_bytes) {
363 if (meta_size_bytes != consumer_queue_->metadata_size()) {
364 ALOGE(
365 "DvrReadBufferQueue::Dequeue: Invalid metadata size, expected (%zu), "
366 "but actual (%zu).",
367 consumer_queue_->metadata_size(), meta_size_bytes);
368 return -EINVAL;
369 }
370
371 size_t slot;
372 pdx::LocalHandle acquire_fence;
373 auto buffer_status = consumer_queue_->Dequeue(
374 timeout, &slot, out_meta, meta_size_bytes, &acquire_fence);
375 if (!buffer_status) {
376 ALOGE_IF(buffer_status.error() != ETIMEDOUT,
377 "dvrReadBufferQueueDequeue: Failed to dequeue buffer: %s",
378 buffer_status.GetErrorMessage().c_str());
379 return -buffer_status.error();
380 }
381
382 read_buffer->read_buffer = buffer_status.take();
383 *out_fence_fd = acquire_fence.Release();
384
385 return 0;
386 }
387
AcquireBuffer(int timeout,DvrReadBuffer ** out_read_buffer,DvrNativeBufferMetadata * out_meta,int * out_fence_fd)388 int DvrReadBufferQueue::AcquireBuffer(int timeout,
389 DvrReadBuffer** out_read_buffer,
390 DvrNativeBufferMetadata* out_meta,
391 int* out_fence_fd) {
392 size_t slot;
393 pdx::LocalHandle acquire_fence;
394 auto buffer_status =
395 consumer_queue_->Dequeue(timeout, &slot, out_meta, &acquire_fence);
396 if (!buffer_status) {
397 ALOGE_IF(buffer_status.error() != ETIMEDOUT,
398 "DvrReadBufferQueue::AcquireBuffer: Failed to dequeue buffer: %s",
399 buffer_status.GetErrorMessage().c_str());
400 return -buffer_status.error();
401 }
402
403 if (read_buffers_[slot] == nullptr) {
404 // Lazy initialization of a read_buffers_ slot. Note that a slot will only
405 // be dynamically allocated once during the entire cycle life of a queue.
406 read_buffers_[slot] = std::make_unique<DvrReadBuffer>();
407 read_buffers_[slot]->slot = slot;
408 }
409
410 LOG_FATAL_IF(
411 read_buffers_[slot]->read_buffer,
412 "DvrReadBufferQueue::AcquireBuffer: Buffer slot is not empty: %zu", slot);
413 read_buffers_[slot]->read_buffer = std::move(buffer_status.take());
414
415 *out_read_buffer = read_buffers_[slot].release();
416 *out_fence_fd = acquire_fence.Release();
417
418 return 0;
419 }
420
ReleaseBuffer(DvrReadBuffer * read_buffer,const DvrNativeBufferMetadata * meta,int release_fence_fd)421 int DvrReadBufferQueue::ReleaseBuffer(DvrReadBuffer* read_buffer,
422 const DvrNativeBufferMetadata* meta,
423 int release_fence_fd) {
424 LOG_FATAL_IF(
425 (read_buffers->slot < 0 || read_buffers->slot >= read_buffers_size()),
426 "DvrReadBufferQueue::ReleaseBuffer: Invalid slot: %zu", slot);
427
428 // Some basic sanity checks before we put the buffer back into a slot.
429 size_t slot = static_cast<size_t>(read_buffer->slot);
430 if (read_buffers_[slot] != nullptr) {
431 ALOGE("DvrReadBufferQueue::ReleaseBuffer: Slot is not empty: %zu", slot);
432 return -EINVAL;
433 }
434 if (read_buffer->read_buffer == nullptr) {
435 ALOGE("DvrReadBufferQueue::ReleaseBuffer: Invalid read buffer.");
436 return -EINVAL;
437 }
438 if (read_buffer->read_buffer->id() != consumer_queue_->GetBufferId(slot)) {
439 ALOGE(
440 "DvrReadBufferQueue::ReleaseBuffer: Buffer to be released does not "
441 "belong to this buffer queue. Releasing buffer: id=%d, buffer in "
442 "queue: id=%d",
443 read_buffer->read_buffer->id(), consumer_queue_->GetBufferId(slot));
444 return -EINVAL;
445 }
446
447 pdx::LocalHandle fence(release_fence_fd);
448 int ret = read_buffer->read_buffer->ReleaseAsync(meta, fence);
449 if (ret < 0) {
450 ALOGE("DvrReadBufferQueue::ReleaseBuffer: Failed to release buffer, ret=%d",
451 ret);
452 return ret;
453 }
454
455 // Put the DvrReadBuffer pointer back into its slot for reuse.
456 read_buffers_[slot].reset(read_buffer);
457 // It's import to reset the read buffer client now. It should stay invalid
458 // until next AcquireBuffer on the same slot.
459 read_buffers_[slot]->read_buffer = nullptr;
460 return 0;
461 }
462
SetBufferAvailableCallback(DvrReadBufferQueueBufferAvailableCallback callback,void * context)463 void DvrReadBufferQueue::SetBufferAvailableCallback(
464 DvrReadBufferQueueBufferAvailableCallback callback, void* context) {
465 if (callback == nullptr) {
466 consumer_queue_->SetBufferAvailableCallback(nullptr);
467 } else {
468 consumer_queue_->SetBufferAvailableCallback(
469 [callback, context]() { callback(context); });
470 }
471 }
472
SetBufferRemovedCallback(DvrReadBufferQueueBufferRemovedCallback callback,void * context)473 void DvrReadBufferQueue::SetBufferRemovedCallback(
474 DvrReadBufferQueueBufferRemovedCallback callback, void* context) {
475 if (callback == nullptr) {
476 consumer_queue_->SetBufferRemovedCallback(nullptr);
477 } else {
478 consumer_queue_->SetBufferRemovedCallback(
479 [callback, context](const std::shared_ptr<BufferHubBuffer>& buffer) {
480 // When buffer is removed from the queue, the slot is already invalid.
481 auto read_buffer = std::make_unique<DvrReadBuffer>();
482 read_buffer->read_buffer =
483 std::static_pointer_cast<BufferConsumer>(buffer);
484 callback(read_buffer.release(), context);
485 });
486 }
487 }
488
HandleEvents()489 int DvrReadBufferQueue::HandleEvents() {
490 // TODO(jwcai) Probably should change HandleQueueEvents to return Status.
491 consumer_queue_->HandleQueueEvents();
492 return 0;
493 }
494
dvrReadBufferQueueDestroy(DvrReadBufferQueue * read_queue)495 void dvrReadBufferQueueDestroy(DvrReadBufferQueue* read_queue) {
496 delete read_queue;
497 }
498
dvrReadBufferQueueGetCapacity(DvrReadBufferQueue * read_queue)499 ssize_t dvrReadBufferQueueGetCapacity(DvrReadBufferQueue* read_queue) {
500 if (!read_queue)
501 return -EINVAL;
502
503 return read_queue->capacity();
504 }
505
dvrReadBufferQueueGetId(DvrReadBufferQueue * read_queue)506 int dvrReadBufferQueueGetId(DvrReadBufferQueue* read_queue) {
507 if (!read_queue)
508 return -EINVAL;
509
510 return read_queue->id();
511 }
512
dvrReadBufferQueueGetEventFd(DvrReadBufferQueue * read_queue)513 int dvrReadBufferQueueGetEventFd(DvrReadBufferQueue* read_queue) {
514 if (!read_queue)
515 return -EINVAL;
516
517 return read_queue->event_fd();
518 }
519
dvrReadBufferQueueCreateReadQueue(DvrReadBufferQueue * read_queue,DvrReadBufferQueue ** out_read_queue)520 int dvrReadBufferQueueCreateReadQueue(DvrReadBufferQueue* read_queue,
521 DvrReadBufferQueue** out_read_queue) {
522 if (!read_queue || !out_read_queue)
523 return -EINVAL;
524
525 return read_queue->CreateReadQueue(out_read_queue);
526 }
527
dvrReadBufferQueueDequeue(DvrReadBufferQueue * read_queue,int timeout,DvrReadBuffer * read_buffer,int * out_fence_fd,void * out_meta,size_t meta_size_bytes)528 int dvrReadBufferQueueDequeue(DvrReadBufferQueue* read_queue, int timeout,
529 DvrReadBuffer* read_buffer, int* out_fence_fd,
530 void* out_meta, size_t meta_size_bytes) {
531 if (!read_queue || !read_buffer || !out_fence_fd)
532 return -EINVAL;
533
534 if (meta_size_bytes != 0 && !out_meta)
535 return -EINVAL;
536
537 return read_queue->Dequeue(timeout, read_buffer, out_fence_fd, out_meta,
538 meta_size_bytes);
539 }
540
dvrReadBufferQueueAcquireBuffer(DvrReadBufferQueue * read_queue,int timeout,DvrReadBuffer ** out_read_buffer,DvrNativeBufferMetadata * out_meta,int * out_fence_fd)541 int dvrReadBufferQueueAcquireBuffer(DvrReadBufferQueue* read_queue, int timeout,
542 DvrReadBuffer** out_read_buffer,
543 DvrNativeBufferMetadata* out_meta,
544 int* out_fence_fd) {
545 if (!read_queue || !out_read_buffer || !out_meta || !out_fence_fd)
546 return -EINVAL;
547
548 return read_queue->AcquireBuffer(timeout, out_read_buffer, out_meta,
549 out_fence_fd);
550 }
551
dvrReadBufferQueueReleaseBuffer(DvrReadBufferQueue * read_queue,DvrReadBuffer * read_buffer,const DvrNativeBufferMetadata * meta,int release_fence_fd)552 int dvrReadBufferQueueReleaseBuffer(DvrReadBufferQueue* read_queue,
553 DvrReadBuffer* read_buffer,
554 const DvrNativeBufferMetadata* meta,
555 int release_fence_fd) {
556 if (!read_queue || !read_buffer || !read_buffer->read_buffer || !meta)
557 return -EINVAL;
558
559 return read_queue->ReleaseBuffer(read_buffer, meta, release_fence_fd);
560 }
561
dvrReadBufferQueueSetBufferAvailableCallback(DvrReadBufferQueue * read_queue,DvrReadBufferQueueBufferAvailableCallback callback,void * context)562 int dvrReadBufferQueueSetBufferAvailableCallback(
563 DvrReadBufferQueue* read_queue,
564 DvrReadBufferQueueBufferAvailableCallback callback, void* context) {
565 if (!read_queue)
566 return -EINVAL;
567
568 read_queue->SetBufferAvailableCallback(callback, context);
569 return 0;
570 }
571
dvrReadBufferQueueSetBufferRemovedCallback(DvrReadBufferQueue * read_queue,DvrReadBufferQueueBufferRemovedCallback callback,void * context)572 int dvrReadBufferQueueSetBufferRemovedCallback(
573 DvrReadBufferQueue* read_queue,
574 DvrReadBufferQueueBufferRemovedCallback callback, void* context) {
575 if (!read_queue)
576 return -EINVAL;
577
578 read_queue->SetBufferRemovedCallback(callback, context);
579 return 0;
580 }
581
dvrReadBufferQueueHandleEvents(DvrReadBufferQueue * read_queue)582 int dvrReadBufferQueueHandleEvents(DvrReadBufferQueue* read_queue) {
583 if (!read_queue)
584 return -EINVAL;
585
586 return read_queue->HandleEvents();
587 }
588
589 } // extern "C"
590