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