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