Sat Apr 26 2014 22:03:20

Asterisk developer's documentation


translate.h File Reference

Support for translation of data formats. translate.c. More...

#include "asterisk/frame.h"
#include "asterisk/plc.h"
#include "asterisk/linkedlists.h"
Include dependency graph for translate.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Data Structures

struct  ast_trans_pvt
 Default structure for translators, with the basic fields and buffers, all allocated as part of the same chunk of memory. The buffer is preceded by AST_FRIENDLY_OFFSET bytes in front of the user portion. 'buf' points right after this space. More...
struct  ast_translator
 Descriptor of a translator. More...

Defines

#define ast_register_translator(t)   __ast_register_translator(t, ast_module_info->self)
 See __ast_register_translator()

Enumerations

enum  ast_trans_cost_table {
  AST_TRANS_COST_LL_LL_ORIGSAMP = 400000, AST_TRANS_COST_LL_LY_ORIGSAMP = 600000, AST_TRANS_COST_LL_LL_UPSAMP = 800000, AST_TRANS_COST_LL_LY_UPSAMP = 825000,
  AST_TRANS_COST_LL_LL_DOWNSAMP = 850000, AST_TRANS_COST_LL_LY_DOWNSAMP = 875000, AST_TRANS_COST_LL_UNKNOWN = 885000, AST_TRANS_COST_LY_LL_ORIGSAMP = 900000,
  AST_TRANS_COST_LY_LY_ORIGSAMP = 915000, AST_TRANS_COST_LY_LL_UPSAMP = 930000, AST_TRANS_COST_LY_LY_UPSAMP = 945000, AST_TRANS_COST_LY_LL_DOWNSAMP = 960000,
  AST_TRANS_COST_LY_LY_DOWNSAMP = 975000, AST_TRANS_COST_LY_UNKNOWN = 985000
}
 Translator Cost Table definition. More...

Functions

int __ast_register_translator (struct ast_translator *t, struct ast_module *module)
 Register a translator This registers a codec translator with asterisk.
struct ast_frameast_trans_frameout (struct ast_trans_pvt *pvt, int datalen, int samples)
 generic frameout function
struct ast_frameast_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
void ast_translate_available_formats (struct ast_format_cap *dest, struct ast_format_cap *src, struct ast_format_cap *result)
 Find available formats.
int ast_translate_init (void)
 Initialize the translation matrix and index to format conversion table.
unsigned int ast_translate_path_steps (struct ast_format *dest, struct ast_format *src)
 Returns the number of steps required to convert from 'src' to 'dest'.
const char * ast_translate_path_to_str (struct ast_trans_pvt *t, struct ast_str **str)
 Puts a string representation of the translation path into outbuf.
void ast_translator_activate (struct ast_translator *t)
 Activate a previously deactivated translator.
int ast_translator_best_choice (struct ast_format_cap *dst_cap, struct ast_format_cap *src_cap, struct ast_format *dst_fmt_out, struct ast_format *src_fmt_out)
 Chooses the best translation path.
struct ast_trans_pvtast_translator_build_path (struct ast_format *dest, struct ast_format *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 *tr)
 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.

Detailed Description

Support for translation of data formats. translate.c.

Definition in file translate.h.


Define Documentation

See __ast_register_translator()

Definition at line 245 of file translate.h.

Referenced by load_module(), and register_translator().


Enumeration Type Documentation

Translator Cost Table definition.

Note:
The defined values in this table must be used to set the translator's table_cost value.
The cost value of the first two values must always add up to be greater than the largest value defined in this table. This is done to guarantee a direct translation will always have precedence over a multi step translation.

This table is built in a way that allows translation paths to be built that guarantee the best possible balance between performance and quality. With this table direct translation paths between two formats will always take precedence over multi step paths, lossless intermediate steps will always be chosen over lossy intermediate steps, and preservation of sample rate across the translation will always have precedence over a path that involves any re-sampling.

Enumerator:
AST_TRANS_COST_LL_LL_ORIGSAMP 

[lossless -> lossless] original sampling

AST_TRANS_COST_LL_LY_ORIGSAMP 

[lossless -> lossy] original sampling

AST_TRANS_COST_LL_LL_UPSAMP 

[lossless -> lossless] up sample

AST_TRANS_COST_LL_LY_UPSAMP 

[lossless -> lossy] up sample

AST_TRANS_COST_LL_LL_DOWNSAMP 

[lossless -> lossless] down sample

AST_TRANS_COST_LL_LY_DOWNSAMP 

[lossless -> lossy] down sample

AST_TRANS_COST_LL_UNKNOWN 

[lossless -> unknown] unknown. This value is for a lossless source translation with an unknown destination and or sample rate conversion.

AST_TRANS_COST_LY_LL_ORIGSAMP 

[lossy -> lossless] original sampling

AST_TRANS_COST_LY_LY_ORIGSAMP 

[lossy -> lossy] original sampling

AST_TRANS_COST_LY_LL_UPSAMP 

[lossy -> lossless] up sample

AST_TRANS_COST_LY_LY_UPSAMP 

[lossy -> lossy] up sample

AST_TRANS_COST_LY_LL_DOWNSAMP 

[lossy -> lossless] down sample

AST_TRANS_COST_LY_LY_DOWNSAMP 

[lossy -> lossy] down sample

AST_TRANS_COST_LY_UNKNOWN 

[lossy -> unknown] unknown. This value is for a lossy source translation with an unknown destination and or sample rate conversion.

Definition at line 59 of file translate.h.

                          {

   /* Lossless Source Translation Costs */

   /*! [lossless -> lossless] original sampling */
   AST_TRANS_COST_LL_LL_ORIGSAMP = 400000,
   /*! [lossless -> lossy]    original sampling */
   AST_TRANS_COST_LL_LY_ORIGSAMP = 600000,

   /*! [lossless -> lossless] up sample */
   AST_TRANS_COST_LL_LL_UPSAMP   = 800000,
   /*! [lossless -> lossy]    up sample */
   AST_TRANS_COST_LL_LY_UPSAMP   = 825000,

   /*! [lossless -> lossless] down sample */
   AST_TRANS_COST_LL_LL_DOWNSAMP = 850000,
   /*! [lossless -> lossy]    down sample */
   AST_TRANS_COST_LL_LY_DOWNSAMP = 875000,

   /*! [lossless -> unknown]    unknown.
    * This value is for a lossless source translation
    * with an unknown destination and or sample rate conversion. */
   AST_TRANS_COST_LL_UNKNOWN     = 885000,

   /* Lossy Source Translation Costs */

   /*! [lossy -> lossless]    original sampling */
   AST_TRANS_COST_LY_LL_ORIGSAMP = 900000,
   /*! [lossy -> lossy]       original sampling */
   AST_TRANS_COST_LY_LY_ORIGSAMP = 915000,

   /*! [lossy -> lossless]    up sample */
   AST_TRANS_COST_LY_LL_UPSAMP   = 930000,
   /*! [lossy -> lossy]       up sample */
   AST_TRANS_COST_LY_LY_UPSAMP   = 945000,

   /*! [lossy -> lossless]    down sample */
   AST_TRANS_COST_LY_LL_DOWNSAMP = 960000,
   /*! [lossy -> lossy]       down sample */
   AST_TRANS_COST_LY_LY_DOWNSAMP = 975000,

   /*! [lossy -> unknown]    unknown.
    * This value is for a lossy source translation
    * with an unknown destination and or sample rate conversion. */
   AST_TRANS_COST_LY_UNKNOWN     = 985000,

};

Function Documentation

int __ast_register_translator ( struct ast_translator t,
struct ast_module mod 
)

Register a translator This registers a codec translator with asterisk.

Parameters:
tpopulated ast_translator structure
modulehandle to the module that owns this translator
Returns:
0 on success, -1 on failure

Definition at line 1047 of file translate.c.

References ast_translator::active, add_format2index(), 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_verb, ast_translator::buf_size, COLOR_BLACK, COLOR_MAGENTA, ast_translator::comp_cost, default_frameout(), ast_translator::dst_fmt_index, ast_translator::dst_format, format2index(), ast_translator::frameout, generate_computational_cost(), generate_table_cost(), ast_format::id, LOG_WARNING, matrix_rebuild(), matrix_resize(), ast_translator::module, ast_translator::name, ast_translator::src_fmt_index, ast_translator::src_format, ast_translator::table_cost, and term_color().

{
   struct ast_translator *u;
   char tmp[80];

   if (add_format2index(t->src_format.id) || add_format2index(t->dst_format.id)) {
      if (matrix_resize(0)) {
         ast_log(LOG_WARNING, "Translator matrix can not represent any more translators.  Out of resources.\n");
         return -1;
      }
      add_format2index(t->src_format.id);
      add_format2index(t->dst_format.id);
   }

   if (!mod) {
      ast_log(LOG_WARNING, "Missing module pointer, you need to supply one\n");
      return -1;
   }

   if (!t->buf_size) {
      ast_log(LOG_WARNING, "empty buf size, you need to supply one\n");
      return -1;
   }
   if (!t->table_cost && !(t->table_cost = generate_table_cost(&t->src_format, &t->dst_format))) {
      ast_log(LOG_WARNING, "Table cost could not be generated for %s, "
         "Please set table_cost variable on translator.\n", t->name);
      return -1;
   }

   t->module = mod;
   t->src_fmt_index = format2index(t->src_format.id);
   t->dst_fmt_index = format2index(t->dst_format.id);
   t->active = 1;

   if (t->src_fmt_index == -1 || t->dst_fmt_index == -1) {
      ast_log(LOG_WARNING, "Invalid translator path: (%s codec is not valid)\n", t->src_fmt_index == -1 ? "starting" : "ending");
      return -1;
   }
   if (t->src_fmt_index >= cur_max_index) {
      ast_log(LOG_WARNING, "Source format %s is larger than cur_max_index\n", ast_getformatname(&t->src_format));
      return -1;
   }

   if (t->dst_fmt_index >= cur_max_index) {
      ast_log(LOG_WARNING, "Destination format %s is larger than cur_max_index\n", ast_getformatname(&t->dst_format));
      return -1;
   }

   if (t->buf_size) {
      /*
       * Align buf_size properly, rounding up to the machine-specific
       * alignment for pointers.
       */
      struct _test_align { void *a, *b; } p;
      int align = (char *)&p.b - (char *)&p.a;

      t->buf_size = ((t->buf_size + align - 1) / align) * align;
   }

   if (t->frameout == NULL) {
      t->frameout = default_frameout;
   }

   generate_computational_cost(t, 1);

   ast_verb(2, "Registered translator '%s' from format %s to %s, table cost, %d, computational cost %d\n",
             term_color(tmp, t->name, COLOR_MAGENTA, COLOR_BLACK, sizeof(tmp)),
             ast_getformatname(&t->src_format), ast_getformatname(&t->dst_format), t->table_cost, t->comp_cost);

   AST_RWLIST_WRLOCK(&translators);

   /* find any existing translators that provide this same srcfmt/dstfmt,
      and put this one in order based on computational cost */
   AST_RWLIST_TRAVERSE_SAFE_BEGIN(&translators, u, list) {
      if ((u->src_fmt_index == t->src_fmt_index) &&
          (u->dst_fmt_index == t->dst_fmt_index) &&
          (u->comp_cost > t->comp_cost)) {
         AST_RWLIST_INSERT_BEFORE_CURRENT(t, list);
         t = NULL;
         break;
      }
   }
   AST_RWLIST_TRAVERSE_SAFE_END;

   /* if no existing translator was found for this format combination,
      add it to the beginning of the list */
   if (t) {
      AST_RWLIST_INSERT_HEAD(&translators, t, list);
   }

   matrix_rebuild(0);

   AST_RWLIST_UNLOCK(&translators);

   return 0;
}
struct ast_frame* ast_translate ( struct ast_trans_pvt path,
struct ast_frame f,
int  consume 
) [read]

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:
trtranslator structure to use for translation
fframe to translate
consumeWhether or not to free the original frame
Returns:
an ast_frame of the new translation format on success, NULL on failure

Definition at line 480 of file translate.c.

References ast_clear_flag, ast_debug, 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, ast_frame_subclass::format, framein(), ast_frame::frametype, ast_frame::len, 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_slinfactory_feed(), ast_write(), ast_writestream(), audiohook_list_translate_to_native(), audiohook_list_translate_to_slin(), audiohook_read_frame_helper(), conf_run(), fax_gateway_framehook(), and softmix_process_write_audio().

{
   struct ast_trans_pvt *p = path;
   struct ast_frame *out;
   struct timeval delivery;
   int has_timing_info;
   long ts;
   long len;
   int seqno;

   has_timing_info = ast_test_flag(f, AST_FRFLAG_HAS_TIMING_INFO);
   ts = f->ts;
   len = f->len;
   seqno = f->seqno;

   if (!ast_tvzero(f->delivery)) {
      if (!ast_tvzero(path->nextin)) {
         /* Make sure this is in line with what we were expecting */
         if (!ast_tveq(path->nextin, f->delivery)) {
            /* The time has changed between what we expected and this
               most recent time on the new packet.  If we have a
               valid prediction adjust our output time appropriately */
            if (!ast_tvzero(path->nextout)) {
               path->nextout = ast_tvadd(path->nextout,
                          ast_tvsub(f->delivery, path->nextin));
            }
            path->nextin = f->delivery;
         }
      } else {
         /* This is our first pass.  Make sure the timing looks good */
         path->nextin = f->delivery;
         path->nextout = f->delivery;
      }
      /* Predict next incoming sample */
      path->nextin = ast_tvadd(path->nextin, ast_samp2tv(f->samples, ast_format_rate(&f->subclass.format)));
   }
   delivery = f->delivery;
   for (out = f; out && p ; p = p->next) {
      framein(p, out);
      if (out != f) {
         ast_frfree(out);
      }
      out = p->t->frameout(p);
   }
   if (out) {
      /* we have a frame, play with times */
      if (!ast_tvzero(delivery)) {
         /* Regenerate prediction after a discontinuity */
         if (ast_tvzero(path->nextout)) {
            path->nextout = ast_tvnow();
         }

         /* Use next predicted outgoing timestamp */
         out->delivery = path->nextout;

         /* Predict next outgoing timestamp from samples in this
            frame. */
         path->nextout = ast_tvadd(path->nextout, ast_samp2tv(out->samples, ast_format_rate(&out->subclass.format)));
         if (f->samples != out->samples && ast_test_flag(out, AST_FRFLAG_HAS_TIMING_INFO)) {
            ast_debug(4, "Sample size different %u vs %u\n", f->samples, out->samples);
            ast_clear_flag(out, AST_FRFLAG_HAS_TIMING_INFO);
         }
      } else {
         out->delivery = ast_tv(0, 0);
         ast_set2_flag(out, has_timing_info, AST_FRFLAG_HAS_TIMING_INFO);
         if (has_timing_info) {
            out->ts = ts;
            out->len = len;
            out->seqno = seqno;
         }
      }
      /* Invalidate prediction if we're entering a silence period */
      if (out->frametype == AST_FRAME_CNG) {
         path->nextout = ast_tv(0, 0);
      }
   }
   if (consume) {
      ast_frfree(f);
   }
   return out;
}
void ast_translate_available_formats ( struct ast_format_cap dest,
struct ast_format_cap src,
struct ast_format_cap result 
)

Find available formats.

Parameters:
destpossible destination formats
srcsource formats
resultcapabilities structure to store available formats in
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:
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 1289 of file translate.c.

References ast_format_cap_add(), ast_format_cap_get_compatible_format(), ast_format_cap_iscompatible(), ast_format_cap_iter_end(), ast_format_cap_iter_next(), ast_format_cap_iter_start(), ast_format_cap_remove_byid(), AST_FORMAT_GET_TYPE, ast_format_set(), AST_FORMAT_TYPE_AUDIO, AST_FORMAT_TYPE_VIDEO, AST_RWLIST_RDLOCK, AST_RWLIST_UNLOCK, format2index(), ast_format::id, index2format(), and matrix_get().

Referenced by ast_rtp_instance_available_formats().

{
   struct ast_format tmp_fmt;
   struct ast_format cur_dest, cur_src;
   int src_audio = 0;
   int src_video = 0;
   int index;

   ast_format_cap_iter_start(dest);
   while (!ast_format_cap_iter_next(dest, &cur_dest)) {
      /* We give preference to a joint format structure if possible */
      if (ast_format_cap_get_compatible_format(src, &cur_dest, &tmp_fmt)) {
         ast_format_cap_add(result, &tmp_fmt);
      } else {
         /* Otherwise we just use the destination format */
         ast_format_cap_add(result, &cur_dest);
      }
   }
   ast_format_cap_iter_end(dest);

   /* if we don't have a source format, we just have to try all
      possible destination formats */
   if (!src) {
      return;
   }

   ast_format_cap_iter_start(src);
   while (!ast_format_cap_iter_next(src, &cur_src)) {
      /* If we have a source audio format, get its format index */
      if (AST_FORMAT_GET_TYPE(cur_src.id) == AST_FORMAT_TYPE_AUDIO) {
         src_audio = format2index(cur_src.id);
      }

      /* If we have a source video format, get its format index */
      if (AST_FORMAT_GET_TYPE(cur_src.id) == AST_FORMAT_TYPE_VIDEO) {
         src_video = format2index(cur_src.id);
      }

      AST_RWLIST_RDLOCK(&translators);

      /* For a given source audio format, traverse the list of
         known audio formats to determine whether there exists
         a translation path from the source format to the
         destination format. */
      for (index = 0; (src_audio >= 0) && index < cur_max_index; index++) {
         ast_format_set(&tmp_fmt, index2format(index), 0);

         if (AST_FORMAT_GET_TYPE(tmp_fmt.id) != AST_FORMAT_TYPE_AUDIO) {
            continue;
         }

         /* if this is not a desired format, nothing to do */
         if (!ast_format_cap_iscompatible(dest, &tmp_fmt)) {
            continue;
         }

         /* if the source is supplying this format, then
            we can leave it in the result */
         if (ast_format_cap_iscompatible(src, &tmp_fmt)) {
            continue;
         }

         /* if we don't have a translation path from the src
            to this format, remove it from the result */
         if (!matrix_get(src_audio, index)->step) {
            ast_format_cap_remove_byid(result, tmp_fmt.id);
            continue;
         }

         /* now check the opposite direction */
         if (!matrix_get(index, src_audio)->step) {
            ast_format_cap_remove_byid(result, tmp_fmt.id);
         }
      }

      /* For a given source video format, traverse the list of
         known video formats to determine whether there exists
         a translation path from the source format to the
         destination format. */
      for (index = 0; (src_video >= 0) && index < cur_max_index; index++) {
         ast_format_set(&tmp_fmt, index2format(index), 0);
         if (AST_FORMAT_GET_TYPE(tmp_fmt.id) != AST_FORMAT_TYPE_VIDEO) {
            continue;
         }

         /* if this is not a desired format, nothing to do */
         if (!ast_format_cap_iscompatible(dest, &tmp_fmt)) {
            continue;
         }

         /* if the source is supplying this format, then
            we can leave it in the result */
         if (ast_format_cap_iscompatible(src, &tmp_fmt)) {
            continue;
         }

         /* if we don't have a translation path from the src
            to this format, remove it from the result */
         if (!matrix_get(src_video, index)->step) {
            ast_format_cap_remove_byid(result, tmp_fmt.id);
            continue;
         }

         /* now check the opposite direction */
         if (!matrix_get(index, src_video)->step) {
            ast_format_cap_remove_byid(result, tmp_fmt.id);
         }
      }
      AST_RWLIST_UNLOCK(&translators);
   }
   ast_format_cap_iter_end(src);
}
int ast_translate_init ( void  )

Initialize the translation matrix and index to format conversion table.

Return values:
0on success
-1on failure

Definition at line 1417 of file translate.c.

References ARRAY_LEN, ast_cli_register_multiple(), ast_register_atexit(), ast_rwlock_init, matrix_resize(), and translate_shutdown().

Referenced by main().

unsigned int ast_translate_path_steps ( struct ast_format dest,
struct ast_format src 
)

Returns the number of steps required to convert from 'src' to 'dest'.

Parameters:
destdestination format
srcsource format
Returns:
the number of translation steps required, or -1 if no path is available

Definition at line 1266 of file translate.c.

References ast_log(), AST_RWLIST_RDLOCK, AST_RWLIST_UNLOCK, format2index(), ast_format::id, LOG_WARNING, matrix_get(), and translator_path::multistep.

Referenced by ast_channel_make_compatible_helper().

{
   unsigned int res = -1;
   int src, dest;
   /* convert bitwise format numbers into array indices */
   src = format2index(src_format->id);
   dest = format2index(dst_format->id);

   if (src == -1 || dest == -1) {
      ast_log(LOG_WARNING, "No translator path: (%s codec is not valid)\n", src == -1 ? "starting" : "ending");
      return -1;
   }
   AST_RWLIST_RDLOCK(&translators);

   if (matrix_get(src, dest)->step) {
      res = matrix_get(src, dest)->multistep + 1;
   }

   AST_RWLIST_UNLOCK(&translators);

   return res;
}
const char* ast_translate_path_to_str ( struct ast_trans_pvt t,
struct ast_str **  str 
)

Puts a string representation of the translation path into outbuf.

Parameters:
translatorstructure containing the translation path
ast_stroutput buffer
Return values:
onsuccess pointer to beginning of outbuf. on failure "".

Definition at line 791 of file translate.c.

References ast_getformatname_multiple_byid(), ast_str_append(), ast_str_buffer(), ast_str_set(), ast_translator::dst_format, ast_format::id, ast_trans_pvt::next, ast_translator::src_format, and ast_trans_pvt::t.

Referenced by handle_showchan(), and serialize_showchan().

{
   struct ast_trans_pvt *pn = p;
   char tmp[256];

   if (!p || !p->t) {
      return "";
   }

   ast_str_set(str, 0, "%s", ast_getformatname_multiple_byid(tmp, sizeof(tmp), p->t->src_format.id));

   while ( (p = pn) ) {
      pn = p->next;
      ast_str_append(str, 0, "->%s", ast_getformatname_multiple_byid(tmp, sizeof(tmp), p->t->dst_format.id));
   }

   return ast_str_buffer(*str);
}

Activate a previously deactivated translator.

Parameters:
ttranslator to activate
Returns:
nothing

Enables the specified translator for use.

Definition at line 1174 of file translate.c.

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

int ast_translator_best_choice ( struct ast_format_cap dst_cap,
struct ast_format_cap src_cap,
struct ast_format dst_fmt_out,
struct ast_format src_fmt_out 
)

Chooses the best translation path.

Given a list of sources, and a designed destination format, which should I choose?

Parameters:
destinationcapabilities
sourcecapabilities
destinationformat chosen out of destination capabilities
sourceformat chosen out of source capabilities
Returns:
Returns 0 on success, -1 if no path could be found.
Note:
dst_cap and src_cap are not mondified.

Definition at line 1191 of file translate.c.

References ast_format_cap_destroy(), ast_format_cap_iter_end(), ast_format_cap_iter_next(), ast_format_cap_iter_start(), ast_format_cap_joint(), ast_format_clear(), ast_format_copy(), ast_format_rate(), AST_RWLIST_RDLOCK, AST_RWLIST_UNLOCK, format2index(), ast_format::id, matrix_get(), translator_path::multistep, and translator_path::table_cost.

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

{
   unsigned int besttablecost = INT_MAX;
   unsigned int beststeps = INT_MAX;
   struct ast_format best;
   struct ast_format bestdst;
   struct ast_format_cap *joint_cap = ast_format_cap_joint(dst_cap, src_cap);
   ast_format_clear(&best);
   ast_format_clear(&bestdst);

   if (joint_cap) { /* yes, pick one and return */
      struct ast_format tmp_fmt;
      ast_format_cap_iter_start(joint_cap);
      while (!ast_format_cap_iter_next(joint_cap, &tmp_fmt)) {
         /* We are guaranteed to find one common format. */
         if (!best.id) {
            ast_format_copy(&best, &tmp_fmt);
            continue;
         }
         /* If there are multiple common formats, pick the one with the highest sample rate */
         if (ast_format_rate(&best) < ast_format_rate(&tmp_fmt)) {
            ast_format_copy(&best, &tmp_fmt);
            continue;
         }

      }
      ast_format_cap_iter_end(joint_cap);

      /* We are done, this is a common format to both. */
      ast_format_copy(dst_fmt_out, &best);
      ast_format_copy(src_fmt_out, &best);
      ast_format_cap_destroy(joint_cap);
      return 0;
   } else {      /* No, we will need to translate */
      struct ast_format cur_dst;
      struct ast_format cur_src;
      AST_RWLIST_RDLOCK(&translators);

      ast_format_cap_iter_start(dst_cap);
      while (!ast_format_cap_iter_next(dst_cap, &cur_dst)) {
         ast_format_cap_iter_start(src_cap);
         while (!ast_format_cap_iter_next(src_cap, &cur_src)) {
            int x = format2index(cur_src.id);
            int y = format2index(cur_dst.id);
            if (x < 0 || y < 0) {
               continue;
            }
            if (!matrix_get(x, y) || !(matrix_get(x, y)->step)) {
               continue;
            }
            if (((matrix_get(x, y)->table_cost < besttablecost) || (matrix_get(x, y)->multistep < beststeps))) {
               /* better than what we have so far */
               ast_format_copy(&best, &cur_src);
               ast_format_copy(&bestdst, &cur_dst);
               besttablecost = matrix_get(x, y)->table_cost;
               beststeps = matrix_get(x, y)->multistep;
            }
         }
         ast_format_cap_iter_end(src_cap);
      }

      ast_format_cap_iter_end(dst_cap);
      AST_RWLIST_UNLOCK(&translators);
      if (best.id) {
         ast_format_copy(dst_fmt_out, &bestdst);
         ast_format_copy(src_fmt_out, &best);
         return 0;
      }
      return -1;
   }
}
struct ast_trans_pvt* ast_translator_build_path ( struct ast_format dst,
struct ast_format src 
) [read]

Builds a translator path Build a path (possibly NULL) from source to dest.

Parameters:
destdestination format
sourcesource format
Returns:
ast_trans_pvt on success, NULL on failure

Definition at line 419 of file translate.c.

References ast_format_set(), ast_getformatname(), ast_log(), AST_RWLIST_RDLOCK, AST_RWLIST_UNLOCK, ast_translator_free_path(), ast_tv(), ast_translator::dst_fmt_index, format2index(), ast_format::id, index2format(), LOG_WARNING, matrix_get(), newpvt(), ast_trans_pvt::next, ast_trans_pvt::nextin, ast_trans_pvt::nextout, translator_path::step, and ast_trans_pvt::t.

Referenced by ast_slinfactory_feed(), ast_writestream(), audiohook_list_translate_to_native(), audiohook_list_translate_to_slin(), audiohook_read_frame_helper(), conf_run(), set_format(), softmix_process_write_audio(), and softmix_translate_helper_change_rate().

{
   struct ast_trans_pvt *head = NULL, *tail = NULL;
   int src_index, dst_index;
   struct ast_format tmp_fmt1;
   struct ast_format tmp_fmt2;

   src_index = format2index(src->id);
   dst_index = format2index(dst->id);

   if (src_index == -1 || dst_index == -1) {
      ast_log(LOG_WARNING, "No translator path: (%s codec is not valid)\n", src_index == -1 ? "starting" : "ending");
      return NULL;
   }

   AST_RWLIST_RDLOCK(&translators);

   while (src_index != dst_index) {
      struct ast_trans_pvt *cur;
      struct ast_format *explicit_dst = NULL;
      struct ast_translator *t = matrix_get(src_index, dst_index)->step;
      if (!t) {
         int src_id = index2format(src_index);
         int dst_id = index2format(dst_index);
         ast_log(LOG_WARNING, "No translator path from %s to %s\n",
            ast_getformatname(ast_format_set(&tmp_fmt1, src_id, 0)),
            ast_getformatname(ast_format_set(&tmp_fmt2, dst_id, 0)));
         AST_RWLIST_UNLOCK(&translators);
         return NULL;
      }
      if (dst_index == t->dst_fmt_index) {
         explicit_dst = dst;
      }
      if (!(cur = newpvt(t, explicit_dst))) {
         int src_id = index2format(src_index);
         int dst_id = index2format(dst_index);
         ast_log(LOG_WARNING, "Failed to build translator step from %s to %s\n",
            ast_getformatname(ast_format_set(&tmp_fmt1, src_id, 0)),
            ast_getformatname(ast_format_set(&tmp_fmt2, dst_id, 0)));
         if (head) {
            ast_translator_free_path(head);
         }
         AST_RWLIST_UNLOCK(&translators);
         return NULL;
      }
      if (!head) {
         head = cur;
      } else {
         tail->next = cur;
      }
      tail = cur;
      cur->nextin = cur->nextout = ast_tv(0, 0);
      /* Keep going if this isn't the final destination */
      src_index = cur->t->dst_fmt_index;
   }

   AST_RWLIST_UNLOCK(&translators);
   return head;
}

Deactivate a translator.

Parameters:
ttranslator to deactivate
Returns:
nothing

Disables the specified translator from being used.

Definition at line 1182 of file translate.c.

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

Unregister a translator Unregisters the given tranlator.

Parameters:
ttranslator to unregister
Returns:
0 on success, -1 on failure

Definition at line 1145 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_verb, COLOR_BLACK, COLOR_MAGENTA, ast_translator::dst_format, ast_translator::list, matrix_rebuild(), ast_translator::name, ast_translator::src_format, and term_color().

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

{
   char tmp[80];
   struct ast_translator *u;
   int found = 0;

   AST_RWLIST_WRLOCK(&translators);
   AST_RWLIST_TRAVERSE_SAFE_BEGIN(&translators, u, list) {
      if (u == t) {
         AST_RWLIST_REMOVE_CURRENT(list);
         ast_verb(2, "Unregistered translator '%s' from format %s to %s\n",
            term_color(tmp, t->name, COLOR_MAGENTA, COLOR_BLACK, sizeof(tmp)),
            ast_getformatname(&t->src_format),
            ast_getformatname(&t->dst_format));
         found = 1;
         break;
      }
   }
   AST_RWLIST_TRAVERSE_SAFE_END;

   if (found) {
      matrix_rebuild(0);
   }

   AST_RWLIST_UNLOCK(&translators);

   return (u ? 0 : -1);
}