Mon Jul 14 17:25:25 2008

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"

Include dependency graph for translate.c:

Go to the source code of this file.

Data Structures

struct  translator_path

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.
static AST_LIST_HEAD_STATIC (translators, ast_translator)
 the list of translators
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 676 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.

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

static AST_LIST_HEAD_STATIC ( translators  ,
ast_translator   
) [static]

the list of translators

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(), 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 310 of file translate.c.

References ast_format_rate(), AST_FRAME_CNG, AST_FRFLAG_HAS_TIMING_INFO, ast_frfree, ast_set2_flag, ast_test_flag, ast_tvadd(), ast_tvsub(), 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().

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

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

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

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

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

Referenced by ast_frame_free().

00961 {
00962    struct ast_trans_pvt *pvt;
00963 
00964    ast_clear_flag(fr, AST_FRFLAG_FROM_TRANSLATOR);
00965 
00966    pvt = (struct ast_trans_pvt *) (((char *) fr) - offsetof(struct ast_trans_pvt, f));
00967 
00968    if (pvt->datalen != -1)
00969       return;
00970    
00971    destroy(pvt);
00972 }

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

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

Referenced by ast_channel_make_compatible().

00864 {
00865    unsigned int res = -1;
00866 
00867    /* convert bitwise format numbers into array indices */
00868    src = powerof(src);
00869    dest = powerof(dest);
00870 
00871    AST_LIST_LOCK(&translators);
00872 
00873    if (tr_matrix[src][dest].step)
00874       res = tr_matrix[src][dest].multistep + 1;
00875 
00876    AST_LIST_UNLOCK(&translators);
00877 
00878    return res;
00879 }

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

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

00800 {
00801    AST_LIST_LOCK(&translators);
00802    t->active = 1;
00803    rebuild_matrix(0);
00804    AST_LIST_UNLOCK(&translators);
00805 }

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 816 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_with_uniqueid(), iax2_request(), and set_format().

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

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_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    AST_LIST_LOCK(&translators);
00278 
00279    while (source != dest) {
00280       struct ast_trans_pvt *cur;
00281       struct ast_translator *t = tr_matrix[source][dest].step;
00282       if (!t) {
00283          ast_log(LOG_WARNING, "No translator path from %s to %s\n", 
00284             ast_getformatname(source), ast_getformatname(dest));
00285          AST_LIST_UNLOCK(&translators);
00286          return NULL;
00287       }
00288       if (!(cur = newpvt(t))) {
00289          ast_log(LOG_WARNING, "Failed to build translator step from %d to %d\n", source, dest);
00290          if (head)
00291             ast_translator_free_path(head);  
00292          AST_LIST_UNLOCK(&translators);
00293          return NULL;
00294       }
00295       if (!head)
00296          head = cur;
00297       else
00298          tail->next = cur;
00299       tail = cur;
00300       cur->nextin = cur->nextout = ast_tv(0, 0);
00301       /* Keep going if this isn't the final destination */
00302       source = cur->t->dstfmt;
00303    }
00304 
00305    AST_LIST_UNLOCK(&translators);
00306    return head;
00307 }

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

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

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

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_closestream(), ast_slinfactory_destroy(), ast_slinfactory_feed(), ast_slinfactory_flush(), ast_translator_build_path(), ast_writestream(), audio_audiohook_write_list(), cl_dequeue_chan(), conf_free(), 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 773 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, option_verbose, rebuild_matrix(), t, term_color(), and VERBOSE_PREFIX_2.

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

00774 {
00775    char tmp[80];
00776    struct ast_translator *u;
00777    int found = 0;
00778 
00779    AST_LIST_LOCK(&translators);
00780    AST_LIST_TRAVERSE_SAFE_BEGIN(&translators, u, list) {
00781       if (u == t) {
00782          AST_LIST_REMOVE_CURRENT(&translators, list);
00783          if (option_verbose > 1)
00784             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));
00785          found = 1;
00786          break;
00787       }
00788    }
00789    AST_LIST_TRAVERSE_SAFE_END;
00790 
00791    if (found)
00792       rebuild_matrix(0);
00793 
00794    AST_LIST_UNLOCK(&translators);
00795 
00796    return (u ? 0 : -1);
00797 }

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

compute the cost of a single translation step

Definition at line 386 of file translate.c.

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

Referenced by __ast_register_translator(), and rebuild_matrix().

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

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

References ast_getformatname(), AST_LIST_TRAVERSE, ast_log(), calc_cost(), ast_translator::cost, 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().

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

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

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

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

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

CLI "show translation" command handler.

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

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


Variable Documentation

struct ast_cli_entry cli_show_translation_deprecated [static]

Initial value:

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

Definition at line 664 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 669 of file translate.c.

Referenced by __ast_register_translator().

char show_trans_usage[] [static]

Definition at line 657 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 Mon Jul 14 17:25:25 2008 for Asterisk - the Open Source PBX by  doxygen 1.5.1