#include <sys/types.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include "asterisk.h"
#include "asterisk/lock.h"
#include "asterisk/channel.h"
#include "asterisk/logger.h"
#include "asterisk/translate.h"
#include "asterisk/options.h"
#include "asterisk/frame.h"
#include "asterisk/sched.h"
#include "asterisk/cli.h"
#include "asterisk/term.h"
Include dependency graph for translate.c:
Go to the source code of this file.
Defines | |
#define | MAX_RECALC 200 |
#define | SHOW_TRANS 11 |
Functions | |
AST_MUTEX_DEFINE_STATIC (list_lock) | |
int | ast_register_translator (struct ast_translator *t) |
ast_frame * | ast_translate (struct ast_trans_pvt *path, struct ast_frame *f, int consume) |
int | ast_translator_best_choice (int *dst, int *srcs) |
Calculate our best translator source format, given costs, and a desired destination. | |
ast_trans_pvt * | ast_translator_build_path (int dest, int source) |
void | ast_translator_free_path (struct ast_trans_pvt *p) |
int | ast_unregister_translator (struct ast_translator *t) |
unregister codec translator | |
static void | calc_cost (struct ast_translator *t, int samples) |
static int | powerof (int d) |
static void | rebuild_matrix (int samples) |
Use the list of translators to build a translation matrix. | |
static int | show_translation (int fd, int argc, char *argv[]) |
CLI "show translation" command handler. | |
Variables | |
static int | added_cli = 0 |
static struct ast_translator * | list = NULL |
static struct ast_cli_entry | show_trans |
static char | show_trans_usage [] |
static struct ast_translator_dir | tr_matrix [MAX_FORMAT][MAX_FORMAT] |
Definition in file translate.c.
|
Definition at line 47 of file translate.c. Referenced by show_translation(). |
|
Referenced by show_translation(). |
|
|
|
Definition at line 396 of file translate.c. References added_cli, ast_cli_register(), ast_getformatname(), ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_verbose(), calc_cost(), COLOR_BLACK, COLOR_MAGENTA, ast_translator::cost, ast_translator::dstfmt, LOG_WARNING, ast_translator::name, ast_translator::next, option_verbose, powerof(), rebuild_matrix(), ast_translator::srcfmt, term_color(), and VERBOSE_PREFIX_2. Referenced by load_module(). 00397 { 00398 char tmp[80]; 00399 t->srcfmt = powerof(t->srcfmt); 00400 t->dstfmt = powerof(t->dstfmt); 00401 if (t->srcfmt >= MAX_FORMAT) { 00402 ast_log(LOG_WARNING, "Source format %s is larger than MAX_FORMAT\n", ast_getformatname(t->srcfmt)); 00403 return -1; 00404 } 00405 if (t->dstfmt >= MAX_FORMAT) { 00406 ast_log(LOG_WARNING, "Destination format %s is larger than MAX_FORMAT\n", ast_getformatname(t->dstfmt)); 00407 return -1; 00408 } 00409 calc_cost(t,1); 00410 if (option_verbose > 1) 00411 ast_verbose(VERBOSE_PREFIX_2 "Registered translator '%s' from format %s to %s, cost %d\n", term_color(tmp, t->name, COLOR_MAGENTA, COLOR_BLACK, sizeof(tmp)), ast_getformatname(1 << t->srcfmt), ast_getformatname(1 << t->dstfmt), t->cost); 00412 ast_mutex_lock(&list_lock); 00413 if (!added_cli) { 00414 ast_cli_register(&show_trans); 00415 added_cli++; 00416 } 00417 t->next = list; 00418 list = t; 00419 rebuild_matrix(0); 00420 ast_mutex_unlock(&list_lock); 00421 return 0; 00422 }
|
|
Definition at line 155 of file translate.c. References AST_FRAME_CNG, ast_frfree(), ast_log(), ast_tvadd(), ast_tvsub(), ast_frame::delivery, ast_translator::framein, ast_frame::frametype, LOG_WARNING, ast_frame::next, ast_trans_pvt::nextin, ast_trans_pvt::nextout, ast_frame::samples, and ast_trans_pvt::step. Referenced by ast_read(), ast_slinfactory_feed(), ast_write(), ast_writestream(), misdn_tx2ast_frm(), and queue_frame_to_spies(). 00156 { 00157 struct ast_trans_pvt *p; 00158 struct ast_frame *out; 00159 struct timeval delivery; 00160 p = path; 00161 /* Feed the first frame into the first translator */ 00162 p->step->framein(p->state, f); 00163 if (!ast_tvzero(f->delivery)) { 00164 if (!ast_tvzero(path->nextin)) { 00165 /* Make sure this is in line with what we were expecting */ 00166 if (!ast_tveq(path->nextin, f->delivery)) { 00167 /* The time has changed between what we expected and this 00168 most recent time on the new packet. If we have a 00169 valid prediction adjust our output time appropriately */ 00170 if (!ast_tvzero(path->nextout)) { 00171 path->nextout = ast_tvadd(path->nextout, 00172 ast_tvsub(f->delivery, path->nextin)); 00173 } 00174 path->nextin = f->delivery; 00175 } 00176 } else { 00177 /* This is our first pass. Make sure the timing looks good */ 00178 path->nextin = f->delivery; 00179 path->nextout = f->delivery; 00180 } 00181 /* Predict next incoming sample */ 00182 path->nextin = ast_tvadd(path->nextin, ast_samp2tv(f->samples, 8000)); 00183 } 00184 delivery = f->delivery; 00185 if (consume) 00186 ast_frfree(f); 00187 while(p) { 00188 out = p->step->frameout(p->state); 00189 /* If we get nothing out, return NULL */ 00190 if (!out) 00191 return NULL; 00192 /* If there is a next state, feed it in there. If not, 00193 return this frame */ 00194 if (p->next) 00195 p->next->step->framein(p->next->state, out); 00196 else { 00197 if (!ast_tvzero(delivery)) { 00198 /* Regenerate prediction after a discontinuity */ 00199 if (ast_tvzero(path->nextout)) 00200 path->nextout = ast_tvnow(); 00201 00202 /* Use next predicted outgoing timestamp */ 00203 out->delivery = path->nextout; 00204 00205 /* Predict next outgoing timestamp from samples in this 00206 frame. */ 00207 path->nextout = ast_tvadd(path->nextout, ast_samp2tv( out->samples, 8000)); 00208 } else { 00209 out->delivery = ast_tv(0, 0); 00210 } 00211 /* Invalidate prediction if we're entering a silence period */ 00212 if (out->frametype == AST_FRAME_CNG) 00213 path->nextout = ast_tv(0, 0); 00214 return out; 00215 } 00216 p = p->next; 00217 } 00218 ast_log(LOG_WARNING, "I should never get here...\n"); 00219 return NULL; 00220 }
|
|
Calculate our best translator source format, given costs, and a desired destination. Given a list of sources, and a designed destination format, which should I choose? Returns 0 on success, -1 if no path could be found. Modifies dests and srcs in place Definition at line 450 of file translate.c. References ast_mutex_lock(), ast_mutex_unlock(), ast_translator::cost, ast_translator_dir::cost, and ast_translator_dir::multistep. Referenced by ast_channel_make_compatible(), ast_request(), iax2_request(), and set_format(). 00451 { 00452 int x,y; 00453 int best = -1; 00454 int bestdst = 0; 00455 int cur = 1; 00456 int besttime = INT_MAX; 00457 int beststeps = INT_MAX; 00458 int common; 00459 00460 if ((common = (*dst) & (*srcs))) { 00461 /* We have a format in common */ 00462 for (y = 0; y < MAX_FORMAT; y++) { 00463 if (cur & common) { 00464 /* This is a common format to both. Pick it if we don't have one already */ 00465 bestdst = cur; 00466 best = cur; 00467 } 00468 cur = cur << 1; 00469 } 00470 } else { 00471 /* We will need to translate */ 00472 ast_mutex_lock(&list_lock); 00473 for (y = 0; y < MAX_FORMAT; y++) { 00474 if (!(cur & *dst)) { 00475 cur = cur << 1; 00476 continue; 00477 } 00478 00479 for (x = 0; x < MAX_FORMAT; x++) { 00480 if ((*srcs & (1 << x)) && /* x is a valid source format */ 00481 tr_matrix[x][y].step) { /* There's a step */ 00482 if (tr_matrix[x][y].cost > besttime) 00483 continue; /* It's more expensive, skip it */ 00484 00485 if (tr_matrix[x][y].cost == besttime && 00486 tr_matrix[x][y].multistep >= beststeps) 00487 continue; /* It requires the same (or more) steps, 00488 skip it */ 00489 00490 /* It's better than what we have so far */ 00491 best = 1 << x; 00492 bestdst = cur; 00493 besttime = tr_matrix[x][y].cost; 00494 beststeps = tr_matrix[x][y].multistep; 00495 } 00496 } 00497 cur = cur << 1; 00498 } 00499 ast_mutex_unlock(&list_lock); 00500 } 00501 00502 if (best > -1) { 00503 *srcs = best; 00504 *dst = bestdst; 00505 best = 0; 00506 } 00507 00508 return best; 00509 }
|
|
Build a set of translators based upon the given source and destination formats Definition at line 106 of file translate.c. References ast_getformatname(), ast_log(), ast_translator_free_path(), LOG_WARNING, malloc, ast_translator::newpvt, ast_trans_pvt::next, ast_trans_pvt::nextin, powerof(), ast_trans_pvt::step, and ast_translator_dir::step. Referenced by ast_slinfactory_feed(), ast_writestream(), misdn_set_opt_exec(), queue_frame_to_spies(), and set_format(). 00107 { 00108 struct ast_trans_pvt *tmpr = NULL, *tmp = NULL; 00109 00110 source = powerof(source); 00111 dest = powerof(dest); 00112 00113 while(source != dest) { 00114 if (!tr_matrix[source][dest].step) { 00115 /* We shouldn't have allocated any memory */ 00116 ast_log(LOG_WARNING, "No translator path from %s to %s\n", 00117 ast_getformatname(source), ast_getformatname(dest)); 00118 return NULL; 00119 } 00120 00121 if (tmp) { 00122 tmp->next = malloc(sizeof(*tmp)); 00123 tmp = tmp->next; 00124 } else 00125 tmp = malloc(sizeof(*tmp)); 00126 00127 if (!tmp) { 00128 ast_log(LOG_WARNING, "Out of memory\n"); 00129 if (tmpr) 00130 ast_translator_free_path(tmpr); 00131 return NULL; 00132 } 00133 00134 /* Set the root, if it doesn't exist yet... */ 00135 if (!tmpr) 00136 tmpr = tmp; 00137 00138 tmp->next = NULL; 00139 tmp->nextin = tmp->nextout = ast_tv(0, 0); 00140 tmp->step = tr_matrix[source][dest].step; 00141 tmp->state = tmp->step->newpvt(); 00142 00143 if (!tmp->state) { 00144 ast_log(LOG_WARNING, "Failed to build translator step from %d to %d\n", source, dest); 00145 ast_translator_free_path(tmpr); 00146 return NULL; 00147 } 00148 00149 /* Keep going if this isn't the final destination */ 00150 source = tmp->step->dstfmt; 00151 } 00152 return tmpr; 00153 }
|
|
Definition at line 92 of file translate.c. References ast_translator::destroy, free, ast_trans_pvt::next, ast_trans_pvt::state, and ast_trans_pvt::step. Referenced by ast_channel_free(), ast_channel_spy_remove(), ast_closestream(), ast_slinfactory_destroy(), ast_slinfactory_feed(), ast_translator_build_path(), ast_writestream(), cl_dequeue_chan(), free_translation(), iax2_destroy(), queue_frame_to_spies(), and set_format(). 00093 { 00094 struct ast_trans_pvt *pl, *pn; 00095 pn = p; 00096 while(pn) { 00097 pl = pn; 00098 pn = pn->next; 00099 if (pl->state && pl->step->destroy) 00100 pl->step->destroy(pl->state); 00101 free(pl); 00102 } 00103 }
|
|
unregister codec translator
Definition at line 425 of file translate.c. References ast_getformatname(), ast_mutex_lock(), ast_mutex_unlock(), ast_verbose(), COLOR_BLACK, COLOR_MAGENTA, ast_translator::dstfmt, ast_translator::name, ast_translator::next, option_verbose, rebuild_matrix(), ast_translator::srcfmt, term_color(), and VERBOSE_PREFIX_2. Referenced by load_module(), and unload_module(). 00426 { 00427 char tmp[80]; 00428 struct ast_translator *u, *ul = NULL; 00429 ast_mutex_lock(&list_lock); 00430 u = list; 00431 while(u) { 00432 if (u == t) { 00433 if (ul) 00434 ul->next = u->next; 00435 else 00436 list = u->next; 00437 if (option_verbose > 1) 00438 ast_verbose(VERBOSE_PREFIX_2 "Unregistered translator '%s' from format %s to %s\n", term_color(tmp, t->name, COLOR_MAGENTA, COLOR_BLACK, sizeof(tmp)), ast_getformatname(1 << t->srcfmt), ast_getformatname(1 << t->dstfmt)); 00439 break; 00440 } 00441 ul = u; 00442 u = u->next; 00443 } 00444 rebuild_matrix(0); 00445 ast_mutex_unlock(&list_lock); 00446 return (u ? 0 : -1); 00447 }
|
|
Definition at line 223 of file translate.c. References ast_frfree(), ast_log(), ast_translator::cost, ast_translator::destroy, ast_translator::framein, ast_translator::frameout, LOG_WARNING, ast_translator::name, ast_translator::newpvt, ast_translator::sample, and ast_frame::samples. Referenced by ast_register_translator(), and rebuild_matrix(). 00224 { 00225 int sofar=0; 00226 struct ast_translator_pvt *pvt; 00227 struct ast_frame *f, *out; 00228 struct timeval start; 00229 int cost; 00230 00231 if(!samples) 00232 samples = 1; 00233 00234 /* If they don't make samples, give them a terrible score */ 00235 if (!t->sample) { 00236 ast_log(LOG_WARNING, "Translator '%s' does not produce sample frames.\n", t->name); 00237 t->cost = 99999; 00238 return; 00239 } 00240 pvt = t->newpvt(); 00241 if (!pvt) { 00242 ast_log(LOG_WARNING, "Translator '%s' appears to be broken and will probably fail.\n", t->name); 00243 t->cost = 99999; 00244 return; 00245 } 00246 start = ast_tvnow(); 00247 /* Call the encoder until we've processed one second of time */ 00248 while(sofar < samples * 8000) { 00249 f = t->sample(); 00250 if (!f) { 00251 ast_log(LOG_WARNING, "Translator '%s' failed to produce a sample frame.\n", t->name); 00252 t->destroy(pvt); 00253 t->cost = 99999; 00254 return; 00255 } 00256 t->framein(pvt, f); 00257 ast_frfree(f); 00258 while((out = t->frameout(pvt))) { 00259 sofar += out->samples; 00260 ast_frfree(out); 00261 } 00262 } 00263 cost = ast_tvdiff_ms(ast_tvnow(), start); 00264 t->destroy(pvt); 00265 t->cost = cost / samples; 00266 if (!t->cost) 00267 t->cost = 1; 00268 }
|
|
Definition at line 82 of file translate.c. References ast_log(), and LOG_WARNING. Referenced by agents_show(), ast_register_translator(), and ast_translator_build_path(). 00083 { 00084 int x; 00085 for (x = 0; x < 32; x++) 00086 if ((1 << x) & d) 00087 return x; 00088 ast_log(LOG_WARNING, "Powerof %d: No power??\n", d); 00089 return -1; 00090 }
|
|
Use the list of translators to build a translation matrix.
Definition at line 271 of file translate.c. References ast_getformatname(), ast_log(), calc_cost(), ast_translator::cost, LOG_DEBUG, ast_translator::next, option_debug, and t. Referenced by ast_register_translator(), ast_unregister_translator(), and show_translation(). 00272 { 00273 struct ast_translator *t; 00274 int changed; 00275 int x, y, z; 00276 00277 if (option_debug) 00278 ast_log(LOG_DEBUG, "Resetting translation matrix\n"); 00279 00280 bzero(tr_matrix, sizeof(tr_matrix)); 00281 00282 for (t = list; t; t = t->next) { 00283 if (samples) 00284 calc_cost(t, samples); 00285 00286 if (!tr_matrix[t->srcfmt][t->dstfmt].step || 00287 tr_matrix[t->srcfmt][t->dstfmt].cost > t->cost) { 00288 tr_matrix[t->srcfmt][t->dstfmt].step = t; 00289 tr_matrix[t->srcfmt][t->dstfmt].cost = t->cost; 00290 } 00291 } 00292 00293 do { 00294 changed = 0; 00295 00296 /* Don't you just love O(N^3) operations? */ 00297 for (x = 0; x< MAX_FORMAT; x++) { /* For each source format */ 00298 for (y = 0; y < MAX_FORMAT; y++) { /* And each destination format */ 00299 if (x == y) /* Except ourselves, of course */ 00300 continue; 00301 00302 for (z=0; z < MAX_FORMAT; z++) { /* And each format it might convert to */ 00303 if ((x == z) || (y == z)) /* Don't ever convert back to us */ 00304 continue; 00305 00306 if (tr_matrix[x][y].step && /* We can convert from x to y */ 00307 tr_matrix[y][z].step && /* And from y to z and... */ 00308 (!tr_matrix[x][z].step || /* Either there isn't an x->z conversion */ 00309 (tr_matrix[x][y].cost + 00310 tr_matrix[y][z].cost < /* Or we're cheaper than the existing */ 00311 tr_matrix[x][z].cost) /* solution */ 00312 )) { 00313 /* We can get from x to z via y with a cost that 00314 is the sum of the transition from x to y and 00315 from y to z */ 00316 00317 tr_matrix[x][z].step = tr_matrix[x][y].step; 00318 tr_matrix[x][z].cost = tr_matrix[x][y].cost + 00319 tr_matrix[y][z].cost; 00320 tr_matrix[x][z].multistep = 1; 00321 if (option_debug) 00322 ast_log(LOG_DEBUG, "Discovered %d cost path from %s to %s, via %d\n", tr_matrix[x][z].cost, ast_getformatname(x), ast_getformatname(z), y); 00323 changed++; 00324 } 00325 } 00326 } 00327 } 00328 } while (changed); 00329 }
|
|
CLI "show translation" command handler.
Definition at line 333 of file translate.c. References ast_cli(), ast_getformatname(), ast_mutex_lock(), ast_mutex_unlock(), ast_translator::cost, MAX_RECALC, rebuild_matrix(), RESULT_SHOWUSAGE, RESULT_SUCCESS, and SHOW_TRANS. 00334 { 00335 #define SHOW_TRANS 11 00336 int x, y, z; 00337 char line[80]; 00338 if (argc > 4) 00339 return RESULT_SHOWUSAGE; 00340 00341 ast_mutex_lock(&list_lock); 00342 if (argv[2] && !strcasecmp(argv[2],"recalc")) { 00343 z = argv[3] ? atoi(argv[3]) : 1; 00344 00345 if (z <= 0) { 00346 ast_cli(fd," C'mon let's be serious here... defaulting to 1.\n"); 00347 z = 1; 00348 } 00349 00350 if (z > MAX_RECALC) { 00351 ast_cli(fd," Maximum limit of recalc exceeded by %d, truncating value to %d\n",z-MAX_RECALC,MAX_RECALC); 00352 z = MAX_RECALC; 00353 } 00354 ast_cli(fd," Recalculating Codec Translation (number of sample seconds: %d)\n\n",z); 00355 rebuild_matrix(z); 00356 } 00357 00358 ast_cli(fd, " Translation times between formats (in milliseconds)\n"); 00359 ast_cli(fd, " Source Format (Rows) Destination Format(Columns)\n\n"); 00360 for (x = -1; x < SHOW_TRANS; x++) { 00361 /* next 2 lines run faster than using strcpy() */ 00362 line[0] = ' '; 00363 line[1] = '\0'; 00364 for (y=-1;y<SHOW_TRANS;y++) { 00365 if (x >= 0 && y >= 0 && tr_matrix[x][y].step) 00366 snprintf(line + strlen(line), sizeof(line) - strlen(line), " %5d", tr_matrix[x][y].cost >= 99999 ? tr_matrix[x][y].cost-99999 : tr_matrix[x][y].cost); 00367 else 00368 if (((x == -1 && y >= 0) || (y == -1 && x >= 0))) { 00369 snprintf(line + strlen(line), sizeof(line) - strlen(line), 00370 " %5s", ast_getformatname(1<<(x+y+1)) ); 00371 } else if (x != -1 && y != -1) { 00372 snprintf(line + strlen(line), sizeof(line) - strlen(line), " -"); 00373 } else { 00374 snprintf(line + strlen(line), sizeof(line) - strlen(line), " "); 00375 } 00376 } 00377 snprintf(line + strlen(line), sizeof(line) - strlen(line), "\n"); 00378 ast_cli(fd, line); 00379 } 00380 ast_mutex_unlock(&list_lock); 00381 return RESULT_SUCCESS; 00382 }
|
|
Definition at line 384 of file translate.c. Referenced by ast_register_translator(). |
|
Definition at line 54 of file translate.c. |
|
Initial value: { { "show", "translation", NULL }, show_translation, "Display translation matrix", show_trans_usage } Definition at line 393 of file translate.c. |
|
Definition at line 386 of file translate.c. |
|
Definition at line 71 of file translate.c. |