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