translate.c File Reference

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

Include dependency graph for translate.c:

Go to the source code of this file.

Data Structures

struct  ast_translator_dir
struct  ast_frame_delivery
struct  ast_trans_pvt

Defines

#define MAX_RECALC   200
#define SHOW_TRANS   11

Functions

 AST_MUTEX_DEFINE_STATIC (list_lock)
void ast_translator_free_path (struct ast_trans_pvt *p)
 Frees a translator path.
struct ast_trans_pvtast_translator_build_path (int dest, int source)
 Builds a translator path.
struct ast_frameast_translate (struct ast_trans_pvt *path, struct ast_frame *f, int consume)
 translates one or more frames
int ast_register_translator (struct ast_translator *t)
 Register a translator.
int ast_unregister_translator (struct ast_translator *t)
 Unregister a translator.
int ast_translator_best_choice (int *dst, int *srcs)
 Chooses the best translation path.


Define Documentation

#define MAX_RECALC   200

Definition at line 31 of file translate.c.

#define SHOW_TRANS   11


Function Documentation

AST_MUTEX_DEFINE_STATIC ( list_lock   ) 

int ast_register_translator ( struct ast_translator t  ) 

Register a translator.

Parameters:
t populated ast_translator structure This registers a codec translator with asterisk Returns 0 on success, -1 on failure

Definition at line 389 of file translate.c.

00390 {
00391    char tmp[80];
00392    t->srcfmt = powerof(t->srcfmt);
00393    t->dstfmt = powerof(t->dstfmt);
00394    if ((t->srcfmt >= MAX_FORMAT) || (t->dstfmt >= MAX_FORMAT)) {
00395       ast_log(LOG_WARNING, "Format %s is larger than MAX_FORMAT\n", ast_getformatname(t->srcfmt));
00396       return -1;
00397    }
00398    calc_cost(t,1);
00399    if (option_verbose > 1)
00400       ast_verbose(VERBOSE_PREFIX_2 "Registered translator '%s' from format %s to %s, cost %d\n", term_color(tmp, t->name, COLOR_MAGENTA, COLOR_BLACK, sizeof(tmp)), ast_getformatname(1 << t->srcfmt), ast_getformatname(1 << t->dstfmt), t->cost);
00401    ast_mutex_lock(&list_lock);
00402    if (!added_cli) {
00403       ast_cli_register(&show_trans);
00404       added_cli++;
00405    }
00406    t->next = list;
00407    list = t;
00408    rebuild_matrix(0);
00409    ast_mutex_unlock(&list_lock);
00410    return 0;
00411 }

struct ast_frame* ast_translate ( struct ast_trans_pvt tr,
struct ast_frame f,
int  consume 
) [read]

translates one or more frames

Parameters:
tr translator structure to use for translation
f frame to translate
consume Whether or not to free the original frame Apply an input frame into the translator and receive zero or one output frames. Consume determines whether the original frame should be freed Returns an ast_frame of the new translation format on success, NULL on failure

Definition at line 137 of file translate.c.

00138 {
00139    struct ast_trans_pvt *p;
00140    struct ast_frame *out;
00141    struct timeval delivery;
00142    p = path;
00143    /* Feed the first frame into the first translator */
00144    p->step->framein(p->state, f);
00145    if (f->delivery.tv_sec || f->delivery.tv_usec) {
00146       if (path->nextin.tv_sec || path->nextin.tv_usec) {
00147          /* Make sure this is in line with what we were expecting */
00148          if ((path->nextin.tv_sec != f->delivery.tv_sec) ||
00149              (path->nextin.tv_usec != f->delivery.tv_usec)) {
00150             /* The time has changed between what we expected and this
00151                most recent time on the new packet.  Adjust our output
00152                time appropriately */
00153             long sdiff;
00154             long udiff;
00155             sdiff = f->delivery.tv_sec - path->nextin.tv_sec;
00156             udiff = f->delivery.tv_usec - path->nextin.tv_usec;
00157             path->nextin.tv_sec = f->delivery.tv_sec;
00158             path->nextin.tv_usec = f->delivery.tv_usec;
00159             path->nextout.tv_sec += sdiff;
00160             path->nextout.tv_usec += udiff;
00161             if (path->nextout.tv_usec < 0) {
00162                path->nextout.tv_usec += 1000000;
00163                path->nextout.tv_sec--;
00164             } else if (path->nextout.tv_usec >= 1000000) {
00165                path->nextout.tv_usec -= 1000000;
00166                path->nextout.tv_sec++;
00167             }
00168          }
00169       } else {
00170          /* This is our first pass.  Make sure the timing looks good */
00171          path->nextin.tv_sec = f->delivery.tv_sec;
00172          path->nextin.tv_usec = f->delivery.tv_usec;
00173          path->nextout.tv_sec = f->delivery.tv_sec;
00174          path->nextout.tv_usec = f->delivery.tv_usec;
00175       }
00176       /* Predict next incoming sample */
00177       path->nextin.tv_sec += (f->samples / 8000);
00178       path->nextin.tv_usec += ((f->samples % 8000) * 125);
00179       if (path->nextin.tv_usec >= 1000000) {
00180          path->nextin.tv_usec -= 1000000;
00181          path->nextin.tv_sec++;
00182       }
00183    }
00184    delivery.tv_sec = f->delivery.tv_sec;
00185    delivery.tv_usec = f->delivery.tv_usec;
00186    if (consume)
00187       ast_frfree(f);
00188    while(p) {
00189       out = p->step->frameout(p->state);
00190       /* If we get nothing out, return NULL */
00191       if (!out)
00192          return NULL;
00193       /* If there is a next state, feed it in there.  If not,
00194          return this frame  */
00195       if (p->next) 
00196          p->next->step->framein(p->next->state, out);
00197       else {
00198          if (delivery.tv_sec || delivery.tv_usec) {
00199             /* Use next predicted outgoing timestamp */
00200             out->delivery.tv_sec = path->nextout.tv_sec;
00201             out->delivery.tv_usec = path->nextout.tv_usec;
00202             
00203             /* Predict next outgoing timestamp from samples in this
00204                frame. */
00205             path->nextout.tv_sec += (out->samples / 8000);
00206             path->nextout.tv_usec += ((out->samples % 8000) * 125);
00207             if (path->nextout.tv_usec >= 1000000) {
00208                path->nextout.tv_sec++;
00209                path->nextout.tv_usec -= 1000000;
00210             }
00211          } else {
00212             out->delivery.tv_sec = 0;
00213             out->delivery.tv_usec = 0;
00214          }
00215          return out;
00216       }
00217       p = p->next;
00218    }
00219    ast_log(LOG_WARNING, "I should never get here...\n");
00220    return NULL;
00221 }

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 0 on success, -1 if no path could be found. Modifies dests and srcs in place

Definition at line 437 of file translate.c.

00438 {
00439    /* Calculate our best source format, given costs, and a desired destination */
00440    int x,y;
00441    int best=-1;
00442    int bestdst=0;
00443    int cur = 1;
00444    int besttime=999999999;
00445    ast_mutex_lock(&list_lock);
00446    for (y=0;y<MAX_FORMAT;y++) {
00447       if ((cur & *dst) && (cur & *srcs)) {
00448          /* This is a common format to both.  Pick it if we don't have one already */
00449          besttime=0;
00450          bestdst = cur;
00451          best = cur;
00452          break;
00453       }
00454       if (cur & *dst)
00455          for (x=0;x<MAX_FORMAT;x++) {
00456             if (tr_matrix[x][y].step &&   /* There's a step */
00457                 (tr_matrix[x][y].cost < besttime) && /* We're better than what exists now */
00458                (*srcs & (1 << x)))        /* x is a valid source format */
00459                {
00460                   best = 1 << x;
00461                   bestdst = cur;
00462                   besttime = tr_matrix[x][y].cost;
00463                }
00464          }
00465       cur = cur << 1;
00466    }
00467    if (best > -1) {
00468       *srcs = best;
00469       *dst = bestdst;
00470       best = 0;
00471    }
00472    ast_mutex_unlock(&list_lock);
00473    return best;
00474 }

struct ast_trans_pvt* ast_translator_build_path ( int  dest,
int  source 
) [read]

Builds a translator path.

Parameters:
dest destination format
source source format Build a path (possibly NULL) from source to dest Returns ast_trans_pvt on success, NULL on failure

Definition at line 87 of file translate.c.

00088 {
00089    struct ast_trans_pvt *tmpr = NULL, *tmp = NULL;
00090    /* One of the hardest parts:  Build a set of translators based upon
00091       the given source and destination formats */
00092    source = powerof(source);
00093    dest = powerof(dest);
00094    while(source != dest) {
00095       if (tr_matrix[source][dest].step) {
00096          if (tmp) {
00097             tmp->next = malloc(sizeof(struct ast_trans_pvt));
00098             tmp = tmp->next;
00099          } else
00100             tmp = malloc(sizeof(struct ast_trans_pvt));
00101 
00102             
00103          if (tmp) {
00104             tmp->next = NULL;
00105             tmp->nextin.tv_sec = 0;
00106             tmp->nextin.tv_usec = 0;
00107             tmp->nextout.tv_sec = 0;
00108             tmp->nextout.tv_usec = 0;
00109             tmp->step = tr_matrix[source][dest].step;
00110             tmp->state = tmp->step->newpvt();
00111             if (!tmp->state) {
00112                ast_log(LOG_WARNING, "Failed to build translator step from %d to %d\n", source, dest);
00113                free(tmp);
00114                tmp = NULL;
00115                return NULL;
00116             }
00117             /* Set the root, if it doesn't exist yet... */
00118             if (!tmpr)
00119                tmpr = tmp;
00120             /* Keep going if this isn't the final destination */
00121             source = tmp->step->dstfmt;
00122          } else {
00123             /* XXX This could leak XXX */
00124             ast_log(LOG_WARNING, "Out of memory\n");
00125             return NULL;
00126          }
00127       } else {
00128          /* We shouldn't have allocated any memory */
00129          ast_log(LOG_WARNING, "No translator path from %s to %s\n", 
00130             ast_getformatname(source), ast_getformatname(dest));
00131          return NULL;
00132       }
00133    }
00134    return tmpr;
00135 }

void ast_translator_free_path ( struct ast_trans_pvt tr  ) 

Frees a translator path.

Parameters:
tr translator path to get rid of Frees the given translator path structure

Definition at line 74 of file translate.c.

00075 {
00076    struct ast_trans_pvt *pl, *pn;
00077    pn = p;
00078    while(pn) {
00079       pl = pn;
00080       pn = pn->next;
00081       if (pl->state && pl->step->destroy)
00082          pl->step->destroy(pl->state);
00083       free(pl);
00084    }
00085 }

int ast_unregister_translator ( struct ast_translator t  ) 

Unregister a translator.

Parameters:
t translator to unregister Unregisters the given tranlator Returns 0 on success, -1 on failure

Definition at line 413 of file translate.c.

00414 {
00415    char tmp[80];
00416    struct ast_translator *u, *ul = NULL;
00417    ast_mutex_lock(&list_lock);
00418    u = list;
00419    while(u) {
00420       if (u == t) {
00421          if (ul)
00422             ul->next = u->next;
00423          else
00424             list = u->next;
00425          if (option_verbose > 1)
00426             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));
00427          break;
00428       }
00429       ul = u;
00430       u = u->next;
00431    }
00432    rebuild_matrix(0);
00433    ast_mutex_unlock(&list_lock);
00434    return (u ? 0 : -1);
00435 }


Generated on Wed Oct 28 17:01:03 2009 for Asterisk by  doxygen 1.5.6