Sat Aug 6 00:40:06 2011

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 bound checks.
static void * newpvt (struct ast_translator *t)
 Allocate the descriptor, required outbuf space, and possibly 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 643 of file translate.c.

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

00644 {
00645    static int added_cli = 0;
00646    struct ast_translator *u;
00647 
00648    if (!mod) {
00649       ast_log(LOG_WARNING, "Missing module pointer, you need to supply one\n");
00650       return -1;
00651    }
00652 
00653    if (!t->buf_size) {
00654       ast_log(LOG_WARNING, "empty buf size, you need to supply one\n");
00655       return -1;
00656    }
00657 
00658    t->module = mod;
00659 
00660    t->srcfmt = powerof(t->srcfmt);
00661    t->dstfmt = powerof(t->dstfmt);
00662    t->active = 1;
00663 
00664    if (t->srcfmt == -1 || t->dstfmt == -1) {
00665       ast_log(LOG_WARNING, "Invalid translator path: (%s codec is not valid)\n", t->srcfmt == -1 ? "starting" : "ending");
00666       return -1;
00667    }
00668    
00669    if (t->srcfmt >= MAX_FORMAT) {
00670       ast_log(LOG_WARNING, "Source format %s is larger than MAX_FORMAT\n", ast_getformatname(t->srcfmt));
00671       return -1;
00672    }
00673 
00674    if (t->dstfmt >= MAX_FORMAT) {
00675       ast_log(LOG_WARNING, "Destination format %s is larger than MAX_FORMAT\n", ast_getformatname(t->dstfmt));
00676       return -1;
00677    }
00678 
00679    if (t->buf_size) {
00680                /*
00681       * Align buf_size properly, rounding up to the machine-specific
00682       * alignment for pointers.
00683       */
00684       struct _test_align { void *a, *b; } p;
00685       int align = (char *)&p.b - (char *)&p.a;
00686 
00687       t->buf_size = ((t->buf_size + align - 1) / align) * align;
00688    }
00689 
00690    if (t->frameout == NULL)
00691       t->frameout = default_frameout;
00692   
00693    calc_cost(t, 1);
00694 
00695    if (option_verbose > 1) {
00696       char tmp[80];
00697 
00698       ast_verbose(VERBOSE_PREFIX_2 "Registered translator '%s' from format %s to %s, cost %d\n",
00699              term_color(tmp, t->name, COLOR_MAGENTA, COLOR_BLACK, sizeof(tmp)),
00700              ast_getformatname(1 << t->srcfmt), ast_getformatname(1 << t->dstfmt), t->cost);
00701    }
00702 
00703    if (!added_cli) {
00704       ast_cli_register_multiple(cli_translate, sizeof(cli_translate) / sizeof(struct ast_cli_entry));
00705       added_cli++;
00706    }
00707 
00708    AST_LIST_LOCK(&translators);
00709 
00710    /* find any existing translators that provide this same srcfmt/dstfmt,
00711       and put this one in order based on cost */
00712    AST_LIST_TRAVERSE_SAFE_BEGIN(&translators, u, list) {
00713       if ((u->srcfmt == t->srcfmt) &&
00714           (u->dstfmt == t->dstfmt) &&
00715           (u->cost > t->cost)) {
00716          AST_LIST_INSERT_BEFORE_CURRENT(&translators, t, list);
00717          t = NULL;
00718       }
00719    }
00720    AST_LIST_TRAVERSE_SAFE_END;
00721 
00722    /* if no existing translator was found for this format combination,
00723       add it to the beginning of the list */
00724    if (t)
00725       AST_LIST_INSERT_HEAD(&translators, t, list);
00726 
00727    rebuild_matrix(0);
00728 
00729    AST_LIST_UNLOCK(&translators);
00730 
00731    return 0;
00732 }

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

generic frameout function

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

00186 {
00187    struct ast_frame *f = &pvt->f;
00188 
00189         if (samples)
00190       f->samples = samples;
00191    else {
00192       if (pvt->samples == 0)
00193          return NULL;
00194       f->samples = pvt->samples;
00195       pvt->samples = 0;
00196    }
00197    if (datalen)
00198       f->datalen = datalen;
00199    else {
00200       f->datalen = pvt->datalen;
00201       pvt->datalen = 0;
00202    }
00203 
00204    f->frametype = AST_FRAME_VOICE;
00205    f->subclass = 1 << (pvt->t->dstfmt);
00206    f->mallocd = 0;
00207    f->offset = AST_FRIENDLY_OFFSET;
00208    f->src = pvt->t->name;
00209    f->data = pvt->outbuf;
00210 
00211    return ast_frisolate(f);
00212 }

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 276 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(), and conf_run().

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

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

00848 {
00849    unsigned int res = dest;
00850    unsigned int x;
00851    unsigned int src_audio = src & AST_FORMAT_AUDIO_MASK;
00852    unsigned int src_video = src & AST_FORMAT_VIDEO_MASK;
00853 
00854    /* if we don't have a source format, we just have to try all
00855       possible destination formats */
00856    if (!src)
00857       return dest;
00858 
00859    /* If we have a source audio format, get its format index */
00860    if (src_audio)
00861       src_audio = powerof(src_audio);
00862 
00863    /* If we have a source video format, get its format index */
00864    if (src_video)
00865       src_video = powerof(src_video);
00866 
00867    AST_LIST_LOCK(&translators);
00868 
00869    /* For a given source audio format, traverse the list of
00870       known audio formats to determine whether there exists
00871       a translation path from the source format to the
00872       destination format. */
00873    for (x = 1; src_audio && x < AST_FORMAT_MAX_AUDIO; x <<= 1) {
00874       /* if this is not a desired format, nothing to do */
00875       if (!(dest & x))
00876          continue;
00877 
00878       /* if the source is supplying this format, then
00879          we can leave it in the result */
00880       if (src & x)
00881          continue;
00882 
00883       /* if we don't have a translation path from the src
00884          to this format, remove it from the result */
00885       if (!tr_matrix[src_audio][powerof(x)].step) {
00886          res &= ~x;
00887          continue;
00888       }
00889 
00890       /* now check the opposite direction */
00891       if (!tr_matrix[powerof(x)][src_audio].step)
00892          res &= ~x;
00893    }
00894 
00895    /* For a given source video format, traverse the list of
00896       known video formats to determine whether there exists
00897       a translation path from the source format to the
00898       destination format. */
00899    for (; src_video && x < AST_FORMAT_MAX_VIDEO; x <<= 1) {
00900       /* if this is not a desired format, nothing to do */
00901       if (!(dest & x))
00902          continue;
00903 
00904       /* if the source is supplying this format, then
00905          we can leave it in the result */
00906       if (src & x)
00907          continue;
00908 
00909       /* if we don't have a translation path from the src
00910          to this format, remove it from the result */
00911       if (!tr_matrix[src_video][powerof(x)].step) {
00912          res &= ~x;
00913          continue;
00914       }
00915 
00916       /* now check the opposite direction */
00917       if (!tr_matrix[powerof(x)][src_video].step)
00918          res &= ~x;
00919    }
00920 
00921    AST_LIST_UNLOCK(&translators);
00922 
00923    return res;
00924 }

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

00826 {
00827    unsigned int res = -1;
00828 
00829    /* convert bitwise format numbers into array indices */
00830    src = powerof(src);
00831    dest = powerof(dest);
00832 
00833    if (src == -1 || dest == -1) {
00834       ast_log(LOG_WARNING, "No translator path: (%s codec is not valid)\n", src == -1 ? "starting" : "ending");
00835       return -1;
00836    }
00837    AST_LIST_LOCK(&translators);
00838 
00839    if (tr_matrix[src][dest].step)
00840       res = tr_matrix[src][dest].multistep + 1;
00841 
00842    AST_LIST_UNLOCK(&translators);
00843 
00844    return res;
00845 }

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

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

00762 {
00763    AST_LIST_LOCK(&translators);
00764    t->active = 1;
00765    rebuild_matrix(0);
00766    AST_LIST_UNLOCK(&translators);
00767 }

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

00779 {
00780    int x,y;
00781    int best = -1;
00782    int bestdst = 0;
00783    int cur, cursrc;
00784    int besttime = INT_MAX;
00785    int beststeps = INT_MAX;
00786    int common = ((*dst) & (*srcs)) & AST_FORMAT_AUDIO_MASK; /* are there common formats ? */
00787 
00788    if (common) { /* yes, pick one and return */
00789       for (cur = 1, y = 0; y <= MAX_AUDIO_FORMAT; cur <<= 1, y++) {
00790          if (cur & common) /* guaranteed to find one */
00791             break;
00792       }
00793       /* We are done, this is a common format to both. */
00794       *srcs = *dst = cur;
00795       return 0;
00796    } else { /* No, we will need to translate */
00797       AST_LIST_LOCK(&translators);
00798       for (cur = 1, y = 0; y <= MAX_AUDIO_FORMAT; cur <<= 1, y++) {
00799          if (! (cur & *dst))
00800             continue;
00801          for (cursrc = 1, x = 0; x <= MAX_AUDIO_FORMAT; cursrc <<= 1, x++) {
00802             if (!(*srcs & cursrc) || !tr_matrix[x][y].step ||
00803                 tr_matrix[x][y].cost >  besttime)
00804                continue;   /* not existing or no better */
00805             if (tr_matrix[x][y].cost < besttime ||
00806                 tr_matrix[x][y].multistep < beststeps) {
00807                /* better than what we have so far */
00808                best = cursrc;
00809                bestdst = cur;
00810                besttime = tr_matrix[x][y].cost;
00811                beststeps = tr_matrix[x][y].multistep;
00812             }
00813          }
00814       }
00815       AST_LIST_UNLOCK(&translators);
00816       if (best > -1) {
00817          *srcs = best;
00818          *dst = bestdst;
00819          best = 0;
00820       }
00821       return best;
00822    }
00823 }

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 231 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(), and set_format().

00232 {
00233    struct ast_trans_pvt *head = NULL, *tail = NULL;
00234    
00235    source = powerof(source);
00236    dest = powerof(dest);
00237 
00238    if (source == -1 || dest == -1) {
00239       ast_log(LOG_WARNING, "No translator path: (%s codec is not valid)\n", source == -1 ? "starting" : "ending");
00240       return NULL;
00241    }
00242 
00243    AST_LIST_LOCK(&translators);
00244 
00245    while (source != dest) {
00246       struct ast_trans_pvt *cur;
00247       struct ast_translator *t = tr_matrix[source][dest].step;
00248       if (!t) {
00249          ast_log(LOG_WARNING, "No translator path from %s to %s\n", 
00250             ast_getformatname(source), ast_getformatname(dest));
00251          AST_LIST_UNLOCK(&translators);
00252          return NULL;
00253       }
00254       if (!(cur = newpvt(t))) {
00255          ast_log(LOG_WARNING, "Failed to build translator step from %d to %d\n", source, dest);
00256          if (head)
00257             ast_translator_free_path(head);  
00258          AST_LIST_UNLOCK(&translators);
00259          return NULL;
00260       }
00261       if (!head)
00262          head = cur;
00263       else
00264          tail->next = cur;
00265       tail = cur;
00266       cur->nextin = cur->nextout = ast_tv(0, 0);
00267       /* Keep going if this isn't the final destination */
00268       source = cur->t->dstfmt;
00269    }
00270 
00271    AST_LIST_UNLOCK(&translators);
00272    return head;
00273 }

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

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

00770 {
00771    AST_LIST_LOCK(&translators);
00772    t->active = 0;
00773    rebuild_matrix(0);
00774    AST_LIST_UNLOCK(&translators);
00775 }

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 221 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(), conf_free(), filestream_destructor(), free_translation(), and set_format().

00222 {
00223    struct ast_trans_pvt *pn = p;
00224    while ( (p = pn) ) {
00225       pn = p->next;
00226       destroy(p);
00227    }
00228 }

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

00736 {
00737    char tmp[80];
00738    struct ast_translator *u;
00739    int found = 0;
00740 
00741    AST_LIST_LOCK(&translators);
00742    AST_LIST_TRAVERSE_SAFE_BEGIN(&translators, u, list) {
00743       if (u == t) {
00744          AST_LIST_REMOVE_CURRENT(&translators, list);
00745          if (option_verbose > 1)
00746             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));
00747          found = 1;
00748          break;
00749       }
00750    }
00751    AST_LIST_TRAVERSE_SAFE_END;
00752 
00753    if (found)
00754       rebuild_matrix(0);
00755 
00756    AST_LIST_UNLOCK(&translators);
00757 
00758    return (u ? 0 : -1);
00759 }

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

compute the cost of a single translation step

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

00353 {
00354    int num_samples = 0;
00355    struct ast_trans_pvt *pvt;
00356    struct timeval start;
00357    int cost;
00358    int out_rate = ast_format_rate(t->dstfmt);
00359 
00360    if (!seconds)
00361       seconds = 1;
00362    
00363    /* If they don't make samples, give them a terrible score */
00364    if (!t->sample) {
00365       ast_log(LOG_WARNING, "Translator '%s' does not produce sample frames.\n", t->name);
00366       t->cost = 99999;
00367       return;
00368    }
00369 
00370    pvt = newpvt(t);
00371    if (!pvt) {
00372       ast_log(LOG_WARNING, "Translator '%s' appears to be broken and will probably fail.\n", t->name);
00373       t->cost = 99999;
00374       return;
00375    }
00376 
00377    start = ast_tvnow();
00378 
00379    /* Call the encoder until we've processed the required number of samples */
00380    while (num_samples < seconds * out_rate) {
00381       struct ast_frame *f = t->sample();
00382       if (!f) {
00383          ast_log(LOG_WARNING, "Translator '%s' failed to produce a sample frame.\n", t->name);
00384          destroy(pvt);
00385          t->cost = 99999;
00386          return;
00387       }
00388       framein(pvt, f);
00389       ast_frfree(f);
00390       while ((f = t->frameout(pvt))) {
00391          num_samples += f->samples;
00392          ast_frfree(f);
00393       }
00394    }
00395 
00396    cost = ast_tvdiff_ms(ast_tvnow(), start);
00397 
00398    destroy(pvt);
00399 
00400    t->cost = cost / seconds;
00401 
00402    if (!t->cost)
00403       t->cost = 1;
00404 }

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

Definition at line 214 of file translate.c.

References ast_trans_frameout().

Referenced by __ast_register_translator().

00215 {
00216    return ast_trans_frameout(pvt, 0, 0);
00217 }

static void destroy ( struct ast_trans_pvt pvt  )  [static]

Definition at line 132 of file translate.c.

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

Referenced by ast_translator_free_path(), and calc_cost().

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

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

framein wrapper, deals with bound checks.

Definition at line 143 of file translate.c.

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

Referenced by ast_translate(), and calc_cost().

00144 {
00145    int ret;
00146    int samples = pvt->samples;   /* initial value */
00147    
00148    /* Copy the last in jb timing info to the pvt */
00149    ast_copy_flags(&pvt->f, f, AST_FRFLAG_HAS_TIMING_INFO);
00150    pvt->f.ts = f->ts;
00151    pvt->f.len = f->len;
00152    pvt->f.seqno = f->seqno;
00153 
00154    if (f->samples == 0) {
00155       ast_log(LOG_WARNING, "no samples for %s\n", pvt->t->name);
00156    }
00157    if (pvt->t->buffer_samples) { /* do not pass empty frames to callback */
00158       if (f->datalen == 0) { /* perform native PLC if available */
00159          /* If the codec has native PLC, then do that */
00160          if (!pvt->t->native_plc)
00161             return 0;
00162       }
00163       if (pvt->samples + f->samples > pvt->t->buffer_samples) {
00164          ast_log(LOG_WARNING, "Out of buffer space\n");
00165          return -1;
00166       }
00167    }
00168    /* we require a framein routine, wouldn't know how to do
00169     * it otherwise.
00170     */
00171    ret = pvt->t->framein(pvt, f);
00172    /* diagnostic ... */
00173    if (pvt->samples == samples)
00174       ast_log(LOG_WARNING, "%s did not update samples %d\n",
00175          pvt->t->name, pvt->samples);
00176         return ret;
00177 }

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

Allocate the descriptor, required outbuf space, and possibly 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    char *ofs;
00104 
00105    /*
00106     * compute the required size adding private descriptor,
00107     * buffer, AST_FRIENDLY_OFFSET.
00108     */
00109    len = sizeof(*pvt) + t->desc_size;
00110    if (t->buf_size)
00111       len += AST_FRIENDLY_OFFSET + t->buf_size;
00112    pvt = ast_calloc(1, len);
00113    if (!pvt)
00114       return NULL;
00115    pvt->t = t;
00116    ofs = (char *)(pvt + 1);   /* pointer to data space */
00117    if (t->desc_size) {     /* first comes the descriptor */
00118       pvt->pvt = ofs;
00119       ofs += t->desc_size;
00120    }
00121    if (t->buf_size)     /* finally buffer and header */
00122       pvt->outbuf = ofs + AST_FRIENDLY_OFFSET;
00123    /* call local init routine, if present */
00124    if (t->newpvt && t->newpvt(pvt)) {
00125       free(pvt);
00126       return NULL;
00127    }
00128    ast_module_ref(t->module);
00129    return pvt;
00130 }

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

00411 {
00412    struct ast_translator *t;
00413    int x;      /* source format index */
00414    int y;      /* intermediate format index */
00415    int z;      /* destination format index */
00416 
00417    if (option_debug)
00418       ast_log(LOG_DEBUG, "Resetting translation matrix\n");
00419 
00420    bzero(tr_matrix, sizeof(tr_matrix));
00421 
00422    /* first, compute all direct costs */
00423    AST_LIST_TRAVERSE(&translators, t, list) {
00424       if (!t->active)
00425          continue;
00426 
00427       x = t->srcfmt;
00428       z = t->dstfmt;
00429 
00430       if (samples)
00431          calc_cost(t, samples);
00432      
00433       if (!tr_matrix[x][z].step || t->cost < tr_matrix[x][z].cost) {
00434          tr_matrix[x][z].step = t;
00435          tr_matrix[x][z].cost = t->cost;
00436       }
00437    }
00438 
00439    /*
00440     * For each triple x, y, z of distinct formats, check if there is
00441     * a path from x to z through y which is cheaper than what is
00442     * currently known, and in case, update the matrix.
00443     * Repeat until the matrix is stable.
00444     */
00445    for (;;) {
00446       int changed = 0;
00447       for (x = 0; x < MAX_FORMAT; x++) {      /* source format */
00448          for (y=0; y < MAX_FORMAT; y++) {    /* intermediate format */
00449             if (x == y)                     /* skip ourselves */
00450                continue;
00451 
00452             for (z=0; z<MAX_FORMAT; z++) {  /* dst format */
00453                int newcost;
00454 
00455                if (z == x || z == y)       /* skip null conversions */
00456                   continue;
00457                if (!tr_matrix[x][y].step)  /* no path from x to y */
00458                   continue;
00459                if (!tr_matrix[y][z].step)  /* no path from y to z */
00460                   continue;
00461                newcost = tr_matrix[x][y].cost + tr_matrix[y][z].cost;
00462                if (tr_matrix[x][z].step && newcost >= tr_matrix[x][z].cost)
00463                   continue;               /* x->y->z is more expensive than
00464                                            * the existing path */
00465                /* ok, we can get from x to z via y with a cost that
00466                   is the sum of the transition from x to y and
00467                   from y to z */
00468                    
00469                tr_matrix[x][z].step = tr_matrix[x][y].step;
00470                tr_matrix[x][z].cost = newcost;
00471                tr_matrix[x][z].multistep = 1;
00472                if (option_debug)
00473                   ast_log(LOG_DEBUG, "Discovered %d cost path from %s to %s, via %s\n", tr_matrix[x][z].cost,
00474                      ast_getformatname(1 << x), ast_getformatname(1 << z), ast_getformatname(1 << y));
00475                changed++;
00476             }
00477          }
00478       }
00479       if (!changed)
00480          break;
00481    }
00482 }

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

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

00556 {
00557    int x, y, z;
00558    int curlen = 0, longest = 0;
00559 
00560    if (argc > 5)
00561       return RESULT_SHOWUSAGE;
00562 
00563    AST_LIST_LOCK(&translators);  
00564    
00565    if (argv[3] && !strcasecmp(argv[3], "recalc")) {
00566       z = argv[4] ? atoi(argv[4]) : 1;
00567 
00568       if (z <= 0) {
00569          ast_cli(fd, "         C'mon let's be serious here... defaulting to 1.\n");
00570          z = 1;
00571       }
00572 
00573       if (z > MAX_RECALC) {
00574          ast_cli(fd, "         Maximum limit of recalc exceeded by %d, truncating value to %d\n", z - MAX_RECALC, MAX_RECALC);
00575          z = MAX_RECALC;
00576       }
00577       ast_cli(fd, "         Recalculating Codec Translation (number of sample seconds: %d)\n\n", z);
00578       rebuild_matrix(z);
00579    }
00580 
00581    ast_cli(fd, "         Translation times between formats (in milliseconds) for one second of data\n");
00582    ast_cli(fd, "          Source Format (Rows) Destination Format (Columns)\n\n");
00583    /* Get the length of the longest (usable?) codec name, so we know how wide the left side should be */
00584    for (x = 0; x < SHOW_TRANS; x++) {
00585       curlen = strlen(ast_getformatname(1 << (x)));
00586       if (curlen > longest)
00587          longest = curlen;
00588    }
00589    for (x = -1; x < SHOW_TRANS; x++) {
00590       char line[120];
00591       char *buf = line;
00592       size_t left = sizeof(line) - 1;  /* one initial space */
00593       /* next 2 lines run faster than using ast_build_string() */
00594       *buf++ = ' ';
00595       *buf = '\0';
00596       for (y = -1; y < SHOW_TRANS; y++) {
00597          if (y >= 0)
00598             curlen = strlen(ast_getformatname(1 << (y)));
00599 
00600          if (x >= 0 && y >= 0 && tr_matrix[x][y].step) {
00601             /* XXX 999 is a little hackish
00602                We don't want this number being larger than the shortest (or current) codec
00603                For now, that is "gsm" */
00604             ast_build_string(&buf, &left, "%*d", curlen + 1, tr_matrix[x][y].cost > 999 ? 0 : tr_matrix[x][y].cost);
00605          } else if (x == -1 && y >= 0) {
00606             /* Top row - use a dynamic size */
00607             ast_build_string(&buf, &left, "%*s", curlen + 1, ast_getformatname(1 << (y)) );
00608          } else if (y == -1 && x >= 0) {
00609             /* Left column - use a static size. */
00610             ast_build_string(&buf, &left, "%*s", longest, ast_getformatname(1 << (x)) );
00611          } else if (x >= 0 && y >= 0) {
00612             ast_build_string(&buf, &left, "%*s", curlen + 1, "-");
00613          } else {
00614             ast_build_string(&buf, &left, "%*s", longest, "");
00615          }
00616       }
00617       ast_build_string(&buf, &left, "\n");
00618       ast_cli(fd, "%s", line);         
00619    }
00620    AST_LIST_UNLOCK(&translators);
00621    return RESULT_SUCCESS;
00622 }

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

CLI "show translation" command handler.

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

00486 {
00487 #define SHOW_TRANS 13
00488    int x, y, z;
00489    int curlen = 0, longest = 0;
00490 
00491    if (argc > 4) 
00492       return RESULT_SHOWUSAGE;
00493 
00494    AST_LIST_LOCK(&translators);  
00495    
00496    if (argv[2] && !strcasecmp(argv[2], "recalc")) {
00497       z = argv[3] ? atoi(argv[3]) : 1;
00498 
00499       if (z <= 0) {
00500          ast_cli(fd, "         C'mon let's be serious here... defaulting to 1.\n");
00501          z = 1;
00502       }
00503 
00504       if (z > MAX_RECALC) {
00505          ast_cli(fd, "         Maximum limit of recalc exceeded by %d, truncating value to %d\n", z - MAX_RECALC, MAX_RECALC);
00506          z = MAX_RECALC;
00507       }
00508       ast_cli(fd, "         Recalculating Codec Translation (number of sample seconds: %d)\n\n", z);
00509       rebuild_matrix(z);
00510    }
00511 
00512    ast_cli(fd, "         Translation times between formats (in milliseconds) for one second of data\n");
00513    ast_cli(fd, "          Source Format (Rows) Destination Format (Columns)\n\n");
00514    /* Get the length of the longest (usable?) codec name, so we know how wide the left side should be */
00515    for (x = 0; x < SHOW_TRANS; x++) {
00516       curlen = strlen(ast_getformatname(1 << (x)));
00517       if (curlen > longest)
00518          longest = curlen;
00519    }
00520    for (x = -1; x < SHOW_TRANS; x++) {
00521       char line[120];
00522       char *buf = line;
00523       size_t left = sizeof(line) - 1;  /* one initial space */
00524       /* next 2 lines run faster than using ast_build_string() */
00525       *buf++ = ' ';
00526       *buf = '\0';
00527       for (y = -1; y < SHOW_TRANS; y++) {
00528          if (y >= 0)
00529             curlen = strlen(ast_getformatname(1 << (y)));
00530 
00531          if (x >= 0 && y >= 0 && tr_matrix[x][y].step) {
00532             /* XXX 999 is a little hackish
00533                We don't want this number being larger than the shortest (or current) codec
00534                For now, that is "gsm" */
00535             ast_build_string(&buf, &left, "%*d", curlen + 1, tr_matrix[x][y].cost > 999 ? 0 : tr_matrix[x][y].cost);
00536          } else if (x == -1 && y >= 0) {
00537             /* Top row - use a dynamic size */
00538             ast_build_string(&buf, &left, "%*s", curlen + 1, ast_getformatname(1 << (y)) );
00539          } else if (y == -1 && x >= 0) {
00540             /* Left column - use a static size. */
00541             ast_build_string(&buf, &left, "%*s", longest, ast_getformatname(1 << (x)) );
00542          } else if (x >= 0 && y >= 0) {
00543             ast_build_string(&buf, &left, "%*s", curlen + 1, "-");
00544          } else {
00545             ast_build_string(&buf, &left, "%*s", longest, "");
00546          }
00547       }
00548       ast_build_string(&buf, &left, "\n");
00549       ast_cli(fd, "%s", line);         
00550    }
00551    AST_LIST_UNLOCK(&translators);
00552    return RESULT_SUCCESS;
00553 }


Variable Documentation

struct ast_cli_entry cli_show_translation_deprecated [static]

Initial value:

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

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

Referenced by __ast_register_translator().

char show_trans_usage[] [static]

Definition at line 624 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 Sat Aug 6 00:40:06 2011 for Asterisk - the Open Source PBX by  doxygen 1.4.7