PipeWire: spa/buffer/alloc.h Source File

PipeWire 0.3.59

alloc.h
Go to the documentation of this file.
1/* Simple Plugin API
2 * Copyright © 2018 Wim Taymans
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
13 * Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21 * DEALINGS IN THE SOFTWARE.
22 */
23#ifndef SPA_BUFFER_ALLOC_H
24#define SPA_BUFFER_ALLOC_H
25
26#ifdef __cplusplus
27extern "C" {
28#endif
29
30#include <spa/buffer/buffer.h>
31
38struct spa_buffer_alloc_info {
39#define SPA_BUFFER_ALLOC_FLAG_INLINE_META (1<<0)
40#define SPA_BUFFER_ALLOC_FLAG_INLINE_CHUNK (1<<1)
41#define SPA_BUFFER_ALLOC_FLAG_INLINE_DATA (1<<2)
42#define SPA_BUFFER_ALLOC_FLAG_INLINE_ALL 0b111
43#define SPA_BUFFER_ALLOC_FLAG_NO_DATA (1<<3)
44 uint32_t flags;
45 uint32_t max_align;
46 uint32_t n_metas;
47 uint32_t n_datas;
48 struct spa_meta *metas;
49 struct spa_data *datas;
50 uint32_t *data_aligns;
51 size_t skel_size;
52 size_t meta_size;
53 size_t chunk_size;
54 size_t data_size;
55 size_t mem_size;
56};
57
79static inline int spa_buffer_alloc_fill_info(struct spa_buffer_alloc_info *info,
80 uint32_t n_metas, struct spa_meta metas[],
81 uint32_t n_datas, struct spa_data datas[],
82 uint32_t data_aligns[])
83{
84 size_t size, *target;
85 uint32_t i;
86
87 info->n_metas = n_metas;
88 info->metas = metas;
89 info->n_datas = n_datas;
90 info->datas = datas;
91 info->data_aligns = data_aligns;
92 info->max_align = 16;
93 info->mem_size = 0;
94 /*
95 * The buffer skeleton is placed in memory like below and can
96 * be accessed as a regular structure.
97 *
98 * +==============================+
99 * | struct spa_buffer |
100 * | uint32_t n_metas | number of metas
101 * | uint32_t n_datas | number of datas
102 * +-| struct spa_meta *metas | pointer to array of metas
103 * +|-| struct spa_data *datas | pointer to array of datas
104 * || +------------------------------+
105 * |+>| struct spa_meta |
106 * | | uint32_t type | metadata
107 * | | uint32_t size | size of metadata
108 * +|--| void *data | pointer to metadata
109 * || | ... <n_metas> | more spa_meta follow
110 * || +------------------------------+
111 * |+->| struct spa_data |
112 * | | uint32_t type | memory type
113 * | | uint32_t flags |
114 * | | int fd | fd of shared memory block
115 * | | uint32_t mapoffset | offset in shared memory of data
116 * | | uint32_t maxsize | size of data block
117 * | +-| void *data | pointer to data
118 * |+|-| struct spa_chunk *chunk | pointer to chunk
119 * ||| | ... <n_datas> | more spa_data follow
120 * ||| +==============================+
121 * VVV
122 *
123 * metadata, chunk and memory can either be placed right
124 * after the skeleton (inlined) or in a separate piece of memory.
125 *
126 * vvv
127 * ||| +==============================+
128 * +-->| meta data memory | metadata memory, 8 byte aligned
129 * || | ... <n_metas> |
130 * || +------------------------------+
131 * +->| struct spa_chunk | memory for n_datas chunks
132 * | | uint32_t offset |
133 * | | uint32_t size |
134 * | | int32_t stride |
135 * | | int32_t dummy |
136 * | | ... <n_datas> chunks |
137 * | +------------------------------+
138 * +>| data | memory for n_datas data, aligned
139 * | ... <n_datas> blocks | according to alignments
140 * +==============================+
141 */
142 info->skel_size = sizeof(struct spa_buffer);
143 info->skel_size += n_metas * sizeof(struct spa_meta);
144 info->skel_size += n_datas * sizeof(struct spa_data);
145
146 for (i = 0, size = 0; i < n_metas; i++)
147 size += SPA_ROUND_UP_N(metas[i].size, 8);
148 info->meta_size = size;
149
150 if (SPA_FLAG_IS_SET(info->flags, SPA_BUFFER_ALLOC_FLAG_INLINE_META))
151 target = &info->skel_size;
152 else
153 target = &info->mem_size;
154 *target += info->meta_size;
155
156 info->chunk_size = n_datas * sizeof(struct spa_chunk);
157 if (SPA_FLAG_IS_SET(info->flags, SPA_BUFFER_ALLOC_FLAG_INLINE_CHUNK))
158 target = &info->skel_size;
159 else
160 target = &info->mem_size;
161 *target += info->chunk_size;
162
163 for (i = 0, size = 0; i < n_datas; i++) {
164 int64_t align = data_aligns[i];
165 info->max_align = SPA_MAX(info->max_align, data_aligns[i]);
166 size = SPA_ROUND_UP_N(size, align);
167 size += datas[i].maxsize;
168 }
169 info->data_size = size;
170
171 if (!SPA_FLAG_IS_SET(info->flags, SPA_BUFFER_ALLOC_FLAG_NO_DATA) &&
172 SPA_FLAG_IS_SET(info->flags, SPA_BUFFER_ALLOC_FLAG_INLINE_DATA))
173 target = &info->skel_size;
174 else
175 target = &info->mem_size;
176
177 *target = SPA_ROUND_UP_N(*target, n_datas ? data_aligns[0] : 1);
178 *target += info->data_size;
179 *target = SPA_ROUND_UP_N(*target, info->max_align);
180
181 return 0;
182}
183
200static inline struct spa_buffer *
201 spa_buffer_alloc_layout(struct spa_buffer_alloc_info *info,
202 void *skel_mem, void *data_mem)
203{
204 struct spa_buffer *b = (struct spa_buffer*)skel_mem;
205 size_t size;
206 uint32_t i;
207 void **dp, *skel, *data;
208 struct spa_chunk *cp;
209
210 b->n_metas = info->n_metas;
211 b->metas = SPA_PTROFF(b, sizeof(struct spa_buffer), struct spa_meta);
212 b->n_datas = info->n_datas;
213 b->datas = SPA_PTROFF(b->metas, info->n_metas * sizeof(struct spa_meta), struct spa_data);
214
215 skel = SPA_PTROFF(b->datas, info->n_datas * sizeof(struct spa_data), void);
216 data = data_mem;
217
218 if (SPA_FLAG_IS_SET(info->flags, SPA_BUFFER_ALLOC_FLAG_INLINE_META))
219 dp = &skel;
220 else
221 dp = &data;
222
223 for (i = 0; i < info->n_metas; i++) {
224 struct spa_meta *m = &b->metas[i];
225 *m = info->metas[i];
226 m->data = *dp;
227 *dp = SPA_PTROFF(*dp, SPA_ROUND_UP_N(m->size, 8), void);
228 }
229
230 size = info->n_datas * sizeof(struct spa_chunk);
231 if (SPA_FLAG_IS_SET(info->flags, SPA_BUFFER_ALLOC_FLAG_INLINE_CHUNK)) {
232 cp = (struct spa_chunk*)skel;
233 skel = SPA_PTROFF(skel, size, void);
234 }
235 else {
236 cp = (struct spa_chunk*)data;
237 data = SPA_PTROFF(data, size, void);
238 }
239
240 if (SPA_FLAG_IS_SET(info->flags, SPA_BUFFER_ALLOC_FLAG_INLINE_DATA))
241 dp = &skel;
242 else
243 dp = &data;
244
245 for (i = 0; i < info->n_datas; i++) {
246 struct spa_data *d = &b->datas[i];
247
248 *d = info->datas[i];
249 d->chunk = &cp[i];
250 if (!SPA_FLAG_IS_SET(info->flags, SPA_BUFFER_ALLOC_FLAG_NO_DATA)) {
251 *dp = SPA_PTR_ALIGN(*dp, info->data_aligns[i], void);
252 d->data = *dp;
253 *dp = SPA_PTROFF(*dp, d->maxsize, void);
254 }
255 }
256 return b;
257}
258
278static inline int
279 spa_buffer_alloc_layout_array(struct spa_buffer_alloc_info *info,
280 uint32_t n_buffers, struct spa_buffer *buffers[],
281 void *skel_mem, void *data_mem)
282{
283 uint32_t i;
284 for (i = 0; i < n_buffers; i++) {
285 buffers[i] = spa_buffer_alloc_layout(info, skel_mem, data_mem);
286 skel_mem = SPA_PTROFF(skel_mem, info->skel_size, void);
287 data_mem = SPA_PTROFF(data_mem, info->mem_size, void);
288 }
289 return 0;
290}
291
313static inline struct spa_buffer **
314 spa_buffer_alloc_array(uint32_t n_buffers, uint32_t flags,
315 uint32_t n_metas, struct spa_meta metas[],
316 uint32_t n_datas, struct spa_data datas[],
317 uint32_t data_aligns[])
318{
319
320 struct spa_buffer **buffers;
321 struct spa_buffer_alloc_info info = { flags | SPA_BUFFER_ALLOC_FLAG_INLINE_ALL, };
322 void *skel;
323
324 spa_buffer_alloc_fill_info(&info, n_metas, metas, n_datas, datas, data_aligns);
325
326 buffers = (struct spa_buffer **)calloc(1, info.max_align +
327 n_buffers * (sizeof(struct spa_buffer *) + info.skel_size));
328 if (buffers == NULL)
329 return NULL;
330
331 skel = SPA_PTROFF(buffers, sizeof(struct spa_buffer *) * n_buffers, void);
332 skel = SPA_PTR_ALIGN(skel, info.max_align, void);
333
334 spa_buffer_alloc_layout_array(&info, n_buffers, buffers, skel, NULL);
335
336 return buffers;
337}
338
343#ifdef __cplusplus
344} /* extern "C" */
345#endif
346
347#endif /* SPA_BUFFER_ALLOC_H */
buffer.h
spa/buffer/buffer.h
spa_buffer_alloc_array
static struct spa_buffer ** spa_buffer_alloc_array(uint32_t n_buffers, uint32_t flags, uint32_t n_metas, struct spa_meta metas[], uint32_t n_datas, struct spa_data datas[], uint32_t data_aligns[])
Allocate an array of buffers.
Definition: alloc.h:324
SPA_BUFFER_ALLOC_FLAG_INLINE_ALL
#define SPA_BUFFER_ALLOC_FLAG_INLINE_ALL
Definition: alloc.h:51
spa_buffer_alloc_layout
static struct spa_buffer * spa_buffer_alloc_layout(struct spa_buffer_alloc_info *info, void *skel_mem, void *data_mem)
Fill skeleton and data according to the allocation info.
Definition: alloc.h:211
SPA_BUFFER_ALLOC_FLAG_INLINE_META
#define SPA_BUFFER_ALLOC_FLAG_INLINE_META
add metadata data in the skeleton
Definition: alloc.h:45
spa_buffer_alloc_fill_info
static int spa_buffer_alloc_fill_info(struct spa_buffer_alloc_info *info, uint32_t n_metas, struct spa_meta metas[], uint32_t n_datas, struct spa_data datas[], uint32_t data_aligns[])
Fill buffer allocation information.
Definition: alloc.h:89
spa_buffer_alloc_layout_array
static int spa_buffer_alloc_layout_array(struct spa_buffer_alloc_info *info, uint32_t n_buffers, struct spa_buffer *buffers[], void *skel_mem, void *data_mem)
Layout an array of buffers.
Definition: alloc.h:289
SPA_BUFFER_ALLOC_FLAG_INLINE_CHUNK
#define SPA_BUFFER_ALLOC_FLAG_INLINE_CHUNK
add chunk data in the skeleton
Definition: alloc.h:47
SPA_BUFFER_ALLOC_FLAG_NO_DATA
#define SPA_BUFFER_ALLOC_FLAG_NO_DATA
don't set data pointers
Definition: alloc.h:53
SPA_BUFFER_ALLOC_FLAG_INLINE_DATA
#define SPA_BUFFER_ALLOC_FLAG_INLINE_DATA
add buffer data to the skeleton
Definition: alloc.h:49
SPA_ROUND_UP_N
#define SPA_ROUND_UP_N(num, align)
Definition: defs.h:333
SPA_PTR_ALIGN
#define SPA_PTR_ALIGN(p, align, type)
Definition: defs.h:340
SPA_FLAG_IS_SET
#define SPA_FLAG_IS_SET(field, flag)
Definition: defs.h:92
SPA_PTROFF
#define SPA_PTROFF(ptr_, offset_, type_)
Return the address (buffer + offset) as pointer of type.
Definition: defs.h:206
SPA_MAX
#define SPA_MAX(a, b)
Definition: defs.h:169
spa_buffer_alloc_info
information about the buffer layout
Definition: alloc.h:43
spa_buffer_alloc_info::mem_size
size_t mem_size
size of the total memory if not inlined
Definition: alloc.h:65
spa_buffer_alloc_info::data_size
size_t data_size
size of the data if not inlined
Definition: alloc.h:64
spa_buffer_alloc_info::n_metas
uint32_t n_metas
Definition: alloc.h:56
spa_buffer_alloc_info::max_align
uint32_t max_align
max of all alignments
Definition: alloc.h:55
spa_buffer_alloc_info::meta_size
size_t meta_size
size of the meta if not inlined
Definition: alloc.h:62
spa_buffer_alloc_info::chunk_size
size_t chunk_size
size of the chunk if not inlined
Definition: alloc.h:63
spa_buffer_alloc_info::skel_size
size_t skel_size
size of the struct spa_buffer and inlined meta/chunk/data
Definition: alloc.h:61
spa_buffer_alloc_info::datas
struct spa_data * datas
Definition: alloc.h:59
spa_buffer_alloc_info::data_aligns
uint32_t * data_aligns
Definition: alloc.h:60
spa_buffer_alloc_info::n_datas
uint32_t n_datas
Definition: alloc.h:57
spa_buffer_alloc_info::metas
struct spa_meta * metas
Definition: alloc.h:58
spa_buffer_alloc_info::flags
uint32_t flags
Definition: alloc.h:54
spa_buffer
A Buffer.
Definition: buffer.h:109
spa_buffer::n_metas
uint32_t n_metas
number of metadata
Definition: buffer.h:110
spa_buffer::metas
struct spa_meta * metas
array of metadata
Definition: buffer.h:112
spa_buffer::datas
struct spa_data * datas
array of data members
Definition: buffer.h:113
spa_buffer::n_datas
uint32_t n_datas
number of data members
Definition: buffer.h:111
spa_chunk
Chunk of memory, can change for each buffer.
Definition: buffer.h:62
spa_chunk::size
uint32_t size
size of valid data.
Definition: buffer.h:66
spa_data
Data for a buffer this stays constant for a buffer.
Definition: buffer.h:81
spa_data::chunk
struct spa_chunk * chunk
valid chunk of memory
Definition: buffer.h:105
spa_data::data
void * data
optional data pointer
Definition: buffer.h:104
spa_data::maxsize
uint32_t maxsize
max size of data
Definition: buffer.h:103
spa_meta
A metadata element.
Definition: meta.h:66
spa_meta::size
uint32_t size
size of metadata
Definition: meta.h:68
spa_meta::data
void * data
pointer to metadata
Definition: meta.h:69