![]() |
Home page |
Mailing list |
Docs
Asterisk developer's documentation :: Codename Pineapple
translate.c File Reference
Definition in file translate.c.
#include "asterisk.h"
#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/lock.h"
#include "asterisk/channel.h"
#include "asterisk/logger.h"
#include "asterisk/translate.h"
#include "asterisk/module.h"
#include "asterisk/options.h"
#include "asterisk/frame.h"
#include "asterisk/sched.h"
#include "asterisk/cli.h"
#include "asterisk/term.h"
Include dependency graph for translate.c:

Go to the source code of this file.
Data Structures | |
| struct | translator_path |
Defines | |
| #define | MAX_RECALC 200 |
| #define | SHOW_TRANS 13 |
Functions | |
| int | __ast_register_translator (struct ast_translator *t, struct ast_module *mod) |
| Register a translator This registers a codec translator with asterisk. | |
| static | AST_RWLIST_HEAD_STATIC (translators, ast_translator) |
| the list of translators | |
| ast_frame * | ast_trans_frameout (struct ast_trans_pvt *pvt, int datalen, int samples) |
| generic frameout function | |
| ast_frame * | ast_translate (struct ast_trans_pvt *path, struct ast_frame *f, int consume) |
| translates one or more frames Apply an input frame into the translator and receive zero or one output frames. Consume determines whether the original frame should be freed | |
| unsigned int | ast_translate_available_formats (unsigned int dest, unsigned int src) |
| Mask off unavailable formats from a format bitmask. | |
| unsigned int | ast_translate_path_steps (unsigned int dest, unsigned int src) |
| Returns the number of steps required to convert from 'src' to 'dest'. | |
| void | ast_translator_activate (struct ast_translator *t) |
| Activate a previously deactivated translator. | |
| int | ast_translator_best_choice (int *dst, int *srcs) |
| Chooses the best translation path. | |
| ast_trans_pvt * | ast_translator_build_path (int dest, int source) |
| Builds a translator path Build a path (possibly NULL) from source to dest. | |
| void | ast_translator_deactivate (struct ast_translator *t) |
| Deactivate a translator. | |
| void | ast_translator_free_path (struct ast_trans_pvt *p) |
| Frees a translator path Frees the given translator path structure. | |
| int | ast_unregister_translator (struct ast_translator *t) |
| Unregister a translator Unregisters the given tranlator. | |
| static void | calc_cost (struct ast_translator *t, int seconds) |
| compute the cost of a single translation step | |
| static struct ast_frame * | default_frameout (struct ast_trans_pvt *pvt) |
| static void | destroy (struct ast_trans_pvt *pvt) |
| static int | framein (struct ast_trans_pvt *pvt, struct ast_frame *f) |
| framein wrapper, deals with plc and bound checks. | |
| static void * | newpvt (struct ast_translator *t) |
| Allocate the descriptor, required outbuf space, and possibly also plc and desc. | |
| static force_inline int | powerof (unsigned int d) |
| returns the index of the lowest bit set | |
| static void | rebuild_matrix (int samples) |
| rebuild a translation matrix. | |
| static int | show_translation (int fd, int argc, char *argv[]) |
Variables | |
| static struct ast_cli_entry | cli_translate [] |
| static const char | show_trans_usage [] |
| static struct translator_path | tr_matrix [MAX_FORMAT][MAX_FORMAT] |
| a matrix that, for any pair of supported formats, indicates the total cost of translation and the first step. The full path can be reconstricted iterating on the matrix until step->dstfmt == desired_format. | |
|
|
Definition at line 49 of file translate.c. Referenced by show_translation(). |
|
|
Referenced by show_translation(). |
|
||||||||||||
|
Register a translator This registers a codec translator with asterisk.
Definition at line 572 of file translate.c. References ast_translator::active, ast_cli_register_multiple(), AST_FORMAT_SLINEAR, ast_getformatname(), ast_log(), AST_RWLIST_INSERT_BEFORE_CURRENT, AST_RWLIST_INSERT_HEAD, AST_RWLIST_TRAVERSE_SAFE_BEGIN, AST_RWLIST_TRAVERSE_SAFE_END, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, ast_verbose(), ast_translator::buf_size, ast_translator::buffer_samples, calc_cost(), cli_translate, COLOR_BLACK, COLOR_MAGENTA, ast_translator::cost, default_frameout(), ast_translator::dstfmt, ast_translator::frameout, LOG_WARNING, MAX_FORMAT, ast_translator::module, ast_translator::name, option_verbose, ast_translator::plc_samples, powerof(), rebuild_matrix(), ast_translator::srcfmt, term_color(), and VERBOSE_PREFIX_2. 00573 { 00574 static int added_cli = 0; 00575 struct ast_translator *u; 00576 00577 if (!mod) { 00578 ast_log(LOG_WARNING, "Missing module pointer, you need to supply one\n"); 00579 return -1; 00580 } 00581 00582 if (!t->buf_size) { 00583 ast_log(LOG_WARNING, "empty buf size, you need to supply one\n"); 00584 return -1; 00585 } 00586 00587 t->module = mod; 00588 00589 t->srcfmt = powerof(t->srcfmt); 00590 t->dstfmt = powerof(t->dstfmt); 00591 t->active = 1; 00592 00593 if (t->plc_samples) { 00594 if (t->buffer_samples < t->plc_samples) { 00595 ast_log(LOG_WARNING, "plc_samples %d buffer_samples %d\n", 00596 t->plc_samples, t->buffer_samples); 00597 return -1; 00598 } 00599 if (t->dstfmt != AST_FORMAT_SLINEAR) 00600 ast_log(LOG_WARNING, "plc_samples %d format %x\n", 00601 t->plc_samples, t->dstfmt); 00602 } 00603 if (t->srcfmt >= MAX_FORMAT) { 00604 ast_log(LOG_WARNING, "Source format %s is larger than MAX_FORMAT\n", ast_getformatname(t->srcfmt)); 00605 return -1; 00606 } 00607 00608 if (t->dstfmt >= MAX_FORMAT) { 00609 ast_log(LOG_WARNING, "Destination format %s is larger than MAX_FORMAT\n", ast_getformatname(t->dstfmt)); 00610 return -1; 00611 } 00612 00613 if (t->buf_size) { 00614 /* 00615 * Align buf_size properly, rounding up to the machine-specific 00616 * alignment for pointers. 00617 */ 00618 struct _test_align { void *a, *b; } p; 00619 int align = (char *)&p.b - (char *)&p.a; 00620 00621 t->buf_size = ((t->buf_size + align - 1) / align) * align; 00622 } 00623 00624 if (t->frameout == NULL) 00625 t->frameout = default_frameout; 00626 00627 calc_cost(t, 1); 00628 00629 if (option_verbose > 1) { 00630 char tmp[80]; 00631 00632 ast_verbose(VERBOSE_PREFIX_2 "Registered translator '%s' from format %s to %s, cost %d\n", 00633 term_color(tmp, t->name, COLOR_MAGENTA, COLOR_BLACK, sizeof(tmp)), 00634 ast_getformatname(1 << t->srcfmt), ast_getformatname(1 << t->dstfmt), t->cost); 00635 } 00636 00637 if (!added_cli) { 00638 ast_cli_register_multiple(cli_translate, sizeof(cli_translate) / sizeof(struct ast_cli_entry)); 00639 added_cli++; 00640 } 00641 00642 AST_RWLIST_WRLOCK(&translators); 00643 00644 /* find any existing translators that provide this same srcfmt/dstfmt, 00645 and put this one in order based on cost */ 00646 AST_RWLIST_TRAVERSE_SAFE_BEGIN(&translators, u, list) { 00647 if ((u->srcfmt == t->srcfmt) && 00648 (u->dstfmt == t->dstfmt) && 00649 (u->cost > t->cost)) { 00650 AST_RWLIST_INSERT_BEFORE_CURRENT(&translators, t, list); 00651 t = NULL; 00652 } 00653 } 00654 AST_RWLIST_TRAVERSE_SAFE_END; 00655 00656 /* if no existing translator was found for this format combination, 00657 add it to the beginning of the list */ 00658 if (t) 00659 AST_RWLIST_INSERT_HEAD(&translators, t, list); 00660 00661 rebuild_matrix(0); 00662 00663 AST_RWLIST_UNLOCK(&translators); 00664 00665 return 0; 00666 }
|
|
||||||||||||
|
the list of translators
|
|
||||||||||||||||
|
||||||||||||||||
|
translates one or more frames Apply an input frame into the translator and receive zero or one output frames. Consume determines whether the original frame should be freed
Definition at line 293 of file translate.c. References ast_tvadd(), ast_tvsub(), ast_frame::delivery, framein(), ast_frame::has_timing_info, len, ast_frame::len, ast_trans_pvt::next, ast_trans_pvt::nextin, ast_trans_pvt::nextout, ast_frame::samples, ast_frame::seqno, and ast_frame::ts. Referenced by __ast_read(), ast_slinfactory_feed(), ast_write(), ast_writestream(), process_ast_dsp(), and queue_frame_to_spies(). 00294 { 00295 struct ast_trans_pvt *p = path; 00296 struct ast_frame *out = f; 00297 struct timeval delivery; 00298 int has_timing_info; 00299 long ts; 00300 long len; 00301 int seqno; 00302 00303 has_timing_info = f->has_timing_info; 00304 ts = f->ts; 00305 len = f->len; 00306 seqno = f->seqno; 00307 00308 /* XXX hmmm... check this below */ 00309 if (!ast_tvzero(f->delivery)) { 00310 if (!ast_tvzero(path->nextin)) { 00311 /* Make sure this is in line with what we were expecting */ 00312 if (!ast_tveq(path->nextin, f->delivery)) { 00313 /* The time has changed between what we expected and this 00314 most recent time on the new packet. If we have a 00315 valid prediction adjust our output time appropriately */ 00316 if (!ast_tvzero(path->nextout)) { 00317 path->nextout = ast_tvadd(path->nextout, 00318 ast_tvsub(f->delivery, path->nextin)); 00319 } 00320 path->nextin = f->delivery; 00321 } 00322 } else { 00323 /* This is our first pass. Make sure the timing looks good */ 00324 path->nextin = f->delivery; 00325 path->nextout = f->delivery; 00326 } 00327 /* Predict next incoming sample */ 00328 path->nextin = ast_tvadd(path->nextin, ast_samp2tv(f->samples, 8000)); 00329 } 00330 delivery = f->delivery; 00331 for ( ; out && p ; p = p->next) { 00332 framein(p, out); 00333 out = p->t->frameout(p); 00334 } 00335 if (consume) 00336 ast_frfree(f); 00337 if (out == NULL) 00338 return NULL; 00339 /* we have a frame, play with times */ 00340 if (!ast_tvzero(delivery)) { 00341 /* Regenerate prediction after a discontinuity */ 00342 if (ast_tvzero(path->nextout)) 00343 path->nextout = ast_tvnow(); 00344 00345 /* Use next predicted outgoing timestamp */ 00346 out->delivery = path->nextout; 00347 00348 /* Predict next outgoing timestamp from samples in this 00349 frame. */ 00350 path->nextout = ast_tvadd(path->nextout, ast_samp2tv( out->samples, 8000)); 00351 } else { 00352 out->delivery = ast_tv(0, 0); 00353 out->has_timing_info = has_timing_info; 00354 if (has_timing_info) { 00355 out->ts = ts; 00356 out->len = len; 00357 out->seqno = seqno; 00358 } 00359 } 00360 /* Invalidate prediction if we're entering a silence period */ 00361 if (out->frametype == AST_FRAME_CNG) 00362 path->nextout = ast_tv(0, 0); 00363 return out; 00364 }
|
|
||||||||||||
|
Mask off unavailable formats from a format bitmask.
Note that only a single audio format and a single video format can be present in 'src', or the function will produce unexpected results. Definition at line 777 of file translate.c. References AST_FORMAT_AUDIO_MASK, AST_FORMAT_MAX_AUDIO, AST_FORMAT_VIDEO_MASK, AST_RWLIST_RDLOCK, powerof(), and tr_matrix. Referenced by sip_call(). 00778 { 00779 unsigned int res = dest; 00780 unsigned int x; 00781 unsigned int src_audio = src & AST_FORMAT_AUDIO_MASK; 00782 unsigned int src_video = src & AST_FORMAT_VIDEO_MASK; 00783 00784 /* if we don't have a source format, we just have to try all 00785 possible destination formats */ 00786 if (!src) 00787 return dest; 00788 00789 /* If we have a source audio format, get its format index */ 00790 if (src_audio) 00791 src_audio = powerof(src_audio); 00792 00793 /* If we have a source video format, get its format index */ 00794 if (src_video) 00795 src_video = powerof(src_video); 00796 00797 AST_RWLIST_RDLOCK(&translators); 00798 00799 /* For a given source audio format, traverse the list of 00800 known audio formats to determine whether there exists 00801 a translation path from the source format to the 00802 destination format. */ 00803 for (x = 1; src_audio && x < AST_FORMAT_MAX_AUDIO; x <<= 1) { 00804 /* if this is not a desired format, nothing to do */ 00805 if (!dest & x) 00806 continue; 00807 00808 /* if the source is supplying this format, then 00809 we can leave it in the result */ 00810 if (src & x) 00811 continue; 00812 00813 /* if we don't have a translation path from the src 00814 to this format, remove it from the result */ 00815 if (!tr_matrix[src_audio][powerof(x)].step) { 00816 res &= ~x; 00817 continue; 00818 } 00819 00820 /* now check the opposite direction */ 00821 if (!tr_matrix[powerof(x)][src_audio].step) 00822 res &= ~x; 00823 } 00824 00825 /* For a given source video format, traverse the list of 00826 known video formats to determine whether there exists 00827 a translation path from the source format to the 00828 destination format. */ 00829 for (; src_video && x < AST_FORMAT_MAX_VIDEO; x <<= 1) { 00830 /* if this is not a desired format, nothing to do */ 00831 if (!dest & x) 00832 continue; 00833 00834 /* if the source is supplying this format, then 00835 we can leave it in the result */ 00836 if (src & x) 00837 continue; 00838 00839 /* if we don't have a translation path from the src 00840 to this format, remove it from the result */ 00841 if (!tr_matrix[src_video][powerof(x)].step) { 00842 res &= ~x; 00843 continue; 00844 } 00845 00846 /* now check the opposite direction */ 00847 if (!tr_matrix[powerof(x)][src_video].step) 00848 res &= ~x; 00849 } 00850 00851 AST_RWLIST_UNLOCK(&translators); 00852 00853 return res; 00854 }
|
|
||||||||||||
|
Returns the number of steps required to convert from 'src' to 'dest'.
Definition at line 759 of file translate.c. References AST_RWLIST_RDLOCK, AST_RWLIST_UNLOCK, translator_path::multistep, powerof(), and tr_matrix. Referenced by ast_channel_make_compatible_helper(). 00760 { 00761 unsigned int res = -1; 00762 00763 /* convert bitwise format numbers into array indices */ 00764 src = powerof(src); 00765 dest = powerof(dest); 00766 00767 AST_RWLIST_RDLOCK(&translators); 00768 00769 if (tr_matrix[src][dest].step) 00770 res = tr_matrix[src][dest].multistep + 1; 00771 00772 AST_RWLIST_UNLOCK(&translators); 00773 00774 return res; 00775 }
|
|
|
Activate a previously deactivated translator.
Definition at line 695 of file translate.c. References ast_translator::active, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, and rebuild_matrix(). 00696 { 00697 AST_RWLIST_WRLOCK(&translators); 00698 t->active = 1; 00699 rebuild_matrix(0); 00700 AST_RWLIST_UNLOCK(&translators); 00701 }
|
|
||||||||||||
|
Chooses the best translation path. Given a list of sources, and a designed destination format, which should I choose?
Definition at line 712 of file translate.c. References MAX_FORMAT. Referenced by ast_channel_make_compatible_helper(), ast_request(), iax2_request(), and set_format(). 00713 { 00714 int x,y; 00715 int best = -1; 00716 int bestdst = 0; 00717 int cur, cursrc; 00718 int besttime = INT_MAX; 00719 int beststeps = INT_MAX; 00720 int common = (*dst) & (*srcs); /* are there common formats ? */ 00721 00722 if (common) { /* yes, pick one and return */ 00723 for (cur = 1, y = 0; y < MAX_FORMAT; cur <<= 1, y++) { 00724 if (cur & common) /* guaranteed to find one */ 00725 break; 00726 } 00727 /* We are done, this is a common format to both. */ 00728 *srcs = *dst = cur; 00729 return 0; 00730 } else { /* No, we will need to translate */ 00731 AST_RWLIST_RDLOCK(&translators); 00732 for (cur = 1, y = 0; y < MAX_FORMAT; cur <<= 1, y++) { 00733 if (! (cur & *dst)) 00734 continue; 00735 for (cursrc = 1, x = 0; x < MAX_FORMAT; cursrc <<= 1, x++) { 00736 if (!(*srcs & cursrc) || !tr_matrix[x][y].step || 00737 tr_matrix[x][y].cost > besttime) 00738 continue; /* not existing or no better */ 00739 if (tr_matrix[x][y].cost < besttime || 00740 tr_matrix[x][y].multistep < beststeps) { 00741 /* better than what we have so far */ 00742 best = cursrc; 00743 bestdst = cur; 00744 besttime = tr_matrix[x][y].cost; 00745 beststeps = tr_matrix[x][y].multistep; 00746 } 00747 } 00748 } 00749 AST_RWLIST_UNLOCK(&translators); 00750 if (best > -1) { 00751 *srcs = best; 00752 *dst = bestdst; 00753 best = 0; 00754 } 00755 return best; 00756 } 00757 }
|
|
||||||||||||
|
Builds a translator path Build a path (possibly NULL) from source to dest.
Definition at line 253 of file translate.c. References ast_getformatname(), ast_log(), AST_RWLIST_RDLOCK, AST_RWLIST_UNLOCK, ast_translator_free_path(), ast_translator::dstfmt, LOG_WARNING, newpvt(), ast_trans_pvt::next, ast_trans_pvt::nextin, ast_trans_pvt::nextout, powerof(), translator_path::step, ast_trans_pvt::t, and tr_matrix. Referenced by ast_slinfactory_feed(), ast_write(), ast_writestream(), queue_frame_to_spies(), read_config(), and set_format(). 00254 { 00255 struct ast_trans_pvt *head = NULL, *tail = NULL; 00256 00257 source = powerof(source); 00258 dest = powerof(dest); 00259 00260 AST_RWLIST_RDLOCK(&translators); 00261 00262 while (source != dest) { 00263 struct ast_trans_pvt *cur; 00264 struct ast_translator *t = tr_matrix[source][dest].step; 00265 if (!t) { 00266 ast_log(LOG_WARNING, "No translator path from %s to %s\n", 00267 ast_getformatname(source), ast_getformatname(dest)); 00268 AST_RWLIST_UNLOCK(&translators); 00269 return NULL; 00270 } 00271 if (!(cur = newpvt(t))) { 00272 ast_log(LOG_WARNING, "Failed to build translator step from %d to %d\n", source, dest); 00273 if (head) 00274 ast_translator_free_path(head); 00275 AST_RWLIST_UNLOCK(&translators); 00276 return NULL; 00277 } 00278 if (!head) 00279 head = cur; 00280 else 00281 tail->next = cur; 00282 tail = cur; 00283 cur->nextin = cur->nextout = ast_tv(0, 0); 00284 /* Keep going if this isn't the final destination */ 00285 source = cur->t->dstfmt; 00286 } 00287 00288 AST_RWLIST_UNLOCK(&translators); 00289 return head; 00290 }
|
|
|
Deactivate a translator.
Definition at line 703 of file translate.c. References ast_translator::active, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, and rebuild_matrix(). 00704 { 00705 AST_RWLIST_WRLOCK(&translators); 00706 t->active = 0; 00707 rebuild_matrix(0); 00708 AST_RWLIST_UNLOCK(&translators); 00709 }
|
|
|
Frees a translator path Frees the given translator path structure.
Definition at line 243 of file translate.c. References destroy(), and ast_trans_pvt::next. Referenced by ast_channel_free(), ast_channel_whisper_stop(), ast_closestream(), ast_slinfactory_destroy(), ast_slinfactory_feed(), ast_translator_build_path(), ast_write(), ast_writestream(), cl_dequeue_chan(), free_translation(), queue_frame_to_spies(), set_format(), and spy_cleanup(). 00244 { 00245 struct ast_trans_pvt *pn = p; 00246 while ( (p = pn) ) { 00247 pn = p->next; 00248 destroy(p); 00249 } 00250 }
|
|
|
Unregister a translator Unregisters the given tranlator.
Definition at line 669 of file translate.c. References ast_getformatname(), AST_RWLIST_REMOVE_CURRENT, AST_RWLIST_TRAVERSE_SAFE_BEGIN, AST_RWLIST_TRAVERSE_SAFE_END, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, ast_verbose(), COLOR_BLACK, COLOR_MAGENTA, ast_translator::dstfmt, ast_translator::name, option_verbose, rebuild_matrix(), ast_translator::srcfmt, term_color(), and VERBOSE_PREFIX_2. 00670 { 00671 char tmp[80]; 00672 struct ast_translator *u; 00673 int found = 0; 00674 00675 AST_RWLIST_WRLOCK(&translators); 00676 AST_RWLIST_TRAVERSE_SAFE_BEGIN(&translators, u, list) { 00677 if (u == t) { 00678 AST_RWLIST_REMOVE_CURRENT(&translators, list); 00679 if (option_verbose > 1) 00680 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)); 00681 found = 1; 00682 break; 00683 } 00684 } 00685 AST_RWLIST_TRAVERSE_SAFE_END; 00686 00687 if (found) 00688 rebuild_matrix(0); 00689 00690 AST_RWLIST_UNLOCK(&translators); 00691 00692 return (u ? 0 : -1); 00693 }
|
|
||||||||||||
|
compute the cost of a single translation step
Definition at line 367 of file translate.c. References ast_frfree(), ast_log(), ast_translator::cost, destroy(), framein(), ast_translator::frameout, LOG_WARNING, ast_translator::name, newpvt(), ast_trans_pvt::pvt, ast_translator::sample, and ast_frame::samples. Referenced by __ast_register_translator(), and rebuild_matrix(). 00368 { 00369 int sofar=0; 00370 struct ast_trans_pvt *pvt; 00371 struct timeval start; 00372 int cost; 00373 00374 if (!seconds) 00375 seconds = 1; 00376 00377 /* If they don't make samples, give them a terrible score */ 00378 if (!t->sample) { 00379 ast_log(LOG_WARNING, "Translator '%s' does not produce sample frames.\n", t->name); 00380 t->cost = 99999; 00381 return; 00382 } 00383 pvt = newpvt(t); 00384 if (!pvt) { 00385 ast_log(LOG_WARNING, "Translator '%s' appears to be broken and will probably fail.\n", t->name); 00386 t->cost = 99999; 00387 return; 00388 } 00389 start = ast_tvnow(); 00390 /* Call the encoder until we've processed the required number of samples */ 00391 while (sofar < seconds * 8000) { 00392 struct ast_frame *f = t->sample(); 00393 if (!f) { 00394 ast_log(LOG_WARNING, "Translator '%s' failed to produce a sample frame.\n", t->name); 00395 destroy(pvt); 00396 t->cost = 99999; 00397 return; 00398 } 00399 framein(pvt, f); 00400 ast_frfree(f); 00401 while ((f = t->frameout(pvt))) { 00402 sofar += f->samples; 00403 ast_frfree(f); 00404 } 00405 } 00406 cost = ast_tvdiff_ms(ast_tvnow(), start); 00407 destroy(pvt); 00408 t->cost = cost / seconds; 00409 if (!t->cost) 00410 t->cost = 1; 00411 }
|
|
|
Definition at line 236 of file translate.c. References ast_trans_frameout(). Referenced by __ast_register_translator(). 00237 { 00238 return ast_trans_frameout(pvt, 0, 0); 00239 }
|
|
|
Definition at line 139 of file translate.c. References ast_module_unref(), ast_translator::destroy, free, ast_translator::module, and ast_trans_pvt::t. Referenced by ast_translator_free_path(), and calc_cost(). 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 }
|
|
||||||||||||
|
framein wrapper, deals with plc and bound checks.
Definition at line 150 of file translate.c. References ast_log(), ast_translator::buffer_samples, ast_trans_pvt::datalen, ast_frame::datalen, ast_trans_pvt::f, ast_translator::framein, ast_frame::has_timing_info, ast_frame::len, LOG_WARNING, ast_translator::name, ast_trans_pvt::outbuf, ast_trans_pvt::plc, plc_fillin(), plc_rx(), ast_translator::plc_samples, ast_frame::samples, ast_trans_pvt::samples, ast_frame::seqno, ast_trans_pvt::t, and ast_frame::ts. Referenced by ast_translate(), and calc_cost(). 00151 { 00152 int16_t *dst = (int16_t *)pvt->outbuf; 00153 int ret; 00154 int samples = pvt->samples; /* initial value */ 00155 00156 /* Copy the last in jb timing info to the pvt */ 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) { /* do not pass empty frames to callback */ 00166 if (f->datalen == 0) { /* perform PLC with nominal framesize of 20ms/160 samples */ 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; /* SLIN has 2bytes for 1sample */ 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 /* we require a framein routine, wouldn't know how to do 00185 * it otherwise. 00186 */ 00187 ret = pvt->t->framein(pvt, f); 00188 /* possibly store data for plc */ 00189 if (!ret && pvt->plc) { 00190 int l = pvt->t->plc_samples; 00191 if (pvt->samples < l) 00192 l = pvt->samples; 00193 plc_rx(pvt->plc, dst + pvt->samples - l, l); 00194 } 00195 /* diagnostic ... */ 00196 if (pvt->samples == samples) 00197 ast_log(LOG_WARNING, "%s did not update samples %d\n", 00198 pvt->t->name, pvt->samples); 00199 return ret; 00200 }
|
|
|
Allocate the descriptor, required outbuf space, and possibly also plc and desc.
Definition at line 99 of file translate.c. References ast_calloc, AST_FRIENDLY_OFFSET, ast_translator::buf_size, ast_translator::desc_size, free, len, ast_translator::newpvt, ast_translator::plc_samples, ast_trans_pvt::pvt, ast_trans_pvt::t, and ast_translator::useplc. Referenced by ast_translator_build_path(), and calc_cost(). 00100 { 00101 struct ast_trans_pvt *pvt; 00102 int len; 00103 int useplc = t->plc_samples > 0 && t->useplc; /* cache, because it can change on the fly */ 00104 char *ofs; 00105 00106 /* 00107 * compute the required size adding private descriptor, 00108 * plc, buffer, AST_FRIENDLY_OFFSET. 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); /* pointer to data space */ 00120 if (t->desc_size) { /* first comes the descriptor */ 00121 pvt->pvt = ofs; 00122 ofs += t->desc_size; 00123 } 00124 if (useplc) { /* then plc state */ 00125 pvt->plc = (plc_state_t *)ofs; 00126 ofs += sizeof(plc_state_t); 00127 } 00128 if (t->buf_size) /* finally buffer and header */ 00129 pvt->outbuf = ofs + AST_FRIENDLY_OFFSET; 00130 /* call local init routine, if present */ 00131 if (t->newpvt && t->newpvt(pvt)) { 00132 free(pvt); 00133 return NULL; 00134 } 00135 ast_module_ref(t->module); 00136 return pvt; 00137 }
|
|
|
returns the index of the lowest bit set
Definition at line 79 of file translate.c. References ast_log(), and LOG_WARNING. Referenced by __ast_register_translator(), agents_show(), ast_translate_available_formats(), ast_translate_path_steps(), and ast_translator_build_path(). 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 }
|
|
|
rebuild a translation matrix.
Definition at line 417 of file translate.c. References ast_translator::active, ast_getformatname(), ast_log(), AST_RWLIST_TRAVERSE, calc_cost(), ast_translator::cost, ast_translator::dstfmt, LOG_DEBUG, MAX_FORMAT, option_debug, ast_translator::srcfmt, and tr_matrix. Referenced by __ast_register_translator(), ast_translator_activate(), ast_translator_deactivate(), ast_unregister_translator(), and show_translation(). 00418 { 00419 struct ast_translator *t; 00420 int x; /* source format index */ 00421 int y; /* intermediate format index */ 00422 int z; /* destination format index */ 00423 00424 if (option_debug) 00425 ast_log(LOG_DEBUG, "Resetting translation matrix\n"); 00426 00427 bzero(tr_matrix, sizeof(tr_matrix)); 00428 00429 /* first, compute all direct costs */ 00430 AST_RWLIST_TRAVERSE(&translators, t, list) { 00431 if (!t->active) 00432 continue; 00433 00434 x = t->srcfmt; 00435 z = t->dstfmt; 00436 00437 if (samples) 00438 calc_cost(t, samples); 00439 00440 if (!tr_matrix[x][z].step || t->cost < tr_matrix[x][z].cost) { 00441 tr_matrix[x][z].step = t; 00442 tr_matrix[x][z].cost = t->cost; 00443 } 00444 } 00445 00446 /* 00447 * For each triple x, y, z of distinct formats, check if there is 00448 * a path from x to z through y which is cheaper than what is 00449 * currently known, and in case, update the matrix. 00450 * Repeat until the matrix is stable. 00451 */ 00452 for (;;) { 00453 int changed = 0; 00454 for (x = 0; x < MAX_FORMAT; x++) { /* source format */ 00455 for (y=0; y < MAX_FORMAT; y++) { /* intermediate format */ 00456 if (x == y) /* skip ourselves */ 00457 continue; 00458 00459 for (z=0; z<MAX_FORMAT; z++) { /* dst format */ 00460 int newcost; 00461 00462 if (z == x || z == y) /* skip null conversions */ 00463 continue; 00464 if (!tr_matrix[x][y].step) /* no path from x to y */ 00465 continue; 00466 if (!tr_matrix[y][z].step) /* no path from y to z */ 00467 continue; 00468 newcost = tr_matrix[x][y].cost + tr_matrix[y][z].cost; 00469 if (tr_matrix[x][z].step && newcost >= tr_matrix[x][z].cost) 00470 continue; /* x->y->z is more expensive than 00471 * the existing path */ 00472 /* ok, we can get from x to z via y with a cost that 00473 is the sum of the transition from x to y and 00474 from y to z */ 00475 00476 tr_matrix[x][z].step = tr_matrix[x][y].step; 00477 tr_matrix[x][z].cost = newcost; 00478 tr_matrix[x][z].multistep = 1; 00479 if (option_debug) 00480 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); 00481 changed++; 00482 } 00483 } 00484 } 00485 if (!changed) 00486 break; 00487 } 00488 }
|
|
||||||||||||||||
|
Definition at line 490 of file translate.c. References ast_cli(), ast_getformatname(), AST_RWLIST_RDLOCK, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, MAX_RECALC, rebuild_matrix(), RESULT_SHOWUSAGE, and SHOW_TRANS. 00491 { 00492 #define SHOW_TRANS 13 00493 int x, y, z; 00494 int curlen = 0, longest = 0; 00495 00496 if (argc > 5) 00497 return RESULT_SHOWUSAGE; 00498 00499 if (argv[3] && !strcasecmp(argv[3], "recalc")) { 00500 z = argv[4] ? atoi(argv[4]) : 1; 00501 00502 if (z <= 0) { 00503 ast_cli(fd, " C'mon let's be serious here... defaulting to 1.\n"); 00504 z = 1; 00505 } 00506 00507 if (z > MAX_RECALC) { 00508 ast_cli(fd, " Maximum limit of recalc exceeded by %d, truncating value to %d\n", z - MAX_RECALC, MAX_RECALC); 00509 z = MAX_RECALC; 00510 } 00511 ast_cli(fd, " Recalculating Codec Translation (number of sample seconds: %d)\n\n", z); 00512 AST_RWLIST_WRLOCK(&translators); 00513 rebuild_matrix(z); 00514 AST_RWLIST_UNLOCK(&translators); 00515 } 00516 00517 AST_RWLIST_RDLOCK(&translators); 00518 00519 ast_cli(fd, " Translation times between formats (in milliseconds) for one second of data\n"); 00520 ast_cli(fd, " Source Format (Rows) Destination Format (Columns)\n\n"); 00521 /* Get the length of the longest (usable?) codec name, so we know how wide the left side should be */ 00522 for (x = 0; x < SHOW_TRANS; x++) { 00523 curlen = strlen(ast_getformatname(1 << (x + 1))); 00524 if (curlen > longest) 00525 longest = curlen; 00526 } 00527 for (x = -1; x < SHOW_TRANS; x++) { 00528 struct ast_str *out = ast_str_alloca(120); 00529 00530 ast_str_set(&out, -1, " "); 00531 for (y = -1; y < SHOW_TRANS; y++) { 00532 curlen = strlen(ast_getformatname(1 << (y))); 00533 00534 if (x >= 0 && y >= 0 && tr_matrix[x][y].step) { 00535 /* XXX 999 is a little hackish 00536 We don't want this number being larger than the shortest (or current) codec 00537 For now, that is "gsm" */ 00538 ast_str_append(&out, -1, "%*d", curlen + 1, tr_matrix[x][y].cost > 999 ? 0 : tr_matrix[x][y].cost); 00539 } else if (x == -1 && y >= 0) { 00540 /* Top row - use a dynamic size */ 00541 ast_str_append(&out, -1, "%*s", curlen + 1, ast_getformatname(1 << (x + y + 1)) ); 00542 } else if (y == -1 && x >= 0) { 00543 /* Left column - use a static size. */ 00544 ast_str_append(&out, -1, "%*s", longest, ast_getformatname(1 << (x + y + 1)) ); 00545 } else if (x >= 0 && y >= 0) { 00546 ast_str_append(&out, -1, "%*s", curlen + 1, "-"); 00547 } else { 00548 ast_str_append(&out, -1, "%*s", longest, ""); 00549 } 00550 } 00551 ast_str_append(&out, -1, "\n"); 00552 ast_cli(fd, out->str); 00553 } 00554 AST_RWLIST_UNLOCK(&translators); 00555 return RESULT_SUCCESS; 00556 }
|
|
|
Initial value: {
{ { "core", "show", "translation", NULL },
show_translation, "Display translation matrix",
show_trans_usage, NULL, NULL },
}
Definition at line 565 of file translate.c. Referenced by __ast_register_translator(). |
|
|
Definition at line 558 of file translate.c. |
|
|
a matrix that, for any pair of supported formats, indicates the total cost of translation and the first step. The full path can be reconstricted iterating on the matrix until step->dstfmt == desired_format. Array indexes are 'src' and 'dest', in that order. Note: the lock in the 'translators' list is also used to protect this structure. Definition at line 70 of file translate.c. Referenced by ast_translate_available_formats(), ast_translate_path_steps(), ast_translator_build_path(), and rebuild_matrix(). |