bbfb69721650fc0c9e379373048b181a9412d3b5
[asterisk/asterisk.git] / main / format.c
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 2014, 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 Format 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 ASTERISK_REGISTER_FILE()
33
34 #include "asterisk/logger.h"
35 #include "asterisk/codec.h"
36 #include "asterisk/format.h"
37 #include "asterisk/astobj2.h"
38 #include "asterisk/strings.h"
39 #include "asterisk/module.h"
40
41 /*! \brief Number of buckets to use for format interfaces (should be prime for performance reasons) */
42 #define FORMAT_INTERFACE_BUCKETS 53
43
44 /*! \brief Definition of a media format */
45 struct ast_format {
46         /*! Name of the format */
47         const char *name;
48         /*! \brief Pointer to the codec in use for this format */
49         struct ast_codec *codec;
50         /*! \brief Attribute specific data, implementation specific */
51         void *attribute_data;
52         /*! \brief Pointer to the optional format interface */
53         const struct ast_format_interface *interface;
54 };
55
56 /*! \brief Structure used when registering a format interface */
57 struct format_interface {
58         /*! \brief Pointer to the format interface itself */
59         const struct ast_format_interface *interface;
60         /*! \brief Name of the codec the interface is for */
61         char codec[0];
62 };
63
64 /*! \brief Container for registered format interfaces */
65 static struct ao2_container *interfaces;
66
67 static int format_interface_hash(const void *obj, int flags)
68 {
69         const struct format_interface *format_interface;
70         const char *key;
71
72         switch (flags & OBJ_SEARCH_MASK) {
73         case OBJ_SEARCH_KEY:
74                 key = obj;
75                 return ast_str_hash(key);
76         case OBJ_SEARCH_OBJECT:
77                 format_interface = obj;
78                 return ast_str_hash(format_interface->codec);
79         default:
80                 /* Hash can only work on something with a full key. */
81                 ast_assert(0);
82                 return 0;
83         }
84 }
85
86 static int format_interface_cmp(void *obj, void *arg, int flags)
87 {
88         const struct format_interface *left = obj;
89         const struct format_interface *right = arg;
90         const char *right_key = arg;
91         int cmp;
92
93         switch (flags & OBJ_SEARCH_MASK) {
94         case OBJ_SEARCH_OBJECT:
95                 cmp = strcmp(left->codec, right->codec);
96                 break;
97         case OBJ_SEARCH_KEY:
98                 cmp = strcmp(left->codec, right_key);
99                 break;
100         case OBJ_SEARCH_PARTIAL_KEY:
101                 cmp = strncmp(left->codec, right_key, strlen(right_key));
102                 break;
103         default:
104                 ast_assert(0);
105                 cmp = 0;
106                 break;
107         }
108         if (cmp) {
109                 return 0;
110         }
111
112         return CMP_MATCH;
113 }
114
115 /*! \brief Function called when the process is shutting down */
116 static void format_shutdown(void)
117 {
118         ao2_cleanup(interfaces);
119         interfaces = NULL;
120 }
121
122 int ast_format_init(void)
123 {
124         interfaces = ao2_container_alloc_options(AO2_ALLOC_OPT_LOCK_RWLOCK, FORMAT_INTERFACE_BUCKETS, format_interface_hash,
125                 format_interface_cmp);
126         if (!interfaces) {
127                 return -1;
128         }
129
130         ast_register_cleanup(format_shutdown);
131
132         return 0;
133 }
134
135 int __ast_format_interface_register(const char *codec, const struct ast_format_interface *interface, struct ast_module *mod)
136 {
137         SCOPED_AO2WRLOCK(lock, interfaces);
138         struct format_interface *format_interface;
139
140         if (!interface->format_clone || !interface->format_destroy) {
141                 ast_log(LOG_ERROR, "Format interface for codec '%s' does not implement required callbacks\n", codec);
142                 return -1;
143         }
144
145         format_interface = ao2_find(interfaces, codec, OBJ_SEARCH_KEY | OBJ_NOLOCK);
146         if (format_interface) {
147                 ast_log(LOG_ERROR, "A format interface is already present for codec '%s'\n", codec);
148                 ao2_ref(format_interface, -1);
149                 return -1;
150         }
151
152         format_interface = ao2_alloc_options(sizeof(*format_interface) + strlen(codec) + 1,
153                 NULL, AO2_ALLOC_OPT_LOCK_NOLOCK);
154         if (!format_interface) {
155                 return -1;
156         }
157         format_interface->interface = interface;
158         strcpy(format_interface->codec, codec); /* Safe */
159
160         /* Once registered a format interface cannot be unregistered. */
161         ast_module_shutdown_ref(mod);
162         ao2_link_flags(interfaces, format_interface, OBJ_NOLOCK);
163         ao2_ref(format_interface, -1);
164
165         ast_verb(2, "Registered format interface for codec '%s'\n", codec);
166
167         return 0;
168 }
169
170 void *ast_format_get_attribute_data(const struct ast_format *format)
171 {
172         return format->attribute_data;
173 }
174
175 void ast_format_set_attribute_data(struct ast_format *format, void *attribute_data)
176 {
177         format->attribute_data = attribute_data;
178 }
179
180 /*! \brief Destructor for media formats */
181 static void format_destroy(void *obj)
182 {
183         struct ast_format *format = obj;
184
185         if (format->interface) {
186                 format->interface->format_destroy(format);
187         }
188
189         ao2_cleanup(format->codec);
190 }
191
192 struct ast_format *ast_format_create_named(const char *format_name, struct ast_codec *codec)
193 {
194         struct ast_format *format;
195         struct format_interface *format_interface;
196
197         format = ao2_t_alloc_options(sizeof(*format), format_destroy,
198                 AO2_ALLOC_OPT_LOCK_NOLOCK, S_OR(codec->description, ""));
199         if (!format) {
200                 return NULL;
201         }
202         format->name = format_name;
203         format->codec = ao2_bump(codec);
204
205         format_interface = ao2_find(interfaces, codec->name, OBJ_SEARCH_KEY);
206         if (format_interface) {
207                 format->interface = format_interface->interface;
208                 ao2_ref(format_interface, -1);
209         }
210
211         return format;
212 }
213
214 struct ast_format *ast_format_clone(const struct ast_format *format)
215 {
216         struct ast_format *cloned = ast_format_create_named(format->name, format->codec);
217
218         if (!cloned) {
219                 return NULL;
220         }
221
222         if (cloned->interface && cloned->interface->format_clone(format, cloned)) {
223                 ao2_ref(cloned, -1);
224                 return NULL;
225         }
226
227         return cloned;
228 }
229
230 struct ast_format *ast_format_create(struct ast_codec *codec)
231 {
232         return ast_format_create_named(codec->name, codec);
233 }
234
235 enum ast_format_cmp_res ast_format_cmp(const struct ast_format *format1, const struct ast_format *format2)
236 {
237         const struct ast_format_interface *interface;
238
239         if (format1 == NULL || format2 == NULL) {
240                 return AST_FORMAT_CMP_NOT_EQUAL;
241         }
242
243         if (format1 == format2) {
244                 return AST_FORMAT_CMP_EQUAL;
245         }
246
247         if (format1->codec != format2->codec) {
248                 return AST_FORMAT_CMP_NOT_EQUAL;
249         }
250
251         interface = format1->interface ? format1->interface : format2->interface;
252
253         if (interface && interface->format_cmp) {
254                 return interface->format_cmp(format1, format2);
255         }
256
257         return AST_FORMAT_CMP_EQUAL;
258 }
259
260 struct ast_format *ast_format_joint(const struct ast_format *format1, const struct ast_format *format2)
261 {
262         const struct ast_format_interface *interface;
263
264         if (format1->codec != format2->codec) {
265                 return NULL;
266         }
267
268         /* If the two formats are the same structure OR if the codec is the same and no attributes
269          * exist we can immediately return a format with reference count bumped up, since they are
270          * the same.
271          */
272         if ((ast_format_cmp(format1, format2) == AST_FORMAT_CMP_EQUAL && !format1->attribute_data && !format2->attribute_data)) {
273                 return ao2_bump((struct ast_format*)format1);
274         }
275
276         interface = format1->interface ? format1->interface : format2->interface;
277
278         /* If there is attribute data on either there has to be an interface */
279         return interface->format_get_joint(format1, format2);
280 }
281
282 struct ast_format *ast_format_attribute_set(const struct ast_format *format, const char *name, const char *value)
283 {
284         const struct ast_format_interface *interface = format->interface;
285
286         if (!interface) {
287                 struct format_interface *format_interface = ao2_find(interfaces, format->codec->name, OBJ_SEARCH_KEY);
288                 if (format_interface) {
289                         interface = format_interface->interface;
290                         ao2_ref(format_interface, -1);
291                 }
292         }
293
294         if (!interface || !interface->format_attribute_set) {
295                 return ao2_bump((struct ast_format*)format);
296         }
297
298         return interface->format_attribute_set(format, name, value);
299 }
300
301 struct ast_format *ast_format_parse_sdp_fmtp(const struct ast_format *format, const char *attributes)
302 {
303         const struct ast_format_interface *interface = format->interface;
304
305         if (!interface) {
306                 struct format_interface *format_interface = ao2_find(interfaces, format->codec->name, OBJ_SEARCH_KEY);
307                 if (format_interface) {
308                         interface = format_interface->interface;
309                         ao2_ref(format_interface, -1);
310                 }
311         }
312
313         if (!interface || !interface->format_parse_sdp_fmtp) {
314                 return ao2_bump((struct ast_format*)format);
315         }
316
317         return interface->format_parse_sdp_fmtp(format, attributes);
318 }
319
320 void ast_format_generate_sdp_fmtp(const struct ast_format *format, unsigned int payload, struct ast_str **str)
321 {
322         if (!format->interface || !format->interface->format_generate_sdp_fmtp) {
323                 return;
324         }
325
326         format->interface->format_generate_sdp_fmtp(format, payload, str);
327 }
328
329 struct ast_codec *ast_format_get_codec(const struct ast_format *format)
330 {
331         return ao2_bump(format->codec);
332 }
333
334 unsigned int ast_format_get_codec_id(const struct ast_format *format)
335 {
336         return format->codec->id;
337 }
338
339 const char *ast_format_get_name(const struct ast_format *format)
340 {
341         return format->name;
342 }
343
344 const char *ast_format_get_codec_name(const struct ast_format *format)
345 {
346         return format->codec->name;
347 }
348
349 int ast_format_can_be_smoothed(const struct ast_format *format)
350 {
351         return format->codec->smooth;
352 }
353
354 enum ast_media_type ast_format_get_type(const struct ast_format *format)
355 {
356         return format->codec->type;
357 }
358
359 unsigned int ast_format_get_default_ms(const struct ast_format *format)
360 {
361         return format->codec->default_ms;
362 }
363
364 unsigned int ast_format_get_minimum_ms(const struct ast_format *format)
365 {
366         return format->codec->minimum_ms;
367 }
368
369 unsigned int ast_format_get_maximum_ms(const struct ast_format *format)
370 {
371         return format->codec->maximum_ms;
372 }
373
374 unsigned int ast_format_get_minimum_bytes(const struct ast_format *format)
375 {
376         return format->codec->minimum_bytes;
377 }
378
379 unsigned int ast_format_get_sample_rate(const struct ast_format *format)
380 {
381         return format->codec->sample_rate ?: 8000;
382 }
383
384 unsigned int ast_format_determine_length(const struct ast_format *format, unsigned int samples)
385 {
386         return ast_codec_determine_length(format->codec, samples);
387 }