Codename Pineapple

Home page | Mailing list | Docs

Last updated: Sat Feb 3 05:01:57 2007

Asterisk developer's documentation :: Codename Pineapple


translate.c File Reference


Detailed Description

Translate via the use of pseudo channels.

Author:
Mark Spencer <markster@digium.com>

Definition in file translate.c.

#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_RWLIST_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.
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[])

Variables

static struct ast_cli_entry cli_translate []
static const 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.


Define Documentation

#define MAX_RECALC   200
 

Definition at line 49 of file translate.c.

Referenced by show_translation().

#define SHOW_TRANS   13
 

Referenced by show_translation().


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

References ast_translator::active, ast_cli_register_multiple(), AST_FORMAT_SLINEAR, ast_getformatname(), ast_log(), AST_RWLIST_INSERT_BEFORE_CURRENT, AST_RWLIST_INSERT_HEAD, AST_RWLIST_TRAVERSE_SAFE_BEGIN, AST_RWLIST_TRAVERSE_SAFE_END, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, ast_verbose(), ast_translator::buf_size, ast_translator::buffer_samples, calc_cost(), cli_translate, COLOR_BLACK, COLOR_MAGENTA, ast_translator::cost, default_frameout(), ast_translator::dstfmt, ast_translator::frameout, LOG_WARNING, MAX_FORMAT, ast_translator::module, ast_translator::name, option_verbose, ast_translator::plc_samples, powerof(), rebuild_matrix(), ast_translator::srcfmt, term_color(), and VERBOSE_PREFIX_2.

00573 {
00574    static int added_cli = 0;
00575    struct ast_translator *u;
00576 
00577    if (!mod) {
00578       ast_log(LOG_WARNING, "Missing module pointer, you need to supply one\n");
00579       return -1;
00580    }
00581 
00582    if (!t->buf_size) {
00583       ast_log(LOG_WARNING, "empty buf size, you need to supply one\n");
00584       return -1;
00585    }
00586 
00587    t->module = mod;
00588 
00589    t->srcfmt = powerof(t->srcfmt);
00590    t->dstfmt = powerof(t->dstfmt);
00591    t->active = 1;
00592 
00593    if (t->plc_samples) {
00594       if (t->buffer_samples < t->plc_samples) {
00595          ast_log(LOG_WARNING, "plc_samples %d buffer_samples %d\n",
00596             t->plc_samples, t->buffer_samples);
00597          return -1;
00598       }
00599       if (t->dstfmt != AST_FORMAT_SLINEAR)
00600          ast_log(LOG_WARNING, "plc_samples %d format %x\n",
00601             t->plc_samples, t->dstfmt);
00602    }
00603    if (t->srcfmt >= MAX_FORMAT) {
00604       ast_log(LOG_WARNING, "Source format %s is larger than MAX_FORMAT\n", ast_getformatname(t->srcfmt));
00605       return -1;
00606    }
00607 
00608    if (t->dstfmt >= MAX_FORMAT) {
00609       ast_log(LOG_WARNING, "Destination format %s is larger than MAX_FORMAT\n", ast_getformatname(t->dstfmt));
00610       return -1;
00611    }
00612 
00613    if (t->buf_size) {
00614                /*
00615       * Align buf_size properly, rounding up to the machine-specific
00616       * alignment for pointers.
00617       */
00618       struct _test_align { void *a, *b; } p;
00619       int align = (char *)&p.b - (char *)&p.a;
00620 
00621       t->buf_size = ((t->buf_size + align - 1) / align) * align;
00622    }
00623 
00624    if (t->frameout == NULL)
00625       t->frameout = default_frameout;
00626   
00627    calc_cost(t, 1);
00628 
00629    if (option_verbose > 1) {
00630       char tmp[80];
00631 
00632       ast_verbose(VERBOSE_PREFIX_2 "Registered translator '%s' from format %s to %s, cost %d\n",
00633              term_color(tmp, t->name, COLOR_MAGENTA, COLOR_BLACK, sizeof(tmp)),
00634              ast_getformatname(1 << t->srcfmt), ast_getformatname(1 << t->dstfmt), t->cost);
00635    }
00636 
00637    if (!added_cli) {
00638       ast_cli_register_multiple(cli_translate, sizeof(cli_translate) / sizeof(struct ast_cli_entry));
00639       added_cli++;
00640    }
00641 
00642    AST_RWLIST_WRLOCK(&translators);
00643 
00644    /* find any existing translators that provide this same srcfmt/dstfmt,
00645       and put this one in order based on cost */
00646    AST_RWLIST_TRAVERSE_SAFE_BEGIN(&translators, u, list) {
00647       if ((u->srcfmt == t->srcfmt) &&
00648           (u->dstfmt == t->dstfmt) &&
00649           (u->cost > t->cost)) {
00650          AST_RWLIST_INSERT_BEFORE_CURRENT(&translators, t, list);
00651          t = NULL;
00652       }
00653    }
00654    AST_RWLIST_TRAVERSE_SAFE_END;
00655 
00656    /* if no existing translator was found for this format combination,
00657       add it to the beginning of the list */
00658    if (t)
00659       AST_RWLIST_INSERT_HEAD(&translators, t, list);
00660 
00661    rebuild_matrix(0);
00662 
00663    AST_RWLIST_UNLOCK(&translators);
00664 
00665    return 0;
00666 }

static AST_RWLIST_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 207 of file translate.c.

References AST_FRAME_VOICE, AST_FRIENDLY_OFFSET, ast_frame::data, ast_frame::datalen, ast_trans_pvt::datalen, ast_translator::dstfmt, ast_trans_pvt::f, ast_frame::frametype, ast_frame::mallocd, ast_translator::name, ast_frame::offset, ast_trans_pvt::outbuf, ast_frame::samples, ast_trans_pvt::samples, ast_frame::src, ast_frame::subclass, and ast_trans_pvt::t.

Referenced by default_frameout().

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

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

References ast_tvadd(), ast_tvsub(), ast_frame::delivery, framein(), ast_frame::has_timing_info, len, ast_frame::len, ast_trans_pvt::next, ast_trans_pvt::nextin, ast_trans_pvt::nextout, ast_frame::samples, ast_frame::seqno, and ast_frame::ts.

Referenced by __ast_read(), ast_slinfactory_feed(), ast_write(), ast_writestream(), process_ast_dsp(), and queue_frame_to_spies().

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

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

References AST_FORMAT_AUDIO_MASK, AST_FORMAT_MAX_AUDIO, AST_FORMAT_VIDEO_MASK, AST_RWLIST_RDLOCK, powerof(), and tr_matrix.

Referenced by sip_call().

00778 {
00779    unsigned int res = dest;
00780    unsigned int x;
00781    unsigned int src_audio = src & AST_FORMAT_AUDIO_MASK;
00782    unsigned int src_video = src & AST_FORMAT_VIDEO_MASK;
00783 
00784    /* if we don't have a source format, we just have to try all
00785       possible destination formats */
00786    if (!src)
00787       return dest;
00788 
00789    /* If we have a source audio format, get its format index */
00790    if (src_audio)
00791       src_audio = powerof(src_audio);
00792 
00793    /* If we have a source video format, get its format index */
00794    if (src_video)
00795       src_video = powerof(src_video);
00796 
00797    AST_RWLIST_RDLOCK(&translators);
00798 
00799    /* For a given source audio format, traverse the list of
00800       known audio formats to determine whether there exists
00801       a translation path from the source format to the
00802       destination format. */
00803    for (x = 1; src_audio && x < AST_FORMAT_MAX_AUDIO; x <<= 1) {
00804       /* if this is not a desired format, nothing to do */
00805       if (!dest & x)
00806          continue;
00807 
00808       /* if the source is supplying this format, then
00809          we can leave it in the result */
00810       if (src & x)
00811          continue;
00812 
00813       /* if we don't have a translation path from the src
00814          to this format, remove it from the result */
00815       if (!tr_matrix[src_audio][powerof(x)].step) {
00816          res &= ~x;
00817          continue;
00818       }
00819 
00820       /* now check the opposite direction */
00821       if (!tr_matrix[powerof(x)][src_audio].step)
00822          res &= ~x;
00823    }
00824 
00825    /* For a given source video format, traverse the list of
00826       known video formats to determine whether there exists
00827       a translation path from the source format to the
00828       destination format. */
00829    for (; src_video && x < AST_FORMAT_MAX_VIDEO; x <<= 1) {
00830       /* if this is not a desired format, nothing to do */
00831       if (!dest & x)
00832          continue;
00833 
00834       /* if the source is supplying this format, then
00835          we can leave it in the result */
00836       if (src & x)
00837          continue;
00838 
00839       /* if we don't have a translation path from the src
00840          to this format, remove it from the result */
00841       if (!tr_matrix[src_video][powerof(x)].step) {
00842          res &= ~x;
00843          continue;
00844       }
00845 
00846       /* now check the opposite direction */
00847       if (!tr_matrix[powerof(x)][src_video].step)
00848          res &= ~x;
00849    }
00850 
00851    AST_RWLIST_UNLOCK(&translators);
00852 
00853    return res;
00854 }

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

References AST_RWLIST_RDLOCK, AST_RWLIST_UNLOCK, translator_path::multistep, powerof(), and tr_matrix.

Referenced by ast_channel_make_compatible_helper().

00760 {
00761    unsigned int res = -1;
00762 
00763    /* convert bitwise format numbers into array indices */
00764    src = powerof(src);
00765    dest = powerof(dest);
00766 
00767    AST_RWLIST_RDLOCK(&translators);
00768 
00769    if (tr_matrix[src][dest].step)
00770       res = tr_matrix[src][dest].multistep + 1;
00771 
00772    AST_RWLIST_UNLOCK(&translators);
00773 
00774    return res;
00775 }

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

References ast_translator::active, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, and rebuild_matrix().

00696 {
00697    AST_RWLIST_WRLOCK(&translators);
00698    t->active = 1;
00699    rebuild_matrix(0);
00700    AST_RWLIST_UNLOCK(&translators);
00701 }

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

References MAX_FORMAT.

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

00713 {
00714    int x,y;
00715    int best = -1;
00716    int bestdst = 0;
00717    int cur, cursrc;
00718    int besttime = INT_MAX;
00719    int beststeps = INT_MAX;
00720    int common = (*dst) & (*srcs);   /* are there common formats ? */
00721 
00722    if (common) { /* yes, pick one and return */
00723       for (cur = 1, y = 0; y < MAX_FORMAT; cur <<= 1, y++) {
00724          if (cur & common) /* guaranteed to find one */
00725             break;
00726       }
00727       /* We are done, this is a common format to both. */
00728       *srcs = *dst = cur;
00729       return 0;
00730    } else { /* No, we will need to translate */
00731       AST_RWLIST_RDLOCK(&translators);
00732       for (cur = 1, y = 0; y < MAX_FORMAT; cur <<= 1, y++) {
00733          if (! (cur & *dst))
00734             continue;
00735          for (cursrc = 1, x = 0; x < MAX_FORMAT; cursrc <<= 1, x++) {
00736             if (!(*srcs & cursrc) || !tr_matrix[x][y].step ||
00737                 tr_matrix[x][y].cost >  besttime)
00738                continue;   /* not existing or no better */
00739             if (tr_matrix[x][y].cost < besttime ||
00740                 tr_matrix[x][y].multistep < beststeps) {
00741                /* better than what we have so far */
00742                best = cursrc;
00743                bestdst = cur;
00744                besttime = tr_matrix[x][y].cost;
00745                beststeps = tr_matrix[x][y].multistep;
00746             }
00747          }
00748       }
00749       AST_RWLIST_UNLOCK(&translators);
00750       if (best > -1) {
00751          *srcs = best;
00752          *dst = bestdst;
00753          best = 0;
00754       }
00755       return best;
00756    }
00757 }

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

References ast_getformatname(), ast_log(), AST_RWLIST_RDLOCK, AST_RWLIST_UNLOCK, 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, ast_trans_pvt::t, and tr_matrix.

Referenced by ast_slinfactory_feed(), ast_write(), ast_writestream(), queue_frame_to_spies(), read_config(), and set_format().

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

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

References ast_translator::active, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, and rebuild_matrix().

00704 {
00705    AST_RWLIST_WRLOCK(&translators);
00706    t->active = 0;
00707    rebuild_matrix(0);
00708    AST_RWLIST_UNLOCK(&translators);
00709 }

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

References destroy(), and ast_trans_pvt::next.

Referenced by ast_channel_free(), ast_channel_whisper_stop(), ast_closestream(), ast_slinfactory_destroy(), ast_slinfactory_feed(), ast_translator_build_path(), ast_write(), ast_writestream(), cl_dequeue_chan(), free_translation(), queue_frame_to_spies(), set_format(), and spy_cleanup().

00244 {
00245    struct ast_trans_pvt *pn = p;
00246    while ( (p = pn) ) {
00247       pn = p->next;
00248       destroy(p);
00249    }
00250 }

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

References ast_getformatname(), AST_RWLIST_REMOVE_CURRENT, AST_RWLIST_TRAVERSE_SAFE_BEGIN, AST_RWLIST_TRAVERSE_SAFE_END, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, ast_verbose(), COLOR_BLACK, COLOR_MAGENTA, ast_translator::dstfmt, ast_translator::name, option_verbose, rebuild_matrix(), ast_translator::srcfmt, term_color(), and VERBOSE_PREFIX_2.

00670 {
00671    char tmp[80];
00672    struct ast_translator *u;
00673    int found = 0;
00674 
00675    AST_RWLIST_WRLOCK(&translators);
00676    AST_RWLIST_TRAVERSE_SAFE_BEGIN(&translators, u, list) {
00677       if (u == t) {
00678          AST_RWLIST_REMOVE_CURRENT(&translators, list);
00679          if (option_verbose > 1)
00680             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));
00681          found = 1;
00682          break;
00683       }
00684    }
00685    AST_RWLIST_TRAVERSE_SAFE_END;
00686 
00687    if (found)
00688       rebuild_matrix(0);
00689 
00690    AST_RWLIST_UNLOCK(&translators);
00691 
00692    return (u ? 0 : -1);
00693 }

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

compute the cost of a single translation step

Definition at line 367 of file translate.c.

References ast_frfree(), ast_log(), ast_translator::cost, destroy(), framein(), ast_translator::frameout, LOG_WARNING, ast_translator::name, newpvt(), ast_trans_pvt::pvt, ast_translator::sample, and ast_frame::samples.

Referenced by __ast_register_translator(), and rebuild_matrix().

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

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

Definition at line 236 of file translate.c.

References ast_trans_frameout().

Referenced by __ast_register_translator().

00237 {
00238    return ast_trans_frameout(pvt, 0, 0);
00239 }

static void destroy struct ast_trans_pvt pvt  )  [static]
 

Definition at line 139 of file translate.c.

References ast_module_unref(), ast_translator::destroy, free, ast_translator::module, and ast_trans_pvt::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_log(), ast_translator::buffer_samples, ast_trans_pvt::datalen, ast_frame::datalen, ast_trans_pvt::f, ast_translator::framein, ast_frame::has_timing_info, ast_frame::len, LOG_WARNING, ast_translator::name, ast_trans_pvt::outbuf, ast_trans_pvt::plc, plc_fillin(), plc_rx(), ast_translator::plc_samples, ast_frame::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    pvt->f.has_timing_info = f->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          return 0;
00178       }
00179       if (pvt->samples + f->samples > pvt->t->buffer_samples) {
00180          ast_log(LOG_WARNING, "Out of buffer space\n");
00181          return -1;
00182       }
00183    }
00184    /* we require a framein routine, wouldn't know how to do
00185     * it otherwise.
00186     */
00187    ret = pvt->t->framein(pvt, f);
00188    /* possibly store data for plc */
00189    if (!ret && pvt->plc) {
00190       int l = pvt->t->plc_samples;
00191       if (pvt->samples < l)
00192          l = pvt->samples;
00193       plc_rx(pvt->plc, dst + pvt->samples - l, l);
00194    }
00195    /* diagnostic ... */
00196    if (pvt->samples == samples)
00197       ast_log(LOG_WARNING, "%s did not update samples %d\n",
00198          pvt->t->name, pvt->samples);
00199         return ret;
00200 }

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_translator::buf_size, ast_translator::desc_size, free, len, ast_translator::newpvt, ast_translator::plc_samples, ast_trans_pvt::pvt, ast_trans_pvt::t, and ast_translator::useplc.

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

References ast_translator::active, ast_getformatname(), ast_log(), AST_RWLIST_TRAVERSE, calc_cost(), ast_translator::cost, ast_translator::dstfmt, LOG_DEBUG, MAX_FORMAT, option_debug, ast_translator::srcfmt, and tr_matrix.

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

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

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

Definition at line 490 of file translate.c.

References ast_cli(), ast_getformatname(), AST_RWLIST_RDLOCK, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, MAX_RECALC, rebuild_matrix(), RESULT_SHOWUSAGE, and SHOW_TRANS.

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


Variable Documentation

struct ast_cli_entry cli_translate[] [static]
 

Initial value:

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

Definition at line 565 of file translate.c.

Referenced by __ast_register_translator().

const char show_trans_usage[] [static]
 

Definition at line 558 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_build_path(), and rebuild_matrix().


Asterisk is a trademark for Digium, inc.. | Edvina.net | Asterisk.org | This documentation was generated with Doxygen