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 
CreateDvrWriteBufferQueueFromProducerQueue(const std::shared_ptr<dvr::ProducerQueue> & producer_queue)20 DvrWriteBufferQueue* CreateDvrWriteBufferQueueFromProducerQueue(
21     const std::shared_ptr<dvr::ProducerQueue>& producer_queue) {
22   return new DvrWriteBufferQueue{std::move(producer_queue)};
23 }
24 
CreateDvrReadBufferQueueFromConsumerQueue(const std::shared_ptr<dvr::ConsumerQueue> & consumer_queue)25 DvrReadBufferQueue* CreateDvrReadBufferQueueFromConsumerQueue(
26     const std::shared_ptr<dvr::ConsumerQueue>& consumer_queue) {
27   return new DvrReadBufferQueue{std::move(consumer_queue)};
28 }
29 
GetProducerQueueFromDvrWriteBufferQueue(DvrWriteBufferQueue * write_queue)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 
dvrWriteBufferQueueDestroy(DvrWriteBufferQueue * write_queue)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 
dvrWriteBufferQueueGetCapacity(DvrWriteBufferQueue * write_queue)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 
dvrWriteBufferQueueGetId(DvrWriteBufferQueue * write_queue)54 int dvrWriteBufferQueueGetId(DvrWriteBufferQueue* write_queue) {
55   if (!write_queue)
56     return -EINVAL;
57 
58   return write_queue->producer_queue->id();
59 }
60 
dvrWriteBufferQueueGetExternalSurface(DvrWriteBufferQueue * write_queue,ANativeWindow ** out_window)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 
dvrWriteBufferQueueCreateReadQueue(DvrWriteBufferQueue * write_queue,DvrReadBufferQueue ** out_read_queue)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 
dvrWriteBufferQueueDequeue(DvrWriteBufferQueue * write_queue,int timeout,DvrWriteBuffer * write_buffer,int * out_fence_fd)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
dvrReadBufferQueueDestroy(DvrReadBufferQueue * read_queue)134 void dvrReadBufferQueueDestroy(DvrReadBufferQueue* read_queue) {
135   delete read_queue;
136 }
137 
dvrReadBufferQueueGetCapacity(DvrReadBufferQueue * read_queue)138 ssize_t dvrReadBufferQueueGetCapacity(DvrReadBufferQueue* read_queue) {
139   if (!read_queue)
140     return -EINVAL;
141 
142   return read_queue->consumer_queue->capacity();
143 }
144 
dvrReadBufferQueueGetId(DvrReadBufferQueue * read_queue)145 int dvrReadBufferQueueGetId(DvrReadBufferQueue* read_queue) {
146   if (!read_queue)
147     return -EINVAL;
148 
149   return read_queue->consumer_queue->id();
150 }
151 
dvrReadBufferQueueCreateReadQueue(DvrReadBufferQueue * read_queue,DvrReadBufferQueue ** out_read_queue)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 
dvrReadBufferQueueDequeue(DvrReadBufferQueue * read_queue,int timeout,DvrReadBuffer * read_buffer,int * out_fence_fd,void * out_meta,size_t meta_size_bytes)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