Translate via the use of pseudo channels. More...
#include "asterisk.h"#include <sys/time.h>#include <sys/resource.h>#include <math.h>#include "asterisk/lock.h"#include "asterisk/channel.h"#include "asterisk/translate.h"#include "asterisk/module.h"#include "asterisk/frame.h"#include "asterisk/sched.h"#include "asterisk/cli.h"#include "asterisk/term.h"
Go to the source code of this file.
Data Structures | |
| struct | translator_path |
Defines | |
| #define | MAX_RECALC 1000 |
| #define | SHOW_TRANS 16 |
Functions | |
| int | __ast_register_translator (struct ast_translator *t, struct ast_module *mod) |
| register codec translator | |
| static | AST_RWLIST_HEAD_STATIC (translators, ast_translator) |
| the list of translators | |
| struct ast_frame * | ast_trans_frameout (struct ast_trans_pvt *pvt, int datalen, int samples) |
| generic frameout routine. If samples and datalen are 0, take whatever is in pvt and reset them, otherwise take the values in the caller and leave alone the pvt values. | |
| struct ast_frame * | ast_translate (struct ast_trans_pvt *path, struct ast_frame *f, int consume) |
| do the actual translation | |
| 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) |
| Calculate our best translator source format, given costs, and a desired destination. | |
| struct ast_trans_pvt * | ast_translator_build_path (int dest, int source) |
| Build a chain of translators based upon the given source and dest formats. | |
| 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 codec translator | |
| 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 char * | handle_cli_core_show_translation (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) |
| 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. | |
Variables | |
| static struct ast_cli_entry | cli_translate [] |
| 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. | |
Translate via the use of pseudo channels.
Definition in file translate.c.
| #define MAX_RECALC 1000 |
Definition at line 43 of file translate.c.
Referenced by handle_cli_core_show_translation().
| #define SHOW_TRANS 16 |
Referenced by handle_cli_core_show_translation().
| int __ast_register_translator | ( | struct ast_translator * | t, | |
| struct ast_module * | mod | |||
| ) |
register codec translator
Register a translator This registers a codec translator with asterisk.
Definition at line 608 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_verb, ast_translator::buf_size, ast_translator::buffer_samples, calc_cost(), 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, ast_translator::plc_samples, powerof(), rebuild_matrix(), ast_translator::srcfmt, and term_color().
00609 { 00610 static int added_cli = 0; 00611 struct ast_translator *u; 00612 char tmp[80]; 00613 00614 if (!mod) { 00615 ast_log(LOG_WARNING, "Missing module pointer, you need to supply one\n"); 00616 return -1; 00617 } 00618 00619 if (!t->buf_size) { 00620 ast_log(LOG_WARNING, "empty buf size, you need to supply one\n"); 00621 return -1; 00622 } 00623 00624 t->module = mod; 00625 00626 t->srcfmt = powerof(t->srcfmt); 00627 t->dstfmt = powerof(t->dstfmt); 00628 t->active = 1; 00629 00630 if (t->srcfmt == -1 || t->dstfmt == -1) { 00631 ast_log(LOG_WARNING, "Invalid translator path: (%s codec is not valid)\n", t->srcfmt == -1 ? "starting" : "ending"); 00632 return -1; 00633 } 00634 if (t->plc_samples) { 00635 if (t->buffer_samples < t->plc_samples) { 00636 ast_log(LOG_WARNING, "plc_samples %d buffer_samples %d\n", 00637 t->plc_samples, t->buffer_samples); 00638 return -1; 00639 } 00640 if (t->dstfmt != powerof(AST_FORMAT_SLINEAR)) 00641 ast_log(LOG_WARNING, "plc_samples %d format %x\n", 00642 t->plc_samples, t->dstfmt); 00643 } 00644 if (t->srcfmt >= MAX_FORMAT) { 00645 ast_log(LOG_WARNING, "Source format %s is larger than MAX_FORMAT\n", ast_getformatname(t->srcfmt)); 00646 return -1; 00647 } 00648 00649 if (t->dstfmt >= MAX_FORMAT) { 00650 ast_log(LOG_WARNING, "Destination format %s is larger than MAX_FORMAT\n", ast_getformatname(t->dstfmt)); 00651 return -1; 00652 } 00653 00654 if (t->buf_size) { 00655 /* 00656 * Align buf_size properly, rounding up to the machine-specific 00657 * alignment for pointers. 00658 */ 00659 struct _test_align { void *a, *b; } p; 00660 int align = (char *)&p.b - (char *)&p.a; 00661 00662 t->buf_size = ((t->buf_size + align - 1) / align) * align; 00663 } 00664 00665 if (t->frameout == NULL) 00666 t->frameout = default_frameout; 00667 00668 calc_cost(t, 1); 00669 00670 ast_verb(2, "Registered translator '%s' from format %s to %s, cost %d\n", 00671 term_color(tmp, t->name, COLOR_MAGENTA, COLOR_BLACK, sizeof(tmp)), 00672 ast_getformatname(1 << t->srcfmt), ast_getformatname(1 << t->dstfmt), t->cost); 00673 00674 if (!added_cli) { 00675 ast_cli_register_multiple(cli_translate, sizeof(cli_translate) / sizeof(struct ast_cli_entry)); 00676 added_cli++; 00677 } 00678 00679 AST_RWLIST_WRLOCK(&translators); 00680 00681 /* find any existing translators that provide this same srcfmt/dstfmt, 00682 and put this one in order based on cost */ 00683 AST_RWLIST_TRAVERSE_SAFE_BEGIN(&translators, u, list) { 00684 if ((u->srcfmt == t->srcfmt) && 00685 (u->dstfmt == t->dstfmt) && 00686 (u->cost > t->cost)) { 00687 AST_RWLIST_INSERT_BEFORE_CURRENT(t, list); 00688 t = NULL; 00689 } 00690 } 00691 AST_RWLIST_TRAVERSE_SAFE_END; 00692 00693 /* if no existing translator was found for this format combination, 00694 add it to the beginning of the list */ 00695 if (t) 00696 AST_RWLIST_INSERT_HEAD(&translators, t, list); 00697 00698 rebuild_matrix(0); 00699 00700 AST_RWLIST_UNLOCK(&translators); 00701 00702 return 0; 00703 }
| static AST_RWLIST_HEAD_STATIC | ( | translators | , | |
| ast_translator | ||||
| ) | [static] |
the list of translators
| struct ast_frame* ast_trans_frameout | ( | struct ast_trans_pvt * | pvt, | |
| int | datalen, | |||
| int | samples | |||
| ) | [read] |
generic frameout routine. If samples and datalen are 0, take whatever is in pvt and reset them, otherwise take the values in the caller and leave alone the pvt values.
generic frameout function
Definition at line 203 of file translate.c.
References AST_FRAME_VOICE, AST_FRIENDLY_OFFSET, ast_frisolate(), ast_trans_pvt::c, ast_frame::data, ast_trans_pvt::datalen, ast_frame::datalen, ast_translator::dstfmt, ast_trans_pvt::f, f, ast_frame::frametype, ast_frame::mallocd, ast_translator::name, ast_frame::offset, ast_trans_pvt::outbuf, ast_frame::ptr, ast_trans_pvt::samples, ast_frame::samples, ast_frame::src, ast_frame::subclass, and ast_trans_pvt::t.
Referenced by default_frameout(), lintoadpcm_frameout(), lintogsm_frameout(), lintoilbc_frameout(), lintolpc10_frameout(), and lintospeex_frameout().
00205 { 00206 struct ast_frame *f = &pvt->f; 00207 00208 if (samples) 00209 f->samples = samples; 00210 else { 00211 if (pvt->samples == 0) 00212 return NULL; 00213 f->samples = pvt->samples; 00214 pvt->samples = 0; 00215 } 00216 if (datalen) 00217 f->datalen = datalen; 00218 else { 00219 f->datalen = pvt->datalen; 00220 pvt->datalen = 0; 00221 } 00222 00223 f->frametype = AST_FRAME_VOICE; 00224 f->subclass = 1 << (pvt->t->dstfmt); 00225 f->mallocd = 0; 00226 f->offset = AST_FRIENDLY_OFFSET; 00227 f->src = pvt->t->name; 00228 f->data.ptr = pvt->outbuf.c; 00229 00230 return ast_frisolate(f); 00231 }
| struct ast_frame* ast_translate | ( | struct ast_trans_pvt * | path, | |
| struct ast_frame * | f, | |||
| int | consume | |||
| ) | [read] |
do the actual translation
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 295 of file translate.c.
References ast_format_rate(), AST_FRAME_CNG, AST_FRFLAG_HAS_TIMING_INFO, ast_frfree, ast_samp2tv(), ast_set2_flag, ast_test_flag, ast_tv(), ast_tvadd(), ast_tveq(), ast_tvnow(), ast_tvsub(), ast_tvzero(), ast_frame::delivery, framein(), ast_frame::frametype, ast_frame::len, len(), ast_trans_pvt::next, ast_trans_pvt::nextin, ast_trans_pvt::nextout, ast_frame::samples, ast_frame::seqno, ast_frame::subclass, and ast_frame::ts.
Referenced by __ast_read(), ast_audiohook_read_frame(), ast_slinfactory_feed(), ast_write(), ast_writestream(), audio_audiohook_write_list(), and conf_run().
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 = ast_test_flag(f, AST_FRFLAG_HAS_TIMING_INFO); 00306 ts = f->ts; 00307 len = f->len; 00308 seqno = f->seqno; 00309 00310 /* XXX hmmm... check this below */ 00311 if (!ast_tvzero(f->delivery)) { 00312 if (!ast_tvzero(path->nextin)) { 00313 /* Make sure this is in line with what we were expecting */ 00314 if (!ast_tveq(path->nextin, f->delivery)) { 00315 /* The time has changed between what we expected and this 00316 most recent time on the new packet. If we have a 00317 valid prediction adjust our output time appropriately */ 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 /* This is our first pass. Make sure the timing looks good */ 00326 path->nextin = f->delivery; 00327 path->nextout = f->delivery; 00328 } 00329 /* Predict next incoming sample */ 00330 path->nextin = ast_tvadd(path->nextin, ast_samp2tv(f->samples, ast_format_rate(f->subclass))); 00331 } 00332 delivery = f->delivery; 00333 for ( ; out && p ; p = p->next) { 00334 framein(p, out); 00335 if (out != f) 00336 ast_frfree(out); 00337 out = p->t->frameout(p); 00338 } 00339 if (consume) 00340 ast_frfree(f); 00341 if (out == NULL) 00342 return NULL; 00343 /* we have a frame, play with times */ 00344 if (!ast_tvzero(delivery)) { 00345 /* Regenerate prediction after a discontinuity */ 00346 if (ast_tvzero(path->nextout)) 00347 path->nextout = ast_tvnow(); 00348 00349 /* Use next predicted outgoing timestamp */ 00350 out->delivery = path->nextout; 00351 00352 /* Predict next outgoing timestamp from samples in this 00353 frame. */ 00354 path->nextout = ast_tvadd(path->nextout, ast_samp2tv(out->samples, ast_format_rate(out->subclass))); 00355 } else { 00356 out->delivery = ast_tv(0, 0); 00357 ast_set2_flag(out, has_timing_info, AST_FRFLAG_HAS_TIMING_INFO); 00358 if (has_timing_info) { 00359 out->ts = ts; 00360 out->len = len; 00361 out->seqno = seqno; 00362 } 00363 } 00364 /* Invalidate prediction if we're entering a silence period */ 00365 if (out->frametype == AST_FRAME_CNG) 00366 path->nextout = ast_tv(0, 0); 00367 return out; 00368 }
| unsigned int ast_translate_available_formats | ( | unsigned int | dest, | |
| unsigned int | src | |||
| ) |
Mask off unavailable formats from a format bitmask.
| dest | possible destination formats | |
| src | source formats |
The result will include all formats from 'dest' that are either present in 'src' or translatable from a format present in 'src'.
Definition at line 817 of file translate.c.
References AST_FORMAT_AUDIO_MASK, AST_FORMAT_VIDEO_MASK, AST_RWLIST_RDLOCK, AST_RWLIST_UNLOCK, powerof(), translator_path::step, and tr_matrix.
Referenced by sip_call().
00818 { 00819 unsigned int res = dest; 00820 unsigned int x; 00821 unsigned int src_audio = src & AST_FORMAT_AUDIO_MASK; 00822 unsigned int src_video = src & AST_FORMAT_VIDEO_MASK; 00823 00824 /* if we don't have a source format, we just have to try all 00825 possible destination formats */ 00826 if (!src) 00827 return dest; 00828 00829 /* If we have a source audio format, get its format index */ 00830 if (src_audio) 00831 src_audio = powerof(src_audio); 00832 00833 /* If we have a source video format, get its format index */ 00834 if (src_video) 00835 src_video = powerof(src_video); 00836 00837 AST_RWLIST_RDLOCK(&translators); 00838 00839 /* For a given source audio format, traverse the list of 00840 known audio formats to determine whether there exists 00841 a translation path from the source format to the 00842 destination format. */ 00843 for (x = 1; src_audio && (x & AST_FORMAT_AUDIO_MASK); x <<= 1) { 00844 /* if this is not a desired format, nothing to do */ 00845 if (!(dest & x)) 00846 continue; 00847 00848 /* if the source is supplying this format, then 00849 we can leave it in the result */ 00850 if (src & x) 00851 continue; 00852 00853 /* if we don't have a translation path from the src 00854 to this format, remove it from the result */ 00855 if (!tr_matrix[src_audio][powerof(x)].step) { 00856 res &= ~x; 00857 continue; 00858 } 00859 00860 /* now check the opposite direction */ 00861 if (!tr_matrix[powerof(x)][src_audio].step) 00862 res &= ~x; 00863 } 00864 00865 /* For a given source video format, traverse the list of 00866 known video formats to determine whether there exists 00867 a translation path from the source format to the 00868 destination format. */ 00869 for (; src_video && (x & AST_FORMAT_VIDEO_MASK); x <<= 1) { 00870 /* if this is not a desired format, nothing to do */ 00871 if (!(dest & x)) 00872 continue; 00873 00874 /* if the source is supplying this format, then 00875 we can leave it in the result */ 00876 if (src & x) 00877 continue; 00878 00879 /* if we don't have a translation path from the src 00880 to this format, remove it from the result */ 00881 if (!tr_matrix[src_video][powerof(x)].step) { 00882 res &= ~x; 00883 continue; 00884 } 00885 00886 /* now check the opposite direction */ 00887 if (!tr_matrix[powerof(x)][src_video].step) 00888 res &= ~x; 00889 } 00890 00891 AST_RWLIST_UNLOCK(&translators); 00892 00893 return res; 00894 }
| unsigned int ast_translate_path_steps | ( | unsigned int | dest, | |
| unsigned int | src | |||
| ) |
Returns the number of steps required to convert from 'src' to 'dest'.
| dest | destination format | |
| src | source format |
Definition at line 795 of file translate.c.
References ast_log(), AST_RWLIST_RDLOCK, AST_RWLIST_UNLOCK, LOG_WARNING, translator_path::multistep, powerof(), and tr_matrix.
Referenced by ast_channel_make_compatible_helper().
00796 { 00797 unsigned int res = -1; 00798 00799 /* convert bitwise format numbers into array indices */ 00800 src = powerof(src); 00801 dest = powerof(dest); 00802 00803 if (src == -1 || dest == -1) { 00804 ast_log(LOG_WARNING, "No translator path: (%s codec is not valid)\n", src == -1 ? "starting" : "ending"); 00805 return -1; 00806 } 00807 AST_RWLIST_RDLOCK(&translators); 00808 00809 if (tr_matrix[src][dest].step) 00810 res = tr_matrix[src][dest].multistep + 1; 00811 00812 AST_RWLIST_UNLOCK(&translators); 00813 00814 return res; 00815 }
| void ast_translator_activate | ( | struct ast_translator * | t | ) |
Activate a previously deactivated translator.
| t | translator to activate |
Enables the specified translator for use.
Definition at line 731 of file translate.c.
References ast_translator::active, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, and rebuild_matrix().
00732 { 00733 AST_RWLIST_WRLOCK(&translators); 00734 t->active = 1; 00735 rebuild_matrix(0); 00736 AST_RWLIST_UNLOCK(&translators); 00737 }
| int ast_translator_best_choice | ( | int * | dst, | |
| int * | srcs | |||
| ) |
Calculate our best translator source format, given costs, and a desired destination.
Chooses the best translation path.
Definition at line 748 of file translate.c.
References AST_FORMAT_AUDIO_MASK, AST_RWLIST_RDLOCK, AST_RWLIST_UNLOCK, translator_path::cost, ast_translator::cost, MAX_AUDIO_FORMAT, translator_path::multistep, and tr_matrix.
Referenced by ast_channel_make_compatible_helper(), ast_request(), iax2_request(), and set_format().
00749 { 00750 int x,y; 00751 int best = -1; 00752 int bestdst = 0; 00753 int cur, cursrc; 00754 int besttime = INT_MAX; 00755 int beststeps = INT_MAX; 00756 int common = ((*dst) & (*srcs)) & AST_FORMAT_AUDIO_MASK; /* are there common formats ? */ 00757 00758 if (common) { /* yes, pick one and return */ 00759 for (cur = 1, y = 0; y <= MAX_AUDIO_FORMAT; cur <<= 1, y++) { 00760 if (cur & common) /* guaranteed to find one */ 00761 break; 00762 } 00763 /* We are done, this is a common format to both. */ 00764 *srcs = *dst = cur; 00765 return 0; 00766 } else { /* No, we will need to translate */ 00767 AST_RWLIST_RDLOCK(&translators); 00768 for (cur = 1, y = 0; y <= MAX_AUDIO_FORMAT; cur <<= 1, y++) { 00769 if (! (cur & *dst)) 00770 continue; 00771 for (cursrc = 1, x = 0; x <= MAX_AUDIO_FORMAT; cursrc <<= 1, x++) { 00772 if (!(*srcs & cursrc) || !tr_matrix[x][y].step || 00773 tr_matrix[x][y].cost > besttime) 00774 continue; /* not existing or no better */ 00775 if (tr_matrix[x][y].cost < besttime || 00776 tr_matrix[x][y].multistep < beststeps) { 00777 /* better than what we have so far */ 00778 best = cursrc; 00779 bestdst = cur; 00780 besttime = tr_matrix[x][y].cost; 00781 beststeps = tr_matrix[x][y].multistep; 00782 } 00783 } 00784 } 00785 AST_RWLIST_UNLOCK(&translators); 00786 if (best > -1) { 00787 *srcs = best; 00788 *dst = bestdst; 00789 best = 0; 00790 } 00791 return best; 00792 } 00793 }
| struct ast_trans_pvt* ast_translator_build_path | ( | int | dest, | |
| int | source | |||
| ) | [read] |
Build a chain of translators based upon the given source and dest formats.
Builds a translator path Build a path (possibly NULL) from source to dest.
Definition at line 250 of file translate.c.
References ast_getformatname(), ast_log(), AST_RWLIST_RDLOCK, AST_RWLIST_UNLOCK, ast_translator_free_path(), ast_tv(), 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_audiohook_read_frame(), ast_slinfactory_feed(), ast_writestream(), audio_audiohook_write_list(), conf_run(), and set_format().
00251 { 00252 struct ast_trans_pvt *head = NULL, *tail = NULL; 00253 00254 source = powerof(source); 00255 dest = powerof(dest); 00256 00257 if (source == -1 || dest == -1) { 00258 ast_log(LOG_WARNING, "No translator path: (%s codec is not valid)\n", source == -1 ? "starting" : "ending"); 00259 return NULL; 00260 } 00261 00262 AST_RWLIST_RDLOCK(&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_RWLIST_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_RWLIST_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 /* Keep going if this isn't the final destination */ 00287 source = cur->t->dstfmt; 00288 } 00289 00290 AST_RWLIST_UNLOCK(&translators); 00291 return head; 00292 }
| void ast_translator_deactivate | ( | struct ast_translator * | t | ) |
Deactivate a translator.
| t | translator to deactivate |
Disables the specified translator from being used.
Definition at line 739 of file translate.c.
References ast_translator::active, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, and rebuild_matrix().
00740 { 00741 AST_RWLIST_WRLOCK(&translators); 00742 t->active = 0; 00743 rebuild_matrix(0); 00744 AST_RWLIST_UNLOCK(&translators); 00745 }
| void ast_translator_free_path | ( | struct ast_trans_pvt * | tr | ) |
Frees a translator path Frees the given translator path structure.
| tr | translator path to get rid of |
Definition at line 240 of file translate.c.
References destroy(), and ast_trans_pvt::next.
Referenced by ast_audiohook_destroy(), ast_audiohook_detach_list(), ast_audiohook_read_frame(), ast_channel_free(), ast_slinfactory_destroy(), ast_slinfactory_feed(), ast_slinfactory_flush(), ast_translator_build_path(), ast_writestream(), audio_audiohook_write_list(), conf_free(), filestream_destructor(), free_translation(), and set_format().
00241 { 00242 struct ast_trans_pvt *pn = p; 00243 while ( (p = pn) ) { 00244 pn = p->next; 00245 destroy(p); 00246 } 00247 }
| int ast_unregister_translator | ( | struct ast_translator * | t | ) |
unregister codec translator
Unregister a translator Unregisters the given tranlator.
Definition at line 706 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_verb, COLOR_BLACK, COLOR_MAGENTA, ast_translator::dstfmt, ast_translator::list, ast_translator::name, rebuild_matrix(), ast_translator::srcfmt, and term_color().
Referenced by drop_translator(), load_module(), unload_module(), and unregister_translators().
00707 { 00708 char tmp[80]; 00709 struct ast_translator *u; 00710 int found = 0; 00711 00712 AST_RWLIST_WRLOCK(&translators); 00713 AST_RWLIST_TRAVERSE_SAFE_BEGIN(&translators, u, list) { 00714 if (u == t) { 00715 AST_RWLIST_REMOVE_CURRENT(list); 00716 ast_verb(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)); 00717 found = 1; 00718 break; 00719 } 00720 } 00721 AST_RWLIST_TRAVERSE_SAFE_END; 00722 00723 if (found) 00724 rebuild_matrix(0); 00725 00726 AST_RWLIST_UNLOCK(&translators); 00727 00728 return (u ? 0 : -1); 00729 }
| static void calc_cost | ( | struct ast_translator * | t, | |
| int | seconds | |||
| ) | [static] |
compute the cost of a single translation step
Definition at line 371 of file translate.c.
References ast_format_rate(), ast_frfree, ast_log(), ast_translator::cost, destroy(), ast_translator::dstfmt, f, 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().
00372 { 00373 int num_samples = 0; 00374 struct ast_trans_pvt *pvt; 00375 struct rusage start; 00376 struct rusage end; 00377 int cost; 00378 int out_rate = ast_format_rate(t->dstfmt); 00379 00380 if (!seconds) 00381 seconds = 1; 00382 00383 /* If they don't make samples, give them a terrible score */ 00384 if (!t->sample) { 00385 ast_log(LOG_WARNING, "Translator '%s' does not produce sample frames.\n", t->name); 00386 t->cost = 999999; 00387 return; 00388 } 00389 00390 pvt = newpvt(t); 00391 if (!pvt) { 00392 ast_log(LOG_WARNING, "Translator '%s' appears to be broken and will probably fail.\n", t->name); 00393 t->cost = 999999; 00394 return; 00395 } 00396 00397 getrusage(RUSAGE_SELF, &start); 00398 00399 /* Call the encoder until we've processed the required number of samples */ 00400 while (num_samples < seconds * out_rate) { 00401 struct ast_frame *f = t->sample(); 00402 if (!f) { 00403 ast_log(LOG_WARNING, "Translator '%s' failed to produce a sample frame.\n", t->name); 00404 destroy(pvt); 00405 t->cost = 999999; 00406 return; 00407 } 00408 framein(pvt, f); 00409 ast_frfree(f); 00410 while ((f = t->frameout(pvt))) { 00411 num_samples += f->samples; 00412 ast_frfree(f); 00413 } 00414 } 00415 00416 getrusage(RUSAGE_SELF, &end); 00417 00418 cost = ((end.ru_utime.tv_sec - start.ru_utime.tv_sec) * 1000000) + end.ru_utime.tv_usec - start.ru_utime.tv_usec; 00419 cost += ((end.ru_stime.tv_sec - start.ru_stime.tv_sec) * 1000000) + end.ru_stime.tv_usec - start.ru_stime.tv_usec; 00420 00421 destroy(pvt); 00422 00423 t->cost = cost / seconds; 00424 00425 if (!t->cost) 00426 t->cost = 1; 00427 }
| static struct ast_frame* default_frameout | ( | struct ast_trans_pvt * | pvt | ) | [static, read] |
Definition at line 233 of file translate.c.
References ast_trans_frameout().
Referenced by __ast_register_translator().
00234 { 00235 return ast_trans_frameout(pvt, 0, 0); 00236 }
| static void destroy | ( | struct ast_trans_pvt * | pvt | ) | [static] |
Definition at line 133 of file translate.c.
References ast_free, ast_module_unref(), ast_translator::destroy, ast_translator::module, and ast_trans_pvt::t.
Referenced by ast_translator_free_path(), and calc_cost().
00134 { 00135 struct ast_translator *t = pvt->t; 00136 00137 if (t->destroy) 00138 t->destroy(pvt); 00139 ast_free(pvt); 00140 ast_module_unref(t->module); 00141 }
| static int framein | ( | struct ast_trans_pvt * | pvt, | |
| struct ast_frame * | f | |||
| ) | [static] |
framein wrapper, deals with plc and bound checks.
Definition at line 144 of file translate.c.
References ast_copy_flags, AST_FRFLAG_HAS_TIMING_INFO, ast_log(), ast_translator::buffer_samples, ast_trans_pvt::datalen, ast_frame::datalen, ast_trans_pvt::f, ast_translator::framein, ast_trans_pvt::i16, ast_frame::len, LOG_WARNING, ast_translator::name, ast_translator::native_plc, 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().
00145 { 00146 int16_t *dst = pvt->outbuf.i16; 00147 int ret; 00148 int samples = pvt->samples; /* initial value */ 00149 00150 /* Copy the last in jb timing info to the pvt */ 00151 ast_copy_flags(&pvt->f, f, AST_FRFLAG_HAS_TIMING_INFO); 00152 pvt->f.ts = f->ts; 00153 pvt->f.len = f->len; 00154 pvt->f.seqno = f->seqno; 00155 00156 if (f->samples == 0) { 00157 ast_log(LOG_WARNING, "no samples for %s\n", pvt->t->name); 00158 } 00159 if (pvt->t->buffer_samples) { /* do not pass empty frames to callback */ 00160 if (f->datalen == 0) { /* perform PLC with nominal framesize of 20ms/160 samples */ 00161 if (pvt->plc) { 00162 int l = pvt->t->plc_samples; 00163 if (pvt->samples + l > pvt->t->buffer_samples) { 00164 ast_log(LOG_WARNING, "Out of buffer space\n"); 00165 return -1; 00166 } 00167 l = plc_fillin(pvt->plc, dst + pvt->samples, l); 00168 pvt->samples += l; 00169 pvt->datalen = pvt->samples * 2; /* SLIN has 2bytes for 1sample */ 00170 } 00171 /* We don't want generic PLC. If the codec has native PLC, then do that */ 00172 if (!pvt->t->native_plc) 00173 return 0; 00174 } 00175 if (pvt->samples + f->samples > pvt->t->buffer_samples) { 00176 ast_log(LOG_WARNING, "Out of buffer space\n"); 00177 return -1; 00178 } 00179 } 00180 /* we require a framein routine, wouldn't know how to do 00181 * it otherwise. 00182 */ 00183 ret = pvt->t->framein(pvt, f); 00184 /* possibly store data for plc */ 00185 if (!ret && pvt->plc) { 00186 int l = pvt->t->plc_samples; 00187 if (pvt->samples < l) 00188 l = pvt->samples; 00189 plc_rx(pvt->plc, dst + pvt->samples - l, l); 00190 } 00191 /* diagnostic ... */ 00192 if (pvt->samples == samples) 00193 ast_log(LOG_WARNING, "%s did not update samples %d\n", 00194 pvt->t->name, pvt->samples); 00195 return ret; 00196 }
| static char* handle_cli_core_show_translation | ( | struct ast_cli_entry * | e, | |
| int | cmd, | |||
| struct ast_cli_args * | a | |||
| ) | [static] |
Definition at line 505 of file translate.c.
References ast_cli_args::argc, ast_cli_args::argv, ast_cli(), ast_getformatname(), AST_RWLIST_RDLOCK, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, ast_str_alloca, ast_str_append(), ast_str_buffer, ast_str_set(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_translator::cost, ast_cli_args::fd, MAX_RECALC, rebuild_matrix(), SHOW_TRANS, tr_matrix, and ast_cli_entry::usage.
00506 { 00507 #define SHOW_TRANS 16 00508 int x, y, z; 00509 int curlen = 0, longest = 0, magnitude[SHOW_TRANS] = { 0, }; 00510 00511 switch (cmd) { 00512 case CLI_INIT: 00513 e->command = "core show translation [recalc]"; 00514 e->usage = 00515 "Usage: core show translation [recalc [<recalc seconds>]]\n" 00516 " Displays known codec translators and the cost associated\n" 00517 " with each conversion. If the argument 'recalc' is supplied along\n" 00518 " with optional number of seconds to test a new test will be performed\n" 00519 " as the chart is being displayed.\n"; 00520 return NULL; 00521 case CLI_GENERATE: 00522 return NULL; 00523 } 00524 00525 if (a->argc > 5) 00526 return CLI_SHOWUSAGE; 00527 00528 if (a->argv[3] && !strcasecmp(a->argv[3], "recalc")) { 00529 z = a->argv[4] ? atoi(a->argv[4]) : 1; 00530 00531 if (z <= 0) { 00532 ast_cli(a->fd, " Recalc must be greater than 0. Defaulting to 1.\n"); 00533 z = 1; 00534 } 00535 00536 if (z > MAX_RECALC) { 00537 ast_cli(a->fd, " Maximum limit of recalc exceeded by %d, truncating value to %d\n", z - MAX_RECALC, MAX_RECALC); 00538 z = MAX_RECALC; 00539 } 00540 ast_cli(a->fd, " Recalculating Codec Translation (number of sample seconds: %d)\n\n", z); 00541 AST_RWLIST_WRLOCK(&translators); 00542 rebuild_matrix(z); 00543 AST_RWLIST_UNLOCK(&translators); 00544 } else if (a->argc > 3) 00545 return CLI_SHOWUSAGE; 00546 00547 AST_RWLIST_RDLOCK(&translators); 00548 00549 ast_cli(a->fd, " Translation times between formats (in microseconds) for one second of data\n"); 00550 ast_cli(a->fd, " Source Format (Rows) Destination Format (Columns)\n\n"); 00551 /* Get the length of the longest (usable?) codec name, so we know how wide the left side should be */ 00552 for (x = 0; x < SHOW_TRANS; x++) { 00553 curlen = strlen(ast_getformatname(1 << (x))); 00554 if (curlen > longest) 00555 longest = curlen; 00556 for (y = 0; y < SHOW_TRANS; y++) { 00557 if (tr_matrix[x][y].cost > pow(10, magnitude[x])) { 00558 magnitude[y] = floor(log10(tr_matrix[x][y].cost)); 00559 } 00560 } 00561 } 00562 for (x = -1; x < SHOW_TRANS; x++) { 00563 struct ast_str *out = ast_str_alloca(125); 00564 /*Go ahead and move to next iteration if dealing with an unknown codec*/ 00565 if(x >= 0 && !strcmp(ast_getformatname(1 << (x)), "unknown")) 00566 continue; 00567 ast_str_set(&out, -1, " "); 00568 for (y = -1; y < SHOW_TRANS; y++) { 00569 /*Go ahead and move to next iteration if dealing with an unknown codec*/ 00570 if (y >= 0 && !strcmp(ast_getformatname(1 << (y)), "unknown")) 00571 continue; 00572 if (y >= 0) 00573 curlen = strlen(ast_getformatname(1 << (y))); 00574 if (y >= 0 && magnitude[y] + 1 > curlen) { 00575 curlen = magnitude[y] + 1; 00576 } 00577 if (curlen < 5) 00578 curlen = 5; 00579 if (x >= 0 && y >= 0 && tr_matrix[x][y].step) { 00580 /* Actual codec output */ 00581 ast_str_append(&out, -1, "%*d", curlen + 1, tr_matrix[x][y].cost); 00582 } else if (x == -1 && y >= 0) { 00583 /* Top row - use a dynamic size */ 00584 ast_str_append(&out, -1, "%*s", curlen + 1, ast_getformatname(1 << (y)) ); 00585 } else if (y == -1 && x >= 0) { 00586 /* Left column - use a static size. */ 00587 ast_str_append(&out, -1, "%*s", longest, ast_getformatname(1 << (x)) ); 00588 } else if (x >= 0 && y >= 0) { 00589 /* Codec not supported */ 00590 ast_str_append(&out, -1, "%*s", curlen + 1, "-"); 00591 } else { 00592 /* Upper left hand corner */ 00593 ast_str_append(&out, -1, "%*s", longest, ""); 00594 } 00595 } 00596 ast_str_append(&out, -1, "\n"); 00597 ast_cli(a->fd, "%s", ast_str_buffer(out)); 00598 } 00599 AST_RWLIST_UNLOCK(&translators); 00600 return CLI_SUCCESS; 00601 }
| static void* newpvt | ( | struct ast_translator * | t | ) | [static] |
Allocate the descriptor, required outbuf space, and possibly also plc and desc.
Definition at line 93 of file translate.c.
References ast_calloc, ast_free, AST_FRIENDLY_OFFSET, ast_module_ref(), ast_translator::buf_size, ast_trans_pvt::c, ast_translator::desc_size, len(), ast_translator::module, ast_translator::newpvt, ast_trans_pvt::outbuf, ast_trans_pvt::plc, 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().
00094 { 00095 struct ast_trans_pvt *pvt; 00096 int len; 00097 int useplc = t->plc_samples > 0 && t->useplc; /* cache, because it can change on the fly */ 00098 char *ofs; 00099 00100 /* 00101 * compute the required size adding private descriptor, 00102 * plc, buffer, AST_FRIENDLY_OFFSET. 00103 */ 00104 len = sizeof(*pvt) + t->desc_size; 00105 if (useplc) 00106 len += sizeof(plc_state_t); 00107 if (t->buf_size) 00108 len += AST_FRIENDLY_OFFSET + t->buf_size; 00109 pvt = ast_calloc(1, len); 00110 if (!pvt) 00111 return NULL; 00112 pvt->t = t; 00113 ofs = (char *)(pvt + 1); /* pointer to data space */ 00114 if (t->desc_size) { /* first comes the descriptor */ 00115 pvt->pvt = ofs; 00116 ofs += t->desc_size; 00117 } 00118 if (useplc) { /* then plc state */ 00119 pvt->plc = (plc_state_t *)ofs; 00120 ofs += sizeof(plc_state_t); 00121 } 00122 if (t->buf_size) /* finally buffer and header */ 00123 pvt->outbuf.c = ofs + AST_FRIENDLY_OFFSET; 00124 /* call local init routine, if present */ 00125 if (t->newpvt && t->newpvt(pvt)) { 00126 ast_free(pvt); 00127 return NULL; 00128 } 00129 ast_module_ref(t->module); 00130 return pvt; 00131 }
| static force_inline int powerof | ( | unsigned int | d | ) | [static] |
returns the index of the lowest bit set
Definition at line 73 of file translate.c.
References ast_log(), and LOG_WARNING.
Referenced by __ast_register_translator(), ast_translate_available_formats(), ast_translate_path_steps(), and ast_translator_build_path().
00074 { 00075 int x = ffs(d); 00076 00077 if (x) 00078 return x - 1; 00079 00080 ast_log(LOG_WARNING, "No bits set? %d\n", d); 00081 00082 return -1; 00083 }
| static void rebuild_matrix | ( | int | samples | ) | [static] |
rebuild a translation matrix.
Definition at line 433 of file translate.c.
References ast_translator::active, ast_debug, ast_getformatname(), AST_RWLIST_TRAVERSE, calc_cost(), translator_path::cost, ast_translator::cost, ast_translator::dstfmt, ast_translator::list, MAX_FORMAT, translator_path::multistep, ast_translator::srcfmt, translator_path::step, and tr_matrix.
Referenced by __ast_register_translator(), ast_translator_activate(), ast_translator_deactivate(), ast_unregister_translator(), and handle_cli_core_show_translation().
00434 { 00435 struct ast_translator *t; 00436 int x; /* source format index */ 00437 int y; /* intermediate format index */ 00438 int z; /* destination format index */ 00439 00440 ast_debug(1, "Resetting translation matrix\n"); 00441 00442 memset(tr_matrix, '\0', sizeof(tr_matrix)); 00443 00444 /* first, compute all direct costs */ 00445 AST_RWLIST_TRAVERSE(&translators, t, list) { 00446 if (!t->active) 00447 continue; 00448 00449 x = t->srcfmt; 00450 z = t->dstfmt; 00451 00452 if (samples) 00453 calc_cost(t, samples); 00454 00455 if (!tr_matrix[x][z].step || t->cost < tr_matrix[x][z].cost) { 00456 tr_matrix[x][z].step = t; 00457 tr_matrix[x][z].cost = t->cost; 00458 } 00459 } 00460 00461 /* 00462 * For each triple x, y, z of distinct formats, check if there is 00463 * a path from x to z through y which is cheaper than what is 00464 * currently known, and in case, update the matrix. 00465 * Repeat until the matrix is stable. 00466 */ 00467 for (;;) { 00468 int changed = 0; 00469 for (x = 0; x < MAX_FORMAT; x++) { /* source format */ 00470 for (y = 0; y < MAX_FORMAT; y++) { /* intermediate format */ 00471 if (x == y) /* skip ourselves */ 00472 continue; 00473 00474 for (z = 0; z<MAX_FORMAT; z++) { /* dst format */ 00475 int newcost; 00476 00477 if (z == x || z == y) /* skip null conversions */ 00478 continue; 00479 if (!tr_matrix[x][y].step) /* no path from x to y */ 00480 continue; 00481 if (!tr_matrix[y][z].step) /* no path from y to z */ 00482 continue; 00483 newcost = tr_matrix[x][y].cost + tr_matrix[y][z].cost; 00484 if (tr_matrix[x][z].step && newcost >= tr_matrix[x][z].cost) 00485 continue; /* x->y->z is more expensive than 00486 * the existing path */ 00487 /* ok, we can get from x to z via y with a cost that 00488 is the sum of the transition from x to y and 00489 from y to z */ 00490 00491 tr_matrix[x][z].step = tr_matrix[x][y].step; 00492 tr_matrix[x][z].cost = newcost; 00493 tr_matrix[x][z].multistep = 1; 00494 ast_debug(3, "Discovered %d cost path from %s to %s, via %s\n", tr_matrix[x][z].cost, 00495 ast_getformatname(1 << x), ast_getformatname(1 << z), ast_getformatname(1 << y)); 00496 changed++; 00497 } 00498 } 00499 } 00500 if (!changed) 00501 break; 00502 } 00503 }
struct ast_cli_entry cli_translate[] [static] |
{
}
Definition at line 603 of file translate.c.
struct translator_path tr_matrix[MAX_FORMAT][MAX_FORMAT] [static] |
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 64 of file translate.c.
Referenced by ast_translate_available_formats(), ast_translate_path_steps(), ast_translator_best_choice(), ast_translator_build_path(), handle_cli_core_show_translation(), and rebuild_matrix().
1.6.1