Translate via the use of pseudo channels. More...
#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"
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 codec translator | |
static | AST_LIST_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 bound checks. | |
static void * | newpvt (struct ast_translator *t) |
Allocate the descriptor, required outbuf space, and possibly 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[]) |
static int | show_translation_deprecated (int fd, int argc, char *argv[]) |
CLI "show translation" command handler. | |
Variables | |
static struct ast_cli_entry | cli_show_translation_deprecated |
static struct ast_cli_entry | cli_translate [] |
static 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. |
Translate via the use of pseudo channels.
Definition in file translate.c.
#define MAX_RECALC 200 |
Definition at line 49 of file translate.c.
Referenced by show_translation(), and show_translation_deprecated().
#define SHOW_TRANS 13 |
Referenced by show_translation(), and show_translation_deprecated().
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 643 of file translate.c.
References ast_translator::active, ast_cli_register_multiple(), ast_getformatname(), AST_LIST_INSERT_BEFORE_CURRENT, AST_LIST_INSERT_HEAD, AST_LIST_LOCK, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, AST_LIST_UNLOCK, ast_log(), ast_verbose(), ast_translator::buf_size, 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, option_verbose, powerof(), rebuild_matrix(), ast_translator::srcfmt, term_color(), and VERBOSE_PREFIX_2.
00644 { 00645 static int added_cli = 0; 00646 struct ast_translator *u; 00647 00648 if (!mod) { 00649 ast_log(LOG_WARNING, "Missing module pointer, you need to supply one\n"); 00650 return -1; 00651 } 00652 00653 if (!t->buf_size) { 00654 ast_log(LOG_WARNING, "empty buf size, you need to supply one\n"); 00655 return -1; 00656 } 00657 00658 t->module = mod; 00659 00660 t->srcfmt = powerof(t->srcfmt); 00661 t->dstfmt = powerof(t->dstfmt); 00662 t->active = 1; 00663 00664 if (t->srcfmt == -1 || t->dstfmt == -1) { 00665 ast_log(LOG_WARNING, "Invalid translator path: (%s codec is not valid)\n", t->srcfmt == -1 ? "starting" : "ending"); 00666 return -1; 00667 } 00668 00669 if (t->srcfmt >= MAX_FORMAT) { 00670 ast_log(LOG_WARNING, "Source format %s is larger than MAX_FORMAT\n", ast_getformatname(t->srcfmt)); 00671 return -1; 00672 } 00673 00674 if (t->dstfmt >= MAX_FORMAT) { 00675 ast_log(LOG_WARNING, "Destination format %s is larger than MAX_FORMAT\n", ast_getformatname(t->dstfmt)); 00676 return -1; 00677 } 00678 00679 if (t->buf_size) { 00680 /* 00681 * Align buf_size properly, rounding up to the machine-specific 00682 * alignment for pointers. 00683 */ 00684 struct _test_align { void *a, *b; } p; 00685 int align = (char *)&p.b - (char *)&p.a; 00686 00687 t->buf_size = ((t->buf_size + align - 1) / align) * align; 00688 } 00689 00690 if (t->frameout == NULL) 00691 t->frameout = default_frameout; 00692 00693 calc_cost(t, 1); 00694 00695 if (option_verbose > 1) { 00696 char tmp[80]; 00697 00698 ast_verbose(VERBOSE_PREFIX_2 "Registered translator '%s' from format %s to %s, cost %d\n", 00699 term_color(tmp, t->name, COLOR_MAGENTA, COLOR_BLACK, sizeof(tmp)), 00700 ast_getformatname(1 << t->srcfmt), ast_getformatname(1 << t->dstfmt), t->cost); 00701 } 00702 00703 if (!added_cli) { 00704 ast_cli_register_multiple(cli_translate, sizeof(cli_translate) / sizeof(struct ast_cli_entry)); 00705 added_cli++; 00706 } 00707 00708 AST_LIST_LOCK(&translators); 00709 00710 /* find any existing translators that provide this same srcfmt/dstfmt, 00711 and put this one in order based on cost */ 00712 AST_LIST_TRAVERSE_SAFE_BEGIN(&translators, u, list) { 00713 if ((u->srcfmt == t->srcfmt) && 00714 (u->dstfmt == t->dstfmt) && 00715 (u->cost > t->cost)) { 00716 AST_LIST_INSERT_BEFORE_CURRENT(&translators, t, list); 00717 t = NULL; 00718 } 00719 } 00720 AST_LIST_TRAVERSE_SAFE_END; 00721 00722 /* if no existing translator was found for this format combination, 00723 add it to the beginning of the list */ 00724 if (t) 00725 AST_LIST_INSERT_HEAD(&translators, t, list); 00726 00727 rebuild_matrix(0); 00728 00729 AST_LIST_UNLOCK(&translators); 00730 00731 return 0; 00732 }
static AST_LIST_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 184 of file translate.c.
References AST_FRAME_VOICE, AST_FRIENDLY_OFFSET, ast_frisolate(), 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_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().
00186 { 00187 struct ast_frame *f = &pvt->f; 00188 00189 if (samples) 00190 f->samples = samples; 00191 else { 00192 if (pvt->samples == 0) 00193 return NULL; 00194 f->samples = pvt->samples; 00195 pvt->samples = 0; 00196 } 00197 if (datalen) 00198 f->datalen = datalen; 00199 else { 00200 f->datalen = pvt->datalen; 00201 pvt->datalen = 0; 00202 } 00203 00204 f->frametype = AST_FRAME_VOICE; 00205 f->subclass = 1 << (pvt->t->dstfmt); 00206 f->mallocd = 0; 00207 f->offset = AST_FRIENDLY_OFFSET; 00208 f->src = pvt->t->name; 00209 f->data = pvt->outbuf; 00210 00211 return ast_frisolate(f); 00212 }
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 276 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().
00277 { 00278 struct ast_trans_pvt *p = path; 00279 struct ast_frame *out = f; 00280 struct timeval delivery; 00281 int has_timing_info; 00282 long ts; 00283 long len; 00284 int seqno; 00285 00286 has_timing_info = ast_test_flag(f, AST_FRFLAG_HAS_TIMING_INFO); 00287 ts = f->ts; 00288 len = f->len; 00289 seqno = f->seqno; 00290 00291 /* XXX hmmm... check this below */ 00292 if (!ast_tvzero(f->delivery)) { 00293 if (!ast_tvzero(path->nextin)) { 00294 /* Make sure this is in line with what we were expecting */ 00295 if (!ast_tveq(path->nextin, f->delivery)) { 00296 /* The time has changed between what we expected and this 00297 most recent time on the new packet. If we have a 00298 valid prediction adjust our output time appropriately */ 00299 if (!ast_tvzero(path->nextout)) { 00300 path->nextout = ast_tvadd(path->nextout, 00301 ast_tvsub(f->delivery, path->nextin)); 00302 } 00303 path->nextin = f->delivery; 00304 } 00305 } else { 00306 /* This is our first pass. Make sure the timing looks good */ 00307 path->nextin = f->delivery; 00308 path->nextout = f->delivery; 00309 } 00310 /* Predict next incoming sample */ 00311 path->nextin = ast_tvadd(path->nextin, ast_samp2tv(f->samples, ast_format_rate(f->subclass))); 00312 } 00313 delivery = f->delivery; 00314 for ( ; out && p ; p = p->next) { 00315 framein(p, out); 00316 if (out != f) 00317 ast_frfree(out); 00318 out = p->t->frameout(p); 00319 } 00320 if (consume) 00321 ast_frfree(f); 00322 if (out == NULL) 00323 return NULL; 00324 /* we have a frame, play with times */ 00325 if (!ast_tvzero(delivery)) { 00326 /* Regenerate prediction after a discontinuity */ 00327 if (ast_tvzero(path->nextout)) 00328 path->nextout = ast_tvnow(); 00329 00330 /* Use next predicted outgoing timestamp */ 00331 out->delivery = path->nextout; 00332 00333 /* Predict next outgoing timestamp from samples in this 00334 frame. */ 00335 path->nextout = ast_tvadd(path->nextout, ast_samp2tv(out->samples, ast_format_rate(out->subclass))); 00336 } else { 00337 out->delivery = ast_tv(0, 0); 00338 ast_set2_flag(out, has_timing_info, AST_FRFLAG_HAS_TIMING_INFO); 00339 if (has_timing_info) { 00340 out->ts = ts; 00341 out->len = len; 00342 out->seqno = seqno; 00343 } 00344 } 00345 /* Invalidate prediction if we're entering a silence period */ 00346 if (out->frametype == AST_FRAME_CNG) 00347 path->nextout = ast_tv(0, 0); 00348 return out; 00349 }
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'.
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 847 of file translate.c.
References AST_FORMAT_AUDIO_MASK, AST_FORMAT_MAX_AUDIO, AST_FORMAT_MAX_VIDEO, AST_FORMAT_VIDEO_MASK, AST_LIST_LOCK, AST_LIST_UNLOCK, powerof(), and tr_matrix.
Referenced by sip_call().
00848 { 00849 unsigned int res = dest; 00850 unsigned int x; 00851 unsigned int src_audio = src & AST_FORMAT_AUDIO_MASK; 00852 unsigned int src_video = src & AST_FORMAT_VIDEO_MASK; 00853 00854 /* if we don't have a source format, we just have to try all 00855 possible destination formats */ 00856 if (!src) 00857 return dest; 00858 00859 /* If we have a source audio format, get its format index */ 00860 if (src_audio) 00861 src_audio = powerof(src_audio); 00862 00863 /* If we have a source video format, get its format index */ 00864 if (src_video) 00865 src_video = powerof(src_video); 00866 00867 AST_LIST_LOCK(&translators); 00868 00869 /* For a given source audio format, traverse the list of 00870 known audio formats to determine whether there exists 00871 a translation path from the source format to the 00872 destination format. */ 00873 for (x = 1; src_audio && x < AST_FORMAT_MAX_AUDIO; x <<= 1) { 00874 /* if this is not a desired format, nothing to do */ 00875 if (!(dest & x)) 00876 continue; 00877 00878 /* if the source is supplying this format, then 00879 we can leave it in the result */ 00880 if (src & x) 00881 continue; 00882 00883 /* if we don't have a translation path from the src 00884 to this format, remove it from the result */ 00885 if (!tr_matrix[src_audio][powerof(x)].step) { 00886 res &= ~x; 00887 continue; 00888 } 00889 00890 /* now check the opposite direction */ 00891 if (!tr_matrix[powerof(x)][src_audio].step) 00892 res &= ~x; 00893 } 00894 00895 /* For a given source video format, traverse the list of 00896 known video formats to determine whether there exists 00897 a translation path from the source format to the 00898 destination format. */ 00899 for (; src_video && x < AST_FORMAT_MAX_VIDEO; x <<= 1) { 00900 /* if this is not a desired format, nothing to do */ 00901 if (!(dest & x)) 00902 continue; 00903 00904 /* if the source is supplying this format, then 00905 we can leave it in the result */ 00906 if (src & x) 00907 continue; 00908 00909 /* if we don't have a translation path from the src 00910 to this format, remove it from the result */ 00911 if (!tr_matrix[src_video][powerof(x)].step) { 00912 res &= ~x; 00913 continue; 00914 } 00915 00916 /* now check the opposite direction */ 00917 if (!tr_matrix[powerof(x)][src_video].step) 00918 res &= ~x; 00919 } 00920 00921 AST_LIST_UNLOCK(&translators); 00922 00923 return res; 00924 }
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 825 of file translate.c.
References AST_LIST_LOCK, AST_LIST_UNLOCK, ast_log(), LOG_WARNING, translator_path::multistep, powerof(), and tr_matrix.
Referenced by ast_channel_make_compatible().
00826 { 00827 unsigned int res = -1; 00828 00829 /* convert bitwise format numbers into array indices */ 00830 src = powerof(src); 00831 dest = powerof(dest); 00832 00833 if (src == -1 || dest == -1) { 00834 ast_log(LOG_WARNING, "No translator path: (%s codec is not valid)\n", src == -1 ? "starting" : "ending"); 00835 return -1; 00836 } 00837 AST_LIST_LOCK(&translators); 00838 00839 if (tr_matrix[src][dest].step) 00840 res = tr_matrix[src][dest].multistep + 1; 00841 00842 AST_LIST_UNLOCK(&translators); 00843 00844 return res; 00845 }
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 761 of file translate.c.
References ast_translator::active, AST_LIST_LOCK, AST_LIST_UNLOCK, and rebuild_matrix().
00762 { 00763 AST_LIST_LOCK(&translators); 00764 t->active = 1; 00765 rebuild_matrix(0); 00766 AST_LIST_UNLOCK(&translators); 00767 }
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 778 of file translate.c.
References AST_FORMAT_AUDIO_MASK, AST_LIST_LOCK, AST_LIST_UNLOCK, translator_path::cost, ast_translator::cost, MAX_AUDIO_FORMAT, translator_path::multistep, and tr_matrix.
Referenced by ast_channel_make_compatible(), ast_request(), iax2_request(), and set_format().
00779 { 00780 int x,y; 00781 int best = -1; 00782 int bestdst = 0; 00783 int cur, cursrc; 00784 int besttime = INT_MAX; 00785 int beststeps = INT_MAX; 00786 int common = ((*dst) & (*srcs)) & AST_FORMAT_AUDIO_MASK; /* are there common formats ? */ 00787 00788 if (common) { /* yes, pick one and return */ 00789 for (cur = 1, y = 0; y <= MAX_AUDIO_FORMAT; cur <<= 1, y++) { 00790 if (cur & common) /* guaranteed to find one */ 00791 break; 00792 } 00793 /* We are done, this is a common format to both. */ 00794 *srcs = *dst = cur; 00795 return 0; 00796 } else { /* No, we will need to translate */ 00797 AST_LIST_LOCK(&translators); 00798 for (cur = 1, y = 0; y <= MAX_AUDIO_FORMAT; cur <<= 1, y++) { 00799 if (! (cur & *dst)) 00800 continue; 00801 for (cursrc = 1, x = 0; x <= MAX_AUDIO_FORMAT; cursrc <<= 1, x++) { 00802 if (!(*srcs & cursrc) || !tr_matrix[x][y].step || 00803 tr_matrix[x][y].cost > besttime) 00804 continue; /* not existing or no better */ 00805 if (tr_matrix[x][y].cost < besttime || 00806 tr_matrix[x][y].multistep < beststeps) { 00807 /* better than what we have so far */ 00808 best = cursrc; 00809 bestdst = cur; 00810 besttime = tr_matrix[x][y].cost; 00811 beststeps = tr_matrix[x][y].multistep; 00812 } 00813 } 00814 } 00815 AST_LIST_UNLOCK(&translators); 00816 if (best > -1) { 00817 *srcs = best; 00818 *dst = bestdst; 00819 best = 0; 00820 } 00821 return best; 00822 } 00823 }
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 231 of file translate.c.
References ast_getformatname(), AST_LIST_LOCK, AST_LIST_UNLOCK, ast_log(), 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, t, and tr_matrix.
Referenced by ast_audiohook_read_frame(), ast_slinfactory_feed(), ast_writestream(), audio_audiohook_write_list(), conf_run(), and set_format().
00232 { 00233 struct ast_trans_pvt *head = NULL, *tail = NULL; 00234 00235 source = powerof(source); 00236 dest = powerof(dest); 00237 00238 if (source == -1 || dest == -1) { 00239 ast_log(LOG_WARNING, "No translator path: (%s codec is not valid)\n", source == -1 ? "starting" : "ending"); 00240 return NULL; 00241 } 00242 00243 AST_LIST_LOCK(&translators); 00244 00245 while (source != dest) { 00246 struct ast_trans_pvt *cur; 00247 struct ast_translator *t = tr_matrix[source][dest].step; 00248 if (!t) { 00249 ast_log(LOG_WARNING, "No translator path from %s to %s\n", 00250 ast_getformatname(source), ast_getformatname(dest)); 00251 AST_LIST_UNLOCK(&translators); 00252 return NULL; 00253 } 00254 if (!(cur = newpvt(t))) { 00255 ast_log(LOG_WARNING, "Failed to build translator step from %d to %d\n", source, dest); 00256 if (head) 00257 ast_translator_free_path(head); 00258 AST_LIST_UNLOCK(&translators); 00259 return NULL; 00260 } 00261 if (!head) 00262 head = cur; 00263 else 00264 tail->next = cur; 00265 tail = cur; 00266 cur->nextin = cur->nextout = ast_tv(0, 0); 00267 /* Keep going if this isn't the final destination */ 00268 source = cur->t->dstfmt; 00269 } 00270 00271 AST_LIST_UNLOCK(&translators); 00272 return head; 00273 }
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 769 of file translate.c.
References ast_translator::active, AST_LIST_LOCK, AST_LIST_UNLOCK, and rebuild_matrix().
00770 { 00771 AST_LIST_LOCK(&translators); 00772 t->active = 0; 00773 rebuild_matrix(0); 00774 AST_LIST_UNLOCK(&translators); 00775 }
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 221 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().
00222 { 00223 struct ast_trans_pvt *pn = p; 00224 while ( (p = pn) ) { 00225 pn = p->next; 00226 destroy(p); 00227 } 00228 }
int ast_unregister_translator | ( | struct ast_translator * | t | ) |
unregister codec translator
Unregister a translator Unregisters the given tranlator.
Definition at line 735 of file translate.c.
References ast_getformatname(), AST_LIST_LOCK, AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, AST_LIST_UNLOCK, ast_verbose(), COLOR_BLACK, COLOR_MAGENTA, ast_translator::dstfmt, ast_translator::list, ast_translator::name, option_verbose, rebuild_matrix(), ast_translator::srcfmt, term_color(), and VERBOSE_PREFIX_2.
Referenced by drop_translator(), load_module(), unload_module(), and unregister_translators().
00736 { 00737 char tmp[80]; 00738 struct ast_translator *u; 00739 int found = 0; 00740 00741 AST_LIST_LOCK(&translators); 00742 AST_LIST_TRAVERSE_SAFE_BEGIN(&translators, u, list) { 00743 if (u == t) { 00744 AST_LIST_REMOVE_CURRENT(&translators, list); 00745 if (option_verbose > 1) 00746 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)); 00747 found = 1; 00748 break; 00749 } 00750 } 00751 AST_LIST_TRAVERSE_SAFE_END; 00752 00753 if (found) 00754 rebuild_matrix(0); 00755 00756 AST_LIST_UNLOCK(&translators); 00757 00758 return (u ? 0 : -1); 00759 }
static void calc_cost | ( | struct ast_translator * | t, | |
int | seconds | |||
) | [static] |
compute the cost of a single translation step
Definition at line 352 of file translate.c.
References ast_format_rate(), ast_frfree, ast_log(), ast_tvdiff_ms(), ast_tvnow(), 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().
00353 { 00354 int num_samples = 0; 00355 struct ast_trans_pvt *pvt; 00356 struct timeval start; 00357 int cost; 00358 int out_rate = ast_format_rate(t->dstfmt); 00359 00360 if (!seconds) 00361 seconds = 1; 00362 00363 /* If they don't make samples, give them a terrible score */ 00364 if (!t->sample) { 00365 ast_log(LOG_WARNING, "Translator '%s' does not produce sample frames.\n", t->name); 00366 t->cost = 99999; 00367 return; 00368 } 00369 00370 pvt = newpvt(t); 00371 if (!pvt) { 00372 ast_log(LOG_WARNING, "Translator '%s' appears to be broken and will probably fail.\n", t->name); 00373 t->cost = 99999; 00374 return; 00375 } 00376 00377 start = ast_tvnow(); 00378 00379 /* Call the encoder until we've processed the required number of samples */ 00380 while (num_samples < seconds * out_rate) { 00381 struct ast_frame *f = t->sample(); 00382 if (!f) { 00383 ast_log(LOG_WARNING, "Translator '%s' failed to produce a sample frame.\n", t->name); 00384 destroy(pvt); 00385 t->cost = 99999; 00386 return; 00387 } 00388 framein(pvt, f); 00389 ast_frfree(f); 00390 while ((f = t->frameout(pvt))) { 00391 num_samples += f->samples; 00392 ast_frfree(f); 00393 } 00394 } 00395 00396 cost = ast_tvdiff_ms(ast_tvnow(), start); 00397 00398 destroy(pvt); 00399 00400 t->cost = cost / seconds; 00401 00402 if (!t->cost) 00403 t->cost = 1; 00404 }
static struct ast_frame* default_frameout | ( | struct ast_trans_pvt * | pvt | ) | [static, read] |
Definition at line 214 of file translate.c.
References ast_trans_frameout().
Referenced by __ast_register_translator().
00215 { 00216 return ast_trans_frameout(pvt, 0, 0); 00217 }
static void destroy | ( | struct ast_trans_pvt * | pvt | ) | [static] |
Definition at line 132 of file translate.c.
References ast_module_unref(), ast_translator::destroy, free, ast_translator::module, ast_trans_pvt::t, and t.
Referenced by ast_translator_free_path(), and calc_cost().
00133 { 00134 struct ast_translator *t = pvt->t; 00135 00136 if (t->destroy) 00137 t->destroy(pvt); 00138 free(pvt); 00139 ast_module_unref(t->module); 00140 }
static int framein | ( | struct ast_trans_pvt * | pvt, | |
struct ast_frame * | f | |||
) | [static] |
framein wrapper, deals with bound checks.
Definition at line 143 of file translate.c.
References ast_copy_flags, AST_FRFLAG_HAS_TIMING_INFO, ast_log(), ast_translator::buffer_samples, ast_frame::datalen, ast_trans_pvt::f, ast_translator::framein, ast_frame::len, LOG_WARNING, ast_translator::name, ast_translator::native_plc, 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().
00144 { 00145 int ret; 00146 int samples = pvt->samples; /* initial value */ 00147 00148 /* Copy the last in jb timing info to the pvt */ 00149 ast_copy_flags(&pvt->f, f, AST_FRFLAG_HAS_TIMING_INFO); 00150 pvt->f.ts = f->ts; 00151 pvt->f.len = f->len; 00152 pvt->f.seqno = f->seqno; 00153 00154 if (f->samples == 0) { 00155 ast_log(LOG_WARNING, "no samples for %s\n", pvt->t->name); 00156 } 00157 if (pvt->t->buffer_samples) { /* do not pass empty frames to callback */ 00158 if (f->datalen == 0) { /* perform native PLC if available */ 00159 /* If the codec has native PLC, then do that */ 00160 if (!pvt->t->native_plc) 00161 return 0; 00162 } 00163 if (pvt->samples + f->samples > pvt->t->buffer_samples) { 00164 ast_log(LOG_WARNING, "Out of buffer space\n"); 00165 return -1; 00166 } 00167 } 00168 /* we require a framein routine, wouldn't know how to do 00169 * it otherwise. 00170 */ 00171 ret = pvt->t->framein(pvt, f); 00172 /* diagnostic ... */ 00173 if (pvt->samples == samples) 00174 ast_log(LOG_WARNING, "%s did not update samples %d\n", 00175 pvt->t->name, pvt->samples); 00176 return ret; 00177 }
static void* newpvt | ( | struct ast_translator * | t | ) | [static] |
Allocate the descriptor, required outbuf space, and possibly desc.
Definition at line 99 of file translate.c.
References ast_calloc, AST_FRIENDLY_OFFSET, ast_module_ref(), ast_translator::buf_size, ast_translator::desc_size, free, len(), ast_translator::module, ast_translator::newpvt, ast_trans_pvt::outbuf, ast_trans_pvt::pvt, and ast_trans_pvt::t.
Referenced by ast_translator_build_path(), and calc_cost().
00100 { 00101 struct ast_trans_pvt *pvt; 00102 int len; 00103 char *ofs; 00104 00105 /* 00106 * compute the required size adding private descriptor, 00107 * buffer, AST_FRIENDLY_OFFSET. 00108 */ 00109 len = sizeof(*pvt) + t->desc_size; 00110 if (t->buf_size) 00111 len += AST_FRIENDLY_OFFSET + t->buf_size; 00112 pvt = ast_calloc(1, len); 00113 if (!pvt) 00114 return NULL; 00115 pvt->t = t; 00116 ofs = (char *)(pvt + 1); /* pointer to data space */ 00117 if (t->desc_size) { /* first comes the descriptor */ 00118 pvt->pvt = ofs; 00119 ofs += t->desc_size; 00120 } 00121 if (t->buf_size) /* finally buffer and header */ 00122 pvt->outbuf = ofs + AST_FRIENDLY_OFFSET; 00123 /* call local init routine, if present */ 00124 if (t->newpvt && t->newpvt(pvt)) { 00125 free(pvt); 00126 return NULL; 00127 } 00128 ast_module_ref(t->module); 00129 return pvt; 00130 }
static force_inline int powerof | ( | unsigned int | d | ) | [static] |
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(), 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 }
static void rebuild_matrix | ( | int | samples | ) | [static] |
rebuild a translation matrix.
Definition at line 410 of file translate.c.
References ast_translator::active, ast_getformatname(), AST_LIST_TRAVERSE, ast_log(), calc_cost(), translator_path::cost, ast_translator::cost, ast_translator::dstfmt, ast_translator::list, LOG_DEBUG, MAX_FORMAT, translator_path::multistep, option_debug, ast_translator::srcfmt, translator_path::step, t, and tr_matrix.
Referenced by __ast_register_translator(), ast_translator_activate(), ast_translator_deactivate(), ast_unregister_translator(), show_translation(), and show_translation_deprecated().
00411 { 00412 struct ast_translator *t; 00413 int x; /* source format index */ 00414 int y; /* intermediate format index */ 00415 int z; /* destination format index */ 00416 00417 if (option_debug) 00418 ast_log(LOG_DEBUG, "Resetting translation matrix\n"); 00419 00420 bzero(tr_matrix, sizeof(tr_matrix)); 00421 00422 /* first, compute all direct costs */ 00423 AST_LIST_TRAVERSE(&translators, t, list) { 00424 if (!t->active) 00425 continue; 00426 00427 x = t->srcfmt; 00428 z = t->dstfmt; 00429 00430 if (samples) 00431 calc_cost(t, samples); 00432 00433 if (!tr_matrix[x][z].step || t->cost < tr_matrix[x][z].cost) { 00434 tr_matrix[x][z].step = t; 00435 tr_matrix[x][z].cost = t->cost; 00436 } 00437 } 00438 00439 /* 00440 * For each triple x, y, z of distinct formats, check if there is 00441 * a path from x to z through y which is cheaper than what is 00442 * currently known, and in case, update the matrix. 00443 * Repeat until the matrix is stable. 00444 */ 00445 for (;;) { 00446 int changed = 0; 00447 for (x = 0; x < MAX_FORMAT; x++) { /* source format */ 00448 for (y=0; y < MAX_FORMAT; y++) { /* intermediate format */ 00449 if (x == y) /* skip ourselves */ 00450 continue; 00451 00452 for (z=0; z<MAX_FORMAT; z++) { /* dst format */ 00453 int newcost; 00454 00455 if (z == x || z == y) /* skip null conversions */ 00456 continue; 00457 if (!tr_matrix[x][y].step) /* no path from x to y */ 00458 continue; 00459 if (!tr_matrix[y][z].step) /* no path from y to z */ 00460 continue; 00461 newcost = tr_matrix[x][y].cost + tr_matrix[y][z].cost; 00462 if (tr_matrix[x][z].step && newcost >= tr_matrix[x][z].cost) 00463 continue; /* x->y->z is more expensive than 00464 * the existing path */ 00465 /* ok, we can get from x to z via y with a cost that 00466 is the sum of the transition from x to y and 00467 from y to z */ 00468 00469 tr_matrix[x][z].step = tr_matrix[x][y].step; 00470 tr_matrix[x][z].cost = newcost; 00471 tr_matrix[x][z].multistep = 1; 00472 if (option_debug) 00473 ast_log(LOG_DEBUG, "Discovered %d cost path from %s to %s, via %s\n", tr_matrix[x][z].cost, 00474 ast_getformatname(1 << x), ast_getformatname(1 << z), ast_getformatname(1 << y)); 00475 changed++; 00476 } 00477 } 00478 } 00479 if (!changed) 00480 break; 00481 } 00482 }
static int show_translation | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 555 of file translate.c.
References ast_build_string(), ast_cli(), ast_getformatname(), AST_LIST_LOCK, AST_LIST_UNLOCK, ast_translator::cost, MAX_RECALC, rebuild_matrix(), RESULT_SHOWUSAGE, RESULT_SUCCESS, SHOW_TRANS, and tr_matrix.
00556 { 00557 int x, y, z; 00558 int curlen = 0, longest = 0; 00559 00560 if (argc > 5) 00561 return RESULT_SHOWUSAGE; 00562 00563 AST_LIST_LOCK(&translators); 00564 00565 if (argv[3] && !strcasecmp(argv[3], "recalc")) { 00566 z = argv[4] ? atoi(argv[4]) : 1; 00567 00568 if (z <= 0) { 00569 ast_cli(fd, " C'mon let's be serious here... defaulting to 1.\n"); 00570 z = 1; 00571 } 00572 00573 if (z > MAX_RECALC) { 00574 ast_cli(fd, " Maximum limit of recalc exceeded by %d, truncating value to %d\n", z - MAX_RECALC, MAX_RECALC); 00575 z = MAX_RECALC; 00576 } 00577 ast_cli(fd, " Recalculating Codec Translation (number of sample seconds: %d)\n\n", z); 00578 rebuild_matrix(z); 00579 } 00580 00581 ast_cli(fd, " Translation times between formats (in milliseconds) for one second of data\n"); 00582 ast_cli(fd, " Source Format (Rows) Destination Format (Columns)\n\n"); 00583 /* Get the length of the longest (usable?) codec name, so we know how wide the left side should be */ 00584 for (x = 0; x < SHOW_TRANS; x++) { 00585 curlen = strlen(ast_getformatname(1 << (x))); 00586 if (curlen > longest) 00587 longest = curlen; 00588 } 00589 for (x = -1; x < SHOW_TRANS; x++) { 00590 char line[120]; 00591 char *buf = line; 00592 size_t left = sizeof(line) - 1; /* one initial space */ 00593 /* next 2 lines run faster than using ast_build_string() */ 00594 *buf++ = ' '; 00595 *buf = '\0'; 00596 for (y = -1; y < SHOW_TRANS; y++) { 00597 if (y >= 0) 00598 curlen = strlen(ast_getformatname(1 << (y))); 00599 00600 if (x >= 0 && y >= 0 && tr_matrix[x][y].step) { 00601 /* XXX 999 is a little hackish 00602 We don't want this number being larger than the shortest (or current) codec 00603 For now, that is "gsm" */ 00604 ast_build_string(&buf, &left, "%*d", curlen + 1, tr_matrix[x][y].cost > 999 ? 0 : tr_matrix[x][y].cost); 00605 } else if (x == -1 && y >= 0) { 00606 /* Top row - use a dynamic size */ 00607 ast_build_string(&buf, &left, "%*s", curlen + 1, ast_getformatname(1 << (y)) ); 00608 } else if (y == -1 && x >= 0) { 00609 /* Left column - use a static size. */ 00610 ast_build_string(&buf, &left, "%*s", longest, ast_getformatname(1 << (x)) ); 00611 } else if (x >= 0 && y >= 0) { 00612 ast_build_string(&buf, &left, "%*s", curlen + 1, "-"); 00613 } else { 00614 ast_build_string(&buf, &left, "%*s", longest, ""); 00615 } 00616 } 00617 ast_build_string(&buf, &left, "\n"); 00618 ast_cli(fd, "%s", line); 00619 } 00620 AST_LIST_UNLOCK(&translators); 00621 return RESULT_SUCCESS; 00622 }
static int show_translation_deprecated | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
CLI "show translation" command handler.
Definition at line 485 of file translate.c.
References ast_build_string(), ast_cli(), ast_getformatname(), AST_LIST_LOCK, AST_LIST_UNLOCK, ast_translator::cost, MAX_RECALC, rebuild_matrix(), RESULT_SHOWUSAGE, RESULT_SUCCESS, SHOW_TRANS, and tr_matrix.
00486 { 00487 #define SHOW_TRANS 13 00488 int x, y, z; 00489 int curlen = 0, longest = 0; 00490 00491 if (argc > 4) 00492 return RESULT_SHOWUSAGE; 00493 00494 AST_LIST_LOCK(&translators); 00495 00496 if (argv[2] && !strcasecmp(argv[2], "recalc")) { 00497 z = argv[3] ? atoi(argv[3]) : 1; 00498 00499 if (z <= 0) { 00500 ast_cli(fd, " C'mon let's be serious here... defaulting to 1.\n"); 00501 z = 1; 00502 } 00503 00504 if (z > MAX_RECALC) { 00505 ast_cli(fd, " Maximum limit of recalc exceeded by %d, truncating value to %d\n", z - MAX_RECALC, MAX_RECALC); 00506 z = MAX_RECALC; 00507 } 00508 ast_cli(fd, " Recalculating Codec Translation (number of sample seconds: %d)\n\n", z); 00509 rebuild_matrix(z); 00510 } 00511 00512 ast_cli(fd, " Translation times between formats (in milliseconds) for one second of data\n"); 00513 ast_cli(fd, " Source Format (Rows) Destination Format (Columns)\n\n"); 00514 /* Get the length of the longest (usable?) codec name, so we know how wide the left side should be */ 00515 for (x = 0; x < SHOW_TRANS; x++) { 00516 curlen = strlen(ast_getformatname(1 << (x))); 00517 if (curlen > longest) 00518 longest = curlen; 00519 } 00520 for (x = -1; x < SHOW_TRANS; x++) { 00521 char line[120]; 00522 char *buf = line; 00523 size_t left = sizeof(line) - 1; /* one initial space */ 00524 /* next 2 lines run faster than using ast_build_string() */ 00525 *buf++ = ' '; 00526 *buf = '\0'; 00527 for (y = -1; y < SHOW_TRANS; y++) { 00528 if (y >= 0) 00529 curlen = strlen(ast_getformatname(1 << (y))); 00530 00531 if (x >= 0 && y >= 0 && tr_matrix[x][y].step) { 00532 /* XXX 999 is a little hackish 00533 We don't want this number being larger than the shortest (or current) codec 00534 For now, that is "gsm" */ 00535 ast_build_string(&buf, &left, "%*d", curlen + 1, tr_matrix[x][y].cost > 999 ? 0 : tr_matrix[x][y].cost); 00536 } else if (x == -1 && y >= 0) { 00537 /* Top row - use a dynamic size */ 00538 ast_build_string(&buf, &left, "%*s", curlen + 1, ast_getformatname(1 << (y)) ); 00539 } else if (y == -1 && x >= 0) { 00540 /* Left column - use a static size. */ 00541 ast_build_string(&buf, &left, "%*s", longest, ast_getformatname(1 << (x)) ); 00542 } else if (x >= 0 && y >= 0) { 00543 ast_build_string(&buf, &left, "%*s", curlen + 1, "-"); 00544 } else { 00545 ast_build_string(&buf, &left, "%*s", longest, ""); 00546 } 00547 } 00548 ast_build_string(&buf, &left, "\n"); 00549 ast_cli(fd, "%s", line); 00550 } 00551 AST_LIST_UNLOCK(&translators); 00552 return RESULT_SUCCESS; 00553 }
struct ast_cli_entry cli_show_translation_deprecated [static] |
{ { "show", "translation", NULL }, show_translation_deprecated, NULL, NULL }
Definition at line 631 of file translate.c.
struct ast_cli_entry cli_translate[] [static] |
{ { { "core", "show", "translation", NULL }, show_translation, "Display translation matrix", show_trans_usage, NULL, &cli_show_translation_deprecated }, }
Definition at line 636 of file translate.c.
char show_trans_usage[] [static] |
Definition at line 624 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 70 of file translate.c.
Referenced by ast_translate_available_formats(), ast_translate_path_steps(), ast_translator_best_choice(), ast_translator_build_path(), rebuild_matrix(), show_translation(), and show_translation_deprecated().