Tue Aug 20 16:35:16 2013

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 {
  AST_TRANS_COST_LL_LL_ORIGSAMP = 400000, AST_TRANS_COST_LL_LY_ORIGSAMP = 600000, AST_TRANS_COST_LL_LL_UPSAMP = 800000, AST_TRANS_COST_LL_LY_UPSAMP = 825000,
  AST_TRANS_COST_LL_LL_DOWNSAMP = 850000, AST_TRANS_COST_LL_LY_DOWNSAMP = 875000, AST_TRANS_COST_LL_UNKNOWN = 885000, AST_TRANS_COST_LY_LL_ORIGSAMP = 900000,
  AST_TRANS_COST_LY_LY_ORIGSAMP = 915000, AST_TRANS_COST_LY_LL_UPSAMP = 930000, AST_TRANS_COST_LY_LY_UPSAMP = 945000, AST_TRANS_COST_LY_LL_DOWNSAMP = 960000,
  AST_TRANS_COST_LY_LY_DOWNSAMP = 975000, AST_TRANS_COST_LY_UNKNOWN = 985000
}
 

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 codec translator
struct ast_frameast_trans_frameout (struct ast_trans_pvt *pvt, int datalen, int samples)
 generic frameout routine. If samples and datalen are 0, take whatever is in pvt and reset them, otherwise take the values in the caller and leave alone the pvt values.
struct ast_frameast_translate (struct ast_trans_pvt *path, struct ast_frame *f, int consume)
 do the actual translation
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)
 Calculate our best translator source format, given costs, and a desired destination.
struct ast_trans_pvtast_translator_build_path (format_t dest, format_t source)
 Build a chain of translators based upon the given source and dest formats.
void ast_translator_deactivate (struct ast_translator *t)
 Deactivate a translator.
void ast_translator_free_path (struct ast_trans_pvt *p)
 Frees a translator path Frees the given translator path structure.
int ast_unregister_translator (struct ast_translator *t)
 unregister codec translator
static void calc_cost (struct ast_translator *t, int seconds)
 compute the cost of a single translation step
static 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 47 of file translate.c.

Referenced by handle_cli_core_show_translation().

#define SHOW_TRANS   64

Enumeration Type Documentation

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

[lossless -> lossless] original sampling

AST_TRANS_COST_LL_LY_ORIGSAMP 

[lossless -> lossy] original sampling

AST_TRANS_COST_LL_LL_UPSAMP 

[lossless -> lossless] up sample

AST_TRANS_COST_LL_LY_UPSAMP 

[lossless -> lossy] up sample

AST_TRANS_COST_LL_LL_DOWNSAMP 

[lossless -> lossless] down sample

AST_TRANS_COST_LL_LY_DOWNSAMP 

[lossless -> lossy] down sample

AST_TRANS_COST_LL_UNKNOWN 

[lossless -> unknown] unknown. This value is for a lossless source translation with an unknown destination and or sample rate conversion.

AST_TRANS_COST_LY_LL_ORIGSAMP 

[lossy -> lossless] original sampling

AST_TRANS_COST_LY_LY_ORIGSAMP 

[lossy -> lossy] original sampling

AST_TRANS_COST_LY_LL_UPSAMP 

[lossy -> lossless] up sample

AST_TRANS_COST_LY_LY_UPSAMP 

[lossy -> lossy] up sample

AST_TRANS_COST_LY_LL_DOWNSAMP 

[lossy -> lossless] down sample

AST_TRANS_COST_LY_LY_DOWNSAMP 

[lossy -> lossy] down sample

AST_TRANS_COST_LY_UNKNOWN 

[lossy -> unknown] unknown. This value is for a lossy source translation with an unknown destination and or sample rate conversion.

Definition at line 57 of file translate.c.

00057                       {
00058 
00059    /* Lossless Source Translation Costs */
00060 
00061    /*! [lossless -> lossless] original sampling */
00062    AST_TRANS_COST_LL_LL_ORIGSAMP = 400000,
00063    /*! [lossless -> lossy]    original sampling */
00064    AST_TRANS_COST_LL_LY_ORIGSAMP = 600000,
00065 
00066    /*! [lossless -> lossless] up sample */
00067    AST_TRANS_COST_LL_LL_UPSAMP   = 800000,
00068    /*! [lossless -> lossy]    up sample */
00069    AST_TRANS_COST_LL_LY_UPSAMP   = 825000,
00070 
00071    /*! [lossless -> lossless] down sample */
00072    AST_TRANS_COST_LL_LL_DOWNSAMP = 850000,
00073    /*! [lossless -> lossy]    down sample */
00074    AST_TRANS_COST_LL_LY_DOWNSAMP = 875000,
00075 
00076    /*! [lossless -> unknown]    unknown.
00077     * This value is for a lossless source translation
00078     * with an unknown destination and or sample rate conversion. */
00079    AST_TRANS_COST_LL_UNKNOWN     = 885000,
00080 
00081    /* Lossy Source Translation Costs */
00082 
00083    /*! [lossy -> lossless]    original sampling */
00084    AST_TRANS_COST_LY_LL_ORIGSAMP = 900000,
00085    /*! [lossy -> lossy]       original sampling */
00086    AST_TRANS_COST_LY_LY_ORIGSAMP = 915000,
00087 
00088    /*! [lossy -> lossless]    up sample */
00089    AST_TRANS_COST_LY_LL_UPSAMP   = 930000,
00090    /*! [lossy -> lossy]       up sample */
00091    AST_TRANS_COST_LY_LY_UPSAMP   = 945000,
00092 
00093    /*! [lossy -> lossless]    down sample */
00094    AST_TRANS_COST_LY_LL_DOWNSAMP = 960000,
00095    /*! [lossy -> lossy]       down sample */
00096    AST_TRANS_COST_LY_LY_DOWNSAMP = 975000,
00097 
00098    /*! [lossy -> unknown]    unknown.
00099     * This value is for a lossy source translation
00100     * with an unknown destination and or sample rate conversion. */
00101    AST_TRANS_COST_LY_UNKNOWN     = 985000,
00102 };


Function Documentation

int __ast_register_translator ( struct ast_translator t,
struct ast_module mod 
)

register codec translator

Register a translator This registers a codec translator with asterisk.

Definition at line 846 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(), 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().

00847 {
00848    static int added_cli = 0;
00849    struct ast_translator *u;
00850    char tmp[80];
00851 
00852    if (!mod) {
00853       ast_log(LOG_WARNING, "Missing module pointer, you need to supply one\n");
00854       return -1;
00855    }
00856 
00857    if (!t->buf_size) {
00858       ast_log(LOG_WARNING, "empty buf size, you need to supply one\n");
00859       return -1;
00860    }
00861 
00862    t->module = mod;
00863 
00864    t->srcfmt = powerof(t->srcfmt);
00865    t->dstfmt = powerof(t->dstfmt);
00866    t->active = 1;
00867 
00868    if (t->srcfmt == -1 || t->dstfmt == -1) {
00869       ast_log(LOG_WARNING, "Invalid translator path: (%s codec is not valid)\n", t->srcfmt == -1 ? "starting" : "ending");
00870       return -1;
00871    }
00872    if (t->srcfmt >= MAX_FORMAT) {
00873       ast_log(LOG_WARNING, "Source format %s is larger than MAX_FORMAT\n", ast_getformatname(t->srcfmt));
00874       return -1;
00875    }
00876 
00877    if (t->dstfmt >= MAX_FORMAT) {
00878       ast_log(LOG_WARNING, "Destination format %s is larger than MAX_FORMAT\n", ast_getformatname(t->dstfmt));
00879       return -1;
00880    }
00881 
00882    if (t->buf_size) {
00883       /*
00884        * Align buf_size properly, rounding up to the machine-specific
00885        * alignment for pointers.
00886        */
00887       struct _test_align { void *a, *b; } p;
00888       int align = (char *)&p.b - (char *)&p.a;
00889 
00890       t->buf_size = ((t->buf_size + align - 1) / align) * align;
00891    }
00892 
00893    if (t->frameout == NULL)
00894       t->frameout = default_frameout;
00895   
00896    calc_cost(t, 1);
00897 
00898    ast_verb(2, "Registered translator '%s' from format %s to %s, cost %d\n",
00899              term_color(tmp, t->name, COLOR_MAGENTA, COLOR_BLACK, sizeof(tmp)),
00900              ast_getformatname(1LL << t->srcfmt), ast_getformatname(1LL << t->dstfmt), t->cost);
00901 
00902    if (!added_cli) {
00903       ast_cli_register_multiple(cli_translate, ARRAY_LEN(cli_translate));
00904       added_cli++;
00905    }
00906 
00907    AST_RWLIST_WRLOCK(&translators);
00908 
00909    /* find any existing translators that provide this same srcfmt/dstfmt,
00910       and put this one in order based on cost */
00911    AST_RWLIST_TRAVERSE_SAFE_BEGIN(&translators, u, list) {
00912       if ((u->srcfmt == t->srcfmt) &&
00913           (u->dstfmt == t->dstfmt) &&
00914           (u->cost > t->cost)) {
00915          AST_RWLIST_INSERT_BEFORE_CURRENT(t, list);
00916          t = NULL;
00917          break;
00918       }
00919    }
00920    AST_RWLIST_TRAVERSE_SAFE_END;
00921 
00922    /* if no existing translator was found for this format combination,
00923       add it to the beginning of the list */
00924    if (t)
00925       AST_RWLIST_INSERT_HEAD(&translators, t, list);
00926 
00927    rebuild_matrix(0);
00928 
00929    AST_RWLIST_UNLOCK(&translators);
00930 
00931    return 0;
00932 }

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

generic frameout routine. If samples and datalen are 0, take whatever is in pvt and reset them, otherwise take the values in the caller and leave alone the pvt values.

generic frameout function

Definition at line 235 of file translate.c.

References AST_FRAME_VOICE, AST_FRIENDLY_OFFSET, ast_frisolate(), ast_trans_pvt::c, ast_frame_subclass::codec, ast_frame::data, ast_trans_pvt::datalen, ast_frame::datalen, ast_translator::dstfmt, ast_trans_pvt::f, f, ast_frame::frametype, ast_frame::mallocd, ast_translator::name, ast_frame::offset, ast_trans_pvt::outbuf, ast_frame::ptr, ast_trans_pvt::samples, ast_frame::samples, ast_frame::src, ast_frame::subclass, and ast_trans_pvt::t.

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

00237 {
00238    struct ast_frame *f = &pvt->f;
00239 
00240    if (samples)
00241       f->samples = samples;
00242    else {
00243       if (pvt->samples == 0)
00244          return NULL;
00245       f->samples = pvt->samples;
00246       pvt->samples = 0;
00247    }
00248    if (datalen)
00249       f->datalen = datalen;
00250    else {
00251       f->datalen = pvt->datalen;
00252       pvt->datalen = 0;
00253    }
00254 
00255    f->frametype = AST_FRAME_VOICE;
00256    f->subclass.codec = 1LL << (pvt->t->dstfmt);
00257    f->mallocd = 0;
00258    f->offset = AST_FRIENDLY_OFFSET;
00259    f->src = pvt->t->name;
00260    f->data.ptr = pvt->outbuf.c;
00261 
00262    return ast_frisolate(f);
00263 }

struct ast_frame* ast_translate ( struct ast_trans_pvt path,
struct ast_frame f,
int  consume 
) [read]

do the actual translation

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

Definition at line 328 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, 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().

00329 {
00330    struct ast_trans_pvt *p = path;
00331    struct ast_frame *out = f;
00332    struct timeval delivery;
00333    int has_timing_info;
00334    long ts;
00335    long len;
00336    int seqno;
00337 
00338    has_timing_info = ast_test_flag(f, AST_FRFLAG_HAS_TIMING_INFO);
00339    ts = f->ts;
00340    len = f->len;
00341    seqno = f->seqno;
00342 
00343    /* XXX hmmm... check this below */
00344    if (!ast_tvzero(f->delivery)) {
00345       if (!ast_tvzero(path->nextin)) {
00346          /* Make sure this is in line with what we were expecting */
00347          if (!ast_tveq(path->nextin, f->delivery)) {
00348             /* The time has changed between what we expected and this
00349                most recent time on the new packet.  If we have a
00350                valid prediction adjust our output time appropriately */
00351             if (!ast_tvzero(path->nextout)) {
00352                path->nextout = ast_tvadd(path->nextout,
00353                           ast_tvsub(f->delivery, path->nextin));
00354             }
00355             path->nextin = f->delivery;
00356          }
00357       } else {
00358          /* This is our first pass.  Make sure the timing looks good */
00359          path->nextin = f->delivery;
00360          path->nextout = f->delivery;
00361       }
00362       /* Predict next incoming sample */
00363       path->nextin = ast_tvadd(path->nextin, ast_samp2tv(f->samples, ast_format_rate(f->subclass.codec)));
00364    }
00365    delivery = f->delivery;
00366    for ( ; out && p ; p = p->next) {
00367       framein(p, out);
00368       if (out != f)
00369          ast_frfree(out);
00370       out = p->t->frameout(p);
00371    }
00372    if (consume)
00373       ast_frfree(f);
00374    if (out == NULL)
00375       return NULL;
00376    /* we have a frame, play with times */
00377    if (!ast_tvzero(delivery)) {
00378       /* Regenerate prediction after a discontinuity */
00379       if (ast_tvzero(path->nextout))
00380          path->nextout = ast_tvnow();
00381 
00382       /* Use next predicted outgoing timestamp */
00383       out->delivery = path->nextout;
00384       
00385       /* Predict next outgoing timestamp from samples in this
00386          frame. */
00387       path->nextout = ast_tvadd(path->nextout, ast_samp2tv(out->samples, ast_format_rate(out->subclass.codec)));
00388    } else {
00389       out->delivery = ast_tv(0, 0);
00390       ast_set2_flag(out, has_timing_info, AST_FRFLAG_HAS_TIMING_INFO);
00391       if (has_timing_info) {
00392          out->ts = ts;
00393          out->len = len;
00394          out->seqno = seqno;
00395       }
00396    }
00397    /* Invalidate prediction if we're entering a silence period */
00398    if (out->frametype == AST_FRAME_CNG)
00399       path->nextout = ast_tv(0, 0);
00400    return out;
00401 }

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

01075 {
01076    format_t res = dest;
01077    format_t x;
01078    format_t src_audio = src & AST_FORMAT_AUDIO_MASK;
01079    format_t src_video = src & AST_FORMAT_VIDEO_MASK;
01080    format_t x_bits;
01081 
01082    /* if we don't have a source format, we just have to try all
01083       possible destination formats */
01084    if (!src)
01085       return dest;
01086 
01087    /* If we have a source audio format, get its format index */
01088    if (src_audio) {
01089       src_audio = powerof(src_audio);
01090    }
01091 
01092    /* If we have a source video format, get its format index */
01093    if (src_video) {
01094       src_video = powerof(src_video);
01095    }
01096 
01097    /* Note that src_audio and src_video are guaranteed to not be
01098     * negative at this point, as we ensured they were non-zero.  It is
01099     * safe to use the return value of powerof as an index into tr_matrix.
01100     */
01101 
01102    AST_RWLIST_RDLOCK(&translators);
01103 
01104    /* For a given source audio format, traverse the list of
01105       known audio formats to determine whether there exists
01106       a translation path from the source format to the
01107       destination format. */
01108    for (x = 1LL; src_audio && x > 0; x <<= 1) {
01109       if (!(x & AST_FORMAT_AUDIO_MASK)) {
01110          continue;
01111       }
01112 
01113       /* if this is not a desired format, nothing to do */
01114       if (!(dest & x))
01115          continue;
01116 
01117       /* if the source is supplying this format, then
01118          we can leave it in the result */
01119       if (src & x)
01120          continue;
01121 
01122       /* if we don't have a translation path from the src
01123          to this format, remove it from the result.  Note that x_bits
01124          cannot be less than 0 as x will always have one bit set to 1 */
01125       x_bits = powerof(x);
01126       if (!tr_matrix[src_audio][x_bits].step) {
01127          res &= ~x;
01128          continue;
01129       }
01130 
01131       /* now check the opposite direction */
01132       if (!tr_matrix[x_bits][src_audio].step)
01133          res &= ~x;
01134    }
01135 
01136    /* For a given source video format, traverse the list of
01137       known video formats to determine whether there exists
01138       a translation path from the source format to the
01139       destination format. */
01140    for (x = 1LL; src_video && x > 0; x <<= 1) {
01141       if (!(x & AST_FORMAT_VIDEO_MASK)) {
01142          continue;
01143       }
01144 
01145       /* if this is not a desired format, nothing to do */
01146       if (!(dest & x))
01147          continue;
01148 
01149       /* if the source is supplying this format, then
01150          we can leave it in the result */
01151       if (src & x)
01152          continue;
01153 
01154       /* if we don't have a translation path from the src
01155          to this format, remove it from the result.  Note that x_bits
01156          cannot be less than 0 as x will always have one bit set to 1 */
01157       x_bits = powerof(x);
01158       if (!tr_matrix[src_video][x_bits].step) {
01159          res &= ~x;
01160          continue;
01161       }
01162 
01163       /* now check the opposite direction */
01164       if (!tr_matrix[x_bits][src_video].step)
01165          res &= ~x;
01166    }
01167 
01168    AST_RWLIST_UNLOCK(&translators);
01169 
01170    return res;
01171 }

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

01053 {
01054    unsigned int res = -1;
01055 
01056    /* convert bitwise format numbers into array indices */
01057    src = powerof(src);
01058    dest = powerof(dest);
01059 
01060    if (src == -1 || dest == -1) {
01061       ast_log(LOG_WARNING, "No translator path: (%s codec is not valid)\n", src == -1 ? "starting" : "ending");
01062       return -1;
01063    }
01064    AST_RWLIST_RDLOCK(&translators);
01065 
01066    if (tr_matrix[src][dest].step)
01067       res = tr_matrix[src][dest].multistep + 1;
01068 
01069    AST_RWLIST_UNLOCK(&translators);
01070 
01071    return res;
01072 }

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 623 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, and ast_trans_pvt::t.

Referenced by handle_showchan(), and serialize_showchan().

00624 {
00625    struct ast_trans_pvt *pn = p;
00626 
00627    if (!p || !p->t) {
00628       return "";
00629    }
00630 
00631    ast_str_set(str, 0, "%s", ast_getformatname(1LL << p->t->srcfmt));
00632 
00633    while ( (p = pn) ) {
00634       pn = p->next;
00635       ast_str_append(str, 0, "->%s", ast_getformatname(1LL << p->t->dstfmt));
00636    }
00637 
00638    return ast_str_buffer(*str);
00639 }

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

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

00961 {
00962    AST_RWLIST_WRLOCK(&translators);
00963    t->active = 1;
00964    rebuild_matrix(0);
00965    AST_RWLIST_UNLOCK(&translators);
00966 }

format_t ast_translator_best_choice ( format_t dst,
format_t srcs 
)

Calculate our best translator source format, given costs, and a desired destination.

Chooses the best translation path.

Definition at line 977 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().

00978 {
00979    int x,y;
00980    int better = 0;
00981    int besttime = INT_MAX;
00982    int beststeps = INT_MAX;
00983    unsigned int best_rate_change = INT_MAX;
00984    format_t best = -1;
00985    format_t bestdst = 0;
00986    format_t cur, cursrc;
00987    format_t common = ((*dst) & (*srcs)) & AST_FORMAT_AUDIO_MASK;  /* are there common formats ? */
00988 
00989    if (common) { /* yes, pick one and return */
00990       for (cur = 1, y = 0; y <= MAX_AUDIO_FORMAT; cur <<= 1, y++) {
00991          if (!(cur & common)) {
00992             continue;
00993          }
00994 
00995          /* We are guaranteed to find one common format. */
00996          if (best == -1) {
00997             best = cur;
00998             continue;
00999          }
01000          /* If there are multiple common formats, pick the one with the highest sample rate */
01001          if (ast_format_rate(best) < ast_format_rate(cur)) {
01002             best = cur;
01003             continue;
01004          }
01005       }
01006       /* We are done, this is a common format to both. */
01007       *srcs = *dst = best;
01008       return 0;
01009    } else {      /* No, we will need to translate */
01010       AST_RWLIST_RDLOCK(&translators);
01011       for (cur = 1, y = 0; y <= MAX_AUDIO_FORMAT; cur <<= 1, y++) {
01012          if (! (cur & *dst)) {
01013             continue;
01014          }
01015          for (cursrc = 1, x = 0; x <= MAX_AUDIO_FORMAT; cursrc <<= 1, x++) {
01016             if (!(*srcs & cursrc) || !tr_matrix[x][y].step) {
01017                continue;
01018             }
01019 
01020             /* This is a better choice if any of the following are true.
01021              * 1. The sample rate conversion is better than the current pick.
01022              * 2. the sample rate conversion is no worse than the current pick and the cost or multistep is better
01023              */
01024             better = 0;
01025             if (tr_matrix[x][y].rate_change < best_rate_change) {
01026                better = 1; /* this match has a better rate conversion */
01027             }
01028             if ((tr_matrix[x][y].rate_change <= best_rate_change) &&
01029                (tr_matrix[x][y].cost < besttime || tr_matrix[x][y].multistep < beststeps)) {
01030                better = 1; /* this match has no worse rate conversion and the conversion cost is less */
01031             }
01032             if (better) {
01033                /* better than what we have so far */
01034                best = cursrc;
01035                bestdst = cur;
01036                besttime = tr_matrix[x][y].cost;
01037                beststeps = tr_matrix[x][y].multistep;
01038                best_rate_change = tr_matrix[x][y].rate_change;
01039             }
01040          }
01041       }
01042       AST_RWLIST_UNLOCK(&translators);
01043       if (best > -1) {
01044          *srcs = best;
01045          *dst = bestdst;
01046          best = 0;
01047       }
01048       return best;
01049    }
01050 }

struct ast_trans_pvt* ast_translator_build_path ( format_t  dest,
format_t  source 
) [read]

Build a chain of translators based upon the given source and dest formats.

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

Definition at line 282 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().

00283 {
00284    struct ast_trans_pvt *head = NULL, *tail = NULL;
00285    
00286    source = powerof(source);
00287    dest = powerof(dest);
00288 
00289    if (source == -1 || dest == -1) {
00290       ast_log(LOG_WARNING, "No translator path: (%s codec is not valid)\n", source == -1 ? "starting" : "ending");
00291       return NULL;
00292    }
00293 
00294    AST_RWLIST_RDLOCK(&translators);
00295 
00296    while (source != dest) {
00297       struct ast_trans_pvt *cur;
00298       struct ast_translator *t = tr_matrix[source][dest].step;
00299       if (!t) {
00300          ast_log(LOG_WARNING, "No translator path from %s to %s\n", 
00301             ast_getformatname(source), ast_getformatname(dest));
00302          AST_RWLIST_UNLOCK(&translators);
00303          return NULL;
00304       }
00305       if (!(cur = newpvt(t))) {
00306          ast_log(LOG_WARNING, "Failed to build translator step from %s to %s\n",
00307             ast_getformatname(source), ast_getformatname(dest));
00308          if (head)
00309             ast_translator_free_path(head);  
00310          AST_RWLIST_UNLOCK(&translators);
00311          return NULL;
00312       }
00313       if (!head)
00314          head = cur;
00315       else
00316          tail->next = cur;
00317       tail = cur;
00318       cur->nextin = cur->nextout = ast_tv(0, 0);
00319       /* Keep going if this isn't the final destination */
00320       source = cur->t->dstfmt;
00321    }
00322 
00323    AST_RWLIST_UNLOCK(&translators);
00324    return head;
00325 }

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

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

00969 {
00970    AST_RWLIST_WRLOCK(&translators);
00971    t->active = 0;
00972    rebuild_matrix(0);
00973    AST_RWLIST_UNLOCK(&translators);
00974 }

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

00273 {
00274    struct ast_trans_pvt *pn = p;
00275    while ( (p = pn) ) {
00276       pn = p->next;
00277       destroy(p);
00278    }
00279 }

int ast_unregister_translator ( struct ast_translator t  ) 

unregister codec translator

Unregister a translator Unregisters the given tranlator.

Definition at line 935 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().

00936 {
00937    char tmp[80];
00938    struct ast_translator *u;
00939    int found = 0;
00940 
00941    AST_RWLIST_WRLOCK(&translators);
00942    AST_RWLIST_TRAVERSE_SAFE_BEGIN(&translators, u, list) {
00943       if (u == t) {
00944          AST_RWLIST_REMOVE_CURRENT(list);
00945          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));
00946          found = 1;
00947          break;
00948       }
00949    }
00950    AST_RWLIST_TRAVERSE_SAFE_END;
00951 
00952    if (found)
00953       rebuild_matrix(0);
00954 
00955    AST_RWLIST_UNLOCK(&translators);
00956 
00957    return (u ? 0 : -1);
00958 }

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

compute the cost of a single translation step

Definition at line 404 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, ast_translator::sample, and ast_frame::samples.

Referenced by __ast_register_translator(), and rebuild_matrix().

00405 {
00406    int num_samples = 0;
00407    struct ast_trans_pvt *pvt;
00408    struct rusage start;
00409    struct rusage end;
00410    int cost;
00411    int out_rate = ast_format_rate(t->dstfmt);
00412 
00413    if (!seconds)
00414       seconds = 1;
00415    
00416    /* If they don't make samples, give them a terrible score */
00417    if (!t->sample) {
00418       ast_log(LOG_WARNING, "Translator '%s' does not produce sample frames.\n", t->name);
00419       t->cost = 999999;
00420       return;
00421    }
00422 
00423    pvt = newpvt(t);
00424    if (!pvt) {
00425       ast_log(LOG_WARNING, "Translator '%s' appears to be broken and will probably fail.\n", t->name);
00426       t->cost = 999999;
00427       return;
00428    }
00429 
00430    getrusage(RUSAGE_SELF, &start);
00431 
00432    /* Call the encoder until we've processed the required number of samples */
00433    while (num_samples < seconds * out_rate) {
00434       struct ast_frame *f = t->sample();
00435       if (!f) {
00436          ast_log(LOG_WARNING, "Translator '%s' failed to produce a sample frame.\n", t->name);
00437          destroy(pvt);
00438          t->cost = 999999;
00439          return;
00440       }
00441       framein(pvt, f);
00442       ast_frfree(f);
00443       while ((f = t->frameout(pvt))) {
00444          num_samples += f->samples;
00445          ast_frfree(f);
00446       }
00447    }
00448 
00449    getrusage(RUSAGE_SELF, &end);
00450 
00451    cost = ((end.ru_utime.tv_sec - start.ru_utime.tv_sec) * 1000000) + end.ru_utime.tv_usec - start.ru_utime.tv_usec;
00452    cost += ((end.ru_stime.tv_sec - start.ru_stime.tv_sec) * 1000000) + end.ru_stime.tv_usec - start.ru_stime.tv_usec;
00453 
00454    destroy(pvt);
00455 
00456    t->cost = cost / seconds;
00457 
00458    if (!t->cost)
00459       t->cost = 1;
00460 }

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

Definition at line 641 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().

00642 {
00643    int which = 0;
00644    int wordlen = strlen(word);
00645    int i;
00646    char *ret = NULL;
00647    size_t len = 0;
00648    const struct ast_format_list *format_list = ast_get_format_list(&len);
00649 
00650    for (i = 0; i < len; i++) {
00651       if (!(format_list[i].bits & AST_FORMAT_AUDIO_MASK)) {
00652          continue;
00653       }
00654       if (!strncasecmp(word, format_list[i].name, wordlen) && ++which > state) {
00655          ret = ast_strdup(format_list[i].name);
00656          break;
00657       }
00658    }
00659    return ret;
00660 }

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

Definition at line 265 of file translate.c.

References ast_trans_frameout().

Referenced by __ast_register_translator().

00266 {
00267    return ast_trans_frameout(pvt, 0, 0);
00268 }

static void destroy ( struct ast_trans_pvt pvt  )  [static]

Definition at line 183 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().

00184 {
00185    struct ast_translator *t = pvt->t;
00186 
00187    if (t->destroy)
00188       t->destroy(pvt);
00189    ast_free(pvt);
00190    ast_module_unref(t->module);
00191 }

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

framein wrapper, deals with bound checks.

Definition at line 194 of file translate.c.

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

Referenced by ast_translate(), and calc_cost().

00195 {
00196    int ret;
00197    int samples = pvt->samples;   /* initial value */
00198    
00199    /* Copy the last in jb timing info to the pvt */
00200    ast_copy_flags(&pvt->f, f, AST_FRFLAG_HAS_TIMING_INFO);
00201    pvt->f.ts = f->ts;
00202    pvt->f.len = f->len;
00203    pvt->f.seqno = f->seqno;
00204 
00205    if (f->samples == 0) {
00206       ast_log(LOG_WARNING, "no samples for %s\n", pvt->t->name);
00207    }
00208    if (pvt->t->buffer_samples) { /* do not pass empty frames to callback */
00209       if (f->datalen == 0) { /* perform native PLC if available */
00210          /* If the codec has native PLC, then do that */
00211          if (!pvt->t->native_plc)
00212             return 0;
00213       }
00214       if (pvt->samples + f->samples > pvt->t->buffer_samples) {
00215          ast_log(LOG_WARNING, "Out of buffer space\n");
00216          return -1;
00217       }
00218    }
00219    /* we require a framein routine, wouldn't know how to do
00220     * it otherwise.
00221     */
00222    ret = pvt->t->framein(pvt, f);
00223    /* diagnostic ... */
00224    if (pvt->samples == samples)
00225       ast_log(LOG_WARNING, "%s did not update samples %d\n",
00226          pvt->t->name, pvt->samples);
00227    return ret;
00228 }

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

Definition at line 462 of file translate.c.

References ast_format_rate(), AST_FORMAT_SLINEAR, AST_FORMAT_SLINEAR16, AST_TRANS_COST_LL_LL_DOWNSAMP, AST_TRANS_COST_LL_LL_ORIGSAMP, AST_TRANS_COST_LL_LL_UPSAMP, AST_TRANS_COST_LL_LY_DOWNSAMP, AST_TRANS_COST_LL_LY_ORIGSAMP, AST_TRANS_COST_LL_LY_UPSAMP, AST_TRANS_COST_LL_UNKNOWN, AST_TRANS_COST_LY_LL_DOWNSAMP, AST_TRANS_COST_LY_LL_ORIGSAMP, AST_TRANS_COST_LY_LL_UPSAMP, AST_TRANS_COST_LY_LY_DOWNSAMP, AST_TRANS_COST_LY_LY_ORIGSAMP, AST_TRANS_COST_LY_LY_UPSAMP, and AST_TRANS_COST_LY_UNKNOWN.

Referenced by rebuild_matrix().

00463 {
00464    int src_ll = src == AST_FORMAT_SLINEAR || src == AST_FORMAT_SLINEAR16;
00465    int dst_ll = dst == AST_FORMAT_SLINEAR || src == AST_FORMAT_SLINEAR16;
00466    int src_rate = ast_format_rate(src);
00467    int dst_rate = ast_format_rate(dst);
00468 
00469    if (src_ll) {
00470       if (dst_ll && (src_rate == dst_rate)) {
00471          return AST_TRANS_COST_LL_LL_ORIGSAMP;
00472       } else if (!dst_ll && (src_rate == dst_rate)) {
00473          return AST_TRANS_COST_LL_LY_ORIGSAMP;
00474       } else if (dst_ll && (src_rate < dst_rate)) {
00475          return AST_TRANS_COST_LL_LL_UPSAMP;
00476       } else if (!dst_ll && (src_rate < dst_rate)) {
00477          return AST_TRANS_COST_LL_LY_UPSAMP;
00478       } else if (dst_ll && (src_rate > dst_rate)) {
00479          return AST_TRANS_COST_LL_LL_DOWNSAMP;
00480       } else if (!dst_ll && (src_rate > dst_rate)) {
00481          return AST_TRANS_COST_LL_LY_DOWNSAMP;
00482       } else {
00483          return AST_TRANS_COST_LL_UNKNOWN;
00484       }
00485    } else {
00486       if (dst_ll && (src_rate == dst_rate)) {
00487          return AST_TRANS_COST_LY_LL_ORIGSAMP;
00488       } else if (!dst_ll && (src_rate == dst_rate)) {
00489          return AST_TRANS_COST_LY_LY_ORIGSAMP;
00490       } else if (dst_ll && (src_rate < dst_rate)) {
00491          return AST_TRANS_COST_LY_LL_UPSAMP;
00492       } else if (!dst_ll && (src_rate < dst_rate)) {
00493          return AST_TRANS_COST_LY_LY_UPSAMP;
00494       } else if (dst_ll && (src_rate > dst_rate)) {
00495          return AST_TRANS_COST_LY_LL_DOWNSAMP;
00496       } else if (!dst_ll && (src_rate > dst_rate)) {
00497          return AST_TRANS_COST_LY_LY_DOWNSAMP;
00498       } else {
00499          return AST_TRANS_COST_LY_UNKNOWN;
00500       }
00501    }
00502 }

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

Definition at line 662 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(), ast_format_list::bits, 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.

00663 {
00664 #define SHOW_TRANS 64
00665    static const char * const option1[] = { "recalc", "paths", NULL };
00666    int x, y, z;
00667    int curlen = 0, longest = 0, magnitude[SHOW_TRANS] = { 0, };
00668 
00669    switch (cmd) {
00670    case CLI_INIT:
00671       e->command = "core show translation";
00672       e->usage =
00673          "Usage: 'core show translation' can be used in two ways.\n"
00674          "       1. 'core show translation [recalc [<recalc seconds>]]\n"
00675          "          Displays known codec translators and the cost associated\n"
00676          "          with each conversion.  If the argument 'recalc' is supplied along\n"
00677          "          with optional number of seconds to test a new test will be performed\n"
00678          "          as the chart is being displayed.\n"
00679          "       2. 'core show translation paths [codec]'\n"
00680          "           This will display all the translation paths associated with a codec\n";
00681       return NULL;
00682    case CLI_GENERATE:
00683       if (a->pos == 3) {
00684          return ast_cli_complete(a->word, option1, a->n);
00685       }
00686       if (a->pos == 4 && !strcasecmp(a->argv[3], option1[1])) {
00687          return complete_trans_path_choice(a->line, a->word, a->pos, a->n);
00688       }
00689       return NULL;
00690    }
00691 
00692    if (a->argc > 5)
00693       return CLI_SHOWUSAGE;
00694 
00695    if (a->argv[3] && !strcasecmp(a->argv[3], option1[1]) && a->argc == 5) {
00696       format_t input_src = 0;
00697       format_t src = 0;
00698       size_t len = 0;
00699       int dst;
00700       int i;
00701       const struct ast_format_list *format_list = ast_get_format_list(&len);
00702       struct ast_str *str = ast_str_alloca(256);
00703       struct ast_translator *step;
00704 
00705       for (i = 0; i < len; i++) {
00706          if (!(format_list[i].bits & AST_FORMAT_AUDIO_MASK)) {
00707             continue;
00708          }
00709          if (!strncasecmp(format_list[i].name, a->argv[4], strlen(format_list[i].name))) {
00710             input_src = format_list[i].bits;
00711          }
00712       }
00713 
00714       if (!input_src) {
00715          ast_cli(a->fd, "Source codec \"%s\" is not found.\n", a->argv[4]);
00716          return CLI_FAILURE;
00717       }
00718 
00719       AST_RWLIST_RDLOCK(&translators);
00720       ast_cli(a->fd, "--- Translation paths SRC Codec \"%s\" sample rate %d ---\n", a->argv[4], ast_format_rate(input_src));
00721       for (i = 0; i < len; i++) {
00722          if (!(format_list[i].bits & AST_FORMAT_AUDIO_MASK) || (format_list[i].bits == input_src)) {
00723             continue;
00724          }
00725          /* Note that dst can never be -1, as an element of format_list will have
00726           * at least one bit set.  src cannot be -1 as well, as it is previously
00727           * sanitized - hence it is safe to directly index tr_matrix with the results
00728           * of powerof.
00729           */
00730          dst = powerof(format_list[i].bits);
00731          src = powerof(input_src);
00732          ast_str_reset(str);
00733          if (tr_matrix[src][dst].step) {
00734             ast_str_append(&str, 0, "%s", ast_getformatname(1LL << tr_matrix[src][dst].step->srcfmt));
00735             while (src != dst) {
00736                step = tr_matrix[src][dst].step;
00737                if (!step) {
00738                   ast_str_reset(str);
00739                   break;
00740                }
00741                ast_str_append(&str, 0, "->%s", ast_getformatname(1LL << step->dstfmt));
00742                src = step->dstfmt;
00743             }
00744          }
00745 
00746          if (ast_strlen_zero(ast_str_buffer(str))) {
00747             ast_str_set(&str, 0, "No Translation Path");
00748          }
00749 
00750          ast_cli(a->fd, "\t%-10.10s To %-10.10s: %-60.60s\n", a->argv[4], format_list[i].name, ast_str_buffer(str));
00751       }
00752       AST_RWLIST_UNLOCK(&translators);
00753 
00754       return CLI_SUCCESS;
00755    } else if (a->argv[3] && !strcasecmp(a->argv[3], "recalc")) {
00756       z = a->argv[4] ? atoi(a->argv[4]) : 1;
00757 
00758       if (z <= 0) {
00759          ast_cli(a->fd, "         Recalc must be greater than 0.  Defaulting to 1.\n");
00760          z = 1;
00761       }
00762 
00763       if (z > MAX_RECALC) {
00764          ast_cli(a->fd, "         Maximum limit of recalc exceeded by %d, truncating value to %d\n", z - MAX_RECALC, MAX_RECALC);
00765          z = MAX_RECALC;
00766       }
00767       ast_cli(a->fd, "         Recalculating Codec Translation (number of sample seconds: %d)\n\n", z);
00768       AST_RWLIST_WRLOCK(&translators);
00769       rebuild_matrix(z);
00770       AST_RWLIST_UNLOCK(&translators);
00771    } else if (a->argc > 3)
00772       return CLI_SHOWUSAGE;
00773 
00774    AST_RWLIST_RDLOCK(&translators);
00775 
00776    ast_cli(a->fd, "         Translation times between formats (in microseconds) for one second of data\n");
00777    ast_cli(a->fd, "          Source Format (Rows) Destination Format (Columns)\n\n");
00778    /* Get the length of the longest (usable?) codec name, so we know how wide the left side should be */
00779    for (x = 0; x < SHOW_TRANS; x++) {
00780       /* translation only applies to audio right now. */
00781       if (!(AST_FORMAT_AUDIO_MASK & (1LL << (x))))
00782          continue;
00783       curlen = strlen(ast_getformatname(1LL << (x)));
00784       if (curlen > longest)
00785          longest = curlen;
00786       for (y = 0; y < SHOW_TRANS; y++) {
00787          if (!(AST_FORMAT_AUDIO_MASK & (1LL << (y))))
00788             continue;
00789          if (tr_matrix[x][y].cost > pow(10, magnitude[x])) {
00790             magnitude[y] = floor(log10(tr_matrix[x][y].cost));
00791          }
00792       }
00793    }
00794    for (x = -1; x < SHOW_TRANS; x++) {
00795       struct ast_str *out = ast_str_alloca(256);
00796       /* translation only applies to audio right now. */
00797       if (x >= 0 && !(AST_FORMAT_AUDIO_MASK & (1LL << (x))))
00798          continue;
00799       /*Go ahead and move to next iteration if dealing with an unknown codec*/
00800       if(x >= 0 && !strcmp(ast_getformatname(1LL << (x)), "unknown"))
00801          continue;
00802       ast_str_set(&out, -1, " ");
00803       for (y = -1; y < SHOW_TRANS; y++) {
00804          /* translation only applies to audio right now. */
00805          if (y >= 0 && !(AST_FORMAT_AUDIO_MASK & (1LL << (y))))
00806             continue;
00807          /*Go ahead and move to next iteration if dealing with an unknown codec*/
00808          if (y >= 0 && !strcmp(ast_getformatname(1LL << (y)), "unknown"))
00809             continue;
00810          if (y >= 0)
00811             curlen = strlen(ast_getformatname(1LL << (y)));
00812          if (y >= 0 && magnitude[y] + 1 > curlen) {
00813             curlen = magnitude[y] + 1;
00814          }
00815          if (curlen < 5)
00816             curlen = 5;
00817          if (x >= 0 && y >= 0 && tr_matrix[x][y].step) {
00818             /* Actual codec output */
00819             ast_str_append(&out, -1, "%*d", curlen + 1, tr_matrix[x][y].cost);
00820          } else if (x == -1 && y >= 0) {
00821             /* Top row - use a dynamic size */
00822             ast_str_append(&out, -1, "%*s", curlen + 1, ast_getformatname(1LL << (y)) );
00823          } else if (y == -1 && x >= 0) {
00824             /* Left column - use a static size. */
00825             ast_str_append(&out, -1, "%*s", longest, ast_getformatname(1LL << (x)) );
00826          } else if (x >= 0 && y >= 0) {
00827             /* Codec not supported */
00828             ast_str_append(&out, -1, "%*s", curlen + 1, "-");
00829          } else {
00830             /* Upper left hand corner */
00831             ast_str_append(&out, -1, "%*s", longest, "");
00832          }
00833       }
00834       ast_str_append(&out, -1, "\n");
00835       ast_cli(a->fd, "%s", ast_str_buffer(out));
00836    }
00837    AST_RWLIST_UNLOCK(&translators);
00838    return CLI_SUCCESS;
00839 }

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

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

Definition at line 150 of file translate.c.

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

Referenced by ast_translator_build_path(), and calc_cost().

00151 {
00152    struct ast_trans_pvt *pvt;
00153    int len;
00154    char *ofs;
00155 
00156    /*
00157     * compute the required size adding private descriptor,
00158     * buffer, AST_FRIENDLY_OFFSET.
00159     */
00160    len = sizeof(*pvt) + t->desc_size;
00161    if (t->buf_size)
00162       len += AST_FRIENDLY_OFFSET + t->buf_size;
00163    pvt = ast_calloc(1, len);
00164    if (!pvt)
00165       return NULL;
00166    pvt->t = t;
00167    ofs = (char *)(pvt + 1);   /* pointer to data space */
00168    if (t->desc_size) {     /* first comes the descriptor */
00169       pvt->pvt = ofs;
00170       ofs += t->desc_size;
00171    }
00172    if (t->buf_size)     /* finally buffer and header */
00173       pvt->outbuf.c = ofs + AST_FRIENDLY_OFFSET;
00174    /* call local init routine, if present */
00175    if (t->newpvt && t->newpvt(pvt)) {
00176       ast_free(pvt);
00177       return NULL;
00178    }
00179    ast_module_ref(t->module);
00180    return pvt;
00181 }

static force_inline int powerof ( format_t  d  )  [static]

returns the index of the lowest bit set

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

Definition at line 130 of file translate.c.

References ast_log(), and LOG_WARNING.

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

00131 {
00132    int x = ffsll(d);
00133 
00134    if (x)
00135       return x - 1;
00136 
00137    ast_log(LOG_WARNING, "No bits set? %llu\n", (unsigned long long) d);
00138 
00139    return -1;
00140 }

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

References ast_translator::active, ast_debug, ast_getformatname(), AST_RWLIST_TRAVERSE, calc_cost(), translator_path::cost, ast_translator::cost, ast_translator::dstfmt, get_rate_change_result(), ast_translator::list, MAX_FORMAT, translator_path::multistep, translator_path::rate_change, ast_translator::srcfmt, translator_path::step, and tr_matrix.

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

00509 {
00510    struct ast_translator *t;
00511    int new_rate_change;
00512    int newcost;
00513    int x;      /* source format index */
00514    int y;      /* intermediate format index */
00515    int z;      /* destination format index */
00516 
00517    ast_debug(1, "Resetting translation matrix\n");
00518 
00519    memset(tr_matrix, '\0', sizeof(tr_matrix));
00520 
00521    /* first, compute all direct costs */
00522    AST_RWLIST_TRAVERSE(&translators, t, list) {
00523       if (!t->active)
00524          continue;
00525 
00526       x = t->srcfmt;
00527       z = t->dstfmt;
00528 
00529       if (samples)
00530          calc_cost(t, samples);
00531 
00532       new_rate_change = get_rate_change_result(1LL << t->srcfmt, 1LL << t->dstfmt);
00533 
00534       /* this translator is the best choice if any of the below are true.
00535        * 1. no translation path is set between x and z yet.
00536        * 2. the new translation costs less and sample rate is no worse than old one. 
00537        * 3. the new translation has a better sample rate conversion than the old one.
00538        */
00539       if (!tr_matrix[x][z].step ||
00540          ((t->cost < tr_matrix[x][z].cost) && (new_rate_change <= tr_matrix[x][z].rate_change)) ||
00541          (new_rate_change < tr_matrix[x][z].rate_change)) {
00542 
00543          tr_matrix[x][z].step = t;
00544          tr_matrix[x][z].cost = t->cost;
00545          tr_matrix[x][z].rate_change = new_rate_change;
00546       }
00547    }
00548 
00549    /*
00550     * For each triple x, y, z of distinct formats, check if there is
00551     * a path from x to z through y which is cheaper than what is
00552     * currently known, and in case, update the matrix.
00553     * Repeat until the matrix is stable.
00554     */
00555    for (;;) {
00556       int changed = 0;
00557       int better_choice = 0;
00558       for (x = 0; x < MAX_FORMAT; x++) {      /* source format */
00559          for (y = 0; y < MAX_FORMAT; y++) {    /* intermediate format */
00560             if (x == y)                     /* skip ourselves */
00561                continue;
00562             for (z = 0; z < MAX_FORMAT; z++) {  /* dst format */
00563                if (z == x || z == y)       /* skip null conversions */
00564                   continue;
00565                if (!tr_matrix[x][y].step)  /* no path from x to y */
00566                   continue;
00567                if (!tr_matrix[y][z].step)  /* no path from y to z */
00568                   continue;
00569 
00570                /* Does x->y->z result in a less optimal sample rate change?
00571                 * Never downgrade the sample rate conversion quality regardless
00572                 * of any cost improvements */
00573                if (tr_matrix[x][z].step &&
00574                   ((tr_matrix[x][z].rate_change < tr_matrix[x][y].rate_change) ||
00575                   (tr_matrix[x][z].rate_change < tr_matrix[y][z].rate_change))) {
00576                   continue;
00577                }
00578 
00579                /* is x->y->z a better sample rate confersion that the current x->z? */
00580                new_rate_change = tr_matrix[x][y].rate_change + tr_matrix[y][z].rate_change;
00581 
00582                /* calculate cost from x->y->z */
00583                newcost = tr_matrix[x][y].cost + tr_matrix[y][z].cost;
00584 
00585                /* Is x->y->z a better choice than x->z?
00586                 * There are three conditions for x->y->z to be a better choice than x->z
00587                 * 1. if there is no step directly between x->z then x->y->z is the best and only current option.
00588                 * 2. if x->y->z results in a more optimal sample rate conversion. */
00589                if (!tr_matrix[x][z].step) {
00590                   better_choice = 1;
00591                } else if (new_rate_change < tr_matrix[x][z].rate_change) {
00592                   better_choice = 1;
00593                } else {
00594                   better_choice = 0;
00595                }
00596 
00597                if (!better_choice) {
00598                   continue;
00599                }
00600                /* ok, we can get from x to z via y with a cost that
00601                   is the sum of the transition from x to y and from y to z */
00602                tr_matrix[x][z].step = tr_matrix[x][y].step;
00603                tr_matrix[x][z].cost = newcost;
00604                tr_matrix[x][z].multistep = 1;
00605 
00606                /* now calculate what kind of sample rate change is required for this multi-step path
00607                 * 
00608                 * if both paths require a change in rate, and they are not in the same direction
00609                 * then this is a up sample down sample conversion scenario. */
00610                tr_matrix[x][z].rate_change = tr_matrix[x][y].rate_change + tr_matrix[y][z].rate_change;
00611 
00612                ast_debug(3, "Discovered %d cost path from %s to %s, via %s\n", tr_matrix[x][z].cost,
00613                     ast_getformatname(1LL << x), ast_getformatname(1LL << z), ast_getformatname(1LL << y));
00614                changed++;
00615             }
00616          }
00617       }
00618       if (!changed)
00619          break;
00620    }
00621 }


Variable Documentation

struct ast_cli_entry cli_translate[] [static]
Initial value:
 {
   AST_CLI_DEFINE(handle_cli_core_show_translation, "Display translation matrix")
}

Definition at line 841 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 121 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 20 Aug 2013 for Asterisk - The Open Source Telephony Project by  doxygen 1.6.1