Asterisk - The Open Source Telephony Project  21.4.1
translate.c
Go to the documentation of this file.
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 1999 - 2006, Digium, Inc.
5  *
6  * Mark Spencer <markster@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 Translate via the use of pseudo channels
22  *
23  * \author Mark Spencer <markster@digium.com>
24  */
25 
26 /*** MODULEINFO
27  <support_level>core</support_level>
28  ***/
29 
30 #include "asterisk.h"
31 
32 #include <sys/time.h>
33 #include <sys/resource.h>
34 #include <math.h>
35 
36 #include "asterisk/lock.h"
37 #include "asterisk/channel.h"
38 #include "asterisk/translate.h"
39 #include "asterisk/module.h"
40 #include "asterisk/frame.h"
41 #include "asterisk/sched.h"
42 #include "asterisk/cli.h"
43 #include "asterisk/term.h"
44 #include "asterisk/format.h"
45 #include "asterisk/linkedlists.h"
46 
47 /*! \todo
48  * TODO: sample frames for each supported input format.
49  * We build this on the fly, by taking an SLIN frame and using
50  * the existing converter to play with it.
51  */
52 
53 /*! max sample recalc */
54 #define MAX_RECALC 1000
55 
56 /*! \brief the list of translators */
58 
60  struct ast_translator *step; /*!< Next step translator */
61  uint32_t table_cost; /*!< Complete table cost to destination */
62  uint32_t comp_cost; /*!< Complete table cost to destination */
63  uint8_t multistep; /*!< Multiple conversions required for this translation */
64 };
65 
66 /*!
67  * \brief a matrix that, for any pair of supported formats,
68  * indicates the total cost of translation and the first step.
69  * The full path can be reconstructed iterating on the matrix
70  * until step->dstfmt == desired_format.
71  *
72  * Array indexes are 'src' and 'dest', in that order.
73  *
74  * Note: the lock in the 'translators' list is also used to protect
75  * this structure.
76  */
77 static struct translator_path **__matrix;
78 
79 /*!
80  * \brief table for converting index to format values.
81  *
82  * \note this table is protected by the table_lock.
83  */
84 static unsigned int *__indextable;
85 
86 /*! protects the __indextable for resizing */
88 
89 /* index size starts at this*/
90 #define INIT_INDEX 32
91 /* index size grows by this as necessary */
92 #define GROW_INDEX 16
93 
94 /*! the current largest index used by the __matrix and __indextable arrays*/
95 static int cur_max_index;
96 /*! the largest index that can be used in either the __indextable or __matrix before resize must occur */
97 static int index_size;
98 
99 static void matrix_rebuild(int samples);
100 
101 /*!
102  * \internal
103  * \brief converts codec id to index value.
104  */
105 static int codec_to_index(unsigned int id)
106 {
107  int x;
108 
109  ast_rwlock_rdlock(&tablelock);
110  for (x = 0; x < cur_max_index; x++) {
111  if (__indextable[x] == id) {
112  /* format already exists in index2format table */
113  ast_rwlock_unlock(&tablelock);
114  return x;
115  }
116  }
117  ast_rwlock_unlock(&tablelock);
118  return -1; /* not found */
119 }
120 
121 /*!
122  * \internal
123  * \brief converts codec to index value.
124  */
125 static int codec2index(struct ast_codec *codec)
126 {
127  return codec_to_index(codec->id);
128 }
129 
130 /*!
131  * \internal
132  * \brief converts format to codec index value.
133  */
134 static int format2index(struct ast_format *format)
135 {
136  return codec_to_index(ast_format_get_codec_id(format));
137 }
138 
139 /*!
140  * \internal
141  * \brief add a new codec to the matrix and index table structures.
142  *
143  * \note it is perfectly safe to call this on codecs already indexed.
144  *
145  * \retval 0 success
146  * \retval -1 matrix and index table need to be resized
147  */
148 static int add_codec2index(struct ast_codec *codec)
149 {
150  if (codec2index(codec) != -1) {
151  /* format is already already indexed */
152  return 0;
153  }
154 
155  ast_rwlock_wrlock(&tablelock);
156  if (cur_max_index == (index_size)) {
157  ast_rwlock_unlock(&tablelock);
158  return -1; /* hit max length */
159  }
160  __indextable[cur_max_index] = codec->id;
161  cur_max_index++;
162  ast_rwlock_unlock(&tablelock);
163 
164  return 0;
165 }
166 
167 /*!
168  * \internal
169  * \brief converts index value back to codec
170  */
171 static struct ast_codec *index2codec(int index)
172 {
173  struct ast_codec *codec;
174 
175  if (index >= cur_max_index) {
176  return 0;
177  }
178  ast_rwlock_rdlock(&tablelock);
179  codec = ast_codec_get_by_id(__indextable[index]);
180  ast_rwlock_unlock(&tablelock);
181 
182  return codec;
183 }
184 
185 /*!
186  * \internal
187  * \brief resize both the matrix and index table so they can represent
188  * more translators
189  *
190  * \note _NO_ locks can be held prior to calling this function
191  *
192  * \retval 0 success
193  * \retval -1 failure. Old matrix and index table can still be used though
194  */
195 static int matrix_resize(int init)
196 {
197  struct translator_path **tmp_matrix = NULL;
198  unsigned int *tmp_table = NULL;
199  int old_index;
200  int x;
201 
203  ast_rwlock_wrlock(&tablelock);
204 
205  old_index = index_size;
206  if (init) {
207  index_size += INIT_INDEX;
208  } else {
209  index_size += GROW_INDEX;
210  }
211 
212  /* make new 2d array of translator_path structures */
213  if (!(tmp_matrix = ast_calloc(1, sizeof(struct translator_path *) * (index_size)))) {
214  goto resize_cleanup;
215  }
216 
217  for (x = 0; x < index_size; x++) {
218  if (!(tmp_matrix[x] = ast_calloc(1, sizeof(struct translator_path) * (index_size)))) {
219  goto resize_cleanup;
220  }
221  }
222 
223  /* make new index table */
224  if (!(tmp_table = ast_calloc(1, sizeof(unsigned int) * index_size))) {
225  goto resize_cleanup;
226  }
227 
228  /* if everything went well this far, free the old and use the new */
229  if (!init) {
230  for (x = 0; x < old_index; x++) {
231  ast_free(__matrix[x]);
232  }
233  ast_free(__matrix);
234 
235  memcpy(tmp_table, __indextable, sizeof(unsigned int) * old_index);
236  ast_free(__indextable);
237  }
238 
239  /* now copy them over */
240  __matrix = tmp_matrix;
241  __indextable = tmp_table;
242 
243  matrix_rebuild(0);
244  ast_rwlock_unlock(&tablelock);
246 
247  return 0;
248 
249 resize_cleanup:
250  ast_rwlock_unlock(&tablelock);
252  if (tmp_matrix) {
253  for (x = 0; x < index_size; x++) {
254  ast_free(tmp_matrix[x]);
255  }
256  ast_free(tmp_matrix);
257  }
258  ast_free(tmp_table);
259 
260  return -1;
261 }
262 
263 /*!
264  * \internal
265  * \brief reinitialize the __matrix during matrix rebuild
266  *
267  * \note must be protected by the translators list lock
268  */
269 static void matrix_clear(void)
270 {
271  int x;
272  for (x = 0; x < index_size; x++) {
273  memset(__matrix[x], '\0', sizeof(struct translator_path) * (index_size));
274  }
275 }
276 
277 /*!
278  * \internal
279  * \brief get a matrix entry
280  *
281  * \note This function must be protected by the translators list lock
282  */
283 static struct translator_path *matrix_get(unsigned int x, unsigned int y)
284 {
285  return __matrix[x] + y;
286 }
287 
288 /*
289  * wrappers around the translator routines.
290  */
291 
292 static void destroy(struct ast_trans_pvt *pvt)
293 {
294  struct ast_translator *t = pvt->t;
295 
296  if (t->destroy) {
297  t->destroy(pvt);
298  }
299  ao2_cleanup(pvt->f.subclass.format);
300  if (pvt->explicit_dst) {
301  ao2_ref(pvt->explicit_dst, -1);
302  pvt->explicit_dst = NULL;
303  }
304  ast_free(pvt);
306 }
307 
308 /*!
309  * \brief Allocate the descriptor, required outbuf space,
310  * and possibly desc.
311  */
312 static struct ast_trans_pvt *newpvt(struct ast_translator *t, struct ast_format *explicit_dst)
313 {
314  struct ast_trans_pvt *pvt;
315  int len;
316  char *ofs;
317 
318  /*
319  * compute the required size adding private descriptor,
320  * buffer, AST_FRIENDLY_OFFSET.
321  */
322  len = sizeof(*pvt) + t->desc_size;
323  if (t->buf_size)
324  len += AST_FRIENDLY_OFFSET + t->buf_size;
325  pvt = ast_calloc(1, len);
326  if (!pvt) {
327  return NULL;
328  }
329  pvt->t = t;
330  ofs = (char *)(pvt + 1); /* pointer to data space */
331  if (t->desc_size) { /* first comes the descriptor */
332  pvt->pvt = ofs;
333  ofs += t->desc_size;
334  }
335  if (t->buf_size) {/* finally buffer and header */
336  pvt->outbuf.c = ofs + AST_FRIENDLY_OFFSET;
337  }
338  /*
339  * If the format has an attribute module, explicit_dst includes the (joined)
340  * result of the SDP negotiation. For example with the Opus Codec, the format
341  * knows whether both parties want to do forward-error correction (FEC).
342  */
343  pvt->explicit_dst = ao2_bump(explicit_dst);
344 
346 
347  /* call local init routine, if present */
348  if (t->newpvt && t->newpvt(pvt)) {
349  ast_free(pvt);
351  return NULL;
352  }
353 
354  /* Setup normal static translation frame. */
355  pvt->f.frametype = AST_FRAME_VOICE;
356  pvt->f.mallocd = 0;
358  pvt->f.src = pvt->t->name;
359  pvt->f.data.ptr = pvt->outbuf.c;
360 
361  /*
362  * If the translator has not provided a format
363  * A) use the joined one,
364  * B) use the cached one, or
365  * C) create one.
366  */
367  if (!pvt->f.subclass.format) {
368  pvt->f.subclass.format = ao2_bump(pvt->explicit_dst);
369 
370  if (!pvt->f.subclass.format && !ast_strlen_zero(pvt->t->format)) {
371  pvt->f.subclass.format = ast_format_cache_get(pvt->t->format);
372  }
373 
374  if (!pvt->f.subclass.format) {
375  struct ast_codec *codec = ast_codec_get(t->dst_codec.name,
377  if (!codec) {
378  ast_log(LOG_ERROR, "Unable to get destination codec\n");
379  destroy(pvt);
380  return NULL;
381  }
382  pvt->f.subclass.format = ast_format_create(codec);
383  ao2_ref(codec, -1);
384  }
385 
386  if (!pvt->f.subclass.format) {
387  ast_log(LOG_ERROR, "Unable to create format\n");
388  destroy(pvt);
389  return NULL;
390  }
391  }
392 
393  return pvt;
394 }
395 
396 /*! \brief framein wrapper, deals with bound checks. */
397 static int framein(struct ast_trans_pvt *pvt, struct ast_frame *f)
398 {
399  /* Copy the last in jb timing info to the pvt */
400  ast_copy_flags(&pvt->f, f, AST_FRFLAG_HAS_TIMING_INFO);
401  pvt->f.ts = f->ts;
402  pvt->f.len = f->len;
403  pvt->f.seqno = f->seqno;
404 
405  if (f->samples == 0) {
406  /* Do not log empty audio frame */
407  if (!f->src || strcasecmp(f->src, "ast_prod")) {
408  ast_log(LOG_WARNING, "no samples for %s\n", pvt->t->name);
409  }
410  }
411  if (pvt->t->buffer_samples) { /* do not pass empty frames to callback */
412  int src_srate = pvt->t->src_codec.sample_rate;
413  int dst_srate = pvt->t->dst_codec.sample_rate;
414 
415  ast_assert(src_srate > 0);
416 
417  if (f->datalen == 0) { /* perform native PLC if available */
418  /* If the codec has native PLC, then do that */
419  if (!pvt->t->native_plc)
420  return 0;
421  }
422 
423  if (pvt->samples + (f->samples * dst_srate / src_srate) > pvt->t->buffer_samples) {
424  ast_log(LOG_WARNING, "Out of buffer space\n");
425  return -1;
426  }
427  }
428  /* we require a framein routine, wouldn't know how to do
429  * it otherwise.
430  */
431  return pvt->t->framein(pvt, f);
432 }
433 
434 /*! \brief generic frameout routine.
435  * If samples and datalen are 0, take whatever is in pvt
436  * and reset them, otherwise take the values in the caller and
437  * leave alone the pvt values.
438  */
440  int datalen, int samples)
441 {
442  struct ast_frame *f = &pvt->f;
443 
444  if (samples) {
445  f->samples = samples;
446  } else {
447  if (pvt->samples == 0) {
448  return NULL;
449  }
450  f->samples = pvt->samples;
451  pvt->samples = 0;
452  }
453  if (datalen) {
454  f->datalen = datalen;
455  f->data.ptr = pvt->outbuf.c;
456  } else {
457  f->datalen = pvt->datalen;
458  if (!f->datalen) {
459  f->data.ptr = NULL;
460  } else {
461  f->data.ptr = pvt->outbuf.c;
462  }
463  pvt->datalen = 0;
464  }
465 
466  return ast_frisolate(f);
467 }
468 
469 static struct ast_frame *default_frameout(struct ast_trans_pvt *pvt)
470 {
471  return ast_trans_frameout(pvt, 0, 0);
472 }
473 
474 /* end of callback wrappers and helpers */
475 
477 {
478  struct ast_trans_pvt *pn = p;
479  while ( (p = pn) ) {
480  pn = p->next;
481  destroy(p);
482  }
483 }
484 
485 /*! \brief Build a chain of translators based upon the given source and dest formats */
487 {
488  struct ast_trans_pvt *head = NULL, *tail = NULL;
489  int src_index, dst_index;
490 
491  src_index = format2index(src);
492  dst_index = format2index(dst);
493 
494  if (src_index < 0 || dst_index < 0) {
495  ast_log(LOG_WARNING, "No translator path: (%s codec is not valid)\n", src_index < 0 ? "starting" : "ending");
496  return NULL;
497  }
498 
500 
501  while (src_index != dst_index) {
502  struct ast_trans_pvt *cur;
503  struct ast_format *explicit_dst = NULL;
504  struct ast_translator *t = matrix_get(src_index, dst_index)->step;
505  if (!t) {
506  ast_log(LOG_WARNING, "No translator path from %s to %s\n",
510  return NULL;
511  }
513  explicit_dst = dst;
514  }
515  if (!(cur = newpvt(t, explicit_dst))) {
516  ast_log(LOG_WARNING, "Failed to build translator step from %s to %s\n",
520  return NULL;
521  }
522  if (!head) {
523  head = cur;
524  } else {
525  tail->next = cur;
526  }
527  tail = cur;
528  cur->nextin = cur->nextout = ast_tv(0, 0);
529  /* Keep going if this isn't the final destination */
530  src_index = cur->t->dst_fmt_index;
531  }
532 
534  return head;
535 }
536 
537 static struct ast_frame *generate_interpolated_slin(struct ast_trans_pvt *p, struct ast_frame *f)
538 {
539  struct ast_frame res = { AST_FRAME_VOICE };
540 
541  /*
542  * If we've gotten here then we should have an interpolated frame that was not handled
543  * by the translation codec. So create an interpolated frame in the appropriate format
544  * that was going to be written. This frame might be handled later by other resources.
545  * For instance, generic plc.
546  *
547  * Note, generic plc is currently only available for the format type 'slin' (8KHz only -
548  * The generic plc code appears to have been based around that). Generic plc is filled
549  * in later on frame write.
550  */
551  if (!ast_opt_generic_plc || f->datalen != 0 ||
553  return NULL;
554  }
555 
556  res.subclass.format = ast_format_cache_get_slin_by_rate(8000); /* ref bumped on dup */
557  res.samples = f->samples;
558  res.datalen = 0;
559  res.data.ptr = NULL;
561 
562  return ast_frdup(&res);
563 }
564 
565 /*! \brief do the actual translation */
566 struct ast_frame *ast_translate(struct ast_trans_pvt *path, struct ast_frame *f, int consume)
567 {
568  struct ast_trans_pvt *p = path;
569  struct ast_frame *out;
570  struct timeval delivery;
571  int has_timing_info;
572  long ts;
573  long len;
574  int seqno;
575 
576  if (f->frametype == AST_FRAME_RTCP) {
577  /* Just pass the feedback to the right callback, if it exists.
578  * This "translation" does nothing so return a null frame. */
579  struct ast_trans_pvt *tp;
580  for (tp = p; tp; tp = tp->next) {
581  if (tp->t->feedback)
582  tp->t->feedback(tp, f);
583  }
584  return &ast_null_frame;
585  }
586 
587  has_timing_info = ast_test_flag(f, AST_FRFLAG_HAS_TIMING_INFO);
588  ts = f->ts;
589  len = f->len;
590  seqno = f->seqno;
591 
592  if (!ast_tvzero(f->delivery)) {
593  if (!ast_tvzero(path->nextin)) {
594  /* Make sure this is in line with what we were expecting */
595  if (!ast_tveq(path->nextin, f->delivery)) {
596  /* The time has changed between what we expected and this
597  most recent time on the new packet. If we have a
598  valid prediction adjust our output time appropriately */
599  if (!ast_tvzero(path->nextout)) {
600  path->nextout = ast_tvadd(path->nextout,
601  ast_tvsub(f->delivery, path->nextin));
602  }
603  path->nextin = f->delivery;
604  }
605  } else {
606  /* This is our first pass. Make sure the timing looks good */
607  path->nextin = f->delivery;
608  path->nextout = f->delivery;
609  }
610  /* Predict next incoming sample */
611  path->nextin = ast_tvadd(path->nextin, ast_samp2tv(
613  }
614  delivery = f->delivery;
615  for (out = f; out && p ; p = p->next) {
616  struct ast_frame *current = out;
617 
618  do {
619  framein(p, current);
620  current = AST_LIST_NEXT(current, frame_list);
621  } while (current);
622  if (out != f) {
623  ast_frfree(out);
624  }
625  out = p->t->frameout(p);
626  }
627 
628  if (!out) {
629  out = generate_interpolated_slin(path, f);
630  }
631 
632  if (out) {
633  /* we have a frame, play with times */
634  if (!ast_tvzero(delivery)) {
635  struct ast_frame *current = out;
636 
637  do {
638  /* Regenerate prediction after a discontinuity */
639  if (ast_tvzero(path->nextout)) {
640  path->nextout = ast_tvnow();
641  }
642 
643  /* Use next predicted outgoing timestamp */
644  current->delivery = path->nextout;
645 
646  /* Invalidate prediction if we're entering a silence period */
647  if (current->frametype == AST_FRAME_CNG) {
648  path->nextout = ast_tv(0, 0);
649  /* Predict next outgoing timestamp from samples in this
650  frame. */
651  } else {
652  path->nextout = ast_tvadd(path->nextout, ast_samp2tv(
653  current->samples, ast_format_get_sample_rate(current->subclass.format)));
654  }
655 
656  if (f->samples != current->samples && ast_test_flag(current, AST_FRFLAG_HAS_TIMING_INFO)) {
657  ast_debug(4, "Sample size different %d vs %d\n", f->samples, current->samples);
658  ast_clear_flag(current, AST_FRFLAG_HAS_TIMING_INFO);
659  }
660  current = AST_LIST_NEXT(current, frame_list);
661  } while (current);
662  } else {
663  out->delivery = ast_tv(0, 0);
664  ast_set2_flag(out, has_timing_info, AST_FRFLAG_HAS_TIMING_INFO);
665  if (has_timing_info) {
666  out->ts = ts;
667  out->len = len;
668  out->seqno = seqno;
669  }
670  /* Invalidate prediction if we're entering a silence period */
671  if (out->frametype == AST_FRAME_CNG) {
672  path->nextout = ast_tv(0, 0);
673  }
674  }
675  }
676  if (consume) {
677  ast_frfree(f);
678  }
679  return out;
680 }
681 
682 /*!
683  * \internal
684  * \brief Compute the computational cost of a single translation step.
685  *
686  * \note This function is only used to decide which translation path to
687  * use between two translators with identical src and dst formats. Computational
688  * cost acts only as a tie breaker. This is done so hardware translators
689  * can naturally have precedence over software translators.
690  */
691 static void generate_computational_cost(struct ast_translator *t, int seconds)
692 {
693  int num_samples = 0;
694  struct ast_trans_pvt *pvt;
695  struct rusage start;
696  struct rusage end;
697  int cost;
698  int out_rate = t->dst_codec.sample_rate;
699 
700  if (!seconds) {
701  seconds = 1;
702  }
703 
704  /* If they don't make samples, give them a terrible score */
705  if (!t->sample) {
706  ast_debug(3, "Translator '%s' does not produce sample frames.\n", t->name);
707  t->comp_cost = 999999;
708  return;
709  }
710 
711  pvt = newpvt(t, NULL);
712  if (!pvt) {
713  ast_log(LOG_WARNING, "Translator '%s' appears to be broken and will probably fail.\n", t->name);
714  t->comp_cost = 999999;
715  return;
716  }
717 
718  getrusage(RUSAGE_SELF, &start);
719 
720  /* Call the encoder until we've processed the required number of samples */
721  while (num_samples < seconds * out_rate) {
722  struct ast_frame *f = t->sample();
723  if (!f) {
724  ast_log(LOG_WARNING, "Translator '%s' failed to produce a sample frame.\n", t->name);
725  destroy(pvt);
726  t->comp_cost = 999999;
727  return;
728  }
729  framein(pvt, f);
730  ast_frfree(f);
731  while ((f = t->frameout(pvt))) {
732  num_samples += f->samples;
733  ast_frfree(f);
734  }
735  }
736 
737  getrusage(RUSAGE_SELF, &end);
738 
739  cost = ((end.ru_utime.tv_sec - start.ru_utime.tv_sec) * 1000000) + end.ru_utime.tv_usec - start.ru_utime.tv_usec;
740  cost += ((end.ru_stime.tv_sec - start.ru_stime.tv_sec) * 1000000) + end.ru_stime.tv_usec - start.ru_stime.tv_usec;
741 
742  destroy(pvt);
743 
744  t->comp_cost = cost / seconds;
745 
746  if (!t->comp_cost) {
747  t->comp_cost = 1;
748  }
749 }
750 
751 /*!
752  * \internal
753  *
754  * \brief If no table cost value was pre set by the translator. An attempt is made to
755  * automatically generate that cost value from the cost table based on our src and
756  * dst formats.
757  *
758  * \note This function allows older translators built before the translation cost
759  * changed away from using onely computational time to continue to be registered
760  * correctly. It is expected that translators built after the introduction of this
761  * function will manually assign their own table cost value.
762  *
763  * \note This function is safe to use on any audio formats that used to be defined in the
764  * first 64 bits of the old bit field codec representation.
765  *
766  * \return Table Cost value greater than 0.
767  * \retval 0 on error.
768  */
769 static int generate_table_cost(struct ast_codec *src, struct ast_codec *dst)
770 {
771  int src_rate = src->sample_rate;
772  int src_ll = 0;
773  int dst_rate = dst->sample_rate;
774  int dst_ll = 0;
775 
776  if ((src->type != AST_MEDIA_TYPE_AUDIO) ||
777  (dst->type != AST_MEDIA_TYPE_AUDIO)) {
778  /* This method of generating table cost is limited to audio.
779  * Translators for media other than audio must manually set their
780  * table cost. */
781  return 0;
782  }
783 
784  src_ll = !strcmp(src->name, "slin");
785  dst_ll = !strcmp(dst->name, "slin");
786  if (src_ll) {
787  if (dst_ll && (src_rate == dst_rate)) {
789  } else if (!dst_ll && (src_rate == dst_rate)) {
791  } else if (dst_ll && (src_rate < dst_rate)) {
793  } else if (!dst_ll && (src_rate < dst_rate)) {
795  } else if (dst_ll && (src_rate > dst_rate)) {
797  } else if (!dst_ll && (src_rate > dst_rate)) {
799  } else {
801  }
802  } else {
803  if (dst_ll && (src_rate == dst_rate)) {
805  } else if (!dst_ll && (src_rate == dst_rate)) {
807  } else if (dst_ll && (src_rate < dst_rate)) {
809  } else if (!dst_ll && (src_rate < dst_rate)) {
811  } else if (dst_ll && (src_rate > dst_rate)) {
813  } else if (!dst_ll && (src_rate > dst_rate)) {
815  } else {
817  }
818  }
819 }
820 
821 /*!
822  * \brief rebuild a translation matrix.
823  * \note This function expects the list of translators to be locked
824 */
825 static void matrix_rebuild(int samples)
826 {
827  struct ast_translator *t;
828  int newtablecost;
829  int x; /* source format index */
830  int y; /* intermediate format index */
831  int z; /* destination format index */
832 
833  ast_debug(1, "Resetting translation matrix\n");
834 
835  matrix_clear();
836 
837  /* first, compute all direct costs */
838  AST_RWLIST_TRAVERSE(&translators, t, list) {
839  if (!t->active) {
840  continue;
841  }
842 
843  x = t->src_fmt_index;
844  z = t->dst_fmt_index;
845 
846  if (samples) {
847  generate_computational_cost(t, samples);
848  }
849 
850  /* This new translator is the best choice if any of the below are true.
851  * 1. no translation path is set between x and z yet.
852  * 2. the new table cost is less.
853  * 3. the new computational cost is less. Computational cost is only used
854  * to break a tie between two identical translation paths.
855  */
856  if (!matrix_get(x, z)->step ||
857  (t->table_cost < matrix_get(x, z)->step->table_cost) ||
858  (t->comp_cost < matrix_get(x, z)->step->comp_cost)) {
859 
860  matrix_get(x, z)->step = t;
861  matrix_get(x, z)->table_cost = t->table_cost;
862  matrix_get(x, z)->comp_cost = t->comp_cost;
863  }
864  }
865 
866  /*
867  * For each triple x, y, z of distinct formats, check if there is
868  * a path from x to z through y which is cheaper than what is
869  * currently known, and in case, update the matrix.
870  * Repeat until the matrix is stable.
871  */
872  for (;;) {
873  int changed = 0;
874  for (x = 0; x < cur_max_index; x++) { /* source format */
875  for (y = 0; y < cur_max_index; y++) { /* intermediate format */
876  if (x == y) { /* skip ourselves */
877  continue;
878  }
879  for (z = 0; z < cur_max_index; z++) { /* dst format */
880  if ((z == x || z == y) || /* skip null conversions */
881  !matrix_get(x, y)->step || /* no path from x to y */
882  !matrix_get(y, z)->step) { /* no path from y to z */
883  continue;
884  }
885 
886  /* calculate table cost from x->y->z */
887  newtablecost = matrix_get(x, y)->table_cost + matrix_get(y, z)->table_cost;
888 
889  /* if no step already exists between x and z OR the new cost of using the intermediate
890  * step is cheaper, use this step. */
891  if (!matrix_get(x, z)->step || (newtablecost < matrix_get(x, z)->table_cost)) {
892  matrix_get(x, z)->step = matrix_get(x, y)->step;
893  matrix_get(x, z)->table_cost = newtablecost;
894  matrix_get(x, z)->multistep = 1;
895  changed++;
896 
897  if (DEBUG_ATLEAST(10)) {
898  struct ast_codec *x_codec = index2codec(x);
899  struct ast_codec *y_codec = index2codec(y);
900  struct ast_codec *z_codec = index2codec(z);
901 
902  ast_log(LOG_DEBUG,
903  "Discovered %u cost path from %s to %s, via %s\n",
904  matrix_get(x, z)->table_cost, x_codec->name,
905  y_codec->name, z_codec->name);
906 
907  ao2_ref(x_codec, -1);
908  ao2_ref(y_codec, -1);
909  ao2_ref(z_codec, -1);
910  }
911  }
912  }
913  }
914  }
915  if (!changed) {
916  break;
917  }
918  }
919 }
920 
921 static void codec_append_name(const struct ast_codec *codec, struct ast_str **buf)
922 {
923  if (codec) {
924  ast_str_append(buf, 0, "(%s@%u)", codec->name, codec->sample_rate);
925  } else {
926  ast_str_append(buf, 0, "(nothing)");
927  }
928 }
929 
930 const char *ast_translate_path_to_str(struct ast_trans_pvt *p, struct ast_str **str)
931 {
932  if (!p || !p->t) {
933  return "";
934  }
935 
936  ast_str_reset(*str);
937  codec_append_name(&p->t->src_codec, str);
938  while (p) {
939  ast_str_append(str, 0, "->");
940  codec_append_name(&p->t->dst_codec, str);
941  p = p->next;
942  }
943 
944  return ast_str_buffer(*str);
945 }
946 
947 static char *complete_trans_path_choice(const char *word)
948 {
949  int i = 1;
950  int wordlen = strlen(word);
951  struct ast_codec *codec;
952 
953  while ((codec = ast_codec_get_by_id(i))) {
954  ++i;
955  if (codec->type != AST_MEDIA_TYPE_AUDIO) {
956  ao2_ref(codec, -1);
957  continue;
958  }
959  if (!strncasecmp(word, codec->name, wordlen)) {
960  if (ast_cli_completion_add(ast_strdup(codec->name))) {
961  ao2_ref(codec, -1);
962  break;
963  }
964  }
965  ao2_ref(codec, -1);
966  }
967 
968  return NULL;
969 }
970 
971 static void handle_cli_recalc(struct ast_cli_args *a)
972 {
973  int time = a->argv[4] ? atoi(a->argv[4]) : 1;
974 
975  if (time <= 0) {
976  ast_cli(a->fd, " Recalc must be greater than 0. Defaulting to 1.\n");
977  time = 1;
978  }
979 
980  if (time > MAX_RECALC) {
981  ast_cli(a->fd, " Maximum limit of recalc exceeded by %d, truncating value to %d\n", time - MAX_RECALC, MAX_RECALC);
982  time = MAX_RECALC;
983  }
984  ast_cli(a->fd, " Recalculating Codec Translation (number of sample seconds: %d)\n\n", time);
986  matrix_rebuild(time);
988 }
989 
990 static char *handle_show_translation_table(struct ast_cli_args *a)
991 {
992  int x, y, i, k, compCost;
993  int longest = 7; /* slin192 */
994  int max_codec_index = 0, curlen = 0;
995  struct ast_str *out = ast_str_create(1024);
996  struct ast_codec *codec;
997 
998  /* Get the length of the longest (usable?) codec name,
999  so we know how wide the left side should be */
1000  for (i = 1; (codec = ast_codec_get_by_id(i)); ao2_ref(codec, -1), ++i) {
1001  ++max_codec_index;
1002  if (codec->type != AST_MEDIA_TYPE_AUDIO) {
1003  continue;
1004  }
1005  curlen = strlen(codec->name);
1006  if (curlen > longest) {
1007  longest = curlen;
1008  }
1009  }
1010 
1012  ast_cli(a->fd, " Translation times between formats (in microseconds) for one second of data\n");
1013  ast_cli(a->fd, " Source Format (Rows) Destination Format (Columns)\n\n");
1014 
1015  for (i = 0; i <= max_codec_index; i++) {
1016  struct ast_codec *row = i ? ast_codec_get_by_id(i) : NULL;
1017 
1018  x = -1;
1019  if ((i > 0) && (row->type != AST_MEDIA_TYPE_AUDIO)) {
1020  ao2_ref(row, -1);
1021  continue;
1022  }
1023 
1024  if ((i > 0) && (x = codec2index(row)) == -1) {
1025  ao2_ref(row, -1);
1026  continue;
1027  }
1028 
1029  ast_str_set(&out, 0, " ");
1030  for (k = 0; k <= max_codec_index; k++) {
1031  int adjust = 0;
1032  struct ast_codec *col = k ? ast_codec_get_by_id(k) : NULL;
1033 
1034  y = -1;
1035  if ((k > 0) && (col->type != AST_MEDIA_TYPE_AUDIO)) {
1036  ao2_ref(col, -1);
1037  continue;
1038  }
1039 
1040  if ((k > 0) && (y = codec2index(col)) == -1) {
1041  ao2_ref(col, -1);
1042  continue;
1043  }
1044 
1045  if (k > 0) {
1046  curlen = strlen(col->name);
1047  if (!strcmp(col->name, "slin") ||
1048  !strcmp(col->name, "speex") ||
1049  !strcmp(col->name, "silk")) {
1050  adjust = log10(col->sample_rate / 1000) + 1;
1051  curlen = curlen + adjust;
1052  }
1053  }
1054 
1055  if (curlen < 5) {
1056  curlen = 5;
1057  }
1058 
1059  if (x >= 0 && y >= 0 && matrix_get(x, y)->step) {
1060  /* Actual codec output */
1061  if (a->argv[3] && !strcasecmp(a->argv[3], "comp")) {
1062  compCost = matrix_get(x, y)->comp_cost;
1063  if (compCost == 0 || compCost == 999999) {
1064  ast_str_append(&out, 0, "%*s", curlen + 1, "-");
1065  } else {
1066  ast_str_append(&out, 0, "%*u", curlen + 1, compCost);
1067  }
1068  } else {
1069  ast_str_append(&out, 0, "%*u", curlen + 1, (matrix_get(x, y)->table_cost / 100));
1070  }
1071  } else if (i == 0 && k > 0) {
1072  /* Top row - use a dynamic size */
1073  if (!strcmp(col->name, "slin") ||
1074  !strcmp(col->name, "speex") ||
1075  !strcmp(col->name, "silk")) {
1076  ast_str_append(&out, 0, "%*s%u", curlen - adjust + 1,
1077  col->name, col->sample_rate / 1000);
1078  } else {
1079  ast_str_append(&out, 0, "%*s", curlen + 1, col->name);
1080  }
1081  } else if (k == 0 && i > 0) {
1082  /* Left column - use a static size. */
1083  if (!strcmp(row->name, "slin") ||
1084  !strcmp(row->name, "speex") ||
1085  !strcmp(row->name, "silk")) {
1086  int adjust_row = log10(row->sample_rate / 1000) + 1;
1087  ast_str_append(&out, 0, "%*s%u", longest - adjust_row,
1088  row->name, row->sample_rate / 1000);
1089  } else {
1090  ast_str_append(&out, 0, "%*s", longest, row->name);
1091  }
1092  } else if (x >= 0 && y >= 0) {
1093  /* Codec not supported */
1094  ast_str_append(&out, 0, "%*s", curlen + 1, "-");
1095  } else {
1096  /* Upper left hand corner */
1097  ast_str_append(&out, 0, "%*s", longest, "");
1098  }
1099  ao2_cleanup(col);
1100  }
1101  ast_str_append(&out, 0, "\n");
1102  ast_cli(a->fd, "%s", ast_str_buffer(out));
1103  ao2_cleanup(row);
1104  }
1105  ast_free(out);
1107  return CLI_SUCCESS;
1108 }
1109 
1110 static char *handle_show_translation_path(struct ast_cli_args *a, const char *codec_name, unsigned int sample_rate)
1111 {
1112  int i = 1;
1113  struct ast_str *str = ast_str_alloca(1024);
1114  struct ast_translator *step;
1115  struct ast_codec *dst_codec;
1116  struct ast_codec *src_codec = ast_codec_get(codec_name, AST_MEDIA_TYPE_AUDIO, sample_rate);
1117 
1118  if (!src_codec) {
1119  ast_cli(a->fd, "Source codec \"%s\" is not found.\n", codec_name);
1120  return CLI_FAILURE;
1121  }
1122 
1124  ast_cli(a->fd, "--- Translation paths SRC Codec \"%s\" sample rate %u ---\n",
1125  codec_name, src_codec->sample_rate);
1126 
1127  while ((dst_codec = ast_codec_get_by_id(i))) {
1128  int src, dst;
1129  char src_buffer[64];
1130  char dst_buffer[64];
1131 
1132  ++i;
1133  if (src_codec == dst_codec ||
1134  dst_codec->type != AST_MEDIA_TYPE_AUDIO) {
1135  ao2_ref(dst_codec, -1);
1136  continue;
1137  }
1138 
1139  dst = codec2index(dst_codec);
1140  src = codec2index(src_codec);
1141 
1142  if (src < 0 || dst < 0) {
1143  ast_str_set(&str, 0, "No Translation Path");
1144  } else {
1145  step = matrix_get(src, dst)->step;
1146 
1147  if (step) {
1148  codec_append_name(&step->src_codec, &str);
1149  while (src != dst) {
1150  src = step->dst_fmt_index;
1151  step = matrix_get(src, dst)->step;
1152  if (!step) {
1153  ast_str_append(&str, 0, "->");
1154  codec_append_name(dst_codec, &str);
1155  break;
1156  }
1157  ast_str_append(&str, 0, "->");
1158  codec_append_name(&step->src_codec, &str);
1159  }
1160  }
1161  }
1162 
1163  snprintf(src_buffer, sizeof(src_buffer), "%s:%u", src_codec->name, src_codec->sample_rate);
1164  snprintf(dst_buffer, sizeof(dst_buffer), "%s:%u", dst_codec->name, dst_codec->sample_rate);
1165  ast_cli(a->fd, "\t%-16.16s To %-16.16s: %-60.60s\n",
1166  src_buffer, dst_buffer, ast_str_buffer(str));
1167  ast_str_reset(str);
1168  ao2_ref(dst_codec, -1);
1169  }
1171  ao2_ref(src_codec, -1);
1172  return CLI_SUCCESS;
1173 }
1174 
1175 static char *handle_cli_core_show_translation(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
1176 {
1177  static const char * const option[] = { "recalc", "paths", "comp", NULL };
1178 
1179  switch (cmd) {
1180  case CLI_INIT:
1181  e->command = "core show translation";
1182  e->usage =
1183  "Usage: 'core show translation' can be used in three ways.\n"
1184  " 1. 'core show translation [recalc [<recalc seconds>]\n"
1185  " Displays known codec translators and the cost associated\n"
1186  " with each conversion. If the argument 'recalc' is supplied along\n"
1187  " with optional number of seconds to test a new test will be performed\n"
1188  " as the chart is being displayed.\n"
1189  " 2. 'core show translation paths [codec [sample_rate]]'\n"
1190  " This will display all the translation paths associated with a codec.\n"
1191  " If a codec has multiple sample rates, the sample rate must be\n"
1192  " provided as well.\n"
1193  " 3. 'core show translation comp [<recalc seconds>]'\n"
1194  " Displays known codec translators and the cost associated\n"
1195  " with each conversion. If the argument 'recalc' is supplied along\n"
1196  " with optional number of seconds to test a new test will be performed\n"
1197  " as the chart is being displayed. The resulting numbers in the table\n"
1198  " give the actual computational costs in microseconds.\n";
1199  return NULL;
1200  case CLI_GENERATE:
1201  if (a->pos == 3) {
1202  return ast_cli_complete(a->word, option, -1);
1203  }
1204  if (a->pos == 4 && !strcasecmp(a->argv[3], option[1])) {
1205  return complete_trans_path_choice(a->word);
1206  }
1207  /* BUGBUG - add tab completion for sample rates */
1208  return NULL;
1209  }
1210 
1211  if (a->argc > 6)
1212  return CLI_SHOWUSAGE;
1213 
1214  if (a->argv[3] && !strcasecmp(a->argv[3], option[1]) && a->argc == 5) { /* show paths */
1215  return handle_show_translation_path(a, a->argv[4], 0);
1216  } else if (a->argv[3] && !strcasecmp(a->argv[3], option[1]) && a->argc == 6) {
1217  unsigned int sample_rate;
1218  if (sscanf(a->argv[5], "%30u", &sample_rate) != 1) {
1219  ast_cli(a->fd, "Invalid sample rate: %s.\n", a->argv[5]);
1220  return CLI_FAILURE;
1221  }
1222  return handle_show_translation_path(a, a->argv[4], sample_rate);
1223  } else if (a->argv[3] && (!strcasecmp(a->argv[3], option[0]) || !strcasecmp(a->argv[3], option[2]))) { /* recalc and then fall through to show table */
1224  handle_cli_recalc(a);
1225  } else if (a->argc > 3) { /* wrong input */
1226  return CLI_SHOWUSAGE;
1227  }
1228 
1229  return handle_show_translation_table(a);
1230 }
1231 
1232 static struct ast_cli_entry cli_translate[] = {
1233  AST_CLI_DEFINE(handle_cli_core_show_translation, "Display translation matrix")
1234 };
1235 
1236 /*! \brief register codec translator */
1238 {
1239  struct ast_translator *u;
1240  char tmp[80];
1241  RAII_VAR(struct ast_codec *, src_codec, NULL, ao2_cleanup);
1242  RAII_VAR(struct ast_codec *, dst_codec, NULL, ao2_cleanup);
1243 
1245  if (!src_codec) {
1246  ast_assert(0);
1247  ast_log(LOG_WARNING, "Failed to register translator: unknown source codec %s\n", t->src_codec.name);
1248  return -1;
1249  }
1250 
1252  if (!dst_codec) {
1253  ast_log(LOG_WARNING, "Failed to register translator: unknown destination codec %s\n", t->dst_codec.name);
1254  return -1;
1255  }
1256 
1257  if (add_codec2index(src_codec) || add_codec2index(dst_codec)) {
1258  if (matrix_resize(0)) {
1259  ast_log(LOG_WARNING, "Translator matrix can not represent any more translators. Out of resources.\n");
1260  return -1;
1261  }
1262  add_codec2index(src_codec);
1263  add_codec2index(dst_codec);
1264  }
1265 
1266  if (!mod) {
1267  ast_log(LOG_WARNING, "Missing module pointer, you need to supply one\n");
1268  return -1;
1269  }
1270 
1271  if (!t->buf_size) {
1272  ast_log(LOG_WARNING, "empty buf size, you need to supply one\n");
1273  return -1;
1274  }
1275  if (!t->table_cost && !(t->table_cost = generate_table_cost(src_codec, dst_codec))) {
1276  ast_log(LOG_WARNING, "Table cost could not be generated for %s, "
1277  "Please set table_cost variable on translator.\n", t->name);
1278  return -1;
1279  }
1280 
1281  t->module = mod;
1282  t->src_fmt_index = codec2index(src_codec);
1283  t->dst_fmt_index = codec2index(dst_codec);
1284  t->active = 1;
1285 
1286  if (t->src_fmt_index < 0 || t->dst_fmt_index < 0) {
1287  ast_log(LOG_WARNING, "Invalid translator path: (%s codec is not valid)\n", t->src_fmt_index < 0 ? "starting" : "ending");
1288  return -1;
1289  }
1290  if (t->src_fmt_index >= cur_max_index) {
1291  ast_log(LOG_WARNING, "Source codec %s is larger than cur_max_index\n", t->src_codec.name);
1292  return -1;
1293  }
1294 
1295  if (t->dst_fmt_index >= cur_max_index) {
1296  ast_log(LOG_WARNING, "Destination codec %s is larger than cur_max_index\n", t->dst_codec.name);
1297  return -1;
1298  }
1299 
1300  if (t->buf_size) {
1301  /*
1302  * Align buf_size properly, rounding up to the machine-specific
1303  * alignment for pointers.
1304  */
1305  struct _test_align { void *a, *b; } p;
1306  int align = (char *)&p.b - (char *)&p.a;
1307 
1308  t->buf_size = ((t->buf_size + align - 1) / align) * align;
1309  }
1310 
1311  if (t->frameout == NULL) {
1312  t->frameout = default_frameout;
1313  }
1314 
1315  generate_computational_cost(t, 1);
1316 
1317  ast_verb(5, "Registered translator '%s' from codec %s to %s, table cost, %d, computational cost %d\n",
1318  term_color(tmp, t->name, COLOR_MAGENTA, COLOR_BLACK, sizeof(tmp)),
1319  t->src_codec.name, t->dst_codec.name, t->table_cost, t->comp_cost);
1320 
1322 
1323  /* find any existing translators that provide this same srcfmt/dstfmt,
1324  and put this one in order based on computational cost */
1325  AST_RWLIST_TRAVERSE_SAFE_BEGIN(&translators, u, list) {
1326  if ((u->src_fmt_index == t->src_fmt_index) &&
1327  (u->dst_fmt_index == t->dst_fmt_index) &&
1328  (u->comp_cost > t->comp_cost)) {
1329  AST_RWLIST_INSERT_BEFORE_CURRENT(t, list);
1330  t = NULL;
1331  break;
1332  }
1333  }
1334  AST_RWLIST_TRAVERSE_SAFE_END;
1335 
1336  /* if no existing translator was found for this codec combination,
1337  add it to the beginning of the list */
1338  if (t) {
1339  AST_RWLIST_INSERT_HEAD(&translators, t, list);
1340  }
1341 
1342  matrix_rebuild(0);
1343 
1345 
1346  return 0;
1347 }
1348 
1349 /*! \brief unregister codec translator */
1351 {
1352  char tmp[80];
1353  struct ast_translator *u;
1354  int found = 0;
1355 
1357  AST_RWLIST_TRAVERSE_SAFE_BEGIN(&translators, u, list) {
1358  if (u == t) {
1359  AST_RWLIST_REMOVE_CURRENT(list);
1360  ast_verb(5, "Unregistered translator '%s' from codec %s to %s\n",
1361  term_color(tmp, t->name, COLOR_MAGENTA, COLOR_BLACK, sizeof(tmp)),
1362  t->src_codec.name, t->dst_codec.name);
1363  found = 1;
1364  break;
1365  }
1366  }
1367  AST_RWLIST_TRAVERSE_SAFE_END;
1368 
1369  if (found && !ast_shutting_down()) {
1370  matrix_rebuild(0);
1371  }
1372 
1374 
1375  return (u ? 0 : -1);
1376 }
1377 
1379 {
1381  t->active = 1;
1382  matrix_rebuild(0);
1384 }
1385 
1387 {
1389  t->active = 0;
1390  matrix_rebuild(0);
1392 }
1393 
1394 /*! Calculate the absolute difference between sample rate of two formats. */
1395 #define format_sample_rate_absdiff(fmt1, fmt2) ({ \
1396  unsigned int rate1 = ast_format_get_sample_rate(fmt1); \
1397  unsigned int rate2 = ast_format_get_sample_rate(fmt2); \
1398  (rate1 > rate2 ? rate1 - rate2 : rate2 - rate1); \
1399 })
1400 
1401 /*! \brief Calculate our best translator source format, given costs, and a desired destination */
1403  struct ast_format_cap *src_cap,
1404  struct ast_format **dst_fmt_out,
1405  struct ast_format **src_fmt_out)
1406 {
1407  unsigned int besttablecost = INT_MAX;
1408  unsigned int beststeps = INT_MAX;
1409  struct ast_format *fmt;
1410  struct ast_format *dst;
1411  struct ast_format *src;
1412  RAII_VAR(struct ast_format *, best, NULL, ao2_cleanup);
1413  RAII_VAR(struct ast_format *, bestdst, NULL, ao2_cleanup);
1414  struct ast_format_cap *joint_cap;
1415  int i;
1416  int j;
1417 
1418  if (ast_format_cap_empty(dst_cap) || ast_format_cap_empty(src_cap)) {
1419  ast_log(LOG_ERROR, "Cannot determine best translation path since one capability supports no formats\n");
1420  return -1;
1421  }
1422 
1424  if (!joint_cap) {
1425  return -1;
1426  }
1427  ast_format_cap_get_compatible(dst_cap, src_cap, joint_cap);
1428 
1429  for (i = 0; i < ast_format_cap_count(joint_cap); ++i, ao2_cleanup(fmt)) {
1430  fmt = ast_format_cap_get_format(joint_cap, i);
1431  if (!fmt
1432  || ast_format_get_type(fmt) != AST_MEDIA_TYPE_AUDIO) {
1433  continue;
1434  }
1435 
1436  if (!best
1438  ao2_replace(best, fmt);
1439  }
1440  }
1441  ao2_ref(joint_cap, -1);
1442 
1443  if (best) {
1444  ao2_replace(*dst_fmt_out, best);
1445  ao2_replace(*src_fmt_out, best);
1446  return 0;
1447  }
1448 
1449  /* need to translate */
1451  for (i = 0; i < ast_format_cap_count(dst_cap); ++i, ao2_cleanup(dst)) {
1452  dst = ast_format_cap_get_format(dst_cap, i);
1453  if (!dst
1454  || ast_format_get_type(dst) != AST_MEDIA_TYPE_AUDIO) {
1455  continue;
1456  }
1457 
1458  for (j = 0; j < ast_format_cap_count(src_cap); ++j, ao2_cleanup(src)) {
1459  int x;
1460  int y;
1461 
1462  src = ast_format_cap_get_format(src_cap, j);
1463  if (!src
1464  || ast_format_get_type(src) != AST_MEDIA_TYPE_AUDIO) {
1465  continue;
1466  }
1467 
1468  x = format2index(src);
1469  y = format2index(dst);
1470  if (x < 0 || y < 0) {
1471  continue;
1472  }
1473  if (!matrix_get(x, y) || !(matrix_get(x, y)->step)) {
1474  continue;
1475  }
1476  if (matrix_get(x, y)->table_cost < besttablecost
1477  || matrix_get(x, y)->multistep < beststeps) {
1478  /* better than what we have so far */
1479  ao2_replace(best, src);
1480  ao2_replace(bestdst, dst);
1481  besttablecost = matrix_get(x, y)->table_cost;
1482  beststeps = matrix_get(x, y)->multistep;
1483  } else if (matrix_get(x, y)->table_cost == besttablecost
1484  && matrix_get(x, y)->multistep == beststeps) {
1485  int replace = 0;
1486  unsigned int gap_selected = format_sample_rate_absdiff(best, bestdst);
1487  unsigned int gap_current = format_sample_rate_absdiff(src, dst);
1488 
1489  if (gap_current < gap_selected) {
1490  /* better than what we have so far */
1491  replace = 1;
1492  } else if (gap_current == gap_selected) {
1493  int src_quality, best_quality;
1494  struct ast_codec *src_codec, *best_codec;
1495 
1496  src_codec = ast_format_get_codec(src);
1497  best_codec = ast_format_get_codec(best);
1498  src_quality = src_codec->quality;
1499  best_quality = best_codec->quality;
1500 
1501  ao2_cleanup(src_codec);
1502  ao2_cleanup(best_codec);
1503 
1504  /* We have a tie, so choose the format with the higher quality, if they differ. */
1505  if (src_quality > best_quality) {
1506  /* Better than what we had before. */
1507  replace = 1;
1508  ast_debug(2, "Tiebreaker: preferring format %s (%d) to %s (%d)\n", ast_format_get_name(src), src_quality,
1509  ast_format_get_name(best), best_quality);
1510  } else {
1511  /* This isn't necessarily indicative of a problem, but in reality this shouldn't really happen, unless
1512  * there are 2 formats that are basically the same. */
1513  ast_debug(1, "Completely ambiguous tie between formats %s and %s (quality %d): sticking with %s, but this is arbitrary\n",
1514  ast_format_get_name(src), ast_format_get_name(best), best_quality, ast_format_get_name(best));
1515  }
1516  }
1517  if (replace) {
1518  ao2_replace(best, src);
1519  ao2_replace(bestdst, dst);
1520  besttablecost = matrix_get(x, y)->table_cost;
1521  beststeps = matrix_get(x, y)->multistep;
1522  }
1523  }
1524  }
1525  }
1527 
1528  if (!best) {
1529  return -1;
1530  }
1531  ao2_replace(*dst_fmt_out, bestdst);
1532  ao2_replace(*src_fmt_out, best);
1533  return 0;
1534 }
1535 
1536 unsigned int ast_translate_path_steps(struct ast_format *dst_format, struct ast_format *src_format)
1537 {
1538  unsigned int res = -1;
1539  /* convert bitwise format numbers into array indices */
1540  int src = format2index(src_format);
1541  int dest = format2index(dst_format);
1542 
1543  if (src < 0 || dest < 0) {
1544  ast_log(LOG_WARNING, "No translator path: (%s codec is not valid)\n", src < 0 ? "starting" : "ending");
1545  return -1;
1546  }
1548 
1549  if (matrix_get(src, dest)->step) {
1550  res = matrix_get(src, dest)->multistep + 1;
1551  }
1552 
1554 
1555  return res;
1556 }
1557 
1558 static void check_translation_path(
1559  struct ast_format_cap *dest, struct ast_format_cap *src,
1560  struct ast_format_cap *result, struct ast_format *src_fmt,
1561  enum ast_media_type type)
1562 {
1563  int i;
1564 
1565  if (ast_format_get_type(src_fmt) != type) {
1566  return;
1567  }
1568 
1569  /* For a given source format, traverse the list of
1570  known formats to determine whether there exists
1571  a translation path from the source format to the
1572  destination format. */
1573  for (i = ast_format_cap_count(result) - 1; 0 <= i; i--) {
1574  int index, src_index;
1575  RAII_VAR(struct ast_format *, fmt, ast_format_cap_get_format(result, i), ao2_cleanup);
1576 
1577  if (ast_format_get_type(fmt) != type) {
1578  continue;
1579  }
1580 
1581  /* if this is not a desired format, nothing to do */
1583  continue;
1584  }
1585 
1586  /* if the source is supplying this format, then
1587  we can leave it in the result */
1589  continue;
1590  }
1591 
1592  /* if this is a pass-through format, not in the source,
1593  we cannot transcode. Therefore, remove it from the result */
1594  src_index = format2index(src_fmt);
1595  index = format2index(fmt);
1596  if (src_index < 0 || index < 0) {
1597  ast_format_cap_remove(result, fmt);
1598  continue;
1599  }
1600 
1601  /* if we don't have a translation path from the src
1602  to this format, remove it from the result */
1603  if (!matrix_get(src_index, index)->step) {
1604  ast_format_cap_remove(result, fmt);
1605  continue;
1606  }
1607 
1608  /* now check the opposite direction */
1609  if (!matrix_get(index, src_index)->step) {
1610  ast_format_cap_remove(result, fmt);
1611  }
1612  }
1613 
1614 }
1615 
1616 void ast_translate_available_formats(struct ast_format_cap *dest, struct ast_format_cap *src, struct ast_format_cap *result)
1617 {
1618  struct ast_format *cur_dest, *cur_src;
1619  int index;
1620 
1621  for (index = 0; index < ast_format_cap_count(dest); ++index) {
1622  if (!(cur_dest = ast_format_cap_get_format(dest, index))) {
1623  continue;
1624  }
1625 
1626  /* We give preference to a joint format structure if possible */
1627  if ((cur_src = ast_format_cap_get_compatible_format(src, cur_dest))) {
1628  ast_format_cap_append(result, cur_src, 0);
1629  ao2_ref(cur_src, -1);
1630  } else {
1631  /* Otherwise we just use the destination format */
1632  ast_format_cap_append(result, cur_dest, 0);
1633  }
1634  ao2_ref(cur_dest, -1);
1635  }
1636 
1637  /* if we don't have a source format, we just have to try all
1638  possible destination formats */
1639  if (!src) {
1640  return;
1641  }
1642 
1643  for (index = 0; index < ast_format_cap_count(src); ++index) {
1644  if (!(cur_src = ast_format_cap_get_format(src, index))) {
1645  continue;
1646  }
1647 
1649  check_translation_path(dest, src, result,
1650  cur_src, AST_MEDIA_TYPE_AUDIO);
1651  check_translation_path(dest, src, result,
1652  cur_src, AST_MEDIA_TYPE_VIDEO);
1654  ao2_ref(cur_src, -1);
1655  }
1656 }
1657 
1658 static void translate_shutdown(void)
1659 {
1660  int x;
1661  ast_cli_unregister_multiple(cli_translate, ARRAY_LEN(cli_translate));
1662 
1663  ast_rwlock_wrlock(&tablelock);
1664  for (x = 0; x < index_size; x++) {
1665  ast_free(__matrix[x]);
1666  }
1667  ast_free(__matrix);
1668  __matrix = NULL;
1669  ast_free(__indextable);
1670  __indextable = NULL;
1671  ast_rwlock_unlock(&tablelock);
1672  ast_rwlock_destroy(&tablelock);
1673 }
1674 
1676 {
1677  int res = 0;
1678  ast_rwlock_init(&tablelock);
1679  res = matrix_resize(1);
1680  res |= ast_cli_register_multiple(cli_translate, ARRAY_LEN(cli_translate));
1681  ast_register_cleanup(translate_shutdown);
1682  return res;
1683 }
int datalen
actual space used in outbuf
Definition: translate.h:218
#define ast_frdup(fr)
Copies a frame.
static int index_size
Definition: translate.c:97
enum ast_media_type ast_format_get_type(const struct ast_format *format)
Get the media type of a format.
Definition: format.c:354
Asterisk locking-related definitions:
const char * name
Name for this codec.
Definition: codec.h:46
Asterisk main include file. File version handling, generic pbx functions.
int ast_shutting_down(void)
Definition: asterisk.c:1876
const char * format
Definition: translate.h:143
struct ast_codec * ast_format_get_codec(const struct ast_format *format)
Get the codec associated with a format.
Definition: format.c:324
int(* newpvt)(struct ast_trans_pvt *)
Definition: translate.h:151
static void matrix_rebuild(int samples)
rebuild a translation matrix.
Definition: translate.c:825
Descriptor of a translator.
Definition: translate.h:137
int ast_cli_unregister_multiple(struct ast_cli_entry *e, int len)
Unregister multiple commands.
Definition: clicompat.c:30
Support for translation of data formats. translate.c.
static ast_rwlock_t tablelock
Definition: translate.c:87
int ast_tveq(struct timeval _a, struct timeval _b)
Returns true if the two struct timeval arguments are equal.
Definition: time.h:147
struct ast_format * ast_format_create(struct ast_codec *codec)
Create a new media format.
Definition: format.c:196
struct ast_codec * ast_codec_get_by_id(int id)
Retrieve a codec given the unique identifier.
Definition: codec.c:338
struct ast_frame * ast_trans_frameout(struct ast_trans_pvt *pvt, int datalen, int samples)
generic frameout routine. If samples and datalen are 0, take whatever is in pvt and reset them...
Definition: translate.c:439
unsigned int id
Internal unique identifier for this codec, set at registration time (starts at 1) ...
Definition: codec.h:44
struct ast_frame f
Definition: translate.h:215
descriptor for a cli entry.
Definition: cli.h:171
#define ast_rwlock_init(rwlock)
wrapper for rwlock with tracking enabled
Definition: lock.h:224
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
Definition: strings.h:761
#define AST_RWLIST_RDLOCK(head)
Read locks a list.
Definition: linkedlists.h:78
int ast_tvzero(const struct timeval t)
Returns true if the argument is 0,0.
Definition: time.h:117
#define AST_LIST_NEXT(elm, field)
Returns the next entry in the list after the given entry.
Definition: linkedlists.h:439
#define AST_RWLIST_WRLOCK(head)
Write locks a list.
Definition: linkedlists.h:52
unsigned int ast_translate_path_steps(struct ast_format *dst_format, struct ast_format *src_format)
Returns the number of steps required to convert from 'src' to 'dest'.
Definition: translate.c:1536
Definition of a media format.
Definition: format.c:43
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
#define ast_cli_register_multiple(e, len)
Register multiple commands.
Definition: cli.h:265
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
Definition: time.h:159
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
const char * ast_format_get_name(const struct ast_format *format)
Get the name associated with a format.
Definition: format.c:334
#define ast_strdup(str)
A wrapper for strdup()
Definition: astmm.h:241
struct ast_trans_pvt * next
Definition: translate.h:227
void ast_translator_activate(struct ast_translator *t)
Activate a previously deactivated translator.
Definition: translate.c:1378
struct ast_codec * ast_codec_get(const char *name, enum ast_media_type type, unsigned int sample_rate)
Retrieve a codec given a name, type, and sample rate.
Definition: codec.c:327
void * pvt
Definition: translate.h:219
struct ast_translator * step
Definition: translate.c:60
void ast_translate_available_formats(struct ast_format_cap *dest, struct ast_format_cap *src, struct ast_format_cap *result)
Find available formats.
Definition: translate.c:1616
struct ast_frame_subclass subclass
#define ast_format_cache_get(name)
Retrieve a named format from the cache.
Definition: format_cache.h:278
static int framein(struct ast_trans_pvt *pvt, struct ast_frame *f)
framein wrapper, deals with bound checks.
Definition: translate.c:397
Media Format API.
char * ast_cli_complete(const char *word, const char *const choices[], int pos)
Definition: main/cli.c:1846
enum ast_format_cmp_res ast_format_cap_iscompatible_format(const struct ast_format_cap *cap, const struct ast_format *format)
Find if ast_format is within the capabilities of the ast_format_cap object.
Definition: format_cap.c:581
#define AST_RWLIST_HEAD_STATIC(name, type)
Defines a structure to be used to hold a read/write list of specified type, statically initialized...
Definition: linkedlists.h:333
#define ao2_bump(obj)
Bump refcount on an AO2 object by one, returning the object.
Definition: astobj2.h:480
static struct translator_path ** __matrix
a matrix that, for any pair of supported formats, indicates the total cost of translation and the fir...
Definition: translate.c:77
int ast_str_set(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Set a dynamic string using variable arguments.
Definition: strings.h:1113
struct ast_module * module
Definition: translate.h:187
void ast_translator_free_path(struct ast_trans_pvt *p)
Frees a translator path Frees the given translator path structure.
Definition: translate.c:476
enum ast_format_cmp_res ast_format_cmp(const struct ast_format *format1, const struct ast_format *format2)
Compare two formats.
Definition: format.c:201
#define format_sample_rate_absdiff(fmt1, fmt2)
Definition: translate.c:1395
General Asterisk PBX channel definitions.
int ast_register_cleanup(void(*func)(void))
Register a function to be executed before Asterisk gracefully exits.
Definition: clicompat.c:19
#define AST_FRIENDLY_OFFSET
Offset into a frame's data buffer.
const char * src
#define ao2_ref(o, delta)
Reference/unreference an object and return the old refcount.
Definition: astobj2.h:459
Scheduler Routines (derived from cheops)
Asterisk internal frame definitions.
struct ast_format * ast_format_cap_get_compatible_format(const struct ast_format_cap *cap, const struct ast_format *format)
Find if input ast_format is within the capabilities of the ast_format_cap object then return the comp...
Definition: format_cap.c:546
struct timeval ast_samp2tv(unsigned int _nsamp, unsigned int _rate)
Returns a timeval corresponding to the duration of n samples at rate r. Useful to convert samples to ...
Definition: time.h:282
unsigned int quality
Format quality, on scale from 0 to 150 (100 is ulaw, the reference). This allows better format to be ...
Definition: codec.h:82
#define ast_format_cap_append(cap, format, framing)
Add format capability to capabilities structure.
Definition: format_cap.h:99
int ast_translate_init(void)
Initialize the translation matrix and index to format conversion table.
Definition: translate.c:1675
A set of macros to manage forward-linked lists.
#define ast_debug(level,...)
Log a DEBUG message.
int buf_size
size of outbuf, in bytes. Mandatory. The wrapper code will also allocate an AST_FRIENDLY_OFFSET space...
Definition: translate.h:182
#define ast_format_cap_alloc(flags)
Allocate a new ast_format_cap structure.
Definition: format_cap.h:49
char * term_color(char *outbuf, const char *inbuf, int fgcolor, int bgcolor, int maxout)
Colorize a specified string by adding terminal color codes.
Definition: term.c:235
void(* destroy)(struct ast_trans_pvt *pvt)
Definition: translate.h:166
static struct ast_trans_pvt * newpvt(struct ast_translator *t, struct ast_format *explicit_dst)
Allocate the descriptor, required outbuf space, and possibly desc.
Definition: translate.c:312
the list of translators
Definition: codec_dahdi.c:281
struct ast_codec dst_codec
Definition: translate.h:140
void(* feedback)(struct ast_trans_pvt *pvt, struct ast_frame *feedback)
Definition: translate.h:162
struct ast_format * explicit_dst
Definition: translate.h:237
Support for dynamic strings.
Definition: strings.h:623
Format capabilities structure, holds formats + preference order + etc.
Definition: format_cap.c:54
Default structure for translators, with the basic fields and buffers, all allocated as part of the sa...
Definition: translate.h:213
static unsigned int * __indextable
table for converting index to format values.
Definition: translate.c:84
uint32_t table_cost
Definition: translate.c:61
struct timeval ast_tvadd(struct timeval a, struct timeval b)
Returns the sum of two timevals a + b.
Definition: extconf.c:2282
struct ast_codec src_codec
Definition: translate.h:139
#define ast_module_ref(mod)
Hold a reference to the module.
Definition: module.h:457
int __ast_register_translator(struct ast_translator *t, struct ast_module *mod)
register codec translator
Definition: translate.c:1237
uint8_t multistep
Definition: translate.c:63
union ast_frame::@224 data
char * command
Definition: cli.h:186
#define ast_calloc(num, len)
A wrapper for calloc()
Definition: astmm.h:202
struct ast_translator::@290 list
int ast_unregister_translator(struct ast_translator *t)
unregister codec translator
Definition: translate.c:1350
#define ast_frisolate(fr)
Makes a frame independent of any static storage.
struct ast_frame *(* sample)(void)
Definition: translate.h:170
unsigned int sample_rate
Sample rate (number of samples carried in a second)
Definition: codec.h:52
struct timeval delivery
const char * usage
Definition: cli.h:177
#define ast_module_unref(mod)
Release a reference to the module.
Definition: module.h:483
struct ast_frame * ast_translate(struct ast_trans_pvt *path, struct ast_frame *f, int consume)
do the actual translation
Definition: translate.c:566
#define MAX_RECALC
Definition: translate.c:54
struct ast_frame ast_null_frame
Definition: main/frame.c:79
void ast_str_reset(struct ast_str *buf)
Reset the content of a dynamic string. Useful before a series of ast_str_append.
Definition: strings.h:693
#define ao2_replace(dst, src)
Replace one object reference with another cleaning up the original.
Definition: astobj2.h:501
Structure for rwlock and tracking information.
Definition: lock.h:157
Standard Command Line Interface.
struct ast_trans_pvt * ast_translator_build_path(struct ast_format *dst, struct ast_format *src)
Build a chain of translators based upon the given source and dest formats.
Definition: translate.c:486
struct timeval ast_tv(ast_time_t sec, ast_suseconds_t usec)
Returns a timeval from sec, usec.
Definition: time.h:235
void ast_translator_deactivate(struct ast_translator *t)
Deactivate a translator.
Definition: translate.c:1386
struct ast_frame *(* frameout)(struct ast_trans_pvt *pvt)
Definition: translate.h:158
unsigned int ast_format_get_sample_rate(const struct ast_format *format)
Get the sample rate of a media format.
Definition: format.c:379
Data structure associated with a single frame of data.
enum ast_media_type type
Type of media this codec contains.
Definition: codec.h:50
static int cur_max_index
Definition: translate.c:95
Handy terminal functions for vt* terms.
struct timeval ast_tvsub(struct timeval a, struct timeval b)
Returns the difference of two timevals a - b.
Definition: extconf.c:2297
ast_media_type
Types of media.
Definition: codec.h:30
#define AST_RWLIST_UNLOCK(head)
Attempts to unlock a read/write based list.
Definition: linkedlists.h:151
enum ast_frame_type frametype
int ast_format_cap_remove(struct ast_format_cap *cap, struct ast_format *format)
Remove format capability from capability structure.
Definition: format_cap.c:495
int ast_format_cap_empty(const struct ast_format_cap *cap)
Determine if a format cap has no formats in it.
Definition: format_cap.c:744
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
struct ast_format * format
int ast_cli_completion_add(char *value)
Add a result to a request for completion options.
Definition: main/cli.c:2761
struct ast_format * ast_format_slin
Built-in cached signed linear 8kHz format.
Definition: format_cache.c:41
Asterisk module definitions.
#define RAII_VAR(vartype, varname, initval, dtor)
Declare a variable that will call a destructor function when it goes out of scope.
Definition: utils.h:941
int ast_format_cap_get_compatible(const struct ast_format_cap *cap1, const struct ast_format_cap *cap2, struct ast_format_cap *result)
Find the compatible formats between two capabilities structures.
Definition: format_cap.c:628
int ast_translator_best_choice(struct ast_format_cap *dst_cap, struct ast_format_cap *src_cap, struct ast_format **dst_fmt_out, struct ast_format **src_fmt_out)
Calculate our best translator source format, given costs, and a desired destination.
Definition: translate.c:1402
unsigned int ast_format_get_codec_id(const struct ast_format *format)
Get the codec identifier associated with a format.
Definition: format.c:329
Represents a media codec within Asterisk.
Definition: codec.h:42
const char * ast_translate_path_to_str(struct ast_trans_pvt *p, struct ast_str **str)
Puts a string representation of the translation path into outbuf.
Definition: translate.c:930
struct ast_format * ast_format_cache_get_slin_by_rate(unsigned int rate)
Retrieve the best signed linear format given a sample rate.
Definition: format_cache.c:512
char name[80]
Definition: translate.h:138
int(* framein)(struct ast_trans_pvt *pvt, struct ast_frame *in)
Definition: translate.h:154
#define ast_str_create(init_len)
Create a malloc'ed dynamic length string.
Definition: strings.h:659
uint32_t comp_cost
Definition: translate.c:62
int buffer_samples
size of outbuf, in samples. Leave it 0 if you want the framein callback deal with the frame...
Definition: translate.h:177