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