Translate via the use of pseudo channels. More...
#include "asterisk.h"
#include <sys/time.h>
#include <sys/resource.h>
#include <math.h>
#include "asterisk/lock.h"
#include "asterisk/channel.h"
#include "asterisk/translate.h"
#include "asterisk/module.h"
#include "asterisk/frame.h"
#include "asterisk/sched.h"
#include "asterisk/cli.h"
#include "asterisk/term.h"
Go to the source code of this file.
Data Structures | |
struct | translator_path |
struct | translators |
the list of translators More... | |
Defines | |
#define | MAX_RECALC 1000 |
#define | SHOW_TRANS 64 |
Enumerations | |
enum | path_samp_change { AST_TRANS_COST_LL_LL_ORIGSAMP = 400000, AST_TRANS_COST_LL_LY_ORIGSAMP = 600000, AST_TRANS_COST_LL_LL_UPSAMP = 800000, AST_TRANS_COST_LL_LY_UPSAMP = 825000, AST_TRANS_COST_LL_LL_DOWNSAMP = 850000, AST_TRANS_COST_LL_LY_DOWNSAMP = 875000, AST_TRANS_COST_LL_UNKNOWN = 885000, AST_TRANS_COST_LY_LL_ORIGSAMP = 900000, AST_TRANS_COST_LY_LY_ORIGSAMP = 915000, AST_TRANS_COST_LY_LL_UPSAMP = 930000, AST_TRANS_COST_LY_LY_UPSAMP = 945000, AST_TRANS_COST_LY_LL_DOWNSAMP = 960000, AST_TRANS_COST_LY_LY_DOWNSAMP = 975000, AST_TRANS_COST_LY_UNKNOWN = 985000 } |
these values indicate how a translation path will affect the sample rate More... | |
Functions | |
int | __ast_register_translator (struct ast_translator *t, struct ast_module *mod) |
register codec translator | |
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, otherwise take the values in the caller and leave alone the pvt values. | |
struct ast_frame * | ast_translate (struct ast_trans_pvt *path, struct ast_frame *f, int consume) |
do the actual translation | |
format_t | ast_translate_available_formats (format_t dest, format_t src) |
Mask off unavailable formats from a format bitmask. | |
unsigned int | ast_translate_path_steps (format_t dest, format_t src) |
Returns the number of steps required to convert from 'src' to 'dest'. | |
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. | |
void | ast_translator_activate (struct ast_translator *t) |
Activate a previously deactivated translator. | |
format_t | ast_translator_best_choice (format_t *dst, format_t *srcs) |
Calculate our best translator source format, given costs, and a desired destination. | |
struct ast_trans_pvt * | ast_translator_build_path (format_t dest, format_t source) |
Build a chain of translators based upon the given source and dest formats. | |
void | ast_translator_deactivate (struct ast_translator *t) |
Deactivate a translator. | |
void | ast_translator_free_path (struct ast_trans_pvt *p) |
Frees a translator path Frees the given translator path structure. | |
int | ast_unregister_translator (struct ast_translator *t) |
unregister codec translator | |
static void | calc_cost (struct ast_translator *t, int seconds) |
compute the cost of a single translation step | |
static char * | complete_trans_path_choice (const char *line, const char *word, int pos, int state) |
static struct ast_frame * | default_frameout (struct ast_trans_pvt *pvt) |
static void | destroy (struct ast_trans_pvt *pvt) |
static int | framein (struct ast_trans_pvt *pvt, struct ast_frame *f) |
framein wrapper, deals with bound checks. | |
static enum path_samp_change | get_rate_change_result (format_t src, format_t dst) |
static char * | handle_cli_core_show_translation (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
static void * | newpvt (struct ast_translator *t) |
Allocate the descriptor, required outbuf space, and possibly desc. | |
static force_inline int | powerof (format_t d) |
returns the index of the lowest bit set | |
static void | rebuild_matrix (int samples) |
rebuild a translation matrix. | |
Variables | |
static struct ast_cli_entry | cli_translate [] |
static struct translator_path | tr_matrix [MAX_FORMAT][MAX_FORMAT] |
a matrix that, for any pair of supported formats, indicates the total cost of translation and the first step. The full path can be reconstricted iterating on the matrix until step->dstfmt == desired_format. |
Translate via the use of pseudo channels.
Definition in file translate.c.
#define MAX_RECALC 1000 |
Definition at line 47 of file translate.c.
Referenced by handle_cli_core_show_translation().
#define SHOW_TRANS 64 |
Referenced by handle_cli_core_show_translation().
enum path_samp_change |
these values indicate how a translation path will affect the sample rate
Definition at line 57 of file translate.c.
00057 { 00058 00059 /* Lossless Source Translation Costs */ 00060 00061 /*! [lossless -> lossless] original sampling */ 00062 AST_TRANS_COST_LL_LL_ORIGSAMP = 400000, 00063 /*! [lossless -> lossy] original sampling */ 00064 AST_TRANS_COST_LL_LY_ORIGSAMP = 600000, 00065 00066 /*! [lossless -> lossless] up sample */ 00067 AST_TRANS_COST_LL_LL_UPSAMP = 800000, 00068 /*! [lossless -> lossy] up sample */ 00069 AST_TRANS_COST_LL_LY_UPSAMP = 825000, 00070 00071 /*! [lossless -> lossless] down sample */ 00072 AST_TRANS_COST_LL_LL_DOWNSAMP = 850000, 00073 /*! [lossless -> lossy] down sample */ 00074 AST_TRANS_COST_LL_LY_DOWNSAMP = 875000, 00075 00076 /*! [lossless -> unknown] unknown. 00077 * This value is for a lossless source translation 00078 * with an unknown destination and or sample rate conversion. */ 00079 AST_TRANS_COST_LL_UNKNOWN = 885000, 00080 00081 /* Lossy Source Translation Costs */ 00082 00083 /*! [lossy -> lossless] original sampling */ 00084 AST_TRANS_COST_LY_LL_ORIGSAMP = 900000, 00085 /*! [lossy -> lossy] original sampling */ 00086 AST_TRANS_COST_LY_LY_ORIGSAMP = 915000, 00087 00088 /*! [lossy -> lossless] up sample */ 00089 AST_TRANS_COST_LY_LL_UPSAMP = 930000, 00090 /*! [lossy -> lossy] up sample */ 00091 AST_TRANS_COST_LY_LY_UPSAMP = 945000, 00092 00093 /*! [lossy -> lossless] down sample */ 00094 AST_TRANS_COST_LY_LL_DOWNSAMP = 960000, 00095 /*! [lossy -> lossy] down sample */ 00096 AST_TRANS_COST_LY_LY_DOWNSAMP = 975000, 00097 00098 /*! [lossy -> unknown] unknown. 00099 * This value is for a lossy source translation 00100 * with an unknown destination and or sample rate conversion. */ 00101 AST_TRANS_COST_LY_UNKNOWN = 985000, 00102 };
int __ast_register_translator | ( | struct ast_translator * | t, | |
struct ast_module * | mod | |||
) |
register codec translator
Register a translator This registers a codec translator with asterisk.
Definition at line 846 of file translate.c.
References ast_translator::active, ARRAY_LEN, ast_cli_register_multiple(), ast_getformatname(), ast_log(), AST_RWLIST_INSERT_BEFORE_CURRENT, AST_RWLIST_INSERT_HEAD, AST_RWLIST_TRAVERSE_SAFE_BEGIN, AST_RWLIST_TRAVERSE_SAFE_END, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, ast_verb, ast_translator::buf_size, calc_cost(), COLOR_BLACK, COLOR_MAGENTA, ast_translator::cost, default_frameout(), ast_translator::dstfmt, ast_translator::frameout, LOG_WARNING, MAX_FORMAT, ast_translator::module, ast_translator::name, powerof(), rebuild_matrix(), ast_translator::srcfmt, and term_color().
00847 { 00848 static int added_cli = 0; 00849 struct ast_translator *u; 00850 char tmp[80]; 00851 00852 if (!mod) { 00853 ast_log(LOG_WARNING, "Missing module pointer, you need to supply one\n"); 00854 return -1; 00855 } 00856 00857 if (!t->buf_size) { 00858 ast_log(LOG_WARNING, "empty buf size, you need to supply one\n"); 00859 return -1; 00860 } 00861 00862 t->module = mod; 00863 00864 t->srcfmt = powerof(t->srcfmt); 00865 t->dstfmt = powerof(t->dstfmt); 00866 t->active = 1; 00867 00868 if (t->srcfmt == -1 || t->dstfmt == -1) { 00869 ast_log(LOG_WARNING, "Invalid translator path: (%s codec is not valid)\n", t->srcfmt == -1 ? "starting" : "ending"); 00870 return -1; 00871 } 00872 if (t->srcfmt >= MAX_FORMAT) { 00873 ast_log(LOG_WARNING, "Source format %s is larger than MAX_FORMAT\n", ast_getformatname(t->srcfmt)); 00874 return -1; 00875 } 00876 00877 if (t->dstfmt >= MAX_FORMAT) { 00878 ast_log(LOG_WARNING, "Destination format %s is larger than MAX_FORMAT\n", ast_getformatname(t->dstfmt)); 00879 return -1; 00880 } 00881 00882 if (t->buf_size) { 00883 /* 00884 * Align buf_size properly, rounding up to the machine-specific 00885 * alignment for pointers. 00886 */ 00887 struct _test_align { void *a, *b; } p; 00888 int align = (char *)&p.b - (char *)&p.a; 00889 00890 t->buf_size = ((t->buf_size + align - 1) / align) * align; 00891 } 00892 00893 if (t->frameout == NULL) 00894 t->frameout = default_frameout; 00895 00896 calc_cost(t, 1); 00897 00898 ast_verb(2, "Registered translator '%s' from format %s to %s, cost %d\n", 00899 term_color(tmp, t->name, COLOR_MAGENTA, COLOR_BLACK, sizeof(tmp)), 00900 ast_getformatname(1LL << t->srcfmt), ast_getformatname(1LL << t->dstfmt), t->cost); 00901 00902 if (!added_cli) { 00903 ast_cli_register_multiple(cli_translate, ARRAY_LEN(cli_translate)); 00904 added_cli++; 00905 } 00906 00907 AST_RWLIST_WRLOCK(&translators); 00908 00909 /* find any existing translators that provide this same srcfmt/dstfmt, 00910 and put this one in order based on cost */ 00911 AST_RWLIST_TRAVERSE_SAFE_BEGIN(&translators, u, list) { 00912 if ((u->srcfmt == t->srcfmt) && 00913 (u->dstfmt == t->dstfmt) && 00914 (u->cost > t->cost)) { 00915 AST_RWLIST_INSERT_BEFORE_CURRENT(t, list); 00916 t = NULL; 00917 break; 00918 } 00919 } 00920 AST_RWLIST_TRAVERSE_SAFE_END; 00921 00922 /* if no existing translator was found for this format combination, 00923 add it to the beginning of the list */ 00924 if (t) 00925 AST_RWLIST_INSERT_HEAD(&translators, t, list); 00926 00927 rebuild_matrix(0); 00928 00929 AST_RWLIST_UNLOCK(&translators); 00930 00931 return 0; 00932 }
struct ast_frame* ast_trans_frameout | ( | struct ast_trans_pvt * | pvt, | |
int | datalen, | |||
int | samples | |||
) | [read] |
generic frameout routine. If samples and datalen are 0, take whatever is in pvt and reset them, otherwise take the values in the caller and leave alone the pvt values.
generic frameout function
Definition at line 235 of file translate.c.
References AST_FRAME_VOICE, AST_FRIENDLY_OFFSET, ast_frisolate(), ast_trans_pvt::c, ast_frame_subclass::codec, ast_frame::data, ast_trans_pvt::datalen, ast_frame::datalen, ast_translator::dstfmt, ast_trans_pvt::f, f, ast_frame::frametype, ast_frame::mallocd, ast_translator::name, ast_frame::offset, ast_trans_pvt::outbuf, ast_frame::ptr, ast_trans_pvt::samples, ast_frame::samples, ast_frame::src, ast_frame::subclass, and ast_trans_pvt::t.
Referenced by default_frameout(), lintoadpcm_frameout(), lintogsm_frameout(), lintoilbc_frameout(), lintolpc10_frameout(), and lintospeex_frameout().
00237 { 00238 struct ast_frame *f = &pvt->f; 00239 00240 if (samples) 00241 f->samples = samples; 00242 else { 00243 if (pvt->samples == 0) 00244 return NULL; 00245 f->samples = pvt->samples; 00246 pvt->samples = 0; 00247 } 00248 if (datalen) 00249 f->datalen = datalen; 00250 else { 00251 f->datalen = pvt->datalen; 00252 pvt->datalen = 0; 00253 } 00254 00255 f->frametype = AST_FRAME_VOICE; 00256 f->subclass.codec = 1LL << (pvt->t->dstfmt); 00257 f->mallocd = 0; 00258 f->offset = AST_FRIENDLY_OFFSET; 00259 f->src = pvt->t->name; 00260 f->data.ptr = pvt->outbuf.c; 00261 00262 return ast_frisolate(f); 00263 }
struct ast_frame* ast_translate | ( | struct ast_trans_pvt * | path, | |
struct ast_frame * | f, | |||
int | consume | |||
) | [read] |
do the actual translation
translates one or more frames Apply an input frame into the translator and receive zero or one output frames. Consume determines whether the original frame should be freed
Definition at line 328 of file translate.c.
References ast_format_rate(), AST_FRAME_CNG, AST_FRFLAG_HAS_TIMING_INFO, ast_frfree, ast_samp2tv(), ast_set2_flag, ast_test_flag, ast_tv(), ast_tvadd(), ast_tveq(), ast_tvnow(), ast_tvsub(), ast_tvzero(), ast_frame_subclass::codec, ast_frame::delivery, framein(), ast_frame::frametype, ast_frame::len, len(), ast_trans_pvt::next, ast_trans_pvt::nextin, ast_trans_pvt::nextout, ast_frame::samples, ast_frame::seqno, ast_frame::subclass, and ast_frame::ts.
Referenced by __ast_read(), ast_audiohook_read_frame(), ast_slinfactory_feed(), ast_write(), ast_writestream(), audio_audiohook_write_list(), and conf_run().
00329 { 00330 struct ast_trans_pvt *p = path; 00331 struct ast_frame *out = f; 00332 struct timeval delivery; 00333 int has_timing_info; 00334 long ts; 00335 long len; 00336 int seqno; 00337 00338 has_timing_info = ast_test_flag(f, AST_FRFLAG_HAS_TIMING_INFO); 00339 ts = f->ts; 00340 len = f->len; 00341 seqno = f->seqno; 00342 00343 /* XXX hmmm... check this below */ 00344 if (!ast_tvzero(f->delivery)) { 00345 if (!ast_tvzero(path->nextin)) { 00346 /* Make sure this is in line with what we were expecting */ 00347 if (!ast_tveq(path->nextin, f->delivery)) { 00348 /* The time has changed between what we expected and this 00349 most recent time on the new packet. If we have a 00350 valid prediction adjust our output time appropriately */ 00351 if (!ast_tvzero(path->nextout)) { 00352 path->nextout = ast_tvadd(path->nextout, 00353 ast_tvsub(f->delivery, path->nextin)); 00354 } 00355 path->nextin = f->delivery; 00356 } 00357 } else { 00358 /* This is our first pass. Make sure the timing looks good */ 00359 path->nextin = f->delivery; 00360 path->nextout = f->delivery; 00361 } 00362 /* Predict next incoming sample */ 00363 path->nextin = ast_tvadd(path->nextin, ast_samp2tv(f->samples, ast_format_rate(f->subclass.codec))); 00364 } 00365 delivery = f->delivery; 00366 for ( ; out && p ; p = p->next) { 00367 framein(p, out); 00368 if (out != f) 00369 ast_frfree(out); 00370 out = p->t->frameout(p); 00371 } 00372 if (consume) 00373 ast_frfree(f); 00374 if (out == NULL) 00375 return NULL; 00376 /* we have a frame, play with times */ 00377 if (!ast_tvzero(delivery)) { 00378 /* Regenerate prediction after a discontinuity */ 00379 if (ast_tvzero(path->nextout)) 00380 path->nextout = ast_tvnow(); 00381 00382 /* Use next predicted outgoing timestamp */ 00383 out->delivery = path->nextout; 00384 00385 /* Predict next outgoing timestamp from samples in this 00386 frame. */ 00387 path->nextout = ast_tvadd(path->nextout, ast_samp2tv(out->samples, ast_format_rate(out->subclass.codec))); 00388 } else { 00389 out->delivery = ast_tv(0, 0); 00390 ast_set2_flag(out, has_timing_info, AST_FRFLAG_HAS_TIMING_INFO); 00391 if (has_timing_info) { 00392 out->ts = ts; 00393 out->len = len; 00394 out->seqno = seqno; 00395 } 00396 } 00397 /* Invalidate prediction if we're entering a silence period */ 00398 if (out->frametype == AST_FRAME_CNG) 00399 path->nextout = ast_tv(0, 0); 00400 return out; 00401 }
Mask off unavailable formats from a format bitmask.
The result will include all formats from 'dest' that are either present in 'src' or translatable from a format present in 'src'.
Definition at line 1074 of file translate.c.
References AST_FORMAT_AUDIO_MASK, AST_FORMAT_VIDEO_MASK, AST_RWLIST_RDLOCK, AST_RWLIST_UNLOCK, powerof(), and tr_matrix.
Referenced by ast_rtp_instance_available_formats().
01075 { 01076 format_t res = dest; 01077 format_t x; 01078 format_t src_audio = src & AST_FORMAT_AUDIO_MASK; 01079 format_t src_video = src & AST_FORMAT_VIDEO_MASK; 01080 format_t x_bits; 01081 01082 /* if we don't have a source format, we just have to try all 01083 possible destination formats */ 01084 if (!src) 01085 return dest; 01086 01087 /* If we have a source audio format, get its format index */ 01088 if (src_audio) { 01089 src_audio = powerof(src_audio); 01090 } 01091 01092 /* If we have a source video format, get its format index */ 01093 if (src_video) { 01094 src_video = powerof(src_video); 01095 } 01096 01097 /* Note that src_audio and src_video are guaranteed to not be 01098 * negative at this point, as we ensured they were non-zero. It is 01099 * safe to use the return value of powerof as an index into tr_matrix. 01100 */ 01101 01102 AST_RWLIST_RDLOCK(&translators); 01103 01104 /* For a given source audio format, traverse the list of 01105 known audio formats to determine whether there exists 01106 a translation path from the source format to the 01107 destination format. */ 01108 for (x = 1LL; src_audio && x > 0; x <<= 1) { 01109 if (!(x & AST_FORMAT_AUDIO_MASK)) { 01110 continue; 01111 } 01112 01113 /* if this is not a desired format, nothing to do */ 01114 if (!(dest & x)) 01115 continue; 01116 01117 /* if the source is supplying this format, then 01118 we can leave it in the result */ 01119 if (src & x) 01120 continue; 01121 01122 /* if we don't have a translation path from the src 01123 to this format, remove it from the result. Note that x_bits 01124 cannot be less than 0 as x will always have one bit set to 1 */ 01125 x_bits = powerof(x); 01126 if (!tr_matrix[src_audio][x_bits].step) { 01127 res &= ~x; 01128 continue; 01129 } 01130 01131 /* now check the opposite direction */ 01132 if (!tr_matrix[x_bits][src_audio].step) 01133 res &= ~x; 01134 } 01135 01136 /* For a given source video format, traverse the list of 01137 known video formats to determine whether there exists 01138 a translation path from the source format to the 01139 destination format. */ 01140 for (x = 1LL; src_video && x > 0; x <<= 1) { 01141 if (!(x & AST_FORMAT_VIDEO_MASK)) { 01142 continue; 01143 } 01144 01145 /* if this is not a desired format, nothing to do */ 01146 if (!(dest & x)) 01147 continue; 01148 01149 /* if the source is supplying this format, then 01150 we can leave it in the result */ 01151 if (src & x) 01152 continue; 01153 01154 /* if we don't have a translation path from the src 01155 to this format, remove it from the result. Note that x_bits 01156 cannot be less than 0 as x will always have one bit set to 1 */ 01157 x_bits = powerof(x); 01158 if (!tr_matrix[src_video][x_bits].step) { 01159 res &= ~x; 01160 continue; 01161 } 01162 01163 /* now check the opposite direction */ 01164 if (!tr_matrix[x_bits][src_video].step) 01165 res &= ~x; 01166 } 01167 01168 AST_RWLIST_UNLOCK(&translators); 01169 01170 return res; 01171 }
Returns the number of steps required to convert from 'src' to 'dest'.
dest | destination format | |
src | source format |
Definition at line 1052 of file translate.c.
References ast_log(), AST_RWLIST_RDLOCK, AST_RWLIST_UNLOCK, LOG_WARNING, translator_path::multistep, powerof(), and tr_matrix.
Referenced by ast_channel_make_compatible_helper().
01053 { 01054 unsigned int res = -1; 01055 01056 /* convert bitwise format numbers into array indices */ 01057 src = powerof(src); 01058 dest = powerof(dest); 01059 01060 if (src == -1 || dest == -1) { 01061 ast_log(LOG_WARNING, "No translator path: (%s codec is not valid)\n", src == -1 ? "starting" : "ending"); 01062 return -1; 01063 } 01064 AST_RWLIST_RDLOCK(&translators); 01065 01066 if (tr_matrix[src][dest].step) 01067 res = tr_matrix[src][dest].multistep + 1; 01068 01069 AST_RWLIST_UNLOCK(&translators); 01070 01071 return res; 01072 }
const char* ast_translate_path_to_str | ( | struct ast_trans_pvt * | t, | |
struct ast_str ** | str | |||
) |
Puts a string representation of the translation path into outbuf.
translator | structure containing the translation path | |
ast_str | output buffer |
on | success pointer to beginning of outbuf. on failure "". |
Definition at line 623 of file translate.c.
References ast_getformatname(), ast_str_append(), ast_str_buffer(), ast_str_set(), ast_translator::dstfmt, ast_trans_pvt::next, ast_translator::srcfmt, and ast_trans_pvt::t.
Referenced by handle_showchan(), and serialize_showchan().
00624 { 00625 struct ast_trans_pvt *pn = p; 00626 00627 if (!p || !p->t) { 00628 return ""; 00629 } 00630 00631 ast_str_set(str, 0, "%s", ast_getformatname(1LL << p->t->srcfmt)); 00632 00633 while ( (p = pn) ) { 00634 pn = p->next; 00635 ast_str_append(str, 0, "->%s", ast_getformatname(1LL << p->t->dstfmt)); 00636 } 00637 00638 return ast_str_buffer(*str); 00639 }
void ast_translator_activate | ( | struct ast_translator * | t | ) |
Activate a previously deactivated translator.
t | translator to activate |
Enables the specified translator for use.
Definition at line 960 of file translate.c.
References ast_translator::active, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, and rebuild_matrix().
00961 { 00962 AST_RWLIST_WRLOCK(&translators); 00963 t->active = 1; 00964 rebuild_matrix(0); 00965 AST_RWLIST_UNLOCK(&translators); 00966 }
Calculate our best translator source format, given costs, and a desired destination.
Chooses the best translation path.
Definition at line 977 of file translate.c.
References AST_FORMAT_AUDIO_MASK, ast_format_rate(), AST_RWLIST_RDLOCK, AST_RWLIST_UNLOCK, translator_path::cost, ast_translator::cost, MAX_AUDIO_FORMAT, translator_path::multistep, translator_path::rate_change, and tr_matrix.
Referenced by ast_channel_make_compatible_helper(), ast_request(), iax2_request(), and set_format().
00978 { 00979 int x,y; 00980 int better = 0; 00981 int besttime = INT_MAX; 00982 int beststeps = INT_MAX; 00983 unsigned int best_rate_change = INT_MAX; 00984 format_t best = -1; 00985 format_t bestdst = 0; 00986 format_t cur, cursrc; 00987 format_t common = ((*dst) & (*srcs)) & AST_FORMAT_AUDIO_MASK; /* are there common formats ? */ 00988 00989 if (common) { /* yes, pick one and return */ 00990 for (cur = 1, y = 0; y <= MAX_AUDIO_FORMAT; cur <<= 1, y++) { 00991 if (!(cur & common)) { 00992 continue; 00993 } 00994 00995 /* We are guaranteed to find one common format. */ 00996 if (best == -1) { 00997 best = cur; 00998 continue; 00999 } 01000 /* If there are multiple common formats, pick the one with the highest sample rate */ 01001 if (ast_format_rate(best) < ast_format_rate(cur)) { 01002 best = cur; 01003 continue; 01004 } 01005 } 01006 /* We are done, this is a common format to both. */ 01007 *srcs = *dst = best; 01008 return 0; 01009 } else { /* No, we will need to translate */ 01010 AST_RWLIST_RDLOCK(&translators); 01011 for (cur = 1, y = 0; y <= MAX_AUDIO_FORMAT; cur <<= 1, y++) { 01012 if (! (cur & *dst)) { 01013 continue; 01014 } 01015 for (cursrc = 1, x = 0; x <= MAX_AUDIO_FORMAT; cursrc <<= 1, x++) { 01016 if (!(*srcs & cursrc) || !tr_matrix[x][y].step) { 01017 continue; 01018 } 01019 01020 /* This is a better choice if any of the following are true. 01021 * 1. The sample rate conversion is better than the current pick. 01022 * 2. the sample rate conversion is no worse than the current pick and the cost or multistep is better 01023 */ 01024 better = 0; 01025 if (tr_matrix[x][y].rate_change < best_rate_change) { 01026 better = 1; /* this match has a better rate conversion */ 01027 } 01028 if ((tr_matrix[x][y].rate_change <= best_rate_change) && 01029 (tr_matrix[x][y].cost < besttime || tr_matrix[x][y].multistep < beststeps)) { 01030 better = 1; /* this match has no worse rate conversion and the conversion cost is less */ 01031 } 01032 if (better) { 01033 /* better than what we have so far */ 01034 best = cursrc; 01035 bestdst = cur; 01036 besttime = tr_matrix[x][y].cost; 01037 beststeps = tr_matrix[x][y].multistep; 01038 best_rate_change = tr_matrix[x][y].rate_change; 01039 } 01040 } 01041 } 01042 AST_RWLIST_UNLOCK(&translators); 01043 if (best > -1) { 01044 *srcs = best; 01045 *dst = bestdst; 01046 best = 0; 01047 } 01048 return best; 01049 } 01050 }
struct ast_trans_pvt* ast_translator_build_path | ( | format_t | dest, | |
format_t | source | |||
) | [read] |
Build a chain of translators based upon the given source and dest formats.
Builds a translator path Build a path (possibly NULL) from source to dest.
Definition at line 282 of file translate.c.
References ast_getformatname(), ast_log(), AST_RWLIST_RDLOCK, AST_RWLIST_UNLOCK, ast_translator_free_path(), ast_tv(), ast_translator::dstfmt, LOG_WARNING, newpvt(), ast_trans_pvt::next, ast_trans_pvt::nextin, ast_trans_pvt::nextout, powerof(), translator_path::step, ast_trans_pvt::t, and tr_matrix.
Referenced by ast_audiohook_read_frame(), ast_slinfactory_feed(), ast_writestream(), audio_audiohook_write_list(), conf_run(), and set_format().
00283 { 00284 struct ast_trans_pvt *head = NULL, *tail = NULL; 00285 00286 source = powerof(source); 00287 dest = powerof(dest); 00288 00289 if (source == -1 || dest == -1) { 00290 ast_log(LOG_WARNING, "No translator path: (%s codec is not valid)\n", source == -1 ? "starting" : "ending"); 00291 return NULL; 00292 } 00293 00294 AST_RWLIST_RDLOCK(&translators); 00295 00296 while (source != dest) { 00297 struct ast_trans_pvt *cur; 00298 struct ast_translator *t = tr_matrix[source][dest].step; 00299 if (!t) { 00300 ast_log(LOG_WARNING, "No translator path from %s to %s\n", 00301 ast_getformatname(source), ast_getformatname(dest)); 00302 AST_RWLIST_UNLOCK(&translators); 00303 return NULL; 00304 } 00305 if (!(cur = newpvt(t))) { 00306 ast_log(LOG_WARNING, "Failed to build translator step from %s to %s\n", 00307 ast_getformatname(source), ast_getformatname(dest)); 00308 if (head) 00309 ast_translator_free_path(head); 00310 AST_RWLIST_UNLOCK(&translators); 00311 return NULL; 00312 } 00313 if (!head) 00314 head = cur; 00315 else 00316 tail->next = cur; 00317 tail = cur; 00318 cur->nextin = cur->nextout = ast_tv(0, 0); 00319 /* Keep going if this isn't the final destination */ 00320 source = cur->t->dstfmt; 00321 } 00322 00323 AST_RWLIST_UNLOCK(&translators); 00324 return head; 00325 }
void ast_translator_deactivate | ( | struct ast_translator * | t | ) |
Deactivate a translator.
t | translator to deactivate |
Disables the specified translator from being used.
Definition at line 968 of file translate.c.
References ast_translator::active, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, and rebuild_matrix().
00969 { 00970 AST_RWLIST_WRLOCK(&translators); 00971 t->active = 0; 00972 rebuild_matrix(0); 00973 AST_RWLIST_UNLOCK(&translators); 00974 }
void ast_translator_free_path | ( | struct ast_trans_pvt * | tr | ) |
Frees a translator path Frees the given translator path structure.
tr | translator path to get rid of |
Definition at line 272 of file translate.c.
References destroy(), and ast_trans_pvt::next.
Referenced by ast_audiohook_destroy(), ast_audiohook_detach_list(), ast_audiohook_read_frame(), ast_channel_destructor(), ast_slinfactory_destroy(), ast_slinfactory_feed(), ast_slinfactory_flush(), ast_translator_build_path(), ast_writestream(), audio_audiohook_write_list(), conf_free(), filestream_destructor(), free_translation(), and set_format().
00273 { 00274 struct ast_trans_pvt *pn = p; 00275 while ( (p = pn) ) { 00276 pn = p->next; 00277 destroy(p); 00278 } 00279 }
int ast_unregister_translator | ( | struct ast_translator * | t | ) |
unregister codec translator
Unregister a translator Unregisters the given tranlator.
Definition at line 935 of file translate.c.
References ast_getformatname(), AST_RWLIST_REMOVE_CURRENT, AST_RWLIST_TRAVERSE_SAFE_BEGIN, AST_RWLIST_TRAVERSE_SAFE_END, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, ast_verb, COLOR_BLACK, COLOR_MAGENTA, ast_translator::dstfmt, ast_translator::list, ast_translator::name, rebuild_matrix(), ast_translator::srcfmt, and term_color().
Referenced by drop_translator(), load_module(), unload_module(), and unregister_translators().
00936 { 00937 char tmp[80]; 00938 struct ast_translator *u; 00939 int found = 0; 00940 00941 AST_RWLIST_WRLOCK(&translators); 00942 AST_RWLIST_TRAVERSE_SAFE_BEGIN(&translators, u, list) { 00943 if (u == t) { 00944 AST_RWLIST_REMOVE_CURRENT(list); 00945 ast_verb(2, "Unregistered translator '%s' from format %s to %s\n", term_color(tmp, t->name, COLOR_MAGENTA, COLOR_BLACK, sizeof(tmp)), ast_getformatname(1LL << t->srcfmt), ast_getformatname(1LL << t->dstfmt)); 00946 found = 1; 00947 break; 00948 } 00949 } 00950 AST_RWLIST_TRAVERSE_SAFE_END; 00951 00952 if (found) 00953 rebuild_matrix(0); 00954 00955 AST_RWLIST_UNLOCK(&translators); 00956 00957 return (u ? 0 : -1); 00958 }
static void calc_cost | ( | struct ast_translator * | t, | |
int | seconds | |||
) | [static] |
compute the cost of a single translation step
Definition at line 404 of file translate.c.
References ast_format_rate(), ast_frfree, ast_log(), ast_translator::cost, destroy(), ast_translator::dstfmt, f, framein(), ast_translator::frameout, LOG_WARNING, ast_translator::name, newpvt(), ast_trans_pvt::pvt, ast_translator::sample, and ast_frame::samples.
Referenced by __ast_register_translator(), and rebuild_matrix().
00405 { 00406 int num_samples = 0; 00407 struct ast_trans_pvt *pvt; 00408 struct rusage start; 00409 struct rusage end; 00410 int cost; 00411 int out_rate = ast_format_rate(t->dstfmt); 00412 00413 if (!seconds) 00414 seconds = 1; 00415 00416 /* If they don't make samples, give them a terrible score */ 00417 if (!t->sample) { 00418 ast_log(LOG_WARNING, "Translator '%s' does not produce sample frames.\n", t->name); 00419 t->cost = 999999; 00420 return; 00421 } 00422 00423 pvt = newpvt(t); 00424 if (!pvt) { 00425 ast_log(LOG_WARNING, "Translator '%s' appears to be broken and will probably fail.\n", t->name); 00426 t->cost = 999999; 00427 return; 00428 } 00429 00430 getrusage(RUSAGE_SELF, &start); 00431 00432 /* Call the encoder until we've processed the required number of samples */ 00433 while (num_samples < seconds * out_rate) { 00434 struct ast_frame *f = t->sample(); 00435 if (!f) { 00436 ast_log(LOG_WARNING, "Translator '%s' failed to produce a sample frame.\n", t->name); 00437 destroy(pvt); 00438 t->cost = 999999; 00439 return; 00440 } 00441 framein(pvt, f); 00442 ast_frfree(f); 00443 while ((f = t->frameout(pvt))) { 00444 num_samples += f->samples; 00445 ast_frfree(f); 00446 } 00447 } 00448 00449 getrusage(RUSAGE_SELF, &end); 00450 00451 cost = ((end.ru_utime.tv_sec - start.ru_utime.tv_sec) * 1000000) + end.ru_utime.tv_usec - start.ru_utime.tv_usec; 00452 cost += ((end.ru_stime.tv_sec - start.ru_stime.tv_sec) * 1000000) + end.ru_stime.tv_usec - start.ru_stime.tv_usec; 00453 00454 destroy(pvt); 00455 00456 t->cost = cost / seconds; 00457 00458 if (!t->cost) 00459 t->cost = 1; 00460 }
static char* complete_trans_path_choice | ( | const char * | line, | |
const char * | word, | |||
int | pos, | |||
int | state | |||
) | [static] |
Definition at line 641 of file translate.c.
References AST_FORMAT_AUDIO_MASK, ast_get_format_list(), ast_strdup, ast_format_list::bits, len(), and name.
Referenced by handle_cli_core_show_translation().
00642 { 00643 int which = 0; 00644 int wordlen = strlen(word); 00645 int i; 00646 char *ret = NULL; 00647 size_t len = 0; 00648 const struct ast_format_list *format_list = ast_get_format_list(&len); 00649 00650 for (i = 0; i < len; i++) { 00651 if (!(format_list[i].bits & AST_FORMAT_AUDIO_MASK)) { 00652 continue; 00653 } 00654 if (!strncasecmp(word, format_list[i].name, wordlen) && ++which > state) { 00655 ret = ast_strdup(format_list[i].name); 00656 break; 00657 } 00658 } 00659 return ret; 00660 }
static struct ast_frame* default_frameout | ( | struct ast_trans_pvt * | pvt | ) | [static, read] |
Definition at line 265 of file translate.c.
References ast_trans_frameout().
Referenced by __ast_register_translator().
00266 { 00267 return ast_trans_frameout(pvt, 0, 0); 00268 }
static void destroy | ( | struct ast_trans_pvt * | pvt | ) | [static] |
Definition at line 183 of file translate.c.
References ast_free, ast_module_unref(), ast_translator::destroy, ast_translator::module, and ast_trans_pvt::t.
Referenced by ast_translator_free_path(), and calc_cost().
00184 { 00185 struct ast_translator *t = pvt->t; 00186 00187 if (t->destroy) 00188 t->destroy(pvt); 00189 ast_free(pvt); 00190 ast_module_unref(t->module); 00191 }
static int framein | ( | struct ast_trans_pvt * | pvt, | |
struct ast_frame * | f | |||
) | [static] |
framein wrapper, deals with bound checks.
Definition at line 194 of file translate.c.
References ast_copy_flags, AST_FRFLAG_HAS_TIMING_INFO, ast_log(), ast_translator::buffer_samples, ast_frame::datalen, ast_trans_pvt::f, ast_translator::framein, ast_frame::len, LOG_WARNING, ast_translator::name, ast_translator::native_plc, ast_frame::samples, ast_trans_pvt::samples, ast_frame::seqno, ast_trans_pvt::t, and ast_frame::ts.
Referenced by ast_translate(), and calc_cost().
00195 { 00196 int ret; 00197 int samples = pvt->samples; /* initial value */ 00198 00199 /* Copy the last in jb timing info to the pvt */ 00200 ast_copy_flags(&pvt->f, f, AST_FRFLAG_HAS_TIMING_INFO); 00201 pvt->f.ts = f->ts; 00202 pvt->f.len = f->len; 00203 pvt->f.seqno = f->seqno; 00204 00205 if (f->samples == 0) { 00206 ast_log(LOG_WARNING, "no samples for %s\n", pvt->t->name); 00207 } 00208 if (pvt->t->buffer_samples) { /* do not pass empty frames to callback */ 00209 if (f->datalen == 0) { /* perform native PLC if available */ 00210 /* If the codec has native PLC, then do that */ 00211 if (!pvt->t->native_plc) 00212 return 0; 00213 } 00214 if (pvt->samples + f->samples > pvt->t->buffer_samples) { 00215 ast_log(LOG_WARNING, "Out of buffer space\n"); 00216 return -1; 00217 } 00218 } 00219 /* we require a framein routine, wouldn't know how to do 00220 * it otherwise. 00221 */ 00222 ret = pvt->t->framein(pvt, f); 00223 /* diagnostic ... */ 00224 if (pvt->samples == samples) 00225 ast_log(LOG_WARNING, "%s did not update samples %d\n", 00226 pvt->t->name, pvt->samples); 00227 return ret; 00228 }
static enum path_samp_change get_rate_change_result | ( | format_t | src, | |
format_t | dst | |||
) | [static] |
Definition at line 462 of file translate.c.
References ast_format_rate(), AST_FORMAT_SLINEAR, AST_FORMAT_SLINEAR16, AST_TRANS_COST_LL_LL_DOWNSAMP, AST_TRANS_COST_LL_LL_ORIGSAMP, AST_TRANS_COST_LL_LL_UPSAMP, AST_TRANS_COST_LL_LY_DOWNSAMP, AST_TRANS_COST_LL_LY_ORIGSAMP, AST_TRANS_COST_LL_LY_UPSAMP, AST_TRANS_COST_LL_UNKNOWN, AST_TRANS_COST_LY_LL_DOWNSAMP, AST_TRANS_COST_LY_LL_ORIGSAMP, AST_TRANS_COST_LY_LL_UPSAMP, AST_TRANS_COST_LY_LY_DOWNSAMP, AST_TRANS_COST_LY_LY_ORIGSAMP, AST_TRANS_COST_LY_LY_UPSAMP, and AST_TRANS_COST_LY_UNKNOWN.
Referenced by rebuild_matrix().
00463 { 00464 int src_ll = src == AST_FORMAT_SLINEAR || src == AST_FORMAT_SLINEAR16; 00465 int dst_ll = dst == AST_FORMAT_SLINEAR || src == AST_FORMAT_SLINEAR16; 00466 int src_rate = ast_format_rate(src); 00467 int dst_rate = ast_format_rate(dst); 00468 00469 if (src_ll) { 00470 if (dst_ll && (src_rate == dst_rate)) { 00471 return AST_TRANS_COST_LL_LL_ORIGSAMP; 00472 } else if (!dst_ll && (src_rate == dst_rate)) { 00473 return AST_TRANS_COST_LL_LY_ORIGSAMP; 00474 } else if (dst_ll && (src_rate < dst_rate)) { 00475 return AST_TRANS_COST_LL_LL_UPSAMP; 00476 } else if (!dst_ll && (src_rate < dst_rate)) { 00477 return AST_TRANS_COST_LL_LY_UPSAMP; 00478 } else if (dst_ll && (src_rate > dst_rate)) { 00479 return AST_TRANS_COST_LL_LL_DOWNSAMP; 00480 } else if (!dst_ll && (src_rate > dst_rate)) { 00481 return AST_TRANS_COST_LL_LY_DOWNSAMP; 00482 } else { 00483 return AST_TRANS_COST_LL_UNKNOWN; 00484 } 00485 } else { 00486 if (dst_ll && (src_rate == dst_rate)) { 00487 return AST_TRANS_COST_LY_LL_ORIGSAMP; 00488 } else if (!dst_ll && (src_rate == dst_rate)) { 00489 return AST_TRANS_COST_LY_LY_ORIGSAMP; 00490 } else if (dst_ll && (src_rate < dst_rate)) { 00491 return AST_TRANS_COST_LY_LL_UPSAMP; 00492 } else if (!dst_ll && (src_rate < dst_rate)) { 00493 return AST_TRANS_COST_LY_LY_UPSAMP; 00494 } else if (dst_ll && (src_rate > dst_rate)) { 00495 return AST_TRANS_COST_LY_LL_DOWNSAMP; 00496 } else if (!dst_ll && (src_rate > dst_rate)) { 00497 return AST_TRANS_COST_LY_LY_DOWNSAMP; 00498 } else { 00499 return AST_TRANS_COST_LY_UNKNOWN; 00500 } 00501 } 00502 }
static char* handle_cli_core_show_translation | ( | struct ast_cli_entry * | e, | |
int | cmd, | |||
struct ast_cli_args * | a | |||
) | [static] |
Definition at line 662 of file translate.c.
References ast_cli_args::argc, ast_cli_args::argv, ast_cli(), ast_cli_complete(), AST_FORMAT_AUDIO_MASK, ast_format_rate(), ast_get_format_list(), ast_getformatname(), AST_RWLIST_RDLOCK, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, ast_str_alloca, ast_str_append(), ast_str_buffer(), ast_str_reset(), ast_str_set(), ast_strlen_zero(), ast_format_list::bits, CLI_FAILURE, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, complete_trans_path_choice(), ast_translator::cost, ast_cli_args::fd, len(), ast_cli_args::line, MAX_RECALC, ast_cli_args::n, ast_format_list::name, name, ast_cli_args::pos, powerof(), rebuild_matrix(), SHOW_TRANS, translator_path::step, str, tr_matrix, ast_cli_entry::usage, and ast_cli_args::word.
00663 { 00664 #define SHOW_TRANS 64 00665 static const char * const option1[] = { "recalc", "paths", NULL }; 00666 int x, y, z; 00667 int curlen = 0, longest = 0, magnitude[SHOW_TRANS] = { 0, }; 00668 00669 switch (cmd) { 00670 case CLI_INIT: 00671 e->command = "core show translation"; 00672 e->usage = 00673 "Usage: 'core show translation' can be used in two ways.\n" 00674 " 1. 'core show translation [recalc [<recalc seconds>]]\n" 00675 " Displays known codec translators and the cost associated\n" 00676 " with each conversion. If the argument 'recalc' is supplied along\n" 00677 " with optional number of seconds to test a new test will be performed\n" 00678 " as the chart is being displayed.\n" 00679 " 2. 'core show translation paths [codec]'\n" 00680 " This will display all the translation paths associated with a codec\n"; 00681 return NULL; 00682 case CLI_GENERATE: 00683 if (a->pos == 3) { 00684 return ast_cli_complete(a->word, option1, a->n); 00685 } 00686 if (a->pos == 4 && !strcasecmp(a->argv[3], option1[1])) { 00687 return complete_trans_path_choice(a->line, a->word, a->pos, a->n); 00688 } 00689 return NULL; 00690 } 00691 00692 if (a->argc > 5) 00693 return CLI_SHOWUSAGE; 00694 00695 if (a->argv[3] && !strcasecmp(a->argv[3], option1[1]) && a->argc == 5) { 00696 format_t input_src = 0; 00697 format_t src = 0; 00698 size_t len = 0; 00699 int dst; 00700 int i; 00701 const struct ast_format_list *format_list = ast_get_format_list(&len); 00702 struct ast_str *str = ast_str_alloca(256); 00703 struct ast_translator *step; 00704 00705 for (i = 0; i < len; i++) { 00706 if (!(format_list[i].bits & AST_FORMAT_AUDIO_MASK)) { 00707 continue; 00708 } 00709 if (!strncasecmp(format_list[i].name, a->argv[4], strlen(format_list[i].name))) { 00710 input_src = format_list[i].bits; 00711 } 00712 } 00713 00714 if (!input_src) { 00715 ast_cli(a->fd, "Source codec \"%s\" is not found.\n", a->argv[4]); 00716 return CLI_FAILURE; 00717 } 00718 00719 AST_RWLIST_RDLOCK(&translators); 00720 ast_cli(a->fd, "--- Translation paths SRC Codec \"%s\" sample rate %d ---\n", a->argv[4], ast_format_rate(input_src)); 00721 for (i = 0; i < len; i++) { 00722 if (!(format_list[i].bits & AST_FORMAT_AUDIO_MASK) || (format_list[i].bits == input_src)) { 00723 continue; 00724 } 00725 /* Note that dst can never be -1, as an element of format_list will have 00726 * at least one bit set. src cannot be -1 as well, as it is previously 00727 * sanitized - hence it is safe to directly index tr_matrix with the results 00728 * of powerof. 00729 */ 00730 dst = powerof(format_list[i].bits); 00731 src = powerof(input_src); 00732 ast_str_reset(str); 00733 if (tr_matrix[src][dst].step) { 00734 ast_str_append(&str, 0, "%s", ast_getformatname(1LL << tr_matrix[src][dst].step->srcfmt)); 00735 while (src != dst) { 00736 step = tr_matrix[src][dst].step; 00737 if (!step) { 00738 ast_str_reset(str); 00739 break; 00740 } 00741 ast_str_append(&str, 0, "->%s", ast_getformatname(1LL << step->dstfmt)); 00742 src = step->dstfmt; 00743 } 00744 } 00745 00746 if (ast_strlen_zero(ast_str_buffer(str))) { 00747 ast_str_set(&str, 0, "No Translation Path"); 00748 } 00749 00750 ast_cli(a->fd, "\t%-10.10s To %-10.10s: %-60.60s\n", a->argv[4], format_list[i].name, ast_str_buffer(str)); 00751 } 00752 AST_RWLIST_UNLOCK(&translators); 00753 00754 return CLI_SUCCESS; 00755 } else if (a->argv[3] && !strcasecmp(a->argv[3], "recalc")) { 00756 z = a->argv[4] ? atoi(a->argv[4]) : 1; 00757 00758 if (z <= 0) { 00759 ast_cli(a->fd, " Recalc must be greater than 0. Defaulting to 1.\n"); 00760 z = 1; 00761 } 00762 00763 if (z > MAX_RECALC) { 00764 ast_cli(a->fd, " Maximum limit of recalc exceeded by %d, truncating value to %d\n", z - MAX_RECALC, MAX_RECALC); 00765 z = MAX_RECALC; 00766 } 00767 ast_cli(a->fd, " Recalculating Codec Translation (number of sample seconds: %d)\n\n", z); 00768 AST_RWLIST_WRLOCK(&translators); 00769 rebuild_matrix(z); 00770 AST_RWLIST_UNLOCK(&translators); 00771 } else if (a->argc > 3) 00772 return CLI_SHOWUSAGE; 00773 00774 AST_RWLIST_RDLOCK(&translators); 00775 00776 ast_cli(a->fd, " Translation times between formats (in microseconds) for one second of data\n"); 00777 ast_cli(a->fd, " Source Format (Rows) Destination Format (Columns)\n\n"); 00778 /* Get the length of the longest (usable?) codec name, so we know how wide the left side should be */ 00779 for (x = 0; x < SHOW_TRANS; x++) { 00780 /* translation only applies to audio right now. */ 00781 if (!(AST_FORMAT_AUDIO_MASK & (1LL << (x)))) 00782 continue; 00783 curlen = strlen(ast_getformatname(1LL << (x))); 00784 if (curlen > longest) 00785 longest = curlen; 00786 for (y = 0; y < SHOW_TRANS; y++) { 00787 if (!(AST_FORMAT_AUDIO_MASK & (1LL << (y)))) 00788 continue; 00789 if (tr_matrix[x][y].cost > pow(10, magnitude[x])) { 00790 magnitude[y] = floor(log10(tr_matrix[x][y].cost)); 00791 } 00792 } 00793 } 00794 for (x = -1; x < SHOW_TRANS; x++) { 00795 struct ast_str *out = ast_str_alloca(256); 00796 /* translation only applies to audio right now. */ 00797 if (x >= 0 && !(AST_FORMAT_AUDIO_MASK & (1LL << (x)))) 00798 continue; 00799 /*Go ahead and move to next iteration if dealing with an unknown codec*/ 00800 if(x >= 0 && !strcmp(ast_getformatname(1LL << (x)), "unknown")) 00801 continue; 00802 ast_str_set(&out, -1, " "); 00803 for (y = -1; y < SHOW_TRANS; y++) { 00804 /* translation only applies to audio right now. */ 00805 if (y >= 0 && !(AST_FORMAT_AUDIO_MASK & (1LL << (y)))) 00806 continue; 00807 /*Go ahead and move to next iteration if dealing with an unknown codec*/ 00808 if (y >= 0 && !strcmp(ast_getformatname(1LL << (y)), "unknown")) 00809 continue; 00810 if (y >= 0) 00811 curlen = strlen(ast_getformatname(1LL << (y))); 00812 if (y >= 0 && magnitude[y] + 1 > curlen) { 00813 curlen = magnitude[y] + 1; 00814 } 00815 if (curlen < 5) 00816 curlen = 5; 00817 if (x >= 0 && y >= 0 && tr_matrix[x][y].step) { 00818 /* Actual codec output */ 00819 ast_str_append(&out, -1, "%*d", curlen + 1, tr_matrix[x][y].cost); 00820 } else if (x == -1 && y >= 0) { 00821 /* Top row - use a dynamic size */ 00822 ast_str_append(&out, -1, "%*s", curlen + 1, ast_getformatname(1LL << (y)) ); 00823 } else if (y == -1 && x >= 0) { 00824 /* Left column - use a static size. */ 00825 ast_str_append(&out, -1, "%*s", longest, ast_getformatname(1LL << (x)) ); 00826 } else if (x >= 0 && y >= 0) { 00827 /* Codec not supported */ 00828 ast_str_append(&out, -1, "%*s", curlen + 1, "-"); 00829 } else { 00830 /* Upper left hand corner */ 00831 ast_str_append(&out, -1, "%*s", longest, ""); 00832 } 00833 } 00834 ast_str_append(&out, -1, "\n"); 00835 ast_cli(a->fd, "%s", ast_str_buffer(out)); 00836 } 00837 AST_RWLIST_UNLOCK(&translators); 00838 return CLI_SUCCESS; 00839 }
static void* newpvt | ( | struct ast_translator * | t | ) | [static] |
Allocate the descriptor, required outbuf space, and possibly desc.
Definition at line 150 of file translate.c.
References ast_calloc, ast_free, AST_FRIENDLY_OFFSET, ast_module_ref(), ast_translator::buf_size, ast_trans_pvt::c, ast_translator::desc_size, len(), ast_translator::module, ast_translator::newpvt, ast_trans_pvt::outbuf, ast_trans_pvt::pvt, and ast_trans_pvt::t.
Referenced by ast_translator_build_path(), and calc_cost().
00151 { 00152 struct ast_trans_pvt *pvt; 00153 int len; 00154 char *ofs; 00155 00156 /* 00157 * compute the required size adding private descriptor, 00158 * buffer, AST_FRIENDLY_OFFSET. 00159 */ 00160 len = sizeof(*pvt) + t->desc_size; 00161 if (t->buf_size) 00162 len += AST_FRIENDLY_OFFSET + t->buf_size; 00163 pvt = ast_calloc(1, len); 00164 if (!pvt) 00165 return NULL; 00166 pvt->t = t; 00167 ofs = (char *)(pvt + 1); /* pointer to data space */ 00168 if (t->desc_size) { /* first comes the descriptor */ 00169 pvt->pvt = ofs; 00170 ofs += t->desc_size; 00171 } 00172 if (t->buf_size) /* finally buffer and header */ 00173 pvt->outbuf.c = ofs + AST_FRIENDLY_OFFSET; 00174 /* call local init routine, if present */ 00175 if (t->newpvt && t->newpvt(pvt)) { 00176 ast_free(pvt); 00177 return NULL; 00178 } 00179 ast_module_ref(t->module); 00180 return pvt; 00181 }
static force_inline int powerof | ( | format_t | d | ) | [static] |
returns the index of the lowest bit set
Definition at line 130 of file translate.c.
References ast_log(), and LOG_WARNING.
Referenced by __ast_register_translator(), ast_translate_available_formats(), ast_translate_path_steps(), ast_translator_build_path(), and handle_cli_core_show_translation().
00131 { 00132 int x = ffsll(d); 00133 00134 if (x) 00135 return x - 1; 00136 00137 ast_log(LOG_WARNING, "No bits set? %llu\n", (unsigned long long) d); 00138 00139 return -1; 00140 }
static void rebuild_matrix | ( | int | samples | ) | [static] |
rebuild a translation matrix.
Definition at line 508 of file translate.c.
References ast_translator::active, ast_debug, ast_getformatname(), AST_RWLIST_TRAVERSE, calc_cost(), translator_path::cost, ast_translator::cost, ast_translator::dstfmt, get_rate_change_result(), ast_translator::list, MAX_FORMAT, translator_path::multistep, translator_path::rate_change, ast_translator::srcfmt, translator_path::step, and tr_matrix.
Referenced by __ast_register_translator(), ast_translator_activate(), ast_translator_deactivate(), ast_unregister_translator(), and handle_cli_core_show_translation().
00509 { 00510 struct ast_translator *t; 00511 int new_rate_change; 00512 int newcost; 00513 int x; /* source format index */ 00514 int y; /* intermediate format index */ 00515 int z; /* destination format index */ 00516 00517 ast_debug(1, "Resetting translation matrix\n"); 00518 00519 memset(tr_matrix, '\0', sizeof(tr_matrix)); 00520 00521 /* first, compute all direct costs */ 00522 AST_RWLIST_TRAVERSE(&translators, t, list) { 00523 if (!t->active) 00524 continue; 00525 00526 x = t->srcfmt; 00527 z = t->dstfmt; 00528 00529 if (samples) 00530 calc_cost(t, samples); 00531 00532 new_rate_change = get_rate_change_result(1LL << t->srcfmt, 1LL << t->dstfmt); 00533 00534 /* this translator is the best choice if any of the below are true. 00535 * 1. no translation path is set between x and z yet. 00536 * 2. the new translation costs less and sample rate is no worse than old one. 00537 * 3. the new translation has a better sample rate conversion than the old one. 00538 */ 00539 if (!tr_matrix[x][z].step || 00540 ((t->cost < tr_matrix[x][z].cost) && (new_rate_change <= tr_matrix[x][z].rate_change)) || 00541 (new_rate_change < tr_matrix[x][z].rate_change)) { 00542 00543 tr_matrix[x][z].step = t; 00544 tr_matrix[x][z].cost = t->cost; 00545 tr_matrix[x][z].rate_change = new_rate_change; 00546 } 00547 } 00548 00549 /* 00550 * For each triple x, y, z of distinct formats, check if there is 00551 * a path from x to z through y which is cheaper than what is 00552 * currently known, and in case, update the matrix. 00553 * Repeat until the matrix is stable. 00554 */ 00555 for (;;) { 00556 int changed = 0; 00557 int better_choice = 0; 00558 for (x = 0; x < MAX_FORMAT; x++) { /* source format */ 00559 for (y = 0; y < MAX_FORMAT; y++) { /* intermediate format */ 00560 if (x == y) /* skip ourselves */ 00561 continue; 00562 for (z = 0; z < MAX_FORMAT; z++) { /* dst format */ 00563 if (z == x || z == y) /* skip null conversions */ 00564 continue; 00565 if (!tr_matrix[x][y].step) /* no path from x to y */ 00566 continue; 00567 if (!tr_matrix[y][z].step) /* no path from y to z */ 00568 continue; 00569 00570 /* Does x->y->z result in a less optimal sample rate change? 00571 * Never downgrade the sample rate conversion quality regardless 00572 * of any cost improvements */ 00573 if (tr_matrix[x][z].step && 00574 ((tr_matrix[x][z].rate_change < tr_matrix[x][y].rate_change) || 00575 (tr_matrix[x][z].rate_change < tr_matrix[y][z].rate_change))) { 00576 continue; 00577 } 00578 00579 /* is x->y->z a better sample rate confersion that the current x->z? */ 00580 new_rate_change = tr_matrix[x][y].rate_change + tr_matrix[y][z].rate_change; 00581 00582 /* calculate cost from x->y->z */ 00583 newcost = tr_matrix[x][y].cost + tr_matrix[y][z].cost; 00584 00585 /* Is x->y->z a better choice than x->z? 00586 * There are three conditions for x->y->z to be a better choice than x->z 00587 * 1. if there is no step directly between x->z then x->y->z is the best and only current option. 00588 * 2. if x->y->z results in a more optimal sample rate conversion. */ 00589 if (!tr_matrix[x][z].step) { 00590 better_choice = 1; 00591 } else if (new_rate_change < tr_matrix[x][z].rate_change) { 00592 better_choice = 1; 00593 } else { 00594 better_choice = 0; 00595 } 00596 00597 if (!better_choice) { 00598 continue; 00599 } 00600 /* ok, we can get from x to z via y with a cost that 00601 is the sum of the transition from x to y and from y to z */ 00602 tr_matrix[x][z].step = tr_matrix[x][y].step; 00603 tr_matrix[x][z].cost = newcost; 00604 tr_matrix[x][z].multistep = 1; 00605 00606 /* now calculate what kind of sample rate change is required for this multi-step path 00607 * 00608 * if both paths require a change in rate, and they are not in the same direction 00609 * then this is a up sample down sample conversion scenario. */ 00610 tr_matrix[x][z].rate_change = tr_matrix[x][y].rate_change + tr_matrix[y][z].rate_change; 00611 00612 ast_debug(3, "Discovered %d cost path from %s to %s, via %s\n", tr_matrix[x][z].cost, 00613 ast_getformatname(1LL << x), ast_getformatname(1LL << z), ast_getformatname(1LL << y)); 00614 changed++; 00615 } 00616 } 00617 } 00618 if (!changed) 00619 break; 00620 } 00621 }
struct ast_cli_entry cli_translate[] [static] |
{ AST_CLI_DEFINE(handle_cli_core_show_translation, "Display translation matrix") }
Definition at line 841 of file translate.c.
struct translator_path tr_matrix[MAX_FORMAT][MAX_FORMAT] [static] |
a matrix that, for any pair of supported formats, indicates the total cost of translation and the first step. The full path can be reconstricted iterating on the matrix until step->dstfmt == desired_format.
Array indexes are 'src' and 'dest', in that order.
Note: the lock in the 'translators' list is also used to protect this structure.
Definition at line 121 of file translate.c.
Referenced by ast_translate_available_formats(), ast_translate_path_steps(), ast_translator_best_choice(), ast_translator_build_path(), handle_cli_core_show_translation(), and rebuild_matrix().