Wed Mar 4 19:58:53 2009

Asterisk developer's documentation


translate.c File Reference

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

#include "asterisk.h"
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include "asterisk/lock.h"
#include "asterisk/channel.h"
#include "asterisk/logger.h"
#include "asterisk/translate.h"
#include "asterisk/module.h"
#include "asterisk/options.h"
#include "asterisk/frame.h"
#include "asterisk/sched.h"
#include "asterisk/cli.h"
#include "asterisk/term.h"

Go to the source code of this file.

Data Structures

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

Defines

#define MAX_RECALC   200
#define SHOW_TRANS   13

Functions

int __ast_register_translator (struct ast_translator *t, struct ast_module *mod)
 Register a translator This registers a codec translator with asterisk.
ast_frameast_trans_frameout (struct ast_trans_pvt *pvt, int datalen, int samples)
 generic frameout function
ast_frameast_translate (struct ast_trans_pvt *path, struct ast_frame *f, int consume)
 translates one or more frames Apply an input frame into the translator and receive zero or one output frames. Consume determines whether the original frame should be freed
unsigned int ast_translate_available_formats (unsigned int dest, unsigned int src)
 Mask off unavailable formats from a format bitmask.
void ast_translate_frame_freed (struct ast_frame *fr)
 Hint that a frame from a translator has been freed.
unsigned int ast_translate_path_steps (unsigned int dest, unsigned int src)
 Returns the number of steps required to convert from 'src' to 'dest'.
void ast_translator_activate (struct ast_translator *t)
 Activate a previously deactivated translator.
int ast_translator_best_choice (int *dst, int *srcs)
 Chooses the best translation path.
ast_trans_pvtast_translator_build_path (int dest, int source)
 Builds a translator path Build a path (possibly NULL) from source to dest.
void ast_translator_deactivate (struct ast_translator *t)
 Deactivate a translator.
void ast_translator_free_path (struct ast_trans_pvt *p)
 Frees a translator path Frees the given translator path structure.
int ast_unregister_translator (struct ast_translator *t)
 Unregister a translator Unregisters the given tranlator.
static void calc_cost (struct ast_translator *t, int seconds)
 compute the cost of a single translation step
static struct ast_framedefault_frameout (struct ast_trans_pvt *pvt)
static void destroy (struct ast_trans_pvt *pvt)
static int framein (struct ast_trans_pvt *pvt, struct ast_frame *f)
 framein wrapper, deals with plc and bound checks.
static void * newpvt (struct ast_translator *t)
 Allocate the descriptor, required outbuf space, and possibly also plc and desc.
static force_inline int powerof (unsigned int d)
 returns the index of the lowest bit set
static void rebuild_matrix (int samples)
 rebuild a translation matrix.
static int show_translation (int fd, int argc, char *argv[])
static int show_translation_deprecated (int fd, int argc, char *argv[])
 CLI "show translation" command handler.

Variables

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


Detailed Description

Translate via the use of pseudo channels.

Author:
Mark Spencer <markster@digium.com>

Definition in file translate.c.


Define Documentation

#define MAX_RECALC   200

Definition at line 49 of file translate.c.

Referenced by show_translation(), and show_translation_deprecated().

#define SHOW_TRANS   13

Referenced by show_translation(), and show_translation_deprecated().


Function Documentation

int __ast_register_translator ( struct ast_translator t,
struct ast_module module 
)

Register a translator This registers a codec translator with asterisk.

Parameters:
t populated ast_translator structure
module handle to the module that owns this translator
Returns:
0 on success, -1 on failure

Definition at line 682 of file translate.c.

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

00683 {
00684    static int added_cli = 0;
00685    struct ast_translator *u;
00686 
00687    if (!mod) {
00688       ast_log(LOG_WARNING, "Missing module pointer, you need to supply one\n");
00689       return -1;
00690    }
00691 
00692    if (!t->buf_size) {
00693       ast_log(LOG_WARNING, "empty buf size, you need to supply one\n");
00694       return -1;
00695    }
00696 
00697    t->module = mod;
00698 
00699    t->srcfmt = powerof(t->srcfmt);
00700    t->dstfmt = powerof(t->dstfmt);
00701    t->active = 1;
00702 
00703    if (t->srcfmt == -1 || t->dstfmt == -1) {
00704       ast_log(LOG_WARNING, "Invalid translator path: (%s codec is not valid)\n", t->srcfmt == -1 ? "starting" : "ending");
00705       return -1;
00706    }
00707    if (t->plc_samples) {
00708       if (t->buffer_samples < t->plc_samples) {
00709          ast_log(LOG_WARNING, "plc_samples %d buffer_samples %d\n",
00710             t->plc_samples, t->buffer_samples);
00711          return -1;
00712       }
00713       if (t->dstfmt != powerof(AST_FORMAT_SLINEAR))
00714          ast_log(LOG_WARNING, "plc_samples %d format %x\n",
00715             t->plc_samples, t->dstfmt);
00716    }
00717    if (t->srcfmt >= MAX_FORMAT) {
00718       ast_log(LOG_WARNING, "Source format %s is larger than MAX_FORMAT\n", ast_getformatname(t->srcfmt));
00719       return -1;
00720    }
00721 
00722    if (t->dstfmt >= MAX_FORMAT) {
00723       ast_log(LOG_WARNING, "Destination format %s is larger than MAX_FORMAT\n", ast_getformatname(t->dstfmt));
00724       return -1;
00725    }
00726 
00727    if (t->buf_size) {
00728                /*
00729       * Align buf_size properly, rounding up to the machine-specific
00730       * alignment for pointers.
00731       */
00732       struct _test_align { void *a, *b; } p;
00733       int align = (char *)&p.b - (char *)&p.a;
00734 
00735       t->buf_size = ((t->buf_size + align - 1) / align) * align;
00736    }
00737 
00738    if (t->frameout == NULL)
00739       t->frameout = default_frameout;
00740   
00741    calc_cost(t, 1);
00742 
00743    if (option_verbose > 1) {
00744       char tmp[80];
00745 
00746       ast_verbose(VERBOSE_PREFIX_2 "Registered translator '%s' from format %s to %s, cost %d\n",
00747              term_color(tmp, t->name, COLOR_MAGENTA, COLOR_BLACK, sizeof(tmp)),
00748              ast_getformatname(1 << t->srcfmt), ast_getformatname(1 << t->dstfmt), t->cost);
00749    }
00750 
00751    if (!added_cli) {
00752       ast_cli_register_multiple(cli_translate, sizeof(cli_translate) / sizeof(struct ast_cli_entry));
00753       added_cli++;
00754    }
00755 
00756    AST_LIST_LOCK(&translators);
00757 
00758    /* find any existing translators that provide this same srcfmt/dstfmt,
00759       and put this one in order based on cost */
00760    AST_LIST_TRAVERSE_SAFE_BEGIN(&translators, u, list) {
00761       if ((u->srcfmt == t->srcfmt) &&
00762           (u->dstfmt == t->dstfmt) &&
00763           (u->cost > t->cost)) {
00764          AST_LIST_INSERT_BEFORE_CURRENT(&translators, t, list);
00765          t = NULL;
00766       }
00767    }
00768    AST_LIST_TRAVERSE_SAFE_END;
00769 
00770    /* if no existing translator was found for this format combination,
00771       add it to the beginning of the list */
00772    if (t)
00773       AST_LIST_INSERT_HEAD(&translators, t, list);
00774 
00775    rebuild_matrix(0);
00776 
00777    AST_LIST_UNLOCK(&translators);
00778 
00779    return 0;
00780 }

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

generic frameout function

Definition at line 221 of file translate.c.

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

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

00223 {
00224    struct ast_frame *f = &pvt->f;
00225 
00226         if (samples)
00227       f->samples = samples;
00228    else {
00229       if (pvt->samples == 0)
00230          return NULL;
00231       f->samples = pvt->samples;
00232       pvt->samples = 0;
00233    }
00234    if (datalen)
00235       f->datalen = datalen;
00236    else {
00237       f->datalen = pvt->datalen;
00238       pvt->datalen = 0;
00239    }
00240 
00241    f->frametype = AST_FRAME_VOICE;
00242    f->subclass = 1 << (pvt->t->dstfmt);
00243    f->mallocd = 0;
00244    f->offset = AST_FRIENDLY_OFFSET;
00245    f->src = pvt->t->name;
00246    f->data = pvt->outbuf;
00247 
00248    ast_set_flag(f, AST_FRFLAG_FROM_TRANSLATOR);
00249 
00250    return f;
00251 }

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

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

Parameters:
tr translator structure to use for translation
f frame to translate
consume Whether or not to free the original frame
Returns:
an ast_frame of the new translation format on success, NULL on failure

Definition at line 315 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, f, framein(), ast_frame::frametype, len(), ast_frame::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().

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

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

Mask off unavailable formats from a format bitmask.

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

Note that only a single audio format and a single video format can be present in 'src', or the function will produce unexpected results.

Definition at line 895 of file translate.c.

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

Referenced by sip_call().

00896 {
00897    unsigned int res = dest;
00898    unsigned int x;
00899    unsigned int src_audio = src & AST_FORMAT_AUDIO_MASK;
00900    unsigned int src_video = src & AST_FORMAT_VIDEO_MASK;
00901 
00902    /* if we don't have a source format, we just have to try all
00903       possible destination formats */
00904    if (!src)
00905       return dest;
00906 
00907    /* If we have a source audio format, get its format index */
00908    if (src_audio)
00909       src_audio = powerof(src_audio);
00910 
00911    /* If we have a source video format, get its format index */
00912    if (src_video)
00913       src_video = powerof(src_video);
00914 
00915    AST_LIST_LOCK(&translators);
00916 
00917    /* For a given source audio format, traverse the list of
00918       known audio formats to determine whether there exists
00919       a translation path from the source format to the
00920       destination format. */
00921    for (x = 1; src_audio && x < AST_FORMAT_MAX_AUDIO; x <<= 1) {
00922       /* if this is not a desired format, nothing to do */
00923       if (!dest & x)
00924          continue;
00925 
00926       /* if the source is supplying this format, then
00927          we can leave it in the result */
00928       if (src & x)
00929          continue;
00930 
00931       /* if we don't have a translation path from the src
00932          to this format, remove it from the result */
00933       if (!tr_matrix[src_audio][powerof(x)].step) {
00934          res &= ~x;
00935          continue;
00936       }
00937 
00938       /* now check the opposite direction */
00939       if (!tr_matrix[powerof(x)][src_audio].step)
00940          res &= ~x;
00941    }
00942 
00943    /* For a given source video format, traverse the list of
00944       known video formats to determine whether there exists
00945       a translation path from the source format to the
00946       destination format. */
00947    for (; src_video && x < AST_FORMAT_MAX_VIDEO; x <<= 1) {
00948       /* if this is not a desired format, nothing to do */
00949       if (!dest & x)
00950          continue;
00951 
00952       /* if the source is supplying this format, then
00953          we can leave it in the result */
00954       if (src & x)
00955          continue;
00956 
00957       /* if we don't have a translation path from the src
00958          to this format, remove it from the result */
00959       if (!tr_matrix[src_video][powerof(x)].step) {
00960          res &= ~x;
00961          continue;
00962       }
00963 
00964       /* now check the opposite direction */
00965       if (!tr_matrix[powerof(x)][src_video].step)
00966          res &= ~x;
00967    }
00968 
00969    AST_LIST_UNLOCK(&translators);
00970 
00971    return res;
00972 }

void ast_translate_frame_freed ( struct ast_frame fr  ) 

Hint that a frame from a translator has been freed.

This is sort of a hack. This function gets called when ast_frame_free() gets called on a frame that has the AST_FRFLAG_FROM_TRANSLATOR flag set. This is because it is possible for a translation path to be destroyed while a frame from a translator is still in use. Specifically, this happens if a masquerade happens after a call to ast_read() but before the frame is done being processed, since the frame processing is generally done without the channel lock held.

Returns:
nothing

Definition at line 974 of file translate.c.

References ast_clear_flag, AST_FRFLAG_FROM_TRANSLATOR, destroy(), f, and ast_trans_pvt::pvt.

Referenced by ast_frame_free().

00975 {
00976    struct ast_trans_pvt *pvt;
00977 
00978    ast_clear_flag(fr, AST_FRFLAG_FROM_TRANSLATOR);
00979 
00980    pvt = (struct ast_trans_pvt *) (((char *) fr) - offsetof(struct ast_trans_pvt, f));
00981 
00982    if (pvt->datalen != -1)
00983       return;
00984    
00985    destroy(pvt);
00986 }

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

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

Referenced by ast_channel_make_compatible().

00874 {
00875    unsigned int res = -1;
00876 
00877    /* convert bitwise format numbers into array indices */
00878    src = powerof(src);
00879    dest = powerof(dest);
00880 
00881    if (src == -1 || dest == -1) {
00882       ast_log(LOG_WARNING, "No translator path: (%s codec is not valid)\n", src == -1 ? "starting" : "ending");
00883       return -1;
00884    }
00885    AST_LIST_LOCK(&translators);
00886 
00887    if (tr_matrix[src][dest].step)
00888       res = tr_matrix[src][dest].multistep + 1;
00889 
00890    AST_LIST_UNLOCK(&translators);
00891 
00892    return res;
00893 }

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

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

00810 {
00811    AST_LIST_LOCK(&translators);
00812    t->active = 1;
00813    rebuild_matrix(0);
00814    AST_LIST_UNLOCK(&translators);
00815 }

int ast_translator_best_choice ( int *  dsts,
int *  srcs 
)

Chooses the best translation path.

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

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

Definition at line 826 of file translate.c.

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

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

00827 {
00828    int x,y;
00829    int best = -1;
00830    int bestdst = 0;
00831    int cur, cursrc;
00832    int besttime = INT_MAX;
00833    int beststeps = INT_MAX;
00834    int common = ((*dst) & (*srcs)) & AST_FORMAT_AUDIO_MASK; /* are there common formats ? */
00835 
00836    if (common) { /* yes, pick one and return */
00837       for (cur = 1, y = 0; y <= MAX_AUDIO_FORMAT; cur <<= 1, y++) {
00838          if (cur & common) /* guaranteed to find one */
00839             break;
00840       }
00841       /* We are done, this is a common format to both. */
00842       *srcs = *dst = cur;
00843       return 0;
00844    } else { /* No, we will need to translate */
00845       AST_LIST_LOCK(&translators);
00846       for (cur = 1, y = 0; y <= MAX_AUDIO_FORMAT; cur <<= 1, y++) {
00847          if (! (cur & *dst))
00848             continue;
00849          for (cursrc = 1, x = 0; x <= MAX_AUDIO_FORMAT; cursrc <<= 1, x++) {
00850             if (!(*srcs & cursrc) || !tr_matrix[x][y].step ||
00851                 tr_matrix[x][y].cost >  besttime)
00852                continue;   /* not existing or no better */
00853             if (tr_matrix[x][y].cost < besttime ||
00854                 tr_matrix[x][y].multistep < beststeps) {
00855                /* better than what we have so far */
00856                best = cursrc;
00857                bestdst = cur;
00858                besttime = tr_matrix[x][y].cost;
00859                beststeps = tr_matrix[x][y].multistep;
00860             }
00861          }
00862       }
00863       AST_LIST_UNLOCK(&translators);
00864       if (best > -1) {
00865          *srcs = best;
00866          *dst = bestdst;
00867          best = 0;
00868       }
00869       return best;
00870    }
00871 }

struct ast_trans_pvt* ast_translator_build_path ( int  dest,
int  source 
)

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

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

Definition at line 270 of file translate.c.

References ast_getformatname(), AST_LIST_LOCK, AST_LIST_UNLOCK, ast_log(), 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, t, 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().

00271 {
00272    struct ast_trans_pvt *head = NULL, *tail = NULL;
00273    
00274    source = powerof(source);
00275    dest = powerof(dest);
00276 
00277    if (source == -1 || dest == -1) {
00278       ast_log(LOG_WARNING, "No translator path: (%s codec is not valid)\n", source == -1 ? "starting" : "ending");
00279       return NULL;
00280    }
00281 
00282    AST_LIST_LOCK(&translators);
00283 
00284    while (source != dest) {
00285       struct ast_trans_pvt *cur;
00286       struct ast_translator *t = tr_matrix[source][dest].step;
00287       if (!t) {
00288          ast_log(LOG_WARNING, "No translator path from %s to %s\n", 
00289             ast_getformatname(source), ast_getformatname(dest));
00290          AST_LIST_UNLOCK(&translators);
00291          return NULL;
00292       }
00293       if (!(cur = newpvt(t))) {
00294          ast_log(LOG_WARNING, "Failed to build translator step from %d to %d\n", source, dest);
00295          if (head)
00296             ast_translator_free_path(head);  
00297          AST_LIST_UNLOCK(&translators);
00298          return NULL;
00299       }
00300       if (!head)
00301          head = cur;
00302       else
00303          tail->next = cur;
00304       tail = cur;
00305       cur->nextin = cur->nextout = ast_tv(0, 0);
00306       /* Keep going if this isn't the final destination */
00307       source = cur->t->dstfmt;
00308    }
00309 
00310    AST_LIST_UNLOCK(&translators);
00311    return head;
00312 }

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

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

00818 {
00819    AST_LIST_LOCK(&translators);
00820    t->active = 0;
00821    rebuild_matrix(0);
00822    AST_LIST_UNLOCK(&translators);
00823 }

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

00261 {
00262    struct ast_trans_pvt *pn = p;
00263    while ( (p = pn) ) {
00264       pn = p->next;
00265       destroy(p);
00266    }
00267 }

int ast_unregister_translator ( struct ast_translator t  ) 

Unregister a translator Unregisters the given tranlator.

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

Definition at line 783 of file translate.c.

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

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

00784 {
00785    char tmp[80];
00786    struct ast_translator *u;
00787    int found = 0;
00788 
00789    AST_LIST_LOCK(&translators);
00790    AST_LIST_TRAVERSE_SAFE_BEGIN(&translators, u, list) {
00791       if (u == t) {
00792          AST_LIST_REMOVE_CURRENT(&translators, list);
00793          if (option_verbose > 1)
00794             ast_verbose(VERBOSE_PREFIX_2 "Unregistered translator '%s' from format %s to %s\n", term_color(tmp, t->name, COLOR_MAGENTA, COLOR_BLACK, sizeof(tmp)), ast_getformatname(1 << t->srcfmt), ast_getformatname(1 << t->dstfmt));
00795          found = 1;
00796          break;
00797       }
00798    }
00799    AST_LIST_TRAVERSE_SAFE_END;
00800 
00801    if (found)
00802       rebuild_matrix(0);
00803 
00804    AST_LIST_UNLOCK(&translators);
00805 
00806    return (u ? 0 : -1);
00807 }

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

compute the cost of a single translation step

Definition at line 391 of file translate.c.

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

Referenced by __ast_register_translator(), and rebuild_matrix().

00392 {
00393    int num_samples = 0;
00394    struct ast_trans_pvt *pvt;
00395    struct timeval start;
00396    int cost;
00397    int out_rate = ast_format_rate(t->dstfmt);
00398 
00399    if (!seconds)
00400       seconds = 1;
00401    
00402    /* If they don't make samples, give them a terrible score */
00403    if (!t->sample) {
00404       ast_log(LOG_WARNING, "Translator '%s' does not produce sample frames.\n", t->name);
00405       t->cost = 99999;
00406       return;
00407    }
00408 
00409    pvt = newpvt(t);
00410    if (!pvt) {
00411       ast_log(LOG_WARNING, "Translator '%s' appears to be broken and will probably fail.\n", t->name);
00412       t->cost = 99999;
00413       return;
00414    }
00415 
00416    start = ast_tvnow();
00417 
00418    /* Call the encoder until we've processed the required number of samples */
00419    while (num_samples < seconds * out_rate) {
00420       struct ast_frame *f = t->sample();
00421       if (!f) {
00422          ast_log(LOG_WARNING, "Translator '%s' failed to produce a sample frame.\n", t->name);
00423          destroy(pvt);
00424          t->cost = 99999;
00425          return;
00426       }
00427       framein(pvt, f);
00428       ast_frfree(f);
00429       while ((f = t->frameout(pvt))) {
00430          num_samples += f->samples;
00431          ast_frfree(f);
00432       }
00433    }
00434 
00435    cost = ast_tvdiff_ms(ast_tvnow(), start);
00436 
00437    destroy(pvt);
00438 
00439    t->cost = cost / seconds;
00440 
00441    if (!t->cost)
00442       t->cost = 1;
00443 }

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

Definition at line 253 of file translate.c.

References ast_trans_frameout().

Referenced by __ast_register_translator().

00254 {
00255    return ast_trans_frameout(pvt, 0, 0);
00256 }

static void destroy ( struct ast_trans_pvt pvt  )  [static]

Definition at line 139 of file translate.c.

References AST_FRFLAG_FROM_TRANSLATOR, ast_module_unref(), ast_test_flag, ast_trans_pvt::datalen, ast_trans_pvt::f, free, ast_trans_pvt::t, and t.

Referenced by ast_translate_frame_freed(), ast_translator_free_path(), and calc_cost().

00140 {
00141    struct ast_translator *t = pvt->t;
00142 
00143    if (ast_test_flag(&pvt->f, AST_FRFLAG_FROM_TRANSLATOR)) {
00144       /* If this flag is still set, that means that the translation path has
00145        * been torn down, while we still have a frame out there being used.
00146        * When ast_frfree() gets called on that frame, this ast_trans_pvt
00147        * will get destroyed, too. */
00148 
00149       /* Set the magic hint that this has been requested to be destroyed. */
00150       pvt->datalen = -1;
00151 
00152       return;
00153    }
00154 
00155    if (t->destroy)
00156       t->destroy(pvt);
00157    free(pvt);
00158    ast_module_unref(t->module);
00159 }

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

framein wrapper, deals with plc and bound checks.

Definition at line 162 of file translate.c.

References ast_copy_flags, AST_FRFLAG_HAS_TIMING_INFO, ast_log(), ast_translator::buffer_samples, ast_trans_pvt::datalen, f, 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_trans_pvt::samples, ast_frame::seqno, ast_trans_pvt::t, and ast_frame::ts.

Referenced by ast_translate(), and calc_cost().

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

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

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

Definition at line 99 of file translate.c.

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

Referenced by ast_translator_build_path(), and calc_cost().

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

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

returns the index of the lowest bit set

Definition at line 79 of file translate.c.

References ast_log(), and LOG_WARNING.

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

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

static void rebuild_matrix ( int  samples  )  [static]

rebuild a translation matrix.

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

Definition at line 449 of file translate.c.

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

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

00450 {
00451    struct ast_translator *t;
00452    int x;      /* source format index */
00453    int y;      /* intermediate format index */
00454    int z;      /* destination format index */
00455 
00456    if (option_debug)
00457       ast_log(LOG_DEBUG, "Resetting translation matrix\n");
00458 
00459    bzero(tr_matrix, sizeof(tr_matrix));
00460 
00461    /* first, compute all direct costs */
00462    AST_LIST_TRAVERSE(&translators, t, list) {
00463       if (!t->active)
00464          continue;
00465 
00466       x = t->srcfmt;
00467       z = t->dstfmt;
00468 
00469       if (samples)
00470          calc_cost(t, samples);
00471      
00472       if (!tr_matrix[x][z].step || t->cost < tr_matrix[x][z].cost) {
00473          tr_matrix[x][z].step = t;
00474          tr_matrix[x][z].cost = t->cost;
00475       }
00476    }
00477 
00478    /*
00479     * For each triple x, y, z of distinct formats, check if there is
00480     * a path from x to z through y which is cheaper than what is
00481     * currently known, and in case, update the matrix.
00482     * Repeat until the matrix is stable.
00483     */
00484    for (;;) {
00485       int changed = 0;
00486       for (x = 0; x < MAX_FORMAT; x++) {      /* source format */
00487          for (y=0; y < MAX_FORMAT; y++) {    /* intermediate format */
00488             if (x == y)                     /* skip ourselves */
00489                continue;
00490 
00491             for (z=0; z<MAX_FORMAT; z++) {  /* dst format */
00492                int newcost;
00493 
00494                if (z == x || z == y)       /* skip null conversions */
00495                   continue;
00496                if (!tr_matrix[x][y].step)  /* no path from x to y */
00497                   continue;
00498                if (!tr_matrix[y][z].step)  /* no path from y to z */
00499                   continue;
00500                newcost = tr_matrix[x][y].cost + tr_matrix[y][z].cost;
00501                if (tr_matrix[x][z].step && newcost >= tr_matrix[x][z].cost)
00502                   continue;               /* x->y->z is more expensive than
00503                                            * the existing path */
00504                /* ok, we can get from x to z via y with a cost that
00505                   is the sum of the transition from x to y and
00506                   from y to z */
00507                    
00508                tr_matrix[x][z].step = tr_matrix[x][y].step;
00509                tr_matrix[x][z].cost = newcost;
00510                tr_matrix[x][z].multistep = 1;
00511                if (option_debug)
00512                   ast_log(LOG_DEBUG, "Discovered %d cost path from %s to %s, via %s\n", tr_matrix[x][z].cost,
00513                      ast_getformatname(1 << x), ast_getformatname(1 << z), ast_getformatname(1 << y));
00514                changed++;
00515             }
00516          }
00517       }
00518       if (!changed)
00519          break;
00520    }
00521 }

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

Definition at line 594 of file translate.c.

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

00595 {
00596    int x, y, z;
00597    int curlen = 0, longest = 0;
00598 
00599    if (argc > 5)
00600       return RESULT_SHOWUSAGE;
00601 
00602    AST_LIST_LOCK(&translators);  
00603    
00604    if (argv[3] && !strcasecmp(argv[3], "recalc")) {
00605       z = argv[4] ? atoi(argv[4]) : 1;
00606 
00607       if (z <= 0) {
00608          ast_cli(fd, "         C'mon let's be serious here... defaulting to 1.\n");
00609          z = 1;
00610       }
00611 
00612       if (z > MAX_RECALC) {
00613          ast_cli(fd, "         Maximum limit of recalc exceeded by %d, truncating value to %d\n", z - MAX_RECALC, MAX_RECALC);
00614          z = MAX_RECALC;
00615       }
00616       ast_cli(fd, "         Recalculating Codec Translation (number of sample seconds: %d)\n\n", z);
00617       rebuild_matrix(z);
00618    }
00619 
00620    ast_cli(fd, "         Translation times between formats (in milliseconds) for one second of data\n");
00621    ast_cli(fd, "          Source Format (Rows) Destination Format (Columns)\n\n");
00622    /* Get the length of the longest (usable?) codec name, so we know how wide the left side should be */
00623    for (x = 0; x < SHOW_TRANS; x++) {
00624       curlen = strlen(ast_getformatname(1 << (x)));
00625       if (curlen > longest)
00626          longest = curlen;
00627    }
00628    for (x = -1; x < SHOW_TRANS; x++) {
00629       char line[120];
00630       char *buf = line;
00631       size_t left = sizeof(line) - 1;  /* one initial space */
00632       /* next 2 lines run faster than using ast_build_string() */
00633       *buf++ = ' ';
00634       *buf = '\0';
00635       for (y = -1; y < SHOW_TRANS; y++) {
00636          if (y >= 0)
00637             curlen = strlen(ast_getformatname(1 << (y)));
00638 
00639          if (x >= 0 && y >= 0 && tr_matrix[x][y].step) {
00640             /* XXX 999 is a little hackish
00641                We don't want this number being larger than the shortest (or current) codec
00642                For now, that is "gsm" */
00643             ast_build_string(&buf, &left, "%*d", curlen + 1, tr_matrix[x][y].cost > 999 ? 0 : tr_matrix[x][y].cost);
00644          } else if (x == -1 && y >= 0) {
00645             /* Top row - use a dynamic size */
00646             ast_build_string(&buf, &left, "%*s", curlen + 1, ast_getformatname(1 << (y)) );
00647          } else if (y == -1 && x >= 0) {
00648             /* Left column - use a static size. */
00649             ast_build_string(&buf, &left, "%*s", longest, ast_getformatname(1 << (x)) );
00650          } else if (x >= 0 && y >= 0) {
00651             ast_build_string(&buf, &left, "%*s", curlen + 1, "-");
00652          } else {
00653             ast_build_string(&buf, &left, "%*s", longest, "");
00654          }
00655       }
00656       ast_build_string(&buf, &left, "\n");
00657       ast_cli(fd, "%s", line);         
00658    }
00659    AST_LIST_UNLOCK(&translators);
00660    return RESULT_SUCCESS;
00661 }

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

CLI "show translation" command handler.

Definition at line 524 of file translate.c.

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

00525 {
00526 #define SHOW_TRANS 13
00527    int x, y, z;
00528    int curlen = 0, longest = 0;
00529 
00530    if (argc > 4) 
00531       return RESULT_SHOWUSAGE;
00532 
00533    AST_LIST_LOCK(&translators);  
00534    
00535    if (argv[2] && !strcasecmp(argv[2], "recalc")) {
00536       z = argv[3] ? atoi(argv[3]) : 1;
00537 
00538       if (z <= 0) {
00539          ast_cli(fd, "         C'mon let's be serious here... defaulting to 1.\n");
00540          z = 1;
00541       }
00542 
00543       if (z > MAX_RECALC) {
00544          ast_cli(fd, "         Maximum limit of recalc exceeded by %d, truncating value to %d\n", z - MAX_RECALC, MAX_RECALC);
00545          z = MAX_RECALC;
00546       }
00547       ast_cli(fd, "         Recalculating Codec Translation (number of sample seconds: %d)\n\n", z);
00548       rebuild_matrix(z);
00549    }
00550 
00551    ast_cli(fd, "         Translation times between formats (in milliseconds) for one second of data\n");
00552    ast_cli(fd, "          Source Format (Rows) Destination Format (Columns)\n\n");
00553    /* Get the length of the longest (usable?) codec name, so we know how wide the left side should be */
00554    for (x = 0; x < SHOW_TRANS; x++) {
00555       curlen = strlen(ast_getformatname(1 << (x)));
00556       if (curlen > longest)
00557          longest = curlen;
00558    }
00559    for (x = -1; x < SHOW_TRANS; x++) {
00560       char line[120];
00561       char *buf = line;
00562       size_t left = sizeof(line) - 1;  /* one initial space */
00563       /* next 2 lines run faster than using ast_build_string() */
00564       *buf++ = ' ';
00565       *buf = '\0';
00566       for (y = -1; y < SHOW_TRANS; y++) {
00567          if (y >= 0)
00568             curlen = strlen(ast_getformatname(1 << (y)));
00569 
00570          if (x >= 0 && y >= 0 && tr_matrix[x][y].step) {
00571             /* XXX 999 is a little hackish
00572                We don't want this number being larger than the shortest (or current) codec
00573                For now, that is "gsm" */
00574             ast_build_string(&buf, &left, "%*d", curlen + 1, tr_matrix[x][y].cost > 999 ? 0 : tr_matrix[x][y].cost);
00575          } else if (x == -1 && y >= 0) {
00576             /* Top row - use a dynamic size */
00577             ast_build_string(&buf, &left, "%*s", curlen + 1, ast_getformatname(1 << (y)) );
00578          } else if (y == -1 && x >= 0) {
00579             /* Left column - use a static size. */
00580             ast_build_string(&buf, &left, "%*s", longest, ast_getformatname(1 << (x)) );
00581          } else if (x >= 0 && y >= 0) {
00582             ast_build_string(&buf, &left, "%*s", curlen + 1, "-");
00583          } else {
00584             ast_build_string(&buf, &left, "%*s", longest, "");
00585          }
00586       }
00587       ast_build_string(&buf, &left, "\n");
00588       ast_cli(fd, "%s", line);         
00589    }
00590    AST_LIST_UNLOCK(&translators);
00591    return RESULT_SUCCESS;
00592 }


Variable Documentation

struct ast_cli_entry cli_show_translation_deprecated [static]

Initial value:

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

Definition at line 670 of file translate.c.

struct ast_cli_entry cli_translate[] [static]

Initial value:

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

Definition at line 675 of file translate.c.

Referenced by __ast_register_translator().

char show_trans_usage[] [static]

Definition at line 663 of file translate.c.

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

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

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

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

Definition at line 70 of file translate.c.

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


Generated on Wed Mar 4 19:58:53 2009 for Asterisk - the Open Source PBX by  doxygen 1.4.7