Wed Oct 28 11:46:21 2009

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"

Include dependency graph for translate.c:

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   16

Functions

int __ast_register_translator (struct ast_translator *t, struct ast_module *mod)
 register codec translator
static void __fini_translators (void)
static void __init_translators (void)
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
unsigned int ast_translate_available_formats (unsigned int dest, unsigned int src)
 Mask off unavailable formats from a format bitmask.
unsigned int ast_translate_path_steps (unsigned int dest, unsigned int src)
 Returns the number of steps required to convert from 'src' to 'dest'.
void ast_translator_activate (struct ast_translator *t)
 Activate a previously deactivated translator.
int ast_translator_best_choice (int *dst, int *srcs)
 Calculate our best translator source format, given costs, and a desired destination.
struct ast_trans_pvtast_translator_build_path (int dest, int 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 struct ast_framedefault_frameout (struct ast_trans_pvt *pvt)
static void destroy (struct ast_trans_pvt *pvt)
static int framein (struct ast_trans_pvt *pvt, struct ast_frame *f)
 framein wrapper, deals with plc and bound checks.
static 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 also plc and desc.
static force_inline int powerof (unsigned int d)
 returns the index of the lowest bit set
static void rebuild_matrix (int samples)
 rebuild a translation matrix.

Variables

static struct ast_cli_entry cli_translate []
static struct translator_path tr_matrix [MAX_FORMAT][MAX_FORMAT]
 a matrix that, for any pair of supported formats, indicates the total cost of translation and the first step. The full path can be reconstricted iterating on the matrix until step->dstfmt == desired_format.


Detailed Description

Translate via the use of pseudo channels.

Author:
Mark Spencer <markster@digium.com>

Definition in file translate.c.


Define Documentation

#define MAX_RECALC   1000

Definition at line 43 of file translate.c.

Referenced by handle_cli_core_show_translation().

#define SHOW_TRANS   16


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

References ast_translator::active, ast_cli_register_multiple(), AST_FORMAT_SLINEAR, 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, ast_translator::buffer_samples, 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, ast_translator::plc_samples, powerof(), rebuild_matrix(), ast_translator::srcfmt, and term_color().

00609 {
00610    static int added_cli = 0;
00611    struct ast_translator *u;
00612    char tmp[80];
00613 
00614    if (!mod) {
00615       ast_log(LOG_WARNING, "Missing module pointer, you need to supply one\n");
00616       return -1;
00617    }
00618 
00619    if (!t->buf_size) {
00620       ast_log(LOG_WARNING, "empty buf size, you need to supply one\n");
00621       return -1;
00622    }
00623 
00624    t->module = mod;
00625 
00626    t->srcfmt = powerof(t->srcfmt);
00627    t->dstfmt = powerof(t->dstfmt);
00628    t->active = 1;
00629 
00630    if (t->srcfmt == -1 || t->dstfmt == -1) {
00631       ast_log(LOG_WARNING, "Invalid translator path: (%s codec is not valid)\n", t->srcfmt == -1 ? "starting" : "ending");
00632       return -1;
00633    }
00634    if (t->plc_samples) {
00635       if (t->buffer_samples < t->plc_samples) {
00636          ast_log(LOG_WARNING, "plc_samples %d buffer_samples %d\n",
00637             t->plc_samples, t->buffer_samples);
00638          return -1;
00639       }
00640       if (t->dstfmt != powerof(AST_FORMAT_SLINEAR))
00641          ast_log(LOG_WARNING, "plc_samples %d format %x\n",
00642             t->plc_samples, t->dstfmt);
00643    }
00644    if (t->srcfmt >= MAX_FORMAT) {
00645       ast_log(LOG_WARNING, "Source format %s is larger than MAX_FORMAT\n", ast_getformatname(t->srcfmt));
00646       return -1;
00647    }
00648 
00649    if (t->dstfmt >= MAX_FORMAT) {
00650       ast_log(LOG_WARNING, "Destination format %s is larger than MAX_FORMAT\n", ast_getformatname(t->dstfmt));
00651       return -1;
00652    }
00653 
00654    if (t->buf_size) {
00655       /*
00656        * Align buf_size properly, rounding up to the machine-specific
00657        * alignment for pointers.
00658        */
00659       struct _test_align { void *a, *b; } p;
00660       int align = (char *)&p.b - (char *)&p.a;
00661 
00662       t->buf_size = ((t->buf_size + align - 1) / align) * align;
00663    }
00664 
00665    if (t->frameout == NULL)
00666       t->frameout = default_frameout;
00667   
00668    calc_cost(t, 1);
00669 
00670    ast_verb(2, "Registered translator '%s' from format %s to %s, cost %d\n",
00671              term_color(tmp, t->name, COLOR_MAGENTA, COLOR_BLACK, sizeof(tmp)),
00672              ast_getformatname(1 << t->srcfmt), ast_getformatname(1 << t->dstfmt), t->cost);
00673 
00674    if (!added_cli) {
00675       ast_cli_register_multiple(cli_translate, sizeof(cli_translate) / sizeof(struct ast_cli_entry));
00676       added_cli++;
00677    }
00678 
00679    AST_RWLIST_WRLOCK(&translators);
00680 
00681    /* find any existing translators that provide this same srcfmt/dstfmt,
00682       and put this one in order based on cost */
00683    AST_RWLIST_TRAVERSE_SAFE_BEGIN(&translators, u, list) {
00684       if ((u->srcfmt == t->srcfmt) &&
00685           (u->dstfmt == t->dstfmt) &&
00686           (u->cost > t->cost)) {
00687          AST_RWLIST_INSERT_BEFORE_CURRENT(t, list);
00688          t = NULL;
00689       }
00690    }
00691    AST_RWLIST_TRAVERSE_SAFE_END;
00692 
00693    /* if no existing translator was found for this format combination,
00694       add it to the beginning of the list */
00695    if (t)
00696       AST_RWLIST_INSERT_HEAD(&translators, t, list);
00697 
00698    rebuild_matrix(0);
00699 
00700    AST_RWLIST_UNLOCK(&translators);
00701 
00702    return 0;
00703 }

static void __fini_translators ( void   )  [static]

Definition at line 46 of file translate.c.

00048 {

static void __init_translators ( void   )  [static]

Definition at line 46 of file translate.c.

00048 {

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

References AST_FRAME_VOICE, AST_FRIENDLY_OFFSET, ast_frisolate(), 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_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().

00205 {
00206    struct ast_frame *f = &pvt->f;
00207 
00208    if (samples)
00209       f->samples = samples;
00210    else {
00211       if (pvt->samples == 0)
00212          return NULL;
00213       f->samples = pvt->samples;
00214       pvt->samples = 0;
00215    }
00216    if (datalen)
00217       f->datalen = datalen;
00218    else {
00219       f->datalen = pvt->datalen;
00220       pvt->datalen = 0;
00221    }
00222 
00223    f->frametype = AST_FRAME_VOICE;
00224    f->subclass = 1 << (pvt->t->dstfmt);
00225    f->mallocd = 0;
00226    f->offset = AST_FRIENDLY_OFFSET;
00227    f->src = pvt->t->name;
00228    f->data = pvt->outbuf;
00229 
00230    return ast_frisolate(f);
00231 }

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 295 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::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(), conf_run(), and process_ast_dsp().

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

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

Mask off unavailable formats from a format bitmask.

Parameters:
dest possible destination formats
src source formats
Returns:
the destination formats that are available in the source or translatable
The result will include all formats from 'dest' that are either present in 'src' or translatable from a format present in 'src'.

Note:
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 817 of file translate.c.

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

Referenced by sip_call().

00818 {
00819    unsigned int res = dest;
00820    unsigned int x;
00821    unsigned int src_audio = src & AST_FORMAT_AUDIO_MASK;
00822    unsigned int src_video = src & AST_FORMAT_VIDEO_MASK;
00823 
00824    /* if we don't have a source format, we just have to try all
00825       possible destination formats */
00826    if (!src)
00827       return dest;
00828 
00829    /* If we have a source audio format, get its format index */
00830    if (src_audio)
00831       src_audio = powerof(src_audio);
00832 
00833    /* If we have a source video format, get its format index */
00834    if (src_video)
00835       src_video = powerof(src_video);
00836 
00837    AST_RWLIST_RDLOCK(&translators);
00838 
00839    /* For a given source audio format, traverse the list of
00840       known audio formats to determine whether there exists
00841       a translation path from the source format to the
00842       destination format. */
00843    for (x = 1; src_audio && (x & AST_FORMAT_AUDIO_MASK); x <<= 1) {
00844       /* if this is not a desired format, nothing to do */
00845       if (!(dest & x))
00846          continue;
00847 
00848       /* if the source is supplying this format, then
00849          we can leave it in the result */
00850       if (src & x)
00851          continue;
00852 
00853       /* if we don't have a translation path from the src
00854          to this format, remove it from the result */
00855       if (!tr_matrix[src_audio][powerof(x)].step) {
00856          res &= ~x;
00857          continue;
00858       }
00859 
00860       /* now check the opposite direction */
00861       if (!tr_matrix[powerof(x)][src_audio].step)
00862          res &= ~x;
00863    }
00864 
00865    /* For a given source video format, traverse the list of
00866       known video formats to determine whether there exists
00867       a translation path from the source format to the
00868       destination format. */
00869    for (; src_video && (x & AST_FORMAT_VIDEO_MASK); x <<= 1) {
00870       /* if this is not a desired format, nothing to do */
00871       if (!(dest & x))
00872          continue;
00873 
00874       /* if the source is supplying this format, then
00875          we can leave it in the result */
00876       if (src & x)
00877          continue;
00878 
00879       /* if we don't have a translation path from the src
00880          to this format, remove it from the result */
00881       if (!tr_matrix[src_video][powerof(x)].step) {
00882          res &= ~x;
00883          continue;
00884       }
00885 
00886       /* now check the opposite direction */
00887       if (!tr_matrix[powerof(x)][src_video].step)
00888          res &= ~x;
00889    }
00890 
00891    AST_RWLIST_UNLOCK(&translators);
00892 
00893    return res;
00894 }

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

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

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

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

00796 {
00797    unsigned int res = -1;
00798 
00799    /* convert bitwise format numbers into array indices */
00800    src = powerof(src);
00801    dest = powerof(dest);
00802 
00803    if (src == -1 || dest == -1) {
00804       ast_log(LOG_WARNING, "No translator path: (%s codec is not valid)\n", src == -1 ? "starting" : "ending");
00805       return -1;
00806    }
00807    AST_RWLIST_RDLOCK(&translators);
00808 
00809    if (tr_matrix[src][dest].step)
00810       res = tr_matrix[src][dest].multistep + 1;
00811 
00812    AST_RWLIST_UNLOCK(&translators);
00813 
00814    return res;
00815 }

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

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

00732 {
00733    AST_RWLIST_WRLOCK(&translators);
00734    t->active = 1;
00735    rebuild_matrix(0);
00736    AST_RWLIST_UNLOCK(&translators);
00737 }

int ast_translator_best_choice ( int *  dst,
int *  srcs 
)

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

Chooses the best translation path.

Definition at line 748 of file translate.c.

References AST_FORMAT_AUDIO_MASK, AST_RWLIST_RDLOCK, AST_RWLIST_UNLOCK, translator_path::cost, ast_translator::cost, MAX_AUDIO_FORMAT, translator_path::multistep, and tr_matrix.

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

00749 {
00750    int x,y;
00751    int best = -1;
00752    int bestdst = 0;
00753    int cur, cursrc;
00754    int besttime = INT_MAX;
00755    int beststeps = INT_MAX;
00756    int common = ((*dst) & (*srcs)) & AST_FORMAT_AUDIO_MASK; /* are there common formats ? */
00757 
00758    if (common) { /* yes, pick one and return */
00759       for (cur = 1, y = 0; y <= MAX_AUDIO_FORMAT; cur <<= 1, y++) {
00760          if (cur & common) /* guaranteed to find one */
00761             break;
00762       }
00763       /* We are done, this is a common format to both. */
00764       *srcs = *dst = cur;
00765       return 0;
00766    } else { /* No, we will need to translate */
00767       AST_RWLIST_RDLOCK(&translators);
00768       for (cur = 1, y = 0; y <= MAX_AUDIO_FORMAT; cur <<= 1, y++) {
00769          if (! (cur & *dst))
00770             continue;
00771          for (cursrc = 1, x = 0; x <= MAX_AUDIO_FORMAT; cursrc <<= 1, x++) {
00772             if (!(*srcs & cursrc) || !tr_matrix[x][y].step ||
00773                 tr_matrix[x][y].cost >  besttime)
00774                continue;   /* not existing or no better */
00775             if (tr_matrix[x][y].cost < besttime ||
00776                 tr_matrix[x][y].multistep < beststeps) {
00777                /* better than what we have so far */
00778                best = cursrc;
00779                bestdst = cur;
00780                besttime = tr_matrix[x][y].cost;
00781                beststeps = tr_matrix[x][y].multistep;
00782             }
00783          }
00784       }
00785       AST_RWLIST_UNLOCK(&translators);
00786       if (best > -1) {
00787          *srcs = best;
00788          *dst = bestdst;
00789          best = 0;
00790       }
00791       return best;
00792    }
00793 }

struct ast_trans_pvt* ast_translator_build_path ( int  dest,
int  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 250 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(), misdn_set_opt_exec(), read_config(), and set_format().

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

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

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

00740 {
00741    AST_RWLIST_WRLOCK(&translators);
00742    t->active = 0;
00743    rebuild_matrix(0);
00744    AST_RWLIST_UNLOCK(&translators);
00745 }

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 240 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_free(), ast_slinfactory_destroy(), ast_slinfactory_feed(), ast_slinfactory_flush(), ast_translator_build_path(), ast_writestream(), audio_audiohook_write_list(), cl_dequeue_chan(), conf_free(), filestream_destructor(), free_translation(), and set_format().

00241 {
00242    struct ast_trans_pvt *pn = p;
00243    while ( (p = pn) ) {
00244       pn = p->next;
00245       destroy(p);
00246    }
00247 }

int ast_unregister_translator ( struct ast_translator t  ) 

unregister codec translator

Unregister a translator Unregisters the given tranlator.

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

00707 {
00708    char tmp[80];
00709    struct ast_translator *u;
00710    int found = 0;
00711 
00712    AST_RWLIST_WRLOCK(&translators);
00713    AST_RWLIST_TRAVERSE_SAFE_BEGIN(&translators, u, list) {
00714       if (u == t) {
00715          AST_RWLIST_REMOVE_CURRENT(list);
00716          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(1 << t->srcfmt), ast_getformatname(1 << t->dstfmt));
00717          found = 1;
00718          break;
00719       }
00720    }
00721    AST_RWLIST_TRAVERSE_SAFE_END;
00722 
00723    if (found)
00724       rebuild_matrix(0);
00725 
00726    AST_RWLIST_UNLOCK(&translators);
00727 
00728    return (u ? 0 : -1);
00729 }

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

compute the cost of a single translation step

Definition at line 371 of file translate.c.

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

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

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

Definition at line 233 of file translate.c.

References ast_trans_frameout().

Referenced by __ast_register_translator().

00234 {
00235    return ast_trans_frameout(pvt, 0, 0);
00236 }

static void destroy ( struct ast_trans_pvt pvt  )  [static]

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

00134 {
00135    struct ast_translator *t = pvt->t;
00136 
00137    if (t->destroy)
00138       t->destroy(pvt);
00139    ast_free(pvt);
00140    ast_module_unref(t->module);
00141 }

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

framein wrapper, deals with plc and bound checks.

Definition at line 144 of file translate.c.

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

Referenced by ast_translate(), and calc_cost().

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

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

Definition at line 505 of file translate.c.

References ast_cli_args::argc, ast_cli_args::argv, ast_cli(), ast_getformatname(), AST_RWLIST_RDLOCK, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, ast_str_alloca, ast_str_append(), ast_str_buffer, ast_str_set(), CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_translator::cost, ast_cli_args::fd, MAX_RECALC, rebuild_matrix(), SHOW_TRANS, tr_matrix, and ast_cli_entry::usage.

00506 {
00507 #define SHOW_TRANS 16
00508    int x, y, z;
00509    int curlen = 0, longest = 0, magnitude[SHOW_TRANS] = { 0, };
00510 
00511    switch (cmd) {
00512    case CLI_INIT:
00513       e->command = "core show translation [recalc]";
00514       e->usage =
00515          "Usage: core show translation [recalc [<recalc seconds>]]\n"
00516          "       Displays known codec translators and the cost associated\n"
00517          "       with each conversion.  If the argument 'recalc' is supplied along\n"
00518          "       with optional number of seconds to test a new test will be performed\n"
00519          "       as the chart is being displayed.\n";
00520       return NULL;
00521    case CLI_GENERATE:
00522       return NULL;
00523    }
00524 
00525    if (a->argc > 5)
00526       return CLI_SHOWUSAGE;
00527 
00528    if (a->argv[3] && !strcasecmp(a->argv[3], "recalc")) {
00529       z = a->argv[4] ? atoi(a->argv[4]) : 1;
00530 
00531       if (z <= 0) {
00532          ast_cli(a->fd, "         Recalc must be greater than 0.  Defaulting to 1.\n");
00533          z = 1;
00534       }
00535 
00536       if (z > MAX_RECALC) {
00537          ast_cli(a->fd, "         Maximum limit of recalc exceeded by %d, truncating value to %d\n", z - MAX_RECALC, MAX_RECALC);
00538          z = MAX_RECALC;
00539       }
00540       ast_cli(a->fd, "         Recalculating Codec Translation (number of sample seconds: %d)\n\n", z);
00541       AST_RWLIST_WRLOCK(&translators);
00542       rebuild_matrix(z);
00543       AST_RWLIST_UNLOCK(&translators);
00544    } else if (a->argc > 3)
00545       return CLI_SHOWUSAGE;
00546 
00547    AST_RWLIST_RDLOCK(&translators);
00548 
00549    ast_cli(a->fd, "         Translation times between formats (in microseconds) for one second of data\n");
00550    ast_cli(a->fd, "          Source Format (Rows) Destination Format (Columns)\n\n");
00551    /* Get the length of the longest (usable?) codec name, so we know how wide the left side should be */
00552    for (x = 0; x < SHOW_TRANS; x++) {
00553       curlen = strlen(ast_getformatname(1 << (x)));
00554       if (curlen > longest)
00555          longest = curlen;
00556       for (y = 0; y < SHOW_TRANS; y++) {
00557          if (tr_matrix[x][y].cost > pow(10, magnitude[x])) {
00558             magnitude[y] = floor(log10(tr_matrix[x][y].cost));
00559          }
00560       }
00561    }
00562    for (x = -1; x < SHOW_TRANS; x++) {
00563       struct ast_str *out = ast_str_alloca(125);
00564       /*Go ahead and move to next iteration if dealing with an unknown codec*/
00565       if(x >= 0 && !strcmp(ast_getformatname(1 << (x)), "unknown"))
00566          continue;
00567       ast_str_set(&out, -1, " ");
00568       for (y = -1; y < SHOW_TRANS; y++) {
00569          /*Go ahead and move to next iteration if dealing with an unknown codec*/
00570          if (y >= 0 && !strcmp(ast_getformatname(1 << (y)), "unknown"))
00571             continue;
00572          if (y >= 0)
00573             curlen = strlen(ast_getformatname(1 << (y)));
00574          if (y >= 0 && magnitude[y] + 1 > curlen) {
00575             curlen = magnitude[y] + 1;
00576          }
00577          if (curlen < 5)
00578             curlen = 5;
00579          if (x >= 0 && y >= 0 && tr_matrix[x][y].step) {
00580             /* Actual codec output */
00581             ast_str_append(&out, -1, "%*d", curlen + 1, tr_matrix[x][y].cost);
00582          } else if (x == -1 && y >= 0) {
00583             /* Top row - use a dynamic size */
00584             ast_str_append(&out, -1, "%*s", curlen + 1, ast_getformatname(1 << (y)) );
00585          } else if (y == -1 && x >= 0) {
00586             /* Left column - use a static size. */
00587             ast_str_append(&out, -1, "%*s", longest, ast_getformatname(1 << (x)) );
00588          } else if (x >= 0 && y >= 0) {
00589             /* Codec not supported */
00590             ast_str_append(&out, -1, "%*s", curlen + 1, "-");
00591          } else {
00592             /* Upper left hand corner */
00593             ast_str_append(&out, -1, "%*s", longest, "");
00594          }
00595       }
00596       ast_str_append(&out, -1, "\n");
00597       ast_cli(a->fd, "%s", ast_str_buffer(out));
00598    }
00599    AST_RWLIST_UNLOCK(&translators);
00600    return CLI_SUCCESS;
00601 }

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

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

Definition at line 93 of file translate.c.

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

Referenced by ast_translator_build_path(), and calc_cost().

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

static force_inline int powerof ( unsigned int  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 73 of file translate.c.

References ast_log(), and LOG_WARNING.

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

00074 {
00075    int x = ffs(d);
00076 
00077    if (x)
00078       return x - 1;
00079 
00080    ast_log(LOG_WARNING, "No bits set? %d\n", d);
00081 
00082    return -1;
00083 }

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 433 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, ast_translator::list, MAX_FORMAT, translator_path::multistep, 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().

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


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 603 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 64 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 Wed Oct 28 11:46:21 2009 for Asterisk - the Open Source PBX by  doxygen 1.5.6