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