Mon Mar 31 07:42:46 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 680 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.

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

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

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

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

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

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

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

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

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

Referenced by ast_frame_free().

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

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

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

Referenced by ast_channel_make_compatible().

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

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

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

00804 {
00805    AST_LIST_LOCK(&translators);
00806    t->active = 1;
00807    rebuild_matrix(0);
00808    AST_LIST_UNLOCK(&translators);
00809 }

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

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

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

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

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

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

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

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 264 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_translator_build_path(), ast_writestream(), audio_audiohook_write_list(), cl_dequeue_chan(), conf_free(), free_translation(), and set_format().

00265 {
00266    struct ast_trans_pvt *pn = p;
00267    while ( (p = pn) ) {
00268       pn = p->next;
00269       destroy(p);
00270    }
00271 }

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

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

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

compute the cost of a single translation step

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

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

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

Definition at line 257 of file translate.c.

References ast_trans_frameout().

Referenced by __ast_register_translator().

00258 {
00259    return ast_trans_frameout(pvt, 0, 0);
00260 }

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_ERROR, 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    if ( f->data == NULL && f->datalen > 0 ) {
00199       ast_log(LOG_ERROR, "NULL pointer in frame data for %s\n", pvt->t->name);
00200       return -1;
00201    }
00202    /* we require a framein routine, wouldn't know how to do
00203     * it otherwise.
00204     */
00205    ret = pvt->t->framein(pvt, f);
00206    /* possibly store data for plc */
00207    if (!ret && pvt->plc) {
00208       int l = pvt->t->plc_samples;
00209       if (pvt->samples < l)
00210          l = pvt->samples;
00211       plc_rx(pvt->plc, dst + pvt->samples - l, l);
00212    }
00213    /* diagnostic ... */
00214    if (pvt->samples == samples)
00215       ast_log(LOG_WARNING, "%s did not update samples %d\n",
00216          pvt->t->name, pvt->samples);
00217         return ret;
00218 }

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

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

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

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

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

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

CLI "show translation" command handler.

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

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


Variable Documentation

struct ast_cli_entry cli_show_translation_deprecated [static]

Initial value:

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

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

Referenced by __ast_register_translator().

char show_trans_usage[] [static]

Definition at line 661 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 Mar 31 07:42:46 2008 for Asterisk - the Open Source PBX by  doxygen 1.5.1