Fri Aug 24 02:28:44 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 653 of file translate.c.

References ast_cli_register_multiple(), AST_FORMAT_SLINEAR, ast_getformatname(), AST_LIST_INSERT_BEFORE_CURRENT, AST_LIST_INSERT_HEAD, AST_LIST_LOCK, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, AST_LIST_UNLOCK, ast_log(), ast_verbose(), calc_cost(), cli_translate, COLOR_BLACK, COLOR_MAGENTA, ast_translator::cost, default_frameout(), ast_translator::dstfmt, LOG_WARNING, MAX_FORMAT, option_verbose, powerof(), rebuild_matrix(), ast_translator::srcfmt, t, term_color(), and VERBOSE_PREFIX_2.

00654 {
00655    static int added_cli = 0;
00656    struct ast_translator *u;
00657 
00658    if (!mod) {
00659       ast_log(LOG_WARNING, "Missing module pointer, you need to supply one\n");
00660       return -1;
00661    }
00662 
00663    if (!t->buf_size) {
00664       ast_log(LOG_WARNING, "empty buf size, you need to supply one\n");
00665       return -1;
00666    }
00667 
00668    t->module = mod;
00669 
00670    t->srcfmt = powerof(t->srcfmt);
00671    t->dstfmt = powerof(t->dstfmt);
00672    t->active = 1;
00673 
00674    if (t->plc_samples) {
00675       if (t->buffer_samples < t->plc_samples) {
00676          ast_log(LOG_WARNING, "plc_samples %d buffer_samples %d\n",
00677             t->plc_samples, t->buffer_samples);
00678          return -1;
00679       }
00680       if (t->dstfmt != powerof(AST_FORMAT_SLINEAR))
00681          ast_log(LOG_WARNING, "plc_samples %d format %x\n",
00682             t->plc_samples, t->dstfmt);
00683    }
00684    if (t->srcfmt >= MAX_FORMAT) {
00685       ast_log(LOG_WARNING, "Source format %s is larger than MAX_FORMAT\n", ast_getformatname(t->srcfmt));
00686       return -1;
00687    }
00688 
00689    if (t->dstfmt >= MAX_FORMAT) {
00690       ast_log(LOG_WARNING, "Destination format %s is larger than MAX_FORMAT\n", ast_getformatname(t->dstfmt));
00691       return -1;
00692    }
00693 
00694    if (t->buf_size) {
00695                /*
00696       * Align buf_size properly, rounding up to the machine-specific
00697       * alignment for pointers.
00698       */
00699       struct _test_align { void *a, *b; } p;
00700       int align = (char *)&p.b - (char *)&p.a;
00701 
00702       t->buf_size = ((t->buf_size + align - 1) / align) * align;
00703    }
00704 
00705    if (t->frameout == NULL)
00706       t->frameout = default_frameout;
00707   
00708    calc_cost(t, 1);
00709 
00710    if (option_verbose > 1) {
00711       char tmp[80];
00712 
00713       ast_verbose(VERBOSE_PREFIX_2 "Registered translator '%s' from format %s to %s, cost %d\n",
00714              term_color(tmp, t->name, COLOR_MAGENTA, COLOR_BLACK, sizeof(tmp)),
00715              ast_getformatname(1 << t->srcfmt), ast_getformatname(1 << t->dstfmt), t->cost);
00716    }
00717 
00718    if (!added_cli) {
00719       ast_cli_register_multiple(cli_translate, sizeof(cli_translate) / sizeof(struct ast_cli_entry));
00720       added_cli++;
00721    }
00722 
00723    AST_LIST_LOCK(&translators);
00724 
00725    /* find any existing translators that provide this same srcfmt/dstfmt,
00726       and put this one in order based on cost */
00727    AST_LIST_TRAVERSE_SAFE_BEGIN(&translators, u, list) {
00728       if ((u->srcfmt == t->srcfmt) &&
00729           (u->dstfmt == t->dstfmt) &&
00730           (u->cost > t->cost)) {
00731          AST_LIST_INSERT_BEFORE_CURRENT(&translators, t, list);
00732          t = NULL;
00733       }
00734    }
00735    AST_LIST_TRAVERSE_SAFE_END;
00736 
00737    /* if no existing translator was found for this format combination,
00738       add it to the beginning of the list */
00739    if (t)
00740       AST_LIST_INSERT_HEAD(&translators, t, list);
00741 
00742    rebuild_matrix(0);
00743 
00744    AST_LIST_UNLOCK(&translators);
00745 
00746    return 0;
00747 }

static AST_LIST_HEAD_STATIC ( translators  ,
ast_translator   
) [static]

the list of translators

struct ast_frame* ast_trans_frameout ( struct ast_trans_pvt pvt,
int  datalen,
int  samples 
)

generic frameout function

Definition at line 213 of file translate.c.

References AST_FRAME_VOICE, AST_FRIENDLY_OFFSET, ast_trans_pvt::datalen, ast_translator::dstfmt, f, ast_trans_pvt::f, ast_translator::name, ast_trans_pvt::outbuf, ast_trans_pvt::samples, and ast_trans_pvt::t.

Referenced by default_frameout(), lintoadpcm_frameout(), lintogsm_frameout(), lintoilbc_frameout(), and lintolpc10_frameout().

00215 {
00216    struct ast_frame *f = &pvt->f;
00217 
00218         if (samples)
00219       f->samples = samples;
00220    else {
00221       if (pvt->samples == 0)
00222          return NULL;
00223       f->samples = pvt->samples;
00224       pvt->samples = 0;
00225    }
00226    if (datalen)
00227       f->datalen = datalen;
00228    else {
00229       f->datalen = pvt->datalen;
00230       pvt->datalen = 0;
00231    }
00232 
00233    f->frametype = AST_FRAME_VOICE;
00234    f->subclass = 1 << (pvt->t->dstfmt);
00235    f->mallocd = 0;
00236    f->offset = AST_FRIENDLY_OFFSET;
00237    f->src = pvt->t->name;
00238    f->data = pvt->outbuf;
00239    return f;
00240 }

struct ast_frame* ast_translate ( struct ast_trans_pvt tr,
struct ast_frame f,
int  consume 
)

translates one or more frames Apply an input frame into the translator and receive zero or one output frames. Consume determines whether the original frame should be freed

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 299 of file translate.c.

References AST_FRAME_CNG, ast_frfree(), ast_tvadd(), ast_tvsub(), ast_frame::delivery, f, framein(), ast_frame::frametype, ast_frame::has_timing_info, len, ast_frame::len, ast_trans_pvt::next, ast_trans_pvt::nextin, ast_trans_pvt::nextout, ast_frame::samples, ast_frame::seqno, and ast_frame::ts.

Referenced by __ast_read(), ast_slinfactory_feed(), ast_write(), ast_writestream(), conf_run(), process_ast_dsp(), and queue_frame_to_spies().

00300 {
00301    struct ast_trans_pvt *p = path;
00302    struct ast_frame *out = f;
00303    struct timeval delivery;
00304    int has_timing_info;
00305    long ts;
00306    long len;
00307    int seqno;
00308 
00309    has_timing_info = f->has_timing_info;
00310    ts = f->ts;
00311    len = f->len;
00312    seqno = f->seqno;
00313 
00314    /* XXX hmmm... check this below */
00315    if (!ast_tvzero(f->delivery)) {
00316       if (!ast_tvzero(path->nextin)) {
00317          /* Make sure this is in line with what we were expecting */
00318          if (!ast_tveq(path->nextin, f->delivery)) {
00319             /* The time has changed between what we expected and this
00320                most recent time on the new packet.  If we have a
00321                valid prediction adjust our output time appropriately */
00322             if (!ast_tvzero(path->nextout)) {
00323                path->nextout = ast_tvadd(path->nextout,
00324                           ast_tvsub(f->delivery, path->nextin));
00325             }
00326             path->nextin = f->delivery;
00327          }
00328       } else {
00329          /* This is our first pass.  Make sure the timing looks good */
00330          path->nextin = f->delivery;
00331          path->nextout = f->delivery;
00332       }
00333       /* Predict next incoming sample */
00334       path->nextin = ast_tvadd(path->nextin, ast_samp2tv(f->samples, 8000));
00335    }
00336    delivery = f->delivery;
00337    for ( ; out && p ; p = p->next) {
00338       framein(p, out);
00339       out = p->t->frameout(p);
00340    }
00341    if (consume)
00342       ast_frfree(f);
00343    if (out == NULL)
00344       return NULL;
00345    /* we have a frame, play with times */
00346    if (!ast_tvzero(delivery)) {
00347       /* Regenerate prediction after a discontinuity */
00348       if (ast_tvzero(path->nextout))
00349          path->nextout = ast_tvnow();
00350 
00351       /* Use next predicted outgoing timestamp */
00352       out->delivery = path->nextout;
00353       
00354       /* Predict next outgoing timestamp from samples in this
00355          frame. */
00356       path->nextout = ast_tvadd(path->nextout, ast_samp2tv( out->samples, 8000));
00357    } else {
00358       out->delivery = ast_tv(0, 0);
00359       out->has_timing_info = has_timing_info;
00360       if (has_timing_info) {
00361          out->ts = ts;
00362          out->len = len;
00363          out->seqno = seqno;
00364       }
00365    }
00366    /* Invalidate prediction if we're entering a silence period */
00367    if (out->frametype == AST_FRAME_CNG)
00368       path->nextout = ast_tv(0, 0);
00369    return out;
00370 }

unsigned int ast_translate_available_formats ( unsigned int  dest,
unsigned int  src 
)

Mask off unavailable formats from a format bitmask.

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 858 of file translate.c.

References AST_FORMAT_AUDIO_MASK, AST_FORMAT_MAX_AUDIO, AST_FORMAT_MAX_VIDEO, AST_FORMAT_VIDEO_MASK, AST_LIST_LOCK, AST_LIST_UNLOCK, powerof(), and tr_matrix.

Referenced by sip_call().

00859 {
00860    unsigned int res = dest;
00861    unsigned int x;
00862    unsigned int src_audio = src & AST_FORMAT_AUDIO_MASK;
00863    unsigned int src_video = src & AST_FORMAT_VIDEO_MASK;
00864 
00865    /* if we don't have a source format, we just have to try all
00866       possible destination formats */
00867    if (!src)
00868       return dest;
00869 
00870    /* If we have a source audio format, get its format index */
00871    if (src_audio)
00872       src_audio = powerof(src_audio);
00873 
00874    /* If we have a source video format, get its format index */
00875    if (src_video)
00876       src_video = powerof(src_video);
00877 
00878    AST_LIST_LOCK(&translators);
00879 
00880    /* For a given source audio format, traverse the list of
00881       known audio formats to determine whether there exists
00882       a translation path from the source format to the
00883       destination format. */
00884    for (x = 1; src_audio && x < AST_FORMAT_MAX_AUDIO; x <<= 1) {
00885       /* if this is not a desired format, nothing to do */
00886       if (!dest & x)
00887          continue;
00888 
00889       /* if the source is supplying this format, then
00890          we can leave it in the result */
00891       if (src & x)
00892          continue;
00893 
00894       /* if we don't have a translation path from the src
00895          to this format, remove it from the result */
00896       if (!tr_matrix[src_audio][powerof(x)].step) {
00897          res &= ~x;
00898          continue;
00899       }
00900 
00901       /* now check the opposite direction */
00902       if (!tr_matrix[powerof(x)][src_audio].step)
00903          res &= ~x;
00904    }
00905 
00906    /* For a given source video format, traverse the list of
00907       known video formats to determine whether there exists
00908       a translation path from the source format to the
00909       destination format. */
00910    for (; src_video && x < AST_FORMAT_MAX_VIDEO; x <<= 1) {
00911       /* if this is not a desired format, nothing to do */
00912       if (!dest & x)
00913          continue;
00914 
00915       /* if the source is supplying this format, then
00916          we can leave it in the result */
00917       if (src & x)
00918          continue;
00919 
00920       /* if we don't have a translation path from the src
00921          to this format, remove it from the result */
00922       if (!tr_matrix[src_video][powerof(x)].step) {
00923          res &= ~x;
00924          continue;
00925       }
00926 
00927       /* now check the opposite direction */
00928       if (!tr_matrix[powerof(x)][src_video].step)
00929          res &= ~x;
00930    }
00931 
00932    AST_LIST_UNLOCK(&translators);
00933 
00934    return res;
00935 }

unsigned int ast_translate_path_steps ( unsigned int  dest,
unsigned int  src 
)

Returns the number of steps required to convert from 'src' to 'dest'.

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

Definition at line 840 of file translate.c.

References AST_LIST_LOCK, AST_LIST_UNLOCK, translator_path::multistep, powerof(), and tr_matrix.

Referenced by ast_channel_make_compatible().

00841 {
00842    unsigned int res = -1;
00843 
00844    /* convert bitwise format numbers into array indices */
00845    src = powerof(src);
00846    dest = powerof(dest);
00847 
00848    AST_LIST_LOCK(&translators);
00849 
00850    if (tr_matrix[src][dest].step)
00851       res = tr_matrix[src][dest].multistep + 1;
00852 
00853    AST_LIST_UNLOCK(&translators);
00854 
00855    return res;
00856 }

void ast_translator_activate ( struct ast_translator t  ) 

Activate a previously deactivated translator.

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

Definition at line 776 of file translate.c.

References AST_LIST_LOCK, AST_LIST_UNLOCK, rebuild_matrix(), and t.

00777 {
00778    AST_LIST_LOCK(&translators);
00779    t->active = 1;
00780    rebuild_matrix(0);
00781    AST_LIST_UNLOCK(&translators);
00782 }

int ast_translator_best_choice ( int *  dsts,
int *  srcs 
)

Chooses the best translation path.

Given a list of sources, and a designed destination format, which should I choose?

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

Definition at line 793 of file translate.c.

References AST_LIST_LOCK, AST_LIST_UNLOCK, ast_translator::cost, translator_path::cost, MAX_FORMAT, translator_path::multistep, and tr_matrix.

Referenced by ast_channel_make_compatible(), ast_request(), iax2_request(), and set_format().

00794 {
00795    int x,y;
00796    int best = -1;
00797    int bestdst = 0;
00798    int cur, cursrc;
00799    int besttime = INT_MAX;
00800    int beststeps = INT_MAX;
00801    int common = (*dst) & (*srcs);   /* are there common formats ? */
00802 
00803    if (common) { /* yes, pick one and return */
00804       for (cur = 1, y = 0; y < MAX_FORMAT; cur <<= 1, y++) {
00805          if (cur & common) /* guaranteed to find one */
00806             break;
00807       }
00808       /* We are done, this is a common format to both. */
00809       *srcs = *dst = cur;
00810       return 0;
00811    } else { /* No, we will need to translate */
00812       AST_LIST_LOCK(&translators);
00813       for (cur = 1, y = 0; y < MAX_FORMAT; cur <<= 1, y++) {
00814          if (! (cur & *dst))
00815             continue;
00816          for (cursrc = 1, x = 0; x < MAX_FORMAT; cursrc <<= 1, x++) {
00817             if (!(*srcs & cursrc) || !tr_matrix[x][y].step ||
00818                 tr_matrix[x][y].cost >  besttime)
00819                continue;   /* not existing or no better */
00820             if (tr_matrix[x][y].cost < besttime ||
00821                 tr_matrix[x][y].multistep < beststeps) {
00822                /* better than what we have so far */
00823                best = cursrc;
00824                bestdst = cur;
00825                besttime = tr_matrix[x][y].cost;
00826                beststeps = tr_matrix[x][y].multistep;
00827             }
00828          }
00829       }
00830       AST_LIST_UNLOCK(&translators);
00831       if (best > -1) {
00832          *srcs = best;
00833          *dst = bestdst;
00834          best = 0;
00835       }
00836       return best;
00837    }
00838 }

struct ast_trans_pvt* ast_translator_build_path ( int  dest,
int  source 
)

Builds a translator path Build a path (possibly NULL) from source to dest.

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

Definition at line 259 of file translate.c.

References ast_getformatname(), AST_LIST_LOCK, AST_LIST_UNLOCK, ast_log(), ast_translator_free_path(), ast_translator::dstfmt, LOG_WARNING, newpvt(), ast_trans_pvt::next, ast_trans_pvt::nextin, ast_trans_pvt::nextout, powerof(), translator_path::step, t, ast_trans_pvt::t, and tr_matrix.

Referenced by ast_slinfactory_feed(), ast_write(), ast_writestream(), conf_run(), misdn_set_opt_exec(), queue_frame_to_spies(), read_config(), and set_format().

00260 {
00261    struct ast_trans_pvt *head = NULL, *tail = NULL;
00262    
00263    source = powerof(source);
00264    dest = powerof(dest);
00265    
00266    AST_LIST_LOCK(&translators);
00267 
00268    while (source != dest) {
00269       struct ast_trans_pvt *cur;
00270       struct ast_translator *t = tr_matrix[source][dest].step;
00271       if (!t) {
00272          ast_log(LOG_WARNING, "No translator path from %s to %s\n", 
00273             ast_getformatname(source), ast_getformatname(dest));
00274          AST_LIST_UNLOCK(&translators);
00275          return NULL;
00276       }
00277       if (!(cur = newpvt(t))) {
00278          ast_log(LOG_WARNING, "Failed to build translator step from %d to %d\n", source, dest);
00279          if (head)
00280             ast_translator_free_path(head);  
00281          AST_LIST_UNLOCK(&translators);
00282          return NULL;
00283       }
00284       if (!head)
00285          head = cur;
00286       else
00287          tail->next = cur;
00288       tail = cur;
00289       cur->nextin = cur->nextout = ast_tv(0, 0);
00290       /* Keep going if this isn't the final destination */
00291       source = cur->t->dstfmt;
00292    }
00293 
00294    AST_LIST_UNLOCK(&translators);
00295    return head;
00296 }

void ast_translator_deactivate ( struct ast_translator t  ) 

Deactivate a translator.

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

Definition at line 784 of file translate.c.

References AST_LIST_LOCK, AST_LIST_UNLOCK, rebuild_matrix(), and t.

00785 {
00786    AST_LIST_LOCK(&translators);
00787    t->active = 0;
00788    rebuild_matrix(0);
00789    AST_LIST_UNLOCK(&translators);
00790 }

void ast_translator_free_path ( struct ast_trans_pvt tr  ) 

Frees a translator path Frees the given translator path structure.

Parameters:
tr translator path to get rid of

Definition at line 249 of file translate.c.

References destroy(), and ast_trans_pvt::next.

Referenced by ast_channel_free(), ast_channel_whisper_stop(), ast_closestream(), ast_slinfactory_destroy(), ast_slinfactory_feed(), ast_translator_build_path(), ast_write(), ast_writestream(), cl_dequeue_chan(), conf_free(), free_translation(), queue_frame_to_spies(), set_format(), and spy_cleanup().

00250 {
00251    struct ast_trans_pvt *pn = p;
00252    while ( (p = pn) ) {
00253       pn = p->next;
00254       destroy(p);
00255    }
00256 }

int ast_unregister_translator ( struct ast_translator t  ) 

Unregister a translator Unregisters the given tranlator.

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

Definition at line 750 of file translate.c.

References ast_getformatname(), AST_LIST_LOCK, AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, AST_LIST_UNLOCK, ast_verbose(), COLOR_BLACK, COLOR_MAGENTA, option_verbose, rebuild_matrix(), t, term_color(), and VERBOSE_PREFIX_2.

Referenced by drop_translator(), load_module(), unload_module(), and unregister_translators().

00751 {
00752    char tmp[80];
00753    struct ast_translator *u;
00754    int found = 0;
00755 
00756    AST_LIST_LOCK(&translators);
00757    AST_LIST_TRAVERSE_SAFE_BEGIN(&translators, u, list) {
00758       if (u == t) {
00759          AST_LIST_REMOVE_CURRENT(&translators, list);
00760          if (option_verbose > 1)
00761             ast_verbose(VERBOSE_PREFIX_2 "Unregistered translator '%s' from format %s to %s\n", term_color(tmp, t->name, COLOR_MAGENTA, COLOR_BLACK, sizeof(tmp)), ast_getformatname(1 << t->srcfmt), ast_getformatname(1 << t->dstfmt));
00762          found = 1;
00763          break;
00764       }
00765    }
00766    AST_LIST_TRAVERSE_SAFE_END;
00767 
00768    if (found)
00769       rebuild_matrix(0);
00770 
00771    AST_LIST_UNLOCK(&translators);
00772 
00773    return (u ? 0 : -1);
00774 }

static void calc_cost ( struct ast_translator t,
int  seconds 
) [static]

compute the cost of a single translation step

Definition at line 373 of file translate.c.

References ast_frfree(), ast_log(), destroy(), f, framein(), LOG_WARNING, newpvt(), and t.

Referenced by __ast_register_translator(), and rebuild_matrix().

00374 {
00375    int sofar=0;
00376    struct ast_trans_pvt *pvt;
00377    struct timeval start;
00378    int cost;
00379 
00380    if (!seconds)
00381       seconds = 1;
00382    
00383    /* If they don't make samples, give them a terrible score */
00384    if (!t->sample) {
00385       ast_log(LOG_WARNING, "Translator '%s' does not produce sample frames.\n", t->name);
00386       t->cost = 99999;
00387       return;
00388    }
00389    pvt = newpvt(t);
00390    if (!pvt) {
00391       ast_log(LOG_WARNING, "Translator '%s' appears to be broken and will probably fail.\n", t->name);
00392       t->cost = 99999;
00393       return;
00394    }
00395    start = ast_tvnow();
00396    /* Call the encoder until we've processed the required number of samples */
00397    while (sofar < seconds * 8000) {
00398       struct ast_frame *f = t->sample();
00399       if (!f) {
00400          ast_log(LOG_WARNING, "Translator '%s' failed to produce a sample frame.\n", t->name);
00401          destroy(pvt);
00402          t->cost = 99999;
00403          return;
00404       }
00405       framein(pvt, f);
00406       ast_frfree(f);
00407       while ((f = t->frameout(pvt))) {
00408          sofar += f->samples;
00409          ast_frfree(f);
00410       }
00411    }
00412    cost = ast_tvdiff_ms(ast_tvnow(), start);
00413    destroy(pvt);
00414    t->cost = cost / seconds;
00415    if (!t->cost)
00416       t->cost = 1;
00417 }

static struct ast_frame* default_frameout ( struct ast_trans_pvt pvt  )  [static]

Definition at line 242 of file translate.c.

References ast_trans_frameout().

Referenced by __ast_register_translator().

00243 {
00244    return ast_trans_frameout(pvt, 0, 0);
00245 }

static void destroy ( struct ast_trans_pvt pvt  )  [static]

Definition at line 139 of file translate.c.

References ast_module_unref(), free, ast_trans_pvt::t, and t.

Referenced by ast_translator_free_path(), and calc_cost().

00140 {
00141    struct ast_translator *t = pvt->t;
00142 
00143    if (t->destroy)
00144       t->destroy(pvt);
00145    free(pvt);
00146    ast_module_unref(t->module);
00147 }

static int framein ( struct ast_trans_pvt pvt,
struct ast_frame f 
) [static]

framein wrapper, deals with plc and bound checks.

Definition at line 150 of file translate.c.

References ast_log(), ast_translator::buffer_samples, ast_trans_pvt::datalen, f, ast_trans_pvt::f, ast_translator::framein, ast_frame::has_timing_info, ast_frame::len, LOG_ERROR, LOG_WARNING, ast_translator::name, ast_translator::native_plc, ast_trans_pvt::outbuf, ast_trans_pvt::plc, plc_fillin(), plc_rx(), ast_translator::plc_samples, ast_trans_pvt::samples, ast_frame::seqno, ast_trans_pvt::t, and ast_frame::ts.

Referenced by ast_translate(), and calc_cost().

00151 {
00152    int16_t *dst = (int16_t *)pvt->outbuf;
00153    int ret;
00154    int samples = pvt->samples;   /* initial value */
00155    
00156    /* Copy the last in jb timing info to the pvt */
00157    pvt->f.has_timing_info = f->has_timing_info;
00158    pvt->f.ts = f->ts;
00159    pvt->f.len = f->len;
00160    pvt->f.seqno = f->seqno;
00161 
00162    if (f->samples == 0) {
00163       ast_log(LOG_WARNING, "no samples for %s\n", pvt->t->name);
00164    }
00165    if (pvt->t->buffer_samples) { /* do not pass empty frames to callback */
00166       if (f->datalen == 0) { /* perform PLC with nominal framesize of 20ms/160 samples */
00167          if (pvt->plc) {
00168             int l = pvt->t->plc_samples;
00169             if (pvt->samples + l > pvt->t->buffer_samples) {
00170                ast_log(LOG_WARNING, "Out of buffer space\n");
00171                return -1;
00172             }
00173             l = plc_fillin(pvt->plc, dst + pvt->samples, l);
00174             pvt->samples += l;
00175             pvt->datalen = pvt->samples * 2; /* SLIN has 2bytes for 1sample */
00176          }
00177          /* We don't want generic PLC. If the codec has native PLC, then do that */
00178          if (!pvt->t->native_plc)
00179             return 0;
00180       }
00181       if (pvt->samples + f->samples > pvt->t->buffer_samples) {
00182          ast_log(LOG_WARNING, "Out of buffer space\n");
00183          return -1;
00184       }
00185    }
00186    if ( f->data == NULL && f->datalen > 0 ) {
00187       ast_log(LOG_ERROR, "NULL pointer in frame data for %s\n", pvt->t->name);
00188       return -1;
00189    }
00190    /* we require a framein routine, wouldn't know how to do
00191     * it otherwise.
00192     */
00193    ret = pvt->t->framein(pvt, f);
00194    /* possibly store data for plc */
00195    if (!ret && pvt->plc) {
00196       int l = pvt->t->plc_samples;
00197       if (pvt->samples < l)
00198          l = pvt->samples;
00199       plc_rx(pvt->plc, dst + pvt->samples - l, l);
00200    }
00201    /* diagnostic ... */
00202    if (pvt->samples == samples)
00203       ast_log(LOG_WARNING, "%s did not update samples %d\n",
00204          pvt->t->name, pvt->samples);
00205         return ret;
00206 }

static void* newpvt ( struct ast_translator t  )  [static]

Allocate the descriptor, required outbuf space, and possibly also plc and desc.

Definition at line 99 of file translate.c.

References ast_calloc, AST_FRIENDLY_OFFSET, ast_module_ref(), free, len, ast_trans_pvt::pvt, and t.

Referenced by ast_translator_build_path(), and calc_cost().

00100 {
00101    struct ast_trans_pvt *pvt;
00102    int len;
00103    int useplc = t->plc_samples > 0 && t->useplc;   /* cache, because it can change on the fly */
00104    char *ofs;
00105 
00106    /*
00107     * compute the required size adding private descriptor,
00108     * plc, buffer, AST_FRIENDLY_OFFSET.
00109     */
00110    len = sizeof(*pvt) + t->desc_size;
00111    if (useplc)
00112       len += sizeof(plc_state_t);
00113    if (t->buf_size)
00114       len += AST_FRIENDLY_OFFSET + t->buf_size;
00115    pvt = ast_calloc(1, len);
00116    if (!pvt)
00117       return NULL;
00118    pvt->t = t;
00119    ofs = (char *)(pvt + 1);   /* pointer to data space */
00120    if (t->desc_size) {     /* first comes the descriptor */
00121       pvt->pvt = ofs;
00122       ofs += t->desc_size;
00123    }
00124    if (useplc) {        /* then plc state */
00125       pvt->plc = (plc_state_t *)ofs;
00126       ofs += sizeof(plc_state_t);
00127    }
00128    if (t->buf_size)     /* finally buffer and header */
00129       pvt->outbuf = ofs + AST_FRIENDLY_OFFSET;
00130    /* call local init routine, if present */
00131    if (t->newpvt && t->newpvt(pvt)) {
00132       free(pvt);
00133       return NULL;
00134    }
00135    ast_module_ref(t->module);
00136    return pvt;
00137 }

static force_inline int powerof ( unsigned int  d  )  [static]

returns the index of the lowest bit set

Definition at line 79 of file translate.c.

References ast_log(), and LOG_WARNING.

Referenced by __ast_register_translator(), agents_show(), ast_translate_available_formats(), ast_translate_path_steps(), and ast_translator_build_path().

00080 {
00081    int x = ffs(d);
00082 
00083    if (x)
00084       return x - 1;
00085 
00086    ast_log(LOG_WARNING, "No bits set? %d\n", d);
00087 
00088    return -1;
00089 }

static void rebuild_matrix ( int  samples  )  [static]

rebuild a translation matrix.

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

Definition at line 423 of file translate.c.

References ast_getformatname(), AST_LIST_TRAVERSE, ast_log(), calc_cost(), ast_translator::cost, LOG_DEBUG, MAX_FORMAT, option_debug, t, and tr_matrix.

Referenced by __ast_register_translator(), ast_translator_activate(), ast_translator_deactivate(), ast_unregister_translator(), show_translation(), and show_translation_deprecated().

00424 {
00425    struct ast_translator *t;
00426    int x;      /* source format index */
00427    int y;      /* intermediate format index */
00428    int z;      /* destination format index */
00429 
00430    if (option_debug)
00431       ast_log(LOG_DEBUG, "Resetting translation matrix\n");
00432 
00433    bzero(tr_matrix, sizeof(tr_matrix));
00434 
00435    /* first, compute all direct costs */
00436    AST_LIST_TRAVERSE(&translators, t, list) {
00437       if (!t->active)
00438          continue;
00439 
00440       x = t->srcfmt;
00441       z = t->dstfmt;
00442 
00443       if (samples)
00444          calc_cost(t, samples);
00445      
00446       if (!tr_matrix[x][z].step || t->cost < tr_matrix[x][z].cost) {
00447          tr_matrix[x][z].step = t;
00448          tr_matrix[x][z].cost = t->cost;
00449       }
00450    }
00451 
00452    /*
00453     * For each triple x, y, z of distinct formats, check if there is
00454     * a path from x to z through y which is cheaper than what is
00455     * currently known, and in case, update the matrix.
00456     * Repeat until the matrix is stable.
00457     */
00458    for (;;) {
00459       int changed = 0;
00460       for (x = 0; x < MAX_FORMAT; x++) {      /* source format */
00461          for (y=0; y < MAX_FORMAT; y++) {    /* intermediate format */
00462             if (x == y)                     /* skip ourselves */
00463                continue;
00464 
00465             for (z=0; z<MAX_FORMAT; z++) {  /* dst format */
00466                int newcost;
00467 
00468                if (z == x || z == y)       /* skip null conversions */
00469                   continue;
00470                if (!tr_matrix[x][y].step)  /* no path from x to y */
00471                   continue;
00472                if (!tr_matrix[y][z].step)  /* no path from y to z */
00473                   continue;
00474                newcost = tr_matrix[x][y].cost + tr_matrix[y][z].cost;
00475                if (tr_matrix[x][z].step && newcost >= tr_matrix[x][z].cost)
00476                   continue;               /* x->y->z is more expensive than
00477                                            * the existing path */
00478                /* ok, we can get from x to z via y with a cost that
00479                   is the sum of the transition from x to y and
00480                   from y to z */
00481                    
00482                tr_matrix[x][z].step = tr_matrix[x][y].step;
00483                tr_matrix[x][z].cost = newcost;
00484                tr_matrix[x][z].multistep = 1;
00485                if (option_debug)
00486                   ast_log(LOG_DEBUG, "Discovered %d cost path from %s to %s, via %d\n", tr_matrix[x][z].cost, ast_getformatname(x), ast_getformatname(z), y);
00487                changed++;
00488             }
00489          }
00490       }
00491       if (!changed)
00492          break;
00493    }
00494 }

static int show_translation ( int  fd,
int  argc,
char *  argv[] 
) [static]

Definition at line 566 of file translate.c.

References ast_build_string(), ast_cli(), ast_getformatname(), AST_LIST_LOCK, AST_LIST_UNLOCK, ast_translator::cost, MAX_RECALC, rebuild_matrix(), RESULT_SHOWUSAGE, RESULT_SUCCESS, SHOW_TRANS, and tr_matrix.

00567 {
00568    int x, y, z;
00569    int curlen = 0, longest = 0;
00570 
00571    if (argc > 5)
00572       return RESULT_SHOWUSAGE;
00573 
00574    AST_LIST_LOCK(&translators);  
00575    
00576    if (argv[3] && !strcasecmp(argv[3], "recalc")) {
00577       z = argv[4] ? atoi(argv[4]) : 1;
00578 
00579       if (z <= 0) {
00580          ast_cli(fd, "         C'mon let's be serious here... defaulting to 1.\n");
00581          z = 1;
00582       }
00583 
00584       if (z > MAX_RECALC) {
00585          ast_cli(fd, "         Maximum limit of recalc exceeded by %d, truncating value to %d\n", z - MAX_RECALC, MAX_RECALC);
00586          z = MAX_RECALC;
00587       }
00588       ast_cli(fd, "         Recalculating Codec Translation (number of sample seconds: %d)\n\n", z);
00589       rebuild_matrix(z);
00590    }
00591 
00592    ast_cli(fd, "         Translation times between formats (in milliseconds) for one second of data\n");
00593    ast_cli(fd, "          Source Format (Rows) Destination Format (Columns)\n\n");
00594    /* Get the length of the longest (usable?) codec name, so we know how wide the left side should be */
00595    for (x = 0; x < SHOW_TRANS; x++) {
00596       curlen = strlen(ast_getformatname(1 << (x + 1)));
00597       if (curlen > longest)
00598          longest = curlen;
00599    }
00600    for (x = -1; x < SHOW_TRANS; x++) {
00601       char line[120];
00602       char *buf = line;
00603       size_t left = sizeof(line) - 1;  /* one initial space */
00604       /* next 2 lines run faster than using ast_build_string() */
00605       *buf++ = ' ';
00606       *buf = '\0';
00607       for (y = -1; y < SHOW_TRANS; y++) {
00608          curlen = strlen(ast_getformatname(1 << (y)));
00609 
00610          if (x >= 0 && y >= 0 && tr_matrix[x][y].step) {
00611             /* XXX 999 is a little hackish
00612                We don't want this number being larger than the shortest (or current) codec
00613                For now, that is "gsm" */
00614             ast_build_string(&buf, &left, "%*d", curlen + 1, tr_matrix[x][y].cost > 999 ? 0 : tr_matrix[x][y].cost);
00615          } else if (x == -1 && y >= 0) {
00616             /* Top row - use a dynamic size */
00617             ast_build_string(&buf, &left, "%*s", curlen + 1, ast_getformatname(1 << (x + y + 1)) );
00618          } else if (y == -1 && x >= 0) {
00619             /* Left column - use a static size. */
00620             ast_build_string(&buf, &left, "%*s", longest, ast_getformatname(1 << (x + y + 1)) );
00621          } else if (x >= 0 && y >= 0) {
00622             ast_build_string(&buf, &left, "%*s", curlen + 1, "-");
00623          } else {
00624             ast_build_string(&buf, &left, "%*s", longest, "");
00625          }
00626       }
00627       ast_build_string(&buf, &left, "\n");
00628       ast_cli(fd, line);         
00629    }
00630    AST_LIST_UNLOCK(&translators);
00631    return RESULT_SUCCESS;
00632 }

static int show_translation_deprecated ( int  fd,
int  argc,
char *  argv[] 
) [static]

CLI "show translation" command handler.

Definition at line 497 of file translate.c.

References ast_build_string(), ast_cli(), ast_getformatname(), AST_LIST_LOCK, AST_LIST_UNLOCK, ast_translator::cost, MAX_RECALC, rebuild_matrix(), RESULT_SHOWUSAGE, RESULT_SUCCESS, SHOW_TRANS, and tr_matrix.

00498 {
00499 #define SHOW_TRANS 13
00500    int x, y, z;
00501    int curlen = 0, longest = 0;
00502 
00503    if (argc > 4) 
00504       return RESULT_SHOWUSAGE;
00505 
00506    AST_LIST_LOCK(&translators);  
00507    
00508    if (argv[2] && !strcasecmp(argv[2], "recalc")) {
00509       z = argv[3] ? atoi(argv[3]) : 1;
00510 
00511       if (z <= 0) {
00512          ast_cli(fd, "         C'mon let's be serious here... defaulting to 1.\n");
00513          z = 1;
00514       }
00515 
00516       if (z > MAX_RECALC) {
00517          ast_cli(fd, "         Maximum limit of recalc exceeded by %d, truncating value to %d\n", z - MAX_RECALC, MAX_RECALC);
00518          z = MAX_RECALC;
00519       }
00520       ast_cli(fd, "         Recalculating Codec Translation (number of sample seconds: %d)\n\n", z);
00521       rebuild_matrix(z);
00522    }
00523 
00524    ast_cli(fd, "         Translation times between formats (in milliseconds) for one second of data\n");
00525    ast_cli(fd, "          Source Format (Rows) Destination Format (Columns)\n\n");
00526    /* Get the length of the longest (usable?) codec name, so we know how wide the left side should be */
00527    for (x = 0; x < SHOW_TRANS; x++) {
00528       curlen = strlen(ast_getformatname(1 << (x + 1)));
00529       if (curlen > longest)
00530          longest = curlen;
00531    }
00532    for (x = -1; x < SHOW_TRANS; x++) {
00533       char line[120];
00534       char *buf = line;
00535       size_t left = sizeof(line) - 1;  /* one initial space */
00536       /* next 2 lines run faster than using ast_build_string() */
00537       *buf++ = ' ';
00538       *buf = '\0';
00539       for (y = -1; y < SHOW_TRANS; y++) {
00540          curlen = strlen(ast_getformatname(1 << (y)));
00541 
00542          if (x >= 0 && y >= 0 && tr_matrix[x][y].step) {
00543             /* XXX 999 is a little hackish
00544                We don't want this number being larger than the shortest (or current) codec
00545                For now, that is "gsm" */
00546             ast_build_string(&buf, &left, "%*d", curlen + 1, tr_matrix[x][y].cost > 999 ? 0 : tr_matrix[x][y].cost);
00547          } else if (x == -1 && y >= 0) {
00548             /* Top row - use a dynamic size */
00549             ast_build_string(&buf, &left, "%*s", curlen + 1, ast_getformatname(1 << (x + y + 1)) );
00550          } else if (y == -1 && x >= 0) {
00551             /* Left column - use a static size. */
00552             ast_build_string(&buf, &left, "%*s", longest, ast_getformatname(1 << (x + y + 1)) );
00553          } else if (x >= 0 && y >= 0) {
00554             ast_build_string(&buf, &left, "%*s", curlen + 1, "-");
00555          } else {
00556             ast_build_string(&buf, &left, "%*s", longest, "");
00557          }
00558       }
00559       ast_build_string(&buf, &left, "\n");
00560       ast_cli(fd, line);         
00561    }
00562    AST_LIST_UNLOCK(&translators);
00563    return RESULT_SUCCESS;
00564 }


Variable Documentation

struct ast_cli_entry cli_show_translation_deprecated [static]

Initial value:

 {
   { "show", "translation", NULL },
   show_translation_deprecated, NULL,
   NULL }

Definition at line 641 of file translate.c.

struct ast_cli_entry cli_translate[] [static]

Initial value:

 {
   { { "core", "show", "translation", NULL },
   show_translation, "Display translation matrix",
   show_trans_usage, NULL, &cli_show_translation_deprecated },
}

Definition at line 646 of file translate.c.

Referenced by __ast_register_translator().

char show_trans_usage[] [static]

Definition at line 634 of file translate.c.

struct translator_path tr_matrix[MAX_FORMAT][MAX_FORMAT] [static]

a matrix that, for any pair of supported formats, indicates the total cost of translation and the first step. The full path can be reconstricted iterating on the matrix until step->dstfmt == desired_format.

Array indexes are 'src' and 'dest', in that order.

Note: the lock in the 'translators' list is also used to protect this structure.

Definition at line 70 of file translate.c.

Referenced by ast_translate_available_formats(), ast_translate_path_steps(), ast_translator_best_choice(), ast_translator_build_path(), rebuild_matrix(), show_translation(), and show_translation_deprecated().


Generated on Fri Aug 24 02:28:45 2007 for Asterisk - the Open Source PBX by  doxygen 1.5.1