Asterisk - The Open Source Telephony Project  GIT-master-16dfe8f
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  if (f->datalen == 0) { /* perform native PLC if available */
412  /* If the codec has native PLC, then do that */
413  if (!pvt->t->native_plc)
414  return 0;
415  }
416  if (pvt->samples + f->samples > pvt->t->buffer_samples) {
417  ast_log(LOG_WARNING, "Out of buffer space\n");
418  return -1;
419  }
420  }
421  /* we require a framein routine, wouldn't know how to do
422  * it otherwise.
423  */
424  return pvt->t->framein(pvt, f);
425 }
426 
427 /*! \brief generic frameout routine.
428  * If samples and datalen are 0, take whatever is in pvt
429  * and reset them, otherwise take the values in the caller and
430  * leave alone the pvt values.
431  */
433  int datalen, int samples)
434 {
435  struct ast_frame *f = &pvt->f;
436 
437  if (samples) {
438  f->samples = samples;
439  } else {
440  if (pvt->samples == 0) {
441  return NULL;
442  }
443  f->samples = pvt->samples;
444  pvt->samples = 0;
445  }
446  if (datalen) {
447  f->datalen = datalen;
448  f->data.ptr = pvt->outbuf.c;
449  } else {
450  f->datalen = pvt->datalen;
451  if (!f->datalen) {
452  f->data.ptr = NULL;
453  } else {
454  f->data.ptr = pvt->outbuf.c;
455  }
456  pvt->datalen = 0;
457  }
458 
459  return ast_frisolate(f);
460 }
461 
462 static struct ast_frame *default_frameout(struct ast_trans_pvt *pvt)
463 {
464  return ast_trans_frameout(pvt, 0, 0);
465 }
466 
467 /* end of callback wrappers and helpers */
468 
470 {
471  struct ast_trans_pvt *pn = p;
472  while ( (p = pn) ) {
473  pn = p->next;
474  destroy(p);
475  }
476 }
477 
478 /*! \brief Build a chain of translators based upon the given source and dest formats */
480 {
481  struct ast_trans_pvt *head = NULL, *tail = NULL;
482  int src_index, dst_index;
483 
484  src_index = format2index(src);
485  dst_index = format2index(dst);
486 
487  if (src_index < 0 || dst_index < 0) {
488  ast_log(LOG_WARNING, "No translator path: (%s codec is not valid)\n", src_index < 0 ? "starting" : "ending");
489  return NULL;
490  }
491 
493 
494  while (src_index != dst_index) {
495  struct ast_trans_pvt *cur;
496  struct ast_format *explicit_dst = NULL;
497  struct ast_translator *t = matrix_get(src_index, dst_index)->step;
498  if (!t) {
499  ast_log(LOG_WARNING, "No translator path from %s to %s\n",
503  return NULL;
504  }
506  explicit_dst = dst;
507  }
508  if (!(cur = newpvt(t, explicit_dst))) {
509  ast_log(LOG_WARNING, "Failed to build translator step from %s to %s\n",
513  return NULL;
514  }
515  if (!head) {
516  head = cur;
517  } else {
518  tail->next = cur;
519  }
520  tail = cur;
521  cur->nextin = cur->nextout = ast_tv(0, 0);
522  /* Keep going if this isn't the final destination */
523  src_index = cur->t->dst_fmt_index;
524  }
525 
527  return head;
528 }
529 
530 static struct ast_frame *generate_interpolated_slin(struct ast_trans_pvt *p, struct ast_frame *f)
531 {
532  struct ast_frame res = { AST_FRAME_VOICE };
533 
534  /*
535  * If we've gotten here then we should have an interpolated frame that was not handled
536  * by the translation codec. So create an interpolated frame in the appropriate format
537  * that was going to be written. This frame might be handled later by other resources.
538  * For instance, generic plc.
539  *
540  * Note, generic plc is currently only available for the format type 'slin' (8KHz only -
541  * The generic plc code appears to have been based around that). Generic plc is filled
542  * in later on frame write.
543  */
544  if (!ast_opt_generic_plc || f->datalen != 0 ||
546  return NULL;
547  }
548 
549  res.subclass.format = ast_format_cache_get_slin_by_rate(8000); /* ref bumped on dup */
550  res.samples = f->samples;
551  res.datalen = 0;
552  res.data.ptr = NULL;
554 
555  return ast_frdup(&res);
556 }
557 
558 /*! \brief do the actual translation */
559 struct ast_frame *ast_translate(struct ast_trans_pvt *path, struct ast_frame *f, int consume)
560 {
561  struct ast_trans_pvt *p = path;
562  struct ast_frame *out;
563  struct timeval delivery;
564  int has_timing_info;
565  long ts;
566  long len;
567  int seqno;
568 
569  if (f->frametype == AST_FRAME_RTCP) {
570  /* Just pass the feedback to the right callback, if it exists.
571  * This "translation" does nothing so return a null frame. */
572  struct ast_trans_pvt *tp;
573  for (tp = p; tp; tp = tp->next) {
574  if (tp->t->feedback)
575  tp->t->feedback(tp, f);
576  }
577  return &ast_null_frame;
578  }
579 
580  has_timing_info = ast_test_flag(f, AST_FRFLAG_HAS_TIMING_INFO);
581  ts = f->ts;
582  len = f->len;
583  seqno = f->seqno;
584 
585  if (!ast_tvzero(f->delivery)) {
586  if (!ast_tvzero(path->nextin)) {
587  /* Make sure this is in line with what we were expecting */
588  if (!ast_tveq(path->nextin, f->delivery)) {
589  /* The time has changed between what we expected and this
590  most recent time on the new packet. If we have a
591  valid prediction adjust our output time appropriately */
592  if (!ast_tvzero(path->nextout)) {
593  path->nextout = ast_tvadd(path->nextout,
594  ast_tvsub(f->delivery, path->nextin));
595  }
596  path->nextin = f->delivery;
597  }
598  } else {
599  /* This is our first pass. Make sure the timing looks good */
600  path->nextin = f->delivery;
601  path->nextout = f->delivery;
602  }
603  /* Predict next incoming sample */
604  path->nextin = ast_tvadd(path->nextin, ast_samp2tv(
606  }
607  delivery = f->delivery;
608  for (out = f; out && p ; p = p->next) {
609  struct ast_frame *current = out;
610 
611  do {
612  framein(p, current);
613  current = AST_LIST_NEXT(current, frame_list);
614  } while (current);
615  if (out != f) {
616  ast_frfree(out);
617  }
618  out = p->t->frameout(p);
619  }
620 
621  if (!out) {
622  out = generate_interpolated_slin(path, f);
623  }
624 
625  if (out) {
626  /* we have a frame, play with times */
627  if (!ast_tvzero(delivery)) {
628  struct ast_frame *current = out;
629 
630  do {
631  /* Regenerate prediction after a discontinuity */
632  if (ast_tvzero(path->nextout)) {
633  path->nextout = ast_tvnow();
634  }
635 
636  /* Use next predicted outgoing timestamp */
637  current->delivery = path->nextout;
638 
639  /* Invalidate prediction if we're entering a silence period */
640  if (current->frametype == AST_FRAME_CNG) {
641  path->nextout = ast_tv(0, 0);
642  /* Predict next outgoing timestamp from samples in this
643  frame. */
644  } else {
645  path->nextout = ast_tvadd(path->nextout, ast_samp2tv(
646  current->samples, ast_format_get_sample_rate(current->subclass.format)));
647  }
648 
649  if (f->samples != current->samples && ast_test_flag(current, AST_FRFLAG_HAS_TIMING_INFO)) {
650  ast_debug(4, "Sample size different %d vs %d\n", f->samples, current->samples);
652  }
653  current = AST_LIST_NEXT(current, frame_list);
654  } while (current);
655  } else {
656  out->delivery = ast_tv(0, 0);
657  ast_set2_flag(out, has_timing_info, AST_FRFLAG_HAS_TIMING_INFO);
658  if (has_timing_info) {
659  out->ts = ts;
660  out->len = len;
661  out->seqno = seqno;
662  }
663  /* Invalidate prediction if we're entering a silence period */
664  if (out->frametype == AST_FRAME_CNG) {
665  path->nextout = ast_tv(0, 0);
666  }
667  }
668  }
669  if (consume) {
670  ast_frfree(f);
671  }
672  return out;
673 }
674 
675 /*!
676  * \internal
677  * \brief Compute the computational cost of a single translation step.
678  *
679  * \note This function is only used to decide which translation path to
680  * use between two translators with identical src and dst formats. Computational
681  * cost acts only as a tie breaker. This is done so hardware translators
682  * can naturally have precedence over software translators.
683  */
684 static void generate_computational_cost(struct ast_translator *t, int seconds)
685 {
686  int num_samples = 0;
687  struct ast_trans_pvt *pvt;
688  struct rusage start;
689  struct rusage end;
690  int cost;
691  int out_rate = t->dst_codec.sample_rate;
692 
693  if (!seconds) {
694  seconds = 1;
695  }
696 
697  /* If they don't make samples, give them a terrible score */
698  if (!t->sample) {
699  ast_debug(3, "Translator '%s' does not produce sample frames.\n", t->name);
700  t->comp_cost = 999999;
701  return;
702  }
703 
704  pvt = newpvt(t, NULL);
705  if (!pvt) {
706  ast_log(LOG_WARNING, "Translator '%s' appears to be broken and will probably fail.\n", t->name);
707  t->comp_cost = 999999;
708  return;
709  }
710 
711  getrusage(RUSAGE_SELF, &start);
712 
713  /* Call the encoder until we've processed the required number of samples */
714  while (num_samples < seconds * out_rate) {
715  struct ast_frame *f = t->sample();
716  if (!f) {
717  ast_log(LOG_WARNING, "Translator '%s' failed to produce a sample frame.\n", t->name);
718  destroy(pvt);
719  t->comp_cost = 999999;
720  return;
721  }
722  framein(pvt, f);
723  ast_frfree(f);
724  while ((f = t->frameout(pvt))) {
725  num_samples += f->samples;
726  ast_frfree(f);
727  }
728  }
729 
730  getrusage(RUSAGE_SELF, &end);
731 
732  cost = ((end.ru_utime.tv_sec - start.ru_utime.tv_sec) * 1000000) + end.ru_utime.tv_usec - start.ru_utime.tv_usec;
733  cost += ((end.ru_stime.tv_sec - start.ru_stime.tv_sec) * 1000000) + end.ru_stime.tv_usec - start.ru_stime.tv_usec;
734 
735  destroy(pvt);
736 
737  t->comp_cost = cost / seconds;
738 
739  if (!t->comp_cost) {
740  t->comp_cost = 1;
741  }
742 }
743 
744 /*!
745  * \internal
746  *
747  * \brief If no table cost value was pre set by the translator. An attempt is made to
748  * automatically generate that cost value from the cost table based on our src and
749  * dst formats.
750  *
751  * \note This function allows older translators built before the translation cost
752  * changed away from using onely computational time to continue to be registered
753  * correctly. It is expected that translators built after the introduction of this
754  * function will manually assign their own table cost value.
755  *
756  * \note This function is safe to use on any audio formats that used to be defined in the
757  * first 64 bits of the old bit field codec representation.
758  *
759  * \retval Table Cost value greater than 0.
760  * \retval 0 on error.
761  */
762 static int generate_table_cost(struct ast_codec *src, struct ast_codec *dst)
763 {
764  int src_rate = src->sample_rate;
765  int src_ll = 0;
766  int dst_rate = dst->sample_rate;
767  int dst_ll = 0;
768 
769  if ((src->type != AST_MEDIA_TYPE_AUDIO) ||
770  (dst->type != AST_MEDIA_TYPE_AUDIO)) {
771  /* This method of generating table cost is limited to audio.
772  * Translators for media other than audio must manually set their
773  * table cost. */
774  return 0;
775  }
776 
777  src_ll = !strcmp(src->name, "slin");
778  dst_ll = !strcmp(dst->name, "slin");
779  if (src_ll) {
780  if (dst_ll && (src_rate == dst_rate)) {
782  } else if (!dst_ll && (src_rate == dst_rate)) {
784  } else if (dst_ll && (src_rate < dst_rate)) {
786  } else 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 {
794  }
795  } else {
796  if (dst_ll && (src_rate == dst_rate)) {
798  } else if (!dst_ll && (src_rate == dst_rate)) {
800  } else if (dst_ll && (src_rate < dst_rate)) {
802  } else 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 {
810  }
811  }
812 }
813 
814 /*!
815  * \brief rebuild a translation matrix.
816  * \note This function expects the list of translators to be locked
817 */
818 static void matrix_rebuild(int samples)
819 {
820  struct ast_translator *t;
821  int newtablecost;
822  int x; /* source format index */
823  int y; /* intermediate format index */
824  int z; /* destination format index */
825 
826  ast_debug(1, "Resetting translation matrix\n");
827 
828  matrix_clear();
829 
830  /* first, compute all direct costs */
832  if (!t->active) {
833  continue;
834  }
835 
836  x = t->src_fmt_index;
837  z = t->dst_fmt_index;
838 
839  if (samples) {
840  generate_computational_cost(t, samples);
841  }
842 
843  /* This new translator is the best choice if any of the below are true.
844  * 1. no translation path is set between x and z yet.
845  * 2. the new table cost is less.
846  * 3. the new computational cost is less. Computational cost is only used
847  * to break a tie between two identical translation paths.
848  */
849  if (!matrix_get(x, z)->step ||
850  (t->table_cost < matrix_get(x, z)->step->table_cost) ||
851  (t->comp_cost < matrix_get(x, z)->step->comp_cost)) {
852 
853  matrix_get(x, z)->step = t;
854  matrix_get(x, z)->table_cost = t->table_cost;
855  }
856  }
857 
858  /*
859  * For each triple x, y, z of distinct formats, check if there is
860  * a path from x to z through y which is cheaper than what is
861  * currently known, and in case, update the matrix.
862  * Repeat until the matrix is stable.
863  */
864  for (;;) {
865  int changed = 0;
866  for (x = 0; x < cur_max_index; x++) { /* source format */
867  for (y = 0; y < cur_max_index; y++) { /* intermediate format */
868  if (x == y) { /* skip ourselves */
869  continue;
870  }
871  for (z = 0; z < cur_max_index; z++) { /* dst format */
872  if ((z == x || z == y) || /* skip null conversions */
873  !matrix_get(x, y)->step || /* no path from x to y */
874  !matrix_get(y, z)->step) { /* no path from y to z */
875  continue;
876  }
877 
878  /* calculate table cost from x->y->z */
879  newtablecost = matrix_get(x, y)->table_cost + matrix_get(y, z)->table_cost;
880 
881  /* if no step already exists between x and z OR the new cost of using the intermediate
882  * step is cheaper, use this step. */
883  if (!matrix_get(x, z)->step || (newtablecost < matrix_get(x, z)->table_cost)) {
884  matrix_get(x, z)->step = matrix_get(x, y)->step;
885  matrix_get(x, z)->table_cost = newtablecost;
886  matrix_get(x, z)->multistep = 1;
887  changed++;
888 
889  if (DEBUG_ATLEAST(10)) {
890  struct ast_codec *x_codec = index2codec(x);
891  struct ast_codec *y_codec = index2codec(y);
892  struct ast_codec *z_codec = index2codec(z);
893 
895  "Discovered %u cost path from %s to %s, via %s\n",
896  matrix_get(x, z)->table_cost, x_codec->name,
897  y_codec->name, z_codec->name);
898 
899  ao2_ref(x_codec, -1);
900  ao2_ref(y_codec, -1);
901  ao2_ref(z_codec, -1);
902  }
903  }
904  }
905  }
906  }
907  if (!changed) {
908  break;
909  }
910  }
911 }
912 
913 static void codec_append_name(const struct ast_codec *codec, struct ast_str **buf)
914 {
915  if (codec) {
916  ast_str_append(buf, 0, "(%s@%u)", codec->name, codec->sample_rate);
917  } else {
918  ast_str_append(buf, 0, "(nothing)");
919  }
920 }
921 
922 const char *ast_translate_path_to_str(struct ast_trans_pvt *p, struct ast_str **str)
923 {
924  if (!p || !p->t) {
925  return "";
926  }
927 
928  ast_str_reset(*str);
929  codec_append_name(&p->t->src_codec, str);
930  while (p) {
931  ast_str_append(str, 0, "->");
932  codec_append_name(&p->t->dst_codec, str);
933  p = p->next;
934  }
935 
936  return ast_str_buffer(*str);
937 }
938 
939 static char *complete_trans_path_choice(const char *word)
940 {
941  int i = 1;
942  int wordlen = strlen(word);
943  struct ast_codec *codec;
944 
945  while ((codec = ast_codec_get_by_id(i))) {
946  ++i;
947  if (codec->type != AST_MEDIA_TYPE_AUDIO) {
948  ao2_ref(codec, -1);
949  continue;
950  }
951  if (!strncasecmp(word, codec->name, wordlen)) {
952  if (ast_cli_completion_add(ast_strdup(codec->name))) {
953  ao2_ref(codec, -1);
954  break;
955  }
956  }
957  ao2_ref(codec, -1);
958  }
959 
960  return NULL;
961 }
962 
963 static void handle_cli_recalc(struct ast_cli_args *a)
964 {
965  int time = a->argv[4] ? atoi(a->argv[4]) : 1;
966 
967  if (time <= 0) {
968  ast_cli(a->fd, " Recalc must be greater than 0. Defaulting to 1.\n");
969  time = 1;
970  }
971 
972  if (time > MAX_RECALC) {
973  ast_cli(a->fd, " Maximum limit of recalc exceeded by %d, truncating value to %d\n", time - MAX_RECALC, MAX_RECALC);
974  time = MAX_RECALC;
975  }
976  ast_cli(a->fd, " Recalculating Codec Translation (number of sample seconds: %d)\n\n", time);
978  matrix_rebuild(time);
980 }
981 
983 {
984  int x, y, i, k;
985  int longest = 7; /* slin192 */
986  int max_codec_index = 0, curlen = 0;
987  struct ast_str *out = ast_str_create(1024);
988  struct ast_codec *codec;
989 
990  /* Get the length of the longest (usable?) codec name,
991  so we know how wide the left side should be */
992  for (i = 1; (codec = ast_codec_get_by_id(i)); ao2_ref(codec, -1), ++i) {
993  ++max_codec_index;
994  if (codec->type != AST_MEDIA_TYPE_AUDIO) {
995  continue;
996  }
997  curlen = strlen(codec->name);
998  if (curlen > longest) {
999  longest = curlen;
1000  }
1001  }
1002 
1004  ast_cli(a->fd, " Translation times between formats (in microseconds) for one second of data\n");
1005  ast_cli(a->fd, " Source Format (Rows) Destination Format (Columns)\n\n");
1006 
1007  for (i = 0; i <= max_codec_index; i++) {
1008  struct ast_codec *row = i ? ast_codec_get_by_id(i) : NULL;
1009 
1010  x = -1;
1011  if ((i > 0) && (row->type != AST_MEDIA_TYPE_AUDIO)) {
1012  ao2_ref(row, -1);
1013  continue;
1014  }
1015 
1016  if ((i > 0) && (x = codec2index(row)) == -1) {
1017  ao2_ref(row, -1);
1018  continue;
1019  }
1020 
1021  ast_str_set(&out, 0, " ");
1022  for (k = 0; k <= max_codec_index; k++) {
1023  int adjust = 0;
1024  struct ast_codec *col = k ? ast_codec_get_by_id(k) : NULL;
1025 
1026  y = -1;
1027  if ((k > 0) && (col->type != AST_MEDIA_TYPE_AUDIO)) {
1028  ao2_ref(col, -1);
1029  continue;
1030  }
1031 
1032  if ((k > 0) && (y = codec2index(col)) == -1) {
1033  ao2_ref(col, -1);
1034  continue;
1035  }
1036 
1037  if (k > 0) {
1038  curlen = strlen(col->name);
1039  if (!strcmp(col->name, "slin") ||
1040  !strcmp(col->name, "speex") ||
1041  !strcmp(col->name, "silk")) {
1042  adjust = log10(col->sample_rate / 1000) + 1;
1043  curlen = curlen + adjust;
1044  }
1045  }
1046 
1047  if (curlen < 5) {
1048  curlen = 5;
1049  }
1050 
1051  if (x >= 0 && y >= 0 && matrix_get(x, y)->step) {
1052  /* Actual codec output */
1053  ast_str_append(&out, 0, "%*u", curlen + 1, (matrix_get(x, y)->table_cost/100));
1054  } else if (i == 0 && k > 0) {
1055  /* Top row - use a dynamic size */
1056  if (!strcmp(col->name, "slin") ||
1057  !strcmp(col->name, "speex") ||
1058  !strcmp(col->name, "silk")) {
1059  ast_str_append(&out, 0, "%*s%u", curlen - adjust + 1,
1060  col->name, col->sample_rate / 1000);
1061  } else {
1062  ast_str_append(&out, 0, "%*s", curlen + 1, col->name);
1063  }
1064  } else if (k == 0 && i > 0) {
1065  /* Left column - use a static size. */
1066  if (!strcmp(row->name, "slin") ||
1067  !strcmp(row->name, "speex") ||
1068  !strcmp(row->name, "silk")) {
1069  int adjust_row = log10(row->sample_rate / 1000) + 1;
1070  ast_str_append(&out, 0, "%*s%u", longest - adjust_row,
1071  row->name, row->sample_rate / 1000);
1072  } else {
1073  ast_str_append(&out, 0, "%*s", longest, row->name);
1074  }
1075  } else if (x >= 0 && y >= 0) {
1076  /* Codec not supported */
1077  ast_str_append(&out, 0, "%*s", curlen + 1, "-");
1078  } else {
1079  /* Upper left hand corner */
1080  ast_str_append(&out, 0, "%*s", longest, "");
1081  }
1082  ao2_cleanup(col);
1083  }
1084  ast_str_append(&out, 0, "\n");
1085  ast_cli(a->fd, "%s", ast_str_buffer(out));
1086  ao2_cleanup(row);
1087  }
1088  ast_free(out);
1090  return CLI_SUCCESS;
1091 }
1092 
1093 static char *handle_show_translation_path(struct ast_cli_args *a, const char *codec_name, unsigned int sample_rate)
1094 {
1095  int i = 1;
1096  struct ast_str *str = ast_str_alloca(1024);
1097  struct ast_translator *step;
1098  struct ast_codec *dst_codec;
1099  struct ast_codec *src_codec = ast_codec_get(codec_name, AST_MEDIA_TYPE_AUDIO, sample_rate);
1100 
1101  if (!src_codec) {
1102  ast_cli(a->fd, "Source codec \"%s\" is not found.\n", codec_name);
1103  return CLI_FAILURE;
1104  }
1105 
1107  ast_cli(a->fd, "--- Translation paths SRC Codec \"%s\" sample rate %u ---\n",
1108  codec_name, src_codec->sample_rate);
1109 
1110  while ((dst_codec = ast_codec_get_by_id(i))) {
1111  int src, dst;
1112  char src_buffer[64];
1113  char dst_buffer[64];
1114 
1115  ++i;
1116  if (src_codec == dst_codec ||
1117  dst_codec->type != AST_MEDIA_TYPE_AUDIO) {
1118  ao2_ref(dst_codec, -1);
1119  continue;
1120  }
1121 
1122  dst = codec2index(dst_codec);
1123  src = codec2index(src_codec);
1124 
1125  if (src < 0 || dst < 0) {
1126  ast_str_set(&str, 0, "No Translation Path");
1127  } else {
1128  step = matrix_get(src, dst)->step;
1129 
1130  if (step) {
1131  codec_append_name(&step->src_codec, &str);
1132  while (src != dst) {
1133  src = step->dst_fmt_index;
1134  step = matrix_get(src, dst)->step;
1135  if (!step) {
1136  ast_str_append(&str, 0, "->");
1137  codec_append_name(dst_codec, &str);
1138  break;
1139  }
1140  ast_str_append(&str, 0, "->");
1141  codec_append_name(&step->src_codec, &str);
1142  }
1143  }
1144  }
1145 
1146  snprintf(src_buffer, sizeof(src_buffer), "%s:%u", src_codec->name, src_codec->sample_rate);
1147  snprintf(dst_buffer, sizeof(dst_buffer), "%s:%u", dst_codec->name, dst_codec->sample_rate);
1148  ast_cli(a->fd, "\t%-16.16s To %-16.16s: %-60.60s\n",
1149  src_buffer, dst_buffer, ast_str_buffer(str));
1150  ast_str_reset(str);
1151  ao2_ref(dst_codec, -1);
1152  }
1154  ao2_ref(src_codec, -1);
1155  return CLI_SUCCESS;
1156 }
1157 
1158 static char *handle_cli_core_show_translation(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
1159 {
1160  static const char * const option[] = { "recalc", "paths", NULL };
1161 
1162  switch (cmd) {
1163  case CLI_INIT:
1164  e->command = "core show translation";
1165  e->usage =
1166  "Usage: 'core show translation' can be used in two ways.\n"
1167  " 1. 'core show translation [recalc [<recalc seconds>]]\n"
1168  " Displays known codec translators and the cost associated\n"
1169  " with each conversion. If the argument 'recalc' is supplied along\n"
1170  " with optional number of seconds to test a new test will be performed\n"
1171  " as the chart is being displayed.\n"
1172  " 2. 'core show translation paths [codec [sample_rate]]'\n"
1173  " This will display all the translation paths associated with a codec.\n"
1174  " If a codec has multiple sample rates, the sample rate must be\n"
1175  " provided as well.\n";
1176  return NULL;
1177  case CLI_GENERATE:
1178  if (a->pos == 3) {
1179  return ast_cli_complete(a->word, option, -1);
1180  }
1181  if (a->pos == 4 && !strcasecmp(a->argv[3], option[1])) {
1182  return complete_trans_path_choice(a->word);
1183  }
1184  /* BUGBUG - add tab completion for sample rates */
1185  return NULL;
1186  }
1187 
1188  if (a->argc > 6)
1189  return CLI_SHOWUSAGE;
1190 
1191  if (a->argv[3] && !strcasecmp(a->argv[3], option[1]) && a->argc == 5) { /* show paths */
1192  return handle_show_translation_path(a, a->argv[4], 0);
1193  } else if (a->argv[3] && !strcasecmp(a->argv[3], option[1]) && a->argc == 6) {
1194  unsigned int sample_rate;
1195  if (sscanf(a->argv[5], "%30u", &sample_rate) != 1) {
1196  ast_cli(a->fd, "Invalid sample rate: %s.\n", a->argv[5]);
1197  return CLI_FAILURE;
1198  }
1199  return handle_show_translation_path(a, a->argv[4], sample_rate);
1200  } else if (a->argv[3] && !strcasecmp(a->argv[3], option[0])) { /* recalc and then fall through to show table */
1201  handle_cli_recalc(a);
1202  } else if (a->argc > 3) { /* wrong input */
1203  return CLI_SHOWUSAGE;
1204  }
1205 
1207 }
1208 
1209 static struct ast_cli_entry cli_translate[] = {
1210  AST_CLI_DEFINE(handle_cli_core_show_translation, "Display translation matrix")
1211 };
1212 
1213 /*! \brief register codec translator */
1215 {
1216  struct ast_translator *u;
1217  char tmp[80];
1220 
1222  if (!src_codec) {
1223  ast_assert(0);
1224  ast_log(LOG_WARNING, "Failed to register translator: unknown source codec %s\n", t->src_codec.name);
1225  return -1;
1226  }
1227 
1229  if (!dst_codec) {
1230  ast_log(LOG_WARNING, "Failed to register translator: unknown destination codec %s\n", t->dst_codec.name);
1231  return -1;
1232  }
1233 
1235  if (matrix_resize(0)) {
1236  ast_log(LOG_WARNING, "Translator matrix can not represent any more translators. Out of resources.\n");
1237  return -1;
1238  }
1241  }
1242 
1243  if (!mod) {
1244  ast_log(LOG_WARNING, "Missing module pointer, you need to supply one\n");
1245  return -1;
1246  }
1247 
1248  if (!t->buf_size) {
1249  ast_log(LOG_WARNING, "empty buf size, you need to supply one\n");
1250  return -1;
1251  }
1253  ast_log(LOG_WARNING, "Table cost could not be generated for %s, "
1254  "Please set table_cost variable on translator.\n", t->name);
1255  return -1;
1256  }
1257 
1258  t->module = mod;
1261  t->active = 1;
1262 
1263  if (t->src_fmt_index < 0 || t->dst_fmt_index < 0) {
1264  ast_log(LOG_WARNING, "Invalid translator path: (%s codec is not valid)\n", t->src_fmt_index < 0 ? "starting" : "ending");
1265  return -1;
1266  }
1267  if (t->src_fmt_index >= cur_max_index) {
1268  ast_log(LOG_WARNING, "Source codec %s is larger than cur_max_index\n", t->src_codec.name);
1269  return -1;
1270  }
1271 
1272  if (t->dst_fmt_index >= cur_max_index) {
1273  ast_log(LOG_WARNING, "Destination codec %s is larger than cur_max_index\n", t->dst_codec.name);
1274  return -1;
1275  }
1276 
1277  if (t->buf_size) {
1278  /*
1279  * Align buf_size properly, rounding up to the machine-specific
1280  * alignment for pointers.
1281  */
1282  struct _test_align { void *a, *b; } p;
1283  int align = (char *)&p.b - (char *)&p.a;
1284 
1285  t->buf_size = ((t->buf_size + align - 1) / align) * align;
1286  }
1287 
1288  if (t->frameout == NULL) {
1290  }
1291 
1293 
1294  ast_verb(2, "Registered translator '%s' from codec %s to %s, table cost, %d, computational cost %d\n",
1295  term_color(tmp, t->name, COLOR_MAGENTA, COLOR_BLACK, sizeof(tmp)),
1296  t->src_codec.name, t->dst_codec.name, t->table_cost, t->comp_cost);
1297 
1299 
1300  /* find any existing translators that provide this same srcfmt/dstfmt,
1301  and put this one in order based on computational cost */
1303  if ((u->src_fmt_index == t->src_fmt_index) &&
1304  (u->dst_fmt_index == t->dst_fmt_index) &&
1305  (u->comp_cost > t->comp_cost)) {
1307  t = NULL;
1308  break;
1309  }
1310  }
1312 
1313  /* if no existing translator was found for this codec combination,
1314  add it to the beginning of the list */
1315  if (t) {
1317  }
1318 
1319  matrix_rebuild(0);
1320 
1322 
1323  return 0;
1324 }
1325 
1326 /*! \brief unregister codec translator */
1328 {
1329  char tmp[80];
1330  struct ast_translator *u;
1331  int found = 0;
1332 
1335  if (u == t) {
1337  ast_verb(2, "Unregistered translator '%s' from codec %s to %s\n",
1338  term_color(tmp, t->name, COLOR_MAGENTA, COLOR_BLACK, sizeof(tmp)),
1339  t->src_codec.name, t->dst_codec.name);
1340  found = 1;
1341  break;
1342  }
1343  }
1345 
1346  if (found && !ast_shutting_down()) {
1347  matrix_rebuild(0);
1348  }
1349 
1351 
1352  return (u ? 0 : -1);
1353 }
1354 
1356 {
1358  t->active = 1;
1359  matrix_rebuild(0);
1361 }
1362 
1364 {
1366  t->active = 0;
1367  matrix_rebuild(0);
1369 }
1370 
1371 /*! Calculate the absolute difference between sample rate of two formats. */
1372 #define format_sample_rate_absdiff(fmt1, fmt2) ({ \
1373  unsigned int rate1 = ast_format_get_sample_rate(fmt1); \
1374  unsigned int rate2 = ast_format_get_sample_rate(fmt2); \
1375  (rate1 > rate2 ? rate1 - rate2 : rate2 - rate1); \
1376 })
1377 
1378 /*! \brief Calculate our best translator source format, given costs, and a desired destination */
1380  struct ast_format_cap *src_cap,
1381  struct ast_format **dst_fmt_out,
1382  struct ast_format **src_fmt_out)
1383 {
1384  unsigned int besttablecost = INT_MAX;
1385  unsigned int beststeps = INT_MAX;
1386  struct ast_format *fmt;
1387  struct ast_format *dst;
1388  struct ast_format *src;
1389  RAII_VAR(struct ast_format *, best, NULL, ao2_cleanup);
1390  RAII_VAR(struct ast_format *, bestdst, NULL, ao2_cleanup);
1391  struct ast_format_cap *joint_cap;
1392  int i;
1393  int j;
1394 
1395  if (ast_format_cap_empty(dst_cap) || ast_format_cap_empty(src_cap)) {
1396  ast_log(LOG_ERROR, "Cannot determine best translation path since one capability supports no formats\n");
1397  return -1;
1398  }
1399 
1401  if (!joint_cap) {
1402  return -1;
1403  }
1404  ast_format_cap_get_compatible(dst_cap, src_cap, joint_cap);
1405 
1406  for (i = 0; i < ast_format_cap_count(joint_cap); ++i, ao2_cleanup(fmt)) {
1407  fmt = ast_format_cap_get_format(joint_cap, i);
1408  if (!fmt
1410  continue;
1411  }
1412 
1413  if (!best
1415  ao2_replace(best, fmt);
1416  }
1417  }
1418  ao2_ref(joint_cap, -1);
1419 
1420  if (best) {
1421  ao2_replace(*dst_fmt_out, best);
1422  ao2_replace(*src_fmt_out, best);
1423  return 0;
1424  }
1425 
1426  /* need to translate */
1428  for (i = 0; i < ast_format_cap_count(dst_cap); ++i, ao2_cleanup(dst)) {
1429  dst = ast_format_cap_get_format(dst_cap, i);
1430  if (!dst
1432  continue;
1433  }
1434 
1435  for (j = 0; j < ast_format_cap_count(src_cap); ++j, ao2_cleanup(src)) {
1436  int x;
1437  int y;
1438 
1439  src = ast_format_cap_get_format(src_cap, j);
1440  if (!src
1442  continue;
1443  }
1444 
1445  x = format2index(src);
1446  y = format2index(dst);
1447  if (x < 0 || y < 0) {
1448  continue;
1449  }
1450  if (!matrix_get(x, y) || !(matrix_get(x, y)->step)) {
1451  continue;
1452  }
1453  if (matrix_get(x, y)->table_cost < besttablecost
1454  || matrix_get(x, y)->multistep < beststeps) {
1455  /* better than what we have so far */
1456  ao2_replace(best, src);
1457  ao2_replace(bestdst, dst);
1458  besttablecost = matrix_get(x, y)->table_cost;
1459  beststeps = matrix_get(x, y)->multistep;
1460  } else if (matrix_get(x, y)->table_cost == besttablecost
1461  && matrix_get(x, y)->multistep == beststeps) {
1462  unsigned int gap_selected = format_sample_rate_absdiff(best, bestdst);
1463  unsigned int gap_current = format_sample_rate_absdiff(src, dst);
1464 
1465  if (gap_current < gap_selected) {
1466  /* better than what we have so far */
1467  ao2_replace(best, src);
1468  ao2_replace(bestdst, dst);
1469  besttablecost = matrix_get(x, y)->table_cost;
1470  beststeps = matrix_get(x, y)->multistep;
1471  }
1472  }
1473  }
1474  }
1476 
1477  if (!best) {
1478  return -1;
1479  }
1480  ao2_replace(*dst_fmt_out, bestdst);
1481  ao2_replace(*src_fmt_out, best);
1482  return 0;
1483 }
1484 
1485 unsigned int ast_translate_path_steps(struct ast_format *dst_format, struct ast_format *src_format)
1486 {
1487  unsigned int res = -1;
1488  /* convert bitwise format numbers into array indices */
1489  int src = format2index(src_format);
1490  int dest = format2index(dst_format);
1491 
1492  if (src < 0 || dest < 0) {
1493  ast_log(LOG_WARNING, "No translator path: (%s codec is not valid)\n", src < 0 ? "starting" : "ending");
1494  return -1;
1495  }
1497 
1498  if (matrix_get(src, dest)->step) {
1499  res = matrix_get(src, dest)->multistep + 1;
1500  }
1501 
1503 
1504  return res;
1505 }
1506 
1508  struct ast_format_cap *dest, struct ast_format_cap *src,
1509  struct ast_format_cap *result, struct ast_format *src_fmt,
1510  enum ast_media_type type)
1511 {
1512  int index, src_index = format2index(src_fmt);
1513  /* For a given source format, traverse the list of
1514  known formats to determine whether there exists
1515  a translation path from the source format to the
1516  destination format. */
1517  for (index = 0; (src_index >= 0) && index < cur_max_index; index++) {
1518  struct ast_codec *codec = index2codec(index);
1519  RAII_VAR(struct ast_format *, fmt, ast_format_create(codec), ao2_cleanup);
1520 
1521  ao2_ref(codec, -1);
1522 
1523  if (ast_format_get_type(fmt) != type) {
1524  continue;
1525  }
1526 
1527  /* if this is not a desired format, nothing to do */
1529  continue;
1530  }
1531 
1532  /* if the source is supplying this format, then
1533  we can leave it in the result */
1535  continue;
1536  }
1537 
1538  /* if we don't have a translation path from the src
1539  to this format, remove it from the result */
1540  if (!matrix_get(src_index, index)->step) {
1541  ast_format_cap_remove(result, fmt);
1542  continue;
1543  }
1544 
1545  /* now check the opposite direction */
1546  if (!matrix_get(index, src_index)->step) {
1547  ast_format_cap_remove(result, fmt);
1548  }
1549  }
1550 
1551 }
1552 
1554 {
1555  struct ast_format *cur_dest, *cur_src;
1556  int index;
1557 
1558  for (index = 0; index < ast_format_cap_count(dest); ++index) {
1559  if (!(cur_dest = ast_format_cap_get_format(dest, index))) {
1560  continue;
1561  }
1562 
1563  /* We give preference to a joint format structure if possible */
1564  if ((cur_src = ast_format_cap_get_compatible_format(src, cur_dest))) {
1565  ast_format_cap_append(result, cur_src, 0);
1566  ao2_ref(cur_src, -1);
1567  } else {
1568  /* Otherwise we just use the destination format */
1569  ast_format_cap_append(result, cur_dest, 0);
1570  }
1571  ao2_ref(cur_dest, -1);
1572  }
1573 
1574  /* if we don't have a source format, we just have to try all
1575  possible destination formats */
1576  if (!src) {
1577  return;
1578  }
1579 
1580  for (index = 0; index < ast_format_cap_count(src); ++index) {
1581  if (!(cur_src = ast_format_cap_get_format(src, index))) {
1582  continue;
1583  }
1584 
1586  check_translation_path(dest, src, result,
1587  cur_src, AST_MEDIA_TYPE_AUDIO);
1588  check_translation_path(dest, src, result,
1589  cur_src, AST_MEDIA_TYPE_VIDEO);
1591  ao2_ref(cur_src, -1);
1592  }
1593 }
1594 
1595 static void translate_shutdown(void)
1596 {
1597  int x;
1598  ast_cli_unregister_multiple(cli_translate, ARRAY_LEN(cli_translate));
1599 
1600  ast_rwlock_wrlock(&tablelock);
1601  for (x = 0; x < index_size; x++) {
1602  ast_free(__matrix[x]);
1603  }
1604  ast_free(__matrix);
1605  __matrix = NULL;
1607  __indextable = NULL;
1608  ast_rwlock_unlock(&tablelock);
1609  ast_rwlock_destroy(&tablelock);
1610 }
1611 
1613 {
1614  int res = 0;
1615  ast_rwlock_init(&tablelock);
1616  res = matrix_resize(1);
1617  res |= ast_cli_register_multiple(cli_translate, ARRAY_LEN(cli_translate));
1619  return res;
1620 }
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:1209
static void matrix_rebuild(int samples)
rebuild a translation matrix.
Definition: translate.c:818
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:432
#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:1158
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:462
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:1485
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:650
#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:1355
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:1553
#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:286
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:963
char * ast_cli_complete(const char *word, const char *const choices[], int pos)
Definition: main/cli.c:1764
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:469
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:1372
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:1093
#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:851
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:1507
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:1612
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:1214
static void translate_shutdown(void)
Definition: translate.c:1595
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:913
#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:1327
#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:559
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:939
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:479
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:1363
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:684
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:2677
static int generate_table_cost(struct ast_codec *src, struct ast_codec *dst)
Definition: translate.c:762
#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:982
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:1379
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:922
static struct ast_frame * generate_interpolated_slin(struct ast_trans_pvt *p, struct ast_frame *f)
Definition: translate.c:530
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:520
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