• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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