Wed Aug 15 01:25:35 2007

Asterisk developer's documentation


translate.c File Reference

Translate via the use of pseudo channels. More...

#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 codec translator
static AST_LIST_HEAD_STATIC (translators, ast_translator)
 the list of translators
struct ast_frameast_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_frameast_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_pvtast_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_framedefault_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.


Detailed Description

Translate via the use of pseudo channels.

Author:
Mark Spencer <markster@digium.com>

Definition in file translate.c.


Define Documentation

#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().


Function Documentation

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.

Parameters:
dest possible destination formats
src source formats
Returns:
the destination formats that are available in the source or translatable
The result will include all formats from 'dest' that are either present in 'src' or translatable from a format present in 'src'.

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'.

Parameters:
dest destination format
src source format
Returns:
the number of translation steps required, or -1 if no path is available

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.

Parameters:
t translator to activate
Returns:
nothing
Enables the specified translator for use.

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.

Parameters:
t translator to deactivate
Returns:
nothing
Disables the specified translator from being used.

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.

Parameters:
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

Todo:
TODO: sample frames for each supported input format. We build this on the fly, by taking an SLIN frame and using the existing converter to play with it.

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.

Note:
This function expects the list of translators to be locked

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 }


Variable Documentation

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().


Generated on Wed Aug 15 01:25:35 2007 for Asterisk - the Open Source PBX by  doxygen 1.5.3