format_cache.c

Go to the documentation of this file.
00001 /*
00002  * Asterisk -- An open source telephony toolkit.
00003  *
00004  * Copyright (C) 2014, Digium, Inc.
00005  *
00006  * Joshua Colp <jcolp@digium.com>
00007  *
00008  * See http://www.asterisk.org for more information about
00009  * the Asterisk project. Please do not directly contact
00010  * any of the maintainers of this project for assistance;
00011  * the project provides a web site, mailing lists and IRC
00012  * channels for your use.
00013  *
00014  * This program is free software, distributed under the terms of
00015  * the GNU General Public License Version 2. See the LICENSE file
00016  * at the top of the source tree.
00017  */
00018 
00019 /*! \file
00020  *
00021  * \brief Media Format Cache API
00022  *
00023  * \author Joshua Colp <jcolp@digium.com>
00024  */
00025 
00026 /*** MODULEINFO
00027    <support_level>core</support_level>
00028  ***/
00029 
00030 #include "asterisk.h"
00031 
00032 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 434383 $")
00033 
00034 #include "asterisk/logger.h"
00035 #include "asterisk/format.h"
00036 #include "asterisk/format_cache.h"
00037 #include "asterisk/astobj2.h"
00038 #include "asterisk/strings.h"
00039 
00040 /*!
00041  * \brief Built-in cached signed linear 8kHz format.
00042  */
00043 struct ast_format *ast_format_slin;
00044 
00045 /*!
00046  * \brief Built-in cached signed linear 12kHz format.
00047  */
00048 struct ast_format *ast_format_slin12;
00049 
00050 /*!
00051  * \brief Built-in cached signed linear 16kHz format.
00052  */
00053 struct ast_format *ast_format_slin16;
00054 
00055 /*!
00056  * \brief Built-in cached signed linear 24kHz format.
00057  */
00058 struct ast_format *ast_format_slin24;
00059 
00060 /*!
00061  * \brief Built-in cached signed linear 32kHz format.
00062  */
00063 struct ast_format *ast_format_slin32;
00064 
00065 /*!
00066  * \brief Built-in cached signed linear 44kHz format.
00067  */
00068 struct ast_format *ast_format_slin44;
00069 
00070 /*!
00071  * \brief Built-in cached signed linear 48kHz format.
00072  */
00073 struct ast_format *ast_format_slin48;
00074 
00075 /*!
00076  * \brief Built-in cached signed linear 96kHz format.
00077  */
00078 struct ast_format *ast_format_slin96;
00079 
00080 /*!
00081  * \brief Built-in cached signed linear 192kHz format.
00082  */
00083 struct ast_format *ast_format_slin192;
00084 
00085 /*!
00086  * \brief Built-in cached ulaw format.
00087  */
00088 struct ast_format *ast_format_ulaw;
00089 
00090 /*!
00091  * \brief Built-in cached alaw format.
00092  */
00093 struct ast_format *ast_format_alaw;
00094 
00095 /*!
00096  * \brief Built-in cached testlaw format.
00097  */
00098 struct ast_format *ast_format_testlaw;
00099 
00100 /*!
00101  * \brief Built-in cached gsm format.
00102  */
00103 struct ast_format *ast_format_gsm;
00104 
00105 /*!
00106  * \brief Built-in cached adpcm format.
00107  */
00108 struct ast_format *ast_format_adpcm;
00109 
00110 /*!
00111  * \brief Built-in cached g722 format.
00112  */
00113 struct ast_format *ast_format_g722;
00114 
00115 /*!
00116  * \brief Built-in cached g726 format.
00117  */
00118 struct ast_format *ast_format_g726;
00119 
00120 /*!
00121  * \brief Built-in cached g726-aal2 format.
00122  */
00123 struct ast_format *ast_format_g726_aal2;
00124 
00125 /*!
00126  * \brief Built-in cached ilbc format.
00127  */
00128 struct ast_format *ast_format_ilbc;
00129 
00130 /*!
00131  * \brief Built-in cached ilbc format.
00132  */
00133 struct ast_format *ast_format_lpc10;
00134 
00135 /*!
00136  * \brief Built-in cached speex format.
00137  */
00138 struct ast_format *ast_format_speex;
00139 
00140 /*!
00141  * \brief Built-in cached speex at 16kHz format.
00142  */
00143 struct ast_format *ast_format_speex16;
00144 
00145 /*!
00146  * \brief Built-in cached speex at 32kHz format.
00147  */
00148 struct ast_format *ast_format_speex32;
00149 
00150 /*!
00151  * \brief Built-in cached g723.1 format.
00152  */
00153 struct ast_format *ast_format_g723;
00154 
00155 /*!
00156  * \brief Built-in cached g729 format.
00157  */
00158 struct ast_format *ast_format_g729;
00159 
00160 /*!
00161  * \brief Built-in cached g719 format.
00162  */
00163 struct ast_format *ast_format_g719;
00164 
00165 /*!
00166  * \brief Built-in cached h261 format.
00167  */
00168 struct ast_format *ast_format_h261;
00169 
00170 /*!
00171  * \brief Built-in cached h263 format.
00172  */
00173 struct ast_format *ast_format_h263;
00174 
00175 /*!
00176  * \brief Built-in cached h263 plus format.
00177  */
00178 struct ast_format *ast_format_h263p;
00179 
00180 /*!
00181  * \brief Built-in cached h264 format.
00182  */
00183 struct ast_format *ast_format_h264;
00184 
00185 /*!
00186  * \brief Built-in cached mp4 format.
00187  */
00188 struct ast_format *ast_format_mp4;
00189 
00190 /*!
00191  * \brief Built-in cached vp8 format.
00192  */
00193 struct ast_format *ast_format_vp8;
00194 
00195 /*!
00196  * \brief Built-in cached jpeg format.
00197  */
00198 struct ast_format *ast_format_jpeg;
00199 
00200 /*!
00201  * \brief Built-in cached png format.
00202  */
00203 struct ast_format *ast_format_png;
00204 
00205 /*!
00206  * \brief Built-in cached siren14 format.
00207  */
00208 struct ast_format *ast_format_siren14;
00209 
00210 /*!
00211  * \brief Built-in cached siren7 format.
00212  */
00213 struct ast_format *ast_format_siren7;
00214 
00215 /*!
00216  * \brief Built-in cached opus format.
00217  */
00218 struct ast_format *ast_format_opus;
00219 
00220 /*!
00221  * \brief Built-in cached t140 format.
00222  */
00223 struct ast_format *ast_format_t140;
00224 
00225 /*!
00226  * \brief Built-in cached t140 red format.
00227  */
00228 struct ast_format *ast_format_t140_red;
00229 
00230 /*!
00231  * \brief Built-in "null" format.
00232  */
00233 struct ast_format *ast_format_none;
00234 
00235 /*! \brief Number of buckets to use for the media format cache (should be prime for performance reasons) */
00236 #define CACHE_BUCKETS 53
00237 
00238 /*! \brief Cached formats */
00239 static struct ao2_container *formats;
00240 
00241 static int format_hash_cb(const void *obj, int flags)
00242 {
00243    const struct ast_format *format;
00244    const char *key;
00245 
00246    switch (flags & OBJ_SEARCH_MASK) {
00247    case OBJ_SEARCH_KEY:
00248       key = obj;
00249       return ast_str_case_hash(key);
00250    case OBJ_SEARCH_OBJECT:
00251       format = obj;
00252       return ast_str_case_hash(ast_format_get_name(format));
00253    default:
00254       /* Hash can only work on something with a full key. */
00255       ast_assert(0);
00256       return 0;
00257    }
00258 }
00259 
00260 static int format_cmp_cb(void *obj, void *arg, int flags)
00261 {
00262    const struct ast_format *left = obj;
00263    const struct ast_format *right = arg;
00264    const char *right_key = arg;
00265    int cmp;
00266 
00267    switch (flags & OBJ_SEARCH_MASK) {
00268    case OBJ_SEARCH_OBJECT:
00269       right_key = ast_format_get_name(right);
00270       /* Fall through */
00271    case OBJ_SEARCH_KEY:
00272       cmp = strcasecmp(ast_format_get_name(left), right_key);
00273       break;
00274    case OBJ_SEARCH_PARTIAL_KEY:
00275       cmp = strncasecmp(ast_format_get_name(left), right_key, strlen(right_key));
00276       break;
00277    default:
00278       ast_assert(0);
00279       cmp = 0;
00280       break;
00281    }
00282    if (cmp) {
00283       return 0;
00284    }
00285 
00286    return CMP_MATCH;
00287 }
00288 
00289 /*! \brief Function called when the process is shutting down */
00290 static void format_cache_shutdown(void)
00291 {
00292    ao2_cleanup(formats);
00293    formats = NULL;
00294 
00295    ao2_replace(ast_format_g723, NULL);
00296    ao2_replace(ast_format_ulaw, NULL);
00297    ao2_replace(ast_format_alaw, NULL);
00298    ao2_replace(ast_format_gsm, NULL);
00299    ao2_replace(ast_format_g726, NULL);
00300    ao2_replace(ast_format_g726_aal2, NULL);
00301    ao2_replace(ast_format_adpcm, NULL);
00302    ao2_replace(ast_format_slin, NULL);
00303    ao2_replace(ast_format_slin12, NULL);
00304    ao2_replace(ast_format_slin16, NULL);
00305    ao2_replace(ast_format_slin24, NULL);
00306    ao2_replace(ast_format_slin32, NULL);
00307    ao2_replace(ast_format_slin44, NULL);
00308    ao2_replace(ast_format_slin48, NULL);
00309    ao2_replace(ast_format_slin96, NULL);
00310    ao2_replace(ast_format_slin192, NULL);
00311    ao2_replace(ast_format_lpc10, NULL);
00312    ao2_replace(ast_format_g729, NULL);
00313    ao2_replace(ast_format_speex, NULL);
00314    ao2_replace(ast_format_speex16, NULL);
00315    ao2_replace(ast_format_speex32, NULL);
00316    ao2_replace(ast_format_ilbc, NULL);
00317    ao2_replace(ast_format_g722, NULL);
00318    ao2_replace(ast_format_siren7, NULL);
00319    ao2_replace(ast_format_siren14, NULL);
00320    ao2_replace(ast_format_testlaw, NULL);
00321    ao2_replace(ast_format_g719, NULL);
00322    ao2_replace(ast_format_opus, NULL);
00323    ao2_replace(ast_format_jpeg, NULL);
00324    ao2_replace(ast_format_png, NULL);
00325    ao2_replace(ast_format_h261, NULL);
00326    ao2_replace(ast_format_h263, NULL);
00327    ao2_replace(ast_format_h263p, NULL);
00328    ao2_replace(ast_format_h264, NULL);
00329    ao2_replace(ast_format_mp4, NULL);
00330    ao2_replace(ast_format_vp8, NULL);
00331    ao2_replace(ast_format_t140_red, NULL);
00332    ao2_replace(ast_format_t140, NULL);
00333    ao2_replace(ast_format_none, NULL);
00334 }
00335 
00336 int ast_format_cache_init(void)
00337 {
00338    formats = ao2_container_alloc_options(AO2_ALLOC_OPT_LOCK_RWLOCK, CACHE_BUCKETS,
00339       format_hash_cb, format_cmp_cb);
00340    if (!formats) {
00341       return -1;
00342    }
00343 
00344    ast_register_cleanup(format_cache_shutdown);
00345 
00346    return 0;
00347 }
00348 
00349 static void set_cached_format(const char *name, struct ast_format *format)
00350 {
00351    if (!strcmp(name, "g723")) {
00352       ao2_replace(ast_format_g723, format);
00353    } else if (!strcmp(name, "ulaw")) {
00354       ao2_replace(ast_format_ulaw, format);
00355    } else if (!strcmp(name, "alaw")) {
00356       ao2_replace(ast_format_alaw, format);
00357    } else if (!strcmp(name, "gsm")) {
00358       ao2_replace(ast_format_gsm, format);
00359    } else if (!strcmp(name, "g726")) {
00360       ao2_replace(ast_format_g726, format);
00361    } else if (!strcmp(name, "g726aal2")) {
00362       ao2_replace(ast_format_g726_aal2, format);
00363    } else if (!strcmp(name, "adpcm")) {
00364       ao2_replace(ast_format_adpcm, format);
00365    } else if (!strcmp(name, "slin")) {
00366       ao2_replace(ast_format_slin, format);
00367    } else if (!strcmp(name, "slin12")) {
00368       ao2_replace(ast_format_slin12, format);
00369    } else if (!strcmp(name, "slin16")) {
00370       ao2_replace(ast_format_slin16, format);
00371    } else if (!strcmp(name, "slin24")) {
00372       ao2_replace(ast_format_slin24, format);
00373    } else if (!strcmp(name, "slin32")) {
00374       ao2_replace(ast_format_slin32, format);
00375    } else if (!strcmp(name, "slin44")) {
00376       ao2_replace(ast_format_slin44, format);
00377    } else if (!strcmp(name, "slin48")) {
00378       ao2_replace(ast_format_slin48, format);
00379    } else if (!strcmp(name, "slin96")) {
00380       ao2_replace(ast_format_slin96, format);
00381    } else if (!strcmp(name, "slin192")) {
00382       ao2_replace(ast_format_slin192, format);
00383    } else if (!strcmp(name, "lpc10")) {
00384       ao2_replace(ast_format_lpc10, format);
00385    } else if (!strcmp(name, "g729")) {
00386       ao2_replace(ast_format_g729, format);
00387    } else if (!strcmp(name, "speex")) {
00388       ao2_replace(ast_format_speex, format);
00389    } else if (!strcmp(name, "speex16")) {
00390       ao2_replace(ast_format_speex16, format);
00391    } else if (!strcmp(name, "speex32")) {
00392       ao2_replace(ast_format_speex32, format);
00393    } else if (!strcmp(name, "ilbc")) {
00394       ao2_replace(ast_format_ilbc, format);
00395    } else if (!strcmp(name, "g722")) {
00396       ao2_replace(ast_format_g722, format);
00397    } else if (!strcmp(name, "siren7")) {
00398       ao2_replace(ast_format_siren7, format);
00399    } else if (!strcmp(name, "siren14")) {
00400       ao2_replace(ast_format_siren14, format);
00401    } else if (!strcmp(name, "testlaw")) {
00402       ao2_replace(ast_format_testlaw, format);
00403    } else if (!strcmp(name, "g719")) {
00404       ao2_replace(ast_format_g719, format);
00405    } else if (!strcmp(name, "opus")) {
00406       ao2_replace(ast_format_opus, format);
00407    } else if (!strcmp(name, "jpeg")) {
00408       ao2_replace(ast_format_jpeg, format);
00409    } else if (!strcmp(name, "png")) {
00410       ao2_replace(ast_format_png, format);
00411    } else if (!strcmp(name, "h261")) {
00412       ao2_replace(ast_format_h261, format);
00413    } else if (!strcmp(name, "h263")) {
00414       ao2_replace(ast_format_h263, format);
00415    } else if (!strcmp(name, "h263p")) {
00416       ao2_replace(ast_format_h263p, format);
00417    } else if (!strcmp(name, "h264")) {
00418       ao2_replace(ast_format_h264, format);
00419    } else if (!strcmp(name, "mpeg4")) {
00420       ao2_replace(ast_format_mp4, format);
00421    } else if (!strcmp(name, "vp8")) {
00422       ao2_replace(ast_format_vp8, format);
00423    } else if (!strcmp(name, "red")) {
00424       ao2_replace(ast_format_t140_red, format);
00425    } else if (!strcmp(name, "t140")) {
00426       ao2_replace(ast_format_t140, format);
00427    } else if (!strcmp(name, "none")) {
00428       ao2_replace(ast_format_none, format);
00429    }
00430 }
00431 
00432 int ast_format_cache_set(struct ast_format *format)
00433 {
00434    SCOPED_AO2WRLOCK(lock, formats);
00435    struct ast_format *old_format;
00436 
00437    ast_assert(format != NULL);
00438 
00439    if (ast_strlen_zero(ast_format_get_name(format))) {
00440       return -1;
00441    }
00442 
00443    old_format = ao2_find(formats, ast_format_get_name(format), OBJ_SEARCH_KEY | OBJ_NOLOCK);
00444    if (old_format) {
00445       ao2_unlink_flags(formats, old_format, OBJ_NOLOCK);
00446    }
00447    ao2_link_flags(formats, format, OBJ_NOLOCK);
00448 
00449    set_cached_format(ast_format_get_name(format), format);
00450 
00451    ast_verb(2, "%s cached format with name '%s'\n",
00452       old_format ? "Updated" : "Created",
00453       ast_format_get_name(format));
00454 
00455    ao2_cleanup(old_format);
00456 
00457    return 0;
00458 }
00459 
00460 struct ast_format *__ast_format_cache_get(const char *name)
00461 {
00462    if (ast_strlen_zero(name)) {
00463       return NULL;
00464    }
00465 
00466    return ao2_find(formats, name, OBJ_SEARCH_KEY);
00467 }
00468 
00469 struct ast_format *__ast_format_cache_get_debug(const char *name, const char *tag, const char *file, int line, const char *func)
00470 {
00471    if (ast_strlen_zero(name)) {
00472       return NULL;
00473    }
00474 
00475    return __ao2_find_debug(formats, name, OBJ_SEARCH_KEY, S_OR(tag, "ast_format_cache_get"), file, line, func);
00476 }
00477 
00478 struct ast_format *ast_format_cache_get_slin_by_rate(unsigned int rate)
00479 {
00480    if (rate >= 192000) {
00481       return ast_format_slin192;
00482    } else if (rate >= 96000) {
00483       return ast_format_slin96;
00484    } else if (rate >= 48000) {
00485       return ast_format_slin48;
00486    } else if (rate >= 44100) {
00487       return ast_format_slin44;
00488    } else if (rate >= 32000) {
00489       return ast_format_slin32;
00490    } else if (rate >= 24000) {
00491       return ast_format_slin24;
00492    } else if (rate >= 16000) {
00493       return ast_format_slin16;
00494    } else if (rate >= 12000) {
00495       return ast_format_slin12;
00496    }
00497    return ast_format_slin;
00498 }
00499 
00500 int ast_format_cache_is_slinear(struct ast_format *format)
00501 {
00502    if ((ast_format_cmp(format, ast_format_slin) == AST_FORMAT_CMP_EQUAL)
00503       || (ast_format_cmp(format, ast_format_slin12) == AST_FORMAT_CMP_EQUAL)
00504       || (ast_format_cmp(format, ast_format_slin16) == AST_FORMAT_CMP_EQUAL)
00505       || (ast_format_cmp(format, ast_format_slin24) == AST_FORMAT_CMP_EQUAL)
00506       || (ast_format_cmp(format, ast_format_slin32) == AST_FORMAT_CMP_EQUAL)
00507       || (ast_format_cmp(format, ast_format_slin44) == AST_FORMAT_CMP_EQUAL)
00508       || (ast_format_cmp(format, ast_format_slin48) == AST_FORMAT_CMP_EQUAL)
00509       || (ast_format_cmp(format, ast_format_slin96) == AST_FORMAT_CMP_EQUAL)
00510       || (ast_format_cmp(format, ast_format_slin192) == AST_FORMAT_CMP_EQUAL)) {
00511       return 1;
00512    }
00513 
00514    return 0;
00515 }
00516 

Generated on Thu Apr 16 06:27:34 2015 for Asterisk - The Open Source Telephony Project by  doxygen 1.5.6