build: Update config.guess and config.sub
[asterisk/asterisk.git] / res / res_format_attr_celt.c
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 2011, Digium, Inc.
5  *
6  * David Vossel <dvossel@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 /*!
20  * \file
21  * \brief CELT format attribute interface
22  *
23  * \author David Vossel <dvossel@digium.com>
24  */
25
26 /*** MODULEINFO
27         <support_level>core</support_level>
28  ***/
29
30 #include "asterisk.h"
31
32 #include "asterisk/module.h"
33 #include "asterisk/format.h"
34
35 /*!
36  * \brief CELT attribute structure.
37  *
38  * \note The only attribute that affects compatibility here is the sample rate.
39  */
40 struct celt_attr {
41         unsigned int samplerate;
42         unsigned int maxbitrate;
43         unsigned int framesize;
44 };
45
46 static void celt_destroy(struct ast_format *format)
47 {
48         struct celt_attr *attr = ast_format_get_attribute_data(format);
49
50         ast_free(attr);
51 }
52
53 static int celt_clone(const struct ast_format *src, struct ast_format *dst)
54 {
55         struct celt_attr *original = ast_format_get_attribute_data(src);
56         struct celt_attr *attr = ast_calloc(1, sizeof(*attr));
57
58         if (!attr) {
59                 return -1;
60         }
61
62         if (original) {
63                 *attr = *original;
64         }
65
66         ast_format_set_attribute_data(dst, attr);
67
68         return 0;
69 }
70
71 static struct ast_format *celt_parse_sdp_fmtp(const struct ast_format *format, const char *attributes)
72 {
73         struct ast_format *cloned;
74         struct celt_attr *attr;
75         unsigned int val;
76
77         cloned = ast_format_clone(format);
78         if (!cloned) {
79                 return NULL;
80         }
81         attr = ast_format_get_attribute_data(cloned);
82
83         if (sscanf(attributes, "framesize=%30u", &val) == 1) {
84                 attr->framesize = val;
85         }
86
87         return cloned;
88 }
89
90 static void celt_generate_sdp_fmtp(const struct ast_format *format, unsigned int payload, struct ast_str **str)
91 {
92         struct celt_attr *attr = ast_format_get_attribute_data(format);
93
94         if (!attr || !attr->framesize) {
95                 return;
96         }
97
98         ast_str_append(str, 0, "a=fmtp:%u framesize=%u\r\n", payload, attr->framesize);
99 }
100
101 static enum ast_format_cmp_res celt_cmp(const struct ast_format *format1, const struct ast_format *format2)
102 {
103         struct celt_attr *attr1 = ast_format_get_attribute_data(format1);
104         struct celt_attr *attr2 = ast_format_get_attribute_data(format2);
105
106         if (((!attr1 || !attr1->samplerate) && (!attr2 || !attr2->samplerate)) ||
107                 (attr1->samplerate == attr2->samplerate)) {
108                 return AST_FORMAT_CMP_EQUAL;
109         }
110
111         return AST_FORMAT_CMP_NOT_EQUAL;
112 }
113
114 static struct ast_format *celt_getjoint(const struct ast_format *format1, const struct ast_format *format2)
115 {
116         struct celt_attr *attr1 = ast_format_get_attribute_data(format1);
117         struct celt_attr *attr2 = ast_format_get_attribute_data(format2);
118         struct ast_format *jointformat;
119         struct celt_attr *jointattr;
120
121         if (attr1 && attr2 && (attr1->samplerate != attr2->samplerate)) {
122                 return NULL;
123         }
124
125         jointformat = ast_format_clone(format1);
126         if (!jointformat) {
127                 return NULL;
128         }
129         jointattr = ast_format_get_attribute_data(jointformat);
130
131         /* either would work, they are guaranteed the same at this point. */
132         jointattr->samplerate = attr1->samplerate;
133         /* Take the lowest max bitrate */
134         jointattr->maxbitrate = MIN(attr1->maxbitrate, attr2->maxbitrate);
135
136         jointattr->framesize = attr2->framesize; /* TODO figure out what joint framesize means */
137
138         return jointformat;
139 }
140
141 static struct ast_format *celt_set(const struct ast_format *format, const char *name, const char *value)
142 {
143         struct ast_format *cloned;
144         struct celt_attr *attr;
145         unsigned int val;
146
147         cloned = ast_format_clone(format);
148         if (!cloned) {
149                 return NULL;
150         }
151         attr = ast_format_get_attribute_data(cloned);
152
153         if (sscanf(value, "%30u", &val) != 1) {
154                 ast_log(LOG_WARNING, "Unknown value '%s' for attribute type '%s'\n",
155                         value, name);
156                 ao2_ref(cloned, -1);
157                 return NULL;
158         }
159
160         if (!strcasecmp(name, "sample_rate")) {
161                 attr->samplerate = val;
162         } else if (!strcasecmp(name, "max_bitrate")) {
163                 attr->maxbitrate = val;
164         } else if (!strcasecmp(name, "frame_size")) {
165                 attr->framesize = val;
166         } else {
167                 ast_log(LOG_WARNING, "Unknown attribute type '%s'\n", name);
168                 ao2_ref(cloned, -1);
169                 return NULL;
170         }
171
172         return cloned;
173 }
174
175 static struct ast_format_interface celt_interface = {
176         .format_destroy = celt_destroy,
177         .format_clone = celt_clone,
178         .format_cmp = celt_cmp,
179         .format_get_joint = celt_getjoint,
180         .format_attribute_set = celt_set,
181         .format_parse_sdp_fmtp = celt_parse_sdp_fmtp,
182         .format_generate_sdp_fmtp = celt_generate_sdp_fmtp,
183 };
184
185 static int load_module(void)
186 {
187         if (ast_format_interface_register("celt", &celt_interface)) {
188                 return AST_MODULE_LOAD_DECLINE;
189         }
190
191         return AST_MODULE_LOAD_SUCCESS;
192 }
193
194 static int unload_module(void)
195 {
196         return 0;
197 }
198
199 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, "CELT Format Attribute Module",
200         .support_level = AST_MODULE_SUPPORT_CORE,
201         .load = load_module,
202         .unload = unload_module,
203         .load_pri = AST_MODPRI_CHANNEL_DEPEND,
204 );