Mon May 14 04:51:43 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 a translator This registers a codec translator with asterisk.
static AST_LIST_HEAD_STATIC (translators, ast_translator)
 the list of translators
ast_frameast_trans_frameout (struct ast_trans_pvt *pvt, int datalen, int samples)
 generic frameout function
ast_frameast_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_pvtast_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_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 module 
)

Register a translator This registers a codec translator with asterisk.

Parameters:
t populated ast_translator structure
module handle to the module that owns this translator
Returns:
0 on success, -1 on failure

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

Parameters:
tr translator structure to use for translation
f frame to translate
consume Whether or not to free the original frame
Returns:
an ast_frame of the new translation format on success, NULL on failure

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.

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

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

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.

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

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?

Returns:
Returns 0 on success, -1 if no path could be found.
Note:
Modifies dests and srcs in place

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.

Parameters:
dest destination format
source source format
Returns:
ast_trans_pvt on success, NULL on failure

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.

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

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.

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

Parameters:
t translator to unregister
Returns:
0 on success, -1 on failure

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.

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

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 }


Variable Documentation

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


Generated on Mon May 14 04:51:44 2007 for Asterisk - the Open Source PBX by  doxygen 1.5.1