Sat Mar 10 01:55:49 2012

Asterisk developer's documentation


translate.c File Reference

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

#include "asterisk.h"
#include <sys/time.h>
#include <sys/resource.h>
#include <math.h>
#include "asterisk/lock.h"
#include "asterisk/channel.h"
#include "asterisk/translate.h"
#include "asterisk/module.h"
#include "asterisk/frame.h"
#include "asterisk/sched.h"
#include "asterisk/cli.h"
#include "asterisk/term.h"

Go to the source code of this file.

Data Structures

struct  translator_path
struct  translators
 the list of translators More...

Defines

#define MAX_RECALC   1000
#define SHOW_TRANS   64

Enumerations

enum  path_samp_change { RATE_CHANGE_NONE = 0, RATE_CHANGE_UPSAMP = 1, RATE_CHANGE_DOWNSAMP = 2, RATE_CHANGE_UPSAMP_DOWNSAMP = 3 }
 these values indicate how a translation path will affect the sample rate More...

Functions

int __ast_register_translator (struct ast_translator *t, struct ast_module *mod)
 Register a translator This registers a codec translator with asterisk.
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
format_t ast_translate_available_formats (format_t dest, format_t src)
 Mask off unavailable formats from a format bitmask.
unsigned int ast_translate_path_steps (format_t dest, format_t src)
 Returns the number of steps required to convert from 'src' to 'dest'.
const char * ast_translate_path_to_str (struct ast_trans_pvt *p, struct ast_str **str)
 Puts a string representation of the translation path into outbuf.
void ast_translator_activate (struct ast_translator *t)
 Activate a previously deactivated translator.
format_t ast_translator_best_choice (format_t *dst, format_t *srcs)
 Chooses the best translation path.
ast_trans_pvtast_translator_build_path (format_t dest, format_t 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 char * complete_trans_path_choice (const char *line, const char *word, int pos, int state)
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 bound checks.
static enum path_samp_change get_rate_change_result (format_t src, format_t dst)
static char * handle_cli_core_show_translation (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static void * newpvt (struct ast_translator *t)
 Allocate the descriptor, required outbuf space, and possibly desc.
static force_inline int powerof (format_t d)
 returns the index of the lowest bit set
static void rebuild_matrix (int samples)
 rebuild a translation matrix.

Variables

static struct ast_cli_entry cli_translate []
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   1000

Definition at line 43 of file translate.c.

Referenced by handle_cli_core_show_translation().

#define SHOW_TRANS   64

Referenced by handle_cli_core_show_translation().


Enumeration Type Documentation

enum path_samp_change

these values indicate how a translation path will affect the sample rate

Note:
These must stay in this order. They are ordered by most optimal selection first.
Enumerator:
RATE_CHANGE_NONE  path uses the same sample rate consistently
RATE_CHANGE_UPSAMP  path will up the sample rate during a translation
RATE_CHANGE_DOWNSAMP  path will have to down the sample rate during a translation.
RATE_CHANGE_UPSAMP_DOWNSAMP  path will both up and down the sample rate during translation

Definition at line 53 of file translate.c.

00053                       {
00054    RATE_CHANGE_NONE = 0, /*!< path uses the same sample rate consistently */
00055    RATE_CHANGE_UPSAMP = 1, /*!< path will up the sample rate during a translation */
00056    RATE_CHANGE_DOWNSAMP = 2, /*!< path will have to down the sample rate during a translation. */
00057    RATE_CHANGE_UPSAMP_DOWNSAMP = 3, /*!< path will both up and down the sample rate during translation */
00058 };


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

References ast_translator::active, ARRAY_LEN, ast_cli_register_multiple(), ast_getformatname(), ast_log(), AST_RWLIST_INSERT_BEFORE_CURRENT, AST_RWLIST_INSERT_HEAD, AST_RWLIST_TRAVERSE_SAFE_BEGIN, AST_RWLIST_TRAVERSE_SAFE_END, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, ast_verb, ast_translator::buf_size, calc_cost(), cli_translate, COLOR_BLACK, COLOR_MAGENTA, ast_translator::cost, default_frameout(), ast_translator::dstfmt, ast_translator::frameout, LOG_WARNING, MAX_FORMAT, ast_translator::module, ast_translator::name, powerof(), rebuild_matrix(), ast_translator::srcfmt, and term_color().

00786 {
00787    static int added_cli = 0;
00788    struct ast_translator *u;
00789    char tmp[80];
00790 
00791    if (!mod) {
00792       ast_log(LOG_WARNING, "Missing module pointer, you need to supply one\n");
00793       return -1;
00794    }
00795 
00796    if (!t->buf_size) {
00797       ast_log(LOG_WARNING, "empty buf size, you need to supply one\n");
00798       return -1;
00799    }
00800 
00801    t->module = mod;
00802 
00803    t->srcfmt = powerof(t->srcfmt);
00804    t->dstfmt = powerof(t->dstfmt);
00805    t->active = 1;
00806 
00807    if (t->srcfmt == -1 || t->dstfmt == -1) {
00808       ast_log(LOG_WARNING, "Invalid translator path: (%s codec is not valid)\n", t->srcfmt == -1 ? "starting" : "ending");
00809       return -1;
00810    }
00811    if (t->srcfmt >= MAX_FORMAT) {
00812       ast_log(LOG_WARNING, "Source format %s is larger than MAX_FORMAT\n", ast_getformatname(t->srcfmt));
00813       return -1;
00814    }
00815 
00816    if (t->dstfmt >= MAX_FORMAT) {
00817       ast_log(LOG_WARNING, "Destination format %s is larger than MAX_FORMAT\n", ast_getformatname(t->dstfmt));
00818       return -1;
00819    }
00820 
00821    if (t->buf_size) {
00822       /*
00823        * Align buf_size properly, rounding up to the machine-specific
00824        * alignment for pointers.
00825        */
00826       struct _test_align { void *a, *b; } p;
00827       int align = (char *)&p.b - (char *)&p.a;
00828 
00829       t->buf_size = ((t->buf_size + align - 1) / align) * align;
00830    }
00831 
00832    if (t->frameout == NULL)
00833       t->frameout = default_frameout;
00834   
00835    calc_cost(t, 1);
00836 
00837    ast_verb(2, "Registered translator '%s' from format %s to %s, cost %d\n",
00838              term_color(tmp, t->name, COLOR_MAGENTA, COLOR_BLACK, sizeof(tmp)),
00839              ast_getformatname(1LL << t->srcfmt), ast_getformatname(1LL << t->dstfmt), t->cost);
00840 
00841    if (!added_cli) {
00842       ast_cli_register_multiple(cli_translate, ARRAY_LEN(cli_translate));
00843       added_cli++;
00844    }
00845 
00846    AST_RWLIST_WRLOCK(&translators);
00847 
00848    /* find any existing translators that provide this same srcfmt/dstfmt,
00849       and put this one in order based on cost */
00850    AST_RWLIST_TRAVERSE_SAFE_BEGIN(&translators, u, list) {
00851       if ((u->srcfmt == t->srcfmt) &&
00852           (u->dstfmt == t->dstfmt) &&
00853           (u->cost > t->cost)) {
00854          AST_RWLIST_INSERT_BEFORE_CURRENT(t, list);
00855          t = NULL;
00856          break;
00857       }
00858    }
00859    AST_RWLIST_TRAVERSE_SAFE_END;
00860 
00861    /* if no existing translator was found for this format combination,
00862       add it to the beginning of the list */
00863    if (t)
00864       AST_RWLIST_INSERT_HEAD(&translators, t, list);
00865 
00866    rebuild_matrix(0);
00867 
00868    AST_RWLIST_UNLOCK(&translators);
00869 
00870    return 0;
00871 }

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

generic frameout function

Definition at line 191 of file translate.c.

References AST_FRAME_VOICE, AST_FRIENDLY_OFFSET, ast_frisolate(), ast_trans_pvt::c, ast_trans_pvt::datalen, ast_translator::dstfmt, ast_trans_pvt::f, 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().

00193 {
00194    struct ast_frame *f = &pvt->f;
00195 
00196    if (samples)
00197       f->samples = samples;
00198    else {
00199       if (pvt->samples == 0)
00200          return NULL;
00201       f->samples = pvt->samples;
00202       pvt->samples = 0;
00203    }
00204    if (datalen)
00205       f->datalen = datalen;
00206    else {
00207       f->datalen = pvt->datalen;
00208       pvt->datalen = 0;
00209    }
00210 
00211    f->frametype = AST_FRAME_VOICE;
00212    f->subclass.codec = 1LL << (pvt->t->dstfmt);
00213    f->mallocd = 0;
00214    f->offset = AST_FRIENDLY_OFFSET;
00215    f->src = pvt->t->name;
00216    f->data.ptr = pvt->outbuf.c;
00217 
00218    return ast_frisolate(f);
00219 }

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

References ast_format_rate(), AST_FRAME_CNG, AST_FRFLAG_HAS_TIMING_INFO, ast_frfree, ast_samp2tv(), ast_set2_flag, ast_test_flag, ast_tv(), ast_tvadd(), ast_tveq(), ast_tvnow(), ast_tvsub(), ast_tvzero(), ast_frame_subclass::codec, ast_frame::delivery, f, framein(), ast_frame::frametype, ast_frame::len, len(), ast_trans_pvt::next, ast_trans_pvt::nextin, ast_trans_pvt::nextout, ast_frame::samples, ast_frame::seqno, ast_frame::subclass, and ast_frame::ts.

Referenced by __ast_read(), ast_audiohook_read_frame(), ast_slinfactory_feed(), ast_write(), ast_writestream(), audio_audiohook_write_list(), and conf_run().

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

format_t ast_translate_available_formats ( format_t  dest,
format_t  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:
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 1013 of file translate.c.

References AST_FORMAT_AUDIO_MASK, AST_FORMAT_VIDEO_MASK, AST_RWLIST_RDLOCK, AST_RWLIST_UNLOCK, powerof(), and tr_matrix.

Referenced by ast_rtp_instance_available_formats().

01014 {
01015    format_t res = dest;
01016    format_t x;
01017    format_t src_audio = src & AST_FORMAT_AUDIO_MASK;
01018    format_t src_video = src & AST_FORMAT_VIDEO_MASK;
01019 
01020    /* if we don't have a source format, we just have to try all
01021       possible destination formats */
01022    if (!src)
01023       return dest;
01024 
01025    /* If we have a source audio format, get its format index */
01026    if (src_audio)
01027       src_audio = powerof(src_audio);
01028 
01029    /* If we have a source video format, get its format index */
01030    if (src_video)
01031       src_video = powerof(src_video);
01032 
01033    AST_RWLIST_RDLOCK(&translators);
01034 
01035    /* For a given source audio format, traverse the list of
01036       known audio formats to determine whether there exists
01037       a translation path from the source format to the
01038       destination format. */
01039    for (x = 1LL; src_audio && x > 0; x <<= 1) {
01040       if (!(x & AST_FORMAT_AUDIO_MASK)) {
01041          continue;
01042       }
01043 
01044       /* if this is not a desired format, nothing to do */
01045       if (!(dest & x))
01046          continue;
01047 
01048       /* if the source is supplying this format, then
01049          we can leave it in the result */
01050       if (src & x)
01051          continue;
01052 
01053       /* if we don't have a translation path from the src
01054          to this format, remove it from the result */
01055       if (!tr_matrix[src_audio][powerof(x)].step) {
01056          res &= ~x;
01057          continue;
01058       }
01059 
01060       /* now check the opposite direction */
01061       if (!tr_matrix[powerof(x)][src_audio].step)
01062          res &= ~x;
01063    }
01064 
01065    /* For a given source video format, traverse the list of
01066       known video formats to determine whether there exists
01067       a translation path from the source format to the
01068       destination format. */
01069    for (x = 1LL; src_video && x > 0; x <<= 1) {
01070       if (!(x & AST_FORMAT_VIDEO_MASK)) {
01071          continue;
01072       }
01073 
01074       /* if this is not a desired format, nothing to do */
01075       if (!(dest & x))
01076          continue;
01077 
01078       /* if the source is supplying this format, then
01079          we can leave it in the result */
01080       if (src & x)
01081          continue;
01082 
01083       /* if we don't have a translation path from the src
01084          to this format, remove it from the result */
01085       if (!tr_matrix[src_video][powerof(x)].step) {
01086          res &= ~x;
01087          continue;
01088       }
01089 
01090       /* now check the opposite direction */
01091       if (!tr_matrix[powerof(x)][src_video].step)
01092          res &= ~x;
01093    }
01094 
01095    AST_RWLIST_UNLOCK(&translators);
01096 
01097    return res;
01098 }

unsigned int ast_translate_path_steps ( format_t  dest,
format_t  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 991 of file translate.c.

References ast_log(), AST_RWLIST_RDLOCK, AST_RWLIST_UNLOCK, LOG_WARNING, translator_path::multistep, powerof(), and tr_matrix.

Referenced by ast_channel_make_compatible_helper().

00992 {
00993    unsigned int res = -1;
00994 
00995    /* convert bitwise format numbers into array indices */
00996    src = powerof(src);
00997    dest = powerof(dest);
00998 
00999    if (src == -1 || dest == -1) {
01000       ast_log(LOG_WARNING, "No translator path: (%s codec is not valid)\n", src == -1 ? "starting" : "ending");
01001       return -1;
01002    }
01003    AST_RWLIST_RDLOCK(&translators);
01004 
01005    if (tr_matrix[src][dest].step)
01006       res = tr_matrix[src][dest].multistep + 1;
01007 
01008    AST_RWLIST_UNLOCK(&translators);
01009 
01010    return res;
01011 }

const char* ast_translate_path_to_str ( struct ast_trans_pvt t,
struct ast_str **  str 
)

Puts a string representation of the translation path into outbuf.

Parameters:
translator structure containing the translation path
ast_str output buffer
Return values:
on success pointer to beginning of outbuf. on failure "".

Definition at line 567 of file translate.c.

References ast_getformatname(), ast_str_append(), ast_str_buffer(), ast_str_set(), ast_translator::dstfmt, ast_trans_pvt::next, ast_translator::srcfmt, str, and ast_trans_pvt::t.

Referenced by handle_showchan(), and serialize_showchan().

00568 {
00569    struct ast_trans_pvt *pn = p;
00570 
00571    if (!p || !p->t) {
00572       return "";
00573    }
00574 
00575    ast_str_set(str, 0, "%s", ast_getformatname(1LL << p->t->srcfmt));
00576 
00577    while ( (p = pn) ) {
00578       pn = p->next;
00579       ast_str_append(str, 0, "->%s", ast_getformatname(1LL << p->t->dstfmt));
00580    }
00581 
00582    return ast_str_buffer(*str);
00583 }

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

References ast_translator::active, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, and rebuild_matrix().

00900 {
00901    AST_RWLIST_WRLOCK(&translators);
00902    t->active = 1;
00903    rebuild_matrix(0);
00904    AST_RWLIST_UNLOCK(&translators);
00905 }

format_t ast_translator_best_choice ( format_t dsts,
format_t 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 916 of file translate.c.

References AST_FORMAT_AUDIO_MASK, ast_format_rate(), AST_RWLIST_RDLOCK, AST_RWLIST_UNLOCK, translator_path::cost, ast_translator::cost, MAX_AUDIO_FORMAT, translator_path::multistep, translator_path::rate_change, and tr_matrix.

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

00917 {
00918    int x,y;
00919    int better = 0;
00920    int besttime = INT_MAX;
00921    int beststeps = INT_MAX;
00922    unsigned int best_rate_change = INT_MAX;
00923    format_t best = -1;
00924    format_t bestdst = 0;
00925    format_t cur, cursrc;
00926    format_t common = ((*dst) & (*srcs)) & AST_FORMAT_AUDIO_MASK;  /* are there common formats ? */
00927 
00928    if (common) { /* yes, pick one and return */
00929       for (cur = 1, y = 0; y <= MAX_AUDIO_FORMAT; cur <<= 1, y++) {
00930          if (!(cur & common)) {
00931             continue;
00932          }
00933 
00934          /* We are guaranteed to find one common format. */
00935          if (best == -1) {
00936             best = cur;
00937             continue;
00938          }
00939          /* If there are multiple common formats, pick the one with the highest sample rate */
00940          if (ast_format_rate(best) < ast_format_rate(cur)) {
00941             best = cur;
00942             continue;
00943          }
00944       }
00945       /* We are done, this is a common format to both. */
00946       *srcs = *dst = best;
00947       return 0;
00948    } else {      /* No, we will need to translate */
00949       AST_RWLIST_RDLOCK(&translators);
00950       for (cur = 1, y = 0; y <= MAX_AUDIO_FORMAT; cur <<= 1, y++) {
00951          if (! (cur & *dst)) {
00952             continue;
00953          }
00954          for (cursrc = 1, x = 0; x <= MAX_AUDIO_FORMAT; cursrc <<= 1, x++) {
00955             if (!(*srcs & cursrc) || !tr_matrix[x][y].step) {
00956                continue;
00957             }
00958 
00959             /* This is a better choice if any of the following are true.
00960              * 1. The sample rate conversion is better than the current pick.
00961              * 2. the sample rate conversion is no worse than the current pick and the cost or multistep is better
00962              */
00963             better = 0;
00964             if (tr_matrix[x][y].rate_change < best_rate_change) {
00965                better = 1; /* this match has a better rate conversion */
00966             }
00967             if ((tr_matrix[x][y].rate_change <= best_rate_change) &&
00968                (tr_matrix[x][y].cost < besttime || tr_matrix[x][y].multistep < beststeps)) {
00969                better = 1; /* this match has no worse rate conversion and the conversion cost is less */
00970             }
00971             if (better) {
00972                /* better than what we have so far */
00973                best = cursrc;
00974                bestdst = cur;
00975                besttime = tr_matrix[x][y].cost;
00976                beststeps = tr_matrix[x][y].multistep;
00977                best_rate_change = tr_matrix[x][y].rate_change;
00978             }
00979          }
00980       }
00981       AST_RWLIST_UNLOCK(&translators);
00982       if (best > -1) {
00983          *srcs = best;
00984          *dst = bestdst;
00985          best = 0;
00986       }
00987       return best;
00988    }
00989 }

struct ast_trans_pvt* ast_translator_build_path ( format_t  dest,
format_t  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 238 of file translate.c.

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

Referenced by ast_audiohook_read_frame(), ast_slinfactory_feed(), ast_writestream(), audio_audiohook_write_list(), conf_run(), and set_format().

00239 {
00240    struct ast_trans_pvt *head = NULL, *tail = NULL;
00241    
00242    source = powerof(source);
00243    dest = powerof(dest);
00244 
00245    if (source == -1 || dest == -1) {
00246       ast_log(LOG_WARNING, "No translator path: (%s codec is not valid)\n", source == -1 ? "starting" : "ending");
00247       return NULL;
00248    }
00249 
00250    AST_RWLIST_RDLOCK(&translators);
00251 
00252    while (source != dest) {
00253       struct ast_trans_pvt *cur;
00254       struct ast_translator *t = tr_matrix[source][dest].step;
00255       if (!t) {
00256          ast_log(LOG_WARNING, "No translator path from %s to %s\n", 
00257             ast_getformatname(source), ast_getformatname(dest));
00258          AST_RWLIST_UNLOCK(&translators);
00259          return NULL;
00260       }
00261       if (!(cur = newpvt(t))) {
00262          ast_log(LOG_WARNING, "Failed to build translator step from %s to %s\n",
00263             ast_getformatname(source), ast_getformatname(dest));
00264          if (head)
00265             ast_translator_free_path(head);  
00266          AST_RWLIST_UNLOCK(&translators);
00267          return NULL;
00268       }
00269       if (!head)
00270          head = cur;
00271       else
00272          tail->next = cur;
00273       tail = cur;
00274       cur->nextin = cur->nextout = ast_tv(0, 0);
00275       /* Keep going if this isn't the final destination */
00276       source = cur->t->dstfmt;
00277    }
00278 
00279    AST_RWLIST_UNLOCK(&translators);
00280    return head;
00281 }

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

References ast_translator::active, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, and rebuild_matrix().

00908 {
00909    AST_RWLIST_WRLOCK(&translators);
00910    t->active = 0;
00911    rebuild_matrix(0);
00912    AST_RWLIST_UNLOCK(&translators);
00913 }

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

References destroy(), and ast_trans_pvt::next.

Referenced by ast_audiohook_destroy(), ast_audiohook_detach_list(), ast_audiohook_read_frame(), ast_channel_destructor(), ast_slinfactory_destroy(), ast_slinfactory_feed(), ast_slinfactory_flush(), ast_translator_build_path(), ast_writestream(), audio_audiohook_write_list(), conf_free(), filestream_destructor(), free_translation(), and set_format().

00229 {
00230    struct ast_trans_pvt *pn = p;
00231    while ( (p = pn) ) {
00232       pn = p->next;
00233       destroy(p);
00234    }
00235 }

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

References ast_getformatname(), AST_RWLIST_REMOVE_CURRENT, AST_RWLIST_TRAVERSE_SAFE_BEGIN, AST_RWLIST_TRAVERSE_SAFE_END, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, ast_verb, COLOR_BLACK, COLOR_MAGENTA, ast_translator::dstfmt, ast_translator::list, ast_translator::name, rebuild_matrix(), ast_translator::srcfmt, and term_color().

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

00875 {
00876    char tmp[80];
00877    struct ast_translator *u;
00878    int found = 0;
00879 
00880    AST_RWLIST_WRLOCK(&translators);
00881    AST_RWLIST_TRAVERSE_SAFE_BEGIN(&translators, u, list) {
00882       if (u == t) {
00883          AST_RWLIST_REMOVE_CURRENT(list);
00884          ast_verb(2, "Unregistered translator '%s' from format %s to %s\n", term_color(tmp, t->name, COLOR_MAGENTA, COLOR_BLACK, sizeof(tmp)), ast_getformatname(1LL << t->srcfmt), ast_getformatname(1LL << t->dstfmt));
00885          found = 1;
00886          break;
00887       }
00888    }
00889    AST_RWLIST_TRAVERSE_SAFE_END;
00890 
00891    if (found)
00892       rebuild_matrix(0);
00893 
00894    AST_RWLIST_UNLOCK(&translators);
00895 
00896    return (u ? 0 : -1);
00897 }

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

compute the cost of a single translation step

Definition at line 360 of file translate.c.

References ast_format_rate(), ast_frfree, ast_log(), ast_translator::cost, destroy(), ast_translator::dstfmt, f, framein(), ast_translator::frameout, LOG_WARNING, ast_translator::name, newpvt(), ast_trans_pvt::pvt, and ast_translator::sample.

Referenced by __ast_register_translator(), and rebuild_matrix().

00361 {
00362    int num_samples = 0;
00363    struct ast_trans_pvt *pvt;
00364    struct rusage start;
00365    struct rusage end;
00366    int cost;
00367    int out_rate = ast_format_rate(t->dstfmt);
00368 
00369    if (!seconds)
00370       seconds = 1;
00371    
00372    /* If they don't make samples, give them a terrible score */
00373    if (!t->sample) {
00374       ast_log(LOG_WARNING, "Translator '%s' does not produce sample frames.\n", t->name);
00375       t->cost = 999999;
00376       return;
00377    }
00378 
00379    pvt = newpvt(t);
00380    if (!pvt) {
00381       ast_log(LOG_WARNING, "Translator '%s' appears to be broken and will probably fail.\n", t->name);
00382       t->cost = 999999;
00383       return;
00384    }
00385 
00386    getrusage(RUSAGE_SELF, &start);
00387 
00388    /* Call the encoder until we've processed the required number of samples */
00389    while (num_samples < seconds * out_rate) {
00390       struct ast_frame *f = t->sample();
00391       if (!f) {
00392          ast_log(LOG_WARNING, "Translator '%s' failed to produce a sample frame.\n", t->name);
00393          destroy(pvt);
00394          t->cost = 999999;
00395          return;
00396       }
00397       framein(pvt, f);
00398       ast_frfree(f);
00399       while ((f = t->frameout(pvt))) {
00400          num_samples += f->samples;
00401          ast_frfree(f);
00402       }
00403    }
00404 
00405    getrusage(RUSAGE_SELF, &end);
00406 
00407    cost = ((end.ru_utime.tv_sec - start.ru_utime.tv_sec) * 1000000) + end.ru_utime.tv_usec - start.ru_utime.tv_usec;
00408    cost += ((end.ru_stime.tv_sec - start.ru_stime.tv_sec) * 1000000) + end.ru_stime.tv_usec - start.ru_stime.tv_usec;
00409 
00410    destroy(pvt);
00411 
00412    t->cost = cost / seconds;
00413 
00414    if (!t->cost)
00415       t->cost = 1;
00416 }

static char* complete_trans_path_choice ( const char *  line,
const char *  word,
int  pos,
int  state 
) [static]

Definition at line 585 of file translate.c.

References AST_FORMAT_AUDIO_MASK, ast_get_format_list(), ast_strdup, ast_format_list::bits, len(), and name.

Referenced by handle_cli_core_show_translation().

00586 {
00587    int which = 0;
00588    int wordlen = strlen(word);
00589    int i;
00590    char *ret = NULL;
00591    size_t len = 0;
00592    const struct ast_format_list *format_list = ast_get_format_list(&len);
00593 
00594    for (i = 0; i < len; i++) {
00595       if (!(format_list[i].bits & AST_FORMAT_AUDIO_MASK)) {
00596          continue;
00597       }
00598       if (!strncasecmp(word, format_list[i].name, wordlen) && ++which > state) {
00599          ret = ast_strdup(format_list[i].name);
00600          break;
00601       }
00602    }
00603    return ret;
00604 }

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

Definition at line 221 of file translate.c.

References ast_trans_frameout().

Referenced by __ast_register_translator().

00222 {
00223    return ast_trans_frameout(pvt, 0, 0);
00224 }

static void destroy ( struct ast_trans_pvt pvt  )  [static]

Definition at line 139 of file translate.c.

References ast_free, ast_module_unref(), ast_translator::destroy, ast_translator::module, and ast_trans_pvt::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    ast_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 bound checks.

Definition at line 150 of file translate.c.

References ast_copy_flags, AST_FRFLAG_HAS_TIMING_INFO, ast_log(), ast_translator::buffer_samples, f, ast_trans_pvt::f, ast_translator::framein, ast_frame::len, LOG_WARNING, ast_translator::name, ast_translator::native_plc, ast_trans_pvt::samples, ast_frame::seqno, ast_trans_pvt::t, and ast_frame::ts.

Referenced by ast_translate(), and calc_cost().

00151 {
00152    int ret;
00153    int samples = pvt->samples;   /* initial value */
00154    
00155    /* Copy the last in jb timing info to the pvt */
00156    ast_copy_flags(&pvt->f, f, AST_FRFLAG_HAS_TIMING_INFO);
00157    pvt->f.ts = f->ts;
00158    pvt->f.len = f->len;
00159    pvt->f.seqno = f->seqno;
00160 
00161    if (f->samples == 0) {
00162       ast_log(LOG_WARNING, "no samples for %s\n", pvt->t->name);
00163    }
00164    if (pvt->t->buffer_samples) { /* do not pass empty frames to callback */
00165       if (f->datalen == 0) { /* perform native PLC if available */
00166          /* If the codec has native PLC, then do that */
00167          if (!pvt->t->native_plc)
00168             return 0;
00169       }
00170       if (pvt->samples + f->samples > pvt->t->buffer_samples) {
00171          ast_log(LOG_WARNING, "Out of buffer space\n");
00172          return -1;
00173       }
00174    }
00175    /* we require a framein routine, wouldn't know how to do
00176     * it otherwise.
00177     */
00178    ret = pvt->t->framein(pvt, f);
00179    /* diagnostic ... */
00180    if (pvt->samples == samples)
00181       ast_log(LOG_WARNING, "%s did not update samples %d\n",
00182          pvt->t->name, pvt->samples);
00183    return ret;
00184 }

static enum path_samp_change get_rate_change_result ( format_t  src,
format_t  dst 
) [static]

Definition at line 418 of file translate.c.

References ast_format_rate(), RATE_CHANGE_DOWNSAMP, RATE_CHANGE_NONE, and RATE_CHANGE_UPSAMP.

Referenced by rebuild_matrix().

00419 {
00420    int src_rate = ast_format_rate(src);
00421    int dst_rate = ast_format_rate(dst);
00422 
00423    /* if src rate is less than dst rate, a sample upgrade is required */
00424    if (src_rate < dst_rate) {
00425       return RATE_CHANGE_UPSAMP;
00426    }
00427 
00428    /* if src rate is larger than dst rate, a downgrade is required */
00429    if (src_rate > dst_rate) {
00430       return RATE_CHANGE_DOWNSAMP;
00431    }
00432 
00433    return RATE_CHANGE_NONE;
00434 }

static char* handle_cli_core_show_translation ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
) [static]

Definition at line 606 of file translate.c.

References ast_cli_args::argc, ast_cli_args::argv, ast_cli(), ast_cli_complete(), AST_FORMAT_AUDIO_MASK, ast_format_rate(), ast_get_format_list(), ast_getformatname(), AST_RWLIST_RDLOCK, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, ast_str_alloca, ast_str_append(), ast_str_buffer(), ast_str_reset(), ast_str_set(), ast_strlen_zero(), CLI_FAILURE, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, complete_trans_path_choice(), ast_translator::cost, ast_cli_args::fd, len(), ast_cli_args::line, MAX_RECALC, ast_cli_args::n, ast_format_list::name, name, ast_cli_args::pos, powerof(), rebuild_matrix(), SHOW_TRANS, translator_path::step, str, tr_matrix, ast_cli_entry::usage, and ast_cli_args::word.

00607 {
00608 #define SHOW_TRANS 64
00609    static const char * const option1[] = { "recalc", "paths", NULL };
00610    int x, y, z;
00611    int curlen = 0, longest = 0, magnitude[SHOW_TRANS] = { 0, };
00612 
00613    switch (cmd) {
00614    case CLI_INIT:
00615       e->command = "core show translation";
00616       e->usage =
00617          "Usage: 'core show translation' can be used in two ways.\n"
00618          "       1. 'core show translation [recalc [<recalc seconds>]]\n"
00619          "          Displays known codec translators and the cost associated\n"
00620          "          with each conversion.  If the argument 'recalc' is supplied along\n"
00621          "          with optional number of seconds to test a new test will be performed\n"
00622          "          as the chart is being displayed.\n"
00623          "       2. 'core show translation paths [codec]'\n"
00624          "           This will display all the translation paths associated with a codec\n";
00625       return NULL;
00626    case CLI_GENERATE:
00627       if (a->pos == 3) {
00628          return ast_cli_complete(a->word, option1, a->n);
00629       }
00630       if (a->pos == 4 && !strcasecmp(a->argv[3], option1[1])) {
00631          return complete_trans_path_choice(a->line, a->word, a->pos, a->n);
00632       }
00633       return NULL;
00634    }
00635 
00636    if (a->argc > 5)
00637       return CLI_SHOWUSAGE;
00638 
00639    if (a->argv[3] && !strcasecmp(a->argv[3], option1[1]) && a->argc == 5) {
00640       format_t input_src = 0;
00641       format_t src = 0;
00642       size_t len = 0;
00643       int dst;
00644       int i;
00645       const struct ast_format_list *format_list = ast_get_format_list(&len);
00646       struct ast_str *str = ast_str_alloca(256);
00647       struct ast_translator *step;
00648 
00649       for (i = 0; i < len; i++) {
00650          if (!(format_list[i].bits & AST_FORMAT_AUDIO_MASK)) {
00651             continue;
00652          }
00653          if (!strncasecmp(format_list[i].name, a->argv[4], strlen(format_list[i].name))) {
00654             input_src = format_list[i].bits;
00655          }
00656       }
00657 
00658       if (!input_src) {
00659          ast_cli(a->fd, "Source codec \"%s\" is not found.\n", a->argv[4]);
00660          return CLI_FAILURE;
00661       }
00662 
00663       AST_RWLIST_RDLOCK(&translators);
00664       ast_cli(a->fd, "--- Translation paths SRC Codec \"%s\" sample rate %d ---\n", a->argv[4], ast_format_rate(input_src));
00665       for (i = 0; i < len; i++) {
00666          if (!(format_list[i].bits & AST_FORMAT_AUDIO_MASK) || (format_list[i].bits == input_src)) {
00667             continue;
00668          }
00669          dst = powerof(format_list[i].bits);
00670          src = powerof(input_src);
00671          ast_str_reset(str);
00672          if (tr_matrix[src][dst].step) {
00673             ast_str_append(&str, 0, "%s", ast_getformatname(1LL << tr_matrix[src][dst].step->srcfmt));
00674             while (src != dst) {
00675                step = tr_matrix[src][dst].step;
00676                if (!step) {
00677                   ast_str_reset(str);
00678                   break;
00679                }
00680                ast_str_append(&str, 0, "->%s", ast_getformatname(1LL << step->dstfmt));
00681                src = step->dstfmt;
00682             }
00683          }
00684 
00685          if (ast_strlen_zero(ast_str_buffer(str))) {
00686             ast_str_set(&str, 0, "No Translation Path");
00687          }
00688 
00689          ast_cli(a->fd, "\t%-10.10s To %-10.10s: %-60.60s\n", a->argv[4], format_list[i].name, ast_str_buffer(str));
00690       }
00691       AST_RWLIST_UNLOCK(&translators);
00692 
00693       return CLI_SUCCESS;
00694    } else if (a->argv[3] && !strcasecmp(a->argv[3], "recalc")) {
00695       z = a->argv[4] ? atoi(a->argv[4]) : 1;
00696 
00697       if (z <= 0) {
00698          ast_cli(a->fd, "         Recalc must be greater than 0.  Defaulting to 1.\n");
00699          z = 1;
00700       }
00701 
00702       if (z > MAX_RECALC) {
00703          ast_cli(a->fd, "         Maximum limit of recalc exceeded by %d, truncating value to %d\n", z - MAX_RECALC, MAX_RECALC);
00704          z = MAX_RECALC;
00705       }
00706       ast_cli(a->fd, "         Recalculating Codec Translation (number of sample seconds: %d)\n\n", z);
00707       AST_RWLIST_WRLOCK(&translators);
00708       rebuild_matrix(z);
00709       AST_RWLIST_UNLOCK(&translators);
00710    } else if (a->argc > 3)
00711       return CLI_SHOWUSAGE;
00712 
00713    AST_RWLIST_RDLOCK(&translators);
00714 
00715    ast_cli(a->fd, "         Translation times between formats (in microseconds) for one second of data\n");
00716    ast_cli(a->fd, "          Source Format (Rows) Destination Format (Columns)\n\n");
00717    /* Get the length of the longest (usable?) codec name, so we know how wide the left side should be */
00718    for (x = 0; x < SHOW_TRANS; x++) {
00719       /* translation only applies to audio right now. */
00720       if (!(AST_FORMAT_AUDIO_MASK & (1LL << (x))))
00721          continue;
00722       curlen = strlen(ast_getformatname(1LL << (x)));
00723       if (curlen > longest)
00724          longest = curlen;
00725       for (y = 0; y < SHOW_TRANS; y++) {
00726          if (!(AST_FORMAT_AUDIO_MASK & (1LL << (y))))
00727             continue;
00728          if (tr_matrix[x][y].cost > pow(10, magnitude[x])) {
00729             magnitude[y] = floor(log10(tr_matrix[x][y].cost));
00730          }
00731       }
00732    }
00733    for (x = -1; x < SHOW_TRANS; x++) {
00734       struct ast_str *out = ast_str_alloca(256);
00735       /* translation only applies to audio right now. */
00736       if (x >= 0 && !(AST_FORMAT_AUDIO_MASK & (1LL << (x))))
00737          continue;
00738       /*Go ahead and move to next iteration if dealing with an unknown codec*/
00739       if(x >= 0 && !strcmp(ast_getformatname(1LL << (x)), "unknown"))
00740          continue;
00741       ast_str_set(&out, -1, " ");
00742       for (y = -1; y < SHOW_TRANS; y++) {
00743          /* translation only applies to audio right now. */
00744          if (y >= 0 && !(AST_FORMAT_AUDIO_MASK & (1LL << (y))))
00745             continue;
00746          /*Go ahead and move to next iteration if dealing with an unknown codec*/
00747          if (y >= 0 && !strcmp(ast_getformatname(1LL << (y)), "unknown"))
00748             continue;
00749          if (y >= 0)
00750             curlen = strlen(ast_getformatname(1LL << (y)));
00751          if (y >= 0 && magnitude[y] + 1 > curlen) {
00752             curlen = magnitude[y] + 1;
00753          }
00754          if (curlen < 5)
00755             curlen = 5;
00756          if (x >= 0 && y >= 0 && tr_matrix[x][y].step) {
00757             /* Actual codec output */
00758             ast_str_append(&out, -1, "%*d", curlen + 1, tr_matrix[x][y].cost);
00759          } else if (x == -1 && y >= 0) {
00760             /* Top row - use a dynamic size */
00761             ast_str_append(&out, -1, "%*s", curlen + 1, ast_getformatname(1LL << (y)) );
00762          } else if (y == -1 && x >= 0) {
00763             /* Left column - use a static size. */
00764             ast_str_append(&out, -1, "%*s", longest, ast_getformatname(1LL << (x)) );
00765          } else if (x >= 0 && y >= 0) {
00766             /* Codec not supported */
00767             ast_str_append(&out, -1, "%*s", curlen + 1, "-");
00768          } else {
00769             /* Upper left hand corner */
00770             ast_str_append(&out, -1, "%*s", longest, "");
00771          }
00772       }
00773       ast_str_append(&out, -1, "\n");
00774       ast_cli(a->fd, "%s", ast_str_buffer(out));
00775    }
00776    AST_RWLIST_UNLOCK(&translators);
00777    return CLI_SUCCESS;
00778 }

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

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

Definition at line 106 of file translate.c.

References ast_calloc, ast_free, AST_FRIENDLY_OFFSET, ast_module_ref(), ast_translator::buf_size, ast_translator::desc_size, len(), ast_translator::module, ast_translator::newpvt, ast_trans_pvt::pvt, and ast_trans_pvt::t.

Referenced by ast_translator_build_path(), and calc_cost().

00107 {
00108    struct ast_trans_pvt *pvt;
00109    int len;
00110    char *ofs;
00111 
00112    /*
00113     * compute the required size adding private descriptor,
00114     * buffer, AST_FRIENDLY_OFFSET.
00115     */
00116    len = sizeof(*pvt) + t->desc_size;
00117    if (t->buf_size)
00118       len += AST_FRIENDLY_OFFSET + t->buf_size;
00119    pvt = ast_calloc(1, len);
00120    if (!pvt)
00121       return NULL;
00122    pvt->t = t;
00123    ofs = (char *)(pvt + 1);   /* pointer to data space */
00124    if (t->desc_size) {     /* first comes the descriptor */
00125       pvt->pvt = ofs;
00126       ofs += t->desc_size;
00127    }
00128    if (t->buf_size)     /* finally buffer and header */
00129       pvt->outbuf.c = ofs + AST_FRIENDLY_OFFSET;
00130    /* call local init routine, if present */
00131    if (t->newpvt && t->newpvt(pvt)) {
00132       ast_free(pvt);
00133       return NULL;
00134    }
00135    ast_module_ref(t->module);
00136    return pvt;
00137 }

static force_inline int powerof ( format_t  d  )  [static]

returns the index of the lowest bit set

Definition at line 86 of file translate.c.

References ast_log(), ffsll(), and LOG_WARNING.

00087 {
00088    int x = ffsll(d);
00089 
00090    if (x)
00091       return x - 1;
00092 
00093    ast_log(LOG_WARNING, "No bits set? %llu\n", (unsigned long long) d);
00094 
00095    return -1;
00096 }

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

References ast_translator::active, ast_debug, ast_getformatname(), AST_RWLIST_TRAVERSE, calc_cost(), ast_translator::cost, ast_translator::dstfmt, get_rate_change_result(), ast_translator::list, MAX_FORMAT, RATE_CHANGE_NONE, RATE_CHANGE_UPSAMP_DOWNSAMP, ast_translator::srcfmt, and tr_matrix.

Referenced by __ast_register_translator(), ast_translator_activate(), ast_translator_deactivate(), ast_unregister_translator(), and handle_cli_core_show_translation().

00441 {
00442    struct ast_translator *t;
00443    int new_rate_change;
00444    int newcost;
00445    int x;      /* source format index */
00446    int y;      /* intermediate format index */
00447    int z;      /* destination format index */
00448 
00449    ast_debug(1, "Resetting translation matrix\n");
00450 
00451    memset(tr_matrix, '\0', sizeof(tr_matrix));
00452 
00453    /* first, compute all direct costs */
00454    AST_RWLIST_TRAVERSE(&translators, t, list) {
00455       if (!t->active)
00456          continue;
00457 
00458       x = t->srcfmt;
00459       z = t->dstfmt;
00460 
00461       if (samples)
00462          calc_cost(t, samples);
00463 
00464       new_rate_change = get_rate_change_result(1LL << t->srcfmt, 1LL << t->dstfmt);
00465 
00466       /* this translator is the best choice if any of the below are true.
00467        * 1. no translation path is set between x and z yet.
00468        * 2. the new translation costs less and sample rate is no worse than old one. 
00469        * 3. the new translation has a better sample rate conversion than the old one.
00470        */
00471       if (!tr_matrix[x][z].step ||
00472          ((t->cost < tr_matrix[x][z].cost) && (new_rate_change <= tr_matrix[x][z].rate_change)) ||
00473          (new_rate_change < tr_matrix[x][z].rate_change)) {
00474 
00475          tr_matrix[x][z].step = t;
00476          tr_matrix[x][z].cost = t->cost;
00477          tr_matrix[x][z].rate_change = new_rate_change;
00478       }
00479    }
00480 
00481    /*
00482     * For each triple x, y, z of distinct formats, check if there is
00483     * a path from x to z through y which is cheaper than what is
00484     * currently known, and in case, update the matrix.
00485     * Repeat until the matrix is stable.
00486     */
00487    for (;;) {
00488       int changed = 0;
00489       int better_choice = 0;
00490       for (x = 0; x < MAX_FORMAT; x++) {      /* source format */
00491          for (y = 0; y < MAX_FORMAT; y++) {    /* intermediate format */
00492             if (x == y)                     /* skip ourselves */
00493                continue;
00494             for (z = 0; z < MAX_FORMAT; z++) {  /* dst format */
00495                if (z == x || z == y)       /* skip null conversions */
00496                   continue;
00497                if (!tr_matrix[x][y].step)  /* no path from x to y */
00498                   continue;
00499                if (!tr_matrix[y][z].step)  /* no path from y to z */
00500                   continue;
00501 
00502                /* Does x->y->z result in a less optimal sample rate change?
00503                 * Never downgrade the sample rate conversion quality regardless
00504                 * of any cost improvements */
00505                if (tr_matrix[x][z].step &&
00506                   ((tr_matrix[x][z].rate_change < tr_matrix[x][y].rate_change) ||
00507                   (tr_matrix[x][z].rate_change < tr_matrix[y][z].rate_change))) {
00508                   continue;
00509                }
00510 
00511                /* is x->y->z a better sample rate confersion that the current x->z? */
00512                new_rate_change = tr_matrix[x][y].rate_change + tr_matrix[y][z].rate_change;
00513 
00514                /* calculate cost from x->y->z */
00515                newcost = tr_matrix[x][y].cost + tr_matrix[y][z].cost;
00516 
00517                /* Is x->y->z a better choice than x->z?
00518                 * There are three conditions for x->y->z to be a better choice than x->z
00519                 * 1. if there is no step directly between x->z then x->y->z is the best and only current option.
00520                 * 2. if x->y->z costs less and the sample rate conversion is no less optimal.
00521                 * 3. if x->y->z results in a more optimal sample rate conversion. */
00522                if (!tr_matrix[x][z].step) {
00523                   better_choice = 1;
00524                } else if ((newcost < tr_matrix[x][z].cost) && (new_rate_change <= tr_matrix[x][z].rate_change)) {
00525                   better_choice = 1;
00526                } else if (new_rate_change < tr_matrix[x][z].rate_change) {
00527                   better_choice = 1;
00528                } else {
00529                   better_choice = 0;
00530                }
00531 
00532                if (!better_choice) {
00533                   continue;
00534                }
00535                /* ok, we can get from x to z via y with a cost that
00536                   is the sum of the transition from x to y and from y to z */
00537                tr_matrix[x][z].step = tr_matrix[x][y].step;
00538                tr_matrix[x][z].cost = newcost;
00539                tr_matrix[x][z].multistep = 1;
00540 
00541                /* now calculate what kind of sample rate change is required for this multi-step path
00542                 * 
00543                 * if both paths require a change in rate, and they are not in the same direction
00544                 * then this is a up sample down sample conversion scenario. */
00545                if ((tr_matrix[x][y].rate_change > RATE_CHANGE_NONE) &&
00546                   (tr_matrix[y][z].rate_change > RATE_CHANGE_NONE) &&
00547                   (tr_matrix[x][y].rate_change != tr_matrix[y][z].rate_change)) {
00548 
00549                   tr_matrix[x][z].rate_change = RATE_CHANGE_UPSAMP_DOWNSAMP;
00550                } else {
00551                   /* else just set the rate change to whichever is worse */
00552                   tr_matrix[x][z].rate_change = tr_matrix[x][y].rate_change > tr_matrix[y][z].rate_change
00553                      ? tr_matrix[x][y].rate_change : tr_matrix[y][z].rate_change;
00554                }
00555 
00556                ast_debug(3, "Discovered %d cost path from %s to %s, via %s\n", tr_matrix[x][z].cost,
00557                     ast_getformatname(1LL << x), ast_getformatname(1LL << z), ast_getformatname(1LL << y));
00558                changed++;
00559             }
00560          }
00561       }
00562       if (!changed)
00563          break;
00564    }
00565 }


Variable Documentation

struct ast_cli_entry cli_translate[] [static]

Initial value:

 {
   { .handler =  handle_cli_core_show_translation , .summary =  "Display translation matrix" ,__VA_ARGS__ }
}

Definition at line 780 of file translate.c.

Referenced by __ast_register_translator().

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

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


Generated on Sat Mar 10 01:55:49 2012 for Asterisk - The Open Source Telephony Project by  doxygen 1.4.7