+
+ if (out_slot) {
+ // TODO(b/65469368): Remove this null check once dvrReadBufferQueueDequeue
+ // is deprecated.
+ *out_slot = slot;
+ }
+ return 0;
+}
+
+int DvrReadBufferQueue::AcquireBuffer(int timeout,
+ DvrReadBuffer** out_read_buffer,
+ DvrNativeBufferMetadata* out_meta,
+ int* out_fence_fd) {
+ DvrReadBuffer read_buffer;
+ int fence_fd;
+ size_t slot;
+ const int ret = Dequeue(timeout, &read_buffer, &fence_fd, &slot, out_meta,
+ sizeof(*out_meta));
+ if (ret < 0) {
+ ALOGE_IF(
+ ret != -ETIMEDOUT,
+ "DvrReadBufferQueue::AcquireBuffer: Failed to dequeue buffer, error=%d",
+ ret);
+ return ret;
+ }
+
+ if (read_buffers_[slot] == nullptr) {
+ // Lazy initialization of a read_buffers_ slot. Note that a slot will only
+ // be dynamically allocated once during the entire cycle life of a queue.
+ read_buffers_[slot] = std::make_unique<DvrReadBuffer>();
+ read_buffers_[slot]->slot = slot;
+ }
+
+ LOG_FATAL_IF(
+ read_buffers_[slot]->read_buffer,
+ "DvrReadBufferQueue::AcquireBuffer: Buffer slot is not empty: %zu", slot);
+ read_buffers_[slot]->read_buffer = std::move(read_buffer.read_buffer);
+
+ *out_read_buffer = read_buffers_[slot].release();
+ *out_fence_fd = fence_fd;
+
+ return 0;
+}
+
+int DvrReadBufferQueue::ReleaseBuffer(DvrReadBuffer* read_buffer,
+ const DvrNativeBufferMetadata* meta,
+ int release_fence_fd) {
+ LOG_FATAL_IF(
+ (read_buffers->slot < 0 || read_buffers->slot >= read_buffers_size()),
+ "DvrReadBufferQueue::ReleaseBuffer: Invalid slot: %zu", slot);
+
+ // Some basic sanity checks before we put the buffer back into a slot.
+ size_t slot = static_cast<size_t>(read_buffer->slot);
+ if (read_buffers_[slot] != nullptr) {
+ ALOGE("DvrReadBufferQueue::ReleaseBuffer: Slot is not empty: %zu", slot);
+ return -EINVAL;
+ }
+ if (read_buffer->read_buffer == nullptr) {
+ ALOGE("DvrReadBufferQueue::ReleaseBuffer: Invalid read buffer.");
+ return -EINVAL;
+ }
+ if (read_buffer->read_buffer->id() != consumer_queue_->GetBufferId(slot)) {
+ ALOGE(
+ "DvrReadBufferQueue::ReleaseBuffer: Buffer to be released does not "
+ "belong to this buffer queue.");
+ return -EINVAL;
+ }
+
+ pdx::LocalHandle fence(release_fence_fd);
+ int ret = 0;
+ if (fence) {
+ ret = read_buffer->read_buffer->Release(fence);
+ } else {
+ // TODO(b/65458354): Send metadata back to producer once shared memory based
+ // metadata is implemented.
+ // TODO(b/65455724): All BufferHub operations should be async.
+ ret = read_buffer->read_buffer->ReleaseAsync();
+ }
+ if (ret < 0) {
+ ALOGE("DvrReadBufferQueue::ReleaseBuffer: Failed to release buffer, ret=%d",
+ ret);
+ return ret;
+ }
+
+ // Put the DvrReadBuffer pointer back into its slot for reuse.
+ read_buffers_[slot].reset(read_buffer);
+ // It's import to reset the read buffer client now. It should stay invalid
+ // until next AcquireBuffer on the same slot.
+ read_buffers_[slot]->read_buffer = nullptr;