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
00026 #include "asterisk.h"
00027
00028 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
00029
00030 #include <sys/types.h>
00031 #include <sys/socket.h>
00032 #include <sys/time.h>
00033 #include <unistd.h>
00034 #include <stdlib.h>
00035 #include <string.h>
00036 #include <stdio.h>
00037
00038 #include "asterisk/lock.h"
00039 #include "asterisk/channel.h"
00040 #include "asterisk/logger.h"
00041 #include "asterisk/translate.h"
00042 #include "asterisk/module.h"
00043 #include "asterisk/options.h"
00044 #include "asterisk/frame.h"
00045 #include "asterisk/sched.h"
00046 #include "asterisk/cli.h"
00047 #include "asterisk/term.h"
00048
00049 #define MAX_RECALC 200
00050
00051
00052 static AST_LIST_HEAD_STATIC(translators, ast_translator);
00053
00054 struct translator_path {
00055 struct ast_translator *step;
00056 unsigned int cost;
00057 unsigned int multistep;
00058 };
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070 static struct translator_path tr_matrix[MAX_FORMAT][MAX_FORMAT];
00071
00072
00073
00074
00075
00076
00077
00078
00079 static force_inline int powerof(unsigned int d)
00080 {
00081 int x = ffs(d);
00082
00083 if (x)
00084 return x - 1;
00085
00086 ast_log(LOG_WARNING, "No bits set? %d\n", d);
00087
00088 return -1;
00089 }
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099 static void *newpvt(struct ast_translator *t)
00100 {
00101 struct ast_trans_pvt *pvt;
00102 int len;
00103 int useplc = t->plc_samples > 0 && t->useplc;
00104 char *ofs;
00105
00106
00107
00108
00109
00110 len = sizeof(*pvt) + t->desc_size;
00111 if (useplc)
00112 len += sizeof(plc_state_t);
00113 if (t->buf_size)
00114 len += AST_FRIENDLY_OFFSET + t->buf_size;
00115 pvt = ast_calloc(1, len);
00116 if (!pvt)
00117 return NULL;
00118 pvt->t = t;
00119 ofs = (char *)(pvt + 1);
00120 if (t->desc_size) {
00121 pvt->pvt = ofs;
00122 ofs += t->desc_size;
00123 }
00124 if (useplc) {
00125 pvt->plc = (plc_state_t *)ofs;
00126 ofs += sizeof(plc_state_t);
00127 }
00128 if (t->buf_size)
00129 pvt->outbuf = ofs + AST_FRIENDLY_OFFSET;
00130
00131 if (t->newpvt && t->newpvt(pvt)) {
00132 free(pvt);
00133 return NULL;
00134 }
00135 ast_module_ref(t->module);
00136 return pvt;
00137 }
00138
00139 static void destroy(struct ast_trans_pvt *pvt)
00140 {
00141 struct ast_translator *t = pvt->t;
00142
00143 if (t->destroy)
00144 t->destroy(pvt);
00145 free(pvt);
00146 ast_module_unref(t->module);
00147 }
00148
00149
00150 static int framein(struct ast_trans_pvt *pvt, struct ast_frame *f)
00151 {
00152 int16_t *dst = (int16_t *)pvt->outbuf;
00153 int ret;
00154 int samples = pvt->samples;
00155
00156
00157 pvt->f.has_timing_info = f->has_timing_info;
00158 pvt->f.ts = f->ts;
00159 pvt->f.len = f->len;
00160 pvt->f.seqno = f->seqno;
00161
00162 if (f->samples == 0) {
00163 ast_log(LOG_WARNING, "no samples for %s\n", pvt->t->name);
00164 }
00165 if (pvt->t->buffer_samples) {
00166 if (f->datalen == 0) {
00167 if (pvt->plc) {
00168 int l = pvt->t->plc_samples;
00169 if (pvt->samples + l > pvt->t->buffer_samples) {
00170 ast_log(LOG_WARNING, "Out of buffer space\n");
00171 return -1;
00172 }
00173 l = plc_fillin(pvt->plc, dst + pvt->samples, l);
00174 pvt->samples += l;
00175 pvt->datalen = pvt->samples * 2;
00176 }
00177 return 0;
00178 }
00179 if (pvt->samples + f->samples > pvt->t->buffer_samples) {
00180 ast_log(LOG_WARNING, "Out of buffer space\n");
00181 return -1;
00182 }
00183 }
00184 if ( f->data == NULL && f->datalen > 0 ) {
00185 ast_log(LOG_ERROR, "NULL pointer in frame data for %s\n", pvt->t->name);
00186 return -1;
00187 }
00188
00189
00190
00191 ret = pvt->t->framein(pvt, f);
00192
00193 if (!ret && pvt->plc) {
00194 int l = pvt->t->plc_samples;
00195 if (pvt->samples < l)
00196 l = pvt->samples;
00197 plc_rx(pvt->plc, dst + pvt->samples - l, l);
00198 }
00199
00200 if (pvt->samples == samples)
00201 ast_log(LOG_WARNING, "%s did not update samples %d\n",
00202 pvt->t->name, pvt->samples);
00203 return ret;
00204 }
00205
00206
00207
00208
00209
00210
00211 struct ast_frame *ast_trans_frameout(struct ast_trans_pvt *pvt,
00212 int datalen, int samples)
00213 {
00214 struct ast_frame *f = &pvt->f;
00215
00216 if (samples)
00217 f->samples = samples;
00218 else {
00219 if (pvt->samples == 0)
00220 return NULL;
00221 f->samples = pvt->samples;
00222 pvt->samples = 0;
00223 }
00224 if (datalen)
00225 f->datalen = datalen;
00226 else {
00227 f->datalen = pvt->datalen;
00228 pvt->datalen = 0;
00229 }
00230
00231 f->frametype = AST_FRAME_VOICE;
00232 f->subclass = 1 << (pvt->t->dstfmt);
00233 f->mallocd = 0;
00234 f->offset = AST_FRIENDLY_OFFSET;
00235 f->src = pvt->t->name;
00236 f->data = pvt->outbuf;
00237 return f;
00238 }
00239
00240 static struct ast_frame *default_frameout(struct ast_trans_pvt *pvt)
00241 {
00242 return ast_trans_frameout(pvt, 0, 0);
00243 }
00244
00245
00246
00247 void ast_translator_free_path(struct ast_trans_pvt *p)
00248 {
00249 struct ast_trans_pvt *pn = p;
00250 while ( (p = pn) ) {
00251 pn = p->next;
00252 destroy(p);
00253 }
00254 }
00255
00256
00257 struct ast_trans_pvt *ast_translator_build_path(int dest, int source)
00258 {
00259 struct ast_trans_pvt *head = NULL, *tail = NULL;
00260
00261 source = powerof(source);
00262 dest = powerof(dest);
00263
00264 AST_LIST_LOCK(&translators);
00265
00266 while (source != dest) {
00267 struct ast_trans_pvt *cur;
00268 struct ast_translator *t = tr_matrix[source][dest].step;
00269 if (!t) {
00270 ast_log(LOG_WARNING, "No translator path from %s to %s\n",
00271 ast_getformatname(source), ast_getformatname(dest));
00272 AST_LIST_UNLOCK(&translators);
00273 return NULL;
00274 }
00275 if (!(cur = newpvt(t))) {
00276 ast_log(LOG_WARNING, "Failed to build translator step from %d to %d\n", source, dest);
00277 if (head)
00278 ast_translator_free_path(head);
00279 AST_LIST_UNLOCK(&translators);
00280 return NULL;
00281 }
00282 if (!head)
00283 head = cur;
00284 else
00285 tail->next = cur;
00286 tail = cur;
00287 cur->nextin = cur->nextout = ast_tv(0, 0);
00288
00289 source = cur->t->dstfmt;
00290 }
00291
00292 AST_LIST_UNLOCK(&translators);
00293 return head;
00294 }
00295
00296
00297 struct ast_frame *ast_translate(struct ast_trans_pvt *path, struct ast_frame *f, int consume)
00298 {
00299 struct ast_trans_pvt *p = path;
00300 struct ast_frame *out = f;
00301 struct timeval delivery;
00302 int has_timing_info;
00303 long ts;
00304 long len;
00305 int seqno;
00306
00307 has_timing_info = f->has_timing_info;
00308 ts = f->ts;
00309 len = f->len;
00310 seqno = f->seqno;
00311
00312
00313 if (!ast_tvzero(f->delivery)) {
00314 if (!ast_tvzero(path->nextin)) {
00315
00316 if (!ast_tveq(path->nextin, f->delivery)) {
00317
00318
00319
00320 if (!ast_tvzero(path->nextout)) {
00321 path->nextout = ast_tvadd(path->nextout,
00322 ast_tvsub(f->delivery, path->nextin));
00323 }
00324 path->nextin = f->delivery;
00325 }
00326 } else {
00327
00328 path->nextin = f->delivery;
00329 path->nextout = f->delivery;
00330 }
00331
00332 path->nextin = ast_tvadd(path->nextin, ast_samp2tv(f->samples, 8000));
00333 }
00334 delivery = f->delivery;
00335 for ( ; out && p ; p = p->next) {
00336 framein(p, out);
00337 out = p->t->frameout(p);
00338 }
00339 if (consume)
00340 ast_frfree(f);
00341 if (out == NULL)
00342 return NULL;
00343
00344 if (!ast_tvzero(delivery)) {
00345
00346 if (ast_tvzero(path->nextout))
00347 path->nextout = ast_tvnow();
00348
00349
00350 out->delivery = path->nextout;
00351
00352
00353
00354 path->nextout = ast_tvadd(path->nextout, ast_samp2tv( out->samples, 8000));
00355 } else {
00356 out->delivery = ast_tv(0, 0);
00357 out->has_timing_info = has_timing_info;
00358 if (has_timing_info) {
00359 out->ts = ts;
00360 out->len = len;
00361 out->seqno = seqno;
00362 }
00363 }
00364
00365 if (out->frametype == AST_FRAME_CNG)
00366 path->nextout = ast_tv(0, 0);
00367 return out;
00368 }
00369
00370
00371 static void calc_cost(struct ast_translator *t, int seconds)
00372 {
00373 int sofar=0;
00374 struct ast_trans_pvt *pvt;
00375 struct timeval start;
00376 int cost;
00377
00378 if (!seconds)
00379 seconds = 1;
00380
00381
00382 if (!t->sample) {
00383 ast_log(LOG_WARNING, "Translator '%s' does not produce sample frames.\n", t->name);
00384 t->cost = 99999;
00385 return;
00386 }
00387 pvt = newpvt(t);
00388 if (!pvt) {
00389 ast_log(LOG_WARNING, "Translator '%s' appears to be broken and will probably fail.\n", t->name);
00390 t->cost = 99999;
00391 return;
00392 }
00393 start = ast_tvnow();
00394
00395 while (sofar < seconds * 8000) {
00396 struct ast_frame *f = t->sample();
00397 if (!f) {
00398 ast_log(LOG_WARNING, "Translator '%s' failed to produce a sample frame.\n", t->name);
00399 destroy(pvt);
00400 t->cost = 99999;
00401 return;
00402 }
00403 framein(pvt, f);
00404 ast_frfree(f);
00405 while ((f = t->frameout(pvt))) {
00406 sofar += f->samples;
00407 ast_frfree(f);
00408 }
00409 }
00410 cost = ast_tvdiff_ms(ast_tvnow(), start);
00411 destroy(pvt);
00412 t->cost = cost / seconds;
00413 if (!t->cost)
00414 t->cost = 1;
00415 }
00416
00417
00418
00419
00420
00421 static void rebuild_matrix(int samples)
00422 {
00423 struct ast_translator *t;
00424 int x;
00425 int y;
00426 int z;
00427
00428 if (option_debug)
00429 ast_log(LOG_DEBUG, "Resetting translation matrix\n");
00430
00431 bzero(tr_matrix, sizeof(tr_matrix));
00432
00433
00434 AST_LIST_TRAVERSE(&translators, t, list) {
00435 if (!t->active)
00436 continue;
00437
00438 x = t->srcfmt;
00439 z = t->dstfmt;
00440
00441 if (samples)
00442 calc_cost(t, samples);
00443
00444 if (!tr_matrix[x][z].step || t->cost < tr_matrix[x][z].cost) {
00445 tr_matrix[x][z].step = t;
00446 tr_matrix[x][z].cost = t->cost;
00447 }
00448 }
00449
00450
00451
00452
00453
00454
00455
00456 for (;;) {
00457 int changed = 0;
00458 for (x = 0; x < MAX_FORMAT; x++) {
00459 for (y=0; y < MAX_FORMAT; y++) {
00460 if (x == y)
00461 continue;
00462
00463 for (z=0; z<MAX_FORMAT; z++) {
00464 int newcost;
00465
00466 if (z == x || z == y)
00467 continue;
00468 if (!tr_matrix[x][y].step)
00469 continue;
00470 if (!tr_matrix[y][z].step)
00471 continue;
00472 newcost = tr_matrix[x][y].cost + tr_matrix[y][z].cost;
00473 if (tr_matrix[x][z].step && newcost >= tr_matrix[x][z].cost)
00474 continue;
00475
00476
00477
00478
00479
00480 tr_matrix[x][z].step = tr_matrix[x][y].step;
00481 tr_matrix[x][z].cost = newcost;
00482 tr_matrix[x][z].multistep = 1;
00483 if (option_debug)
00484 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);
00485 changed++;
00486 }
00487 }
00488 }
00489 if (!changed)
00490 break;
00491 }
00492 }
00493
00494
00495 static int show_translation_deprecated(int fd, int argc, char *argv[])
00496 {
00497 #define SHOW_TRANS 13
00498 int x, y, z;
00499 int curlen = 0, longest = 0;
00500
00501 if (argc > 4)
00502 return RESULT_SHOWUSAGE;
00503
00504 AST_LIST_LOCK(&translators);
00505
00506 if (argv[2] && !strcasecmp(argv[2], "recalc")) {
00507 z = argv[3] ? atoi(argv[3]) : 1;
00508
00509 if (z <= 0) {
00510 ast_cli(fd, " C'mon let's be serious here... defaulting to 1.\n");
00511 z = 1;
00512 }
00513
00514 if (z > MAX_RECALC) {
00515 ast_cli(fd, " Maximum limit of recalc exceeded by %d, truncating value to %d\n", z - MAX_RECALC, MAX_RECALC);
00516 z = MAX_RECALC;
00517 }
00518 ast_cli(fd, " Recalculating Codec Translation (number of sample seconds: %d)\n\n", z);
00519 rebuild_matrix(z);
00520 }
00521
00522 ast_cli(fd, " Translation times between formats (in milliseconds) for one second of data\n");
00523 ast_cli(fd, " Source Format (Rows) Destination Format (Columns)\n\n");
00524
00525 for (x = 0; x < SHOW_TRANS; x++) {
00526 curlen = strlen(ast_getformatname(1 << (x + 1)));
00527 if (curlen > longest)
00528 longest = curlen;
00529 }
00530 for (x = -1; x < SHOW_TRANS; x++) {
00531 char line[120];
00532 char *buf = line;
00533 size_t left = sizeof(line) - 1;
00534
00535 *buf++ = ' ';
00536 *buf = '\0';
00537 for (y = -1; y < SHOW_TRANS; y++) {
00538 curlen = strlen(ast_getformatname(1 << (y)));
00539
00540 if (x >= 0 && y >= 0 && tr_matrix[x][y].step) {
00541
00542
00543
00544 ast_build_string(&buf, &left, "%*d", curlen + 1, tr_matrix[x][y].cost > 999 ? 0 : tr_matrix[x][y].cost);
00545 } else if (x == -1 && y >= 0) {
00546
00547 ast_build_string(&buf, &left, "%*s", curlen + 1, ast_getformatname(1 << (x + y + 1)) );
00548 } else if (y == -1 && x >= 0) {
00549
00550 ast_build_string(&buf, &left, "%*s", longest, ast_getformatname(1 << (x + y + 1)) );
00551 } else if (x >= 0 && y >= 0) {
00552 ast_build_string(&buf, &left, "%*s", curlen + 1, "-");
00553 } else {
00554 ast_build_string(&buf, &left, "%*s", longest, "");
00555 }
00556 }
00557 ast_build_string(&buf, &left, "\n");
00558 ast_cli(fd, line);
00559 }
00560 AST_LIST_UNLOCK(&translators);
00561 return RESULT_SUCCESS;
00562 }
00563
00564 static int show_translation(int fd, int argc, char *argv[])
00565 {
00566 int x, y, z;
00567 int curlen = 0, longest = 0;
00568
00569 if (argc > 5)
00570 return RESULT_SHOWUSAGE;
00571
00572 AST_LIST_LOCK(&translators);
00573
00574 if (argv[3] && !strcasecmp(argv[3], "recalc")) {
00575 z = argv[4] ? atoi(argv[4]) : 1;
00576
00577 if (z <= 0) {
00578 ast_cli(fd, " C'mon let's be serious here... defaulting to 1.\n");
00579 z = 1;
00580 }
00581
00582 if (z > MAX_RECALC) {
00583 ast_cli(fd, " Maximum limit of recalc exceeded by %d, truncating value to %d\n", z - MAX_RECALC, MAX_RECALC);
00584 z = MAX_RECALC;
00585 }
00586 ast_cli(fd, " Recalculating Codec Translation (number of sample seconds: %d)\n\n", z);
00587 rebuild_matrix(z);
00588 }
00589
00590 ast_cli(fd, " Translation times between formats (in milliseconds) for one second of data\n");
00591 ast_cli(fd, " Source Format (Rows) Destination Format (Columns)\n\n");
00592
00593 for (x = 0; x < SHOW_TRANS; x++) {
00594 curlen = strlen(ast_getformatname(1 << (x + 1)));
00595 if (curlen > longest)
00596 longest = curlen;
00597 }
00598 for (x = -1; x < SHOW_TRANS; x++) {
00599 char line[120];
00600 char *buf = line;
00601 size_t left = sizeof(line) - 1;
00602
00603 *buf++ = ' ';
00604 *buf = '\0';
00605 for (y = -1; y < SHOW_TRANS; y++) {
00606 curlen = strlen(ast_getformatname(1 << (y)));
00607
00608 if (x >= 0 && y >= 0 && tr_matrix[x][y].step) {
00609
00610
00611
00612 ast_build_string(&buf, &left, "%*d", curlen + 1, tr_matrix[x][y].cost > 999 ? 0 : tr_matrix[x][y].cost);
00613 } else if (x == -1 && y >= 0) {
00614
00615 ast_build_string(&buf, &left, "%*s", curlen + 1, ast_getformatname(1 << (x + y + 1)) );
00616 } else if (y == -1 && x >= 0) {
00617
00618 ast_build_string(&buf, &left, "%*s", longest, ast_getformatname(1 << (x + y + 1)) );
00619 } else if (x >= 0 && y >= 0) {
00620 ast_build_string(&buf, &left, "%*s", curlen + 1, "-");
00621 } else {
00622 ast_build_string(&buf, &left, "%*s", longest, "");
00623 }
00624 }
00625 ast_build_string(&buf, &left, "\n");
00626 ast_cli(fd, line);
00627 }
00628 AST_LIST_UNLOCK(&translators);
00629 return RESULT_SUCCESS;
00630 }
00631
00632 static char show_trans_usage[] =
00633 "Usage: core show translation [recalc] [<recalc seconds>]\n"
00634 " Displays known codec translators and the cost associated\n"
00635 "with each conversion. If the argument 'recalc' is supplied along\n"
00636 "with optional number of seconds to test a new test will be performed\n"
00637 "as the chart is being displayed.\n";
00638
00639 static struct ast_cli_entry cli_show_translation_deprecated = {
00640 { "show", "translation", NULL },
00641 show_translation_deprecated, NULL,
00642 NULL };
00643
00644 static struct ast_cli_entry cli_translate[] = {
00645 { { "core", "show", "translation", NULL },
00646 show_translation, "Display translation matrix",
00647 show_trans_usage, NULL, &cli_show_translation_deprecated },
00648 };
00649
00650
00651 int __ast_register_translator(struct ast_translator *t, struct ast_module *mod)
00652 {
00653 static int added_cli = 0;
00654 struct ast_translator *u;
00655
00656 if (!mod) {
00657 ast_log(LOG_WARNING, "Missing module pointer, you need to supply one\n");
00658 return -1;
00659 }
00660
00661 if (!t->buf_size) {
00662 ast_log(LOG_WARNING, "empty buf size, you need to supply one\n");
00663 return -1;
00664 }
00665
00666 t->module = mod;
00667
00668 t->srcfmt = powerof(t->srcfmt);
00669 t->dstfmt = powerof(t->dstfmt);
00670 t->active = 1;
00671
00672 if (t->plc_samples) {
00673 if (t->buffer_samples < t->plc_samples) {
00674 ast_log(LOG_WARNING, "plc_samples %d buffer_samples %d\n",
00675 t->plc_samples, t->buffer_samples);
00676 return -1;
00677 }
00678 if (t->dstfmt != AST_FORMAT_SLINEAR)
00679 ast_log(LOG_WARNING, "plc_samples %d format %x\n",
00680 t->plc_samples, t->dstfmt);
00681 }
00682 if (t->srcfmt >= MAX_FORMAT) {
00683 ast_log(LOG_WARNING, "Source format %s is larger than MAX_FORMAT\n", ast_getformatname(t->srcfmt));
00684 return -1;
00685 }
00686
00687 if (t->dstfmt >= MAX_FORMAT) {
00688 ast_log(LOG_WARNING, "Destination format %s is larger than MAX_FORMAT\n", ast_getformatname(t->dstfmt));
00689 return -1;
00690 }
00691
00692 if (t->buf_size) {
00693
00694
00695
00696
00697 struct _test_align { void *a, *b; } p;
00698 int align = (char *)&p.b - (char *)&p.a;
00699
00700 t->buf_size = ((t->buf_size + align - 1) / align) * align;
00701 }
00702
00703 if (t->frameout == NULL)
00704 t->frameout = default_frameout;
00705
00706 calc_cost(t, 1);
00707
00708 if (option_verbose > 1) {
00709 char tmp[80];
00710
00711 ast_verbose(VERBOSE_PREFIX_2 "Registered translator '%s' from format %s to %s, cost %d\n",
00712 term_color(tmp, t->name, COLOR_MAGENTA, COLOR_BLACK, sizeof(tmp)),
00713 ast_getformatname(1 << t->srcfmt), ast_getformatname(1 << t->dstfmt), t->cost);
00714 }
00715
00716 if (!added_cli) {
00717 ast_cli_register_multiple(cli_translate, sizeof(cli_translate) / sizeof(struct ast_cli_entry));
00718 added_cli++;
00719 }
00720
00721 AST_LIST_LOCK(&translators);
00722
00723
00724
00725 AST_LIST_TRAVERSE_SAFE_BEGIN(&translators, u, list) {
00726 if ((u->srcfmt == t->srcfmt) &&
00727 (u->dstfmt == t->dstfmt) &&
00728 (u->cost > t->cost)) {
00729 AST_LIST_INSERT_BEFORE_CURRENT(&translators, t, list);
00730 t = NULL;
00731 }
00732 }
00733 AST_LIST_TRAVERSE_SAFE_END;
00734
00735
00736
00737 if (t)
00738 AST_LIST_INSERT_HEAD(&translators, t, list);
00739
00740 rebuild_matrix(0);
00741
00742 AST_LIST_UNLOCK(&translators);
00743
00744 return 0;
00745 }
00746
00747
00748 int ast_unregister_translator(struct ast_translator *t)
00749 {
00750 char tmp[80];
00751 struct ast_translator *u;
00752 int found = 0;
00753
00754 AST_LIST_LOCK(&translators);
00755 AST_LIST_TRAVERSE_SAFE_BEGIN(&translators, u, list) {
00756 if (u == t) {
00757 AST_LIST_REMOVE_CURRENT(&translators, list);
00758 if (option_verbose > 1)
00759 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));
00760 found = 1;
00761 break;
00762 }
00763 }
00764 AST_LIST_TRAVERSE_SAFE_END;
00765
00766 if (found)
00767 rebuild_matrix(0);
00768
00769 AST_LIST_UNLOCK(&translators);
00770
00771 return (u ? 0 : -1);
00772 }
00773
00774 void ast_translator_activate(struct ast_translator *t)
00775 {
00776 AST_LIST_LOCK(&translators);
00777 t->active = 1;
00778 rebuild_matrix(0);
00779 AST_LIST_UNLOCK(&translators);
00780 }
00781
00782 void ast_translator_deactivate(struct ast_translator *t)
00783 {
00784 AST_LIST_LOCK(&translators);
00785 t->active = 0;
00786 rebuild_matrix(0);
00787 AST_LIST_UNLOCK(&translators);
00788 }
00789
00790
00791 int ast_translator_best_choice(int *dst, int *srcs)
00792 {
00793 int x,y;
00794 int best = -1;
00795 int bestdst = 0;
00796 int cur, cursrc;
00797 int besttime = INT_MAX;
00798 int beststeps = INT_MAX;
00799 int common = (*dst) & (*srcs);
00800
00801 if (common) {
00802 for (cur = 1, y = 0; y < MAX_FORMAT; cur <<= 1, y++) {
00803 if (cur & common)
00804 break;
00805 }
00806
00807 *srcs = *dst = cur;
00808 return 0;
00809 } else {
00810 AST_LIST_LOCK(&translators);
00811 for (cur = 1, y = 0; y < MAX_FORMAT; cur <<= 1, y++) {
00812 if (! (cur & *dst))
00813 continue;
00814 for (cursrc = 1, x = 0; x < MAX_FORMAT; cursrc <<= 1, x++) {
00815 if (!(*srcs & cursrc) || !tr_matrix[x][y].step ||
00816 tr_matrix[x][y].cost > besttime)
00817 continue;
00818 if (tr_matrix[x][y].cost < besttime ||
00819 tr_matrix[x][y].multistep < beststeps) {
00820
00821 best = cursrc;
00822 bestdst = cur;
00823 besttime = tr_matrix[x][y].cost;
00824 beststeps = tr_matrix[x][y].multistep;
00825 }
00826 }
00827 }
00828 AST_LIST_UNLOCK(&translators);
00829 if (best > -1) {
00830 *srcs = best;
00831 *dst = bestdst;
00832 best = 0;
00833 }
00834 return best;
00835 }
00836 }
00837
00838 unsigned int ast_translate_path_steps(unsigned int dest, unsigned int src)
00839 {
00840 unsigned int res = -1;
00841
00842
00843 src = powerof(src);
00844 dest = powerof(dest);
00845
00846 AST_LIST_LOCK(&translators);
00847
00848 if (tr_matrix[src][dest].step)
00849 res = tr_matrix[src][dest].multistep + 1;
00850
00851 AST_LIST_UNLOCK(&translators);
00852
00853 return res;
00854 }
00855
00856 unsigned int ast_translate_available_formats(unsigned int dest, unsigned int src)
00857 {
00858 unsigned int res = dest;
00859 unsigned int x;
00860 unsigned int src_audio = src & AST_FORMAT_AUDIO_MASK;
00861 unsigned int src_video = src & AST_FORMAT_VIDEO_MASK;
00862
00863
00864
00865 if (!src)
00866 return dest;
00867
00868
00869 if (src_audio)
00870 src_audio = powerof(src_audio);
00871
00872
00873 if (src_video)
00874 src_video = powerof(src_video);
00875
00876 AST_LIST_LOCK(&translators);
00877
00878
00879
00880
00881
00882 for (x = 1; src_audio && x < AST_FORMAT_MAX_AUDIO; x <<= 1) {
00883
00884 if (!dest & x)
00885 continue;
00886
00887
00888
00889 if (src & x)
00890 continue;
00891
00892
00893
00894 if (!tr_matrix[src_audio][powerof(x)].step) {
00895 res &= ~x;
00896 continue;
00897 }
00898
00899
00900 if (!tr_matrix[powerof(x)][src_audio].step)
00901 res &= ~x;
00902 }
00903
00904
00905
00906
00907
00908 for (; src_video && x < AST_FORMAT_MAX_VIDEO; x <<= 1) {
00909
00910 if (!dest & x)
00911 continue;
00912
00913
00914
00915 if (src & x)
00916 continue;
00917
00918
00919
00920 if (!tr_matrix[src_video][powerof(x)].step) {
00921 res &= ~x;
00922 continue;
00923 }
00924
00925
00926 if (!tr_matrix[powerof(x)][src_video].step)
00927 res &= ~x;
00928 }
00929
00930 AST_LIST_UNLOCK(&translators);
00931
00932 return res;
00933 }