stream: ast_stream_clone() cannot copy the opaque user data.
[asterisk/asterisk.git] / main / stream.c
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 2017, Digium, Inc.
5  *
6  * Joshua Colp <jcolp@digium.com>
7  *
8  * See http://www.asterisk.org for more information about
9  * the Asterisk project. Please do not directly contact
10  * any of the maintainers of this project for assistance;
11  * the project provides a web site, mailing lists and IRC
12  * channels for your use.
13  *
14  * This program is free software, distributed under the terms of
15  * the GNU General Public License Version 2. See the LICENSE file
16  * at the top of the source tree.
17  */
18
19 /*! \file
20  *
21  * \brief Media Stream API
22  *
23  * \author Joshua Colp <jcolp@digium.com>
24  */
25
26 /*** MODULEINFO
27         <support_level>core</support_level>
28  ***/
29
30 #include "asterisk.h"
31
32 #include "asterisk/logger.h"
33 #include "asterisk/stream.h"
34 #include "asterisk/strings.h"
35 #include "asterisk/format.h"
36 #include "asterisk/format_cap.h"
37
38 struct ast_stream {
39         /*!
40          * \brief The type of media the stream is handling
41          */
42         enum ast_media_type type;
43
44         /*!
45          * \brief The position of the stream in the topology
46          */
47         unsigned int position;
48
49         /*!
50          * \brief Current formats negotiated on the stream
51          */
52         struct ast_format_cap *formats;
53
54         /*!
55          * \brief The current state of the stream
56          */
57         enum ast_stream_state state;
58
59         /*!
60          * \brief Opaque stream data
61          */
62         void *data[AST_STREAM_DATA_SLOT_MAX];
63
64         /*!
65          * \brief What to do with data when the stream is freed
66          */
67         ast_stream_data_free_fn data_free_fn[AST_STREAM_DATA_SLOT_MAX];
68
69         /*!
70          * \brief Name for the stream within the context of the channel it is on
71          */
72         char name[0];
73 };
74
75 struct ast_stream_topology {
76         /*!
77          * \brief A vector of all the streams in this topology
78          */
79         AST_VECTOR(, struct ast_stream *) streams;
80 };
81
82 struct ast_stream *ast_stream_alloc(const char *name, enum ast_media_type type)
83 {
84         struct ast_stream *stream;
85
86         stream = ast_calloc(1, sizeof(*stream) + strlen(S_OR(name, "")) + 1);
87         if (!stream) {
88                 return NULL;
89         }
90
91         stream->type = type;
92         stream->state = AST_STREAM_STATE_INACTIVE;
93         strcpy(stream->name, S_OR(name, "")); /* Safe */
94
95         return stream;
96 }
97
98 struct ast_stream *ast_stream_clone(const struct ast_stream *stream)
99 {
100         struct ast_stream *new_stream;
101         size_t stream_size;
102         int idx;
103
104         if (!stream) {
105                 return NULL;
106         }
107
108         stream_size = sizeof(*stream) + strlen(stream->name) + 1;
109         new_stream = ast_calloc(1, stream_size);
110         if (!new_stream) {
111                 return NULL;
112         }
113
114         memcpy(new_stream, stream, stream_size);
115         if (new_stream->formats) {
116                 ao2_ref(new_stream->formats, +1);
117         }
118
119         /* We cannot clone the opaque data because we don't know how. */
120         for (idx = 0; idx < AST_STREAM_DATA_SLOT_MAX; ++idx) {
121                 new_stream->data[idx] = NULL;
122                 new_stream->data_free_fn[idx] = NULL;
123         }
124
125         return new_stream;
126 }
127
128 void ast_stream_free(struct ast_stream *stream)
129 {
130         int i;
131
132         if (!stream) {
133                 return;
134         }
135
136         for (i = 0; i < AST_STREAM_DATA_SLOT_MAX; i++) {
137                 if (stream->data_free_fn[i]) {
138                         stream->data_free_fn[i](stream->data[i]);
139                 }
140         }
141
142         ao2_cleanup(stream->formats);
143         ast_free(stream);
144 }
145
146 const char *ast_stream_get_name(const struct ast_stream *stream)
147 {
148         ast_assert(stream != NULL);
149
150         return stream->name;
151 }
152
153 enum ast_media_type ast_stream_get_type(const struct ast_stream *stream)
154 {
155         ast_assert(stream != NULL);
156
157         return stream->type;
158 }
159
160 void ast_stream_set_type(struct ast_stream *stream, enum ast_media_type type)
161 {
162         ast_assert(stream != NULL);
163
164         stream->type = type;
165 }
166
167 struct ast_format_cap *ast_stream_get_formats(const struct ast_stream *stream)
168 {
169         ast_assert(stream != NULL);
170
171         return stream->formats;
172 }
173
174 void ast_stream_set_formats(struct ast_stream *stream, struct ast_format_cap *caps)
175 {
176         ast_assert(stream != NULL);
177
178         ao2_cleanup(stream->formats);
179         stream->formats = ao2_bump(caps);
180 }
181
182 enum ast_stream_state ast_stream_get_state(const struct ast_stream *stream)
183 {
184         ast_assert(stream != NULL);
185
186         return stream->state;
187 }
188
189 void ast_stream_set_state(struct ast_stream *stream, enum ast_stream_state state)
190 {
191         ast_assert(stream != NULL);
192
193         stream->state = state;
194 }
195
196 const char *ast_stream_state2str(enum ast_stream_state state)
197 {
198         switch (state) {
199         case AST_STREAM_STATE_REMOVED:
200                 return "removed";
201         case AST_STREAM_STATE_SENDRECV:
202                 return "sendrecv";
203         case AST_STREAM_STATE_SENDONLY:
204                 return "sendonly";
205         case AST_STREAM_STATE_RECVONLY:
206                 return "recvonly";
207         case AST_STREAM_STATE_INACTIVE:
208                 return "inactive";
209         default:
210                 return "<unknown>";
211         }
212 }
213
214 void *ast_stream_get_data(struct ast_stream *stream, enum ast_stream_data_slot slot)
215 {
216         ast_assert(stream != NULL);
217
218         return stream->data[slot];
219 }
220
221 void *ast_stream_set_data(struct ast_stream *stream, enum ast_stream_data_slot slot,
222         void *data, ast_stream_data_free_fn data_free_fn)
223 {
224         ast_assert(stream != NULL);
225
226         stream->data[slot] = data;
227         stream->data_free_fn[slot] = data_free_fn;
228
229         return data;
230 }
231
232 int ast_stream_get_position(const struct ast_stream *stream)
233 {
234         ast_assert(stream != NULL);
235
236         return stream->position;
237 }
238
239 #define TOPOLOGY_INITIAL_STREAM_COUNT 2
240 struct ast_stream_topology *ast_stream_topology_alloc(void)
241 {
242         struct ast_stream_topology *topology;
243
244         topology = ast_calloc(1, sizeof(*topology));
245         if (!topology) {
246                 return NULL;
247         }
248
249         if (AST_VECTOR_INIT(&topology->streams, TOPOLOGY_INITIAL_STREAM_COUNT)) {
250                 ast_free(topology);
251                 topology = NULL;
252         }
253
254         return topology;
255 }
256
257 struct ast_stream_topology *ast_stream_topology_clone(
258         const struct ast_stream_topology *topology)
259 {
260         struct ast_stream_topology *new_topology;
261         int i;
262
263         ast_assert(topology != NULL);
264
265         new_topology = ast_stream_topology_alloc();
266         if (!new_topology) {
267                 return NULL;
268         }
269
270         for (i = 0; i < AST_VECTOR_SIZE(&topology->streams); i++) {
271                 struct ast_stream *stream =
272                         ast_stream_clone(AST_VECTOR_GET(&topology->streams, i));
273
274                 if (!stream || AST_VECTOR_APPEND(&new_topology->streams, stream)) {
275                         ast_stream_free(stream);
276                         ast_stream_topology_free(new_topology);
277                         return NULL;
278                 }
279         }
280
281         return new_topology;
282 }
283
284 void ast_stream_topology_free(struct ast_stream_topology *topology)
285 {
286         if (!topology) {
287                 return;
288         }
289
290         AST_VECTOR_CALLBACK_VOID(&topology->streams, ast_stream_free);
291         AST_VECTOR_FREE(&topology->streams);
292         ast_free(topology);
293 }
294
295 int ast_stream_topology_append_stream(struct ast_stream_topology *topology, struct ast_stream *stream)
296 {
297         ast_assert(topology && stream);
298
299         if (AST_VECTOR_APPEND(&topology->streams, stream)) {
300                 return -1;
301         }
302
303         stream->position = AST_VECTOR_SIZE(&topology->streams) - 1;
304
305         return AST_VECTOR_SIZE(&topology->streams) - 1;
306 }
307
308 int ast_stream_topology_get_count(const struct ast_stream_topology *topology)
309 {
310         ast_assert(topology != NULL);
311
312         return AST_VECTOR_SIZE(&topology->streams);
313 }
314
315 struct ast_stream *ast_stream_topology_get_stream(
316         const struct ast_stream_topology *topology, unsigned int stream_num)
317 {
318         ast_assert(topology != NULL);
319
320         return AST_VECTOR_GET(&topology->streams, stream_num);
321 }
322
323 int ast_stream_topology_set_stream(struct ast_stream_topology *topology,
324         unsigned int position, struct ast_stream *stream)
325 {
326         struct ast_stream *existing_stream;
327
328         ast_assert(topology && stream);
329
330         if (position > AST_VECTOR_SIZE(&topology->streams)) {
331                 return -1;
332         }
333
334         if (position < AST_VECTOR_SIZE(&topology->streams)) {
335                 existing_stream = AST_VECTOR_GET(&topology->streams, position);
336                 ast_stream_free(existing_stream);
337         }
338
339         stream->position = position;
340
341         if (position == AST_VECTOR_SIZE(&topology->streams)) {
342                 AST_VECTOR_APPEND(&topology->streams, stream);
343                 return 0;
344         }
345
346         return AST_VECTOR_REPLACE(&topology->streams, position, stream);
347 }
348
349 struct ast_stream_topology *ast_stream_topology_create_from_format_cap(
350         struct ast_format_cap *cap)
351 {
352         struct ast_stream_topology *topology;
353         enum ast_media_type type;
354
355         topology = ast_stream_topology_alloc();
356         if (!topology || !cap || !ast_format_cap_count(cap)) {
357                 return topology;
358         }
359
360         for (type = AST_MEDIA_TYPE_UNKNOWN + 1; type < AST_MEDIA_TYPE_END; type++) {
361                 struct ast_format_cap *new_cap;
362                 struct ast_stream *stream;
363
364                 if (!ast_format_cap_has_type(cap, type)) {
365                         continue;
366                 }
367
368                 new_cap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
369                 if (!new_cap) {
370                         ast_stream_topology_free(topology);
371                         return NULL;
372                 }
373
374                 ast_format_cap_set_framing(new_cap, ast_format_cap_get_framing(cap));
375                 if (ast_format_cap_append_from_cap(new_cap, cap, type)) {
376                         ao2_cleanup(new_cap);
377                         ast_stream_topology_free(topology);
378                         return NULL;
379                 }
380
381                 stream = ast_stream_alloc(ast_codec_media_type2str(type), type);
382                 if (!stream) {
383                         ao2_cleanup(new_cap);
384                         ast_stream_topology_free(topology);
385                         return NULL;
386                 }
387                 /* We're transferring the initial ref so no bump needed */
388                 stream->formats = new_cap;
389                 stream->state = AST_STREAM_STATE_SENDRECV;
390                 if (ast_stream_topology_append_stream(topology, stream) == -1) {
391                         ast_stream_free(stream);
392                         ast_stream_topology_free(topology);
393                         return NULL;
394                 }
395         }
396
397         return topology;
398 }
399
400 struct ast_format_cap *ast_format_cap_from_stream_topology(
401     struct ast_stream_topology *topology)
402 {
403         struct ast_format_cap *caps;
404         int i;
405
406         ast_assert(topology != NULL);
407
408         caps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
409         if (!caps) {
410                 return NULL;
411         }
412
413         for (i = 0; i < AST_VECTOR_SIZE(&topology->streams); i++) {
414                 struct ast_stream *stream = AST_VECTOR_GET(&topology->streams, i);
415
416                 if (!stream->formats) {
417                         continue;
418                 }
419
420                 ast_format_cap_append_from_cap(caps, stream->formats, AST_MEDIA_TYPE_UNKNOWN);
421         }
422
423         return caps;
424 }
425
426 struct ast_stream *ast_stream_topology_get_first_stream_by_type(
427         const struct ast_stream_topology *topology,
428         enum ast_media_type type)
429 {
430         int i;
431
432         ast_assert(topology != NULL);
433
434         for (i = 0; i < AST_VECTOR_SIZE(&topology->streams); i++) {
435                 struct ast_stream *stream = AST_VECTOR_GET(&topology->streams, i);
436
437                 if (stream->type == type) {
438                         return stream;
439                 }
440         }
441
442         return NULL;
443 }
444
445 void ast_stream_topology_map(const struct ast_stream_topology *topology,
446         struct ast_vector_int *types, struct ast_vector_int *v0, struct ast_vector_int *v1)
447 {
448         int i;
449         int nths[AST_MEDIA_TYPE_END] = {0};
450         int size = ast_stream_topology_get_count(topology);
451
452         /*
453          * Clear out any old mappings and initialize the new ones
454          */
455         AST_VECTOR_FREE(v0);
456         AST_VECTOR_FREE(v1);
457
458         /*
459          * Both vectors are sized to the topology. The media types vector is always
460          * guaranteed to be the size of the given topology or greater.
461          */
462         AST_VECTOR_INIT(v0, size);
463         AST_VECTOR_INIT(v1, size);
464
465         for (i = 0; i < size; ++i) {
466                 struct ast_stream *stream = ast_stream_topology_get_stream(topology, i);
467                 enum ast_media_type type = ast_stream_get_type(stream);
468                 int index = AST_VECTOR_GET_INDEX_NTH(types, ++nths[type],
469                         type, AST_VECTOR_ELEM_DEFAULT_CMP);
470
471                 if (index == -1) {
472                         /*
473                          * If a given type is not found for an index level then update the
474                          * media types vector with that type. This keeps the media types
475                          * vector always at the max topology size.
476                          */
477                         AST_VECTOR_APPEND(types, type);
478                         index = AST_VECTOR_SIZE(types) - 1;
479                 }
480
481                 /*
482                  * The mapping is reflexive in the sense that if it maps in one direction
483                  * then the reverse direction maps back to the other's index.
484                  */
485                 AST_VECTOR_REPLACE(v0, i, index);
486                 AST_VECTOR_REPLACE(v1, index, i);
487         }
488 }