media formats: re-architect handling of media for performance improvements
[asterisk/asterisk.git] / main / format_cache.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 Cache 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_FILE_VERSION(__FILE__, "$Revision$")
33
34 #include "asterisk/logger.h"
35 #include "asterisk/format.h"
36 #include "asterisk/format_cache.h"
37 #include "asterisk/astobj2.h"
38 #include "asterisk/strings.h"
39
40 /*!
41  * \brief Built-in cached signed linear 8kHz format.
42  */
43 struct ast_format *ast_format_slin;
44
45 /*!
46  * \brief Built-in cached signed linear 12kHz format.
47  */
48 struct ast_format *ast_format_slin12;
49
50 /*!
51  * \brief Built-in cached signed linear 16kHz format.
52  */
53 struct ast_format *ast_format_slin16;
54
55 /*!
56  * \brief Built-in cached signed linear 24kHz format.
57  */
58 struct ast_format *ast_format_slin24;
59
60 /*!
61  * \brief Built-in cached signed linear 32kHz format.
62  */
63 struct ast_format *ast_format_slin32;
64
65 /*!
66  * \brief Built-in cached signed linear 44kHz format.
67  */
68 struct ast_format *ast_format_slin44;
69
70 /*!
71  * \brief Built-in cached signed linear 48kHz format.
72  */
73 struct ast_format *ast_format_slin48;
74
75 /*!
76  * \brief Built-in cached signed linear 96kHz format.
77  */
78 struct ast_format *ast_format_slin96;
79
80 /*!
81  * \brief Built-in cached signed linear 192kHz format.
82  */
83 struct ast_format *ast_format_slin192;
84
85 /*!
86  * \brief Built-in cached ulaw format.
87  */
88 struct ast_format *ast_format_ulaw;
89
90 /*!
91  * \brief Built-in cached alaw format.
92  */
93 struct ast_format *ast_format_alaw;
94
95 /*!
96  * \brief Built-in cached testlaw format.
97  */
98 struct ast_format *ast_format_testlaw;
99
100 /*!
101  * \brief Built-in cached gsm format.
102  */
103 struct ast_format *ast_format_gsm;
104
105 /*!
106  * \brief Built-in cached adpcm format.
107  */
108 struct ast_format *ast_format_adpcm;
109
110 /*!
111  * \brief Built-in cached g722 format.
112  */
113 struct ast_format *ast_format_g722;
114
115 /*!
116  * \brief Built-in cached g726 format.
117  */
118 struct ast_format *ast_format_g726;
119
120 /*!
121  * \brief Built-in cached g726-aal2 format.
122  */
123 struct ast_format *ast_format_g726_aal2;
124
125 /*!
126  * \brief Built-in cached ilbc format.
127  */
128 struct ast_format *ast_format_ilbc;
129
130 /*!
131  * \brief Built-in cached ilbc format.
132  */
133 struct ast_format *ast_format_lpc10;
134
135 /*!
136  * \brief Built-in cached speex format.
137  */
138 struct ast_format *ast_format_speex;
139
140 /*!
141  * \brief Built-in cached speex at 16kHz format.
142  */
143 struct ast_format *ast_format_speex16;
144
145 /*!
146  * \brief Built-in cached speex at 32kHz format.
147  */
148 struct ast_format *ast_format_speex32;
149
150 /*!
151  * \brief Built-in cached g723.1 format.
152  */
153 struct ast_format *ast_format_g723;
154
155 /*!
156  * \brief Built-in cached g729 format.
157  */
158 struct ast_format *ast_format_g729;
159
160 /*!
161  * \brief Built-in cached g719 format.
162  */
163 struct ast_format *ast_format_g719;
164
165 /*!
166  * \brief Built-in cached h261 format.
167  */
168 struct ast_format *ast_format_h261;
169
170 /*!
171  * \brief Built-in cached h263 format.
172  */
173 struct ast_format *ast_format_h263;
174
175 /*!
176  * \brief Built-in cached h263 plus format.
177  */
178 struct ast_format *ast_format_h263p;
179
180 /*!
181  * \brief Built-in cached h264 format.
182  */
183 struct ast_format *ast_format_h264;
184
185 /*!
186  * \brief Built-in cached mp4 format.
187  */
188 struct ast_format *ast_format_mp4;
189
190 /*!
191  * \brief Built-in cached vp8 format.
192  */
193 struct ast_format *ast_format_vp8;
194
195 /*!
196  * \brief Built-in cached jpeg format.
197  */
198 struct ast_format *ast_format_jpeg;
199
200 /*!
201  * \brief Built-in cached png format.
202  */
203 struct ast_format *ast_format_png;
204
205 /*!
206  * \brief Built-in cached siren14 format.
207  */
208 struct ast_format *ast_format_siren14;
209
210 /*!
211  * \brief Built-in cached siren7 format.
212  */
213 struct ast_format *ast_format_siren7;
214
215 /*!
216  * \brief Built-in cached opus format.
217  */
218 struct ast_format *ast_format_opus;
219
220 /*!
221  * \brief Built-in cached t140 format.
222  */
223 struct ast_format *ast_format_t140;
224
225 /*!
226  * \brief Built-in cached t140 red format.
227  */
228 struct ast_format *ast_format_t140_red;
229
230 /*!
231  * \brief Built-in cached vp8 format.
232  */
233 struct ast_format *ast_format_vp8;
234
235 /*!
236  * \brief Built-in "null" format.
237  */
238 struct ast_format *ast_format_none;
239
240 /*! \brief Number of buckets to use for the media format cache (should be prime for performance reasons) */
241 #define CACHE_BUCKETS 53
242
243 /*! \brief Cached formats */
244 static struct ao2_container *formats;
245
246 static int format_hash_cb(const void *obj, int flags)
247 {
248         const struct ast_format *format;
249         const char *key;
250
251         switch (flags & OBJ_SEARCH_MASK) {
252         case OBJ_SEARCH_KEY:
253                 key = obj;
254                 return ast_str_case_hash(key);
255         case OBJ_SEARCH_OBJECT:
256                 format = obj;
257                 return ast_str_case_hash(ast_format_get_name(format));
258         default:
259                 /* Hash can only work on something with a full key. */
260                 ast_assert(0);
261                 return 0;
262         }
263 }
264
265 static int format_cmp_cb(void *obj, void *arg, int flags)
266 {
267         const struct ast_format *left = obj;
268         const struct ast_format *right = arg;
269         const char *right_key = arg;
270         int cmp;
271
272         switch (flags & OBJ_SEARCH_MASK) {
273         case OBJ_SEARCH_OBJECT:
274                 right_key = ast_format_get_name(right);
275                 /* Fall through */
276         case OBJ_SEARCH_KEY:
277                 cmp = strcasecmp(ast_format_get_name(left), right_key);
278                 break;
279         case OBJ_SEARCH_PARTIAL_KEY:
280                 cmp = strncasecmp(ast_format_get_name(left), right_key, strlen(right_key));
281                 break;
282         default:
283                 ast_assert(0);
284                 cmp = 0;
285                 break;
286         }
287         if (cmp) {
288                 return 0;
289         }
290
291         return CMP_MATCH;
292 }
293
294 /*! \brief Function called when the process is shutting down */
295 static void format_cache_shutdown(void)
296 {
297         ao2_cleanup(formats);
298         formats = NULL;
299
300         ao2_replace(ast_format_g723, NULL);
301         ao2_replace(ast_format_ulaw, NULL);
302         ao2_replace(ast_format_alaw, NULL);
303         ao2_replace(ast_format_gsm, NULL);
304         ao2_replace(ast_format_g726, NULL);
305         ao2_replace(ast_format_g726_aal2, NULL);
306         ao2_replace(ast_format_adpcm, NULL);
307         ao2_replace(ast_format_slin, NULL);
308         ao2_replace(ast_format_slin12, NULL);
309         ao2_replace(ast_format_slin16, NULL);
310         ao2_replace(ast_format_slin24, NULL);
311         ao2_replace(ast_format_slin32, NULL);
312         ao2_replace(ast_format_slin44, NULL);
313         ao2_replace(ast_format_slin48, NULL);
314         ao2_replace(ast_format_slin96, NULL);
315         ao2_replace(ast_format_slin192, NULL);
316         ao2_replace(ast_format_lpc10, NULL);
317         ao2_replace(ast_format_g729, NULL);
318         ao2_replace(ast_format_speex, NULL);
319         ao2_replace(ast_format_speex16, NULL);
320         ao2_replace(ast_format_speex32, NULL);
321         ao2_replace(ast_format_ilbc, NULL);
322         ao2_replace(ast_format_g722, NULL);
323         ao2_replace(ast_format_siren7, NULL);
324         ao2_replace(ast_format_siren14, NULL);
325         ao2_replace(ast_format_testlaw, NULL);
326         ao2_replace(ast_format_g719, NULL);
327         ao2_replace(ast_format_opus, NULL);
328         ao2_replace(ast_format_jpeg, NULL);
329         ao2_replace(ast_format_png, NULL);
330         ao2_replace(ast_format_h261, NULL);
331         ao2_replace(ast_format_h263, NULL);
332         ao2_replace(ast_format_h263p, NULL);
333         ao2_replace(ast_format_h264, NULL);
334         ao2_replace(ast_format_mp4, NULL);
335         ao2_replace(ast_format_vp8, NULL);
336         ao2_replace(ast_format_t140_red, NULL);
337         ao2_replace(ast_format_t140, NULL);
338         ao2_replace(ast_format_none, NULL);
339 }
340
341 int ast_format_cache_init(void)
342 {
343         formats = ao2_container_alloc_options(AO2_ALLOC_OPT_LOCK_RWLOCK, CACHE_BUCKETS,
344                 format_hash_cb, format_cmp_cb);
345         if (!formats) {
346                 return -1;
347         }
348
349         ast_register_atexit(format_cache_shutdown);
350
351         return 0;
352 }
353
354 static void set_cached_format(const char *name, struct ast_format *format)
355 {
356         if (!strcmp(name, "g723")) {
357                 ao2_replace(ast_format_g723, format);
358         } else if (!strcmp(name, "ulaw")) {
359                 ao2_replace(ast_format_ulaw, format);
360         } else if (!strcmp(name, "alaw")) {
361                 ao2_replace(ast_format_alaw, format);
362         } else if (!strcmp(name, "gsm")) {
363                 ao2_replace(ast_format_gsm, format);
364         } else if (!strcmp(name, "g726")) {
365                 ao2_replace(ast_format_g726, format);
366         } else if (!strcmp(name, "g726aal2")) {
367                 ao2_replace(ast_format_g726_aal2, format);
368         } else if (!strcmp(name, "adpcm")) {
369                 ao2_replace(ast_format_adpcm, format);
370         } else if (!strcmp(name, "slin")) {
371                 ao2_replace(ast_format_slin, format);
372         } else if (!strcmp(name, "slin12")) {
373                 ao2_replace(ast_format_slin12, format);
374         } else if (!strcmp(name, "slin16")) {
375                 ao2_replace(ast_format_slin16, format);
376         } else if (!strcmp(name, "slin24")) {
377                 ao2_replace(ast_format_slin24, format);
378         } else if (!strcmp(name, "slin32")) {
379                 ao2_replace(ast_format_slin32, format);
380         } else if (!strcmp(name, "slin44")) {
381                 ao2_replace(ast_format_slin44, format);
382         } else if (!strcmp(name, "slin48")) {
383                 ao2_replace(ast_format_slin48, format);
384         } else if (!strcmp(name, "slin96")) {
385                 ao2_replace(ast_format_slin96, format);
386         } else if (!strcmp(name, "slin192")) {
387                 ao2_replace(ast_format_slin192, format);
388         } else if (!strcmp(name, "lpc10")) {
389                 ao2_replace(ast_format_lpc10, format);
390         } else if (!strcmp(name, "g729")) {
391                 ao2_replace(ast_format_g729, format);
392         } else if (!strcmp(name, "speex")) {
393                 ao2_replace(ast_format_speex, format);
394         } else if (!strcmp(name, "speex16")) {
395                 ao2_replace(ast_format_speex16, format);
396         } else if (!strcmp(name, "speex32")) {
397                 ao2_replace(ast_format_speex32, format);
398         } else if (!strcmp(name, "ilbc")) {
399                 ao2_replace(ast_format_ilbc, format);
400         } else if (!strcmp(name, "g722")) {
401                 ao2_replace(ast_format_g722, format);
402         } else if (!strcmp(name, "siren7")) {
403                 ao2_replace(ast_format_siren7, format);
404         } else if (!strcmp(name, "siren14")) {
405                 ao2_replace(ast_format_siren14, format);
406         } else if (!strcmp(name, "testlaw")) {
407                 ao2_replace(ast_format_testlaw, format);
408         } else if (!strcmp(name, "g719")) {
409                 ao2_replace(ast_format_g719, format);
410         } else if (!strcmp(name, "opus")) {
411                 ao2_replace(ast_format_opus, format);
412         } else if (!strcmp(name, "jpeg")) {
413                 ao2_replace(ast_format_jpeg, format);
414         } else if (!strcmp(name, "png")) {
415                 ao2_replace(ast_format_png, format);
416         } else if (!strcmp(name, "h261")) {
417                 ao2_replace(ast_format_h261, format);
418         } else if (!strcmp(name, "h263")) {
419                 ao2_replace(ast_format_h263, format);
420         } else if (!strcmp(name, "h263p")) {
421                 ao2_replace(ast_format_h263p, format);
422         } else if (!strcmp(name, "h264")) {
423                 ao2_replace(ast_format_h264, format);
424         } else if (!strcmp(name, "mpeg4")) {
425                 ao2_replace(ast_format_mp4, format);
426         } else if (!strcmp(name, "vp8")) {
427                 ao2_replace(ast_format_vp8, format);
428         } else if (!strcmp(name, "red")) {
429                 ao2_replace(ast_format_t140_red, format);
430         } else if (!strcmp(name, "t140")) {
431                 ao2_replace(ast_format_t140, format);
432         } else if (!strcmp(name, "none")) {
433                 ao2_replace(ast_format_none, format);
434         }
435 }
436
437 int ast_format_cache_set(struct ast_format *format)
438 {
439         SCOPED_AO2WRLOCK(lock, formats);
440         struct ast_format *old_format;
441
442         ast_assert(format != NULL);
443
444         if (ast_strlen_zero(ast_format_get_name(format))) {
445                 return -1;
446         }
447
448         old_format = ao2_find(formats, ast_format_get_name(format), OBJ_SEARCH_KEY | OBJ_NOLOCK);
449         if (old_format) {
450                 ao2_unlink_flags(formats, old_format, OBJ_NOLOCK);
451         }
452         ao2_link_flags(formats, format, OBJ_NOLOCK);
453
454         set_cached_format(ast_format_get_name(format), format);
455
456         ast_verb(2, "%s cached format with name '%s'\n",
457                 old_format ? "Updated" : "Created",
458                 ast_format_get_name(format));
459
460         ao2_cleanup(old_format);
461
462         return 0;
463 }
464
465 struct ast_format *__ast_format_cache_get(const char *name)
466 {
467         if (ast_strlen_zero(name)) {
468                 return NULL;
469         }
470
471         return ao2_find(formats, name, OBJ_SEARCH_KEY);
472 }
473
474 struct ast_format *__ast_format_cache_get_debug(const char *name, const char *tag, const char *file, int line, const char *func)
475 {
476         if (ast_strlen_zero(name)) {
477                 return NULL;
478         }
479
480         return __ao2_find_debug(formats, name, OBJ_SEARCH_KEY, S_OR(tag, "ast_format_cache_get"), file, line, func);
481 }
482
483 struct ast_format *ast_format_cache_get_slin_by_rate(unsigned int rate)
484 {
485         if (rate >= 192000) {
486                 return ast_format_slin192;
487         } else if (rate >= 96000) {
488                 return ast_format_slin96;
489         } else if (rate >= 48000) {
490                 return ast_format_slin48;
491         } else if (rate >= 44100) {
492                 return ast_format_slin44;
493         } else if (rate >= 32000) {
494                 return ast_format_slin32;
495         } else if (rate >= 24000) {
496                 return ast_format_slin24;
497         } else if (rate >= 16000) {
498                 return ast_format_slin16;
499         } else if (rate >= 12000) {
500                 return ast_format_slin12;
501         }
502         return ast_format_slin;
503 }
504
505 int ast_format_cache_is_slinear(struct ast_format *format)
506 {
507         if ((ast_format_cmp(format, ast_format_slin) == AST_FORMAT_CMP_EQUAL)
508                 || (ast_format_cmp(format, ast_format_slin16) == AST_FORMAT_CMP_EQUAL)
509                 || (ast_format_cmp(format, ast_format_slin24) == AST_FORMAT_CMP_EQUAL)
510                 || (ast_format_cmp(format, ast_format_slin32) == AST_FORMAT_CMP_EQUAL)
511                 || (ast_format_cmp(format, ast_format_slin44) == AST_FORMAT_CMP_EQUAL)
512                 || (ast_format_cmp(format, ast_format_slin48) == AST_FORMAT_CMP_EQUAL)
513                 || (ast_format_cmp(format, ast_format_slin96) == AST_FORMAT_CMP_EQUAL)
514                 || (ast_format_cmp(format, ast_format_slin192) == AST_FORMAT_CMP_EQUAL)) {
515                 return 1;
516         }
517
518         return 0;
519 }