Asterisk - The Open Source Telephony Project GIT-master-f36a736
res_format_attr_silk.c
Go to the documentation of this file.
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 SILK 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 <ctype.h> /* for tolower */
33
34#include "asterisk/module.h"
35#include "asterisk/format.h"
36#include "asterisk/logger.h" /* for ast_log, LOG_WARNING */
37#include "asterisk/strings.h" /* for ast_str_append */
38#include "asterisk/utils.h" /* for MAX, MIN */
39
40/*!
41 * \brief SILK attribute structure.
42 *
43 * \note The only attribute that affects compatibility here is the sample rate.
44 */
45struct silk_attr {
46 unsigned int maxbitrate;
47 unsigned int dtx;
48 unsigned int fec;
50};
51
52static void silk_destroy(struct ast_format *format)
53{
54 struct silk_attr *attr = ast_format_get_attribute_data(format);
55
56 ast_free(attr);
57}
58
59static void attr_init(struct silk_attr *attr)
60{
61 memset(attr, 0, sizeof(*attr));
62}
63
64static int silk_clone(const struct ast_format *src, struct ast_format *dst)
65{
66 struct silk_attr *original = ast_format_get_attribute_data(src);
67 struct silk_attr *attr = ast_malloc(sizeof(*attr));
68
69 if (!attr) {
70 return -1;
71 }
72
73 if (original) {
74 *attr = *original;
75 } else {
76 attr_init(attr);
77 }
78
80
81 return 0;
82}
83
84static struct ast_format *silk_parse_sdp_fmtp(const struct ast_format *format, const char *attributes)
85{
86 char *attribs = ast_strdupa(attributes), *attrib;
87 struct ast_format *cloned;
88 struct silk_attr *attr;
89 unsigned int val;
90
91 cloned = ast_format_clone(format);
92 if (!cloned) {
93 return NULL;
94 }
95 attr = ast_format_get_attribute_data(cloned);
96
97 /* lower-case everything, so we are case-insensitive */
98 for (attrib = attribs; *attrib; ++attrib) {
99 *attrib = tolower(*attrib);
100 } /* based on channels/chan_sip.c:process_a_sdp_image() */
101
102 if (sscanf(attribs, "maxaveragebitrate=%30u", &val) == 1) {
103 attr->maxbitrate = val;
104 }
105 if (sscanf(attribs, "usedtx=%30u", &val) == 1) {
106 attr->dtx = val;
107 }
108 if (sscanf(attribs, "useinbandfec=%30u", &val) == 1) {
109 attr->fec = val;
110 }
111
112 return cloned;
113}
114
115static void silk_generate_sdp_fmtp(const struct ast_format *format, unsigned int payload, struct ast_str **str)
116{
117 struct silk_attr *attr = ast_format_get_attribute_data(format);
118
119 if (!attr) {
120 return;
121 }
122
123 if ((attr->maxbitrate > 5000) && (attr->maxbitrate < 40000)) {
124 ast_str_append(str, 0, "a=fmtp:%u maxaveragebitrate=%u\r\n", payload, attr->maxbitrate);
125 }
126
127 if (attr->dtx) {
128 ast_str_append(str, 0, "a=fmtp:%u usedtx=%u\r\n", payload, attr->dtx);
129 }
130 if (attr->fec) {
131 ast_str_append(str, 0, "a=fmtp:%u useinbandfec=%u\r\n", payload, attr->fec);
132 }
133}
134
135static enum ast_format_cmp_res silk_cmp(const struct ast_format *format1, const struct ast_format *format2)
136{
139 }
140
142}
143
144static struct ast_format *silk_getjoint(const struct ast_format *format1, const struct ast_format *format2)
145{
146 struct silk_attr *attr1 = ast_format_get_attribute_data(format1);
147 struct silk_attr *attr2 = ast_format_get_attribute_data(format2);
148 struct ast_format *jointformat;
149 struct silk_attr *attr_res;
150
152 return NULL;
153 }
154
155 jointformat = ast_format_clone(format1);
156 if (!jointformat) {
157 return NULL;
158 }
159 attr_res = ast_format_get_attribute_data(jointformat);
160
161 if (!attr1 || !attr2) {
162 attr_init(attr_res);
163 } else {
164 /* Take the lowest max bitrate */
165 attr_res->maxbitrate = MIN(attr1->maxbitrate, attr2->maxbitrate);
166
167 /* Only do dtx if both sides want it. DTX is a trade off between
168 * computational complexity and bandwidth. */
169 attr_res->dtx = attr1->dtx && attr2->dtx ? 1 : 0;
170
171 /* Only do FEC if both sides want it. If a peer specifically requests not
172 * to receive with FEC, it may be a waste of bandwidth. */
173 attr_res->fec = attr1->fec && attr2->fec ? 1 : 0;
174
175 /* Use the maximum packetloss percentage between the two attributes. This affects how
176 * much redundancy is used in the FEC. */
178 }
179
180 return jointformat;
181}
182
183static struct ast_format *silk_set(const struct ast_format *format, const char *name, const char *value)
184{
185 struct ast_format *cloned;
186 struct silk_attr *attr;
187 unsigned int val;
188
189 if (sscanf(value, "%30u", &val) != 1) {
190 ast_log(LOG_WARNING, "Unknown value '%s' for attribute type '%s'\n",
191 value, name);
192 return NULL;
193 }
194
195 cloned = ast_format_clone(format);
196 if (!cloned) {
197 return NULL;
198 }
199 attr = ast_format_get_attribute_data(cloned);
200
201 if (!strcasecmp(name, "max_bitrate")) {
202 attr->maxbitrate = val;
203 } else if (!strcasecmp(name, "dtx")) {
204 attr->dtx = val;
205 } else if (!strcasecmp(name, "fec")) {
206 attr->fec = val;
207 } else if (!strcasecmp(name, "packetloss_percentage")) {
209 } else {
210 ast_log(LOG_WARNING, "unknown attribute type %s\n", name);
211 }
212
213 return cloned;
214}
215
216static const void *silk_get(const struct ast_format *format, const char *name)
217{
218 struct silk_attr *attr = ast_format_get_attribute_data(format);
219 unsigned int *val;
220
221 if (!strcasecmp(name, "max_bitrate")) {
222 val = &attr->maxbitrate;
223 } else if (!strcasecmp(name, "dtx")) {
224 val = &attr->dtx;
225 } else if (!strcasecmp(name, "fec")) {
226 val = &attr->fec;
227 } else if (!strcasecmp(name, "packetloss_percentage")) {
228 val = &attr->packetloss_percentage;
229 } else {
230 ast_log(LOG_WARNING, "unknown attribute type %s\n", name);
231 return NULL;
232 }
233
234 return val;
235}
236
239 .format_clone = silk_clone,
240 .format_cmp = silk_cmp,
241 .format_get_joint = silk_getjoint,
242 .format_attribute_set = silk_set,
243 .format_attribute_get = silk_get,
244 .format_parse_sdp_fmtp = silk_parse_sdp_fmtp,
245 .format_generate_sdp_fmtp = silk_generate_sdp_fmtp,
246};
247
248static int load_module(void)
249{
252 }
253
255}
256
257static int unload_module(void)
258{
259 return 0;
260}
261
262AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, "SILK Format Attribute Module",
263 .support_level = AST_MODULE_SUPPORT_CORE,
264 .load = load_module,
265 .unload = unload_module,
266 .load_pri = AST_MODPRI_CHANNEL_DEPEND,
const char * str
Definition: app_jack.c:147
Asterisk main include file. File version handling, generic pbx functions.
#define ast_free(a)
Definition: astmm.h:180
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:298
#define ast_malloc(len)
A wrapper for malloc()
Definition: astmm.h:191
#define ast_log
Definition: astobj2.c:42
Media Format API.
void * ast_format_get_attribute_data(const struct ast_format *format)
Get the attribute data on a format.
Definition: format.c:125
unsigned int ast_format_get_sample_rate(const struct ast_format *format)
Get the sample rate of a media format.
Definition: format.c:379
void ast_format_set_attribute_data(struct ast_format *format, void *attribute_data)
Set the attribute data on a format.
Definition: format.c:130
ast_format_cmp_res
Format comparison results.
Definition: format.h:34
@ AST_FORMAT_CMP_EQUAL
Definition: format.h:36
@ AST_FORMAT_CMP_NOT_EQUAL
Definition: format.h:38
struct ast_format * ast_format_clone(const struct ast_format *format)
Clone an existing media format so it can be modified.
Definition: format.c:180
#define ast_format_interface_register(codec, interface)
Register a format interface for use with the provided codec.
Definition: format.h:273
static const char name[]
Definition: format_mp3.c:68
Support for logging to various files, console and syslog Configuration in file logger....
#define LOG_WARNING
Asterisk module definitions.
@ AST_MODFLAG_LOAD_ORDER
Definition: module.h:331
#define AST_MODULE_INFO(keystr, flags_to_set, desc, fields...)
Definition: module.h:557
@ AST_MODPRI_CHANNEL_DEPEND
Definition: module.h:340
@ AST_MODULE_SUPPORT_CORE
Definition: module.h:121
#define ASTERISK_GPL_KEY
The text the key() function should return.
Definition: module.h:46
@ AST_MODULE_LOAD_SUCCESS
Definition: module.h:70
@ AST_MODULE_LOAD_DECLINE
Module has failed to load, may be in an inconsistent state.
Definition: module.h:78
static struct ast_format * silk_parse_sdp_fmtp(const struct ast_format *format, const char *attributes)
static struct ast_format_interface silk_interface
static struct ast_format * silk_set(const struct ast_format *format, const char *name, const char *value)
static int silk_clone(const struct ast_format *src, struct ast_format *dst)
static struct ast_format * silk_getjoint(const struct ast_format *format1, const struct ast_format *format2)
static void silk_destroy(struct ast_format *format)
static const void * silk_get(const struct ast_format *format, const char *name)
static void attr_init(struct silk_attr *attr)
static int load_module(void)
static int unload_module(void)
static void silk_generate_sdp_fmtp(const struct ast_format *format, unsigned int payload, struct ast_str **str)
static enum ast_format_cmp_res silk_cmp(const struct ast_format *format1, const struct ast_format *format2)
#define NULL
Definition: resample.c:96
String manipulation functions.
int ast_str_append(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Append to a thread local dynamic string.
Definition: strings.h:1139
Optional format interface to extend format operations.
Definition: format.h:44
void(*const format_destroy)(struct ast_format *format)
Callback for when the format is destroyed, used to release attribute resources.
Definition: format.h:50
Definition of a media format.
Definition: format.c:43
Support for dynamic strings.
Definition: strings.h:623
SILK attribute structure.
unsigned int fec
unsigned int packetloss_percentage
unsigned int maxbitrate
unsigned int dtx
Definition: ast_expr2.c:325
int value
Definition: syslog.c:37
Utility functions.
#define MIN(a, b)
Definition: utils.h:231
#define MAX(a, b)
Definition: utils.h:233