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: 67631 $")
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 + 1)));
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 curlen = strlen(ast_getformatname(1 << (y)));
00537
00538 if (x >= 0 && y >= 0 && tr_matrix[x][y].step) {
00539
00540
00541
00542 ast_build_string(&buf, &left, "%*d", curlen + 1, tr_matrix[x][y].cost > 999 ? 0 : tr_matrix[x][y].cost);
00543 } else if (x == -1 && y >= 0) {
00544
00545 ast_build_string(&buf, &left, "%*s", curlen + 1, ast_getformatname(1 << (x + y + 1)) );
00546 } else if (y == -1 && x >= 0) {
00547
00548 ast_build_string(&buf, &left, "%*s", longest, ast_getformatname(1 << (x + y + 1)) );
00549 } else if (x >= 0 && y >= 0) {
00550 ast_build_string(&buf, &left, "%*s", curlen + 1, "-");
00551 } else {
00552 ast_build_string(&buf, &left, "%*s", longest, "");
00553 }
00554 }
00555 ast_build_string(&buf, &left, "\n");
00556 ast_cli(fd, line);
00557 }
00558 AST_LIST_UNLOCK(&translators);
00559 return RESULT_SUCCESS;
00560 }
00561
00562 static int show_translation(int fd, int argc, char *argv[])
00563 {
00564 int x, y, z;
00565 int curlen = 0, longest = 0;
00566
00567 if (argc > 5)
00568 return RESULT_SHOWUSAGE;
00569
00570 AST_LIST_LOCK(&translators);
00571
00572 if (argv[3] && !strcasecmp(argv[3], "recalc")) {
00573 z = argv[4] ? atoi(argv[4]) : 1;
00574
00575 if (z <= 0) {
00576 ast_cli(fd, " C'mon let's be serious here... defaulting to 1.\n");
00577 z = 1;
00578 }
00579
00580 if (z > MAX_RECALC) {
00581 ast_cli(fd, " Maximum limit of recalc exceeded by %d, truncating value to %d\n", z - MAX_RECALC, MAX_RECALC);
00582 z = MAX_RECALC;
00583 }
00584 ast_cli(fd, " Recalculating Codec Translation (number of sample seconds: %d)\n\n", z);
00585 rebuild_matrix(z);
00586 }
00587
00588 ast_cli(fd, " Translation times between formats (in milliseconds) for one second of data\n");
00589 ast_cli(fd, " Source Format (Rows) Destination Format (Columns)\n\n");
00590
00591 for (x = 0; x < SHOW_TRANS; x++) {
00592 curlen = strlen(ast_getformatname(1 << (x + 1)));
00593 if (curlen > longest)
00594 longest = curlen;
00595 }
00596 for (x = -1; x < SHOW_TRANS; x++) {
00597 char line[120];
00598 char *buf = line;
00599 size_t left = sizeof(line) - 1;
00600
00601 *buf++ = ' ';
00602 *buf = '\0';
00603 for (y = -1; y < SHOW_TRANS; y++) {
00604 curlen = strlen(ast_getformatname(1 << (y)));
00605
00606 if (x >= 0 && y >= 0 && tr_matrix[x][y].step) {
00607
00608
00609
00610 ast_build_string(&buf, &left, "%*d", curlen + 1, tr_matrix[x][y].cost > 999 ? 0 : tr_matrix[x][y].cost);
00611 } else if (x == -1 && y >= 0) {
00612
00613 ast_build_string(&buf, &left, "%*s", curlen + 1, ast_getformatname(1 << (x + y + 1)) );
00614 } else if (y == -1 && x >= 0) {
00615
00616 ast_build_string(&buf, &left, "%*s", longest, ast_getformatname(1 << (x + y + 1)) );
00617 } else if (x >= 0 && y >= 0) {
00618 ast_build_string(&buf, &left, "%*s", curlen + 1, "-");
00619 } else {
00620 ast_build_string(&buf, &left, "%*s", longest, "");
00621 }
00622 }
00623 ast_build_string(&buf, &left, "\n");
00624 ast_cli(fd, line);
00625 }
00626 AST_LIST_UNLOCK(&translators);
00627 return RESULT_SUCCESS;
00628 }
00629
00630 static char show_trans_usage[] =
00631 "Usage: core show translation [recalc] [<recalc seconds>]\n"
00632 " Displays known codec translators and the cost associated\n"
00633 "with each conversion. If the argument 'recalc' is supplied along\n"
00634 "with optional number of seconds to test a new test will be performed\n"
00635 "as the chart is being displayed.\n";
00636
00637 static struct ast_cli_entry cli_show_translation_deprecated = {
00638 { "show", "translation", NULL },
00639 show_translation_deprecated, NULL,
00640 NULL };
00641
00642 static struct ast_cli_entry cli_translate[] = {
00643 { { "core", "show", "translation", NULL },
00644 show_translation, "Display translation matrix",
00645 show_trans_usage, NULL, &cli_show_translation_deprecated },
00646 };
00647
00648
00649 int __ast_register_translator(struct ast_translator *t, struct ast_module *mod)
00650 {
00651 static int added_cli = 0;
00652 struct ast_translator *u;
00653
00654 if (!mod) {
00655 ast_log(LOG_WARNING, "Missing module pointer, you need to supply one\n");
00656 return -1;
00657 }
00658
00659 if (!t->buf_size) {
00660 ast_log(LOG_WARNING, "empty buf size, you need to supply one\n");
00661 return -1;
00662 }
00663
00664 t->module = mod;
00665
00666 t->srcfmt = powerof(t->srcfmt);
00667 t->dstfmt = powerof(t->dstfmt);
00668 t->active = 1;
00669
00670 if (t->plc_samples) {
00671 if (t->buffer_samples < t->plc_samples) {
00672 ast_log(LOG_WARNING, "plc_samples %d buffer_samples %d\n",
00673 t->plc_samples, t->buffer_samples);
00674 return -1;
00675 }
00676 if (t->dstfmt != powerof(AST_FORMAT_SLINEAR))
00677 ast_log(LOG_WARNING, "plc_samples %d format %x\n",
00678 t->plc_samples, t->dstfmt);
00679 }
00680 if (t->srcfmt >= MAX_FORMAT) {
00681 ast_log(LOG_WARNING, "Source format %s is larger than MAX_FORMAT\n", ast_getformatname(t->srcfmt));
00682 return -1;
00683 }
00684
00685 if (t->dstfmt >= MAX_FORMAT) {
00686 ast_log(LOG_WARNING, "Destination format %s is larger than MAX_FORMAT\n", ast_getformatname(t->dstfmt));
00687 return -1;
00688 }
00689
00690 if (t->buf_size) {
00691
00692
00693
00694
00695 struct _test_align { void *a, *b; } p;
00696 int align = (char *)&p.b - (char *)&p.a;
00697
00698 t->buf_size = ((t->buf_size + align - 1) / align) * align;
00699 }
00700
00701 if (t->frameout == NULL)
00702 t->frameout = default_frameout;
00703
00704 calc_cost(t, 1);
00705
00706 if (option_verbose > 1) {
00707 char tmp[80];
00708
00709 ast_verbose(VERBOSE_PREFIX_2 "Registered translator '%s' from format %s to %s, cost %d\n",
00710 term_color(tmp, t->name, COLOR_MAGENTA, COLOR_BLACK, sizeof(tmp)),
00711 ast_getformatname(1 << t->srcfmt), ast_getformatname(1 << t->dstfmt), t->cost);
00712 }
00713
00714 if (!added_cli) {
00715 ast_cli_register_multiple(cli_translate, sizeof(cli_translate) / sizeof(struct ast_cli_entry));
00716 added_cli++;
00717 }
00718
00719 AST_LIST_LOCK(&translators);
00720
00721
00722
00723 AST_LIST_TRAVERSE_SAFE_BEGIN(&translators, u, list) {
00724 if ((u->srcfmt == t->srcfmt) &&
00725 (u->dstfmt == t->dstfmt) &&
00726 (u->cost > t->cost)) {
00727 AST_LIST_INSERT_BEFORE_CURRENT(&translators, t, list);
00728 t = NULL;
00729 }
00730 }
00731 AST_LIST_TRAVERSE_SAFE_END;
00732
00733
00734
00735 if (t)
00736 AST_LIST_INSERT_HEAD(&translators, t, list);
00737
00738 rebuild_matrix(0);
00739
00740 AST_LIST_UNLOCK(&translators);
00741
00742 return 0;
00743 }
00744
00745
00746 int ast_unregister_translator(struct ast_translator *t)
00747 {
00748 char tmp[80];
00749 struct ast_translator *u;
00750 int found = 0;
00751
00752 AST_LIST_LOCK(&translators);
00753 AST_LIST_TRAVERSE_SAFE_BEGIN(&translators, u, list) {
00754 if (u == t) {
00755 AST_LIST_REMOVE_CURRENT(&translators, list);
00756 if (option_verbose > 1)
00757 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));
00758 found = 1;
00759 break;
00760 }
00761 }
00762 AST_LIST_TRAVERSE_SAFE_END;
00763
00764 if (found)
00765 rebuild_matrix(0);
00766
00767 AST_LIST_UNLOCK(&translators);
00768
00769 return (u ? 0 : -1);
00770 }
00771
00772 void ast_translator_activate(struct ast_translator *t)
00773 {
00774 AST_LIST_LOCK(&translators);
00775 t->active = 1;
00776 rebuild_matrix(0);
00777 AST_LIST_UNLOCK(&translators);
00778 }
00779
00780 void ast_translator_deactivate(struct ast_translator *t)
00781 {
00782 AST_LIST_LOCK(&translators);
00783 t->active = 0;
00784 rebuild_matrix(0);
00785 AST_LIST_UNLOCK(&translators);
00786 }
00787
00788
00789 int ast_translator_best_choice(int *dst, int *srcs)
00790 {
00791 int x,y;
00792 int best = -1;
00793 int bestdst = 0;
00794 int cur, cursrc;
00795 int besttime = INT_MAX;
00796 int beststeps = INT_MAX;
00797 int common = (*dst) & (*srcs);
00798
00799 if (common) {
00800 for (cur = 1, y = 0; y < MAX_FORMAT; cur <<= 1, y++) {
00801 if (cur & common)
00802 break;
00803 }
00804
00805 *srcs = *dst = cur;
00806 return 0;
00807 } else {
00808 AST_LIST_LOCK(&translators);
00809 for (cur = 1, y = 0; y < MAX_FORMAT; cur <<= 1, y++) {
00810 if (! (cur & *dst))
00811 continue;
00812 for (cursrc = 1, x = 0; x < MAX_FORMAT; cursrc <<= 1, x++) {
00813 if (!(*srcs & cursrc) || !tr_matrix[x][y].step ||
00814 tr_matrix[x][y].cost > besttime)
00815 continue;
00816 if (tr_matrix[x][y].cost < besttime ||
00817 tr_matrix[x][y].multistep < beststeps) {
00818
00819 best = cursrc;
00820 bestdst = cur;
00821 besttime = tr_matrix[x][y].cost;
00822 beststeps = tr_matrix[x][y].multistep;
00823 }
00824 }
00825 }
00826 AST_LIST_UNLOCK(&translators);
00827 if (best > -1) {
00828 *srcs = best;
00829 *dst = bestdst;
00830 best = 0;
00831 }
00832 return best;
00833 }
00834 }
00835
00836 unsigned int ast_translate_path_steps(unsigned int dest, unsigned int src)
00837 {
00838 unsigned int res = -1;
00839
00840
00841 src = powerof(src);
00842 dest = powerof(dest);
00843
00844 AST_LIST_LOCK(&translators);
00845
00846 if (tr_matrix[src][dest].step)
00847 res = tr_matrix[src][dest].multistep + 1;
00848
00849 AST_LIST_UNLOCK(&translators);
00850
00851 return res;
00852 }
00853
00854 unsigned int ast_translate_available_formats(unsigned int dest, unsigned int src)
00855 {
00856 unsigned int res = dest;
00857 unsigned int x;
00858 unsigned int src_audio = src & AST_FORMAT_AUDIO_MASK;
00859 unsigned int src_video = src & AST_FORMAT_VIDEO_MASK;
00860
00861
00862
00863 if (!src)
00864 return dest;
00865
00866
00867 if (src_audio)
00868 src_audio = powerof(src_audio);
00869
00870
00871 if (src_video)
00872 src_video = powerof(src_video);
00873
00874 AST_LIST_LOCK(&translators);
00875
00876
00877
00878
00879
00880 for (x = 1; src_audio && x < AST_FORMAT_MAX_AUDIO; x <<= 1) {
00881
00882 if (!dest & x)
00883 continue;
00884
00885
00886
00887 if (src & x)
00888 continue;
00889
00890
00891
00892 if (!tr_matrix[src_audio][powerof(x)].step) {
00893 res &= ~x;
00894 continue;
00895 }
00896
00897
00898 if (!tr_matrix[powerof(x)][src_audio].step)
00899 res &= ~x;
00900 }
00901
00902
00903
00904
00905
00906 for (; src_video && x < AST_FORMAT_MAX_VIDEO; x <<= 1) {
00907
00908 if (!dest & x)
00909 continue;
00910
00911
00912
00913 if (src & x)
00914 continue;
00915
00916
00917
00918 if (!tr_matrix[src_video][powerof(x)].step) {
00919 res &= ~x;
00920 continue;
00921 }
00922
00923
00924 if (!tr_matrix[powerof(x)][src_video].step)
00925 res &= ~x;
00926 }
00927
00928 AST_LIST_UNLOCK(&translators);
00929
00930 return res;
00931 }