Home | History | Annotate | Download | only in libdvr
      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/Surface.h>
      6 #include <private/dvr/buffer_hub_queue_client.h>
      7 #include <private/dvr/buffer_hub_queue_producer.h>
      8 
      9 #include "dvr_internal.h"
     10 
     11 #define CHECK_PARAM(param)                                               \
     12   LOG_ALWAYS_FATAL_IF(param == nullptr, "%s: " #param "cannot be NULL.", \
     13                       __FUNCTION__)
     14 
     15 using namespace android;
     16 
     17 namespace android {
     18 namespace dvr {
     19 
     20 DvrWriteBufferQueue* CreateDvrWriteBufferQueueFromProducerQueue(
     21     const std::shared_ptr<dvr::ProducerQueue>& producer_queue) {
     22   return new DvrWriteBufferQueue{std::move(producer_queue)};
     23 }
     24 
     25 DvrReadBufferQueue* CreateDvrReadBufferQueueFromConsumerQueue(
     26     const std::shared_ptr<dvr::ConsumerQueue>& consumer_queue) {
     27   return new DvrReadBufferQueue{std::move(consumer_queue)};
     28 }
     29 
     30 dvr::ProducerQueue* GetProducerQueueFromDvrWriteBufferQueue(
     31     DvrWriteBufferQueue* write_queue) {
     32   return write_queue->producer_queue.get();
     33 }
     34 
     35 }  // namespace dvr
     36 }  // namespace android
     37 
     38 extern "C" {
     39 
     40 void dvrWriteBufferQueueDestroy(DvrWriteBufferQueue* write_queue) {
     41   if (write_queue != nullptr && write_queue->native_window != nullptr)
     42     ANativeWindow_release(write_queue->native_window);
     43 
     44   delete write_queue;
     45 }
     46 
     47 ssize_t dvrWriteBufferQueueGetCapacity(DvrWriteBufferQueue* write_queue) {
     48   if (!write_queue || !write_queue->producer_queue)
     49     return -EINVAL;
     50 
     51   return write_queue->producer_queue->capacity();
     52 }
     53 
     54 int dvrWriteBufferQueueGetId(DvrWriteBufferQueue* write_queue) {
     55   if (!write_queue)
     56     return -EINVAL;
     57 
     58   return write_queue->producer_queue->id();
     59 }
     60 
     61 int dvrWriteBufferQueueGetExternalSurface(DvrWriteBufferQueue* write_queue,
     62                                           ANativeWindow** out_window) {
     63   if (!write_queue || !out_window)
     64     return -EINVAL;
     65 
     66   if (write_queue->producer_queue->metadata_size() !=
     67       sizeof(DvrNativeBufferMetadata)) {
     68     ALOGE(
     69         "The size of buffer metadata (%zu) of the write queue does not match "
     70         "of size of DvrNativeBufferMetadata (%zu).",
     71         write_queue->producer_queue->metadata_size(),
     72         sizeof(DvrNativeBufferMetadata));
     73     return -EINVAL;
     74   }
     75 
     76   // Lazy creation of |native_window|.
     77   if (write_queue->native_window == nullptr) {
     78     sp<IGraphicBufferProducer> gbp =
     79         dvr::BufferHubQueueProducer::Create(write_queue->producer_queue);
     80     sp<Surface> surface = new Surface(gbp, true);
     81     write_queue->native_window = static_cast<ANativeWindow*>(surface.get());
     82     ANativeWindow_acquire(write_queue->native_window);
     83   }
     84 
     85   *out_window = write_queue->native_window;
     86   return 0;
     87 }
     88 
     89 int dvrWriteBufferQueueCreateReadQueue(DvrWriteBufferQueue* write_queue,
     90                                        DvrReadBufferQueue** out_read_queue) {
     91   if (!write_queue || !write_queue->producer_queue || !out_read_queue)
     92     return -EINVAL;
     93 
     94   auto read_queue = std::make_unique<DvrReadBufferQueue>();
     95   read_queue->consumer_queue =
     96       write_queue->producer_queue->CreateConsumerQueue();
     97   if (read_queue->consumer_queue == nullptr) {
     98     ALOGE(
     99         "dvrWriteBufferQueueCreateReadQueue: Failed to create consumer queue "
    100         "from DvrWriteBufferQueue[%p].",
    101         write_queue);
    102     return -ENOMEM;
    103   }
    104 
    105   *out_read_queue = read_queue.release();
    106   return 0;
    107 }
    108 
    109 int dvrWriteBufferQueueDequeue(DvrWriteBufferQueue* write_queue, int timeout,
    110                                DvrWriteBuffer* write_buffer,
    111                                int* out_fence_fd) {
    112   if (!write_queue || !write_queue->producer_queue || !write_buffer ||
    113       !out_fence_fd) {
    114     return -EINVAL;
    115   }
    116 
    117   size_t slot;
    118   pdx::LocalHandle release_fence;
    119   auto buffer_status =
    120       write_queue->producer_queue->Dequeue(timeout, &slot, &release_fence);
    121   if (!buffer_status) {
    122     ALOGE_IF(buffer_status.error() != ETIMEDOUT,
    123              "dvrWriteBufferQueueDequeue: Failed to dequeue buffer: %s",
    124              buffer_status.GetErrorMessage().c_str());
    125     return -buffer_status.error();
    126   }
    127 
    128   write_buffer->write_buffer = buffer_status.take();
    129   *out_fence_fd = release_fence.Release();
    130   return 0;
    131 }
    132 
    133 // ReadBufferQueue
    134 void dvrReadBufferQueueDestroy(DvrReadBufferQueue* read_queue) {
    135   delete read_queue;
    136 }
    137 
    138 ssize_t dvrReadBufferQueueGetCapacity(DvrReadBufferQueue* read_queue) {
    139   if (!read_queue)
    140     return -EINVAL;
    141 
    142   return read_queue->consumer_queue->capacity();
    143 }
    144 
    145 int dvrReadBufferQueueGetId(DvrReadBufferQueue* read_queue) {
    146   if (!read_queue)
    147     return -EINVAL;
    148 
    149   return read_queue->consumer_queue->id();
    150 }
    151 
    152 int dvrReadBufferQueueCreateReadQueue(DvrReadBufferQueue* read_queue,
    153                                       DvrReadBufferQueue** out_read_queue) {
    154   if (!read_queue || !read_queue->consumer_queue || !out_read_queue)
    155     return -EINVAL;
    156 
    157   auto new_read_queue = std::make_unique<DvrReadBufferQueue>();
    158   new_read_queue->consumer_queue =
    159       read_queue->consumer_queue->CreateConsumerQueue();
    160   if (new_read_queue->consumer_queue == nullptr) {
    161     ALOGE(
    162         "dvrReadBufferQueueCreateReadQueue: Failed to create consumer queue "
    163         "from DvrReadBufferQueue[%p].",
    164         read_queue);
    165     return -ENOMEM;
    166   }
    167 
    168   *out_read_queue = new_read_queue.release();
    169   return 0;
    170 }
    171 
    172 int dvrReadBufferQueueDequeue(DvrReadBufferQueue* read_queue, int timeout,
    173                               DvrReadBuffer* read_buffer, int* out_fence_fd,
    174                               void* out_meta, size_t meta_size_bytes) {
    175   if (!read_queue || !read_queue->consumer_queue || !read_buffer ||
    176       !out_fence_fd || !out_meta) {
    177     return -EINVAL;
    178   }
    179 
    180   if (meta_size_bytes != read_queue->consumer_queue->metadata_size()) {
    181     ALOGE(
    182         "dvrReadBufferQueueDequeue: Invalid metadata size, expected (%zu), "
    183         "but actual (%zu).",
    184         read_queue->consumer_queue->metadata_size(), meta_size_bytes);
    185     return -EINVAL;
    186   }
    187 
    188   size_t slot;
    189   pdx::LocalHandle acquire_fence;
    190   auto buffer_status = read_queue->consumer_queue->Dequeue(
    191       timeout, &slot, out_meta, meta_size_bytes, &acquire_fence);
    192   if (!buffer_status) {
    193     ALOGE_IF(buffer_status.error() != ETIMEDOUT,
    194              "dvrReadBufferQueueDequeue: Failed to dequeue buffer: %s",
    195              buffer_status.GetErrorMessage().c_str());
    196     return -buffer_status.error();
    197   }
    198 
    199   read_buffer->read_buffer = buffer_status.take();
    200   *out_fence_fd = acquire_fence.Release();
    201   return 0;
    202 }
    203 
    204 }  // extern "C"
    205