2 * Asterisk -- An open source telephony toolkit.
4 * Copyright (C) 2014, Digium, Inc.
6 * Joshua Colp <jcolp@digium.com>
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.
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.
21 * \brief Media Format Cache API
23 * \author Joshua Colp <jcolp@digium.com>
27 <support_level>core</support_level>
32 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
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"
41 * \brief Built-in cached signed linear 8kHz format.
43 struct ast_format *ast_format_slin;
46 * \brief Built-in cached signed linear 12kHz format.
48 struct ast_format *ast_format_slin12;
51 * \brief Built-in cached signed linear 16kHz format.
53 struct ast_format *ast_format_slin16;
56 * \brief Built-in cached signed linear 24kHz format.
58 struct ast_format *ast_format_slin24;
61 * \brief Built-in cached signed linear 32kHz format.
63 struct ast_format *ast_format_slin32;
66 * \brief Built-in cached signed linear 44kHz format.
68 struct ast_format *ast_format_slin44;
71 * \brief Built-in cached signed linear 48kHz format.
73 struct ast_format *ast_format_slin48;
76 * \brief Built-in cached signed linear 96kHz format.
78 struct ast_format *ast_format_slin96;
81 * \brief Built-in cached signed linear 192kHz format.
83 struct ast_format *ast_format_slin192;
86 * \brief Built-in cached ulaw format.
88 struct ast_format *ast_format_ulaw;
91 * \brief Built-in cached alaw format.
93 struct ast_format *ast_format_alaw;
96 * \brief Built-in cached testlaw format.
98 struct ast_format *ast_format_testlaw;
101 * \brief Built-in cached gsm format.
103 struct ast_format *ast_format_gsm;
106 * \brief Built-in cached adpcm format.
108 struct ast_format *ast_format_adpcm;
111 * \brief Built-in cached g722 format.
113 struct ast_format *ast_format_g722;
116 * \brief Built-in cached g726 format.
118 struct ast_format *ast_format_g726;
121 * \brief Built-in cached g726-aal2 format.
123 struct ast_format *ast_format_g726_aal2;
126 * \brief Built-in cached ilbc format.
128 struct ast_format *ast_format_ilbc;
131 * \brief Built-in cached ilbc format.
133 struct ast_format *ast_format_lpc10;
136 * \brief Built-in cached speex format.
138 struct ast_format *ast_format_speex;
141 * \brief Built-in cached speex at 16kHz format.
143 struct ast_format *ast_format_speex16;
146 * \brief Built-in cached speex at 32kHz format.
148 struct ast_format *ast_format_speex32;
151 * \brief Built-in cached g723.1 format.
153 struct ast_format *ast_format_g723;
156 * \brief Built-in cached g729 format.
158 struct ast_format *ast_format_g729;
161 * \brief Built-in cached g719 format.
163 struct ast_format *ast_format_g719;
166 * \brief Built-in cached h261 format.
168 struct ast_format *ast_format_h261;
171 * \brief Built-in cached h263 format.
173 struct ast_format *ast_format_h263;
176 * \brief Built-in cached h263 plus format.
178 struct ast_format *ast_format_h263p;
181 * \brief Built-in cached h264 format.
183 struct ast_format *ast_format_h264;
186 * \brief Built-in cached mp4 format.
188 struct ast_format *ast_format_mp4;
191 * \brief Built-in cached vp8 format.
193 struct ast_format *ast_format_vp8;
196 * \brief Built-in cached jpeg format.
198 struct ast_format *ast_format_jpeg;
201 * \brief Built-in cached png format.
203 struct ast_format *ast_format_png;
206 * \brief Built-in cached siren14 format.
208 struct ast_format *ast_format_siren14;
211 * \brief Built-in cached siren7 format.
213 struct ast_format *ast_format_siren7;
216 * \brief Built-in cached opus format.
218 struct ast_format *ast_format_opus;
221 * \brief Built-in cached t140 format.
223 struct ast_format *ast_format_t140;
226 * \brief Built-in cached t140 red format.
228 struct ast_format *ast_format_t140_red;
231 * \brief Built-in cached vp8 format.
233 struct ast_format *ast_format_vp8;
236 * \brief Built-in "null" format.
238 struct ast_format *ast_format_none;
240 /*! \brief Number of buckets to use for the media format cache (should be prime for performance reasons) */
241 #define CACHE_BUCKETS 53
243 /*! \brief Cached formats */
244 static struct ao2_container *formats;
246 static int format_hash_cb(const void *obj, int flags)
248 const struct ast_format *format;
251 switch (flags & OBJ_SEARCH_MASK) {
254 return ast_str_case_hash(key);
255 case OBJ_SEARCH_OBJECT:
257 return ast_str_case_hash(ast_format_get_name(format));
259 /* Hash can only work on something with a full key. */
265 static int format_cmp_cb(void *obj, void *arg, int flags)
267 const struct ast_format *left = obj;
268 const struct ast_format *right = arg;
269 const char *right_key = arg;
272 switch (flags & OBJ_SEARCH_MASK) {
273 case OBJ_SEARCH_OBJECT:
274 right_key = ast_format_get_name(right);
277 cmp = strcasecmp(ast_format_get_name(left), right_key);
279 case OBJ_SEARCH_PARTIAL_KEY:
280 cmp = strncasecmp(ast_format_get_name(left), right_key, strlen(right_key));
294 /*! \brief Function called when the process is shutting down */
295 static void format_cache_shutdown(void)
297 ao2_cleanup(formats);
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);
341 int ast_format_cache_init(void)
343 formats = ao2_container_alloc_options(AO2_ALLOC_OPT_LOCK_RWLOCK, CACHE_BUCKETS,
344 format_hash_cb, format_cmp_cb);
349 ast_register_atexit(format_cache_shutdown);
354 static void set_cached_format(const char *name, struct ast_format *format)
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);
437 int ast_format_cache_set(struct ast_format *format)
439 SCOPED_AO2WRLOCK(lock, formats);
440 struct ast_format *old_format;
442 ast_assert(format != NULL);
444 if (ast_strlen_zero(ast_format_get_name(format))) {
448 old_format = ao2_find(formats, ast_format_get_name(format), OBJ_SEARCH_KEY | OBJ_NOLOCK);
450 ao2_unlink_flags(formats, old_format, OBJ_NOLOCK);
452 ao2_link_flags(formats, format, OBJ_NOLOCK);
454 set_cached_format(ast_format_get_name(format), format);
456 ast_verb(2, "%s cached format with name '%s'\n",
457 old_format ? "Updated" : "Created",
458 ast_format_get_name(format));
460 ao2_cleanup(old_format);
465 struct ast_format *__ast_format_cache_get(const char *name)
467 if (ast_strlen_zero(name)) {
471 return ao2_find(formats, name, OBJ_SEARCH_KEY);
474 struct ast_format *__ast_format_cache_get_debug(const char *name, const char *tag, const char *file, int line, const char *func)
476 if (ast_strlen_zero(name)) {
480 return __ao2_find_debug(formats, name, OBJ_SEARCH_KEY, S_OR(tag, "ast_format_cache_get"), file, line, func);
483 struct ast_format *ast_format_cache_get_slin_by_rate(unsigned int rate)
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;
502 return ast_format_slin;
505 int ast_format_cache_is_slinear(struct ast_format *format)
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)) {