00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #include <sys/types.h>
00026 #include <sys/socket.h>
00027 #include <sys/time.h>
00028 #include <unistd.h>
00029 #include <stdlib.h>
00030 #include <string.h>
00031 #include <stdio.h>
00032
00033 #include "asterisk.h"
00034
00035 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 11120 $")
00036
00037 #include "asterisk/lock.h"
00038 #include "asterisk/channel.h"
00039 #include "asterisk/logger.h"
00040 #include "asterisk/translate.h"
00041 #include "asterisk/options.h"
00042 #include "asterisk/frame.h"
00043 #include "asterisk/sched.h"
00044 #include "asterisk/cli.h"
00045 #include "asterisk/term.h"
00046
00047 #define MAX_RECALC 200
00048
00049
00050
00051
00052
00053 AST_MUTEX_DEFINE_STATIC(list_lock);
00054 static struct ast_translator *list = NULL;
00055
00056 struct ast_translator_dir {
00057 struct ast_translator *step;
00058 unsigned int cost;
00059 unsigned int multistep;
00060 };
00061
00062 struct ast_frame_delivery {
00063 struct ast_frame *f;
00064 struct ast_channel *chan;
00065 int fd;
00066 struct translator_pvt *owner;
00067 struct ast_frame_delivery *prev;
00068 struct ast_frame_delivery *next;
00069 };
00070
00071 static struct ast_translator_dir tr_matrix[MAX_FORMAT][MAX_FORMAT];
00072
00073 struct ast_trans_pvt {
00074 struct ast_translator *step;
00075 struct ast_translator_pvt *state;
00076 struct ast_trans_pvt *next;
00077 struct timeval nextin;
00078 struct timeval nextout;
00079 };
00080
00081
00082 static int powerof(int d)
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 }
00091
00092 void ast_translator_free_path(struct ast_trans_pvt *p)
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 }
00104
00105
00106 struct ast_trans_pvt *ast_translator_build_path(int dest, int source)
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
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
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
00150 source = tmp->step->dstfmt;
00151 }
00152 return tmpr;
00153 }
00154
00155 struct ast_frame *ast_translate(struct ast_trans_pvt *path, struct ast_frame *f, int consume)
00156 {
00157 struct ast_trans_pvt *p;
00158 struct ast_frame *out;
00159 struct timeval delivery;
00160 p = path;
00161
00162 p->step->framein(p->state, f);
00163 if (!ast_tvzero(f->delivery)) {
00164 if (!ast_tvzero(path->nextin)) {
00165
00166 if (!ast_tveq(path->nextin, f->delivery)) {
00167
00168
00169
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
00178 path->nextin = f->delivery;
00179 path->nextout = f->delivery;
00180 }
00181
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
00190 if (!out)
00191 return NULL;
00192
00193
00194 if (p->next)
00195 p->next->step->framein(p->next->state, out);
00196 else {
00197 if (!ast_tvzero(delivery)) {
00198
00199 if (ast_tvzero(path->nextout))
00200 path->nextout = ast_tvnow();
00201
00202
00203 out->delivery = path->nextout;
00204
00205
00206
00207 path->nextout = ast_tvadd(path->nextout, ast_samp2tv( out->samples, 8000));
00208 } else {
00209 out->delivery = ast_tv(0, 0);
00210 }
00211
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 }
00221
00222
00223 static void calc_cost(struct ast_translator *t, int samples)
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
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
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 }
00269
00270
00271 static void rebuild_matrix(int samples)
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
00297 for (x = 0; x< MAX_FORMAT; x++) {
00298 for (y = 0; y < MAX_FORMAT; y++) {
00299 if (x == y)
00300 continue;
00301
00302 for (z=0; z < MAX_FORMAT; z++) {
00303 if ((x == z) || (y == z))
00304 continue;
00305
00306 if (tr_matrix[x][y].step &&
00307 tr_matrix[y][z].step &&
00308 (!tr_matrix[x][z].step ||
00309 (tr_matrix[x][y].cost +
00310 tr_matrix[y][z].cost <
00311 tr_matrix[x][z].cost)
00312 )) {
00313
00314
00315
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 }
00330
00331
00332
00333 static int show_translation(int fd, int argc, char *argv[])
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
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 }
00383
00384 static int added_cli = 0;
00385
00386 static char show_trans_usage[] =
00387 "Usage: show translation [recalc] [<recalc seconds>]\n"
00388 " Displays known codec translators and the cost associated\n"
00389 "with each conversion. If the argument 'recalc' is supplied along\n"
00390 "with optional number of seconds to test a new test will be performed\n"
00391 "as the chart is being displayed.\n";
00392
00393 static struct ast_cli_entry show_trans =
00394 { { "show", "translation", NULL }, show_translation, "Display translation matrix", show_trans_usage };
00395
00396 int ast_register_translator(struct ast_translator *t)
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 }
00423
00424
00425 int ast_unregister_translator(struct ast_translator *t)
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 }
00448
00449
00450 int ast_translator_best_choice(int *dst, int *srcs)
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
00462 for (y = 0; y < MAX_FORMAT; y++) {
00463 if (cur & common) {
00464
00465 bestdst = cur;
00466 best = cur;
00467 }
00468 cur = cur << 1;
00469 }
00470 } else {
00471
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)) &&
00481 tr_matrix[x][y].step) {
00482 if (tr_matrix[x][y].cost > besttime)
00483 continue;
00484
00485 if (tr_matrix[x][y].cost == besttime &&
00486 tr_matrix[x][y].multistep >= beststeps)
00487 continue;
00488
00489
00490
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 }