#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"
Go to the source code of this file.
Data Structures | |
struct | ast_frame_delivery |
struct | ast_trans_pvt |
struct | ast_translator_dir |
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.
#define MAX_RECALC 200 |
#define SHOW_TRANS 11 |
Referenced by show_translation().
AST_MUTEX_DEFINE_STATIC | ( | list_lock | ) |
int ast_register_translator | ( | struct ast_translator * | t | ) |
t | populated ast_translator structure This registers a codec translator with asterisk Returns 0 on success, -1 on failure |
Definition at line 396 of file translate.c.
References ast_cli_register(), ast_getformatname(), ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_verbose(), calc_cost(), COLOR_BLACK, COLOR_MAGENTA, list, LOG_WARNING, option_verbose, powerof(), rebuild_matrix(), show_trans, t, 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 }
struct ast_frame* ast_translate | ( | struct ast_trans_pvt * | tr, | |
struct ast_frame * | f, | |||
int | consume | |||
) |
tr | translator structure to use for translation | |
f | frame to translate | |
consume | Whether or not to free the original frame Apply an input frame into the translator and receive zero or one output frames. Consume determines whether the original frame should be freed Returns an ast_frame of the new translation format on success, NULL on failure |
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(), process_ast_dsp(), 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 }
int ast_translator_best_choice | ( | int * | dsts, | |
int * | srcs | |||
) |
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_dir::cost, ast_translator_dir::multistep, and tr_matrix.
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 }
struct ast_trans_pvt* ast_translator_build_path | ( | int | dest, | |
int | source | |||
) |
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, ast_translator_dir::step, and tr_matrix.
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 }
void ast_translator_free_path | ( | struct ast_trans_pvt * | tr | ) |
tr | translator path to get rid of Frees the given translator path structure |
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_closestream(), ast_slinfactory_destroy(), ast_slinfactory_feed(), ast_translator_build_path(), ast_writestream(), cl_dequeue_chan(), free_translation(), iax2_destroy(), queue_frame_to_spies(), set_format(), and spy_cleanup().
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 }
int ast_unregister_translator | ( | struct ast_translator * | t | ) |
unregister codec translator
t | translator to unregister Unregisters the given tranlator Returns 0 on success, -1 on failure |
Definition at line 425 of file translate.c.
References ast_getformatname(), ast_mutex_lock(), ast_mutex_unlock(), ast_verbose(), COLOR_BLACK, COLOR_MAGENTA, list, ast_imager::next, ast_translator::next, option_verbose, rebuild_matrix(), t, 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 }
static void calc_cost | ( | struct ast_translator * | t, | |
int | samples | |||
) | [static] |
Definition at line 223 of file translate.c.
References ast_frfree(), ast_log(), LOG_WARNING, ast_frame::samples, and t.
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 }
static int powerof | ( | int | d | ) | [static] |
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 }
static void rebuild_matrix | ( | int | samples | ) | [static] |
Use the list of translators to build a translation matrix.
Definition at line 271 of file translate.c.
References ast_log(), calc_cost(), list, LOG_DEBUG, option_debug, t, and tr_matrix.
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 }
static int show_translation | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
CLI "show translation" command handler.
Definition at line 333 of file translate.c.
References ast_cli(), ast_getformatname(), ast_mutex_lock(), ast_mutex_unlock(), MAX_RECALC, rebuild_matrix(), RESULT_SHOWUSAGE, RESULT_SUCCESS, SHOW_TRANS, and tr_matrix.
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 }
int added_cli = 0 [static] |
Definition at line 384 of file translate.c.
struct ast_translator* list = NULL [static] |
Definition at line 54 of file translate.c.
struct ast_cli_entry show_trans [static] |
Initial value:
{ { "show", "translation", NULL }, show_translation, "Display translation matrix", show_trans_usage }
Definition at line 393 of file translate.c.
Referenced by ast_register_translator().
char show_trans_usage[] [static] |
Definition at line 386 of file translate.c.
struct ast_translator_dir tr_matrix[MAX_FORMAT][MAX_FORMAT] [static] |
Definition at line 71 of file translate.c.
Referenced by ast_translator_best_choice(), ast_translator_build_path(), rebuild_matrix(), and show_translation().