PipeWire: spa/buffer/alloc.h Source File

PipeWire 0.3.51

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 info->max_align = SPA_MAX(info->max_align, data_aligns[i]);
165 size = SPA_ROUND_UP_N(size, data_aligns[i]);
166 size += datas[i].maxsize;
167 }
168 info->data_size = size;
169
170 if (!SPA_FLAG_IS_SET(info->flags, SPA_BUFFER_ALLOC_FLAG_NO_DATA) &&
171 SPA_FLAG_IS_SET(info->flags, SPA_BUFFER_ALLOC_FLAG_INLINE_DATA))
172 target = &info->skel_size;
173 else
174 target = &info->mem_size;
175
176 *target = SPA_ROUND_UP_N(*target, n_datas ? data_aligns[0] : 1);
177 *target += info->data_size;
178 *target = SPA_ROUND_UP_N(*target, info->max_align);
179
180 return 0;
181}
182
199static inline struct spa_buffer *
200 spa_buffer_alloc_layout(struct spa_buffer_alloc_info *info,
201 void *skel_mem, void *data_mem)
202{
203 struct spa_buffer *b = (struct spa_buffer*)skel_mem;
204 size_t size;
205 uint32_t i;
206 void **dp, *skel, *data;
207 struct spa_chunk *cp;
208
209 b->n_metas = info->n_metas;
210 b->metas = SPA_PTROFF(b, sizeof(struct spa_buffer), struct spa_meta);
211 b->n_datas = info->n_datas;
212 b->datas = SPA_PTROFF(b->metas, info->n_metas * sizeof(struct spa_meta), struct spa_data);
213
214 skel = SPA_PTROFF(b->datas, info->n_datas * sizeof(struct spa_data), void);
215 data = data_mem;
216
217 if (SPA_FLAG_IS_SET(info->flags, SPA_BUFFER_ALLOC_FLAG_INLINE_META))
218 dp = &skel;
219 else
220 dp = &data;
221
222 for (i = 0; i < info->n_metas; i++) {
223 struct spa_meta *m = &b->metas[i];
224 *m = info->metas[i];
225 m->data = *dp;
226 *dp = SPA_PTROFF(*dp, SPA_ROUND_UP_N(m->size, 8), void);
227 }
228
229 size = info->n_datas * sizeof(struct spa_chunk);
230 if (SPA_FLAG_IS_SET(info->flags, SPA_BUFFER_ALLOC_FLAG_INLINE_CHUNK)) {
231 cp = (struct spa_chunk*)skel;
232 skel = SPA_PTROFF(skel, size, void);
233 }
234 else {
235 cp = (struct spa_chunk*)data;
236 data = SPA_PTROFF(data, size, void);
237 }
238
239 if (SPA_FLAG_IS_SET(info->flags, SPA_BUFFER_ALLOC_FLAG_INLINE_DATA))
240 dp = &skel;
241 else
242 dp = &data;
243
244 for (i = 0; i < info->n_datas; i++) {
245 struct spa_data *d = &b->datas[i];
246
247 *d = info->datas[i];
248 d->chunk = &cp[i];
249 if (!SPA_FLAG_IS_SET(info->flags, SPA_BUFFER_ALLOC_FLAG_NO_DATA)) {
250 *dp = SPA_PTR_ALIGN(*dp, info->data_aligns[i], void);
251 d->data = *dp;
252 *dp = SPA_PTROFF(*dp, d->maxsize, void);
253 }
254 }
255 return b;
256}
257
277static inline int
278 spa_buffer_alloc_layout_array(struct spa_buffer_alloc_info *info,
279 uint32_t n_buffers, struct spa_buffer *buffers[],
280 void *skel_mem, void *data_mem)
281{
282 uint32_t i;
283 for (i = 0; i < n_buffers; i++) {
284 buffers[i] = spa_buffer_alloc_layout(info, skel_mem, data_mem);
285 skel_mem = SPA_PTROFF(skel_mem, info->skel_size, void);
286 data_mem = SPA_PTROFF(data_mem, info->mem_size, void);
287 }
288 return 0;
289}
290
312static inline struct spa_buffer **
313 spa_buffer_alloc_array(uint32_t n_buffers, uint32_t flags,
314 uint32_t n_metas, struct spa_meta metas[],
315 uint32_t n_datas, struct spa_data datas[],
316 uint32_t data_aligns[])
317{
318
319 struct spa_buffer **buffers;
320 struct spa_buffer_alloc_info info = { flags | SPA_BUFFER_ALLOC_FLAG_INLINE_ALL, };
321 void *skel;
322
323 spa_buffer_alloc_fill_info(&info, n_metas, metas, n_datas, datas, data_aligns);
324
325 buffers = (struct spa_buffer **)calloc(1, info.max_align +
326 n_buffers * (sizeof(struct spa_buffer *) + info.skel_size));
327 if (buffers == NULL)
328 return NULL;
329
330 skel = SPA_PTROFF(buffers, sizeof(struct spa_buffer *) * n_buffers, void);
331 skel = SPA_PTR_ALIGN(skel, info.max_align, void);
332
333 spa_buffer_alloc_layout_array(&info, n_buffers, buffers, skel, NULL);
334
335 return buffers;
336}
337
342#ifdef __cplusplus
343} /* extern "C" */
344#endif
345
346#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:323
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:210
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:288
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:296
SPA_PTR_ALIGN
#define SPA_PTR_ALIGN(p, align, type)
Definition: defs.h:303
SPA_FLAG_IS_SET
#define SPA_FLAG_IS_SET(field, flag)
Definition: defs.h:82
SPA_PTROFF
#define SPA_PTROFF(ptr_, offset_, type_)
Return the address (buffer + offset) as pointer of type.
Definition: defs.h:183
SPA_MAX
#define SPA_MAX(a, b)
Definition: defs.h:152
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:105
spa_buffer::n_metas
uint32_t n_metas
number of metadata
Definition: buffer.h:106
spa_buffer::metas
struct spa_meta * metas
array of metadata
Definition: buffer.h:108
spa_buffer::datas
struct spa_data * datas
array of data members
Definition: buffer.h:109
spa_buffer::n_datas
uint32_t n_datas
number of data members
Definition: buffer.h:107
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:77
spa_data::chunk
struct spa_chunk * chunk
valid chunk of memory
Definition: buffer.h:101
spa_data::data
void * data
optional data pointer
Definition: buffer.h:100
spa_data::maxsize
uint32_t maxsize
max size of data
Definition: buffer.h:99
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