Asterisk - The Open Source Telephony Project  18.5.0
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 <[email protected]>
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 <[email protected]>
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"
37 #include "asterisk/format_cache.h"
38 #include "asterisk/format_cap.h"
39 #include "asterisk/utils.h"
40 
41 #include "include/codec_pref.h"
43 
44 void 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 
77 struct 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]);
83  *result = ast_format_compatibility_bitfield2format(pref_bitfield);
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 
112 int 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 
178 int 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 
246 static 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 */
268 static 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) {
282  codec_pref_remove_index(pref, x);
283  break;
284  }
285  }
286 }
287 
288 void 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  */
324 static const uint64_t iax2_supported_formats[] = {
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  *
399  * \return Nothing
400  */
401 static void iax2_codec_pref_append_bitfield(struct iax2_codec_pref *pref, uint64_t bitfield, unsigned int framing)
402 {
403  int format_index;
404  int x;
405 
406  format_index = iax2_codec_pref_format_bitfield_to_order_value(bitfield);
407  if (!format_index) {
408  return;
409  }
410 
411  codec_pref_remove(pref, format_index);
412 
413  for (x = 0; x < ARRAY_LEN(pref->order); ++x) {
414  if (!pref->order[x]) {
415  pref->order[x] = format_index;
416  pref->framing[x] = framing;
417  break;
418  }
419  }
420 }
421 
422 void iax2_codec_pref_append(struct iax2_codec_pref *pref, struct ast_format *format, unsigned int framing)
423 {
424  uint64_t bitfield;
425 
426  bitfield = ast_format_compatibility_format2bitfield(format);
427  if (!bitfield) {
428  return;
429  }
430 
431  iax2_codec_pref_append_bitfield(pref, bitfield, framing);
432 }
433 
434 void iax2_codec_pref_prepend(struct iax2_codec_pref *pref, struct ast_format *format, unsigned int framing,
435  int only_if_existing)
436 {
437  uint64_t bitfield;
438  int format_index;
439  int x;
440 
441  bitfield = ast_format_compatibility_format2bitfield(format);
442  if (!bitfield) {
443  return;
444  }
445  format_index = iax2_codec_pref_format_bitfield_to_order_value(bitfield);
446  if (!format_index) {
447  return;
448  }
449 
450  /* Now find any existing occurrence, or the end */
451  for (x = 0; x < ARRAY_LEN(pref->order); ++x) {
452  if (!pref->order[x] || pref->order[x] == format_index)
453  break;
454  }
455 
456  /*
457  * The array can never be full without format_index
458  * also being in the array.
459  */
460  ast_assert(x < ARRAY_LEN(pref->order));
461 
462  /* If we failed to find any occurrence, set to the end for safety. */
463  if (ARRAY_LEN(pref->order) <= x) {
464  x = ARRAY_LEN(pref->order) - 1;
465  }
466 
467  if (only_if_existing && !pref->order[x]) {
468  return;
469  }
470 
471  /* Move down to make space to insert - either all the way to the end,
472  or as far as the existing location (which will be overwritten) */
473  for (; x > 0; --x) {
474  pref->order[x] = pref->order[x - 1];
475  pref->framing[x] = pref->framing[x - 1];
476  }
477 
478  /* And insert the new entry */
479  pref->order[0] = format_index;
480  pref->framing[0] = framing;
481 }
482 
483 uint64_t iax2_codec_pref_from_bitfield(struct iax2_codec_pref *pref, uint64_t bitfield)
484 {
485  int bit;
486  uint64_t working_bitfield;
487  uint64_t best_bitfield;
488  struct ast_format *format;
489 
490  /* Init the preference list. */
491  memset(pref, 0, sizeof(*pref));
492 
493  working_bitfield = bitfield;
494 
495  /* Add the "best" codecs first. */
496  while (working_bitfield) {
497  best_bitfield = iax2_format_compatibility_best(working_bitfield);
498  if (!best_bitfield) {
499  /* No more codecs considered best. */
500  break;
501  }
502 
503  /* Remove current "best" codec to find the next "best". */
504  working_bitfield &= ~best_bitfield;
505 
506  format = ast_format_compatibility_bitfield2format(best_bitfield);
507  /* The best_bitfield should always be convertible to a format. */
508  ast_assert(format != NULL);
509 
510  iax2_codec_pref_append_bitfield(pref, best_bitfield, 0);
511  }
512 
513  /* Add any remaining codecs. */
514  if (working_bitfield) {
515  for (bit = 0; bit < 64; ++bit) {
516  uint64_t mask = (1ULL << bit);
517 
518  if (mask & working_bitfield) {
520  if (!format) {
521  /* The bit is not associated with any format. */
522  bitfield &= ~mask;
523  continue;
524  }
525 
526  iax2_codec_pref_append_bitfield(pref, mask, 0);
527  }
528  }
529  }
530 
531  return bitfield;
532 }
Asterisk main include file. File version handling, generic pbx functions.
struct ast_format * ast_format_compatibility_bitfield2format(uint64_t bitfield)
Convert a bitfield to its respective format structure.
#define ARRAY_LEN(a)
Definition: isdn_lib.c:42
uint64_t ast_format_compatibility_format2bitfield(const struct ast_format *format)
Convert a format structure to its respective bitfield.
static void iax2_codec_pref_append_bitfield(struct iax2_codec_pref *pref, uint64_t bitfield, unsigned int framing)
Definition: codec_pref.c:401
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
Media Format Bitfield Compatibility API.
Codec API.
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:483
static const uint64_t iax2_supported_formats[]
Formats supported by IAX2.
Definition: codec_pref.c:324
Definition of a media format.
Definition: format.c:43
void iax2_codec_pref_remove_missing(struct iax2_codec_pref *pref, uint64_t bitfield)
Removes format from the pref list that aren&#39;t in the bitfield.
Definition: codec_pref.c:288
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:434
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
#define ast_assert(a)
Definition: utils.h:695
const char * ast_format_get_name(const struct ast_format *format)
Get the name associated with a format.
Definition: format.c:334
#define NULL
Definition: resample.c:96
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
Utility functions.
Media Format API.
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
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
#define ao2_ref(o, delta)
Definition: astobj2.h:464
#define ast_format_cap_append(cap, format, framing)
Definition: format_cap.h:103
#define ast_format_cap_alloc(flags)
Definition: format_cap.h:52
Format Capabilities API.
Format capabilities structure, holds formats + preference order + etc.
Definition: format_cap.c:54
Media Format Bitfield Compatibility 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
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:422
static const char name[]
Definition: cdr_mysql.c:74
unsigned int framing[IAX2_CODEC_PREF_SIZE]
Definition: codec_pref.h:38
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
Support for logging to various files, console and syslog Configuration in file logger.conf.
char order[IAX2_CODEC_PREF_SIZE]
Definition: codec_pref.h:36
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
static PGresult * result
Definition: cel_pgsql.c:88
uint64_t iax2_format_compatibility_best(uint64_t formats)
Pick the best format from the given bitfield formats.
Media Format Bitfield Compatibility 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
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
static void codec_pref_remove_index(struct iax2_codec_pref *pref, int codec_pref_index)
Definition: codec_pref.c:246
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
static snd_pcm_format_t format
Definition: chan_alsa.c:102
static void codec_pref_remove(struct iax2_codec_pref *pref, int format_index)
Remove codec from pref list.
Definition: codec_pref.c:268
Media Format Cache API.