Asterisk - The Open Source Telephony Project GIT-master-a358458
Data Structures | Macros | Functions | Variables
translate.c File Reference

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

#include "asterisk.h"
#include <sys/time.h>
#include <sys/resource.h>
#include <math.h>
#include "asterisk/lock.h"
#include "asterisk/channel.h"
#include "asterisk/translate.h"
#include "asterisk/module.h"
#include "asterisk/frame.h"
#include "asterisk/sched.h"
#include "asterisk/cli.h"
#include "asterisk/term.h"
#include "asterisk/format.h"
#include "asterisk/linkedlists.h"
Include dependency graph for translate.c:

Go to the source code of this file.

Data Structures

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

Macros

#define format_sample_rate_absdiff(fmt1, fmt2)
 
#define GROW_INDEX   16
 
#define INIT_INDEX   32
 
#define MAX_RECALC   1000
 

Functions

int __ast_register_translator (struct ast_translator *t, struct ast_module *mod)
 register codec translator More...
 
static int add_codec2index (struct ast_codec *codec)
 
struct ast_frameast_trans_frameout (struct ast_trans_pvt *pvt, int datalen, int samples)
 generic frameout routine. If samples and datalen are 0, take whatever is in pvt and reset them, otherwise take the values in the caller and leave alone the pvt values. More...
 
struct ast_frameast_translate (struct ast_trans_pvt *path, struct ast_frame *f, int consume)
 do the actual translation More...
 
void ast_translate_available_formats (struct ast_format_cap *dest, struct ast_format_cap *src, struct ast_format_cap *result)
 Find available formats. More...
 
int ast_translate_init (void)
 Initialize the translation matrix and index to format conversion table. More...
 
unsigned int ast_translate_path_steps (struct ast_format *dst_format, struct ast_format *src_format)
 Returns the number of steps required to convert from 'src' to 'dest'. More...
 
const char * ast_translate_path_to_str (struct ast_trans_pvt *p, struct ast_str **str)
 Puts a string representation of the translation path into outbuf. More...
 
void ast_translator_activate (struct ast_translator *t)
 Activate a previously deactivated translator. More...
 
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)
 Calculate our best translator source format, given costs, and a desired destination. More...
 
struct ast_trans_pvtast_translator_build_path (struct ast_format *dst, struct ast_format *src)
 Build a chain of translators based upon the given source and dest formats. More...
 
void ast_translator_deactivate (struct ast_translator *t)
 Deactivate a translator. More...
 
void ast_translator_free_path (struct ast_trans_pvt *p)
 Frees a translator path Frees the given translator path structure. More...
 
int ast_unregister_translator (struct ast_translator *t)
 unregister codec translator More...
 
static void check_translation_path (struct ast_format_cap *dest, struct ast_format_cap *src, struct ast_format_cap *result, struct ast_format *src_fmt, enum ast_media_type type)
 
static int codec2index (struct ast_codec *codec)
 
static void codec_append_name (const struct ast_codec *codec, struct ast_str **buf)
 
static int codec_to_index (unsigned int id)
 
static char * complete_trans_path_choice (const char *word)
 
static struct ast_framedefault_frameout (struct ast_trans_pvt *pvt)
 
static void destroy (struct ast_trans_pvt *pvt)
 
static int format2index (struct ast_format *format)
 
static int framein (struct ast_trans_pvt *pvt, struct ast_frame *f)
 framein wrapper, deals with bound checks.
More...
 
static void generate_computational_cost (struct ast_translator *t, int seconds)
 
static struct ast_framegenerate_interpolated_slin (struct ast_trans_pvt *p, struct ast_frame *f)
 
static int generate_table_cost (struct ast_codec *src, struct ast_codec *dst)
 
static char * handle_cli_core_show_translation (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 
static void handle_cli_recalc (struct ast_cli_args *a)
 
static char * handle_show_translation_path (struct ast_cli_args *a, const char *codec_name, unsigned int sample_rate)
 
static char * handle_show_translation_table (struct ast_cli_args *a)
 
static struct ast_codecindex2codec (int index)
 
static void matrix_clear (void)
 
static struct translator_pathmatrix_get (unsigned int x, unsigned int y)
 
static void matrix_rebuild (int samples)
 rebuild a translation matrix. More...
 
static int matrix_resize (int init)
 
static struct ast_trans_pvtnewpvt (struct ast_translator *t, struct ast_format *explicit_dst)
 Allocate the descriptor, required outbuf space, and possibly desc. More...
 
static void translate_shutdown (void)
 

Variables

static unsigned int * __indextable
 table for converting index to format values. More...
 
static struct translator_path ** __matrix
 a matrix that, for any pair of supported formats, indicates the total cost of translation and the first step. The full path can be reconstructed iterating on the matrix until step->dstfmt == desired_format. More...
 
static struct ast_cli_entry cli_translate []
 
static int cur_max_index
 
static int index_size
 
static ast_rwlock_t tablelock
 
static struct translators translators = { .first = NULL, .last = NULL, .lock = { PTHREAD_RWLOCK_INITIALIZER , NULL, {1, 0} } , }
 

Detailed Description

Translate via the use of pseudo channels.

Author
Mark Spencer marks.nosp@m.ter@.nosp@m.digiu.nosp@m.m.co.nosp@m.m

Definition in file translate.c.

Macro Definition Documentation

◆ format_sample_rate_absdiff

#define format_sample_rate_absdiff (   fmt1,
  fmt2 
)
Value:
({ \
unsigned int rate1 = ast_format_get_sample_rate(fmt1); \
unsigned int rate2 = ast_format_get_sample_rate(fmt2); \
(rate1 > rate2 ? rate1 - rate2 : rate2 - rate1); \
})
unsigned int ast_format_get_sample_rate(const struct ast_format *format)
Get the sample rate of a media format.
Definition: format.c:379

Calculate the absolute difference between sample rate of two formats.

Definition at line 1395 of file translate.c.

◆ GROW_INDEX

#define GROW_INDEX   16

Definition at line 92 of file translate.c.

◆ INIT_INDEX

#define INIT_INDEX   32

Definition at line 90 of file translate.c.

◆ MAX_RECALC

#define MAX_RECALC   1000
Todo:
TODO: sample frames for each supported input format. We build this on the fly, by taking an SLIN frame and using the existing converter to play with it.

max sample recalc

Definition at line 54 of file translate.c.

Function Documentation

◆ __ast_register_translator()

int __ast_register_translator ( struct ast_translator t,
struct ast_module mod 
)

register codec translator

Register a translator This registers a codec translator with asterisk.

Definition at line 1237 of file translate.c.

1238{
1239 struct ast_translator *u;
1240 char tmp[80];
1243
1245 if (!src_codec) {
1246 ast_assert(0);
1247 ast_log(LOG_WARNING, "Failed to register translator: unknown source codec %s\n", t->src_codec.name);
1248 return -1;
1249 }
1250
1252 if (!dst_codec) {
1253 ast_log(LOG_WARNING, "Failed to register translator: unknown destination codec %s\n", t->dst_codec.name);
1254 return -1;
1255 }
1256
1258 if (matrix_resize(0)) {
1259 ast_log(LOG_WARNING, "Translator matrix can not represent any more translators. Out of resources.\n");
1260 return -1;
1261 }
1264 }
1265
1266 if (!mod) {
1267 ast_log(LOG_WARNING, "Missing module pointer, you need to supply one\n");
1268 return -1;
1269 }
1270
1271 if (!t->buf_size) {
1272 ast_log(LOG_WARNING, "empty buf size, you need to supply one\n");
1273 return -1;
1274 }
1276 ast_log(LOG_WARNING, "Table cost could not be generated for %s, "
1277 "Please set table_cost variable on translator.\n", t->name);
1278 return -1;
1279 }
1280
1281 t->module = mod;
1284 t->active = 1;
1285
1286 if (t->src_fmt_index < 0 || t->dst_fmt_index < 0) {
1287 ast_log(LOG_WARNING, "Invalid translator path: (%s codec is not valid)\n", t->src_fmt_index < 0 ? "starting" : "ending");
1288 return -1;
1289 }
1290 if (t->src_fmt_index >= cur_max_index) {
1291 ast_log(LOG_WARNING, "Source codec %s is larger than cur_max_index\n", t->src_codec.name);
1292 return -1;
1293 }
1294
1295 if (t->dst_fmt_index >= cur_max_index) {
1296 ast_log(LOG_WARNING, "Destination codec %s is larger than cur_max_index\n", t->dst_codec.name);
1297 return -1;
1298 }
1299
1300 if (t->buf_size) {
1301 /*
1302 * Align buf_size properly, rounding up to the machine-specific
1303 * alignment for pointers.
1304 */
1305 struct _test_align { void *a, *b; } p;
1306 int align = (char *)&p.b - (char *)&p.a;
1307
1308 t->buf_size = ((t->buf_size + align - 1) / align) * align;
1309 }
1310
1311 if (t->frameout == NULL) {
1313 }
1314
1316
1317 ast_verb(5, "Registered translator '%s' from codec %s to %s, table cost, %d, computational cost %d\n",
1320
1322
1323 /* find any existing translators that provide this same srcfmt/dstfmt,
1324 and put this one in order based on computational cost */
1326 if ((u->src_fmt_index == t->src_fmt_index) &&
1327 (u->dst_fmt_index == t->dst_fmt_index) &&
1328 (u->comp_cost > t->comp_cost)) {
1330 t = NULL;
1331 break;
1332 }
1333 }
1335
1336 /* if no existing translator was found for this codec combination,
1337 add it to the beginning of the list */
1338 if (t) {
1340 }
1341
1342 matrix_rebuild(0);
1343
1345
1346 return 0;
1347}
#define ast_log
Definition: astobj2.c:42
#define ao2_cleanup(obj)
Definition: astobj2.h:1934
static int tmp()
Definition: bt_open.c:389
struct ast_codec * ast_codec_get(const char *name, enum ast_media_type type, unsigned int sample_rate)
Retrieve a codec given a name, type, and sample rate.
Definition: codec.c:327
#define ast_verb(level,...)
#define LOG_WARNING
#define AST_RWLIST_TRAVERSE_SAFE_BEGIN
Definition: linkedlists.h:545
#define AST_RWLIST_WRLOCK(head)
Write locks a list.
Definition: linkedlists.h:52
#define AST_RWLIST_UNLOCK(head)
Attempts to unlock a read/write based list.
Definition: linkedlists.h:151
#define AST_RWLIST_TRAVERSE_SAFE_END
Definition: linkedlists.h:617
#define AST_RWLIST_INSERT_HEAD
Definition: linkedlists.h:718
#define AST_RWLIST_INSERT_BEFORE_CURRENT
Definition: linkedlists.h:610
#define NULL
Definition: resample.c:96
Represents a media codec within Asterisk.
Definition: codec.h:42
unsigned int sample_rate
Sample rate (number of samples carried in a second)
Definition: codec.h:52
enum ast_media_type type
Type of media this codec contains.
Definition: codec.h:50
const char * name
Name for this codec.
Definition: codec.h:46
Descriptor of a translator.
Definition: translate.h:137
char name[80]
Definition: translate.h:138
int buf_size
size of outbuf, in bytes. Mandatory. The wrapper code will also allocate an AST_FRIENDLY_OFFSET space...
Definition: translate.h:182
struct ast_codec src_codec
Definition: translate.h:139
struct ast_module * module
Definition: translate.h:187
struct ast_frame *(* frameout)(struct ast_trans_pvt *pvt)
Definition: translate.h:158
struct ast_codec dst_codec
Definition: translate.h:140
the list of translators
Definition: codec_dahdi.c:281
#define COLOR_MAGENTA
Definition: term.h:60
#define COLOR_BLACK
Definition: term.h:50
char * term_color(char *outbuf, const char *inbuf, int fgcolor, int bgcolor, int maxout)
Colorize a specified string by adding terminal color codes.
Definition: term.c:235
static struct test_val b
static struct test_val a
static int cur_max_index
Definition: translate.c:95
static int add_codec2index(struct ast_codec *codec)
Definition: translate.c:148
static struct ast_frame * default_frameout(struct ast_trans_pvt *pvt)
Definition: translate.c:469
static void matrix_rebuild(int samples)
rebuild a translation matrix.
Definition: translate.c:825
static int matrix_resize(int init)
Definition: translate.c:195
static int codec2index(struct ast_codec *codec)
Definition: translate.c:125
static void generate_computational_cost(struct ast_translator *t, int seconds)
Definition: translate.c:691
static int generate_table_cost(struct ast_codec *src, struct ast_codec *dst)
Definition: translate.c:769
#define RAII_VAR(vartype, varname, initval, dtor)
Declare a variable that will call a destructor function when it goes out of scope.
Definition: utils.h:941
#define ast_assert(a)
Definition: utils.h:739

References a, ast_translator::active, add_codec2index(), ao2_cleanup, ast_assert, ast_codec_get(), 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, b, ast_translator::buf_size, codec2index(), COLOR_BLACK, COLOR_MAGENTA, ast_translator::comp_cost, cur_max_index, default_frameout(), ast_translator::dst_codec, ast_translator::dst_fmt_index, ast_translator::frameout, generate_computational_cost(), generate_table_cost(), LOG_WARNING, matrix_rebuild(), matrix_resize(), ast_translator::module, ast_codec::name, ast_translator::name, NULL, RAII_VAR, ast_codec::sample_rate, ast_translator::src_codec, ast_translator::src_fmt_index, ast_translator::table_cost, term_color(), tmp(), and ast_codec::type.

◆ add_codec2index()

static int add_codec2index ( struct ast_codec codec)
static

Definition at line 148 of file translate.c.

149{
150 if (codec2index(codec) != -1) {
151 /* format is already already indexed */
152 return 0;
153 }
154
156 if (cur_max_index == (index_size)) {
158 return -1; /* hit max length */
159 }
160 __indextable[cur_max_index] = codec->id;
163
164 return 0;
165}
#define ast_rwlock_wrlock(a)
Definition: lock.h:236
#define ast_rwlock_unlock(a)
Definition: lock.h:234
unsigned int id
Internal unique identifier for this codec, set at registration time (starts at 1)
Definition: codec.h:44
static ast_rwlock_t tablelock
Definition: translate.c:87
static int index_size
Definition: translate.c:97
static unsigned int * __indextable
table for converting index to format values.
Definition: translate.c:84

References __indextable, ast_rwlock_unlock, ast_rwlock_wrlock, codec2index(), cur_max_index, ast_codec::id, index_size, and tablelock.

Referenced by __ast_register_translator().

◆ ast_trans_frameout()

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

generic frameout routine. If samples and datalen are 0, take whatever is in pvt and reset them, otherwise take the values in the caller and leave alone the pvt values.

generic frameout function

Definition at line 439 of file translate.c.

441{
442 struct ast_frame *f = &pvt->f;
443
444 if (samples) {
445 f->samples = samples;
446 } else {
447 if (pvt->samples == 0) {
448 return NULL;
449 }
450 f->samples = pvt->samples;
451 pvt->samples = 0;
452 }
453 if (datalen) {
454 f->datalen = datalen;
455 f->data.ptr = pvt->outbuf.c;
456 } else {
457 f->datalen = pvt->datalen;
458 if (!f->datalen) {
459 f->data.ptr = NULL;
460 } else {
461 f->data.ptr = pvt->outbuf.c;
462 }
463 pvt->datalen = 0;
464 }
465
466 return ast_frisolate(f);
467}
#define ast_frisolate(fr)
Makes a frame independent of any static storage.
Data structure associated with a single frame of data.
union ast_frame::@226 data
struct ast_frame f
Definition: translate.h:215
int datalen
actual space used in outbuf
Definition: translate.h:218
union ast_trans_pvt::@287 outbuf

References ast_frisolate, ast_trans_pvt::c, ast_frame::data, ast_frame::datalen, ast_trans_pvt::datalen, ast_trans_pvt::f, NULL, ast_trans_pvt::outbuf, ast_frame::ptr, ast_frame::samples, and ast_trans_pvt::samples.

Referenced by default_frameout(), lintoadpcm_frameout(), lintocodec2_frameout(), lintogsm_frameout(), lintoilbc_frameout(), lintolpc10_frameout(), and lintospeex_frameout().

◆ ast_translate()

struct ast_frame * ast_translate ( struct ast_trans_pvt path,
struct ast_frame f,
int  consume 
)

do the actual translation

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. In case the frame type is AST_FRAME_RTCP, the frame is not translated but passed to the translator codecs via the feedback callback, and a pointer to ast_null_frame is returned after that.

Definition at line 566 of file translate.c.

567{
568 struct ast_trans_pvt *p = path;
569 struct ast_frame *out;
570 struct timeval delivery;
571 int has_timing_info;
572 long ts;
573 long len;
574 int seqno;
575
576 if (f->frametype == AST_FRAME_RTCP) {
577 /* Just pass the feedback to the right callback, if it exists.
578 * This "translation" does nothing so return a null frame. */
579 struct ast_trans_pvt *tp;
580 for (tp = p; tp; tp = tp->next) {
581 if (tp->t->feedback)
582 tp->t->feedback(tp, f);
583 }
584 return &ast_null_frame;
585 }
586
587 has_timing_info = ast_test_flag(f, AST_FRFLAG_HAS_TIMING_INFO);
588 ts = f->ts;
589 len = f->len;
590 seqno = f->seqno;
591
592 if (!ast_tvzero(f->delivery)) {
593 if (!ast_tvzero(path->nextin)) {
594 /* Make sure this is in line with what we were expecting */
595 if (!ast_tveq(path->nextin, f->delivery)) {
596 /* The time has changed between what we expected and this
597 most recent time on the new packet. If we have a
598 valid prediction adjust our output time appropriately */
599 if (!ast_tvzero(path->nextout)) {
600 path->nextout = ast_tvadd(path->nextout,
601 ast_tvsub(f->delivery, path->nextin));
602 }
603 path->nextin = f->delivery;
604 }
605 } else {
606 /* This is our first pass. Make sure the timing looks good */
607 path->nextin = f->delivery;
608 path->nextout = f->delivery;
609 }
610 /* Predict next incoming sample */
611 path->nextin = ast_tvadd(path->nextin, ast_samp2tv(
613 }
614 delivery = f->delivery;
615 for (out = f; out && p ; p = p->next) {
616 struct ast_frame *current = out;
617
618 do {
619 framein(p, current);
621 } while (current);
622 if (out != f) {
624 }
625 out = p->t->frameout(p);
626 }
627
628 if (!out) {
630 }
631
632 if (out) {
633 /* we have a frame, play with times */
634 if (!ast_tvzero(delivery)) {
635 struct ast_frame *current = out;
636
637 do {
638 /* Regenerate prediction after a discontinuity */
639 if (ast_tvzero(path->nextout)) {
640 path->nextout = ast_tvnow();
641 }
642
643 /* Use next predicted outgoing timestamp */
644 current->delivery = path->nextout;
645
646 /* Invalidate prediction if we're entering a silence period */
647 if (current->frametype == AST_FRAME_CNG) {
648 path->nextout = ast_tv(0, 0);
649 /* Predict next outgoing timestamp from samples in this
650 frame. */
651 } else {
652 path->nextout = ast_tvadd(path->nextout, ast_samp2tv(
653 current->samples, ast_format_get_sample_rate(current->subclass.format)));
654 }
655
657 ast_debug(4, "Sample size different %d vs %d\n", f->samples, current->samples);
659 }
661 } while (current);
662 } else {
663 out->delivery = ast_tv(0, 0);
665 if (has_timing_info) {
666 out->ts = ts;
667 out->len = len;
668 out->seqno = seqno;
669 }
670 /* Invalidate prediction if we're entering a silence period */
671 if (out->frametype == AST_FRAME_CNG) {
672 path->nextout = ast_tv(0, 0);
673 }
674 }
675 }
676 if (consume) {
677 ast_frfree(f);
678 }
679 return out;
680}
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
@ AST_FRFLAG_HAS_TIMING_INFO
#define ast_frfree(fr)
@ AST_FRAME_RTCP
struct ast_frame ast_null_frame
Definition: main/frame.c:79
#define ast_debug(level,...)
Log a DEBUG message.
#define AST_LIST_NEXT(elm, field)
Returns the next entry in the list after the given entry.
Definition: linkedlists.h:439
size_t current
Definition: main/cli.c:113
struct ast_format * format
struct ast_frame_subclass subclass
struct timeval delivery
enum ast_frame_type frametype
Default structure for translators, with the basic fields and buffers, all allocated as part of the sa...
Definition: translate.h:213
struct timeval nextout
Definition: translate.h:229
struct timeval nextin
Definition: translate.h:228
struct ast_trans_pvt * next
Definition: translate.h:227
struct ast_translator * t
Definition: translate.h:214
void(* feedback)(struct ast_trans_pvt *pvt, struct ast_frame *feedback)
Definition: translate.h:162
struct timeval ast_samp2tv(unsigned int _nsamp, unsigned int _rate)
Returns a timeval corresponding to the duration of n samples at rate r. Useful to convert samples to ...
Definition: time.h:282
int ast_tveq(struct timeval _a, struct timeval _b)
Returns true if the two struct timeval arguments are equal.
Definition: time.h:147
int ast_tvzero(const struct timeval t)
Returns true if the argument is 0,0.
Definition: time.h:117
struct timeval ast_tvadd(struct timeval a, struct timeval b)
Returns the sum of two timevals a + b.
Definition: extconf.c:2282
struct timeval ast_tvsub(struct timeval a, struct timeval b)
Returns the difference of two timevals a - b.
Definition: extconf.c:2297
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
Definition: time.h:159
struct timeval ast_tv(ast_time_t sec, ast_suseconds_t usec)
Returns a timeval from sec, usec.
Definition: time.h:235
static struct ast_frame * generate_interpolated_slin(struct ast_trans_pvt *p, struct ast_frame *f)
Definition: translate.c:537
static int framein(struct ast_trans_pvt *pvt, struct ast_frame *f)
framein wrapper, deals with bound checks.
Definition: translate.c:397
FILE * out
Definition: utils/frame.c:33
#define ast_test_flag(p, flag)
Definition: utils.h:63
#define ast_set2_flag(p, value, flag)
Definition: utils.h:94
#define ast_clear_flag(p, flag)
Definition: utils.h:77

References ast_clear_flag, ast_debug, ast_format_get_sample_rate(), AST_FRAME_CNG, AST_FRAME_RTCP, AST_FRFLAG_HAS_TIMING_INFO, ast_frfree, AST_LIST_NEXT, ast_null_frame, ast_samp2tv(), ast_set2_flag, ast_test_flag, ast_tv(), ast_tvadd(), ast_tveq(), ast_tvnow(), ast_tvsub(), ast_tvzero(), current, ast_frame::delivery, ast_trans_pvt::f, ast_translator::feedback, ast_frame_subclass::format, framein(), ast_translator::frameout, ast_frame::frametype, generate_interpolated_slin(), len(), ast_frame::len, ast_trans_pvt::next, ast_trans_pvt::nextin, ast_trans_pvt::nextout, out, ast_frame::samples, ast_frame::seqno, ast_frame::subclass, ast_trans_pvt::t, and ast_frame::ts.

Referenced by __ast_read(), ast_slinfactory_feed(), ast_write_stream(), 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().

◆ ast_translate_available_formats()

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
[out]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 1616 of file translate.c.

1617{
1618 struct ast_format *cur_dest, *cur_src;
1619 int index;
1620
1621 for (index = 0; index < ast_format_cap_count(dest); ++index) {
1622 if (!(cur_dest = ast_format_cap_get_format(dest, index))) {
1623 continue;
1624 }
1625
1626 /* We give preference to a joint format structure if possible */
1627 if ((cur_src = ast_format_cap_get_compatible_format(src, cur_dest))) {
1628 ast_format_cap_append(result, cur_src, 0);
1629 ao2_ref(cur_src, -1);
1630 } else {
1631 /* Otherwise we just use the destination format */
1632 ast_format_cap_append(result, cur_dest, 0);
1633 }
1634 ao2_ref(cur_dest, -1);
1635 }
1636
1637 /* if we don't have a source format, we just have to try all
1638 possible destination formats */
1639 if (!src) {
1640 return;
1641 }
1642
1643 for (index = 0; index < ast_format_cap_count(src); ++index) {
1644 if (!(cur_src = ast_format_cap_get_format(src, index))) {
1645 continue;
1646 }
1647
1649 check_translation_path(dest, src, result,
1650 cur_src, AST_MEDIA_TYPE_AUDIO);
1651 check_translation_path(dest, src, result,
1652 cur_src, AST_MEDIA_TYPE_VIDEO);
1654 ao2_ref(cur_src, -1);
1655 }
1656}
#define ao2_ref(o, delta)
Reference/unreference an object and return the old refcount.
Definition: astobj2.h:459
static PGresult * result
Definition: cel_pgsql.c:84
@ AST_MEDIA_TYPE_AUDIO
Definition: codec.h:32
@ AST_MEDIA_TYPE_VIDEO
Definition: codec.h:33
struct ast_format * ast_format_cap_get_format(const struct ast_format_cap *cap, int position)
Get the format at a specific index.
Definition: format_cap.c:400
#define ast_format_cap_append(cap, format, framing)
Add format capability to capabilities structure.
Definition: format_cap.h:99
size_t ast_format_cap_count(const struct ast_format_cap *cap)
Get the number of formats present within the capabilities structure.
Definition: format_cap.c:395
struct ast_format * ast_format_cap_get_compatible_format(const struct ast_format_cap *cap, const struct ast_format *format)
Find if input ast_format is within the capabilities of the ast_format_cap object then return the comp...
Definition: format_cap.c:546
#define AST_RWLIST_RDLOCK(head)
Read locks a list.
Definition: linkedlists.h:78
Definition of a media format.
Definition: format.c:43
static void check_translation_path(struct ast_format_cap *dest, struct ast_format_cap *src, struct ast_format_cap *result, struct ast_format *src_fmt, enum ast_media_type type)
Definition: translate.c:1558

References ao2_ref, ast_format_cap_append, ast_format_cap_count(), ast_format_cap_get_compatible_format(), ast_format_cap_get_format(), AST_MEDIA_TYPE_AUDIO, AST_MEDIA_TYPE_VIDEO, AST_RWLIST_RDLOCK, AST_RWLIST_UNLOCK, check_translation_path(), and result.

Referenced by ast_rtp_instance_available_formats().

◆ ast_translate_init()

int ast_translate_init ( void  )

Initialize the translation matrix and index to format conversion table.

Return values
0on success
-1on failure

Definition at line 1675 of file translate.c.

1676{
1677 int res = 0;
1679 res = matrix_resize(1);
1682 return res;
1683}
int ast_register_cleanup(void(*func)(void))
Register a function to be executed before Asterisk gracefully exits.
Definition: clicompat.c:19
#define ast_cli_register_multiple(e, len)
Register multiple commands.
Definition: cli.h:265
#define ast_rwlock_init(rwlock)
wrapper for rwlock with tracking enabled
Definition: lock.h:224
static void translate_shutdown(void)
Definition: translate.c:1658
static struct ast_cli_entry cli_translate[]
Definition: translate.c:1232
#define ARRAY_LEN(a)
Definition: utils.h:666

References ARRAY_LEN, ast_cli_register_multiple, ast_register_cleanup(), ast_rwlock_init, cli_translate, matrix_resize(), tablelock, and translate_shutdown().

Referenced by asterisk_daemon().

◆ ast_translate_path_steps()

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
Return values
-1if no path is available

Definition at line 1536 of file translate.c.

1537{
1538 unsigned int res = -1;
1539 /* convert bitwise format numbers into array indices */
1540 int src = format2index(src_format);
1541 int dest = format2index(dst_format);
1542
1543 if (src < 0 || dest < 0) {
1544 ast_log(LOG_WARNING, "No translator path: (%s codec is not valid)\n", src < 0 ? "starting" : "ending");
1545 return -1;
1546 }
1548
1549 if (matrix_get(src, dest)->step) {
1550 res = matrix_get(src, dest)->multistep + 1;
1551 }
1552
1554
1555 return res;
1556}
uint8_t multistep
Definition: translate.c:63
static struct translator_path * matrix_get(unsigned int x, unsigned int y)
Definition: translate.c:283
static int format2index(struct ast_format *format)
Definition: translate.c:134

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

Referenced by ast_channel_make_compatible_helper().

◆ ast_translate_path_to_str()

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
ttranslator structure containing the translation path
strast_str output buffer
Returns
on success pointer to beginning of outbuf
Return values
""on failure

Definition at line 930 of file translate.c.

931{
932 if (!p || !p->t) {
933 return "";
934 }
935
938 while (p) {
939 ast_str_append(str, 0, "->");
941 p = p->next;
942 }
943
944 return ast_str_buffer(*str);
945}
const char * str
Definition: app_jack.c:147
int ast_str_append(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Append to a thread local dynamic string.
Definition: strings.h:1139
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
Definition: strings.h:761
void ast_str_reset(struct ast_str *buf)
Reset the content of a dynamic string. Useful before a series of ast_str_append.
Definition: strings.h:693
static void codec_append_name(const struct ast_codec *codec, struct ast_str **buf)
Definition: translate.c:921

References ast_str_append(), ast_str_buffer(), ast_str_reset(), codec_append_name(), ast_translator::dst_codec, ast_trans_pvt::next, ast_translator::src_codec, str, and ast_trans_pvt::t.

Referenced by chan_pjsip_write_stream(), generate_status(), handle_showchan(), and serialize_showchan().

◆ ast_translator_activate()

void ast_translator_activate ( struct ast_translator t)

Activate a previously deactivated translator.

Parameters
ttranslator to activate

Enables the specified translator for use.

Definition at line 1378 of file translate.c.

1379{
1381 t->active = 1;
1382 matrix_rebuild(0);
1384}

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

◆ ast_translator_best_choice()

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 
)

Calculate our best translator source format, given costs, and a desired destination.

Chooses the best translation path.

Definition at line 1402 of file translate.c.

1406{
1407 unsigned int besttablecost = INT_MAX;
1408 unsigned int beststeps = INT_MAX;
1409 struct ast_format *fmt;
1410 struct ast_format *dst;
1411 struct ast_format *src;
1412 RAII_VAR(struct ast_format *, best, NULL, ao2_cleanup);
1413 RAII_VAR(struct ast_format *, bestdst, NULL, ao2_cleanup);
1414 struct ast_format_cap *joint_cap;
1415 int i;
1416 int j;
1417
1418 if (ast_format_cap_empty(dst_cap) || ast_format_cap_empty(src_cap)) {
1419 ast_log(LOG_ERROR, "Cannot determine best translation path since one capability supports no formats\n");
1420 return -1;
1421 }
1422
1424 if (!joint_cap) {
1425 return -1;
1426 }
1427 ast_format_cap_get_compatible(dst_cap, src_cap, joint_cap);
1428
1429 for (i = 0; i < ast_format_cap_count(joint_cap); ++i, ao2_cleanup(fmt)) {
1430 fmt = ast_format_cap_get_format(joint_cap, i);
1431 if (!fmt
1433 continue;
1434 }
1435
1436 if (!best
1438 ao2_replace(best, fmt);
1439 }
1440 }
1441 ao2_ref(joint_cap, -1);
1442
1443 if (best) {
1444 ao2_replace(*dst_fmt_out, best);
1445 ao2_replace(*src_fmt_out, best);
1446 return 0;
1447 }
1448
1449 /* need to translate */
1451 for (i = 0; i < ast_format_cap_count(dst_cap); ++i, ao2_cleanup(dst)) {
1452 dst = ast_format_cap_get_format(dst_cap, i);
1453 if (!dst
1455 continue;
1456 }
1457
1458 for (j = 0; j < ast_format_cap_count(src_cap); ++j, ao2_cleanup(src)) {
1459 int x;
1460 int y;
1461
1462 src = ast_format_cap_get_format(src_cap, j);
1463 if (!src
1465 continue;
1466 }
1467
1468 x = format2index(src);
1469 y = format2index(dst);
1470 if (x < 0 || y < 0) {
1471 continue;
1472 }
1473 if (!matrix_get(x, y) || !(matrix_get(x, y)->step)) {
1474 continue;
1475 }
1476 if (matrix_get(x, y)->table_cost < besttablecost
1477 || matrix_get(x, y)->multistep < beststeps) {
1478 /* better than what we have so far */
1479 ao2_replace(best, src);
1480 ao2_replace(bestdst, dst);
1481 besttablecost = matrix_get(x, y)->table_cost;
1482 beststeps = matrix_get(x, y)->multistep;
1483 } else if (matrix_get(x, y)->table_cost == besttablecost
1484 && matrix_get(x, y)->multistep == beststeps) {
1485 int replace = 0;
1486 unsigned int gap_selected = format_sample_rate_absdiff(best, bestdst);
1487 unsigned int gap_current = format_sample_rate_absdiff(src, dst);
1488
1489 if (gap_current < gap_selected) {
1490 /* better than what we have so far */
1491 replace = 1;
1492 } else if (gap_current == gap_selected) {
1493 int src_quality, best_quality;
1494 struct ast_codec *src_codec, *best_codec;
1495
1496 src_codec = ast_format_get_codec(src);
1497 best_codec = ast_format_get_codec(best);
1498 src_quality = src_codec->quality;
1499 best_quality = best_codec->quality;
1500
1501 ao2_cleanup(src_codec);
1502 ao2_cleanup(best_codec);
1503
1504 /* We have a tie, so choose the format with the higher quality, if they differ. */
1505 if (src_quality > best_quality) {
1506 /* Better than what we had before. */
1507 replace = 1;
1508 ast_debug(2, "Tiebreaker: preferring format %s (%d) to %s (%d)\n", ast_format_get_name(src), src_quality,
1509 ast_format_get_name(best), best_quality);
1510 } else {
1511 /* This isn't necessarily indicative of a problem, but in reality this shouldn't really happen, unless
1512 * there are 2 formats that are basically the same. */
1513 ast_debug(1, "Completely ambiguous tie between formats %s and %s (quality %d): sticking with %s, but this is arbitrary\n",
1514 ast_format_get_name(src), ast_format_get_name(best), best_quality, ast_format_get_name(best));
1515 }
1516 }
1517 if (replace) {
1518 ao2_replace(best, src);
1519 ao2_replace(bestdst, dst);
1520 besttablecost = matrix_get(x, y)->table_cost;
1521 beststeps = matrix_get(x, y)->multistep;
1522 }
1523 }
1524 }
1525 }
1527
1528 if (!best) {
1529 return -1;
1530 }
1531 ao2_replace(*dst_fmt_out, bestdst);
1532 ao2_replace(*src_fmt_out, best);
1533 return 0;
1534}
#define ao2_replace(dst, src)
Replace one object reference with another cleaning up the original.
Definition: astobj2.h:501
enum ast_media_type ast_format_get_type(const struct ast_format *format)
Get the media type of a format.
Definition: format.c:354
struct ast_codec * ast_format_get_codec(const struct ast_format *format)
Get the codec associated with a format.
Definition: format.c:324
const char * ast_format_get_name(const struct ast_format *format)
Get the name associated with a format.
Definition: format.c:334
int ast_format_cap_empty(const struct ast_format_cap *cap)
Determine if a format cap has no formats in it.
Definition: format_cap.c:744
int ast_format_cap_get_compatible(const struct ast_format_cap *cap1, const struct ast_format_cap *cap2, struct ast_format_cap *result)
Find the compatible formats between two capabilities structures.
Definition: format_cap.c:628
@ AST_FORMAT_CAP_FLAG_DEFAULT
Definition: format_cap.h:38
#define ast_format_cap_alloc(flags)
Allocate a new ast_format_cap structure.
Definition: format_cap.h:49
static int replace(struct ast_channel *chan, const char *cmd, char *data, struct ast_str **buf, ssize_t len)
Definition: func_strings.c:888
#define LOG_ERROR
unsigned int quality
Format quality, on scale from 0 to 150 (100 is ulaw, the reference). This allows better format to be ...
Definition: codec.h:82
Format capabilities structure, holds formats + preference order + etc.
Definition: format_cap.c:54
uint32_t table_cost
Definition: translate.c:61
#define format_sample_rate_absdiff(fmt1, fmt2)
Definition: translate.c:1395

References ao2_cleanup, ao2_ref, ao2_replace, ast_debug, ast_format_cap_alloc, ast_format_cap_count(), ast_format_cap_empty(), AST_FORMAT_CAP_FLAG_DEFAULT, ast_format_cap_get_compatible(), ast_format_cap_get_format(), ast_format_get_codec(), ast_format_get_name(), ast_format_get_sample_rate(), ast_format_get_type(), ast_log, AST_MEDIA_TYPE_AUDIO, AST_RWLIST_RDLOCK, AST_RWLIST_UNLOCK, format2index(), format_sample_rate_absdiff, LOG_ERROR, matrix_get(), translator_path::multistep, NULL, ast_codec::quality, RAII_VAR, replace(), and translator_path::table_cost.

Referenced by ast_channel_make_compatible_helper(), ast_speech_new(), iax2_request(), local_request_with_stream_topology(), request_channel(), and set_format().

◆ ast_translator_build_path()

struct ast_trans_pvt * ast_translator_build_path ( struct ast_format dst,
struct ast_format src 
)

Build a chain of translators based upon the given source and dest formats.

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

Definition at line 486 of file translate.c.

487{
488 struct ast_trans_pvt *head = NULL, *tail = NULL;
489 int src_index, dst_index;
490
491 src_index = format2index(src);
492 dst_index = format2index(dst);
493
494 if (src_index < 0 || dst_index < 0) {
495 ast_log(LOG_WARNING, "No translator path: (%s codec is not valid)\n", src_index < 0 ? "starting" : "ending");
496 return NULL;
497 }
498
500
501 while (src_index != dst_index) {
502 struct ast_trans_pvt *cur;
503 struct ast_format *explicit_dst = NULL;
504 struct ast_translator *t = matrix_get(src_index, dst_index)->step;
505 if (!t) {
506 ast_log(LOG_WARNING, "No translator path from %s to %s\n",
510 return NULL;
511 }
513 explicit_dst = dst;
514 }
515 if (!(cur = newpvt(t, explicit_dst))) {
516 ast_log(LOG_WARNING, "Failed to build translator step from %s to %s\n",
520 return NULL;
521 }
522 if (!head) {
523 head = cur;
524 } else {
525 tail->next = cur;
526 }
527 tail = cur;
528 cur->nextin = cur->nextout = ast_tv(0, 0);
529 /* Keep going if this isn't the final destination */
530 src_index = cur->t->dst_fmt_index;
531 }
532
534 return head;
535}
struct ast_translator * step
Definition: translate.c:60
void ast_translator_free_path(struct ast_trans_pvt *p)
Frees a translator path Frees the given translator path structure.
Definition: translate.c:476
static struct ast_trans_pvt * newpvt(struct ast_translator *t, struct ast_format *explicit_dst)
Allocate the descriptor, required outbuf space, and possibly desc.
Definition: translate.c:312

References ast_format_get_name(), ast_format_get_sample_rate(), ast_format_get_type(), ast_log, AST_RWLIST_RDLOCK, AST_RWLIST_UNLOCK, ast_translator_free_path(), ast_tv(), ast_translator::dst_codec, ast_translator::dst_fmt_index, format2index(), LOG_WARNING, matrix_get(), newpvt(), ast_trans_pvt::next, ast_trans_pvt::nextin, ast_trans_pvt::nextout, NULL, ast_codec::sample_rate, translator_path::step, ast_trans_pvt::t, and ast_codec::type.

Referenced by ast_set_read_format_path(), ast_set_write_format_path(), 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().

◆ ast_translator_deactivate()

void ast_translator_deactivate ( struct ast_translator t)

Deactivate a translator.

Parameters
ttranslator to deactivate

Disables the specified translator from being used.

Definition at line 1386 of file translate.c.

1387{
1389 t->active = 0;
1390 matrix_rebuild(0);
1392}

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

◆ ast_translator_free_path()

void ast_translator_free_path ( struct ast_trans_pvt tr)

◆ ast_unregister_translator()

int ast_unregister_translator ( struct ast_translator t)

unregister codec translator

Unregister a translator Unregisters the given translator.

Definition at line 1350 of file translate.c.

1351{
1352 char tmp[80];
1353 struct ast_translator *u;
1354 int found = 0;
1355
1358 if (u == t) {
1360 ast_verb(5, "Unregistered translator '%s' from codec %s to %s\n",
1362 t->src_codec.name, t->dst_codec.name);
1363 found = 1;
1364 break;
1365 }
1366 }
1368
1369 if (found && !ast_shutting_down()) {
1370 matrix_rebuild(0);
1371 }
1372
1374
1375 return (u ? 0 : -1);
1376}
int ast_shutting_down(void)
Definition: asterisk.c:1872
#define AST_RWLIST_REMOVE_CURRENT
Definition: linkedlists.h:570
struct ast_translator::@286 list

References AST_RWLIST_REMOVE_CURRENT, AST_RWLIST_TRAVERSE_SAFE_BEGIN, AST_RWLIST_TRAVERSE_SAFE_END, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, ast_shutting_down(), ast_verb, COLOR_BLACK, COLOR_MAGENTA, ast_translator::dst_codec, ast_translator::list, matrix_rebuild(), ast_codec::name, ast_translator::name, ast_translator::src_codec, term_color(), and tmp().

Referenced by unload_module(), and unregister_translators().

◆ check_translation_path()

static void check_translation_path ( struct ast_format_cap dest,
struct ast_format_cap src,
struct ast_format_cap result,
struct ast_format src_fmt,
enum ast_media_type  type 
)
static

Definition at line 1558 of file translate.c.

1562{
1563 int i;
1564
1565 if (ast_format_get_type(src_fmt) != type) {
1566 return;
1567 }
1568
1569 /* For a given source format, traverse the list of
1570 known formats to determine whether there exists
1571 a translation path from the source format to the
1572 destination format. */
1573 for (i = ast_format_cap_count(result) - 1; 0 <= i; i--) {
1574 int index, src_index;
1576
1577 if (ast_format_get_type(fmt) != type) {
1578 continue;
1579 }
1580
1581 /* if this is not a desired format, nothing to do */
1583 continue;
1584 }
1585
1586 /* if the source is supplying this format, then
1587 we can leave it in the result */
1589 continue;
1590 }
1591
1592 /* if this is a pass-through format, not in the source,
1593 we cannot transcode. Therefore, remove it from the result */
1594 src_index = format2index(src_fmt);
1595 index = format2index(fmt);
1596 if (src_index < 0 || index < 0) {
1598 continue;
1599 }
1600
1601 /* if we don't have a translation path from the src
1602 to this format, remove it from the result */
1603 if (!matrix_get(src_index, index)->step) {
1605 continue;
1606 }
1607
1608 /* now check the opposite direction */
1609 if (!matrix_get(index, src_index)->step) {
1611 }
1612 }
1613
1614}
static const char type[]
Definition: chan_ooh323.c:109
@ AST_FORMAT_CMP_EQUAL
Definition: format.h:36
@ AST_FORMAT_CMP_NOT_EQUAL
Definition: format.h:38
int ast_format_cap_remove(struct ast_format_cap *cap, struct ast_format *format)
Remove format capability from capability structure.
Definition: format_cap.c:495
enum ast_format_cmp_res ast_format_cap_iscompatible_format(const struct ast_format_cap *cap, const struct ast_format *format)
Find if ast_format is within the capabilities of the ast_format_cap object.
Definition: format_cap.c:581

References ao2_cleanup, ast_format_cap_count(), ast_format_cap_get_format(), ast_format_cap_iscompatible_format(), ast_format_cap_remove(), AST_FORMAT_CMP_EQUAL, AST_FORMAT_CMP_NOT_EQUAL, ast_format_get_type(), format2index(), matrix_get(), RAII_VAR, result, and type.

Referenced by ast_translate_available_formats().

◆ codec2index()

static int codec2index ( struct ast_codec codec)
static

Definition at line 125 of file translate.c.

126{
127 return codec_to_index(codec->id);
128}
static int codec_to_index(unsigned int id)
Definition: translate.c:105

References codec_to_index(), and ast_codec::id.

Referenced by __ast_register_translator(), add_codec2index(), handle_show_translation_path(), and handle_show_translation_table().

◆ codec_append_name()

static void codec_append_name ( const struct ast_codec codec,
struct ast_str **  buf 
)
static

Definition at line 921 of file translate.c.

922{
923 if (codec) {
924 ast_str_append(buf, 0, "(%s@%u)", codec->name, codec->sample_rate);
925 } else {
926 ast_str_append(buf, 0, "(nothing)");
927 }
928}
char buf[BUFSIZE]
Definition: eagi_proxy.c:66

References ast_str_append(), buf, ast_codec::name, and ast_codec::sample_rate.

Referenced by ast_translate_path_to_str(), and handle_show_translation_path().

◆ codec_to_index()

static int codec_to_index ( unsigned int  id)
static

Definition at line 105 of file translate.c.

106{
107 int x;
108
110 for (x = 0; x < cur_max_index; x++) {
111 if (__indextable[x] == id) {
112 /* format already exists in index2format table */
114 return x;
115 }
116 }
118 return -1; /* not found */
119}
#define ast_rwlock_rdlock(a)
Definition: lock.h:235

References __indextable, ast_rwlock_rdlock, ast_rwlock_unlock, cur_max_index, and tablelock.

Referenced by codec2index(), and format2index().

◆ complete_trans_path_choice()

static char * complete_trans_path_choice ( const char *  word)
static

Definition at line 947 of file translate.c.

948{
949 int i = 1;
950 int wordlen = strlen(word);
951 struct ast_codec *codec;
952
953 while ((codec = ast_codec_get_by_id(i))) {
954 ++i;
955 if (codec->type != AST_MEDIA_TYPE_AUDIO) {
956 ao2_ref(codec, -1);
957 continue;
958 }
959 if (!strncasecmp(word, codec->name, wordlen)) {
961 ao2_ref(codec, -1);
962 break;
963 }
964 }
965 ao2_ref(codec, -1);
966 }
967
968 return NULL;
969}
#define ast_strdup(str)
A wrapper for strdup()
Definition: astmm.h:241
int ast_cli_completion_add(char *value)
Add a result to a request for completion options.
Definition: main/cli.c:2756
struct ast_codec * ast_codec_get_by_id(int id)
Retrieve a codec given the unique identifier.
Definition: codec.c:338
short word

References ao2_ref, ast_cli_completion_add(), ast_codec_get_by_id(), AST_MEDIA_TYPE_AUDIO, ast_strdup, ast_codec::name, NULL, and ast_codec::type.

Referenced by handle_cli_core_show_translation().

◆ default_frameout()

static struct ast_frame * default_frameout ( struct ast_trans_pvt pvt)
static

Definition at line 469 of file translate.c.

470{
471 return ast_trans_frameout(pvt, 0, 0);
472}
struct ast_frame * ast_trans_frameout(struct ast_trans_pvt *pvt, int datalen, int samples)
generic frameout routine. If samples and datalen are 0, take whatever is in pvt and reset them,...
Definition: translate.c:439

References ast_trans_frameout().

Referenced by __ast_register_translator().

◆ destroy()

static void destroy ( struct ast_trans_pvt pvt)
static

Definition at line 292 of file translate.c.

293{
294 struct ast_translator *t = pvt->t;
295
296 if (t->destroy) {
297 t->destroy(pvt);
298 }
300 if (pvt->explicit_dst) {
301 ao2_ref(pvt->explicit_dst, -1);
302 pvt->explicit_dst = NULL;
303 }
304 ast_free(pvt);
306}
#define ast_free(a)
Definition: astmm.h:180
#define ast_module_unref(mod)
Release a reference to the module.
Definition: module.h:469
struct ast_format * explicit_dst
Definition: translate.h:237
void(* destroy)(struct ast_trans_pvt *pvt)
Definition: translate.h:166

References ao2_cleanup, ao2_ref, ast_free, ast_module_unref, ast_translator::destroy, ast_trans_pvt::explicit_dst, ast_trans_pvt::f, ast_frame_subclass::format, ast_translator::module, NULL, ast_frame::subclass, and ast_trans_pvt::t.

Referenced by ast_translator_free_path(), generate_computational_cost(), and newpvt().

◆ format2index()

static int format2index ( struct ast_format format)
static

Definition at line 134 of file translate.c.

135{
137}
unsigned int ast_format_get_codec_id(const struct ast_format *format)
Get the codec identifier associated with a format.
Definition: format.c:329

References ast_format_get_codec_id(), and codec_to_index().

Referenced by ast_translate_path_steps(), ast_translator_best_choice(), ast_translator_build_path(), and check_translation_path().

◆ framein()

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

framein wrapper, deals with bound checks.

Definition at line 397 of file translate.c.

398{
399 /* Copy the last in jb timing info to the pvt */
401 pvt->f.ts = f->ts;
402 pvt->f.len = f->len;
403 pvt->f.seqno = f->seqno;
404
405 if (f->samples == 0) {
406 /* Do not log empty audio frame */
407 if (!f->src || strcasecmp(f->src, "ast_prod")) {
408 ast_log(LOG_WARNING, "no samples for %s\n", pvt->t->name);
409 }
410 }
411 if (pvt->t->buffer_samples) { /* do not pass empty frames to callback */
412 int src_srate = pvt->t->src_codec.sample_rate;
413 int dst_srate = pvt->t->dst_codec.sample_rate;
414
415 ast_assert(src_srate > 0);
416
417 if (f->datalen == 0) { /* perform native PLC if available */
418 /* If the codec has native PLC, then do that */
419 if (!pvt->t->native_plc)
420 return 0;
421 }
422
423 if (pvt->samples + (f->samples * dst_srate / src_srate) > pvt->t->buffer_samples) {
424 ast_log(LOG_WARNING, "Out of buffer space\n");
425 return -1;
426 }
427 }
428 /* we require a framein routine, wouldn't know how to do
429 * it otherwise.
430 */
431 return pvt->t->framein(pvt, f);
432}
const char * src
int buffer_samples
size of outbuf, in samples. Leave it 0 if you want the framein callback deal with the frame....
Definition: translate.h:177
int(* framein)(struct ast_trans_pvt *pvt, struct ast_frame *in)
Definition: translate.h:154
#define ast_copy_flags(dest, src, flagz)
Definition: utils.h:84

References ast_assert, ast_copy_flags, AST_FRFLAG_HAS_TIMING_INFO, ast_log, ast_translator::buffer_samples, ast_frame::datalen, ast_translator::dst_codec, ast_trans_pvt::f, ast_translator::framein, ast_frame::len, LOG_WARNING, ast_translator::name, ast_translator::native_plc, ast_codec::sample_rate, ast_frame::samples, ast_trans_pvt::samples, ast_frame::seqno, ast_frame::src, ast_translator::src_codec, ast_trans_pvt::t, and ast_frame::ts.

Referenced by ast_translate(), and generate_computational_cost().

◆ generate_computational_cost()

static void generate_computational_cost ( struct ast_translator t,
int  seconds 
)
static

Definition at line 691 of file translate.c.

692{
693 int num_samples = 0;
694 struct ast_trans_pvt *pvt;
695 struct rusage start;
696 struct rusage end;
697 int cost;
698 int out_rate = t->dst_codec.sample_rate;
699
700 if (!seconds) {
701 seconds = 1;
702 }
703
704 /* If they don't make samples, give them a terrible score */
705 if (!t->sample) {
706 ast_debug(3, "Translator '%s' does not produce sample frames.\n", t->name);
707 t->comp_cost = 999999;
708 return;
709 }
710
711 pvt = newpvt(t, NULL);
712 if (!pvt) {
713 ast_log(LOG_WARNING, "Translator '%s' appears to be broken and will probably fail.\n", t->name);
714 t->comp_cost = 999999;
715 return;
716 }
717
718 getrusage(RUSAGE_SELF, &start);
719
720 /* Call the encoder until we've processed the required number of samples */
721 while (num_samples < seconds * out_rate) {
722 struct ast_frame *f = t->sample();
723 if (!f) {
724 ast_log(LOG_WARNING, "Translator '%s' failed to produce a sample frame.\n", t->name);
725 destroy(pvt);
726 t->comp_cost = 999999;
727 return;
728 }
729 framein(pvt, f);
730 ast_frfree(f);
731 while ((f = t->frameout(pvt))) {
732 num_samples += f->samples;
733 ast_frfree(f);
734 }
735 }
736
737 getrusage(RUSAGE_SELF, &end);
738
739 cost = ((end.ru_utime.tv_sec - start.ru_utime.tv_sec) * 1000000) + end.ru_utime.tv_usec - start.ru_utime.tv_usec;
740 cost += ((end.ru_stime.tv_sec - start.ru_stime.tv_sec) * 1000000) + end.ru_stime.tv_usec - start.ru_stime.tv_usec;
741
742 destroy(pvt);
743
744 t->comp_cost = cost / seconds;
745
746 if (!t->comp_cost) {
747 t->comp_cost = 1;
748 }
749}
char * end
Definition: eagi_proxy.c:73
void * pvt
Definition: translate.h:219
struct ast_frame *(* sample)(void)
Definition: translate.h:170

References ast_debug, ast_frfree, ast_log, ast_translator::comp_cost, destroy(), ast_translator::dst_codec, end, framein(), ast_translator::frameout, LOG_WARNING, ast_translator::name, newpvt(), NULL, ast_trans_pvt::pvt, ast_translator::sample, ast_codec::sample_rate, and ast_frame::samples.

Referenced by __ast_register_translator(), and matrix_rebuild().

◆ generate_interpolated_slin()

static struct ast_frame * generate_interpolated_slin ( struct ast_trans_pvt p,
struct ast_frame f 
)
static

Definition at line 537 of file translate.c.

538{
539 struct ast_frame res = { AST_FRAME_VOICE };
540
541 /*
542 * If we've gotten here then we should have an interpolated frame that was not handled
543 * by the translation codec. So create an interpolated frame in the appropriate format
544 * that was going to be written. This frame might be handled later by other resources.
545 * For instance, generic plc.
546 *
547 * Note, generic plc is currently only available for the format type 'slin' (8KHz only -
548 * The generic plc code appears to have been based around that). Generic plc is filled
549 * in later on frame write.
550 */
551 if (!ast_opt_generic_plc || f->datalen != 0 ||
553 return NULL;
554 }
555
556 res.subclass.format = ast_format_cache_get_slin_by_rate(8000); /* ref bumped on dup */
557 res.samples = f->samples;
558 res.datalen = 0;
559 res.data.ptr = NULL;
561
562 return ast_frdup(&res);
563}
enum ast_format_cmp_res ast_format_cmp(const struct ast_format *format1, const struct ast_format *format2)
Compare two formats.
Definition: format.c:201
struct ast_format * ast_format_slin
Built-in cached signed linear 8kHz format.
Definition: format_cache.c:41
struct ast_format * ast_format_cache_get_slin_by_rate(unsigned int rate)
Retrieve the best signed linear format given a sample rate.
Definition: format_cache.c:512
#define ast_frdup(fr)
Copies a frame.
#define AST_FRIENDLY_OFFSET
Offset into a frame's data buffer.
@ AST_FRAME_VOICE
#define ast_opt_generic_plc
Definition: options.h:134

References ast_format_cache_get_slin_by_rate(), ast_format_cmp(), AST_FORMAT_CMP_NOT_EQUAL, ast_format_slin, AST_FRAME_VOICE, ast_frdup, AST_FRIENDLY_OFFSET, ast_opt_generic_plc, ast_frame::data, ast_frame::datalen, ast_trans_pvt::explicit_dst, ast_frame_subclass::format, NULL, ast_frame::offset, ast_frame::ptr, ast_frame::samples, and ast_frame::subclass.

Referenced by ast_translate().

◆ generate_table_cost()

static int generate_table_cost ( struct ast_codec src,
struct ast_codec dst 
)
static

Definition at line 769 of file translate.c.

770{
771 int src_rate = src->sample_rate;
772 int src_ll = 0;
773 int dst_rate = dst->sample_rate;
774 int dst_ll = 0;
775
776 if ((src->type != AST_MEDIA_TYPE_AUDIO) ||
777 (dst->type != AST_MEDIA_TYPE_AUDIO)) {
778 /* This method of generating table cost is limited to audio.
779 * Translators for media other than audio must manually set their
780 * table cost. */
781 return 0;
782 }
783
784 src_ll = !strcmp(src->name, "slin");
785 dst_ll = !strcmp(dst->name, "slin");
786 if (src_ll) {
787 if (dst_ll && (src_rate == dst_rate)) {
789 } else if (!dst_ll && (src_rate == dst_rate)) {
791 } else if (dst_ll && (src_rate < dst_rate)) {
793 } else if (!dst_ll && (src_rate < dst_rate)) {
795 } else if (dst_ll && (src_rate > dst_rate)) {
797 } else if (!dst_ll && (src_rate > dst_rate)) {
799 } else {
801 }
802 } else {
803 if (dst_ll && (src_rate == dst_rate)) {
805 } else if (!dst_ll && (src_rate == dst_rate)) {
807 } else if (dst_ll && (src_rate < dst_rate)) {
809 } else if (!dst_ll && (src_rate < dst_rate)) {
811 } else if (dst_ll && (src_rate > dst_rate)) {
813 } else if (!dst_ll && (src_rate > dst_rate)) {
815 } else {
817 }
818 }
819}
@ AST_TRANS_COST_LY_LY_DOWNSAMP
Definition: translate.h:100
@ AST_TRANS_COST_LL_LL_DOWNSAMP
Definition: translate.h:76
@ AST_TRANS_COST_LY_LY_ORIGSAMP
Definition: translate.h:90
@ AST_TRANS_COST_LL_LL_UPSAMP
Definition: translate.h:71
@ AST_TRANS_COST_LY_LL_ORIGSAMP
Definition: translate.h:88
@ AST_TRANS_COST_LL_UNKNOWN
Definition: translate.h:83
@ AST_TRANS_COST_LY_LL_DOWNSAMP
Definition: translate.h:98
@ AST_TRANS_COST_LL_LY_DOWNSAMP
Definition: translate.h:78
@ AST_TRANS_COST_LL_LY_ORIGSAMP
Definition: translate.h:68
@ AST_TRANS_COST_LY_UNKNOWN
Definition: translate.h:105
@ AST_TRANS_COST_LL_LY_UPSAMP
Definition: translate.h:73
@ AST_TRANS_COST_LY_LY_UPSAMP
Definition: translate.h:95
@ AST_TRANS_COST_LY_LL_UPSAMP
Definition: translate.h:93
@ AST_TRANS_COST_LL_LL_ORIGSAMP
Definition: translate.h:66

References AST_MEDIA_TYPE_AUDIO, AST_TRANS_COST_LL_LL_DOWNSAMP, AST_TRANS_COST_LL_LL_ORIGSAMP, AST_TRANS_COST_LL_LL_UPSAMP, AST_TRANS_COST_LL_LY_DOWNSAMP, AST_TRANS_COST_LL_LY_ORIGSAMP, AST_TRANS_COST_LL_LY_UPSAMP, AST_TRANS_COST_LL_UNKNOWN, AST_TRANS_COST_LY_LL_DOWNSAMP, AST_TRANS_COST_LY_LL_ORIGSAMP, AST_TRANS_COST_LY_LL_UPSAMP, AST_TRANS_COST_LY_LY_DOWNSAMP, AST_TRANS_COST_LY_LY_ORIGSAMP, AST_TRANS_COST_LY_LY_UPSAMP, AST_TRANS_COST_LY_UNKNOWN, ast_codec::name, ast_codec::sample_rate, ast_frame::src, and ast_codec::type.

Referenced by __ast_register_translator().

◆ handle_cli_core_show_translation()

static char * handle_cli_core_show_translation ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
)
static

Definition at line 1175 of file translate.c.

1176{
1177 static const char * const option[] = { "recalc", "paths", "comp", NULL };
1178
1179 switch (cmd) {
1180 case CLI_INIT:
1181 e->command = "core show translation";
1182 e->usage =
1183 "Usage: 'core show translation' can be used in three ways.\n"
1184 " 1. 'core show translation [recalc [<recalc seconds>]\n"
1185 " Displays known codec translators and the cost associated\n"
1186 " with each conversion. If the argument 'recalc' is supplied along\n"
1187 " with optional number of seconds to test a new test will be performed\n"
1188 " as the chart is being displayed.\n"
1189 " 2. 'core show translation paths [codec [sample_rate]]'\n"
1190 " This will display all the translation paths associated with a codec.\n"
1191 " If a codec has multiple sample rates, the sample rate must be\n"
1192 " provided as well.\n"
1193 " 3. 'core show translation comp [<recalc seconds>]'\n"
1194 " Displays known codec translators and the cost associated\n"
1195 " with each conversion. If the argument 'recalc' is supplied along\n"
1196 " with optional number of seconds to test a new test will be performed\n"
1197 " as the chart is being displayed. The resulting numbers in the table\n"
1198 " give the actual computational costs in microseconds.\n";
1199 return NULL;
1200 case CLI_GENERATE:
1201 if (a->pos == 3) {
1202 return ast_cli_complete(a->word, option, -1);
1203 }
1204 if (a->pos == 4 && !strcasecmp(a->argv[3], option[1])) {
1205 return complete_trans_path_choice(a->word);
1206 }
1207 /* BUGBUG - add tab completion for sample rates */
1208 return NULL;
1209 }
1210
1211 if (a->argc > 6)
1212 return CLI_SHOWUSAGE;
1213
1214 if (a->argv[3] && !strcasecmp(a->argv[3], option[1]) && a->argc == 5) { /* show paths */
1215 return handle_show_translation_path(a, a->argv[4], 0);
1216 } else if (a->argv[3] && !strcasecmp(a->argv[3], option[1]) && a->argc == 6) {
1217 unsigned int sample_rate;
1218 if (sscanf(a->argv[5], "%30u", &sample_rate) != 1) {
1219 ast_cli(a->fd, "Invalid sample rate: %s.\n", a->argv[5]);
1220 return CLI_FAILURE;
1221 }
1222 return handle_show_translation_path(a, a->argv[4], sample_rate);
1223 } else if (a->argv[3] && (!strcasecmp(a->argv[3], option[0]) || !strcasecmp(a->argv[3], option[2]))) { /* recalc and then fall through to show table */
1225 } else if (a->argc > 3) { /* wrong input */
1226 return CLI_SHOWUSAGE;
1227 }
1228
1230}
#define CLI_SHOWUSAGE
Definition: cli.h:45
void ast_cli(int fd, const char *fmt,...)
Definition: clicompat.c:6
char * ast_cli_complete(const char *word, const char *const choices[], int pos)
Definition: main/cli.c:1841
@ CLI_INIT
Definition: cli.h:152
@ CLI_GENERATE
Definition: cli.h:153
#define CLI_FAILURE
Definition: cli.h:46
char * command
Definition: cli.h:186
const char * usage
Definition: cli.h:177
static char * handle_show_translation_table(struct ast_cli_args *a)
Definition: translate.c:990
static void handle_cli_recalc(struct ast_cli_args *a)
Definition: translate.c:971
static char * handle_show_translation_path(struct ast_cli_args *a, const char *codec_name, unsigned int sample_rate)
Definition: translate.c:1110
static char * complete_trans_path_choice(const char *word)
Definition: translate.c:947

References a, ast_cli(), ast_cli_complete(), CLI_FAILURE, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, ast_cli_entry::command, complete_trans_path_choice(), handle_cli_recalc(), handle_show_translation_path(), handle_show_translation_table(), NULL, ast_codec::sample_rate, and ast_cli_entry::usage.

◆ handle_cli_recalc()

static void handle_cli_recalc ( struct ast_cli_args a)
static

Definition at line 971 of file translate.c.

972{
973 int time = a->argv[4] ? atoi(a->argv[4]) : 1;
974
975 if (time <= 0) {
976 ast_cli(a->fd, " Recalc must be greater than 0. Defaulting to 1.\n");
977 time = 1;
978 }
979
980 if (time > MAX_RECALC) {
981 ast_cli(a->fd, " Maximum limit of recalc exceeded by %d, truncating value to %d\n", time - MAX_RECALC, MAX_RECALC);
982 time = MAX_RECALC;
983 }
984 ast_cli(a->fd, " Recalculating Codec Translation (number of sample seconds: %d)\n\n", time);
986 matrix_rebuild(time);
988}
#define MAX_RECALC
Definition: translate.c:54

References a, ast_cli(), AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, matrix_rebuild(), and MAX_RECALC.

Referenced by handle_cli_core_show_translation().

◆ handle_show_translation_path()

static char * handle_show_translation_path ( struct ast_cli_args a,
const char *  codec_name,
unsigned int  sample_rate 
)
static

Definition at line 1110 of file translate.c.

1111{
1112 int i = 1;
1113 struct ast_str *str = ast_str_alloca(1024);
1114 struct ast_translator *step;
1115 struct ast_codec *dst_codec;
1116 struct ast_codec *src_codec = ast_codec_get(codec_name, AST_MEDIA_TYPE_AUDIO, sample_rate);
1117
1118 if (!src_codec) {
1119 ast_cli(a->fd, "Source codec \"%s\" is not found.\n", codec_name);
1120 return CLI_FAILURE;
1121 }
1122
1124 ast_cli(a->fd, "--- Translation paths SRC Codec \"%s\" sample rate %u ---\n",
1125 codec_name, src_codec->sample_rate);
1126
1127 while ((dst_codec = ast_codec_get_by_id(i))) {
1128 int src, dst;
1129 char src_buffer[64];
1130 char dst_buffer[64];
1131
1132 ++i;
1133 if (src_codec == dst_codec ||
1134 dst_codec->type != AST_MEDIA_TYPE_AUDIO) {
1135 ao2_ref(dst_codec, -1);
1136 continue;
1137 }
1138
1139 dst = codec2index(dst_codec);
1140 src = codec2index(src_codec);
1141
1142 if (src < 0 || dst < 0) {
1143 ast_str_set(&str, 0, "No Translation Path");
1144 } else {
1145 step = matrix_get(src, dst)->step;
1146
1147 if (step) {
1149 while (src != dst) {
1150 src = step->dst_fmt_index;
1151 step = matrix_get(src, dst)->step;
1152 if (!step) {
1153 ast_str_append(&str, 0, "->");
1154 codec_append_name(dst_codec, &str);
1155 break;
1156 }
1157 ast_str_append(&str, 0, "->");
1159 }
1160 }
1161 }
1162
1163 snprintf(src_buffer, sizeof(src_buffer), "%s:%u", src_codec->name, src_codec->sample_rate);
1164 snprintf(dst_buffer, sizeof(dst_buffer), "%s:%u", dst_codec->name, dst_codec->sample_rate);
1165 ast_cli(a->fd, "\t%-16.16s To %-16.16s: %-60.60s\n",
1166 src_buffer, dst_buffer, ast_str_buffer(str));
1168 ao2_ref(dst_codec, -1);
1169 }
1171 ao2_ref(src_codec, -1);
1172 return CLI_SUCCESS;
1173}
#define CLI_SUCCESS
Definition: cli.h:44
#define ast_str_alloca(init_len)
Definition: strings.h:848
int ast_str_set(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Set a dynamic string using variable arguments.
Definition: strings.h:1113
Support for dynamic strings.
Definition: strings.h:623

References a, ao2_ref, ast_cli(), ast_codec_get(), ast_codec_get_by_id(), AST_MEDIA_TYPE_AUDIO, AST_RWLIST_RDLOCK, AST_RWLIST_UNLOCK, ast_str_alloca, ast_str_append(), ast_str_buffer(), ast_str_reset(), ast_str_set(), CLI_FAILURE, CLI_SUCCESS, codec2index(), codec_append_name(), ast_translator::dst_fmt_index, matrix_get(), ast_codec::name, ast_codec::sample_rate, ast_translator::src_codec, translator_path::step, str, and ast_codec::type.

Referenced by handle_cli_core_show_translation().

◆ handle_show_translation_table()

static char * handle_show_translation_table ( struct ast_cli_args a)
static

Definition at line 990 of file translate.c.

991{
992 int x, y, i, k, compCost;
993 int longest = 7; /* slin192 */
994 int max_codec_index = 0, curlen = 0;
995 struct ast_str *out = ast_str_create(1024);
996 struct ast_codec *codec;
997
998 /* Get the length of the longest (usable?) codec name,
999 so we know how wide the left side should be */
1000 for (i = 1; (codec = ast_codec_get_by_id(i)); ao2_ref(codec, -1), ++i) {
1001 ++max_codec_index;
1002 if (codec->type != AST_MEDIA_TYPE_AUDIO) {
1003 continue;
1004 }
1005 curlen = strlen(codec->name);
1006 if (curlen > longest) {
1007 longest = curlen;
1008 }
1009 }
1010
1012 ast_cli(a->fd, " Translation times between formats (in microseconds) for one second of data\n");
1013 ast_cli(a->fd, " Source Format (Rows) Destination Format (Columns)\n\n");
1014
1015 for (i = 0; i <= max_codec_index; i++) {
1016 struct ast_codec *row = i ? ast_codec_get_by_id(i) : NULL;
1017
1018 x = -1;
1019 if ((i > 0) && (row->type != AST_MEDIA_TYPE_AUDIO)) {
1020 ao2_ref(row, -1);
1021 continue;
1022 }
1023
1024 if ((i > 0) && (x = codec2index(row)) == -1) {
1025 ao2_ref(row, -1);
1026 continue;
1027 }
1028
1029 ast_str_set(&out, 0, " ");
1030 for (k = 0; k <= max_codec_index; k++) {
1031 int adjust = 0;
1032 struct ast_codec *col = k ? ast_codec_get_by_id(k) : NULL;
1033
1034 y = -1;
1035 if ((k > 0) && (col->type != AST_MEDIA_TYPE_AUDIO)) {
1036 ao2_ref(col, -1);
1037 continue;
1038 }
1039
1040 if ((k > 0) && (y = codec2index(col)) == -1) {
1041 ao2_ref(col, -1);
1042 continue;
1043 }
1044
1045 if (k > 0) {
1046 curlen = strlen(col->name);
1047 if (!strcmp(col->name, "slin") ||
1048 !strcmp(col->name, "speex") ||
1049 !strcmp(col->name, "silk")) {
1050 adjust = log10(col->sample_rate / 1000) + 1;
1051 curlen = curlen + adjust;
1052 }
1053 }
1054
1055 if (curlen < 5) {
1056 curlen = 5;
1057 }
1058
1059 if (x >= 0 && y >= 0 && matrix_get(x, y)->step) {
1060 /* Actual codec output */
1061 if (a->argv[3] && !strcasecmp(a->argv[3], "comp")) {
1062 compCost = matrix_get(x, y)->comp_cost;
1063 if (compCost == 0 || compCost == 999999) {
1064 ast_str_append(&out, 0, "%*s", curlen + 1, "-");
1065 } else {
1066 ast_str_append(&out, 0, "%*u", curlen + 1, compCost);
1067 }
1068 } else {
1069 ast_str_append(&out, 0, "%*u", curlen + 1, (matrix_get(x, y)->table_cost / 100));
1070 }
1071 } else if (i == 0 && k > 0) {
1072 /* Top row - use a dynamic size */
1073 if (!strcmp(col->name, "slin") ||
1074 !strcmp(col->name, "speex") ||
1075 !strcmp(col->name, "silk")) {
1076 ast_str_append(&out, 0, "%*s%u", curlen - adjust + 1,
1077 col->name, col->sample_rate / 1000);
1078 } else {
1079 ast_str_append(&out, 0, "%*s", curlen + 1, col->name);
1080 }
1081 } else if (k == 0 && i > 0) {
1082 /* Left column - use a static size. */
1083 if (!strcmp(row->name, "slin") ||
1084 !strcmp(row->name, "speex") ||
1085 !strcmp(row->name, "silk")) {
1086 int adjust_row = log10(row->sample_rate / 1000) + 1;
1087 ast_str_append(&out, 0, "%*s%u", longest - adjust_row,
1088 row->name, row->sample_rate / 1000);
1089 } else {
1090 ast_str_append(&out, 0, "%*s", longest, row->name);
1091 }
1092 } else if (x >= 0 && y >= 0) {
1093 /* Codec not supported */
1094 ast_str_append(&out, 0, "%*s", curlen + 1, "-");
1095 } else {
1096 /* Upper left hand corner */
1097 ast_str_append(&out, 0, "%*s", longest, "");
1098 }
1099 ao2_cleanup(col);
1100 }
1101 ast_str_append(&out, 0, "\n");
1102 ast_cli(a->fd, "%s", ast_str_buffer(out));
1103 ao2_cleanup(row);
1104 }
1105 ast_free(out);
1107 return CLI_SUCCESS;
1108}
#define ast_str_create(init_len)
Create a malloc'ed dynamic length string.
Definition: strings.h:659
uint32_t comp_cost
Definition: translate.c:62

References a, ao2_cleanup, ao2_ref, ast_cli(), ast_codec_get_by_id(), ast_free, AST_MEDIA_TYPE_AUDIO, AST_RWLIST_RDLOCK, AST_RWLIST_UNLOCK, ast_str_append(), ast_str_buffer(), ast_str_create, ast_str_set(), CLI_SUCCESS, codec2index(), translator_path::comp_cost, matrix_get(), ast_codec::name, NULL, out, ast_codec::sample_rate, and ast_codec::type.

Referenced by handle_cli_core_show_translation().

◆ index2codec()

static struct ast_codec * index2codec ( int  index)
static

Definition at line 171 of file translate.c.

172{
173 struct ast_codec *codec;
174
175 if (index >= cur_max_index) {
176 return 0;
177 }
179 codec = ast_codec_get_by_id(__indextable[index]);
181
182 return codec;
183}

References __indextable, ast_codec_get_by_id(), ast_rwlock_rdlock, ast_rwlock_unlock, cur_max_index, and tablelock.

Referenced by matrix_rebuild().

◆ matrix_clear()

static void matrix_clear ( void  )
static

Definition at line 269 of file translate.c.

270{
271 int x;
272 for (x = 0; x < index_size; x++) {
273 memset(__matrix[x], '\0', sizeof(struct translator_path) * (index_size));
274 }
275}
static struct translator_path ** __matrix
a matrix that, for any pair of supported formats, indicates the total cost of translation and the fir...
Definition: translate.c:77

References __matrix, and index_size.

Referenced by matrix_rebuild().

◆ matrix_get()

static struct translator_path * matrix_get ( unsigned int  x,
unsigned int  y 
)
static

◆ matrix_rebuild()

static void matrix_rebuild ( int  samples)
static

rebuild a translation matrix.

Note
This function expects the list of translators to be locked

Definition at line 825 of file translate.c.

826{
827 struct ast_translator *t;
828 int newtablecost;
829 int x; /* source format index */
830 int y; /* intermediate format index */
831 int z; /* destination format index */
832
833 ast_debug(1, "Resetting translation matrix\n");
834
835 matrix_clear();
836
837 /* first, compute all direct costs */
839 if (!t->active) {
840 continue;
841 }
842
843 x = t->src_fmt_index;
844 z = t->dst_fmt_index;
845
846 if (samples) {
847 generate_computational_cost(t, samples);
848 }
849
850 /* This new translator is the best choice if any of the below are true.
851 * 1. no translation path is set between x and z yet.
852 * 2. the new table cost is less.
853 * 3. the new computational cost is less. Computational cost is only used
854 * to break a tie between two identical translation paths.
855 */
856 if (!matrix_get(x, z)->step ||
857 (t->table_cost < matrix_get(x, z)->step->table_cost) ||
858 (t->comp_cost < matrix_get(x, z)->step->comp_cost)) {
859
860 matrix_get(x, z)->step = t;
861 matrix_get(x, z)->table_cost = t->table_cost;
862 matrix_get(x, z)->comp_cost = t->comp_cost;
863 }
864 }
865
866 /*
867 * For each triple x, y, z of distinct formats, check if there is
868 * a path from x to z through y which is cheaper than what is
869 * currently known, and in case, update the matrix.
870 * Repeat until the matrix is stable.
871 */
872 for (;;) {
873 int changed = 0;
874 for (x = 0; x < cur_max_index; x++) { /* source format */
875 for (y = 0; y < cur_max_index; y++) { /* intermediate format */
876 if (x == y) { /* skip ourselves */
877 continue;
878 }
879 for (z = 0; z < cur_max_index; z++) { /* dst format */
880 if ((z == x || z == y) || /* skip null conversions */
881 !matrix_get(x, y)->step || /* no path from x to y */
882 !matrix_get(y, z)->step) { /* no path from y to z */
883 continue;
884 }
885
886 /* calculate table cost from x->y->z */
887 newtablecost = matrix_get(x, y)->table_cost + matrix_get(y, z)->table_cost;
888
889 /* if no step already exists between x and z OR the new cost of using the intermediate
890 * step is cheaper, use this step. */
891 if (!matrix_get(x, z)->step || (newtablecost < matrix_get(x, z)->table_cost)) {
892 matrix_get(x, z)->step = matrix_get(x, y)->step;
893 matrix_get(x, z)->table_cost = newtablecost;
894 matrix_get(x, z)->multistep = 1;
895 changed++;
896
897 if (DEBUG_ATLEAST(10)) {
898 struct ast_codec *x_codec = index2codec(x);
899 struct ast_codec *y_codec = index2codec(y);
900 struct ast_codec *z_codec = index2codec(z);
901
903 "Discovered %u cost path from %s to %s, via %s\n",
904 matrix_get(x, z)->table_cost, x_codec->name,
905 y_codec->name, z_codec->name);
906
907 ao2_ref(x_codec, -1);
908 ao2_ref(y_codec, -1);
909 ao2_ref(z_codec, -1);
910 }
911 }
912 }
913 }
914 }
915 if (!changed) {
916 break;
917 }
918 }
919}
#define DEBUG_ATLEAST(level)
#define LOG_DEBUG
#define AST_RWLIST_TRAVERSE
Definition: linkedlists.h:494
static void matrix_clear(void)
Definition: translate.c:269
static struct ast_codec * index2codec(int index)
Definition: translate.c:171

References ast_translator::active, ao2_ref, ast_debug, ast_log, AST_RWLIST_TRAVERSE, ast_translator::comp_cost, translator_path::comp_cost, cur_max_index, DEBUG_ATLEAST, ast_translator::dst_fmt_index, generate_computational_cost(), index2codec(), ast_translator::list, LOG_DEBUG, matrix_clear(), matrix_get(), translator_path::multistep, ast_codec::name, ast_translator::src_fmt_index, translator_path::step, ast_translator::table_cost, and translator_path::table_cost.

Referenced by __ast_register_translator(), ast_translator_activate(), ast_translator_deactivate(), ast_unregister_translator(), handle_cli_recalc(), and matrix_resize().

◆ matrix_resize()

static int matrix_resize ( int  init)
static

Definition at line 195 of file translate.c.

196{
197 struct translator_path **tmp_matrix = NULL;
198 unsigned int *tmp_table = NULL;
199 int old_index;
200 int x;
201
204
205 old_index = index_size;
206 if (init) {
208 } else {
210 }
211
212 /* make new 2d array of translator_path structures */
213 if (!(tmp_matrix = ast_calloc(1, sizeof(struct translator_path *) * (index_size)))) {
214 goto resize_cleanup;
215 }
216
217 for (x = 0; x < index_size; x++) {
218 if (!(tmp_matrix[x] = ast_calloc(1, sizeof(struct translator_path) * (index_size)))) {
219 goto resize_cleanup;
220 }
221 }
222
223 /* make new index table */
224 if (!(tmp_table = ast_calloc(1, sizeof(unsigned int) * index_size))) {
225 goto resize_cleanup;
226 }
227
228 /* if everything went well this far, free the old and use the new */
229 if (!init) {
230 for (x = 0; x < old_index; x++) {
231 ast_free(__matrix[x]);
232 }
234
235 memcpy(tmp_table, __indextable, sizeof(unsigned int) * old_index);
237 }
238
239 /* now copy them over */
240 __matrix = tmp_matrix;
241 __indextable = tmp_table;
242
246
247 return 0;
248
249resize_cleanup:
252 if (tmp_matrix) {
253 for (x = 0; x < index_size; x++) {
254 ast_free(tmp_matrix[x]);
255 }
256 ast_free(tmp_matrix);
257 }
258 ast_free(tmp_table);
259
260 return -1;
261}
#define ast_calloc(num, len)
A wrapper for calloc()
Definition: astmm.h:202
#define INIT_INDEX
Definition: translate.c:90
#define GROW_INDEX
Definition: translate.c:92

References __indextable, __matrix, ast_calloc, ast_free, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, ast_rwlock_unlock, ast_rwlock_wrlock, GROW_INDEX, index_size, INIT_INDEX, matrix_rebuild(), NULL, and tablelock.

Referenced by __ast_register_translator(), and ast_translate_init().

◆ newpvt()

static struct ast_trans_pvt * newpvt ( struct ast_translator t,
struct ast_format explicit_dst 
)
static

Allocate the descriptor, required outbuf space, and possibly desc.

Definition at line 312 of file translate.c.

313{
314 struct ast_trans_pvt *pvt;
315 int len;
316 char *ofs;
317
318 /*
319 * compute the required size adding private descriptor,
320 * buffer, AST_FRIENDLY_OFFSET.
321 */
322 len = sizeof(*pvt) + t->desc_size;
323 if (t->buf_size)
325 pvt = ast_calloc(1, len);
326 if (!pvt) {
327 return NULL;
328 }
329 pvt->t = t;
330 ofs = (char *)(pvt + 1); /* pointer to data space */
331 if (t->desc_size) { /* first comes the descriptor */
332 pvt->pvt = ofs;
333 ofs += t->desc_size;
334 }
335 if (t->buf_size) {/* finally buffer and header */
336 pvt->outbuf.c = ofs + AST_FRIENDLY_OFFSET;
337 }
338 /*
339 * If the format has an attribute module, explicit_dst includes the (joined)
340 * result of the SDP negotiation. For example with the Opus Codec, the format
341 * knows whether both parties want to do forward-error correction (FEC).
342 */
343 pvt->explicit_dst = ao2_bump(explicit_dst);
344
346
347 /* call local init routine, if present */
348 if (t->newpvt && t->newpvt(pvt)) {
349 ast_free(pvt);
351 return NULL;
352 }
353
354 /* Setup normal static translation frame. */
355 pvt->f.frametype = AST_FRAME_VOICE;
356 pvt->f.mallocd = 0;
357 pvt->f.offset = AST_FRIENDLY_OFFSET;
358 pvt->f.src = pvt->t->name;
359 pvt->f.data.ptr = pvt->outbuf.c;
360
361 /*
362 * If the translator has not provided a format
363 * A) use the joined one,
364 * B) use the cached one, or
365 * C) create one.
366 */
367 if (!pvt->f.subclass.format) {
368 pvt->f.subclass.format = ao2_bump(pvt->explicit_dst);
369
370 if (!pvt->f.subclass.format && !ast_strlen_zero(pvt->t->format)) {
371 pvt->f.subclass.format = ast_format_cache_get(pvt->t->format);
372 }
373
374 if (!pvt->f.subclass.format) {
375 struct ast_codec *codec = ast_codec_get(t->dst_codec.name,
377 if (!codec) {
378 ast_log(LOG_ERROR, "Unable to get destination codec\n");
379 destroy(pvt);
380 return NULL;
381 }
382 pvt->f.subclass.format = ast_format_create(codec);
383 ao2_ref(codec, -1);
384 }
385
386 if (!pvt->f.subclass.format) {
387 ast_log(LOG_ERROR, "Unable to create format\n");
388 destroy(pvt);
389 return NULL;
390 }
391 }
392
393 return pvt;
394}
#define ao2_bump(obj)
Bump refcount on an AO2 object by one, returning the object.
Definition: astobj2.h:480
struct ast_format * ast_format_create(struct ast_codec *codec)
Create a new media format.
Definition: format.c:196
#define ast_format_cache_get(name)
Retrieve a named format from the cache.
Definition: format_cache.h:278
#define ast_module_ref(mod)
Hold a reference to the module.
Definition: module.h:443
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:65
int(* newpvt)(struct ast_trans_pvt *)
Definition: translate.h:151

References ao2_bump, ao2_ref, ast_calloc, ast_codec_get(), ast_format_cache_get, ast_format_create(), AST_FRAME_VOICE, ast_free, AST_FRIENDLY_OFFSET, ast_log, ast_module_ref, ast_module_unref, ast_strlen_zero(), ast_translator::buf_size, ast_translator::desc_size, destroy(), ast_translator::dst_codec, ast_trans_pvt::explicit_dst, ast_trans_pvt::f, ast_frame_subclass::format, len(), LOG_ERROR, ast_translator::module, ast_codec::name, ast_translator::newpvt, NULL, ast_trans_pvt::pvt, ast_codec::sample_rate, ast_frame::subclass, ast_trans_pvt::t, and ast_codec::type.

Referenced by ast_translator_build_path(), and generate_computational_cost().

◆ translate_shutdown()

static void translate_shutdown ( void  )
static

Definition at line 1658 of file translate.c.

1659{
1660 int x;
1662
1664 for (x = 0; x < index_size; x++) {
1665 ast_free(__matrix[x]);
1666 }
1668 __matrix = NULL;
1673}
int ast_cli_unregister_multiple(struct ast_cli_entry *e, int len)
Unregister multiple commands.
Definition: clicompat.c:30
#define ast_rwlock_destroy(rwlock)
Definition: lock.h:233

References __indextable, __matrix, ARRAY_LEN, ast_cli_unregister_multiple(), ast_free, ast_rwlock_destroy, ast_rwlock_unlock, ast_rwlock_wrlock, cli_translate, index_size, NULL, and tablelock.

Referenced by ast_translate_init().

Variable Documentation

◆ __indextable

unsigned int* __indextable
static

table for converting index to format values.

Note
this table is protected by the table_lock.

Definition at line 84 of file translate.c.

Referenced by add_codec2index(), codec_to_index(), index2codec(), matrix_resize(), and translate_shutdown().

◆ __matrix

struct translator_path** __matrix
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 reconstructed 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 77 of file translate.c.

Referenced by matrix_clear(), matrix_get(), matrix_resize(), and translate_shutdown().

◆ cli_translate

struct ast_cli_entry cli_translate[]
static
Initial value:
= {
{ .handler = handle_cli_core_show_translation , .summary = "Display translation matrix" ,}
}
static char * handle_cli_core_show_translation(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: translate.c:1175

Definition at line 1232 of file translate.c.

Referenced by ast_translate_init(), and translate_shutdown().

◆ cur_max_index

int cur_max_index
static

the current largest index used by the __matrix and __indextable arrays

Definition at line 95 of file translate.c.

Referenced by __ast_register_translator(), add_codec2index(), codec_to_index(), index2codec(), and matrix_rebuild().

◆ index_size

int index_size
static

the largest index that can be used in either the __indextable or __matrix before resize must occur

Definition at line 97 of file translate.c.

Referenced by add_codec2index(), matrix_clear(), matrix_resize(), and translate_shutdown().

◆ tablelock

ast_rwlock_t tablelock
static

protects the __indextable for resizing

Definition at line 87 of file translate.c.

Referenced by add_codec2index(), ast_translate_init(), codec_to_index(), index2codec(), matrix_resize(), and translate_shutdown().

◆ translators

struct translators translators = { .first = NULL, .last = NULL, .lock = { PTHREAD_RWLOCK_INITIALIZER , NULL, {1, 0} } , }
static