#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"
Include dependency graph for translate.c:
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 a translator This registers a codec translator with asterisk. | |
static | AST_LIST_HEAD_STATIC (translators, ast_translator) |
the list of translators | |
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 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 * | 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 653 of file translate.c.
References 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(), 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.
00654 { 00655 static int added_cli = 0; 00656 struct ast_translator *u; 00657 00658 if (!mod) { 00659 ast_log(LOG_WARNING, "Missing module pointer, you need to supply one\n"); 00660 return -1; 00661 } 00662 00663 if (!t->buf_size) { 00664 ast_log(LOG_WARNING, "empty buf size, you need to supply one\n"); 00665 return -1; 00666 } 00667 00668 t->module = mod; 00669 00670 t->srcfmt = powerof(t->srcfmt); 00671 t->dstfmt = powerof(t->dstfmt); 00672 t->active = 1; 00673 00674 if (t->plc_samples) { 00675 if (t->buffer_samples < t->plc_samples) { 00676 ast_log(LOG_WARNING, "plc_samples %d buffer_samples %d\n", 00677 t->plc_samples, t->buffer_samples); 00678 return -1; 00679 } 00680 if (t->dstfmt != powerof(AST_FORMAT_SLINEAR)) 00681 ast_log(LOG_WARNING, "plc_samples %d format %x\n", 00682 t->plc_samples, t->dstfmt); 00683 } 00684 if (t->srcfmt >= MAX_FORMAT) { 00685 ast_log(LOG_WARNING, "Source format %s is larger than MAX_FORMAT\n", ast_getformatname(t->srcfmt)); 00686 return -1; 00687 } 00688 00689 if (t->dstfmt >= MAX_FORMAT) { 00690 ast_log(LOG_WARNING, "Destination format %s is larger than MAX_FORMAT\n", ast_getformatname(t->dstfmt)); 00691 return -1; 00692 } 00693 00694 if (t->buf_size) { 00695 /* 00696 * Align buf_size properly, rounding up to the machine-specific 00697 * alignment for pointers. 00698 */ 00699 struct _test_align { void *a, *b; } p; 00700 int align = (char *)&p.b - (char *)&p.a; 00701 00702 t->buf_size = ((t->buf_size + align - 1) / align) * align; 00703 } 00704 00705 if (t->frameout == NULL) 00706 t->frameout = default_frameout; 00707 00708 calc_cost(t, 1); 00709 00710 if (option_verbose > 1) { 00711 char tmp[80]; 00712 00713 ast_verbose(VERBOSE_PREFIX_2 "Registered translator '%s' from format %s to %s, cost %d\n", 00714 term_color(tmp, t->name, COLOR_MAGENTA, COLOR_BLACK, sizeof(tmp)), 00715 ast_getformatname(1 << t->srcfmt), ast_getformatname(1 << t->dstfmt), t->cost); 00716 } 00717 00718 if (!added_cli) { 00719 ast_cli_register_multiple(cli_translate, sizeof(cli_translate) / sizeof(struct ast_cli_entry)); 00720 added_cli++; 00721 } 00722 00723 AST_LIST_LOCK(&translators); 00724 00725 /* find any existing translators that provide this same srcfmt/dstfmt, 00726 and put this one in order based on cost */ 00727 AST_LIST_TRAVERSE_SAFE_BEGIN(&translators, u, list) { 00728 if ((u->srcfmt == t->srcfmt) && 00729 (u->dstfmt == t->dstfmt) && 00730 (u->cost > t->cost)) { 00731 AST_LIST_INSERT_BEFORE_CURRENT(&translators, t, list); 00732 t = NULL; 00733 } 00734 } 00735 AST_LIST_TRAVERSE_SAFE_END; 00736 00737 /* if no existing translator was found for this format combination, 00738 add it to the beginning of the list */ 00739 if (t) 00740 AST_LIST_INSERT_HEAD(&translators, t, list); 00741 00742 rebuild_matrix(0); 00743 00744 AST_LIST_UNLOCK(&translators); 00745 00746 return 0; 00747 }
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 | |||
) |
generic frameout function
Definition at line 213 of file translate.c.
References AST_FRAME_VOICE, AST_FRIENDLY_OFFSET, 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().
00215 { 00216 struct ast_frame *f = &pvt->f; 00217 00218 if (samples) 00219 f->samples = samples; 00220 else { 00221 if (pvt->samples == 0) 00222 return NULL; 00223 f->samples = pvt->samples; 00224 pvt->samples = 0; 00225 } 00226 if (datalen) 00227 f->datalen = datalen; 00228 else { 00229 f->datalen = pvt->datalen; 00230 pvt->datalen = 0; 00231 } 00232 00233 f->frametype = AST_FRAME_VOICE; 00234 f->subclass = 1 << (pvt->t->dstfmt); 00235 f->mallocd = 0; 00236 f->offset = AST_FRIENDLY_OFFSET; 00237 f->src = pvt->t->name; 00238 f->data = pvt->outbuf; 00239 return f; 00240 }
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 299 of file translate.c.
References AST_FRAME_CNG, ast_frfree(), ast_tvadd(), ast_tvsub(), ast_frame::delivery, f, framein(), ast_frame::frametype, ast_frame::has_timing_info, len, ast_frame::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().
00300 { 00301 struct ast_trans_pvt *p = path; 00302 struct ast_frame *out = f; 00303 struct timeval delivery; 00304 int has_timing_info; 00305 long ts; 00306 long len; 00307 int seqno; 00308 00309 has_timing_info = f->has_timing_info; 00310 ts = f->ts; 00311 len = f->len; 00312 seqno = f->seqno; 00313 00314 /* XXX hmmm... check this below */ 00315 if (!ast_tvzero(f->delivery)) { 00316 if (!ast_tvzero(path->nextin)) { 00317 /* Make sure this is in line with what we were expecting */ 00318 if (!ast_tveq(path->nextin, f->delivery)) { 00319 /* The time has changed between what we expected and this 00320 most recent time on the new packet. If we have a 00321 valid prediction adjust our output time appropriately */ 00322 if (!ast_tvzero(path->nextout)) { 00323 path->nextout = ast_tvadd(path->nextout, 00324 ast_tvsub(f->delivery, path->nextin)); 00325 } 00326 path->nextin = f->delivery; 00327 } 00328 } else { 00329 /* This is our first pass. Make sure the timing looks good */ 00330 path->nextin = f->delivery; 00331 path->nextout = f->delivery; 00332 } 00333 /* Predict next incoming sample */ 00334 path->nextin = ast_tvadd(path->nextin, ast_samp2tv(f->samples, 8000)); 00335 } 00336 delivery = f->delivery; 00337 for ( ; out && p ; p = p->next) { 00338 framein(p, out); 00339 out = p->t->frameout(p); 00340 } 00341 if (consume) 00342 ast_frfree(f); 00343 if (out == NULL) 00344 return NULL; 00345 /* we have a frame, play with times */ 00346 if (!ast_tvzero(delivery)) { 00347 /* Regenerate prediction after a discontinuity */ 00348 if (ast_tvzero(path->nextout)) 00349 path->nextout = ast_tvnow(); 00350 00351 /* Use next predicted outgoing timestamp */ 00352 out->delivery = path->nextout; 00353 00354 /* Predict next outgoing timestamp from samples in this 00355 frame. */ 00356 path->nextout = ast_tvadd(path->nextout, ast_samp2tv( out->samples, 8000)); 00357 } else { 00358 out->delivery = ast_tv(0, 0); 00359 out->has_timing_info = has_timing_info; 00360 if (has_timing_info) { 00361 out->ts = ts; 00362 out->len = len; 00363 out->seqno = seqno; 00364 } 00365 } 00366 /* Invalidate prediction if we're entering a silence period */ 00367 if (out->frametype == AST_FRAME_CNG) 00368 path->nextout = ast_tv(0, 0); 00369 return out; 00370 }
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 858 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().
00859 { 00860 unsigned int res = dest; 00861 unsigned int x; 00862 unsigned int src_audio = src & AST_FORMAT_AUDIO_MASK; 00863 unsigned int src_video = src & AST_FORMAT_VIDEO_MASK; 00864 00865 /* if we don't have a source format, we just have to try all 00866 possible destination formats */ 00867 if (!src) 00868 return dest; 00869 00870 /* If we have a source audio format, get its format index */ 00871 if (src_audio) 00872 src_audio = powerof(src_audio); 00873 00874 /* If we have a source video format, get its format index */ 00875 if (src_video) 00876 src_video = powerof(src_video); 00877 00878 AST_LIST_LOCK(&translators); 00879 00880 /* For a given source audio format, traverse the list of 00881 known audio formats to determine whether there exists 00882 a translation path from the source format to the 00883 destination format. */ 00884 for (x = 1; src_audio && x < AST_FORMAT_MAX_AUDIO; x <<= 1) { 00885 /* if this is not a desired format, nothing to do */ 00886 if (!dest & x) 00887 continue; 00888 00889 /* if the source is supplying this format, then 00890 we can leave it in the result */ 00891 if (src & x) 00892 continue; 00893 00894 /* if we don't have a translation path from the src 00895 to this format, remove it from the result */ 00896 if (!tr_matrix[src_audio][powerof(x)].step) { 00897 res &= ~x; 00898 continue; 00899 } 00900 00901 /* now check the opposite direction */ 00902 if (!tr_matrix[powerof(x)][src_audio].step) 00903 res &= ~x; 00904 } 00905 00906 /* For a given source video format, traverse the list of 00907 known video formats to determine whether there exists 00908 a translation path from the source format to the 00909 destination format. */ 00910 for (; src_video && x < AST_FORMAT_MAX_VIDEO; x <<= 1) { 00911 /* if this is not a desired format, nothing to do */ 00912 if (!dest & x) 00913 continue; 00914 00915 /* if the source is supplying this format, then 00916 we can leave it in the result */ 00917 if (src & x) 00918 continue; 00919 00920 /* if we don't have a translation path from the src 00921 to this format, remove it from the result */ 00922 if (!tr_matrix[src_video][powerof(x)].step) { 00923 res &= ~x; 00924 continue; 00925 } 00926 00927 /* now check the opposite direction */ 00928 if (!tr_matrix[powerof(x)][src_video].step) 00929 res &= ~x; 00930 } 00931 00932 AST_LIST_UNLOCK(&translators); 00933 00934 return res; 00935 }
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 840 of file translate.c.
References AST_LIST_LOCK, AST_LIST_UNLOCK, translator_path::multistep, powerof(), and tr_matrix.
Referenced by ast_channel_make_compatible().
00841 { 00842 unsigned int res = -1; 00843 00844 /* convert bitwise format numbers into array indices */ 00845 src = powerof(src); 00846 dest = powerof(dest); 00847 00848 AST_LIST_LOCK(&translators); 00849 00850 if (tr_matrix[src][dest].step) 00851 res = tr_matrix[src][dest].multistep + 1; 00852 00853 AST_LIST_UNLOCK(&translators); 00854 00855 return res; 00856 }
void ast_translator_activate | ( | struct ast_translator * | t | ) |
Activate a previously deactivated translator.
t | translator to activate |
Definition at line 776 of file translate.c.
References AST_LIST_LOCK, AST_LIST_UNLOCK, rebuild_matrix(), and t.
00777 { 00778 AST_LIST_LOCK(&translators); 00779 t->active = 1; 00780 rebuild_matrix(0); 00781 AST_LIST_UNLOCK(&translators); 00782 }
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 793 of file translate.c.
References AST_LIST_LOCK, AST_LIST_UNLOCK, ast_translator::cost, translator_path::cost, MAX_FORMAT, translator_path::multistep, and tr_matrix.
Referenced by ast_channel_make_compatible(), ast_request(), iax2_request(), and set_format().
00794 { 00795 int x,y; 00796 int best = -1; 00797 int bestdst = 0; 00798 int cur, cursrc; 00799 int besttime = INT_MAX; 00800 int beststeps = INT_MAX; 00801 int common = (*dst) & (*srcs); /* are there common formats ? */ 00802 00803 if (common) { /* yes, pick one and return */ 00804 for (cur = 1, y = 0; y < MAX_FORMAT; cur <<= 1, y++) { 00805 if (cur & common) /* guaranteed to find one */ 00806 break; 00807 } 00808 /* We are done, this is a common format to both. */ 00809 *srcs = *dst = cur; 00810 return 0; 00811 } else { /* No, we will need to translate */ 00812 AST_LIST_LOCK(&translators); 00813 for (cur = 1, y = 0; y < MAX_FORMAT; cur <<= 1, y++) { 00814 if (! (cur & *dst)) 00815 continue; 00816 for (cursrc = 1, x = 0; x < MAX_FORMAT; cursrc <<= 1, x++) { 00817 if (!(*srcs & cursrc) || !tr_matrix[x][y].step || 00818 tr_matrix[x][y].cost > besttime) 00819 continue; /* not existing or no better */ 00820 if (tr_matrix[x][y].cost < besttime || 00821 tr_matrix[x][y].multistep < beststeps) { 00822 /* better than what we have so far */ 00823 best = cursrc; 00824 bestdst = cur; 00825 besttime = tr_matrix[x][y].cost; 00826 beststeps = tr_matrix[x][y].multistep; 00827 } 00828 } 00829 } 00830 AST_LIST_UNLOCK(&translators); 00831 if (best > -1) { 00832 *srcs = best; 00833 *dst = bestdst; 00834 best = 0; 00835 } 00836 return best; 00837 } 00838 }
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 259 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, t, ast_trans_pvt::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().
00260 { 00261 struct ast_trans_pvt *head = NULL, *tail = NULL; 00262 00263 source = powerof(source); 00264 dest = powerof(dest); 00265 00266 AST_LIST_LOCK(&translators); 00267 00268 while (source != dest) { 00269 struct ast_trans_pvt *cur; 00270 struct ast_translator *t = tr_matrix[source][dest].step; 00271 if (!t) { 00272 ast_log(LOG_WARNING, "No translator path from %s to %s\n", 00273 ast_getformatname(source), ast_getformatname(dest)); 00274 AST_LIST_UNLOCK(&translators); 00275 return NULL; 00276 } 00277 if (!(cur = newpvt(t))) { 00278 ast_log(LOG_WARNING, "Failed to build translator step from %d to %d\n", source, dest); 00279 if (head) 00280 ast_translator_free_path(head); 00281 AST_LIST_UNLOCK(&translators); 00282 return NULL; 00283 } 00284 if (!head) 00285 head = cur; 00286 else 00287 tail->next = cur; 00288 tail = cur; 00289 cur->nextin = cur->nextout = ast_tv(0, 0); 00290 /* Keep going if this isn't the final destination */ 00291 source = cur->t->dstfmt; 00292 } 00293 00294 AST_LIST_UNLOCK(&translators); 00295 return head; 00296 }
void ast_translator_deactivate | ( | struct ast_translator * | t | ) |
Deactivate a translator.
t | translator to deactivate |
Definition at line 784 of file translate.c.
References AST_LIST_LOCK, AST_LIST_UNLOCK, rebuild_matrix(), and t.
00785 { 00786 AST_LIST_LOCK(&translators); 00787 t->active = 0; 00788 rebuild_matrix(0); 00789 AST_LIST_UNLOCK(&translators); 00790 }
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 249 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().
00250 { 00251 struct ast_trans_pvt *pn = p; 00252 while ( (p = pn) ) { 00253 pn = p->next; 00254 destroy(p); 00255 } 00256 }
int ast_unregister_translator | ( | struct ast_translator * | t | ) |
Unregister a translator Unregisters the given tranlator.
t | translator to unregister |
Definition at line 750 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, option_verbose, rebuild_matrix(), t, term_color(), and VERBOSE_PREFIX_2.
Referenced by drop_translator(), load_module(), unload_module(), and unregister_translators().
00751 { 00752 char tmp[80]; 00753 struct ast_translator *u; 00754 int found = 0; 00755 00756 AST_LIST_LOCK(&translators); 00757 AST_LIST_TRAVERSE_SAFE_BEGIN(&translators, u, list) { 00758 if (u == t) { 00759 AST_LIST_REMOVE_CURRENT(&translators, list); 00760 if (option_verbose > 1) 00761 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)); 00762 found = 1; 00763 break; 00764 } 00765 } 00766 AST_LIST_TRAVERSE_SAFE_END; 00767 00768 if (found) 00769 rebuild_matrix(0); 00770 00771 AST_LIST_UNLOCK(&translators); 00772 00773 return (u ? 0 : -1); 00774 }
static void calc_cost | ( | struct ast_translator * | t, | |
int | seconds | |||
) | [static] |
compute the cost of a single translation step
Definition at line 373 of file translate.c.
References ast_frfree(), ast_log(), destroy(), f, framein(), LOG_WARNING, newpvt(), and t.
Referenced by __ast_register_translator(), and rebuild_matrix().
00374 { 00375 int sofar=0; 00376 struct ast_trans_pvt *pvt; 00377 struct timeval start; 00378 int cost; 00379 00380 if (!seconds) 00381 seconds = 1; 00382 00383 /* If they don't make samples, give them a terrible score */ 00384 if (!t->sample) { 00385 ast_log(LOG_WARNING, "Translator '%s' does not produce sample frames.\n", t->name); 00386 t->cost = 99999; 00387 return; 00388 } 00389 pvt = newpvt(t); 00390 if (!pvt) { 00391 ast_log(LOG_WARNING, "Translator '%s' appears to be broken and will probably fail.\n", t->name); 00392 t->cost = 99999; 00393 return; 00394 } 00395 start = ast_tvnow(); 00396 /* Call the encoder until we've processed the required number of samples */ 00397 while (sofar < seconds * 8000) { 00398 struct ast_frame *f = t->sample(); 00399 if (!f) { 00400 ast_log(LOG_WARNING, "Translator '%s' failed to produce a sample frame.\n", t->name); 00401 destroy(pvt); 00402 t->cost = 99999; 00403 return; 00404 } 00405 framein(pvt, f); 00406 ast_frfree(f); 00407 while ((f = t->frameout(pvt))) { 00408 sofar += f->samples; 00409 ast_frfree(f); 00410 } 00411 } 00412 cost = ast_tvdiff_ms(ast_tvnow(), start); 00413 destroy(pvt); 00414 t->cost = cost / seconds; 00415 if (!t->cost) 00416 t->cost = 1; 00417 }
static struct ast_frame* default_frameout | ( | struct ast_trans_pvt * | pvt | ) | [static] |
Definition at line 242 of file translate.c.
References ast_trans_frameout().
Referenced by __ast_register_translator().
00243 { 00244 return ast_trans_frameout(pvt, 0, 0); 00245 }
static void destroy | ( | struct ast_trans_pvt * | pvt | ) | [static] |
Definition at line 139 of file translate.c.
References ast_module_unref(), free, 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, f, ast_trans_pvt::f, ast_translator::framein, ast_frame::has_timing_info, ast_frame::len, LOG_ERROR, 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_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 if ( f->data == NULL && f->datalen > 0 ) { 00187 ast_log(LOG_ERROR, "NULL pointer in frame data for %s\n", pvt->t->name); 00188 return -1; 00189 } 00190 /* we require a framein routine, wouldn't know how to do 00191 * it otherwise. 00192 */ 00193 ret = pvt->t->framein(pvt, f); 00194 /* possibly store data for plc */ 00195 if (!ret && pvt->plc) { 00196 int l = pvt->t->plc_samples; 00197 if (pvt->samples < l) 00198 l = pvt->samples; 00199 plc_rx(pvt->plc, dst + pvt->samples - l, l); 00200 } 00201 /* diagnostic ... */ 00202 if (pvt->samples == samples) 00203 ast_log(LOG_WARNING, "%s did not update samples %d\n", 00204 pvt->t->name, pvt->samples); 00205 return ret; 00206 }
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(), 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 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 423 of file translate.c.
References ast_getformatname(), AST_LIST_TRAVERSE, ast_log(), calc_cost(), ast_translator::cost, 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().
00424 { 00425 struct ast_translator *t; 00426 int x; /* source format index */ 00427 int y; /* intermediate format index */ 00428 int z; /* destination format index */ 00429 00430 if (option_debug) 00431 ast_log(LOG_DEBUG, "Resetting translation matrix\n"); 00432 00433 bzero(tr_matrix, sizeof(tr_matrix)); 00434 00435 /* first, compute all direct costs */ 00436 AST_LIST_TRAVERSE(&translators, t, list) { 00437 if (!t->active) 00438 continue; 00439 00440 x = t->srcfmt; 00441 z = t->dstfmt; 00442 00443 if (samples) 00444 calc_cost(t, samples); 00445 00446 if (!tr_matrix[x][z].step || t->cost < tr_matrix[x][z].cost) { 00447 tr_matrix[x][z].step = t; 00448 tr_matrix[x][z].cost = t->cost; 00449 } 00450 } 00451 00452 /* 00453 * For each triple x, y, z of distinct formats, check if there is 00454 * a path from x to z through y which is cheaper than what is 00455 * currently known, and in case, update the matrix. 00456 * Repeat until the matrix is stable. 00457 */ 00458 for (;;) { 00459 int changed = 0; 00460 for (x = 0; x < MAX_FORMAT; x++) { /* source format */ 00461 for (y=0; y < MAX_FORMAT; y++) { /* intermediate format */ 00462 if (x == y) /* skip ourselves */ 00463 continue; 00464 00465 for (z=0; z<MAX_FORMAT; z++) { /* dst format */ 00466 int newcost; 00467 00468 if (z == x || z == y) /* skip null conversions */ 00469 continue; 00470 if (!tr_matrix[x][y].step) /* no path from x to y */ 00471 continue; 00472 if (!tr_matrix[y][z].step) /* no path from y to z */ 00473 continue; 00474 newcost = tr_matrix[x][y].cost + tr_matrix[y][z].cost; 00475 if (tr_matrix[x][z].step && newcost >= tr_matrix[x][z].cost) 00476 continue; /* x->y->z is more expensive than 00477 * the existing path */ 00478 /* ok, we can get from x to z via y with a cost that 00479 is the sum of the transition from x to y and 00480 from y to z */ 00481 00482 tr_matrix[x][z].step = tr_matrix[x][y].step; 00483 tr_matrix[x][z].cost = newcost; 00484 tr_matrix[x][z].multistep = 1; 00485 if (option_debug) 00486 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); 00487 changed++; 00488 } 00489 } 00490 } 00491 if (!changed) 00492 break; 00493 } 00494 }
static int show_translation | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
Definition at line 566 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.
00567 { 00568 int x, y, z; 00569 int curlen = 0, longest = 0; 00570 00571 if (argc > 5) 00572 return RESULT_SHOWUSAGE; 00573 00574 AST_LIST_LOCK(&translators); 00575 00576 if (argv[3] && !strcasecmp(argv[3], "recalc")) { 00577 z = argv[4] ? atoi(argv[4]) : 1; 00578 00579 if (z <= 0) { 00580 ast_cli(fd, " C'mon let's be serious here... defaulting to 1.\n"); 00581 z = 1; 00582 } 00583 00584 if (z > MAX_RECALC) { 00585 ast_cli(fd, " Maximum limit of recalc exceeded by %d, truncating value to %d\n", z - MAX_RECALC, MAX_RECALC); 00586 z = MAX_RECALC; 00587 } 00588 ast_cli(fd, " Recalculating Codec Translation (number of sample seconds: %d)\n\n", z); 00589 rebuild_matrix(z); 00590 } 00591 00592 ast_cli(fd, " Translation times between formats (in milliseconds) for one second of data\n"); 00593 ast_cli(fd, " Source Format (Rows) Destination Format (Columns)\n\n"); 00594 /* Get the length of the longest (usable?) codec name, so we know how wide the left side should be */ 00595 for (x = 0; x < SHOW_TRANS; x++) { 00596 curlen = strlen(ast_getformatname(1 << (x + 1))); 00597 if (curlen > longest) 00598 longest = curlen; 00599 } 00600 for (x = -1; x < SHOW_TRANS; x++) { 00601 char line[120]; 00602 char *buf = line; 00603 size_t left = sizeof(line) - 1; /* one initial space */ 00604 /* next 2 lines run faster than using ast_build_string() */ 00605 *buf++ = ' '; 00606 *buf = '\0'; 00607 for (y = -1; y < SHOW_TRANS; y++) { 00608 curlen = strlen(ast_getformatname(1 << (y))); 00609 00610 if (x >= 0 && y >= 0 && tr_matrix[x][y].step) { 00611 /* XXX 999 is a little hackish 00612 We don't want this number being larger than the shortest (or current) codec 00613 For now, that is "gsm" */ 00614 ast_build_string(&buf, &left, "%*d", curlen + 1, tr_matrix[x][y].cost > 999 ? 0 : tr_matrix[x][y].cost); 00615 } else if (x == -1 && y >= 0) { 00616 /* Top row - use a dynamic size */ 00617 ast_build_string(&buf, &left, "%*s", curlen + 1, ast_getformatname(1 << (x + y + 1)) ); 00618 } else if (y == -1 && x >= 0) { 00619 /* Left column - use a static size. */ 00620 ast_build_string(&buf, &left, "%*s", longest, ast_getformatname(1 << (x + y + 1)) ); 00621 } else if (x >= 0 && y >= 0) { 00622 ast_build_string(&buf, &left, "%*s", curlen + 1, "-"); 00623 } else { 00624 ast_build_string(&buf, &left, "%*s", longest, ""); 00625 } 00626 } 00627 ast_build_string(&buf, &left, "\n"); 00628 ast_cli(fd, line); 00629 } 00630 AST_LIST_UNLOCK(&translators); 00631 return RESULT_SUCCESS; 00632 }
static int show_translation_deprecated | ( | int | fd, | |
int | argc, | |||
char * | argv[] | |||
) | [static] |
CLI "show translation" command handler.
Definition at line 497 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.
00498 { 00499 #define SHOW_TRANS 13 00500 int x, y, z; 00501 int curlen = 0, longest = 0; 00502 00503 if (argc > 4) 00504 return RESULT_SHOWUSAGE; 00505 00506 AST_LIST_LOCK(&translators); 00507 00508 if (argv[2] && !strcasecmp(argv[2], "recalc")) { 00509 z = argv[3] ? atoi(argv[3]) : 1; 00510 00511 if (z <= 0) { 00512 ast_cli(fd, " C'mon let's be serious here... defaulting to 1.\n"); 00513 z = 1; 00514 } 00515 00516 if (z > MAX_RECALC) { 00517 ast_cli(fd, " Maximum limit of recalc exceeded by %d, truncating value to %d\n", z - MAX_RECALC, MAX_RECALC); 00518 z = MAX_RECALC; 00519 } 00520 ast_cli(fd, " Recalculating Codec Translation (number of sample seconds: %d)\n\n", z); 00521 rebuild_matrix(z); 00522 } 00523 00524 ast_cli(fd, " Translation times between formats (in milliseconds) for one second of data\n"); 00525 ast_cli(fd, " Source Format (Rows) Destination Format (Columns)\n\n"); 00526 /* Get the length of the longest (usable?) codec name, so we know how wide the left side should be */ 00527 for (x = 0; x < SHOW_TRANS; x++) { 00528 curlen = strlen(ast_getformatname(1 << (x + 1))); 00529 if (curlen > longest) 00530 longest = curlen; 00531 } 00532 for (x = -1; x < SHOW_TRANS; x++) { 00533 char line[120]; 00534 char *buf = line; 00535 size_t left = sizeof(line) - 1; /* one initial space */ 00536 /* next 2 lines run faster than using ast_build_string() */ 00537 *buf++ = ' '; 00538 *buf = '\0'; 00539 for (y = -1; y < SHOW_TRANS; y++) { 00540 curlen = strlen(ast_getformatname(1 << (y))); 00541 00542 if (x >= 0 && y >= 0 && tr_matrix[x][y].step) { 00543 /* XXX 999 is a little hackish 00544 We don't want this number being larger than the shortest (or current) codec 00545 For now, that is "gsm" */ 00546 ast_build_string(&buf, &left, "%*d", curlen + 1, tr_matrix[x][y].cost > 999 ? 0 : tr_matrix[x][y].cost); 00547 } else if (x == -1 && y >= 0) { 00548 /* Top row - use a dynamic size */ 00549 ast_build_string(&buf, &left, "%*s", curlen + 1, ast_getformatname(1 << (x + y + 1)) ); 00550 } else if (y == -1 && x >= 0) { 00551 /* Left column - use a static size. */ 00552 ast_build_string(&buf, &left, "%*s", longest, ast_getformatname(1 << (x + y + 1)) ); 00553 } else if (x >= 0 && y >= 0) { 00554 ast_build_string(&buf, &left, "%*s", curlen + 1, "-"); 00555 } else { 00556 ast_build_string(&buf, &left, "%*s", longest, ""); 00557 } 00558 } 00559 ast_build_string(&buf, &left, "\n"); 00560 ast_cli(fd, line); 00561 } 00562 AST_LIST_UNLOCK(&translators); 00563 return RESULT_SUCCESS; 00564 }
struct ast_cli_entry cli_show_translation_deprecated [static] |
Initial value:
{ { "show", "translation", NULL }, show_translation_deprecated, NULL, NULL }
Definition at line 641 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 646 of file translate.c.
Referenced by __ast_register_translator().
char show_trans_usage[] [static] |
Definition at line 634 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().