#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 649 of file translate.c.
00650 { 00651 static int added_cli = 0; 00652 struct ast_translator *u; 00653 00654 if (!mod) { 00655 ast_log(LOG_WARNING, "Missing module pointer, you need to supply one\n"); 00656 return -1; 00657 } 00658 00659 if (!t->buf_size) { 00660 ast_log(LOG_WARNING, "empty buf size, you need to supply one\n"); 00661 return -1; 00662 } 00663 00664 t->module = mod; 00665 00666 t->srcfmt = powerof(t->srcfmt); 00667 t->dstfmt = powerof(t->dstfmt); 00668 t->active = 1; 00669 00670 if (t->plc_samples) { 00671 if (t->buffer_samples < t->plc_samples) { 00672 ast_log(LOG_WARNING, "plc_samples %d buffer_samples %d\n", 00673 t->plc_samples, t->buffer_samples); 00674 return -1; 00675 } 00676 if (t->dstfmt != powerof(AST_FORMAT_SLINEAR)) 00677 ast_log(LOG_WARNING, "plc_samples %d format %x\n", 00678 t->plc_samples, t->dstfmt); 00679 } 00680 if (t->srcfmt >= MAX_FORMAT) { 00681 ast_log(LOG_WARNING, "Source format %s is larger than MAX_FORMAT\n", ast_getformatname(t->srcfmt)); 00682 return -1; 00683 } 00684 00685 if (t->dstfmt >= MAX_FORMAT) { 00686 ast_log(LOG_WARNING, "Destination format %s is larger than MAX_FORMAT\n", ast_getformatname(t->dstfmt)); 00687 return -1; 00688 } 00689 00690 if (t->buf_size) { 00691 /* 00692 * Align buf_size properly, rounding up to the machine-specific 00693 * alignment for pointers. 00694 */ 00695 struct _test_align { void *a, *b; } p; 00696 int align = (char *)&p.b - (char *)&p.a; 00697 00698 t->buf_size = ((t->buf_size + align - 1) / align) * align; 00699 } 00700 00701 if (t->frameout == NULL) 00702 t->frameout = default_frameout; 00703 00704 calc_cost(t, 1); 00705 00706 if (option_verbose > 1) { 00707 char tmp[80]; 00708 00709 ast_verbose(VERBOSE_PREFIX_2 "Registered translator '%s' from format %s to %s, cost %d\n", 00710 term_color(tmp, t->name, COLOR_MAGENTA, COLOR_BLACK, sizeof(tmp)), 00711 ast_getformatname(1 << t->srcfmt), ast_getformatname(1 << t->dstfmt), t->cost); 00712 } 00713 00714 if (!added_cli) { 00715 ast_cli_register_multiple(cli_translate, sizeof(cli_translate) / sizeof(struct ast_cli_entry)); 00716 added_cli++; 00717 } 00718 00719 AST_LIST_LOCK(&translators); 00720 00721 /* find any existing translators that provide this same srcfmt/dstfmt, 00722 and put this one in order based on cost */ 00723 AST_LIST_TRAVERSE_SAFE_BEGIN(&translators, u, list) { 00724 if ((u->srcfmt == t->srcfmt) && 00725 (u->dstfmt == t->dstfmt) && 00726 (u->cost > t->cost)) { 00727 AST_LIST_INSERT_BEFORE_CURRENT(&translators, t, list); 00728 t = NULL; 00729 } 00730 } 00731 AST_LIST_TRAVERSE_SAFE_END; 00732 00733 /* if no existing translator was found for this format combination, 00734 add it to the beginning of the list */ 00735 if (t) 00736 AST_LIST_INSERT_HEAD(&translators, t, list); 00737 00738 rebuild_matrix(0); 00739 00740 AST_LIST_UNLOCK(&translators); 00741 00742 return 0; 00743 }
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.
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.
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 854 of file translate.c.
Referenced by sip_call().
00855 { 00856 unsigned int res = dest; 00857 unsigned int x; 00858 unsigned int src_audio = src & AST_FORMAT_AUDIO_MASK; 00859 unsigned int src_video = src & AST_FORMAT_VIDEO_MASK; 00860 00861 /* if we don't have a source format, we just have to try all 00862 possible destination formats */ 00863 if (!src) 00864 return dest; 00865 00866 /* If we have a source audio format, get its format index */ 00867 if (src_audio) 00868 src_audio = powerof(src_audio); 00869 00870 /* If we have a source video format, get its format index */ 00871 if (src_video) 00872 src_video = powerof(src_video); 00873 00874 AST_LIST_LOCK(&translators); 00875 00876 /* For a given source audio format, traverse the list of 00877 known audio formats to determine whether there exists 00878 a translation path from the source format to the 00879 destination format. */ 00880 for (x = 1; src_audio && x < AST_FORMAT_MAX_AUDIO; x <<= 1) { 00881 /* if this is not a desired format, nothing to do */ 00882 if (!dest & x) 00883 continue; 00884 00885 /* if the source is supplying this format, then 00886 we can leave it in the result */ 00887 if (src & x) 00888 continue; 00889 00890 /* if we don't have a translation path from the src 00891 to this format, remove it from the result */ 00892 if (!tr_matrix[src_audio][powerof(x)].step) { 00893 res &= ~x; 00894 continue; 00895 } 00896 00897 /* now check the opposite direction */ 00898 if (!tr_matrix[powerof(x)][src_audio].step) 00899 res &= ~x; 00900 } 00901 00902 /* For a given source video format, traverse the list of 00903 known video formats to determine whether there exists 00904 a translation path from the source format to the 00905 destination format. */ 00906 for (; src_video && x < AST_FORMAT_MAX_VIDEO; x <<= 1) { 00907 /* if this is not a desired format, nothing to do */ 00908 if (!dest & x) 00909 continue; 00910 00911 /* if the source is supplying this format, then 00912 we can leave it in the result */ 00913 if (src & x) 00914 continue; 00915 00916 /* if we don't have a translation path from the src 00917 to this format, remove it from the result */ 00918 if (!tr_matrix[src_video][powerof(x)].step) { 00919 res &= ~x; 00920 continue; 00921 } 00922 00923 /* now check the opposite direction */ 00924 if (!tr_matrix[powerof(x)][src_video].step) 00925 res &= ~x; 00926 } 00927 00928 AST_LIST_UNLOCK(&translators); 00929 00930 return res; 00931 }
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 836 of file translate.c.
Referenced by ast_channel_make_compatible().
00837 { 00838 unsigned int res = -1; 00839 00840 /* convert bitwise format numbers into array indices */ 00841 src = powerof(src); 00842 dest = powerof(dest); 00843 00844 AST_LIST_LOCK(&translators); 00845 00846 if (tr_matrix[src][dest].step) 00847 res = tr_matrix[src][dest].multistep + 1; 00848 00849 AST_LIST_UNLOCK(&translators); 00850 00851 return res; 00852 }
void ast_translator_activate | ( | struct ast_translator * | t | ) |
Activate a previously deactivated translator.
t | translator to activate |
Definition at line 772 of file translate.c.
00773 { 00774 AST_LIST_LOCK(&translators); 00775 t->active = 1; 00776 rebuild_matrix(0); 00777 AST_LIST_UNLOCK(&translators); 00778 }
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 789 of file translate.c.
Referenced by ast_channel_make_compatible(), ast_request(), iax2_request(), and set_format().
00790 { 00791 int x,y; 00792 int best = -1; 00793 int bestdst = 0; 00794 int cur, cursrc; 00795 int besttime = INT_MAX; 00796 int beststeps = INT_MAX; 00797 int common = (*dst) & (*srcs); /* are there common formats ? */ 00798 00799 if (common) { /* yes, pick one and return */ 00800 for (cur = 1, y = 0; y < MAX_FORMAT; cur <<= 1, y++) { 00801 if (cur & common) /* guaranteed to find one */ 00802 break; 00803 } 00804 /* We are done, this is a common format to both. */ 00805 *srcs = *dst = cur; 00806 return 0; 00807 } else { /* No, we will need to translate */ 00808 AST_LIST_LOCK(&translators); 00809 for (cur = 1, y = 0; y < MAX_FORMAT; cur <<= 1, y++) { 00810 if (! (cur & *dst)) 00811 continue; 00812 for (cursrc = 1, x = 0; x < MAX_FORMAT; cursrc <<= 1, x++) { 00813 if (!(*srcs & cursrc) || !tr_matrix[x][y].step || 00814 tr_matrix[x][y].cost > besttime) 00815 continue; /* not existing or no better */ 00816 if (tr_matrix[x][y].cost < besttime || 00817 tr_matrix[x][y].multistep < beststeps) { 00818 /* better than what we have so far */ 00819 best = cursrc; 00820 bestdst = cur; 00821 besttime = tr_matrix[x][y].cost; 00822 beststeps = tr_matrix[x][y].multistep; 00823 } 00824 } 00825 } 00826 AST_LIST_UNLOCK(&translators); 00827 if (best > -1) { 00828 *srcs = best; 00829 *dst = bestdst; 00830 best = 0; 00831 } 00832 return best; 00833 } 00834 }
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.
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 780 of file translate.c.
00781 { 00782 AST_LIST_LOCK(&translators); 00783 t->active = 0; 00784 rebuild_matrix(0); 00785 AST_LIST_UNLOCK(&translators); 00786 }
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.
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 746 of file translate.c.
Referenced by drop_translator(), load_module(), unload_module(), and unregister_translators().
00747 { 00748 char tmp[80]; 00749 struct ast_translator *u; 00750 int found = 0; 00751 00752 AST_LIST_LOCK(&translators); 00753 AST_LIST_TRAVERSE_SAFE_BEGIN(&translators, u, list) { 00754 if (u == t) { 00755 AST_LIST_REMOVE_CURRENT(&translators, list); 00756 if (option_verbose > 1) 00757 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)); 00758 found = 1; 00759 break; 00760 } 00761 } 00762 AST_LIST_TRAVERSE_SAFE_END; 00763 00764 if (found) 00765 rebuild_matrix(0); 00766 00767 AST_LIST_UNLOCK(&translators); 00768 00769 return (u ? 0 : -1); 00770 }
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 562 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.
00563 { 00564 int x, y, z; 00565 int curlen = 0, longest = 0; 00566 00567 if (argc > 5) 00568 return RESULT_SHOWUSAGE; 00569 00570 AST_LIST_LOCK(&translators); 00571 00572 if (argv[3] && !strcasecmp(argv[3], "recalc")) { 00573 z = argv[4] ? atoi(argv[4]) : 1; 00574 00575 if (z <= 0) { 00576 ast_cli(fd, " C'mon let's be serious here... defaulting to 1.\n"); 00577 z = 1; 00578 } 00579 00580 if (z > MAX_RECALC) { 00581 ast_cli(fd, " Maximum limit of recalc exceeded by %d, truncating value to %d\n", z - MAX_RECALC, MAX_RECALC); 00582 z = MAX_RECALC; 00583 } 00584 ast_cli(fd, " Recalculating Codec Translation (number of sample seconds: %d)\n\n", z); 00585 rebuild_matrix(z); 00586 } 00587 00588 ast_cli(fd, " Translation times between formats (in milliseconds) for one second of data\n"); 00589 ast_cli(fd, " Source Format (Rows) Destination Format (Columns)\n\n"); 00590 /* Get the length of the longest (usable?) codec name, so we know how wide the left side should be */ 00591 for (x = 0; x < SHOW_TRANS; x++) { 00592 curlen = strlen(ast_getformatname(1 << (x + 1))); 00593 if (curlen > longest) 00594 longest = curlen; 00595 } 00596 for (x = -1; x < SHOW_TRANS; x++) { 00597 char line[120]; 00598 char *buf = line; 00599 size_t left = sizeof(line) - 1; /* one initial space */ 00600 /* next 2 lines run faster than using ast_build_string() */ 00601 *buf++ = ' '; 00602 *buf = '\0'; 00603 for (y = -1; y < SHOW_TRANS; y++) { 00604 curlen = strlen(ast_getformatname(1 << (y))); 00605 00606 if (x >= 0 && y >= 0 && tr_matrix[x][y].step) { 00607 /* XXX 999 is a little hackish 00608 We don't want this number being larger than the shortest (or current) codec 00609 For now, that is "gsm" */ 00610 ast_build_string(&buf, &left, "%*d", curlen + 1, tr_matrix[x][y].cost > 999 ? 0 : tr_matrix[x][y].cost); 00611 } else if (x == -1 && y >= 0) { 00612 /* Top row - use a dynamic size */ 00613 ast_build_string(&buf, &left, "%*s", curlen + 1, ast_getformatname(1 << (x + y + 1)) ); 00614 } else if (y == -1 && x >= 0) { 00615 /* Left column - use a static size. */ 00616 ast_build_string(&buf, &left, "%*s", longest, ast_getformatname(1 << (x + y + 1)) ); 00617 } else if (x >= 0 && y >= 0) { 00618 ast_build_string(&buf, &left, "%*s", curlen + 1, "-"); 00619 } else { 00620 ast_build_string(&buf, &left, "%*s", longest, ""); 00621 } 00622 } 00623 ast_build_string(&buf, &left, "\n"); 00624 ast_cli(fd, line); 00625 } 00626 AST_LIST_UNLOCK(&translators); 00627 return RESULT_SUCCESS; 00628 }
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 + 1))); 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 curlen = strlen(ast_getformatname(1 << (y))); 00537 00538 if (x >= 0 && y >= 0 && tr_matrix[x][y].step) { 00539 /* XXX 999 is a little hackish 00540 We don't want this number being larger than the shortest (or current) codec 00541 For now, that is "gsm" */ 00542 ast_build_string(&buf, &left, "%*d", curlen + 1, tr_matrix[x][y].cost > 999 ? 0 : tr_matrix[x][y].cost); 00543 } else if (x == -1 && y >= 0) { 00544 /* Top row - use a dynamic size */ 00545 ast_build_string(&buf, &left, "%*s", curlen + 1, ast_getformatname(1 << (x + y + 1)) ); 00546 } else if (y == -1 && x >= 0) { 00547 /* Left column - use a static size. */ 00548 ast_build_string(&buf, &left, "%*s", longest, ast_getformatname(1 << (x + y + 1)) ); 00549 } else if (x >= 0 && y >= 0) { 00550 ast_build_string(&buf, &left, "%*s", curlen + 1, "-"); 00551 } else { 00552 ast_build_string(&buf, &left, "%*s", longest, ""); 00553 } 00554 } 00555 ast_build_string(&buf, &left, "\n"); 00556 ast_cli(fd, line); 00557 } 00558 AST_LIST_UNLOCK(&translators); 00559 return RESULT_SUCCESS; 00560 }
struct ast_cli_entry cli_show_translation_deprecated [static] |
Initial value:
{ { "show", "translation", NULL }, show_translation_deprecated, NULL, NULL }
Definition at line 637 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 642 of file translate.c.
char show_trans_usage[] [static] |
Definition at line 630 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().