#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 a translator This registers a codec translator with asterisk. | |
ast_frame * | ast_trans_frameout (struct ast_trans_pvt *pvt, int datalen, int samples) |
generic frameout function | |
ast_frame * | ast_translate (struct ast_trans_pvt *path, struct ast_frame *f, int consume) |
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 | |
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) |
Chooses the best translation path. | |
ast_trans_pvt * | ast_translator_build_path (format_t dest, format_t source) |
Builds a translator path Build a path (possibly NULL) from source to dest. | |
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 a translator Unregisters the given tranlator. | |
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. |
Definition in file translate.c.
#define MAX_RECALC 1000 |
#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 * | module | |||
) |
Register a translator This registers a codec translator with asterisk.
t | populated ast_translator structure | |
module | handle to the module that owns this translator |
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(), cli_translate, 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 | |||
) |
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_trans_pvt::datalen, ast_translator::dstfmt, ast_trans_pvt::f, f, ast_translator::name, ast_trans_pvt::outbuf, ast_trans_pvt::samples, and ast_trans_pvt::t.
Referenced by default_frameout(), lintoadpcm_frameout(), lintogsm_frameout(), lintoilbc_frameout(), and lintolpc10_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 * | tr, | |
struct ast_frame * | f, | |||
int | consume | |||
) |
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
tr | translator structure to use for translation | |
f | frame to translate | |
consume | Whether or not to free the original frame |
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, f, 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.
dest | possible destination formats | |
src | source formats |
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, str, 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 |
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 }
Chooses the best translation path.
Given a list of sources, and a designed destination format, which should I choose?
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 | |||
) |
Builds a translator path Build a path (possibly NULL) from source to dest.
dest | destination format | |
source | source format |
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 |
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 a translator Unregisters the given tranlator.
t | translator to unregister |
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, and ast_translator::sample.
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] |
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, f, ast_trans_pvt::f, ast_translator::framein, ast_frame::len, LOG_WARNING, ast_translator::name, ast_translator::native_plc, 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(), 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_translator::desc_size, len(), ast_translator::module, ast_translator::newpvt, 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(), ffsll(), and LOG_WARNING.
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(), ast_translator::cost, ast_translator::dstfmt, get_rate_change_result(), ast_translator::list, MAX_FORMAT, ast_translator::srcfmt, 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] |
Initial value:
{ { .handler = handle_cli_core_show_translation , .summary = "Display translation matrix" ,__VA_ARGS__ } }
Definition at line 841 of file translate.c.
Referenced by __ast_register_translator().
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().