Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit fcc70bdc authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Overhual DvrBuffer and DvrBufferQueue API: Step 1" into oc-mr1-dev

parents 4b58ec86 638b7f74
Loading
Loading
Loading
Loading
+6 −1
Original line number Diff line number Diff line
@@ -66,6 +66,11 @@ class BufferHubQueue : public pdx::Client {

  explicit operator bool() const { return epoll_fd_.IsValid(); }

  int GetBufferId(size_t slot) const {
    return (slot < buffers_.size() && buffers_[slot]) ? buffers_[slot]->id()
                                                      : -1;
  }

  std::shared_ptr<BufferHubBuffer> GetBuffer(size_t slot) const {
    return buffers_[slot];
  }
@@ -218,7 +223,7 @@ class BufferHubQueue : public pdx::Client {
  // Tracks the buffers belonging to this queue. Buffers are stored according to
  // "slot" in this vector. Each slot is a logical id of the buffer within this
  // queue regardless of its queue position or presence in the ring buffer.
  std::vector<std::shared_ptr<BufferHubBuffer>> buffers_{kMaxQueueCapacity};
  std::array<std::shared_ptr<BufferHubBuffer>, kMaxQueueCapacity> buffers_;

  // Buffers and related data that are available for dequeue.
  RingBuffer<Entry> available_buffers_{kMaxQueueCapacity};
+16 −2
Original line number Diff line number Diff line
@@ -44,8 +44,14 @@ void dvrWriteBufferCreateEmpty(DvrWriteBuffer** write_buffer) {
}

void dvrWriteBufferDestroy(DvrWriteBuffer* write_buffer) {
  if (write_buffer != nullptr) {
    ALOGW_IF(
        write_buffer->slot != -1,
        "dvrWriteBufferDestroy: Destroying a buffer associated with a valid "
        "buffer queue slot. This may indicate possible leaks.");
    delete write_buffer;
  }
}

int dvrWriteBufferIsValid(DvrWriteBuffer* write_buffer) {
  return write_buffer && write_buffer->write_buffer;
@@ -107,7 +113,15 @@ void dvrReadBufferCreateEmpty(DvrReadBuffer** read_buffer) {
    *read_buffer = new DvrReadBuffer;
}

void dvrReadBufferDestroy(DvrReadBuffer* read_buffer) { delete read_buffer; }
void dvrReadBufferDestroy(DvrReadBuffer* read_buffer) {
  if (read_buffer != nullptr) {
    ALOGW_IF(
        read_buffer->slot != -1,
        "dvrReadBufferDestroy: Destroying a buffer associated with a valid "
        "buffer queue slot. This may indicate possible leaks.");
    delete read_buffer;
  }
}

int dvrReadBufferIsValid(DvrReadBuffer* read_buffer) {
  return read_buffer && read_buffer->read_buffer;
+224 −9
Original line number Diff line number Diff line
@@ -63,7 +63,7 @@ int DvrWriteBufferQueue::CreateReadQueue(DvrReadBufferQueue** out_read_queue) {
}

int DvrWriteBufferQueue::Dequeue(int timeout, DvrWriteBuffer* write_buffer,
                                 int* out_fence_fd) {
                                 int* out_fence_fd, size_t* out_slot) {
  size_t slot;
  pdx::LocalHandle fence;
  std::shared_ptr<BufferProducer> buffer_producer;
@@ -141,6 +141,86 @@ int DvrWriteBufferQueue::Dequeue(int timeout, DvrWriteBuffer* write_buffer,

  write_buffer->write_buffer = std::move(buffer_producer);
  *out_fence_fd = fence.Release();
  if (out_slot) {
    // TODO(b/65469368): Remove this null check once dvrWriteBufferQueueDequeue
    // is deprecated.
    *out_slot = slot;
  }
  return 0;
}

int DvrWriteBufferQueue::GainBuffer(int timeout,
                                    DvrWriteBuffer** out_write_buffer,
                                    DvrNativeBufferMetadata* out_meta,
                                    int* out_fence_fd) {
  DvrWriteBuffer write_buffer;
  int fence_fd;
  size_t slot;
  const int ret = Dequeue(timeout, &write_buffer, &fence_fd, &slot);
  if (ret < 0) {
    ALOGE_IF(
        ret != -ETIMEDOUT,
        "DvrWriteBufferQueue::GainBuffer: Failed to dequeue buffer, ret=%d",
        ret);
    return ret;
  }

  if (write_buffers_[slot] == nullptr) {
    // Lazy initialization of a write_buffers_ slot. Note that a slot will only
    // be dynamically allocated once during the entire cycle life of a queue.
    write_buffers_[slot] = std::make_unique<DvrWriteBuffer>();
    write_buffers_[slot]->slot = slot;
  }

  LOG_ALWAYS_FATAL_IF(
      write_buffers_[slot]->write_buffer,
      "DvrWriteBufferQueue::GainBuffer: Buffer slot is not empty: %zu", slot);
  write_buffers_[slot]->write_buffer = std::move(write_buffer.write_buffer);

  *out_write_buffer = write_buffers_[slot].release();
  *out_fence_fd = fence_fd;

  return 0;
}

int DvrWriteBufferQueue::PostBuffer(DvrWriteBuffer* write_buffer,
                                    const DvrNativeBufferMetadata* meta,
                                    int ready_fence_fd) {
  LOG_FATAL_IF(
      (write_buffers->slot < 0 || write_buffers->slot >= write_buffers_.size()),
      "DvrWriteBufferQueue::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>(write_buffer->slot);
  if (write_buffers_[slot] != nullptr) {
    ALOGE("DvrWriteBufferQueue::PostBuffer: Slot is not empty: %zu", slot);
    return -EINVAL;
  }
  if (write_buffer->write_buffer == nullptr) {
    ALOGE("DvrWriteBufferQueue::PostBuffer: Invalid write buffer.");
    return -EINVAL;
  }
  if (write_buffer->write_buffer->id() != producer_queue_->GetBufferId(slot)) {
    ALOGE(
        "DvrWriteBufferQueue::PostBuffer: Buffer to be released does not "
        "belong to this buffer queue.");
    return -EINVAL;
  }

  pdx::LocalHandle fence(ready_fence_fd);
  // TODO(b/65455724): All BufferHub operations should be async.
  const int ret = write_buffer->write_buffer->Post(fence, meta, sizeof(*meta));
  if (ret < 0) {
    ALOGE("DvrWriteBufferQueue::PostBuffer: Failed to post buffer, ret=%d",
          ret);
    return ret;
  }

  // Put the DvrWriteBuffer pointer back into its slot for reuse.
  write_buffers_[slot].reset(write_buffer);
  // It's import to reset the write buffer client now. It should stay invalid
  // until next GainBuffer on the same slot.
  write_buffers_[slot]->write_buffer = nullptr;
  return 0;
}

@@ -236,7 +316,29 @@ int dvrWriteBufferQueueDequeue(DvrWriteBufferQueue* write_queue, int timeout,
  if (!write_queue || !write_buffer || !out_fence_fd)
    return -EINVAL;

  return write_queue->Dequeue(timeout, write_buffer, out_fence_fd);
  // TODO(b/65469368): Deprecate this API once new GainBuffer API is in use.
  return write_queue->Dequeue(timeout, write_buffer, out_fence_fd, nullptr);
}

int dvrWriteBufferQueueGainBuffer(DvrWriteBufferQueue* write_queue, int timeout,
                                  DvrWriteBuffer** out_write_buffer,
                                  DvrNativeBufferMetadata* out_meta,
                                  int* out_fence_fd) {
  if (!write_queue || !out_write_buffer || !out_meta || !out_fence_fd)
    return -EINVAL;

  return write_queue->GainBuffer(timeout, out_write_buffer, out_meta,
                                 out_fence_fd);
}

int dvrWriteBufferQueuePostBuffer(DvrWriteBufferQueue* write_queue,
                                  DvrWriteBuffer* write_buffer,
                                  const DvrNativeBufferMetadata* meta,
                                  int ready_fence_fd) {
  if (!write_queue || !write_buffer || !write_buffer->write_buffer || !meta)
    return -EINVAL;

  return write_queue->PostBuffer(write_buffer, meta, ready_fence_fd);
}

int dvrWriteBufferQueueResizeBuffer(DvrWriteBufferQueue* write_queue,
@@ -268,8 +370,8 @@ int DvrReadBufferQueue::CreateReadQueue(DvrReadBufferQueue** out_read_queue) {
}

int DvrReadBufferQueue::Dequeue(int timeout, DvrReadBuffer* read_buffer,
                                int* out_fence_fd, void* out_meta,
                                size_t meta_size_bytes) {
                                int* out_fence_fd, size_t* out_slot,
                                void* out_meta, size_t meta_size_bytes) {
  if (meta_size_bytes != consumer_queue_->metadata_size()) {
    ALOGE(
        "DvrReadBufferQueue::Dequeue: Invalid metadata size, expected (%zu), "
@@ -291,6 +393,95 @@ int DvrReadBufferQueue::Dequeue(int timeout, DvrReadBuffer* read_buffer,

  read_buffer->read_buffer = buffer_status.take();
  *out_fence_fd = acquire_fence.Release();

  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;
  return 0;
}

@@ -311,9 +502,11 @@ void DvrReadBufferQueue::SetBufferRemovedCallback(
  } else {
    consumer_queue_->SetBufferRemovedCallback(
        [callback, context](const std::shared_ptr<BufferHubBuffer>& buffer) {
          DvrReadBuffer read_buffer{
              std::static_pointer_cast<BufferConsumer>(buffer)};
          callback(&read_buffer, context);
          // When buffer is removed from the queue, the slot is already invalid.
          auto read_buffer = std::make_unique<DvrReadBuffer>();
          read_buffer->read_buffer =
              std::static_pointer_cast<BufferConsumer>(buffer);
          callback(read_buffer.release(), context);
        });
  }
}
@@ -366,8 +559,30 @@ int dvrReadBufferQueueDequeue(DvrReadBufferQueue* read_queue, int timeout,
  if (meta_size_bytes != 0 && !out_meta)
    return -EINVAL;

  return read_queue->Dequeue(timeout, read_buffer, out_fence_fd, out_meta,
                             meta_size_bytes);
  // TODO(b/65469368): Deprecate this API once new AcquireBuffer API is in use.
  return read_queue->Dequeue(timeout, read_buffer, out_fence_fd, nullptr,
                             out_meta, meta_size_bytes);
}

int dvrReadBufferQueueAcquireBuffer(DvrReadBufferQueue* read_queue, int timeout,
                                    DvrReadBuffer** out_read_buffer,
                                    DvrNativeBufferMetadata* out_meta,
                                    int* out_fence_fd) {
  if (!read_queue || !out_read_buffer || !out_meta || !out_fence_fd)
    return -EINVAL;

  return read_queue->AcquireBuffer(timeout, out_read_buffer, out_meta,
                                   out_fence_fd);
}

int dvrReadBufferQueueReleaseBuffer(DvrReadBufferQueue* read_queue,
                                    DvrReadBuffer* read_buffer,
                                    const DvrNativeBufferMetadata* meta,
                                    int release_fence_fd) {
  if (!read_queue || !read_buffer || !read_buffer->read_buffer || !meta)
    return -EINVAL;

  return read_queue->ReleaseBuffer(read_buffer, meta, release_fence_fd);
}

int dvrReadBufferQueueSetBufferAvailableCallback(
+22 −2
Original line number Diff line number Diff line
@@ -5,10 +5,14 @@
#include <private/dvr/buffer_hub_queue_client.h>
#include <sys/cdefs.h>

#include <array>
#include <memory>

#include "dvr_internal.h"

struct ANativeWindow;

typedef struct DvrNativeBufferMetadata DvrNativeBufferMetadata;
typedef struct DvrReadBuffer DvrReadBuffer;
typedef struct DvrReadBufferQueue DvrReadBufferQueue;
typedef struct DvrWriteBuffer DvrWriteBuffer;
@@ -17,6 +21,7 @@ typedef void (*DvrReadBufferQueueBufferRemovedCallback)(DvrReadBuffer* buffer,
                                                        void* context);

struct DvrWriteBufferQueue {
  using BufferHubQueue = android::dvr::BufferHubQueue;
  using ProducerQueue = android::dvr::ProducerQueue;

  // Create a concrete object for DvrWriteBufferQueue.
@@ -37,19 +42,28 @@ struct DvrWriteBufferQueue {

  int GetNativeWindow(ANativeWindow** out_window);
  int CreateReadQueue(DvrReadBufferQueue** out_read_queue);
  int Dequeue(int timeout, DvrWriteBuffer* write_buffer, int* out_fence_fd);
  int Dequeue(int timeout, DvrWriteBuffer* write_buffer, int* out_fence_fd,
              size_t* out_slot);
  int GainBuffer(int timeout, DvrWriteBuffer** out_write_buffer,
                 DvrNativeBufferMetadata* out_meta, int* out_fence_fd);
  int PostBuffer(DvrWriteBuffer* write_buffer,
                 const DvrNativeBufferMetadata* meta, int ready_fence_fd);
  int ResizeBuffer(uint32_t width, uint32_t height);

 private:
  std::shared_ptr<ProducerQueue> producer_queue_;
  std::array<std::unique_ptr<DvrWriteBuffer>, BufferHubQueue::kMaxQueueCapacity>
      write_buffers_;

  uint32_t width_;
  uint32_t height_;
  uint32_t format_;

  android::sp<android::Surface> native_window_;
};

struct DvrReadBufferQueue {
  using BufferHubQueue = android::dvr::BufferHubQueue;
  using ConsumerQueue = android::dvr::ConsumerQueue;

  explicit DvrReadBufferQueue(
@@ -61,7 +75,11 @@ struct DvrReadBufferQueue {

  int CreateReadQueue(DvrReadBufferQueue** out_read_queue);
  int Dequeue(int timeout, DvrReadBuffer* read_buffer, int* out_fence_fd,
              void* out_meta, size_t meta_size_bytes);
              size_t* out_slot, void* out_meta, size_t meta_size_bytes);
  int AcquireBuffer(int timeout, DvrReadBuffer** out_read_buffer,
                    DvrNativeBufferMetadata* out_meta, int* out_fence_fd);
  int ReleaseBuffer(DvrReadBuffer* read_buffer,
                    const DvrNativeBufferMetadata* meta, int release_fence_fd);
  void SetBufferAvailableCallback(
      DvrReadBufferQueueBufferAvailableCallback callback, void* context);
  void SetBufferRemovedCallback(
@@ -70,6 +88,8 @@ struct DvrReadBufferQueue {

 private:
  std::shared_ptr<ConsumerQueue> consumer_queue_;
  std::array<std::unique_ptr<DvrReadBuffer>, BufferHubQueue::kMaxQueueCapacity>
      read_buffers_;
};

#endif  // ANDROID_DVR_BUFFER_QUEUE_INTERNAL_H_
+10 −0
Original line number Diff line number Diff line
@@ -34,10 +34,20 @@ DvrWriteBuffer* CreateDvrWriteBufferFromBufferProducer(
extern "C" {

struct DvrWriteBuffer {
  // The slot nubmer of the buffer, a valid slot number must be in the range of
  // [0, android::BufferQueueDefs::NUM_BUFFER_SLOTS). This is only valid for
  // DvrWriteBuffer acquired from a DvrWriteBufferQueue.
  int32_t slot = -1;

  std::shared_ptr<android::dvr::BufferProducer> write_buffer;
};

struct DvrReadBuffer {
  // The slot nubmer of the buffer, a valid slot number must be in the range of
  // [0, android::BufferQueueDefs::NUM_BUFFER_SLOTS). This is only valid for
  // DvrReadBuffer acquired from a DvrReadBufferQueue.
  int32_t slot = -1;

  std::shared_ptr<android::dvr::BufferConsumer> read_buffer;
};

Loading