Wed Jan 27 20:02:50 2016

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

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

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_clear_flag, ast_debug, 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 (out) {
00373       /* we have a frame, play with times */
00374       if (!ast_tvzero(delivery)) {
00375          /* Regenerate prediction after a discontinuity */
00376          if (ast_tvzero(path->nextout)) {
00377             path->nextout = ast_tvnow();
00378          }
00379 
00380          /* Use next predicted outgoing timestamp */
00381          out->delivery = path->nextout;
00382 
00383          /* Predict next outgoing timestamp from samples in this
00384             frame. */
00385          path->nextout = ast_tvadd(path->nextout, ast_samp2tv(out->samples, ast_format_rate(out->subclass.codec)));
00386          if (f->samples != out->samples && ast_test_flag(out, AST_FRFLAG_HAS_TIMING_INFO)) {
00387             ast_debug(4, "Sample size different %d vs %d\n", f->samples, out->samples);
00388             ast_clear_flag(out, AST_FRFLAG_HAS_TIMING_INFO);
00389          }
00390       } else {
00391          out->delivery = ast_tv(0, 0);
00392          ast_set2_flag(out, has_timing_info, AST_FRFLAG_HAS_TIMING_INFO);
00393          if (has_timing_info) {
00394             out->ts = ts;
00395             out->len = len;
00396             out->seqno = seqno;
00397          }
00398       }
00399       /* Invalidate prediction if we're entering a silence period */
00400       if (out->frametype == AST_FRAME_CNG) {
00401          path->nextout = ast_tv(0, 0);
00402       }
00403    }
00404    if (consume) {
00405       ast_frfree(f);
00406    }
00407    return out;
00408 }

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

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

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

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

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

00631 {
00632    struct ast_trans_pvt *pn = p;
00633 
00634    if (!p || !p->t) {
00635       return "";
00636    }
00637 
00638    ast_str_set(str, 0, "%s", ast_getformatname(1LL << p->t->srcfmt));
00639 
00640    while ( (p = pn) ) {
00641       pn = p->next;
00642       ast_str_append(str, 0, "->%s", ast_getformatname(1LL << p->t->dstfmt));
00643    }
00644 
00645    return ast_str_buffer(*str);
00646 }

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

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

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

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

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

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

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

00976 {
00977    AST_RWLIST_WRLOCK(&translators);
00978    t->active = 0;
00979    rebuild_matrix(0);
00980    AST_RWLIST_UNLOCK(&translators);
00981 }

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

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

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

compute the cost of a single translation step

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

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

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

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

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

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

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

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

Definition at line 669 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.

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

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

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


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 848 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 27 Jan 2016 for Asterisk - The Open Source Telephony Project by  doxygen 1.6.1