#include "include/dvr/dvr_api.h" #include "include/dvr/dvr_buffer_queue.h" #include <android/native_window.h> #include <gui/Surface.h> #include <private/dvr/buffer_hub_queue_client.h> #include <private/dvr/buffer_hub_queue_producer.h> #include "dvr_internal.h" #define CHECK_PARAM(param) \ LOG_ALWAYS_FATAL_IF(param == nullptr, "%s: " #param "cannot be NULL.", \ __FUNCTION__) using namespace android; namespace android { namespace dvr { DvrWriteBufferQueue* CreateDvrWriteBufferQueueFromProducerQueue( const std::shared_ptr<dvr::ProducerQueue>& producer_queue) { return new DvrWriteBufferQueue{std::move(producer_queue)}; } DvrReadBufferQueue* CreateDvrReadBufferQueueFromConsumerQueue( const std::shared_ptr<dvr::ConsumerQueue>& consumer_queue) { return new DvrReadBufferQueue{std::move(consumer_queue)}; } dvr::ProducerQueue* GetProducerQueueFromDvrWriteBufferQueue( DvrWriteBufferQueue* write_queue) { return write_queue->producer_queue.get(); } } // namespace dvr } // namespace android extern "C" { void dvrWriteBufferQueueDestroy(DvrWriteBufferQueue* write_queue) { if (write_queue != nullptr && write_queue->native_window != nullptr) ANativeWindow_release(write_queue->native_window); delete write_queue; } ssize_t dvrWriteBufferQueueGetCapacity(DvrWriteBufferQueue* write_queue) { if (!write_queue || !write_queue->producer_queue) return -EINVAL; return write_queue->producer_queue->capacity(); } int dvrWriteBufferQueueGetId(DvrWriteBufferQueue* write_queue) { if (!write_queue) return -EINVAL; return write_queue->producer_queue->id(); } int dvrWriteBufferQueueGetExternalSurface(DvrWriteBufferQueue* write_queue, ANativeWindow** out_window) { if (!write_queue || !out_window) return -EINVAL; if (write_queue->producer_queue->metadata_size() != sizeof(DvrNativeBufferMetadata)) { ALOGE( "The size of buffer metadata (%zu) of the write queue does not match " "of size of DvrNativeBufferMetadata (%zu).", write_queue->producer_queue->metadata_size(), sizeof(DvrNativeBufferMetadata)); return -EINVAL; } // Lazy creation of |native_window|. if (write_queue->native_window == nullptr) { sp<IGraphicBufferProducer> gbp = dvr::BufferHubQueueProducer::Create(write_queue->producer_queue); sp<Surface> surface = new Surface(gbp, true); write_queue->native_window = static_cast<ANativeWindow*>(surface.get()); ANativeWindow_acquire(write_queue->native_window); } *out_window = write_queue->native_window; return 0; } int dvrWriteBufferQueueCreateReadQueue(DvrWriteBufferQueue* write_queue, DvrReadBufferQueue** out_read_queue) { if (!write_queue || !write_queue->producer_queue || !out_read_queue) return -EINVAL; auto read_queue = std::make_unique<DvrReadBufferQueue>(); read_queue->consumer_queue = write_queue->producer_queue->CreateConsumerQueue(); if (read_queue->consumer_queue == nullptr) { ALOGE( "dvrWriteBufferQueueCreateReadQueue: Failed to create consumer queue " "from DvrWriteBufferQueue[%p].", write_queue); return -ENOMEM; } *out_read_queue = read_queue.release(); return 0; } int dvrWriteBufferQueueDequeue(DvrWriteBufferQueue* write_queue, int timeout, DvrWriteBuffer* write_buffer, int* out_fence_fd) { if (!write_queue || !write_queue->producer_queue || !write_buffer || !out_fence_fd) { return -EINVAL; } size_t slot; pdx::LocalHandle release_fence; auto buffer_status = write_queue->producer_queue->Dequeue(timeout, &slot, &release_fence); if (!buffer_status) { ALOGE_IF(buffer_status.error() != ETIMEDOUT, "dvrWriteBufferQueueDequeue: Failed to dequeue buffer: %s", buffer_status.GetErrorMessage().c_str()); return -buffer_status.error(); } write_buffer->write_buffer = buffer_status.take(); *out_fence_fd = release_fence.Release(); return 0; } // ReadBufferQueue void dvrReadBufferQueueDestroy(DvrReadBufferQueue* read_queue) { delete read_queue; } ssize_t dvrReadBufferQueueGetCapacity(DvrReadBufferQueue* read_queue) { if (!read_queue) return -EINVAL; return read_queue->consumer_queue->capacity(); } int dvrReadBufferQueueGetId(DvrReadBufferQueue* read_queue) { if (!read_queue) return -EINVAL; return read_queue->consumer_queue->id(); } int dvrReadBufferQueueCreateReadQueue(DvrReadBufferQueue* read_queue, DvrReadBufferQueue** out_read_queue) { if (!read_queue || !read_queue->consumer_queue || !out_read_queue) return -EINVAL; auto new_read_queue = std::make_unique<DvrReadBufferQueue>(); new_read_queue->consumer_queue = read_queue->consumer_queue->CreateConsumerQueue(); if (new_read_queue->consumer_queue == nullptr) { ALOGE( "dvrReadBufferQueueCreateReadQueue: Failed to create consumer queue " "from DvrReadBufferQueue[%p].", read_queue); return -ENOMEM; } *out_read_queue = new_read_queue.release(); return 0; } int dvrReadBufferQueueDequeue(DvrReadBufferQueue* read_queue, int timeout, DvrReadBuffer* read_buffer, int* out_fence_fd, void* out_meta, size_t meta_size_bytes) { if (!read_queue || !read_queue->consumer_queue || !read_buffer || !out_fence_fd || !out_meta) { return -EINVAL; } if (meta_size_bytes != read_queue->consumer_queue->metadata_size()) { ALOGE( "dvrReadBufferQueueDequeue: Invalid metadata size, expected (%zu), " "but actual (%zu).", read_queue->consumer_queue->metadata_size(), meta_size_bytes); return -EINVAL; } size_t slot; pdx::LocalHandle acquire_fence; auto buffer_status = read_queue->consumer_queue->Dequeue( timeout, &slot, out_meta, meta_size_bytes, &acquire_fence); if (!buffer_status) { ALOGE_IF(buffer_status.error() != ETIMEDOUT, "dvrReadBufferQueueDequeue: Failed to dequeue buffer: %s", buffer_status.GetErrorMessage().c_str()); return -buffer_status.error(); } read_buffer->read_buffer = buffer_status.take(); *out_fence_fd = acquire_fence.Release(); return 0; } } // extern "C"