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