#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 plc and bound checks. | |
static void * | newpvt (struct ast_translator *t) |
Allocate the descriptor, required outbuf space, and possibly also plc and desc. | |
static force_inline int | powerof (unsigned int d) |
returns the index of the lowest bit set | |
static void | rebuild_matrix (int samples) |
rebuild a translation matrix. | |
static int | show_translation (int fd, int argc, char *argv[]) |
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 * | mod | |||
) |
register codec translator
Register a translator This registers a codec translator with asterisk.
Definition at line 651 of file translate.c.
References ast_translator::active, ast_cli_register_multiple(), AST_FORMAT_SLINEAR, 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, 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, option_verbose, ast_translator::plc_samples, powerof(), rebuild_matrix(), ast_translator::srcfmt, term_color(), and VERBOSE_PREFIX_2.
00652 { 00653 static int added_cli = 0; 00654 struct ast_translator *u; 00655 00656 if (!mod) { 00657 ast_log(LOG_WARNING, "Missing module pointer, you need to supply one\n"); 00658 return -1; 00659 } 00660 00661 if (!t->buf_size) { 00662 ast_log(LOG_WARNING, "empty buf size, you need to supply one\n"); 00663 return -1; 00664 } 00665 00666 t->module = mod; 00667 00668 t->srcfmt = powerof(t->srcfmt); 00669 t->dstfmt = powerof(t->dstfmt); 00670 t->active = 1; 00671 00672 if (t->plc_samples) { 00673 if (t->buffer_samples < t->plc_samples) { 00674 ast_log(LOG_WARNING, "plc_samples %d buffer_samples %d\n", 00675 t->plc_samples, t->buffer_samples); 00676 return -1; 00677 } 00678 if (t->dstfmt != powerof(AST_FORMAT_SLINEAR)) 00679 ast_log(LOG_WARNING, "plc_samples %d format %x\n", 00680 t->plc_samples, t->dstfmt); 00681 } 00682 if (t->srcfmt >= MAX_FORMAT) { 00683 ast_log(LOG_WARNING, "Source format %s is larger than MAX_FORMAT\n", ast_getformatname(t->srcfmt)); 00684 return -1; 00685 } 00686 00687 if (t->dstfmt >= MAX_FORMAT) { 00688 ast_log(LOG_WARNING, "Destination format %s is larger than MAX_FORMAT\n", ast_getformatname(t->dstfmt)); 00689 return -1; 00690 } 00691 00692 if (t->buf_size) { 00693 /* 00694 * Align buf_size properly, rounding up to the machine-specific 00695 * alignment for pointers. 00696 */ 00697 struct _test_align { void *a, *b; } p; 00698 int align = (char *)&p.b - (char *)&p.a; 00699 00700 t->buf_size = ((t->buf_size + align - 1) / align) * align; 00701 } 00702 00703 if (t->frameout == NULL) 00704 t->frameout = default_frameout; 00705 00706 calc_cost(t, 1); 00707 00708 if (option_verbose > 1) { 00709 char tmp[80]; 00710 00711 ast_verbose(VERBOSE_PREFIX_2 "Registered translator '%s' from format %s to %s, cost %d\n", 00712 term_color(tmp, t->name, COLOR_MAGENTA, COLOR_BLACK, sizeof(tmp)), 00713 ast_getformatname(1 << t->srcfmt), ast_getformatname(1 << t->dstfmt), t->cost); 00714 } 00715 00716 if (!added_cli) { 00717 ast_cli_register_multiple(cli_translate, sizeof(cli_translate) / sizeof(struct ast_cli_entry)); 00718 added_cli++; 00719 } 00720 00721 AST_LIST_LOCK(&translators); 00722 00723 /* find any existing translators that provide this same srcfmt/dstfmt, 00724 and put this one in order based on cost */ 00725 AST_LIST_TRAVERSE_SAFE_BEGIN(&translators, u, list) { 00726 if ((u->srcfmt == t->srcfmt) && 00727 (u->dstfmt == t->dstfmt) && 00728 (u->cost > t->cost)) { 00729 AST_LIST_INSERT_BEFORE_CURRENT(&translators, t, list); 00730 t = NULL; 00731 } 00732 } 00733 AST_LIST_TRAVERSE_SAFE_END; 00734 00735 /* if no existing translator was found for this format combination, 00736 add it to the beginning of the list */ 00737 if (t) 00738 AST_LIST_INSERT_HEAD(&translators, t, list); 00739 00740 rebuild_matrix(0); 00741 00742 AST_LIST_UNLOCK(&translators); 00743 00744 return 0; 00745 }
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 209 of file translate.c.
References AST_FRAME_VOICE, AST_FRIENDLY_OFFSET, 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(), lintolpc10_frameout(), and lintospeex_frameout().
00211 { 00212 struct ast_frame *f = &pvt->f; 00213 00214 if (samples) 00215 f->samples = samples; 00216 else { 00217 if (pvt->samples == 0) 00218 return NULL; 00219 f->samples = pvt->samples; 00220 pvt->samples = 0; 00221 } 00222 if (datalen) 00223 f->datalen = datalen; 00224 else { 00225 f->datalen = pvt->datalen; 00226 pvt->datalen = 0; 00227 } 00228 00229 f->frametype = AST_FRAME_VOICE; 00230 f->subclass = 1 << (pvt->t->dstfmt); 00231 f->mallocd = 0; 00232 f->offset = AST_FRIENDLY_OFFSET; 00233 f->src = pvt->t->name; 00234 f->data = pvt->outbuf; 00235 return f; 00236 }
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_FRAME_CNG, ast_frfree, ast_tvadd(), ast_tvsub(), ast_frame::delivery, framein(), ast_frame::frametype, ast_frame::has_timing_info, ast_frame::len, len, ast_trans_pvt::next, ast_trans_pvt::nextin, ast_trans_pvt::nextout, ast_frame::samples, ast_frame::seqno, and ast_frame::ts.
Referenced by __ast_read(), ast_slinfactory_feed(), ast_write(), ast_writestream(), conf_run(), process_ast_dsp(), and queue_frame_to_spies().
00296 { 00297 struct ast_trans_pvt *p = path; 00298 struct ast_frame *out = f; 00299 struct timeval delivery; 00300 int has_timing_info; 00301 long ts; 00302 long len; 00303 int seqno; 00304 00305 has_timing_info = f->has_timing_info; 00306 ts = f->ts; 00307 len = f->len; 00308 seqno = f->seqno; 00309 00310 /* 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, 8000)); 00331 } 00332 delivery = f->delivery; 00333 for ( ; out && p ; p = p->next) { 00334 framein(p, out); 00335 out = p->t->frameout(p); 00336 } 00337 if (consume) 00338 ast_frfree(f); 00339 if (out == NULL) 00340 return NULL; 00341 /* we have a frame, play with times */ 00342 if (!ast_tvzero(delivery)) { 00343 /* Regenerate prediction after a discontinuity */ 00344 if (ast_tvzero(path->nextout)) 00345 path->nextout = ast_tvnow(); 00346 00347 /* Use next predicted outgoing timestamp */ 00348 out->delivery = path->nextout; 00349 00350 /* Predict next outgoing timestamp from samples in this 00351 frame. */ 00352 path->nextout = ast_tvadd(path->nextout, ast_samp2tv( out->samples, 8000)); 00353 } else { 00354 out->delivery = ast_tv(0, 0); 00355 out->has_timing_info = has_timing_info; 00356 if (has_timing_info) { 00357 out->ts = ts; 00358 out->len = len; 00359 out->seqno = seqno; 00360 } 00361 } 00362 /* Invalidate prediction if we're entering a silence period */ 00363 if (out->frametype == AST_FRAME_CNG) 00364 path->nextout = ast_tv(0, 0); 00365 return out; 00366 }
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 856 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().
00857 { 00858 unsigned int res = dest; 00859 unsigned int x; 00860 unsigned int src_audio = src & AST_FORMAT_AUDIO_MASK; 00861 unsigned int src_video = src & AST_FORMAT_VIDEO_MASK; 00862 00863 /* if we don't have a source format, we just have to try all 00864 possible destination formats */ 00865 if (!src) 00866 return dest; 00867 00868 /* If we have a source audio format, get its format index */ 00869 if (src_audio) 00870 src_audio = powerof(src_audio); 00871 00872 /* If we have a source video format, get its format index */ 00873 if (src_video) 00874 src_video = powerof(src_video); 00875 00876 AST_LIST_LOCK(&translators); 00877 00878 /* For a given source audio format, traverse the list of 00879 known audio formats to determine whether there exists 00880 a translation path from the source format to the 00881 destination format. */ 00882 for (x = 1; src_audio && x < AST_FORMAT_MAX_AUDIO; x <<= 1) { 00883 /* if this is not a desired format, nothing to do */ 00884 if (!dest & x) 00885 continue; 00886 00887 /* if the source is supplying this format, then 00888 we can leave it in the result */ 00889 if (src & x) 00890 continue; 00891 00892 /* if we don't have a translation path from the src 00893 to this format, remove it from the result */ 00894 if (!tr_matrix[src_audio][powerof(x)].step) { 00895 res &= ~x; 00896 continue; 00897 } 00898 00899 /* now check the opposite direction */ 00900 if (!tr_matrix[powerof(x)][src_audio].step) 00901 res &= ~x; 00902 } 00903 00904 /* For a given source video format, traverse the list of 00905 known video formats to determine whether there exists 00906 a translation path from the source format to the 00907 destination format. */ 00908 for (; src_video && x < AST_FORMAT_MAX_VIDEO; x <<= 1) { 00909 /* if this is not a desired format, nothing to do */ 00910 if (!dest & x) 00911 continue; 00912 00913 /* if the source is supplying this format, then 00914 we can leave it in the result */ 00915 if (src & x) 00916 continue; 00917 00918 /* if we don't have a translation path from the src 00919 to this format, remove it from the result */ 00920 if (!tr_matrix[src_video][powerof(x)].step) { 00921 res &= ~x; 00922 continue; 00923 } 00924 00925 /* now check the opposite direction */ 00926 if (!tr_matrix[powerof(x)][src_video].step) 00927 res &= ~x; 00928 } 00929 00930 AST_LIST_UNLOCK(&translators); 00931 00932 return res; 00933 }
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 838 of file translate.c.
References AST_LIST_LOCK, AST_LIST_UNLOCK, translator_path::multistep, powerof(), and tr_matrix.
Referenced by ast_channel_make_compatible().
00839 { 00840 unsigned int res = -1; 00841 00842 /* convert bitwise format numbers into array indices */ 00843 src = powerof(src); 00844 dest = powerof(dest); 00845 00846 AST_LIST_LOCK(&translators); 00847 00848 if (tr_matrix[src][dest].step) 00849 res = tr_matrix[src][dest].multistep + 1; 00850 00851 AST_LIST_UNLOCK(&translators); 00852 00853 return res; 00854 }
void ast_translator_activate | ( | struct ast_translator * | t | ) |
Activate a previously deactivated translator.
t | translator to activate |
Definition at line 774 of file translate.c.
References ast_translator::active, AST_LIST_LOCK, AST_LIST_UNLOCK, and rebuild_matrix().
00775 { 00776 AST_LIST_LOCK(&translators); 00777 t->active = 1; 00778 rebuild_matrix(0); 00779 AST_LIST_UNLOCK(&translators); 00780 }
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 791 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_with_uniqueid(), iax2_request(), and set_format().
00792 { 00793 int x,y; 00794 int best = -1; 00795 int bestdst = 0; 00796 int cur, cursrc; 00797 int besttime = INT_MAX; 00798 int beststeps = INT_MAX; 00799 int common = ((*dst) & (*srcs)) & AST_FORMAT_AUDIO_MASK; /* are there common formats ? */ 00800 00801 if (common) { /* yes, pick one and return */ 00802 for (cur = 1, y = 0; y <= MAX_AUDIO_FORMAT; cur <<= 1, y++) { 00803 if (cur & common) /* guaranteed to find one */ 00804 break; 00805 } 00806 /* We are done, this is a common format to both. */ 00807 *srcs = *dst = cur; 00808 return 0; 00809 } else { /* No, we will need to translate */ 00810 AST_LIST_LOCK(&translators); 00811 for (cur = 1, y = 0; y <= MAX_AUDIO_FORMAT; cur <<= 1, y++) { 00812 if (! (cur & *dst)) 00813 continue; 00814 for (cursrc = 1, x = 0; x <= MAX_AUDIO_FORMAT; cursrc <<= 1, x++) { 00815 if (!(*srcs & cursrc) || !tr_matrix[x][y].step || 00816 tr_matrix[x][y].cost > besttime) 00817 continue; /* not existing or no better */ 00818 if (tr_matrix[x][y].cost < besttime || 00819 tr_matrix[x][y].multistep < beststeps) { 00820 /* better than what we have so far */ 00821 best = cursrc; 00822 bestdst = cur; 00823 besttime = tr_matrix[x][y].cost; 00824 beststeps = tr_matrix[x][y].multistep; 00825 } 00826 } 00827 } 00828 AST_LIST_UNLOCK(&translators); 00829 if (best > -1) { 00830 *srcs = best; 00831 *dst = bestdst; 00832 best = 0; 00833 } 00834 return best; 00835 } 00836 }
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 255 of file translate.c.
References ast_getformatname(), AST_LIST_LOCK, AST_LIST_UNLOCK, ast_log(), ast_translator_free_path(), ast_translator::dstfmt, LOG_WARNING, newpvt(), ast_trans_pvt::next, ast_trans_pvt::nextin, ast_trans_pvt::nextout, powerof(), translator_path::step, ast_trans_pvt::t, t, and tr_matrix.
Referenced by ast_slinfactory_feed(), ast_write(), ast_writestream(), conf_run(), misdn_set_opt_exec(), queue_frame_to_spies(), read_config(), and set_format().
00256 { 00257 struct ast_trans_pvt *head = NULL, *tail = NULL; 00258 00259 source = powerof(source); 00260 dest = powerof(dest); 00261 00262 AST_LIST_LOCK(&translators); 00263 00264 while (source != dest) { 00265 struct ast_trans_pvt *cur; 00266 struct ast_translator *t = tr_matrix[source][dest].step; 00267 if (!t) { 00268 ast_log(LOG_WARNING, "No translator path from %s to %s\n", 00269 ast_getformatname(source), ast_getformatname(dest)); 00270 AST_LIST_UNLOCK(&translators); 00271 return NULL; 00272 } 00273 if (!(cur = newpvt(t))) { 00274 ast_log(LOG_WARNING, "Failed to build translator step from %d to %d\n", source, dest); 00275 if (head) 00276 ast_translator_free_path(head); 00277 AST_LIST_UNLOCK(&translators); 00278 return NULL; 00279 } 00280 if (!head) 00281 head = cur; 00282 else 00283 tail->next = cur; 00284 tail = cur; 00285 cur->nextin = cur->nextout = ast_tv(0, 0); 00286 /* Keep going if this isn't the final destination */ 00287 source = cur->t->dstfmt; 00288 } 00289 00290 AST_LIST_UNLOCK(&translators); 00291 return head; 00292 }
void ast_translator_deactivate | ( | struct ast_translator * | t | ) |
Deactivate a translator.
t | translator to deactivate |
Definition at line 782 of file translate.c.
References ast_translator::active, AST_LIST_LOCK, AST_LIST_UNLOCK, and rebuild_matrix().
00783 { 00784 AST_LIST_LOCK(&translators); 00785 t->active = 0; 00786 rebuild_matrix(0); 00787 AST_LIST_UNLOCK(&translators); 00788 }
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 245 of file translate.c.
References destroy(), and ast_trans_pvt::next.
Referenced by ast_channel_free(), ast_channel_whisper_stop(), ast_closestream(), ast_slinfactory_destroy(), ast_slinfactory_feed(), ast_translator_build_path(), ast_write(), ast_writestream(), cl_dequeue_chan(), conf_free(), free_translation(), queue_frame_to_spies(), set_format(), and spy_cleanup().
00246 { 00247 struct ast_trans_pvt *pn = p; 00248 while ( (p = pn) ) { 00249 pn = p->next; 00250 destroy(p); 00251 } 00252 }
int ast_unregister_translator | ( | struct ast_translator * | t | ) |
unregister codec translator
Unregister a translator Unregisters the given tranlator.
Definition at line 748 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::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().
00749 { 00750 char tmp[80]; 00751 struct ast_translator *u; 00752 int found = 0; 00753 00754 AST_LIST_LOCK(&translators); 00755 AST_LIST_TRAVERSE_SAFE_BEGIN(&translators, u, list) { 00756 if (u == t) { 00757 AST_LIST_REMOVE_CURRENT(&translators, list); 00758 if (option_verbose > 1) 00759 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)); 00760 found = 1; 00761 break; 00762 } 00763 } 00764 AST_LIST_TRAVERSE_SAFE_END; 00765 00766 if (found) 00767 rebuild_matrix(0); 00768 00769 AST_LIST_UNLOCK(&translators); 00770 00771 return (u ? 0 : -1); 00772 }
static void calc_cost | ( | struct ast_translator * | t, | |
int | seconds | |||
) | [static] |
compute the cost of a single translation step
Definition at line 369 of file translate.c.
References ast_frfree, ast_log(), ast_translator::cost, destroy(), f, framein(), ast_translator::frameout, LOG_WARNING, ast_translator::name, newpvt(), ast_translator::sample, and ast_frame::samples.
Referenced by __ast_register_translator(), and rebuild_matrix().
00370 { 00371 int sofar=0; 00372 struct ast_trans_pvt *pvt; 00373 struct timeval start; 00374 int cost; 00375 00376 if (!seconds) 00377 seconds = 1; 00378 00379 /* If they don't make samples, give them a terrible score */ 00380 if (!t->sample) { 00381 ast_log(LOG_WARNING, "Translator '%s' does not produce sample frames.\n", t->name); 00382 t->cost = 99999; 00383 return; 00384 } 00385 pvt = newpvt(t); 00386 if (!pvt) { 00387 ast_log(LOG_WARNING, "Translator '%s' appears to be broken and will probably fail.\n", t->name); 00388 t->cost = 99999; 00389 return; 00390 } 00391 start = ast_tvnow(); 00392 /* Call the encoder until we've processed the required number of samples */ 00393 while (sofar < seconds * 8000) { 00394 struct ast_frame *f = t->sample(); 00395 if (!f) { 00396 ast_log(LOG_WARNING, "Translator '%s' failed to produce a sample frame.\n", t->name); 00397 destroy(pvt); 00398 t->cost = 99999; 00399 return; 00400 } 00401 framein(pvt, f); 00402 ast_frfree(f); 00403 while ((f = t->frameout(pvt))) { 00404 sofar += f->samples; 00405 ast_frfree(f); 00406 } 00407 } 00408 cost = ast_tvdiff_ms(ast_tvnow(), start); 00409 destroy(pvt); 00410 t->cost = cost / seconds; 00411 if (!t->cost) 00412 t->cost = 1; 00413 }
static struct ast_frame* default_frameout | ( | struct ast_trans_pvt * | pvt | ) | [static, read] |
Definition at line 238 of file translate.c.
References ast_trans_frameout().
Referenced by __ast_register_translator().
00239 { 00240 return ast_trans_frameout(pvt, 0, 0); 00241 }
static void destroy | ( | struct ast_trans_pvt * | pvt | ) | [static] |
Definition at line 139 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().
00140 { 00141 struct ast_translator *t = pvt->t; 00142 00143 if (t->destroy) 00144 t->destroy(pvt); 00145 free(pvt); 00146 ast_module_unref(t->module); 00147 }
static int framein | ( | struct ast_trans_pvt * | pvt, | |
struct ast_frame * | f | |||
) | [static] |
framein wrapper, deals with plc and bound checks.
Definition at line 150 of file translate.c.
References ast_log(), ast_translator::buffer_samples, ast_trans_pvt::datalen, ast_frame::datalen, ast_trans_pvt::f, ast_translator::framein, ast_frame::has_timing_info, ast_frame::len, LOG_WARNING, ast_translator::name, ast_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().
00151 { 00152 int16_t *dst = (int16_t *)pvt->outbuf; 00153 int ret; 00154 int samples = pvt->samples; /* initial value */ 00155 00156 /* Copy the last in jb timing info to the pvt */ 00157 pvt->f.has_timing_info = f->has_timing_info; 00158 pvt->f.ts = f->ts; 00159 pvt->f.len = f->len; 00160 pvt->f.seqno = f->seqno; 00161 00162 if (f->samples == 0) { 00163 ast_log(LOG_WARNING, "no samples for %s\n", pvt->t->name); 00164 } 00165 if (pvt->t->buffer_samples) { /* do not pass empty frames to callback */ 00166 if (f->datalen == 0) { /* perform PLC with nominal framesize of 20ms/160 samples */ 00167 if (pvt->plc) { 00168 int l = pvt->t->plc_samples; 00169 if (pvt->samples + l > pvt->t->buffer_samples) { 00170 ast_log(LOG_WARNING, "Out of buffer space\n"); 00171 return -1; 00172 } 00173 l = plc_fillin(pvt->plc, dst + pvt->samples, l); 00174 pvt->samples += l; 00175 pvt->datalen = pvt->samples * 2; /* SLIN has 2bytes for 1sample */ 00176 } 00177 /* We don't want generic PLC. If the codec has native PLC, then do that */ 00178 if (!pvt->t->native_plc) 00179 return 0; 00180 } 00181 if (pvt->samples + f->samples > pvt->t->buffer_samples) { 00182 ast_log(LOG_WARNING, "Out of buffer space\n"); 00183 return -1; 00184 } 00185 } 00186 /* we require a framein routine, wouldn't know how to do 00187 * it otherwise. 00188 */ 00189 ret = pvt->t->framein(pvt, f); 00190 /* possibly store data for plc */ 00191 if (!ret && pvt->plc) { 00192 int l = pvt->t->plc_samples; 00193 if (pvt->samples < l) 00194 l = pvt->samples; 00195 plc_rx(pvt->plc, dst + pvt->samples - l, l); 00196 } 00197 /* diagnostic ... */ 00198 if (pvt->samples == samples) 00199 ast_log(LOG_WARNING, "%s did not update samples %d\n", 00200 pvt->t->name, pvt->samples); 00201 return ret; 00202 }
static void* newpvt | ( | struct ast_translator * | t | ) | [static] |
Allocate the descriptor, required outbuf space, and possibly also plc and desc.
Definition at line 99 of file translate.c.
References ast_calloc, AST_FRIENDLY_OFFSET, ast_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::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().
00100 { 00101 struct ast_trans_pvt *pvt; 00102 int len; 00103 int useplc = t->plc_samples > 0 && t->useplc; /* cache, because it can change on the fly */ 00104 char *ofs; 00105 00106 /* 00107 * compute the required size adding private descriptor, 00108 * plc, buffer, AST_FRIENDLY_OFFSET. 00109 */ 00110 len = sizeof(*pvt) + t->desc_size; 00111 if (useplc) 00112 len += sizeof(plc_state_t); 00113 if (t->buf_size) 00114 len += AST_FRIENDLY_OFFSET + t->buf_size; 00115 pvt = ast_calloc(1, len); 00116 if (!pvt) 00117 return NULL; 00118 pvt->t = t; 00119 ofs = (char *)(pvt + 1); /* pointer to data space */ 00120 if (t->desc_size) { /* first comes the descriptor */ 00121 pvt->pvt = ofs; 00122 ofs += t->desc_size; 00123 } 00124 if (useplc) { /* then plc state */ 00125 pvt->plc = (plc_state_t *)ofs; 00126 ofs += sizeof(plc_state_t); 00127 } 00128 if (t->buf_size) /* finally buffer and header */ 00129 pvt->outbuf = ofs + AST_FRIENDLY_OFFSET; 00130 /* call local init routine, if present */ 00131 if (t->newpvt && t->newpvt(pvt)) { 00132 free(pvt); 00133 return NULL; 00134 } 00135 ast_module_ref(t->module); 00136 return pvt; 00137 }
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 419 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, 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().
00420 { 00421 struct ast_translator *t; 00422 int x; /* source format index */ 00423 int y; /* intermediate format index */ 00424 int z; /* destination format index */ 00425 00426 if (option_debug) 00427 ast_log(LOG_DEBUG, "Resetting translation matrix\n"); 00428 00429 bzero(tr_matrix, sizeof(tr_matrix)); 00430 00431 /* first, compute all direct costs */ 00432 AST_LIST_TRAVERSE(&translators, t, list) { 00433 if (!t->active) 00434 continue; 00435 00436 x = t->srcfmt; 00437 z = t->dstfmt; 00438 00439 if (samples) 00440 calc_cost(t, samples); 00441 00442 if (!tr_matrix[x][z].step || t->cost < tr_matrix[x][z].cost) { 00443 tr_matrix[x][z].step = t; 00444 tr_matrix[x][z].cost = t->cost; 00445 } 00446 } 00447 00448 /* 00449 * For each triple x, y, z of distinct formats, check if there is 00450 * a path from x to z through y which is cheaper than what is 00451 * currently known, and in case, update the matrix. 00452 * Repeat until the matrix is stable. 00453 */ 00454 for (;;) { 00455 int changed = 0; 00456 for (x = 0; x < MAX_FORMAT; x++) { /* source format */ 00457 for (y=0; y < MAX_FORMAT; y++) { /* intermediate format */ 00458 if (x == y) /* skip ourselves */ 00459 continue; 00460 00461 for (z=0; z<MAX_FORMAT; z++) { /* dst format */ 00462 int newcost; 00463 00464 if (z == x || z == y) /* skip null conversions */ 00465 continue; 00466 if (!tr_matrix[x][y].step) /* no path from x to y */ 00467 continue; 00468 if (!tr_matrix[y][z].step) /* no path from y to z */ 00469 continue; 00470 newcost = tr_matrix[x][y].cost + tr_matrix[y][z].cost; 00471 if (tr_matrix[x][z].step && newcost >= tr_matrix[x][z].cost) 00472 continue; /* x->y->z is more expensive than 00473 * the existing path */ 00474 /* ok, we can get from x to z via y with a cost that 00475 is the sum of the transition from x to y and 00476 from y to z */ 00477 00478 tr_matrix[x][z].step = tr_matrix[x][y].step; 00479 tr_matrix[x][z].cost = newcost; 00480 tr_matrix[x][z].multistep = 1; 00481 if (option_debug) 00482 ast_log(LOG_DEBUG, "Discovered %d cost path from %s to %s, via %d\n", tr_matrix[x][z].cost, ast_getformatname(x), ast_getformatname(z), y); 00483 changed++; 00484 } 00485 } 00486 } 00487 if (!changed) 00488 break; 00489 } 00490 }
static int show_translation | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 563 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.
00564 { 00565 int x, y, z; 00566 int curlen = 0, longest = 0; 00567 00568 if (argc > 5) 00569 return RESULT_SHOWUSAGE; 00570 00571 AST_LIST_LOCK(&translators); 00572 00573 if (argv[3] && !strcasecmp(argv[3], "recalc")) { 00574 z = argv[4] ? atoi(argv[4]) : 1; 00575 00576 if (z <= 0) { 00577 ast_cli(fd, " C'mon let's be serious here... defaulting to 1.\n"); 00578 z = 1; 00579 } 00580 00581 if (z > MAX_RECALC) { 00582 ast_cli(fd, " Maximum limit of recalc exceeded by %d, truncating value to %d\n", z - MAX_RECALC, MAX_RECALC); 00583 z = MAX_RECALC; 00584 } 00585 ast_cli(fd, " Recalculating Codec Translation (number of sample seconds: %d)\n\n", z); 00586 rebuild_matrix(z); 00587 } 00588 00589 ast_cli(fd, " Translation times between formats (in milliseconds) for one second of data\n"); 00590 ast_cli(fd, " Source Format (Rows) Destination Format (Columns)\n\n"); 00591 /* Get the length of the longest (usable?) codec name, so we know how wide the left side should be */ 00592 for (x = 0; x < SHOW_TRANS; x++) { 00593 curlen = strlen(ast_getformatname(1 << (x))); 00594 if (curlen > longest) 00595 longest = curlen; 00596 } 00597 for (x = -1; x < SHOW_TRANS; x++) { 00598 char line[120]; 00599 char *buf = line; 00600 size_t left = sizeof(line) - 1; /* one initial space */ 00601 /* next 2 lines run faster than using ast_build_string() */ 00602 *buf++ = ' '; 00603 *buf = '\0'; 00604 for (y = -1; y < SHOW_TRANS; y++) { 00605 if (y >= 0) 00606 curlen = strlen(ast_getformatname(1 << (y))); 00607 00608 if (x >= 0 && y >= 0 && tr_matrix[x][y].step) { 00609 /* XXX 999 is a little hackish 00610 We don't want this number being larger than the shortest (or current) codec 00611 For now, that is "gsm" */ 00612 ast_build_string(&buf, &left, "%*d", curlen + 1, tr_matrix[x][y].cost > 999 ? 0 : tr_matrix[x][y].cost); 00613 } else if (x == -1 && y >= 0) { 00614 /* Top row - use a dynamic size */ 00615 ast_build_string(&buf, &left, "%*s", curlen + 1, ast_getformatname(1 << (y)) ); 00616 } else if (y == -1 && x >= 0) { 00617 /* Left column - use a static size. */ 00618 ast_build_string(&buf, &left, "%*s", longest, ast_getformatname(1 << (x)) ); 00619 } else if (x >= 0 && y >= 0) { 00620 ast_build_string(&buf, &left, "%*s", curlen + 1, "-"); 00621 } else { 00622 ast_build_string(&buf, &left, "%*s", longest, ""); 00623 } 00624 } 00625 ast_build_string(&buf, &left, "\n"); 00626 ast_cli(fd, line); 00627 } 00628 AST_LIST_UNLOCK(&translators); 00629 return RESULT_SUCCESS; 00630 }
static int show_translation_deprecated | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
CLI "show translation" command handler.
Definition at line 493 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.
00494 { 00495 #define SHOW_TRANS 13 00496 int x, y, z; 00497 int curlen = 0, longest = 0; 00498 00499 if (argc > 4) 00500 return RESULT_SHOWUSAGE; 00501 00502 AST_LIST_LOCK(&translators); 00503 00504 if (argv[2] && !strcasecmp(argv[2], "recalc")) { 00505 z = argv[3] ? atoi(argv[3]) : 1; 00506 00507 if (z <= 0) { 00508 ast_cli(fd, " C'mon let's be serious here... defaulting to 1.\n"); 00509 z = 1; 00510 } 00511 00512 if (z > MAX_RECALC) { 00513 ast_cli(fd, " Maximum limit of recalc exceeded by %d, truncating value to %d\n", z - MAX_RECALC, MAX_RECALC); 00514 z = MAX_RECALC; 00515 } 00516 ast_cli(fd, " Recalculating Codec Translation (number of sample seconds: %d)\n\n", z); 00517 rebuild_matrix(z); 00518 } 00519 00520 ast_cli(fd, " Translation times between formats (in milliseconds) for one second of data\n"); 00521 ast_cli(fd, " Source Format (Rows) Destination Format (Columns)\n\n"); 00522 /* Get the length of the longest (usable?) codec name, so we know how wide the left side should be */ 00523 for (x = 0; x < SHOW_TRANS; x++) { 00524 curlen = strlen(ast_getformatname(1 << (x))); 00525 if (curlen > longest) 00526 longest = curlen; 00527 } 00528 for (x = -1; x < SHOW_TRANS; x++) { 00529 char line[120]; 00530 char *buf = line; 00531 size_t left = sizeof(line) - 1; /* one initial space */ 00532 /* next 2 lines run faster than using ast_build_string() */ 00533 *buf++ = ' '; 00534 *buf = '\0'; 00535 for (y = -1; y < SHOW_TRANS; y++) { 00536 if (y >= 0) 00537 curlen = strlen(ast_getformatname(1 << (y))); 00538 00539 if (x >= 0 && y >= 0 && tr_matrix[x][y].step) { 00540 /* XXX 999 is a little hackish 00541 We don't want this number being larger than the shortest (or current) codec 00542 For now, that is "gsm" */ 00543 ast_build_string(&buf, &left, "%*d", curlen + 1, tr_matrix[x][y].cost > 999 ? 0 : tr_matrix[x][y].cost); 00544 } else if (x == -1 && y >= 0) { 00545 /* Top row - use a dynamic size */ 00546 ast_build_string(&buf, &left, "%*s", curlen + 1, ast_getformatname(1 << (y)) ); 00547 } else if (y == -1 && x >= 0) { 00548 /* Left column - use a static size. */ 00549 ast_build_string(&buf, &left, "%*s", longest, ast_getformatname(1 << (x)) ); 00550 } else if (x >= 0 && y >= 0) { 00551 ast_build_string(&buf, &left, "%*s", curlen + 1, "-"); 00552 } else { 00553 ast_build_string(&buf, &left, "%*s", longest, ""); 00554 } 00555 } 00556 ast_build_string(&buf, &left, "\n"); 00557 ast_cli(fd, line); 00558 } 00559 AST_LIST_UNLOCK(&translators); 00560 return RESULT_SUCCESS; 00561 }
struct ast_cli_entry cli_show_translation_deprecated [static] |
Initial value:
{ { "show", "translation", NULL }, show_translation_deprecated, NULL, NULL }
Definition at line 639 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 644 of file translate.c.
char show_trans_usage[] [static] |
Definition at line 632 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().