Asterisk - The Open Source Telephony Project GIT-master-7e7a603
codec_pref.c
Go to the documentation of this file.
1/*
2 * Asterisk -- An open source telephony toolkit.
3 *
4 * Copyright (C) 2014, Digium, Inc.
5 *
6 * Joshua Colp <jcolp@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/*! \file
20 *
21 * \brief Media Format Bitfield Compatibility API
22 *
23 * \author Joshua Colp <jcolp@digium.com>
24 */
25
26/*** MODULEINFO
27 <support_level>core</support_level>
28 ***/
29
30#include "asterisk.h"
31
32#include "asterisk/logger.h"
33#include "asterisk/astobj2.h"
34#include "asterisk/codec.h"
35#include "asterisk/format.h"
38#include "asterisk/format_cap.h"
39#include "asterisk/utils.h"
40
41#include "include/codec_pref.h"
43
44void iax2_codec_pref_convert(struct iax2_codec_pref *pref, char *buf, size_t size, int right)
45{
46 static int differential = (int) 'A';
47 int x;
48
49 if (right) {
50 --size;/* Save room for the nul string terminator. */
51 for (x = 0; x < ARRAY_LEN(pref->order) && x < size; ++x) {
52 if (!pref->order[x]) {
53 break;
54 }
55
56 buf[x] = pref->order[x] + differential;
57 }
58
59 buf[x] = '\0';
60 } else {
61 for (x = 0; x < ARRAY_LEN(pref->order) && x < size; ++x) {
62 if (buf[x] == '\0') {
63 break;
64 }
65
66 pref->order[x] = buf[x] - differential;
67 pref->framing[x] = 0;
68 }
69
70 if (x < ARRAY_LEN(pref->order)) {
71 pref->order[x] = 0;
72 pref->framing[x] = 0;
73 }
74 }
75}
76
77struct ast_format *iax2_codec_pref_index(struct iax2_codec_pref *pref, int idx, struct ast_format **result)
78{
79 if (0 <= idx && idx < ARRAY_LEN(pref->order) && pref->order[idx]) {
80 uint64_t pref_bitfield;
81
82 pref_bitfield = iax2_codec_pref_order_value_to_format_bitfield(pref->order[idx]);
84 } else {
85 *result = NULL;
86 }
87
88 return *result;
89}
90
92{
93 int idx;
94
95 for (idx = 0; idx < ARRAY_LEN(pref->order); ++idx) {
96 uint64_t pref_bitfield;
97 struct ast_format *pref_format;
98
99 pref_bitfield = iax2_codec_pref_order_value_to_format_bitfield(pref->order[idx]);
100 if (!pref_bitfield) {
101 break;
102 }
103
104 pref_format = ast_format_compatibility_bitfield2format(pref_bitfield);
105 if (pref_format && ast_format_cap_append(cap, pref_format, pref->framing[idx])) {
106 return -1;
107 }
108 }
109 return 0;
110}
111
112int iax2_codec_pref_best_bitfield2cap(uint64_t bitfield, struct iax2_codec_pref *prefs, struct ast_format_cap *cap)
113{
114 uint64_t best_bitfield;
115 struct ast_format *format;
116
117 /* Add any user preferred codecs first. */
118 if (prefs) {
119 int idx;
120
121 for (idx = 0; bitfield && idx < ARRAY_LEN(prefs->order); ++idx) {
122 best_bitfield = iax2_codec_pref_order_value_to_format_bitfield(prefs->order[idx]);
123 if (!best_bitfield) {
124 break;
125 }
126
127 if (best_bitfield & bitfield) {
128 format = ast_format_compatibility_bitfield2format(best_bitfield);
129 if (format && ast_format_cap_append(cap, format, prefs->framing[idx])) {
130 return -1;
131 }
132
133 /* Remove just added codec. */
134 bitfield &= ~best_bitfield;
135 }
136 }
137 }
138
139 /* Add the hard coded "best" codecs. */
140 while (bitfield) {
141 best_bitfield = iax2_format_compatibility_best(bitfield);
142 if (!best_bitfield) {
143 /* No more codecs considered best. */
144 break;
145 }
146
147 format = ast_format_compatibility_bitfield2format(best_bitfield);
148 /* The best_bitfield should always be convertible to a format. */
149 ast_assert(format != NULL);
150
151 if (ast_format_cap_append(cap, format, 0)) {
152 return -1;
153 }
154
155 /* Remove just added "best" codec to find the next "best". */
156 bitfield &= ~best_bitfield;
157 }
158
159 /* Add any remaining codecs. */
160 if (bitfield) {
161 int bit;
162
163 for (bit = 0; bit < 64; ++bit) {
164 uint64_t mask = (1ULL << bit);
165
166 if (mask & bitfield) {
168 if (format && ast_format_cap_append(cap, format, 0)) {
169 return -1;
170 }
171 }
172 }
173 }
174
175 return 0;
176}
177
178int iax2_codec_pref_string(struct iax2_codec_pref *pref, char *buf, size_t size)
179{
180 int x;
181 struct ast_format_cap *cap;
182 size_t total_len;
183 char *cur;
184
185 /* This function is useless if you have less than a 6 character buffer.
186 * '(...)' is six characters. */
187 if (size < 6) {
188 return -1;
189 }
190
191 /* Convert the preferences into a format cap so that we can read the format names */
193 if (!cap || iax2_codec_pref_to_cap(pref, cap)) {
194 strcpy(buf, "(...)"); /* Safe */
195 ao2_cleanup(cap);
196 return -1;
197 }
198
199 /* We know that at a minimum, 3 characters are used - (, ), and \0 */
200 total_len = size - 3;
201
202 /* This character has already been accounted for total_len purposes */
203 buf[0] = '(';
204 cur = buf + 1;
205
206 /* Loop through the formats and write as many into the buffer as we can */
207 for (x = 0; x < ast_format_cap_count(cap); x++) {
208 size_t name_len;
209 struct ast_format *fmt = ast_format_cap_get_format(cap, x);
210 const char *name = ast_format_get_name(fmt);
211
212 name_len = strlen(name);
213
214 /* all entries after the first need a delimiter character */
215 if (x) {
216 name_len++;
217 }
218
219 /* Terminate the list early if we don't have room for the entry.
220 * If it's not the last entry in the list, save enough room to write '...'.
221 */
222 if (((x == ast_format_cap_count(cap) - 1) && (total_len < name_len)) ||
223 ((x < ast_format_cap_count(cap) - 1) && (total_len < name_len + 3))) {
224 strcpy(cur, "...");
225 cur += 3;
226 total_len -= 3;
227 ao2_ref(fmt, -1);
228 break;
229 }
230
231 sprintf(cur, "%s%s", x ? "|" : "", name);
232 cur += name_len;
233 total_len -= name_len;
234
235 ao2_ref(fmt, -1);
236 }
237 ao2_ref(cap, -1);
238
239 /* These two characters have already been accounted for total_len purposes */
240 cur[0] = ')';
241 cur[1] = '\0';
242
243 return size - total_len;
244}
245
246static void codec_pref_remove_index(struct iax2_codec_pref *pref, int codec_pref_index)
247{
248 int idx;
249
250 idx = codec_pref_index;
251 if (idx == ARRAY_LEN(pref->order) - 1) {
252 /* Remove from last array entry. */
253 pref->order[idx] = 0;
254 pref->framing[idx] = 0;
255 return;
256 }
257
258 for (; idx < ARRAY_LEN(pref->order); ++idx) {
259 pref->order[idx] = pref->order[idx + 1];
260 pref->framing[idx] = pref->framing[idx + 1];
261 if (!pref->order[idx]) {
262 return;
263 }
264 }
265}
266
267/*! \brief Remove codec from pref list */
268static void codec_pref_remove(struct iax2_codec_pref *pref, int format_index)
269{
270 int x;
271
272 if (!pref->order[0]) {
273 return;
274 }
275
276 for (x = 0; x < ARRAY_LEN(pref->order); ++x) {
277 if (!pref->order[x]) {
278 break;
279 }
280
281 if (pref->order[x] == format_index) {
283 break;
284 }
285 }
286}
287
288void iax2_codec_pref_remove_missing(struct iax2_codec_pref *pref, uint64_t bitfield)
289{
290 int idx;
291
292 if (!pref->order[0]) {
293 return;
294 }
295
296 /*
297 * Work from the end of the list so we always deal with
298 * unmodified entries in case we have to remove a pref.
299 */
300 for (idx = ARRAY_LEN(pref->order); idx--;) {
301 uint64_t pref_bitfield;
302
303 pref_bitfield = iax2_codec_pref_order_value_to_format_bitfield(pref->order[idx]);
304 if (!pref_bitfield) {
305 continue;
306 }
307
308 /* If this format isn't in the bitfield, remove it from the prefs. */
309 if (!(pref_bitfield & bitfield)) {
310 codec_pref_remove_index(pref, idx);
311 }
312 }
313}
314
315/*!
316 * \brief Formats supported by IAX2.
317 *
318 * \note All AST_FORMAT_xxx compatibility bit defines must be
319 * represented here.
320 *
321 * \note The order is important because the array index+1 values
322 * go out over the wire.
323 */
324static const uint64_t iax2_supported_formats[] = {
351 0, /* reserved; was AST_FORMAT_TESTLAW */
353 0, /* Place holder */
354 0, /* Place holder */
355 0, /* Place holder */
356 0, /* Place holder */
357 0, /* Place holder */
358 0, /* Place holder */
359 0, /* Place holder */
360 0, /* Place holder */
363 /* ONLY ADD TO THE END OF THIS LIST */
364 /* XXX Use up the place holder slots first. */
365};
366
368{
369 if (order_value < 1 || ARRAY_LEN(iax2_supported_formats) < order_value) {
370 return 0;
371 }
372
373 return iax2_supported_formats[order_value - 1];
374}
375
377{
378 int idx;
379
380 if (bitfield) {
381 for (idx = 0; idx < ARRAY_LEN(iax2_supported_formats); ++idx) {
382 if (iax2_supported_formats[idx] == bitfield) {
383 return idx + 1;
384 }
385 }
386 }
387 return 0;
388}
389
390/*!
391 * \internal
392 * \brief Append the bitfield format to the codec preference list.
393 * \since 13.0.0
394 *
395 * \param pref Codec preference list to append the given bitfield.
396 * \param bitfield Format bitfield to append.
397 * \param framing Framing size of the codec.
398 */
399static void iax2_codec_pref_append_bitfield(struct iax2_codec_pref *pref, uint64_t bitfield, unsigned int framing)
400{
401 int format_index;
402 int x;
403
404 format_index = iax2_codec_pref_format_bitfield_to_order_value(bitfield);
405 if (!format_index) {
406 return;
407 }
408
409 codec_pref_remove(pref, format_index);
410
411 for (x = 0; x < ARRAY_LEN(pref->order); ++x) {
412 if (!pref->order[x]) {
413 pref->order[x] = format_index;
414 pref->framing[x] = framing;
415 break;
416 }
417 }
418}
419
420void iax2_codec_pref_append(struct iax2_codec_pref *pref, struct ast_format *format, unsigned int framing)
421{
422 uint64_t bitfield;
423
425 if (!bitfield) {
426 return;
427 }
428
429 iax2_codec_pref_append_bitfield(pref, bitfield, framing);
430}
431
432void iax2_codec_pref_prepend(struct iax2_codec_pref *pref, struct ast_format *format, unsigned int framing,
433 int only_if_existing)
434{
435 uint64_t bitfield;
436 int format_index;
437 int x;
438
440 if (!bitfield) {
441 return;
442 }
443 format_index = iax2_codec_pref_format_bitfield_to_order_value(bitfield);
444 if (!format_index) {
445 return;
446 }
447
448 /* Now find any existing occurrence, or the end */
449 for (x = 0; x < ARRAY_LEN(pref->order); ++x) {
450 if (!pref->order[x] || pref->order[x] == format_index)
451 break;
452 }
453
454 /*
455 * The array can never be full without format_index
456 * also being in the array.
457 */
458 ast_assert(x < ARRAY_LEN(pref->order));
459
460 /* If we failed to find any occurrence, set to the end for safety. */
461 if (ARRAY_LEN(pref->order) <= x) {
462 x = ARRAY_LEN(pref->order) - 1;
463 }
464
465 if (only_if_existing && !pref->order[x]) {
466 return;
467 }
468
469 /* Move down to make space to insert - either all the way to the end,
470 or as far as the existing location (which will be overwritten) */
471 for (; x > 0; --x) {
472 pref->order[x] = pref->order[x - 1];
473 pref->framing[x] = pref->framing[x - 1];
474 }
475
476 /* And insert the new entry */
477 pref->order[0] = format_index;
478 pref->framing[0] = framing;
479}
480
481uint64_t iax2_codec_pref_from_bitfield(struct iax2_codec_pref *pref, uint64_t bitfield)
482{
483 int bit;
484 uint64_t working_bitfield;
485 uint64_t best_bitfield;
486 struct ast_format *format;
487
488 /* Init the preference list. */
489 memset(pref, 0, sizeof(*pref));
490
491 working_bitfield = bitfield;
492
493 /* Add the "best" codecs first. */
494 while (working_bitfield) {
495 best_bitfield = iax2_format_compatibility_best(working_bitfield);
496 if (!best_bitfield) {
497 /* No more codecs considered best. */
498 break;
499 }
500
501 /* Remove current "best" codec to find the next "best". */
502 working_bitfield &= ~best_bitfield;
503
504 format = ast_format_compatibility_bitfield2format(best_bitfield);
505 /* The best_bitfield should always be convertible to a format. */
506 ast_assert(format != NULL);
507
508 iax2_codec_pref_append_bitfield(pref, best_bitfield, 0);
509 }
510
511 /* Add any remaining codecs. */
512 if (working_bitfield) {
513 for (bit = 0; bit < 64; ++bit) {
514 uint64_t mask = (1ULL << bit);
515
516 if (mask & working_bitfield) {
518 if (!format) {
519 /* The bit is not associated with any format. */
520 bitfield &= ~mask;
521 continue;
522 }
523
524 iax2_codec_pref_append_bitfield(pref, mask, 0);
525 }
526 }
527 }
528
529 return bitfield;
530}
Asterisk main include file. File version handling, generic pbx functions.
#define ao2_cleanup(obj)
Definition: astobj2.h:1934
#define ao2_ref(o, delta)
Reference/unreference an object and return the old refcount.
Definition: astobj2.h:459
static PGresult * result
Definition: cel_pgsql.c:84
uint64_t iax2_format_compatibility_best(uint64_t formats)
Pick the best format from the given bitfield formats.
Media Format Bitfield Compatibility API.
Codec API.
int iax2_codec_pref_string(struct iax2_codec_pref *pref, char *buf, size_t size)
Dump audio codec preference list into a string.
Definition: codec_pref.c:178
static void iax2_codec_pref_append_bitfield(struct iax2_codec_pref *pref, uint64_t bitfield, unsigned int framing)
Definition: codec_pref.c:399
void iax2_codec_pref_prepend(struct iax2_codec_pref *pref, struct ast_format *format, unsigned int framing, int only_if_existing)
Prepend an audio codec to a preference list, removing it first if it was already there.
Definition: codec_pref.c:432
int iax2_codec_pref_format_bitfield_to_order_value(uint64_t bitfield)
Convert a format bitfield into an iax2_codec_pref order value.
Definition: codec_pref.c:376
uint64_t iax2_codec_pref_order_value_to_format_bitfield(int order_value)
Convert an iax2_codec_pref order value into a format bitfield.
Definition: codec_pref.c:367
uint64_t iax2_codec_pref_from_bitfield(struct iax2_codec_pref *pref, uint64_t bitfield)
Create codec preference list from the given bitfield formats.
Definition: codec_pref.c:481
struct ast_format * iax2_codec_pref_index(struct iax2_codec_pref *pref, int idx, struct ast_format **result)
Codec located at a particular place in the preference index.
Definition: codec_pref.c:77
void iax2_codec_pref_convert(struct iax2_codec_pref *pref, char *buf, size_t size, int right)
Shift an audio codec preference list up or down 65 bytes so that it becomes an ASCII string.
Definition: codec_pref.c:44
void iax2_codec_pref_remove_missing(struct iax2_codec_pref *pref, uint64_t bitfield)
Removes format from the pref list that aren't in the bitfield.
Definition: codec_pref.c:288
void iax2_codec_pref_append(struct iax2_codec_pref *pref, struct ast_format *format, unsigned int framing)
Append a audio codec to a preference list, removing it first if it was already there.
Definition: codec_pref.c:420
static void codec_pref_remove_index(struct iax2_codec_pref *pref, int codec_pref_index)
Definition: codec_pref.c:246
static void codec_pref_remove(struct iax2_codec_pref *pref, int format_index)
Remove codec from pref list.
Definition: codec_pref.c:268
static const uint64_t iax2_supported_formats[]
Formats supported by IAX2.
Definition: codec_pref.c:324
int iax2_codec_pref_to_cap(struct iax2_codec_pref *pref, struct ast_format_cap *cap)
Convert a preference structure to a capabilities structure.
Definition: codec_pref.c:91
int iax2_codec_pref_best_bitfield2cap(uint64_t bitfield, struct iax2_codec_pref *prefs, struct ast_format_cap *cap)
Convert a bitfield to a format capabilities structure in the "best" order.
Definition: codec_pref.c:112
Media Format Bitfield Compatibility API.
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
Media Format API.
const char * ast_format_get_name(const struct ast_format *format)
Get the name associated with a format.
Definition: format.c:334
Media Format Cache API.
Format Capabilities API.
struct ast_format * ast_format_cap_get_format(const struct ast_format_cap *cap, int position)
Get the format at a specific index.
Definition: format_cap.c:400
@ AST_FORMAT_CAP_FLAG_DEFAULT
Definition: format_cap.h:38
#define ast_format_cap_append(cap, format, framing)
Add format capability to capabilities structure.
Definition: format_cap.h:99
#define ast_format_cap_alloc(flags)
Allocate a new ast_format_cap structure.
Definition: format_cap.h:49
size_t ast_format_cap_count(const struct ast_format_cap *cap)
Get the number of formats present within the capabilities structure.
Definition: format_cap.c:395
static const char name[]
Definition: format_mp3.c:68
Media Format Bitfield Compatibility API.
uint64_t ast_format_compatibility_format2bitfield(const struct ast_format *format)
Convert a format structure to its respective bitfield.
struct ast_format * ast_format_compatibility_bitfield2format(uint64_t bitfield)
Convert a bitfield to its respective format structure.
Support for logging to various files, console and syslog Configuration in file logger....
#define NULL
Definition: resample.c:96
Format capabilities structure, holds formats + preference order + etc.
Definition: format_cap.c:54
Definition of a media format.
Definition: format.c:43
unsigned int framing[IAX2_CODEC_PREF_SIZE]
Definition: codec_pref.h:38
char order[IAX2_CODEC_PREF_SIZE]
Definition: codec_pref.h:36
Utility functions.
#define ast_assert(a)
Definition: utils.h:739
#define ARRAY_LEN(a)
Definition: utils.h:666