2 * Asterisk -- An open source telephony toolkit.
4 * Copyright (C) 1999 - 2006, Digium, Inc.
6 * Mark Spencer <markster@digium.com>
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.
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.
21 * \brief Translate via the use of pseudo channels
23 * \author Mark Spencer <markster@digium.com>
26 #define MOD_LOADER /* not really a module */
29 ASTERISK_FILE_VERSION(__FILE__
, "$Revision$")
31 #include <sys/types.h>
32 #include <sys/socket.h>
39 #include "asterisk/lock.h"
40 #include "asterisk/channel.h"
41 #include "asterisk/logger.h"
42 #include "asterisk/translate.h"
43 #include "asterisk/module.h"
44 #include "asterisk/options.h"
45 #include "asterisk/frame.h"
46 #include "asterisk/sched.h"
47 #include "asterisk/cli.h"
48 #include "asterisk/term.h"
50 #define MAX_RECALC 200 /* max sample recalc */
52 /*! \brief the list of translators */
53 static AST_LIST_HEAD_STATIC(translators
, ast_translator
);
55 struct translator_path
{
56 struct ast_translator
*step
; /*!< Next step translator */
57 unsigned int cost
; /*!< Complete cost to destination */
58 unsigned int multistep
; /*!< Multiple conversions required for this translation */
61 /*! \brief a matrix that, for any pair of supported formats,
62 * indicates the total cost of translation and the first step.
63 * The full path can be reconstricted iterating on the matrix
64 * until step->dstfmt == desired_format.
66 * Array indexes are 'src' and 'dest', in that order.
68 static struct translator_path tr_matrix
[MAX_FORMAT
][MAX_FORMAT
];
71 * TODO: sample frames for each supported input format.
72 * We build this on the fly, by taking an SLIN frame and using
73 * the existing converter to play with it.
76 /*! \brief returns the index of the lowest bit set */
77 static force_inline
int powerof(unsigned int d
)
84 ast_log(LOG_WARNING
, "No bits set? %d\n", d
);
90 * wrappers around the translator routines.
94 * \brief Allocate the descriptor, required outbuf space,
95 * and possibly also plc and desc.
97 static void *newpvt(struct ast_translator
*t
)
99 struct ast_trans_pvt
*pvt
;
101 int useplc
= t
->plc_samples
> 0 && t
->useplc
; /* cache, because it can change on the fly */
103 struct module_symbols
*ms
= t
->module
;
106 * compute the required size adding private descriptor,
107 * plc, buffer, AST_FRIENDLY_OFFSET.
109 len
= sizeof(*pvt
) + t
->desc_size
;
111 len
+= sizeof(plc_state_t
);
113 len
+= AST_FRIENDLY_OFFSET
+ t
->buf_size
;
114 pvt
= ast_calloc(1, len
);
118 ofs
= (char *)(pvt
+ 1); /* pointer to data space */
119 if (t
->desc_size
) { /* first comes the descriptor */
123 if (useplc
) { /* then plc state */
124 pvt
->plc
= (plc_state_t
*)ofs
;
125 ofs
+= sizeof(plc_state_t
);
127 if (t
->buf_size
) /* finally buffer and header */
128 pvt
->outbuf
= ofs
+ AST_FRIENDLY_OFFSET
;
129 /* call local init routine, if present */
130 if (t
->newpvt
&& t
->newpvt(pvt
)) {
134 ast_atomic_fetchadd_int(&ms
->usecnt
, +1);
135 ast_update_use_count();
139 static void destroy(struct ast_trans_pvt
*pvt
)
141 struct ast_translator
*t
= pvt
->t
;
142 struct module_symbols
*ms
= t
->module
;
147 ast_atomic_fetchadd_int(&ms
->usecnt
, -1);
148 ast_update_use_count();
151 /*! \brief framein wrapper, deals with plc and bound checks. */
152 static int framein(struct ast_trans_pvt
*pvt
, struct ast_frame
*f
)
154 int16_t *dst
= (int16_t *)pvt
->outbuf
;
156 int samples
= pvt
->samples
; /* initial value */
158 /* Copy the last in jb timing info to the pvt */
159 pvt
->f
.has_timing_info
= f
->has_timing_info
;
162 pvt
->f
.seqno
= f
->seqno
;
164 if (f
->samples
== 0) {
165 ast_log(LOG_WARNING
, "no samples for %s\n", pvt
->t
->name
);
167 if (pvt
->t
->buffer_samples
) { /* do not pass empty frames to callback */
168 if (f
->datalen
== 0) { /* perform PLC with nominal framesize of 20ms/160 samples */
170 int l
= pvt
->t
->plc_samples
;
171 if (pvt
->samples
+ l
> pvt
->t
->buffer_samples
) {
172 ast_log(LOG_WARNING
, "Out of buffer space\n");
175 l
= plc_fillin(pvt
->plc
, dst
+ pvt
->samples
, l
);
180 if (pvt
->samples
+ f
->samples
> pvt
->t
->buffer_samples
) {
181 ast_log(LOG_WARNING
, "Out of buffer space\n");
185 /* we require a framein routine, wouldn't know how to do
188 ret
= pvt
->t
->framein(pvt
, f
);
189 /* possibly store data for plc */
190 if (!ret
&& pvt
->plc
) {
191 int l
= pvt
->t
->plc_samples
;
192 if (pvt
->samples
< l
)
194 plc_rx(pvt
->plc
, dst
+ pvt
->samples
- l
, l
);
197 if (pvt
->samples
== samples
)
198 ast_log(LOG_WARNING
, "%s did not update samples %d\n",
199 pvt
->t
->name
, pvt
->samples
);
203 /*! \brief generic frameout routine.
204 * If samples and datalen are 0, take whatever is in pvt
205 * and reset them, otherwise take the values in the caller and
206 * leave alone the pvt values.
208 struct ast_frame
*ast_trans_frameout(struct ast_trans_pvt
*pvt
,
209 int datalen
, int samples
)
211 struct ast_frame
*f
= &pvt
->f
;
214 f
->samples
= samples
;
216 if (pvt
->samples
== 0)
218 f
->samples
= pvt
->samples
;
222 f
->datalen
= datalen
;
224 f
->datalen
= pvt
->datalen
;
228 f
->frametype
= AST_FRAME_VOICE
;
229 f
->subclass
= 1 << (pvt
->t
->dstfmt
);
231 f
->offset
= AST_FRIENDLY_OFFSET
;
232 f
->src
= pvt
->t
->name
;
233 f
->data
= pvt
->outbuf
;
237 static struct ast_frame
*default_frameout(struct ast_trans_pvt
*pvt
)
239 return ast_trans_frameout(pvt
, 0, 0);
242 /* end of callback wrappers and helpers */
244 void ast_translator_free_path(struct ast_trans_pvt
*p
)
246 struct ast_trans_pvt
*pn
= p
;
253 /*! \brief Build a chain of translators based upon the given source and dest formats */
254 struct ast_trans_pvt
*ast_translator_build_path(int dest
, int source
)
256 struct ast_trans_pvt
*head
= NULL
, *tail
= NULL
;
258 source
= powerof(source
);
259 dest
= powerof(dest
);
261 while (source
!= dest
) {
262 struct ast_trans_pvt
*cur
;
263 struct ast_translator
*t
= tr_matrix
[source
][dest
].step
;
265 ast_log(LOG_WARNING
, "No translator path from %s to %s\n",
266 ast_getformatname(source
), ast_getformatname(dest
));
269 if (!(cur
= newpvt(t
))) {
270 ast_log(LOG_WARNING
, "Failed to build translator step from %d to %d\n", source
, dest
);
272 ast_translator_free_path(head
);
280 cur
->nextin
= cur
->nextout
= ast_tv(0, 0);
281 /* Keep going if this isn't the final destination */
282 source
= cur
->t
->dstfmt
;
287 /*! \brief do the actual translation */
288 struct ast_frame
*ast_translate(struct ast_trans_pvt
*path
, struct ast_frame
*f
, int consume
)
290 struct ast_trans_pvt
*p
= path
;
291 struct ast_frame
*out
= f
;
292 struct timeval delivery
;
298 has_timing_info
= f
->has_timing_info
;
303 /* XXX hmmm... check this below */
304 if (!ast_tvzero(f
->delivery
)) {
305 if (!ast_tvzero(path
->nextin
)) {
306 /* Make sure this is in line with what we were expecting */
307 if (!ast_tveq(path
->nextin
, f
->delivery
)) {
308 /* The time has changed between what we expected and this
309 most recent time on the new packet. If we have a
310 valid prediction adjust our output time appropriately */
311 if (!ast_tvzero(path
->nextout
)) {
312 path
->nextout
= ast_tvadd(path
->nextout
,
313 ast_tvsub(f
->delivery
, path
->nextin
));
315 path
->nextin
= f
->delivery
;
318 /* This is our first pass. Make sure the timing looks good */
319 path
->nextin
= f
->delivery
;
320 path
->nextout
= f
->delivery
;
322 /* Predict next incoming sample */
323 path
->nextin
= ast_tvadd(path
->nextin
, ast_samp2tv(f
->samples
, 8000));
325 delivery
= f
->delivery
;
326 for ( ; out
&& p
; p
= p
->next
) {
328 out
= p
->t
->frameout(p
);
334 /* we have a frame, play with times */
335 if (!ast_tvzero(delivery
)) {
336 /* Regenerate prediction after a discontinuity */
337 if (ast_tvzero(path
->nextout
))
338 path
->nextout
= ast_tvnow();
340 /* Use next predicted outgoing timestamp */
341 out
->delivery
= path
->nextout
;
343 /* Predict next outgoing timestamp from samples in this
345 path
->nextout
= ast_tvadd(path
->nextout
, ast_samp2tv( out
->samples
, 8000));
347 out
->delivery
= ast_tv(0, 0);
348 out
->has_timing_info
= has_timing_info
;
349 if (has_timing_info
) {
355 /* Invalidate prediction if we're entering a silence period */
356 if (out
->frametype
== AST_FRAME_CNG
)
357 path
->nextout
= ast_tv(0, 0);
361 /*! \brief compute the cost of a single translation step */
362 static void calc_cost(struct ast_translator
*t
, int seconds
)
365 struct ast_trans_pvt
*pvt
;
366 struct timeval start
;
372 /* If they don't make samples, give them a terrible score */
374 ast_log(LOG_WARNING
, "Translator '%s' does not produce sample frames.\n", t
->name
);
380 ast_log(LOG_WARNING
, "Translator '%s' appears to be broken and will probably fail.\n", t
->name
);
385 /* Call the encoder until we've processed the required number of samples */
386 while (sofar
< seconds
* 8000) {
387 struct ast_frame
*f
= t
->sample();
389 ast_log(LOG_WARNING
, "Translator '%s' failed to produce a sample frame.\n", t
->name
);
396 while ((f
= t
->frameout(pvt
))) {
401 cost
= ast_tvdiff_ms(ast_tvnow(), start
);
403 t
->cost
= cost
/ seconds
;
409 * \brief rebuild a translation matrix.
410 * \note This function expects the list of translators to be locked
412 static void rebuild_matrix(int samples
)
414 struct ast_translator
*t
;
415 int x
; /* source format index */
416 int y
; /* intermediate format index */
417 int z
; /* destination format index */
420 ast_log(LOG_DEBUG
, "Resetting translation matrix\n");
422 bzero(tr_matrix
, sizeof(tr_matrix
));
424 /* first, compute all direct costs */
425 AST_LIST_TRAVERSE(&translators
, t
, list
) {
430 calc_cost(t
, samples
);
432 if (!tr_matrix
[x
][z
].step
|| t
->cost
< tr_matrix
[x
][z
].cost
) {
433 tr_matrix
[x
][z
].step
= t
;
434 tr_matrix
[x
][z
].cost
= t
->cost
;
439 * For each triple x, y, z of distinct formats, check if there is
440 * a path from x to z through y which is cheaper than what is
441 * currently known, and in case, update the matrix.
442 * Repeat until the matrix is stable.
446 for (x
= 0; x
< MAX_FORMAT
; x
++) { /* source format */
447 for (y
=0; y
< MAX_FORMAT
; y
++) { /* intermediate format */
448 if (x
== y
) /* skip ourselves */
451 for (z
=0; z
<MAX_FORMAT
; z
++) { /* dst format */
454 if (z
== x
|| z
== y
) /* skip null conversions */
456 if (!tr_matrix
[x
][y
].step
) /* no path from x to y */
458 if (!tr_matrix
[y
][z
].step
) /* no path from y to z */
460 newcost
= tr_matrix
[x
][y
].cost
+ tr_matrix
[y
][z
].cost
;
461 if (tr_matrix
[x
][z
].step
&& newcost
>= tr_matrix
[x
][z
].cost
)
462 continue; /* x->y->z is more expensive than
463 * the existing path */
464 /* ok, we can get from x to z via y with a cost that
465 is the sum of the transition from x to y and
468 tr_matrix
[x
][z
].step
= tr_matrix
[x
][y
].step
;
469 tr_matrix
[x
][z
].cost
= newcost
;
470 tr_matrix
[x
][z
].multistep
= 1;
472 ast_log(LOG_DEBUG
, "Discovered %d cost path from %s to %s, via %d\n", tr_matrix
[x
][z
].cost
, ast_getformatname(x
), ast_getformatname(z
), y
);
482 /*! \brief CLI "show translation" command handler */
483 static int show_translation(int fd
, int argc
, char *argv
[])
485 #define SHOW_TRANS 11
489 return RESULT_SHOWUSAGE
;
491 AST_LIST_LOCK(&translators
);
493 if (argv
[2] && !strcasecmp(argv
[2], "recalc")) {
494 z
= argv
[3] ? atoi(argv
[3]) : 1;
497 ast_cli(fd
, " C'mon let's be serious here... defaulting to 1.\n");
501 if (z
> MAX_RECALC
) {
502 ast_cli(fd
, " Maximum limit of recalc exceeded by %d, truncating value to %d\n", z
- MAX_RECALC
, MAX_RECALC
);
505 ast_cli(fd
, " Recalculating Codec Translation (number of sample seconds: %d)\n\n", z
);
509 ast_cli(fd
, " Translation times between formats (in milliseconds)\n");
510 ast_cli(fd
, " Source Format (Rows) Destination Format(Columns)\n\n");
511 for (x
= -1; x
< SHOW_TRANS
; x
++) {
514 size_t left
= sizeof(line
) - 1; /* one initial space */
515 /* next 2 lines run faster than using ast_build_string() */
518 for (y
= -1; y
< SHOW_TRANS
; y
++) {
519 if (x
>= 0 && y
>= 0 && tr_matrix
[x
][y
].step
) /* XXX what is 99999 ? */
520 ast_build_string(&buf
, &left
, " %5d", tr_matrix
[x
][y
].cost
>= 99999 ? 0 : tr_matrix
[x
][y
].cost
);
521 else if (((x
== -1 && y
>= 0) || (y
== -1 && x
>= 0))) {
522 ast_build_string(&buf
, &left
, " %5s", ast_getformatname(1 << (x
+ y
+ 1)) );
523 } else if (x
!= -1 && y
!= -1) {
524 ast_build_string(&buf
, &left
, " -");
526 ast_build_string(&buf
, &left
, " ");
529 ast_build_string(&buf
, &left
, "\n");
532 AST_LIST_UNLOCK(&translators
);
533 return RESULT_SUCCESS
;
537 static char show_trans_usage
[] =
538 "Usage: show translation [recalc] [<recalc seconds>]\n"
539 " Displays known codec translators and the cost associated\n"
540 "with each conversion. If the argument 'recalc' is supplied along\n"
541 "with optional number of seconds to test a new test will be performed\n"
542 "as the chart is being displayed.\n";
544 static struct ast_cli_entry show_trans
=
545 { { "show", "translation", NULL
}, show_translation
, "Display translation matrix", show_trans_usage
};
547 /*! \brief register codec translator */
548 int ast_register_translator(struct ast_translator
*t
, void *module
)
550 static int added_cli
= 0;
552 if (module
== NULL
) {
553 ast_log(LOG_WARNING
, "Missing module pointer, you need to supply one\n");
557 if (t
->buf_size
== 0) {
558 ast_log(LOG_WARNING
, "empty buf size, you need to supply one\n");
561 if (t
->plc_samples
) {
562 if (t
->buffer_samples
< t
->plc_samples
) {
563 ast_log(LOG_WARNING
, "plc_samples %d buffer_samples %d\n",
564 t
->plc_samples
, t
->buffer_samples
);
567 if (t
->dstfmt
!= AST_FORMAT_SLINEAR
)
568 ast_log(LOG_WARNING
, "plc_samples %d format %x\n",
569 t
->plc_samples
, t
->dstfmt
);
571 t
->srcfmt
= powerof(t
->srcfmt
);
572 t
->dstfmt
= powerof(t
->dstfmt
);
573 /* XXX maybe check that it is not existing yet ? */
574 if (t
->srcfmt
>= MAX_FORMAT
) {
575 ast_log(LOG_WARNING
, "Source format %s is larger than MAX_FORMAT\n", ast_getformatname(t
->srcfmt
));
578 if (t
->dstfmt
>= MAX_FORMAT
) {
579 ast_log(LOG_WARNING
, "Destination format %s is larger than MAX_FORMAT\n", ast_getformatname(t
->dstfmt
));
584 * Align buf_size properly, rounding up to the machine-specific
585 * alignment for pointers.
587 struct _test_align
{ void *a
, *b
; } p
;
588 int align
= (char *)&p
.b
- (char *)&p
.a
;
589 t
->buf_size
= ((t
->buf_size
+ align
- 1) / align
) * align
;
591 if (t
->frameout
== NULL
)
592 t
->frameout
= default_frameout
;
595 if (option_verbose
> 1) {
597 ast_verbose(VERBOSE_PREFIX_2
"Registered translator '%s' from format %s to %s, cost %d\n",
598 term_color(tmp
, t
->name
, COLOR_MAGENTA
, COLOR_BLACK
, sizeof(tmp
)),
599 ast_getformatname(1 << t
->srcfmt
), ast_getformatname(1 << t
->dstfmt
), t
->cost
);
601 AST_LIST_LOCK(&translators
);
603 ast_cli_register(&show_trans
);
606 AST_LIST_INSERT_HEAD(&translators
, t
, list
);
608 AST_LIST_UNLOCK(&translators
);
612 /*! \brief unregister codec translator */
613 int ast_unregister_translator(struct ast_translator
*t
)
616 struct ast_translator
*u
;
617 AST_LIST_LOCK(&translators
);
618 AST_LIST_TRAVERSE_SAFE_BEGIN(&translators
, u
, list
) {
620 AST_LIST_REMOVE_CURRENT(&translators
, list
);
621 if (option_verbose
> 1)
622 ast_verbose(VERBOSE_PREFIX_2
"Unregistered translator '%s' from format %s to %s\n", term_color(tmp
, t
->name
, COLOR_MAGENTA
, COLOR_BLACK
, sizeof(tmp
)), ast_getformatname(1 << t
->srcfmt
), ast_getformatname(1 << t
->dstfmt
));
626 AST_LIST_TRAVERSE_SAFE_END
628 AST_LIST_UNLOCK(&translators
);
632 /*! \brief Calculate our best translator source format, given costs, and a desired destination */
633 int ast_translator_best_choice(int *dst
, int *srcs
)
639 int besttime
= INT_MAX
;
640 int beststeps
= INT_MAX
;
641 int common
= (*dst
) & (*srcs
); /* are there common formats ? */
643 if (common
) { /* yes, pick one and return */
644 for (cur
= 1, y
= 0; y
< MAX_FORMAT
; cur
<<= 1, y
++) {
645 if (cur
& common
) /* guaranteed to find one */
648 /* We are done, this is a common format to both. */
651 } else { /* No, we will need to translate */
652 AST_LIST_LOCK(&translators
);
653 for (cur
= 1, y
= 0; y
< MAX_FORMAT
; cur
<<= 1, y
++) {
656 for (cursrc
= 1, x
= 0; x
< MAX_FORMAT
; cursrc
<<= 1, x
++) {
657 if (!(*srcs
& cursrc
) || !tr_matrix
[x
][y
].step
||
658 tr_matrix
[x
][y
].cost
> besttime
)
659 continue; /* not existing or no better */
660 if (tr_matrix
[x
][y
].cost
< besttime
||
661 tr_matrix
[x
][y
].multistep
< beststeps
) {
662 /* better than what we have so far */
665 besttime
= tr_matrix
[x
][y
].cost
;
666 beststeps
= tr_matrix
[x
][y
].multistep
;
670 AST_LIST_UNLOCK(&translators
);
680 unsigned int ast_translate_path_steps(unsigned int dest
, unsigned int src
)
682 /* convert bitwise format numbers into array indices */
684 dest
= powerof(dest
);
685 if (!tr_matrix
[src
][dest
].step
)
688 return tr_matrix
[src
][dest
].multistep
+ 1;