Fri Aug 13 18:21:32 2010

Asterisk developer's documentation


translate.c File Reference

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

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

Go to the source code of this file.

Data Structures

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

Defines

#define MAX_RECALC   200
#define SHOW_TRANS   13

Functions

int __ast_register_translator (struct ast_translator *t, struct ast_module *mod)
 Register a translator This registers a codec translator with asterisk.
ast_frameast_trans_frameout (struct ast_trans_pvt *pvt, int datalen, int samples)
 generic frameout function
ast_frameast_translate (struct ast_trans_pvt *path, struct ast_frame *f, int consume)
 translates one or more frames Apply an input frame into the translator and receive zero or one output frames. Consume determines whether the original frame should be freed
unsigned int ast_translate_available_formats (unsigned int dest, unsigned int src)
 Mask off unavailable formats from a format bitmask.
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 668 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.

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

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

generic frameout function

Definition at line 209 of file translate.c.

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

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

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

References ast_format_rate(), AST_FRAME_CNG, AST_FRFLAG_HAS_TIMING_INFO, ast_frfree, ast_samp2tv(), ast_set2_flag, ast_test_flag, ast_tv(), ast_tvadd(), ast_tveq(), ast_tvnow(), ast_tvsub(), ast_tvzero(), ast_frame::delivery, f, framein(), ast_frame::frametype, len(), ast_frame::len, ast_trans_pvt::next, ast_trans_pvt::nextin, ast_trans_pvt::nextout, ast_frame::samples, ast_frame::seqno, ast_frame::subclass, and ast_frame::ts.

Referenced by __ast_read(), ast_audiohook_read_frame(), ast_slinfactory_feed(), ast_write(), ast_writestream(), audio_audiohook_write_list(), conf_run(), and process_ast_dsp().

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

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 }

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

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

Referenced by ast_channel_make_compatible().

00860 {
00861    unsigned int res = -1;
00862 
00863    /* convert bitwise format numbers into array indices */
00864    src = powerof(src);
00865    dest = powerof(dest);
00866 
00867    if (src == -1 || dest == -1) {
00868       ast_log(LOG_WARNING, "No translator path: (%s codec is not valid)\n", src == -1 ? "starting" : "ending");
00869       return -1;
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 795 of file translate.c.

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

00796 {
00797    AST_LIST_LOCK(&translators);
00798    t->active = 1;
00799    rebuild_matrix(0);
00800    AST_LIST_UNLOCK(&translators);
00801 }

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

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

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

References ast_getformatname(), AST_LIST_LOCK, AST_LIST_UNLOCK, ast_log(), ast_translator_free_path(), ast_tv(), ast_translator::dstfmt, LOG_WARNING, newpvt(), ast_trans_pvt::next, ast_trans_pvt::nextin, ast_trans_pvt::nextout, powerof(), translator_path::step, t, ast_trans_pvt::t, and tr_matrix.

Referenced by ast_audiohook_read_frame(), ast_slinfactory_feed(), ast_writestream(), audio_audiohook_write_list(), conf_run(), misdn_set_opt_exec(), read_config(), and set_format().

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

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 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 = 0;
00807    rebuild_matrix(0);
00808    AST_LIST_UNLOCK(&translators);
00809 }

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

References destroy(), and ast_trans_pvt::next.

Referenced by ast_audiohook_destroy(), ast_audiohook_detach_list(), ast_audiohook_read_frame(), ast_channel_free(), ast_slinfactory_destroy(), ast_slinfactory_feed(), ast_slinfactory_flush(), ast_translator_build_path(), ast_writestream(), audio_audiohook_write_list(), cl_dequeue_chan(), conf_free(), filestream_destructor(), free_translation(), and set_format().

00247 {
00248    struct ast_trans_pvt *pn = p;
00249    while ( (p = pn) ) {
00250       pn = p->next;
00251       destroy(p);
00252    }
00253 }

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

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

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

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

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

compute the cost of a single translation step

Definition at line 377 of file translate.c.

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

Referenced by __ast_register_translator(), and rebuild_matrix().

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

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

Definition at line 239 of file translate.c.

References ast_trans_frameout().

Referenced by __ast_register_translator().

00240 {
00241    return ast_trans_frameout(pvt, 0, 0);
00242 }

static void destroy ( struct ast_trans_pvt pvt  )  [static]

Definition at line 139 of file translate.c.

References ast_module_unref(), free, ast_trans_pvt::t, and t.

Referenced by ast_translator_free_path(), and calc_cost().

00140 {
00141    struct ast_translator *t = pvt->t;
00142 
00143    if (t->destroy)
00144       t->destroy(pvt);
00145    free(pvt);
00146    ast_module_unref(t->module);
00147 }

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

framein wrapper, deals with plc and bound checks.

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

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

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

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

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

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

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

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

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

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

CLI "show translation" command handler.

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

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


Variable Documentation

struct ast_cli_entry cli_show_translation_deprecated [static]

Initial value:

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

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

Referenced by __ast_register_translator().

char show_trans_usage[] [static]

Definition at line 649 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 Fri Aug 13 18:21:32 2010 for Asterisk - the Open Source PBX by  doxygen 1.4.7