format.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 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: 434047 $")
00033 
00034 #include "asterisk/logger.h"
00035 #include "asterisk/codec.h"
00036 #include "asterisk/format.h"
00037 #include "asterisk/astobj2.h"
00038 #include "asterisk/strings.h"
00039 
00040 /*! \brief Number of buckets to use for format interfaces (should be prime for performance reasons) */
00041 #define FORMAT_INTERFACE_BUCKETS 53
00042 
00043 /*! \brief Definition of a media format */
00044 struct ast_format {
00045    /*! Name of the format */
00046    const char *name;
00047    /*! \brief Pointer to the codec in use for this format */
00048    struct ast_codec *codec;
00049    /*! \brief Attribute specific data, implementation specific */
00050    void *attribute_data;
00051    /*! \brief Pointer to the optional format interface */
00052    const struct ast_format_interface *interface;
00053 };
00054 
00055 /*! \brief Structure used when registering a format interface */
00056 struct format_interface {
00057    /*! \brief Pointer to the format interface itself */
00058    const struct ast_format_interface *interface;
00059    /*! \brief Name of the codec the interface is for */
00060    char codec[0];
00061 };
00062 
00063 /*! \brief Container for registered format interfaces */
00064 static struct ao2_container *interfaces;
00065 
00066 static int format_interface_hash(const void *obj, int flags)
00067 {
00068    const struct format_interface *format_interface;
00069    const char *key;
00070 
00071    switch (flags & OBJ_SEARCH_MASK) {
00072    case OBJ_SEARCH_KEY:
00073       key = obj;
00074       return ast_str_hash(key);
00075    case OBJ_SEARCH_OBJECT:
00076       format_interface = obj;
00077       return ast_str_hash(format_interface->codec);
00078    default:
00079       /* Hash can only work on something with a full key. */
00080       ast_assert(0);
00081       return 0;
00082    }
00083 }
00084 
00085 static int format_interface_cmp(void *obj, void *arg, int flags)
00086 {
00087    const struct format_interface *left = obj;
00088    const struct format_interface *right = arg;
00089    const char *right_key = arg;
00090    int cmp;
00091 
00092    switch (flags & OBJ_SEARCH_MASK) {
00093    case OBJ_SEARCH_OBJECT:
00094       cmp = strcmp(left->codec, right->codec);
00095       break;
00096    case OBJ_SEARCH_KEY:
00097       cmp = strcmp(left->codec, right_key);
00098       break;
00099    case OBJ_SEARCH_PARTIAL_KEY:
00100       cmp = strncmp(left->codec, right_key, strlen(right_key));
00101       break;
00102    default:
00103       ast_assert(0);
00104       cmp = 0;
00105       break;
00106    }
00107    if (cmp) {
00108       return 0;
00109    }
00110 
00111    return CMP_MATCH;
00112 }
00113 
00114 /*! \brief Function called when the process is shutting down */
00115 static void format_shutdown(void)
00116 {
00117    ao2_cleanup(interfaces);
00118    interfaces = NULL;
00119 }
00120 
00121 int ast_format_init(void)
00122 {
00123    interfaces = ao2_container_alloc_options(AO2_ALLOC_OPT_LOCK_RWLOCK, FORMAT_INTERFACE_BUCKETS, format_interface_hash,
00124       format_interface_cmp);
00125    if (!interfaces) {
00126       return -1;
00127    }
00128 
00129    ast_register_cleanup(format_shutdown);
00130 
00131    return 0;
00132 }
00133 
00134 int __ast_format_interface_register(const char *codec, const struct ast_format_interface *interface, struct ast_module *mod)
00135 {
00136    SCOPED_AO2WRLOCK(lock, interfaces);
00137    struct format_interface *format_interface;
00138 
00139    if (!interface->format_clone || !interface->format_destroy) {
00140       ast_log(LOG_ERROR, "Format interface for codec '%s' does not implement required callbacks\n", codec);
00141       return -1;
00142    }
00143 
00144    format_interface = ao2_find(interfaces, codec, OBJ_SEARCH_KEY | OBJ_NOLOCK);
00145    if (format_interface) {
00146       ast_log(LOG_ERROR, "A format interface is already present for codec '%s'\n", codec);
00147       ao2_ref(format_interface, -1);
00148       return -1;
00149    }
00150 
00151    format_interface = ao2_alloc_options(sizeof(*format_interface) + strlen(codec) + 1,
00152       NULL, AO2_ALLOC_OPT_LOCK_NOLOCK);
00153    if (!format_interface) {
00154       return -1;
00155    }
00156    format_interface->interface = interface;
00157    strcpy(format_interface->codec, codec); /* Safe */
00158 
00159    ao2_link_flags(interfaces, format_interface, OBJ_NOLOCK);
00160    ao2_ref(format_interface, -1);
00161 
00162    ast_verb(2, "Registered format interface for codec '%s'\n", codec);
00163 
00164    return 0;
00165 }
00166 
00167 void *ast_format_get_attribute_data(const struct ast_format *format)
00168 {
00169    return format->attribute_data;
00170 }
00171 
00172 void ast_format_set_attribute_data(struct ast_format *format, void *attribute_data)
00173 {
00174    format->attribute_data = attribute_data;
00175 }
00176 
00177 /*! \brief Destructor for media formats */
00178 static void format_destroy(void *obj)
00179 {
00180    struct ast_format *format = obj;
00181 
00182    if (format->interface) {
00183       format->interface->format_destroy(format);
00184    }
00185 
00186    ao2_cleanup(format->codec);
00187 }
00188 
00189 struct ast_format *ast_format_create_named(const char *format_name, struct ast_codec *codec)
00190 {
00191    struct ast_format *format;
00192    struct format_interface *format_interface;
00193 
00194    format = ao2_t_alloc_options(sizeof(*format), format_destroy,
00195       AO2_ALLOC_OPT_LOCK_NOLOCK, S_OR(codec->description, ""));
00196    if (!format) {
00197       return NULL;
00198    }
00199    format->name = format_name;
00200    format->codec = ao2_bump(codec);
00201 
00202    format_interface = ao2_find(interfaces, codec->name, OBJ_SEARCH_KEY);
00203    if (format_interface) {
00204       format->interface = format_interface->interface;
00205       ao2_ref(format_interface, -1);
00206    }
00207 
00208    return format;
00209 }
00210 
00211 struct ast_format *ast_format_clone(const struct ast_format *format)
00212 {
00213    struct ast_format *cloned = ast_format_create_named(format->name, format->codec);
00214 
00215    if (!cloned) {
00216       return NULL;
00217    }
00218 
00219    if (cloned->interface && cloned->interface->format_clone(format, cloned)) {
00220       ao2_ref(cloned, -1);
00221       return NULL;
00222    }
00223 
00224    return cloned;
00225 }
00226 
00227 struct ast_format *ast_format_create(struct ast_codec *codec)
00228 {
00229    return ast_format_create_named(codec->name, codec);
00230 }
00231 
00232 enum ast_format_cmp_res ast_format_cmp(const struct ast_format *format1, const struct ast_format *format2)
00233 {
00234    const struct ast_format_interface *interface;
00235 
00236    if (format1 == NULL || format2 == NULL) {
00237       return AST_FORMAT_CMP_NOT_EQUAL;
00238    }
00239 
00240    if (format1 == format2) {
00241       return AST_FORMAT_CMP_EQUAL;
00242    }
00243 
00244    if (format1->codec != format2->codec) {
00245       return AST_FORMAT_CMP_NOT_EQUAL;
00246    }
00247 
00248    interface = format1->interface ? format1->interface : format2->interface;
00249 
00250    if (interface && interface->format_cmp) {
00251       return interface->format_cmp(format1, format2);
00252    }
00253 
00254    return AST_FORMAT_CMP_EQUAL;
00255 }
00256 
00257 struct ast_format *ast_format_joint(const struct ast_format *format1, const struct ast_format *format2)
00258 {
00259    const struct ast_format_interface *interface;
00260 
00261    if (format1->codec != format2->codec) {
00262       return NULL;
00263    }
00264 
00265    /* If the two formats are the same structure OR if the codec is the same and no attributes
00266     * exist we can immediately return a format with reference count bumped up, since they are
00267     * the same.
00268     */
00269    if ((ast_format_cmp(format1, format2) == AST_FORMAT_CMP_EQUAL && !format1->attribute_data && !format2->attribute_data)) {
00270       return ao2_bump((struct ast_format*)format1);
00271    }
00272 
00273    interface = format1->interface ? format1->interface : format2->interface;
00274 
00275    /* If there is attribute data on either there has to be an interface */
00276    return interface->format_get_joint(format1, format2);
00277 }
00278 
00279 struct ast_format *ast_format_attribute_set(const struct ast_format *format, const char *name, const char *value)
00280 {
00281    const struct ast_format_interface *interface = format->interface;
00282 
00283    if (!interface) {
00284       struct format_interface *format_interface = ao2_find(interfaces, format->codec->name, OBJ_SEARCH_KEY);
00285       if (format_interface) {
00286          interface = format_interface->interface;
00287          ao2_ref(format_interface, -1);
00288       }
00289    }
00290 
00291    if (!interface || !interface->format_attribute_set) {
00292       return ao2_bump((struct ast_format*)format);
00293    }
00294 
00295    return interface->format_attribute_set(format, name, value);
00296 }
00297 
00298 struct ast_format *ast_format_parse_sdp_fmtp(const struct ast_format *format, const char *attributes)
00299 {
00300    const struct ast_format_interface *interface = format->interface;
00301 
00302    if (!interface) {
00303       struct format_interface *format_interface = ao2_find(interfaces, format->codec->name, OBJ_SEARCH_KEY);
00304       if (format_interface) {
00305          interface = format_interface->interface;
00306          ao2_ref(format_interface, -1);
00307       }
00308    }
00309 
00310    if (!interface || !interface->format_parse_sdp_fmtp) {
00311       return ao2_bump((struct ast_format*)format);
00312    }
00313 
00314    return interface->format_parse_sdp_fmtp(format, attributes);
00315 }
00316 
00317 void ast_format_generate_sdp_fmtp(const struct ast_format *format, unsigned int payload, struct ast_str **str)
00318 {
00319    if (!format->interface || !format->interface->format_generate_sdp_fmtp) {
00320       return;
00321    }
00322 
00323    format->interface->format_generate_sdp_fmtp(format, payload, str);
00324 }
00325 
00326 struct ast_codec *ast_format_get_codec(const struct ast_format *format)
00327 {
00328    return ao2_bump(format->codec);
00329 }
00330 
00331 unsigned int ast_format_get_codec_id(const struct ast_format *format)
00332 {
00333    return format->codec->id;
00334 }
00335 
00336 const char *ast_format_get_name(const struct ast_format *format)
00337 {
00338    return format->name;
00339 }
00340 
00341 const char *ast_format_get_codec_name(const struct ast_format *format)
00342 {
00343    return format->codec->name;
00344 }
00345 
00346 int ast_format_can_be_smoothed(const struct ast_format *format)
00347 {
00348    return format->codec->smooth;
00349 }
00350 
00351 enum ast_media_type ast_format_get_type(const struct ast_format *format)
00352 {
00353    return format->codec->type;
00354 }
00355 
00356 unsigned int ast_format_get_default_ms(const struct ast_format *format)
00357 {
00358    return format->codec->default_ms;
00359 }
00360 
00361 unsigned int ast_format_get_minimum_ms(const struct ast_format *format)
00362 {
00363    return format->codec->minimum_ms;
00364 }
00365 
00366 unsigned int ast_format_get_maximum_ms(const struct ast_format *format)
00367 {
00368    return format->codec->maximum_ms;
00369 }
00370 
00371 unsigned int ast_format_get_minimum_bytes(const struct ast_format *format)
00372 {
00373    return format->codec->minimum_bytes;
00374 }
00375 
00376 unsigned int ast_format_get_sample_rate(const struct ast_format *format)
00377 {
00378    return format->codec->sample_rate ?: 8000;
00379 }
00380 
00381 unsigned int ast_format_determine_length(const struct ast_format *format, unsigned int samples)
00382 {
00383    return ast_codec_determine_length(format->codec, samples);
00384 }

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