Remove constant conditionals (dead-code).
[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 #include "asterisk/logger.h"
33 #include "asterisk/codec.h"
34 #include "asterisk/format.h"
35 #include "asterisk/astobj2.h"
36 #include "asterisk/strings.h"
37 #include "asterisk/module.h"
38
39 /*! \brief Number of buckets to use for format interfaces (should be prime for performance reasons) */
40 #define FORMAT_INTERFACE_BUCKETS 53
41
42 /*! \brief Definition of a media format */
43 struct ast_format {
44         /*! Name of the format */
45         const char *name;
46         /*! \brief Pointer to the codec in use for this format */
47         struct ast_codec *codec;
48         /*! \brief Attribute specific data, implementation specific */
49         void *attribute_data;
50         /*! \brief Pointer to the optional format interface */
51         const struct ast_format_interface *interface;
52         /*! \brief The number if audio channels used, if more than one an interleaved format is required */
53         unsigned int channel_count;
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 unsigned int ast_format_get_channel_count(const struct ast_format *format)
181 {
182         return format->channel_count;
183 }
184
185 void ast_format_set_channel_count(struct ast_format *format, unsigned int channel_count)
186 {
187         format->channel_count = channel_count;
188 }
189
190 /*! \brief Destructor for media formats */
191 static void format_destroy(void *obj)
192 {
193         struct ast_format *format = obj;
194
195         if (format->interface) {
196                 format->interface->format_destroy(format);
197         }
198
199         ao2_cleanup(format->codec);
200 }
201
202 struct ast_format *ast_format_create_named(const char *format_name, struct ast_codec *codec)
203 {
204         struct ast_format *format;
205         struct format_interface *format_interface;
206
207         format = ao2_t_alloc_options(sizeof(*format), format_destroy,
208                 AO2_ALLOC_OPT_LOCK_NOLOCK, S_OR(codec->description, ""));
209         if (!format) {
210                 return NULL;
211         }
212         format->name = format_name;
213         format->codec = ao2_bump(codec);
214         format->channel_count = 1;
215
216         format_interface = ao2_find(interfaces, codec->name, OBJ_SEARCH_KEY);
217         if (format_interface) {
218                 format->interface = format_interface->interface;
219                 ao2_ref(format_interface, -1);
220         }
221
222         return format;
223 }
224
225 struct ast_format *ast_format_clone(const struct ast_format *format)
226 {
227         struct ast_format *cloned = ast_format_create_named(format->name, format->codec);
228
229         if (!cloned) {
230                 return NULL;
231         }
232
233         if (cloned->interface && cloned->interface->format_clone(format, cloned)) {
234                 ao2_ref(cloned, -1);
235                 return NULL;
236         }
237
238         return cloned;
239 }
240
241 struct ast_format *ast_format_create(struct ast_codec *codec)
242 {
243         return ast_format_create_named(codec->name, codec);
244 }
245
246 enum ast_format_cmp_res ast_format_cmp(const struct ast_format *format1, const struct ast_format *format2)
247 {
248         const struct ast_format_interface *interface;
249
250         if (format1 == NULL || format2 == NULL) {
251                 return AST_FORMAT_CMP_NOT_EQUAL;
252         }
253
254         if (format1 == format2) {
255                 return AST_FORMAT_CMP_EQUAL;
256         }
257
258         if (format1->codec != format2->codec) {
259                 return AST_FORMAT_CMP_NOT_EQUAL;
260         }
261
262         interface = format1->interface ? format1->interface : format2->interface;
263
264         if (interface && interface->format_cmp) {
265                 return interface->format_cmp(format1, format2);
266         }
267
268         return AST_FORMAT_CMP_EQUAL;
269 }
270
271 struct ast_format *ast_format_joint(const struct ast_format *format1, const struct ast_format *format2)
272 {
273         const struct ast_format_interface *interface;
274
275         if (format1->codec != format2->codec) {
276                 return NULL;
277         }
278
279         /* If the two formats are the same structure OR if the codec is the same and no attributes
280          * exist we can immediately return a format with reference count bumped up, since they are
281          * the same.
282          */
283         if ((ast_format_cmp(format1, format2) == AST_FORMAT_CMP_EQUAL && !format1->attribute_data && !format2->attribute_data)) {
284                 return ao2_bump((struct ast_format*)format1);
285         }
286
287         interface = format1->interface ? format1->interface : format2->interface;
288
289         /* If there is attribute data on either there has to be an interface */
290         return interface->format_get_joint(format1, format2);
291 }
292
293 struct ast_format *ast_format_attribute_set(const struct ast_format *format, const char *name, const char *value)
294 {
295         const struct ast_format_interface *interface = format->interface;
296
297         if (!interface) {
298                 struct format_interface *format_interface = ao2_find(interfaces, format->codec->name, OBJ_SEARCH_KEY);
299                 if (format_interface) {
300                         interface = format_interface->interface;
301                         ao2_ref(format_interface, -1);
302                 }
303         }
304
305         if (!interface || !interface->format_attribute_set) {
306                 return ao2_bump((struct ast_format*)format);
307         }
308
309         return interface->format_attribute_set(format, name, value);
310 }
311
312 const void *ast_format_attribute_get(const struct ast_format *format, const char *name)
313 {
314         const struct ast_format_interface *interface = format->interface;
315
316         if (!interface) {
317                 struct format_interface *format_interface = ao2_find(interfaces, format->codec->name, OBJ_SEARCH_KEY);
318                 if (format_interface) {
319                         interface = format_interface->interface;
320                         ao2_ref(format_interface, -1);
321                 }
322         }
323
324         if (!interface || !interface->format_attribute_get) {
325                 return NULL;
326         }
327
328         return interface->format_attribute_get(format, name);
329 }
330
331 struct ast_format *ast_format_parse_sdp_fmtp(const struct ast_format *format, const char *attributes)
332 {
333         const struct ast_format_interface *interface = format->interface;
334
335         if (!interface) {
336                 struct format_interface *format_interface = ao2_find(interfaces, format->codec->name, OBJ_SEARCH_KEY);
337                 if (format_interface) {
338                         interface = format_interface->interface;
339                         ao2_ref(format_interface, -1);
340                 }
341         }
342
343         if (!interface || !interface->format_parse_sdp_fmtp) {
344                 return ao2_bump((struct ast_format*)format);
345         }
346
347         return interface->format_parse_sdp_fmtp(format, attributes);
348 }
349
350 void ast_format_generate_sdp_fmtp(const struct ast_format *format, unsigned int payload, struct ast_str **str)
351 {
352         const struct ast_format_interface *interface = format->interface;
353
354         if (!interface) {
355                 struct format_interface *format_interface = ao2_find(interfaces, format->codec->name, OBJ_SEARCH_KEY);
356                 if (format_interface) {
357                         interface = format_interface->interface;
358                         ao2_ref(format_interface, -1);
359                 }
360         }
361
362         if (!interface || !interface->format_generate_sdp_fmtp) {
363                 return;
364         }
365
366         interface->format_generate_sdp_fmtp(format, payload, str);
367 }
368
369 struct ast_codec *ast_format_get_codec(const struct ast_format *format)
370 {
371         return ao2_bump(format->codec);
372 }
373
374 unsigned int ast_format_get_codec_id(const struct ast_format *format)
375 {
376         return format->codec->id;
377 }
378
379 const char *ast_format_get_name(const struct ast_format *format)
380 {
381         return format->name;
382 }
383
384 const char *ast_format_get_codec_name(const struct ast_format *format)
385 {
386         return format->codec->name;
387 }
388
389 int ast_format_can_be_smoothed(const struct ast_format *format)
390 {
391         return format->codec->smooth;
392 }
393
394 int ast_format_get_smoother_flags(const struct ast_format *format)
395 {
396         return format->codec->smoother_flags;
397 }
398
399 enum ast_media_type ast_format_get_type(const struct ast_format *format)
400 {
401         return format->codec->type;
402 }
403
404 unsigned int ast_format_get_default_ms(const struct ast_format *format)
405 {
406         return format->codec->default_ms;
407 }
408
409 unsigned int ast_format_get_minimum_ms(const struct ast_format *format)
410 {
411         return format->codec->minimum_ms;
412 }
413
414 unsigned int ast_format_get_maximum_ms(const struct ast_format *format)
415 {
416         return format->codec->maximum_ms;
417 }
418
419 unsigned int ast_format_get_minimum_bytes(const struct ast_format *format)
420 {
421         return format->codec->minimum_bytes;
422 }
423
424 unsigned int ast_format_get_sample_rate(const struct ast_format *format)
425 {
426         return format->codec->sample_rate ?: 8000;
427 }
428
429 unsigned int ast_format_determine_length(const struct ast_format *format, unsigned int samples)
430 {
431         return ast_codec_determine_length(format->codec, samples);
432 }