#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 |
struct | translators |
the list of translators More... | |
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. | |
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 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. |
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 * | module | |||
) |
Register a translator This registers a codec translator with asterisk.
t | populated ast_translator structure | |
module | handle to the module that owns this translator |
Definition at line 643 of file translate.c.
References 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(), calc_cost(), cli_translate, COLOR_BLACK, COLOR_MAGENTA, ast_translator::cost, default_frameout(), ast_translator::dstfmt, LOG_WARNING, MAX_FORMAT, option_verbose, powerof(), rebuild_matrix(), ast_translator::srcfmt, t, 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 }
struct ast_frame* ast_trans_frameout | ( | struct ast_trans_pvt * | pvt, | |
int | datalen, | |||
int | samples | |||
) |
generic frameout function
Definition at line 184 of file translate.c.
References AST_FRAME_VOICE, AST_FRIENDLY_OFFSET, ast_frisolate(), ast_trans_pvt::datalen, ast_translator::dstfmt, f, ast_trans_pvt::f, ast_translator::name, ast_trans_pvt::outbuf, ast_trans_pvt::samples, and ast_trans_pvt::t.
Referenced by default_frameout(), lintoadpcm_frameout(), lintogsm_frameout(), lintoilbc_frameout(), and lintolpc10_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 * | tr, | |
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
tr | translator structure to use for translation | |
f | frame to translate | |
consume | Whether or not to free the original frame |
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, f, framein(), ast_frame::frametype, len(), ast_frame::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 |
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 |
Definition at line 761 of file translate.c.
References AST_LIST_LOCK, AST_LIST_UNLOCK, rebuild_matrix(), and t.
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 * | dsts, | |
int * | srcs | |||
) |
Chooses the best translation path.
Given a list of sources, and a designed destination format, which should I choose?
Definition at line 778 of file translate.c.
References AST_FORMAT_AUDIO_MASK, AST_LIST_LOCK, AST_LIST_UNLOCK, ast_translator::cost, translator_path::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 | |||
) |
Builds a translator path Build a path (possibly NULL) from source to dest.
dest | destination format | |
source | source format |
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, t, 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().
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 |
Definition at line 769 of file translate.c.
References AST_LIST_LOCK, AST_LIST_UNLOCK, rebuild_matrix(), and t.
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 a translator Unregisters the given tranlator.
t | translator to unregister |
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::list, option_verbose, rebuild_matrix(), t, 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(), destroy(), f, framein(), LOG_WARNING, newpvt(), ast_trans_pvt::pvt, and t.
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] |
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(), free, 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, f, ast_trans_pvt::f, ast_translator::framein, ast_frame::len, LOG_WARNING, ast_translator::name, ast_translator::native_plc, 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(), free, len(), ast_trans_pvt::pvt, and 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(), 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 }
static void rebuild_matrix | ( | int | samples | ) | [static] |
rebuild a translation matrix.
Definition at line 410 of file translate.c.
References ast_getformatname(), AST_LIST_TRAVERSE, ast_log(), calc_cost(), ast_translator::cost, ast_translator::list, LOG_DEBUG, MAX_FORMAT, option_debug, 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] |
Initial value:
{ { "show", "translation", NULL }, show_translation_deprecated, NULL, NULL }
Definition at line 631 of file translate.c.
struct ast_cli_entry cli_translate[] [static] |
Initial value:
{ { { "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.
Referenced by __ast_register_translator().
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().