Merge "lock: Improve performance of DEBUG_THREADS."
[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 #include "asterisk/vector.h"
38 #include "asterisk/config.h"
39 #include "asterisk/rtp_engine.h"
40
41 struct ast_stream_metadata_entry {
42         size_t length;
43         int value_start;
44         char name_value[0];
45 };
46
47 struct ast_stream {
48         /*!
49          * \brief The type of media the stream is handling
50          */
51         enum ast_media_type type;
52
53         /*!
54          * \brief The position of the stream in the topology
55          */
56         unsigned int position;
57
58         /*!
59          * \brief Current formats negotiated on the stream
60          */
61         struct ast_format_cap *formats;
62
63         /*!
64          * \brief The current state of the stream
65          */
66         enum ast_stream_state state;
67
68         /*!
69          * \brief Stream metadata vector
70          */
71         struct ast_variable *metadata;
72
73         /*!
74          * \brief The group that the stream is part of
75          */
76         int group;
77
78         /*!
79          * \brief The rtp_codecs used by the stream
80          */
81         struct ast_rtp_codecs *rtp_codecs;
82
83         /*!
84          * \brief Name for the stream within the context of the channel it is on
85          */
86         char name[0];
87 };
88
89 struct ast_stream_topology {
90         /*!
91          * \brief A vector of all the streams in this topology
92          */
93         AST_VECTOR(, struct ast_stream *) streams;
94 };
95
96 struct ast_stream *ast_stream_alloc(const char *name, enum ast_media_type type)
97 {
98         struct ast_stream *stream;
99
100         stream = ast_calloc(1, sizeof(*stream) + strlen(S_OR(name, "")) + 1);
101         if (!stream) {
102                 return NULL;
103         }
104
105         stream->type = type;
106         stream->state = AST_STREAM_STATE_INACTIVE;
107         stream->group = -1;
108         strcpy(stream->name, S_OR(name, "")); /* Safe */
109
110         return stream;
111 }
112
113 struct ast_stream *ast_stream_clone(const struct ast_stream *stream, const char *name)
114 {
115         struct ast_stream *new_stream;
116         size_t stream_size;
117         const char *stream_name;
118
119         if (!stream) {
120                 return NULL;
121         }
122
123         stream_name = name ?: stream->name;
124         stream_size = sizeof(*stream) + strlen(stream_name) + 1;
125         new_stream = ast_calloc(1, stream_size);
126         if (!new_stream) {
127                 return NULL;
128         }
129
130         memcpy(new_stream, stream, sizeof(*new_stream));
131         strcpy(new_stream->name, stream_name); /* Safe */
132         new_stream->group = -1;
133         if (new_stream->formats) {
134                 ao2_ref(new_stream->formats, +1);
135         }
136
137         new_stream->metadata = ast_stream_get_metadata_list(stream);
138
139         /* rtp_codecs aren't cloned */
140
141         return new_stream;
142 }
143
144 void ast_stream_free(struct ast_stream *stream)
145 {
146         if (!stream) {
147                 return;
148         }
149
150         ast_variables_destroy(stream->metadata);
151
152         if (stream->rtp_codecs) {
153                 ast_rtp_codecs_payloads_destroy(stream->rtp_codecs);
154         }
155
156         ao2_cleanup(stream->formats);
157         ast_free(stream);
158 }
159
160 const char *ast_stream_get_name(const struct ast_stream *stream)
161 {
162         ast_assert(stream != NULL);
163
164         return stream->name;
165 }
166
167 enum ast_media_type ast_stream_get_type(const struct ast_stream *stream)
168 {
169         ast_assert(stream != NULL);
170
171         return stream->type;
172 }
173
174 void ast_stream_set_type(struct ast_stream *stream, enum ast_media_type type)
175 {
176         ast_assert(stream != NULL);
177
178         stream->type = type;
179 }
180
181 struct ast_format_cap *ast_stream_get_formats(const struct ast_stream *stream)
182 {
183         ast_assert(stream != NULL);
184
185         return stream->formats;
186 }
187
188 void ast_stream_set_formats(struct ast_stream *stream, struct ast_format_cap *caps)
189 {
190         ast_assert(stream != NULL);
191
192         ao2_cleanup(stream->formats);
193         stream->formats = ao2_bump(caps);
194 }
195
196 enum ast_stream_state ast_stream_get_state(const struct ast_stream *stream)
197 {
198         ast_assert(stream != NULL);
199
200         return stream->state;
201 }
202
203 void ast_stream_set_state(struct ast_stream *stream, enum ast_stream_state state)
204 {
205         ast_assert(stream != NULL);
206
207         stream->state = state;
208 }
209
210 const char *ast_stream_state2str(enum ast_stream_state state)
211 {
212         switch (state) {
213         case AST_STREAM_STATE_REMOVED:
214                 return "removed";
215         case AST_STREAM_STATE_SENDRECV:
216                 return "sendrecv";
217         case AST_STREAM_STATE_SENDONLY:
218                 return "sendonly";
219         case AST_STREAM_STATE_RECVONLY:
220                 return "recvonly";
221         case AST_STREAM_STATE_INACTIVE:
222                 return "inactive";
223         default:
224                 return "<unknown>";
225         }
226 }
227
228 enum ast_stream_state ast_stream_str2state(const char *str)
229 {
230         if (!strcmp("sendrecv", str)) {
231                 return AST_STREAM_STATE_SENDRECV;
232         }
233         if (!strcmp("sendonly", str)) {
234                 return AST_STREAM_STATE_SENDONLY;
235         }
236         if (!strcmp("recvonly", str)) {
237                 return AST_STREAM_STATE_RECVONLY;
238         }
239         if (!strcmp("inactive", str)) {
240                 return AST_STREAM_STATE_INACTIVE;
241         }
242         return AST_STREAM_STATE_REMOVED;
243 }
244
245 const char *ast_stream_get_metadata(const struct ast_stream *stream, const char *m_key)
246 {
247         struct ast_variable *v;
248
249         ast_assert_return(stream != NULL, NULL);
250         ast_assert_return(m_key != NULL, NULL);
251
252         for (v = stream->metadata; v; v = v->next) {
253                 if (strcmp(v->name, m_key) == 0) {
254                         return v->value;
255                 }
256         }
257
258         return NULL;
259 }
260
261 struct ast_variable *ast_stream_get_metadata_list(const struct ast_stream *stream)
262 {
263         struct ast_variable *v;
264         struct ast_variable *vout = NULL;
265
266         ast_assert_return(stream != NULL, NULL);
267
268         for (v = stream->metadata; v; v = v->next) {
269                 struct ast_variable *vt = ast_variable_new(v->name, v->value, "");
270
271                 if (!vt) {
272                         ast_variables_destroy(vout);
273                         return NULL;
274                 }
275
276                 ast_variable_list_append(&vout, vt);
277         }
278
279         return vout;
280 }
281
282 int ast_stream_set_metadata(struct ast_stream *stream, const char *m_key, const char *value)
283 {
284         struct ast_variable *v;
285         struct ast_variable *prev;
286
287         ast_assert_return(stream != NULL, -1);
288         ast_assert_return(m_key != NULL, -1);
289
290         prev = NULL;
291         v = stream->metadata;
292         while(v) {
293                 struct ast_variable *next = v->next;
294                 if (strcmp(v->name, m_key) == 0) {
295                         if (prev) {
296                                 prev->next = next;
297                         } else {
298                                 stream->metadata = next;
299                         }
300                         ast_free(v);
301                         break;
302                 } else {
303                         prev = v;
304                 }
305                 v = next;
306         }
307
308         if (!value) {
309                 return 0;
310         }
311
312         v = ast_variable_new(m_key, value, "");
313         if (!v) {
314                 return -1;
315         }
316
317         ast_variable_list_append(&stream->metadata, v);
318
319         return 0;
320 }
321
322 int ast_stream_get_position(const struct ast_stream *stream)
323 {
324         ast_assert(stream != NULL);
325
326         return stream->position;
327 }
328
329 struct ast_rtp_codecs *ast_stream_get_rtp_codecs(const struct ast_stream *stream)
330 {
331         ast_assert(stream != NULL);
332
333         return stream->rtp_codecs;
334 }
335
336 void ast_stream_set_rtp_codecs(struct ast_stream *stream, struct ast_rtp_codecs *rtp_codecs)
337 {
338         ast_assert(stream != NULL);
339
340         if (stream->rtp_codecs) {
341                 ast_rtp_codecs_payloads_destroy(rtp_codecs);
342         }
343
344         stream->rtp_codecs = rtp_codecs;
345 }
346
347 static void stream_topology_destroy(void *data)
348 {
349         struct ast_stream_topology *topology = data;
350
351         AST_VECTOR_CALLBACK_VOID(&topology->streams, ast_stream_free);
352         AST_VECTOR_FREE(&topology->streams);
353 }
354
355 #define TOPOLOGY_INITIAL_STREAM_COUNT 2
356 struct ast_stream_topology *ast_stream_topology_alloc(void)
357 {
358         struct ast_stream_topology *topology;
359
360         topology = ao2_alloc_options(sizeof(*topology), stream_topology_destroy, AO2_ALLOC_OPT_LOCK_NOLOCK);
361         if (!topology) {
362                 return NULL;
363         }
364
365         if (AST_VECTOR_INIT(&topology->streams, TOPOLOGY_INITIAL_STREAM_COUNT)) {
366                 ao2_ref(topology, -1);
367                 topology = NULL;
368         }
369
370         return topology;
371 }
372
373 struct ast_stream_topology *ast_stream_topology_clone(
374         const struct ast_stream_topology *topology)
375 {
376         struct ast_stream_topology *new_topology;
377         int i;
378
379         ast_assert(topology != NULL);
380
381         new_topology = ast_stream_topology_alloc();
382         if (!new_topology) {
383                 return NULL;
384         }
385
386         for (i = 0; i < AST_VECTOR_SIZE(&topology->streams); i++) {
387                 struct ast_stream *existing = AST_VECTOR_GET(&topology->streams, i);
388                 struct ast_stream *stream = ast_stream_clone(existing, NULL);
389
390                 if (!stream || AST_VECTOR_APPEND(&new_topology->streams, stream)) {
391                         ast_stream_free(stream);
392                         ast_stream_topology_free(new_topology);
393                         return NULL;
394                 }
395
396                 ast_stream_set_group(stream, ast_stream_get_group(existing));
397         }
398
399         return new_topology;
400 }
401
402 int ast_stream_topology_equal(const struct ast_stream_topology *left,
403         const struct ast_stream_topology *right)
404 {
405         int index;
406
407         ast_assert(left != NULL);
408         ast_assert(right != NULL);
409
410         if (ast_stream_topology_get_count(left) != ast_stream_topology_get_count(right)) {
411                 return 0;
412         }
413
414         for (index = 0; index < ast_stream_topology_get_count(left); ++index) {
415                 const struct ast_stream *left_stream = ast_stream_topology_get_stream(left, index);
416                 const struct ast_stream *right_stream = ast_stream_topology_get_stream(right, index);
417
418                 if (ast_stream_get_type(left_stream) != ast_stream_get_type(right_stream)) {
419                         return 0;
420                 }
421
422                 if (ast_stream_get_state(left_stream) != ast_stream_get_state(right_stream)) {
423                         return 0;
424                 }
425
426                 if (!ast_stream_get_formats(left_stream) && ast_stream_get_formats(right_stream) &&
427                         ast_format_cap_count(ast_stream_get_formats(right_stream))) {
428                         /* A NULL format capabilities and an empty format capabilities are the same, as they have
429                          * no formats inside. If one does though... they are not equal.
430                          */
431                         return 0;
432                 } else if (!ast_stream_get_formats(right_stream) && ast_stream_get_formats(left_stream) &&
433                         ast_format_cap_count(ast_stream_get_formats(left_stream))) {
434                         return 0;
435                 } else if (ast_stream_get_formats(left_stream) && ast_stream_get_formats(right_stream) &&
436                         !ast_format_cap_identical(ast_stream_get_formats(left_stream), ast_stream_get_formats(right_stream))) {
437                         /* But if both are actually present we need to do an actual identical check. */
438                         return 0;
439                 }
440
441                 if (strcmp(ast_stream_get_name(left_stream), ast_stream_get_name(right_stream))) {
442                         return 0;
443                 }
444         }
445
446         return 1;
447 }
448
449 void ast_stream_topology_free(struct ast_stream_topology *topology)
450 {
451         ao2_cleanup(topology);
452 }
453
454 int ast_stream_topology_append_stream(struct ast_stream_topology *topology, struct ast_stream *stream)
455 {
456         ast_assert(topology && stream);
457
458         if (AST_VECTOR_APPEND(&topology->streams, stream)) {
459                 return -1;
460         }
461
462         stream->position = AST_VECTOR_SIZE(&topology->streams) - 1;
463
464         return AST_VECTOR_SIZE(&topology->streams) - 1;
465 }
466
467 int ast_stream_topology_get_count(const struct ast_stream_topology *topology)
468 {
469         ast_assert(topology != NULL);
470
471         return AST_VECTOR_SIZE(&topology->streams);
472 }
473
474 struct ast_stream *ast_stream_topology_get_stream(
475         const struct ast_stream_topology *topology, unsigned int stream_num)
476 {
477         ast_assert(topology != NULL);
478
479         return AST_VECTOR_GET(&topology->streams, stream_num);
480 }
481
482 int ast_stream_topology_set_stream(struct ast_stream_topology *topology,
483         unsigned int position, struct ast_stream *stream)
484 {
485         struct ast_stream *existing_stream;
486
487         ast_assert(topology && stream);
488
489         if (position > AST_VECTOR_SIZE(&topology->streams)) {
490                 return -1;
491         }
492
493         if (position < AST_VECTOR_SIZE(&topology->streams)) {
494                 existing_stream = AST_VECTOR_GET(&topology->streams, position);
495                 ast_stream_free(existing_stream);
496         }
497
498         stream->position = position;
499
500         if (position == AST_VECTOR_SIZE(&topology->streams)) {
501                 return AST_VECTOR_APPEND(&topology->streams, stream);
502         }
503
504         return AST_VECTOR_REPLACE(&topology->streams, position, stream);
505 }
506
507 int ast_stream_topology_del_stream(struct ast_stream_topology *topology,
508         unsigned int position)
509 {
510         struct ast_stream *stream;
511
512         ast_assert(topology != NULL);
513
514         if (AST_VECTOR_SIZE(&topology->streams) <= position) {
515                 return -1;
516         }
517
518         stream = AST_VECTOR_REMOVE_ORDERED(&topology->streams, position);
519         ast_stream_free(stream);
520
521         /* Fix up higher stream position indices */
522         for (; position < AST_VECTOR_SIZE(&topology->streams); ++position) {
523                 stream = AST_VECTOR_GET(&topology->streams, position);
524                 stream->position = position;
525         }
526
527         return 0;
528 }
529
530 struct ast_stream_topology *ast_stream_topology_create_from_format_cap(
531         struct ast_format_cap *cap)
532 {
533         struct ast_stream_topology *topology;
534         enum ast_media_type type;
535
536         topology = ast_stream_topology_alloc();
537         if (!topology || !cap || !ast_format_cap_count(cap)) {
538                 return topology;
539         }
540
541         for (type = AST_MEDIA_TYPE_UNKNOWN + 1; type < AST_MEDIA_TYPE_END; type++) {
542                 struct ast_format_cap *new_cap;
543                 struct ast_stream *stream;
544
545                 if (!ast_format_cap_has_type(cap, type)) {
546                         continue;
547                 }
548
549                 new_cap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
550                 if (!new_cap) {
551                         ast_stream_topology_free(topology);
552                         return NULL;
553                 }
554
555                 ast_format_cap_set_framing(new_cap, ast_format_cap_get_framing(cap));
556                 if (ast_format_cap_append_from_cap(new_cap, cap, type)) {
557                         ao2_cleanup(new_cap);
558                         ast_stream_topology_free(topology);
559                         return NULL;
560                 }
561
562                 stream = ast_stream_alloc(ast_codec_media_type2str(type), type);
563                 if (!stream) {
564                         ao2_cleanup(new_cap);
565                         ast_stream_topology_free(topology);
566                         return NULL;
567                 }
568                 /* We're transferring the initial ref so no bump needed */
569                 stream->formats = new_cap;
570                 stream->state = AST_STREAM_STATE_SENDRECV;
571                 if (ast_stream_topology_append_stream(topology, stream) == -1) {
572                         ast_stream_free(stream);
573                         ast_stream_topology_free(topology);
574                         return NULL;
575                 }
576         }
577
578         return topology;
579 }
580
581 struct ast_format_cap *ast_format_cap_from_stream_topology(
582     struct ast_stream_topology *topology)
583 {
584         struct ast_format_cap *caps;
585         int i;
586
587         ast_assert(topology != NULL);
588
589         caps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
590         if (!caps) {
591                 return NULL;
592         }
593
594         for (i = 0; i < AST_VECTOR_SIZE(&topology->streams); i++) {
595                 struct ast_stream *stream;
596
597                 stream = AST_VECTOR_GET(&topology->streams, i);
598                 if (!stream->formats
599                         || stream->state == AST_STREAM_STATE_REMOVED) {
600                         continue;
601                 }
602
603                 ast_format_cap_append_from_cap(caps, stream->formats, AST_MEDIA_TYPE_UNKNOWN);
604         }
605
606         return caps;
607 }
608
609 struct ast_stream *ast_stream_topology_get_first_stream_by_type(
610         const struct ast_stream_topology *topology,
611         enum ast_media_type type)
612 {
613         int i;
614
615         ast_assert(topology != NULL);
616
617         for (i = 0; i < AST_VECTOR_SIZE(&topology->streams); i++) {
618                 struct ast_stream *stream;
619
620                 stream = AST_VECTOR_GET(&topology->streams, i);
621                 if (stream->type == type
622                         && stream->state != AST_STREAM_STATE_REMOVED) {
623                         return stream;
624                 }
625         }
626
627         return NULL;
628 }
629
630 void ast_stream_topology_map(const struct ast_stream_topology *topology,
631         struct ast_vector_int *types, struct ast_vector_int *v0, struct ast_vector_int *v1)
632 {
633         int i;
634         int nths[AST_MEDIA_TYPE_END] = {0};
635         int size = ast_stream_topology_get_count(topology);
636
637         /*
638          * Clear out any old mappings and initialize the new ones
639          */
640         AST_VECTOR_FREE(v0);
641         AST_VECTOR_FREE(v1);
642
643         /*
644          * Both vectors are sized to the topology. The media types vector is always
645          * guaranteed to be the size of the given topology or greater.
646          */
647         AST_VECTOR_INIT(v0, size);
648         AST_VECTOR_INIT(v1, size);
649
650         for (i = 0; i < size; ++i) {
651                 struct ast_stream *stream = ast_stream_topology_get_stream(topology, i);
652                 enum ast_media_type type = ast_stream_get_type(stream);
653                 int index = AST_VECTOR_GET_INDEX_NTH(types, ++nths[type],
654                         type, AST_VECTOR_ELEM_DEFAULT_CMP);
655
656                 if (index == -1) {
657                         /*
658                          * If a given type is not found for an index level then update the
659                          * media types vector with that type. This keeps the media types
660                          * vector always at the max topology size.
661                          */
662                         AST_VECTOR_APPEND(types, type);
663                         index = AST_VECTOR_SIZE(types) - 1;
664                 }
665
666                 /*
667                  * The mapping is reflexive in the sense that if it maps in one direction
668                  * then the reverse direction maps back to the other's index.
669                  */
670                 AST_VECTOR_REPLACE(v0, i, index);
671                 AST_VECTOR_REPLACE(v1, index, i);
672         }
673 }
674
675 int ast_stream_get_group(const struct ast_stream *stream)
676 {
677         ast_assert(stream != NULL);
678
679         return stream->group;
680 }
681
682 void ast_stream_set_group(struct ast_stream *stream, int group)
683 {
684         ast_assert(stream != NULL);
685
686         stream->group = group;
687 }