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: 94829 $")
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
00178 if (!pvt->t->native_plc)
00179 return 0;
00180 }
00181 if (pvt->samples + f->samples > pvt->t->buffer_samples) {
00182 ast_log(LOG_WARNING, "Out of buffer space\n");
00183 return -1;
00184 }
00185 }
00186
00187
00188
00189 ret = pvt->t->framein(pvt, f);
00190
00191 if (!ret && pvt->plc) {
00192 int l = pvt->t->plc_samples;
00193 if (pvt->samples < l)
00194 l = pvt->samples;
00195 plc_rx(pvt->plc, dst + pvt->samples - l, l);
00196 }
00197
00198 if (pvt->samples == samples)
00199 ast_log(LOG_WARNING, "%s did not update samples %d\n",
00200 pvt->t->name, pvt->samples);
00201 return ret;
00202 }
00203
00204
00205
00206
00207
00208
00209 struct ast_frame *ast_trans_frameout(struct ast_trans_pvt *pvt,
00210 int datalen, int samples)
00211 {
00212 struct ast_frame *f = &pvt->f;
00213
00214 if (samples)
00215 f->samples = samples;
00216 else {
00217 if (pvt->samples == 0)
00218 return NULL;
00219 f->samples = pvt->samples;
00220 pvt->samples = 0;
00221 }
00222 if (datalen)
00223 f->datalen = datalen;
00224 else {
00225 f->datalen = pvt->datalen;
00226 pvt->datalen = 0;
00227 }
00228
00229 f->frametype = AST_FRAME_VOICE;
00230 f->subclass = 1 << (pvt->t->dstfmt);
00231 f->mallocd = 0;
00232 f->offset = AST_FRIENDLY_OFFSET;
00233 f->src = pvt->t->name;
00234 f->data = pvt->outbuf;
00235 return f;
00236 }
00237
00238 static struct ast_frame *default_frameout(struct ast_trans_pvt *pvt)
00239 {
00240 return ast_trans_frameout(pvt, 0, 0);
00241 }
00242
00243
00244
00245 void ast_translator_free_path(struct ast_trans_pvt *p)
00246 {
00247 struct ast_trans_pvt *pn = p;
00248 while ( (p = pn) ) {
00249 pn = p->next;
00250 destroy(p);
00251 }
00252 }
00253
00254
00255 struct ast_trans_pvt *ast_translator_build_path(int dest, int source)
00256 {
00257 struct ast_trans_pvt *head = NULL, *tail = NULL;
00258
00259 source = powerof(source);
00260 dest = powerof(dest);
00261
00262 AST_LIST_LOCK(&translators);
00263
00264 while (source != dest) {
00265 struct ast_trans_pvt *cur;
00266 struct ast_translator *t = tr_matrix[source][dest].step;
00267 if (!t) {
00268 ast_log(LOG_WARNING, "No translator path from %s to %s\n",
00269 ast_getformatname(source), ast_getformatname(dest));
00270 AST_LIST_UNLOCK(&translators);
00271 return NULL;
00272 }
00273 if (!(cur = newpvt(t))) {
00274 ast_log(LOG_WARNING, "Failed to build translator step from %d to %d\n", source, dest);
00275 if (head)
00276 ast_translator_free_path(head);
00277 AST_LIST_UNLOCK(&translators);
00278 return NULL;
00279 }
00280 if (!head)
00281 head = cur;
00282 else
00283 tail->next = cur;
00284 tail = cur;
00285 cur->nextin = cur->nextout = ast_tv(0, 0);
00286
00287 source = cur->t->dstfmt;
00288 }
00289
00290 AST_LIST_UNLOCK(&translators);
00291 return head;
00292 }
00293
00294
00295 struct ast_frame *ast_translate(struct ast_trans_pvt *path, struct ast_frame *f, int consume)
00296 {
00297 struct ast_trans_pvt *p = path;
00298 struct ast_frame *out = f;
00299 struct timeval delivery;
00300 int has_timing_info;
00301 long ts;
00302 long len;
00303 int seqno;
00304
00305 has_timing_info = f->has_timing_info;
00306 ts = f->ts;
00307 len = f->len;
00308 seqno = f->seqno;
00309
00310
00311 if (!ast_tvzero(f->delivery)) {
00312 if (!ast_tvzero(path->nextin)) {
00313
00314 if (!ast_tveq(path->nextin, f->delivery)) {
00315
00316
00317
00318 if (!ast_tvzero(path->nextout)) {
00319 path->nextout = ast_tvadd(path->nextout,
00320 ast_tvsub(f->delivery, path->nextin));
00321 }
00322 path->nextin = f->delivery;
00323 }
00324 } else {
00325
00326 path->nextin = f->delivery;
00327 path->nextout = f->delivery;
00328 }
00329
00330 path->nextin = ast_tvadd(path->nextin, ast_samp2tv(f->samples, 8000));
00331 }
00332 delivery = f->delivery;
00333 for ( ; out && p ; p = p->next) {
00334 framein(p, out);
00335 out = p->t->frameout(p);
00336 }
00337 if (consume)
00338 ast_frfree(f);
00339 if (out == NULL)
00340 return NULL;
00341
00342 if (!ast_tvzero(delivery)) {
00343
00344 if (ast_tvzero(path->nextout))
00345 path->nextout = ast_tvnow();
00346
00347
00348 out->delivery = path->nextout;
00349
00350
00351
00352 path->nextout = ast_tvadd(path->nextout, ast_samp2tv( out->samples, 8000));
00353 } else {
00354 out->delivery = ast_tv(0, 0);
00355 out->has_timing_info = has_timing_info;
00356 if (has_timing_info) {
00357 out->ts = ts;
00358 out->len = len;
00359 out->seqno = seqno;
00360 }
00361 }
00362
00363 if (out->frametype == AST_FRAME_CNG)
00364 path->nextout = ast_tv(0, 0);
00365 return out;
00366 }
00367
00368
00369 static void calc_cost(struct ast_translator *t, int seconds)
00370 {
00371 int sofar=0;
00372 struct ast_trans_pvt *pvt;
00373 struct timeval start;
00374 int cost;
00375
00376 if (!seconds)
00377 seconds = 1;
00378
00379
00380 if (!t->sample) {
00381 ast_log(LOG_WARNING, "Translator '%s' does not produce sample frames.\n", t->name);
00382 t->cost = 99999;
00383 return;
00384 }
00385 pvt = newpvt(t);
00386 if (!pvt) {
00387 ast_log(LOG_WARNING, "Translator '%s' appears to be broken and will probably fail.\n", t->name);
00388 t->cost = 99999;
00389 return;
00390 }
00391 start = ast_tvnow();
00392
00393 while (sofar < seconds * 8000) {
00394 struct ast_frame *f = t->sample();
00395 if (!f) {
00396 ast_log(LOG_WARNING, "Translator '%s' failed to produce a sample frame.\n", t->name);
00397 destroy(pvt);
00398 t->cost = 99999;
00399 return;
00400 }
00401 framein(pvt, f);
00402 ast_frfree(f);
00403 while ((f = t->frameout(pvt))) {
00404 sofar += f->samples;
00405 ast_frfree(f);
00406 }
00407 }
00408 cost = ast_tvdiff_ms(ast_tvnow(), start);
00409 destroy(pvt);
00410 t->cost = cost / seconds;
00411 if (!t->cost)
00412 t->cost = 1;
00413 }
00414
00415
00416
00417
00418
00419 static void rebuild_matrix(int samples)
00420 {
00421 struct ast_translator *t;
00422 int x;
00423 int y;
00424 int z;
00425
00426 if (option_debug)
00427 ast_log(LOG_DEBUG, "Resetting translation matrix\n");
00428
00429 bzero(tr_matrix, sizeof(tr_matrix));
00430
00431
00432 AST_LIST_TRAVERSE(&translators, t, list) {
00433 if (!t->active)
00434 continue;
00435
00436 x = t->srcfmt;
00437 z = t->dstfmt;
00438
00439 if (samples)
00440 calc_cost(t, samples);
00441
00442 if (!tr_matrix[x][z].step || t->cost < tr_matrix[x][z].cost) {
00443 tr_matrix[x][z].step = t;
00444 tr_matrix[x][z].cost = t->cost;
00445 }
00446 }
00447
00448
00449
00450
00451
00452
00453
00454 for (;;) {
00455 int changed = 0;
00456 for (x = 0; x < MAX_FORMAT; x++) {
00457 for (y=0; y < MAX_FORMAT; y++) {
00458 if (x == y)
00459 continue;
00460
00461 for (z=0; z<MAX_FORMAT; z++) {
00462 int newcost;
00463
00464 if (z == x || z == y)
00465 continue;
00466 if (!tr_matrix[x][y].step)
00467 continue;
00468 if (!tr_matrix[y][z].step)
00469 continue;
00470 newcost = tr_matrix[x][y].cost + tr_matrix[y][z].cost;
00471 if (tr_matrix[x][z].step && newcost >= tr_matrix[x][z].cost)
00472 continue;
00473
00474
00475
00476
00477
00478 tr_matrix[x][z].step = tr_matrix[x][y].step;
00479 tr_matrix[x][z].cost = newcost;
00480 tr_matrix[x][z].multistep = 1;
00481 if (option_debug)
00482 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);
00483 changed++;
00484 }
00485 }
00486 }
00487 if (!changed)
00488 break;
00489 }
00490 }
00491
00492
00493 static int show_translation_deprecated(int fd, int argc, char *argv[])
00494 {
00495 #define SHOW_TRANS 13
00496 int x, y, z;
00497 int curlen = 0, longest = 0;
00498
00499 if (argc > 4)
00500 return RESULT_SHOWUSAGE;
00501
00502 AST_LIST_LOCK(&translators);
00503
00504 if (argv[2] && !strcasecmp(argv[2], "recalc")) {
00505 z = argv[3] ? atoi(argv[3]) : 1;
00506
00507 if (z <= 0) {
00508 ast_cli(fd, " C'mon let's be serious here... defaulting to 1.\n");
00509 z = 1;
00510 }
00511
00512 if (z > MAX_RECALC) {
00513 ast_cli(fd, " Maximum limit of recalc exceeded by %d, truncating value to %d\n", z - MAX_RECALC, MAX_RECALC);
00514 z = MAX_RECALC;
00515 }
00516 ast_cli(fd, " Recalculating Codec Translation (number of sample seconds: %d)\n\n", z);
00517 rebuild_matrix(z);
00518 }
00519
00520 ast_cli(fd, " Translation times between formats (in milliseconds) for one second of data\n");
00521 ast_cli(fd, " Source Format (Rows) Destination Format (Columns)\n\n");
00522
00523 for (x = 0; x < SHOW_TRANS; x++) {
00524 curlen = strlen(ast_getformatname(1 << (x)));
00525 if (curlen > longest)
00526 longest = curlen;
00527 }
00528 for (x = -1; x < SHOW_TRANS; x++) {
00529 char line[120];
00530 char *buf = line;
00531 size_t left = sizeof(line) - 1;
00532
00533 *buf++ = ' ';
00534 *buf = '\0';
00535 for (y = -1; y < SHOW_TRANS; y++) {
00536 if (y >= 0)
00537 curlen = strlen(ast_getformatname(1 << (y)));
00538
00539 if (x >= 0 && y >= 0 && tr_matrix[x][y].step) {
00540
00541
00542
00543 ast_build_string(&buf, &left, "%*d", curlen + 1, tr_matrix[x][y].cost > 999 ? 0 : tr_matrix[x][y].cost);
00544 } else if (x == -1 && y >= 0) {
00545
00546 ast_build_string(&buf, &left, "%*s", curlen + 1, ast_getformatname(1 << (y)) );
00547 } else if (y == -1 && x >= 0) {
00548
00549 ast_build_string(&buf, &left, "%*s", longest, ast_getformatname(1 << (x)) );
00550 } else if (x >= 0 && y >= 0) {
00551 ast_build_string(&buf, &left, "%*s", curlen + 1, "-");
00552 } else {
00553 ast_build_string(&buf, &left, "%*s", longest, "");
00554 }
00555 }
00556 ast_build_string(&buf, &left, "\n");
00557 ast_cli(fd, line);
00558 }
00559 AST_LIST_UNLOCK(&translators);
00560 return RESULT_SUCCESS;
00561 }
00562
00563 static int show_translation(int fd, int argc, char *argv[])
00564 {
00565 int x, y, z;
00566 int curlen = 0, longest = 0;
00567
00568 if (argc > 5)
00569 return RESULT_SHOWUSAGE;
00570
00571 AST_LIST_LOCK(&translators);
00572
00573 if (argv[3] && !strcasecmp(argv[3], "recalc")) {
00574 z = argv[4] ? atoi(argv[4]) : 1;
00575
00576 if (z <= 0) {
00577 ast_cli(fd, " C'mon let's be serious here... defaulting to 1.\n");
00578 z = 1;
00579 }
00580
00581 if (z > MAX_RECALC) {
00582 ast_cli(fd, " Maximum limit of recalc exceeded by %d, truncating value to %d\n", z - MAX_RECALC, MAX_RECALC);
00583 z = MAX_RECALC;
00584 }
00585 ast_cli(fd, " Recalculating Codec Translation (number of sample seconds: %d)\n\n", z);
00586 rebuild_matrix(z);
00587 }
00588
00589 ast_cli(fd, " Translation times between formats (in milliseconds) for one second of data\n");
00590 ast_cli(fd, " Source Format (Rows) Destination Format (Columns)\n\n");
00591
00592 for (x = 0; x < SHOW_TRANS; x++) {
00593 curlen = strlen(ast_getformatname(1 << (x)));
00594 if (curlen > longest)
00595 longest = curlen;
00596 }
00597 for (x = -1; x < SHOW_TRANS; x++) {
00598 char line[120];
00599 char *buf = line;
00600 size_t left = sizeof(line) - 1;
00601
00602 *buf++ = ' ';
00603 *buf = '\0';
00604 for (y = -1; y < SHOW_TRANS; y++) {
00605 if (y >= 0)
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 << (y)) );
00616 } else if (y == -1 && x >= 0) {
00617
00618 ast_build_string(&buf, &left, "%*s", longest, ast_getformatname(1 << (x)) );
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 != powerof(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)) & AST_FORMAT_AUDIO_MASK;
00800
00801 if (common) {
00802 for (cur = 1, y = 0; y <= MAX_AUDIO_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_AUDIO_FORMAT; cur <<= 1, y++) {
00812 if (! (cur & *dst))
00813 continue;
00814 for (cursrc = 1, x = 0; x <= MAX_AUDIO_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 }