#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. | |
void | ast_translate_frame_freed (struct ast_frame *fr) |
Hint that a frame from a translator has been freed. | |
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 676 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.
00677 { 00678 static int added_cli = 0; 00679 struct ast_translator *u; 00680 00681 if (!mod) { 00682 ast_log(LOG_WARNING, "Missing module pointer, you need to supply one\n"); 00683 return -1; 00684 } 00685 00686 if (!t->buf_size) { 00687 ast_log(LOG_WARNING, "empty buf size, you need to supply one\n"); 00688 return -1; 00689 } 00690 00691 t->module = mod; 00692 00693 t->srcfmt = powerof(t->srcfmt); 00694 t->dstfmt = powerof(t->dstfmt); 00695 t->active = 1; 00696 00697 if (t->plc_samples) { 00698 if (t->buffer_samples < t->plc_samples) { 00699 ast_log(LOG_WARNING, "plc_samples %d buffer_samples %d\n", 00700 t->plc_samples, t->buffer_samples); 00701 return -1; 00702 } 00703 if (t->dstfmt != powerof(AST_FORMAT_SLINEAR)) 00704 ast_log(LOG_WARNING, "plc_samples %d format %x\n", 00705 t->plc_samples, t->dstfmt); 00706 } 00707 if (t->srcfmt >= MAX_FORMAT) { 00708 ast_log(LOG_WARNING, "Source format %s is larger than MAX_FORMAT\n", ast_getformatname(t->srcfmt)); 00709 return -1; 00710 } 00711 00712 if (t->dstfmt >= MAX_FORMAT) { 00713 ast_log(LOG_WARNING, "Destination format %s is larger than MAX_FORMAT\n", ast_getformatname(t->dstfmt)); 00714 return -1; 00715 } 00716 00717 if (t->buf_size) { 00718 /* 00719 * Align buf_size properly, rounding up to the machine-specific 00720 * alignment for pointers. 00721 */ 00722 struct _test_align { void *a, *b; } p; 00723 int align = (char *)&p.b - (char *)&p.a; 00724 00725 t->buf_size = ((t->buf_size + align - 1) / align) * align; 00726 } 00727 00728 if (t->frameout == NULL) 00729 t->frameout = default_frameout; 00730 00731 calc_cost(t, 1); 00732 00733 if (option_verbose > 1) { 00734 char tmp[80]; 00735 00736 ast_verbose(VERBOSE_PREFIX_2 "Registered translator '%s' from format %s to %s, cost %d\n", 00737 term_color(tmp, t->name, COLOR_MAGENTA, COLOR_BLACK, sizeof(tmp)), 00738 ast_getformatname(1 << t->srcfmt), ast_getformatname(1 << t->dstfmt), t->cost); 00739 } 00740 00741 if (!added_cli) { 00742 ast_cli_register_multiple(cli_translate, sizeof(cli_translate) / sizeof(struct ast_cli_entry)); 00743 added_cli++; 00744 } 00745 00746 AST_LIST_LOCK(&translators); 00747 00748 /* find any existing translators that provide this same srcfmt/dstfmt, 00749 and put this one in order based on cost */ 00750 AST_LIST_TRAVERSE_SAFE_BEGIN(&translators, u, list) { 00751 if ((u->srcfmt == t->srcfmt) && 00752 (u->dstfmt == t->dstfmt) && 00753 (u->cost > t->cost)) { 00754 AST_LIST_INSERT_BEFORE_CURRENT(&translators, t, list); 00755 t = NULL; 00756 } 00757 } 00758 AST_LIST_TRAVERSE_SAFE_END; 00759 00760 /* if no existing translator was found for this format combination, 00761 add it to the beginning of the list */ 00762 if (t) 00763 AST_LIST_INSERT_HEAD(&translators, t, list); 00764 00765 rebuild_matrix(0); 00766 00767 AST_LIST_UNLOCK(&translators); 00768 00769 return 0; 00770 }
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 221 of file translate.c.
References AST_FRAME_VOICE, AST_FRFLAG_FROM_TRANSLATOR, AST_FRIENDLY_OFFSET, ast_set_flag, 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().
00223 { 00224 struct ast_frame *f = &pvt->f; 00225 00226 if (samples) 00227 f->samples = samples; 00228 else { 00229 if (pvt->samples == 0) 00230 return NULL; 00231 f->samples = pvt->samples; 00232 pvt->samples = 0; 00233 } 00234 if (datalen) 00235 f->datalen = datalen; 00236 else { 00237 f->datalen = pvt->datalen; 00238 pvt->datalen = 0; 00239 } 00240 00241 f->frametype = AST_FRAME_VOICE; 00242 f->subclass = 1 << (pvt->t->dstfmt); 00243 f->mallocd = 0; 00244 f->offset = AST_FRIENDLY_OFFSET; 00245 f->src = pvt->t->name; 00246 f->data = pvt->outbuf; 00247 00248 ast_set_flag(f, AST_FRFLAG_FROM_TRANSLATOR); 00249 00250 return f; 00251 }
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 310 of file translate.c.
References ast_format_rate(), AST_FRAME_CNG, AST_FRFLAG_HAS_TIMING_INFO, ast_frfree, ast_set2_flag, ast_test_flag, ast_tvadd(), ast_tvsub(), 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(), conf_run(), and process_ast_dsp().
00311 { 00312 struct ast_trans_pvt *p = path; 00313 struct ast_frame *out = f; 00314 struct timeval delivery; 00315 int has_timing_info; 00316 long ts; 00317 long len; 00318 int seqno; 00319 00320 has_timing_info = ast_test_flag(f, AST_FRFLAG_HAS_TIMING_INFO); 00321 ts = f->ts; 00322 len = f->len; 00323 seqno = f->seqno; 00324 00325 /* XXX hmmm... check this below */ 00326 if (!ast_tvzero(f->delivery)) { 00327 if (!ast_tvzero(path->nextin)) { 00328 /* Make sure this is in line with what we were expecting */ 00329 if (!ast_tveq(path->nextin, f->delivery)) { 00330 /* The time has changed between what we expected and this 00331 most recent time on the new packet. If we have a 00332 valid prediction adjust our output time appropriately */ 00333 if (!ast_tvzero(path->nextout)) { 00334 path->nextout = ast_tvadd(path->nextout, 00335 ast_tvsub(f->delivery, path->nextin)); 00336 } 00337 path->nextin = f->delivery; 00338 } 00339 } else { 00340 /* This is our first pass. Make sure the timing looks good */ 00341 path->nextin = f->delivery; 00342 path->nextout = f->delivery; 00343 } 00344 /* Predict next incoming sample */ 00345 path->nextin = ast_tvadd(path->nextin, ast_samp2tv(f->samples, ast_format_rate(f->subclass))); 00346 } 00347 delivery = f->delivery; 00348 for ( ; out && p ; p = p->next) { 00349 framein(p, out); 00350 if (out != f) 00351 ast_frfree(out); 00352 out = p->t->frameout(p); 00353 } 00354 if (consume) 00355 ast_frfree(f); 00356 if (out == NULL) 00357 return NULL; 00358 /* we have a frame, play with times */ 00359 if (!ast_tvzero(delivery)) { 00360 /* Regenerate prediction after a discontinuity */ 00361 if (ast_tvzero(path->nextout)) 00362 path->nextout = ast_tvnow(); 00363 00364 /* Use next predicted outgoing timestamp */ 00365 out->delivery = path->nextout; 00366 00367 /* Predict next outgoing timestamp from samples in this 00368 frame. */ 00369 path->nextout = ast_tvadd(path->nextout, ast_samp2tv(out->samples, ast_format_rate(out->subclass))); 00370 } else { 00371 out->delivery = ast_tv(0, 0); 00372 ast_set2_flag(out, has_timing_info, AST_FRFLAG_HAS_TIMING_INFO); 00373 if (has_timing_info) { 00374 out->ts = ts; 00375 out->len = len; 00376 out->seqno = seqno; 00377 } 00378 } 00379 /* Invalidate prediction if we're entering a silence period */ 00380 if (out->frametype == AST_FRAME_CNG) 00381 path->nextout = ast_tv(0, 0); 00382 return out; 00383 }
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 881 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().
00882 { 00883 unsigned int res = dest; 00884 unsigned int x; 00885 unsigned int src_audio = src & AST_FORMAT_AUDIO_MASK; 00886 unsigned int src_video = src & AST_FORMAT_VIDEO_MASK; 00887 00888 /* if we don't have a source format, we just have to try all 00889 possible destination formats */ 00890 if (!src) 00891 return dest; 00892 00893 /* If we have a source audio format, get its format index */ 00894 if (src_audio) 00895 src_audio = powerof(src_audio); 00896 00897 /* If we have a source video format, get its format index */ 00898 if (src_video) 00899 src_video = powerof(src_video); 00900 00901 AST_LIST_LOCK(&translators); 00902 00903 /* For a given source audio format, traverse the list of 00904 known audio formats to determine whether there exists 00905 a translation path from the source format to the 00906 destination format. */ 00907 for (x = 1; src_audio && x < AST_FORMAT_MAX_AUDIO; x <<= 1) { 00908 /* if this is not a desired format, nothing to do */ 00909 if (!dest & x) 00910 continue; 00911 00912 /* if the source is supplying this format, then 00913 we can leave it in the result */ 00914 if (src & x) 00915 continue; 00916 00917 /* if we don't have a translation path from the src 00918 to this format, remove it from the result */ 00919 if (!tr_matrix[src_audio][powerof(x)].step) { 00920 res &= ~x; 00921 continue; 00922 } 00923 00924 /* now check the opposite direction */ 00925 if (!tr_matrix[powerof(x)][src_audio].step) 00926 res &= ~x; 00927 } 00928 00929 /* For a given source video format, traverse the list of 00930 known video formats to determine whether there exists 00931 a translation path from the source format to the 00932 destination format. */ 00933 for (; src_video && x < AST_FORMAT_MAX_VIDEO; x <<= 1) { 00934 /* if this is not a desired format, nothing to do */ 00935 if (!dest & x) 00936 continue; 00937 00938 /* if the source is supplying this format, then 00939 we can leave it in the result */ 00940 if (src & x) 00941 continue; 00942 00943 /* if we don't have a translation path from the src 00944 to this format, remove it from the result */ 00945 if (!tr_matrix[src_video][powerof(x)].step) { 00946 res &= ~x; 00947 continue; 00948 } 00949 00950 /* now check the opposite direction */ 00951 if (!tr_matrix[powerof(x)][src_video].step) 00952 res &= ~x; 00953 } 00954 00955 AST_LIST_UNLOCK(&translators); 00956 00957 return res; 00958 }
void ast_translate_frame_freed | ( | struct ast_frame * | fr | ) |
Hint that a frame from a translator has been freed.
This is sort of a hack. This function gets called when ast_frame_free() gets called on a frame that has the AST_FRFLAG_FROM_TRANSLATOR flag set. This is because it is possible for a translation path to be destroyed while a frame from a translator is still in use. Specifically, this happens if a masquerade happens after a call to ast_read() but before the frame is done being processed, since the frame processing is generally done without the channel lock held.
Definition at line 960 of file translate.c.
References ast_clear_flag, AST_FRFLAG_FROM_TRANSLATOR, ast_trans_pvt::datalen, destroy(), and f.
Referenced by ast_frame_free().
00961 { 00962 struct ast_trans_pvt *pvt; 00963 00964 ast_clear_flag(fr, AST_FRFLAG_FROM_TRANSLATOR); 00965 00966 pvt = (struct ast_trans_pvt *) (((char *) fr) - offsetof(struct ast_trans_pvt, f)); 00967 00968 if (pvt->datalen != -1) 00969 return; 00970 00971 destroy(pvt); 00972 }
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 863 of file translate.c.
References AST_LIST_LOCK, AST_LIST_UNLOCK, translator_path::multistep, powerof(), and tr_matrix.
Referenced by ast_channel_make_compatible().
00864 { 00865 unsigned int res = -1; 00866 00867 /* convert bitwise format numbers into array indices */ 00868 src = powerof(src); 00869 dest = powerof(dest); 00870 00871 AST_LIST_LOCK(&translators); 00872 00873 if (tr_matrix[src][dest].step) 00874 res = tr_matrix[src][dest].multistep + 1; 00875 00876 AST_LIST_UNLOCK(&translators); 00877 00878 return res; 00879 }
void ast_translator_activate | ( | struct ast_translator * | t | ) |
Activate a previously deactivated translator.
t | translator to activate |
Definition at line 799 of file translate.c.
References ast_translator::active, AST_LIST_LOCK, AST_LIST_UNLOCK, and rebuild_matrix().
00800 { 00801 AST_LIST_LOCK(&translators); 00802 t->active = 1; 00803 rebuild_matrix(0); 00804 AST_LIST_UNLOCK(&translators); 00805 }
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 816 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().
00817 { 00818 int x,y; 00819 int best = -1; 00820 int bestdst = 0; 00821 int cur, cursrc; 00822 int besttime = INT_MAX; 00823 int beststeps = INT_MAX; 00824 int common = ((*dst) & (*srcs)) & AST_FORMAT_AUDIO_MASK; /* are there common formats ? */ 00825 00826 if (common) { /* yes, pick one and return */ 00827 for (cur = 1, y = 0; y <= MAX_AUDIO_FORMAT; cur <<= 1, y++) { 00828 if (cur & common) /* guaranteed to find one */ 00829 break; 00830 } 00831 /* We are done, this is a common format to both. */ 00832 *srcs = *dst = cur; 00833 return 0; 00834 } else { /* No, we will need to translate */ 00835 AST_LIST_LOCK(&translators); 00836 for (cur = 1, y = 0; y <= MAX_AUDIO_FORMAT; cur <<= 1, y++) { 00837 if (! (cur & *dst)) 00838 continue; 00839 for (cursrc = 1, x = 0; x <= MAX_AUDIO_FORMAT; cursrc <<= 1, x++) { 00840 if (!(*srcs & cursrc) || !tr_matrix[x][y].step || 00841 tr_matrix[x][y].cost > besttime) 00842 continue; /* not existing or no better */ 00843 if (tr_matrix[x][y].cost < besttime || 00844 tr_matrix[x][y].multistep < beststeps) { 00845 /* better than what we have so far */ 00846 best = cursrc; 00847 bestdst = cur; 00848 besttime = tr_matrix[x][y].cost; 00849 beststeps = tr_matrix[x][y].multistep; 00850 } 00851 } 00852 } 00853 AST_LIST_UNLOCK(&translators); 00854 if (best > -1) { 00855 *srcs = best; 00856 *dst = bestdst; 00857 best = 0; 00858 } 00859 return best; 00860 } 00861 }
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 270 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_audiohook_read_frame(), ast_slinfactory_feed(), ast_writestream(), audio_audiohook_write_list(), conf_run(), misdn_set_opt_exec(), read_config(), and set_format().
00271 { 00272 struct ast_trans_pvt *head = NULL, *tail = NULL; 00273 00274 source = powerof(source); 00275 dest = powerof(dest); 00276 00277 AST_LIST_LOCK(&translators); 00278 00279 while (source != dest) { 00280 struct ast_trans_pvt *cur; 00281 struct ast_translator *t = tr_matrix[source][dest].step; 00282 if (!t) { 00283 ast_log(LOG_WARNING, "No translator path from %s to %s\n", 00284 ast_getformatname(source), ast_getformatname(dest)); 00285 AST_LIST_UNLOCK(&translators); 00286 return NULL; 00287 } 00288 if (!(cur = newpvt(t))) { 00289 ast_log(LOG_WARNING, "Failed to build translator step from %d to %d\n", source, dest); 00290 if (head) 00291 ast_translator_free_path(head); 00292 AST_LIST_UNLOCK(&translators); 00293 return NULL; 00294 } 00295 if (!head) 00296 head = cur; 00297 else 00298 tail->next = cur; 00299 tail = cur; 00300 cur->nextin = cur->nextout = ast_tv(0, 0); 00301 /* Keep going if this isn't the final destination */ 00302 source = cur->t->dstfmt; 00303 } 00304 00305 AST_LIST_UNLOCK(&translators); 00306 return head; 00307 }
void ast_translator_deactivate | ( | struct ast_translator * | t | ) |
Deactivate a translator.
t | translator to deactivate |
Definition at line 807 of file translate.c.
References ast_translator::active, AST_LIST_LOCK, AST_LIST_UNLOCK, and rebuild_matrix().
00808 { 00809 AST_LIST_LOCK(&translators); 00810 t->active = 0; 00811 rebuild_matrix(0); 00812 AST_LIST_UNLOCK(&translators); 00813 }
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 260 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_closestream(), ast_slinfactory_destroy(), ast_slinfactory_feed(), ast_slinfactory_flush(), ast_translator_build_path(), ast_writestream(), audio_audiohook_write_list(), cl_dequeue_chan(), conf_free(), free_translation(), and set_format().
00261 { 00262 struct ast_trans_pvt *pn = p; 00263 while ( (p = pn) ) { 00264 pn = p->next; 00265 destroy(p); 00266 } 00267 }
int ast_unregister_translator | ( | struct ast_translator * | t | ) |
unregister codec translator
Unregister a translator Unregisters the given tranlator.
Definition at line 773 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().
00774 { 00775 char tmp[80]; 00776 struct ast_translator *u; 00777 int found = 0; 00778 00779 AST_LIST_LOCK(&translators); 00780 AST_LIST_TRAVERSE_SAFE_BEGIN(&translators, u, list) { 00781 if (u == t) { 00782 AST_LIST_REMOVE_CURRENT(&translators, list); 00783 if (option_verbose > 1) 00784 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)); 00785 found = 1; 00786 break; 00787 } 00788 } 00789 AST_LIST_TRAVERSE_SAFE_END; 00790 00791 if (found) 00792 rebuild_matrix(0); 00793 00794 AST_LIST_UNLOCK(&translators); 00795 00796 return (u ? 0 : -1); 00797 }
static void calc_cost | ( | struct ast_translator * | t, | |
int | seconds | |||
) | [static] |
compute the cost of a single translation step
Definition at line 386 of file translate.c.
References ast_format_rate(), ast_frfree, ast_log(), ast_translator::cost, destroy(), ast_translator::dstfmt, f, framein(), ast_translator::frameout, LOG_WARNING, ast_translator::name, newpvt(), ast_translator::sample, and ast_frame::samples.
Referenced by __ast_register_translator(), and rebuild_matrix().
00387 { 00388 int num_samples = 0; 00389 struct ast_trans_pvt *pvt; 00390 struct timeval start; 00391 int cost; 00392 int out_rate = ast_format_rate(t->dstfmt); 00393 00394 if (!seconds) 00395 seconds = 1; 00396 00397 /* If they don't make samples, give them a terrible score */ 00398 if (!t->sample) { 00399 ast_log(LOG_WARNING, "Translator '%s' does not produce sample frames.\n", t->name); 00400 t->cost = 99999; 00401 return; 00402 } 00403 00404 pvt = newpvt(t); 00405 if (!pvt) { 00406 ast_log(LOG_WARNING, "Translator '%s' appears to be broken and will probably fail.\n", t->name); 00407 t->cost = 99999; 00408 return; 00409 } 00410 00411 start = ast_tvnow(); 00412 00413 /* Call the encoder until we've processed the required number of samples */ 00414 while (num_samples < seconds * out_rate) { 00415 struct ast_frame *f = t->sample(); 00416 if (!f) { 00417 ast_log(LOG_WARNING, "Translator '%s' failed to produce a sample frame.\n", t->name); 00418 destroy(pvt); 00419 t->cost = 99999; 00420 return; 00421 } 00422 framein(pvt, f); 00423 ast_frfree(f); 00424 while ((f = t->frameout(pvt))) { 00425 num_samples += f->samples; 00426 ast_frfree(f); 00427 } 00428 } 00429 00430 cost = ast_tvdiff_ms(ast_tvnow(), start); 00431 00432 destroy(pvt); 00433 00434 t->cost = cost / seconds; 00435 00436 if (!t->cost) 00437 t->cost = 1; 00438 }
static struct ast_frame* default_frameout | ( | struct ast_trans_pvt * | pvt | ) | [static, read] |
Definition at line 253 of file translate.c.
References ast_trans_frameout().
Referenced by __ast_register_translator().
00254 { 00255 return ast_trans_frameout(pvt, 0, 0); 00256 }
static void destroy | ( | struct ast_trans_pvt * | pvt | ) | [static] |
Definition at line 139 of file translate.c.
References AST_FRFLAG_FROM_TRANSLATOR, ast_module_unref(), ast_test_flag, ast_trans_pvt::datalen, ast_translator::destroy, ast_trans_pvt::f, free, ast_translator::module, ast_trans_pvt::t, and t.
Referenced by ast_translate_frame_freed(), ast_translator_free_path(), and calc_cost().
00140 { 00141 struct ast_translator *t = pvt->t; 00142 00143 if (ast_test_flag(&pvt->f, AST_FRFLAG_FROM_TRANSLATOR)) { 00144 /* If this flag is still set, that means that the translation path has 00145 * been torn down, while we still have a frame out there being used. 00146 * When ast_frfree() gets called on that frame, this ast_trans_pvt 00147 * will get destroyed, too. */ 00148 00149 /* Set the magic hint that this has been requested to be destroyed. */ 00150 pvt->datalen = -1; 00151 00152 return; 00153 } 00154 00155 if (t->destroy) 00156 t->destroy(pvt); 00157 free(pvt); 00158 ast_module_unref(t->module); 00159 }
static int framein | ( | struct ast_trans_pvt * | pvt, | |
struct ast_frame * | f | |||
) | [static] |
framein wrapper, deals with plc and bound checks.
Definition at line 162 of file translate.c.
References ast_copy_flags, AST_FRFLAG_HAS_TIMING_INFO, ast_log(), ast_translator::buffer_samples, ast_trans_pvt::datalen, ast_frame::datalen, ast_trans_pvt::f, ast_translator::framein, ast_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().
00163 { 00164 int16_t *dst = (int16_t *)pvt->outbuf; 00165 int ret; 00166 int samples = pvt->samples; /* initial value */ 00167 00168 /* Copy the last in jb timing info to the pvt */ 00169 ast_copy_flags(&pvt->f, f, AST_FRFLAG_HAS_TIMING_INFO); 00170 pvt->f.ts = f->ts; 00171 pvt->f.len = f->len; 00172 pvt->f.seqno = f->seqno; 00173 00174 if (f->samples == 0) { 00175 ast_log(LOG_WARNING, "no samples for %s\n", pvt->t->name); 00176 } 00177 if (pvt->t->buffer_samples) { /* do not pass empty frames to callback */ 00178 if (f->datalen == 0) { /* perform PLC with nominal framesize of 20ms/160 samples */ 00179 if (pvt->plc) { 00180 int l = pvt->t->plc_samples; 00181 if (pvt->samples + l > pvt->t->buffer_samples) { 00182 ast_log(LOG_WARNING, "Out of buffer space\n"); 00183 return -1; 00184 } 00185 l = plc_fillin(pvt->plc, dst + pvt->samples, l); 00186 pvt->samples += l; 00187 pvt->datalen = pvt->samples * 2; /* SLIN has 2bytes for 1sample */ 00188 } 00189 /* We don't want generic PLC. If the codec has native PLC, then do that */ 00190 if (!pvt->t->native_plc) 00191 return 0; 00192 } 00193 if (pvt->samples + f->samples > pvt->t->buffer_samples) { 00194 ast_log(LOG_WARNING, "Out of buffer space\n"); 00195 return -1; 00196 } 00197 } 00198 /* we require a framein routine, wouldn't know how to do 00199 * it otherwise. 00200 */ 00201 ret = pvt->t->framein(pvt, f); 00202 /* possibly store data for plc */ 00203 if (!ret && pvt->plc) { 00204 int l = pvt->t->plc_samples; 00205 if (pvt->samples < l) 00206 l = pvt->samples; 00207 plc_rx(pvt->plc, dst + pvt->samples - l, l); 00208 } 00209 /* diagnostic ... */ 00210 if (pvt->samples == samples) 00211 ast_log(LOG_WARNING, "%s did not update samples %d\n", 00212 pvt->t->name, pvt->samples); 00213 return ret; 00214 }
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 444 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().
00445 { 00446 struct ast_translator *t; 00447 int x; /* source format index */ 00448 int y; /* intermediate format index */ 00449 int z; /* destination format index */ 00450 00451 if (option_debug) 00452 ast_log(LOG_DEBUG, "Resetting translation matrix\n"); 00453 00454 bzero(tr_matrix, sizeof(tr_matrix)); 00455 00456 /* first, compute all direct costs */ 00457 AST_LIST_TRAVERSE(&translators, t, list) { 00458 if (!t->active) 00459 continue; 00460 00461 x = t->srcfmt; 00462 z = t->dstfmt; 00463 00464 if (samples) 00465 calc_cost(t, samples); 00466 00467 if (!tr_matrix[x][z].step || t->cost < tr_matrix[x][z].cost) { 00468 tr_matrix[x][z].step = t; 00469 tr_matrix[x][z].cost = t->cost; 00470 } 00471 } 00472 00473 /* 00474 * For each triple x, y, z of distinct formats, check if there is 00475 * a path from x to z through y which is cheaper than what is 00476 * currently known, and in case, update the matrix. 00477 * Repeat until the matrix is stable. 00478 */ 00479 for (;;) { 00480 int changed = 0; 00481 for (x = 0; x < MAX_FORMAT; x++) { /* source format */ 00482 for (y=0; y < MAX_FORMAT; y++) { /* intermediate format */ 00483 if (x == y) /* skip ourselves */ 00484 continue; 00485 00486 for (z=0; z<MAX_FORMAT; z++) { /* dst format */ 00487 int newcost; 00488 00489 if (z == x || z == y) /* skip null conversions */ 00490 continue; 00491 if (!tr_matrix[x][y].step) /* no path from x to y */ 00492 continue; 00493 if (!tr_matrix[y][z].step) /* no path from y to z */ 00494 continue; 00495 newcost = tr_matrix[x][y].cost + tr_matrix[y][z].cost; 00496 if (tr_matrix[x][z].step && newcost >= tr_matrix[x][z].cost) 00497 continue; /* x->y->z is more expensive than 00498 * the existing path */ 00499 /* ok, we can get from x to z via y with a cost that 00500 is the sum of the transition from x to y and 00501 from y to z */ 00502 00503 tr_matrix[x][z].step = tr_matrix[x][y].step; 00504 tr_matrix[x][z].cost = newcost; 00505 tr_matrix[x][z].multistep = 1; 00506 if (option_debug) 00507 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); 00508 changed++; 00509 } 00510 } 00511 } 00512 if (!changed) 00513 break; 00514 } 00515 }
static int show_translation | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 588 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.
00589 { 00590 int x, y, z; 00591 int curlen = 0, longest = 0; 00592 00593 if (argc > 5) 00594 return RESULT_SHOWUSAGE; 00595 00596 AST_LIST_LOCK(&translators); 00597 00598 if (argv[3] && !strcasecmp(argv[3], "recalc")) { 00599 z = argv[4] ? atoi(argv[4]) : 1; 00600 00601 if (z <= 0) { 00602 ast_cli(fd, " C'mon let's be serious here... defaulting to 1.\n"); 00603 z = 1; 00604 } 00605 00606 if (z > MAX_RECALC) { 00607 ast_cli(fd, " Maximum limit of recalc exceeded by %d, truncating value to %d\n", z - MAX_RECALC, MAX_RECALC); 00608 z = MAX_RECALC; 00609 } 00610 ast_cli(fd, " Recalculating Codec Translation (number of sample seconds: %d)\n\n", z); 00611 rebuild_matrix(z); 00612 } 00613 00614 ast_cli(fd, " Translation times between formats (in milliseconds) for one second of data\n"); 00615 ast_cli(fd, " Source Format (Rows) Destination Format (Columns)\n\n"); 00616 /* Get the length of the longest (usable?) codec name, so we know how wide the left side should be */ 00617 for (x = 0; x < SHOW_TRANS; x++) { 00618 curlen = strlen(ast_getformatname(1 << (x))); 00619 if (curlen > longest) 00620 longest = curlen; 00621 } 00622 for (x = -1; x < SHOW_TRANS; x++) { 00623 char line[120]; 00624 char *buf = line; 00625 size_t left = sizeof(line) - 1; /* one initial space */ 00626 /* next 2 lines run faster than using ast_build_string() */ 00627 *buf++ = ' '; 00628 *buf = '\0'; 00629 for (y = -1; y < SHOW_TRANS; y++) { 00630 if (y >= 0) 00631 curlen = strlen(ast_getformatname(1 << (y))); 00632 00633 if (x >= 0 && y >= 0 && tr_matrix[x][y].step) { 00634 /* XXX 999 is a little hackish 00635 We don't want this number being larger than the shortest (or current) codec 00636 For now, that is "gsm" */ 00637 ast_build_string(&buf, &left, "%*d", curlen + 1, tr_matrix[x][y].cost > 999 ? 0 : tr_matrix[x][y].cost); 00638 } else if (x == -1 && y >= 0) { 00639 /* Top row - use a dynamic size */ 00640 ast_build_string(&buf, &left, "%*s", curlen + 1, ast_getformatname(1 << (y)) ); 00641 } else if (y == -1 && x >= 0) { 00642 /* Left column - use a static size. */ 00643 ast_build_string(&buf, &left, "%*s", longest, ast_getformatname(1 << (x)) ); 00644 } else if (x >= 0 && y >= 0) { 00645 ast_build_string(&buf, &left, "%*s", curlen + 1, "-"); 00646 } else { 00647 ast_build_string(&buf, &left, "%*s", longest, ""); 00648 } 00649 } 00650 ast_build_string(&buf, &left, "\n"); 00651 ast_cli(fd, line); 00652 } 00653 AST_LIST_UNLOCK(&translators); 00654 return RESULT_SUCCESS; 00655 }
static int show_translation_deprecated | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
CLI "show translation" command handler.
Definition at line 518 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.
00519 { 00520 #define SHOW_TRANS 13 00521 int x, y, z; 00522 int curlen = 0, longest = 0; 00523 00524 if (argc > 4) 00525 return RESULT_SHOWUSAGE; 00526 00527 AST_LIST_LOCK(&translators); 00528 00529 if (argv[2] && !strcasecmp(argv[2], "recalc")) { 00530 z = argv[3] ? atoi(argv[3]) : 1; 00531 00532 if (z <= 0) { 00533 ast_cli(fd, " C'mon let's be serious here... defaulting to 1.\n"); 00534 z = 1; 00535 } 00536 00537 if (z > MAX_RECALC) { 00538 ast_cli(fd, " Maximum limit of recalc exceeded by %d, truncating value to %d\n", z - MAX_RECALC, MAX_RECALC); 00539 z = MAX_RECALC; 00540 } 00541 ast_cli(fd, " Recalculating Codec Translation (number of sample seconds: %d)\n\n", z); 00542 rebuild_matrix(z); 00543 } 00544 00545 ast_cli(fd, " Translation times between formats (in milliseconds) for one second of data\n"); 00546 ast_cli(fd, " Source Format (Rows) Destination Format (Columns)\n\n"); 00547 /* Get the length of the longest (usable?) codec name, so we know how wide the left side should be */ 00548 for (x = 0; x < SHOW_TRANS; x++) { 00549 curlen = strlen(ast_getformatname(1 << (x))); 00550 if (curlen > longest) 00551 longest = curlen; 00552 } 00553 for (x = -1; x < SHOW_TRANS; x++) { 00554 char line[120]; 00555 char *buf = line; 00556 size_t left = sizeof(line) - 1; /* one initial space */ 00557 /* next 2 lines run faster than using ast_build_string() */ 00558 *buf++ = ' '; 00559 *buf = '\0'; 00560 for (y = -1; y < SHOW_TRANS; y++) { 00561 if (y >= 0) 00562 curlen = strlen(ast_getformatname(1 << (y))); 00563 00564 if (x >= 0 && y >= 0 && tr_matrix[x][y].step) { 00565 /* XXX 999 is a little hackish 00566 We don't want this number being larger than the shortest (or current) codec 00567 For now, that is "gsm" */ 00568 ast_build_string(&buf, &left, "%*d", curlen + 1, tr_matrix[x][y].cost > 999 ? 0 : tr_matrix[x][y].cost); 00569 } else if (x == -1 && y >= 0) { 00570 /* Top row - use a dynamic size */ 00571 ast_build_string(&buf, &left, "%*s", curlen + 1, ast_getformatname(1 << (y)) ); 00572 } else if (y == -1 && x >= 0) { 00573 /* Left column - use a static size. */ 00574 ast_build_string(&buf, &left, "%*s", longest, ast_getformatname(1 << (x)) ); 00575 } else if (x >= 0 && y >= 0) { 00576 ast_build_string(&buf, &left, "%*s", curlen + 1, "-"); 00577 } else { 00578 ast_build_string(&buf, &left, "%*s", longest, ""); 00579 } 00580 } 00581 ast_build_string(&buf, &left, "\n"); 00582 ast_cli(fd, line); 00583 } 00584 AST_LIST_UNLOCK(&translators); 00585 return RESULT_SUCCESS; 00586 }
struct ast_cli_entry cli_show_translation_deprecated [static] |
Initial value:
{ { "show", "translation", NULL }, show_translation_deprecated, NULL, NULL }
Definition at line 664 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 669 of file translate.c.
char show_trans_usage[] [static] |
Definition at line 657 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().